bcachefs: fix restart handling in bch2_alloc_write_key()

This is ugly:

We may discover in alloc_write_key that the data type we calculated is
wrong, because BCH_DATA_need_discard is checked/set elsewhere, and the
disk accounting counters we calculated need to be updated.

But bch2_alloc_key_to_dev_counters(..., BTREE_TRIGGER_gc) is not safe
w.r.t. transaction restarts, so we need to propagate the fixup back to
our gc state in case we take a transaction restart.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-10-16 03:36:40 -04:00
parent 7ee4be9c62
commit d8b5059774

View File

@ -820,12 +820,22 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
* fix that here: * fix that here:
*/ */
alloc_data_type_set(&gc, gc.data_type); alloc_data_type_set(&gc, gc.data_type);
if (gc.data_type != old_gc.data_type || if (gc.data_type != old_gc.data_type ||
gc.dirty_sectors != old_gc.dirty_sectors) { gc.dirty_sectors != old_gc.dirty_sectors) {
ret = bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc); ret = bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc);
if (ret) if (ret)
return ret; return ret;
/*
* Ugly: alloc_key_to_dev_counters(..., BTREE_TRIGGER_gc) is not
* safe w.r.t. transaction restarts, so fixup the gc_bucket so
* we don't run it twice:
*/
percpu_down_read(&c->mark_lock);
struct bucket *gc_m = gc_bucket(ca, iter->pos.offset);
gc_m->data_type = gc.data_type;
gc_m->dirty_sectors = gc.dirty_sectors;
percpu_up_read(&c->mark_lock);
} }
if (fsck_err_on(new.data_type != gc.data_type, if (fsck_err_on(new.data_type != gc.data_type,