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

Commit b5330655 authored by Joe Thornber's avatar Joe Thornber Committed by Mike Snitzer
Browse files

dm thin: handle metadata failures more consistently



Introduce metadata_operation_failed() wrappers, around set_pool_mode(),
to assist with improving the consistency of how metadata failures are
handled.  Logging is improved and metadata operation failures trigger
read-only mode immediately.

Also, eliminate redundant set_pool_mode() calls in the two
alloc_data_block() caller's error paths.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 88a6621b
Loading
Loading
Loading
Loading
+27 −21
Original line number Original line Diff line number Diff line
@@ -198,7 +198,7 @@ struct pool {
};
};


static enum pool_mode get_pool_mode(struct pool *pool);
static enum pool_mode get_pool_mode(struct pool *pool);
static void set_pool_mode(struct pool *pool, enum pool_mode mode);
static void metadata_operation_failed(struct pool *pool, const char *op, int r);


/*
/*
 * Target context for a pool.
 * Target context for a pool.
@@ -641,9 +641,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
	 */
	 */
	r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
	r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
	if (r) {
	if (r) {
		DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
		metadata_operation_failed(pool, "dm_thin_insert_block", r);
			    dm_device_name(pool->pool_md), r);
		set_pool_mode(pool, PM_READ_ONLY);
		cell_error(pool, m->cell);
		cell_error(pool, m->cell);
		goto out;
		goto out;
	}
	}
@@ -900,11 +898,8 @@ static int commit(struct pool *pool)
		return -EINVAL;
		return -EINVAL;


	r = dm_pool_commit_metadata(pool->pmd);
	r = dm_pool_commit_metadata(pool->pmd);
	if (r) {
	if (r)
		DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d",
		metadata_operation_failed(pool, "dm_pool_commit_metadata", r);
			    dm_device_name(pool->pool_md), r);
		set_pool_mode(pool, PM_READ_ONLY);
	}


	return r;
	return r;
}
}
@@ -941,8 +936,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
		return -EINVAL;
		return -EINVAL;


	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
	if (r)
	if (r) {
		metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
		return r;
		return r;
	}


	check_low_water_mark(pool, free_blocks);
	check_low_water_mark(pool, free_blocks);


@@ -956,8 +953,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
			return r;
			return r;


		r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
		r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
		if (r)
		if (r) {
			metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
			return r;
			return r;
		}


		/*
		/*
		 * If we still have no space we set a flag to avoid
		 * If we still have no space we set a flag to avoid
@@ -980,11 +979,11 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
	if (r) {
	if (r) {
		if (r == -ENOSPC &&
		if (r == -ENOSPC &&
		    !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
		    !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
		    !free_blocks) {
		    !free_blocks)
			DMWARN("%s: no free metadata space available.",
			DMWARN("%s: no free metadata space available.",
			       dm_device_name(pool->pool_md));
			       dm_device_name(pool->pool_md));
			set_pool_mode(pool, PM_READ_ONLY);

		}
		metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
		return r;
		return r;
	}
	}


@@ -1126,7 +1125,6 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
	default:
	default:
		DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
		DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
			    __func__, r);
			    __func__, r);
		set_pool_mode(pool, PM_READ_ONLY);
		cell_error(pool, cell);
		cell_error(pool, cell);
		break;
		break;
	}
	}
@@ -1205,7 +1203,6 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
	default:
	default:
		DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
		DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
			    __func__, r);
			    __func__, r);
		set_pool_mode(pool, PM_READ_ONLY);
		cell_error(pool, cell);
		cell_error(pool, cell);
		break;
		break;
	}
	}
@@ -1449,6 +1446,18 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
	}
	}
}
}


/*
 * Rather than calling set_pool_mode directly, use these which describe the
 * reason for mode degradation.
 */
static void metadata_operation_failed(struct pool *pool, const char *op, int r)
{
	DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
		    dm_device_name(pool->pool_md), op, r);

	set_pool_mode(pool, PM_READ_ONLY);
}

/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/


/*
/*
@@ -2209,9 +2218,7 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
	} else if (data_size > sb_data_size) {
	} else if (data_size > sb_data_size) {
		r = dm_pool_resize_data_dev(pool->pmd, data_size);
		r = dm_pool_resize_data_dev(pool->pmd, data_size);
		if (r) {
		if (r) {
			DMERR("%s: failed to resize data device",
			metadata_operation_failed(pool, "dm_pool_resize_data_dev", r);
			      dm_device_name(pool->pool_md));
			set_pool_mode(pool, PM_READ_ONLY);
			return r;
			return r;
		}
		}


@@ -2248,8 +2255,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
	} else if (metadata_dev_size > sb_metadata_dev_size) {
	} else if (metadata_dev_size > sb_metadata_dev_size) {
		r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
		r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
		if (r) {
		if (r) {
			DMERR("%s: failed to resize metadata device",
			metadata_operation_failed(pool, "dm_pool_resize_metadata_dev", r);
			      dm_device_name(pool->pool_md));
			return r;
			return r;
		}
		}