[Devel] [PATCH RHEL7 COMMIT] fs: generic_file_direct_write() switch to iov_iter
Konstantin Khorenko
khorenko at virtuozzo.com
Mon May 25 17:52:03 MSK 2020
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 at 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 at 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(-)
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);
/*
More information about the Devel
mailing list