Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/spdk/blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,10 @@ int spdk_bs_blob_deep_copy(struct spdk_blob_store *bs, struct spdk_io_channel *c
* This call set a snapshot as the parent of a blob, making the blob a clone of this snapshot.
* The previous parent of the blob, if any, can be another snapshot or an external snapshot; if
* the blob is not a clone, it must be thin-provisioned.
* Blob and parent snapshot must have the same size.
* The blob must have at least as many clusters as the parent snapshot
* (child cluster count >= parent cluster count). A child with more clusters
* than the parent is valid; reads beyond the parent range return zeros via
* thin provisioning.
Comment on lines +925 to +928
*
* \param bs blobstore.
* \param blob_id The id of the blob.
Expand Down
5 changes: 3 additions & 2 deletions lib/blob/blobstore.c
Original file line number Diff line number Diff line change
Expand Up @@ -8311,8 +8311,9 @@ bs_set_parent_snapshot_open_cpl(void *cb_arg, struct spdk_blob *snapshot, int bs
return;
}

if (blob->active.num_clusters != snapshot->active.num_clusters) {
SPDK_ERRLOG("parent blob has a number of clusters different from child's ones\n");
if (blob->active.num_clusters < snapshot->active.num_clusters) {
SPDK_ERRLOG("child blob has fewer clusters (%" PRIu64 ") than parent snapshot (%" PRIu64 ")\n",
blob->active.num_clusters, snapshot->active.num_clusters);
ctx->bserrno = -EINVAL;
spdk_blob_close(blob, bs_set_parent_close_snapshot, ctx);
Comment thread
shuo-wu marked this conversation as resolved.
return;
Comment thread
shuo-wu marked this conversation as resolved.
Expand Down
30 changes: 22 additions & 8 deletions test/unit/lib/blob/blob.c/blob_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -10393,14 +10393,14 @@ blob_set_parent(void)
struct spdk_blob_store *bs = g_bs;
struct spdk_blob_opts opts;
struct ut_esnap_opts esnap_opts;
struct spdk_blob *blob1, *blob2, *blob3, *blob4, *blob5;
spdk_blob_id blobid1, blobid2, blobid3, blobid4, blobid5,
struct spdk_blob *blob1, *blob2, *blob3, *blob4, *blob5, *blob6;
spdk_blob_id blobid1, blobid2, blobid3, blobid4, blobid5, blobid6,
snapshotid1, snapshotid2, snapshotid3;
uint32_t cluster_sz, block_sz;
const uint32_t esnap_num_clusters = 4;
uint64_t esnap_num_blocks;
spdk_blob_id ids[2];
size_t clone_count = 2;
spdk_blob_id ids[3];
size_t clone_count = 3;

cluster_sz = spdk_bs_get_cluster_size(bs);
block_sz = spdk_bs_get_io_unit_size(bs);
Expand Down Expand Up @@ -10453,10 +10453,10 @@ blob_set_parent(void)
poll_threads();
CU_ASSERT(g_bserrno == -EINVAL);

/* Call set_parent with blob and snapshot of different size */
/* Call set_parent with blob that has more clusters than snapshot (child > parent, now succeeds) */
spdk_bs_blob_set_parent(bs, blobid2, snapshotid1, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == -EINVAL);
CU_ASSERT(g_bserrno == 0);
Comment on lines +10456 to +10459

/* Call set_parent correctly with a snapshot's clone blob */
spdk_bs_blob_set_parent(bs, blobid1, snapshotid1, blob_op_complete, NULL);
Expand All @@ -10467,8 +10467,8 @@ blob_set_parent(void)
CU_ASSERT(spdk_blob_is_clone(blob1));
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid1) == snapshotid1);
CU_ASSERT(spdk_blob_get_clones(bs, snapshotid1, ids, &clone_count) == 0);
CU_ASSERT(clone_count == 2);
CU_ASSERT(ids[1] == blobid1);
CU_ASSERT(clone_count == 3);
CU_ASSERT(ids[2] == blobid1);

/* Create another normal blob with size equal to esnap size and make a snapshot */
ut_spdk_blob_opts_init(&opts);
Expand All @@ -10483,6 +10483,19 @@ blob_set_parent(void)
SPDK_CU_ASSERT_FATAL(g_blobid != SPDK_BLOBID_INVALID);
snapshotid3 = g_blobid;

/* Create a thin-provisioned blob with fewer clusters than snapshotid3 to verify child < parent fails */
ut_spdk_blob_opts_init(&opts);
opts.num_clusters = esnap_num_clusters / 2;
opts.thin_provision = true;
blob6 = ut_blob_create_and_open(bs, &opts);
SPDK_CU_ASSERT_FATAL(blob6 != NULL);
blobid6 = spdk_blob_get_id(blob6);

/* Call set_parent with child having fewer clusters than parent snapshot (should fail) */
spdk_bs_blob_set_parent(bs, blobid6, snapshotid3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == -EINVAL);

/* Call set_parent correctly with an esnap's clone blob */
spdk_bs_blob_set_parent(bs, blobid2, snapshotid3, blob_op_complete, NULL);
poll_threads();
Expand Down Expand Up @@ -10530,6 +10543,7 @@ blob_set_parent(void)
/* Clean up */
ut_blob_close_and_delete(bs, blob5);
ut_blob_close_and_delete(bs, blob4);
ut_blob_close_and_delete(bs, blob6);
ut_blob_close_and_delete(bs, blob3);
ut_blob_close_and_delete(bs, blob2);
ut_blob_close_and_delete(bs, blob1);
Expand Down
Loading