Messages in this thread Patch in this message | | | From | (Bjorn Ekwall) | Subject | Re: Oops with 1.3.79 and kerneld | Date | Wed, 27 Mar 1996 22:27:04 +0100 (MET) |
| |
Matthias Sattler <m_sattle@poker.informatik.uni-kl.de> wrote: > Mar 27 12:00:25 gandalf insmod: Initialization of st failed > Mar 27 12:00:25 gandalf kernel: Detected scsi tape st0 at scsi0, channel 0, id 3, lun 0 > Mar 27 12:00:25 gandalf kernel: st: Can't allocate new tape buffer (nbr 0). [...] > > Mar 27 12:00:25 gandalf kernel: Can't continue without at least one tape buffer. > Mar 27 12:01:25 gandalf kernel: Unable to handle kernel paging request at virtual address c1866ce0 > > It seemed to happen when kerneld tried to unload sr_mod (I don't even have a
Nope, I'm almost certain it happened when init_module in st.o failed.
I looked at the scsi sources and think I have found a suspect... In linux/drivers/scsi/scsi.c the code looks like this:
static int scsi_register_device_module(struct Scsi_Device_Template * tpnt) { Scsi_Device * SDpnt;
if (tpnt->next) return 1;
1===> scsi_register_device(tpnt); /* * First scan the devices that we know about, and see if we notice them. */
for(SDpnt = scsi_devices; SDpnt; SDpnt = SDpnt->next) if(tpnt->detect) SDpnt->attached += (*tpnt->detect)(SDpnt);
/* * If any of the devices would match this driver, then perform the * init function. */ if(tpnt->init && tpnt->dev_noticed) if ((*tpnt->init)()) return 1; 2==============================^^^^^^^^
So, if the *tpnt->init() call failed (at arrow #2 above), a return will be made to init_module in the upper level driver (st.o in this case), and the init_module function will fail.
This means that the module will never become resident in the kernel, but instead immediately removed by the code in linux/kernel/module.c
Unfortunately the st.o module was registred at arrow #1 above, but it was never _unregistred_ before the "return 1"...
A first fix (completely untested!!!) could look like this:
--- linux/drivers/scsi/scsi.c.ouch Wed Mar 27 22:18:13 1996 +++ linux/drivers/scsi/scsi.c Wed Mar 27 22:22:11 1996 @@ -88,6 +88,7 @@ Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt, struct Scsi_Host *shpnt, char * scsi_result); void scsi_build_commandblocks(Scsi_Device * SDpnt); +static int scsi_unregister_device(struct Scsi_Device_Template * tpnt); #ifdef CONFIG_MODULES extern struct symbol_table scsi_symbol_table; @@ -2968,7 +2969,12 @@ * init function. */ if(tpnt->init && tpnt->dev_noticed) - if ((*tpnt->init)()) return 1; + if ((*tpnt->init)()) { + /* ouch... scsi_unregister_device does a MOD_DEC_USE_COUNT */ + MOD_INC_USE_COUNT; + scsi_unregister_device(tpnt); + return 1; + } /* * Now actually connect the devices to the new driver.
A more pleasing arrangement of MOD_INC_USE_COUNT can surely be found...
Bjorn
| |