Commit 7d5224fc authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Optimize fiemap

Reflink caused fiemap performance to regress badly - this gets us back
to where we were.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 4e1510c3
...@@ -1203,6 +1203,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1203,6 +1203,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
BKEY_PADDED(k) cur, prev; BKEY_PADDED(k) cur, prev;
struct bpos end = POS(ei->v.i_ino, (start + len) >> 9);
unsigned offset_into_extent, sectors; unsigned offset_into_extent, sectors;
bool have_extent = false; bool have_extent = false;
int ret = 0; int ret = 0;
...@@ -1217,14 +1218,16 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1217,14 +1218,16 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
bch2_trans_init(&trans, c, 0, 0); bch2_trans_init(&trans, c, 0, 0);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
POS(ei->v.i_ino, start >> 9), POS(ei->v.i_ino, start >> 9), 0);
BTREE_ITER_SLOTS); retry:
while ((k = bch2_btree_iter_peek(iter)).k &&
while (bkey_cmp(iter->pos, POS(ei->v.i_ino, (start + len) >> 9)) < 0) { !(ret = bkey_err(k)) &&
k = bch2_btree_iter_peek_slot(iter); bkey_cmp(iter->pos, end) < 0) {
ret = bkey_err(k); if (!bkey_extent_is_data(k.k) &&
if (ret) k.k->type != KEY_TYPE_reservation) {
goto err; bch2_btree_iter_next(iter);
continue;
}
bkey_reassemble(&cur.k, k); bkey_reassemble(&cur.k, k);
k = bkey_i_to_s_c(&cur.k); k = bkey_i_to_s_c(&cur.k);
...@@ -1240,34 +1243,37 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1240,34 +1243,37 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
sectors = min(sectors, k.k->size - offset_into_extent); sectors = min(sectors, k.k->size - offset_into_extent);
bch2_cut_front(POS(k.k->p.inode, if (offset_into_extent)
bkey_start_offset(k.k) + offset_into_extent), bch2_cut_front(POS(k.k->p.inode,
&cur.k); bkey_start_offset(k.k) +
offset_into_extent),
&cur.k);
bch2_key_resize(&cur.k.k, sectors); bch2_key_resize(&cur.k.k, sectors);
cur.k.k.p.offset = iter->pos.offset + cur.k.k.size; cur.k.k.p.offset = iter->pos.offset + cur.k.k.size;
if (bkey_extent_is_data(k.k) || if (have_extent) {
k.k->type == KEY_TYPE_reservation) { ret = bch2_fill_extent(c, info,
if (have_extent) { bkey_i_to_s_c(&prev.k), 0);
ret = bch2_fill_extent(c, info, if (ret)
bkey_i_to_s_c(&prev.k), 0); break;
if (ret)
break;
}
bkey_copy(&prev.k, &cur.k);
have_extent = true;
} }
bch2_btree_iter_set_pos(iter, bkey_copy(&prev.k, &cur.k);
POS(iter->pos.inode, have_extent = true;
iter->pos.offset + sectors));
if (k.k->type == KEY_TYPE_reflink_v)
bch2_btree_iter_set_pos(iter, k.k->p);
else
bch2_btree_iter_next(iter);
} }
if (ret == -EINTR)
goto retry;
if (!ret && have_extent) if (!ret && have_extent)
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(&prev.k), ret = bch2_fill_extent(c, info, bkey_i_to_s_c(&prev.k),
FIEMAP_EXTENT_LAST); FIEMAP_EXTENT_LAST);
err:
ret = bch2_trans_exit(&trans) ?: ret; ret = bch2_trans_exit(&trans) ?: ret;
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
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