scsi: Serialize LUN reset execution

Task management functions don't require performance. Serializing
execution of task managment functions will sipmlify and stabilize
the logic and will be helpful for upcoming patches to support
other task management functions.

This patch introduces two queues, pending and submitted queue,
and serializes LUN reset exection and makes LUN hot removal
wait for LUN reset.

Besides, checking if LUN is NULL is moved to the upper layer as
same as IO task submission.

Change-Id: Ia0cf3f437a745ee70fc9b17744cc63c833690dda
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/434764
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-11-28 09:47:45 +09:00 committed by Ben Walker
parent 408728025e
commit 6dd09113e5
6 changed files with 111 additions and 129 deletions

View File

@ -3221,6 +3221,13 @@ spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
task->tag = task_tag; task->tag = task_tag;
task->scsi.lun = spdk_scsi_dev_get_lun(dev, lun_i); task->scsi.lun = spdk_scsi_dev_get_lun(dev, lun_i);
if (task->scsi.lun == NULL) {
task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
spdk_iscsi_task_mgmt_response(conn, task);
spdk_iscsi_task_put(task);
return 0;
}
switch (function) { switch (function) {
/* abort task identified by Referenced Task Tag field */ /* abort task identified by Referenced Task Tag field */
case ISCSI_TASK_FUNC_ABORT_TASK: case ISCSI_TASK_FUNC_ABORT_TASK:

View File

@ -252,7 +252,8 @@ spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
assert(task != NULL); assert(task != NULL);
task->function = func; task->function = func;
spdk_scsi_lun_task_mgmt_execute(task); spdk_scsi_lun_append_mgmt_task(task->lun, task);
spdk_scsi_lun_execute_mgmt_task(task->lun);
} }
void void
@ -406,7 +407,9 @@ spdk_scsi_dev_has_pending_tasks(const struct spdk_scsi_dev *dev)
int i; int i;
for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; ++i) { for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; ++i) {
if (dev->lun[i] && spdk_scsi_lun_has_pending_tasks(dev->lun[i])) { if (dev->lun[i] &&
(spdk_scsi_lun_has_pending_tasks(dev->lun[i]) ||
spdk_scsi_lun_has_pending_mgmt_tasks(dev->lun[i]))) {
return true; return true;
} }
} }

View File

@ -49,6 +49,18 @@ spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *ta
task->cpl_fn(task); task->cpl_fn(task);
} }
static void
spdk_scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
{
TAILQ_REMOVE(&lun->mgmt_tasks, task, scsi_link);
task->cpl_fn(task);
/* Try to execute the first pending mgmt task if it exists. */
spdk_scsi_lun_execute_mgmt_task(lun);
}
/* This will be called in the callback to the bdev reset function. */
void void
spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
{ {
@ -64,30 +76,14 @@ spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_ta
} }
} }
task->cpl_fn(task); spdk_scsi_lun_complete_mgmt_task(lun, task);
} }
static void static void
spdk_scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) _spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
struct spdk_scsi_task *task)
{ {
assert(task->function != SPDK_SCSI_TASK_FUNC_LUN_RESET); TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
task->cpl_fn(task);
}
int
spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
{
if (!task) {
return -1;
}
if (!task->lun) {
/* LUN does not exist */
task->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
task->cpl_fn(task);
return -1;
}
switch (task->function) { switch (task->function) {
case SPDK_SCSI_TASK_FUNC_ABORT_TASK: case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
@ -102,7 +98,7 @@ spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
case SPDK_SCSI_TASK_FUNC_LUN_RESET: case SPDK_SCSI_TASK_FUNC_LUN_RESET:
spdk_bdev_scsi_reset(task); spdk_bdev_scsi_reset(task);
return 0; return;
default: default:
SPDK_ERRLOG("Unknown Task Management Function!\n"); SPDK_ERRLOG("Unknown Task Management Function!\n");
@ -115,9 +111,32 @@ spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
break; break;
} }
spdk_scsi_lun_complete_mgmt_task(task->lun, task); spdk_scsi_lun_complete_mgmt_task(lun, task);
}
return -1; void
spdk_scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun,
struct spdk_scsi_task *task)
{
TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, task, scsi_link);
}
void
spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun)
{
struct spdk_scsi_task *task;
if (!TAILQ_EMPTY(&lun->mgmt_tasks)) {
return;
}
task = TAILQ_FIRST(&lun->pending_mgmt_tasks);
if (task == NULL) {
return;
}
TAILQ_REMOVE(&lun->pending_mgmt_tasks, task, scsi_link);
_spdk_scsi_lun_execute_mgmt_task(lun, task);
} }
void void
@ -241,7 +260,8 @@ spdk_scsi_lun_check_pending_tasks(void *arg)
{ {
struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg; struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
if (spdk_scsi_lun_has_pending_tasks(lun)) { if (spdk_scsi_lun_has_pending_tasks(lun) ||
spdk_scsi_lun_has_pending_mgmt_tasks(lun)) {
return -1; return -1;
} }
spdk_poller_unregister(&lun->hotremove_poller); spdk_poller_unregister(&lun->hotremove_poller);
@ -255,7 +275,8 @@ _spdk_scsi_lun_hot_remove(void *arg1)
{ {
struct spdk_scsi_lun *lun = arg1; struct spdk_scsi_lun *lun = arg1;
if (spdk_scsi_lun_has_pending_tasks(lun)) { if (spdk_scsi_lun_has_pending_tasks(lun) ||
spdk_scsi_lun_has_pending_mgmt_tasks(lun)) {
lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_pending_tasks, lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_pending_tasks,
lun, 10); lun, 10);
} else { } else {
@ -323,6 +344,8 @@ spdk_scsi_lun_construct(struct spdk_bdev *bdev,
} }
TAILQ_INIT(&lun->tasks); TAILQ_INIT(&lun->tasks);
TAILQ_INIT(&lun->mgmt_tasks);
TAILQ_INIT(&lun->pending_mgmt_tasks);
lun->bdev = bdev; lun->bdev = bdev;
lun->io_channel = NULL; lun->io_channel = NULL;
@ -446,6 +469,13 @@ spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
return lun->dev; return lun->dev;
} }
bool
spdk_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun)
{
return !TAILQ_EMPTY(&lun->pending_mgmt_tasks) ||
!TAILQ_EMPTY(&lun->mgmt_tasks);
}
bool bool
spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun) spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun)
{ {

View File

@ -117,6 +117,13 @@ struct spdk_scsi_lun {
/** pending tasks */ /** pending tasks */
TAILQ_HEAD(tasks, spdk_scsi_task) tasks; TAILQ_HEAD(tasks, spdk_scsi_task) tasks;
/** submitted management tasks */
TAILQ_HEAD(mgmt_tasks, spdk_scsi_task) mgmt_tasks;
/** pending management tasks */
TAILQ_HEAD(pending_mgmt_tasks, spdk_scsi_task) pending_mgmt_tasks;
}; };
struct spdk_lun_db_entry { struct spdk_lun_db_entry {
@ -137,7 +144,9 @@ _spdk_scsi_lun *spdk_scsi_lun_construct(struct spdk_bdev *bdev,
void spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun); void spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun);
void spdk_scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); void spdk_scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
int spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task); void spdk_scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
void spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun);
bool spdk_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun);
void spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); void spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
void spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); void spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
bool spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun); bool spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun);

View File

@ -111,10 +111,20 @@ spdk_bdev_get_by_name(const char *bdev_name)
return NULL; return NULL;
} }
int void
spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task) spdk_scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
{ {
return 0; }
void
spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun)
{
}
bool
spdk_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun)
{
return false;
} }
void void

View File

@ -163,7 +163,10 @@ void spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev,
void void
spdk_bdev_scsi_reset(struct spdk_scsi_task *task) spdk_bdev_scsi_reset(struct spdk_scsi_task *task)
{ {
return; task->status = SPDK_SCSI_STATUS_GOOD;
task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
spdk_scsi_lun_complete_reset_task(task->lun, task);
} }
int int
@ -219,37 +222,6 @@ lun_destruct(struct spdk_scsi_lun *lun)
spdk_scsi_lun_destruct(lun); spdk_scsi_lun_destruct(lun);
} }
static void
lun_task_mgmt_execute_null_task(void)
{
int rc;
rc = spdk_scsi_lun_task_mgmt_execute(NULL);
/* returns -1 since we passed NULL for the task */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT_EQUAL(g_task_count, 0);
}
static void
lun_task_mgmt_execute_abort_task_null_lun_failure(void)
{
struct spdk_scsi_task mgmt_task = { 0 };
struct spdk_scsi_port initiator_port = { 0 };
int rc;
ut_init_task(&mgmt_task);
mgmt_task.lun = NULL;
mgmt_task.initiator_port = &initiator_port;
mgmt_task.function = SPDK_SCSI_TASK_FUNC_ABORT_TASK;
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task);
/* returns -1 since we passed NULL for LUN */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT_EQUAL(g_task_count, 0);
}
static void static void
lun_task_mgmt_execute_abort_task_not_supported(void) lun_task_mgmt_execute_abort_task_not_supported(void)
{ {
@ -259,7 +231,6 @@ lun_task_mgmt_execute_abort_task_not_supported(void)
struct spdk_scsi_port initiator_port = { 0 }; struct spdk_scsi_port initiator_port = { 0 };
struct spdk_scsi_dev dev = { 0 }; struct spdk_scsi_dev dev = { 0 };
uint8_t cdb[6] = { 0 }; uint8_t cdb[6] = { 0 };
int rc;
lun = lun_construct(); lun = lun_construct();
lun->dev = &dev; lun->dev = &dev;
@ -279,10 +250,10 @@ lun_task_mgmt_execute_abort_task_not_supported(void)
/* task should now be on the tasks list */ /* task should now be on the tasks list */
CU_ASSERT(!TAILQ_EMPTY(&lun->tasks)); CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task); spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);
spdk_scsi_lun_execute_mgmt_task(lun);
/* returns -1 since task abort is not supported */ /* task abort is not supported */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED); CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
/* task is still on the tasks list */ /* task is still on the tasks list */
@ -294,26 +265,6 @@ lun_task_mgmt_execute_abort_task_not_supported(void)
lun_destruct(lun); lun_destruct(lun);
} }
static void
lun_task_mgmt_execute_abort_task_all_null_lun_failure(void)
{
struct spdk_scsi_task mgmt_task = { 0 };
struct spdk_scsi_port initiator_port = { 0 };
int rc;
ut_init_task(&mgmt_task);
mgmt_task.lun = NULL;
mgmt_task.initiator_port = &initiator_port;
mgmt_task.function = SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET;
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task);
/* Returns -1 since we passed NULL for lun */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT_EQUAL(g_task_count, 0);
}
static void static void
lun_task_mgmt_execute_abort_task_all_not_supported(void) lun_task_mgmt_execute_abort_task_all_not_supported(void)
{ {
@ -322,7 +273,6 @@ lun_task_mgmt_execute_abort_task_all_not_supported(void)
struct spdk_scsi_task mgmt_task = { 0 }; struct spdk_scsi_task mgmt_task = { 0 };
struct spdk_scsi_port initiator_port = { 0 }; struct spdk_scsi_port initiator_port = { 0 };
struct spdk_scsi_dev dev = { 0 }; struct spdk_scsi_dev dev = { 0 };
int rc;
uint8_t cdb[6] = { 0 }; uint8_t cdb[6] = { 0 };
lun = lun_construct(); lun = lun_construct();
@ -344,10 +294,10 @@ lun_task_mgmt_execute_abort_task_all_not_supported(void)
/* task should now be on the tasks list */ /* task should now be on the tasks list */
CU_ASSERT(!TAILQ_EMPTY(&lun->tasks)); CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task); spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);
spdk_scsi_lun_execute_mgmt_task(lun);
/* returns -1 since task abort is not supported */ /* task abort is not supported */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED); CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
/* task is still on the tasks list */ /* task is still on the tasks list */
@ -360,31 +310,12 @@ lun_task_mgmt_execute_abort_task_all_not_supported(void)
lun_destruct(lun); lun_destruct(lun);
} }
static void
lun_task_mgmt_execute_lun_reset_failure(void)
{
struct spdk_scsi_task mgmt_task = { 0 };
int rc;
ut_init_task(&mgmt_task);
mgmt_task.lun = NULL;
mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task);
/* Returns -1 since we passed NULL for lun */
CU_ASSERT_TRUE(rc < 0);
CU_ASSERT_EQUAL(g_task_count, 0);
}
static void static void
lun_task_mgmt_execute_lun_reset(void) lun_task_mgmt_execute_lun_reset(void)
{ {
struct spdk_scsi_lun *lun; struct spdk_scsi_lun *lun;
struct spdk_scsi_task mgmt_task = { 0 }; struct spdk_scsi_task mgmt_task = { 0 };
struct spdk_scsi_dev dev = { 0 }; struct spdk_scsi_dev dev = { 0 };
int rc;
lun = lun_construct(); lun = lun_construct();
lun->dev = &dev; lun->dev = &dev;
@ -393,16 +324,16 @@ lun_task_mgmt_execute_lun_reset(void)
mgmt_task.lun = lun; mgmt_task.lun = lun;
mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET; mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task); spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);
spdk_scsi_lun_execute_mgmt_task(lun);
/* Returns success */ /* Returns success */
CU_ASSERT_EQUAL(rc, 0); CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
lun_destruct(lun); lun_destruct(lun);
/* task is still on the tasks list */ CU_ASSERT_EQUAL(g_task_count, 0);
CU_ASSERT_EQUAL(g_task_count, 1);
g_task_count = 0;
} }
static void static void
@ -411,7 +342,6 @@ lun_task_mgmt_execute_invalid_case(void)
struct spdk_scsi_lun *lun; struct spdk_scsi_lun *lun;
struct spdk_scsi_task mgmt_task = { 0 }; struct spdk_scsi_task mgmt_task = { 0 };
struct spdk_scsi_dev dev = { 0 }; struct spdk_scsi_dev dev = { 0 };
int rc;
lun = lun_construct(); lun = lun_construct();
lun->dev = &dev; lun->dev = &dev;
@ -420,10 +350,11 @@ lun_task_mgmt_execute_invalid_case(void)
mgmt_task.function = 5; mgmt_task.function = 5;
/* Pass an invalid value to the switch statement */ /* Pass an invalid value to the switch statement */
rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task); spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);
spdk_scsi_lun_execute_mgmt_task(lun);
/* Returns -1 on passing an invalid value to the switch case */ /* function code is invalid */
CU_ASSERT_TRUE(rc < 0); CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
lun_destruct(lun); lun_destruct(lun);
@ -620,18 +551,10 @@ main(int argc, char **argv)
} }
if ( if (
CU_add_test(suite, "task management - null task failure", CU_add_test(suite, "task management abort task - not supported",
lun_task_mgmt_execute_null_task) == NULL lun_task_mgmt_execute_abort_task_not_supported) == NULL
|| CU_add_test(suite, "task management abort task - null lun failure",
lun_task_mgmt_execute_abort_task_null_lun_failure) == NULL
|| CU_add_test(suite, "task management abort task - not supported",
lun_task_mgmt_execute_abort_task_not_supported) == NULL
|| CU_add_test(suite, "task management abort task set - null lun failure",
lun_task_mgmt_execute_abort_task_all_null_lun_failure) == NULL
|| CU_add_test(suite, "task management abort task set - success", || CU_add_test(suite, "task management abort task set - success",
lun_task_mgmt_execute_abort_task_all_not_supported) == NULL lun_task_mgmt_execute_abort_task_all_not_supported) == NULL
|| CU_add_test(suite, "task management - lun reset failure",
lun_task_mgmt_execute_lun_reset_failure) == NULL
|| CU_add_test(suite, "task management - lun reset success", || CU_add_test(suite, "task management - lun reset success",
lun_task_mgmt_execute_lun_reset) == NULL lun_task_mgmt_execute_lun_reset) == NULL
|| CU_add_test(suite, "task management - invalid option", || CU_add_test(suite, "task management - invalid option",