flat: fix unmap len in load error path
[pandora-kernel.git] / fs / super.c
index 61fa181..5c35bc7 100644 (file)
 
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/acct.h>
 #include <linux/blkdev.h>
-#include <linux/quotaops.h>
-#include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/security.h>
-#include <linux/syscalls.h>
 #include <linux/writeback.h>           /* for the emergency remount stuff */
 #include <linux/idr.h>
-#include <linux/kobject.h>
 #include <linux/mutex.h>
-#include <linux/file.h>
 #include <linux/backing-dev.h>
-#include <asm/uaccess.h>
 #include "internal.h"
 
 
@@ -95,13 +87,12 @@ static struct super_block *alloc_super(struct file_system_type *type)
                s->s_count = 1;
                atomic_set(&s->s_active, 1);
                mutex_init(&s->s_vfs_rename_mutex);
+               lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
                mutex_init(&s->s_dquot.dqio_mutex);
                mutex_init(&s->s_dquot.dqonoff_mutex);
                init_rwsem(&s->s_dquot.dqptr_sem);
                init_waitqueue_head(&s->s_wait_unfrozen);
                s->s_maxbytes = MAX_NON_LFS;
-               s->dq_op = sb_dquot_ops;
-               s->s_qcop = sb_quotactl_ops;
                s->s_op = &default_op;
                s->s_time_gran = 1000000000;
        }
@@ -166,7 +157,6 @@ void deactivate_locked_super(struct super_block *s)
 {
        struct file_system_type *fs = s->s_type;
        if (atomic_dec_and_test(&s->s_active)) {
-               vfs_dq_off(s, 0);
                fs->kill_sb(s);
                put_filesystem(fs);
                put_super(s);
@@ -530,7 +520,7 @@ rescan:
 int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 {
        int retval;
-       int remount_rw, remount_ro;
+       int remount_ro;
 
        if (sb->s_frozen != SB_UNFROZEN)
                return -EBUSY;
@@ -546,7 +536,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
        sync_filesystem(sb);
 
        remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY);
-       remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
 
        /* If we are remounting RDONLY and current sb is read/write,
           make sure there are no rw files opened */
@@ -555,9 +544,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
                        mark_files_ro(sb);
                else if (!fs_may_remount_ro(sb))
                        return -EBUSY;
-               retval = vfs_dq_off(sb, 1);
-               if (retval < 0 && retval != -ENOSYS)
-                       return -EBUSY;
        }
 
        if (sb->s_op->remount_fs) {
@@ -566,8 +552,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
                        return retval;
        }
        sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
-       if (remount_rw)
-               vfs_dq_quota_on_remount(sb);
+
        /*
         * Some filesystems modify their metadata via some other path than the
         * bdev buffer cache (eg. use a private mapping, or directories in
@@ -951,6 +936,96 @@ out:
 
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
 
+/**
+ * freeze_super - lock the filesystem and force it into a consistent state
+ * @sb: the super to lock
+ *
+ * Syncs the super to make sure the filesystem is consistent and calls the fs's
+ * freeze_fs.  Subsequent calls to this without first thawing the fs will return
+ * -EBUSY.
+ */
+int freeze_super(struct super_block *sb)
+{
+       int ret;
+
+       atomic_inc(&sb->s_active);
+       down_write(&sb->s_umount);
+       if (sb->s_frozen) {
+               deactivate_locked_super(sb);
+               return -EBUSY;
+       }
+
+       if (sb->s_flags & MS_RDONLY) {
+               sb->s_frozen = SB_FREEZE_TRANS;
+               smp_wmb();
+               up_write(&sb->s_umount);
+               return 0;
+       }
+
+       sb->s_frozen = SB_FREEZE_WRITE;
+       smp_wmb();
+
+       sync_filesystem(sb);
+
+       sb->s_frozen = SB_FREEZE_TRANS;
+       smp_wmb();
+
+       sync_blockdev(sb->s_bdev);
+       if (sb->s_op->freeze_fs) {
+               ret = sb->s_op->freeze_fs(sb);
+               if (ret) {
+                       printk(KERN_ERR
+                               "VFS:Filesystem freeze failed\n");
+                       sb->s_frozen = SB_UNFROZEN;
+                       deactivate_locked_super(sb);
+                       return ret;
+               }
+       }
+       up_write(&sb->s_umount);
+       return 0;
+}
+EXPORT_SYMBOL(freeze_super);
+
+/**
+ * thaw_super -- unlock filesystem
+ * @sb: the super to thaw
+ *
+ * Unlocks the filesystem and marks it writeable again after freeze_super().
+ */
+int thaw_super(struct super_block *sb)
+{
+       int error;
+
+       down_write(&sb->s_umount);
+       if (sb->s_frozen == SB_UNFROZEN) {
+               up_write(&sb->s_umount);
+               return -EINVAL;
+       }
+
+       if (sb->s_flags & MS_RDONLY)
+               goto out;
+
+       if (sb->s_op->unfreeze_fs) {
+               error = sb->s_op->unfreeze_fs(sb);
+               if (error) {
+                       printk(KERN_ERR
+                               "VFS:Filesystem thaw failed\n");
+                       sb->s_frozen = SB_FREEZE_TRANS;
+                       up_write(&sb->s_umount);
+                       return error;
+               }
+       }
+
+out:
+       sb->s_frozen = SB_UNFROZEN;
+       smp_wmb();
+       wake_up(&sb->s_wait_unfrozen);
+       deactivate_locked_super(sb);
+
+       return 0;
+}
+EXPORT_SYMBOL(thaw_super);
+
 static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
 {
        int err;