mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] sbp2: fix spinlock recursion
@ 2006-04-01 19:11 Stefan Richter
  2006-04-02  0:52 ` Andrew Morton
  2006-04-04 22:13 ` [stable] " Greg KH
  0 siblings, 2 replies; 4+ messages in thread
From: Stefan Richter @ 2006-04-01 19:11 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: stable, linux-kernel, linux1394-devel, Jody McIntyre, Andrew Morton

sbp2util_mark_command_completed takes a lock which was already taken by
sbp2scsi_complete_all_commands.  This is a regression in Linux 2.6.15.
Reported by Kristian Harms at
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=187394

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/ieee1394/sbp2.c |   32 +++++++++++++++-----------------
 1 files changed, 15 insertions(+), 17 deletions(-)

--- linux-2.6.16.1/drivers/ieee1394/sbp2.c.orig	2006-04-01 19:06:31.000000000 +0200
+++ linux-2.6.16.1/drivers/ieee1394/sbp2.c	2006-04-01 19:07:00.000000000 +0200
@@ -495,22 +495,17 @@ static struct sbp2_command_info *sbp2uti
 /*
  * This function finds the sbp2_command for a given outstanding SCpnt.
  * Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+		struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
 	struct sbp2_command_info *command;
-	unsigned long flags;
 
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
-			if (command->Current_SCpnt == SCpnt) {
-				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+	if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+			if (command->Current_SCpnt == SCpnt)
 				return command;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return NULL;
 }
 
@@ -579,17 +574,15 @@ static void sbp2util_free_command_dma(st
 
 /*
  * This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
-					    struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+		struct scsi_id_instance_data *scsi_id,
+		struct sbp2_command_info *command)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	list_del(&command->list);
 	sbp2util_free_command_dma(command);
 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
 /*
@@ -2177,7 +2170,9 @@ static int sbp2_handle_status_write(stru
 		 * Matched status with command, now grab scsi command pointers and check status
 		 */
 		SCpnt = command->Current_SCpnt;
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		sbp2util_mark_command_completed(scsi_id, command);
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		if (SCpnt) {
 
@@ -2513,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cm
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct sbp2_command_info *command;
+	unsigned long flags;
 
 	SBP2_ERR("aborting sbp2 command");
 	scsi_print_command(SCpnt);
@@ -2523,6 +2519,7 @@ static int sbp2scsi_abort(struct scsi_cm
 		 * Right now, just return any matching command structures
 		 * to the free pool.
 		 */
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 		if (command) {
 			SBP2_DEBUG("Found command to abort");
@@ -2540,6 +2537,7 @@ static int sbp2scsi_abort(struct scsi_cm
 				command->Current_done(command->Current_SCpnt);
 			}
 		}
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		/*
 		 * Initiate a fetch agent reset.



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] sbp2: fix spinlock recursion
  2006-04-01 19:11 [PATCH] sbp2: fix spinlock recursion Stefan Richter
@ 2006-04-02  0:52 ` Andrew Morton
  2006-04-02  9:35   ` Stefan Richter
  2006-04-04 22:13 ` [stable] " Greg KH
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2006-04-02  0:52 UTC (permalink / raw)
  To: Stefan Richter; +Cc: torvalds, stable, linux-kernel, linux1394-devel, scjody

Stefan Richter <stefanr@s5r6.in-berlin.de> wrote:
>
> @@ -2540,6 +2537,7 @@ static int sbp2scsi_abort(struct scsi_cm
>   				command->Current_done(command->Current_SCpnt);
>   			}
>   		}
>  +		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);

This changes the call environment for all implementations of
->Current_done().  Are they all safe to call under this lock?

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] sbp2: fix spinlock recursion
  2006-04-02  0:52 ` Andrew Morton
@ 2006-04-02  9:35   ` Stefan Richter
  0 siblings, 0 replies; 4+ messages in thread
From: Stefan Richter @ 2006-04-02  9:35 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, stable, linux-kernel, linux1394-devel, scjody

Andrew Morton wrote:
> Stefan Richter <stefanr@s5r6.in-berlin.de> wrote:
> 
>>@@ -2540,6 +2537,7 @@ static int sbp2scsi_abort(struct scsi_cm
>>  				command->Current_done(command->Current_SCpnt);
>>  			}
>>  		}
>> +		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
> 
> 
> This changes the call environment for all implementations of
> ->Current_done().  Are they all safe to call under this lock?

Short answer: Yes, trust me. ;-) Long answer:

The done() callbacks are passed on to sbp2 from the SCSI stack along 
with each SCSI command via the queuecommand hook. The done() callback is 
safe to call in atomic context. So does 
Documentation/scsi/scsi_mid_low_api.txt say, and many if not all SCSI 
low-level handlers rely on this fact. So whatever this callback does, it 
is "self-contained" and it won't conflict with sbp2's internal ORB list 
handling. In particular, it won't race with the sbp2_command_orb_lock.

Moreover, sbp2 already calls the done() handler with 
sbp2_command_orb_lock taken in sbp2scsi_complete_all_commands(). I admit 
this is ultimately no proof of correctness, especially since this 
portion of code introduced the spinlock recursion in the first place and 
we didn't realize it since this code's submission before 2.6.15 until 
now. (I have learned a lesson from this.)

I stress-tested my patch on x86 uniprocessor with a preemptible SMP 
kernel (alas I have no SMP machine yet) and made sure that all code 
paths which involve the sbp2_command_orb_lock were gone through multiple 
times. Which is of course also no proof.
-- 
Stefan Richter
-=====-=-==- -=-- ---=-
http://arcgraph.de/sr/

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [stable] [PATCH] sbp2: fix spinlock recursion
  2006-04-01 19:11 [PATCH] sbp2: fix spinlock recursion Stefan Richter
  2006-04-02  0:52 ` Andrew Morton
@ 2006-04-04 22:13 ` Greg KH
  1 sibling, 0 replies; 4+ messages in thread
From: Greg KH @ 2006-04-04 22:13 UTC (permalink / raw)
  To: Stefan Richter
  Cc: Linus Torvalds, Jody McIntyre, linux1394-devel, stable, linux-kernel

On Sat, Apr 01, 2006 at 09:11:41PM +0200, Stefan Richter wrote:
> sbp2util_mark_command_completed takes a lock which was already taken by
> sbp2scsi_complete_all_commands.  This is a regression in Linux 2.6.15.
> Reported by Kristian Harms at
> https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=187394
> 
> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

queued to -stable, thanks.

greg k-h


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-04-04 22:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-01 19:11 [PATCH] sbp2: fix spinlock recursion Stefan Richter
2006-04-02  0:52 ` Andrew Morton
2006-04-02  9:35   ` Stefan Richter
2006-04-04 22:13 ` [stable] " Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome