Commit c645cc69 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

scsi: Reorder LUN hot removal to check outstanding tasks and then IO channel



Reorder operations of LUN hot removal so that following are satisfied.

Wait for completion of all outstanding tasks first. (After turning lun->removed
on, there will be no new outstanding task.)

Then wait for IO channel being freed. (For VHOST SCSI, IO channel is freed
in the callback handler of hot removal. For iSCSI, IO channel is freed when
the final connection exits. IO channel of LUN is freed only by the allocator.)

Then free LUN finally.

For VHOST SCSI, the callback handler of hot removal will
call spdk_scsi_lun_destruct() in spdk_scsi_dev_destruct(). But lun->removed is
already turned on and spdk_scsi_lun_hot_remove() will be NOP. Hence LUN is
freed safely by the first caller of spdk_scsi_lun_hot_remove().

Change-Id: I276dfed1d4a7767e382003bd9bb389aaff920115
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/417196


Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 8ee51221
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -191,39 +191,61 @@ spdk_scsi_lun_remove(struct spdk_scsi_lun *lun)
}

static int
spdk_scsi_lun_hot_remove_poll(void *arg)
spdk_scsi_lun_check_io_channel(void *arg)
{
	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;

	if (spdk_scsi_lun_has_pending_tasks(lun) ||
	    lun->io_channel != NULL) {
	if (lun->io_channel) {
		return -1;
	}

	spdk_poller_unregister(&lun->hotremove_poller);
	spdk_scsi_lun_remove(lun);

	spdk_scsi_lun_remove(lun);
	return -1;
}

static void
_spdk_scsi_lun_hot_remove(void *arg1)
spdk_scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
{
	struct spdk_scsi_lun *lun = arg1;

	if (lun->hotremove_cb) {
		lun->hotremove_cb(lun, lun->hotremove_ctx);
	}

	if (spdk_scsi_lun_has_pending_tasks(lun) ||
	    lun->io_channel != NULL) {
		lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_hot_remove_poll,
	if (lun->io_channel) {
		lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_io_channel,
					lun, 10);
	} else {
		spdk_scsi_lun_remove(lun);
	}
}

static int
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)) {
		return -1;
	}
	spdk_poller_unregister(&lun->hotremove_poller);

	spdk_scsi_lun_notify_hot_remove(lun);
	return -1;
}

static void
_spdk_scsi_lun_hot_remove(void *arg1)
{
	struct spdk_scsi_lun *lun = arg1;

	if (spdk_scsi_lun_has_pending_tasks(lun)) {
		lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_pending_tasks,
					lun, 10);
	} else {
		spdk_scsi_lun_notify_hot_remove(lun);
	}
}

static void
spdk_scsi_lun_hot_remove(void *remove_ctx)
{