blobstore: allow creating clones out of read-only snapshots
Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com> Change-Id: Iad67be79d0ddd8c498950c4f7b1b3203e47a7a41 Reviewed-on: https://review.gerrithub.io/393936 Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Maciej Szwed <maciej.szwed@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
777627e024
commit
3eb5130de6
@ -374,6 +374,22 @@ void spdk_bs_create_snapshot(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
const struct spdk_blob_xattr_opts *snapshot_xattrs,
|
||||
spdk_blob_op_with_id_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Create a clone of specified read-only blob.
|
||||
*
|
||||
* Structure clone_xattrs as well as anything it references (like e.g. names
|
||||
* array) must be valid until the completion is called.
|
||||
*
|
||||
* \param bs blobstore.
|
||||
* \param blobid Id of the read only blob used as a snapshot for new clone.
|
||||
* \param clone_xattrs xattrs specified for clone.
|
||||
* \param cb_fn Called when the operation is complete.
|
||||
* \param cb_arg Argument passed to function cb_fn.
|
||||
*/
|
||||
void spdk_bs_create_clone(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
const struct spdk_blob_xattr_opts *clone_xattrs,
|
||||
spdk_blob_op_with_id_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Delete an existing blob from the given blobstore.
|
||||
*
|
||||
|
@ -3843,6 +3843,92 @@ void spdk_bs_create_snapshot(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
}
|
||||
/* END spdk_bs_create_snapshot */
|
||||
|
||||
/* START spdk_bs_create_clone */
|
||||
|
||||
static void
|
||||
_spdk_bs_xattr_clone(void *arg, const char *name,
|
||||
const void **value, size_t *value_len)
|
||||
{
|
||||
assert(strncmp(name, BLOB_SNAPSHOT, sizeof(BLOB_SNAPSHOT)) == 0);
|
||||
|
||||
struct spdk_blob *blob = (struct spdk_blob *)arg;
|
||||
*value = &blob->id;
|
||||
*value_len = sizeof(blob->id);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_bs_clone_newblob_create_cpl(void *cb_arg, spdk_blob_id blobid, int bserrno)
|
||||
{
|
||||
struct spdk_clone_snapshot_ctx *ctx = (struct spdk_clone_snapshot_ctx *)cb_arg;
|
||||
|
||||
ctx->cpl.u.blobid.blobid = blobid;
|
||||
_spdk_bs_clone_snapshot_origblob_cleanup(ctx, bserrno);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_bs_clone_origblob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bserrno)
|
||||
{
|
||||
struct spdk_clone_snapshot_ctx *ctx = (struct spdk_clone_snapshot_ctx *)cb_arg;
|
||||
struct spdk_blob_opts opts;
|
||||
struct spdk_blob_xattr_opts internal_xattrs;
|
||||
char *xattr_names[] = { BLOB_SNAPSHOT };
|
||||
|
||||
if (bserrno != 0) {
|
||||
_spdk_bs_clone_snapshot_cleanup_finish(ctx, bserrno);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->original.blob = _blob;
|
||||
|
||||
if (!_blob->data_ro || !_blob->md_ro) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Clone not from read-only blob\n");
|
||||
_spdk_bs_clone_snapshot_origblob_cleanup(ctx, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_blob_opts_init(&opts);
|
||||
_spdk_blob_xattrs_init(&internal_xattrs);
|
||||
|
||||
opts.thin_provision = true;
|
||||
opts.num_clusters = spdk_blob_get_num_clusters(_blob);
|
||||
if (ctx->xattrs) {
|
||||
memcpy(&opts.xattrs, ctx->xattrs, sizeof(*ctx->xattrs));
|
||||
}
|
||||
|
||||
/* Set internal xattr BLOB_SNAPSHOT */
|
||||
internal_xattrs.count = 1;
|
||||
internal_xattrs.ctx = _blob;
|
||||
internal_xattrs.names = xattr_names;
|
||||
internal_xattrs.get_value = _spdk_bs_xattr_clone;
|
||||
|
||||
_spdk_bs_create_blob(_blob->bs, &opts, &internal_xattrs,
|
||||
_spdk_bs_clone_newblob_create_cpl, ctx);
|
||||
}
|
||||
|
||||
void spdk_bs_create_clone(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
const struct spdk_blob_xattr_opts *clone_xattrs,
|
||||
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_clone_snapshot_ctx *ctx = calloc(1, sizeof(*ctx));
|
||||
|
||||
if (!ctx) {
|
||||
cb_fn(cb_arg, SPDK_BLOBID_INVALID, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->cpl.type = SPDK_BS_CPL_TYPE_BLOBID;
|
||||
ctx->cpl.u.blobid.cb_fn = cb_fn;
|
||||
ctx->cpl.u.blobid.cb_arg = cb_arg;
|
||||
ctx->cpl.u.blobid.blobid = SPDK_BLOBID_INVALID;
|
||||
ctx->bserrno = 0;
|
||||
ctx->xattrs = clone_xattrs;
|
||||
ctx->original.id = blobid;
|
||||
|
||||
spdk_bs_open_blob(bs, ctx->original.id, _spdk_bs_clone_origblob_open_cpl, ctx);
|
||||
}
|
||||
|
||||
/* END spdk_bs_create_clone */
|
||||
|
||||
/* START spdk_blob_resize */
|
||||
void
|
||||
spdk_blob_resize(struct spdk_blob *blob, uint64_t sz, spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
|
@ -674,6 +674,136 @@ blob_snapshot(void)
|
||||
g_bs = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
blob_clone(void)
|
||||
{
|
||||
struct spdk_blob_store *bs;
|
||||
struct spdk_bs_dev *dev;
|
||||
struct spdk_blob_opts opts;
|
||||
struct spdk_blob *blob, *snapshot, *clone;
|
||||
spdk_blob_id blobid, cloneid, snapshotid;
|
||||
struct spdk_blob_xattr_opts xattrs;
|
||||
const void *value;
|
||||
size_t value_len;
|
||||
int rc;
|
||||
|
||||
dev = init_dev();
|
||||
|
||||
spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
||||
bs = g_bs;
|
||||
|
||||
/* Create blob with 10 clusters */
|
||||
|
||||
spdk_blob_opts_init(&opts);
|
||||
opts.num_clusters = 10;
|
||||
|
||||
spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
|
||||
blobid = g_blobid;
|
||||
|
||||
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
blob = g_blob;
|
||||
CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10)
|
||||
|
||||
/* Create snapshot */
|
||||
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
|
||||
snapshotid = g_blobid;
|
||||
|
||||
spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
snapshot = g_blob;
|
||||
CU_ASSERT(snapshot->data_ro == true)
|
||||
CU_ASSERT(snapshot->md_ro == true)
|
||||
CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10);
|
||||
|
||||
spdk_blob_close(snapshot, blob_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Create clone from snapshot with xattrs */
|
||||
xattrs.names = g_xattr_names;
|
||||
xattrs.get_value = _get_xattr_value;
|
||||
xattrs.count = 3;
|
||||
xattrs.ctx = &g_ctx;
|
||||
|
||||
spdk_bs_create_clone(bs, snapshotid, &xattrs, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
|
||||
cloneid = g_blobid;
|
||||
|
||||
spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
clone = g_blob;
|
||||
CU_ASSERT(clone->data_ro == false)
|
||||
CU_ASSERT(clone->md_ro == false)
|
||||
CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10);
|
||||
|
||||
rc = spdk_blob_get_xattr_value(clone, g_xattr_names[0], &value, &value_len);
|
||||
CU_ASSERT(rc == 0);
|
||||
SPDK_CU_ASSERT_FATAL(value != NULL);
|
||||
CU_ASSERT(value_len == strlen(g_xattr_values[0]));
|
||||
CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len);
|
||||
|
||||
rc = spdk_blob_get_xattr_value(clone, g_xattr_names[1], &value, &value_len);
|
||||
CU_ASSERT(rc == 0);
|
||||
SPDK_CU_ASSERT_FATAL(value != NULL);
|
||||
CU_ASSERT(value_len == strlen(g_xattr_values[1]));
|
||||
CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len);
|
||||
|
||||
rc = spdk_blob_get_xattr_value(clone, g_xattr_names[2], &value, &value_len);
|
||||
CU_ASSERT(rc == 0);
|
||||
SPDK_CU_ASSERT_FATAL(value != NULL);
|
||||
CU_ASSERT(value_len == strlen(g_xattr_values[2]));
|
||||
CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len);
|
||||
|
||||
|
||||
spdk_blob_close(clone, blob_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Try to create clone from not read only blob */
|
||||
spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == -EINVAL);
|
||||
CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID);
|
||||
|
||||
/* Mark blob as read only */
|
||||
spdk_blob_set_read_only(blob);
|
||||
spdk_blob_sync_md(blob, blob_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Create clone from read only blob */
|
||||
spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
|
||||
cloneid = g_blobid;
|
||||
|
||||
spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
clone = g_blob;
|
||||
CU_ASSERT(clone->data_ro == false)
|
||||
CU_ASSERT(clone->md_ro == false)
|
||||
CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10);
|
||||
|
||||
spdk_blob_close(clone, blob_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_blob_close(blob, blob_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_bs_unload(g_bs, bs_op_complete, NULL);
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
g_bs = NULL;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
blob_delete(void)
|
||||
{
|
||||
@ -3653,6 +3783,7 @@ int main(int argc, char **argv)
|
||||
CU_add_test(suite, "blob_create_internal", blob_create_internal) == NULL ||
|
||||
CU_add_test(suite, "blob_thin_provision", blob_thin_provision) == NULL ||
|
||||
CU_add_test(suite, "blob_snapshot", blob_snapshot) == NULL ||
|
||||
CU_add_test(suite, "blob_clone", blob_clone) == NULL ||
|
||||
CU_add_test(suite, "blob_delete", blob_delete) == NULL ||
|
||||
CU_add_test(suite, "blob_resize", blob_resize) == NULL ||
|
||||
CU_add_test(suite, "blob_read_only", blob_read_only) == NULL ||
|
||||
|
Loading…
Reference in New Issue
Block a user