diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-04-01 00:37:30 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:08:19 +0300 |
commit | 6bd1305735bc4346e0ca6cc0ff27517e8bab8f0d (patch) | |
tree | c4669543a1d97bfef05dd3f6e284d12f2e02986b | |
parent | 36e916e13b694e18d2928d0bda54fb5805051129 (diff) | |
download | linux-6bd1305735bc4346e0ca6cc0ff27517e8bab8f0d.tar.xz |
bcachefs: Fsck locking improvements
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/dirent.c | 19 | ||||
-rw-r--r-- | fs/bcachefs/dirent.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 80 | ||||
-rw-r--r-- | fs/bcachefs/inode.c | 35 | ||||
-rw-r--r-- | fs/bcachefs/inode.h | 5 |
5 files changed, 83 insertions, 57 deletions
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index 672a94936179..4479a9f55ddf 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -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) { diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h index 7b47573dcc46..bc64718a7832 100644 --- a/fs/bcachefs/dirent.h +++ b/fs/bcachefs/dirent.h @@ -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 *); diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 79e4b1b6a556..661131d5a114 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -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); diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 7be24865cc3f..8e7bec8ce542 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -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 diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h index 07d7020f230d..ada639c06619 100644 --- a/fs/bcachefs/inode.h +++ b/fs/bcachefs/inode.h @@ -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) { |