[PATCH] fix for ide-scsi crash

From: Andries . Brouwer
Date: Sun Jan 18 2004 - 23:39:52 EST


A rather reproducible crash with ide-scsi that I reported
yesterday is fixed by the patch below.

(Most of this is just polishing that emacs did while my eyes
looked at the code. The only change is not doing
ide_do_drive_cmd (drive, rq, ide_end);
spin_lock_irq(cmd->device->host->host_lock);
since cmd may be freed already.)

Andries

[With this in place I wrote three times 640 MB to floptical and diffed;
no problems occurred. Without it the system would crash each time.]

diff -u --recursive --new-file -X /linux/dontdiff a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c 2004-01-11 14:20:49.000000000 +0100
+++ b/drivers/ide/ide-io.c 2004-01-19 05:00:47.000000000 +0100
@@ -1300,7 +1300,7 @@
* Initialize a request before we fill it in and send it down to
* ide_do_drive_cmd. Commands must be set up by this function. Right
* now it doesn't do a lot, but if that changes abusers will have a
- * nasty suprise.
+ * nasty surprise.
*/

void ide_init_drive_cmd (struct request *rq)
diff -u --recursive --new-file -X /linux/dontdiff a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c 2003-12-18 03:59:05.000000000 +0100
+++ b/drivers/scsi/ide-scsi.c 2004-01-19 05:30:28.000000000 +0100
@@ -148,7 +148,8 @@
count = IDE_MIN (pc->sg->length - pc->b_count, bcount);
buf = page_address(pc->sg->page) + pc->sg->offset;
atapi_input_bytes (drive, buf + pc->b_count, count);
- bcount -= count; pc->b_count += count;
+ bcount -= count;
+ pc->b_count += count;
if (pc->b_count == pc->sg->length) {
pc->sg++;
pc->b_count = 0;
@@ -191,8 +192,12 @@
return;
if (drive->media == ide_cdrom || drive->media == ide_optical) {
if (c[0] == READ_6 || c[0] == WRITE_6) {
- c[8] = c[4]; c[5] = c[3]; c[4] = c[2];
- c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0;
+ c[8] = c[4];
+ c[5] = c[3];
+ c[4] = c[2];
+ c[3] = c[1] & 0x1f;
+ c[2] = 0;
+ c[1] &= 0xe0;
c[0] += (READ_10 - READ_6);
}
if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
@@ -380,7 +385,7 @@
static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
{
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- idescsi_pc_t *pc=scsi->pc;
+ idescsi_pc_t *pc = scsi->pc;
struct request *rq = pc->rq;
atapi_bcount_t bcount;
atapi_status_t status;
@@ -664,8 +669,6 @@
.ioctl = idescsi_ide_ioctl,
};

-static int idescsi_attach(ide_drive_t *drive);
-
static int idescsi_slave_configure(Scsi_Device * sdp)
{
/* Configure detected device */
@@ -794,7 +797,8 @@
idescsi_pc_t *pc = NULL;

if (!drive) {
- printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->device->id);
+ printk (KERN_ERR "ide-scsi: drive id %d not present\n",
+ cmd->device->id);
goto abort;
}
scsi = drive_to_idescsi(drive);
@@ -827,25 +831,30 @@
idescsi_transform_pc1 (drive, pc);

if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
+ printk ("ide-scsi: %s: que %lu, cmd = ",
+ drive->name, cmd->serial_number);
hexdump(cmd->cmnd, cmd->cmd_len);
if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
- printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
+ printk("ide-scsi: %s: que %lu, tsl = ",
+ drive->name, cmd->serial_number);
hexdump(pc->c, 12);
}
}

- ide_init_drive_cmd (rq);
+ ide_init_drive_cmd(rq);
rq->special = (char *) pc;
- rq->bio = idescsi_dma_bio (drive, pc);
+ rq->bio = idescsi_dma_bio(drive, pc);
rq->flags = REQ_SPECIAL;
- spin_unlock_irq(cmd->device->host->host_lock);
- (void) ide_do_drive_cmd (drive, rq, ide_end);
- spin_lock_irq(cmd->device->host->host_lock);
+ {
+ struct Scsi_Host *host = cmd->device->host;
+ spin_unlock_irq(host->host_lock);
+ (void) ide_do_drive_cmd(drive, rq, ide_end);
+ spin_lock_irq(host->host_lock);
+ }
return 0;
abort:
- if (pc) kfree (pc);
- if (rq) kfree (rq);
+ kfree (pc);
+ kfree (rq);
cmd->result = DID_ERROR << 16;
done(cmd);
return 1;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/