devfs
[Top] [All Lists]

[PATCH] sd-many for 2.5.3 (uses devfs)

To: linux-kernel@xxxxxxxxxxxxxxx, linux-scsi@xxxxxxxxxxxxxxx, devfs-announce-list@xxxxxxxxxxxxxxxxxxxxxxxx
Subject: [PATCH] sd-many for 2.5.3 (uses devfs)
From: Richard Gooch <rgooch@xxxxxxxxxxxxxxx>
Date: Thu, 31 Jan 2002 01:15:53 -0700
Sender: owner-devfs@xxxxxxxxxxx
  Hi, all. Appended is my sd-many patch. It supports up to 2080
SD's. This patch is against 2.5.3, and is essentially the same as
the patch for 2.4.18, but ported to the 2.5.x API's.

Success/failure reports welcomed. It Boots For Me[tm].

                                Regards,

                                        Richard....
Permanent: rgooch@xxxxxxxxxxxxx
Current:   rgooch@xxxxxxxxxxxxxxx

diff -urN linux-2.5.3/drivers/scsi/Config.help linux/drivers/scsi/Config.help
--- linux-2.5.3/drivers/scsi/Config.help        Fri Jan 25 17:04:16 2002
+++ linux/drivers/scsi/Config.help      Thu Jan 31 00:34:49 2002
@@ -34,6 +34,16 @@
   is located on a SCSI disk. In this case, do not compile the driver
   for your SCSI host adapter (below) as a module either.
 
+CONFIG_SD_MANY
+  This allows you to support a very large number of SCSI discs
+  (approximately 2080). You will also need to set CONFIG_DEVFS_FS=y
+  later. This option may consume all unassigned block majors
+  (i.e. those which do not have an allocation in
+  Documentation/devices.txt). Enabling this will consume a few extra
+  kilobytes of kernel memory.
+
+  Unless you have a large storage array, say N.
+
 CONFIG_SD_EXTRA_DEVS
   This controls the amount of additional space allocated in tables for
   drivers that are loaded as modules after the kernel is booted.  In
diff -urN linux-2.5.3/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- linux-2.5.3/drivers/scsi/Config.in  Tue Nov 27 10:23:27 2001
+++ linux/drivers/scsi/Config.in        Thu Jan 31 00:34:49 2002
@@ -3,7 +3,8 @@
 dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
 
 if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
-   int  'Maximum number of SCSI disks that can be loaded as modules' 
CONFIG_SD_EXTRA_DEVS 40
+   bool '    Many (~2080) SCSI discs support (requires devfs)' CONFIG_SD_MANY
+   int  '    Maximum number of SCSI disks that can be loaded as modules' 
CONFIG_SD_EXTRA_DEVS 40
 fi
 
 dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
diff -urN linux-2.5.3/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- linux-2.5.3/drivers/scsi/hosts.h    Tue Jan 29 22:44:26 2002
+++ linux/drivers/scsi/hosts.h  Thu Jan 31 00:37:21 2002
@@ -501,9 +501,8 @@
     const char * tag;
     struct module * module;      /* Used for loadable modules */
     unsigned char scsi_type;
-    unsigned int major;
-    unsigned int min_major;      /* Minimum major in range. */ 
-    unsigned int max_major;      /* Maximum major in range. */
+    unsigned int *majors;         /* Array of majors used by driver */
+    unsigned int num_majors;      /* Number of majors used by driver */
     unsigned int nr_dev;         /* Number currently attached */
     unsigned int dev_noticed;    /* Number of devices detected. */
     unsigned int dev_max;        /* Current size of arrays */
diff -urN linux-2.5.3/drivers/scsi/osst.c linux/drivers/scsi/osst.c
--- linux-2.5.3/drivers/scsi/osst.c     Tue Dec 25 18:04:40 2001
+++ linux/drivers/scsi/osst.c   Thu Jan 31 00:34:49 2002
@@ -163,7 +163,6 @@
        name:           "OnStream tape",
        tag:            "osst",
        scsi_type:      TYPE_TAPE,
-       major:          OSST_MAJOR,
        detect:         osst_detect,
        init:           osst_init,
        attach:         osst_attach,
