!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/fs/   drwxr-xr-x
Free 318.36 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     super.c (26.1 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 *  linux/fs/super.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  super.c contains code to handle: - mount structures
 *                                   - super-block tables
 *                                   - filesystem drivers list
 *                                   - mount system call
 *                                   - umount system call
 *                                   - ustat system call
 *
 * GK 2/5/95  -  Changed to support mounting the root fs via NFS
 *
 *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
 *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
 *  Added options to /proc/mounts:
 *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
 *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
 *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
 */

#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;

/*
 * Handling of filesystem drivers list.
 * Rules:
 *    Inclusion to/removals from/scanning of list are protected by spinlock.
 *    During the unload module must call unregister_filesystem().
 *    We can access the fields of list element if:
 *        1) spinlock is held or
 *        2) we hold the reference to the module.
 *    The latter can be guaranteed by call of try_inc_mod_count(); if it
 *    returned 0 we must skip the element, otherwise we got the reference.
 *    Once the reference is obtained we can drop the spinlock.
 */

static struct file_system_type *file_systems;
static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;

/* WARNING: This can be used only if we _already_ own a reference */
static void get_filesystem(struct file_system_type *fs)
{
    if (fs->owner)
        __MOD_INC_USE_COUNT(fs->owner);
}

static void put_filesystem(struct file_system_type *fs)
{
    if (fs->owner)
        __MOD_DEC_USE_COUNT(fs->owner);
}

static struct file_system_type **find_filesystem(const char *name)
{
    struct file_system_type **p;
    for (p=&file_systems; *p; p=&(*p)->next)
        if (strcmp((*p)->name,name) == 0)
            break;
    return p;
}

/**
 *    register_filesystem - register a new filesystem
 *    @fs: the file system structure
 *
 *    Adds the file system passed to the list of file systems the kernel
 *    is aware of for mount and other syscalls. Returns 0 on success,
 *    or a negative errno code on an error.
 *
 *    The &struct file_system_type that is passed is linked into the kernel 
 *    structures and must not be freed until the file system has been
 *    unregistered.
 */
 
int register_filesystem(struct file_system_type * fs)
{
    int res = 0;
    struct file_system_type ** p;

    if (!fs)
        return -EINVAL;
    if (fs->next)
        return -EBUSY;
    INIT_LIST_HEAD(&fs->fs_supers);
    write_lock(&file_systems_lock);
    p = find_filesystem(fs->name);
    if (*p)
        res = -EBUSY;
    else
        *p = fs;
    write_unlock(&file_systems_lock);
    return res;
}

/**
 *    unregister_filesystem - unregister a file system
 *    @fs: filesystem to unregister
 *
 *    Remove a file system that was previously successfully registered
 *    with the kernel. An error is returned if the file system is not found.
 *    Zero is returned on a success.
 *    
 *    Once this function has returned the &struct file_system_type structure
 *    may be freed or reused.
 */
 
int unregister_filesystem(struct file_system_type * fs)
{
    struct file_system_type ** tmp;

    write_lock(&file_systems_lock);
    tmp = &file_systems;
    while (*tmp) {
        if (fs == *tmp) {
            *tmp = fs->next;
            fs->next = NULL;
            write_unlock(&file_systems_lock);
            return 0;
        }
        tmp = &(*tmp)->next;
    }
    write_unlock(&file_systems_lock);
    return -EINVAL;
}

static int fs_index(const char * __name)
{
    struct file_system_type * tmp;
    char * name;
    int err, index;

    name = getname(__name);
    err = PTR_ERR(name);
    if (IS_ERR(name))
        return err;

    err = -EINVAL;
    read_lock(&file_systems_lock);
    for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
        if (strcmp(tmp->name,name) == 0) {
            err = index;
            break;
        }
    }
    read_unlock(&file_systems_lock);
    putname(name);
    return err;
}

static int fs_name(unsigned int index, char * buf)
{
    struct file_system_type * tmp;
    int len, res;

    read_lock(&file_systems_lock);
    for (tmp = file_systems; tmp; tmp = tmp->next, index--)
        if (index <= 0 && try_inc_mod_count(tmp->owner))
                break;
    read_unlock(&file_systems_lock);
    if (!tmp)
        return -EINVAL;

    /* OK, we got the reference, so we can safely block */
    len = strlen(tmp->name) + 1;
    res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
    put_filesystem(tmp);
    return res;
}

static int fs_maxindex(void)
{
    struct file_system_type * tmp;
    int index;

    read_lock(&file_systems_lock);
    for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
        ;
    read_unlock(&file_systems_lock);
    return index;
}

