X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fsuper.c;fp=fs%2Fsuper.c;h=87845e4234fe02b467794d6b095b26b1a16a58e2;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=a4269d5ac0ebde83da265caa59368aab0a58cfa3;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/fs/super.c b/fs/super.c index a4269d5ac..87845e423 100644 --- a/fs/super.c +++ b/fs/super.c @@ -20,6 +20,7 @@ * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 */ +#include #include #include #include @@ -36,7 +37,6 @@ #include /* for the emergency remount stuff */ #include #include -#include #include #include #include @@ -51,17 +51,17 @@ DEFINE_SPINLOCK(sb_lock); /** * alloc_super - create new superblock - * @type: filesystem type superblock should belong to * * 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(struct file_system_type *type) +static struct super_block *alloc_super(void) { - struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER); + struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER); static struct super_operations default_op; if (s) { + memset(s, 0, sizeof(struct super_block)); if (security_sb_alloc(s)) { kfree(s); s = NULL; @@ -75,19 +75,12 @@ static struct super_block *alloc_super(struct file_system_type *type) INIT_LIST_HEAD(&s->s_inodes); init_rwsem(&s->s_umount); mutex_init(&s->s_lock); - lockdep_set_class(&s->s_umount, &type->s_umount_key); - /* - * The locking rules for s_lock are up to the - * filesystem. For example ext3fs has different - * lock ordering than usbfs: - */ - lockdep_set_class(&s->s_lock, &type->s_lock_key); down_write(&s->s_umount); s->s_count = S_BIAS; atomic_set(&s->s_active, 1); - mutex_init(&s->s_vfs_rename_mutex); - mutex_init(&s->s_dquot.dqio_mutex); - mutex_init(&s->s_dquot.dqonoff_mutex); + sema_init(&s->s_vfs_rename_sem,1); + sema_init(&s->s_dquot.dqio_sem, 1); + sema_init(&s->s_dquot.dqonoff_sem, 1); init_rwsem(&s->s_dquot.dqptr_sem); init_waitqueue_head(&s->s_wait_unfrozen); s->s_maxbytes = MAX_NON_LFS; @@ -231,17 +224,17 @@ static int grab_super(struct super_block *s) * that need destruction out of superblock, call generic_shutdown_super() * and release aforementioned objects. Note: dentries and inodes _are_ * taken care of and do not need specific handling. - * - * Upon calling this function, the filesystem may no longer alter or - * rearrange the set of dentries belonging to this super_block, nor may it - * change the attachments of dentries to inodes. */ void generic_shutdown_super(struct super_block *sb) { + struct dentry *root = sb->s_root; struct super_operations *sop = sb->s_op; - if (sb->s_root) { - shrink_dcache_for_umount(sb); + if (root) { + sb->s_root = NULL; + shrink_dcache_parent(root); + shrink_dcache_anon(&sb->s_anon); + dput(root); fsync_super(sb); lock_super(sb); sb->s_flags &= ~MS_ACTIVE; @@ -305,7 +298,7 @@ retry: } if (!s) { spin_unlock(&sb_lock); - s = alloc_super(type); + s = alloc_super(); if (!s) return ERR_PTR(-ENOMEM); goto retry; @@ -390,9 +383,9 @@ restart: void sync_filesystems(int wait) { struct super_block *sb; - static DEFINE_MUTEX(mutex); + static DECLARE_MUTEX(mutex); - mutex_lock(&mutex); /* Could be down_interruptible */ + down(&mutex); /* Could be down_interruptible */ spin_lock(&sb_lock); list_for_each_entry(sb, &super_blocks, s_list) { if (!sb->s_op->sync_fs) @@ -421,7 +414,7 @@ restart: goto restart; } spin_unlock(&sb_lock); - mutex_unlock(&mutex); + up(&mutex); } /** @@ -495,7 +488,7 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) s = user_get_super(new_decode_dev(dev)); if (s == NULL) goto out; - err = vfs_statfs(s->s_root, &sbuf); + err = vfs_statfs(s, &sbuf); drop_super(s); if (err) goto out; @@ -685,10 +678,9 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action) } } -int get_sb_bdev(struct file_system_type *fs_type, +struct super_block *get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int), - struct vfsmount *mnt) + int (*fill_super)(struct super_block *, void *, int)) { struct block_device *bdev; struct super_block *s; @@ -696,53 +688,48 @@ int get_sb_bdev(struct file_system_type *fs_type, bdev = open_bdev_excl(dev_name, flags, fs_type); if (IS_ERR(bdev)) - return PTR_ERR(bdev); + return (struct super_block *)bdev; /* * once the super is inserted into the list by sget, s_umount * will protect the lockfs code from trying to start a snapshot * while we are mounting */ - mutex_lock(&bdev->bd_mount_mutex); + down(&bdev->bd_mount_sem); s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); - mutex_unlock(&bdev->bd_mount_mutex); + up(&bdev->bd_mount_sem); if (IS_ERR(s)) - goto error_s; + goto out; if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { up_write(&s->s_umount); deactivate_super(s); - error = -EBUSY; - goto error_bdev; + s = ERR_PTR(-EBUSY); } - - close_bdev_excl(bdev); + goto out; } else { char b[BDEVNAME_SIZE]; s->s_flags = flags; strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); sb_set_blocksize(s, block_size(bdev)); - error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); - goto error; + s = ERR_PTR(error); + } else { + s->s_flags |= MS_ACTIVE; + bdev_uevent(bdev, KOBJ_MOUNT); } - - s->s_flags |= MS_ACTIVE; - bdev_uevent(bdev, KOBJ_MOUNT); } - return simple_set_mnt(mnt, s); + return s; -error_s: - error = PTR_ERR(s); -error_bdev: +out: close_bdev_excl(bdev); -error: - return error; + return s; } EXPORT_SYMBOL(get_sb_bdev); @@ -759,27 +746,26 @@ void kill_block_super(struct super_block *sb) EXPORT_SYMBOL(kill_block_super); -int get_sb_nodev(struct file_system_type *fs_type, +struct super_block *get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int), - struct vfsmount *mnt) + int (*fill_super)(struct super_block *, void *, int)) { int error; struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); if (IS_ERR(s)) - return PTR_ERR(s); + return s; s->s_flags = flags; - error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); - return error; + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; - return simple_set_mnt(mnt, s); + return s; } EXPORT_SYMBOL(get_sb_nodev); @@ -789,116 +775,107 @@ static int compare_single(struct super_block *s, void *p) return 1; } -int get_sb_single(struct file_system_type *fs_type, +struct super_block *get_sb_single(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int), - struct vfsmount *mnt) + int (*fill_super)(struct super_block *, void *, int)) { struct super_block *s; int error; s = sget(fs_type, compare_single, set_anon_super, NULL); if (IS_ERR(s)) - return PTR_ERR(s); + return s; if (!s->s_root) { s->s_flags = flags; - error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); - return error; + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; } do_remount_sb(s, flags, data, 0); - return simple_set_mnt(mnt, s); + return s; } EXPORT_SYMBOL(get_sb_single); struct vfsmount * -vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) +do_kern_mount(const char *fstype, int flags, const char *name, void *data) { - struct vfsmount *mnt; + struct file_system_type *type = get_fs_type(fstype); struct super_block *sb; - char *secdata = NULL; + struct vfsmount *mnt; int error; + char *secdata = NULL; if (!type) return ERR_PTR(-ENODEV); - error = -ENOMEM; + sb = ERR_PTR(-EPERM); + if ((type->fs_flags & FS_BINARY_MOUNTDATA) && + !vx_capable(CAP_SYS_ADMIN, VXC_BINARY_MOUNT)) + goto out; + + sb = ERR_PTR(-ENOMEM); mnt = alloc_vfsmnt(name); if (!mnt) goto out; if (data) { secdata = alloc_secdata(); - if (!secdata) + if (!secdata) { + sb = ERR_PTR(-ENOMEM); goto out_mnt; + } error = security_sb_copy_data(type, data, secdata); - if (error) + if (error) { + sb = ERR_PTR(error); goto out_free_secdata; + } } - error = type->get_sb(type, flags, name, data, mnt); - if (error < 0) + sb = type->get_sb(type, flags, name, data); + if (IS_ERR(sb)) goto out_free_secdata; - sb = mnt->mnt_sb; error = -EPERM; - if (!vx_capable(CAP_SYS_ADMIN, VXC_BINARY_MOUNT) && !sb->s_bdev && + if (!capable(CAP_SYS_ADMIN) && !sb->s_bdev && (sb->s_magic != PROC_SUPER_MAGIC) && (sb->s_magic != DEVPTS_SUPER_MAGIC)) goto out_sb; - error = security_sb_kern_mount(sb, secdata); + error = security_sb_kern_mount(sb, secdata); if (error) goto out_sb; - - mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sb->s_root); + mnt->mnt_mountpoint = sb->s_root; mnt->mnt_parent = mnt; - up_write(&mnt->mnt_sb->s_umount); + up_write(&sb->s_umount); free_secdata(secdata); + put_filesystem(type); return mnt; out_sb: - dput(mnt->mnt_root); - up_write(&mnt->mnt_sb->s_umount); - deactivate_super(mnt->mnt_sb); + up_write(&sb->s_umount); + deactivate_super(sb); + sb = ERR_PTR(error); out_free_secdata: free_secdata(secdata); out_mnt: free_vfsmnt(mnt); out: - return ERR_PTR(error); -} - -EXPORT_SYMBOL_GPL(vfs_kern_mount); - -struct vfsmount * -do_kern_mount(const char *fstype, int flags, const char *name, void *data) -{ - struct file_system_type *type = get_fs_type(fstype); - struct vfsmount *mnt; - - if (!type) - return ERR_PTR(-ENODEV); - - mnt = ERR_PTR(-EPERM); - if ((type->fs_flags & FS_BINARY_MOUNTDATA) && - !vx_capable(CAP_SYS_ADMIN, VXC_BINARY_MOUNT)) - goto out_put; - - mnt = vfs_kern_mount(type, flags, name, data); -out_put: put_filesystem(type); - return mnt; + return (struct vfsmount *)sb; } +EXPORT_SYMBOL_GPL(do_kern_mount); + struct vfsmount *kern_mount(struct file_system_type *type) { - return vfs_kern_mount(type, 0, type->name, NULL); + return do_kern_mount(type->name, 0, type->name, NULL); } EXPORT_SYMBOL(kern_mount);