Commit 09cf698a authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6d1ff4d6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -244,4 +244,8 @@ int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
int import_single_range(int type, void __user *buf, size_t len,
		 struct iovec *iov, struct iov_iter *i);

int iov_iter_for_each_range(struct iov_iter *i, size_t bytes,
			    int (*f)(struct kvec *vec, void *context),
			    void *context);

#endif
+22 −0
Original line number Diff line number Diff line
@@ -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);