diff options
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 937ae87..77070ab 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -34,6 +34,7 @@ #include <sys/errno.h> #include <sys/sio.h> #include <sys/filedesc.h> +#include <sys/atomic.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/limits.h> @@ -141,6 +142,40 @@ sys_open(struct syscall_args *scargs) /* * arg0: fd + */ +scret_t +sys_close(struct syscall_args *args) +{ + struct filedesc *filedes; + struct proc *td; + int fd = args->arg0; + + if ((filedes = fd_get(fd)) == NULL) { + return -EBADF; + } + + /* Return if other threads still hold a ref */ + if (atomic_dec_int(&filedes->refcnt) > 0) { + return 0; + } + + td = this_td(); + + /* + * Each file descriptor structure references a vnode, + * we want to reclaim it or at the very least drop + * one of its references. After we've cleaned up within + * the file descriptor, we can clear it from the fd table + * and free up the memory for it. + */ + vfs_release_vnode(filedes->vp); + td->fds[fd] = NULL; + dynfree(filedes); + return 0; +} + +/* + * arg0: fd * arg1: buf * arg2: count */ |