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.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c
index 78132e40..815260bc 100644
--- a/libbcachefs/btree_gc.c
+++ b/libbcachefs/btree_gc.c
@@ -129,6 +129,8 @@ static u8 bch2_btree_mark_key(struct bch_fs *c, enum bkey_type type,
int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
struct bkey_s_c k)
{
+ enum bch_data_types data_type = type == BKEY_TYPE_BTREE
+ ? BCH_DATA_BTREE : BCH_DATA_USER;
int ret = 0;
switch (k.k->type) {
@@ -137,6 +139,15 @@ int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const struct bch_extent_ptr *ptr;
+ if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
+ (!c->opts.nofsck &&
+ fsck_err_on(!bch2_sb_has_replicas(c, e, data_type), c,
+ "superblock not marked as containing replicas"))) {
+ ret = bch2_check_mark_super(c, e, data_type);
+ if (ret)
+ return ret;
+ }
+
extent_for_each_ptr(e, ptr) {
struct bch_dev *ca = c->devs[ptr->dev];
struct bucket *g = PTR_BUCKET(ca, ptr);
@@ -147,7 +158,7 @@ int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
new.gen = ptr->gen;
new.gen_valid = 1;
}));
- ca->need_prio_write = true;
+ ca->need_alloc_write = true;
}
if (fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
@@ -159,7 +170,7 @@ int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
new.gen = ptr->gen;
new.gen_valid = 1;
}));
- ca->need_prio_write = true;
+ ca->need_alloc_write = true;
set_bit(BCH_FS_FIXED_GENS, &c->flags);
}
@@ -168,6 +179,7 @@ int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
}
}
+
atomic64_set(&c->key_version,
max_t(u64, k.k->version.lo,
atomic64_read(&c->key_version)));
@@ -348,17 +360,6 @@ void bch2_mark_dev_metadata(struct bch_fs *c, struct bch_dev *ca)
}
spin_unlock(&c->journal.lock);
-
- spin_lock(&ca->prio_buckets_lock);
-
- for (i = 0; i < prio_buckets(ca) * 2; i++) {
- b = ca->prio_buckets[i];
- if (b)
- bch2_mark_metadata_bucket(ca, ca->buckets + b,
- BUCKET_PRIOS, true);
- }
-
- spin_unlock(&ca->prio_buckets_lock);
}
static void bch2_mark_metadata(struct bch_fs *c)
@@ -474,10 +475,6 @@ void bch2_gc(struct bch_fs *c)
* move around - if references move backwards in the ordering GC
* uses, GC could skip past them
*/
-
- if (test_bit(BCH_FS_GC_FAILURE, &c->flags))
- return;
-
trace_gc_start(c);
/*
@@ -487,6 +484,8 @@ void bch2_gc(struct bch_fs *c)
bch2_recalc_sectors_available(c);
down_write(&c->gc_lock);
+ if (test_bit(BCH_FS_GC_FAILURE, &c->flags))
+ goto out;
bch2_gc_start(c);
@@ -502,8 +501,7 @@ void bch2_gc(struct bch_fs *c)
if (ret) {
bch_err(c, "btree gc failed: %d", ret);
set_bit(BCH_FS_GC_FAILURE, &c->flags);
- up_write(&c->gc_lock);
- return;
+ goto out;
}
gc_pos_set(c, gc_phase(c->gc_pos.phase + 1));
@@ -518,7 +516,7 @@ void bch2_gc(struct bch_fs *c)
/* Indicates that gc is no longer in progress: */
gc_pos_set(c, gc_phase(GC_PHASE_DONE));
c->gc_count++;
-
+out:
up_write(&c->gc_lock);
trace_gc_end(c);
bch2_time_stats_update(&c->btree_gc_time, start_time);
@@ -529,6 +527,12 @@ void bch2_gc(struct bch_fs *c)
*/
for_each_member_device(ca, c, i)
bch2_wake_allocator(ca);
+
+ /*
+ * At startup, allocations can happen directly instead of via the
+ * allocator thread - issue wakeup in case they blocked on gc_lock:
+ */
+ closure_wake_up(&c->freelist_wait);
}
/* Btree coalescing */
@@ -997,6 +1001,14 @@ int bch2_initial_gc(struct bch_fs *c, struct list_head *journal)
unsigned iter = 0;
enum btree_id id;
int ret;
+
+ mutex_lock(&c->sb_lock);
+ if (!bch2_sb_get_replicas(c->disk_sb)) {
+ if (BCH_SB_INITIALIZED(c->disk_sb))
+ bch_info(c, "building replicas info");
+ set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
+ }
+ mutex_unlock(&c->sb_lock);
again:
bch2_gc_start(c);
@@ -1006,11 +1018,9 @@ again:
return ret;
}
- if (journal) {
- ret = bch2_journal_mark(c, journal);
- if (ret)
- return ret;
- }
+ ret = bch2_journal_mark(c, journal);
+ if (ret)
+ return ret;
bch2_mark_metadata(c);