[7062] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

Re: [kernel] Re: [PATCH] Bug wrt failing init of scsi modules

daemon@ATHENA.MIT.EDU (Kurt Garloff)
Fri Aug 27 10:15:21 1999

Date:   Fri, 27 Aug 1999 15:56:29 +0200
From:   Kurt Garloff <garloff@suse.de>
To:     Linus Torvalds <torvalds@transmeta.com>,
        Alan Cox <alan@lxorguk.ukuu.org.uk>,
        Linux SCSI list <linux-scsi@vger.rutgers.edu>,
        Linux kernel list <linux-kernel@vger.rutgers.edu>,
        kernel@suse.de, mantel@suse.de
Mail-Followup-To: Linus Torvalds <torvalds@transmeta.com>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Linux SCSI list <linux-scsi@vger.rutgers.edu>,
	Linux kernel list <linux-kernel@vger.rutgers.edu>, kernel@suse.de,
	mantel@suse.de
In-Reply-To: <19990827101248.A487@kurt.kdt.de>; from Kurt Garloff on Fri, Aug 27, 1999 at 10:12:48AM +0200


--U+BazGySraz5kW0T
Content-Type: multipart/mixed; boundary="/9DWx/yDrRhgMJTb"


--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

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 we=
ll.
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)=20


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,
--=20
Kurt Garloff  <garloff@suse.de>                             Wuppertal, FRG
PGP2 key: See mail header, key servers            Linux kernel development
SuSE GmbH, N=FCrnberg, FRG               SCSI drivers: tmscsim(DC390), DC395

--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=us-ascii
Content-Description: 22x-scsi-mod-unregister2.diff
Content-Disposition: attachment; filename="22x-scsi-mod-unregister2.diff"
Content-Transfer-Encoding: quoted-printable

--- 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);
=20
 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
+ *=20
+ *  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.  garloff@suse.de 990827
  */
=20
 #include <linux/config.h>
@@ -2709,13 +2713,19 @@
     else
        tpnt->present =3D tpnt->detect(tpnt);
=20
-    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 =3D=3D next_scsi_host)=20
         {
 	    if(tpnt->present > 1)=20
             {
 		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 =3D scsi_hosts; /* Add to the linked list */
@@ -2841,9 +2852,8 @@
 	    (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 #endif
=20
-    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;
=20
     scsi_register_device(tpnt);
+    MOD_INC_USE_COUNT;
     /*
      * First scan the devices that we know about, and see if we notice the=
m.
      */
@@ -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)())=20
+	{
+	    __MOD_DEC_USE_COUNT(tpnt->module);
+	    scsi_unregister_device (tpnt);
+	    return 1;
+	}
=20
     /*
      * 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;
=20
     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 =3D 0;
     for(shpnt =3D scsi_hostlist; shpnt; shpnt =3D shpnt->next)
@@ -3341,7 +3358,7 @@
             for(SCpnt=3DSDpnt->device_queue; SCpnt; SCpnt =3D 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++,=20
=20
                        SCpnt->host ? SCpnt->host->host_no : -1,
@@ -3400,6 +3417,15 @@
         }
     }
     printk("wait_for_request =3D %p\n", wait_for_request);
+    sdtpnt =3D scsi_devicelist;
+    printk("SCSI List of Device Templates: %p", sdtpnt);
+    while (sdtpnt)
+    {
+	printk ("(%s)->%p", sdtpnt->tag, sdtpnt->next);
+	sdtpnt =3D 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;
=20
+    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 =3D=3D 0) return 0;
=20
     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;
+  =20
+    if (!sr_registered && is_reg_blkdev(SCSI_CDROM_MAJOR)) {
+	    printk("Unable to get major %d for SCSI-CD\n",SCSI_CDROM_MAJOR);
+	    return 1;
+    }
=20
     if(sr_template.dev_noticed =3D=3D 0) return 0;
=20
     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++;
     }
=20
--- 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 *);
=20
=20
-struct Scsi_Device_Template sg_template =3D {NULL, NULL, "sg", NULL, 0xff,
+struct Scsi_Device_Template sg_template =3D {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 =3D 0;
+  =20
+    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;
+    }
=20
     if (sg_template.dev_noticed =3D=3D 0) return 0;
=20
     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++;
     }
=20
--- 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
=20
+  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 =3D=3D 0) return 0;
=20
   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++;
   }
=20

--/9DWx/yDrRhgMJTb--

--U+BazGySraz5kW0T
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3i

iQCVAwUBN8aZDRaQN/7O/JIVAQGyIQP/UVeo4ZKPtbv4lMv6+XZhY3uz1xjK7QW1
w4FMj0xza4FjA3HHGYikIkiLHZFZ8ms4KVVkHS3bgOqOUoa/U+327EFl7t6I//26
jq/1SF1G6W20KggSBBTOOfY0BdjBiJJ+LFJ55+pgmxCoOlPgOPZ1JH134NEBLitt
iESFU7mrbgA=
=t+Iv
-----END PGP SIGNATURE-----

--U+BazGySraz5kW0T--

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post