diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-21 13:13:57 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-21 13:19:09 -0400 |
commit | 2db3f2c51b10e90dfd37dd3f2cb5839c08713882 (patch) | |
tree | d981d5d82a1d12677b6de23143285de2ebaea59f | |
parent | f4e73b27cd4fa6b7594ee7de2ed5f4fe5a5c515f (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.c | 32 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs.h | 18 | ||||
-rw-r--r-- | fs/bcachefs/lru.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 13 |
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: |