Towards sys_close()/sys_flush()

This commit is contained in:
Bahadir Balban
2008-04-25 22:14:59 +01:00
parent 488d9e6271
commit c9b9f9d111
3 changed files with 106 additions and 31 deletions

View File

@@ -36,6 +36,8 @@
#define VMA_PRIVATE (1 << 6)
/* Copy-on-write semantics */
#define VMA_FIXED (1 << 7)
/* Set when the page is dirty in cache but not written to disk */
#define VM_DIRTY (1 << 8)
/* Defines the type of file. A device file? Regular file? One used at boot? */
enum VM_FILE_TYPE {
@@ -89,8 +91,8 @@ struct fault_data {
struct vm_pager_ops {
struct page *(*page_in)(struct vm_object *vm_obj,
unsigned long pfn_offset);
struct page *(*page_out)(struct vm_object *vm_obj,
unsigned long pfn_offset);
int (*page_out)(struct vm_object *vm_obj,
unsigned long pfn_offset);
int (*release_pages)(struct vm_object *vm_obj);
};

View File

@@ -186,7 +186,6 @@ int insert_page_olist(struct page *this, struct vm_object *vmo)
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.
@@ -210,6 +209,65 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
return 0;
}
int vfs_write(unsigned long vnum, unsigned long file_offset,
unsigned long npages, void *pagebuf)
{
int err;
l4_save_ipcregs();
write_mr(L4SYS_ARG0, vnum);
write_mr(L4SYS_ARG1, file_offset);
write_mr(L4SYS_ARG2, npages);
write_mr(L4SYS_ARG3, (u32)pagebuf);
if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_PAGER_WRITE)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
return err;
}
/* Check if syscall was successful */
if ((err = l4_get_retval()) < 0) {
printf("%s: Pager to VFS write error: %d.\n", __FUNCTION__, err);
return err;
}
l4_restore_ipcregs();
return err;
}
/* Writes pages in cache back to their file */
int write_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
unsigned long pfn_end)
{
int err;
for (int f_offset = pfn_start; f_offset < pfn_end; f_offset++) {
err = vmfile->vm_obj.pager->ops.page_out(&vmfile->vm_obj,
f_offset);
if (err < 0) {
printf("%s: %s:Could not write page %d "
"to file with vnum: 0x%x\n", __TASKNAME__,
__FUNCTION__, f_offset, vm_file_to_vnum(vmfile));
return err;
}
}
return 0;
}
int do_flush_file_pages(struct vm_file *vmfile)
{
}
int sys_close(void)
{
}
int sys_flush(void)
{
}
/* FIXME: Add error handling to this */
/* Extends a file's size by adding it new pages */
@@ -243,34 +301,6 @@ int new_file_pages(struct vm_file *f, unsigned long start, unsigned long end)
return 0;
}
int vfs_write(unsigned long vnum, unsigned long file_offset,
unsigned long npages, void *pagebuf)
{
int err;
l4_save_ipcregs();
write_mr(L4SYS_ARG0, vnum);
write_mr(L4SYS_ARG1, file_offset);
write_mr(L4SYS_ARG2, npages);
write_mr(L4SYS_ARG3, (u32)pagebuf);
if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_PAGER_WRITE)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
return err;
}
/* Check if syscall was successful */
if ((err = l4_get_retval()) < 0) {
printf("%s: Pager to VFS write error: %d.\n", __FUNCTION__, err);
return err;
}
l4_restore_ipcregs();
return err;
}
/* TODO:
* Re-evaluate. Possibly merge with read_cache_pages.
*/

View File

@@ -61,6 +61,48 @@ int default_release_pages(struct vm_object *vm_obj)
return 0;
}
int file_page_out(struct vm_object *vm_obj, unsigned long page_offset)
{
struct vm_file *f = vm_object_to_file(vm_obj);
struct page *page;
void *vaddr, *paddr;
int err;
/* Check first if the file has such a page at all */
if (__pfn(page_align_up(f->length) <= page_offset)) {
printf("%s: %s: Trying to look up page %d, but file length "
"is %d bytes.\n", __TASKNAME__, __FUNCTION__,
page_offset, f->length);
BUG();
}
/* If the page is not in the page cache, simply return. */
if (!(page = find_page(vm_obj, page_offset)))
return 0;
/* If the page is not dirty, simply return */
if (!(page->flags & VM_DIRTY))
return 0;
/* Map the page to vfs task */
l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, VFS_TID);
/* Syscall to vfs to read into the page. */
if ((err = vfs_write(vm_file_to_vnum(f), page_offset, 1, vaddr)) < 0)
goto out_err;
/* Unmap it from vfs */
l4_unmap(vaddr, 1, VFS_TID);
/* Update page details */
page->flags &= ~VM_DIRTY;
return 0;
out_err:
l4_unmap(vaddr, 1, VFS_TID);
return err;
}
struct page *file_page_in(struct vm_object *vm_obj, unsigned long page_offset)
{
@@ -125,6 +167,7 @@ out_err:
struct vm_pager file_pager = {
.ops = {
.page_in = file_page_in,
.page_out = file_page_out,
.release_pages = default_release_pages,
},
};