diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2021-04-25 07:03:16 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2021-06-10 17:45:11 +0200 |
commit | 610c7a71543df32fcecf64004f974905f5881fb3 (patch) | |
tree | 7811b3b50723fe322b5c60c79fb3d8d38e5edd0b /lib/iov_iter.c | |
parent | iov_iter_alignment(): don't bother with iterate_all_kinds() (diff) | |
download | linux-610c7a71543df32fcecf64004f974905f5881fb3.tar.xz linux-610c7a71543df32fcecf64004f974905f5881fb3.zip |
iov_iter_gap_alignment(): get rid of iterate_all_kinds()
For one thing, it's only used for iovec (and makes sense only for those).
For another, here we don't care about iov_offset, since the beginning of
the first segment and the end of the last one are ignored. So it makes
a lot more sense to just walk through the iovec array...
We need to deal with the case of truncated iov_iter, but unlike the
situation with iov_iter_alignment() we don't care where the last
segment ends - just which segment is the last one.
[fixed a braino spotted by Qian Cai <quic_qiancai@quicinc.com>]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r-- | lib/iov_iter.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index ed9318358b68..6569e3f5d01d 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1398,23 +1398,24 @@ EXPORT_SYMBOL(iov_iter_alignment); unsigned long iov_iter_gap_alignment(const struct iov_iter *i) { unsigned long res = 0; + unsigned long v = 0; size_t size = i->count; + unsigned k; - if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { - WARN_ON(1); + if (WARN_ON(!iter_is_iovec(i))) return ~0U; - } - iterate_all_kinds(i, size, v, - (res |= (!res ? 0 : (unsigned long)v.iov_base) | - (size != v.iov_len ? size : 0), 0), - (res |= (!res ? 0 : (unsigned long)v.bv_offset) | - (size != v.bv_len ? size : 0)), - (res |= (!res ? 0 : (unsigned long)v.iov_base) | - (size != v.iov_len ? size : 0)), - (res |= (!res ? 0 : (unsigned long)v.bv_offset) | - (size != v.bv_len ? size : 0)) - ); + for (k = 0; k < i->nr_segs; k++) { + if (i->iov[k].iov_len) { + unsigned long base = (unsigned long)i->iov[k].iov_base; + if (v) // if not the first one + res |= base | v; // this start | previous end + v = base + i->iov[k].iov_len; + if (size <= i->iov[k].iov_len) + break; + size -= i->iov[k].iov_len; + } + } return res; } EXPORT_SYMBOL(iov_iter_gap_alignment); |