[Devel] [PATCH rh7 v2 2/4] fs/iov_iter: Introduce and use iov_iter.type instead of "ops" verification

Konstantin Khorenko khorenko at virtuozzo.com
Fri Dec 25 19:15:06 MSK 2020


zfs code checks the iov_iter type via "type" struct field, so
we have to
  1) have it
  2) put proper types there

https://bugs.openvz.org/browse/OVZ-7243

Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 include/linux/fs.h | 164 +++++++++++++++++++++++++++++----------------
 1 file changed, 105 insertions(+), 59 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2f498238202a..61dcc20052c3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -330,14 +330,69 @@ struct page;
 struct address_space;
 struct writeback_control;
 
+enum iter_type {
+	/* iter types */
+	ITER_IOVEC	= 4,	/* ii_iovec_ops	*/
+	ITER_KVEC	= 8,	/* ms type, not used in vzkernel */
+	ITER_BVEC	= 16,	/* ii_bvec_ops	*/
+	ITER_PIPE	= 32,	/* ms type, not used in vzkernel */
+	ITER_DISCARD	= 64,	/* ms type, not used in vzkernel */
+	ITER_PAGE	= 128,	/* ii_page_ops, currently not used */
+	ITER_PLAIN	= 256,	/* ii_plain_ops	*/
+	ITER_BAD	= 512,	/* ii_bad_ops	*/
+};
+
 struct iov_iter {
-	struct iov_iter_ops *ops;
+	/*
+	 * Bit 0 is the read/write bit, set if we're writing.
+	 * !!! VZ kernel does not set/use bit 0 for direction !!!
+	 *
+	 * Bit 1 is the BVEC_FLAG_NO_REF bit, set if type is a bvec and
+	 * the caller isn't expecting to drop a page reference when done.
+	 */
+	unsigned int type;
+
 	unsigned long data;
 	unsigned long nr_segs;
 	size_t iov_offset;
 	size_t count;
 };
 
