[PATCH v3 3/4] bcachefs: refactor fiemap processing into extent helper and struct

Brian Foster
2024-04-08T14:46:52Z

The bulk of the loop in bch2_fiemap() involves processing the
current extent key from the iter, including following indirections
and trimming the extent size and such. This patch makes a few
changes to reduce the size of the loop and facilitate future changes
to support delalloc extents.

Define a new bch_fiemap_extent structure to wrap the bkey buffer
that holds the extent key to report to userspace along with
associated fiemap flags. Update bch2_fill_extent() to take the
bch_fiemap_extent as a param instead of the individual fields.
Finally, lift the bulk of the extent processing into a
bch2_fiemap_extent() helper that takes the current key and formats
the bch_fiemap_extent appropriately for the fill function.

No functional changes intended by this patch.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
fs/bcachefs/fs.c | 90 +++++++++++++++++++++++++++++-------------------
1 file changed, 55 insertions(+), 35 deletions(-)

diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 9c86749b256e..9f14eb256c09 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -896,10 +896,18 @@ static int bch2_tmpfile(struct mnt_idmap *idmap,
return finish_open_simple(file, 0);
}

+struct bch_fiemap_extent {
+ struct bkey_buf kbuf;
+ unsigned flags;
+};
+
static int bch2_fill_extent(struct bch_fs *c,
struct fiemap_extent_info *info,
- struct bkey_s_c k, unsigned flags)
+ struct bch_fiemap_extent *fe)
{
+ struct bkey_s_c k = bkey_i_to_s_c(fe->kbuf.k);
+ unsigned flags = fe->flags;
+
if (bkey_extent_is_direct_data(k.k)) {
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry;
@@ -952,6 +960,39 @@ static int bch2_fill_extent(struct bch_fs *c,
}
}

+static int bch2_fiemap_extent(struct btree_trans *trans,
+ struct btree_iter *iter, struct bkey_s_c k,
+ struct bch_fiemap_extent *cur)
+{
+ unsigned offset_into_extent, sectors;
+ enum btree_id data_btree = BTREE_ID_extents;
+ int ret;
+
+ offset_into_extent = iter->pos.offset - bkey_start_offset(k.k);
+ sectors = k.k->size - offset_into_extent;
+
+ bch2_bkey_buf_reassemble(&cur->kbuf, trans->c, k);
+
+ ret = bch2_read_indirect_extent(trans, &data_btree, &offset_into_extent,
+ &cur->kbuf);
+ if (ret)
+ return ret;
+
+ k = bkey_i_to_s_c(cur->kbuf.k);
+ sectors = min(sectors, k.k->size - offset_into_extent);
+
+ bch2_cut_front(POS(k.k->p.inode,
+ bkey_start_offset(k.k) + offset_into_extent),
+ cur->kbuf.k);
+ bch2_key_resize(&cur->kbuf.k->k, sectors);
+ cur->kbuf.k->k.p = iter->pos;
+ cur->kbuf.k->k.p.offset += cur->kbuf.k->k.size;
+
+ cur->flags = 0;
+
+ return 0;
+}
+
static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
u64 start, u64 len)
{
@@ -960,9 +1001,8 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
struct btree_trans *trans;
struct btree_iter iter;
struct bkey_s_c k;
- struct bkey_buf cur, prev;
+ struct bch_fiemap_extent cur, prev;
struct bpos end = POS(ei->v.i_ino, (start + len) >> 9);
- unsigned offset_into_extent, sectors;
bool have_extent = false;
u32 snapshot;
int ret = 0;
@@ -976,8 +1016,8 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,

start >>= 9;

- bch2_bkey_buf_init(&cur);
- bch2_bkey_buf_init(&prev);
+ bch2_bkey_buf_init(&cur.kbuf);
+ bch2_bkey_buf_init(&prev.kbuf);
trans = bch2_trans_get(c);
retry:
bch2_trans_begin(trans);
@@ -992,7 +1032,6 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
while (!(ret = btree_trans_too_many_iters(trans)) &&
(k = bch2_btree_iter_peek_upto(&iter, end)).k &&
!(ret = bkey_err(k))) {
- enum btree_id data_btree = BTREE_ID_extents;

if (!bkey_extent_is_data(k.k) &&
k.k->type != KEY_TYPE_reservation) {
@@ -1000,40 +1039,21 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
continue;
}

- offset_into_extent = iter.pos.offset -
- bkey_start_offset(k.k);
- sectors = k.k->size - offset_into_extent;
-
- bch2_bkey_buf_reassemble(&cur, c, k);
-
- ret = bch2_read_indirect_extent(trans, &data_btree,
- &offset_into_extent, &cur);
+ ret = bch2_fiemap_extent(trans, &iter, k, &cur);
if (ret)
break;
-
- k = bkey_i_to_s_c(cur.k);
- bch2_bkey_buf_realloc(&prev, c, k.k->u64s);
-
- sectors = min(sectors, k.k->size - offset_into_extent);
- start = iter.pos.offset + sectors;
-
- bch2_cut_front(POS(k.k->p.inode,
- bkey_start_offset(k.k) +
- offset_into_extent),
- cur.k);
- bch2_key_resize(&cur.k->k, sectors);
- cur.k->k.p = iter.pos;
- cur.k->k.p.offset += cur.k->k.size;
+ bch2_bkey_buf_realloc(&prev.kbuf, c, cur.kbuf.k->k.u64s);
+ start = cur.kbuf.k->k.p.offset;

if (have_extent) {
bch2_trans_unlock(trans);
- ret = bch2_fill_extent(c, info,
- bkey_i_to_s_c(prev.k), 0);
+ ret = bch2_fill_extent(c, info, &prev);
if (ret)
break;
}

- bkey_copy(prev.k, cur.k);
+ bkey_copy(prev.kbuf.k, cur.kbuf.k);
+ prev.flags = cur.flags;
have_extent = true;

bch2_btree_iter_set_pos(&iter, POS(iter.pos.inode, start));
@@ -1046,13 +1066,13 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,

if (!ret && have_extent) {
bch2_trans_unlock(trans);
- ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k),
- FIEMAP_EXTENT_LAST);
+ prev.flags |= FIEMAP_EXTENT_LAST;
+ ret = bch2_fill_extent(c, info, &prev);
}

bch2_trans_put(trans);
- bch2_bkey_buf_exit(&cur, c);
- bch2_bkey_buf_exit(&prev, c);
+ bch2_bkey_buf_exit(&cur.kbuf, c);
+ bch2_bkey_buf_exit(&prev.kbuf, c);
return ret < 0 ? ret : 0;
}

--
2.44.0