summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-31 17:37:30 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-03-31 19:00:00 -0400
commitb0f850cf91fc7f31fa0df4e66ace1e0631107d68 (patch)
treec9bd2cc83524376df87bd6776e4eda901052c097
parent0153a587eb787a4fd0da93e0a153b4a57695a077 (diff)
bcachefs: Fsck locking improvements
-rw-r--r--fs/bcachefs/dirent.c19
-rw-r--r--fs/bcachefs/dirent.h1
-rw-r--r--fs/bcachefs/fsck.c80
-rw-r--r--fs/bcachefs/inode.c35
-rw-r--r--fs/bcachefs/inode.h5
5 files changed, 83 insertions, 57 deletions
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index 58289fccb8dc..14a9a2c0ef02 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -328,17 +328,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;
@@ -347,11 +348,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 ed09d3064139..a35d3aad29c1 100644
--- a/fs/bcachefs/dirent.h
+++ b/fs/bcachefs/dirent.h
@@ -54,6 +54,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 bc501d40dfed..ceb38de9688b 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -127,18 +127,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;
@@ -444,12 +447,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;
@@ -514,6 +520,8 @@ static int check_extents(struct bch_fs *c)
}
err:
fsck_err:
+ if (ret == -EINTR)
+ goto retry;
return bch2_trans_exit(&trans) ?: ret;
}
@@ -536,21 +544,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;
@@ -619,7 +626,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;
@@ -670,6 +677,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;
}
@@ -688,17 +698,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;
@@ -721,6 +730,8 @@ static int check_xattrs(struct bch_fs *c)
}
err:
fsck_err:
+ if (ret == -EINTR)
+ goto retry;
return bch2_trans_exit(&trans) ?: ret;
}
@@ -904,6 +915,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");
@@ -918,9 +930,8 @@ restart_dfs:
}
ret = path_down(&path, BCACHEFS_ROOT_INO);
- if (ret) {
- return ret;
- }
+ if (ret)
+ goto err;
while (path.nr) {
next:
@@ -982,14 +993,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,
@@ -1017,15 +1033,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 {
@@ -1069,6 +1082,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);
@@ -1326,6 +1340,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);
@@ -1425,6 +1440,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 58d58cc4785e..9bfbd867cde4 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -445,31 +445,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 0d609985d15b..e86f312637b3 100644
--- a/fs/bcachefs/inode.h
+++ b/fs/bcachefs/inode.h
@@ -59,8 +59,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 timespec64 bch2_time_to_timespec(struct bch_fs *c, u64 time)
{