vfs: add vfs_iocb_iter_[read|write] helper functions
authorJiufei Xue <jiufei.xue@linux.alibaba.com>
Wed, 20 Nov 2019 09:45:25 +0000 (17:45 +0800)
committerMiklos Szeredi <mszeredi@redhat.com>
Fri, 24 Jan 2020 08:46:46 +0000 (09:46 +0100)
This doesn't cause any behavior changes and will be used by overlay async
IO implementation.

Signed-off-by: Jiufei Xue <jiufei.xue@linux.alibaba.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/read_write.c
include/linux/fs.h

index 5bbf587f5bc135485d21331039a8085f1e0500f7..bc75493e747ba0f30ce42118b7fe0b261fdaf265 100644 (file)
@@ -939,6 +939,34 @@ out:
        return ret;
 }
 
+ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
+                          struct iov_iter *iter)
+{
+       size_t tot_len;
+       ssize_t ret = 0;
+
+       if (!file->f_op->read_iter)
+               return -EINVAL;
+       if (!(file->f_mode & FMODE_READ))
+               return -EBADF;
+       if (!(file->f_mode & FMODE_CAN_READ))
+               return -EINVAL;
+
+       tot_len = iov_iter_count(iter);
+       if (!tot_len)
+               goto out;
+       ret = rw_verify_area(READ, file, &iocb->ki_pos, tot_len);
+       if (ret < 0)
+               return ret;
+
+       ret = call_read_iter(file, iocb, iter);
+out:
+       if (ret >= 0)
+               fsnotify_access(file);
+       return ret;
+}
+EXPORT_SYMBOL(vfs_iocb_iter_read);
+
 ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
                rwf_t flags)
 {
@@ -975,6 +1003,34 @@ static ssize_t do_iter_write(struct file *file, struct iov_iter *iter,
        return ret;
 }
 
+ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
+                           struct iov_iter *iter)
+{
+       size_t tot_len;
+       ssize_t ret = 0;
+
+       if (!file->f_op->write_iter)
+               return -EINVAL;
+       if (!(file->f_mode & FMODE_WRITE))
+               return -EBADF;
+       if (!(file->f_mode & FMODE_CAN_WRITE))
+               return -EINVAL;
+
+       tot_len = iov_iter_count(iter);
+       if (!tot_len)
+               return 0;
+       ret = rw_verify_area(WRITE, file, &iocb->ki_pos, tot_len);
+       if (ret < 0)
+               return ret;
+
+       ret = call_write_iter(file, iocb, iter);
+       if (ret > 0)
+               fsnotify_modify(file);
+
+       return ret;
+}
+EXPORT_SYMBOL(vfs_iocb_iter_write);
+
 ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
                rwf_t flags)
 {
index 98e0349adb52638708b2d2a89fcf5ca4947b6c8c..28315a286bab048a730463e16657eee554026f1f 100644 (file)
@@ -2078,6 +2078,18 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
        };
 }
 
+static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
+                              struct file *filp)
+{
+       *kiocb = (struct kiocb) {
+               .ki_filp = filp,
+               .ki_flags = kiocb_src->ki_flags,
+               .ki_hint = kiocb_src->ki_hint,
+               .ki_ioprio = kiocb_src->ki_ioprio,
+               .ki_pos = kiocb_src->ki_pos,
+       };
+}
+
 /*
  * Inode state bits.  Protected by inode->i_lock
  *
@@ -3108,6 +3120,10 @@ ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
                rwf_t flags);
 ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
                rwf_t flags);
+ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
+                          struct iov_iter *iter);
+ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
+                           struct iov_iter *iter);
 
 /* fs/block_dev.c */
 extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);