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)
|
static size_t copy_to_iter_iovec(void *from, size_t bytes, struct iov_iter *i)
|
||||||
{
|
{
|
||||||
size_t skip, copy, left, wanted;
|
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;
|
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
|
* 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
|
* 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;
|
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,
|
static ssize_t get_pages_bvec(struct iov_iter *i,
|
||||||
struct page **pages, size_t maxsize, unsigned maxpages,
|
struct page **pages, size_t maxsize, unsigned maxpages,
|
||||||
size_t *start)
|
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)
|
void iov_iter_advance(struct iov_iter *i, size_t size)
|
||||||
{
|
{
|
||||||
if (i->type & ITER_BVEC)
|
iterate_and_advance(i, size, v, 0, 0)
|
||||||
advance_bvec(i, size);
|
|
||||||
else
|
|
||||||
advance_iovec(i, size);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iov_iter_advance);
|
EXPORT_SYMBOL(iov_iter_advance);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue