Commit 9ce189c4 authored by Yalong Wang's avatar Yalong Wang Committed by Jim Harris
Browse files

lib/blob: Skip cluster release when blob in special state.



We shoule consider the locked_operation_in_progress
when release cluster. Otherwise, issues might occur.

For example, during blob flattening, the volume remains thin-provisioned.
If a cluster-aligned unmap occurs, it may release a cluster,
leading to an unallocated cluster after flattening completes.

Change-Id: Ib93dd28d30d05b05b97386ae5dd46245452a4a9b
Signed-off-by: default avatarYalong Wang <yalong9@staff.sina.com.cn>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/25725


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Reviewed-by: default avatarMateusz Kozlowski <mateusz.kozlowski@solidigm.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarGangCao <gang.cao@intel.com>
parent b46e69f3
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -3210,8 +3210,13 @@ blob_request_submit_op_single(struct spdk_io_channel *_ch, struct spdk_blob *blo
		struct spdk_blob_free_cluster_ctx *ctx = NULL;
		spdk_bs_batch_t *batch;

		/* if aligned with cluster release cluster */
		/* if aligned with cluster release cluster,
		 * but if blob locked_operation_in_progress has been set
		 * because of some specical cases, such as doing inflate,
		 * we should skip the operation of release cluster.
		 */
		if (spdk_blob_is_thin_provisioned(blob) && is_allocated &&
		    (!blob->locked_operation_in_progress) &&
		    blob_backed_with_zeroes_dev(blob) &&
		    bs_io_units_per_cluster(blob) == length) {
			struct spdk_bs_channel *bs_channel = spdk_io_channel_get_ctx(_ch);
+56 −0
Original line number Diff line number Diff line
@@ -5804,6 +5804,61 @@ blob_inflate_rw(void)
	_blob_inflate_rw(true);
}

static void
blob_inflate_unmap(void)
{
	struct spdk_blob_store *bs = g_bs;
	struct spdk_blob_opts opts;
	struct spdk_blob *blob;
	spdk_blob_id blobid;
	struct spdk_io_channel *channel;
	uint64_t io_units_per_cluster;
	uint8_t	*payload;
	uint32_t payload_size;

	channel = spdk_bs_alloc_io_channel(bs);
	SPDK_CU_ASSERT_FATAL(channel != NULL);

	/* Create blob with 10 clusters */
	ut_spdk_blob_opts_init(&opts);
	opts.num_clusters = 10;
	opts.thin_provision = true;

	blob = ut_blob_create_and_open(bs, &opts);
	blobid = spdk_blob_get_id(blob);
	io_units_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_io_unit_size(bs);
	CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10);
	CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == true);
	CU_ASSERT(spdk_blob_get_num_allocated_clusters(blob) == 0);

	payload_size = opts.num_clusters * spdk_bs_get_cluster_size(bs);
	payload = malloc(payload_size);
	SPDK_CU_ASSERT_FATAL(payload != NULL);

	spdk_blob_io_write(blob, channel, payload, 0,
			   io_units_per_cluster, blob_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(spdk_blob_get_num_allocated_clusters(blob) == 1);

	/* During inflate, submit unmap with cluster size, the cluster should not be release to ensure the blob is thick */
	spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
	spdk_blob_io_unmap(blob, channel, 0, io_units_per_cluster,
			   blob_op_complete, NULL);
	poll_threads();

	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == false);
	CU_ASSERT(spdk_blob_get_num_allocated_clusters(blob) == 10);

	spdk_bs_free_io_channel(channel);
	poll_threads();

	free(payload);

	ut_blob_close_and_delete(bs, blob);
}

/**
 * Snapshot-clones relation test
 *
@@ -10253,6 +10308,7 @@ main(int argc, char **argv)
		CU_ADD_TEST(suite, blob_delete_snapshot_power_failure);
		CU_ADD_TEST(suite, blob_create_snapshot_power_failure);
		CU_ADD_TEST(suite_bs, blob_inflate_rw);
		CU_ADD_TEST(suite_bs, blob_inflate_unmap);
		CU_ADD_TEST(suite_bs, blob_snapshot_freeze_io);
		CU_ADD_TEST(suite_bs, blob_operation_split_rw);
		CU_ADD_TEST(suite_bs, blob_operation_split_rw_iov);