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

bcachefs: Journal write path refactoring, debug improvements

parent 47d6ee76
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1564,6 +1564,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
	printbuf_indent_sub(out, 2);

	for_each_member_device_rcu(c, ca, &c->rw_devs[BCH_DATA_journal]) {
		if (!ca->mi.durability)
			continue;

		struct journal_device *ja = &ca->journal;

		if (!test_bit(ca->dev_idx, c->rw_devs[BCH_DATA_journal].d))
@@ -1573,6 +1576,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
			continue;

		prt_printf(out, "dev %u:\n",			ca->dev_idx);
		prt_printf(out, "durability %u:\n",		ca->mi.durability);
		printbuf_indent_add(out, 2);
		prt_printf(out, "nr\t%u\n",			ja->nr);
		prt_printf(out, "bucket size\t%u\n",		ca->mi.bucket_size);
@@ -1584,6 +1588,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
		printbuf_indent_sub(out, 2);
	}

	prt_printf(out, "replicas want %u need %u\n", c->opts.metadata_replicas, c->opts.metadata_replicas_required);

	rcu_read_unlock();

	--out->atomic;
+39 −31
Original line number Diff line number Diff line
@@ -1420,6 +1420,35 @@ int bch2_journal_read(struct bch_fs *c,

/* journal write: */

static void journal_advance_devs_to_next_bucket(struct journal *j,
						struct dev_alloc_list *devs,
						unsigned sectors, u64 seq)
{
	struct bch_fs *c = container_of(j, struct bch_fs, journal);

	darray_for_each(*devs, i) {
		struct bch_dev *ca = rcu_dereference(c->devs[*i]);
		if (!ca)
			continue;

		struct journal_device *ja = &ca->journal;

		if (sectors > ja->sectors_free &&
		    sectors <= ca->mi.bucket_size &&
		    bch2_journal_dev_buckets_available(j, ja,
					journal_space_discarded)) {
			ja->cur_idx = (ja->cur_idx + 1) % ja->nr;
			ja->sectors_free = ca->mi.bucket_size;

			/*
			 * ja->bucket_seq[ja->cur_idx] must always have
			 * something sensible:
			 */
			ja->bucket_seq[ja->cur_idx] = le64_to_cpu(seq);
		}
	}
}

static void __journal_write_alloc(struct journal *j,
				  struct journal_buf *w,
				  struct dev_alloc_list *devs,
@@ -1429,9 +1458,6 @@ static void __journal_write_alloc(struct journal *j,
{
	struct bch_fs *c = container_of(j, struct bch_fs, journal);

	if (*replicas >= replicas_want)
		return;

	darray_for_each(*devs, i) {
		struct bch_dev *ca = rcu_dereference(c->devs[*i]);
		if (!ca)
@@ -1491,6 +1517,7 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w)
		READ_ONCE(c->opts.metadata_replicas);
	unsigned replicas_need = min_t(unsigned, replicas_want,
				       READ_ONCE(c->opts.metadata_replicas_required));
	bool advance_done = false;

	rcu_read_lock();

@@ -1502,45 +1529,26 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w)
			replicas += ca->mi.durability;
	}

retry:
retry_target:
	devs = target_rw_devs(c, BCH_DATA_journal, target);

	devs_sorted = bch2_dev_alloc_list(c, &j->wp.stripe, &devs);

retry_alloc:
	__journal_write_alloc(j, w, &devs_sorted, sectors, &replicas, replicas_want);

	if (replicas >= replicas_want)
	if (likely(replicas >= replicas_want))
		goto done;

	darray_for_each(devs_sorted, i) {
		struct bch_dev *ca = rcu_dereference(c->devs[*i]);
		if (!ca)
			continue;

		struct journal_device *ja = &ca->journal;

		if (sectors > ja->sectors_free &&
		    sectors <= ca->mi.bucket_size &&
		    bch2_journal_dev_buckets_available(j, ja,
					journal_space_discarded)) {
			ja->cur_idx = (ja->cur_idx + 1) % ja->nr;
			ja->sectors_free = ca->mi.bucket_size;

			/*
			 * ja->bucket_seq[ja->cur_idx] must always have
			 * something sensible:
			 */
			ja->bucket_seq[ja->cur_idx] = le64_to_cpu(w->data->seq);
		}
	if (!advance_done) {
		journal_advance_devs_to_next_bucket(j, &devs_sorted, sectors, w->data->seq);
		advance_done = true;
		goto retry_alloc;
	}

	__journal_write_alloc(j, w, &devs_sorted,
			      sectors, &replicas, replicas_want);

	if (replicas < replicas_want && target) {
		/* Retry from all devices: */
		target = 0;
		goto retry;
		advance_done = false;
		goto retry_target;
	}
done:
	rcu_read_unlock();