Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94563bad authored by Mike Snitzer's avatar Mike Snitzer
Browse files

dm thin: always return -ENOSPC if no_free_space is set



If pool has 'no_free_space' set it means a previous allocation already
determined the pool has no free space (and failed that allocation with
-ENOSPC).  By always returning -ENOSPC if 'no_free_space' is set, we do
not allow the pool to oscillate between allocating blocks and then not.

But a side-effect of this determinism is that if a user wants to be able
to allocate new blocks they'll need to reload the pool's table (to clear
the 'no_free_space' flag).  This reload will happen automatically if the
pool's data volume is resized.  But if the user takes action to free a
lot of space by deleting snapshot volumes, etc the pool will no longer
allow data allocations to continue without an intervening table reload.

Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
Acked-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent f11c1c56
Loading
Loading
Loading
Loading
+31 −25
Original line number Diff line number Diff line
@@ -918,6 +918,13 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
	unsigned long flags;
	struct pool *pool = tc->pool;

	/*
	 * Once no_free_space is set we must not allow allocation to succeed.
	 * Otherwise it is difficult to explain, debug, test and support.
	 */
	if (pool->no_free_space)
		return -ENOSPC;

	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
	if (r)
		return r;
@@ -932,9 +939,6 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
	}

	if (!free_blocks) {
		if (pool->no_free_space)
			return -ENOSPC;
		else {
		/*
		 * Try to commit to see if that will free up some
		 * more space.
@@ -947,7 +951,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)

		/*
		 * If we still have no space we set a flag to avoid
			 * doing all this checking and return -ENOSPC.
		 * doing all this checking and return -ENOSPC.  This
		 * flag serves as a latch that disallows allocations from
		 * this pool until the admin takes action (e.g. resize or
		 * table reload).
		 */
		if (!free_blocks) {
			DMWARN("%s: no free space available.",
@@ -958,7 +965,6 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
			return -ENOSPC;
		}
	}
	}

	r = dm_pool_alloc_data_block(pool->pmd, result);
	if (r)
@@ -2695,7 +2701,7 @@ static struct target_type pool_target = {
	.name = "thin-pool",
	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
		    DM_TARGET_IMMUTABLE,
	.version = {1, 8, 0},
	.version = {1, 9, 0},
	.module = THIS_MODULE,
	.ctr = pool_ctr,
	.dtr = pool_dtr,
@@ -2982,7 +2988,7 @@ static int thin_iterate_devices(struct dm_target *ti,

static struct target_type thin_target = {
	.name = "thin",
	.version = {1, 8, 0},
	.version = {1, 9, 0},
	.module	= THIS_MODULE,
	.ctr = thin_ctr,
	.dtr = thin_dtr,