/*
 * Whee.. Weird sysv syscall. 
 */
asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
{
    int retval = -EINVAL;

    switch (option) {
        case 1:
            retval = fs_index((const char *) arg1);
            break;

        case 2:
            retval = fs_name(arg1, (char *) arg2);
            break;

        case 3:
            retval = fs_maxindex();
            break;
    }
    return retval;
}

int get_filesystem_list(char * buf)
{
    int len = 0;
    struct file_system_type * tmp;

    read_lock(&file_systems_lock);
    tmp = file_systems;
    while (tmp && len < PAGE_SIZE - 80) {
        len += sprintf(buf+len, "%s\t%s\n",
            (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
            tmp->name);
        tmp = tmp->next;
    }
    read_unlock(&file_systems_lock);
    return len;
}

struct file_system_type *get_fs_type(const char *name)
{
    struct file_system_type *fs;
    
    read_lock(&file_systems_lock);
    fs = *(find_filesystem(name));
    if (fs && !try_inc_mod_count(fs->owner))
        fs = NULL;
    read_unlock(&file_systems_lock);
    if (!fs && (request_module(name) == 0)) {
        read_lock(&file_systems_lock);
        fs = *(find_filesystem(name));
        if (fs && !try_inc_mod_count(fs->owner))
            fs = NULL;
        read_unlock(&file_systems_lock);
    }
    return fs;
}

/**
 *    alloc_super    -    create new superblock
 *
 *    Allocates and initializes a new &struct super_block.  alloc_super()
 *    returns a pointer new superblock or %NULL if allocation had failed.
 */
static struct super_block *alloc_super(void)
{
    struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
    if (s) {
        memset(s, 0, sizeof(struct super_block));
        INIT_LIST_HEAD(&s->s_dirty);
        INIT_LIST_HEAD(&s->s_locked_inodes);
        INIT_LIST_HEAD(&s->s_files);
        INIT_LIST_HEAD(&s->s_instances);
        init_rwsem(&s->s_umount);
        sema_init(&s->s_lock, 1);
        down_write(&s->s_umount);
        s->s_count = S_BIAS;
        atomic_set(&s->s_active, 1);
        sema_init(&s->s_vfs_rename_sem,1);
        sema_init(&s->s_nfsd_free_path_sem,1);
        sema_init(&s->s_dquot.dqio_sem, 1);
        sema_init(&s->s_dquot.dqoff_sem, 1);
        s->s_maxbytes = MAX_NON_LFS;
        s->s_qop = sb_generic_quota_ops;
    }
    return s;
}

/**
 *    destroy_super    -    frees a superblock
 *    @s: superblock to free
 *
 *    Frees a superblock.
 */
static inline void destroy_super(struct super_block *s)
{
    kfree(s);
}

/* Superblock refcounting  */

/**
 *    deactivate_super    -    turn an active reference into temporary
 *    @s: superblock to deactivate
 *
 *    Turns an active reference into temporary one.  Returns 0 if there are
 *    other active references, 1 if we had deactivated the last one.
 */
static inline int deactivate_super(struct super_block *s)
{
    if (!atomic_dec_and_lock(&s->s_active, &sb_lock))
        return 0;
    s->s_count -= S_BIAS-1;
    spin_unlock(&sb_lock);
    return 1;
}

/**
 *    put_super    -    drop a temporary reference to superblock
 *    @s: superblock in question
 *
 *    Drops a temporary reference, frees superblock if there's no
 *    references left.
 */
static inline void put_super(struct super_block *s)
{
    spin_lock(&sb_lock);
    if (!--s->s_count)
        destroy_super(s);
    spin_unlock(&sb_lock);
}

/**
 *    grab_super    - acquire an active reference
 *    @s    - reference we are trying to make active
 *
 *    Tries to acquire an active reference.  grab_super() is used when we
 *     had just found a superblock in super_blocks or fs_type->fs_supers
 *    and want to turn it into a full-blown active reference.  grab_super()
 *    is called with sb_lock held and drops it.  Returns 1 in case of
 *    success, 0 if we had failed (superblock contents was already dead or
 *    dying when grab_super() had been called).
 */
static int grab_super(struct super_block *s)
{
    s->s_count++;
    spin_unlock(&sb_lock);
    down_write(&s->s_umount);
    if (s->s_root) {
        spin_lock(&sb_lock);
        if (s->s_count > S_BIAS) {
            atomic_inc(&s->s_active);
            s->s_count--;
            spin_unlock(&sb_lock);
            return 1;
        }
        spin_unlock(&sb_lock);
    }
    up_write(&s->s_umount);
    put_super(s);
    return 0;
}
 
/**
 *    insert_super    -    put superblock on the lists
 *    @s:    superblock in question
 *    @type:    filesystem type it will belong to
 *
 *    Associates superblock with fs type and puts it on per-type and global
 *    superblocks' lists.  Should be called with sb_lock held; drops it.
 */
static void insert_super(struct super_block *s, struct file_system_type *type)
{
    s->s_type = type;
    list_add(&s->s_list, super_blocks.prev);
    list_add(&s->s_instances, &type->fs_supers);
    spin_unlock(&sb_lock);
    get_filesystem(type);
}

void put_unnamed_dev(kdev_t dev);    /* should become static */

/**
 *    remove_super    -    makes superblock unreachable
 *    @s:    superblock in question
 *
 *    Removes superblock from the lists, unlocks it, drop the reference
 *    and releases the hosting device.  @s should have no active
 *    references by that time and after remove_super() it's essentially
 *    in rundown mode - all remaining references are temporary, no new
 *    reference of any sort are going to appear and all holders of
 *    temporary ones will eventually drop them.  At that point superblock
 *    itself will be destroyed; all its contents is already gone.
 */
static void remove_super(struct super_block *s)
{
    kdev_t dev = s->s_dev;
    struct block_device *bdev = s->s_bdev;
    struct file_system_type *fs = s->s_type;

    spin_lock(&sb_lock);
    list_del(&s->s_list);
    list_del(&s->s_instances);
    spin_unlock(&sb_lock);
    up_write(&s->s_umount);
    put_super(s);
    put_filesystem(fs);
    if (bdev)
        blkdev_put(bdev, BDEV_FS);
    else
        put_unnamed_dev(dev);
}

struct vfsmount *alloc_vfsmnt(void);
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)
{
    struct list_head *p;

    list_for_each(p, &super_blocks) {
        struct super_block * s = sb_entry(p);
        if (s->s_dev == dev) {
            s->s_count++;
            return s;
        }
    }
    return NULL;
}

