Commit d0e3f624 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Ben Walker
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/434766


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent b409bf40
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -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);
}

/* 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
spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
{
	if (task->status == SPDK_SCSI_STATUS_GOOD) {
		/*
		 * The backend LUN device was just reset. If there are active tasks
		 * in the backend, it means that LUN reset fails, and we set failure
		 * status to LUN reset task.
		 */
		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;
		if (spdk_scsi_lun_has_outstanding_tasks(lun)) {
			lun->reset_poller =
				spdk_poller_register(spdk_scsi_lun_reset_check_outstanding_tasks,
						     task, 10);
			return;
		}
	}

+2 −0
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ struct spdk_scsi_lun {
	/** pending management 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 {
+10 −0
Original line number Diff line number Diff line
@@ -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
spdk_lun_ut_cpl_task(struct spdk_scsi_task *task)
{