bcachefs: Fsck locking improvements
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 31 Mar 2019 21:37:30 +0000 (17:37 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:19 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/dirent.c
fs/bcachefs/dirent.h
fs/bcachefs/fsck.c
fs/bcachefs/inode.c
fs/bcachefs/inode.h

index 672a9493617949d15332e135757100f6810b4bf2..4479a9f55ddf41a9301672b18bb7a68551de81db 100644 (file)
@@ -329,17 +329,18 @@ out:
        return inum;
 }
 
-int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
+int bch2_empty_dir_trans(struct btree_trans *trans, u64 dir_inum)
 {
-       struct btree_trans trans;
        struct btree_iter *iter;
        struct bkey_s_c k;
        int ret = 0;
 
-       bch2_trans_init(&trans, c);
+       iter = bch2_trans_get_iter(trans, BTREE_ID_DIRENTS,
+                                  POS(dir_inum, 0), 0);
+       if (IS_ERR(iter))
+               return PTR_ERR(iter);
 
-       for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
-                          POS(dir_inum, 0), 0, k) {
+       for_each_btree_key_continue(iter, 0, k) {
                if (k.k->p.inode > dir_inum)
                        break;
 
@@ -348,11 +349,17 @@ int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
                        break;
                }
        }
-       bch2_trans_exit(&trans);
+       bch2_trans_iter_put(trans, iter);
 
        return ret;
 }
 
+int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
+{
+       return bch2_trans_do(c, NULL, 0,
+               bch2_empty_dir_trans(&trans, dir_inum));
+}
+
 int bch2_readdir(struct bch_fs *c, struct file *file,
                 struct dir_context *ctx)
 {
index 7b47573dcc464faf790dfa8a5fb3e5da21e29d7f..bc64718a78328a9899f29dcffd6c22f6b38cee8a 100644 (file)
@@ -55,6 +55,7 @@ int bch2_dirent_rename(struct btree_trans *,
 u64 bch2_dirent_lookup(struct bch_fs *, u64, const struct bch_hash_info *,
                       const struct qstr *);
 
+int bch2_empty_dir_trans(struct btree_trans *, u64);
 int bch2_empty_dir(struct bch_fs *, u64);
 int bch2_readdir(struct bch_fs *, struct file *, struct dir_context *);
 
index 79e4b1b6a556779f8e695dff5875f80dc57e55ef..661131d5a114fc22f2e07b0400b29798f3b19893 100644 (file)
@@ -128,18 +128,21 @@ static struct inode_walker inode_walker_init(void)
        };
 }
 
-static int walk_inode(struct bch_fs *c, struct inode_walker *w, u64 inum)
+static int walk_inode(struct btree_trans *trans,
+                     struct inode_walker *w, u64 inum)
 {
-       w->first_this_inode     = inum != w->cur_inum;
-       w->cur_inum             = inum;
-
-       if (w->first_this_inode) {
-               int ret = bch2_inode_find_by_inum(c, inum, &w->inode);
+       if (inum != w->cur_inum) {
+               int ret = bch2_inode_find_by_inum_trans(trans, inum,
+                                                       &w->inode);
 
                if (ret && ret != -ENOENT)
                        return ret;
 
-               w->have_inode = !ret;
+               w->have_inode   = !ret;
+               w->cur_inum     = inum;
+               w->first_this_inode = true;
+       } else {
+               w->first_this_inode = false;
        }
 
        return 0;
@@ -445,12 +448,15 @@ static int check_extents(struct bch_fs *c)
        int ret = 0;
 
        bch2_trans_init(&trans, c);
+       bch2_trans_preload_iters(&trans);
 
        bch_verbose(c, "checking extents");
 
-       for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
-                          POS(BCACHEFS_ROOT_INO, 0), 0, k) {
-               ret = walk_inode(c, &w, k.k->p.inode);
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
+                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+retry:
+       for_each_btree_key_continue(iter, 0, k) {
+               ret = walk_inode(&trans, &w, k.k->p.inode);
                if (ret)
                        break;
 
@@ -515,6 +521,8 @@ static int check_extents(struct bch_fs *c)
        }
 err:
 fsck_err:
+       if (ret == -EINTR)
+               goto retry;
        return bch2_trans_exit(&trans) ?: ret;
 }
 
@@ -537,21 +545,20 @@ static int check_dirents(struct bch_fs *c)
        bch_verbose(c, "checking dirents");
 
        bch2_trans_init(&trans, c);
-
        bch2_trans_preload_iters(&trans);
 
-       iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
-                                  POS(BCACHEFS_ROOT_INO, 0), 0);
-
        hash_check_init(&h);
 
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
+                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+retry:
        for_each_btree_key_continue(iter, 0, k) {
                struct bkey_s_c_dirent d;
                struct bch_inode_unpacked target;
                bool have_target;
                u64 d_inum;
 
-               ret = walk_inode(c, &w, k.k->p.inode);
+               ret = walk_inode(&trans, &w, k.k->p.inode);
                if (ret)
                        break;
 
@@ -620,7 +627,7 @@ static int check_dirents(struct bch_fs *c)
                        continue;
                }
 
