From a646aba83573ee19b24da0949e879ebbd6e6edc5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 23 Nov 2012 09:02:10 +0000 Subject: [PATCH] scst: Don't suspend activity during removal of a SCSI device (merge r4399 from trunk) SCST allows SCSI pass-through to SCSI devices registered with the SCSI initiator core. SCST I/O activity has to be suspended before a LUN that corresponds to such a SCSI device can be removed safely. Do not suspend I/O when a SCSI device is being removed that has not been exported as an SCST LUN such that removal of such devices does not slow down I/O. git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@4624 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_main.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 4e2346445..b970117a9 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -991,23 +991,44 @@ out_resume: goto out; } +static struct scst_device *__scst_lookup_device(struct scsi_device *scsidp) +{ + struct scst_device *d; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) + lockdep_assert_held(&scst_mutex); +#endif + + list_for_each_entry(d, &scst_dev_list, dev_list_entry) + if (d->scsi_dev == scsidp) + return d; + + return NULL; +} + static void scst_unregister_device(struct scsi_device *scsidp) { - struct scst_device *d, *dev = NULL; + struct scst_device *dev; struct scst_acg_dev *acg_dev, *aa; + bool activity_suspended = false; TRACE_ENTRY(); - scst_suspend_activity(false); mutex_lock(&scst_mutex); - list_for_each_entry(d, &scst_dev_list, dev_list_entry) { - if (d->scsi_dev == scsidp) { - dev = d; - TRACE_DBG("Device %p found", dev); - break; - } + dev = __scst_lookup_device(scsidp); + + if (dev && + (!list_empty(&dev->dev_tgt_dev_list) || + !list_empty(&dev->dev_acg_dev_list))) { + mutex_unlock(&scst_mutex); + + scst_suspend_activity(false); + activity_suspended = true; + mutex_lock(&scst_mutex); + dev = __scst_lookup_device(scsidp); } + if (dev == NULL) { PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%d not found", scsidp->host->host_no, scsidp->channel, scsidp->id, @@ -1030,7 +1051,8 @@ static void scst_unregister_device(struct scsi_device *scsidp) mutex_unlock(&scst_mutex); - scst_resume_activity(); + if (activity_suspended) + scst_resume_activity(); scst_dev_sysfs_del(dev); @@ -1046,7 +1068,8 @@ out: out_unlock: mutex_unlock(&scst_mutex); - scst_resume_activity(); + if (activity_suspended) + scst_resume_activity(); goto out; }