void drop_super(struct super_block *sb)
{
    up_read(&sb->s_umount);
    put_super(sb);
}

static inline void write_super(struct super_block *sb)
{
    lock_super(sb);
    if (sb->s_root && sb->s_dirt)
        if (sb->s_op && sb->s_op->write_super)
            sb->s_op->write_super(sb);
    unlock_super(sb);
}

/*
 * Note: check the dirty flag before waiting, so we don't
 * hold up the sync while mounting a device. (The newly
 * mounted device won't need syncing.)
 */
void sync_supers(kdev_t dev)
{
    struct super_block * sb;

    if (dev) {
        sb = get_super(dev);
        if (sb) {
            if (sb->s_dirt)
                write_super(sb);
            drop_super(sb);
        }
        return;
    }
restart:
    spin_lock(&sb_lock);
    sb = sb_entry(super_blocks.next);
    while (sb != sb_entry(&super_blocks))
        if (sb->s_dirt) {
            sb->s_count++;
            spin_unlock(&sb_lock);
            down_read(&sb->s_umount);
            write_super(sb);
            drop_super(sb);
            goto restart;
        } else
            sb = sb_entry(sb->s_list.next);
    spin_unlock(&sb_lock);
}

/**
 *    get_super    -    get the superblock of a device
 *    @dev: device to get the superblock for
 *    
 *    Scans the superblock list and finds the superblock of the file system
 *    mounted on the device given. %NULL is returned if no match is found.
 */
 
struct super_block * get_super(kdev_t dev)
{
    struct super_block * s;

    if (!dev)
        return NULL;
restart:
    spin_lock(&sb_lock);
    s = find_super(dev);
    if (s) {
        spin_unlock(&sb_lock);
        down_read(&s->s_umount);
        if (s->s_root)
            return s;
        drop_super(s);
        goto restart;
    }
    spin_unlock(&sb_lock);
    return NULL;
}

asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
{
        struct super_block *s;
        struct ustat tmp;
        struct statfs sbuf;
    int err = -EINVAL;

        s = get_super(to_kdev_t(dev));
        if (s == NULL)
                goto out;
    err = vfs_statfs(s, &sbuf);
    drop_super(s);
    if (err)
        goto out;

        memset(&tmp,0,sizeof(struct ustat));
        tmp.f_tfree = sbuf.f_bfree;
        tmp.f_tinode = sbuf.f_ffree;

        err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0;
out:
    return err;
}

