Adds reading pages into page-cache in an ordered manner.

Added reading pages from the page cache into user buffer for sys_read.
Increases stack sizes to 4 pages.
Updated README to include more details about multi-pager environments.
This commit is contained in:
Bahadir Balban
2008-02-27 01:17:36 +00:00
parent 2a5cdf80b5
commit 0c9b42121a
9 changed files with 144 additions and 76 deletions

View File

@@ -66,15 +66,12 @@ int memfs_format_filesystem(void *buffer)
INIT_LIST_HEAD(&sb->inode_cache_list);
memfs_init_caches(sb);
/*
* TODO: Make sure root vnode has a vnode number of 0 !!!.
* This is used in early root lookup.
*/
BUG();
/* We allocate and fix a root inode so the sb is ready for mount */
sb->root = memfs_create_inode(sb);
/* Some early-init code relies on root having inode number 0 */
BUG_ON(sb->root->inum != 0);
return 0;
}

View File

@@ -113,15 +113,7 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
int sys_close(l4id_t sender, int fd)
{
struct vnode *v;
/* Get the task */
BUG_ON(!(task = find_task(sender)));
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL; /* No such vnode */
return 0;
}
int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)

View File

@@ -112,6 +112,9 @@ static inline struct vm_area *find_vma(unsigned long addr,
return 0;
}
/* Adds a page to its vmfile's page cache in order of offset. */
int insert_page_olist(struct page *this, struct vm_file *f);
/* Pagers */
extern struct vm_pager default_file_pager;
extern struct vm_pager boot_file_pager;

View File

@@ -20,13 +20,6 @@
#include <syscalls.h>
#include <file.h>
/* FIXME:LOCKING:FIXME:LOCKING:FIXME:LOCKING
* NOTE: For multithreadded MM0, not suprisingly, we need locking on
* vmas, vm_files, and all global variables. Also at times, the per-task
* lists of items (e.g. vmas) must be entirely locked. Pages already have
* locking.
*/
void handle_requests(void)
{
/* Generic ipc data */

View File

@@ -130,7 +130,7 @@ int do_file_page(struct fault_data *fault)
/* Add the page to it's owner's list of in-memory pages */
BUG_ON(!list_empty(&page->list));
list_add(&page->list, &page->owner->page_cache_list);
insert_page_olist(page, page->owner);
spin_unlock(&page->lock);
//printf("%s: Mapped new page @ 0x%x to task: %d\n", __TASKNAME__,
// fault->address, fault->task->tid);
@@ -184,7 +184,7 @@ int do_file_page(struct fault_data *fault)
/* Add the page to it's owner's list of in-memory pages */
BUG_ON(!list_empty(&page->list));
list_add(&page->list, &page->owner->page_cache_list);
insert_page_olist(page, page->owner);
spin_unlock(&page->lock);
/*
@@ -244,7 +244,7 @@ int do_file_page(struct fault_data *fault)
/* Add the page to it's owner's list of in-memory pages */
BUG_ON(!list_empty(&page->list));
list_add(&page->list, &page->owner->page_cache_list);
insert_page_olist(page, page->owner);
spin_unlock(&page->lock);
} else
BUG();
@@ -333,7 +333,7 @@ int do_anon_page(struct fault_data *fault)
/* Add the page to it's owner's list of in-memory pages */
BUG_ON(!list_empty(&page->list));
list_add(&page->list, &page->owner->page_cache_list);
insert_page_olist(page, page->owner);
/* The offset of this page in its owner file */
page->f_offset = __pfn(fault->address)
@@ -391,15 +391,15 @@ int do_page_fault(struct fault_data *fault)
/* vma flags show no access */
if (vma_flags & VM_NONE) {
printf("Illegal access, tid: %d, address: %x\n",
fault->task->tid, fault->address);
printf("Illegal access, tid: %d, address: 0x%x, PC @ 0x%x,\n",
fault->task->tid, fault->address, fault->kdata->faulty_pc);
BUG();
}
/* The access reason is not included in the vma's listed flags */
if (!(reason & vma_flags)) {
printf("Illegal access, tid: %d, address: %x\n",
fault->task->tid, fault->address);
printf("Illegal access, tid: %d, address: 0x%x, PC @ 0x%x\n",
fault->task->tid, fault->address, fault->kdata->faulty_pc);
BUG();
}

View File

