From: Boaz Harrosh <boazh@xxxxxxxxxx> We establish an fadvise dispatch with zus. We also define a new IOCTL to drive this into zuf. The IOCTL has the same structure and constants as the fadvise syscall. However: TODO: The VFS does not call into the FS for fadvise, And since we do not use a page-cache it is an no-op for zuf. We need to send a patch to vfs that lets an FS Hop in if it wants to implement its own fadvise. Signed-off-by: Boaz Harrosh <boazh@xxxxxxxxxx> --- fs/zuf/_extern.h | 2 ++ fs/zuf/ioctl.c | 25 ++++++++++++++++++++++ fs/zuf/rw.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ fs/zuf/zuf-core.c | 1 + fs/zuf/zus_api.h | 14 ++++++++++++ 5 files changed, 96 insertions(+) diff --git a/fs/zuf/_extern.h b/fs/zuf/_extern.h index 2e515af0bb22..e345b737499d 100644 --- a/fs/zuf/_extern.h +++ b/fs/zuf/_extern.h @@ -66,6 +66,8 @@ ssize_t zuf_rw_read_iter(struct super_block *sb, struct inode *inode, ssize_t zuf_rw_write_iter(struct super_block *sb, struct inode *inode, struct kiocb *kiocb, struct iov_iter *ii); int zuf_trim_edge(struct inode *inode, ulong filepos, uint len); +int zuf_fadvise(struct super_block *sb, struct inode *inode, + loff_t offset, loff_t len, int advise, bool rand); int zuf_iom_execute_sync(struct super_block *sb, struct inode *inode, __u64 *iom_e, uint iom_n); int zuf_iom_execute_async(struct super_block *sb, struct zus_iomap_build *iomb, diff --git a/fs/zuf/ioctl.c b/fs/zuf/ioctl.c index 13ce65764c38..fb9727ab9d31 100644 --- a/fs/zuf/ioctl.c +++ b/fs/zuf/ioctl.c @@ -238,6 +238,29 @@ static int _ioc_setversion(struct inode *inode, uint __user *parg) return err; } +static int _ioc_fadvise(struct file *file, ulong arg) +{ + struct inode *inode = file_inode(file); + struct zuf_inode_info *zii = ZUII(inode); + struct zufs_ioc_fadvise iof = {}; + int err; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + if (arg && copy_from_user(&iof, (void __user *)arg, sizeof(iof))) + return -EFAULT; + + zuf_r_lock(zii); + + err = zuf_fadvise(inode->i_sb, inode, iof.offset, iof.length, + iof.advise, file->f_mode & FMODE_RANDOM); + + zuf_r_unlock(zii); + + return err; +} + long zuf_ioctl(struct file *filp, unsigned int cmd, ulong arg) { struct inode *inode = filp->f_inode; @@ -252,6 +275,8 @@ long zuf_ioctl(struct file *filp, unsigned int cmd, ulong arg) return put_user(inode->i_generation, (int __user *)arg); case FS_IOC_SETVERSION: return _ioc_setversion(inode, parg); + case ZUFS_IOC_FADVISE: + return _ioc_fadvise(filp, arg); default: return _ioctl_dispatch(inode, cmd, arg); } diff --git a/fs/zuf/rw.c b/fs/zuf/rw.c index 400d24ea7914..0cdb3c257ff8 100644 --- a/fs/zuf/rw.c +++ b/fs/zuf/rw.c @@ -315,6 +315,60 @@ ssize_t zuf_rw_write_iter(struct super_block *sb, struct inode *inode, return ret; } +static int _fadv_willneed(struct super_block *sb, struct inode *inode, + loff_t offset, loff_t len, bool rand) +{ + struct zufs_ioc_IO io = {}; + struct __zufs_ra ra = { + .start = md_o2p(offset), + .ra_pages = md_o2p_up(len), + .prev_pos = offset - 1, + }; + int err; + + io.ra.start = ra.start; + io.ra.ra_pages = ra.ra_pages; + io.ra.prev_pos = ra.prev_pos; + io.flags = rand ? ZUFS_IO_RAND : 0; + + err = _IO_dispatch(SBI(sb), &io, ZUII(inode), ZUFS_OP_PRE_READ, 0, + NULL, 0, offset, 0); + return err; +} + +static int _fadv_dontneed(struct super_block *sb, struct inode *inode, + loff_t offset, loff_t len) +{ + struct zufs_ioc_range ioc_range = { + .hdr.in_len = sizeof(ioc_range), + .hdr.operation = ZUFS_OP_SYNC, + .zus_ii = ZUII(inode)->zus_ii, + .offset = offset, + .length = len, + .ioc_flags = ZUFS_RF_DONTNEED, + }; + + return zufc_dispatch(ZUF_ROOT(SBI(sb)), &ioc_range.hdr, NULL, 0); +} + +int zuf_fadvise(struct super_block *sb, struct inode *inode, + loff_t offset, loff_t len, int advise, bool rand) +{ + switch (advise) { + case POSIX_FADV_WILLNEED: + return _fadv_willneed(sb, inode, offset, len, rand); + case POSIX_FADV_DONTNEED: + return _fadv_dontneed(sb, inode, offset, len); + case POSIX_FADV_NOREUSE: /* TODO */ + case POSIX_FADV_SEQUENTIAL: /* TODO: turn off random */ + case POSIX_FADV_NORMAL: + return 0; + default: + return -EINVAL; + } + return -EINVAL; +} + /* ~~~~ iom_dec.c ~~~ */ /* for now here (at rw.c) looks logical */ diff --git a/fs/zuf/zuf-core.c b/fs/zuf/zuf-core.c index c6b614465ab3..2afccfcf90bb 100644 --- a/fs/zuf/zuf-core.c +++ b/fs/zuf/zuf-core.c @@ -778,6 +778,7 @@ const char *zuf_op_name(enum e_zufs_operation op) CASE_ENUM_NAME(ZUFS_OP_CLONE ); CASE_ENUM_NAME(ZUFS_OP_COPY ); CASE_ENUM_NAME(ZUFS_OP_READ ); + CASE_ENUM_NAME(ZUFS_OP_PRE_READ ); CASE_ENUM_NAME(ZUFS_OP_WRITE ); CASE_ENUM_NAME(ZUFS_OP_GET_BLOCK ); CASE_ENUM_NAME(ZUFS_OP_PUT_BLOCK ); diff --git a/fs/zuf/zus_api.h b/fs/zuf/zus_api.h index 40f369d20306..95fb5c35cde5 100644 --- a/fs/zuf/zus_api.h +++ b/fs/zuf/zus_api.h @@ -159,6 +159,19 @@ struct zus_inode { /* Total ZUFS_INODE_SIZE bytes always */ }; +/* ~~~~~ vfs extension ioctl commands ~~~~~ */ + +/* TODO: This one needs to be an FS vector called from + * the fadvise() system call. (Future patch) + */ +struct zufs_ioc_fadvise { + __u64 offset; + __u64 length; /* if 0 all file */ + __u64 advise; +} __packed; + +#define ZUFS_IOC_FADVISE _IOW('S', 2, struct zufs_ioc_fadvise) + /* ~~~~~ ZUFS API ioctl commands ~~~~~ */ enum { ZUS_API_MAP_MAX_PAGES = 1024, @@ -341,6 +354,7 @@ enum e_zufs_operation { ZUFS_OP_COPY, ZUFS_OP_READ, + ZUFS_OP_PRE_READ, ZUFS_OP_WRITE, ZUFS_OP_GET_BLOCK, ZUFS_OP_PUT_BLOCK, -- 2.20.1