From 6e573423507ecfd1a67a13714915dd69f063b959 Mon Sep 17 00:00:00 2001 From: Guy Zana <guy@cloudius-systems.com> Date: Tue, 12 Mar 2013 11:24:38 +0200 Subject: [PATCH] Initial fileops abstraction --- fs/build.mak | 3 +- fs/vfs/vfs_fops.c | 108 ++++++++++++++++++++++++++++++++++++++ fs/vfs/vfs_syscalls.c | 72 +++++++------------------ include/osv/file.h | 119 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 245 insertions(+), 57 deletions(-) create mode 100644 fs/vfs/vfs_fops.c diff --git a/fs/build.mak b/fs/build.mak index dec9818fe..47d1abf23 100644 --- a/fs/build.mak +++ b/fs/build.mak @@ -13,7 +13,8 @@ fs += vfs/main.o \ vfs/vfs_mount.o \ vfs/vfs_vnode.o \ vfs/vfs_task.o \ - vfs/vfs_syscalls.o + vfs/vfs_syscalls.o \ + vfs/vfs_fops.o fs += ramfs/ramfs_vfsops.o \ ramfs/ramfs_vnops.o diff --git a/fs/vfs/vfs_fops.c b/fs/vfs/vfs_fops.c new file mode 100644 index 000000000..40d094918 --- /dev/null +++ b/fs/vfs/vfs_fops.c @@ -0,0 +1,108 @@ + +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <osv/file.h> +#include <fs/vfs/vfs.h> + +static int vfs_fo_init(struct file *fp) +{ + return 0; +} + +static int vfs_close(struct file *fp) +{ + struct vnode *vp = fp->f_vnode; + int error; + + vn_lock(vp); + error = VOP_CLOSE(vp, fp); + if (error) { + vn_unlock(vp); + return error; + } + vput(vp); + return 0; +} + +static int vfs_read(struct file *fp, struct uio *uio, int flags) +{ + struct vnode *vp = fp->f_vnode; + int error; + size_t count; + ssize_t bytes; + + bytes = uio->uio_resid; + + vn_lock(vp); + if ((flags & FOF_OFFSET) == 0) + uio->uio_offset = fp->f_offset; + + error = VOP_READ(vp, uio, 0); + if (!error) { + count = bytes - uio->uio_resid; + if ((flags & FOF_OFFSET) == 0) + fp->f_offset += count; + } + vn_unlock(vp); + + return error; +} + + +static int vfs_write(struct file *fp, struct uio *uio, int flags) +{ + struct vnode *vp = fp->f_vnode; + int ioflags = 0; + int error; + size_t count; + ssize_t bytes; + + bytes = uio->uio_resid; + + vn_lock(vp); + if ((flags & FOF_OFFSET) == 0) + uio->uio_offset = fp->f_offset; + + error = VOP_WRITE(vp, uio, ioflags); + if (!error) { + count = bytes - uio->uio_resid; + if ((flags & FOF_OFFSET) == 0) + fp->f_offset += count; + } + + vn_unlock(vp); + return error; +} + +static int vfs_ioctl(struct file *fp, u_long com, void *data) +{ + struct vnode *vp = fp->f_vnode; + int error; + + vn_lock(vp); + error = VOP_IOCTL(vp, fp, com, data); + vn_unlock(vp); + + return error; +} + +static int vfs_stat(struct file *fp, struct stat *st) +{ + struct vnode *vp = fp->f_vnode; + int error; + + vn_lock(vp); + error = vn_stat(vp, st); + vn_unlock(vp); + + return error; +} + +struct fileops vfs_ops = { + .fo_init = vfs_fo_init, + .fo_close = vfs_close, + .fo_read = vfs_read, + .fo_write = vfs_write, + .fo_ioctl = vfs_ioctl, + .fo_stat = vfs_stat, +}; diff --git a/fs/vfs/vfs_syscalls.c b/fs/vfs/vfs_syscalls.c index 50c1731dc..242be8968 100755 --- a/fs/vfs/vfs_syscalls.c +++ b/fs/vfs/vfs_syscalls.c @@ -131,10 +131,12 @@ sys_open(char *path, int flags, mode_t mode, file_t *pfp) return error; } memset(fp, 0, sizeof(struct file)); - fp->f_vnode = vp; fp->f_flags = flags; - fp->f_offset = 0; fp->f_count = 1; + fp->f_offset = 0; + fp->f_vnode = vp; + fp->f_ops = &vfs_ops; + fp->f_type = DTYPE_VNODE; *pfp = fp; vn_unlock(vp); return 0; @@ -143,9 +145,6 @@ sys_open(char *path, int flags, mode_t mode, file_t *pfp) int sys_close(file_t fp) { - vnode_t vp; - int error; - DPRINTF(VFSDB_SYSCALL, ("sys_close: fp=%x count=%d\n", (u_int)fp, fp->f_count)); @@ -155,13 +154,7 @@ sys_close(file_t fp) if (--fp->f_count > 0) return 0; - vp = fp->f_vnode; - vn_lock(vp); - if ((error = VOP_CLOSE(vp, fp)) != 0) { - vn_unlock(vp); - return error; - } - vput(vp); + fo_close(fp); free(fp); return 0; } @@ -170,7 +163,6 @@ int sys_read(file_t fp, struct iovec *iov, size_t niov, off_t offset, size_t *count) { - struct vnode *vp = fp->f_vnode; struct uio *uio = NULL; ssize_t bytes; int error; @@ -185,25 +177,18 @@ sys_read(file_t fp, struct iovec *iov, size_t niov, if (error) return error; + bytes = uio->uio_resid; + if (uio->uio_resid == 0) { *count = 0; return 0; } - bytes = uio->uio_resid; - vn_lock(vp); uio->uio_rw = UIO_READ; - if (offset == -1) - uio->uio_offset = fp->f_offset; - else - uio->uio_offset = offset; - error = VOP_READ(vp, uio, 0); - if (!error) { - *count = bytes - uio->uio_resid; - if (offset == -1) - fp->f_offset += *count; - } - vn_unlock(vp); + uio->uio_offset = offset; + fo_read(fp, uio, (offset == -1) ? 0 : FOF_OFFSET); + *count = bytes - uio->uio_resid; + return error; } @@ -211,10 +196,8 @@ int sys_write(file_t fp, struct iovec *iov, size_t niov, off_t offset, size_t *count) { - struct vnode *vp = fp->f_vnode; struct uio *uio = NULL; ssize_t bytes; - int ioflags = 0; int error; DPRINTF(VFSDB_SYSCALL, ("sys_write: fp=%x uio=%x niv=%zu\n", @@ -222,8 +205,6 @@ sys_write(file_t fp, struct iovec *iov, size_t niov, if ((fp->f_flags & FWRITE) == 0) return EBADF; - if (fp->f_flags & O_APPEND) - ioflags |= IO_APPEND; error = copyinuio(iov, niov, &uio); if (error) @@ -233,21 +214,14 @@ sys_write(file_t fp, struct iovec *iov, size_t niov, *count = 0; return 0; } + bytes = uio->uio_resid; - vn_lock(vp); uio->uio_rw = UIO_WRITE; - if (offset == -1) - uio->uio_offset = fp->f_offset; - else - uio->uio_offset = offset; - error = VOP_WRITE(vp, uio, ioflags); - if (!error) { - *count = bytes - uio->uio_resid; - if (offset == -1) - fp->f_offset += *count; - } - vn_unlock(vp); + uio->uio_offset = offset; + fo_write(fp, uio, (offset == -1) ? 0 : FOF_OFFSET); + *count = bytes - uio->uio_resid; + return error; } @@ -302,7 +276,6 @@ sys_lseek(file_t fp, off_t off, int type, off_t *origin) int sys_ioctl(file_t fp, u_long request, void *buf) { - vnode_t vp; int error; DPRINTF(VFSDB_SYSCALL, ("sys_ioctl: fp=%x request=%x\n", fp, request)); @@ -310,10 +283,8 @@ sys_ioctl(file_t fp, u_long request, void *buf) if ((fp->f_flags & (FREAD | FWRITE)) == 0) return EBADF; - vp = fp->f_vnode; - vn_lock(vp); - error = VOP_IOCTL(vp, fp, request, buf); - vn_unlock(vp); + error = fo_ioctl(fp, request, buf); + DPRINTF(VFSDB_SYSCALL, ("sys_ioctl: comp error=%d\n", error)); return error; } @@ -339,15 +310,12 @@ sys_fsync(file_t fp) int sys_fstat(file_t fp, struct stat *st) { - vnode_t vp; int error = 0; DPRINTF(VFSDB_SYSCALL, ("sys_fstat: fp=%x\n", fp)); - vp = fp->f_vnode; - vn_lock(vp); - error = vn_stat(vp, st); - vn_unlock(vp); + error = fo_stat(fp, st); + return error; } diff --git a/include/osv/file.h b/include/osv/file.h index eecdaa353..69bcf6800 100755 --- a/include/osv/file.h +++ b/include/osv/file.h @@ -27,27 +27,138 @@ * SUCH DAMAGE. */ -#ifndef _SYS_FILE_H_ -#define _SYS_FILE_H_ +#ifndef _OSV_FILE_H_ +#define _OSV_FILE_H_ #include <sys/cdefs.h> #include <sys/types.h> +#include <sys/stat.h> + +#include <osv/uio.h> __BEGIN_DECLS +/* + * File type + */ +typedef enum { + DTYPE_UNSPEC, + DTYPE_VNODE, + DTYPE_SOCKET +} filetype_t; + struct vnode; +struct fileops; /* * File structure */ struct file { - int f_flags; /* open flag */ + int f_flags; /* open flags */ int f_count; /* reference count */ off_t f_offset; /* current position in file */ struct vnode *f_vnode; /* vnode */ + struct fileops *f_ops; /* file ops abstraction */ + void *f_data; /* file descriptor specific data */ + filetype_t f_type; /* descriptor type */ }; + typedef struct file *file_t; +#define FOF_OFFSET 0x0800 /* Use the offset in uio argument */ + +typedef int fo_init_t(struct file *fp); +typedef int fo_rdwr_t(struct file *fp, struct uio *uio, int flags); +typedef int fo_truncate_t(struct file *fp, off_t length); +typedef int fo_ioctl_t(struct file *fp, u_long com, void *data); +typedef int fo_poll_t(struct file *fp, int events); +typedef int fo_stat_t(struct file *fp, struct stat *sb); +typedef int fo_close_t(struct file *fp); +typedef int fo_chmod_t(struct file *fp, mode_t mode); + + +struct fileops { + fo_init_t *fo_init; + fo_rdwr_t *fo_read; + fo_rdwr_t *fo_write; + fo_truncate_t *fo_truncate; + fo_ioctl_t *fo_ioctl; + fo_poll_t *fo_poll; + fo_stat_t *fo_stat; + fo_close_t *fo_close; + fo_chmod_t *fo_chmod; +}; + +extern struct fileops vfs_ops; + + +/* + * Easy inline functions for invoking the file operations + */ +static __inline fo_init_t fo_init; +static __inline fo_rdwr_t fo_read; +static __inline fo_rdwr_t fo_write; +static __inline fo_truncate_t fo_truncate; +static __inline fo_ioctl_t fo_ioctl; +static __inline fo_poll_t fo_poll; +static __inline fo_stat_t fo_stat; +static __inline fo_close_t fo_close; +static __inline fo_chmod_t fo_chmod; + +static __inline int +fo_init(struct file *fp) +{ + return fp->f_ops->fo_init(fp); +} + +static __inline int +fo_read(struct file *fp, struct uio *uio, int flags) +{ + return fp->f_ops->fo_read(fp, uio, flags); +} + +static __inline int +fo_write(struct file *fp, struct uio *uio, int flags) +{ + return fp->f_ops->fo_write(fp, uio, flags); +} + +static __inline int +fo_truncate(struct file *fp, off_t length) +{ + return fp->f_ops->fo_truncate(fp, length); +} + +static __inline int +fo_ioctl(struct file *fp, u_long com, void *data) +{ + return fp->f_ops->fo_ioctl(fp, com, data); +} + +static __inline int +fo_poll(struct file *fp, int events) +{ + return fp->f_ops->fo_poll(fp, events); +} + +static __inline int +fo_stat(struct file *fp, struct stat *sb) +{ + return fp->f_ops->fo_stat(fp, sb); +} + +static __inline int +fo_close(struct file *fp) +{ + return fp->f_ops->fo_close(fp); +} + +static __inline int +fo_chmod(struct file *fp, mode_t mode) +{ + return fp->f_ops->fo_chmod(fp, mode); +} + __END_DECLS -#endif /* !_SYS_FILE_H_ */ +#endif /* !_OSV_FILE_H_ */ -- GitLab