Added sys_close and sys_fsync

Untested.
This commit is contained in:
Bahadir Balban
2008-05-23 03:59:18 +00:00
parent 00b47117b0
commit 6be310f460
8 changed files with 148 additions and 21 deletions

View File

@@ -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__ */

View File

@@ -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]);

View File

@@ -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

View File

@@ -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__ */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)