summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_gc.c')
-rw-r--r--libbcachefs/btree_gc.c63
1 files changed, 27 insertions, 36 deletions
diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c
index 02b14e38..969c1f19 100644
--- a/libbcachefs/btree_gc.c
+++ b/libbcachefs/btree_gc.c
@@ -148,6 +148,9 @@ int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
? BCH_DATA_BTREE : BCH_DATA_USER;
int ret = 0;
+ BUG_ON(journal_seq_verify(c) &&
+ k.k->version.lo > journal_cur_seq(&c->journal));
+
if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
fsck_err_on(!bch2_bkey_replicas_marked(c, data_type, k), c,
"superblock not marked as containing replicas (type %u)",
@@ -243,6 +246,11 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id)
unsigned max_stale;
int ret = 0;
+ gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0));
+
+ if (!c->btree_roots[btree_id].b)
+ return 0;
+
/*
* if expensive_debug_checks is on, run range_checks on all leaf nodes:
*/
@@ -454,7 +462,7 @@ static void bch2_gc_start(struct bch_fs *c)
* Indicates to buckets code that gc is now in progress - done under
* usage_lock to avoid racing with bch2_mark_key():
*/
- __gc_pos_set(c, GC_POS_MIN);
+ __gc_pos_set(c, gc_phase(GC_PHASE_START));
/* Save a copy of the existing bucket stats while we recompute them: */
for_each_member_device(ca, c, i) {
@@ -535,22 +543,18 @@ void bch2_gc(struct bch_fs *c)
bch2_gc_start(c);
- /* Walk btree: */
- while (c->gc_pos.phase < (int) BTREE_ID_NR) {
- int ret = c->btree_roots[c->gc_pos.phase].b
- ? bch2_gc_btree(c, (int) c->gc_pos.phase)
- : 0;
+ bch2_mark_superblocks(c);
+ /* Walk btree: */
+ for (i = 0; i < BTREE_ID_NR; i++) {
+ int ret = bch2_gc_btree(c, i);
if (ret) {
bch_err(c, "btree gc failed: %d", ret);
set_bit(BCH_FS_GC_FAILURE, &c->flags);
goto out;
}
-
- gc_pos_set(c, gc_phase(c->gc_pos.phase + 1));
}
- bch2_mark_superblocks(c);
bch2_mark_pending_btree_node_frees(c);
bch2_mark_allocator_buckets(c);
@@ -780,13 +784,13 @@ next:
bch2_keylist_add_in_order(&keylist, &new_nodes[i]->key);
/* Insert the newly coalesced nodes */
- bch2_btree_insert_node(as, parent, iter, &keylist);
+ bch2_btree_insert_node(as, parent, iter, &keylist, 0);
BUG_ON(!bch2_keylist_empty(&keylist));
BUG_ON(iter->l[old_nodes[0]->level].b != old_nodes[0]);
- BUG_ON(!bch2_btree_iter_node_replace(iter, new_nodes[0]));
+ bch2_btree_iter_node_replace(iter, new_nodes[0]);
for (i = 0; i < nr_new_nodes; i++)
bch2_btree_open_bucket_put(c, new_nodes[i]);
@@ -1003,6 +1007,8 @@ static int bch2_initial_gc_btree(struct bch_fs *c, enum btree_id id)
btree_node_range_checks_init(&r, 0);
+ gc_pos_set(c, gc_pos_btree(id, POS_MIN, 0));
+
if (!c->btree_roots[id].b)
return 0;
@@ -1041,36 +1047,33 @@ err:
return bch2_btree_iter_unlock(&iter) ?: ret;
}
-static int __bch2_initial_gc(struct bch_fs *c, struct list_head *journal)
+int bch2_initial_gc(struct bch_fs *c, struct list_head *journal)
{
unsigned iter = 0;
enum btree_id id;
- int ret;
+ int ret = 0;
- mutex_lock(&c->sb_lock);
- if (!bch2_sb_get_replicas(c->disk_sb.sb)) {
- if (BCH_SB_INITIALIZED(c->disk_sb.sb))
- bch_info(c, "building replicas info");
- set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
- }
- mutex_unlock(&c->sb_lock);
+ down_write(&c->gc_lock);
again:
bch2_gc_start(c);
+ bch2_mark_superblocks(c);
+
for (id = 0; id < BTREE_ID_NR; id++) {
ret = bch2_initial_gc_btree(c, id);
if (ret)
- return ret;
+ goto err;
}
ret = bch2_journal_mark(c, journal);
if (ret)
- return ret;
+ goto err;
if (test_bit(BCH_FS_FIXED_GENS, &c->flags)) {
if (iter++ > 2) {
bch_info(c, "Unable to fix bucket gens, looping");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
bch_info(c, "Fixed gens, restarting initial mark and sweep:");
@@ -1085,21 +1088,9 @@ again:
if (c->sb.encryption_type)
atomic64_add(1 << 16, &c->key_version);
- bch2_mark_superblocks(c);
-
gc_pos_set(c, gc_phase(GC_PHASE_DONE));
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
-
- return 0;
-}
-
-int bch2_initial_gc(struct bch_fs *c, struct list_head *journal)
-{
- int ret;
-
- down_write(&c->gc_lock);
- ret = __bch2_initial_gc(c, journal);
+err:
up_write(&c->gc_lock);
-
return ret;
}