@@ -132,18 +132,55 @@ int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd,
return 0;
}
/* TODO: Implement this */
struct page *find_page(struct vm_file *f, unsigned long pfn)
{
struct page *p;
list_for_each_entry(p, &f->page_cache_list, list) {
list_for_each_entry(p, &f->page_cache_list, list)
if (p->f_offset == pfn)
return p;
}
return 0;
}
/*
* Inserts the page to vmfile's list in order of page frame offset.
* We use an ordered list instead of a radix or btree for now.
*/
int insert_page_olist(struct page *this, struct vm_file *f)
{
struct page *before, *after;
/* Add if list is empty */
if (list_empty(&f->page_cache_list)) {
list_add_tail(&this->list, &f->page_cache_list);
return 0;
}
/* Else find the right interval */
list_for_each_entry(before, &f->page_cache_list, list) {
after = list_entry(before->list.next, struct page, list);
/* If there's only one in list */
if (before->list.next == &f->page_cache_list) {
/* Add to end if greater */
if (this->f_offset > before->f_offset)
list_add_tail(&this->list, &before->list);
/* Add to beginning if smaller */
else if (this->f_offset < before->f_offset)
list_add(&this->list, &before->list);
return 0;
}
/* If this page is in-between two other, insert it there */
if (before->f_offset < this->f_offset &&
after->f_offset > this->f_offset) {
list_add_tail(&this->list, &before->list);
return 0;
}
}
BUG();
}
/*
* This reads-in a range of pages from a file and populates the page cache
* just like a page fault, but its not in the page fault path.
@@ -180,7 +217,7 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
/* Add the page to owner's list of in-memory pages */
BUG_ON(!list_empty(&page->list));
list_add(&page->list, &vmfile->page_cache_list);
insert_page_olist(page, vmfile);
spin_unlock(&page->lock);
}
}
@@ -188,11 +225,49 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
return 0;
}
/* Reads a page range from an ordered list of pages into buffer */
int read_cache_pages(struct vm_file *vmfile, void *buf, unsigned long pfn_start,
unsigned long pfn_end, unsigned long offset,
int count)
{
struct page *head, *next;
int copysize, left;
list_for_each_entry(head, &vmfile->page_cache_list, list)
if (head->f_offset == pfn_start)
goto copy;
BUG();
copy:
left = count;
/* Copy the first page */
copysize = (left <= PAGE_SIZE) ? left : PAGE_SIZE;
memcpy(buf, (void *)phys_to_virt((void *)page_to_phys(head)) + offset,
copysize);
left -= copysize;
/* Copy the rest. Urgh, lots of arithmetic here. */
list_for_each_entry(next, &head->list, list) {
if (left == 0 || next->f_offset == pfn_end)
break;
copysize = (left <= PAGE_SIZE) ? left : PAGE_SIZE;
memcpy(buf + count - left,
(void *)phys_to_virt((void *)page_to_phys(next)),
copysize);
left -= copysize;
}
BUG_ON(left != 0);
return 0;
}
int sys_read(l4id_t sender, int fd, void *buf, int count)
{
unsigned long foff_pfn_start, foff_pfn_end;
unsigned long cursor, first_pgoff;
struct vm_file *vmfile;
unsigned long cursor;
struct tcb *t;
int err;
@@ -208,43 +283,26 @@ int sys_read(l4id_t sender, int fd, void *buf, int count)
foff_pfn_start = __pfn(cursor);
foff_pfn_end = __pfn(page_align_up(cursor + count));
/* Read the page range into the cache from file */
if ((err = read_file_pages(vmfile, foff_pfn_start, foff_pfn_end) < 0))
return err;
/*
* FIXME: If vmfiles are mapped contiguously on mm0, then these reads
* can be implemented as a straightforward copy as below.
*
* The problem is that in-memory file pages are usually non-contiguous.
* memcpy(buf, (void *)(vmfile->base + cursor), count);
*/
/* The offset of cursor on first page */
first_pgoff = PAGE_MASK & cursor;
/* Read it into the user buffer from the cache */
if ((err = read_cache_pages(vmfile, buf, foff_pfn_start, foff_pfn_end,
first_pgoff, count)) < 0)
return err;
/* Update cursor on success */
t->fd[fd].cursor += count;
return 0;
}
int sys_write(l4id_t sender, int fd, void *buf, int count)
{
unsigned long foff_pfn_start, foff_pfn_end;
struct vm_file *vmfile;
unsigned long cursor;
struct tcb *t;
int err;
BUG_ON(!(t = find_task(sender)));
/* TODO: Check user buffer and count validity */
if (fd < 0 || fd > TASK_OFILES_MAX)
return -EINVAL;
vmfile = t->fd[fd].vmfile;
cursor = t->fd[fd].cursor;
foff_pfn_start = __pfn(cursor);
foff_pfn_end = __pfn(page_align_up(cursor + count));
if ((err = write_file_pages(vmfile, foff_pfn_start, foff_pfn_end) < 0))
return err;
return 0;
}

View File

@@ -127,9 +127,9 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
goto error;
}
/* mmap each task's stack as single page anonymous memory. */
if ((err = do_mmap(0, 0, task, USER_AREA_END - PAGE_SIZE,
VM_READ | VM_WRITE | VMA_ANON, 1) < 0)) {
/* mmap each task's stack as 4-page anonymous memory. */
if ((err = do_mmap(0, 0, task, USER_AREA_END - PAGE_SIZE * 4,
VM_READ | VM_WRITE | VMA_ANON, 4) < 0)) {
printf("do_mmap: Mapping stack failed with %d.\n", err);
goto error;
}

View File

@@ -26,9 +26,12 @@ void main(void)
{
printf("\n%s: Started with tid %d.\n", __TASKNAME__, self_tid());
/* Sync with pager */
wait_pager(0);
dirtest();
while (1)
wait_pager(0);
#if 0
/* Check mmap/munmap */
mmaptest();