On Fri, Aug 27, 1999 at 10:12:48AM +0200, Kurt Garloff wrote:
> Unfortunately I did this patch in two steps and erroneously booted the
> middle kernel instead of the latest one when testing. While the error
> description is correct, the patch sent out is wrong. Sorry!
> I will send another one after thourough testing.

So, here is a patch for this problem. A minimal patch would have just added
__DEC_MOD_USE_COUNT(tpnt->module); unregister_SCSI_device(tpnt);
at the right places.

However, I found the module usage counters to be messy and fixed them as well.
I did some tests, but I have to do some more with fully modularized scsi
code to see, if I didn't miss anything there.

I also solved another problem with sr/sd_mod being loaded in presence of
compiled in versions of the kernel. This was detected by the
register_blkdev() call in the past. The problem was that it was only called,
when devices of this category were actually found. So you could end up with
a sr_mod and a sr in the kernel.
I added is_reg_blk/chrdev(uint major) to the kernel and made the high level
SCSI code test for already being registered before succeeding their init.

A formatting typo in scsi_dump_info() is also fixed and the dump of the
scsi_devicelist has been added. (Should be called scsi_devicetemplate_list,
BTW) 


One problem is not addressed by this patch:
Nothing protects scsi_mod from being loaded with scsi support in the kernel.
I did not yet see a nice solution for this, as no resources are registered.
Addind a global var is not a nice way, either. Suggestions?


Patch (again against 2.2.12) is appended. I'd suggest inclusion into the
kernel after some more tests.

Regards,
-- 
Kurt Garloff  <[EMAIL PROTECTED]>                             Wuppertal, FRG
PGP2 key: See mail header, key servers            Linux kernel development
SuSE GmbH, N�rnberg, FRG               SCSI drivers: tmscsim(DC390), DC395
--- linux-2.2.12/fs/devices.c.orig      Wed Dec 23 20:39:49 1998
+++ linux-2.2.12/fs/devices.c   Fri Aug 27 11:36:48 1999
@@ -370,3 +370,13 @@
        sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
        return buffer;
 }
+
+struct file_operations * is_reg_blkdev(unsigned int major)
+{
+       return blkdevs[major].fops;
+}
+
+struct file_operations * is_reg_chrdev(unsigned int major)
+{
+       return chrdevs[major].fops;
+}
--- linux-2.2.12/kernel/ksyms.c.orig    Mon Aug  9 21:04:41 1999
+++ linux-2.2.12/kernel/ksyms.c Fri Aug 27 11:34:14 1999
@@ -196,8 +196,10 @@
 /* device registration */
 EXPORT_SYMBOL(register_chrdev);
 EXPORT_SYMBOL(unregister_chrdev);
+EXPORT_SYMBOL(is_reg_chrdev);
 EXPORT_SYMBOL(register_blkdev);
 EXPORT_SYMBOL(unregister_blkdev);
+EXPORT_SYMBOL(is_reg_blkdev);
 EXPORT_SYMBOL(tty_register_driver);
 EXPORT_SYMBOL(tty_unregister_driver);
 EXPORT_SYMBOL(tty_std_termios);
--- linux-2.2.12/include/linux/fs.h.orig        Fri Aug 27 01:53:30 1999
+++ linux-2.2.12/include/linux/fs.h     Fri Aug 27 11:34:44 1999
@@ -728,7 +728,8 @@
 extern char * bdevname(kdev_t dev);
 extern char * cdevname(kdev_t dev);
 extern char * kdevname(kdev_t dev);
-
+extern inline struct file_operations * is_reg_blkdev(unsigned int major);
+extern inline struct file_operations * is_reg_chrdev(unsigned int major);
 
 extern void init_fifo(struct inode * inode);
 extern struct inode_operations fifo_inode_operations;
--- linux-2.2.12/drivers/scsi/scsi.c.orig       Mon Aug  9 21:04:40 1999
+++ linux-2.2.12/drivers/scsi/scsi.c    Fri Aug 27 15:33:31 1999
@@ -34,6 +34,10 @@
  *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  *
  *  out_of_space + add-single-device work, D. Gilbert (dpg) 990612
+ * 
+ *  Call init regardless of dev_noticed and have the s?_init() handle it
+ *  and unregister in case of failure. Similar for host adapters.
+ *  Fixed module counters.  [EMAIL PROTECTED] 990827
  */
 
 #include <linux/config.h>
@@ -2709,13 +2713,19 @@
     else
        tpnt->present = tpnt->detect(tpnt);
 
