iov_iter: massage iterate_iovec and iterate_kvec to logics similar to iterate_bvec
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 26 Apr 2021 03:46:09 +0000 (23:46 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 10 Jun 2021 15:45:16 +0000 (11:45 -0400)
Premature optimization is the root of all evil...  Trying
to unroll the first pass through the loop makes it harder
to follow and not just for readers - compiler ends up
generating worse code than it would on a "non-optimized"
loop.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
lib/iov_iter.c

index 763114a..2098059 100644 (file)
 
 #define PIPE_PARANOIA /* for now */
 
-#define iterate_iovec(i, n, __v, __p, skip, STEP) {    \
-       size_t left;                                    \
-       size_t wanted = n;                              \
-       __p = i->iov;                                   \
-       __v.iov_len = min(n, __p->iov_len - skip);      \
-       if (likely(__v.iov_len)) {                      \
-               __v.iov_base = __p->iov_base + skip;    \
-               left = (STEP);                          \
-               __v.iov_len -= left;                    \
-               skip += __v.iov_len;                    \
-               n -= __v.iov_len;                       \
-       } else {                                        \
-               left = 0;                               \
-       }                                               \
-       while (unlikely(!left && n)) {                  \
-               __p++;                                  \
-               __v.iov_len = min(n, __p->iov_len);     \
-               if (unlikely(!__v.iov_len))             \
-                       continue;                       \
-               __v.iov_base = __p->iov_base;           \
-               left = (STEP);                          \
-               __v.iov_len -= left;                    \
-               skip = __v.iov_len;                     \
-               n -= __v.iov_len;                       \
-       }                                               \
-       n = wanted - n;                                 \
+#define iterate_iovec(i, n, __v, __p, skip, STEP) {            \
+       size_t left;                                            \
+       size_t wanted = n;                                      \
+       __p = i->iov;                                           \
+       do {                                                    \
+               __v.iov_len = min(n, __p->iov_len - skip);      \
+               if (likely(__v.iov_len)) {                      \
+                       __v.iov_base = __p->iov_base + skip;    \
+                       left = (STEP);                          \
+                       __v.iov_len -= left;                    \
+                       skip += __v.iov_len;                    \
+                       n -= __v.iov_len;                       \
+                       if (skip < __p->iov_len)                \
+                               break;                          \
+               }                                               \
+               __p++;                                          \
+               skip = 0;                                       \
+       } while (n);                                            \
+       n = wanted - n;                                         \
 }
 
-#define iterate_kvec(i, n, __v, __p, skip, STEP) {     \
-       size_t wanted = n;                              \
-       __p = i->kvec;                                  \
-       __v.iov_len = min(n, __p->iov_len - skip);      \
-       if (likely(__v.iov_len)) {                      \
-               __v.iov_base = __p->iov_base + skip;    \
-               (void)(STEP);                           \
-               skip += __v.iov_len;                    \
-               n -= __v.iov_len;                       \
-       }                                               \
-       while (unlikely(n)) {                           \
-               __p++;                                  \
-               __v.iov_len = min(n, __p->iov_len);     \
-               if (unlikely(!__v.iov_len))             \
-                       continue;                       \
-               __v.iov_base = __p->iov_base;           \
-               (void)(STEP);                           \
-               skip = __v.iov_len;                     \
-               n -= __v.iov_len;                       \
-       }                                               \
-       n = wanted;                                     \
+#define iterate_kvec(i, n, __v, __p, skip, STEP) {             \
+       size_t wanted = n;                                      \
+       __p = i->kvec;                                          \
+       do {                                                    \
+               __v.iov_len = min(n, __p->iov_len - skip);      \
+               if (likely(__v.iov_len)) {                      \
+                       __v.iov_base = __p->iov_base + skip;    \
+                       (void)(STEP);                           \
+                       skip += __v.iov_len;                    \
+                       n -= __v.iov_len;                       \
+                       if (skip < __p->iov_len)                \
+                               break;                          \
+               }                                               \
+               __p++;                                          \
+               skip = 0;                                       \
+       } while (n);                                            \
+       n = wanted - n;                                         \
 }
 
 #define iterate_bvec(i, n, __v, __bi, skip, STEP) {    \
                        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;                           \
                } else if (iov_iter_is_bvec(i)) {               \
                        const struct kvec *kvec;                \
                        struct kvec v;                          \
                        iterate_kvec(i, n, v, kvec, skip, (K))  \
-                       if (skip == kvec->iov_len) {            \
-                               kvec++;                         \
-                               skip = 0;                       \
-                       }                                       \
                        i->nr_segs -= kvec - i->kvec;           \
                        i->kvec = kvec;                         \
                } else if (iov_iter_is_xarray(i)) {             \