bcachefs: Convert raw uses of bch2_btree_iter_link() to new transactions
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 12 Jul 2018 23:19:41 +0000 (19:19 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:07 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs-io.c
fs/bcachefs/fsck.c

index 56d2117..b53fbdc 100644 (file)
@@ -390,7 +390,8 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
        struct bchfs_write_op *op = container_of(wop,
                                struct bchfs_write_op, op);
        struct keylist *keys = &op->op.insert_keys;
-       struct btree_iter extent_iter, inode_iter;
+       struct btree_trans trans;
+       struct btree_iter *extent_iter, *inode_iter = NULL;
        struct bchfs_extent_trans_hook hook;
        struct bkey_i *k = bch2_keylist_front(keys);
        s64 orig_sectors_added = op->sectors_added;
@@ -398,12 +399,13 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
 
        BUG_ON(k->k.p.inode != op->inode->v.i_ino);
 
-       bch2_btree_iter_init(&extent_iter, wop->c, BTREE_ID_EXTENTS,
-                            bkey_start_pos(&bch2_keylist_front(keys)->k),
-                            BTREE_ITER_INTENT);
-       bch2_btree_iter_init(&inode_iter, wop->c, BTREE_ID_INODES,
-                            POS(extent_iter.pos.inode, 0),
-                            BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+       bch2_trans_init(&trans, wop->c);
+
+       extent_iter = bch2_trans_get_iter(&trans,
+                               BTREE_ID_EXTENTS,
+                               bkey_start_pos(&bch2_keylist_front(keys)->k),
+                               BTREE_ITER_INTENT);
+       BUG_ON(IS_ERR(extent_iter));
 
        hook.op                 = op;
        hook.hook.fn            = bchfs_extent_update_hook;
@@ -417,23 +419,28 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
                        hook.need_inode_update = true;
 
                /* optimization for fewer transaction restarts: */
-               ret = bch2_btree_iter_traverse(&extent_iter);
+               ret = bch2_btree_iter_traverse(extent_iter);
                if (ret)
                        goto err;
 
                if (hook.need_inode_update) {
                        struct bkey_s_c inode;
 
-                       if (!btree_iter_linked(&inode_iter))
-                               bch2_btree_iter_link(&extent_iter, &inode_iter);
+                       if (!inode_iter) {
+                               inode_iter = bch2_trans_get_iter(&trans,
+                                       BTREE_ID_INODES,
+                                       POS(extent_iter->pos.inode, 0),
+                                       BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+                               BUG_ON(IS_ERR(inode_iter));
+                       }
 
-                       inode = bch2_btree_iter_peek_slot(&inode_iter);
+                       inode = bch2_btree_iter_peek_slot(inode_iter);
                        if ((ret = btree_iter_err(inode)))
                                goto err;
 
                        if (WARN_ONCE(inode.k->type != BCH_INODE_FS,
                                      "inode %llu not found when updating",
-                                     extent_iter.pos.inode)) {
+                                     extent_iter->pos.inode)) {
                                ret = -ENOENT;
                                break;
                        }
@@ -441,7 +448,7 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
                        if (WARN_ONCE(bkey_bytes(inode.k) >
                                      sizeof(hook.inode_p),
                                      "inode %llu too big (%zu bytes, buf %zu)",
-                                     extent_iter.pos.inode,
+                                     extent_iter->pos.inode,
                                      bkey_bytes(inode.k),
                                      sizeof(hook.inode_p))) {
                                ret = -ENOENT;
@@ -453,7 +460,7 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
                                               &hook.inode_u);
                        if (WARN_ONCE(ret,
                                      "error %i unpacking inode %llu",
-                                     ret, extent_iter.pos.inode)) {
+                                     ret, extent_iter->pos.inode)) {
                                ret = -ENOENT;
                                break;
                        }
@@ -463,8 +470,8 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
                                        BTREE_INSERT_NOFAIL|
                                        BTREE_INSERT_ATOMIC|
                                        BTREE_INSERT_USE_RESERVE,
-                                       BTREE_INSERT_ENTRY(&extent_iter, k),
-                                       BTREE_INSERT_ENTRY_EXTRA_RES(&inode_iter,
+                                       BTREE_INSERT_ENTRY(extent_iter, k),
+                                       BTREE_INSERT_ENTRY_EXTRA_RES(inode_iter,
                                                        &hook.inode_p.inode.k_i, 2));
                } else {
                        ret = bch2_btree_insert_at(wop->c, &wop->res,
@@ -472,10 +479,10 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
                                        BTREE_INSERT_NOFAIL|
                                        BTREE_INSERT_ATOMIC|
                                        BTREE_INSERT_USE_RESERVE,
-                                       BTREE_INSERT_ENTRY(&extent_iter, k));
+                                       BTREE_INSERT_ENTRY(extent_iter, k));
                }
 
