diff --git a/tasks/fs0/include/syscalls.h b/tasks/fs0/include/syscalls.h index 987b0f4..b18505b 100644 --- a/tasks/fs0/include/syscalls.h +++ b/tasks/fs0/include/syscalls.h @@ -6,26 +6,28 @@ #ifndef __FS0_SYSCALLS_H__ #define __FS0_SYSCALLS_H__ +#include + /* Posix calls */ -int sys_open(l4id_t sender, char *pathname, int flags, u32 mode); -int sys_readdir(l4id_t sender, int fd, void *buf, int count); -int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode); -int sys_chdir(l4id_t sender, const char *pathname); +int sys_open(struct tcb *sender, const char *pathname, int flags, u32 mode); +int sys_readdir(struct tcb *sender, int fd, void *buf, int count); +int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode); +int sys_chdir(struct tcb *sender, const char *pathname); /* Calls from pager that completes a posix call */ -int pager_sys_open(l4id_t sender, l4id_t opener, int fd); -int pager_sys_read(l4id_t sender, unsigned long vnum, unsigned long f_offset, +int pager_sys_open(struct tcb *sender, l4id_t opener, int fd); +int pager_sys_read(struct tcb *sender, unsigned long vnum, unsigned long f_offset, unsigned long npages, void *pagebuf); -int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, +int pager_sys_write(struct tcb *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, +int pager_sys_close(struct tcb *sender, l4id_t closer, int fd); +int pager_update_stats(struct tcb *sender, unsigned long vnum, unsigned long newsize); -int pager_notify_fork(l4id_t sender, l4id_t parid, +int pager_notify_fork(struct tcb *sender, l4id_t parid, l4id_t chid, unsigned long utcb_address); #endif /* __FS0_SYSCALLS_H__ */ diff --git a/tasks/fs0/main.c b/tasks/fs0/main.c index 5e22da9..d9d4b98 100644 --- a/tasks/fs0/main.c +++ b/tasks/fs0/main.c @@ -16,6 +16,7 @@ #include #include #include +#include /* * TODO: @@ -48,19 +49,25 @@ void wait_pager(l4id_t partner) void handle_fs_requests(void) { u32 mr[MR_UNUSED_TOTAL]; - l4id_t sender; - int err; + l4id_t senderid; + struct tcb *sender; + int ret; u32 tag; - if ((err = l4_receive(L4_ANYTHREAD)) < 0) { + if ((ret = l4_receive(L4_ANYTHREAD)) < 0) { printf("%s: %s: IPC Error: %d. Quitting...\n", __TASKNAME__, - __FUNCTION__, err); + __FUNCTION__, ret); BUG(); } /* Read conventional ipc data */ tag = l4_get_tag(); - sender = l4_get_sender(); + senderid = l4_get_sender(); + + if (!(sender = find_task(senderid))) { + l4_ipc_return(-ESRCH); + return; + } /* Read mrs not used by syslib */ for (int i = 0; i < MR_UNUSED_TOTAL; i++) @@ -71,40 +78,40 @@ void handle_fs_requests(void) switch(tag) { case L4_IPC_TAG_WAIT: printf("%s: Synced with waiting thread.\n", __TASKNAME__); - break; + return; /* No reply for this tag */ case L4_IPC_TAG_OPEN: - sys_open(sender, (void *)mr[0], (int)mr[1], (unsigned int)mr[2]); + ret = sys_open(sender, (void *)mr[0], (int)mr[1], (unsigned int)mr[2]); break; case L4_IPC_TAG_MKDIR: - sys_mkdir(sender, (const char *)mr[0], (unsigned int)mr[1]); + ret = sys_mkdir(sender, (const char *)mr[0], (unsigned int)mr[1]); break; case L4_IPC_TAG_CHDIR: - sys_chdir(sender, (const char *)mr[0]); + ret = sys_chdir(sender, (const char *)mr[0]); break; case L4_IPC_TAG_READDIR: - sys_readdir(sender, (int)mr[0], (void *)mr[1], (int)mr[2]); + ret = sys_readdir(sender, (int)mr[0], (void *)mr[1], (int)mr[2]); break; case L4_IPC_TAG_PAGER_READ: - pager_sys_read(sender, (unsigned long)mr[0], (unsigned long)mr[1], - (unsigned long)mr[2], (void *)mr[3]); + ret = pager_sys_read(sender, (unsigned long)mr[0], (unsigned long)mr[1], + (unsigned long)mr[2], (void *)mr[3]); break; case L4_IPC_TAG_PAGER_OPEN: - pager_sys_open(sender, (l4id_t)mr[0], (int)mr[1]); + ret = pager_sys_open(sender, (l4id_t)mr[0], (int)mr[1]); break; case L4_IPC_TAG_PAGER_WRITE: - pager_sys_write(sender, (unsigned long)mr[0], (unsigned long)mr[1], - (unsigned long)mr[2], (void *)mr[3]); + ret = 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]); + ret = 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]); + ret = pager_update_stats(sender, (unsigned long)mr[0], + (unsigned long)mr[1]); break; case L4_IPC_TAG_NOTIFY_FORK: - pager_notify_fork(sender, (l4id_t)mr[0], (l4id_t)mr[1], - (unsigned long)mr[2]); + ret = pager_notify_fork(sender, (l4id_t)mr[0], (l4id_t)mr[1], + (unsigned long)mr[2]); break; default: @@ -112,6 +119,12 @@ void handle_fs_requests(void) "received from tid: %d. Ignoring.\n", __TASKNAME__, mr[MR_TAG], sender); } + + /* Reply */ + if ((ret = l4_ipc_return(ret)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, ret); + BUG(); + } } void main(void) diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 81d6c19..6f5c047 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -17,6 +17,7 @@ #include #include #include +#include #define NILFD -1 @@ -30,39 +31,36 @@ * keeping the request flow in one way. */ -int pager_sys_open(l4id_t sender, l4id_t opener, int fd) +int pager_sys_open(struct tcb *pager, l4id_t opener, int fd) { struct tcb *task; struct vnode *v; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); + // + if (pager->tid != PAGER_TID) + return -EINVAL; /* Check if such task exists */ - if (!(task = find_task(opener))) { - l4_ipc_return(-ESRCH); - return 0; - } + if (!(task = find_task(opener))) + return -ESRCH; /* Check if that fd has been opened */ - if (task->fd[fd] == NILFD) { - l4_ipc_return(-EBADF); - return 0; - } + if (task->fd[fd] == NILFD) + return -EBADF; /* Search the vnode by that vnum */ if (IS_ERR(v = vfs_lookup_byvnum(vfs_root.pivot->sb, - task->fd[fd]))) { - l4_ipc_return((int)v); - return 0; - } + task->fd[fd]))) + return (int)v; - /* Write file information */ + /* + * Write file information, they will + * be sent via the return reply. + */ write_mr(L4SYS_ARG0, v->vnum); write_mr(L4SYS_ARG1, v->size); - /* Return ipc with success code */ - l4_ipc_return(0); - return 0; } @@ -112,7 +110,7 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata, * 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) +int pager_sys_close(struct tcb *sender, l4id_t closer, int fd) { struct tcb *task; int err; @@ -124,12 +122,10 @@ int pager_sys_close(l4id_t sender, l4id_t closer, int fd) if ((err = id_del(task->fdpool, fd)) < 0) { printf("%s: Error releasing fd identifier.\n", __FUNCTION__); - l4_ipc_return(err); - return 0; + return err; } task->fd[fd] = NILFD; - l4_ipc_return(0); return 0; } @@ -138,26 +134,20 @@ int pager_sys_close(l4id_t sender, l4id_t closer, int fd) * - Allocate a copy of path string since lookup destroys it * - Check flags and mode. */ -int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode) +int sys_open(struct tcb *task, const char *pathname, int flags, unsigned int mode) { struct pathdata *pdata; struct vnode *v; - struct tcb *task; int fd; int retval; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - /* Get the task */ - BUG_ON(!(task = find_task(sender))); - /* Parse path data */ if (IS_ERR(pdata = pathdata_parse(pathname, alloca(strlen(pathname) + 1), - task))) { - l4_ipc_return((int)pdata); - return 0; - } + task))) + return (int)pdata; /* Creating new file */ if (flags & O_CREAT) { @@ -184,77 +174,64 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode) out: pathdata_destroy(pdata); - l4_ipc_return(retval); - return 0; + return retval; } -int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode) +int sys_mkdir(struct tcb *task, const char *pathname, unsigned int mode) { - struct tcb *task; struct pathdata *pdata; struct vnode *v; - - /* Get the task */ - BUG_ON(!(task = find_task(sender))); + int ret = 0; /* Parse path data */ if (IS_ERR(pdata = pathdata_parse(pathname, alloca(strlen(pathname) + 1), - task))) { - l4_ipc_return((int)pdata); - return 0; - } + task))) + return (int)pdata; /* Make sure we create a directory */ mode |= S_IFDIR; /* Create the directory or fail */ if (IS_ERR(v = vfs_create(task, pdata, mode))) - l4_ipc_return((int)v); - else - l4_ipc_return(0); + ret = (int)v; /* Destroy extracted path data */ pathdata_destroy(pdata); - return 0; + return ret; } -int sys_chdir(l4id_t sender, const char *pathname) +int sys_chdir(struct tcb *task, const char *pathname) { struct vnode *v; - struct tcb *task; struct pathdata *pdata; - - /* Get the task */ - BUG_ON(!(task = find_task(sender))); + int ret = 0; /* Parse path data */ if (IS_ERR(pdata = pathdata_parse(pathname, alloca(strlen(pathname) + 1), - task))) { - l4_ipc_return((int)pdata); - return 0; - } + task))) + return (int)pdata; /* Get the vnode */ if (IS_ERR(v = vfs_lookup_bypath(pdata))) { - l4_ipc_return((int)v); - return 0; + ret = (int)v; + goto out; } /* Ensure it's a directory */ if (!vfs_isdir(v)) { - l4_ipc_return(-ENOTDIR); - return 0; + ret = -ENOTDIR; + goto out; } /* Assign the current directory pointer */ task->curdir = v; +out: /* Destroy extracted path data */ pathdata_destroy(pdata); - l4_ipc_return(0); - return 0; + return ret; } void fill_kstat(struct vnode *v, struct kstat *ks) @@ -271,33 +248,24 @@ void fill_kstat(struct vnode *v, struct kstat *ks) ks->ctime = v->ctime; } -int sys_fstat(l4id_t sender, int fd, void *statbuf) +int sys_fstat(struct tcb *task, int fd, void *statbuf) { struct vnode *v; - struct tcb *task; unsigned long vnum; - int retval; - - /* Get the task */ - BUG_ON(!(task = find_task(sender))); /* Get the vnum */ - if (fd < 0 || fd > TASK_FILES_MAX) { - l4_ipc_return(-EINVAL); - return 0; - } + if (fd < 0 || fd > TASK_FILES_MAX || task->fd[fd] == NILFD) + return -EBADF; + vnum = task->fd[fd]; /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { - retval = -EINVAL; /* No such vnode */ - return 0; - } + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) + return -EINVAL; /* Fill in the c0-style stat structure */ fill_kstat(v, statbuf); - l4_ipc_return(0); return 0; } @@ -306,34 +274,31 @@ int sys_fstat(l4id_t sender, int fd, void *statbuf) * converted to posix style stat structure via the libposix * library in userspace. */ -int sys_stat(l4id_t sender, const char *pathname, void *statbuf) +int sys_stat(struct tcb *task, const char *pathname, void *statbuf) { struct vnode *v; - struct tcb *task; struct pathdata *pdata; - - /* Get the task */ - BUG_ON(!(task = find_task(sender))); + int ret = 0; /* Parse path data */ if (IS_ERR(pdata = pathdata_parse(pathname, alloca(strlen(pathname) + 1), - task))) { - l4_ipc_return((int)pdata); - return 0; - } + task))) + return (int)pdata; /* Get the vnode */ if (IS_ERR(v = vfs_lookup_bypath(pdata))) { - l4_ipc_return((int)v); - return 0; + ret = (int)v; + goto out; } /* Fill in the c0-style stat structure */ fill_kstat(v, statbuf); - l4_ipc_return(0); - return 0; +out: + /* Destroy extracted path data */ + pathdata_destroy(pdata); + return ret; } /* @@ -341,65 +306,44 @@ int sys_stat(l4id_t sender, const char *pathname, void *statbuf) * That call is in the pager. This merely supplies the pages the pager needs * if they're not in the page cache. */ -int pager_sys_read(l4id_t sender, unsigned long vnum, unsigned long f_offset, +int pager_sys_read(struct tcb *pager, unsigned long vnum, unsigned long f_offset, unsigned long npages, void *pagebuf) { struct vnode *v; - int err, retval = 0; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - if (sender != PAGER_TID) { - retval = -EINVAL; - goto out; - } + if (pager->tid != PAGER_TID) + return -EINVAL; /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { - retval = -EINVAL; /* No such vnode */ - goto out; - } + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) + return -EINVAL; /* Ensure vnode is not a directory */ - if (vfs_isdir(v)) { - retval = -EISDIR; - goto out; - } + if (vfs_isdir(v)) + return -EISDIR; - if ((err = v->fops.read(v, f_offset, npages, pagebuf)) < 0) { - retval = err; - goto out; - } - -out: - l4_ipc_return(retval); - return 0; + return v->fops.read(v, f_offset, npages, pagebuf); } -int pager_update_stats(l4id_t sender, unsigned long vnum, +int pager_update_stats(struct tcb *pager, unsigned long vnum, unsigned long newsize) { struct vnode *v; - int retval = 0; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - if (sender != PAGER_TID) { - retval = -EINVAL; - goto out; - } + if (pager->tid != PAGER_TID) + return -EINVAL; /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { - retval = -EINVAL; /* No such vnode */ - goto out; - } + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) + return -EINVAL; v->size = newsize; v->sb->ops->write_vnode(v->sb, v); -out: - l4_ipc_return(retval); return 0; } @@ -410,30 +354,23 @@ out: * * The buffer must be contiguous by page, if npages > 1. */ -int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, +int pager_sys_write(struct tcb *pager, unsigned long vnum, unsigned long f_offset, unsigned long npages, void *pagebuf) { struct vnode *v; - int err, retval = 0; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - if (sender != PAGER_TID) { - retval = -EINVAL; - goto out; - } + if (pager->tid != PAGER_TID) + return -EINVAL; /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { - retval = -EINVAL; /* No such vnode */ - goto out; - } + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) + return -EINVAL; /* Ensure vnode is not a directory */ - if (vfs_isdir(v)) { - retval = -EISDIR; - goto out; - } + if (vfs_isdir(v)) + return -EISDIR; printf("%s/%s: Writing to vnode %lu, at pgoff 0x%x, %d pages, buf at 0x%x\n", __TASKNAME__, __FUNCTION__, vnum, f_offset, npages, pagebuf); @@ -443,16 +380,7 @@ int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, * But we expect an explicit pager_update_stats from the * pager to update the new file size on the vnode. */ - if ((err = v->fops.write(v, f_offset, npages, pagebuf)) < 0) { - retval = err; - goto out; - } - -out: - // printf("%s/%s: Returning ipc result.\n", __TASKNAME__, __FUNCTION__); - l4_ipc_return(retval); - // printf("%s/%s: Done.\n", __TASKNAME__, __FUNCTION__); - return 0; + return v->fops.write(v, f_offset, npages, pagebuf); } /* @@ -494,47 +422,35 @@ int fill_dirent(void *buf, unsigned long vnum, int offset, char *name) * * FIXME: Ensure buf is in shared utcb, and count does not exceed it. */ -int sys_readdir(l4id_t sender, int fd, void *buf, int count) +int sys_readdir(struct tcb *t, int fd, void *buf, int count) { int dirent_size = sizeof(struct dirent); int total = 0, nbytes = 0; unsigned long vnum; struct vnode *v; struct dentry *d; - struct tcb *t; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - /* Get the task */ - BUG_ON(!(t = find_task(sender))); - /* Check address is in task's utcb */ if ((unsigned long)buf < t->utcb_address || - (unsigned long)buf > t->utcb_address + PAGE_SIZE) { - l4_ipc_return(-EINVAL); - return 0; - } + (unsigned long)buf > t->utcb_address + PAGE_SIZE) + return -EINVAL; - if (fd < 0 || fd > TASK_FILES_MAX) { - l4_ipc_return(-EBADF); - return 0; - } + if (fd < 0 || fd > TASK_FILES_MAX || t->fd[fd] == NILFD) + return -EBADF; - /* Convert fd to vnum. */ - BUG_ON((vnum = t->fd[fd]) < 0); + vnum = t->fd[fd]; /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { - l4_ipc_return(-EINVAL); - return 0; /* No such vnode */ - } + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) + return -EINVAL; + d = list_entry(v->dentries.next, struct dentry, vref); /* Ensure vnode is a directory */ - if (!vfs_isdir(v)) { - l4_ipc_return(-ENOTDIR); - return 0; - } + if (!vfs_isdir(v)) + return -ENOTDIR; /* Write pseudo-entries . and .. to user buffer */ if (count < dirent_size) @@ -554,13 +470,9 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count) count -= dirent_size; /* Copy fs-specific dir to buf in struct dirent format */ - if ((total = v->ops.filldir(buf, v, count)) < 0) { - l4_ipc_return(total); - return 0; - } - nbytes += total; - l4_ipc_return(nbytes); + if ((total = v->ops.filldir(buf, v, count)) < 0) + return total; - return 0; + return nbytes + total; } diff --git a/tasks/fs0/src/task.c b/tasks/fs0/src/task.c index a5a8233..291cd7d 100644 --- a/tasks/fs0/src/task.c +++ b/tasks/fs0/src/task.c @@ -16,6 +16,7 @@ #include #include #include +#include struct tcb_head { struct list_head list; @@ -124,7 +125,7 @@ out_err: * Receives ipc from pager about a new fork event and * the information on the resulting child task. */ -int pager_notify_fork(l4id_t sender, l4id_t parid, +int pager_notify_fork(struct tcb *sender, l4id_t parid, l4id_t chid, unsigned long utcb_address) { struct tcb *child, *parent; @@ -132,10 +133,8 @@ int pager_notify_fork(l4id_t sender, l4id_t parid, // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); BUG_ON(!(parent = find_task(parid))); - if (IS_ERR(child = create_tcb())) { - l4_ipc_return((int)child); - return 0; - } + if (IS_ERR(child = create_tcb())) + return (int)child; /* Initialise fields sent by pager */ child->tid = chid; @@ -152,10 +151,7 @@ int pager_notify_fork(l4id_t sender, l4id_t parid, id_pool_copy(child->fdpool, parent->fdpool, TASK_FILES_MAX); memcpy(child->fd, parent->fd, TASK_FILES_MAX * sizeof(int)); - l4_ipc_return(0); - printf("%s/%s: Exiting...\n", __TASKNAME__, __FUNCTION__); - return 0; }