[rh7,14/30] iot_iter: Add iov_iter_alignment()

Submitted by Kirill Tkhai on May 20, 2020, 4:04 p.m.

Details

Message ID 158999067461.2234365.1550519543570867569.stgit@localhost.localdomain
State New
Series "fs, direct_IO: Switch to iov_iter and allow bio_vec for ext4"
Headers show

Commit Message

Kirill Tkhai May 20, 2020, 4:04 p.m.
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>
---
 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 bf42e056bcad..63481fb49967 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 f08f59fafde5..59e26d833ac4 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);