From: Bart Van Assche <bart.vanassche@sandisk.com>
To: Johannes Thumshirn <jthumshirn@suse.de>,
Christoph Hellwig <hch@lst.de>,
linux-scsi@vger.kernel.org,
James.Bottomley@HansenPartnership.com
Subject: Re: [PATCH] scsi: restart list search after unlock in scsi_remove_target
Date: Tue, 27 Oct 2015 13:14:40 -0700 [thread overview]
Message-ID: <562FDB30.1060304@sandisk.com> (raw)
In-Reply-To: <1445848537.16404.26.camel@suse.de>
On 10/26/2015 01:35 AM, Johannes Thumshirn wrote:
> I haven't heard anything from the original reporter of the lockup but
> my test's went all O.K., so
>
> Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Hello Christoph and Johannes,
How about the patch below, which is a variant of Christoph's patch ?
Thanks,
Bart.
[PATCH] scsi: Restart list search after unlock in scsi_remove_target
When dropping a lock while iterating a list we must restart the search
as other threads could have manipulated the list under us. Without this
we can get stuck in an endless loop. Introduce a new member variable
"visible" in struct scsi_target to track presence in sysfs.
Reported-by: Johannes Thumshirn <jthumshirn@suse.de>
---
drivers/scsi/scsi_scan.c | 16 +++-------------
drivers/scsi/scsi_sysfs.c | 19 ++++++-------------
include/scsi/scsi_device.h | 1 +
3 files changed, 10 insertions(+), 26 deletions(-)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f9f3f82..7b74470 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -314,7 +314,6 @@ static void scsi_target_destroy(struct scsi_target *starget)
struct Scsi_Host *shost = dev_to_shost(dev->parent);
unsigned long flags;
- starget->state = STARGET_DEL;
transport_destroy_device(dev);
spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->target_destroy)
@@ -379,12 +378,8 @@ static void scsi_target_reap_ref_release(struct kref *kref)
struct scsi_target *starget
= container_of(kref, struct scsi_target, reap_ref);
- /*
- * if we get here and the target is still in the CREATED state that
- * means it was allocated but never made visible (because a scan
- * turned up no LUNs), so don't call device_del() on it.
- */
- if (starget->state != STARGET_CREATED) {
+ if (starget->visible) {
+ starget->visible = false;
transport_remove_device(&starget->dev);
device_del(&starget->dev);
}
@@ -507,12 +502,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
*/
void scsi_target_reap(struct scsi_target *starget)
{
- /*
- * serious problem if this triggers: STARGET_DEL is only set in the if
- * the reap_ref drops to zero, so we're trying to do another final put
- * on an already released kref
- */
- BUG_ON(starget->state == STARGET_DEL);
+ starget->state = STARGET_DEL;
scsi_target_reap_ref_put(starget);
}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 5e085d4..de8e202 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -974,7 +974,7 @@ static int scsi_target_add(struct scsi_target *starget)
{
int error;
- if (starget->state != STARGET_CREATED)
+ if (starget->visible)
return 0;
error = device_add(&starget->dev);
@@ -983,6 +983,7 @@ static int scsi_target_add(struct scsi_target *starget)
return error;
}
transport_add_device(&starget->dev);
+ starget->visible = true;
starget->state = STARGET_RUNNING;
pm_runtime_set_active(&starget->dev);
@@ -1166,31 +1167,23 @@ static void __scsi_remove_target(struct scsi_target *starget)
void scsi_remove_target(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev->parent);
- struct scsi_target *starget, *last = NULL;
+ struct scsi_target *starget;
unsigned long flags;
- /* remove targets being careful to lookup next entry before
- * deleting the last
- */
+restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, &shost->__targets, siblings) {
if (starget->state == STARGET_DEL)
continue;
if (starget->dev.parent == dev || &starget->dev == dev) {
- /* assuming new targets arrive at the end */
kref_get(&starget->reap_ref);
spin_unlock_irqrestore(shost->host_lock, flags);
- if (last)
- scsi_target_reap(last);
- last = starget;
__scsi_remove_target(starget);
- spin_lock_irqsave(shost->host_lock, flags);
+ scsi_target_reap(starget);
+ goto restart;
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (last)
- scsi_target_reap(last);
}
EXPORT_SYMBOL(scsi_remove_target);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index fe89d7c..d5a5f21 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -267,6 +267,7 @@ struct scsi_target {
unsigned int expecting_lun_change:1; /* A device has reported
* a 3F/0E UA, other devices on
* the same target will also. */
+ unsigned int visible:1; /* visible in sysfs */
/* commands actually active on LLD. */
atomic_t target_busy;
atomic_t target_blocked;
--
2.1.4
next prev parent reply other threads:[~2015-10-27 20:14 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-19 14:35 [PATCH] scsi: restart list search after unlock in scsi_remove_target Christoph Hellwig
2015-10-19 15:36 ` Bart Van Assche
2015-10-19 15:56 ` Christoph Hellwig
2015-10-19 16:01 ` James Bottomley
2015-10-19 17:21 ` Dan Williams
2015-10-26 8:35 ` Johannes Thumshirn
2015-10-27 20:14 ` Bart Van Assche [this message]
2015-10-30 8:26 ` Johannes Thumshirn
2015-10-27 16:33 ` Johannes Thumshirn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=562FDB30.1060304@sandisk.com \
--to=bart.vanassche@sandisk.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=hch@lst.de \
--cc=jthumshirn@suse.de \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).