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 <[email protected]>
---
 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 c9f426905ef9..1364f491af87 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -826,10 +826,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;
@@ -882,6 +890,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)
 {
@@ -890,9 +931,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;
@@ -906,8 +946,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);
@@ -922,7 +962,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) {
@@ -930,40 +969,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));
@@ -976,13 +996,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.42.0


Reply via email to