-    if (tpnt->present)
+    /* No need to clean up. The host should scsi_unregister() if
+     * detect() called scsi_register() before but detection failed. */
+    if (!tpnt->present)
+       return 1;
+    else
     {
+       MOD_INC_USE_COUNT;
        if(pcount == next_scsi_host) 
         {
            if(tpnt->present > 1) 
             {
                printk("Failure to register low-level scsi driver");
+               __MOD_DEC_USE_COUNT(tpnt->module);
                scsi_unregister_host(tpnt);
                return 1;
            }
@@ -2723,6 +2733,7 @@
              * The low-level driver failed to register a driver.  We
             *  can do this now.
             */
+           printk("Register driver for host %s\n", tpnt->name);
            scsi_register(tpnt,0);
        }
        tpnt->next = scsi_hosts; /* Add to the linked list */
@@ -2841,9 +2852,8 @@
            (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 #endif
 
-    MOD_INC_USE_COUNT;
-
     if (out_of_space) {
+       __MOD_DEC_USE_COUNT(tpnt->module);
        scsi_unregister_host(tpnt); /* easiest way to clean up?? */
        return 1;
     }
@@ -3114,6 +3124,7 @@
     if (tpnt->next) return 1;
 
     scsi_register_device(tpnt);
+    MOD_INC_USE_COUNT;
     /*
      * First scan the devices that we know about, and see if we notice them.
      */
@@ -3131,8 +3142,13 @@
      * 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;
+    if(tpnt->init)
+       if ((*tpnt->init)()) 
+       {
+           __MOD_DEC_USE_COUNT(tpnt->module);
+           scsi_unregister_device (tpnt);
+           return 1;
+       }
 
     /*
      * Now actually connect the devices to the new driver.
@@ -3163,9 +3179,9 @@
     if(tpnt->finish && tpnt->nr_dev)  (*tpnt->finish)();
     if (! out_of_space)
        resize_dma_pool();
-    MOD_INC_USE_COUNT;
 
     if (out_of_space) {
+       __MOD_DEC_USE_COUNT(tpnt->module);
        scsi_unregister_device(tpnt); /* easiest way to clean up?? */
        return 1;
     }
@@ -3318,6 +3334,7 @@
     struct Scsi_Host * shpnt;
     Scsi_Cmnd * SCpnt;
     Scsi_Device * SDpnt;
+    struct Scsi_Device_Template * sdtpnt;
     printk("Dump of scsi host parameters:\n");
     i = 0;
     for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
@@ -3341,7 +3358,7 @@
             for(SCpnt=SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
             {
                 /*  (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to 
ito) cmd snse result %d %x      */
-                printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 
0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
+                printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 
+0x%2.2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
                        i++, 
 
                        SCpnt->host ? SCpnt->host->host_no : -1,
@@ -3400,6 +3417,15 @@
         }
     }
     printk("wait_for_request = %p\n", wait_for_request);
+    sdtpnt = scsi_devicelist;
+    printk("SCSI List of Device Templates: %p", sdtpnt);
+    while (sdtpnt)
+    {
+       printk ("(%s)->%p", sdtpnt->tag, sdtpnt->next);
+       sdtpnt = sdtpnt->next;
+    }
+    printk ("\n");
+
 #endif /* CONFIG_SCSI_LOGGING */ /* } */
 #endif /* CONFIG_PROC_FS */
 }
--- linux-2.2.12/drivers/scsi/sd.c.orig Mon Aug  9 21:05:05 1999
+++ linux-2.2.12/drivers/scsi/sd.c      Fri Aug 27 13:39:10 1999
@@ -1494,6 +1494,11 @@
 {
     int i;
 
+    if(!sd_registered && is_reg_blkdev(SD_MAJOR(0))) {
+       printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(0));
+       return 1;
+    }
+
     if (sd_template.dev_noticed == 0) return 0;
 
     if (!rscsi_disks)
--- linux-2.2.12/drivers/scsi/sr.c.orig Fri Jan 15 23:41:04 1999
+++ linux-2.2.12/drivers/scsi/sr.c      Fri Aug 27 13:43:26 1999
@@ -1014,14 +1014,16 @@
 static int sr_init()
 {
     int i;
+   
+    if (!sr_registered && is_reg_blkdev(SCSI_CDROM_MAJOR)) {
+           printk("Unable to get major %d for SCSI-CD\n",SCSI_CDROM_MAJOR);
+           return 1;
+    }
 
     if(sr_template.dev_noticed == 0) return 0;
 
     if(!sr_registered) {
-       if (register_blkdev(MAJOR_NR,"sr",&cdrom_fops)) {
-           printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
-           return 1;
-       }
+       register_blkdev(SCSI_CDROM_MAJOR,"sr",&cdrom_fops);
        sr_registered++;
     }
 
--- linux-2.2.12/drivers/scsi/sg.c.orig Tue Jun  8 01:27:06 1999
+++ linux-2.2.12/drivers/scsi/sg.c      Fri Aug 27 15:35:16 1999
@@ -113,7 +113,7 @@
 static void sg_detach(Scsi_Device *);
 
 
-struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
+struct Scsi_Device_Template sg_template = {NULL, "generic", "sg", NULL, 0xff,
                                            SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
                                            sg_detect, sg_init,
                                            sg_finish, sg_attach, sg_detach};
@@ -948,16 +948,17 @@
 static int sg_init()
 {
     static int sg_registered = 0;
+   
+    if(!sg_registered && is_reg_chrdev(SCSI_GENERIC_MAJOR)) {
+       printk("Unable to get major %d for generic SCSI device\n",
+               SCSI_GENERIC_MAJOR);
+       return 1;
+    }
 
     if (sg_template.dev_noticed == 0) return 0;
 
     if(!sg_registered) {
-        if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
-        {
-            printk("Unable to get major %d for generic SCSI device\n",
-                   SCSI_GENERIC_MAJOR);
-            return 1;
-        }
+        register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops);
         sg_registered++;
     }
 
--- linux-2.2.12/drivers/scsi/st.c.orig Sat May 22 23:51:26 1999
+++ linux-2.2.12/drivers/scsi/st.c      Fri Aug 27 13:41:28 1999
@@ -3453,13 +3453,15 @@
   int target_nbr;
 #endif
 
+  if(!st_registered && is_reg_chrdev(SCSI_TAPE_MAJOR)) {
+      printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",SCSI_TAPE_MAJOR);
+      return 1;
+  }
+
   if (st_template.dev_noticed == 0) return 0;
 
   if(!st_registered) {
-    if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
-      printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR);
-      return 1;
-    }
+    register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops);
     st_registered++;
   }
 

PGP signature

Reply via email to