public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* Fwd: [PATCH] 2.5.54 fix ide-cd/ide-scsi oopses after module unload
@ 2003-01-04 11:18 Douglas Gilbert
  0 siblings, 0 replies; only message in thread
From: Douglas Gilbert @ 2003-01-04 11:18 UTC (permalink / raw)
  To: linux-scsi; +Cc: mikpe, wrlk

[-- Attachment #1: Type: text/plain, Size: 3180 bytes --]

Mikael Pettersson posted the following to the linux-kernel
mailing list. His patch includes a fix that Willem Riede
spotted as well (no driver_unregister() in ide.c). Willem
also had other changes in ide-scsi.c which are still pending.
See attached file.


Doug Gilbert


Mikael Pettersson wrote on lkml:
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

In 2.5 (the bug's been there since 2.5.42), rmmod:ing a
modular IDE subdriver like ide-cd or ide-scsi and then
rebooting causes an oops in device_shutdown(). This is because
the IDE layer doesn't reset the drive->gendev.driver pointer
that it previously set up to point to data structures in the
subdriver module. device_shutdown() sees a non-NULL ->driver,
dereferences it, and oopses.

The patch below for 2.5.54 fixes two generic bugs related to
unloading of modular IDE subdrivers, and one specific to ide-scsi:

1. ata_attach() needs to set drive->gendev.driver = NULL
    when no specific driver claims the drive. This prevents a
    drive previously owned by a subdriver module from keeping
    its ->gendev.driver pointing into that module.

2. ide_unregister_driver() needs to unregister &driver->gen_driver;
    this is to balance the corresponding register call in
    ide_register_driver(). [This part of the patch is originally
    by Patrick Mochel.]

3. ide-scsi.c abuses ide_driver_t's busy field as a counter
    while the field in fact is a single-bit boolean. This causes
    the busyness of the driver to be incorrect while the driver
    is active. (From my recent patch for 2.4.20-ac2/2.4.21-pre2.)

With these three fixes modular ide-cd and ide-scsi work quite
reliably for me in 2.5.54.

/Mikael

diff -ruN linux-2.5.54/drivers/ide/ide.c 
linux-2.5.54.ide-fixes/drivers/ide/ide.c
--- linux-2.5.54/drivers/ide/ide.c	2003-01-02 14:27:55.000000000 +0100
+++ linux-2.5.54.ide-fixes/drivers/ide/ide.c	2003-01-04 
02:34:02.000000000 +0100
@@ -1346,6 +1346,7 @@
  	spin_unlock(&drivers_lock);
  	spin_lock(&drives_lock);
  	list_add_tail(&drive->list, &ata_unused);
+	drive->gendev.driver = NULL;
  	spin_unlock(&drives_lock);
  	return 1;
  }
@@ -2308,6 +2309,8 @@
  	list_del(&driver->drivers);
  	spin_unlock(&drivers_lock);

+	driver_unregister(&driver->gen_driver);
+
  	while(!list_empty(&driver->drives)) {
  		drive = list_entry(driver->drives.next, ide_drive_t, list);
  		if (driver->cleanup(drive)) {
diff -ruN linux-2.5.54/drivers/scsi/ide-scsi.c 
linux-2.5.54.ide-fixes/drivers/scsi/ide-scsi.c
--- linux-2.5.54/drivers/scsi/ide-scsi.c	2002-12-24 13:53:50.000000000 +0100
+++ linux-2.5.54.ide-fixes/drivers/scsi/ide-scsi.c	2003-01-04 
02:34:02.000000000 +0100
@@ -590,6 +590,7 @@
  	set_bit(IDESCSI_LOG_CMD, &scsi->log);
  #endif /* IDESCSI_DEBUG_LOG */
  	idescsi_add_settings(drive);
+	DRIVER(drive)->busy--;
  }

  static int idescsi_cleanup (ide_drive_t *drive)
@@ -995,7 +996,7 @@
  	for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
  		drive = idescsi_drives[id];
  		if (drive)
-			DRIVER(drive)->busy--;
+			DRIVER(drive)->busy = 0;
  	}
  	scsi_unregister   (idescsi_host);
  	device_unregister(&idescsi_primary);
-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[-- Attachment #2: ide-scsi_2553wr2.diff --]
[-- Type: text/plain, Size: 997 bytes --]

--- linux/drivers/scsi/ide-scsi.c	2002-12-24 18:12:54.000000000 +1100
+++ linux/drivers/scsi/ide-scsi.c2553wr2	2002-12-24 09:30:17.000000000 +1100
@@ -289,6 +289,7 @@
 	pc->timeout = jiffies + WAIT_READY;
 	/* NOTE! Save the failed packet command in "rq->buffer" */
 	rq->buffer = (void *) failed_command->special;
+	pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
 	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
 		printk ("ide-scsi: %s: queue cmd = ", drive->name);
 		hexdump(pc->c, 6);
@@ -876,7 +877,8 @@
 			/* is cmd active?
 			 *  need to lock so this stuff doesn't change under us */
 			spin_lock_irqsave(&ide_lock, flags);
-			if (scsi->pc && scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
+			if (scsi->pc && scsi->pc->scsi_cmd && 
+					scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
 				/* yep - let's give it some more time - 
 				 * we can do that, we're in _our_ error kernel thread */
 				spin_unlock_irqrestore(&ide_lock, flags);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-01-04 11:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-04 11:18 Fwd: [PATCH] 2.5.54 fix ide-cd/ide-scsi oopses after module unload Douglas Gilbert

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