From ee2bf8e7f3bc7b84c095be782f459c7dee9391a9 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Wed, 14 Oct 2009 00:36:01 +0300 Subject: [PATCH] Write cache pages seems to work OK. --- conts/posix/mm0/mm/file.c | 165 +++++++++------------------------ conts/posix/test0/src/fileio.c | 7 +- 2 files changed, 50 insertions(+), 122 deletions(-) diff --git a/conts/posix/mm0/mm/file.c b/conts/posix/mm0/mm/file.c index f103efb..cf6bab4 100644 --- a/conts/posix/mm0/mm/file.c +++ b/conts/posix/mm0/mm/file.c @@ -45,16 +45,14 @@ int page_copy(struct page *dst, struct page *src, dstvaddr = l4_map_helper((void *)page_to_phys(dst), 1); srcvaddr = l4_map_helper((void *)page_to_phys(src), 1); - -#if 0 - printf("%s: Copying from page with offset %d to page with offset %d\n" - "src copy offset: 0x%x, dst copy offset: 0x%x, copy size: %d\n", +/* + printf("%s: Copying from page with offset %lx to page with offset %lx\n" + "src copy offset: 0x%lx, dst copy offset: 0x%lx, copy size: %lx\n", __FUNCTION__, src->offset, dst->offset, src_offset, dst_offset, size); - - printf("%s: Copying string: %s\n", __FUNCTION__, - srcvaddr + src_offset); -#endif +*/ +// printf("%s: Copying string: %s, source: %lx\n", __FUNCTION__, +// (char *)(srcvaddr + src_offset), (unsigned long)srcvaddr+src_offset); memcpy(dstvaddr + dst_offset, srcvaddr + src_offset, size); @@ -510,68 +508,7 @@ int new_file_pages(struct vm_file *f, unsigned long start, unsigned long end) return 0; } -/* TODO: - * Re-evaluate. Possibly merge with read_cache_pages. - */ - -/* Writes user data in buffer into pages in cache */ -int write_cache_pages_orig(struct vm_file *vmfile, struct tcb *task, void *buf, - unsigned long pfn_start, unsigned long pfn_end, - unsigned long cursor_offset, int count) -{ - struct page *head, *this; - unsigned long last_pgoff; /* Last copied page's offset */ - unsigned long copy_offset; /* Current copy offset on the buffer */ - int copysize, left; - - /* Find the head of consecutive pages */ - list_foreach_struct(head, &vmfile->vm_obj.page_cache, list) - if (head->offset == pfn_start) - goto copy; - - /* - * Page not found, this is a bug. The writeable page range - * must have been readied by read_file_pages()/new_file_pages(). - */ - BUG(); - -copy: - left = count; - - /* Copy the first page and unmap. */ - copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE; - copy_offset = (unsigned long)buf; - page_copy(head, task_virt_to_page(task, copy_offset), - cursor_offset, copy_offset & PAGE_MASK, copysize); - head->flags |= VM_DIRTY; - head->owner->flags |= VM_DIRTY; - left -= copysize; - last_pgoff = head->offset; - - /* Map the rest, copy and unmap. */ - list_foreach_struct(this, &head->list, list) { - if (left == 0 || this->offset == pfn_end) - break; - - /* Make sure we're advancing on pages consecutively */ - BUG_ON(this->offset != last_pgoff + 1); - - copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE; - copy_offset = (unsigned long)buf + count - left; - - /* Must be page aligned */ - BUG_ON(!is_page_aligned(copy_offset)); - - page_copy(this, task_virt_to_page(task, copy_offset), - 0, 0, copysize); - this->flags |= VM_DIRTY; - left -= copysize; - last_pgoff = this->offset; - } - BUG_ON(left != 0); - - return count - left; -} +#define page_offset(x) ((unsigned long)(x) & PAGE_MASK) /* * Writes user data in buffer into pages in cache. If a page is not @@ -582,57 +519,45 @@ int write_cache_pages(struct vm_file *vmfile, struct tcb *task, void *buf, unsigned long pfn_start, unsigned long pfn_end, unsigned long cursor_offset, int count) { - struct page *head; - unsigned long last_pgoff; /* Last copied page's offset */ - unsigned long copy_offset; /* Current copy offset on the buffer */ + struct page *file_page; + unsigned long task_offset; /* Current copy offset on the task buffer */ + unsigned long file_offset; /* Current copy offset on the file */ int copysize, left; + int empty; + + task_offset = (unsigned long)buf; + file_offset = cursor_offset; + left = count; + + printf("%s: cursor_offset: 0x%lx, count: 0x%x, buf: %p\n", + __FUNCTION__, cursor_offset, count, buf); /* Find the head of consecutive pages */ - list_foreach_struct(head, &vmfile->vm_obj.page_cache, list) { - /* First page */ - if (head->offset == pfn_start) { - left = count; - - /* Copy the first page and unmap. */ - if (is_page_aligned(buf)) { - copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE; - } else { - if (left < (PAGE_MASK & (unsigned long)buf)) - copysize = left; - else - copysize = (PAGE_MASK & - (unsigned long)buf); - } - copy_offset = (unsigned long)buf; - page_copy(head, task_virt_to_page(task, copy_offset), - cursor_offset, copy_offset & PAGE_MASK, - copysize); - head->flags |= VM_DIRTY; - head->owner->flags |= VM_DIRTY; - left -= copysize; - last_pgoff = head->offset; - - /* Rest of the consecutive pages */ - } else if (head->offset > pfn_start && head->offset < pfn_end) { - - /* Make sure we're advancing on pages consecutively */ - BUG_ON(head->offset != last_pgoff + 1); - - copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE; - copy_offset = (unsigned long)buf + count - left; - - /* Must be page aligned */ - BUG_ON(!is_page_aligned(copy_offset)); - - page_copy(head, task_virt_to_page(task, copy_offset), - 0, 0, copysize); - head->flags |= VM_DIRTY; - left -= copysize; - last_pgoff = head->offset; - } else if (head->offset == pfn_end || left == 0) + list_foreach_struct(file_page, &vmfile->vm_obj.page_cache, list) { + if (file_page->offset < pfn_start) + continue; + else if (file_page->offset == pfn_end || left == 0) break; - } + empty = PAGE_SIZE - page_offset(file_offset); + + /* Copy until the page is filled */ + while (empty && left) { + copysize = min(PAGE_SIZE - page_offset(file_offset), left); + copysize = min(copysize, PAGE_SIZE - page_offset(task_offset)); + //printf("empty: %d, left: %d, copysize: %d, copy to page with pfn %lx, offset 0x%lx, from page with pfn %lx, offset 0x%lx\n", + // empty, left, copysize, file_page->offset, page_offset(file_offset),task_virt_to_page(task,task_offset)->offset, page_offset(task_offset)); + page_copy(file_page, task_virt_to_page(task, task_offset), + page_offset(file_offset), page_offset(task_offset), + copysize); + empty -= copysize; + left -= copysize; + task_offset += copysize; + file_offset += copysize; + } + file_page->flags |= VM_DIRTY; + file_page->owner->flags |= VM_DIRTY; + } BUG_ON(left != 0); return count - left; @@ -656,6 +581,8 @@ int read_cache_pages(struct vm_file *vmfile, struct tcb *task, void *buf, unsigned long last_pgoff; /* Last copied page's offset */ unsigned long copy_offset; /* Current copy offset on the buffer */ + printf("%s: cursor_offset: 0x%lx, count: 0x%x, buf: %p\n", __FUNCTION__, cursor_offset, count, buf); + /* Find the head of consecutive pages */ list_foreach_struct(head, &vmfile->vm_obj.page_cache, list) if (head->offset == pfn_start) @@ -773,7 +700,7 @@ int sys_write(struct tcb *task, int fd, void *buf, int count) unsigned long pfn_wstart, pfn_wend; /* Write start/end */ unsigned long pfn_fstart, pfn_fend; /* File start/end */ unsigned long pfn_nstart, pfn_nend; /* New pages start/end */ - unsigned long cursor, byte_offset; + unsigned long cursor; struct vm_file *vmfile; int ret = 0; @@ -855,9 +782,9 @@ int sys_write(struct tcb *task, int fd, void *buf, int count) * At this point be it new or existing file pages, all pages * to be written are expected to be in the page cache. Write. */ - byte_offset = PAGE_MASK & cursor; + //byte_offset = PAGE_MASK & cursor; if ((ret = write_cache_pages(vmfile, task, buf, pfn_wstart, - pfn_wend, byte_offset, count)) < 0) + pfn_wend, cursor, count)) < 0) return ret; /* diff --git a/conts/posix/test0/src/fileio.c b/conts/posix/test0/src/fileio.c index fd7ee56..672b1ec 100644 --- a/conts/posix/test0/src/fileio.c +++ b/conts/posix/test0/src/fileio.c @@ -16,7 +16,7 @@ int small_io_test(void) char strbuf[30]; char strbuf2[30]; char *path = "/text.txt"; - //char stackbuf[PAGE_SIZE*2]; +// char stackbuf[PAGE_SIZE*2]; fd1 = open(path, O_TRUNC | O_RDWR | O_CREAT, S_IRWXU); fd2 = open(path, O_RDWR, 0); @@ -26,7 +26,7 @@ int small_io_test(void) for (int i = 0; i < 4; i++) { sprintf(strbuf, "%s%d", string, i); - test_printf("Writing to %s offset %x, string: %s\n", + printf("Writing to %s offset %x, string: %s\n", path, i*PAGE_SIZE, strbuf); lseek(fd1, i*PAGE_SIZE, SEEK_SET); write(fd1, strbuf, strlen(strbuf) + 1); @@ -38,7 +38,7 @@ int small_io_test(void) sprintf(strbuf2, "%s%d", string, i); lseek(fd2, i*PAGE_SIZE, SEEK_SET); read(fd2, strbuf, 30); - test_printf("Read %s, offset %x as %s\n", + printf("Read %s, offset %x as %s\n", path, i*PAGE_SIZE, strbuf); if (strcmp(strbuf, strbuf2)) goto out_err; @@ -51,6 +51,7 @@ int small_io_test(void) printf("stackbuf beginning: %s\n second page beginning: %s\n", stackbuf, &stackbuf[PAGE_SIZE]); #endif + close(fd2); printf("MINI IO TEST -- PASSED --\n");