-               BUG_ON(bkey_cmp(extent_iter.pos, bkey_start_pos(&k->k)));
+               BUG_ON(bkey_cmp(extent_iter->pos, bkey_start_pos(&k->k)));
 
                if (WARN_ONCE(!ret != !k->k.size,
                              "ret %i k->size %u", ret, k->k.size))
@@ -486,12 +493,11 @@ err:
                if (ret)
                        break;
 
-               BUG_ON(bkey_cmp(extent_iter.pos, k->k.p) < 0);
+               BUG_ON(bkey_cmp(extent_iter->pos, k->k.p) < 0);
                bch2_keylist_pop_front(keys);
        } while (!bch2_keylist_empty(keys));
 
-       bch2_btree_iter_unlock(&extent_iter);
-       bch2_btree_iter_unlock(&inode_iter);
+       bch2_trans_exit(&trans);
 
        if (op->is_dio) {
                struct dio_write *dio = container_of(op, struct dio_write, iop);
@@ -2363,8 +2369,8 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
        struct address_space *mapping = inode->v.i_mapping;
-       struct btree_iter src;
-       struct btree_iter dst;
+       struct btree_trans trans;
+       struct btree_iter *src, *dst;
        BKEY_PADDED(k) copy;
        struct bkey_s_c k;
        struct i_sectors_hook i_sectors_hook = i_sectors_hook_init(inode, 0);
@@ -2374,13 +2380,17 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
        if ((offset | len) & (block_bytes(c) - 1))
                return -EINVAL;
 
-       bch2_btree_iter_init(&dst, c, BTREE_ID_EXTENTS,
+       bch2_trans_init(&trans, c);
+
+       dst = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
                             POS(inode->v.i_ino, offset >> 9),
                             BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+       BUG_ON(IS_ERR(dst));
+
        /* position will be set from dst iter's position: */
-       bch2_btree_iter_init(&src, c, BTREE_ID_EXTENTS, POS_MIN,
+       src = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
                             BTREE_ITER_SLOTS);
-       bch2_btree_iter_link(&src, &dst);
+       BUG_ON(IS_ERR(src));
 
        /*
         * We need i_mutex to keep the page cache consistent with the extents
@@ -2409,24 +2419,24 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
        if (ret)
                goto err;
 
-       while (bkey_cmp(dst.pos,
+       while (bkey_cmp(dst->pos,
                        POS(inode->v.i_ino,
                            round_up(new_size, PAGE_SIZE) >> 9)) < 0) {
                struct disk_reservation disk_res;
 
-               bch2_btree_iter_set_pos(&src,
-                       POS(dst.pos.inode, dst.pos.offset + (len >> 9)));
+               bch2_btree_iter_set_pos(src,
+                       POS(dst->pos.inode, dst->pos.offset + (len >> 9)));
 
-               k = bch2_btree_iter_peek_slot(&src);
+               k = bch2_btree_iter_peek_slot(src);
                if ((ret = btree_iter_err(k)))
                        goto btree_iter_err;
 
                bkey_reassemble(&copy.k, k);
 
-               bch2_cut_front(src.pos, &copy.k);
+               bch2_cut_front(src->pos, &copy.k);
                copy.k.k.p.offset -= len >> 9;
 
-               BUG_ON(bkey_cmp(dst.pos, bkey_start_pos(&copy.k.k)));
+               BUG_ON(bkey_cmp(dst->pos, bkey_start_pos(&copy.k.k)));
 
                ret = bch2_disk_reservation_get(c, &disk_res, copy.k.k.size,
                                bch2_extent_nr_dirty_ptrs(bkey_i_to_s_c(&copy.k)),
@@ -2437,14 +2447,13 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
                                           &inode->ei_journal_seq,
                                           BTREE_INSERT_ATOMIC|
                                           BTREE_INSERT_NOFAIL,
-                                          BTREE_INSERT_ENTRY(&dst, &copy.k));
+                                          BTREE_INSERT_ENTRY(dst, &copy.k));
                bch2_disk_reservation_put(c, &disk_res);
 btree_iter_err:
                if (ret == -EINTR)
                        ret = 0;
                if (ret) {
-                       bch2_btree_iter_unlock(&src);
-                       bch2_btree_iter_unlock(&dst);
+                       bch2_trans_exit(&trans);
                        goto err_put_sectors_dirty;
                }
                /*
@@ -2452,11 +2461,10 @@ btree_iter_err:
                 * pointers... which isn't a _super_ serious problem...
                 */
 
-               bch2_btree_iter_cond_resched(&src);
+               bch2_btree_iter_cond_resched(src);
        }
 
-       bch2_btree_iter_unlock(&src);
-       bch2_btree_iter_unlock(&dst);
+       bch2_trans_exit(&trans);
 
        ret = bch2_inode_truncate(c, inode->v.i_ino,
                                 round_up(new_size, block_bytes(c)) >> 9,
index c352fa0..50e310f 100644 (file)
@@ -127,16 +127,22 @@ static int walk_inode(struct bch_fs *c, struct inode_walker *w, u64 inum)
 
 struct hash_check {
        struct bch_hash_info    info;
-       struct btree_iter       chain;
-       struct btree_iter       iter;
+       struct btree_trans      *trans;
+
+       /* start of current chain of hash collisions: */
+       struct btree_iter       *chain;
+
+       /* next offset in current chain of hash collisions: */
        u64                     next;
 };
 
 static void hash_check_init(const struct bch_hash_desc desc,
-                           struct hash_check *h, struct bch_fs *c)
+                           struct btree_trans *trans,
+                           struct hash_check *h)
 {
-       bch2_btree_iter_init(&h->chain, c, desc.btree_id, POS_MIN, 0);
-       bch2_btree_iter_init(&h->iter, c, desc.btree_id, POS_MIN, 0);
+       h->trans = trans;
+       h->chain = bch2_trans_get_iter(trans, desc.btree_id, POS_MIN, 0);
+       h->next = -1;
 }
 
 static void hash_check_set_inode(struct hash_check *h, struct bch_fs *c,
@@ -207,6 +213,42 @@ err:
        return ret;
 }
 
+static int hash_check_duplicates(const struct bch_hash_desc desc,
+                                struct hash_check *h, struct bch_fs *c,
+                                struct btree_iter *k_iter, struct bkey_s_c k)
+{
+       struct btree_iter *iter;
+       struct bkey_s_c k2;
+       char buf[200];
+       int ret = 0;
+
+       if (!bkey_cmp(h->chain->pos, k_iter->pos))
+               return 0;
+
+       iter = bch2_trans_copy_iter(h->trans, h->chain);
+       BUG_ON(IS_ERR(iter));
+
+       for_each_btree_key_continue(iter, 0, k2) {
+               if (bkey_cmp(k2.k->p, k.k->p) >= 0)
+                       break;
+
+               if (fsck_err_on(k2.k->type == desc.key_type &&
+                               !desc.cmp_bkey(k, k2), c,
+                               "duplicate hash table keys:\n%s",
+                               (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
+                                                      buf, sizeof(buf), k), buf))) {
+                       ret = fsck_hash_delete_at(desc, &h->info, k_iter);
+                       if (ret)
+                               return ret;
+                       ret = 1;
+                       break;
+               }
+       }
+fsck_err:
+       bch2_trans_iter_free(h->trans, iter);
+       return ret;
+}
+
 static int hash_check_key(const struct bch_hash_desc desc,
                          struct hash_check *h, struct bch_fs *c,
                          struct btree_iter *k_iter, struct bkey_s_c k)
