[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 6/7] lib/9pfs: Add open, close and readdir vnops
From: Cristian Banu <cristb@xxxxxxxxx> This patch adds the open, close and readdir VFS node operations. In order to cache stat structures on sequential readdir calls, a buffer is placed in the f_data field of a file struct. Signed-off-by: Cristian Banu <cristb@xxxxxxxxx> --- lib/9pfs/9pfs_vnops.c | 178 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 3 deletions(-) diff --git a/lib/9pfs/9pfs_vnops.c b/lib/9pfs/9pfs_vnops.c index 50f83148..bf008a88 100644 --- a/lib/9pfs/9pfs_vnops.c +++ b/lib/9pfs/9pfs_vnops.c @@ -47,6 +47,26 @@ #include "9pfs.h" +static uint8_t uk_9pfs_open_mode_from_posix_flags(unsigned long flags) +{ + uint8_t mode = 0; + uint8_t flags_rw = flags & (UK_FREAD | UK_FWRITE); + + if (flags_rw == UK_FREAD) + mode = UK_9P_OREAD; + else if (flags_rw == UK_FWRITE) + mode = UK_9P_OWRITE; + else if (flags_rw == (UK_FREAD | UK_FWRITE)) + mode = UK_9P_ORDWR; + + if (flags & O_EXCL) + mode |= UK_9P_OEXCL; + if (flags & O_TRUNC) + mode |= UK_9P_OTRUNC; + + return mode; +} + static int uk_9pfs_posix_perm_from_mode(int mode) { int res; @@ -73,6 +93,13 @@ static uint32_t uk_9pfs_perm_from_posix_mode(mode_t mode) return res; } +static int uk_9pfs_dttype_from_mode(int mode) +{ + if (mode & UK_9P_DMDIR) + return DT_DIR; + return DT_REG; +} + static int uk_9pfs_posix_mode_from_mode(int mode) { int res; @@ -131,6 +158,75 @@ void uk_9pfs_free_vnode_data(struct vnode *vp) vp->v_data = NULL; } +/* + * The closing variant of the function will enforce freeing the associated + * resources only if the vnode was removed via an unlink/rmdir operation. + */ +static void uk_9pfs_free_vnode_data_closing(struct vnode *vp) +{ + struct uk_9pfs_node_data *nd = UK_9PFS_ND(vp); + + if (!nd->removed) + return; + + uk_9pfs_free_vnode_data(vp); +} + +static int uk_9pfs_open(struct vfscore_file *file) +{ + struct uk_9pdev *dev = UK_9PFS_MD(file->f_dentry->d_mount)->dev; + struct uk_9pfid *openedfid; + struct uk_9pfs_file_data *fd; + int rc; + + /* Allocate memory for file data. */ + fd = calloc(1, sizeof(*fd)); + if (!fd) + return ENOMEM; + + /* Clone fid. */ + openedfid = uk_9p_walk(dev, UK_9PFS_VFID(file->f_dentry->d_vnode), + NULL); + if (PTRISERR(openedfid)) { + rc = PTR2ERR(openedfid); + goto out; + } + + /* Open cloned fid. */ + rc = uk_9p_open(dev, openedfid, + uk_9pfs_open_mode_from_posix_flags(file->f_flags)); + + if (rc) + goto out_err; + + fd->fid = openedfid; + file->f_data = fd; + UK_9PFS_ND(file->f_dentry->d_vnode)->nb_open_files++; + + return 0; + +out_err: + uk_9pfid_put(openedfid); +out: + free(fd); + return -rc; +} + +static int uk_9pfs_close(struct vnode *vn __unused, struct vfscore_file *file) +{ + struct uk_9pfs_file_data *fd = UK_9PFS_FD(file); + + if (fd->readdir_buf) + free(fd->readdir_buf); + + uk_9pfid_put(fd->fid); + free(fd); + UK_9PFS_ND(file->f_dentry->d_vnode)->nb_open_files--; + uk_9pfs_free_vnode_data_closing(file->f_dentry->d_vnode); + + return 0; +} + static int uk_9pfs_lookup(struct vnode *dvp, char *name, struct vnode **vpp) { struct uk_9pdev *dev = UK_9PFS_MD(dvp->v_mount)->dev; @@ -266,7 +362,85 @@ static int uk_9pfs_rmdir(struct vnode *dvp, struct vnode *vp, static int uk_9pfs_readdir(struct vnode *vp, struct vfscore_file *fp, struct dirent *dir) { - return ENOENT; + struct uk_9pdev *dev = UK_9PFS_MD(vp->v_mount)->dev; + struct uk_9pfs_file_data *fd = UK_9PFS_FD(fp); + int rc; + struct uk_9p_stat stat; + struct uk_9preq fake_request; + +again: + if (!fd->readdir_buf) { + fd->readdir_buf = malloc(UK_9PFS_READDIR_BUFSZ); + if (!fd->readdir_buf) + return ENOMEM; + + /* Currently the readdir() buffer is empty. */ + fd->readdir_off = 0; + fd->readdir_sz = 0; + } + + if (fd->readdir_off == fd->readdir_sz) { + fd->readdir_off = 0; + fd->readdir_sz = uk_9p_read(dev, fd->fid, fp->f_offset, + UK_9PFS_READDIR_BUFSZ, fd->readdir_buf); + if (fd->readdir_sz < 0) { + rc = fd->readdir_sz; + goto out; + } + + /* End of directory. */ + if (fd->readdir_sz == 0) { + rc = -ENOENT; + goto out; + } + + /* + * Update offset for the next readdir() call which requires + * the next chunk of data to be transferred. + */ + fp->f_offset += fd->readdir_sz; + } + + /* + * Build a fake request to use the 9P request API to read from the + * buffer the stat structure. + */ + fake_request.recv.buf = fd->readdir_buf; + fake_request.recv.size = fd->readdir_sz; + fake_request.recv.offset = fd->readdir_off; + fake_request.state = UK_9PREQ_RECEIVED; + rc = uk_9preq_deserialize(&fake_request, "S", &stat); + + if (rc == -ENOBUFS) { + /* + * Retry with a clean buffer, maybe the stat structure got + * chunked and is not whole, although the RFC says this should + * not happen. + */ + fd->readdir_off = 0; + fd->readdir_sz = 0; + goto again; + } + + /* Update the readdir() offset to the offset after deserialization. */ + fd->readdir_off = fake_request.recv.offset; + + /* + * Any other error besides ENOBUFS when deserializing is considered + * an IO error. + */ + if (rc) { + rc = -EIO; + goto out; + } + + dir->d_type = uk_9pfs_dttype_from_mode(stat.mode); + dir->d_ino = uk_9pfs_ino(&stat); + strlcpy((char *) &dir->d_name, stat.name.data, + MIN(sizeof(dir->d_name), stat.name.size + 1U)); + +out: + return -rc; } #define uk_9pfs_seek ((vnop_seek_t)vfscore_vop_nullop) @@ -281,8 +455,6 @@ static int uk_9pfs_readdir(struct vnode *vp, struct vfscore_file *fp, #define uk_9pfs_symlink ((vnop_symlink_t)vfscore_vop_eperm) #define uk_9pfs_fallocate ((vnop_fallocate_t)vfscore_vop_nullop) #define uk_9pfs_rename ((vnop_rename_t)vfscore_vop_einval) -#define uk_9pfs_open ((vnop_open_t)vfscore_vop_einval) -#define uk_9pfs_close ((vnop_close_t)vfscore_vop_einval) #define uk_9pfs_read ((vnop_read_t)vfscore_vop_einval) #define uk_9pfs_write ((vnop_write_t)vfscore_vop_einval) -- 2.20.1 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |