Commit d8b50597 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 7ee4be9c
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -820,12 +820,22 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
	 * fix that here:
	 */
	alloc_data_type_set(&gc, gc.data_type);

	if (gc.data_type != old_gc.data_type ||
	    gc.dirty_sectors != old_gc.dirty_sectors) {
		ret = bch2_alloc_key_to_dev_counters(trans, ca, &old_gc, &gc, BTREE_TRIGGER_gc);
		if (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,