diff -urN linux-2.4.9/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.4.9/Documentation/Configure.help Sun Aug 12 11:51:41 2001 +++ linux/Documentation/Configure.help Fri Aug 17 22:11:39 2001 @@ -5423,6 +5423,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.9/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog --- linux-2.4.9/Documentation/filesystems/devfs/ChangeLog Wed Jul 11 15:55:41 2001 +++ linux/Documentation/filesystems/devfs/ChangeLog Tue Aug 21 23:52:09 2001 @@ -1675,3 +1675,68 @@ - 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 + +- Fixed drivers/char/stallion.c for devfs + +- Added DEVFSD_NOTIFY_DELETE event + +- Updated README from master HTML file + +- Removed #include from fs/devfs/base.c +=============================================================================== +Changes for patch v185 + +- Made and in fs/devfs/util.c + private + +- Fixed inode table races by removing it and using inode->u.generic_ip + instead + +- Moved into + +- Moved into +=============================================================================== +Changes for patch v186 + +- Fixed race in for uni-processor + +- Fixed drivers/scsi/sd.h for when CONFIG_SD_MANY=n + +- Updated README from master HTML file +=============================================================================== +Changes for patch v187 + +- Fixed drivers/char/stallion.c for devfs + +- Fixed drivers/char/rocket.c for devfs + +- Fixed bug in : limited to 128 numbers +=============================================================================== +Changes for patch v188 + +- Updated major masks in fs/devfs/util.c up to Linus' "no new majors" + proclamation. Block: were 126 now 122 free, char: were 26 now 19 free + +- Updated README from master HTML file + +- Removed remnant of multi-mount support in + +- Removed unused DEVFS_FL_SHOW_UNREG flag +=============================================================================== +Changes for patch v189 + +- Removed nlink field from struct devfs_inode + +- Removed auto-ownership for /dev/pty/* (BSD ptys) and used + DEVFS_FL_CURRENT_OWNER|DEVFS_FL_NO_PERSISTENCE for /dev/pty/s* (just + like Unix98 pty slaves) and made /dev/pty/m* rw-rw-rw- access diff -urN linux-2.4.9/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README --- linux-2.4.9/Documentation/filesystems/devfs/README Tue Jun 12 11:57:46 2001 +++ linux/Documentation/filesystems/devfs/README Sat Aug 18 00:12:40 2001 @@ -3,7 +3,7 @@ Linux Devfs (Device File System) FAQ Richard Gooch -26-APR-2001 +16-AUG-2001 ----------------------------------------------------------------------------- @@ -18,17 +18,14 @@ http://www.atnf.csiro.au/~rgooch/linux/ -NEWSFLASH: The official 2.3.46 kernel has -included the devfs patch. Future patches will be released which -build on this. These patches are rolled into Linus' tree from time to -time. - A mailing list is available which you may subscribe to. Send email to majordomo@oss.sgi.com with the following line in the body of the message: subscribe devfs -The list is archived at +To unsubscribe, send the message body: +unsubscribe devfs +instead. The list is archived at http://oss.sgi.com/projects/devfs/archive/. @@ -71,6 +68,8 @@ Other resources +Translations of this document + ----------------------------------------------------------------------------- @@ -82,7 +81,7 @@ name rather than major and minor numbers. These devices will appear in devfs automatically, with whatever default ownership and protection the driver specified. A daemon (devfsd) can be used to -override these defaults. +override these defaults. Devfs has been in the kernel since 2.3.46. NOTE that devfs is entirely optional. If you prefer the old disc-based device nodes, then simply leave CONFIG_DEVFS_FS=n (the @@ -604,6 +603,20 @@ has problems with symbolic links. Append the following lines to your /etc/securetty file: +vc/1 +vc/2 +vc/3 +vc/4 +vc/5 +vc/6 +vc/7 +vc/8 + +This will not weaken security. If you have a version of util-linux +earlier than 2.10.h, please upgrade to 2.10.h or later. If you +absolutely cannot upgrade, then also append the following lines to +your /etc/securetty file: + 1 2 3 @@ -618,27 +631,13 @@ are problems with dealing with symlinks, I'm suspicious of the level of security offered in any case. -A better solution is to install util-linux-2.10.h or later, which -fixes a bug with ttyname handling in the login programme. Then append -the following lines to your /etc/securetty file: - -vc/1 -vc/2 -vc/3 -vc/4 -vc/5 -vc/6 -vc/7 -vc/8 - -This will not weaken security. - XFree86 While not essential, it's probably a good idea to upgrade to XFree86 4.0, as patches went in to make it more devfs-friendly. If you don't, you'll probably need to apply the following patch to /etc/security/console.perms so that ordinary users can run -startx. +startx. Note that not all distributions have this file (e.g. Debian), +so if it's not present, don't worry about it. --- /etc/security/console.perms.orig Sat Apr 17 16:26:47 1999 +++ /etc/security/console.perms Fri Feb 25 23:53:55 2000 @@ -805,8 +804,17 @@ directory to store the database. The sample /etc/devfsd.conf file above may still be used. You will need to create the /dev-state directory prior to installing devfsd. If you have -old permissions in /dev, then just copy the device nodes over -to the new directory. +old permissions in /dev, then just copy (or move) the device +nodes over to the new directory. + +Which method is better? + +The best method is to have the permissions database stored in the +mounted-over /dev. This is because you will not need to copy +device nodes over to /dev-state, and because it allows you to +switch between devfs and non-devfs kernels, without requiring you to +copy permissions between /dev-state (for devfs) and +/dev (for non-devfs). Dealing with drivers without devfs support @@ -1038,6 +1046,13 @@ directory tree that reflects the topology of available devices. The topological tree is useful for finding how your devices are arranged. +Below is a list of the naming schemes for the most common drivers. A +list of reserved device names is +available for reference. Please send email to +rgooch@atnf.csiro.au to obtain an allocation. Please be +patient (the maintainer is busy). An alternative name may be allocated +instead of the requested name, at the discretion of the maintainer. + Disc Devices All discs, whether SCSI, IDE or whatever, are placed under the @@ -1486,6 +1501,17 @@ namespace, but have had no response. +How can I test if devfs is mounted on /dev? + +The device filesystem will always create an entry called +".devfsd", which is used to communicate with the daemon. Even +if the daemon is not running, this entry will exist. Testing for the +existence of this entry is the approved method of determining if devfs +is mounted or not. Note that the type of entry (i.e. regular file, +character device, named pipe, etc.) may change without notice. Only +the existence of the entry should be relied upon. + + @@ -1713,6 +1739,23 @@ 2nd Annual Storage Management Workshop held in Miamia, Florida, U.S.A. in October 2000. + + + + +----------------------------------------------------------------------------- + + +Translations of this document + +This document has been translated into other languages. + + + + +A Korean translation by viatoris@nownuri.net is available at + +http://home.nownuri.net/~viatoris/devfs/devfs.html diff -urN linux-2.4.9/Documentation/filesystems/devfs/boot-options linux/Documentation/filesystems/devfs/boot-options --- linux-2.4.9/Documentation/filesystems/devfs/boot-options Mon May 8 23:00:41 2000 +++ linux/Documentation/filesystems/devfs/boot-options Sat Aug 18 19:24:54 2001 @@ -4,7 +4,7 @@ Richard Gooch - 30-APR-2000 + 18-AUG-2001 When CONFIG_DEVFS_DEBUG is enabled, you can pass several boot options @@ -19,6 +19,8 @@ devfs=dmod,dreg +You may prefix "no" to any option. This will invert the option. + Debugging Options ================= @@ -42,11 +44,11 @@ dilookup print inode lookup requests -diread print inode reads +diget print VFS inode allocations diunlink print inode unlinks -diwrite print inode writes +dichange print inode changes dimknod print calls to mknod(2) @@ -58,10 +60,6 @@ These control the default behaviour of devfs. The options are: -show show unregistered devices by default - mount mount devfs onto /dev at boot time - -nomount do not mount devfs onto /dev at boot time only disable non-devfs device nodes for devfs-capable drivers diff -urN linux-2.4.9/drivers/char/pty.c linux/drivers/char/pty.c --- linux-2.4.9/drivers/char/pty.c Thu Jun 29 19:25:50 2000 +++ linux/drivers/char/pty.c Tue Aug 21 23:20:00 2001 @@ -334,7 +334,8 @@ /* Register a slave for the master */ if (tty->driver.major == PTY_MASTER_MAJOR) tty_register_devfs(&tty->link->driver, - DEVFS_FL_AUTO_OWNER | DEVFS_FL_WAIT, + DEVFS_FL_CURRENT_OWNER | + DEVFS_FL_NO_PERSISTENCE | DEVFS_FL_WAIT, tty->link->driver.minor_start + MINOR(tty->device)-tty->driver.minor_start); retval = 0; diff -urN linux-2.4.9/drivers/char/rocket.c linux/drivers/char/rocket.c --- linux-2.4.9/drivers/char/rocket.c Mon Jul 2 14:56:41 2001 +++ linux/drivers/char/rocket.c Fri Aug 17 22:11:39 2001 @@ -2185,7 +2185,11 @@ */ memset(&rocket_driver, 0, sizeof(struct tty_driver)); rocket_driver.magic = TTY_DRIVER_MAGIC; +#ifdef CONFIG_DEVFS_FS + rocket_driver.name = "tts/R%d"; +#else rocket_driver.name = "ttyR"; +#endif rocket_driver.major = TTY_ROCKET_MAJOR; rocket_driver.minor_start = 0; rocket_driver.num = MAX_RP_PORTS; @@ -2227,7 +2231,11 @@ * the minor number and the subtype code. */ callout_driver = rocket_driver; +#ifdef CONFIG_DEVFS_FS + callout_driver.name = "cua/R%d"; +#else callout_driver.name = "cur"; +#endif callout_driver.major = CUA_ROCKET_MAJOR; callout_driver.minor_start = 0; callout_driver.subtype = SERIAL_TYPE_CALLOUT; diff -urN linux-2.4.9/drivers/char/stallion.c linux/drivers/char/stallion.c --- linux-2.4.9/drivers/char/stallion.c Fri Mar 2 12:12:07 2001 +++ linux/drivers/char/stallion.c Fri Aug 17 22:11:39 2001 @@ -139,8 +139,13 @@ static char *stl_drvtitle = "Stallion Multiport Serial Driver"; static char *stl_drvname = "stallion"; static char *stl_drvversion = "5.6.0"; +#ifdef CONFIG_DEVFS_FS +static char *stl_serialname = "tts/E%d"; +static char *stl_calloutname = "cua/E%d"; +#else static char *stl_serialname = "ttyE"; static char *stl_calloutname = "cue"; +#endif static struct tty_driver stl_serial; static struct tty_driver stl_callout; diff -urN linux-2.4.9/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- linux-2.4.9/drivers/char/tty_io.c Sun Aug 12 18:36:24 2001 +++ linux/drivers/char/tty_io.c Tue Aug 21 23:11:18 2001 @@ -2021,7 +2021,7 @@ break; default: if (driver->major == PTY_MASTER_MAJOR) - flags |= DEVFS_FL_AUTO_OWNER; + mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; break; } if ( (minor < driver->minor_start) || diff -urN linux-2.4.9/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- linux-2.4.9/drivers/scsi/Config.in Thu Jul 5 12:28:16 2001 +++ linux/drivers/scsi/Config.in Fri Aug 17 22:11:39 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.9/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- linux-2.4.9/drivers/scsi/hosts.h Wed Aug 15 15:23:11 2001 +++ linux/drivers/scsi/hosts.h Fri Aug 17 22:20:25 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.9/drivers/scsi/osst.c linux/drivers/scsi/osst.c --- linux-2.4.9/drivers/scsi/osst.c Thu Jul 19 22:18:15 2001 +++ linux/drivers/scsi/osst.c Fri Aug 17 22:11:39 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.9/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- linux-2.4.9/drivers/scsi/scsi_lib.c Sun Aug 12 11:51:42 2001 +++ linux/drivers/scsi/scsi_lib.c Fri Aug 17 22:11:39 2001 @@ -788,25 +788,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.9/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- linux-2.4.9/drivers/scsi/sd.c Sun Aug 5 14:12:41 2001 +++ linux/drivers/scsi/sd.c Fri Aug 17 22:11:39 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 (devnum) >> 4); + } + return -ENODEV; +} +#endif static void rw_intr(Scsi_Cmnd * SCpnt); @@ -1052,6 +1061,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 < 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. @@ -1066,16 +1112,20 @@ 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; + } 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; } } @@ -1085,22 +1135,22 @@ if (rscsi_disks) return 0; - rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC); + rscsi_disks = vmalloc(sd_template.dev_max * sizeof(Scsi_Disk)); if (!rscsi_disks) goto cleanup_devfs; memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk)); /* for every (necessary) major: */ - sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); + sd_sizes = vmalloc((sd_template.dev_max << 4) * sizeof(int)); if (!sd_sizes) goto cleanup_disks; memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); - sd_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); + sd_blocksizes = vmalloc((sd_template.dev_max << 4) * sizeof(int)); if (!sd_blocksizes) goto cleanup_sizes; - sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); + sd_hardsizes = vmalloc((sd_template.dev_max << 4) * sizeof(int)); if (!sd_hardsizes) goto cleanup_blocksizes; @@ -1113,9 +1163,7 @@ blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4); hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4); } - sd = kmalloc((sd_template.dev_max << 4) * - sizeof(struct hd_struct), - GFP_ATOMIC); + sd = vmalloc((sd_template.dev_max << 4) * sizeof(struct hd_struct)); if (!sd) goto cleanup_sd; memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct)); @@ -1162,19 +1210,20 @@ } kfree(sd_gendisks); cleanup_sd_gendisks: - kfree(sd); + vfree(sd); cleanup_sd: - kfree(sd_hardsizes); + vfree(sd_hardsizes); cleanup_blocksizes: - kfree(sd_blocksizes); + vfree(sd_blocksizes); cleanup_sizes: - kfree(sd_sizes); + vfree(sd_sizes); cleanup_disks: - kfree(rscsi_disks); + vfree(rscsi_disks); cleanup_devfs: for (i = 0; i < N_USED_SD_MAJORS; i++) { devfs_unregister_blkdev(SD_MAJOR(i), "sd"); } + sd_dealloc_majors(); sd_registered--; return 1; } @@ -1382,6 +1431,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.9/drivers/scsi/sd.h linux/drivers/scsi/sd.h --- linux-2.4.9/drivers/scsi/sd.h Wed Aug 15 15:23:15 2001 +++ linux/drivers/scsi/sd.h Sat Aug 18 23:34:58 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 -#define SD_MAJOR_MASK (N_SD_MAJORS - 1) +#ifdef CONFIG_SD_MANY +#define SD_PARTITION(i) ((sd_devnum_to_index((i)) << 4) | ((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.4.9/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- linux-2.4.9/drivers/scsi/sg.c Wed Jul 4 16:39:28 2001 +++ linux/drivers/scsi/sg.c Fri Aug 17 22:11:39 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.9/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- linux-2.4.9/drivers/scsi/sr.c Thu Jul 5 12:28:17 2001 +++ linux/drivers/scsi/sr.c Fri Aug 17 22:11:39 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.9/drivers/scsi/st.c linux/drivers/scsi/st.c --- linux-2.4.9/drivers/scsi/st.c Sun Aug 12 12:21:47 2001 +++ linux/drivers/scsi/st.c Fri Aug 17 22:11:39 2001 @@ -166,7 +166,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.9/fs/devfs/base.c linux/fs/devfs/base.c --- linux-2.4.9/fs/devfs/base.c Wed Jul 11 15:55:41 2001 +++ linux/fs/devfs/base.c Tue Aug 21 00:43:35 2001 @@ -388,7 +388,7 @@ Work sponsored by SGI. v0.83 19991107 Richard Gooch - Added DEVFS_ FL_WAIT flag. + Added DEVFS_FL_WAIT flag. Work sponsored by SGI. v0.84 19991107 Richard Gooch @@ -511,6 +511,30 @@ 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 + 20010730 Richard Gooch + Added DEVFSD_NOTIFY_DELETE event. + 20010801 Richard Gooch + Removed #include . + v0.109 + 20010807 Richard Gooch + Fixed inode table races by removing it and using + inode->u.generic_ip instead. + Moved into . + Moved into . + v0.110 + 20010808 Richard Gooch + Fixed race in for uni-processor. + v0.111 + 20010818 Richard Gooch + Removed remnant of multi-mount support in . + Removed unused DEVFS_FL_SHOW_UNREG flag. + v0.112 + 20010820 Richard Gooch + Removed nlink field from struct devfs_inode. + v0.113 */ #include #include @@ -539,15 +563,13 @@ #include #include #include -#include #include #include -#define DEVFS_VERSION "0.107 (20010709)" +#define DEVFS_VERSION "0.113 (20010820)" #define DEVFS_NAME "devfs" -#define INODE_TABLE_INC 250 #define FIRST_INODE 1 #define STRING_LENGTH 256 @@ -557,7 +579,7 @@ # define FALSE 0 #endif -#define IS_HIDDEN(de) (( ((de)->hide && !is_devfsd_or_child(fs_info)) || (!(de)->registered&& !(de)->show_unreg))) +#define IS_HIDDEN(de) (( ((de)->hide && !is_devfsd_or_child(fs_info)) || !(de)->registered)) #define DEBUG_NONE 0x00000 #define DEBUG_MODULE_LOAD 0x00001 @@ -567,8 +589,8 @@ #define DEBUG_S_PUT 0x00010 #define DEBUG_I_LOOKUP 0x00020 #define DEBUG_I_CREATE 0x00040 -#define DEBUG_I_READ 0x00080 -#define DEBUG_I_WRITE 0x00100 +#define DEBUG_I_GET 0x00080 +#define DEBUG_I_CHANGE 0x00100 #define DEBUG_I_UNLINK 0x00200 #define DEBUG_I_RLINK 0x00400 #define DEBUG_I_FLINK 0x00800 @@ -577,16 +599,12 @@ #define DEBUG_D_DELETE 0x04000 #define DEBUG_D_RELEASE 0x08000 #define DEBUG_D_IPUT 0x10000 -#define DEBUG_ALL (DEBUG_MODULE_LOAD | DEBUG_REGISTER | \ - DEBUG_SET_FLAGS | DEBUG_I_LOOKUP | \ - DEBUG_I_UNLINK | DEBUG_I_MKNOD | \ - DEBUG_D_RELEASE | DEBUG_D_IPUT) +#define DEBUG_ALL 0xfffff #define DEBUG_DISABLED DEBUG_NONE #define OPTION_NONE 0x00 -#define OPTION_SHOW 0x01 -#define OPTION_MOUNT 0x02 -#define OPTION_ONLY 0x04 +#define OPTION_MOUNT 0x01 +#define OPTION_ONLY 0x02 #define OOPS(format, args...) {printk (format, ## args); \ printk ("Forcing Oops\n"); \ @@ -650,7 +668,6 @@ umode_t mode; uid_t uid; gid_t gid; - nlink_t nlink; }; struct devfs_entry @@ -672,7 +689,6 @@ umode_t mode; unsigned short namelen; /* I think 64k+ filenames are a way off... */ unsigned char registered:1; - unsigned char show_unreg:1; unsigned char hide:1; unsigned char no_persistence:1; char name[1]; /* This is just a dummy: the allocated array is @@ -693,9 +709,6 @@ struct fs_info /* This structure is for the mounted devfs */ { - unsigned int num_inodes; /* Number of inodes created */ - unsigned int table_size; /* Size of the inode pointer table */ - struct devfs_entry **table; struct super_block *sb; volatile struct devfsd_buf_entry *devfsd_buffer; spinlock_t devfsd_buffer_lock; @@ -789,40 +802,22 @@ static struct devfs_entry *create_entry (struct devfs_entry *parent, const char *name,unsigned int namelen) { - struct devfs_entry *new, **table; + struct devfs_entry *new; + static unsigned long inode_counter = FIRST_INODE; + static spinlock_t counter_lock = SPIN_LOCK_UNLOCKED; - /* First ensure table size is enough */ - if (fs_info.num_inodes >= fs_info.table_size) - { - if ( ( table = kmalloc (sizeof *table * - (fs_info.table_size + INODE_TABLE_INC), - GFP_KERNEL) ) == NULL ) return NULL; - fs_info.table_size += INODE_TABLE_INC; -#ifdef CONFIG_DEVFS_DEBUG - if (devfs_debug & DEBUG_I_CREATE) - printk ("%s: create_entry(): grew inode table to: %u entries\n", - DEVFS_NAME, fs_info.table_size); -#endif - if (fs_info.table) - { - memcpy (table, fs_info.table, sizeof *table *fs_info.num_inodes); - kfree (fs_info.table); - } - fs_info.table = table; - } if ( name && (namelen < 1) ) namelen = strlen (name); if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL ) return NULL; /* Magic: this will set the ctime to zero, thus subsequent lookups will trigger the call to */ memset (new, 0, sizeof *new + namelen); + spin_lock (&counter_lock); + new->inode.ino = inode_counter++; + spin_unlock (&counter_lock); new->parent = parent; if (name) memcpy (new->name, name, namelen); new->namelen = namelen; - new->inode.ino = fs_info.num_inodes + FIRST_INODE; - new->inode.nlink = 1; - fs_info.table[fs_info.num_inodes] = new; - ++fs_info.num_inodes; if (parent == NULL) return new; new->prev = parent->u.dir.last; /* Insert into the parent directory's list of children */ @@ -1083,14 +1078,10 @@ int do_check) { struct devfs_entry *de; - struct fs_info *fs_info; if (inode == NULL) return NULL; - if (inode->i_ino < FIRST_INODE) return NULL; - fs_info = inode->i_sb->u.generic_sbp; - if (fs_info == NULL) return NULL; - if (inode->i_ino - FIRST_INODE >= fs_info->num_inodes) return NULL; - de = fs_info->table[inode->i_ino - FIRST_INODE]; + de = inode->u.generic_ip; + if (!de) printk (__FUNCTION__ "(): NULL de for inode %ld\n", inode->i_ino); if (do_check && de && !de->registered) de = NULL; return de; } /* End Function get_devfs_entry_from_vfs_inode */ @@ -1342,12 +1333,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 @@ -1377,8 +1368,6 @@ ++de->parent->u.dir.num_removable; } de->u.fcb.open = FALSE; - de->show_unreg = ( (boot_options & OPTION_SHOW) - || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE; de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE; de->no_persistence = (flags & DEVFS_FL_NO_PERSISTENCE) ? TRUE : FALSE; de->registered = TRUE; @@ -1418,7 +1407,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) @@ -1475,7 +1464,7 @@ { int is_new; unsigned int linklength; - char *newname; + char *newlink; struct devfs_entry *de; if (handle != NULL) *handle = NULL; @@ -1494,49 +1483,30 @@ return -EINVAL; } linklength = strlen (link); - de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new, - FALSE); - if (de == NULL) return -ENOMEM; - if (!S_ISLNK (de->mode) && de->registered) + if ( ( newlink = kmalloc (linklength + 1, GFP_KERNEL) ) == NULL ) + return -ENOMEM; + memcpy (newlink, link, linklength); + newlink[linklength] = '\0'; + if ( ( de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, + &is_new, FALSE) ) == NULL ) { - printk ("%s: devfs_do_symlink(): non-link entry already exists\n", - DEVFS_NAME); + kfree (newlink); + return -ENOMEM; + } + if (de->registered) + { + kfree (newlink); + printk ("%s: devfs_do_symlink(%s): entry already exists\n", + DEVFS_NAME, name); return -EEXIST; } - if (handle != NULL) *handle = de; de->mode = S_IFLNK | S_IRUGO | S_IXUGO; de->info = info; - de->show_unreg = ( (boot_options & OPTION_SHOW) - || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE; de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE; - /* Note there is no need to fiddle the dentry cache if the symlink changes - as the symlink follow method is called every time it's needed */ - if ( de->registered && (linklength == de->u.symlink.length) ) - { - /* New link is same length as old link */ - if (memcmp (link, de->u.symlink.linkname, linklength) == 0) return 0; - return -EEXIST; /* Contents would change */ - } - /* Have to create/update */ - if (de->registered) return -EEXIST; - if ( ( newname = kmalloc (linklength + 1, GFP_KERNEL) ) == NULL ) - { - struct devfs_entry *parent = de->parent; - - if (!is_new) return -ENOMEM; - /* Have to clean up */ - if (de->prev == NULL) parent->u.dir.first = de->next; - else de->prev->next = de->next; - if (de->next == NULL) parent->u.dir.last = de->prev; - else de->next->prev = de->prev; - kfree (de); - return -ENOMEM; - } - de->u.symlink.linkname = newname; - memcpy (de->u.symlink.linkname, link, linklength); - de->u.symlink.linkname[linklength] = '\0'; + de->u.symlink.linkname = newlink; de->u.symlink.length = linklength; de->registered = TRUE; + if (handle != NULL) *handle = de; return 0; } /* End Function devfs_do_symlink */ @@ -1621,7 +1591,6 @@ de->mode = S_IFDIR | S_IRUGO | S_IXUGO; de->info = info; if (!de->registered) de->u.dir.num_removable = 0; - de->show_unreg = (boot_options & OPTION_SHOW) ? TRUE : FALSE; de->hide = FALSE; de->registered = TRUE; return de; @@ -1674,7 +1643,6 @@ if (de == NULL) return -EINVAL; if (!de->registered) return -ENODEV; - if (de->show_unreg) fl |= DEVFS_FL_SHOW_UNREG; if (de->hide) fl |= DEVFS_FL_HIDE; if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) ) { @@ -1704,7 +1672,6 @@ printk ("%s: devfs_set_flags(): de->name: \"%s\"\n", DEVFS_NAME, de->name); #endif - de->show_unreg = (flags & DEVFS_FL_SHOW_UNREG) ? TRUE : FALSE; de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE; if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) ) { @@ -2053,16 +2020,16 @@ {"dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, {"dreg", DEBUG_REGISTER, &devfs_debug_init}, {"dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, - {"diread", DEBUG_I_READ, &devfs_debug_init}, + {"diget", DEBUG_I_GET, &devfs_debug_init}, {"dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, - {"diwrite", DEBUG_I_WRITE, &devfs_debug_init}, + {"dichange", DEBUG_I_CHANGE, &devfs_debug_init}, {"dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, {"dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, {"diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, #endif /* CONFIG_DEVFS_DEBUG */ - {"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 +2041,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); @@ -2247,121 +2214,36 @@ static struct file_operations devfs_dir_fops; static struct inode_operations devfs_symlink_iops; -static void devfs_read_inode (struct inode *inode) -{ - struct devfs_entry *de; - - de = get_devfs_entry_from_vfs_inode (inode, TRUE); - if (de == NULL) - { - printk ("%s: read_inode(%d): VFS inode: %p NO devfs_entry\n", - DEVFS_NAME, (int) inode->i_ino, inode); - return; - } -#ifdef CONFIG_DEVFS_DEBUG - if (devfs_debug & DEBUG_I_READ) - printk ("%s: read_inode(%d): VFS inode: %p devfs_entry: %p\n", - DEVFS_NAME, (int) inode->i_ino, inode, de); -#endif - inode->i_blocks = 0; - inode->i_blksize = 1024; - inode->i_op = &devfs_iops; - inode->i_fop = &devfs_fops; - inode->i_rdev = NODEV; - if ( S_ISCHR (de->inode.mode) ) - { - inode->i_rdev = MKDEV (de->u.fcb.u.device.major, - de->u.fcb.u.device.minor); - inode->i_cdev = cdget (kdev_t_to_nr(inode->i_rdev)); - } - else if ( S_ISBLK (de->inode.mode) ) - { - inode->i_rdev = MKDEV (de->u.fcb.u.device.major, - de->u.fcb.u.device.minor); - inode->i_bdev = bdget (kdev_t_to_nr(inode->i_rdev)); - if (inode->i_bdev) - { - if (!inode->i_bdev->bd_op && de->u.fcb.ops) - inode->i_bdev->bd_op = de->u.fcb.ops; - } - else printk ("%s: read_inode(%d): no block device from bdget()\n", - DEVFS_NAME, (int) inode->i_ino); - } - else if ( S_ISFIFO (de->inode.mode) ) inode->i_fop = &def_fifo_fops; - else if ( S_ISREG (de->inode.mode) ) inode->i_size = de->u.fcb.u.file.size; - else if ( S_ISDIR (de->inode.mode) ) - { - inode->i_op = &devfs_dir_iops; - inode->i_fop = &devfs_dir_fops; - } - else if ( S_ISLNK (de->inode.mode) ) - { - inode->i_op = &devfs_symlink_iops; - inode->i_size = de->u.symlink.length; - } - inode->i_mode = de->inode.mode; - inode->i_uid = de->inode.uid; - inode->i_gid = de->inode.gid; - inode->i_atime = de->inode.atime; - inode->i_mtime = de->inode.mtime; - inode->i_ctime = de->inode.ctime; - inode->i_nlink = de->inode.nlink; -#ifdef CONFIG_DEVFS_DEBUG - if (devfs_debug & DEBUG_I_READ) - printk ("%s: mode: 0%o uid: %d gid: %d\n", - DEVFS_NAME, (int) inode->i_mode, - (int) inode->i_uid, (int) inode->i_gid); -#endif -} /* End Function devfs_read_inode */ - -static void devfs_write_inode (struct inode *inode, int wait) +static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr) { - int index; + int retval; struct devfs_entry *de; + struct inode *inode = dentry->d_inode; struct fs_info *fs_info = inode->i_sb->u.generic_sbp; - if (inode->i_ino < FIRST_INODE) return; - index = inode->i_ino - FIRST_INODE; - lock_kernel (); - if (index >= fs_info->num_inodes) - { - printk ("%s: writing inode: %lu for which there is no entry!\n", - DEVFS_NAME, inode->i_ino); - unlock_kernel (); - return; - } - de = fs_info->table[index]; + de = get_devfs_entry_from_vfs_inode (inode, TRUE); + if (de == NULL) return -ENODEV; + retval = inode_change_ok (inode, iattr); + if (retval != 0) return retval; + inode_setattr (inode, iattr); #ifdef CONFIG_DEVFS_DEBUG - if (devfs_debug & DEBUG_I_WRITE) + if (devfs_debug & DEBUG_I_CHANGE) { - printk ("%s: write_inode(%d): VFS inode: %p devfs_entry: %p\n", + printk ("%s: notify_change(%d): VFS inode: %p devfs_entry: %p\n", DEVFS_NAME, (int) inode->i_ino, inode, de); printk ("%s: mode: 0%o uid: %d gid: %d\n", DEVFS_NAME, (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid); } #endif + /* Inode is not on hash chains, thus must save permissions here rather + than in a write_inode() method */ de->inode.mode = inode->i_mode; de->inode.uid = inode->i_uid; de->inode.gid = inode->i_gid; de->inode.atime = inode->i_atime; de->inode.mtime = inode->i_mtime; de->inode.ctime = inode->i_ctime; - unlock_kernel (); -} /* End Function devfs_write_inode */ - -static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr) -{ - int retval; - struct devfs_entry *de; - struct inode *inode = dentry->d_inode; - struct fs_info *fs_info = inode->i_sb->u.generic_sbp; - - de = get_devfs_entry_from_vfs_inode (inode, TRUE); - if (de == NULL) return -ENODEV; - retval = inode_change_ok (inode, iattr); - if (retval != 0) return retval; - inode_setattr (inode, iattr); if ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) ) devfsd_notify_one (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, inode->i_uid, inode->i_gid, fs_info); @@ -2381,8 +2263,7 @@ static struct super_operations devfs_sops = { - read_inode: devfs_read_inode, - write_inode: devfs_write_inode, + put_inode: force_delete, statfs: devfs_statfs, }; @@ -2411,8 +2292,68 @@ printk (" old inode: %p\n", de->inode.dentry->d_inode); return NULL; } - if ( ( inode = iget (sb, de->inode.ino) ) == NULL ) return NULL; + if ( ( inode = new_inode (sb) ) == NULL ) + { + printk ("%s: get_vfs_inode(%s): new_inode() failed, de: %p\n", + DEVFS_NAME, de->name, de); + return NULL; + } de->inode.dentry = dentry; + inode->u.generic_ip = de; + inode->i_ino = de->inode.ino; +#ifdef CONFIG_DEVFS_DEBUG + if (devfs_debug & DEBUG_I_GET) + printk ("%s: get_vfs_inode(%d): VFS inode: %p devfs_entry: %p\n", + DEVFS_NAME, (int) inode->i_ino, inode, de); +#endif + inode->i_blocks = 0; + inode->i_blksize = 1024; + inode->i_op = &devfs_iops; + inode->i_fop = &devfs_fops; + inode->i_rdev = NODEV; + if ( S_ISCHR (de->inode.mode) ) + { + inode->i_rdev = MKDEV (de->u.fcb.u.device.major, + de->u.fcb.u.device.minor); + inode->i_cdev = cdget (kdev_t_to_nr(inode->i_rdev)); + } + else if ( S_ISBLK (de->inode.mode) ) + { + inode->i_rdev = MKDEV (de->u.fcb.u.device.major, + de->u.fcb.u.device.minor); + inode->i_bdev = bdget (kdev_t_to_nr(inode->i_rdev)); + if (inode->i_bdev) + { + if (!inode->i_bdev->bd_op && de->u.fcb.ops) + inode->i_bdev->bd_op = de->u.fcb.ops; + } + else printk ("%s: get_vfs_inode(%d): no block device from bdget()\n", + DEVFS_NAME, (int) inode->i_ino); + } + else if ( S_ISFIFO (de->inode.mode) ) inode->i_fop = &def_fifo_fops; + else if ( S_ISREG (de->inode.mode) ) inode->i_size = de->u.fcb.u.file.size; + else if ( S_ISDIR (de->inode.mode) ) + { + inode->i_op = &devfs_dir_iops; + inode->i_fop = &devfs_dir_fops; + } + else if ( S_ISLNK (de->inode.mode) ) + { + inode->i_op = &devfs_symlink_iops; + inode->i_size = de->u.symlink.length; + } + inode->i_mode = de->inode.mode; + inode->i_uid = de->inode.uid; + inode->i_gid = de->inode.gid; + inode->i_atime = de->inode.atime; + inode->i_mtime = de->inode.mtime; + inode->i_ctime = de->inode.ctime; +#ifdef CONFIG_DEVFS_DEBUG + if (devfs_debug & DEBUG_I_GET) + printk ("%s: mode: 0%o uid: %d gid: %d\n", + DEVFS_NAME, (int) inode->i_mode, + (int) inode->i_uid, (int) inode->i_gid); +#endif return inode; } /* End Function get_vfs_inode */ @@ -2725,14 +2666,14 @@ memcpy (txt, dentry->d_name.name, (dentry->d_name.len >= STRING_LENGTH) ? (STRING_LENGTH - 1) : dentry->d_name.len); -#ifdef CONFIG_DEVFS_DEBUG - if (devfs_debug & DEBUG_I_LOOKUP) - printk ("%s: lookup(%s): dentry: %p by: \"%s\"\n", - DEVFS_NAME, txt, dentry, current->comm); -#endif fs_info = dir->i_sb->u.generic_sbp; /* First try to get the devfs entry for this directory */ parent = get_devfs_entry_from_vfs_inode (dir, TRUE); +#ifdef CONFIG_DEVFS_DEBUG + if (devfs_debug & DEBUG_I_LOOKUP) + printk ("%s: lookup(%s): dentry: %p parent: %p by: \"%s\"\n", + DEVFS_NAME, txt, dentry, parent, current->comm); +#endif if (parent == NULL) return ERR_PTR (-ENOENT); /* Try to reclaim an existing devfs entry */ de = search_for_entry_in_dir (parent, @@ -2823,6 +2764,7 @@ static int devfs_unlink (struct inode *dir, struct dentry *dentry) { struct devfs_entry *de; + struct inode *inode = dentry->d_inode; #ifdef CONFIG_DEVFS_DEBUG char txt[STRING_LENGTH]; @@ -2838,6 +2780,8 @@ de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE); if (de == NULL) return -ENOENT; + devfsd_notify_one (de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, dir->i_sb->u.generic_sbp); de->registered = FALSE; de->hide = TRUE; if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname); @@ -2954,6 +2898,8 @@ } } if (has_children) return -ENOTEMPTY; + devfsd_notify_one (de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); de->hide = TRUE; de->registered = FALSE; free_dentries (de); @@ -2989,29 +2935,29 @@ de = search_for_entry (parent, dentry->d_name.name, dentry->d_name.len, FALSE, TRUE, &is_new, FALSE); if (de == NULL) return -ENOMEM; - if (!de->registered) + if (de->registered) { - /* Since we created the devfs entry we get to choose things */ - de->info = NULL; - de->mode = mode; - if ( S_ISBLK (mode) || S_ISCHR (mode) ) - { - de->u.fcb.u.device.major = MAJOR (rdev); - de->u.fcb.u.device.minor = MINOR (rdev); - de->u.fcb.default_uid = current->euid; - de->u.fcb.default_gid = current->egid; - de->u.fcb.ops = NULL; - de->u.fcb.auto_owner = FALSE; - de->u.fcb.aopen_notify = FALSE; - de->u.fcb.open = FALSE; - } - else if ( S_ISFIFO (mode) ) - { - de->u.fifo.uid = current->euid; - de->u.fifo.gid = current->egid; - } + printk ("%s: mknod(): existing entry\n", DEVFS_NAME); + return -EEXIST; + } + de->info = NULL; + de->mode = mode; + if ( S_ISBLK (mode) || S_ISCHR (mode) ) + { + de->u.fcb.u.device.major = MAJOR (rdev); + de->u.fcb.u.device.minor = MINOR (rdev); + de->u.fcb.default_uid = current->euid; + de->u.fcb.default_gid = current->egid; + de->u.fcb.ops = NULL; + de->u.fcb.auto_owner = FALSE; + de->u.fcb.aopen_notify = FALSE; + de->u.fcb.open = FALSE; + } + else if ( S_ISFIFO (mode) ) + { + de->u.fifo.uid = current->euid; + de->u.fifo.gid = current->egid; } - de->show_unreg = FALSE; de->hide = FALSE; de->inode.mode = mode; de->inode.uid = current->euid; diff -urN linux-2.4.9/fs/devfs/util.c linux/fs/devfs/util.c --- linux-2.4.9/fs/devfs/util.c Wed Jul 11 15:55:41 2001 +++ linux/fs/devfs/util.c Sat Aug 18 00:11:22 2001 @@ -39,6 +39,15 @@ Created and . 20010710 Richard Gooch Created . + 20010730 Richard Gooch + Documentation typo fix. + 20010806 Richard Gooch + Made and private. + 20010813 Richard Gooch + Fixed bug in : limited to 128 numbers + 20010818 Richard Gooch + Updated major masks up to Linus' "no new majors" proclamation. + Block: were 126 now 122 free, char: were 26 now 19 free. */ #include #include @@ -181,15 +190,15 @@ }; /* Block majors already assigned: - 0-3, 7-9, 11-12, 13-63, 65-93, 95-99, 101, 103-111, 120-127, 199, 201, - 240-255 + 0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255 + Total free: 122 */ static struct major_list block_major_list = {SPIN_LOCK_UNLOCKED, {0xfffffb8f, /* Majors 0 to 31 */ 0xffffffff, /* Majors 32 to 63 */ - 0xbffffffe, /* Majors 64 to 95 */ - 0xff00ffaf, /* Majors 96 to 127 */ + 0xfffffffe, /* Majors 64 to 95 */ + 0xff03ffef, /* Majors 96 to 127 */ 0x00000000, /* Majors 128 to 159 */ 0x00000000, /* Majors 160 to 191 */ 0x00000280, /* Majors 192 to 223 */ @@ -197,7 +206,8 @@ }; /* Char majors already assigned: - 0-7, 9-151, 154-158, 160-195, 198-211, 216-221, 224-225, 240-255 + 0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255 + Total free: 19 */ static struct major_list char_major_list = {SPIN_LOCK_UNLOCKED, @@ -207,14 +217,14 @@ 0xffffffff, /* Majors 96 to 127 */ 0x7cffffff, /* Majors 128 to 159 */ 0xffffffff, /* Majors 160 to 191 */ - 0x3f0fffcf, /* Majors 192 to 223 */ - 0xffff0003} /* Majors 224 to 255 */ + 0x3f0fffff, /* Majors 192 to 223 */ + 0xffff007f} /* Majors 224 to 255 */ }; /** * 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 +248,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. */ @@ -273,16 +283,16 @@ int none_free; }; -DECLARE_MUTEX (block_semaphore); +static DECLARE_MUTEX (block_semaphore); static struct device_list block_list; -DECLARE_MUTEX (char_semaphore); +static DECLARE_MUTEX (char_semaphore); static struct device_list char_list; /** * 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 +357,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. @@ -437,6 +447,7 @@ space->length = length; } number = find_first_zero_bit (space->bits, space->length << 3); + --space->num_free; __set_bit (number, space->bits); up (&space->semaphore); return number; diff -urN linux-2.4.9/include/linux/blk.h linux/include/linux/blk.h --- linux-2.4.9/include/linux/blk.h Wed Aug 15 15:21:32 2001 +++ linux/include/linux/blk.h Sat Aug 18 23:34:27 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) diff -urN linux-2.4.9/include/linux/devfs_fs.h linux/include/linux/devfs_fs.h --- linux-2.4.9/include/linux/devfs_fs.h Wed Feb 16 16:42:06 2000 +++ linux/include/linux/devfs_fs.h Fri Aug 17 22:11:39 2001 @@ -20,6 +20,7 @@ #define DEVFSD_NOTIFY_LOOKUP 4 #define DEVFSD_NOTIFY_CHANGE 5 #define DEVFSD_NOTIFY_CREATE 6 +#define DEVFSD_NOTIFY_DELETE 7 #define DEVFS_PATHLEN 1024 /* Never change this otherwise the binary interface will change */ diff -urN linux-2.4.9/include/linux/devfs_fs_kernel.h linux/include/linux/devfs_fs_kernel.h --- linux-2.4.9/include/linux/devfs_fs_kernel.h Fri Aug 17 22:20:00 2001 +++ linux/include/linux/devfs_fs_kernel.h Sat Aug 18 23:33:50 2001 @@ -30,17 +30,15 @@ is closed, ownership reverts back to <> and <> and the protection is set to read-write for all */ -#define DEVFS_FL_SHOW_UNREG 0x002 /* Show unregistered entries in - directory listings */ -#define DEVFS_FL_HIDE 0x004 /* Do not show entry in directory list */ -#define DEVFS_FL_AUTO_DEVNUM 0x008 /* Automatically generate device number +#define DEVFS_FL_HIDE 0x002 /* Do not show entry in directory list */ +#define DEVFS_FL_AUTO_DEVNUM 0x004 /* Automatically generate device number */ -#define DEVFS_FL_AOPEN_NOTIFY 0x010 /* Asynchronously notify devfsd on open +#define DEVFS_FL_AOPEN_NOTIFY 0x008 /* Asynchronously notify devfsd on open */ -#define DEVFS_FL_REMOVABLE 0x020 /* This is a removable media device */ -#define DEVFS_FL_WAIT 0x040 /* Wait for devfsd to finish */ -#define DEVFS_FL_NO_PERSISTENCE 0x080 /* Forget changes after unregister */ -#define DEVFS_FL_CURRENT_OWNER 0x100 /* Set initial ownership to current */ +#define DEVFS_FL_REMOVABLE 0x010 /* This is a removable media device */ +#define DEVFS_FL_WAIT 0x020 /* Wait for devfsd to finish */ +#define DEVFS_FL_NO_PERSISTENCE 0x040 /* Forget changes after unregister */ +#define DEVFS_FL_CURRENT_OWNER 0x080 /* Set initial ownership to current */ #define DEVFS_FL_DEFAULT DEVFS_FL_NONE