diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-02-18 07:44:03 +0100 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-10-12 04:36:54 +0200 |
commit | 09cf698a594276139b7dfafb232af3fe4fbc4438 (patch) | |
tree | 163c2dbfca800af81aed88f993e6db004093c35b /lib | |
parent | lnet_return_rx_credits_locked: don't abuse list_entry (diff) | |
download | linux-09cf698a594276139b7dfafb232af3fe4fbc4438.tar.xz linux-09cf698a594276139b7dfafb232af3fe4fbc4438.zip |
new primitive: iov_iter_for_each_range()
For kvec and bvec: feeds segments to given callback as long as it
returns 0. For iovec and pipe: fails.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/iov_iter.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 1c1c06ddc20a..970212670b6a 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1446,3 +1446,25 @@ int import_single_range(int rw, void __user *buf, size_t len, return 0; } EXPORT_SYMBOL(import_single_range); + +int iov_iter_for_each_range(struct iov_iter *i, size_t bytes, + int (*f)(struct kvec *vec, void *context), + void *context) +{ + struct kvec w; + int err = -EINVAL; + if (!bytes) + return 0; + + iterate_all_kinds(i, bytes, v, -EINVAL, ({ + w.iov_base = kmap(v.bv_page) + v.bv_offset; + w.iov_len = v.bv_len; + err = f(&w, context); + kunmap(v.bv_page); + err;}), ({ + w = v; + err = f(&w, context);}) + ) + return err; +} +EXPORT_SYMBOL(iov_iter_for_each_range); |