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: Tomasz Kulasek <tomaszx.kulasek@intel.com> Reviewed-on: https://review.gerrithub.io/417938 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
6fc44a7aea
commit
d3c6335bc9
@ -1649,13 +1649,15 @@ _spdk_bs_allocate_and_copy_cluster(struct spdk_blob *blob,
|
|||||||
ctx->blob = blob;
|
ctx->blob = blob;
|
||||||
ctx->page = cluster_start_page;
|
ctx->page = cluster_start_page;
|
||||||
|
|
||||||
ctx->buf = spdk_dma_malloc(blob->bs->cluster_sz, blob->back_bs_dev->blocklen, NULL);
|
if (blob->parent_id != SPDK_BLOBID_INVALID) {
|
||||||
if (!ctx->buf) {
|
ctx->buf = spdk_dma_malloc(blob->bs->cluster_sz, blob->back_bs_dev->blocklen, NULL);
|
||||||
SPDK_ERRLOG("DMA allocation for cluster of size = %" PRIu32 " failed.\n",
|
if (!ctx->buf) {
|
||||||
blob->bs->cluster_sz);
|
SPDK_ERRLOG("DMA allocation for cluster of size = %" PRIu32 " failed.\n",
|
||||||
free(ctx);
|
blob->bs->cluster_sz);
|
||||||
spdk_bs_user_op_abort(op);
|
free(ctx);
|
||||||
return;
|
spdk_bs_user_op_abort(op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _spdk_bs_allocate_cluster(blob, cluster_number, &ctx->new_cluster, false);
|
rc = _spdk_bs_allocate_cluster(blob, cluster_number, &ctx->new_cluster, false);
|
||||||
@ -1682,11 +1684,16 @@ _spdk_bs_allocate_and_copy_cluster(struct spdk_blob *blob,
|
|||||||
/* Queue the user op to block other incoming operations */
|
/* Queue the user op to block other incoming operations */
|
||||||
TAILQ_INSERT_TAIL(&ch->need_cluster_alloc, op, link);
|
TAILQ_INSERT_TAIL(&ch->need_cluster_alloc, op, link);
|
||||||
|
|
||||||
/* Read cluster from backing device */
|
if (blob->parent_id != SPDK_BLOBID_INVALID) {
|
||||||
spdk_bs_sequence_read_bs_dev(ctx->seq, blob->back_bs_dev, ctx->buf,
|
/* Read cluster from backing device */
|
||||||
_spdk_bs_dev_page_to_lba(blob->back_bs_dev, cluster_start_page),
|
spdk_bs_sequence_read_bs_dev(ctx->seq, blob->back_bs_dev, ctx->buf,
|
||||||
_spdk_bs_dev_byte_to_lba(blob->back_bs_dev, blob->bs->cluster_sz),
|
_spdk_bs_dev_page_to_lba(blob->back_bs_dev, cluster_start_page),
|
||||||
_spdk_blob_write_copy, ctx);
|
_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
|
static void
|
||||||
|
@ -3718,8 +3718,11 @@ blob_thin_prov_rw(void)
|
|||||||
struct spdk_blob_opts opts;
|
struct spdk_blob_opts opts;
|
||||||
spdk_blob_id blobid;
|
spdk_blob_id blobid;
|
||||||
uint64_t free_clusters;
|
uint64_t free_clusters;
|
||||||
|
uint64_t page_size;
|
||||||
uint8_t payload_read[10 * 4096];
|
uint8_t payload_read[10 * 4096];
|
||||||
uint8_t payload_write[10 * 4096];
|
uint8_t payload_write[10 * 4096];
|
||||||
|
uint64_t write_bytes;
|
||||||
|
uint64_t read_bytes;
|
||||||
|
|
||||||
dev = init_dev();
|
dev = init_dev();
|
||||||
|
|
||||||
@ -3728,6 +3731,7 @@ blob_thin_prov_rw(void)
|
|||||||
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
||||||
bs = g_bs;
|
bs = g_bs;
|
||||||
free_clusters = spdk_bs_free_cluster_count(bs);
|
free_clusters = spdk_bs_free_cluster_count(bs);
|
||||||
|
page_size = spdk_bs_get_page_size(bs);
|
||||||
|
|
||||||
channel = spdk_bs_alloc_io_channel(bs);
|
channel = spdk_bs_alloc_io_channel(bs);
|
||||||
CU_ASSERT(channel != NULL);
|
CU_ASSERT(channel != NULL);
|
||||||
@ -3766,10 +3770,17 @@ blob_thin_prov_rw(void)
|
|||||||
CU_ASSERT(g_bserrno == 0);
|
CU_ASSERT(g_bserrno == 0);
|
||||||
CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 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));
|
memset(payload_write, 0xE5, sizeof(payload_write));
|
||||||
spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
|
spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
|
||||||
CU_ASSERT(g_bserrno == 0);
|
CU_ASSERT(g_bserrno == 0);
|
||||||
CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
|
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);
|
spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
|
||||||
CU_ASSERT(g_bserrno == 0);
|
CU_ASSERT(g_bserrno == 0);
|
||||||
@ -4001,8 +4012,12 @@ blob_snapshot_rw(void)
|
|||||||
struct spdk_blob_opts opts;
|
struct spdk_blob_opts opts;
|
||||||
spdk_blob_id blobid, snapshotid;
|
spdk_blob_id blobid, snapshotid;
|
||||||
uint64_t free_clusters;
|
uint64_t free_clusters;
|
||||||
|
uint64_t cluster_size;
|
||||||
|
uint64_t page_size;
|
||||||
uint8_t payload_read[10 * 4096];
|
uint8_t payload_read[10 * 4096];
|
||||||
uint8_t payload_write[10 * 4096];
|
uint8_t payload_write[10 * 4096];
|
||||||
|
uint64_t write_bytes;
|
||||||
|
uint64_t read_bytes;
|
||||||
|
|
||||||
dev = init_dev();
|
dev = init_dev();
|
||||||
|
|
||||||
@ -4011,6 +4026,8 @@ blob_snapshot_rw(void)
|
|||||||
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
||||||
bs = g_bs;
|
bs = g_bs;
|
||||||
free_clusters = spdk_bs_free_cluster_count(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);
|
channel = spdk_bs_alloc_io_channel(bs);
|
||||||
CU_ASSERT(channel != NULL);
|
CU_ASSERT(channel != NULL);
|
||||||
@ -4057,11 +4074,20 @@ blob_snapshot_rw(void)
|
|||||||
|
|
||||||
CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5)
|
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));
|
memset(payload_write, 0xAA, sizeof(payload_write));
|
||||||
spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
|
spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL);
|
||||||
CU_ASSERT(g_bserrno == 0);
|
CU_ASSERT(g_bserrno == 0);
|
||||||
CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs));
|
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);
|
spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL);
|
||||||
CU_ASSERT(g_bserrno == 0);
|
CU_ASSERT(g_bserrno == 0);
|
||||||
CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
|
CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0);
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#define DEV_BUFFER_BLOCKLEN (4096)
|
#define DEV_BUFFER_BLOCKLEN (4096)
|
||||||
#define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
|
#define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
|
||||||
uint8_t *g_dev_buffer;
|
uint8_t *g_dev_buffer;
|
||||||
|
uint64_t g_dev_write_bytes;
|
||||||
|
uint64_t g_dev_read_bytes;
|
||||||
|
|
||||||
/* Define here for UT only. */
|
/* Define here for UT only. */
|
||||||
struct spdk_io_channel g_io_channel;
|
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;
|
length = lba_count * dev->blocklen;
|
||||||
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
||||||
memcpy(payload, &g_dev_buffer[offset], length);
|
memcpy(payload, &g_dev_buffer[offset], length);
|
||||||
|
g_dev_read_bytes += length;
|
||||||
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
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;
|
length = lba_count * dev->blocklen;
|
||||||
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
||||||
memcpy(&g_dev_buffer[offset], payload, length);
|
memcpy(&g_dev_buffer[offset], payload, length);
|
||||||
|
g_dev_write_bytes += length;
|
||||||
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
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;
|
offset += iov[i].iov_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_dev_read_bytes += length;
|
||||||
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
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;
|
offset += iov[i].iov_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_dev_write_bytes += length;
|
||||||
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
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;
|
length = lba_count * dev->blocklen;
|
||||||
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
|
||||||
memset(&g_dev_buffer[offset], 0, length);
|
memset(&g_dev_buffer[offset], 0, length);
|
||||||
|
g_dev_write_bytes += length;
|
||||||
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user