lkml.org 
[lkml]   [2006]   [Apr]   [1]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    DateSat, 1 Apr 2006 21:11:41 +0200 (CEST)
    FromStefan Richter <>
    Subject[PATCH] sbp2: fix spinlock recursion
    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.
    
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    
    
    \
     
     \ /
      Last update: 2006-04-03 14:19    [from the cache]
    ©2003-2008