From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Mon, 30 Jul 2001 20:31:09 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Mon, 30 Jul 2001 20:30:58 -0400 Received: from [209.226.93.226] ([209.226.93.226]:56826 "EHLO mobilix.ras.ucalgary.ca") by vger.kernel.org with ESMTP id ; Mon, 30 Jul 2001 20:30:36 -0400 Date: Mon, 30 Jul 2001 20:30:40 -0400 Message-Id: <200107310030.f6V0UeJ13558@mobilix.ras.ucalgary.ca> From: Richard Gooch To: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org Cc: devfs-announce-list@mobilix.ras.ucalgary.ca Subject: [RFT] Support for ~2144 SCSI discs Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Original-Recipient: rfc822;linux-kernel-outgoing Hi, all. Below is a patch that adds support for large numbers of SCSI discs (approximately 2144). I'd like people to try this out. I'm not doing my normal devfs-patch-v??? thing because this is completely untested (I'm away from my SCSI boxes), and I don't want to put a possibly FS-corrupting patch on my ftp archive. The code does compile and link, though. There are 3 cases I'd like to have tested: - people with 1 to 16 SCSI discs - people with 17 to 128 SCSI discs - people with >128 SCSI discs because each of these exercises a slightly different setup path. Please send success or failure reports to me. REMINDER: be careful with this patch. It could corrupt your FS. Regards, Richard.... Permanent: rgooch@atnf.csiro.au Current: rgooch@ras.ucalgary.ca diff -urN linux-2.4.7/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.4.7/Documentation/Configure.help Thu Jul 19 20:48:15 2001 +++ linux/Documentation/Configure.help Mon Jul 23 01:19:24 2001 @@ -5410,6 +5410,17 @@ located on a SCSI disk. In this case, do not compile the driver for your SCSI host adapter (below) as a module either. +Many SCSI Discs support +CONFIG_SD_MANY + This allows you to support a very large number of SCSI discs + (approximately 2144). 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. + Extra SCSI Disks CONFIG_SD_EXTRA_DEVS This controls the amount of additional space allocated in tables for diff -urN linux-2.4.7/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog --- linux-2.4.7/Documentation/filesystems/devfs/ChangeLog Wed Jul 11 17:55:41 2001 +++ linux/Documentation/filesystems/devfs/ChangeLog Mon Jul 30 19:13:00 2001 @@ -1675,3 +1675,13 @@ - Fixed number leak for /dev/cdroms/cdrom%d - Fixed number leak for /dev/discs/disc%d +=============================================================================== +Changes for patch v183 + +- Fixed bug in which could hang boot process +=============================================================================== +Changes for patch v184 + +- Support large numbers of SCSI discs (~2144) + +- Documentation typo fix for fs/devfs/util.c diff -urN linux-2.4.7/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- linux-2.4.7/drivers/scsi/Config.in Thu Jul 5 14:28:16 2001 +++ linux/drivers/scsi/Config.in Mon Jul 23 01:19:47 2001 @@ -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 (~2144) 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.4.7/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- linux-2.4.7/drivers/scsi/hosts.h Fri Jul 20 15:55:46 2001 +++ linux/drivers/scsi/hosts.h Mon Jul 30 19:20:27 2001 @@ -506,9 +506,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.4.7/drivers/scsi/osst.c linux/drivers/scsi/osst.c --- linux-2.4.7/drivers/scsi/osst.c Fri Jul 20 00:18:15 2001 +++ linux/drivers/scsi/osst.c Mon Jul 30 17:57:27 2001 @@ -160,7 +160,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.4.7/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- linux-2.4.7/drivers/scsi/scsi_lib.c Thu Jul 19 23:48:04 2001 +++ linux/drivers/scsi/scsi_lib.c Mon Jul 30 17:52:35 2001 @@ -769,25 +769,10 @@ * 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.4.7/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- linux-2.4.7/drivers/scsi/sd.c Thu Jul 5 14:28:17 2001 +++ linux/drivers/scsi/sd.c Mon Jul 30 20:10:58 2001 @@ -28,6 +28,8 @@ * * Modified by Alex Davis * Fix problem where removable media could be ejected after sd_open. + * + * Modified by Richard Gooch rgooch@atnf.csiro.au to support >128 discs. */ #include @@ -65,7 +67,7 @@ * static const char RCSid[] = "$Header:"; */ -#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i)) +#define SD_MAJOR(i) sd_template.majors[(i)] #define SCSI_DISKS_PER_MAJOR 16 #define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8) @@ -108,12 +110,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, @@ -123,6 +119,19 @@ init_command:sd_init_command, }; +#ifdef CONFIG_SD_MANY +static inline int sd_devnum_to_index (int devnum) +{ + int i, major = MAJOR (devnum); + + for (i = 0; i < sd_template.num_majors; ++i) + { + if (sd_template.majors[i] != major) continue; + return (i << 4) | (MINOR (i) >> 4); + } + return -ENODEV; +} +#endif static void rw_intr(Scsi_Cmnd * SCpnt); @@ -1043,6 +1052,41 @@ 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_ATOMIC) ) == 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 < N_USED_SD_MAJORS); ++i) { + if ( ( major = devfs_alloc_major (DEVFS_SPECIAL_BLK) ) < 0 ) + 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. @@ -1057,16 +1101,16 @@ if (sd_template.dev_noticed == 0) return 0; - if (!rscsi_disks) + if (!rscsi_disks) { 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; + } if (!sd_registered) { for (i = 0; i < N_USED_SD_MAJORS; i++) { if (devfs_register_blkdev(SD_MAJOR(i), "sd", &sd_fops)) { printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i)); + sd_dealloc_majors(); return 1; } } @@ -1166,6 +1210,7 @@ for (i = 0; i < N_USED_SD_MAJORS; i++) { devfs_unregister_blkdev(SD_MAJOR(i), "sd"); } + sd_dealloc_majors(); sd_registered--; return 1; } @@ -1373,6 +1418,7 @@ scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); + sd_dealloc_majors(); for (i = 0; i < N_USED_SD_MAJORS; i++) devfs_unregister_blkdev(SD_MAJOR(i), "sd"); diff -urN linux-2.4.7/drivers/scsi/sd.h linux/drivers/scsi/sd.h --- linux-2.4.7/drivers/scsi/sd.h Fri Jul 20 15:55:46 2001 +++ linux/drivers/scsi/sd.h Mon Jul 30 20:09:12 2001 @@ -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 +#ifdef CONFIG_SD_MANY +#define SD_PARTITION(i) ((sd_devnum_to_index((i)) << 4) | ((i)&0x0f)) +#else #define SD_MAJOR_MASK (N_SD_MAJORS - 1) #define SD_PARTITION(i) (((MAJOR(i) & SD_MAJOR_MASK) << 8) | (MINOR(i) & 255)) +#endif #endif diff -urN linux-2.4.7/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- linux-2.4.7/drivers/scsi/sg.c Wed Jul 4 18:39:28 2001 +++ linux/drivers/scsi/sg.c Mon Jul 30 17:57:52 2001 @@ -123,7 +123,6 @@ { tag:"sg", scsi_type:0xff, - major:SCSI_GENERIC_MAJOR, detect:sg_detect, init:sg_init, finish:sg_finish, diff -urN linux-2.4.7/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- linux-2.4.7/drivers/scsi/sr.c Thu Jul 5 14:28:17 2001 +++ linux/drivers/scsi/sr.c Mon Jul 30 17:59:33 2001 @@ -69,12 +69,15 @@ static int sr_init_command(Scsi_Cmnd *); +static unsigned int sr_major = SCSI_CDROM_MAJOR; + static struct Scsi_Device_Template sr_template = { 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.4.7/drivers/scsi/st.c linux/drivers/scsi/st.c --- linux-2.4.7/drivers/scsi/st.c Fri Jul 20 00:16:32 2001 +++ linux/drivers/scsi/st.c Mon Jul 30 17:58:22 2001 @@ -160,7 +160,6 @@ name:"tape", tag:"st", scsi_type:TYPE_TAPE, - major:SCSI_TAPE_MAJOR, detect:st_detect, init:st_init, attach:st_attach, diff -urN linux-2.4.7/fs/devfs/base.c linux/fs/devfs/base.c --- linux-2.4.7/fs/devfs/base.c Wed Jul 11 17:55:41 2001 +++ linux/fs/devfs/base.c Mon Jul 30 19:10:41 2001 @@ -511,6 +511,9 @@ Removed broken devnum allocation and use . Fixed old devnum leak by calling new . v0.107 + 20010712 Richard Gooch + Fixed bug in which could hang boot process. + v0.108 */ #include #include @@ -543,7 +546,7 @@ #include #include -#define DEVFS_VERSION "0.107 (20010709)" +#define DEVFS_VERSION "0.108 (20010712)" #define DEVFS_NAME "devfs" @@ -1342,12 +1345,12 @@ return NULL; } } - de->u.fcb.autogen = 0; + de->u.fcb.autogen = FALSE; if ( S_ISCHR (mode) || S_ISBLK (mode) ) { de->u.fcb.u.device.major = major; de->u.fcb.u.device.minor = minor; - de->u.fcb.autogen = (devnum == NODEV) ? 0 : 1; + de->u.fcb.autogen = (devnum == NODEV) ? FALSE : TRUE; } else if ( S_ISREG (mode) ) de->u.fcb.u.file.size = 0; else @@ -1418,7 +1421,7 @@ MKDEV (de->u.fcb.u.device.major, de->u.fcb.u.device.minor) ); } - de->u.fcb.autogen = 0; + de->u.fcb.autogen = FALSE; return; } if (S_ISLNK (de->mode) && de->registered) @@ -2063,6 +2066,7 @@ {"show", OPTION_SHOW, &boot_options}, {"only", OPTION_ONLY, &boot_options}, {"mount", OPTION_MOUNT, &boot_options}, + {NULL, 0, NULL} }; while ( (*str != '\0') && !isspace (*str) ) @@ -2074,7 +2078,7 @@ invert = 1; str += 2; } - for (i = 0; i < sizeof (devfs_options_tab); i++) + for (i = 0; devfs_options_tab[i].name != NULL; i++) { int len = strlen (devfs_options_tab[i].name); diff -urN linux-2.4.7/fs/devfs/util.c linux/fs/devfs/util.c --- linux-2.4.7/fs/devfs/util.c Wed Jul 11 17:55:41 2001 +++ linux/fs/devfs/util.c Mon Jul 30 18:28:12 2001 @@ -39,6 +39,8 @@ Created and . 20010710 Richard Gooch Created . + 20010730 Richard Gooch + Documentation typo fix. */ #include #include @@ -214,7 +216,7 @@ /** * devfs_alloc_major - Allocate a major number. - * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK) + * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK) * Returns the allocated major, else -1 if none are available. * This routine is thread safe and does not block. @@ -238,7 +240,7 @@ /** * devfs_dealloc_major - Deallocate a major number. - * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK) + * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK) * @major: The major number. * This routine is thread safe and does not block. */ @@ -282,7 +284,7 @@ /** * devfs_alloc_devnum - Allocate a device number. - * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK). + * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK). * * Returns the allocated device number, else NODEV if none are available. * This routine is thread safe and may block. @@ -347,7 +349,7 @@ /** * devfs_dealloc_devnum - Dellocate a device number. - * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK). + * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK). * @devnum: The device number. * * This routine is thread safe and does not block. diff -urN linux-2.4.7/include/linux/blk.h linux/include/linux/blk.h --- linux-2.4.7/include/linux/blk.h Mon Jul 30 19:20:01 2001 +++ linux/include/linux/blk.h Mon Jul 30 20:05:18 2001 @@ -144,7 +144,11 @@ #define DEVICE_NAME "scsidisk" #define TIMEOUT_VALUE (2*HZ) +#ifdef CONFIG_SD_MANY +#define DEVICE_NR(device) sd_devnum_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)