[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