|
@@ -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);
|
|
|
|