]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext4/super.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/viro/bdev
[linux-2.6-omap-h63xx.git] / fs / ext4 / super.c
index 9f5468fb06da8589bafb192acbe0ebcf99428d68..bdddea14e782f041381837d1488506fd951cbc99 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
+#include <linux/marker.h>
 #include <linux/log2.h>
 #include <linux/crc16.h>
 #include <asm/uaccess.h>
@@ -373,66 +374,6 @@ void ext4_update_dynamic_rev(struct super_block *sb)
         */
 }
 
-int ext4_update_compat_feature(handle_t *handle,
-                                       struct super_block *sb, __u32 compat)
-{
-       int err = 0;
-       if (!EXT4_HAS_COMPAT_FEATURE(sb, compat)) {
-               err = ext4_journal_get_write_access(handle,
-                               EXT4_SB(sb)->s_sbh);
-               if (err)
-                       return err;
-               EXT4_SET_COMPAT_FEATURE(sb, compat);
-               sb->s_dirt = 1;
-               handle->h_sync = 1;
-               BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-                                       "call ext4_journal_dirty_met adata");
-               err = ext4_journal_dirty_metadata(handle,
-                               EXT4_SB(sb)->s_sbh);
-       }
-       return err;
-}
-
-int ext4_update_rocompat_feature(handle_t *handle,
-                                       struct super_block *sb, __u32 rocompat)
-{
-       int err = 0;
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, rocompat)) {
-               err = ext4_journal_get_write_access(handle,
-                               EXT4_SB(sb)->s_sbh);
-               if (err)
-                       return err;
-               EXT4_SET_RO_COMPAT_FEATURE(sb, rocompat);
-               sb->s_dirt = 1;
-               handle->h_sync = 1;
-               BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-                                       "call ext4_journal_dirty_met adata");
-               err = ext4_journal_dirty_metadata(handle,
-                               EXT4_SB(sb)->s_sbh);
-       }
-       return err;
-}
-
-int ext4_update_incompat_feature(handle_t *handle,
-                                       struct super_block *sb, __u32 incompat)
-{
-       int err = 0;
-       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, incompat)) {
-               err = ext4_journal_get_write_access(handle,
-                               EXT4_SB(sb)->s_sbh);
-               if (err)
-                       return err;
-               EXT4_SET_INCOMPAT_FEATURE(sb, incompat);
-               sb->s_dirt = 1;
-               handle->h_sync = 1;
-               BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-                                       "call ext4_journal_dirty_met adata");
-               err = ext4_journal_dirty_metadata(handle,
-                               EXT4_SB(sb)->s_sbh);
-       }
-       return err;
-}
-
 /*
  * Open the external journal device
  */
@@ -458,7 +399,7 @@ fail:
 static int ext4_blkdev_put(struct block_device *bdev)
 {
        bd_release(bdev);
-       return blkdev_put(bdev);
+       return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 }
 
 static int ext4_blkdev_remove(struct ext4_sb_info *sbi)
@@ -506,17 +447,18 @@ static void ext4_put_super(struct super_block *sb)
        ext4_mb_release(sb);
        ext4_ext_release(sb);
        ext4_xattr_put_super(sb);
-       jbd2_journal_destroy(sbi->s_journal);
+       if (jbd2_journal_destroy(sbi->s_journal) < 0)
+               ext4_abort(sb, __func__, "Couldn't clean up the journal");
        sbi->s_journal = NULL;
        if (!(sb->s_flags & MS_RDONLY)) {
                EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
                es->s_state = cpu_to_le16(sbi->s_mount_state);
-               BUFFER_TRACE(sbi->s_sbh, "marking dirty");
-               mark_buffer_dirty(sbi->s_sbh);
                ext4_commit_super(sb, es, 1);
        }
-       if (sbi->s_proc)
+       if (sbi->s_proc) {
+               remove_proc_entry("inode_readahead_blks", sbi->s_proc);
                remove_proc_entry(sb->s_id, ext4_proc_root);
+       }
 
        for (i = 0; i < sbi->s_gdb_count; i++)
                brelse(sbi->s_group_desc[i]);
@@ -568,11 +510,10 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
        ei->i_acl = EXT4_ACL_NOT_CACHED;
        ei->i_default_acl = EXT4_ACL_NOT_CACHED;
 #endif
-       ei->i_block_alloc_info = NULL;
        ei->vfs_inode.i_version = 1;
        ei->vfs_inode.i_data.writeback_index = 0;
        memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
@@ -605,7 +546,7 @@ static void init_once(void *foo)
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
        INIT_LIST_HEAD(&ei->i_orphan);
-#ifdef CONFIG_EXT4DEV_FS_XATTR
+#ifdef CONFIG_EXT4_FS_XATTR
        init_rwsem(&ei->xattr_sem);
 #endif
        init_rwsem(&ei->i_data_sem);
@@ -631,8 +572,7 @@ static void destroy_inodecache(void)
 
 static void ext4_clear_inode(struct inode *inode)
 {
-       struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info;
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
        if (EXT4_I(inode)->i_acl &&
                        EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
                posix_acl_release(EXT4_I(inode)->i_acl);
@@ -644,10 +584,7 @@ static void ext4_clear_inode(struct inode *inode)
                EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED;
        }
 #endif
-       ext4_discard_reservation(inode);
-       EXT4_I(inode)->i_block_alloc_info = NULL;
-       if (unlikely(rsv))
-               kfree(rsv);
+       ext4_discard_preallocations(inode);
        jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
                                       &EXT4_I(inode)->jinode);
 }
@@ -724,7 +661,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",debug");
        if (test_opt(sb, OLDALLOC))
                seq_puts(seq, ",oldalloc");
-#ifdef CONFIG_EXT4DEV_FS_XATTR
+#ifdef CONFIG_EXT4_FS_XATTR
        if (test_opt(sb, XATTR_USER) &&
                !(def_mount_opts & EXT4_DEFM_XATTR_USER))
                seq_puts(seq, ",user_xattr");
@@ -733,7 +670,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",nouser_xattr");
        }
 #endif
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
        if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
                seq_puts(seq, ",acl");
        if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
@@ -758,8 +695,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",nobh");
        if (!test_opt(sb, EXTENTS))
                seq_puts(seq, ",noextents");
-       if (!test_opt(sb, MBALLOC))
-               seq_puts(seq, ",nomballoc");
        if (test_opt(sb, I_VERSION))
                seq_puts(seq, ",i_version");
        if (!test_opt(sb, DELALLOC))
@@ -779,6 +714,13 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
        else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
                seq_puts(seq, ",data=writeback");
 
+       if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
+               seq_printf(seq, ",inode_readahead_blks=%u",
+                          sbi->s_inode_readahead_blks);
+
+       if (test_opt(sb, DATA_ERR_ABORT))
+               seq_puts(seq, ",data_err=abort");
+
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -902,20 +844,22 @@ static const struct export_operations ext4_export_ops = {
 enum {
        Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
        Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
-       Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
+       Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
        Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
        Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
        Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
        Opt_journal_checksum, Opt_journal_async_commit,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+       Opt_data_err_abort, Opt_data_err_ignore,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
        Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
-       Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+       Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+       Opt_inode_readahead_blks
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_bsd_df, "bsddf"},
        {Opt_minix_df, "minixdf"},
        {Opt_grpid, "grpid"},
@@ -929,8 +873,6 @@ static match_table_t tokens = {
        {Opt_err_panic, "errors=panic"},
        {Opt_err_ro, "errors=remount-ro"},
        {Opt_nouid32, "nouid32"},
-       {Opt_nocheck, "nocheck"},
-       {Opt_nocheck, "check=none"},
        {Opt_debug, "debug"},
        {Opt_oldalloc, "oldalloc"},
        {Opt_orlov, "orlov"},
@@ -953,6 +895,8 @@ static match_table_t tokens = {
        {Opt_data_journal, "data=journal"},
        {Opt_data_ordered, "data=ordered"},
        {Opt_data_writeback, "data=writeback"},
+       {Opt_data_err_abort, "data_err=abort"},
+       {Opt_data_err_ignore, "data_err=ignore"},
        {Opt_offusrjquota, "usrjquota="},
        {Opt_usrjquota, "usrjquota=%s"},
        {Opt_offgrpjquota, "grpjquota="},
@@ -967,12 +911,11 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
        {Opt_noextents, "noextents"},
        {Opt_i_version, "i_version"},
-       {Opt_mballoc, "mballoc"},
-       {Opt_nomballoc, "nomballoc"},
        {Opt_stripe, "stripe=%u"},
        {Opt_resize, "resize"},
        {Opt_delalloc, "delalloc"},
        {Opt_nodelalloc, "nodelalloc"},
+       {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
        {Opt_err, NULL},
 };
 
@@ -1066,9 +1009,6 @@ static int parse_options(char *options, struct super_block *sb,
                case Opt_nouid32:
                        set_opt(sbi->s_mount_opt, NO_UID32);
                        break;
-               case Opt_nocheck:
-                       clear_opt(sbi->s_mount_opt, CHECK);
-                       break;
                case Opt_debug:
                        set_opt(sbi->s_mount_opt, DEBUG);
                        break;
@@ -1078,7 +1018,7 @@ static int parse_options(char *options, struct super_block *sb,
                case Opt_orlov:
                        clear_opt(sbi->s_mount_opt, OLDALLOC);
                        break;
-#ifdef CONFIG_EXT4DEV_FS_XATTR
+#ifdef CONFIG_EXT4_FS_XATTR
                case Opt_user_xattr:
                        set_opt(sbi->s_mount_opt, XATTR_USER);
                        break;
@@ -1092,7 +1032,7 @@ static int parse_options(char *options, struct super_block *sb,
                               "not supported\n");
                        break;
 #endif
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
                case Opt_acl:
                        set_opt(sbi->s_mount_opt, POSIX_ACL);
                        break;
@@ -1186,6 +1126,12 @@ static int parse_options(char *options, struct super_block *sb,
                                sbi->s_mount_opt |= data_opt;
                        }
                        break;
+               case Opt_data_err_abort:
+                       set_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
+                       break;
+               case Opt_data_err_ignore:
+                       clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
+                       break;
 #ifdef CONFIG_QUOTA
                case Opt_usrjquota:
                        qtype = USRQUOTA;
@@ -1365,12 +1311,6 @@ set_qf_format:
                case Opt_nodelalloc:
                        clear_opt(sbi->s_mount_opt, DELALLOC);
                        break;
-               case Opt_mballoc:
-                       set_opt(sbi->s_mount_opt, MBALLOC);
-                       break;
-               case Opt_nomballoc:
-                       clear_opt(sbi->s_mount_opt, MBALLOC);
-                       break;
                case Opt_stripe:
                        if (match_int(&args[0], &option))
                                return 0;
@@ -1381,6 +1321,13 @@ set_qf_format:
                case Opt_delalloc:
                        set_opt(sbi->s_mount_opt, DELALLOC);
                        break;
+               case Opt_inode_readahead_blks:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       if (option < 0 || option > (1 << 30))
+                               return 0;
+                       sbi->s_inode_readahead_blks = option;
+                       break;
                default:
                        printk(KERN_ERR
                               "EXT4-fs: Unrecognized mount option \"%s\" "
@@ -1604,14 +1551,14 @@ static int ext4_check_descriptors(struct super_block *sb)
                if (block_bitmap < first_block || block_bitmap > last_block) {
                        printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
                               "Block bitmap for group %lu not in group "
-                              "(block %llu)!", i, block_bitmap);
+                              "(block %llu)!\n", i, block_bitmap);
                        return 0;
                }
                inode_bitmap = ext4_inode_bitmap(sb, gdp);
                if (inode_bitmap < first_block || inode_bitmap > last_block) {
                        printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
                               "Inode bitmap for group %lu not in group "
-                              "(block %llu)!", i, inode_bitmap);
+                              "(block %llu)!\n", i, inode_bitmap);
                        return 0;
                }
                inode_table = ext4_inode_table(sb, gdp);
@@ -1619,7 +1566,7 @@ static int ext4_check_descriptors(struct super_block *sb)
                    inode_table + sbi->s_itb_per_group - 1 > last_block) {
                        printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
                               "Inode table for group %lu not in group "
-                              "(block %llu)!", i, inode_table);
+                              "(block %llu)!\n", i, inode_table);
                        return 0;
                }
                spin_lock(sb_bgl_lock(sbi, i));
@@ -1764,13 +1711,13 @@ static void ext4_orphan_cleanup(struct super_block *sb,
  *
  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
  */
-static loff_t ext4_max_size(int blkbits)
+static loff_t ext4_max_size(int blkbits, int has_huge_files)
 {
        loff_t res;
        loff_t upper_limit = MAX_LFS_FILESIZE;
 
        /* small i_blocks in vfs inode? */
-       if (sizeof(blkcnt_t) < sizeof(u64)) {
+       if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
                /*
                 * CONFIG_LSF is not enabled implies the inode
                 * i_block represent total blocks in 512 bytes
@@ -1800,7 +1747,7 @@ static loff_t ext4_max_size(int blkbits)
  * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
  * We need to be 1 filesystem block less than the 2^48 sector limit.
  */
-static loff_t ext4_max_bitmap_size(int bits)
+static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
 {
        loff_t res = EXT4_NDIR_BLOCKS;
        int meta_blocks;
@@ -1813,11 +1760,11 @@ static loff_t ext4_max_bitmap_size(int bits)
         * total number of  512 bytes blocks of the file
         */
 
-       if (sizeof(blkcnt_t) < sizeof(u64)) {
+       if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
                /*
-                * CONFIG_LSF is not enabled implies the inode
-                * i_block represent total blocks in 512 bytes
-                * 32 == size of vfs inode i_blocks * 8
+                * !has_huge_files or CONFIG_LSF is not enabled
+                * implies the inode i_block represent total blocks in
+                * 512 bytes 32 == size of vfs inode i_blocks * 8
                 */
                upper_limit = (1LL << 32) - 1;
 
@@ -1926,7 +1873,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        int blocksize;
        int db_count;
        int i;
-       int needs_recovery;
+       int needs_recovery, has_huge_files;
        __le32 features;
        __u64 blocks_count;
        int err;
@@ -1938,6 +1885,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT4_DEF_RESUID;
        sbi->s_resgid = EXT4_DEF_RESGID;
+       sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
        sbi->s_sb_block = sb_block;
 
        unlock_kernel();
@@ -1985,11 +1933,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                set_opt(sbi->s_mount_opt, GRPID);
        if (def_mount_opts & EXT4_DEFM_UID16)
                set_opt(sbi->s_mount_opt, NO_UID32);
-#ifdef CONFIG_EXT4DEV_FS_XATTR
+#ifdef CONFIG_EXT4_FS_XATTR
        if (def_mount_opts & EXT4_DEFM_XATTR_USER)
                set_opt(sbi->s_mount_opt, XATTR_USER);
 #endif
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
        if (def_mount_opts & EXT4_DEFM_ACL)
                set_opt(sbi->s_mount_opt, POSIX_ACL);
 #endif
@@ -2024,11 +1972,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                ext4_warning(sb, __func__,
                        "extents feature not enabled on this filesystem, "
                        "use tune2fs.\n");
-       /*
-        * turn on mballoc code by default in ext4 filesystem
-        * Use -o nomballoc to turn it off
-        */
-       set_opt(sbi->s_mount_opt, MBALLOC);
 
        /*
         * enable delayed allocation by default
@@ -2052,16 +1995,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                       "EXT4-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
 
-       /*
-        * Since ext4 is still considered development code, we require
-        * that the TEST_FILESYS flag in s->flags be set.
-        */
-       if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) {
-               printk(KERN_WARNING "EXT4-fs: %s: not marked "
-                      "OK to use with test code.\n", sb->s_id);
-               goto failed_mount;
-       }
-
        /*
         * Check feature flags regardless of the revision level, since we
         * previously didn't change the revision level when setting the flags,
@@ -2081,7 +2014,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                       sb->s_id, le32_to_cpu(features));
                goto failed_mount;
        }
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
+       has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb,
+                                   EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
+       if (has_huge_files) {
                /*
                 * Large file size enabled file system can only be
                 * mount if kernel is build with CONFIG_LSF
@@ -2131,8 +2066,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                }
        }
 
-       sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits);
-       sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits);
+       sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
+                                                     has_huge_files);
+       sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
 
        if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
                sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
@@ -2231,9 +2167,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
+#ifdef CONFIG_PROC_FS
        if (ext4_proc_root)
                sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
 
+       if (sbi->s_proc)
+               proc_create_data("inode_readahead_blks", 0644, sbi->s_proc,
+                                &ext4_ui_proc_fops,
+                                &sbi->s_inode_readahead_blks);
+#endif
+
        bgl_lock_init(&sbi->s_blockgroup_lock);
 
        for (i = 0; i < db_count; i++) {
@@ -2280,19 +2223,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount3;
        }
 
-       /* per fileystem reservation list head & lock */
-       spin_lock_init(&sbi->s_rsv_window_lock);
-       sbi->s_rsv_window_root = RB_ROOT;
-       /* Add a single, static dummy reservation to the start of the
-        * reservation window list --- it gives us a placeholder for
-        * append-at-start-of-list which makes the allocation logic
-        * _much_ simpler. */
-       sbi->s_rsv_window_head.rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
-       sbi->s_rsv_window_head.rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
-       sbi->s_rsv_window_head.rsv_alloc_hit = 0;
-       sbi->s_rsv_window_head.rsv_goal_size = 0;
-       ext4_rsv_window_add(sb, &sbi->s_rsv_window_head);
-
        sbi->s_stripe = ext4_get_stripe_size(sbi);
 
        /*
@@ -2462,6 +2392,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        "available.\n");
        }
 
+       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+               printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
+                               "requested data journaling mode\n");
+               clear_opt(sbi->s_mount_opt, DELALLOC);
+       } else if (test_opt(sb, DELALLOC))
+               printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
+
+       ext4_ext_init(sb);
+       err = ext4_mb_init(sb, needs_recovery);
+       if (err) {
+               printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
+                      err);
+               goto failed_mount4;
+       }
+
        /*
         * akpm: core read_super() calls in here with the superblock locked.
         * That deadlocks, because orphan cleanup needs to lock the superblock
@@ -2481,16 +2426,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
               test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
               "writeback");
 
-       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
-               printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
-                               "requested data journaling mode\n");
-               clear_opt(sbi->s_mount_opt, DELALLOC);
-       } else if (test_opt(sb, DELALLOC))
-               printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
-
-       ext4_ext_init(sb);
-       ext4_mb_init(sb, needs_recovery);
-
        lock_kernel();
        return 0;
 
@@ -2513,8 +2448,10 @@ failed_mount2:
                brelse(sbi->s_group_desc[i]);
        kfree(sbi->s_group_desc);
 failed_mount:
-       if (sbi->s_proc)
+       if (sbi->s_proc) {
+               remove_proc_entry("inode_readahead_blks", sbi->s_proc);
                remove_proc_entry(sb->s_id, ext4_proc_root);
+       }
 #ifdef CONFIG_QUOTA
        for (i = 0; i < MAXQUOTAS; i++)
                kfree(sbi->s_qf_names[i]);
@@ -2548,6 +2485,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
                journal->j_flags |= JBD2_BARRIER;
        else
                journal->j_flags &= ~JBD2_BARRIER;
+       if (test_opt(sb, DATA_ERR_ABORT))
+               journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR;
+       else
+               journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
        spin_unlock(&journal->j_state_lock);
 }
 
@@ -2612,7 +2553,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
        if (bd_claim(bdev, sb)) {
                printk(KERN_ERR
                        "EXT4: failed to claim external journal device.\n");
-               blkdev_put(bdev);
+               blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
                return NULL;
        }
 
@@ -2867,7 +2808,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
        journal_t *journal = EXT4_SB(sb)->s_journal;
 
        jbd2_journal_lock_updates(journal);
-       jbd2_journal_flush(journal);
+       if (jbd2_journal_flush(journal) < 0)
+               goto out;
+
        lock_super(sb);
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
            sb->s_flags & MS_RDONLY) {
@@ -2876,6 +2819,8 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
                ext4_commit_super(sb, es, 1);
        }
        unlock_super(sb);
+
+out:
        jbd2_journal_unlock_updates(journal);
 }
 
@@ -2954,6 +2899,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
 {
        tid_t target;
 
+       trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
        sb->s_dirt = 0;
        if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
                if (wait)
@@ -2975,7 +2921,13 @@ static void ext4_write_super_lockfs(struct super_block *sb)
 
                /* Now we set up the journal barrier. */
                jbd2_journal_lock_updates(journal);
-               jbd2_journal_flush(journal);
+
+               /*
+                * We don't want to clear needs_recovery flag when we failed
+                * to flush the journal.
+                */
+               if (jbd2_journal_flush(journal) < 0)
+                       return;
 
                /* Journal blocked and flushed, clear needs_recovery flag. */
                EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
@@ -3376,30 +3328,30 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
  * Standard function to be called on quota_on
  */
 static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-                        char *path, int remount)
+                        char *name, int remount)
 {
        int err;
-       struct nameidata nd;
+       struct path path;
 
        if (!test_opt(sb, QUOTA))
                return -EINVAL;
-       /* When remounting, no checks are needed and in fact, path is NULL */
+       /* When remounting, no checks are needed and in fact, name is NULL */
        if (remount)
-               return vfs_quota_on(sb, type, format_id, path, remount);
+               return vfs_quota_on(sb, type, format_id, name, remount);
 
-       err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+       err = kern_path(name, LOOKUP_FOLLOW, &path);
        if (err)
                return err;
 
        /* Quotafile not on the same filesystem? */
-       if (nd.path.mnt->mnt_sb != sb) {
-               path_put(&nd.path);
+       if (path.mnt->mnt_sb != sb) {
+               path_put(&path);
                return -EXDEV;
        }
        /* Journaling quota? */
        if (EXT4_SB(sb)->s_qf_names[type]) {
                /* Quotafile not in fs root? */
-               if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+               if (path.dentry->d_parent != sb->s_root)
                        printk(KERN_WARNING
                                "EXT4-fs: Quota file not on filesystem root. "
                                "Journaled quota will not work.\n");
@@ -3409,18 +3361,22 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
         * When we journal data on quota file, we have to flush journal to see
         * all updates to the file when we bypass pagecache...
         */
-       if (ext4_should_journal_data(nd.path.dentry->d_inode)) {
+       if (ext4_should_journal_data(path.dentry->d_inode)) {
                /*
                 * We don't need to lock updates but journal_flush() could
                 * otherwise be livelocked...
                 */
                jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
-               jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+               err = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
                jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+               if (err) {
+                       path_put(&path);
+                       return err;
+               }
        }
 
-       err = vfs_quota_on_path(sb, type, format_id, &nd.path);
-       path_put(&nd.path);
+       err = vfs_quota_on_path(sb, type, format_id, &path);
+       path_put(&path);
        return err;
 }
 
@@ -3583,13 +3539,34 @@ const struct file_operations ext4_ui_proc_fops = {
 };
 #endif
 
+static struct file_system_type ext4_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "ext4",
+       .get_sb         = ext4_get_sb,
+       .kill_sb        = kill_block_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+
+#ifdef CONFIG_EXT4DEV_COMPAT
+static int ext4dev_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+{
+       printk(KERN_WARNING "EXT4-fs: Update your userspace programs "
+              "to mount using ext4\n");
+       printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility "
+              "will go away by 2.6.31\n");
+       return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
+}
+
 static struct file_system_type ext4dev_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ext4dev",
-       .get_sb         = ext4_get_sb,
+       .get_sb         = ext4dev_get_sb,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS("ext4dev");
+#endif
 
 static int __init init_ext4_fs(void)
 {
@@ -3606,9 +3583,16 @@ static int __init init_ext4_fs(void)
        err = init_inodecache();
        if (err)
                goto out1;
-       err = register_filesystem(&ext4dev_fs_type);
+       err = register_filesystem(&ext4_fs_type);
        if (err)
                goto out;
+#ifdef CONFIG_EXT4DEV_COMPAT
+       err = register_filesystem(&ext4dev_fs_type);
+       if (err) {
+               unregister_filesystem(&ext4_fs_type);
+               goto out;
+       }
+#endif
        return 0;
 out:
        destroy_inodecache();
@@ -3621,7 +3605,10 @@ out2:
 
 static void __exit exit_ext4_fs(void)
 {
+       unregister_filesystem(&ext4_fs_type);
+#ifdef CONFIG_EXT4DEV_COMPAT
        unregister_filesystem(&ext4dev_fs_type);
+#endif
        destroy_inodecache();
        exit_ext4_xattr();
        exit_ext4_mballoc();