summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-07 21:07:39 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-06-11 11:35:24 -0400
commit452b9cf4ec14ee1278f8c375f7e0c4917e565b4d (patch)
tree4653fccbba2e468fd84bd08e390aaa77a933df3f
parent651151fcbeb11d9a27ab7f9a91f2c2b20bb1ee29 (diff)
bcachefs: btree gc refactoring
-rw-r--r--fs/bcachefs/bcachefs.h8
-rw-r--r--fs/bcachefs/btree_gc.c56
-rw-r--r--fs/bcachefs/btree_gc.h24
-rw-r--r--fs/bcachefs/buckets.c5
-rw-r--r--fs/bcachefs/super.c7
5 files changed, 51 insertions, 49 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index b9f0f8234007..1482b80a8672 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -318,7 +318,13 @@ enum bch_time_stats {
struct btree;
enum gc_phase {
- GC_PHASE_SB = BTREE_ID_NR + 1,
+ GC_PHASE_START,
+ GC_PHASE_SB,
+
+#define DEF_BTREE_ID(kwd, val, name) GC_PHASE_BTREE_##kwd,
+ DEFINE_BCH_BTREE_IDS()
+#undef DEF_BTREE_ID
+
GC_PHASE_PENDING_DELETE,
GC_PHASE_ALLOC,
GC_PHASE_DONE
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 6d1199fe67bd..8f5594cf0cde 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -246,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:
*/
@@ -457,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) {
@@ -538,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);
@@ -1006,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;
@@ -1044,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:");
@@ -1088,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;
}
diff --git a/fs/bcachefs/btree_gc.h b/fs/bcachefs/btree_gc.h
index 4d1ab9dbe9c8..214a3fe3aabe 100644
--- a/fs/bcachefs/btree_gc.h
+++ b/fs/bcachefs/btree_gc.h
@@ -46,8 +46,6 @@ static inline struct gc_pos gc_phase(enum gc_phase phase)
};
}
-#define GC_POS_MIN gc_phase(0)
-
static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
{
if (l.phase != r.phase)
@@ -59,17 +57,23 @@ static inline int gc_pos_cmp(struct gc_pos l, struct gc_pos r)
return 0;
}
+static inline struct gc_pos gc_pos_btree(enum btree_id id,
+ struct bpos pos, unsigned level)
+{
+ return (struct gc_pos) {
+ .phase = GC_PHASE_BTREE_EXTENTS + id,
+ .pos = pos,
+ .level = level,
+ };
+}
+
/*
* GC position of the pointers within a btree node: note, _not_ for &b->key
* itself, that lives in the parent node:
*/
static inline struct gc_pos gc_pos_btree_node(struct btree *b)
{
- return (struct gc_pos) {
- .phase = b->btree_id,
- .pos = b->key.k.p,
- .level = b->level,
- };
+ return gc_pos_btree(b->btree_id, b->key.k.p, b->level);
}
/*
@@ -81,11 +85,7 @@ static inline struct gc_pos gc_pos_btree_node(struct btree *b)
*/
static inline struct gc_pos gc_pos_btree_root(enum btree_id id)
{
- return (struct gc_pos) {
- .phase = (int) id,
- .pos = POS_MAX,
- .level = U8_MAX,
- };
+ return gc_pos_btree(id, POS_MAX, BTREE_MAX_DEPTH);
}
static inline struct gc_pos gc_pos_alloc(struct bch_fs *c, struct open_bucket *ob)
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index b17189ee2e4f..431124450405 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -358,8 +358,9 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
old.data_type != new.data_type) {
BUG_ON(!c);
bch2_fs_inconsistent(c,
- "different types of data in same bucket: %u, %u",
- old.data_type, new.data_type);
+ "different types of data in same bucket: %s, %s",
+ bch2_data_types[old.data_type],
+ bch2_data_types[new.data_type]);
}
dev_usage = this_cpu_ptr(ca->usage_percpu);
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 1ed8478f2e4c..a6604cb95367 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -715,6 +715,13 @@ const char *bch2_fs_start(struct bch_fs *c)
bch2_recalc_capacity(c);
if (BCH_SB_INITIALIZED(c->disk_sb.sb)) {
+ mutex_lock(&c->sb_lock);
+ if (!bch2_sb_get_replicas(c->disk_sb.sb)) {
+ bch_info(c, "building replicas info");
+ set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
+ }
+ mutex_unlock(&c->sb_lock);
+
ret = bch2_journal_read(c, &journal);
if (ret)
goto err;