summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-08-28 20:03:51 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2020-05-06 17:14:15 -0400
commit9b2540475287237fc542e0b36c7a02d960aec795 (patch)
treee635808f6b71ed4178efcc00c7f14117ff6da5e9
parent0aecf705738551bc43e6ee2a948fb91b855309b0 (diff)
block: optimize bvec_iter_advance()
This results in fewer branches/cmov instructions in the inner loop Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--include/linux/bvec.h32
1 files changed, 21 insertions, 11 deletions
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index fe7a22dd133b..843d434df4e8 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -72,26 +72,36 @@ struct bvec_iter {
static inline bool bvec_iter_advance(const struct bio_vec *bv,
struct bvec_iter *iter, unsigned bytes)
{
+ unsigned bvec_len;
+
if (WARN_ONCE(bytes > iter->bi_size,
"Attempted to advance past end of bvec iter\n")) {
iter->bi_size = 0;
return false;
}
- while (bytes) {
- unsigned iter_len = bvec_iter_len(bv, *iter);
- unsigned len = min(bytes, iter_len);
+ iter->bi_size -= bytes;
+ iter->bi_done += bytes;
- bytes -= len;
- iter->bi_size -= len;
- iter->bi_bvec_done += len;
- iter->bi_done += len;
+ bv += iter->bi_idx;
- if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {
- iter->bi_bvec_done = 0;
- iter->bi_idx++;
- }
+ while (1) {
+ /* don't deref bv when bytes == 0: */
+ if (!bytes)
+ break;
+
+ bvec_len = bv->bv_len - iter->bi_bvec_done;
+ if (bytes < bvec_len)
+ break;
+
+ bytes -= bvec_len;
+
+ iter->bi_bvec_done = 0;
+ iter->bi_idx++;
+ bv++;
}
+
+ iter->bi_bvec_done += bytes;
return true;
}