[RHEL7,COMMIT] iot_iter: Add iov_iter_alignment()

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

Details

Message ID 202005251452.04PEqK55004190@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 abcd1caadfd8ceb3a0b2b1d8a51d30e384e1c1cb
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Mon May 25 17:52:19 2020 +0300

    iot_iter: Add iov_iter_alignment()
    
    Part of ms commit 62a8067a7f35 "bio_vec-backed iov_iter"
    
    "const" modifiers are discarded because of FUSE.
    
    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
---
 include/linux/fs.h |  2 ++
 mm/iov-iter.c      | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

Patch hide | download patch | download mbox

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5f10c8486a6f7..f787d68600234 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3651,6 +3651,8 @@  static inline iop_dentry_open_t get_dentry_open_iop(struct inode *inode)
 	return wrapper ? wrapper->dentry_open : NULL;
 }
 
+extern unsigned long iov_iter_alignment(struct iov_iter *i);
+
 extern bool path_noexec(const struct path *path);
 
 #endif /* _LINUX_FS_H */
diff --git a/mm/iov-iter.c b/mm/iov-iter.c
index f08f59fafde5d..59e26d833ac49 100644
--- a/mm/iov-iter.c
+++ b/mm/iov-iter.c
@@ -854,3 +854,60 @@  struct iov_iter_ops ii_bad_ops = {
 	.ii_get_page = ii_bad_get_page,
 };
 EXPORT_SYMBOL(ii_bad_ops);
+
+static unsigned long alignment_bvec(struct iov_iter *i)
+{
+	struct bio_vec *bvec = iov_iter_bvec(i);
+	unsigned long res;
+	size_t size = i->count;
+	size_t n;
+
+	if (!size)
+		return 0;
+
+	res = bvec->bv_offset + i->iov_offset;
+	n = bvec->bv_len - i->iov_offset;
+	if (n >= size)
+		return res | size;
+	size -= n;
+	res |= n;
+	while (size > (++bvec)->bv_len) {
+		res |= bvec->bv_offset | bvec->bv_len;
+		size -= bvec->bv_len;
+	}
+	res |= bvec->bv_offset | size;
+	return res;
+}
+
+static unsigned long alignment_iovec(const struct iov_iter *i)
+{
+	const struct iovec *iov = iov_iter_iovec(i);
+	unsigned long res;
+	size_t size = i->count;
+	size_t n;
+
+	if (!size)
+		return 0;
+
+	res = (unsigned long)iov->iov_base + i->iov_offset;
+	n = iov->iov_len - i->iov_offset;
+	if (n >= size)
+		return res | size;
+	size -= n;
+	res |= n;
+	while (size > (++iov)->iov_len) {
+		res |= (unsigned long)iov->iov_base | iov->iov_len;
+		size -= iov->iov_len;
+	}
+	res |= (unsigned long)iov->iov_base | size;
+	return res;
+}
+
+unsigned long iov_iter_alignment(struct iov_iter *i)
+{
+	if (iov_iter_has_bvec(i))
+		return alignment_bvec(i);
+	else
+		return alignment_iovec(i);
+}
+EXPORT_SYMBOL(iov_iter_alignment);