mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Towards sys_close()/sys_flush()
This commit is contained in:
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user