Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1364038 > unrolled thread

[PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state

Started byJohannes Thumshirn <jthumshirn@suse.de>
First post2016-03-24 11:00 +0100
Last post2016-03-29 09:50 +0200
Articles 4 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state Johannes Thumshirn <jthumshirn@suse.de> - 2016-03-24 11:00 +0100
    Re: [PATCH] scsi: Add intermediate STARGET_REMOVE state to  scsi_target_state "Ewan D. Milne" <emilne@redhat.com> - 2016-03-24 16:50 +0100
      Re: [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state Johannes Thumshirn <jthumshirn@suse.de> - 2016-03-29 09:30 +0200
      Re: [PATCH] scsi: Add intermediate STARGET_REMOVE state to  scsi_target_state Christoph Hellwig <hch@infradead.org> - 2016-03-29 09:50 +0200

#1364038 — [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state

FromJohannes Thumshirn <jthumshirn@suse.de>
Date2016-03-24 11:00 +0100
Subject[PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state
Message-ID<rgadC-EQ-19@gated-at.bofh.it>
The target state machine only knows 'STARGET_DEL', which is set once
scsi_target_destroy() is called.
However, by that time the structure is still part of the __stargets
list of the SCSI host, so any concurrent invocation will see this as
a valid target, causing an access to freed memory.

This patch adds an intermediate state 'STARGET_REMOVE', which is set
as soon as the target is scheduled to be removed.
With this any concurrent invocation will be able to skip these
targets and avoid the above scenario.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Fixes: 90a88d6ef 'scsi: fix soft lockup in scsi_remove_target() on module removal'
Cc: stable@vger.kernel.org
Reviewed-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/scsi_scan.c   | 1 +
 drivers/scsi/scsi_sysfs.c  | 2 ++
 include/scsi/scsi_device.h | 1 +
 3 files changed, 4 insertions(+)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 6a82066..37459dfa 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -315,6 +315,7 @@ static void scsi_target_destroy(struct scsi_target *starget)
 	struct Scsi_Host *shost = dev_to_shost(dev->parent);
 	unsigned long flags;
 
+	BUG_ON(starget->state != STARGET_REMOVE);
 	starget->state = STARGET_DEL;
 	transport_destroy_device(dev);
 	spin_lock_irqsave(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 00bc721..0df82e8 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1279,11 +1279,13 @@ restart:
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_for_each_entry(starget, &shost->__targets, siblings) {
 		if (starget->state == STARGET_DEL ||
+		    starget->state == STARGET_REMOVE ||
 		    starget == last_target)
 			continue;
 		if (starget->dev.parent == dev || &starget->dev == dev) {
 			kref_get(&starget->reap_ref);
 			last_target = starget;
+			starget->state = STARGET_REMOVE;
 			spin_unlock_irqrestore(shost->host_lock, flags);
 			__scsi_remove_target(starget);
 			scsi_target_reap(starget);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index f63a167..2bffaa6 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -240,6 +240,7 @@ scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...);
 enum scsi_target_state {
 	STARGET_CREATED = 1,
 	STARGET_RUNNING,
+	STARGET_REMOVE,
 	STARGET_DEL,
 };
 
-- 
1.8.5.6

[toc] | [next] | [standalone]


#1364288 — Re: [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state

From"Ewan D. Milne" <emilne@redhat.com>
Date2016-03-24 16:50 +0100
SubjectRe: [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state
Message-ID<rgfGi-4EY-25@gated-at.bofh.it>
In reply to#1364038
On Thu, 2016-03-24 at 10:56 +0100, Johannes Thumshirn wrote:
> The target state machine only knows 'STARGET_DEL', which is set once
> scsi_target_destroy() is called.
> However, by that time the structure is still part of the __stargets
> list of the SCSI host, so any concurrent invocation will see this as
> a valid target, causing an access to freed memory.
> 
> This patch adds an intermediate state 'STARGET_REMOVE', which is set
> as soon as the target is scheduled to be removed.
> With this any concurrent invocation will be able to skip these
> targets and avoid the above scenario.
> 
> Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
> Fixes: 90a88d6ef 'scsi: fix soft lockup in scsi_remove_target() on module removal'
> Cc: stable@vger.kernel.org
> Reviewed-by: Hannes Reinecke <hare@suse.com>
> ---
>  drivers/scsi/scsi_scan.c   | 1 +
>  drivers/scsi/scsi_sysfs.c  | 2 ++
>  include/scsi/scsi_device.h | 1 +
>  3 files changed, 4 insertions(+)
> 
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index 6a82066..37459dfa 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -315,6 +315,7 @@ static void scsi_target_destroy(struct scsi_target *starget)
>  	struct Scsi_Host *shost = dev_to_shost(dev->parent);
>  	unsigned long flags;
>  
> +	BUG_ON(starget->state != STARGET_REMOVE);
>  	starget->state = STARGET_DEL;
>  	transport_destroy_device(dev);
>  	spin_lock_irqsave(shost->host_lock, flags);
> diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
> index 00bc721..0df82e8 100644
> --- a/drivers/scsi/scsi_sysfs.c
> +++ b/drivers/scsi/scsi_sysfs.c
> @@ -1279,11 +1279,13 @@ restart:
>  	spin_lock_irqsave(shost->host_lock, flags);
>  	list_for_each_entry(starget, &shost->__targets, siblings) {
>  		if (starget->state == STARGET_DEL ||
> +		    starget->state == STARGET_REMOVE ||
>  		    starget == last_target)
>  			continue;
>  		if (starget->dev.parent == dev || &starget->dev == dev) {
>  			kref_get(&starget->reap_ref);
>  			last_target = starget;
> +			starget->state = STARGET_REMOVE;
>  			spin_unlock_irqrestore(shost->host_lock, flags);
>  			__scsi_remove_target(starget);
>  			scsi_target_reap(starget);
> diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> index f63a167..2bffaa6 100644
> --- a/include/scsi/scsi_device.h
> +++ b/include/scsi/scsi_device.h
> @@ -240,6 +240,7 @@ scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...);
>  enum scsi_target_state {
>  	STARGET_CREATED = 1,
>  	STARGET_RUNNING,
> +	STARGET_REMOVE,
>  	STARGET_DEL,
>  };
>  

This looks fine.  Do we still need 90a88d6ef (scsi: fix soft lockup in
scsi_remove_target() on module removal) or can that be reverted now,
since the STARGET_REMOVE state will allow the iteration to continue?

Reviewed-by: Ewan D. Milne <emilne@redhat.com>

[toc] | [prev] | [next] | [standalone]


#1365933

FromJohannes Thumshirn <jthumshirn@suse.de>
Date2016-03-29 09:30 +0200
Message-ID<rhWga-2Ka-15@gated-at.bofh.it>
In reply to#1364288
On Donnerstag, 24. März 2016 11:42:44 CEST Ewan D. Milne wrote:
> On Thu, 2016-03-24 at 10:56 +0100, Johannes Thumshirn wrote:
> > The target state machine only knows 'STARGET_DEL', which is set once
> > scsi_target_destroy() is called.
> > However, by that time the structure is still part of the __stargets
> > list of the SCSI host, so any concurrent invocation will see this as
> > a valid target, causing an access to freed memory.
> > 
> > This patch adds an intermediate state 'STARGET_REMOVE', which is set
> > as soon as the target is scheduled to be removed.
> > With this any concurrent invocation will be able to skip these
> > targets and avoid the above scenario.
> > 
> > Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
> > Fixes: 90a88d6ef 'scsi: fix soft lockup in scsi_remove_target() on module
> > removal' Cc: stable@vger.kernel.org
> > Reviewed-by: Hannes Reinecke <hare@suse.com>
> > ---
> > 
> >  drivers/scsi/scsi_scan.c   | 1 +
> >  drivers/scsi/scsi_sysfs.c  | 2 ++
> >  include/scsi/scsi_device.h | 1 +
> >  3 files changed, 4 insertions(+)
> > 
> > diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> > index 6a82066..37459dfa 100644
> > --- a/drivers/scsi/scsi_scan.c
> > +++ b/drivers/scsi/scsi_scan.c
> > @@ -315,6 +315,7 @@ static void scsi_target_destroy(struct scsi_target
> > *starget)> 
> >  	struct Scsi_Host *shost = dev_to_shost(dev->parent);
> >  	unsigned long flags;
> > 
> > +	BUG_ON(starget->state != STARGET_REMOVE);
> > 
> >  	starget->state = STARGET_DEL;
> >  	transport_destroy_device(dev);
> >  	spin_lock_irqsave(shost->host_lock, flags);
> > 
> > diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
> > index 00bc721..0df82e8 100644
> > --- a/drivers/scsi/scsi_sysfs.c
> > +++ b/drivers/scsi/scsi_sysfs.c
> > 
> > @@ -1279,11 +1279,13 @@ restart:
> >  	spin_lock_irqsave(shost->host_lock, flags);
> >  	list_for_each_entry(starget, &shost->__targets, siblings) {
> >  	
> >  		if (starget->state == STARGET_DEL ||
> > 
> > +		    starget->state == STARGET_REMOVE ||
> > 
> >  		    starget == last_target)
> >  			
> >  			continue;
> >  		
> >  		if (starget->dev.parent == dev || &starget->dev == dev) {
> >  		
> >  			kref_get(&starget->reap_ref);
> >  			last_target = starget;
> > 
> > +			starget->state = STARGET_REMOVE;
> > 
> >  			spin_unlock_irqrestore(shost->host_lock, flags);
> >  			__scsi_remove_target(starget);
> >  			scsi_target_reap(starget);
> > 
> > diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> > index f63a167..2bffaa6 100644
> > --- a/include/scsi/scsi_device.h
> > +++ b/include/scsi/scsi_device.h
> > @@ -240,6 +240,7 @@ scmd_printk(const char *, const struct scsi_cmnd *,
> > const char *, ...);> 
> >  enum scsi_target_state {
> >  
> >  	STARGET_CREATED = 1,
> >  	STARGET_RUNNING,
> > 
> > +	STARGET_REMOVE,
> > 
> >  	STARGET_DEL,
> >  
> >  };
> 
> This looks fine.  Do we still need 90a88d6ef (scsi: fix soft lockup in
> scsi_remove_target() on module removal) or can that be reverted now,
> since the STARGET_REMOVE state will allow the iteration to continue?
> 
> Reviewed-by: Ewan D. Milne <emilne@redhat.com>

We've tested it on-top of 90a88d6ef, so I'm not quite sure.

Anyways, I've seen a mail from the 0-day bot regarding this patch, so I'll 
have to check that one first.

-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

[toc] | [prev] | [next] | [standalone]


#1365958 — Re: [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state

FromChristoph Hellwig <hch@infradead.org>
Date2016-03-29 09:50 +0200
SubjectRe: [PATCH] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state
Message-ID<rhWzw-2QS-19@gated-at.bofh.it>
In reply to#1364288
On Thu, Mar 24, 2016 at 11:42:44AM -0400, Ewan D. Milne wrote:
> This looks fine.  Do we still need 90a88d6ef (scsi: fix soft lockup in
> scsi_remove_target() on module removal) or can that be reverted now,
> since the STARGET_REMOVE state will allow the iteration to continue?

Yes, that stale pointer check is something I'd really, really prefer
not to have around in the long run.

Otherwise the patch looks like the right direction to me.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web