bcachefs: Fix gc handling of bucket gens
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
committed by
Kent Overstreet
parent
86a225c42d
commit
28062d320b
@ -142,22 +142,23 @@ static int bch2_gc_mark_key(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
bkey_for_each_ptr(ptrs, ptr) {
|
bkey_for_each_ptr(ptrs, ptr) {
|
||||||
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
|
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
|
||||||
struct bucket *g = PTR_BUCKET(ca, ptr, true);
|
struct bucket *g = PTR_BUCKET(ca, ptr, true);
|
||||||
|
struct bucket *g2 = PTR_BUCKET(ca, ptr, false);
|
||||||
|
|
||||||
if (mustfix_fsck_err_on(!g->gen_valid, c,
|
if (mustfix_fsck_err_on(!g->gen_valid, c,
|
||||||
"found ptr with missing gen in alloc btree,\n"
|
"found ptr with missing gen in alloc btree,\n"
|
||||||
"type %u gen %u",
|
"type %u gen %u",
|
||||||
k.k->type, ptr->gen)) {
|
k.k->type, ptr->gen)) {
|
||||||
g->_mark.gen = ptr->gen;
|
g2->_mark.gen = g->_mark.gen = ptr->gen;
|
||||||
g->_mark.dirty = true;
|
g2->_mark.dirty = g->_mark.dirty = true;
|
||||||
g->gen_valid = 1;
|
g2->gen_valid = g->gen_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
|
if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
|
||||||
"%u ptr gen in the future: %u > %u",
|
"%u ptr gen in the future: %u > %u",
|
||||||
k.k->type, ptr->gen, g->mark.gen)) {
|
k.k->type, ptr->gen, g->mark.gen)) {
|
||||||
g->_mark.gen = ptr->gen;
|
g2->_mark.gen = g->_mark.gen = ptr->gen;
|
||||||
g->_mark.dirty = true;
|
g2->_mark.dirty = g->_mark.dirty = true;
|
||||||
g->gen_valid = 1;
|
g2->gen_valid = g->gen_valid = true;
|
||||||
set_bit(BCH_FS_FIXED_GENS, &c->flags);
|
set_bit(BCH_FS_FIXED_GENS, &c->flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,10 +693,12 @@ static int bch2_gc_start(struct bch_fs *c)
|
|||||||
dst->first_bucket = src->first_bucket;
|
dst->first_bucket = src->first_bucket;
|
||||||
dst->nbuckets = src->nbuckets;
|
dst->nbuckets = src->nbuckets;
|
||||||
|
|
||||||
for (b = 0; b < src->nbuckets; b++)
|
for (b = 0; b < src->nbuckets; b++) {
|
||||||
dst->b[b]._mark.gen =
|
dst->b[b]._mark.gen =
|
||||||
dst->b[b].oldest_gen =
|
dst->b[b].oldest_gen =
|
||||||
src->b[b].mark.gen;
|
src->b[b].mark.gen;
|
||||||
|
dst->b[b].gen_valid = src->b[b].gen_valid;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
percpu_up_write(&c->mark_lock);
|
percpu_up_write(&c->mark_lock);
|
||||||
@ -754,6 +757,8 @@ out:
|
|||||||
if (iter++ <= 2) {
|
if (iter++ <= 2) {
|
||||||
bch_info(c, "Fixed gens, restarting mark and sweep:");
|
bch_info(c, "Fixed gens, restarting mark and sweep:");
|
||||||
clear_bit(BCH_FS_FIXED_GENS, &c->flags);
|
clear_bit(BCH_FS_FIXED_GENS, &c->flags);
|
||||||
|
__gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
|
||||||
|
bch2_gc_free(c);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ static inline struct bucket *PTR_BUCKET(struct bch_dev *ca,
|
|||||||
const struct bch_extent_ptr *ptr,
|
const struct bch_extent_ptr *ptr,
|
||||||
bool gc)
|
bool gc)
|
||||||
{
|
{
|
||||||
return bucket(ca, PTR_BUCKET_NR(ca, ptr));
|
return __bucket(ca, PTR_BUCKET_NR(ca, ptr), gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct bucket_mark ptr_bucket_mark(struct bch_dev *ca,
|
static inline struct bucket_mark ptr_bucket_mark(struct bch_dev *ca,
|
||||||
|
Reference in New Issue
Block a user