iov_iter: use bvec iterator to implement iterate_bvec()
authorMing Lei <ming.lei@canonical.com>
Mon, 30 May 2016 13:34:32 +0000 (21:34 +0800)
committerJens Axboe <axboe@fb.com>
Thu, 9 Jun 2016 16:02:47 +0000 (10:02 -0600)
bvec has one native/mature iterator for long time, so not
necessary to use the reinvented wheel for iterating bvecs
in lib/iov_iter.c.

Two ITER_BVEC test cases are run:
- xfstest(-g auto) on loop dio/aio, no regression found
- swap file works well under extreme stress(stress-ng --all 64 -t
  800 -v), and lots of OOMs are triggerd, and the whole
system still survives

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Tested-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
lib/iov_iter.c

index 0cd522753ff5c6830673e6d9f0cb46d70b4c9c23..d67c8288d95dba435bf608b6258c3168c8206d7a 100644 (file)
        n = wanted;                                     \
 }
 
-#define iterate_bvec(i, n, __v, __p, skip, STEP) {     \
-       size_t wanted = n;                              \
-       __p = i->bvec;                                  \
-       __v.bv_len = min_t(size_t, n, __p->bv_len - skip);      \
-       if (likely(__v.bv_len)) {                       \
-               __v.bv_page = __p->bv_page;             \
-               __v.bv_offset = __p->bv_offset + skip;  \
-               (void)(STEP);                           \
-               skip += __v.bv_len;                     \
-               n -= __v.bv_len;                        \
-       }                                               \
-       while (unlikely(n)) {                           \
-               __p++;                                  \
-               __v.bv_len = min_t(size_t, n, __p->bv_len);     \
-               if (unlikely(!__v.bv_len))              \
+#define iterate_bvec(i, n, __v, __bi, skip, STEP) {    \
+       struct bvec_iter __start;                       \
+       __start.bi_size = n;                            \
+       __start.bi_bvec_done = skip;                    \
+       __start.bi_idx = 0;                             \
+       for_each_bvec(__v, i->bvec, __bi, __start) {    \
+               if (!__v.bv_len)                        \
                        continue;                       \
-               __v.bv_page = __p->bv_page;             \
-               __v.bv_offset = __p->bv_offset;         \
                (void)(STEP);                           \
-               skip = __v.bv_len;                      \
-               n -= __v.bv_len;                        \
        }                                               \
-       n = wanted;                                     \
 }
 
 #define iterate_all_kinds(i, n, v, I, B, K) {                  \
        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))          \
+               struct bvec_iter __bi;                          \
+               iterate_bvec(i, n, v, __bi, skip, (B))          \
        } else if (unlikely(i->type & ITER_KVEC)) {             \
                const struct kvec *kvec;                        \
                struct kvec v;                                  \
        if (i->count) {                                         \
                size_t skip = i->iov_offset;                    \
                if (unlikely(i->type & ITER_BVEC)) {            \
-                       const struct bio_vec *bvec;             \
+                       const struct bio_vec *bvec = i->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;                         \
+                       struct bvec_iter __bi;                  \
+                       iterate_bvec(i, n, v, __bi, skip, (B))  \
+                       i->bvec = __bvec_iter_bvec(i->bvec, __bi);      \
+                       i->nr_segs -= i->bvec - bvec;           \
+                       skip = __bi.bi_bvec_done;               \
                } else if (unlikely(i->type & ITER_KVEC)) {     \
                        const struct kvec *kvec;                \
                        struct kvec v;                          \