From 6be310f460b13f15930287e9875308268f8e913a Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Fri, 23 May 2008 03:59:18 +0000 Subject: [PATCH] Added sys_close and sys_fsync Untested. --- tasks/fs0/include/syscalls.h | 1 + tasks/fs0/main.c | 3 + tasks/fs0/src/syscalls.c | 24 ++++++++ tasks/libl4/include/l4lib/ipcdefs.h | 12 ++-- tasks/libposix/close.c | 33 ++++++++++- tasks/mm0/include/file.h | 2 + tasks/mm0/main.c | 8 +++ tasks/mm0/src/file.c | 86 ++++++++++++++++++++++++----- 8 files changed, 148 insertions(+), 21 deletions(-) diff --git a/tasks/fs0/include/syscalls.h b/tasks/fs0/include/syscalls.h index a375957..601b97f 100644 --- a/tasks/fs0/include/syscalls.h +++ b/tasks/fs0/include/syscalls.h @@ -19,6 +19,7 @@ int pager_sys_read(l4id_t sender, unsigned long vnum, unsigned long f_offset, int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, unsigned long npages, void *pagebuf); +int pager_sys_close(l4id_t sender, l4id_t closer, int fd); int pager_update_stats(l4id_t sender, unsigned long vnum, unsigned long newsize); #endif /* __FS0_SYSCALLS_H__ */ diff --git a/tasks/fs0/main.c b/tasks/fs0/main.c index d76ee2b..ea56714 100644 --- a/tasks/fs0/main.c +++ b/tasks/fs0/main.c @@ -92,6 +92,9 @@ void handle_fs_requests(void) pager_sys_write(sender, (unsigned long)mr[0], (unsigned long)mr[1], (unsigned long)mr[2], (void *)mr[3]); break; + case L4_IPC_TAG_PAGER_CLOSE: + pager_sys_close(sender, (l4id_t)mr[0], (int)mr[1]); + break; case L4_IPC_TAG_PAGER_UPDATE_STATS: pager_update_stats(sender, (unsigned long)mr[0], (unsigned long)mr[1]); diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 00deda3..aca8c08 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -93,6 +93,30 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata, return newnode; } +/* Pager notifies vfs about a closed file descriptor. + * + * FIXME: fsync + close could be done under a single "close" ipc + * from pager. Currently there are 2 ipcs: 1 fsync + 1 fd close. + */ +int pager_sys_close(l4id_t sender, l4id_t closer, int fd) +{ + struct tcb *task; + int err; + + BUG_ON(!(task = find_task(sender))); + + if ((err = id_del(task->fdpool, task->fd[fd])) < 0) { + printf("%s: Error releasing fd identifier.\n", + __FUNCTION__); + l4_ipc_return(err); + return 0; + } + task->fd[fd] = -1; + + l4_ipc_return(0); + return 0; +} + /* FIXME: * - Is it already open? * - Allocate a copy of path string since lookup destroys it diff --git a/tasks/libl4/include/l4lib/ipcdefs.h b/tasks/libl4/include/l4lib/ipcdefs.h index 379769c..b6ac159 100644 --- a/tasks/libl4/include/l4lib/ipcdefs.h +++ b/tasks/libl4/include/l4lib/ipcdefs.h @@ -45,13 +45,15 @@ #define L4_IPC_TAG_FORK 22 #define L4_IPC_TAG_STAT 23 #define L4_IPC_TAG_FSTAT 24 +#define L4_IPC_TAG_FSYNC 25 /* Pager notifies vfs of file close */ /* Tags for ipc between fs0 and mm0 */ -#define L4_IPC_TAG_TASKDATA 25 -#define L4_IPC_TAG_PAGER_OPEN 26 /* vfs sends the pager open file data. */ -#define L4_IPC_TAG_PAGER_READ 27 /* Pager reads file contents from vfs */ -#define L4_IPC_TAG_PAGER_WRITE 28 /* Pager writes file contents to vfs */ -#define L4_IPC_TAG_PAGER_UPDATE_STATS 29 /* Pager updates file stats in vfs */ +#define L4_IPC_TAG_TASKDATA 40 +#define L4_IPC_TAG_PAGER_OPEN 41 /* vfs sends the pager open file data. */ +#define L4_IPC_TAG_PAGER_READ 42 /* Pager reads file contents from vfs */ +#define L4_IPC_TAG_PAGER_WRITE 43 /* Pager writes file contents to vfs */ +#define L4_IPC_TAG_PAGER_CLOSE 44 /* Pager notifies vfs of file close */ +#define L4_IPC_TAG_PAGER_UPDATE_STATS 45 /* Pager updates file stats in vfs */ #endif /* __IPCDEFS_H__ */ diff --git a/tasks/libposix/close.c b/tasks/libposix/close.c index 8f10c17..19bf379 100644 --- a/tasks/libposix/close.c +++ b/tasks/libposix/close.c @@ -1,5 +1,5 @@ /* - * l4/posix glue for close() + * l4/posix glue for close() and fsync() * * Copyright (C) 2007 Bahadir Balban */ @@ -44,3 +44,34 @@ int close(int fd) return ret; } +static inline int l4_fsync(int fd) +{ + write_mr(L4SYS_ARG0, fd); + + /* Call pager with close() request. Check ipc error. */ + if ((fd = l4_sendrecv(PAGER_TID, PAGER_TID, L4_IPC_TAG_FSYNC)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, fd); + return fd; + } + /* Check if syscall itself was successful */ + if ((fd = l4_get_retval()) < 0) { + printf("%s: CLOSE Error: %d.\n", __FUNCTION__, fd); + return fd; + } + return fd; +} + +int fsync(int fd) +{ + int ret = l4_fsync(fd); + + /* If error, return positive error code */ + if (ret < 0) { + errno = -ret; + return -1; + } + + /* else return value */ + return ret; +} + diff --git a/tasks/mm0/include/file.h b/tasks/mm0/include/file.h index 4545024..46ec07d 100644 --- a/tasks/mm0/include/file.h +++ b/tasks/mm0/include/file.h @@ -17,6 +17,8 @@ int vfs_write(unsigned long vnum, unsigned long f_offset, unsigned long npages, int sys_read(l4id_t sender, int fd, void *buf, int count); int sys_write(l4id_t sender, int fd, void *buf, int count); int sys_lseek(l4id_t sender, int fd, off_t offset, int whence); +int sys_close(l4id_t sender, int fd); +int sys_fsync(l4id_t sender, int fd); struct vfs_file_data { unsigned long vnum; diff --git a/tasks/mm0/main.c b/tasks/mm0/main.c index 3b71a02..60ef1b7 100644 --- a/tasks/mm0/main.c +++ b/tasks/mm0/main.c @@ -97,6 +97,14 @@ void handle_requests(void) sys_write(sender, (int)mr[0], (void *)mr[1], (int)mr[2]); break; + case L4_IPC_TAG_CLOSE: + sys_close(sender, (int)mr[0]); + break; + + case L4_IPC_TAG_FSYNC: + sys_fsync(sender, (int)mr[0]); + break; + case L4_IPC_TAG_LSEEK: sys_lseek(sender, (int)mr[0], (off_t)mr[1], (int)mr[2]); break; diff --git a/tasks/mm0/src/file.c b/tasks/mm0/src/file.c index 3946815..367a763 100644 --- a/tasks/mm0/src/file.c +++ b/tasks/mm0/src/file.c @@ -237,6 +237,31 @@ int vfs_write(unsigned long vnum, unsigned long file_offset, return err; } +int vfs_close(l4id_t sender, int fd) +{ + int err; + + l4_save_ipcregs(); + + write_mr(L4SYS_ARG0, sender); + write_mr(L4SYS_ARG1, fd); + + if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_PAGER_CLOSE)) < 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 updated file stats back to vfs. (e.g. new file size) */ int vfs_update_file_stats(struct vm_file *f) { @@ -255,7 +280,8 @@ int vfs_update_file_stats(struct vm_file *f) /* Check if syscall was successful */ if ((err = l4_get_retval()) < 0) { - printf("%s: Pager to VFS write error: %d.\n", __FUNCTION__, err); + printf("%s: Pager to VFS write error: %d.\n", + __FUNCTION__, err); return err; } @@ -285,6 +311,7 @@ int write_file_pages(struct vm_file *f, unsigned long pfn_start, return 0; } +/* Flush all dirty file pages and update file stats */ int flush_file_pages(struct vm_file *f) { write_file_pages(f, 0, __pfn(page_align_up(f->length))); @@ -294,38 +321,67 @@ int flush_file_pages(struct vm_file *f) return 0; } -int sys_close(l4id_t sender, int fd) +/* Given a task and fd syncs all IO on it */ +int fsync_common(l4id_t sender, int fd) { - struct tcb *task; struct vm_file *f; - int retval, err; + struct tcb *task; + int err; /* Get the task */ BUG_ON(!(task = find_task(sender))); /* Check fd validity */ - if (fd < 0 || fd > TASK_FILES_MAX || !task->fd[fd].vmfile) { - retval = -EBADF; - goto out; - } + if (fd < 0 || fd > TASK_FILES_MAX || !task->fd[fd].vmfile) + return -EBADF; /* Finish I/O on file */ f = task->fd[fd].vmfile; - if ((err = flush_file_pages(f)) < 0) { - retval = err; - goto out; - } + if ((err = flush_file_pages(f)) < 0) + return err; -out: - l4_ipc_return(retval); return 0; } -int sys_fsync(int fd) +/* Closes the file descriptor and notifies vfs */ +int fd_close(l4id_t sender, int fd) { + struct tcb *task; + int err; + + /* Get the task */ + BUG_ON(!(task = find_task(sender))); + + if ((err = vfs_close(task->tid, fd)) < 0) + return err; + + task->fd[fd].vnum = 0; + task->fd[fd].cursor = 0; + task->fd[fd].vmfile = 0; + return 0; } +int sys_close(l4id_t sender, int fd) +{ + int err; + + /* Sync the file and update stats */ + if ((err = fsync_common(sender, fd)) < 0) { + l4_ipc_return(err); + return 0; + } + + /* Close the file descriptor. */ + return fd_close(sender, fd); +} + +int sys_fsync(l4id_t sender, int fd) +{ + /* Sync the file and update stats */ + return fsync_common(sender, fd); +} + /* FIXME: Add error handling to this */ /* Extends a file's size by adding it new pages */ int new_file_pages(struct vm_file *f, unsigned long start, unsigned long end)