Split the iterate_and_advance() macro into iovec, bvec, kvec and discard variants. It doesn't handle pipes. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- lib/iov_iter.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 280b5c9c9a9c..a221e7771201 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -147,6 +147,68 @@ static inline bool page_copy_sane(struct page *page, size_t offset, size_t n); } \ } +#define iterate_and_advance_iovec(i, n, v, CMD) { \ + if (unlikely(i->count < n)) \ + n = i->count; \ + if (i->count) { \ + size_t skip = i->iov_offset; \ + const struct iovec *iov; \ + struct iovec v; \ + iterate_iovec(i, n, v, iov, skip, (CMD)) \ + if (skip == iov->iov_len) { \ + iov++; \ + skip = 0; \ + } \ + i->nr_segs -= iov - i->iov; \ + i->iov = iov; \ + i->count -= n; \ + i->iov_offset = skip; \ + } \ +} + +#define iterate_and_advance_bvec(i, n, v, CMD) { \ + if (unlikely(i->count < n)) \ + n = i->count; \ + if (i->count) { \ + size_t skip = i->iov_offset; \ + const struct bio_vec *bvec = i->bvec; \ + struct bio_vec v; \ + struct bvec_iter __bi; \ + iterate_bvec(i, n, v, __bi, skip, (CMD)) \ + i->bvec = __bvec_iter_bvec(i->bvec, __bi); \ + i->nr_segs -= i->bvec - bvec; \ + skip = __bi.bi_bvec_done; \ + i->count -= n; \ + i->iov_offset = skip; \ + } \ +} + +#define iterate_and_advance_kvec(i, n, v, CMD) { \ + if (unlikely(i->count < n)) \ + n = i->count; \ + if (i->count) { \ + size_t skip = i->iov_offset; \ + const struct kvec *kvec; \ + struct kvec v; \ + iterate_kvec(i, n, v, kvec, skip, (CMD)) \ + if (skip == kvec->iov_len) { \ + kvec++; \ + skip = 0; \ + } \ + i->nr_segs -= kvec - i->kvec; \ + i->kvec = kvec; \ + i->count -= n; \ + i->iov_offset = skip; \ + } \ +} + +#define iterate_and_advance_discard(i, n) { \ + if (unlikely(i->count < n)) \ + n = i->count; \ + i->count -= n; \ + i->iov_offset += n; \ +} + static int copyout(void __user *to, const void *from, size_t n) { if (should_fail_usercopy())