Commit 366c3af0 authored by Stefan Richter's avatar Stefan Richter Committed by Greg Kroah-Hartman

[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=187394Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 91a4ee3e
...@@ -495,22 +495,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb( ...@@ -495,22 +495,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
/* /*
* This function finds the sbp2_command for a given outstanding SCpnt. * This function finds the sbp2_command for a given outstanding SCpnt.
* Only looks at the inuse list. * 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; 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))
if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { if (command->Current_SCpnt == SCpnt)
if (command->Current_SCpnt == SCpnt) {
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return command; return command;
}
}
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return NULL; return NULL;
} }
...@@ -579,17 +574,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command) ...@@ -579,17 +574,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
/* /*
* This function moves a command to the completed orb list. * 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, static void sbp2util_mark_command_completed(
struct sbp2_command_info *command) 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); list_del(&command->list);
sbp2util_free_command_dma(command); sbp2util_free_command_dma(command);
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); 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(struct hpsb_host *host, int nodeid, int dest ...@@ -2177,7 +2170,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
* Matched status with command, now grab scsi command pointers and check status * Matched status with command, now grab scsi command pointers and check status
*/ */
SCpnt = command->Current_SCpnt; SCpnt = command->Current_SCpnt;
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
sbp2util_mark_command_completed(scsi_id, command); sbp2util_mark_command_completed(scsi_id, command);
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
if (SCpnt) { if (SCpnt) {
...@@ -2513,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) ...@@ -2513,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct sbp2scsi_host_info *hi = scsi_id->hi; struct sbp2scsi_host_info *hi = scsi_id->hi;
struct sbp2_command_info *command; struct sbp2_command_info *command;
unsigned long flags;
SBP2_ERR("aborting sbp2 command"); SBP2_ERR("aborting sbp2 command");
scsi_print_command(SCpnt); scsi_print_command(SCpnt);
...@@ -2523,6 +2519,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) ...@@ -2523,6 +2519,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
* Right now, just return any matching command structures * Right now, just return any matching command structures
* to the free pool. * to the free pool.
*/ */
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
if (command) { if (command) {
SBP2_DEBUG("Found command to abort"); SBP2_DEBUG("Found command to abort");
...@@ -2540,6 +2537,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) ...@@ -2540,6 +2537,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
command->Current_done(command->Current_SCpnt); command->Current_done(command->Current_SCpnt);
} }
} }
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
/* /*
* Initiate a fetch agent reset. * Initiate a fetch agent reset.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment