diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-07 21:07:39 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-11 11:35:24 -0400 |
commit | 452b9cf4ec14ee1278f8c375f7e0c4917e565b4d (patch) | |
tree | 4653fccbba2e468fd84bd08e390aaa77a933df3f | |
parent | 651151fcbeb11d9a27ab7f9a91f2c2b20bb1ee29 (diff) |
bcachefs: btree gc refactoring
-rw-r--r-- | fs/bcachefs/bcachefs.h | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 56 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.h | 24 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 7 |
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; |