| From stable-bounces@linux.kernel.org Mon Dec 12 12:27:15 2005 |
| Date: Mon, 31 Oct 2005 09:05:36 -0800 |
| Message-Id: <200510311705.j9VH5aDM031690@hera.kernel.org> |
| From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org> |
| To: git-commits-head@vger.kernel.org |
| Cc: |
| Subject: libata: locking rewrite (== fix) |
| |
| From: Jeff Garzik <jgarzik@pobox.com> |
| |
| [libata] locking rewrite (== fix) |
| |
| A lot of power packed into a little patch. |
| |
| This change eliminates the sharing between our controller-wide spinlock |
| and the SCSI core's Scsi_Host lock. As the locking in libata was |
| already highly compartmentalized, always referencing our own lock, and |
| never scsi_host::host_lock. |
| |
| As a side effect, this change eliminates a deadlock from calling |
| scsi_finish_command() while inside our spinlock. |
| |
| |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/scsi/libata-core.c | 2 -- |
| drivers/scsi/libata-scsi.c | 9 ++++++++- |
| 2 files changed, 8 insertions(+), 3 deletions(-) |
| |
| --- linux-2.6.14.3.orig/drivers/scsi/libata-core.c |
| +++ linux-2.6.14.3/drivers/scsi/libata-core.c |
| @@ -3916,8 +3916,6 @@ static void ata_host_init(struct ata_por |
| host->unique_id = ata_unique_id++; |
| host->max_cmd_len = 12; |
| |
| - scsi_assign_lock(host, &host_set->lock); |
| - |
| ap->flags = ATA_FLAG_PORT_DISABLED; |
| ap->id = host->unique_id; |
| ap->host = host; |
| --- linux-2.6.14.3.orig/drivers/scsi/libata-scsi.c |
| +++ linux-2.6.14.3/drivers/scsi/libata-scsi.c |
| @@ -39,6 +39,7 @@ |
| #include <scsi/scsi.h> |
| #include "scsi.h" |
| #include <scsi/scsi_host.h> |
| +#include <scsi/scsi_device.h> |
| #include <linux/libata.h> |
| #include <asm/uaccess.h> |
| |
| @@ -1565,8 +1566,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd * |
| struct ata_port *ap; |
| struct ata_device *dev; |
| struct scsi_device *scsidev = cmd->device; |
| + struct Scsi_Host *shost = scsidev->host; |
| |
| - ap = (struct ata_port *) &scsidev->host->hostdata[0]; |
| + ap = (struct ata_port *) &shost->hostdata[0]; |
| + |
| + spin_unlock(shost->host_lock); |
| + spin_lock(&ap->host_set->lock); |
| |
| ata_scsi_dump_cdb(ap, cmd); |
| |
| @@ -1589,6 +1594,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd * |
| ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); |
| |
| out_unlock: |
| + spin_unlock(&ap->host_set->lock); |
| + spin_lock(shost->host_lock); |
| return 0; |
| } |
| |