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

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


Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 40872802
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3221,6 +3221,13 @@ spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
	task->tag = task_tag;
	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) {
	/* abort task identified by Referenced Task Tag field */
	case ISCSI_TASK_FUNC_ABORT_TASK:
+5 −2
Original line number Diff line number Diff line
@@ -252,7 +252,8 @@ spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
	assert(task != NULL);

	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
@@ -406,7 +407,9 @@ spdk_scsi_dev_has_pending_tasks(const struct spdk_scsi_dev *dev)
	int 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;
		}
	}
+55 −25
Original line number Diff line number Diff line
@@ -49,6 +49,18 @@ spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *ta
	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
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
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);

	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;
	}
	TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);

	switch (task->function) {
	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:
		spdk_bdev_scsi_reset(task);
		return 0;
		return;

	default:
		SPDK_ERRLOG("Unknown Task Management Function!\n");
@@ -115,9 +111,32 @@ spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
		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
@@ -241,7 +260,8 @@ spdk_scsi_lun_check_pending_tasks(void *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;
	}
	spdk_poller_unregister(&lun->hotremove_poller);
@@ -255,7 +275,8 @@ _spdk_scsi_lun_hot_remove(void *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, 10);
	} else {
@@ -323,6 +344,8 @@ spdk_scsi_lun_construct(struct spdk_bdev *bdev,
	}

	TAILQ_INIT(&lun->tasks);
	TAILQ_INIT(&lun->mgmt_tasks);
	TAILQ_INIT(&lun->pending_mgmt_tasks);

	lun->bdev = bdev;
	lun->io_channel = NULL;
@@ -446,6 +469,13 @@ spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
	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
spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun)
{
+10 −1
Original line number Diff line number Diff line
@@ -117,6 +117,13 @@ struct spdk_scsi_lun {

	/** pending 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 {
@@ -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_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_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);
+13 −3
Original line number Diff line number Diff line
@@ -111,10 +111,20 @@ spdk_bdev_get_by_name(const char *bdev_name)
	return NULL;
}

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)
{
	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
Loading