blobstore: block simultaneous operations on blobs
Block operation that should not be done simultaneously. Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Change-Id: I3cab510377a49be4e5847ba37a6218f0025c0db6 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450014 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
478c2e6f64
commit
e6100af425
@ -4296,6 +4296,8 @@ _spdk_bs_snapshot_unfreeze_cpl(void *cb_arg, int bserrno)
|
||||
}
|
||||
|
||||
ctx->original.id = origblob->id;
|
||||
origblob->locked_operation_in_progress = false;
|
||||
|
||||
spdk_blob_close(origblob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
}
|
||||
|
||||
@ -4533,10 +4535,20 @@ _spdk_bs_snapshot_origblob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int b
|
||||
if (_blob->data_ro || _blob->md_ro) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot create snapshot from read only blob with id %lu\n",
|
||||
_blob->id);
|
||||
_spdk_bs_clone_snapshot_origblob_cleanup(ctx, -EINVAL);
|
||||
ctx->bserrno = -EINVAL;
|
||||
spdk_blob_close(_blob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_blob->locked_operation_in_progress) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot create snapshot - another operation in progress\n");
|
||||
ctx->bserrno = -EBUSY;
|
||||
spdk_blob_close(_blob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
_blob->locked_operation_in_progress = true;
|
||||
|
||||
spdk_blob_opts_init(&opts);
|
||||
_spdk_blob_xattrs_init(&internal_xattrs);
|
||||
|
||||
@ -4633,10 +4645,20 @@ _spdk_bs_clone_origblob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bser
|
||||
|
||||
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);
|
||||
ctx->bserrno = -EINVAL;
|
||||
spdk_blob_close(_blob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_blob->locked_operation_in_progress) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot create clone - another operation in progress\n");
|
||||
ctx->bserrno = -EBUSY;
|
||||
spdk_blob_close(_blob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
_blob->locked_operation_in_progress = true;
|
||||
|
||||
spdk_blob_opts_init(&opts);
|
||||
_spdk_blob_xattrs_init(&internal_xattrs);
|
||||
|
||||
@ -4812,8 +4834,18 @@ _spdk_bs_inflate_blob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bserrn
|
||||
_spdk_bs_clone_snapshot_cleanup_finish(ctx, bserrno);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->original.blob = _blob;
|
||||
|
||||
if (_blob->locked_operation_in_progress) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot inflate blob - another operation in progress\n");
|
||||
ctx->bserrno = -EBUSY;
|
||||
spdk_blob_close(_blob, _spdk_bs_clone_snapshot_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
_blob->locked_operation_in_progress = true;
|
||||
|
||||
if (!ctx->allocate_all && _blob->parent_id == SPDK_BLOBID_INVALID) {
|
||||
/* This blob have no parent, so we cannot decouple it. */
|
||||
SPDK_ERRLOG("Cannot decouple parent of blob with no parent.\n");
|
||||
@ -5060,6 +5092,14 @@ _spdk_bs_delete_open_cpl(void *cb_arg, struct spdk_blob *blob, int bserrno)
|
||||
return;
|
||||
}
|
||||
|
||||
if (blob->locked_operation_in_progress) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot remove blob - another operation in progress\n");
|
||||
spdk_blob_close(blob, _spdk_bs_delete_ebusy_close_cpl, seq);
|
||||
return;
|
||||
}
|
||||
|
||||
blob->locked_operation_in_progress = true;
|
||||
|
||||
/*
|
||||
* Remove the blob from the blob_store list now, to ensure it does not
|
||||
* get returned after this point by _spdk_blob_lookup().
|
||||
|
@ -6463,6 +6463,130 @@ blob_io_unit_compatiblity(void)
|
||||
g_blobid = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
blob_simultaneous_operations(void)
|
||||
{
|
||||
struct spdk_blob_store *bs;
|
||||
struct spdk_bs_dev *dev;
|
||||
struct spdk_blob_opts opts;
|
||||
struct spdk_blob *blob, *snapshot;
|
||||
spdk_blob_id blobid, snapshotid;
|
||||
struct spdk_io_channel *channel;
|
||||
|
||||
dev = init_dev();
|
||||
|
||||
spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
||||
bs = g_bs;
|
||||
|
||||
channel = spdk_bs_alloc_io_channel(bs);
|
||||
SPDK_CU_ASSERT_FATAL(channel != NULL);
|
||||
|
||||
spdk_blob_opts_init(&opts);
|
||||
opts.num_clusters = 10;
|
||||
|
||||
spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
|
||||
poll_threads();
|
||||
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);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
blob = g_blob;
|
||||
|
||||
/* Create snapshot and try to remove blob in the same time:
|
||||
* - snapshot should be created successfully
|
||||
* - delete operation should fail w -EBUSY */
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
/* Deletion failure */
|
||||
CU_ASSERT(g_bserrno == -EBUSY);
|
||||
poll_threads();
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
/* Snapshot creation success */
|
||||
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);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
|
||||
snapshot = g_blob;
|
||||
|
||||
/* Inflate blob and try to remove blob in the same time:
|
||||
* - blob should be inflated successfully
|
||||
* - delete operation should fail w -EBUSY */
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
/* Deletion failure */
|
||||
CU_ASSERT(g_bserrno == -EBUSY);
|
||||
poll_threads();
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
/* Inflation success */
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Clone snapshot and try to remove snapshot in the same time:
|
||||
* - snapshot should be cloned successfully
|
||||
* - delete operation should fail w -EBUSY */
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL);
|
||||
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
|
||||
/* Deletion failure */
|
||||
CU_ASSERT(g_bserrno == -EBUSY);
|
||||
poll_threads();
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
/* Clone created */
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Resize blob and try to remove blob in the same time:
|
||||
* - blob should be resized successfully
|
||||
* - delete operation should fail w -EBUSY */
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
spdk_blob_resize(blob, 50, blob_op_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
|
||||
CU_ASSERT(blob->locked_operation_in_progress == true);
|
||||
/* Deletion failure */
|
||||
CU_ASSERT(g_bserrno == -EBUSY);
|
||||
poll_threads();
|
||||
CU_ASSERT(blob->locked_operation_in_progress == false);
|
||||
/* Blob resized successfully */
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_blob_close(blob, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_blob_close(snapshot, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
spdk_bs_unload(g_bs, bs_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
g_bs = NULL;
|
||||
|
||||
spdk_bs_free_io_channel(channel);
|
||||
poll_threads();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -6530,7 +6654,8 @@ int main(int argc, char **argv)
|
||||
CU_add_test(suite, "blob_operation_split_rw", blob_operation_split_rw) == NULL ||
|
||||
CU_add_test(suite, "blob_operation_split_rw_iov", blob_operation_split_rw_iov) == NULL ||
|
||||
CU_add_test(suite, "blob_io_unit", blob_io_unit) == NULL ||
|
||||
CU_add_test(suite, "blob_io_unit_compatiblity", blob_io_unit_compatiblity) == NULL
|
||||
CU_add_test(suite, "blob_io_unit_compatiblity", blob_io_unit_compatiblity) == NULL ||
|
||||
CU_add_test(suite, "blob_simultaneous_operations", blob_simultaneous_operations) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user