Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
[pandora-kernel.git] / fs / super.c
index 15f2afd..8a669f6 100644 (file)
@@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb)
        if (root) {
                sb->s_root = NULL;
                shrink_dcache_parent(root);
-               shrink_dcache_anon(&sb->s_anon);
+               shrink_dcache_sb(sb);
                dput(root);
                fsync_super(sb);
                lock_super(sb);
@@ -486,7 +486,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, &sbuf);
+       err = vfs_statfs(s->s_root, &sbuf);
        drop_super(s);
        if (err)
                goto out;
@@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
        }
 }
 
-struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+int 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))
+       int (*fill_super)(struct super_block *, void *, int),
+       struct vfsmount *mnt)
 {
        struct block_device *bdev;
        struct super_block *s;
@@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
 
        bdev = open_bdev_excl(dev_name, flags, fs_type);
        if (IS_ERR(bdev))
-               return (struct super_block *)bdev;
+               return PTR_ERR(bdev);
 
        /*
         * once the super is inserted into the list by sget, s_umount
@@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
        s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
        mutex_unlock(&bdev->bd_mount_mutex);
        if (IS_ERR(s))
-               goto out;
+               goto error_s;
 
        if (s->s_root) {
                if ((flags ^ s->s_flags) & MS_RDONLY) {
                        up_write(&s->s_umount);
                        deactivate_super(s);
-                       s = ERR_PTR(-EBUSY);
+                       error = -EBUSY;
+                       goto error_bdev;
                }
-               goto out;
+
+               close_bdev_excl(bdev);
        } else {
                char b[BDEVNAME_SIZE];
 
@@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
                if (error) {
                        up_write(&s->s_umount);
                        deactivate_super(s);
-                       s = ERR_PTR(error);
-               } else {
-                       s->s_flags |= MS_ACTIVE;
-                       bdev_uevent(bdev, KOBJ_MOUNT);
+                       goto error;
                }
+
+               s->s_flags |= MS_ACTIVE;
+               bdev_uevent(bdev, KOBJ_MOUNT);
        }
 
-       return s;
+       return simple_set_mnt(mnt, s);
 
-out:
+error_s:
+       error = PTR_ERR(s);
+error_bdev:
        close_bdev_excl(bdev);
-       return s;
+error:
+       return error;
 }
 
 EXPORT_SYMBOL(get_sb_bdev);
@@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb)
 
 EXPORT_SYMBOL(kill_block_super);
 
-struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+int get_sb_nodev(struct file_system_type *fs_type,
        int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int))
+       int (*fill_super)(struct super_block *, void *, int),
+       struct vfsmount *mnt)
 {
        int error;
        struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
 
        if (IS_ERR(s))
-               return s;
+               return PTR_ERR(s);
 
        s->s_flags = flags;
 
@@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
        if (error) {
                up_write(&s->s_umount);
                deactivate_super(s);
-               return ERR_PTR(error);
+               return error;
        }
        s->s_flags |= MS_ACTIVE;
-       return s;
+       return simple_set_mnt(mnt, s);
 }
 
 EXPORT_SYMBOL(get_sb_nodev);
@@ -773,28 +780,29 @@ static int compare_single(struct super_block *s, void *p)
        return 1;
 }
 
-struct super_block *get_sb_single(struct file_system_type *fs_type,
+int get_sb_single(struct file_system_type *fs_type,
        int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int))
+       int (*fill_super)(struct super_block *, void *, int),
+       struct vfsmount *mnt)
 {
        struct super_block *s;
        int error;
 
        s = sget(fs_type, compare_single, set_anon_super, NULL);
        if (IS_ERR(s))
-               return s;
+               return PTR_ERR(s);
        if (!s->s_root) {
                s->s_flags = flags;
                error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        up_write(&s->s_umount);
                        deactivate_super(s);
-                       return ERR_PTR(error);
+                       return error;
                }
                s->s_flags |= MS_ACTIVE;
        }
        do_remount_sb(s, flags, data, 0);
-       return s;
+       return simple_set_mnt(mnt, s);
 }
 
 EXPORT_SYMBOL(get_sb_single);
@@ -802,52 +810,51 @@ EXPORT_SYMBOL(get_sb_single);
 struct vfsmount *
 vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
 {
-       struct super_block *sb = ERR_PTR(-ENOMEM);
        struct vfsmount *mnt;
-       int error;
        char *secdata = NULL;
+       int error;
+
+       if (!type)
+               return ERR_PTR(-ENODEV);
 
+       error = -ENOMEM;
        mnt = alloc_vfsmnt(name);
        if (!mnt)
                goto out;
 
        if (data) {
                secdata = alloc_secdata();
-               if (!secdata) {
-                       sb = ERR_PTR(-ENOMEM);
+               if (!secdata)
                        goto out_mnt;
-               }
 
                error = security_sb_copy_data(type, data, secdata);
-               if (error) {
-                       sb = ERR_PTR(error);
+               if (error)
                        goto out_free_secdata;
-               }
        }
 
-       sb = type->get_sb(type, flags, name, data);
-       if (IS_ERR(sb))
+       error = type->get_sb(type, flags, name, data, mnt);
+       if (error < 0)
                goto out_free_secdata;
-       error = security_sb_kern_mount(sb, secdata);
+
+       error = security_sb_kern_mount(mnt->mnt_sb, secdata);
        if (error)
                goto out_sb;
-       mnt->mnt_sb = sb;
-       mnt->mnt_root = dget(sb->s_root);
-       mnt->mnt_mountpoint = sb->s_root;
+
+       mnt->mnt_mountpoint = mnt->mnt_root;
        mnt->mnt_parent = mnt;
-       up_write(&sb->s_umount);
+       up_write(&mnt->mnt_sb->s_umount);
        free_secdata(secdata);
        return mnt;
 out_sb:
-       up_write(&sb->s_umount);
-       deactivate_super(sb);
-       sb = ERR_PTR(error);
+       dput(mnt->mnt_root);
+       up_write(&mnt->mnt_sb->s_umount);
+       deactivate_super(mnt->mnt_sb);
 out_free_secdata:
        free_secdata(secdata);
 out_mnt:
        free_vfsmnt(mnt);
 out:
-       return (struct vfsmount *)sb;
+       return ERR_PTR(error);
 }
 
 EXPORT_SYMBOL_GPL(vfs_kern_mount);