summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-04-21 13:13:57 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-04-21 13:19:09 -0400
commit2db3f2c51b10e90dfd37dd3f2cb5839c08713882 (patch)
treed981d5d82a1d12677b6de23143285de2ebaea59f
parentf4e73b27cd4fa6b7594ee7de2ed5f4fe5a5c515f (diff)
bcachefs: Go RW before bch2_check_lrus()
btree updates before going RW are expensive if they're in random order, since they use the list of keys for journal replay to insert, which is just a gap buffer. This patch improves the bucket invalidate path so that if bch2_check_lrus() hasn't finished it only prints warnings instead of doing an emergency shutdown, which means we can now set BCH_FS_MAY_GO_RW before bch2_check_lrus(). Also, the filesystem state bits are reorganized a bit. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/alloc_background.c32
-rw-r--r--fs/bcachefs/bcachefs.h18
-rw-r--r--fs/bcachefs/lru.c4
-rw-r--r--fs/bcachefs/recovery.c13
4 files changed, 46 insertions, 21 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index b1c2aecb36b0..5f52f279626a 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -1088,6 +1088,7 @@ static int invalidate_one_bucket(struct btree_trans *trans, struct bch_dev *ca)
bch2_trans_iter_init(trans, &lru_iter, BTREE_ID_lru,
POS(ca->dev_idx, 0), 0);
+next_lru:
k = bch2_btree_iter_peek(&lru_iter);
ret = bkey_err(k);
if (ret)
@@ -1096,9 +1097,20 @@ static int invalidate_one_bucket(struct btree_trans *trans, struct bch_dev *ca)
if (!k.k || k.k->p.inode != ca->dev_idx)
goto out;
- if (bch2_trans_inconsistent_on(k.k->type != KEY_TYPE_lru, trans,
- "non lru key in lru btree"))
- goto out;
+ if (k.k->type != KEY_TYPE_lru) {
+ pr_buf(&buf, "non lru key in lru btree:\n ");
+ bch2_bkey_val_to_text(&buf, c, k);
+
+ if (!test_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags)) {
+ bch_err(c, "%s", buf.buf);
+ bch2_btree_iter_advance(&lru_iter);
+ goto next_lru;
+ } else {
+ bch2_trans_inconsistent(trans, "%s", buf.buf);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
idx = k.k->p.offset;
bucket = le64_to_cpu(bkey_s_c_to_lru(k).v->idx);
@@ -1111,13 +1123,19 @@ static int invalidate_one_bucket(struct btree_trans *trans, struct bch_dev *ca)
if (idx != alloc_lru_idx(a->v)) {
pr_buf(&buf, "alloc key does not point back to lru entry when invalidating bucket:\n ");
-
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&a->k_i));
pr_buf(&buf, "\n ");
bch2_bkey_val_to_text(&buf, c, k);
- bch2_trans_inconsistent(trans, "%s", buf.buf);
- ret = -EINVAL;
- goto out;
+
+ if (!test_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags)) {
+ bch_err(c, "%s", buf.buf);
+ bch2_btree_iter_advance(&lru_iter);
+ goto next_lru;
+ } else {
+ bch2_trans_inconsistent(trans, "%s", buf.buf);
+ ret = -EINVAL;
+ goto out;
+ }
}
SET_BCH_ALLOC_V4_NEED_INC_GEN(&a->v, false);
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index 5373f7f23b98..45f7634ce529 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -494,11 +494,6 @@ struct bch_dev {
enum {
/* startup: */
- BCH_FS_CLEAN_SHUTDOWN,
- BCH_FS_INITIAL_GC_DONE,
- BCH_FS_INITIAL_GC_UNFIXED,
- BCH_FS_TOPOLOGY_REPAIR_DONE,
- BCH_FS_FSCK_DONE,
BCH_FS_STARTED,
BCH_FS_MAY_GO_RW,
BCH_FS_RW,
@@ -508,16 +503,21 @@ enum {
BCH_FS_STOPPING,
BCH_FS_EMERGENCY_RO,
BCH_FS_WRITE_DISABLE_COMPLETE,
+ BCH_FS_CLEAN_SHUTDOWN,
+
+ /* fsck passes: */
+ BCH_FS_TOPOLOGY_REPAIR_DONE,
+ BCH_FS_INITIAL_GC_DONE, /* kill when we enumerate fsck passes */
+ BCH_FS_CHECK_LRUS_DONE,
+ BCH_FS_FSCK_DONE,
+ BCH_FS_INITIAL_GC_UNFIXED, /* kill when we enumerate fsck errors */
+ BCH_FS_NEED_ANOTHER_GC,
/* errors: */
BCH_FS_ERROR,
BCH_FS_TOPOLOGY_ERROR,
BCH_FS_ERRORS_FIXED,
BCH_FS_ERRORS_NOT_FIXED,
-
- /* misc: */
- BCH_FS_NEED_ANOTHER_GC,
- BCH_FS_DELETED_NODES,
};
struct btree_debug {
diff --git a/fs/bcachefs/lru.c b/fs/bcachefs/lru.c
index fe9d15742947..ce23b38382f5 100644
--- a/fs/bcachefs/lru.c
+++ b/fs/bcachefs/lru.c
@@ -204,7 +204,9 @@ int bch2_check_lrus(struct bch_fs *c, bool initial)
for_each_btree_key(&trans, iter, BTREE_ID_lru, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) {
- ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+ ret = __bch2_trans_do(&trans, NULL, NULL,
+ BTREE_INSERT_NOFAIL|
+ BTREE_INSERT_LAZY_RW,
bch2_check_lru_key(&trans, &iter, initial));
if (ret)
break;
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index 10b46eb54ca8..17860e7b7372 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -994,7 +994,6 @@ static int bch2_fs_initialize_subvolumes(struct bch_fs *c)
if (ret)
return ret;
-
bkey_subvolume_init(&root_volume.k_i);
root_volume.k.p.offset = BCACHEFS_ROOT_SUBVOL;
root_volume.v.flags = 0;
@@ -1228,6 +1227,8 @@ use_clean:
goto err;
bch_verbose(c, "done checking allocations");
+ set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
+
bch_info(c, "checking need_discard and freespace btrees");
err = "error checking need_discard and freespace btrees";
ret = bch2_check_alloc_info(c);
@@ -1235,19 +1236,23 @@ use_clean:
goto err;
bch_verbose(c, "done checking need_discard and freespace btrees");
+ set_bit(BCH_FS_MAY_GO_RW, &c->flags);
+
bch_info(c, "checking lrus");
err = "error checking lrus";
ret = bch2_check_lrus(c, true);
if (ret)
goto err;
bch_verbose(c, "done checking lrus");
+
+ set_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags);
+ } else {
+ set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
+ set_bit(BCH_FS_MAY_GO_RW, &c->flags);
}
bch2_stripes_heap_start(c);
- set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
- set_bit(BCH_FS_MAY_GO_RW, &c->flags);
-
/*
* Skip past versions that might have possibly been used (as nonces),
* but hadn't had their pointers written: