scsi: LUN reset waits for completion of all prior tasks
IO submissions to backends have to complete first in LUN reset. Previous patch makes the waiting time limited. LUN reset don't use timeout for now because even if LUN reset reports timeout, error handling of the initiator will be escalated and the initiator will issue stronger command and will wait eventually until all outstanding tasks completed. Besides, not using timeout in LUN reset will make implementation simple. If timeout becomes necessary, I'll do it in the separate patch later. Change-Id: Ie9e4502068c19b1727ea65dc773ddf08cedec7c4 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/434766 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
b409bf4080
commit
d0e3f624f0
@ -61,19 +61,37 @@ spdk_scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_tas
|
|||||||
spdk_scsi_lun_execute_mgmt_task(lun);
|
spdk_scsi_lun_execute_mgmt_task(lun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This will be called in the callback to the bdev reset function. */
|
static bool
|
||||||
|
spdk_scsi_lun_has_outstanding_tasks(struct spdk_scsi_lun *lun)
|
||||||
|
{
|
||||||
|
return !TAILQ_EMPTY(&lun->tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset task have to wait until all prior outstanding tasks complete. */
|
||||||
|
static int
|
||||||
|
spdk_scsi_lun_reset_check_outstanding_tasks(void *arg)
|
||||||
|
{
|
||||||
|
struct spdk_scsi_task *task = (struct spdk_scsi_task *)arg;
|
||||||
|
struct spdk_scsi_lun *lun = task->lun;
|
||||||
|
|
||||||
|
if (spdk_scsi_lun_has_outstanding_tasks(lun)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
spdk_poller_unregister(&lun->reset_poller);
|
||||||
|
|
||||||
|
spdk_scsi_lun_complete_mgmt_task(lun, task);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (task->status == SPDK_SCSI_STATUS_GOOD) {
|
if (task->status == SPDK_SCSI_STATUS_GOOD) {
|
||||||
/*
|
if (spdk_scsi_lun_has_outstanding_tasks(lun)) {
|
||||||
* The backend LUN device was just reset. If there are active tasks
|
lun->reset_poller =
|
||||||
* in the backend, it means that LUN reset fails, and we set failure
|
spdk_poller_register(spdk_scsi_lun_reset_check_outstanding_tasks,
|
||||||
* status to LUN reset task.
|
task, 10);
|
||||||
*/
|
return;
|
||||||
if (spdk_scsi_lun_has_pending_tasks(lun)) {
|
|
||||||
SPDK_ERRLOG("lun->tasks should be empty after reset\n");
|
|
||||||
task->response = SPDK_SCSI_TASK_MGMT_RESP_TARGET_FAILURE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,8 @@ struct spdk_scsi_lun {
|
|||||||
/** pending management tasks */
|
/** pending management tasks */
|
||||||
TAILQ_HEAD(pending_mgmt_tasks, spdk_scsi_task) pending_mgmt_tasks;
|
TAILQ_HEAD(pending_mgmt_tasks, spdk_scsi_task) pending_mgmt_tasks;
|
||||||
|
|
||||||
|
/** poller to check completion of tasks prior to reset */
|
||||||
|
struct spdk_poller *reset_poller;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spdk_lun_db_entry {
|
struct spdk_lun_db_entry {
|
||||||
|
@ -77,6 +77,16 @@ void _spdk_trace_record(uint64_t tsc, uint16_t tpoint_id, uint16_t poller_id,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t spdk_get_ticks(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t spdk_get_ticks_hz(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_lun_ut_cpl_task(struct spdk_scsi_task *task)
|
spdk_lun_ut_cpl_task(struct spdk_scsi_task *task)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user