summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/btree_gc.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-02-11 19:27:33 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:15 -0400
commit76f4c7b0c33d86bfa3973655ea6ed6182039ca99 (patch)
treec1593933a6a5ffd921a9de004392365552ad1b35 /fs/bcachefs/btree_gc.c
parent053dbb377dd2874942a1ca8517d454f35916a782 (diff)
downloadlinux-stable-76f4c7b0c33d86bfa3973655ea6ed6182039ca99.tar.gz
linux-stable-76f4c7b0c33d86bfa3973655ea6ed6182039ca99.tar.bz2
linux-stable-76f4c7b0c33d86bfa3973655ea6ed6182039ca99.zip
bcachefs: Fix oldest_gen handling
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_gc.c')
-rw-r--r--fs/bcachefs/btree_gc.c119
1 files changed, 35 insertions, 84 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 899bdfa4d6d3..391389d431c8 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -167,9 +167,10 @@ static int bch2_gc_mark_key(struct bch_fs *c, struct bkey_s_c k,
bkey_for_each_ptr(ptrs, ptr) {
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
size_t b = PTR_BUCKET_NR(ca, ptr);
+ struct bucket *g = __bucket(ca, b, true);
- if (gen_after(ca->oldest_gens[b], ptr->gen))
- ca->oldest_gens[b] = ptr->gen;
+ if (gen_after(g->oldest_gen, ptr->gen))
+ g->oldest_gen = ptr->gen;
*max_stale = max(*max_stale, ptr_stale(ca, ptr));
}
@@ -486,89 +487,38 @@ static void bch2_gc_free(struct bch_fs *c)
percpu_up_write(&c->mark_lock);
}
-static void bch2_gc_done_nocheck(struct bch_fs *c)
-{
- struct bch_dev *ca;
- unsigned i;
-
- {
- struct genradix_iter dst_iter = genradix_iter_init(&c->stripes[0], 0);
- struct genradix_iter src_iter = genradix_iter_init(&c->stripes[1], 0);
- struct stripe *dst, *src;
-
- c->ec_stripes_heap.used = 0;
-
- while ((dst = genradix_iter_peek(&dst_iter, &c->stripes[0])) &&
- (src = genradix_iter_peek(&src_iter, &c->stripes[1]))) {
- *dst = *src;
-
- if (dst->alive)
- bch2_stripes_heap_insert(c, dst, dst_iter.pos);
-
- genradix_iter_advance(&dst_iter, &c->stripes[0]);
- genradix_iter_advance(&src_iter, &c->stripes[1]);
- }
- }
-
- for_each_member_device(ca, c, i) {
- struct bucket_array *src = __bucket_array(ca, 1);
-
- memcpy(__bucket_array(ca, 0), src,
- sizeof(struct bucket_array) +
- sizeof(struct bucket) * src->nbuckets);
- };
-
- for_each_member_device(ca, c, i) {
- unsigned nr = sizeof(struct bch_dev_usage) / sizeof(u64);
- struct bch_dev_usage *dst = (void *)
- bch2_acc_percpu_u64s((void *) ca->usage[0], nr);
- struct bch_dev_usage *src = (void *)
- bch2_acc_percpu_u64s((void *) ca->usage[1], nr);
-
- *dst = *src;
- }
-
- {
- unsigned nr = sizeof(struct bch_fs_usage) / sizeof(u64) +
- c->replicas.nr;
- struct bch_fs_usage *dst = (void *)
- bch2_acc_percpu_u64s((void *) c->usage[0], nr);
- struct bch_fs_usage *src = (void *)
- bch2_acc_percpu_u64s((void *) c->usage[1], nr);
- unsigned offset = offsetof(typeof(*dst), s.gc_start);
-
- memcpy((void *) dst + offset,
- (void *) src + offset,
- nr * sizeof(u64) - offset);
- }
-}
-
static void bch2_gc_done(struct bch_fs *c, bool initial)
{
struct bch_dev *ca;
+ bool verify = !initial ||
+ (c->sb.compat & (1ULL << BCH_COMPAT_FEAT_ALLOC_INFO));
unsigned i;
#define copy_field(_f, _msg, ...) \
if (dst->_f != src->_f) { \
- bch_err(c, _msg ": got %llu, should be %llu, fixing" \
- , ##__VA_ARGS__, dst->_f, src->_f); \
+ if (verify) \
+ bch_err(c, _msg ": got %llu, should be %llu, fixing"\
+ , ##__VA_ARGS__, dst->_f, src->_f); \
dst->_f = src->_f; \
}
#define copy_stripe_field(_f, _msg, ...) \
if (dst->_f != src->_f) { \
- bch_err_ratelimited(c, "stripe %zu has wrong "_msg \
- ": got %u, should be %u, fixing", \
- dst_iter.pos, ##__VA_ARGS__, \
- dst->_f, src->_f); \
+ if (verify) \
+ bch_err_ratelimited(c, "stripe %zu has wrong "_msg\
+ ": got %u, should be %u, fixing", \
+ dst_iter.pos, ##__VA_ARGS__, \
+ dst->_f, src->_f); \
dst->_f = src->_f; \
dst->dirty = true; \
}
#define copy_bucket_field(_f) \
if (dst->b[b].mark._f != src->b[b].mark._f) { \
- bch_err_ratelimited(c, "dev %u bucket %zu has wrong " #_f\
- ": got %u, should be %u, fixing", \
- i, b, dst->b[b].mark._f, src->b[b].mark._f); \
+ if (verify) \
+ bch_err_ratelimited(c, "dev %u bucket %zu has wrong " #_f\
+ ": got %u, should be %u, fixing", i, b, \
+ dst->b[b].mark._f, src->b[b].mark._f); \
dst->b[b]._mark._f = src->b[b].mark._f; \
+ dst->b[b]._mark.dirty = true; \
}
#define copy_dev_field(_f, _msg, ...) \
copy_field(_f, "dev %u has wrong " _msg, i, ##__VA_ARGS__)
@@ -577,12 +527,6 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
percpu_down_write(&c->mark_lock);
- if (initial &&
- !(c->sb.compat & (1ULL << BCH_COMPAT_FEAT_ALLOC_INFO))) {
- bch2_gc_done_nocheck(c);
- goto out;
- }
-
{
struct genradix_iter dst_iter = genradix_iter_init(&c->stripes[0], 0);
struct genradix_iter src_iter = genradix_iter_init(&c->stripes[1], 0);
@@ -633,6 +577,11 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
copy_bucket_field(stripe);
copy_bucket_field(dirty_sectors);
copy_bucket_field(cached_sectors);
+
+ if (dst->b[b].oldest_gen != src->b[b].oldest_gen) {
+ dst->b[b].oldest_gen = src->b[b].oldest_gen;
+ dst->b[b]._mark.dirty = true;
+ }
}
};
@@ -645,16 +594,16 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
unsigned b;
for (b = 0; b < BCH_DATA_NR; b++)
- copy_dev_field(buckets[b],
- "buckets[%s]", bch2_data_types[b]);
- copy_dev_field(buckets_alloc, "buckets_alloc");
- copy_dev_field(buckets_ec, "buckets_ec");
+ copy_dev_field(buckets[b], "buckets[%s]",
+ bch2_data_types[b]);
+ copy_dev_field(buckets_alloc, "buckets_alloc");
+ copy_dev_field(buckets_ec, "buckets_ec");
+ copy_dev_field(buckets_unavailable, "buckets_unavailable");
for (b = 0; b < BCH_DATA_NR; b++)
- copy_dev_field(sectors[b],
- "sectors[%s]", bch2_data_types[b]);
- copy_dev_field(sectors_fragmented,
- "sectors_fragmented");
+ copy_dev_field(sectors[b], "sectors[%s]",
+ bch2_data_types[b]);
+ copy_dev_field(sectors_fragmented, "sectors_fragmented");
}
{
@@ -682,7 +631,7 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
copy_fs_field(data[i], "data[%i]", i);
}
}
-out:
+
percpu_up_write(&c->mark_lock);
#undef copy_fs_field
@@ -745,7 +694,9 @@ static int bch2_gc_start(struct bch_fs *c)
dst->nbuckets = src->nbuckets;
for (b = 0; b < src->nbuckets; b++)
- dst->b[b]._mark.gen = src->b[b].mark.gen;
+ dst->b[b]._mark.gen =
+ dst->b[b].oldest_gen =
+ src->b[b].mark.gen;
};
percpu_up_write(&c->mark_lock);