-               ret = bch2_inode_find_by_inum(c, d_inum, &target);
+               ret = bch2_inode_find_by_inum_trans(&trans, d_inum, &target);
                if (ret && ret != -ENOENT)
                        break;
 
@@ -671,6 +678,9 @@ static int check_dirents(struct bch_fs *c)
        hash_stop_chain(&trans, &h);
 err:
 fsck_err:
+       if (ret == -EINTR)
+               goto retry;
+
        return bch2_trans_exit(&trans) ?: ret;
 }
 
@@ -689,17 +699,16 @@ static int check_xattrs(struct bch_fs *c)
 
        bch_verbose(c, "checking xattrs");
 
-       bch2_trans_init(&trans, c);
+       hash_check_init(&h);
 
+       bch2_trans_init(&trans, c);
        bch2_trans_preload_iters(&trans);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_XATTRS,
                                   POS(BCACHEFS_ROOT_INO, 0), 0);
-
-       hash_check_init(&h);
-
+retry:
        for_each_btree_key_continue(iter, 0, k) {
-               ret = walk_inode(c, &w, k.k->p.inode);
+               ret = walk_inode(&trans, &w, k.k->p.inode);
                if (ret)
                        break;
 
@@ -722,6 +731,8 @@ static int check_xattrs(struct bch_fs *c)
        }
 err:
 fsck_err:
+       if (ret == -EINTR)
+               goto retry;
        return bch2_trans_exit(&trans) ?: ret;
 }
 
@@ -905,6 +916,7 @@ static int check_directory_structure(struct bch_fs *c,
        int ret = 0;
 
        bch2_trans_init(&trans, c);
+       bch2_trans_preload_iters(&trans);
 
        bch_verbose(c, "checking directory structure");
 
@@ -919,9 +931,8 @@ restart_dfs:
        }
 
        ret = path_down(&path, BCACHEFS_ROOT_INO);
-       if (ret) {
-               return ret;
-       }
+       if (ret)
+               goto err;
 
        while (path.nr) {
 next:
@@ -983,14 +994,19 @@ up:
                path.nr--;
        }
 
-       for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN, 0, k) {
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES, POS_MIN, 0);
+retry:
+       for_each_btree_key_continue(iter, 0, k) {
                if (k.k->type != KEY_TYPE_inode)
                        continue;
 
                if (!S_ISDIR(le16_to_cpu(bkey_s_c_to_inode(k).v->bi_mode)))
                        continue;
 
-               if (!bch2_empty_dir(c, k.k->p.inode))
+               ret = bch2_empty_dir_trans(&trans, k.k->p.inode);
+               if (ret == -EINTR)
+                       goto retry;
+               if (!ret)
                        continue;
 
                if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.inode), c,
@@ -1018,15 +1034,12 @@ up:
                memset(&path, 0, sizeof(path));
                goto restart_dfs;
        }
-
-out:
-       kfree(dirs_done.bits);
-       kfree(path.entries);
-       return ret;
 err:
 fsck_err:
        ret = bch2_trans_exit(&trans) ?: ret;
-       goto out;
+       kfree(dirs_done.bits);
+       kfree(path.entries);
+       return ret;
 }
 
 struct nlink {
@@ -1070,6 +1083,7 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
        int ret;
 
        bch2_trans_init(&trans, c);
+       bch2_trans_preload_iters(&trans);
 
        inc_link(c, links, range_start, range_end, BCACHEFS_ROOT_INO, false);
 
@@ -1327,6 +1341,7 @@ static int bch2_gc_walk_inodes(struct bch_fs *c,
        u64 nlinks_pos;
 
        bch2_trans_init(&trans, c);
+       bch2_trans_preload_iters(&trans);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES,
                                   POS(range_start, 0), 0);
@@ -1426,6 +1441,7 @@ static int check_inodes_fast(struct bch_fs *c)
        int ret = 0, ret2;
 
        bch2_trans_init(&trans, c);
+       bch2_trans_preload_iters(&trans);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES,
                                   POS_MIN, 0);
index 7be24865cc3f084ed32c6e730cfad7cb3988a3c3..8e7bec8ce542570085fc77b00c3f7062734b3873 100644 (file)
@@ -444,31 +444,32 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
        return ret;
 }
 
-int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
-                           struct bch_inode_unpacked *inode)
+int bch2_inode_find_by_inum_trans(struct btree_trans *trans, u64 inode_nr,
+                                 struct bch_inode_unpacked *inode)
 {
-       struct btree_trans trans;
        struct btree_iter *iter;
        struct bkey_s_c k;
        int ret = -ENOENT;
 
-       bch2_trans_init(&trans, c);
+       iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
+                       POS(inode_nr, 0), BTREE_ITER_SLOTS);
+       if (IS_ERR(iter))
+               return PTR_ERR(iter);
 
-       for_each_btree_key(&trans, iter, BTREE_ID_INODES,
-                          POS(inode_nr, 0), BTREE_ITER_SLOTS, k) {
-               switch (k.k->type) {
-               case KEY_TYPE_inode:
-                       ret = bch2_inode_unpack(bkey_s_c_to_inode(k), inode);
-                       break;
-               default:
-                       /* hole, not found */
-                       break;
-               }
+       k = bch2_btree_iter_peek_slot(iter);
+       if (k.k->type == KEY_TYPE_inode)
+               ret = bch2_inode_unpack(bkey_s_c_to_inode(k), inode);
 
-               break;
-       }
+       bch2_trans_iter_put(trans, iter);
 
-       return bch2_trans_exit(&trans) ?: ret;
+       return ret;
+}
+
+int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
+                           struct bch_inode_unpacked *inode)
+{
+       return bch2_trans_do(c, NULL, 0,
+               bch2_inode_find_by_inum_trans(&trans, inode_nr, inode));
 }
 
 #ifdef CONFIG_BCACHEFS_DEBUG
index 07d7020f230d0ce2d4aa150b5e881b495b7ae57d..ada639c066198dfe7978d98e8186460d3dfc9555 100644 (file)
@@ -60,8 +60,9 @@ int bch2_inode_create(struct bch_fs *, struct bch_inode_unpacked *,
 
 int bch2_inode_rm(struct bch_fs *, u64);
 
-int bch2_inode_find_by_inum(struct bch_fs *, u64,
-                          struct bch_inode_unpacked *);
+int bch2_inode_find_by_inum_trans(struct btree_trans *, u64,
+                                 struct bch_inode_unpacked *);
+int bch2_inode_find_by_inum(struct bch_fs *, u64, struct bch_inode_unpacked *);
 
 static inline struct bch_io_opts bch2_inode_opts_get(struct bch_inode_unpacked *inode)
 {