Commit 0af8a06a authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: deallocate_extra_replicas()



When allocating from devices with different durability, we might end up
with more replicas than required; this changes
bch2_alloc_sectors_start() to check for this, and drop replicas that
aren't needed to hit the number of replicas requested.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 8a443d3e
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -1297,6 +1297,30 @@ static struct write_point *writepoint_find(struct btree_trans *trans,
	return wp;
}

static noinline void
deallocate_extra_replicas(struct bch_fs *c,
			  struct open_buckets *ptrs,
			  struct open_buckets *ptrs_no_use,
			  unsigned extra_replicas)
{
	struct open_buckets ptrs2 = { 0 };
	struct open_bucket *ob;
	unsigned i;

	open_bucket_for_each(c, ptrs, ob, i) {
		unsigned d = bch_dev_bkey_exists(c, ob->dev)->mi.durability;

		if (d && d <= extra_replicas) {
			extra_replicas -= d;
			ob_push(c, ptrs_no_use, ob);
		} else {
			ob_push(c, &ptrs2, ob);
		}
	}

	*ptrs = ptrs2;
}

/*
 * Get us an open_bucket we can allocate from, return with it locked:
 */
@@ -1385,6 +1409,9 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans,
	if (ret)
		goto err;

	if (nr_effective > nr_replicas)
		deallocate_extra_replicas(c, &ptrs, &wp->ptrs, nr_effective - nr_replicas);

	/* Free buckets we didn't use: */
	open_bucket_for_each(c, &wp->ptrs, ob, i)
		open_bucket_free_unused(c, ob);