From c645cc69ab178de4b795a54a863fa39567ceedb1 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Thu, 28 Jun 2018 10:56:06 +0900 Subject: [PATCH] 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: Shuhei Matsumoto Reviewed-on: https://review.gerrithub.io/417196 Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris Tested-by: SPDK Automated Test System --- lib/scsi/lun.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/lib/scsi/lun.c b/lib/scsi/lun.c index cd477ed9d..157265c46 100644 --- a/lib/scsi/lun.c +++ b/lib/scsi/lun.c @@ -191,18 +191,45 @@ 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_notify_hot_remove(struct spdk_scsi_lun *lun) +{ + if (lun->hotremove_cb) { + lun->hotremove_cb(lun, lun->hotremove_ctx); + } + + 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; } @@ -211,16 +238,11 @@ _spdk_scsi_lun_hot_remove(void *arg1) { 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 (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_remove(lun); + spdk_scsi_lun_notify_hot_remove(lun); } }