[RHEL7,COMMIT] fs: generic_file_direct_write() switch to iov_iter

Submitted by Konstantin Khorenko on May 25, 2020, 2:52 p.m.

Details

Message ID 202005251452.04PEq3kx003588@finist-ce7.sw.ru
State New
Series "fs, direct_IO: Switch to iov_iter and allow bio_vec for ext4"
Headers show

Commit Message

Konstantin Khorenko May 25, 2020, 2:52 p.m.
The commit is pushed to "branch-rh7-3.10.0-1127.8.2.vz7.161.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1127.8.2.vz7.161.1
------>
commit 1d548ec800c178452f7b221b5c0462651c7f7e06
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Mon May 25 17:52:03 2020 +0300

    fs: generic_file_direct_write() switch to iov_iter
    
    generic_file_direct_write_iter() is not needed anymore.
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
    
    =====================
    Patchset description:
    [00/30] fs,direct_IO: Switch to iov_iter and allow bio_vec for ext4
    
    This patchset transforms direct_IO callbacks, blockdev_direct_IO
    and its underlining functions to iov_iter, and introduces complete
    support of iov_iter for ext4.
    
    Supported iov_iter subtypes for ext4 is iovec and bio_vec. The first
    is for traditional user-submitted aio, while bio_vec is the type,
    which is important for us, since we use it in ploop.
    
    bio_vec operates with pages instead of user addresses (like iovec
    does), so it requires specific callbacks in do_blockdev_direct_IO()
    and in the functions it calls.
    
    The patchset reworks do_blockdev_direct_IO() in the same manner
    as in mainstrean. The most of rest patches are prepared manually,
    since we have significant differences to ms (RHEL7 patches, our
    direct IO patches for FUSE; all they have changed many functions).
    At the end, kaio engine (resulting in direct_IO) became possible
    to be enabled for ext4.
    
    https://jira.sw.ru/browse/PSBM-99793
---
 fs/btrfs/file.c    |  6 ++----
 fs/fuse/file.c     |  9 ++-------
 fs/ocfs2/file.c    | 10 ++++++----
 include/linux/fs.h |  4 ++--
 mm/filemap.c       | 24 +++---------------------
 5 files changed, 15 insertions(+), 38 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 80dcf423266ce..3abb3567112aa 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1756,15 +1756,13 @@  static ssize_t __btrfs_direct_write(struct kiocb *iocb,
 	loff_t endbyte;
 	int err;
 
-	written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos,
-					    count, ocount);
+	iov_iter_init(&i, iov, nr_segs, count, 0);
+	written = generic_file_direct_write(iocb, &i, pos, ppos, ocount);
 
 	if (written < 0 || written == count)
 		return written;
 
 	pos += written;
-	count -= written;
-	iov_iter_init(&i, iov, nr_segs, count, written);
 	written_buffered = __btrfs_buffered_write(file, &i, pos);
 	if (written_buffered < 0) {
 		err = written_buffered;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4c58d527ec7e4..973f1513868a5 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1598,16 +1598,11 @@  static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		goto out;
 
 	if (file->f_flags & O_DIRECT) {
-		written = generic_file_direct_write(iocb, iov, &nr_segs,
-						    pos, &iocb->ki_pos,
-						    count, ocount);
+		iov_iter_init(&i, iov, nr_segs, count, 0);
+		written = generic_file_direct_write(iocb, &i, pos, &pos, ocount);
 		if (written < 0 || written == count)
 			goto out;
 
-		pos += written;
-		count -= written;
-
-		iov_iter_init(&i, iov, nr_segs, count, written);
 		written_buffered = fuse_perform_write(file, mapping, &i, pos);
 		if (written_buffered < 0) {
 			err = written_buffered;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 2bcf1677a59b1..60ea07def7e2f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2238,6 +2238,7 @@  static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 	int full_coherency = !(osb->s_mount_opt &
 			       OCFS2_MOUNT_COHERENCY_BUFFERED);
 	int unaligned_dio = 0;
+	struct iov_iter from;
 
 	trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
 		(unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -2354,17 +2355,18 @@  static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 	if (ret)
 		goto out_dio;
 
+	iov_iter_init(&from, iov, nr_segs, count, 0);
 	if (direct_io) {
-		written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
-						    ppos, count, ocount);
+		written = generic_file_direct_write_iter(iocb, &from, *ppos,
+						    ppos, ocount);
 		if (written < 0) {
 			ret = written;
 			goto out_dio;
 		}
 	} else {
 		current->backing_dev_info = file->f_mapping->backing_dev_info;
-		written = generic_file_buffered_write(iocb, iov, nr_segs, *ppos,
-						      ppos, count, 0);
+		written = generic_file_buffered_write_iter(iocb, &from, *ppos, ppos, 0);
+
 		current->backing_dev_info = NULL;
 	}
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ff3a59ddad5f8..4cd0cc93d32a3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3216,8 +3216,8 @@  extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, un
 extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *, loff_t *);
 extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
 extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *, loff_t);
-extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
-		unsigned long *, loff_t, loff_t *, size_t, size_t);
+extern ssize_t generic_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
+		loff_t pos, loff_t *ppos, size_t count);
 extern ssize_t generic_file_direct_write_iter(struct kiocb *, struct iov_iter *,
 		loff_t, loff_t *, size_t);
 extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
diff --git a/mm/filemap.c b/mm/filemap.c
index 3c2eb02778c77..d13bc7fef066b 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2825,7 +2825,7 @@  int pagecache_write_end(struct file *file, struct address_space *mapping,
 EXPORT_SYMBOL(pagecache_write_end);
 
 ssize_t
-generic_file_direct_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+generic_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
 		loff_t pos, loff_t *ppos, size_t count)
 {
 	struct file	*file = iocb->ki_filp;
@@ -2881,6 +2881,7 @@  generic_file_direct_write_iter(struct kiocb *iocb, struct iov_iter *iter,
 
 	if (written > 0) {
 		pos += written;
+		iov_iter_advance(iter, written);
 		if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
 			i_size_write(inode, pos);
 			mark_inode_dirty(inode);
@@ -2890,23 +2891,6 @@  generic_file_direct_write_iter(struct kiocb *iocb, struct iov_iter *iter,
 out:
 	return written;
 }
-EXPORT_SYMBOL(generic_file_direct_write_iter);
-
-ssize_t
-generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
-		unsigned long *nr_segs, loff_t pos, loff_t *ppos,
-		size_t count, size_t ocount)
-{
-	struct iov_iter iter;
-	ssize_t ret;
-
-	iov_iter_init(&iter, iov, *nr_segs, ocount, 0);
-	ret = generic_file_direct_write_iter(iocb, &iter, pos, ppos, count);
-	/* generic_file_direct_write_iter() might have shortened the vec */
-	if (*nr_segs != iter.nr_segs)
-		*nr_segs = iter.nr_segs;
-	return ret;
-}
 EXPORT_SYMBOL(generic_file_direct_write);
 
 /*
@@ -3124,8 +3108,7 @@  ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
 		loff_t endbyte;
 		ssize_t written_buffered;
 
-		written = generic_file_direct_write_iter(iocb, iter, pos,
-							 ppos, count);
+		written = generic_file_direct_write(iocb, iter, pos, ppos, count);
 		/*
 		 * If the write stopped short of completing, fall back to
 		 * buffered writes.  Some filesystems do this for writes to
@@ -3138,7 +3121,6 @@  ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
 
 		pos += written;
 		count -= written;
-		iov_iter_advance(iter, written);
 		written_buffered = generic_file_buffered_write_iter(iocb, iter,
 						pos, ppos, written);
 		/*