@@ -219,13 +261,8 @@ static int hash_check_key(const struct bch_hash_desc desc,
            k.k->type != desc.key_type)
                return 0;
 
-       if (k.k->p.offset != h->next) {
-               if (!btree_iter_linked(&h->chain)) {
-                       bch2_btree_iter_link(k_iter, &h->chain);
-                       bch2_btree_iter_link(k_iter, &h->iter);
-               }
-               bch2_btree_iter_copy(&h->chain, k_iter);
-       }
+       if (k.k->p.offset != h->next)
+               bch2_btree_iter_copy(h->chain, k_iter);
        h->next = k.k->p.offset + 1;
 
        if (k.k->type != desc.key_type)
@@ -233,11 +270,11 @@ static int hash_check_key(const struct bch_hash_desc desc,
 
        hashed = desc.hash_bkey(&h->info, k);
 
-       if (fsck_err_on(hashed < h->chain.pos.offset ||
+       if (fsck_err_on(hashed < h->chain->pos.offset ||
                        hashed > k.k->p.offset, c,
                        "hash table key at wrong offset: %llu, "
                        "hashed to %llu chain starts at %llu\n%s",
-                       k.k->p.offset, hashed, h->chain.pos.offset,
+                       k.k->p.offset, hashed, h->chain->pos.offset,
                        (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
                                               buf, sizeof(buf), k), buf))) {
                ret = hash_redo_key(desc, h, c, k_iter, k, hashed);
@@ -248,25 +285,7 @@ static int hash_check_key(const struct bch_hash_desc desc,
                return 1;
        }
 
-       if (!bkey_cmp(h->chain.pos, k_iter->pos))
-               return 0;
-
-       bch2_btree_iter_copy(&h->iter, &h->chain);
-       while (bkey_cmp(h->iter.pos, k_iter->pos) < 0) {
-               struct bkey_s_c k2 = bch2_btree_iter_peek(&h->iter);
-
-               if (fsck_err_on(k2.k->type == desc.key_type &&
-                               !desc.cmp_bkey(k, k2), c,
-                               "duplicate hash table keys:\n%s",
-                               (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
-                                                      buf, sizeof(buf), k), buf))) {
-                       ret = fsck_hash_delete_at(desc, &h->info, &h->iter);
-                       if (ret)
-                               return ret;
-                       return 1;
-               }
-               bch2_btree_iter_next(&h->iter);
-       }
+       ret = hash_check_duplicates(desc, h, c, k_iter, k);
 fsck_err:
        return ret;
 }
@@ -368,7 +387,8 @@ static int check_dirents(struct bch_fs *c)
 {
        struct inode_walker w = inode_walker_init();
        struct hash_check h;
-       struct btree_iter iter;
+       struct btree_trans trans;
+       struct btree_iter *iter;
        struct bkey_s_c k;
        unsigned name_len;
        char buf[200];
@@ -376,10 +396,16 @@ static int check_dirents(struct bch_fs *c)
 
        bch_verbose(c, "checking dirents");
 
-       hash_check_init(bch2_dirent_hash_desc, &h, c);
+       bch2_trans_init(&trans, c);
 
-       for_each_btree_key(&iter, c, BTREE_ID_DIRENTS,
-                          POS(BCACHEFS_ROOT_INO, 0), 0, k) {
+       BUG_ON(bch2_trans_preload_iters(&trans));
+
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
+                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+
+       hash_check_init(bch2_dirent_hash_desc, &trans, &h);
+
+       for_each_btree_key_continue(iter, 0, k) {
                struct bkey_s_c_dirent d;
                struct bch_inode_unpacked target;
                bool have_target;
@@ -398,7 +424,7 @@ static int check_dirents(struct bch_fs *c)
                                mode_to_type(w.inode.bi_mode),
                                (bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
                                                       buf, sizeof(buf), k), buf))) {
-                       ret = bch2_btree_delete_at(&iter, 0);
+                       ret = bch2_btree_delete_at(iter, 0);
                        if (ret)
                                goto err;
                        continue;
@@ -407,7 +433,7 @@ static int check_dirents(struct bch_fs *c)
                if (w.first_this_inode && w.have_inode)
                        hash_check_set_inode(&h, c, &w.inode);
 
-               ret = hash_check_key(bch2_dirent_hash_desc, &h, c, &iter, k);
+               ret = hash_check_key(bch2_dirent_hash_desc, &h, c, iter, k);
                if (ret > 0) {
                        ret = 0;
                        continue;
@@ -431,7 +457,7 @@ static int check_dirents(struct bch_fs *c)
                    fsck_err_on(name_len == 2 &&
                                !memcmp(d.v->d_name, "..", 2), c,
                                ".. dirent")) {
-                       ret = remove_dirent(c, &iter, d);
+                       ret = remove_dirent(c, iter, d);
                        if (ret)
                                goto err;
                        continue;
@@ -441,7 +467,7 @@ static int check_dirents(struct bch_fs *c)
                                "dirent points to own directory:\n%s",
                                (bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
                                                       buf, sizeof(buf), k), buf))) {
-                       ret = remove_dirent(c, &iter, d);
+                       ret = remove_dirent(c, iter, d);
                        if (ret)
                                goto err;
                        continue;
@@ -458,7 +484,7 @@ static int check_dirents(struct bch_fs *c)
                                "dirent points to missing inode:\n%s",
                                (bch2_bkey_val_to_text(c, (enum bkey_type) BTREE_ID_DIRENTS,
                                                       buf, sizeof(buf), k), buf))) {
-                       ret = remove_dirent(c, &iter, d);
+                       ret = remove_dirent(c, iter, d);
                        if (ret)
                                goto err;
                        continue;
@@ -484,7 +510,7 @@ static int check_dirents(struct bch_fs *c)
 
                        ret = bch2_btree_insert_at(c, NULL, NULL, NULL,
                                        BTREE_INSERT_NOFAIL,
-                                       BTREE_INSERT_ENTRY(&iter, &n->k_i));
+                                       BTREE_INSERT_ENTRY(iter, &n->k_i));
                        kfree(n);
                        if (ret)
                                goto err;
