async: Rename _special -> _domain for clarity.
[safe/jmp/linux-2.6] / fs / super.c
index 453877c..61dce00 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/kobject.h>
 #include <linux/mutex.h>
 #include <linux/file.h>
+#include <linux/async.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -70,6 +71,8 @@ static struct super_block *alloc_super(struct file_system_type *type)
                INIT_LIST_HEAD(&s->s_instances);
                INIT_HLIST_HEAD(&s->s_anon);
                INIT_LIST_HEAD(&s->s_inodes);
+               INIT_LIST_HEAD(&s->s_dentry_lru);
+               INIT_LIST_HEAD(&s->s_async_list);
                init_rwsem(&s->s_umount);
                mutex_init(&s->s_lock);
                lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -288,11 +291,18 @@ void generic_shutdown_super(struct super_block *sb)
 {
        const struct super_operations *sop = sb->s_op;
 
+
        if (sb->s_root) {
                shrink_dcache_for_umount(sb);
                fsync_super(sb);
                lock_super(sb);
                sb->s_flags &= ~MS_ACTIVE;
+
+               /*
+                * wait for asynchronous fs operations to finish before going further
+                */
+               async_synchronize_full_domain(&sb->s_async_list);
+
                /* bad name - it should be evict_inodes() */
                invalidate_inodes(sb);
                lock_kernel();
@@ -460,6 +470,7 @@ restart:
                sb->s_count++;
                spin_unlock(&sb_lock);
                down_read(&sb->s_umount);
+               async_synchronize_full_domain(&sb->s_async_list);
                if (sb->s_root && (wait || sb->s_dirt))
                        sb->s_op->sync_fs(sb, wait);
                up_read(&sb->s_umount);
@@ -533,7 +544,7 @@ rescan:
        return NULL;
 }
 
-asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf)
+SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
 {
         struct super_block *s;
         struct ustat tmp;
@@ -681,7 +692,7 @@ void emergency_remount(void)
  * filesystems which don't use real block-devices.  -- jrs
  */
 
-static struct idr unnamed_dev_idr;
+static DEFINE_IDA(unnamed_dev_ida);
 static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
 
 int set_anon_super(struct super_block *s, void *data)
@@ -690,10 +701,10 @@ int set_anon_super(struct super_block *s, void *data)
        int error;
 
  retry:
-       if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0)
+       if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0)
                return -ENOMEM;
        spin_lock(&unnamed_dev_lock);
-       error = idr_get_new(&unnamed_dev_idr, NULL, &dev);
+       error = ida_get_new(&unnamed_dev_ida, &dev);
        spin_unlock(&unnamed_dev_lock);
        if (error == -EAGAIN)
                /* We raced and lost with another CPU. */
@@ -703,7 +714,7 @@ int set_anon_super(struct super_block *s, void *data)
 
        if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
                spin_lock(&unnamed_dev_lock);
-               idr_remove(&unnamed_dev_idr, dev);
+               ida_remove(&unnamed_dev_ida, dev);
                spin_unlock(&unnamed_dev_lock);
                return -EMFILE;
        }
@@ -719,17 +730,12 @@ void kill_anon_super(struct super_block *sb)
 
        generic_shutdown_super(sb);
        spin_lock(&unnamed_dev_lock);
-       idr_remove(&unnamed_dev_idr, slot);
+       ida_remove(&unnamed_dev_ida, slot);
        spin_unlock(&unnamed_dev_lock);
 }
 
 EXPORT_SYMBOL(kill_anon_super);
 
-void __init unnamed_dev_init(void)
-{
-       idr_init(&unnamed_dev_idr);
-}
-
 void kill_litter_super(struct super_block *sb)
 {
        if (sb->s_root)
@@ -759,9 +765,13 @@ int get_sb_bdev(struct file_system_type *fs_type,
 {
        struct block_device *bdev;
        struct super_block *s;
+       fmode_t mode = FMODE_READ;
        int error = 0;
 
-       bdev = open_bdev_excl(dev_name, flags, fs_type);
+       if (!(flags & MS_RDONLY))
+               mode |= FMODE_WRITE;
+
+       bdev = open_bdev_exclusive(dev_name, mode, fs_type);
        if (IS_ERR(bdev))
                return PTR_ERR(bdev);
 
@@ -784,11 +794,12 @@ int get_sb_bdev(struct file_system_type *fs_type,
                        goto error_bdev;
                }
 
-               close_bdev_excl(bdev);
+               close_bdev_exclusive(bdev, mode);
        } else {
                char b[BDEVNAME_SIZE];
 
                s->s_flags = flags;
+               s->s_mode = mode;
                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);
@@ -799,6 +810,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
                }
 
                s->s_flags |= MS_ACTIVE;
+               bdev->bd_super = s;
        }
 
        return simple_set_mnt(mnt, s);
@@ -806,7 +818,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
 error_s:
        error = PTR_ERR(s);
 error_bdev:
-       close_bdev_excl(bdev);
+       close_bdev_exclusive(bdev, mode);
 error:
        return error;
 }
@@ -816,10 +828,12 @@ EXPORT_SYMBOL(get_sb_bdev);
 void kill_block_super(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
+       fmode_t mode = sb->s_mode;
 
+       bdev->bd_super = 0;
        generic_shutdown_super(sb);
        sync_blockdev(bdev);
-       close_bdev_excl(bdev);
+       close_bdev_exclusive(bdev, mode);
 }
 
 EXPORT_SYMBOL(kill_block_super);
@@ -912,7 +926,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
                goto out_free_secdata;
        BUG_ON(!mnt->mnt_sb);
 
-       error = security_sb_kern_mount(mnt->mnt_sb, secdata);
+       error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
        if (error)
                goto out_sb;