lvol: do not unload/destroy lvs when operation on lvol is pending
There is a scenario where we can try do unload or remove lvol store while lvol present on that lvol store is being closed or destroyed. Scenario: 1. send delete_bdev rpc command 2. command returns before lvol is actually closed/destroyed (does not wait for callback) 3. send destroy_lvol_store rpc command 4. lvs is destroyed before lvol is destroyed 5. lvol destroy callback is called on destroeyd lvol store Aboive scenario can be reproduced using: spdk/test/vhost/spdk_vhost.sh --integrity-lvol-scsi Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Change-Id: Ie715279195bd4b1145cf05d4f5a8477b4fac87f7 Reviewed-on: https://review.gerrithub.io/383595 Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
2baeea7dd4
commit
e68e2e749b
@ -101,6 +101,7 @@ struct spdk_lvol {
|
||||
bool close_only;
|
||||
struct spdk_bdev *bdev;
|
||||
int ref_count;
|
||||
bool action_in_progress;
|
||||
TAILQ_ENTRY(spdk_lvol) link;
|
||||
};
|
||||
|
||||
|
@ -112,6 +112,12 @@ spdk_lvol_open(struct spdk_lvol *lvol, spdk_lvol_op_with_handle_complete cb_fn,
|
||||
return;
|
||||
}
|
||||
|
||||
if (lvol->action_in_progress == true) {
|
||||
SPDK_ERRLOG("Cannot open lvol - operations on lvol pending\n");
|
||||
cb_fn(cb_arg, lvol, -EBUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lvol->ref_count > 0) {
|
||||
lvol->ref_count++;
|
||||
cb_fn(cb_arg, lvol, 0);
|
||||
@ -602,8 +608,13 @@ spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
|
||||
if (lvol->ref_count != 0) {
|
||||
if (lvol->action_in_progress == true) {
|
||||
SPDK_ERRLOG("Cannot unload lvol store - operations on lvols pending\n");
|
||||
cb_fn(cb_arg, -EBUSY);
|
||||
return -EBUSY;
|
||||
} else if (lvol->ref_count != 0) {
|
||||
SPDK_ERRLOG("Lvols still open on lvol store\n");
|
||||
cb_fn(cb_arg, -EBUSY);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
@ -679,8 +690,13 @@ spdk_lvs_destroy(struct spdk_lvol_store *lvs, bool unmap_device, spdk_lvs_op_com
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
|
||||
if (iter_lvol->ref_count != 0) {
|
||||
if (iter_lvol->action_in_progress == true) {
|
||||
SPDK_ERRLOG("Cannot destroy lvol store - operations on lvols pending\n");
|
||||
cb_fn(cb_arg, -EBUSY);
|
||||
return -EBUSY;
|
||||
} else if (iter_lvol->ref_count != 0) {
|
||||
SPDK_ERRLOG("Lvols still open on lvol store\n");
|
||||
cb_fn(cb_arg, -EBUSY);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
@ -730,7 +746,9 @@ _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno)
|
||||
}
|
||||
}
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol %s closed\n", lvol->old_name) ;
|
||||
lvol->action_in_progress = false;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol %s closed\n", lvol->old_name);
|
||||
|
||||
if (lvol->lvol_store->destruct_req && all_lvols_closed == true) {
|
||||
spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
|
||||
@ -1025,6 +1043,8 @@ spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_
|
||||
return;
|
||||
}
|
||||
|
||||
lvol->action_in_progress = true;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
@ -1071,6 +1091,8 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar
|
||||
return;
|
||||
}
|
||||
|
||||
lvol->action_in_progress = true;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
|
@ -429,9 +429,9 @@ lvs_init_unload_success(void)
|
||||
|
||||
/* Lvol store has an open lvol, this unload should fail. */
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_unload(g_lvol_store, NULL, NULL);
|
||||
rc = spdk_lvs_unload(g_lvol_store, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == -EBUSY);
|
||||
CU_ASSERT(g_lvserrno == -1);
|
||||
CU_ASSERT(g_lvserrno == -EBUSY);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
|
||||
|
||||
@ -477,9 +477,9 @@ lvs_init_destroy_success(void)
|
||||
|
||||
/* Lvol store contains one lvol, this destroy should fail. */
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_destroy(g_lvol_store, true, NULL, NULL);
|
||||
rc = spdk_lvs_destroy(g_lvol_store, true, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == -EBUSY);
|
||||
CU_ASSERT(g_lvserrno == -1);
|
||||
CU_ASSERT(g_lvserrno == -EBUSY);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||
|
||||
spdk_lvol_close(g_lvol, close_cb, NULL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user