diff mbox series

[RFC,16/17] zuf: Special IOCTL fadvise (TODO)

Message ID 20190219115136.29952-17-boaz@plexistor.com (mailing list archive)
State New, archived
Headers show
Series zuf: ZUFS Zero-copy User-mode FileSystem | expand

Commit Message

Boaz Harrosh Feb. 19, 2019, 11:51 a.m. UTC
From: Boaz Harrosh <boazh@netapp.com>

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@netapp.com>
---
 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 mbox series

Patch

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,