static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
                       struct file_system_type *type, 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;
}

/*
 * Unnamed block devices are dummy devices used by virtual
 * filesystems which don't use real block-devices.  -- jrs
 */

static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))];

kdev_t get_unnamed_dev(void)
{
    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;
}

void put_unnamed_dev(kdev_t dev)
{
    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));
}

static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
    char *dev_name, int flags, void * data)
{
    struct inode *inode;
    struct block_device *bdev;
    struct block_device_operations *bdops;
    devfs_handle_t de;
    struct super_block * s;
    struct nameidata nd;
    struct list_head *p;
    kdev_t dev;
    int error = 0;
    mode_t mode = FMODE_READ; /* we always need it ;-) */

    /* What device it is? */
    if (!dev_name || !*dev_name)
        return ERR_PTR(-EINVAL);
    if (path_init(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
        error = path_walk(dev_name, &nd);
    if (error)
        return ERR_PTR(error);
    inode = nd.dentry->d_inode;
    error = -ENOTBLK;
    if (!S_ISBLK(inode->i_mode))
        goto out;
    error = -EACCES;
    if (nd.mnt->mnt_flags & MNT_NODEV)
        goto out;
    bd_acquire(inode);
    bdev = inode->i_bdev;
    de = devfs_get_handle_from_inode (inode);
    bdops = devfs_get_ops (de);         /*  Increments module use count  */
    if (bdops) bdev->bd_op = bdops;
    /* Done with lookups, semaphore down */
    dev = to_kdev_t(bdev->bd_dev);
    if (!(flags & MS_RDONLY))
        mode |= FMODE_WRITE;
    error = blkdev_get(bdev, mode, 0, BDEV_FS);
    devfs_put_ops (de);   /*  Decrement module use count now we're safe  */
    if (error)
        goto out;
    check_disk_change(dev);
    error = -EACCES;
    if (!(flags & MS_RDONLY) && is_read_only(dev)) {
        blkdev_put(bdev, BDEV_FS);
        goto out;
    }

    error = -ENOMEM;
    s = alloc_super();
    if (!s) {
        blkdev_put(bdev, BDEV_FS);
        goto out;
    }

    error = -EBUSY;
restart:
    spin_lock(&sb_lock);

    list_for_each(p, &super_blocks) {
        struct super_block *old = sb_entry(p);
        if (old->s_dev != dev)
            continue;
        if (old->s_type != fs_type ||
            ((flags ^ old->s_flags) & MS_RDONLY)) {
            spin_unlock(&sb_lock);
            destroy_super(s);
            blkdev_put(bdev, BDEV_FS);
            goto out;
        }
        if (!grab_super(old))
            goto restart;
        destroy_super(s);
        blkdev_put(bdev, BDEV_FS);
        path_release(&nd);
        return old;
    }
    s->s_dev = dev;
    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;
    s->s_flags |= MS_ACTIVE;
    unlock_super(s);
    path_release(&nd);
    return s;

out_fail:
    unlock_super(s);
    deactivate_super(s);
    remove_super(s);
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)
{
    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;
    }
    return ERR_PTR(error);
}

static struct super_block *get_sb_single(struct file_system_type *fs_type,
    int flags, 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;
        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;
        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);
    }
}

void kill_super(struct super_block *sb)
{
    struct dentry *root = sb->s_root;
    struct file_system_type *fs = sb->s_type;
    struct super_operations *sop = sb->s_op;

    if (!deactivate_super(sb))
        return;

    down_write(&sb->s_umount);
    lock_kernel();
    sb->s_root = NULL;
    /* Need to clean after the sucker */
    if (fs->fs_flags & FS_LITTER)
        d_genocide(root);
    shrink_dcache_parent(root);
    dput(root);
    fsync_super(sb);
    lock_super(sb);
    sb->s_flags &= ~MS_ACTIVE;
    invalidate_inodes(sb);    /* bad name - it should be evict_inodes() */
    if (sop) {
        if (sop->write_super && sb->s_dirt)
            sop->write_super(sb);
        if (sop->put_super)
            sop->put_super(sb);
    }

    /* Forget any remaining inodes */
    if (invalidate_inodes(sb)) {
        printk("VFS: Busy inodes after unmount. "
            "Self-destruct in 5 seconds.  Have a nice day...\n");
    }

    unlock_kernel();
    unlock_super(sb);
    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);
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0059 ]--