Commit 795ee49c authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe

block: optimise bvec_iter_advance()

bvec_iter_advance() is quite popular, but compilers fail to do proper
alias analysis and optimise it good enough. The assembly is checked
for gcc 9.2, x86-64.

- remove @iter->bi_size from min(...), as it's always less than @bytes.
Modify at the beginning and forget about it.

- the compiler isn't able to collapse memory dependencies and remove
writes in the loop. Help it by explicitely using local vars.
Signed-off-by: default avatarArvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 8cdda87a
...@@ -87,26 +87,24 @@ struct bvec_iter_all { ...@@ -87,26 +87,24 @@ struct bvec_iter_all {
static inline bool bvec_iter_advance(const struct bio_vec *bv, static inline bool bvec_iter_advance(const struct bio_vec *bv,
struct bvec_iter *iter, unsigned bytes) struct bvec_iter *iter, unsigned bytes)
{ {
unsigned int idx = iter->bi_idx;
if (WARN_ONCE(bytes > iter->bi_size, if (WARN_ONCE(bytes > iter->bi_size,
"Attempted to advance past end of bvec iter\n")) { "Attempted to advance past end of bvec iter\n")) {
iter->bi_size = 0; iter->bi_size = 0;
return false; return false;
} }
while (bytes) { iter->bi_size -= bytes;
const struct bio_vec *cur = bv + iter->bi_idx; bytes += iter->bi_bvec_done;
unsigned len = min3(bytes, iter->bi_size,
cur->bv_len - iter->bi_bvec_done);
bytes -= len;
iter->bi_size -= len;
iter->bi_bvec_done += len;
if (iter->bi_bvec_done == cur->bv_len) { while (bytes && bytes >= bv[idx].bv_len) {
iter->bi_bvec_done = 0; bytes -= bv[idx].bv_len;
iter->bi_idx++; idx++;
}
} }
iter->bi_idx = idx;
iter->bi_bvec_done = bytes;
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment