Commit d3c6335b authored by Tomasz Kulasek's avatar Tomasz Kulasek Committed by Ben Walker
Browse files

blobstore: no copy write in thin-provisioning



This patch prevents to copy cluster data when there is not
backing blob to improve cluster allocation performance
in thin provisioned blobs.

Change-Id: Ie766d2e5274daa74c2b13b2198a20205e3417467
Signed-off-by: default avatarTomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/417938


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 6fc44a7a
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -1649,6 +1649,7 @@ _spdk_bs_allocate_and_copy_cluster(struct spdk_blob *blob,
	ctx->blob = blob;
	ctx->page = cluster_start_page;

	if (blob->parent_id != SPDK_BLOBID_INVALID) {
		ctx->buf = spdk_dma_malloc(blob->bs->cluster_sz, blob->back_bs_dev->blocklen, NULL);
		if (!ctx->buf) {
			SPDK_ERRLOG("DMA allocation for cluster of size = %" PRIu32 " failed.\n",
@@ -1657,6 +1658,7 @@ _spdk_bs_allocate_and_copy_cluster(struct spdk_blob *blob,
			spdk_bs_user_op_abort(op);
			return;
		}
	}

	rc = _spdk_bs_allocate_cluster(blob, cluster_number, &ctx->new_cluster, false);
	if (rc != 0) {
@@ -1682,11 +1684,16 @@ _spdk_bs_allocate_and_copy_cluster(struct spdk_blob *blob,
	/* Queue the user op to block other incoming operations */
	TAILQ_INSERT_TAIL(&ch->need_cluster_alloc, op, link);

	if (blob->parent_id != SPDK_BLOBID_INVALID) {
		/* Read cluster from backing device */
		spdk_bs_sequence_read_bs_dev(ctx->seq, blob->back_bs_dev, ctx->buf,
					     _spdk_bs_dev_page_to_lba(blob->back_bs_dev, cluster_start_page),
					     _spdk_bs_dev_byte_to_lba(blob->back_bs_dev, blob->bs->cluster_sz),
					     _spdk_blob_write_copy, ctx);
	} else {
		_spdk_blob_insert_cluster_on_md_thread(ctx->blob, cluster_number, ctx->new_cluster,
						       _spdk_blob_insert_cluster_cpl, ctx);
	}
}

static void
+26 −0
Original line number Diff line number Diff line
@@ -3718,8 +3718,11 @@ blob_thin_prov_rw(void)
	struct spdk_blob_opts opts;
	spdk_blob_id blobid;
	uint64_t free_clusters;
	uint64_t page_size;
	uint8_t payload_read[10 * 4096];
	uint8_t payload_write[10 * 4096];
	uint64_t write_bytes;
	uint64_t read_bytes;

	dev = init_dev();

@@ -3728,6 +3731,7 @@ blob_thin_prov_rw(void)
	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
	bs = g_bs;
	free_clusters = spdk_bs_free_cluster_count(bs);
	page_size = spdk_bs_get_page_size(bs);

	channel = spdk_bs_alloc_io_channel(bs);
	CU_ASSERT(channel != NULL);
@@ -3766,10 +3770,17 @@ blob_thin_prov_rw(void)
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0);

	write_bytes = g_dev_write_bytes;
	read_bytes = g_dev_read_bytes;

	memset(payload_write, 0xE5, sizeof(payload_write));
	spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
	/* For thin-provisioned blob we need to write 10 pages plus one page metadata and
	 * read 0 bytes */
	CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 11);
	CU_ASSERT(g_dev_read_bytes - read_bytes == 0);

	spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
@@ -4001,8 +4012,12 @@ blob_snapshot_rw(void)
	struct spdk_blob_opts opts;
	spdk_blob_id blobid, snapshotid;
	uint64_t free_clusters;
	uint64_t cluster_size;
	uint64_t page_size;
	uint8_t payload_read[10 * 4096];
	uint8_t payload_write[10 * 4096];
	uint64_t write_bytes;
	uint64_t read_bytes;

	dev = init_dev();

@@ -4011,6 +4026,8 @@ blob_snapshot_rw(void)
	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
	bs = g_bs;
	free_clusters = spdk_bs_free_cluster_count(bs);
	cluster_size = spdk_bs_get_cluster_size(bs);
	page_size = spdk_bs_get_page_size(bs);

	channel = spdk_bs_alloc_io_channel(bs);
	CU_ASSERT(channel != NULL);
@@ -4057,11 +4074,20 @@ blob_snapshot_rw(void)

	CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5)

	write_bytes = g_dev_write_bytes;
	read_bytes = g_dev_read_bytes;

	memset(payload_write, 0xAA, sizeof(payload_write));
	spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));

	/* For a clone we need to allocate and copy one cluster, update one page of metadata
	 * and then write 10 pages of payload.
	 */
	CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 11 + cluster_size);
	CU_ASSERT(g_dev_read_bytes - read_bytes == cluster_size);

	spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
	CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
+7 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#define DEV_BUFFER_BLOCKLEN (4096)
#define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
uint8_t *g_dev_buffer;
uint64_t g_dev_write_bytes;
uint64_t g_dev_read_bytes;

/* Define here for UT only. */
struct spdk_io_channel g_io_channel;
@@ -86,6 +88,7 @@ dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload
	length = lba_count * dev->blocklen;
	SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
	memcpy(payload, &g_dev_buffer[offset], length);
	g_dev_read_bytes += length;
	spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
}

@@ -100,6 +103,7 @@ dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payloa
	length = lba_count * dev->blocklen;
	SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
	memcpy(&g_dev_buffer[offset], payload, length);
	g_dev_write_bytes += length;
	spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
}

@@ -134,6 +138,7 @@ dev_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
		offset += iov[i].iov_len;
	}

	g_dev_read_bytes += length;
	spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
}

@@ -156,6 +161,7 @@ dev_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
		offset += iov[i].iov_len;
	}

	g_dev_write_bytes += length;
	spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
}

@@ -191,6 +197,7 @@ dev_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
	length = lba_count * dev->blocklen;
	SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
	memset(&g_dev_buffer[offset], 0, length);
	g_dev_write_bytes += length;
	spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
}