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: Arvind Sankar <nivedita@alum.mit.edu> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
8cdda87a44
commit
795ee49c1a
|
@ -87,26 +87,24 @@ struct bvec_iter_all {
|
|||
static inline bool bvec_iter_advance(const struct bio_vec *bv,
|
||||
struct bvec_iter *iter, unsigned bytes)
|
||||
{
|
||||
unsigned int idx = iter->bi_idx;
|
||||
|
||||
if (WARN_ONCE(bytes > iter->bi_size,
|
||||
"Attempted to advance past end of bvec iter\n")) {
|
||||
iter->bi_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (bytes) {
|
||||
const struct bio_vec *cur = bv + iter->bi_idx;
|
||||
unsigned len = min3(bytes, iter->bi_size,
|
||||
cur->bv_len - iter->bi_bvec_done);
|
||||
iter->bi_size -= bytes;
|
||||
bytes += iter->bi_bvec_done;
|
||||
|
||||
bytes -= len;
|
||||
iter->bi_size -= len;
|
||||
iter->bi_bvec_done += len;
|
||||
while (bytes && bytes >= bv[idx].bv_len) {
|
||||
bytes -= bv[idx].bv_len;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (iter->bi_bvec_done == cur->bv_len) {
|
||||
iter->bi_bvec_done = 0;
|
||||
iter->bi_idx++;
|
||||
}
|
||||
}
|
||||
iter->bi_idx = idx;
|
||||
iter->bi_bvec_done = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue