diff -urN stock/linux-2.1.91-pre1/Documentation/Configure.help linux-2.1.91-pre1/Documentation/Configure.help --- stock/linux-2.1.91-pre1/Documentation/Configure.help Thu Mar 26 01:42:47 1998 +++ linux-2.1.91-pre1/Documentation/Configure.help Thu Mar 26 01:46:34 1998 @@ -5422,6 +5422,13 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. +/dev/pts filesystem +CONFIG_DEVPTS_FS + A filesystem which when mounted on /dev/pts and used in conjunction + with the /dev/ptmx multiplexing pty device, should allow full + support for Unix98 pty's without requiring setuid or daemons. glibc + 2.1 contains the requisite support for this mode of operation. + Macintosh partition map support CONFIG_MAC_PARTITION Say Y here if you want your Linux system to be able to read the diff -urN stock/linux-2.1.91-pre1/drivers/char/Makefile linux-2.1.91-pre1/drivers/char/Makefile --- stock/linux-2.1.91-pre1/drivers/char/Makefile Mon Jan 12 14:46:16 1998 +++ linux-2.1.91-pre1/drivers/char/Makefile Tue Mar 24 17:34:41 1998 @@ -20,7 +20,8 @@ L_TARGET := char.a M_OBJS := -L_OBJS := tty_io.o n_tty.o tty_ioctl.o pty.o mem.o random.o +L_OBJS := tty_io.o n_tty.o tty_ioctl.o mem.o random.o +LX_OBJS := pty.o ifdef CONFIG_VT L_OBJS += console.o vt.o vc_screen.o consolemap.o consolemap_deftbl.o diff -urN stock/linux-2.1.91-pre1/drivers/char/pty.c linux-2.1.91-pre1/drivers/char/pty.c --- stock/linux-2.1.91-pre1/drivers/char/pty.c Thu Feb 12 16:25:04 1998 +++ linux-2.1.91-pre1/drivers/char/pty.c Tue Mar 24 20:33:04 1998 @@ -7,6 +7,9 @@ * -- C. Scott Ananian , 14-Jan-1998 */ +#include +#include /* For EXPORT_SYMBOL */ + #include #include #include @@ -43,6 +46,37 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) +#ifdef CONFIG_DEVPTS_FS +#define DEVPTS 1 + +extern void devpts_pty_new(int); +extern void devpts_pty_kill(int); + +#elif defined(CONFIG_DEVPTS_FS_MODULE) +#define DEVPTS 1 +/* + * This is a hack so we can install/deinstall the devpts notification. + */ +typedef void (*upcall)(int); + +upcall upcall_devpts_new = NULL; +upcall upcall_devpts_kill = NULL; + +void register_devpts_upcall(upcall new, upcall kill) +{ + upcall_devpts_new = new; + upcall_devpts_kill = kill; +} + +EXPORT_SYMBOL(register_devpts_upcall); + +#define devpts_pty_new(X) (upcall_devpts_new ? upcall_devpts_new(X) : (void)0) +#define devpts_pty_kill(X) (upcall_devpts_kill ? upcall_devpts_kill(X) : (void)0) +#else +#define devpts_pty_new(X) ((void) 0) +#define devpts_pty_kill(X) ((void) 0) +#endif + static void pty_close(struct tty_struct * tty, struct file * filp) { if (!tty) @@ -66,6 +100,7 @@ if (tty->driver.subtype == PTY_TYPE_MASTER) { tty_hangup(tty->link); set_bit(TTY_OTHER_CLOSED, &tty->flags); + devpts_pty_kill(MINOR(tty->device) - tty->driver.minor_start); } } @@ -275,6 +310,7 @@ clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&pty->open_wait); set_bit(TTY_THROTTLED, &tty->flags); + devpts_pty_new(line); retval = 0; out: return retval; @@ -288,6 +324,11 @@ __initfunc(int pty_init(void)) { + +#ifdef CONFIG_DEVPTS_FS + init_devpts_fs(); +#endif + memset(&pty_state, 0, sizeof(pty_state)); memset(&pty_driver, 0, sizeof(struct tty_driver)); pty_driver.magic = TTY_DRIVER_MAGIC; @@ -363,6 +404,5 @@ panic("Couldn't register compat pty driver"); if (tty_register_driver(&old_pty_slave_driver)) panic("Couldn't register compat pty slave driver"); - return 0; } diff -urN stock/linux-2.1.91-pre1/fs/Config.in linux-2.1.91-pre1/fs/Config.in --- stock/linux-2.1.91-pre1/fs/Config.in Fri Mar 6 10:03:04 1998 +++ linux-2.1.91-pre1/fs/Config.in Tue Mar 24 17:34:41 1998 @@ -74,6 +74,7 @@ fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS + tristate '/dev/pts filesystem support (EXPERIMENTAL)' CONFIG_DEVPTS_FS fi bool 'Macintosh partition map support' CONFIG_MAC_PARTITION endmenu diff -urN stock/linux-2.1.91-pre1/fs/Makefile linux-2.1.91-pre1/fs/Makefile --- stock/linux-2.1.91-pre1/fs/Makefile Tue Jan 20 16:44:57 1998 +++ linux-2.1.91-pre1/fs/Makefile Tue Mar 24 17:34:41 1998 @@ -17,7 +17,8 @@ MOD_LIST_NAME := FS_MODULES ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \ - hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd nls + hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \ + nls devpts ifeq ($(CONFIG_QUOTA),y) O_OBJS += dquot.o @@ -223,6 +224,14 @@ else ifeq ($(CONFIG_ADFS_FS),m) MOD_SUB_DIRS += adfs + endif +endif + +ifeq ($(CONFIG_DEVPTS_FS),y) +SUB_DIRS += devpts +else + ifeq ($(CONFIG_DEVPTS_FS),m) + MOD_SUB_DIRS += devpts endif endif diff -urN stock/linux-2.1.91-pre1/fs/adfs/super.c linux-2.1.91-pre1/fs/adfs/super.c --- stock/linux-2.1.91-pre1/fs/adfs/super.c Thu Feb 19 14:46:15 1998 +++ linux-2.1.91-pre1/fs/adfs/super.c Tue Mar 24 17:34:41 1998 @@ -100,11 +100,11 @@ int i; lock_super (sb); sb->s_dev = 0; + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) brelse (sb->u.adfs_sb.s_map[i]); kfree (sb->u.adfs_sb.s_map); brelse (sb->u.adfs_sb.s_sbh); - unlock_super (sb); MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/autofs/inode.c linux-2.1.91-pre1/fs/autofs/inode.c --- stock/linux-2.1.91-pre1/fs/autofs/inode.c Fri Aug 15 10:01:29 1997 +++ linux-2.1.91-pre1/fs/autofs/inode.c Tue Mar 24 17:34:41 1998 @@ -42,15 +42,15 @@ autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ lock_super(sb); + sb->s_dev = 0; + autofs_hash_nuke(&sbi->dirhash); for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { if ( test_bit(n, sbi->symlink_bitmap) ) kfree(sbi->symlink[n].data); } - sb->s_dev = 0; kfree(sb->u.generic_sbp); - unlock_super(sb); DPRINTK(("autofs: shutting down\n")); diff -urN stock/linux-2.1.91-pre1/fs/coda/inode.c linux-2.1.91-pre1/fs/coda/inode.c --- stock/linux-2.1.91-pre1/fs/coda/inode.c Tue Mar 17 21:19:05 1998 +++ linux-2.1.91-pre1/fs/coda/inode.c Tue Mar 24 17:34:41 1998 @@ -162,8 +162,8 @@ ENTRY; lock_super(sb); - sb->s_dev = 0; + coda_cache_clear_all(sb); sb_info = coda_sbp(sb); sb_info->sbi_vcomm->vc_inuse = 0; @@ -171,7 +171,6 @@ printk("Coda: Bye bye.\n"); memset(sb_info, 0, sizeof(* sb_info)); - unlock_super(sb); MOD_DEC_USE_COUNT; EXIT; } diff -urN stock/linux-2.1.91-pre1/fs/devpts/Makefile linux-2.1.91-pre1/fs/devpts/Makefile --- stock/linux-2.1.91-pre1/fs/devpts/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.1.91-pre1/fs/devpts/Makefile Tue Mar 24 17:34:41 1998 @@ -0,0 +1,10 @@ +# +# Makefile for the linux /dev/pts virtual filesystem. +# + +O_TARGET := devpts.o +O_OBJS := root.o inode.o + +M_OBJS := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -urN stock/linux-2.1.91-pre1/fs/devpts/devpts_i.h linux-2.1.91-pre1/fs/devpts/devpts_i.h --- stock/linux-2.1.91-pre1/fs/devpts/devpts_i.h Wed Dec 31 16:00:00 1969 +++ linux-2.1.91-pre1/fs/devpts/devpts_i.h Tue Mar 24 17:53:03 1998 @@ -0,0 +1,44 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/devpts_i.h + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include +#include +#include + +struct devpts_sb_info { + u32 magic; + struct super_block *next; + struct super_block **back; + int setuid; + int setgid; + uid_t uid; + gid_t gid; + umode_t mode; + + struct inode *inodes[NR_PTYS]; +}; + +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define DEVPTS_SBI_MAGIC 0x01da1d02 + +extern inline struct devpts_sb_info *SBI(struct super_block *sb) +{ + return (struct devpts_sb_info *)(sb->u.generic_sbp); +} + +extern struct inode_operations devpts_root_inode_operations; +extern struct inode_operations devpts_device_inode_operations; + +/* Defined in drivers/char/pty.c; this is our link to reality */ +typedef void (*upcall)(int); +extern void register_devpts_upcall(upcall new, upcall kill); + diff -urN stock/linux-2.1.91-pre1/fs/devpts/inode.c linux-2.1.91-pre1/fs/devpts/inode.c --- stock/linux-2.1.91-pre1/fs/devpts/inode.c Wed Dec 31 16:00:00 1969 +++ linux-2.1.91-pre1/fs/devpts/inode.c Tue Mar 24 20:38:44 1998 @@ -0,0 +1,374 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/inode.c + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devpts_i.h" + +static struct super_block *mounts = NULL; + +static void devpts_put_inode(struct inode *inode) +{ +} + +static void devpts_delete_inode(struct inode *inode) +{ + inode->i_size = 0; +} + +static void devpts_put_super(struct super_block *sb) +{ + struct devpts_sb_info *sbi = SBI(sb); + struct inode *inode; + int i; + + for ( i = 0 ; i < NR_PTYS ; i++ ) { + if ( (inode = sbi->inodes[i]) ) { + if ( inode->i_count != 1 ) + printk("devpts_put_super: badness: entry %d count %d\n", + i, inode->i_count); + iput(inode); + } + } + + lock_super(sb); + sb->s_dev = 0; + + *sbi->back = sbi->next; + if ( sbi->next ) + SBI(sbi->next)->back = sbi->back; + + kfree(sbi); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static void devpts_read_inode(struct inode *inode); +static void devpts_write_inode(struct inode *inode); + +static struct super_operations devpts_sops = { + devpts_read_inode, + devpts_write_inode, + devpts_put_inode, + devpts_delete_inode, + NULL, /* notify_change */ + devpts_put_super, + NULL, /* write_super */ + devpts_statfs, + NULL, /* remount_fs */ + NULL, /* clear_inode */ +}; + +static int devpts_parse_options(char *options, struct devpts_sb_info *sbi) +{ + int setuid = 0; + int setgid = 0; + uid_t uid = 0; /* To shut up gcc */ + gid_t gid = 0; + umode_t mode = 0600; + char *this_char, *value; + + if ( !options ) return 1; + for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + if (!strcmp(this_char,"uid")) { + if (!value || !*value) + return 1; + uid = simple_strtoul(value,&value,0); + if (*value) + return 1; + setuid = 1; + } + else if (!strcmp(this_char,"gid")) { + if (!value || !*value) + return 1; + gid = simple_strtoul(value,&value,0); + if (*value) + return 1; + setgid = 1; + } + else if (!strcmp(this_char,"mode")) { + if (!value || !*value) + return 1; + mode = simple_strtoul(value,&value,8); + if (*value) + return 1; + } + else + return 1; + } + sbi->setuid = setuid; + sbi->setgid = setgid; + sbi->uid = uid; + sbi->gid = gid; + sbi->mode = mode & ~S_IFMT; + + return 0; +} + +struct super_block *devpts_read_super(struct super_block *s, void *data, + int silent) +{ + struct inode * root_inode; + struct dentry * root; + struct devpts_sb_info *sbi; + + MOD_INC_USE_COUNT; + + lock_super(s); + /* Super block already completed? */ + if (s->s_root) + goto out_unlock; + + sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL); + if ( !sbi ) + goto fail_unlock; + + sbi->magic = DEVPTS_SBI_MAGIC; + memset(sbi->inodes, 0, sizeof sbi->inodes); + + s->u.generic_sbp = (void *) sbi; + s->s_blocksize = 1024; + s->s_blocksize_bits = 10; + s->s_magic = DEVPTS_SUPER_MAGIC; + s->s_op = &devpts_sops; + s->s_root = NULL; + unlock_super(s); /* shouldn't we keep it locked a while longer? */ + + /* + * Get the root inode and dentry, but defer checking for errors. + */ + root_inode = iget(s, 1); /* inode 1 == root directory */ + root = d_alloc_root(root_inode, NULL); + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dput; + + if (!root) + goto fail_iput; + + /* Can this call block? (It shouldn't) */ + if ( devpts_parse_options(data,sbi) ) { + printk("devpts: called with bogus options\n"); + goto fail_dput; + } + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dec; + + /* + * Success! Install the root dentry now to indicate completion. + */ + lock_super(s); + s->s_root = root; + + sbi->next = mounts; + if ( sbi->next ) + SBI(sbi->next)->back = &(sbi->next); + sbi->back = &mounts; + mounts = s; + + unlock_super(s); + return s; + + /* + * Success ... somebody else completed the super block for us. + */ +out_unlock: + unlock_super(s); + goto out_dec; +out_dput: + if (root) + dput(root); + else + iput(root_inode); +out_dec: + MOD_DEC_USE_COUNT; + return s; + + /* + * Failure ... clear the s_dev slot and clean up. + */ +fail_dput: + /* + * dput() can block, so we clear the super block first. + */ + s->s_dev = 0; + dput(root); + goto fail_free; +fail_iput: + printk("devpts: get root dentry failed\n"); + /* + * iput() can block, so we clear the super block first. + */ + s->s_dev = 0; + iput(root_inode); +fail_free: + kfree(sbi); + goto fail_dec; +fail_unlock: + unlock_super(s); +fail_dec: + s->s_dev = 0; + MOD_DEC_USE_COUNT; + return NULL; +} + +static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +{ + struct statfs tmp; + + tmp.f_type = DEVPTS_SUPER_MAGIC; + tmp.f_bsize = 1024; + tmp.f_blocks = 0; + tmp.f_bfree = 0; + tmp.f_bavail = 0; + tmp.f_files = 0; + tmp.f_ffree = 0; + tmp.f_namelen = NAME_MAX; + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; +} + +static void devpts_read_inode(struct inode *inode) +{ + ino_t ino = inode->i_ino; + + inode->i_op = NULL; + inode->i_mode = 0; + inode->i_nlink = 0; + inode->i_size = 0; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_blocks = 0; + inode->i_blksize = 1024; + inode->i_uid = inode->i_gid = 0; + + if ( ino == 1 ) { + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; + inode->i_op = &devpts_root_inode_operations; + inode->i_nlink = 2; + return; + } + + ino -= 2; + if ( ino >= NR_PTYS ) + return; /* Bogus */ + + inode->i_nlink = 1; + + inode->i_mode = S_IFCHR; + inode->i_rdev = MKDEV(PTY_SLAVE_MAJOR, ino); + + inode->i_op = &chrdev_inode_operations; + + return; +} + +static void devpts_write_inode(struct inode *inode) +{ +} + +static struct file_system_type devpts_fs_type = { + "devpts", + 0, + devpts_read_super, + NULL +}; + +void devpts_pty_new(int number) +{ + struct super_block *sb; + struct devpts_sb_info *sbi; + struct inode *inode; + + for ( sb = mounts ; sb ; sb = sbi->next ) { + sbi = SBI(sb); + + if ( sbi->inodes[number] ) { + continue; /* Already registered, this does happen */ + } + + /* Yes, this looks backwards, but it is correct */ + inode = iget(sb, number+2); + if ( inode ) { + inode->i_uid = sbi->setuid ? sbi->uid : current->uid; + inode->i_gid = sbi->setgid ? sbi->gid : current->gid; + inode->i_mode = sbi->mode | S_IFCHR; + sbi->inodes[number] = inode; + } + } +} + +void devpts_pty_kill(int number) +{ + struct super_block *sb; + struct devpts_sb_info *sbi; + struct inode *inode; + + for ( sb = mounts ; sb ; sb = sbi->next ) { + sbi = SBI(sb); + + inode = sbi->inodes[number]; + + if ( inode ) { + sbi->inodes[number] = NULL; + inode->i_nlink = 0; /* Is this right? */ + iput(inode); + } + } +} + +__initfunc(int init_devpts_fs(void)) +{ + return register_filesystem(&devpts_fs_type); + +} + +#ifdef MODULE + +int init_module(void) +{ + int err = init_devpts_fs(); + if ( !err ) { + register_devpts_upcall(devpts_pty_new, devpts_pty_kill); + } + return err; +} + +void cleanup_module(void) +{ + register_devpts_upcall(NULL, NULL); + unregister_filesystem(&devpts_fs_type); +} + +#endif diff -urN stock/linux-2.1.91-pre1/fs/devpts/root.c linux-2.1.91-pre1/fs/devpts/root.c --- stock/linux-2.1.91-pre1/fs/devpts/root.c Wed Dec 31 16:00:00 1969 +++ linux-2.1.91-pre1/fs/devpts/root.c Tue Mar 24 17:34:41 1998 @@ -0,0 +1,169 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/root.c + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include +#include +#include +#include "devpts_i.h" + +static int devpts_root_readdir(struct file *,void *,filldir_t); +static int devpts_root_lookup(struct inode *,struct dentry *); +static int devpts_revalidate(struct dentry *); + +static struct file_operations devpts_root_operations = { + NULL, /* llseek */ + NULL, /* read */ + NULL, /* write */ + devpts_root_readdir, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* open */ + NULL, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +struct inode_operations devpts_root_inode_operations = { + &devpts_root_operations, /* file operations */ + NULL, /* create */ + devpts_root_lookup, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL /* revalidate */ +}; + +static struct dentry_operations devpts_dentry_operations = { + devpts_revalidate, /* d_revalidate */ + NULL, /* d_hash */ + NULL, /* d_compare */ +}; + +/* + * The normal naming convention is simply /dev/pts/; this conforms + * to the System V naming convention + */ + +#define genptsname(buf,num) sprintf(buf, "%d", num) + +static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode * inode = filp->f_dentry->d_inode; + struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb); + off_t nr; + char numbuf[16]; + + if (!inode || !S_ISDIR(inode->i_mode)) + return -ENOTDIR; + + nr = filp->f_pos; + + switch(nr) + { + case 0: + if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) + return 0; + filp->f_pos = ++nr; + /* fall through */ + case 1: + if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) + return 0; + filp->f_pos = ++nr; + /* fall through */ + default: + while ( nr < NR_PTYS+2 ) { + int ptynr = nr - 2; + if ( sbi->inodes[ptynr] ) { + genptsname(numbuf, ptynr); + if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 ) + return 0; + } + filp->f_pos = ++nr; + } + break; + } + + return 0; +} + +/* + * Revalidate is called on every cache lookup. We use it to check that + * the pty really does still exist. Never revalidate negative dentries; + * for simplicity (fix later?) + */ +static int devpts_revalidate(struct dentry * dentry) +{ + struct devpts_sb_info *sbi; + + if ( !dentry->d_inode ) + return 0; + + sbi = SBI(dentry->d_inode->i_sb); + + return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode ); +} + +static int devpts_root_lookup(struct inode * dir, struct dentry * dentry) +{ + struct devpts_sb_info *sbi = SBI(dir->i_sb); + int entry, i; + const char *p; + + if (!S_ISDIR(dir->i_mode)) + return -ENOTDIR; + + dentry->d_inode = NULL; /* Assume failure */ + dentry->d_op = &devpts_dentry_operations; + + if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) { + entry = 0; + } else if ( dentry->d_name.len < 1 ) { + return 0; + } else { + p = dentry->d_name.name; + if ( *p < '1' || *p > '9' ) + return 0; + entry = *p++ - '0'; + + for ( i = dentry->d_name.len-1 ; i ; i-- ) { + if ( *p < '0' || *p > '9' ) + return 0; + entry *= 10; + entry += (*p++ - '0'); + } + } + + dentry->d_inode = sbi->inodes[entry]; + if ( dentry->d_inode ) + dentry->d_inode->i_count++; + + d_add(dentry, dentry->d_inode); + + return 0; +} diff -urN stock/linux-2.1.91-pre1/fs/ext2/super.c linux-2.1.91-pre1/fs/ext2/super.c --- stock/linux-2.1.91-pre1/fs/ext2/super.c Wed Jul 16 10:26:21 1997 +++ linux-2.1.91-pre1/fs/ext2/super.c Tue Mar 24 17:34:42 1998 @@ -126,7 +126,7 @@ if (sb->u.ext2_sb.s_block_bitmap[i]) brelse (sb->u.ext2_sb.s_block_bitmap[i]); brelse (sb->u.ext2_sb.s_sbh); - unlock_super (sb); + MOD_DEC_USE_COUNT; return; } diff -urN stock/linux-2.1.91-pre1/fs/fat/inode.c linux-2.1.91-pre1/fs/fat/inode.c --- stock/linux-2.1.91-pre1/fs/fat/inode.c Wed Jan 21 17:46:56 1998 +++ linux-2.1.91-pre1/fs/fat/inode.c Tue Mar 24 17:34:42 1998 @@ -100,7 +100,7 @@ MSDOS_SB(sb)->options.iocharset = NULL; } sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; return; } diff -urN stock/linux-2.1.91-pre1/fs/hfs/super.c linux-2.1.91-pre1/fs/hfs/super.c --- stock/linux-2.1.91-pre1/fs/hfs/super.c Wed Mar 11 20:22:05 1998 +++ linux-2.1.91-pre1/fs/hfs/super.c Tue Mar 24 17:34:42 1998 @@ -140,7 +140,6 @@ MOD_DEC_USE_COUNT; - unlock_super(sb); return; } diff -urN stock/linux-2.1.91-pre1/fs/hpfs/hpfs_fs.c linux-2.1.91-pre1/fs/hpfs/hpfs_fs.c --- stock/linux-2.1.91-pre1/fs/hpfs/hpfs_fs.c Tue Nov 18 10:36:45 1997 +++ linux-2.1.91-pre1/fs/hpfs/hpfs_fs.c Tue Mar 24 17:34:42 1998 @@ -733,7 +733,7 @@ { lock_super(s); s->s_dev = 0; - unlock_super(s); + MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/isofs/inode.c linux-2.1.91-pre1/fs/isofs/inode.c --- stock/linux-2.1.91-pre1/fs/isofs/inode.c Sat Feb 21 13:19:29 1998 +++ linux-2.1.91-pre1/fs/isofs/inode.c Tue Mar 24 17:34:42 1998 @@ -56,7 +56,7 @@ check_malloc, check_bread); #endif sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; return; } diff -urN stock/linux-2.1.91-pre1/fs/minix/inode.c linux-2.1.91-pre1/fs/minix/inode.c --- stock/linux-2.1.91-pre1/fs/minix/inode.c Wed Jan 21 14:27:57 1998 +++ linux-2.1.91-pre1/fs/minix/inode.c Tue Mar 24 17:34:42 1998 @@ -71,7 +71,7 @@ brelse (sb->u.minix_sb.s_sbh); kfree(sb->u.minix_sb.s_imap); sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; return; } diff -urN stock/linux-2.1.91-pre1/fs/ncpfs/inode.c linux-2.1.91-pre1/fs/ncpfs/inode.c --- stock/linux-2.1.91-pre1/fs/ncpfs/inode.c Tue Mar 17 11:53:16 1998 +++ linux-2.1.91-pre1/fs/ncpfs/inode.c Tue Mar 24 17:34:42 1998 @@ -425,7 +425,6 @@ ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); sb->s_dev = 0; - unlock_super(sb); MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/nfs/inode.c linux-2.1.91-pre1/fs/nfs/inode.c --- stock/linux-2.1.91-pre1/fs/nfs/inode.c Tue Mar 10 13:31:22 1998 +++ linux-2.1.91-pre1/fs/nfs/inode.c Tue Mar 24 17:34:42 1998 @@ -143,7 +143,7 @@ kfree(server->hostname); sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/ntfs/fs.c linux-2.1.91-pre1/fs/ntfs/fs.c --- stock/linux-2.1.91-pre1/fs/ntfs/fs.c Tue Mar 10 14:43:13 1998 +++ linux-2.1.91-pre1/fs/ntfs/fs.c Tue Mar 24 17:34:42 1998 @@ -698,7 +698,7 @@ vol=NTFS_SB2VOL(sb); /* Tell the kernel that the super block is no more used */ sb->s_dev = 0; - unlock_super(sb); + ntfs_release_volume(vol); if(vol->nls_map) unload_nls(vol->nls_map); diff -urN stock/linux-2.1.91-pre1/fs/proc/inode.c linux-2.1.91-pre1/fs/proc/inode.c --- stock/linux-2.1.91-pre1/fs/proc/inode.c Thu Mar 26 01:42:55 1998 +++ linux-2.1.91-pre1/fs/proc/inode.c Tue Mar 24 17:34:42 1998 @@ -84,7 +84,6 @@ { lock_super(sb); sb->s_dev = 0; - unlock_super(sb); } static struct super_operations proc_sops = { diff -urN stock/linux-2.1.91-pre1/fs/romfs/inode.c linux-2.1.91-pre1/fs/romfs/inode.c --- stock/linux-2.1.91-pre1/fs/romfs/inode.c Sat Feb 28 13:31:07 1998 +++ linux-2.1.91-pre1/fs/romfs/inode.c Tue Mar 24 17:34:42 1998 @@ -159,7 +159,7 @@ { lock_super(sb); sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; return; } diff -urN stock/linux-2.1.91-pre1/fs/smbfs/inode.c linux-2.1.91-pre1/fs/smbfs/inode.c --- stock/linux-2.1.91-pre1/fs/smbfs/inode.c Sat Feb 28 13:15:17 1998 +++ linux-2.1.91-pre1/fs/smbfs/inode.c Tue Mar 24 17:34:42 1998 @@ -339,8 +339,6 @@ smb_vfree(server->packet); sb->s_dev = 0; - unlock_super(sb); - MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/super.c linux-2.1.91-pre1/fs/super.c --- stock/linux-2.1.91-pre1/fs/super.c Tue Mar 10 14:43:13 1998 +++ linux-2.1.91-pre1/fs/super.c Tue Mar 24 17:34:42 1998 @@ -668,18 +668,25 @@ if (retval) goto out; - /* Forget any inodes */ - if (invalidate_inodes(sb)) { - printk("VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Bye-bye..\n"); - } - if (sb->s_op) { if (sb->s_op->write_super && sb->s_dirt) sb->s_op->write_super(sb); if (sb->s_op->put_super) sb->s_op->put_super(sb); } + + if ( !sb->s_lock ) + lock_super(sb); + + /* Forget any inodes */ + if (invalidate_inodes(sb)) { + printk("VFS: Busy inodes after unmount. " + "Self-destruct in 5 seconds. Have a nice day...\n"); + } + + sb->s_dev = 0; /* Free the superblock */ + unlock_super(sb); + remove_vfsmnt(dev); out: return retval; diff -urN stock/linux-2.1.91-pre1/fs/sysv/inode.c linux-2.1.91-pre1/fs/sysv/inode.c --- stock/linux-2.1.91-pre1/fs/sysv/inode.c Fri Feb 20 18:28:23 1998 +++ linux-2.1.91-pre1/fs/sysv/inode.c Tue Mar 24 17:34:42 1998 @@ -538,7 +538,7 @@ if (sb->s_blocksize != BLOCK_SIZE) set_blocksize(sb->s_dev,BLOCK_SIZE); sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; } diff -urN stock/linux-2.1.91-pre1/fs/ufs/ufs_super.c linux-2.1.91-pre1/fs/ufs/ufs_super.c --- stock/linux-2.1.91-pre1/fs/ufs/ufs_super.c Fri Feb 20 18:28:23 1998 +++ linux-2.1.91-pre1/fs/ufs/ufs_super.c Tue Mar 24 17:34:42 1998 @@ -343,7 +343,6 @@ /* XXX - free allocated kernel memory */ /* includes freeing usb page */ - unlock_super (sb); MOD_DEC_USE_COUNT; return;