From a9f14c773fb122a4b283fc7b79d9f98703a18890 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 12 Nov 2018 17:26:36 -0500 Subject: bcachefs: More btree gc refactorings more prep work for erasure coding --- fs/bcachefs/btree_gc.c | 174 +++++++++++++++++++++++++++---------------------- 1 file changed, 97 insertions(+), 77 deletions(-) (limited to 'fs/bcachefs/btree_gc.c') diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index dabdcdf4766b..6b67da90bcea 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -119,86 +119,105 @@ static bool bkey_type_needs_gc(enum bkey_type type) } } -u8 bch2_btree_key_recalc_oldest_gen(struct bch_fs *c, struct bkey_s_c k) +static void ptr_gen_recalc_oldest(struct bch_fs *c, + const struct bch_extent_ptr *ptr, + u8 *max_stale) { - const struct bch_extent_ptr *ptr; - u8 max_stale = 0; + struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); + size_t b = PTR_BUCKET_NR(ca, ptr); - if (bkey_extent_is_data(k.k)) { - struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + if (gen_after(ca->oldest_gens[b], ptr->gen)) + ca->oldest_gens[b] = ptr->gen; - extent_for_each_ptr(e, ptr) { - struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); - size_t b = PTR_BUCKET_NR(ca, ptr); + *max_stale = max(*max_stale, ptr_stale(ca, ptr)); +} - if (gen_after(ca->oldest_gens[b], ptr->gen)) - ca->oldest_gens[b] = ptr->gen; +static u8 ptr_gens_recalc_oldest(struct bch_fs *c, + enum bkey_type type, + struct bkey_s_c k) +{ + const struct bch_extent_ptr *ptr; + u8 max_stale = 0; - max_stale = max(max_stale, ptr_stale(ca, ptr)); + switch (type) { + case BKEY_TYPE_BTREE: + case BKEY_TYPE_EXTENTS: + switch (k.k->type) { + case BCH_EXTENT: + case BCH_EXTENT_CACHED: { + struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + + extent_for_each_ptr(e, ptr) + ptr_gen_recalc_oldest(c, ptr, &max_stale); + break; } + } + break; + default: + break; } return max_stale; } -static int bch2_btree_mark_ptrs_initial(struct bch_fs *c, enum bkey_type type, - struct bkey_s_c k) +static int ptr_gen_check(struct bch_fs *c, + enum bkey_type type, + const struct bch_extent_ptr *ptr) { - enum bch_data_type data_type = type == BKEY_TYPE_BTREE - ? BCH_DATA_BTREE : BCH_DATA_USER; + struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); + size_t b = PTR_BUCKET_NR(ca, ptr); + struct bucket *g = PTR_BUCKET(ca, ptr); int ret = 0; - BUG_ON(journal_seq_verify(c) && - k.k->version.lo > journal_cur_seq(&c->journal)); + if (mustfix_fsck_err_on(!g->mark.gen_valid, c, + "found ptr with missing gen in alloc btree,\n" + "type %u gen %u", + type, ptr->gen)) { + g->_mark.gen = ptr->gen; + g->_mark.gen_valid = 1; + set_bit(b, ca->buckets_dirty); + } - if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) || - fsck_err_on(!bch2_bkey_replicas_marked(c, type, k, false), c, - "superblock not marked as containing replicas (type %u)", - data_type)) { - ret = bch2_mark_bkey_replicas(c, type, k); - if (ret) - return ret; + if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c, + "%u ptr gen in the future: %u > %u", + type, ptr->gen, g->mark.gen)) { + g->_mark.gen = ptr->gen; + g->_mark.gen_valid = 1; + set_bit(b, ca->buckets_dirty); + set_bit(BCH_FS_FIXED_GENS, &c->flags); } +fsck_err: + return ret; +} - switch (k.k->type) { - case BCH_EXTENT: - case BCH_EXTENT_CACHED: { - struct bkey_s_c_extent e = bkey_s_c_to_extent(k); - const struct bch_extent_ptr *ptr; - - extent_for_each_ptr(e, ptr) { - struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); - size_t b = PTR_BUCKET_NR(ca, ptr); - struct bucket *g = PTR_BUCKET(ca, ptr); - - if (mustfix_fsck_err_on(!g->mark.gen_valid, c, - "found ptr with missing gen in alloc btree,\n" - "type %s gen %u", - bch2_data_types[data_type], - ptr->gen)) { - g->_mark.gen = ptr->gen; - g->_mark.gen_valid = 1; - set_bit(b, ca->buckets_dirty); - } +static int ptr_gens_check(struct bch_fs *c, enum bkey_type type, + struct bkey_s_c k) +{ + const struct bch_extent_ptr *ptr; + int ret = 0; - if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c, - "%s ptr gen in the future: %u > %u", - bch2_data_types[data_type], - ptr->gen, g->mark.gen)) { - g->_mark.gen = ptr->gen; - g->_mark.gen_valid = 1; - set_bit(b, ca->buckets_dirty); - set_bit(BCH_FS_FIXED_GENS, &c->flags); - } + switch (type) { + case BKEY_TYPE_BTREE: + case BKEY_TYPE_EXTENTS: + switch (k.k->type) { + case BCH_EXTENT: + case BCH_EXTENT_CACHED: { + struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + extent_for_each_ptr(e, ptr) { + ret = ptr_gen_check(c, type, ptr); + if (ret) + return ret; + + } + break; + } } break; - } + default: + break; } - if (k.k->version.lo > atomic64_read(&c->key_version)) - atomic64_set(&c->key_version, k.k->version.lo); -fsck_err: return ret; } @@ -215,31 +234,32 @@ static int bch2_gc_mark_key(struct bch_fs *c, enum bkey_type type, (initial ? BCH_BUCKET_MARK_NOATOMIC : 0); int ret = 0; - switch (type) { - case BKEY_TYPE_BTREE: - case BKEY_TYPE_EXTENTS: - if (initial) { - ret = bch2_btree_mark_ptrs_initial(c, type, k); - if (ret < 0) + if (initial) { + BUG_ON(journal_seq_verify(c) && + k.k->version.lo > journal_cur_seq(&c->journal)); + + if (k.k->version.lo > atomic64_read(&c->key_version)) + atomic64_set(&c->key_version, k.k->version.lo); + + if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) || + fsck_err_on(!bch2_bkey_replicas_marked(c, type, k, + false), c, + "superblock not marked as containing replicas (type %u)", + type)) { + ret = bch2_mark_bkey_replicas(c, type, k); + if (ret) return ret; } - break; - default: - break; - } - bch2_mark_key(c, type, k, true, k.k->size, - pos, NULL, 0, flags); - - switch (type) { - case BKEY_TYPE_BTREE: - case BKEY_TYPE_EXTENTS: - ret = bch2_btree_key_recalc_oldest_gen(c, k); - break; - default: - break; + ret = ptr_gens_check(c, type, k); + if (ret) + return ret; } + bch2_mark_key(c, type, k, true, k.k->size, pos, NULL, 0, flags); + + ret = ptr_gens_recalc_oldest(c, type, k); +fsck_err: return ret; } -- cgit v1.2.3