summaryrefslogtreecommitdiff
path: root/fs/bcachefs/ec.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-02-11 22:48:05 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2024-07-14 19:00:13 -0400
commitfb23d57a6dfc4e521c003dc542799f07d22d269e (patch)
tree0a814ccf2c3c06614f1b2ed0a48950f3a57783e4 /fs/bcachefs/ec.c
parent4c4a7d48bd59380fa4fc75f2cd341e9de09adbf7 (diff)
downloadlwn-fb23d57a6dfc4e521c003dc542799f07d22d269e.tar.gz
lwn-fb23d57a6dfc4e521c003dc542799f07d22d269e.zip
bcachefs: Convert gc to new accounting
Rewrite fsck/gc for the new accounting scheme. This adds a second set of in-memory accounting counters for gc to use; like with other parts of gc we run all trigger in TRIGGER_GC mode, then compare what we calculated to existing in-memory accounting at the end. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/ec.c')
-rw-r--r--fs/bcachefs/ec.c97
1 files changed, 42 insertions, 55 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 819d61b9ab83..3c3a2a7e8389 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -301,13 +301,12 @@ static int mark_stripe_bucket(struct btree_trans *trans,
bucket_lock(g);
struct bch_alloc_v4 old = bucket_m_to_alloc(*g), new = old;
ret = __mark_stripe_bucket(trans, ca, s, ptr_idx, deleting, bucket, &new, flags);
- if (!ret) {
- alloc_to_bucket(g, new);
- bch2_dev_usage_update(c, ca, &old, &new);
- }
+ alloc_to_bucket(g, new);
bucket_unlock(g);
err_unlock:
percpu_up_read(&c->mark_lock);
+ if (!ret)
+ ret = bch2_alloc_key_to_dev_counters(trans, ca, &old, &new, flags);
}
err:
bch2_dev_put(ca);
@@ -369,7 +368,12 @@ int bch2_trigger_stripe(struct btree_trans *trans,
if (unlikely(flags & BTREE_TRIGGER_check_repair))
return bch2_check_fix_ptrs(trans, btree, level, _new.s_c, flags);
- if (flags & BTREE_TRIGGER_transactional) {
+ BUG_ON(new_s && old_s &&
+ (new_s->nr_blocks != old_s->nr_blocks ||
+ new_s->nr_redundant != old_s->nr_redundant));
+
+
+ if (flags & (BTREE_TRIGGER_transactional|BTREE_TRIGGER_gc)) {
/*
* If the pointers aren't changing, we don't need to do anything:
*/
@@ -380,9 +384,34 @@ int bch2_trigger_stripe(struct btree_trans *trans,
new_s->nr_blocks * sizeof(struct bch_extent_ptr)))
return 0;
- BUG_ON(new_s && old_s &&
- (new_s->nr_blocks != old_s->nr_blocks ||
- new_s->nr_redundant != old_s->nr_redundant));
+ struct gc_stripe *gc = NULL;
+ if (flags & BTREE_TRIGGER_gc) {
+ gc = genradix_ptr_alloc(&c->gc_stripes, idx, GFP_KERNEL);
+ if (!gc) {
+ bch_err(c, "error allocating memory for gc_stripes, idx %llu", idx);
+ return -BCH_ERR_ENOMEM_mark_stripe;
+ }
+
+ /*
+ * This will be wrong when we bring back runtime gc: we should
+ * be unmarking the old key and then marking the new key
+ *
+ * Also: when we bring back runtime gc, locking
+ */
+ gc->alive = true;
+ gc->sectors = le16_to_cpu(new_s->sectors);
+ gc->nr_blocks = new_s->nr_blocks;
+ gc->nr_redundant = new_s->nr_redundant;
+
+ for (unsigned i = 0; i < new_s->nr_blocks; i++)
+ gc->ptrs[i] = new_s->ptrs[i];
+
+ /*
+ * gc recalculates this field from stripe ptr
+ * references:
+ */
+ memset(gc->block_sectors, 0, sizeof(gc->block_sectors));
+ }
if (new_s) {
s64 sectors = (u64) le16_to_cpu(new_s->sectors) * new_s->nr_redundant;
@@ -391,9 +420,12 @@ int bch2_trigger_stripe(struct btree_trans *trans,
.type = BCH_DISK_ACCOUNTING_replicas,
};
bch2_bkey_to_replicas(&acc.replicas, new);
- int ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1);
+ int ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1, gc);
if (ret)
return ret;
+
+ if (gc)
+ memcpy(&gc->r.e, &acc.replicas, replicas_entry_bytes(&acc.replicas));
}
if (old_s) {
@@ -403,7 +435,7 @@ int bch2_trigger_stripe(struct btree_trans *trans,
.type = BCH_DISK_ACCOUNTING_replicas,
};
bch2_bkey_to_replicas(&acc.replicas, old);
- int ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1);
+ int ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1, gc);
if (ret)
return ret;
}
@@ -452,51 +484,6 @@ int bch2_trigger_stripe(struct btree_trans *trans,
}
}
- if (flags & BTREE_TRIGGER_gc) {
- struct gc_stripe *m =
- genradix_ptr_alloc(&c->gc_stripes, idx, GFP_KERNEL);
-
- if (!m) {
- bch_err(c, "error allocating memory for gc_stripes, idx %llu",
- idx);
- return -BCH_ERR_ENOMEM_mark_stripe;
- }
- /*
- * This will be wrong when we bring back runtime gc: we should
- * be unmarking the old key and then marking the new key
- */
- m->alive = true;
- m->sectors = le16_to_cpu(new_s->sectors);
- m->nr_blocks = new_s->nr_blocks;
- m->nr_redundant = new_s->nr_redundant;
-
- for (unsigned i = 0; i < new_s->nr_blocks; i++)
- m->ptrs[i] = new_s->ptrs[i];
-
- bch2_bkey_to_replicas(&m->r.e, new);
-
- /*
- * gc recalculates this field from stripe ptr
- * references:
- */
- memset(m->block_sectors, 0, sizeof(m->block_sectors));
-
- int ret = mark_stripe_buckets(trans, old, new, flags);
- if (ret)
- return ret;
-
- ret = bch2_update_replicas(c, new, &m->r.e,
- ((s64) m->sectors * m->nr_redundant));
- if (ret) {
- struct printbuf buf = PRINTBUF;
-
- bch2_bkey_val_to_text(&buf, c, new);
- bch2_fs_fatal_error(c, ": no replicas entry for %s", buf.buf);
- printbuf_exit(&buf);
- return ret;
- }
- }
-
return 0;
}