patch-2.4.19 linux-2.4.19/fs/super.c
Next file: linux-2.4.19/fs/udf/balloc.c
Previous file: linux-2.4.19/fs/smbfs/proc.c
Back to the patch index
Back to the overall index
- Lines: 766
- Date:
Fri Aug 2 17:39:45 2002
- Orig file:
linux-2.4.18/fs/super.c
- Orig date:
Mon Feb 25 11:38:09 2002
diff -urN linux-2.4.18/fs/super.c linux-2.4.19/fs/super.c
@@ -21,36 +21,19 @@
*/
#include <linux/config.h>
-#include <linux/string.h>
#include <linux/slab.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/fd.h>
-#include <linux/init.h>
#include <linux/major.h>
-#include <linux/quotaops.h>
#include <linux/acct.h>
#include <asm/uaccess.h>
-#include <linux/nfs_fs.h>
-#include <linux/nfs_fs_sb.h>
-#include <linux/nfs_mount.h>
-
#include <linux/kmod.h>
#define __NO_VERSION__
#include <linux/module.h>
-extern void wait_for_keypress(void);
-
-extern int root_mountflags;
-
-int do_remount_sb(struct super_block *sb, int flags, void * data);
-
-/* this is initialized in init/main.c */
-kdev_t ROOT_DEV;
-
LIST_HEAD(super_blocks);
spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
@@ -392,7 +375,7 @@
get_filesystem(type);
}
-void put_unnamed_dev(kdev_t dev); /* should become static */
+static void put_anon_dev(kdev_t dev);
/**
* remove_super - makes superblock unreachable
@@ -422,16 +405,11 @@
if (bdev)
blkdev_put(bdev, BDEV_FS);
else
- put_unnamed_dev(dev);
+ put_anon_dev(dev);
}
-struct vfsmount *alloc_vfsmnt(void);
+struct vfsmount *alloc_vfsmnt(char *name);
void free_vfsmnt(struct vfsmount *mnt);
-void set_devname(struct vfsmount *mnt, const char *name);
-
-/* Will go away */
-extern struct vfsmount *root_vfsmnt;
-extern int graft_tree(struct vfsmount *mnt, struct nameidata *nd);
static inline struct super_block * find_super(kdev_t dev)
{
@@ -549,35 +527,38 @@
return err;
}
-static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
- struct file_system_type *type, int flags,
- void *data)
+/**
+ * do_remount_sb - asks filesystem to change mount options.
+ * @sb: superblock in question
+ * @flags: numeric part of options
+ * @data: the rest of options
+ *
+ * Alters the mount options of a mounted file system.
+ */
+int do_remount_sb(struct super_block *sb, int flags, void *data)
{
- struct super_block * s;
- s = alloc_super();
- if (!s)
- goto out;
- s->s_dev = dev;
- s->s_bdev = bdev;
- s->s_flags = flags;
- spin_lock(&sb_lock);
- insert_super(s, type);
- lock_super(s);
- if (!type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
- goto out_fail;
- s->s_flags |= MS_ACTIVE;
- unlock_super(s);
- /* tell bdcache that we are going to keep this one */
- if (bdev)
- atomic_inc(&bdev->bd_count);
-out:
- return s;
-
-out_fail:
- unlock_super(s);
- deactivate_super(s);
- remove_super(s);
- return NULL;
+ int retval;
+
+ if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
+ return -EACCES;
+ /*flags |= MS_RDONLY;*/
+ if (flags & MS_RDONLY)
+ acct_auto_close(sb->s_dev);
+ shrink_dcache_sb(sb);
+ fsync_super(sb);
+ /* If we are remounting RDONLY, make sure there are no rw files open */
+ if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
+ if (!fs_may_remount_ro(sb))
+ return -EBUSY;
+ if (sb->s_op && sb->s_op->remount_fs) {
+ lock_super(sb);
+ retval = sb->s_op->remount_fs(sb, &flags, data);
+ unlock_super(sb);
+ if (retval)
+ return retval;
+ }
+ sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
+ return 0;
}
/*
@@ -585,31 +566,84 @@
* filesystems which don't use real block-devices. -- jrs
*/
-static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))];
+enum {Max_anon = 256};
+static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
+static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
-kdev_t get_unnamed_dev(void)
+/**
+ * put_anon_dev - release anonymous device number.
+ * @dev: device in question
+ */
+static void put_anon_dev(kdev_t dev)
{
- int i;
-
- for (i = 1; i < 256; i++) {
- if (!test_and_set_bit(i,unnamed_dev_in_use))
- return MKDEV(UNNAMED_MAJOR, i);
- }
- return 0;
+ spin_lock(&unnamed_dev_lock);
+ clear_bit(MINOR(dev), unnamed_dev_in_use);
+ spin_unlock(&unnamed_dev_lock);
}
-void put_unnamed_dev(kdev_t dev)
+/**
+ * get_anon_super - allocate a superblock for non-device fs
+ * @type: filesystem type
+ * @compare: check if existing superblock is what we want
+ * @data: argument for @compare.
+ *
+ * get_anon_super is a helper for non-blockdevice filesystems.
+ * It either finds and returns one of the superblocks of given type
+ * (if it can find one that would satisfy caller) or creates a new
+ * one. In the either case we return an active reference to superblock
+ * with ->s_umount locked. If superblock is new it gets a new
+ * anonymous device allocated for it and is inserted into lists -
+ * other initialization is left to caller.
+ *
+ * Rather than duplicating all that logics every time when
+ * we want something that doesn't fit "nodev" and "single" we pull
+ * the relevant code into common helper and let get_sb_...() call
+ * it.
+ *
+ * NB: get_sb_...() is going to become an fs type method, with
+ * current ->read_super() becoming a callback used by common instances.
+ */
+struct super_block *get_anon_super(struct file_system_type *type,
+ int (*compare)(struct super_block *,void *), void *data)
{
- if (!dev || MAJOR(dev) != UNNAMED_MAJOR)
- return;
- if (test_and_clear_bit(MINOR(dev), unnamed_dev_in_use))
- return;
- printk("VFS: put_unnamed_dev: freeing unused device %s\n",
- kdevname(dev));
+ struct super_block *s = alloc_super();
+ kdev_t dev;
+ struct list_head *p;
+
+ if (!s)
+ return ERR_PTR(-ENOMEM);
+
+retry:
+ spin_lock(&sb_lock);
+ if (compare) list_for_each(p, &type->fs_supers) {
+ struct super_block *old;
+ old = list_entry(p, struct super_block, s_instances);
+ if (!compare(old, data))
+ continue;
+ if (!grab_super(old))
+ goto retry;
+ destroy_super(s);
+ return old;
+ }
+
+ spin_lock(&unnamed_dev_lock);
+ dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
+ if (dev == Max_anon) {
+ spin_unlock(&unnamed_dev_lock);
+ spin_unlock(&sb_lock);
+ destroy_super(s);
+ return ERR_PTR(-EMFILE);
+ }
+ set_bit(dev, unnamed_dev_in_use);
+ spin_unlock(&unnamed_dev_lock);
+
+ s->s_dev = dev;
+ insert_super(s, type);
+ return s;
}
static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
- char *dev_name, int flags, void * data)
+ int flags, char *dev_name, void * data)
{
struct inode *inode;
struct block_device *bdev;
@@ -651,17 +685,13 @@
goto out;
check_disk_change(dev);
error = -EACCES;
- if (!(flags & MS_RDONLY) && is_read_only(dev)) {
- blkdev_put(bdev, BDEV_FS);
- goto out;
- }
+ if (!(flags & MS_RDONLY) && is_read_only(dev))
+ goto out1;
error = -ENOMEM;
s = alloc_super();
- if (!s) {
- blkdev_put(bdev, BDEV_FS);
- goto out;
- }
+ if (!s)
+ goto out1;
error = -EBUSY;
restart:
@@ -675,8 +705,7 @@
((flags ^ old->s_flags) & MS_RDONLY)) {
spin_unlock(&sb_lock);
destroy_super(s);
- blkdev_put(bdev, BDEV_FS);
- goto out;
+ goto out1;
}
if (!grab_super(old))
goto restart;
@@ -689,85 +718,102 @@
s->s_bdev = bdev;
s->s_flags = flags;
insert_super(s, fs_type);
-
- error = -EINVAL;
- lock_super(s);
if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
- goto out_fail;
+ goto Einval;
s->s_flags |= MS_ACTIVE;
- unlock_super(s);
path_release(&nd);
return s;
-out_fail:
- unlock_super(s);
+Einval:
deactivate_super(s);
remove_super(s);
+ error = -EINVAL;
+ goto out;
+out1:
+ blkdev_put(bdev, BDEV_FS);
out:
path_release(&nd);
return ERR_PTR(error);
}
static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
- int flags, void * data)
+ int flags, char *dev_name, void *data)
{
- kdev_t dev;
- int error = -EMFILE;
- dev = get_unnamed_dev();
- if (dev) {
- struct super_block * sb;
- error = -EINVAL;
- sb = read_super(dev, NULL, fs_type, flags, data);
- if (sb)
- return sb;
+ struct super_block *s = get_anon_super(fs_type, NULL, NULL);
+
+ if (IS_ERR(s))
+ return s;
+
+ s->s_flags = flags;
+ if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+ deactivate_super(s);
+ remove_super(s);
+ return ERR_PTR(-EINVAL);
}
- return ERR_PTR(error);
+ s->s_flags |= MS_ACTIVE;
+ return s;
+}
+
+static int compare_single(struct super_block *s, void *p)
+{
+ return 1;
}
static struct super_block *get_sb_single(struct file_system_type *fs_type,
- int flags, void *data)
+ int flags, char *dev_name, void *data)
{
- struct super_block * s = alloc_super();
- if (!s)
- return ERR_PTR(-ENOMEM);
- /*
- * Get the superblock of kernel-wide instance, but
- * keep the reference to fs_type.
- */
-retry:
- spin_lock(&sb_lock);
- if (!list_empty(&fs_type->fs_supers)) {
- struct super_block *old;
- old = list_entry(fs_type->fs_supers.next, struct super_block,
- s_instances);
- if (!grab_super(old))
- goto retry;
- destroy_super(s);
- do_remount_sb(old, flags, data);
- return old;
- } else {
- kdev_t dev = get_unnamed_dev();
- if (!dev) {
- spin_unlock(&sb_lock);
- destroy_super(s);
- return ERR_PTR(-EMFILE);
- }
- s->s_dev = dev;
+ struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
+
+ if (IS_ERR(s))
+ return s;
+ if (!s->s_root) {
s->s_flags = flags;
- insert_super(s, fs_type);
- lock_super(s);
- if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
- goto out_fail;
+ if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+ deactivate_super(s);
+ remove_super(s);
+ return ERR_PTR(-EINVAL);
+ }
s->s_flags |= MS_ACTIVE;
- unlock_super(s);
- return s;
-
- out_fail:
- unlock_super(s);
- deactivate_super(s);
- remove_super(s);
- return ERR_PTR(-EINVAL);
}
+ do_remount_sb(s, flags, data);
+ return s;
+}
+
+struct vfsmount *
+do_kern_mount(const char *fstype, int flags, char *name, void *data)
+{
+ struct file_system_type *type = get_fs_type(fstype);
+ struct super_block *sb = ERR_PTR(-ENOMEM);
+ struct vfsmount *mnt;
+
+ if (!type)
+ return ERR_PTR(-ENODEV);
+
+ mnt = alloc_vfsmnt(name);
+ if (!mnt)
+ goto out;
+ if (type->fs_flags & FS_REQUIRES_DEV)
+ sb = get_sb_bdev(type, flags, name, data);
+ else if (type->fs_flags & FS_SINGLE)
+ sb = get_sb_single(type, flags, name, data);
+ else
+ sb = get_sb_nodev(type, flags, name, data);
+ if (IS_ERR(sb))
+ goto out_mnt;
+ if (type->fs_flags & FS_NOMOUNT)
+ sb->s_flags |= MS_NOUSER;
+ mnt->mnt_sb = sb;
+ mnt->mnt_root = dget(sb->s_root);
+ mnt->mnt_mountpoint = sb->s_root;
+ mnt->mnt_parent = mnt;
+ up_write(&sb->s_umount);
+ put_filesystem(type);
+ return mnt;
+out_mnt:
+ free_vfsmnt(mnt);
+out:
+ put_filesystem(type);
+ return (struct vfsmount *)sb;
}
void kill_super(struct super_block *sb)
@@ -780,7 +826,6 @@
return;
down_write(&sb->s_umount);
- lock_kernel();
sb->s_root = NULL;
/* Need to clean after the sucker */
if (fs->fs_flags & FS_LITTER)
@@ -789,6 +834,7 @@
dput(root);
fsync_super(sb);
lock_super(sb);
+ lock_kernel();
sb->s_flags &= ~MS_ACTIVE;
invalidate_inodes(sb); /* bad name - it should be evict_inodes() */
if (sop) {
@@ -800,7 +846,7 @@
/* Forget any remaining inodes */
if (invalidate_inodes(sb)) {
- printk("VFS: Busy inodes after unmount. "
+ printk(KERN_ERR "VFS: Busy inodes after unmount. "
"Self-destruct in 5 seconds. Have a nice day...\n");
}
@@ -809,313 +855,7 @@
remove_super(sb);
}
-/*
- * Alters the mount flags of a mounted file system. Only the mount point
- * is used as a reference - file system type and the device are ignored.
- */
-
-int do_remount_sb(struct super_block *sb, int flags, void *data)
-{
- int retval;
-
- if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
- return -EACCES;
- /*flags |= MS_RDONLY;*/
- if (flags & MS_RDONLY)
- acct_auto_close(sb->s_dev);
- shrink_dcache_sb(sb);
- fsync_super(sb);
- /* If we are remounting RDONLY, make sure there are no rw files open */
- if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
- if (!fs_may_remount_ro(sb))
- return -EBUSY;
- if (sb->s_op && sb->s_op->remount_fs) {
- lock_super(sb);
- retval = sb->s_op->remount_fs(sb, &flags, data);
- unlock_super(sb);
- if (retval)
- return retval;
- }
- sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
-
- /*
- * We can't invalidate inodes as we can loose data when remounting
- * (someone might manage to alter data while we are waiting in lock_super()
- * or in foo_remount_fs()))
- */
-
- return 0;
-}
-
-struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data)
-{
- struct file_system_type * fstype;
- struct vfsmount *mnt = NULL;
- struct super_block *sb;
-
- if (!type || !memchr(type, 0, PAGE_SIZE))
- return ERR_PTR(-EINVAL);
-
- /* we need capabilities... */
- if (!capable(CAP_SYS_ADMIN))
- return ERR_PTR(-EPERM);
-
- /* ... filesystem driver... */
- fstype = get_fs_type(type);
- if (!fstype)
- return ERR_PTR(-ENODEV);
-
- /* ... allocated vfsmount... */
- mnt = alloc_vfsmnt();
- if (!mnt) {
- mnt = ERR_PTR(-ENOMEM);
- goto fs_out;
- }
- set_devname(mnt, name);
- /* get locked superblock */
- if (fstype->fs_flags & FS_REQUIRES_DEV)
- sb = get_sb_bdev(fstype, name, flags, data);
- else if (fstype->fs_flags & FS_SINGLE)
- sb = get_sb_single(fstype, flags, data);
- else
- sb = get_sb_nodev(fstype, flags, data);
-
- if (IS_ERR(sb)) {
- free_vfsmnt(mnt);
- mnt = (struct vfsmount *)sb;
- goto fs_out;
- }
- if (fstype->fs_flags & FS_NOMOUNT)
- sb->s_flags |= MS_NOUSER;
-
- mnt->mnt_sb = sb;
- mnt->mnt_root = dget(sb->s_root);
- mnt->mnt_mountpoint = mnt->mnt_root;
- mnt->mnt_parent = mnt;
- up_write(&sb->s_umount);
-fs_out:
- put_filesystem(fstype);
- return mnt;
-}
-
struct vfsmount *kern_mount(struct file_system_type *type)
{
- return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL);
-}
-
-static char * __initdata root_mount_data;
-static int __init root_data_setup(char *str)
-{
- root_mount_data = str;
- return 1;
-}
-
-static char * __initdata root_fs_names;
-static int __init fs_names_setup(char *str)
-{
- root_fs_names = str;
- return 1;
-}
-
-__setup("rootflags=", root_data_setup);
-__setup("rootfstype=", fs_names_setup);
-
-static void __init get_fs_names(char *page)
-{
- char *s = page;
-
- if (root_fs_names) {
- strcpy(page, root_fs_names);
- while (*s++) {
- if (s[-1] == ',')
- s[-1] = '\0';
- }
- } else {
- int len = get_filesystem_list(page);
- char *p, *next;
-
- page[len] = '\0';
- for (p = page-1; p; p = next) {
- next = strchr(++p, '\n');
- if (*p++ != '\t')
- continue;
- while ((*s++ = *p++) != '\n')
- ;
- s[-1] = '\0';
- }
- }
- *s = '\0';
-}
-
-void __init mount_root(void)
-{
- struct nameidata root_nd;
- struct super_block * sb;
- struct vfsmount *vfsmnt;
- struct block_device *bdev = NULL;
- mode_t mode;
- int retval;
- void *handle;
- char path[64];
- int path_start = -1;
- char *name = "/dev/root";
- char *fs_names, *p;
-#ifdef CONFIG_ROOT_NFS
- void *data;
-#endif
- root_mountflags |= MS_VERBOSE;
-
-#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) != UNNAMED_MAJOR)
- goto skip_nfs;
- data = nfs_root_data();
- if (!data)
- goto no_nfs;
- vfsmnt = do_kern_mount("nfs", root_mountflags, "/dev/root", data);
- if (!IS_ERR(vfsmnt)) {
- printk ("VFS: Mounted root (%s filesystem).\n", "nfs");
- ROOT_DEV = vfsmnt->mnt_sb->s_dev;
- goto attach_it;
- }
-no_nfs:
- printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
- ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-skip_nfs:
-#endif
-
-#ifdef CONFIG_BLK_DEV_FD
- if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
-#ifdef CONFIG_BLK_DEV_RAM
- extern int rd_doload;
- extern void rd_load_secondary(void);
-#endif
- floppy_eject();
-#ifndef CONFIG_BLK_DEV_RAM
- printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
-#else
- /* rd_doload is 2 for a dual initrd/ramload setup */
- if(rd_doload==2)
- rd_load_secondary();
- else
-#endif
- {
- printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
- wait_for_keypress();
- }
- }
-#endif
-
- fs_names = __getname();
- get_fs_names(fs_names);
-
- devfs_make_root (root_device_name);
- handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,
- MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
- DEVFS_SPECIAL_BLK, 1);
- if (handle) /* Sigh: bd*() functions only paper over the cracks */
- {
- unsigned major, minor;
-
- devfs_get_maj_min (handle, &major, &minor);
- ROOT_DEV = MKDEV (major, minor);
- }
-
- /*
- * Probably pure paranoia, but I'm less than happy about delving into
- * devfs crap and checking it right now. Later.
- */
- if (!ROOT_DEV)
- panic("I have no root and I want to scream");
-
-retry:
- bdev = bdget(kdev_t_to_nr(ROOT_DEV));
- if (!bdev)
- panic(__FUNCTION__ ": unable to allocate root device");
- bdev->bd_op = devfs_get_ops (handle); /* Increments module use count */
- path_start = devfs_generate_path (handle, path + 5, sizeof (path) - 5);
- mode = FMODE_READ;
- if (!(root_mountflags & MS_RDONLY))
- mode |= FMODE_WRITE;
- retval = blkdev_get(bdev, mode, 0, BDEV_FS);
- devfs_put_ops (handle); /* Decrement module use count now we're safe */
- if (retval == -EROFS) {
- root_mountflags |= MS_RDONLY;
- goto retry;
- }
- if (retval) {
- /*
- * Allow the user to distinguish between failed open
- * and bad superblock on root device.
- */
-Eio:
- printk ("VFS: Cannot open root device \"%s\" or %s\n",
- root_device_name, kdevname (ROOT_DEV));
- printk ("Please append a correct \"root=\" boot option\n");
- panic("VFS: Unable to mount root fs on %s",
- kdevname(ROOT_DEV));
- }
-
- check_disk_change(ROOT_DEV);
- sb = get_super(ROOT_DEV);
- if (sb) {
- /* FIXME */
- p = (char *)sb->s_type->name;
- atomic_inc(&sb->s_active);
- up_read(&sb->s_umount);
- down_write(&sb->s_umount);
- goto mount_it;
- }
-
- for (p = fs_names; *p; p += strlen(p)+1) {
- struct file_system_type * fs_type = get_fs_type(p);
- if (!fs_type)
- continue;
- atomic_inc(&bdev->bd_count);
- retval = blkdev_get(bdev, mode, 0, BDEV_FS);
- if (retval)
- goto Eio;
- sb = read_super(ROOT_DEV, bdev, fs_type,
- root_mountflags, root_mount_data);
- put_filesystem(fs_type);
- if (sb) {
- blkdev_put(bdev, BDEV_FS);
- goto mount_it;
- }
- }
- panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
-
-mount_it:
- /* FIXME */
- up_write(&sb->s_umount);
- printk ("VFS: Mounted root (%s filesystem)%s.\n", p,
- (sb->s_flags & MS_RDONLY) ? " readonly" : "");
- putname(fs_names);
- if (path_start >= 0) {
- name = path + path_start;
- devfs_unregister (devfs_find_handle(NULL, "root", 0, 0, 0, 0));
- devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
- name + 5, NULL, NULL);
- memcpy (name, "/dev/", 5);
- }
- vfsmnt = alloc_vfsmnt();
- if (!vfsmnt)
- panic("VFS: alloc_vfsmnt failed for root fs");
-
- set_devname(vfsmnt, name);
- vfsmnt->mnt_sb = sb;
- vfsmnt->mnt_root = dget(sb->s_root);
- bdput(bdev); /* sb holds a reference */
-
-
-#ifdef CONFIG_ROOT_NFS
-attach_it:
-#endif
- root_nd.mnt = root_vfsmnt;
- root_nd.dentry = root_vfsmnt->mnt_sb->s_root;
- graft_tree(vfsmnt, &root_nd);
-
- set_fs_root(current->fs, vfsmnt, vfsmnt->mnt_root);
- set_fs_pwd(current->fs, vfsmnt, vfsmnt->mnt_root);
-
- mntput(vfsmnt);
+ return do_kern_mount(type->name, 0, (char *)type->name, NULL);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)