Commit 468035ca authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Start gc, copygc, rebalance threads after initing writes ref



This fixes a bug where copygc would occasionally race with going
read-write and die, thinking we were read only, because it couldn't take
a ref on c->writes.

It's not necessary for copygc (or rebalance, or copygc) to take write
refs; they could run with BCH_TRANS_COMMIT_nocheck_rw, but this is an
easier fix that making sure that flag is passed correctly everywhere.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 202a7c29
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -423,6 +423,18 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
		bch2_dev_allocator_add(c, ca);
	bch2_recalc_capacity(c);

	set_bit(BCH_FS_RW, &c->flags);
	set_bit(BCH_FS_WAS_RW, &c->flags);

#ifndef BCH_WRITE_REF_DEBUG
	percpu_ref_reinit(&c->writes);
#else
	for (i = 0; i < BCH_WRITE_REF_NR; i++) {
		BUG_ON(atomic_long_read(&c->writes[i]));
		atomic_long_inc(&c->writes[i]);
	}
#endif

	ret = bch2_gc_thread_start(c);
	if (ret) {
		bch_err(c, "error starting gc thread");
@@ -439,23 +451,15 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
			goto err;
	}

#ifndef BCH_WRITE_REF_DEBUG
	percpu_ref_reinit(&c->writes);
#else
	for (i = 0; i < BCH_WRITE_REF_NR; i++) {
		BUG_ON(atomic_long_read(&c->writes[i]));
		atomic_long_inc(&c->writes[i]);
	}
#endif
	set_bit(BCH_FS_RW, &c->flags);
	set_bit(BCH_FS_WAS_RW, &c->flags);

	bch2_do_discards(c);
	bch2_do_invalidates(c);
	bch2_do_stripe_deletes(c);
	bch2_do_pending_node_rewrites(c);
	return 0;
err:
	if (test_bit(BCH_FS_RW, &c->flags))
		bch2_fs_read_only(c);
	else
		__bch2_fs_read_only(c);
	return ret;
}