Commit 91f8b567 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: More btree gc refactorings

more prep work for erasure coding
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1d25849c
......@@ -122,86 +122,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;
}
......@@ -218,31 +237,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;
}
......
......@@ -11,7 +11,6 @@ void bch2_gc(struct bch_fs *);
void bch2_gc_thread_stop(struct bch_fs *);
int bch2_gc_thread_start(struct bch_fs *);
int bch2_initial_gc(struct bch_fs *, struct list_head *);
u8 bch2_btree_key_recalc_oldest_gen(struct bch_fs *, struct bkey_s_c);
void bch2_mark_dev_superblock(struct bch_fs *, struct bch_dev *, unsigned);
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment