Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
[safe/jmp/linux-2.6] / fs / ext3 / super.c
index 34b6fca..427496c 100644 (file)
 #include "acl.h"
 #include "namei.h"
 
+#ifdef CONFIG_EXT3_DEFAULTS_TO_ORDERED
+  #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_ORDERED_DATA
+#else
+  #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_WRITEBACK_DATA
+#endif
+
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
                             unsigned long journal_devnum);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
                               unsigned int);
-static void ext3_commit_super (struct super_block * sb,
-                              struct ext3_super_block * es,
+static int ext3_commit_super(struct super_block *sb,
+                              struct ext3_super_block *es,
                               int sync);
 static void ext3_mark_recovery_complete(struct super_block * sb,
                                        struct ext3_super_block * es);
@@ -60,9 +66,8 @@ static const char *ext3_decode_error(struct super_block * sb, int errno,
                                     char nbuf[16]);
 static int ext3_remount (struct super_block * sb, int * flags, char * data);
 static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
-static void ext3_unlockfs(struct super_block *sb);
-static void ext3_write_super (struct super_block * sb);
-static void ext3_write_super_lockfs(struct super_block *sb);
+static int ext3_unfreeze(struct super_block *sb);
+static int ext3_freeze(struct super_block *sb);
 
 /*
  * Wrappers for journal_start/end.
@@ -281,7 +286,8 @@ void ext3_abort (struct super_block * sb, const char * function,
        EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
        sb->s_flags |= MS_RDONLY;
        EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
-       journal_abort(EXT3_SB(sb)->s_journal, -EIO);
+       if (EXT3_SB(sb)->s_journal)
+               journal_abort(EXT3_SB(sb)->s_journal, -EIO);
 }
 
 void ext3_warning (struct super_block * sb, const char * function,
@@ -347,7 +353,7 @@ fail:
 static int ext3_blkdev_put(struct block_device *bdev)
 {
        bd_release(bdev);
-       return blkdev_put(bdev);
+       return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 }
 
 static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
@@ -390,11 +396,16 @@ static void ext3_put_super (struct super_block * sb)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
        struct ext3_super_block *es = sbi->s_es;
-       int i;
+       int i, err;
+
+       lock_kernel();
 
        ext3_xattr_put_super(sb);
-       if (journal_destroy(sbi->s_journal) < 0)
+       err = journal_destroy(sbi->s_journal);
+       sbi->s_journal = NULL;
+       if (err < 0)
                ext3_abort(sb, __func__, "Couldn't clean up the journal");
+
        if (!(sb->s_flags & MS_RDONLY)) {
                EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
                es->s_state = cpu_to_le16(sbi->s_mount_state);
@@ -435,8 +446,10 @@ static void ext3_put_super (struct super_block * sb)
                ext3_blkdev_remove(sbi);
        }
        sb->s_fs_info = NULL;
+       kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
-       return;
+
+       unlock_kernel();
 }
 
 static struct kmem_cache *ext3_inode_cachep;
@@ -451,12 +464,10 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
        ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-       ei->i_acl = EXT3_ACL_NOT_CACHED;
-       ei->i_default_acl = EXT3_ACL_NOT_CACHED;
-#endif
        ei->i_block_alloc_info = NULL;
        ei->vfs_inode.i_version = 1;
+       atomic_set(&ei->i_datasync_tid, 0);
+       atomic_set(&ei->i_sync_tid, 0);
        return &ei->vfs_inode;
 }
 
@@ -505,18 +516,6 @@ static void destroy_inodecache(void)
 static void ext3_clear_inode(struct inode *inode)
 {
        struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-       if (EXT3_I(inode)->i_acl &&
-                       EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_acl);
-               EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
-       }
-       if (EXT3_I(inode)->i_default_acl &&
-                       EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_default_acl);
-               EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
-       }
-#endif
        ext3_discard_reservation(inode);
        EXT3_I(inode)->i_block_alloc_info = NULL;
        if (unlikely(rsv))
@@ -546,6 +545,19 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl
 #endif
 }
 
+static char *data_mode_string(unsigned long mode)
+{
+       switch (mode) {
+       case EXT3_MOUNT_JOURNAL_DATA:
+               return "journal";
+       case EXT3_MOUNT_ORDERED_DATA:
+               return "ordered";
+       case EXT3_MOUNT_WRITEBACK_DATA:
+               return "writeback";
+       }
+       return "unknown";
+}
+
 /*
  * Show an option if
  *  - it's set to a non-default value OR
@@ -619,13 +631,8 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (test_opt(sb, NOBH))
                seq_puts(seq, ",nobh");
 
-       if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-               seq_puts(seq, ",data=journal");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
-               seq_puts(seq, ",data=ordered");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
-               seq_puts(seq, ",data=writeback");
-
+       seq_printf(seq, ",data=%s", data_mode_string(sbi->s_mount_opt &
+                                                    EXT3_MOUNT_DATA_FLAGS));
        if (test_opt(sb, DATA_ERR_ABORT))
                seq_puts(seq, ",data_err=abort");
 
@@ -678,12 +685,30 @@ static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid,
                                    ext3_nfs_get_inode);
 }
 
+/*
+ * Try to release metadata pages (indirect blocks, directories) which are
+ * mapped via the block device.  Since these pages could have journal heads
+ * which would prevent try_to_free_buffers() from freeing them, we must use
+ * jbd layer's try_to_free_buffers() function to release them.
+ */
+static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
+                                gfp_t wait)
+{
+       journal_t *journal = EXT3_SB(sb)->s_journal;
+
+       WARN_ON(PageChecked(page));
+       if (!page_has_buffers(page))
+               return 0;
+       if (journal)
+               return journal_try_to_free_buffers(journal, page, 
+                                                  wait & ~__GFP_WAIT);
+       return try_to_free_buffers(page);
+}
+
 #ifdef CONFIG_QUOTA
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
 
-static int ext3_dquot_initialize(struct inode *inode, int type);
-static int ext3_dquot_drop(struct inode *inode);
 static int ext3_write_dquot(struct dquot *dquot);
 static int ext3_acquire_dquot(struct dquot *dquot);
 static int ext3_release_dquot(struct dquot *dquot);
@@ -697,9 +722,9 @@ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 static ssize_t ext3_quota_write(struct super_block *sb, int type,
                                const char *data, size_t len, loff_t off);
 
-static struct dquot_operations ext3_quota_operations = {
-       .initialize     = ext3_dquot_initialize,
-       .drop           = ext3_dquot_drop,
+static const struct dquot_operations ext3_quota_operations = {
+       .initialize     = dquot_initialize,
+       .drop           = dquot_drop,
        .alloc_space    = dquot_alloc_space,
        .alloc_inode    = dquot_alloc_inode,
        .free_space     = dquot_free_space,
@@ -709,10 +734,12 @@ static struct dquot_operations ext3_quota_operations = {
        .acquire_dquot  = ext3_acquire_dquot,
        .release_dquot  = ext3_release_dquot,
        .mark_dirty     = ext3_mark_dquot_dirty,
-       .write_info     = ext3_write_info
+       .write_info     = ext3_write_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
-static struct quotactl_ops ext3_qctl_operations = {
+static const struct quotactl_ops ext3_qctl_operations = {
        .quota_on       = ext3_quota_on,
        .quota_off      = vfs_quota_off,
        .quota_sync     = vfs_quota_sync,
@@ -730,10 +757,9 @@ static const struct super_operations ext3_sops = {
        .dirty_inode    = ext3_dirty_inode,
        .delete_inode   = ext3_delete_inode,
        .put_super      = ext3_put_super,
-       .write_super    = ext3_write_super,
        .sync_fs        = ext3_sync_fs,
-       .write_super_lockfs = ext3_write_super_lockfs,
-       .unlockfs       = ext3_unlockfs,
+       .freeze_fs      = ext3_freeze,
+       .unfreeze_fs    = ext3_unfreeze,
        .statfs         = ext3_statfs,
        .remount_fs     = ext3_remount,
        .clear_inode    = ext3_clear_inode,
@@ -742,6 +768,7 @@ static const struct super_operations ext3_sops = {
        .quota_read     = ext3_quota_read,
        .quota_write    = ext3_quota_write,
 #endif
+       .bdev_try_to_free_page = bdev_try_to_free_page,
 };
 
 static const struct export_operations ext3_export_ops = {
@@ -1007,12 +1034,18 @@ static int parse_options (char *options, struct super_block *sb,
                datacheck:
                        if (is_remount) {
                                if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
-                                               != data_opt) {
-                                       printk(KERN_ERR
-                                               "EXT3-fs: cannot change data "
-                                               "mode on remount\n");
-                                       return 0;
-                               }
+                                               == data_opt)
+                                       break;
+                               printk(KERN_ERR
+                                       "EXT3-fs (device %s): Cannot change "
+                                       "data mode on remount. The filesystem "
+                                       "is mounted in data=%s mode and you "
+                                       "try to remount it in data=%s mode.\n",
+                                       sb->s_id,
+                                       data_mode_string(sbi->s_mount_opt &
+                                                       EXT3_MOUNT_DATA_FLAGS),
+                                       data_mode_string(data_opt));
+                               return 0;
                        } else {
                                sbi->s_mount_opt &= ~EXT3_MOUNT_DATA_FLAGS;
                                sbi->s_mount_opt |= data_opt;
@@ -1031,8 +1064,7 @@ static int parse_options (char *options, struct super_block *sb,
                case Opt_grpjquota:
                        qtype = GRPQUOTA;
 set_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            !sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR
                                        "EXT3-fs: Cannot change journaled "
@@ -1071,8 +1103,7 @@ set_qf_name:
                case Opt_offgrpjquota:
                        qtype = GRPQUOTA;
 clear_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR "EXT3-fs: Cannot change "
                                        "journaled quota options when "
@@ -1091,8 +1122,7 @@ clear_qf_name:
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
 set_qf_format:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
                                printk(KERN_ERR "EXT3-fs: Cannot change "
                                        "journaled quota options when "
@@ -1111,8 +1141,7 @@ set_qf_format:
                        set_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
                case Opt_noquota:
-                       if (sb_any_quota_enabled(sb) ||
-                           sb_any_quota_suspended(sb)) {
+                       if (sb_any_quota_loaded(sb)) {
                                printk(KERN_ERR "EXT3-fs: Cannot change quota "
                                        "options when quota turned on.\n");
                                return 0;
@@ -1414,7 +1443,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                }
 
                list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-               DQUOT_INIT(inode);
+               vfs_dq_init(inode);
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
                                "%s: truncating inode %lu to %Ld bytes\n",
@@ -1544,6 +1573,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
+
+       sbi->s_blockgroup_lock =
+               kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
+       if (!sbi->s_blockgroup_lock) {
+               kfree(sbi);
+               return -ENOMEM;
+       }
        sb->s_fs_info = sbi;
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT3_DEF_RESUID;
@@ -1661,7 +1697,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       hblock = bdev_hardsect_size(sb->s_bdev);
+       hblock = bdev_logical_block_size(sb->s_bdev);
        if (sb->s_blocksize != blocksize) {
                /*
                 * Make sure the blocksize for the filesystem is larger
@@ -1740,6 +1776,17 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        for (i=0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
+       i = le32_to_cpu(es->s_flags);
+       if (i & EXT2_FLAGS_UNSIGNED_HASH)
+               sbi->s_hash_unsigned = 3;
+       else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+#ifdef __CHAR_UNSIGNED__
+               es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+               sbi->s_hash_unsigned = 3;
+#else
+               es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+#endif
+       }
 
        if (sbi->s_blocks_per_group > blocksize * 8) {
                printk (KERN_ERR
@@ -1765,7 +1812,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                printk(KERN_ERR "EXT3-fs: filesystem on %s:"
                        " too large to mount safely\n", sb->s_id);
                if (sizeof(sector_t) < 8)
-                       printk(KERN_WARNING "EXT3-fs: CONFIG_LBD not "
+                       printk(KERN_WARNING "EXT3-fs: CONFIG_LBDAF not "
                                        "enabled\n");
                goto failed_mount;
        }
@@ -1784,7 +1831,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       bgl_lock_init(&sbi->s_blockgroup_lock);
+       bgl_lock_init(sbi->s_blockgroup_lock);
 
        for (i = 0; i < db_count; i++) {
                block = descriptor_loc(sb, logic_sb_block, i);
@@ -1878,7 +1925,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                    cope, else JOURNAL_DATA */
                if (journal_check_available_features
                    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))
-                       set_opt(sbi->s_mount_opt, ORDERED_DATA);
+                       set_opt(sbi->s_mount_opt, DEFAULT_DATA_MODE);
                else
                        set_opt(sbi->s_mount_opt, JOURNAL_DATA);
                break;
@@ -1974,6 +2021,7 @@ failed_mount:
        brelse(bh);
 out_fail:
        sb->s_fs_info = NULL;
+       kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
        lock_kernel();
        return ret;
@@ -2067,12 +2115,12 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        if (bd_claim(bdev, sb)) {
                printk(KERN_ERR
                        "EXT3: failed to claim external journal device.\n");
-               blkdev_put(bdev);
+               blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
                return NULL;
        }
 
        blocksize = sb->s_blocksize;
-       hblock = bdev_hardsect_size(bdev);
+       hblock = bdev_logical_block_size(bdev);
        if (blocksize < hblock) {
                printk(KERN_ERR
                        "EXT3-fs: blocksize too small for journal device.\n");
@@ -2217,7 +2265,6 @@ static int ext3_load_journal(struct super_block *sb,
        if (journal_devnum &&
            journal_devnum != le32_to_cpu(es->s_journal_dev)) {
                es->s_journal_dev = cpu_to_le32(journal_devnum);
-               sb->s_dirt = 1;
 
                /* Make sure we flush the recovery flag to disk. */
                ext3_commit_super(sb, es, 1);
@@ -2260,7 +2307,6 @@ static int ext3_create_journal(struct super_block * sb,
        EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL);
 
        es->s_journal_inum = cpu_to_le32(journal_inum);
-       sb->s_dirt = 1;
 
        /* Make sure we flush the recovery flag to disk. */
        ext3_commit_super(sb, es, 1);
@@ -2268,21 +2314,34 @@ static int ext3_create_journal(struct super_block * sb,
        return 0;
 }
 
-static void ext3_commit_super (struct super_block * sb,
-                              struct ext3_super_block * es,
+static int ext3_commit_super(struct super_block *sb,
+                              struct ext3_super_block *es,
                               int sync)
 {
        struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
+       int error = 0;
 
        if (!sbh)
-               return;
-       es->s_wtime = cpu_to_le32(get_seconds());
+               return error;
+       /*
+        * If the file system is mounted read-only, don't update the
+        * superblock write time.  This avoids updating the superblock
+        * write time when we are mounting the root file system
+        * read/only but we need to replay the journal; at that point,
+        * for people who are east of GMT and who make their clock
+        * tick in localtime for Windows bug-for-bug compatibility,
+        * the clock is set in the future, and this will cause e2fsck
+        * to complain and force a full file system check.
+        */
+       if (!(sb->s_flags & MS_RDONLY))
+               es->s_wtime = cpu_to_le32(get_seconds());
        es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
        es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
        BUFFER_TRACE(sbh, "marking dirty");
        mark_buffer_dirty(sbh);
        if (sync)
-               sync_dirty_buffer(sbh);
+               error = sync_dirty_buffer(sbh);
+       return error;
 }
 
 
@@ -2304,7 +2363,6 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
        if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
            sb->s_flags & MS_RDONLY) {
                EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-               sb->s_dirt = 0;
                ext3_commit_super(sb, es, 1);
        }
        unlock_super(sb);
@@ -2363,32 +2421,14 @@ int ext3_force_commit(struct super_block *sb)
                return 0;
 
        journal = EXT3_SB(sb)->s_journal;
-       sb->s_dirt = 0;
        ret = ext3_journal_force_commit(journal);
        return ret;
 }
 
-/*
- * Ext3 always journals updates to the superblock itself, so we don't
- * have to propagate any other updates to the superblock on disk at this
- * point.  Just start an async writeback to get the buffers on their way
- * to the disk.
- *
- * This implicitly triggers the writebehind on sync().
- */
-
-static void ext3_write_super (struct super_block * sb)
-{
-       if (mutex_trylock(&sb->s_lock) != 0)
-               BUG();
-       sb->s_dirt = 0;
-}
-
 static int ext3_sync_fs(struct super_block *sb, int wait)
 {
        tid_t target;
 
-       sb->s_dirt = 0;
        if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
                if (wait)
                        log_wait_commit(EXT3_SB(sb)->s_journal, target);
@@ -2400,12 +2440,13 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
  * LVM calls this function before a (read-only) snapshot is created.  This
  * gives us a chance to flush the journal completely and mark the fs clean.
  */
-static void ext3_write_super_lockfs(struct super_block *sb)
+static int ext3_freeze(struct super_block *sb)
 {
-       sb->s_dirt = 0;
+       int error = 0;
+       journal_t *journal;
 
        if (!(sb->s_flags & MS_RDONLY)) {
-               journal_t *journal = EXT3_SB(sb)->s_journal;
+               journal = EXT3_SB(sb)->s_journal;
 
                /* Now we set up the journal barrier. */
                journal_lock_updates(journal);
@@ -2414,20 +2455,28 @@ static void ext3_write_super_lockfs(struct super_block *sb)
                 * We don't want to clear needs_recovery flag when we failed
                 * to flush the journal.
                 */
-               if (journal_flush(journal) < 0)
-                       return;
+               error = journal_flush(journal);
+               if (error < 0)
+                       goto out;
 
                /* Journal blocked and flushed, clear needs_recovery flag. */
                EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-               ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
+               error = ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
+               if (error)
+                       goto out;
        }
+       return 0;
+
+out:
+       journal_unlock_updates(journal);
+       return error;
 }
 
 /*
  * Called by LVM after the snapshot is done.  We need to reset the RECOVER
  * flag here, even though the filesystem is not technically dirty yet.
  */
-static void ext3_unlockfs(struct super_block *sb)
+static int ext3_unfreeze(struct super_block *sb)
 {
        if (!(sb->s_flags & MS_RDONLY)) {
                lock_super(sb);
@@ -2437,6 +2486,7 @@ static void ext3_unlockfs(struct super_block *sb)
                unlock_super(sb);
                journal_unlock_updates(EXT3_SB(sb)->s_journal);
        }
+       return 0;
 }
 
 static int ext3_remount (struct super_block * sb, int * flags, char * data)
@@ -2451,7 +2501,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
        int i;
 #endif
 
+       lock_kernel();
+
        /* Store the original options */
+       lock_super(sb);
        old_sb_flags = sb->s_flags;
        old_opts.s_mount_opt = sbi->s_mount_opt;
        old_opts.s_resuid = sbi->s_resuid;
@@ -2559,6 +2612,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
                        kfree(old_opts.s_qf_names[i]);
 #endif
+       unlock_super(sb);
+       unlock_kernel();
        return 0;
 restore_opts:
        sb->s_flags = old_sb_flags;
@@ -2575,6 +2630,8 @@ restore_opts:
                sbi->s_qf_names[i] = old_opts.s_qf_names[i];
        }
 #endif
+       unlock_super(sb);
+       unlock_kernel();
        return err;
 }
 
@@ -2649,7 +2706,7 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
  * Process 1                         Process 2
  * ext3_create()                     quota_sync()
  *   journal_start()                   write_dquot()
- *   DQUOT_INIT()                        down(dqio_mutex)
+ *   vfs_dq_init()                       down(dqio_mutex)
  *     down(dqio_mutex)                    journal_start()
  *
  */
@@ -2661,44 +2718,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
        return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 }
 
-static int ext3_dquot_initialize(struct inode *inode, int type)
-{
-       handle_t *handle;
-       int ret, err;
-
-       /* We may create quota structure so we need to reserve enough blocks */
-       handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
-       ret = dquot_initialize(inode, type);
-       err = ext3_journal_stop(handle);
-       if (!ret)
-               ret = err;
-       return ret;
-}
-
-static int ext3_dquot_drop(struct inode *inode)
-{
-       handle_t *handle;
-       int ret, err;
-
-       /* We may delete quota structure so we need to reserve enough blocks */
-       handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle)) {
-               /*
-                * We call dquot_drop() anyway to at least release references
-                * to quota structures so that umount does not hang.
-                */
-               dquot_drop(inode);
-               return PTR_ERR(handle);
-       }
-       ret = dquot_drop(inode);
-       err = ext3_journal_stop(handle);
-       if (!ret)
-               ret = err;
-       return ret;
-}
-
 static int ext3_write_dquot(struct dquot *dquot)
 {
        int ret, err;
@@ -2836,7 +2855,7 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
                err = journal_flush(EXT3_SB(sb)->s_journal);
                journal_unlock_updates(EXT3_SB(sb)->s_journal);
                if (err) {
-                       path_put(&nd.path);
+                       path_put(&path);
                        return err;
                }
        }