mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-07 13:53:24 +00:00
iov_iter.c: iterate_and_advance
same as iterate_all_kinds, but iterator is moved to the position past the last byte we'd handled. iov_iter_advance() converted to it Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
04a311655b
commit
7ce2a91e51
104
mm/iov_iter.c
104
mm/iov_iter.c
@ -70,6 +70,33 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define iterate_and_advance(i, n, v, I, B) { \
|
||||
size_t skip = i->iov_offset; \
|
||||
if (unlikely(i->type & ITER_BVEC)) { \
|
||||
const struct bio_vec *bvec; \
|
||||
struct bio_vec v; \
|
||||
iterate_bvec(i, n, v, bvec, skip, (B)) \
|
||||
if (skip == bvec->bv_len) { \
|
||||
bvec++; \
|
||||
skip = 0; \
|
||||
} \
|
||||
i->nr_segs -= bvec - i->bvec; \
|
||||
i->bvec = bvec; \
|
||||
} else { \
|
||||
const struct iovec *iov; \
|
||||
struct iovec v; \
|
||||
iterate_iovec(i, n, v, iov, skip, (I)) \
|
||||
if (skip == iov->iov_len) { \
|
||||
iov++; \
|
||||
skip = 0; \
|
||||
} \
|
||||
i->nr_segs -= iov - i->iov; \
|
||||
i->iov = iov; \
|
||||
} \
|
||||
i->count -= n; \
|
||||
i->iov_offset = skip; \
|
||||
}
|
||||
|
||||
static size_t copy_to_iter_iovec(void *from, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
size_t skip, copy, left, wanted;
|
||||
@ -366,42 +393,6 @@ static size_t zero_iovec(size_t bytes, struct iov_iter *i)
|
||||
return wanted - bytes;
|
||||
}
|
||||
|
||||
static void advance_iovec(struct iov_iter *i, size_t bytes)
|
||||
{
|
||||
BUG_ON(i->count < bytes);
|
||||
|
||||
if (likely(i->nr_segs == 1)) {
|
||||
i->iov_offset += bytes;
|
||||
i->count -= bytes;
|
||||
} else {
|
||||
const struct iovec *iov = i->iov;
|
||||
size_t base = i->iov_offset;
|
||||
unsigned long nr_segs = i->nr_segs;
|
||||
|
||||
/*
|
||||
* The !iov->iov_len check ensures we skip over unlikely
|
||||
* zero-length segments (without overruning the iovec).
|
||||
*/
|
||||
while (bytes || unlikely(i->count && !iov->iov_len)) {
|
||||
int copy;
|
||||
|
||||
copy = min(bytes, iov->iov_len - base);
|
||||
BUG_ON(!i->count || i->count < copy);
|
||||
i->count -= copy;
|
||||
bytes -= copy;
|
||||
base += copy;
|
||||
if (iov->iov_len == base) {
|
||||
iov++;
|
||||
nr_segs--;
|
||||
base = 0;
|
||||
}
|
||||
}
|
||||
i->iov = iov;
|
||||
i->iov_offset = base;
|
||||
i->nr_segs = nr_segs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fault in the first iovec of the given iov_iter, to a maximum length
|
||||
* of bytes. Returns 0 on success, or non-zero if the memory could not be
|
||||
@ -685,42 +676,6 @@ static size_t zero_bvec(size_t bytes, struct iov_iter *i)
|
||||
return wanted - bytes;
|
||||
}
|
||||
|
||||
static void advance_bvec(struct iov_iter *i, size_t bytes)
|
||||
{
|
||||
BUG_ON(i->count < bytes);
|
||||
|
||||
if (likely(i->nr_segs == 1)) {
|
||||
i->iov_offset += bytes;
|
||||
i->count -= bytes;
|
||||
} else {
|
||||
const struct bio_vec *bvec = i->bvec;
|
||||
size_t base = i->iov_offset;
|
||||
unsigned long nr_segs = i->nr_segs;
|
||||
|
||||
/*
|
||||
* The !iov->iov_len check ensures we skip over unlikely
|
||||
* zero-length segments (without overruning the iovec).
|
||||
*/
|
||||
while (bytes || unlikely(i->count && !bvec->bv_len)) {
|
||||
int copy;
|
||||
|
||||
copy = min(bytes, bvec->bv_len - base);
|
||||
BUG_ON(!i->count || i->count < copy);
|
||||
i->count -= copy;
|
||||
bytes -= copy;
|
||||
base += copy;
|
||||
if (bvec->bv_len == base) {
|
||||
bvec++;
|
||||
nr_segs--;
|
||||
base = 0;
|
||||
}
|
||||
}
|
||||
i->bvec = bvec;
|
||||
i->iov_offset = base;
|
||||
i->nr_segs = nr_segs;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t get_pages_bvec(struct iov_iter *i,
|
||||
struct page **pages, size_t maxsize, unsigned maxpages,
|
||||
size_t *start)
|
||||
@ -849,10 +804,7 @@ EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
|
||||
|
||||
void iov_iter_advance(struct iov_iter *i, size_t size)
|
||||
{
|
||||
if (i->type & ITER_BVEC)
|
||||
advance_bvec(i, size);
|
||||
else
|
||||
advance_iovec(i, size);
|
||||
iterate_and_advance(i, size, v, 0, 0)
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_advance);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user