@@ -493,9 +519,7 @@ static int check_dirents(struct bch_fs *c)
        }
 err:
 fsck_err:
-       bch2_btree_iter_unlock(&h.chain);
-       bch2_btree_iter_unlock(&h.iter);
-       return bch2_btree_iter_unlock(&iter) ?: ret;
+       return bch2_trans_exit(&trans) ?: ret;
 }
 
 /*
@@ -506,16 +530,23 @@ static int check_xattrs(struct bch_fs *c)
 {
        struct inode_walker w = inode_walker_init();
        struct hash_check h;
-       struct btree_iter iter;
+       struct btree_trans trans;
+       struct btree_iter *iter;
        struct bkey_s_c k;
        int ret = 0;
 
        bch_verbose(c, "checking xattrs");
 
-       hash_check_init(bch2_xattr_hash_desc, &h, c);
+       bch2_trans_init(&trans, c);
 
-       for_each_btree_key(&iter, c, BTREE_ID_XATTRS,
-                          POS(BCACHEFS_ROOT_INO, 0), 0, k) {
+       BUG_ON(bch2_trans_preload_iters(&trans));
+
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_XATTRS,
+                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+
+       hash_check_init(bch2_xattr_hash_desc, &trans, &h);
+
+       for_each_btree_key_continue(iter, 0, k) {
                ret = walk_inode(c, &w, k.k->p.inode);
                if (ret)
                        break;
@@ -523,7 +554,7 @@ static int check_xattrs(struct bch_fs *c)
                if (fsck_err_on(!w.have_inode, c,
                                "xattr for missing inode %llu",
                                k.k->p.inode)) {
-                       ret = bch2_btree_delete_at(&iter, 0);
+                       ret = bch2_btree_delete_at(iter, 0);
                        if (ret)
                                goto err;
                        continue;
@@ -532,15 +563,13 @@ static int check_xattrs(struct bch_fs *c)
                if (w.first_this_inode && w.have_inode)
                        hash_check_set_inode(&h, c, &w.inode);
 
-               ret = hash_check_key(bch2_xattr_hash_desc, &h, c, &iter, k);
+               ret = hash_check_key(bch2_xattr_hash_desc, &h, c, iter, k);
                if (ret)
                        goto fsck_err;
        }
 err:
 fsck_err:
-       bch2_btree_iter_unlock(&h.chain);
-       bch2_btree_iter_unlock(&h.iter);
-       return bch2_btree_iter_unlock(&iter) ?: ret;
+       return bch2_trans_exit(&trans) ?: ret;
 }
 
 /* Get root directory, create if it doesn't exist: */