Patch to mcd.c (was: Re: Bug in sysmount:1.3.75 ?)

Bjorn Ekwall (bj0rn@blox.se)
Wed, 20 Mar 1996 21:38:29 +0100 (MET)


Andreas Dietrich <quasi@baccus.franken.de> wrote:
>
> Hello!
>
> I'm using kernel 1.3.75 and I had the following oops, when trying to
> mount my Mitsumi Doublespeed CDROM, which failed to initialize.
> (This happens sometimes -- also with the dos-drivers!).
>
> I've experienced this bug several times, with different kernels;
> unfortunately I do not remember exactly (was just too lazy to report it
> earlier -- Sorry about that!)
>
> I compiled mcd as a module, using kerneld to load it, in case this
> is important.
> I used gcc2.6.3/a.out to compile kernel and modules.
>
> The command that lead to the oops was mount /cd.

The initialisation of the module wasn't clean w.r.t. (un)register_blkdev.

When kerneld was triggered to load the module, modprobe failed since
init_module exited with "Init failed. No mcd device at 0x330 irq 10".

This made modprobe _unload_ the module, but the entry for this device
was left in the kernel table for block-devices!

When sys_mount then tried to check fops->open, it accessed the memory
where the module _used_ to be. Since it was unloaded, you got an Ooops!

The included patch cleans that one up.

Bjorn <bj0rn@blox.se>

--- linux/drivers/cdrom/mcd.c.org Wed Mar 20 21:02:26 1996
+++ linux/drivers/cdrom/mcd.c Wed Mar 20 21:34:07 1996
@@ -60,6 +60,7 @@
17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
07 July 1995 Modifications by Andrew J. Kroll

+ Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
*/

#include <linux/module.h>
@@ -1181,6 +1182,7 @@
}

if (check_region(mcd_port, 4)) {
+ unregister_blkdev(MAJOR_NR, "mcd");
printk("Init failed, I/O port (%X) already in use\n",
mcd_port);
return -EIO;
@@ -1204,6 +1206,7 @@
if (count >= 2000000) {
printk("Init failed. No mcd device at 0x%x irq %d\n",
mcd_port, mcd_irq);
+ unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
}
count = inb(MCDPORT(0)); /* pick up the status */
@@ -1211,13 +1214,16 @@
outb(MCMD_GET_VERSION,MCDPORT(0));
for(count=0;count<3;count++)
if(getValue(result+count)) {
+ unregister_blkdev(MAJOR_NR, "mcd");
printk("mitsumi get version failed at 0x%d\n",
mcd_port);
return -EIO;
}

- if (result[0] == result[1] && result[1] == result[2])
+ if (result[0] == result[1] && result[1] == result[2]) {
+ unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
+ }
printk("Mitsumi status, type and version : %02X %c %x ",
result[0],result[1],result[2]);

@@ -1239,6 +1245,7 @@
if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))
{
printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
+ unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
}
request_region(mcd_port, 4,"mcd");