diff -urN linux-2.5.3/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- linux-2.5.3/drivers/scsi/scsi_lib.c Mon Jan 14 12:25:29 2002
+++ linux/drivers/scsi/scsi_lib.c       Thu Jan 31 00:34:49 2002
@@ -749,25 +749,12 @@
                 * Search for a block device driver that supports this
                 * major.
                 */
-               if (spnt->blk && spnt->major == major) {
-                       return spnt;
-               }
-               /*
-                * I am still not entirely satisfied with this solution,
-                * but it is good enough for now.  Disks have a number of
-                * major numbers associated with them, the primary
-                * 8, which we test above, and a secondary range of 7
-                * different consecutive major numbers.   If this ever
-                * becomes insufficient, then we could add another function
-                * to the structure, and generalize this completely.
-                */
-               if( spnt->min_major != 0 
-                   && spnt->max_major != 0
-                   && major >= spnt->min_major
-                   && major <= spnt->max_major )
-               {
-                       return spnt;
-               }
+               int i;
+               if (!spnt->blk || !spnt->majors)
+                       continue;
+               for (i = 0; i < spnt->num_majors; ++i)
+                       if (spnt->majors[i] == major)
+                               return spnt;
        }
        return NULL;
 }
diff -urN linux-2.5.3/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- linux-2.5.3/drivers/scsi/sd.c       Mon Dec 31 19:01:44 2001
+++ linux/drivers/scsi/sd.c     Thu Jan 31 00:44:50 2002
@@ -28,6 +28,8 @@
  *     
  *      Modified by Alex Davis <letmein@xxxxxxxxx>
  *       Fix problem where removable media could be ejected after sd_open.
+ *
+ *       Modified by Richard Gooch rgooch@xxxxxxxxxxxxx to support >128 discs.
  */
 
 #include <linux/config.h>
@@ -61,7 +63,11 @@
 
 #include <linux/genhd.h>
 
+#ifdef CONFIG_SD_MANY
+#define SD_MAJOR(i) sd_template.majors[(i)]
+#else
 #define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+#endif
 
 #define SCSI_DISKS_PER_MAJOR   16
 #define SD_MAJOR_NUMBER(i)     SD_MAJOR((i) >> 8)
@@ -72,6 +78,14 @@
 
 #define MAX_RETRIES 5
 
+#ifdef CONFIG_SD_MANY
+#define sdmalloc(size) vmalloc((size))
+#define sdfree(ptr) vfree((ptr))
+#else
+#define sdmalloc(size) kmalloc((size),GFP_ATOMIC)
+#define sdfree(ptr) kfree((ptr))
+#endif
+
 /*
  *  Time out in seconds for disks and Magneto-opticals (which are slower).
  */
@@ -103,12 +117,6 @@
        name:"disk",
        tag:"sd",
        scsi_type:TYPE_DISK,
-       major:SCSI_DISK0_MAJOR,
-        /*
-         * Secondary range of majors that this driver handles.
-         */
-       min_major:SCSI_DISK1_MAJOR,
-       max_major:SCSI_DISK7_MAJOR,
        blk:1,
        detect:sd_detect,
        init:sd_init,
@@ -137,6 +145,20 @@
 }
 #endif
 
+#ifdef CONFIG_SD_MANY
+static inline int sd_kdev_to_index(kdev_t dev)
+{
+       int i, major = major (dev);
+
+       for (i = 0; i < sd_template.num_majors; ++i) {
+               if (sd_template.majors[i] != major)
+                       continue;
+               return (i << 4) | (minor (dev) >> 4);
+       }
+       return -ENODEV;
+}
+#endif
+
 static int sd_ioctl(struct inode * inode, struct file * file, unsigned int 
cmd, unsigned long arg)
 {
        kdev_t dev = inode->i_rdev;
@@ -665,7 +687,6 @@
  * them to SCSI commands.
  */
 
-
 static int check_scsidisk_media_change(kdev_t full_dev)
 {
        int retval;
@@ -1046,6 +1067,43 @@
        return i;
 }
 
+static int sd_alloc_majors(void)
+/*  Allocate as many majors as required
+ */
+{
+       int i, major;
+
+       if ( ( sd_template.majors =
+              kmalloc(sizeof *sd_template.majors * N_USED_SD_MAJORS,
+                      GFP_KERNEL) ) == NULL ) {
+               printk("sd.c: unable to allocate major array\n");
+               return -ENOMEM;
+       }
+       sd_template.majors[0] = SCSI_DISK0_MAJOR;
+       for (i = 1; (i < N_USED_SD_MAJORS) && (i <N_SD_PREASSIGNED_MAJORS);++i)
+               sd_template.majors[i] = SCSI_DISK1_MAJOR + i - 1;
+       for (; (i >= N_SD_PREASSIGNED_MAJORS) && (i < N_USED_SD_MAJORS); ++i) {
+               if ( ( major = devfs_alloc_major(DEVFS_SPECIAL_BLK) ) < 0 ) {
+                       printk(KERN_WARNING __FUNCTION__ "() major[%d] 
allocation failed\n", i);
+                       break;
+               }
+               sd_template.majors[i] = major;
+       }
+       sd_template.dev_max = i * SCSI_DISKS_PER_MAJOR;
+       sd_template.num_majors = i;
+       return 0;
+}      /*  End Function sd_alloc_majors  */
+
+static void sd_dealloc_majors(void)
+/*  Deallocate all the allocated majors
+ */
+{
+       int i;
+
+       for (i = sd_template.num_majors - 1; i >= N_SD_PREASSIGNED_MAJORS; --i)
+               devfs_dealloc_major(DEVFS_SPECIAL_BLK, sd_template.majors[i]);
+}      /*  End Function sd_dealloc_majors  */
+
 /*
  * The sd_init() function looks at all SCSI drives present, determines
  * their size, and reads partition table entries for them.
@@ -1060,11 +1118,15 @@
        if (sd_template.dev_noticed == 0)
                return 0;
 
-       if (!rscsi_disks)
+       if (!rscsi_disks) {
+               if ( in_interrupt() ) {
+                       printk (__FUNCTION__ "(): called from interrupt\n");
+                       return 1;
+               }
                sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
-
-       if (sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR)
-               sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR;
+               if ( sd_alloc_majors() )
+                       return 1;
+       }
 
        /* At most 16 partitions on each scsi disk. */
        maxparts = (sd_template.dev_max << 4);
@@ -1077,6 +1139,7 @@
                                                  &sd_fops)) {
                                printk("Unable to get major %d for SCSI disk\n",
                                       SD_MAJOR(i));
+                               sd_dealloc_majors();
                                return 1;
                        }
                }
@@ -1087,7 +1150,7 @@
                return 0;
 
        /* allocate memory */
-#define init_mem_lth(x,n)      x = kmalloc((n) * sizeof(*x), GFP_ATOMIC)
+#define init_mem_lth(x,n)      x = sdmalloc((n) * sizeof(*x))
 #define zero_mem_lth(x,n)      memset(x, 0, (n) * sizeof(*x))
 
        init_mem_lth(rscsi_disks, sd_template.dev_max);
@@ -1153,19 +1216,20 @@
 cleanup_gendisks:
        /* kfree can handle NULL, so no test is required here */
        for (i = 0; i < N_USED_SD_MAJORS; i++) {
-               kfree(sd_gendisks[i].de_arr);
-               kfree(sd_gendisks[i].flags);
+               sdfree(sd_gendisks[i].de_arr);
+               sdfree(sd_gendisks[i].flags);
        }
 cleanup_mem:
-       kfree(sd_gendisks);
-       kfree(sd);
-       kfree(sd_blocksizes);
-       kfree(sd_sizes);
-       kfree(rscsi_disks);
+       sdfree(sd_gendisks);
+       sdfree(sd);
+       sdfree(sd_blocksizes);
+       sdfree(sd_sizes);
+       sdfree(rscsi_disks);
        for (i = 0; i < N_USED_SD_MAJORS; i++) {
                devfs_unregister_blkdev(SD_MAJOR(i), "sd");
        }
        sd_registered--;
+       sd_dealloc_majors();
        return 1;
 }
 
@@ -1338,15 +1402,16 @@
 
        scsi_unregister_device(&sd_template);
 
+       sd_dealloc_majors();
        for (i = 0; i < N_USED_SD_MAJORS; i++)
                devfs_unregister_blkdev(SD_MAJOR(i), "sd");
 
        sd_registered--;
        if (rscsi_disks != NULL) {
-               kfree(rscsi_disks);
-               kfree(sd_sizes);
-               kfree(sd_blocksizes);
-               kfree((char *) sd);
+               sdfree(rscsi_disks);
+               sdfree(sd_sizes);
+               sdfree(sd_blocksizes);
+               sdfree((char *) sd);
        }
        for (i = 0; i < N_USED_SD_MAJORS; i++) {
                del_gendisk(&(sd_gendisks[i]));
@@ -1354,7 +1419,7 @@
        }
        sd_template.dev_max = 0;
        if (sd_gendisks != &sd_gendisk)
-               kfree(sd_gendisks);
+               sdfree(sd_gendisks);
 }
 
 module_init(init_sd);
diff -urN linux-2.5.3/drivers/scsi/sd.h linux/drivers/scsi/sd.h
--- linux-2.5.3/drivers/scsi/sd.h       Tue Jan 29 22:44:26 2002
+++ linux/drivers/scsi/sd.h     Thu Jan 31 00:51:47 2002
@@ -42,10 +42,14 @@
  */
 extern kdev_t sd_find_target(void *host, int tgt);
 
-#define N_SD_MAJORS    8
+#define N_SD_PREASSIGNED_MAJORS        8
 
-#define SD_MAJOR_MASK  (N_SD_MAJORS - 1)
+#ifdef CONFIG_SD_MANY
+#define SD_PARTITION(i)                ((sd_kdev_to_index((i)) << 4) | 
(minor(i)&0x0f))
+#else
+#define SD_MAJOR_MASK  (N_SD_PREASSIGNED_MAJORS - 1)
 #define SD_PARTITION(i)                (((major(i) & SD_MAJOR_MASK) << 8) | 
(minor(i) & 255))
+#endif
 
 #endif
 
diff -urN linux-2.5.3/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- linux-2.5.3/drivers/scsi/sg.c       Thu Jan 17 14:59:33 2002
+++ linux/drivers/scsi/sg.c     Thu Jan 31 00:34:49 2002
@@ -124,7 +124,6 @@
       module:THIS_MODULE,
       tag:"sg",
       scsi_type:0xff,
-      major:SCSI_GENERIC_MAJOR,
       detect:sg_detect,
       init:sg_init,
       finish:sg_finish,
diff -urN linux-2.5.3/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- linux-2.5.3/drivers/scsi/sr.c       Thu Jan 17 14:59:33 2002
+++ linux/drivers/scsi/sr.c     Thu Jan 31 00:34:49 2002
@@ -69,13 +69,16 @@
 
 static int sr_init_command(Scsi_Cmnd *);
 
+static unsigned int sr_major = SCSI_CDROM_MAJOR;
+
 static struct Scsi_Device_Template sr_template =
 {
        module:THIS_MODULE,
        name:"cdrom",
        tag:"sr",
        scsi_type:TYPE_ROM,
-       major:SCSI_CDROM_MAJOR,
+       majors:&sr_major,
+       num_majors:1,
        blk:1,
        detect:sr_detect,
        init:sr_init,
diff -urN linux-2.5.3/drivers/scsi/st.c linux/drivers/scsi/st.c
--- linux-2.5.3/drivers/scsi/st.c       Wed Jan 23 16:30:47 2002
+++ linux/drivers/scsi/st.c     Thu Jan 31 00:34:49 2002
@@ -166,7 +166,6 @@
        name:           "tape", 
        tag:            "st", 
        scsi_type:      TYPE_TAPE,
-       major:          SCSI_TAPE_MAJOR, 
        detect:         st_detect, 
        attach:         st_attach, 
        detach:         st_detach
diff -urN linux-2.5.3/include/linux/blk.h linux/include/linux/blk.h
--- linux-2.5.3/include/linux/blk.h     Tue Jan 29 22:42:34 2002
+++ linux/include/linux/blk.h   Thu Jan 31 00:37:01 2002
@@ -148,7 +148,11 @@
 
 #define DEVICE_NAME "scsidisk"
 #define TIMEOUT_VALUE (2*HZ)
+#ifdef CONFIG_SD_MANY
+#define DEVICE_NR(device) sd_kdev_to_index((device))
+#else
 #define DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8 - 4)) + 
(minor(device) >> 4))
+#endif
 
 /* Kludge to use the same number for both char and block major numbers */
 #elif  (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] sd-many for 2.5.3 (uses devfs), Richard Gooch <=