+extern struct iov_iter_ops ii_bvec_ops;
+extern struct iov_iter_ops ii_page_ops;
+extern struct iov_iter_ops ii_iovec_ops;
+extern struct iov_iter_ops ii_bad_ops;
+extern struct iov_iter_ops ii_plain_ops;
+
+static inline struct iov_iter_ops *iov_iter_get_ops(const struct iov_iter *iter)
+{
+	switch (iter->type) {
+	case ITER_IOVEC:
+		return &ii_iovec_ops;
+	/*
+	case ITER_KVEC:
+		return lalala;
+	*/
+	case ITER_BVEC:
+		return &ii_iovec_ops;
+	/*
+	case ITER_PIPE:
+		return lalala;
+	case ITER_DISCARD:
+		return lalala;
+	*/
+	case ITER_PAGE:
+		return &ii_page_ops;
+	case ITER_PLAIN:
+		return &ii_plain_ops;
+	case ITER_BAD:
+		return &ii_bad_ops;
+	default:
+		/* we must be aware about unexpected types */
+		BUG();
+	}
+}
+
 struct iov_iter_ops {
 	size_t (*ii_copy_to_user_atomic)(struct page *, struct iov_iter *,
 					 unsigned long, size_t);
@@ -359,59 +414,81 @@ struct iov_iter_ops {
 static inline size_t iov_iter_copy_to_user_atomic(struct page *page,
                 struct iov_iter *i, unsigned long offset, size_t bytes)
 {
-	return i->ops->ii_copy_to_user_atomic(page, i, offset, bytes);
+	return iov_iter_get_ops(i)->ii_copy_to_user_atomic(page, i, offset,
+							   bytes);
 }
 static inline size_t iov_iter_copy_to_user(struct page *page,
 		struct iov_iter *i, unsigned long offset, size_t bytes)
 {
-	return i->ops->ii_copy_to_user(page, i, offset, bytes);
+	return iov_iter_get_ops(i)->ii_copy_to_user(page, i, offset, bytes);
 }
 static inline size_t iov_iter_copy_from_user_atomic(struct page *page,
                 struct iov_iter *i, unsigned long offset, size_t bytes)
 {
-	return i->ops->ii_copy_from_user_atomic(page, i, offset, bytes);
+	return iov_iter_get_ops(i)->ii_copy_from_user_atomic(page, i, offset,
+							     bytes);
 }
 static inline size_t iov_iter_copy_from_user(struct page *page,
 		struct iov_iter *i, unsigned long offset, size_t bytes)
 {
-	return i->ops->ii_copy_from_user(page, i, offset, bytes);
+	return iov_iter_get_ops(i)->ii_copy_from_user(page, i, offset, bytes);
 }
 static inline void iov_iter_advance(struct iov_iter *i, size_t bytes)
 {
-	return i->ops->ii_advance(i, bytes);
+	return iov_iter_get_ops(i)->ii_advance(i, bytes);
 }
 static inline int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
 {
-	return i->ops->ii_fault_in_readable(i, bytes);
+	return iov_iter_get_ops(i)->ii_fault_in_readable(i, bytes);
 }
 static inline size_t iov_iter_single_seg_count(const struct iov_iter *i)
 {
-	return i->ops->ii_single_seg_count(i);
+	return iov_iter_get_ops(i)->ii_single_seg_count(i);
 }
 static inline int iov_iter_shorten(struct iov_iter *i, size_t count)
 {
-	return i->ops->ii_shorten(i, count);
+	return iov_iter_get_ops(i)->ii_shorten(i, count);
 }
 
 static inline void *iov_iter_kmap_atomic(const struct iov_iter *i, void **bufp,
 					 size_t *len)
 {
-	return i->ops->ii_kmap_atomic(i, bufp, len);
+	return iov_iter_get_ops(i)->ii_kmap_atomic(i, bufp, len);
 }
 
 static inline struct page *iov_iter_kmap(const struct iov_iter *i, void **bufp,
 					 size_t *len)
 {
-	return i->ops->ii_kmap(i, bufp, len);
+	return iov_iter_get_ops(i)->ii_kmap(i, bufp, len);
 }
 
 static inline struct page *iov_iter_get_page(const struct iov_iter *i,
 					     size_t *off, size_t *len)
 {
-	return i->ops->ii_get_page(i, off, len);
+	return iov_iter_get_ops(i)->ii_get_page(i, off, len);
 }
 
-extern struct iov_iter_ops ii_bvec_ops;
+static inline void iov_iter_init(struct iov_iter *i,
+			const struct iovec *iov, unsigned long nr_segs,
+			size_t count, size_t written)
+{
+	i->type = ITER_IOVEC;
+	i->data = (unsigned long)iov;
+	i->nr_segs = nr_segs;
+	i->iov_offset = 0;
+	i->count = count + written;
+
+	iov_iter_advance(i, written);
+}
+static inline int iov_iter_has_iovec(const struct iov_iter *i)
+{
+	return i->type == ITER_IOVEC;
+}
+static inline struct iovec *iov_iter_iovec(const struct iov_iter *i)
+{
+	BUG_ON(!iov_iter_has_iovec(i));
+	return (struct iovec *)i->data;
+}
 
 struct bio_vec;
 static inline void iov_iter_init_bvec(struct iov_iter *i,
@@ -419,7 +496,7 @@ static inline void iov_iter_init_bvec(struct iov_iter *i,
 				      unsigned long nr_segs,
 				      size_t count, size_t written)
 {
-	i->ops = &ii_bvec_ops;
+	i->type = ITER_BVEC;
 	i->data = (unsigned long)bvec;
 	i->nr_segs = nr_segs;
 	i->iov_offset = 0;
@@ -429,7 +506,7 @@ static inline void iov_iter_init_bvec(struct iov_iter *i,
 }
 static inline int iov_iter_has_bvec(struct iov_iter *i)
 {
-	return i->ops == &ii_bvec_ops;
+	return i->type == ITER_BVEC;
 }
 static inline struct bio_vec *iov_iter_bvec(struct iov_iter *i)
 {
@@ -437,13 +514,11 @@ static inline struct bio_vec *iov_iter_bvec(struct iov_iter *i)
 	return (struct bio_vec *)i->data;
 }
 
-extern struct iov_iter_ops ii_page_ops;
-
 static inline void iov_iter_init_page(struct iov_iter *i,
 				      struct page *page,
 				      size_t count, size_t written)
 {
-	i->ops = &ii_page_ops;
+	i->type = ITER_PAGE;
 	i->data = (unsigned long)page;
 	i->nr_segs = 1;
 	i->iov_offset = 0;
@@ -453,7 +528,7 @@ static inline void iov_iter_init_page(struct iov_iter *i,
 }
 static inline int iov_iter_has_page(struct iov_iter *i)
 {
-	return i->ops == &ii_page_ops;
+	return i->type == ITER_PAGE;
 }
 static inline struct page *iov_iter_page(struct iov_iter *i)
 {
@@ -461,37 +536,10 @@ static inline struct page *iov_iter_page(struct iov_iter *i)
 	return (struct page *)i->data;
 }
 
-extern struct iov_iter_ops ii_iovec_ops;
-
-static inline void iov_iter_init(struct iov_iter *i,
-			const struct iovec *iov, unsigned long nr_segs,
-			size_t count, size_t written)
-{
-	i->ops = &ii_iovec_ops;
-	i->data = (unsigned long)iov;
-	i->nr_segs = nr_segs;
-	i->iov_offset = 0;
-	i->count = count + written;
-
-	iov_iter_advance(i, written);
-}
-
-extern struct iov_iter_ops ii_bad_ops;
-
-static inline void iov_iter_init_bad(struct iov_iter *i)
-{
-	i->ops = &ii_bad_ops;
-	i->data = 0;
-	i->nr_segs = 0;
-	i->iov_offset = 0;
-	i->count = 0;
-}
-
-extern struct iov_iter_ops ii_plain_ops;
 static inline void iov_iter_init_plain(struct iov_iter *i, void *data,
 				       size_t count, size_t written)
 {
-	i->ops = &ii_plain_ops;
+	i->type = ITER_PLAIN;
 	i->data = (unsigned long)data;
 	i->nr_segs = 1;
 	i->iov_offset = 0;
@@ -499,20 +547,9 @@ static inline void iov_iter_init_plain(struct iov_iter *i, void *data,
 
 	iov_iter_advance(i, written);
 }
-
-static inline int iov_iter_has_iovec(const struct iov_iter *i)
-{
-	return i->ops == &ii_iovec_ops;
-}
-static inline struct iovec *iov_iter_iovec(const struct iov_iter *i)
-{
-	BUG_ON(!iov_iter_has_iovec(i));
-	return (struct iovec *)i->data;
-}
-
 static inline int iov_iter_has_plain(const struct iov_iter *i)
 {
-	return i->ops == &ii_plain_ops;
+	return i->type == ITER_PLAIN;
 }
 static inline void *iov_iter_plain(const struct iov_iter *i)
 {
@@ -520,6 +557,15 @@ static inline void *iov_iter_plain(const struct iov_iter *i)
 	return (void *)i->data;
 }
 
+static inline void iov_iter_init_bad(struct iov_iter *i)
+{
+	i->type = ITER_BAD;
+	i->data = 0;
+	i->nr_segs = 0;
+	i->iov_offset = 0;
+	i->count = 0;
+}
+
 static inline size_t iov_iter_count(const struct iov_iter *i)
 {
 	return i->count;
-- 
2.24.3



More information about the Devel mailing list