Embed a struct path into struct nameidata instead of nd->{dentry,mnt}
[safe/jmp/linux-2.6] / fs / ext4 / super.c
index d0d8c76..3711799 100644 (file)
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+#include <linux/log2.h>
+#include <linux/crc16.h>
 
 #include <asm/uaccess.h>
 
 #include "xattr.h"
 #include "acl.h"
 #include "namei.h"
+#include "group.h"
 
 static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
                             unsigned long journal_devnum);
@@ -66,31 +70,31 @@ static void ext4_write_super_lockfs(struct super_block *sb);
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
                               struct ext4_group_desc *bg)
 {
-       return le32_to_cpu(bg->bg_block_bitmap) |
+       return le32_to_cpu(bg->bg_block_bitmap_lo) |
                (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
-                (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
+               (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
 }
 
 ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
                               struct ext4_group_desc *bg)
 {
-       return le32_to_cpu(bg->bg_inode_bitmap) |
+       return le32_to_cpu(bg->bg_inode_bitmap_lo) |
                (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
-                (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
+               (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
 }
 
 ext4_fsblk_t ext4_inode_table(struct super_block *sb,
                              struct ext4_group_desc *bg)
 {
-       return le32_to_cpu(bg->bg_inode_table) |
+       return le32_to_cpu(bg->bg_inode_table_lo) |
                (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
-                (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
+               (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
 }
 
 void ext4_block_bitmap_set(struct super_block *sb,
                           struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
-       bg->bg_block_bitmap = cpu_to_le32((u32)blk);
+       bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk);
        if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
                bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
 }
@@ -98,7 +102,7 @@ void ext4_block_bitmap_set(struct super_block *sb,
 void ext4_inode_bitmap_set(struct super_block *sb,
                           struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
-       bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
+       bg->bg_inode_bitmap_lo  = cpu_to_le32((u32)blk);
        if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
                bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
 }
@@ -106,7 +110,7 @@ void ext4_inode_bitmap_set(struct super_block *sb,
 void ext4_inode_table_set(struct super_block *sb,
                          struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
-       bg->bg_inode_table = cpu_to_le32((u32)blk);
+       bg->bg_inode_table_lo = cpu_to_le32((u32)blk);
        if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
                bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
 }
@@ -369,6 +373,66 @@ 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
  */
@@ -439,6 +503,7 @@ static void ext4_put_super (struct super_block * sb)
        struct ext4_super_block *es = sbi->s_es;
        int i;
 
+       ext4_mb_release(sb);
        ext4_ext_release(sb);
        ext4_xattr_put_super(sb);
        jbd2_journal_destroy(sbi->s_journal);
@@ -505,6 +570,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_block_alloc_info = NULL;
        ei->vfs_inode.i_version = 1;
        memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
+       INIT_LIST_HEAD(&ei->i_prealloc_list);
+       spin_lock_init(&ei->i_prealloc_lock);
        return &ei->vfs_inode;
 }
 
@@ -521,7 +588,7 @@ static void ext4_destroy_inode(struct inode *inode)
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
 {
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
@@ -529,7 +596,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 #ifdef CONFIG_EXT4DEV_FS_XATTR
        init_rwsem(&ei->xattr_sem);
 #endif
-       mutex_init(&ei->truncate_mutex);
+       init_rwsem(&ei->i_data_sem);
        inode_init_once(&ei->vfs_inode);
 }
 
@@ -539,7 +606,7 @@ static int init_inodecache(void)
                                             sizeof(struct ext4_inode_info),
                                             0, (SLAB_RECLAIM_ACCOUNT|
                                                SLAB_MEM_SPREAD),
-                                            init_once, NULL);
+                                            init_once);
        if (ext4_inode_cachep == NULL)
                return -ENOMEM;
        return 0;
@@ -594,10 +661,92 @@ static inline void ext4_show_quota_options(struct seq_file *seq, struct super_bl
 #endif
 }
 
+/*
+ * Show an option if
+ *  - it's set to a non-default value OR
+ *  - if the per-sb default is different from the global default
+ */
 static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
+       int def_errors;
+       unsigned long def_mount_opts;
        struct super_block *sb = vfs->mnt_sb;
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_super_block *es = sbi->s_es;
 
+       def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+       def_errors     = le16_to_cpu(es->s_errors);
+
+       if (sbi->s_sb_block != 1)
+               seq_printf(seq, ",sb=%llu", sbi->s_sb_block);
+       if (test_opt(sb, MINIX_DF))
+               seq_puts(seq, ",minixdf");
+       if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS))
+               seq_puts(seq, ",grpid");
+       if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS))
+               seq_puts(seq, ",nogrpid");
+       if (sbi->s_resuid != EXT4_DEF_RESUID ||
+           le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) {
+               seq_printf(seq, ",resuid=%u", sbi->s_resuid);
+       }
+       if (sbi->s_resgid != EXT4_DEF_RESGID ||
+           le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) {
+               seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+       }
+       if (test_opt(sb, ERRORS_RO)) {
+               if (def_errors == EXT4_ERRORS_PANIC ||
+                   def_errors == EXT4_ERRORS_CONTINUE) {
+                       seq_puts(seq, ",errors=remount-ro");
+               }
+       }
+       if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
+               seq_puts(seq, ",errors=continue");
+       if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
+               seq_puts(seq, ",errors=panic");
+       if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16))
+               seq_puts(seq, ",nouid32");
+       if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG))
+               seq_puts(seq, ",debug");
+       if (test_opt(sb, OLDALLOC))
+               seq_puts(seq, ",oldalloc");
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+       if (test_opt(sb, XATTR_USER) &&
+               !(def_mount_opts & EXT4_DEFM_XATTR_USER))
+               seq_puts(seq, ",user_xattr");
+       if (!test_opt(sb, XATTR_USER) &&
+           (def_mount_opts & EXT4_DEFM_XATTR_USER)) {
+               seq_puts(seq, ",nouser_xattr");
+       }
+#endif
+#ifdef CONFIG_EXT4DEV_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))
+               seq_puts(seq, ",noacl");
+#endif
+       if (!test_opt(sb, RESERVATION))
+               seq_puts(seq, ",noreservation");
+       if (sbi->s_commit_interval) {
+               seq_printf(seq, ",commit=%u",
+                          (unsigned) (sbi->s_commit_interval / HZ));
+       }
+       if (test_opt(sb, BARRIER))
+               seq_puts(seq, ",barrier=1");
+       if (test_opt(sb, NOBH))
+               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 (sbi->s_stripe)
+               seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+       /*
+        * journal mode get enabled in different ways
+        * So just print the value even if we didn't specify it
+        */
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
                seq_puts(seq, ",data=journal");
        else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
@@ -606,18 +755,14 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",data=writeback");
 
        ext4_show_quota_options(seq, sb);
-
        return 0;
 }
 
 
-static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+               u64 ino, u32 generation)
 {
-       __u32 *objp = vobjp;
-       unsigned long ino = objp[0];
-       __u32 generation = objp[1];
        struct inode *inode;
-       struct dentry *result;
 
        if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
                return ERR_PTR(-ESTALE);
@@ -632,23 +777,29 @@ static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
         * Currently we don't know the generation for parent directory, so
         * a generation of 0 means "accept any"
         */
-       inode = iget(sb, ino);
-       if (inode == NULL)
-               return ERR_PTR(-ENOMEM);
-       if (is_bad_inode(inode) ||
-           (generation && inode->i_generation != generation)) {
+       inode = ext4_iget(sb, ino);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (generation && inode->i_generation != generation) {
                iput(inode);
                return ERR_PTR(-ESTALE);
        }
-       /* now to find a dentry.
-        * If possible, get a well-connected one
-        */
-       result = d_alloc_anon(inode);
-       if (!result) {
-               iput(inode);
-               return ERR_PTR(-ENOMEM);
-       }
-       return result;
+
+       return inode;
+}
+
+static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
+{
+       return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+                                   ext4_nfs_get_inode);
+}
+
+static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
+{
+       return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+                                   ext4_nfs_get_inode);
 }
 
 #ifdef CONFIG_QUOTA
@@ -698,7 +849,6 @@ static struct quotactl_ops ext4_qctl_operations = {
 static const struct super_operations ext4_sops = {
        .alloc_inode    = ext4_alloc_inode,
        .destroy_inode  = ext4_destroy_inode,
-       .read_inode     = ext4_read_inode,
        .write_inode    = ext4_write_inode,
        .dirty_inode    = ext4_dirty_inode,
        .delete_inode   = ext4_delete_inode,
@@ -717,9 +867,10 @@ static const struct super_operations ext4_sops = {
 #endif
 };
 
-static struct export_operations ext4_export_ops = {
+static const struct export_operations ext4_export_ops = {
+       .fh_to_dentry = ext4_fh_to_dentry,
+       .fh_to_parent = ext4_fh_to_parent,
        .get_parent = ext4_get_parent,
-       .get_dentry = ext4_get_dentry,
 };
 
 enum {
@@ -729,11 +880,13 @@ enum {
        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_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_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
+       Opt_mballoc, Opt_nomballoc, Opt_stripe,
 };
 
 static match_table_t tokens = {
@@ -768,6 +921,8 @@ static match_table_t tokens = {
        {Opt_journal_update, "journal=update"},
        {Opt_journal_inum, "journal=%u"},
        {Opt_journal_dev, "journal_dev=%u"},
+       {Opt_journal_checksum, "journal_checksum"},
+       {Opt_journal_async_commit, "journal_async_commit"},
        {Opt_abort, "abort"},
        {Opt_data_journal, "data=journal"},
        {Opt_data_ordered, "data=ordered"},
@@ -784,6 +939,11 @@ static match_table_t tokens = {
        {Opt_usrquota, "usrquota"},
        {Opt_barrier, "barrier=%u"},
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
+       {Opt_i_version, "i_version"},
+       {Opt_mballoc, "mballoc"},
+       {Opt_nomballoc, "nomballoc"},
+       {Opt_stripe, "stripe=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
 };
@@ -954,6 +1114,13 @@ static int parse_options (char *options, struct super_block *sb,
                                return 0;
                        *journal_devnum = option;
                        break;
+               case Opt_journal_checksum:
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+                       break;
+               case Opt_journal_async_commit:
+                       set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+                       break;
                case Opt_noload:
                        set_opt (sbi->s_mount_opt, NOLOAD);
                        break;
@@ -963,7 +1130,7 @@ static int parse_options (char *options, struct super_block *sb,
                        if (option < 0)
                                return 0;
                        if (option == 0)
-                               option = JBD_DEFAULT_MAX_COMMIT_AGE;
+                               option = JBD2_DEFAULT_MAX_COMMIT_AGE;
                        sbi->s_commit_interval = HZ * option;
                        break;
                case Opt_data_journal:
@@ -1119,6 +1286,26 @@ clear_qf_name:
                case Opt_extents:
                        set_opt (sbi->s_mount_opt, EXTENTS);
                        break;
+               case Opt_noextents:
+                       clear_opt (sbi->s_mount_opt, EXTENTS);
+                       break;
+               case Opt_i_version:
+                       set_opt(sbi->s_mount_opt, I_VERSION);
+                       sb->s_flags |= MS_I_VERSION;
+                       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;
+                       if (option < 0)
+                               return 0;
+                       sbi->s_stripe = option;
+                       break;
                default:
                        printk (KERN_ERR
                                "EXT4-fs: Unrecognized mount option \"%s\" "
@@ -1231,8 +1418,45 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
        return res;
 }
 
+__le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
+                           struct ext4_group_desc *gdp)
+{
+       __u16 crc = 0;
+
+       if (sbi->s_es->s_feature_ro_compat &
+           cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+               int offset = offsetof(struct ext4_group_desc, bg_checksum);
+               __le32 le_group = cpu_to_le32(block_group);
+
+               crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
+               crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
+               crc = crc16(crc, (__u8 *)gdp, offset);
+               offset += sizeof(gdp->bg_checksum); /* skip checksum */
+               /* for checksum of struct ext4_group_desc do the rest...*/
+               if ((sbi->s_es->s_feature_incompat &
+                    cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
+                   offset < le16_to_cpu(sbi->s_es->s_desc_size))
+                       crc = crc16(crc, (__u8 *)gdp + offset,
+                                   le16_to_cpu(sbi->s_es->s_desc_size) -
+                                       offset);
+       }
+
+       return cpu_to_le16(crc);
+}
+
+int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group,
+                               struct ext4_group_desc *gdp)
+{
+       if ((sbi->s_es->s_feature_ro_compat &
+            cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) &&
+           (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp)))
+               return 0;
+
+       return 1;
+}
+
 /* Called at mount-time, super-block is locked */
-static int ext4_check_descriptors (struct super_block * sb)
+static int ext4_check_descriptors(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
@@ -1240,28 +1464,28 @@ static int ext4_check_descriptors (struct super_block * sb)
        ext4_fsblk_t block_bitmap;
        ext4_fsblk_t inode_bitmap;
        ext4_fsblk_t inode_table;
-       struct ext4_group_desc * gdp = NULL;
-       int desc_block = 0;
-       int i;
+       int flexbg_flag = 0;
+       ext4_group_t i;
+
+       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+               flexbg_flag = 1;
 
        ext4_debug ("Checking group descriptors");
 
-       for (i = 0; i < sbi->s_groups_count; i++)
-       {
-               if (i == sbi->s_groups_count - 1)
+       for (i = 0; i < sbi->s_groups_count; i++) {
+               struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+
+               if (i == sbi->s_groups_count - 1 || flexbg_flag)
                        last_block = ext4_blocks_count(sbi->s_es) - 1;
                else
                        last_block = first_block +
                                (EXT4_BLOCKS_PER_GROUP(sb) - 1);
 
-               if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
-                       gdp = (struct ext4_group_desc *)
-                                       sbi->s_group_desc[desc_block++]->b_data;
                block_bitmap = ext4_block_bitmap(sb, gdp);
                if (block_bitmap < first_block || block_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
-                                   "Block bitmap for group %d"
+                                   "Block bitmap for group %lu"
                                    " not in group (block %llu)!",
                                    i, block_bitmap);
                        return 0;
@@ -1270,24 +1494,30 @@ static int ext4_check_descriptors (struct super_block * sb)
                if (inode_bitmap < first_block || inode_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
-                                   "Inode bitmap for group %d"
+                                   "Inode bitmap for group %lu"
                                    " not in group (block %llu)!",
                                    i, inode_bitmap);
                        return 0;
                }
                inode_table = ext4_inode_table(sb, gdp);
                if (inode_table < first_block ||
-                   inode_table + sbi->s_itb_per_group > last_block)
+                   inode_table + sbi->s_itb_per_group - 1 > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
-                                   "Inode table for group %d"
+                                   "Inode table for group %lu"
                                    " not in group (block %llu)!",
                                    i, inode_table);
                        return 0;
                }
-               first_block += EXT4_BLOCKS_PER_GROUP(sb);
-               gdp = (struct ext4_group_desc *)
-                       ((__u8 *)gdp + EXT4_DESC_SIZE(sb));
+               if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
+                       ext4_error(sb, __FUNCTION__,
+                                  "Checksum for group %lu failed (%u!=%u)\n",
+                                   i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
+                                   gdp)), le16_to_cpu(gdp->bg_checksum));
+                       return 0;
+               }
+               if (!flexbg_flag)
+                       first_block += EXT4_BLOCKS_PER_GROUP(sb);
        }
 
        ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
@@ -1295,7 +1525,6 @@ static int ext4_check_descriptors (struct super_block * sb)
        return 1;
 }
 
-
 /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
  * the superblock) which were deleted from all directories, but held open by
  * a process at the time of a crash.  We walk the list and try to delete these
@@ -1408,22 +1637,95 @@ static void ext4_orphan_cleanup (struct super_block * sb,
 #endif
        sb->s_flags = s_flags; /* Restore MS_RDONLY status */
 }
+/*
+ * Maximal extent format file size.
+ * Resulting logical blkno at s_maxbytes must fit in our on-disk
+ * extent format containers, within a sector_t, and within i_blocks
+ * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
+ * so that won't be a limiting factor.
+ *
+ * Note, this does *not* consider any metadata overhead for vfs i_blocks.
+ */
+static loff_t ext4_max_size(int blkbits)
+{
+       loff_t res;
+       loff_t upper_limit = MAX_LFS_FILESIZE;
+
+       /* small i_blocks in vfs inode? */
+       if (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
+                */
+               upper_limit = (1LL << 32) - 1;
+
+               /* total blocks in file system block size */
+               upper_limit >>= (blkbits - 9);
+               upper_limit <<= blkbits;
+       }
+
+       /* 32-bit extent-start container, ee_block */
+       res = 1LL << 32;
+       res <<= blkbits;
+       res -= 1;
 
-#define log2(n) ffz(~(n))
+       /* Sanity check against vm- & vfs- imposed limits */
+       if (res > upper_limit)
+               res = upper_limit;
+
+       return res;
+}
 
 /*
- * Maximal file size.  There is a direct, and {,double-,triple-}indirect
- * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
- * We need to be 1 filesystem block less than the 2^32 sector limit.
+ * Maximal bitmap file size.  There is a direct, and {,double-,triple-}indirect
+ * 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_size(int bits)
+static loff_t ext4_max_bitmap_size(int bits)
 {
        loff_t res = EXT4_NDIR_BLOCKS;
-       /* This constant is calculated to be the largest file size for a
-        * dense, 4k-blocksize file such that the total number of
+       int meta_blocks;
+       loff_t upper_limit;
+       /* This is calculated to be the largest file size for a
+        * dense, bitmapped file such that the total number of
         * sectors in the file, including data and all indirect blocks,
-        * does not exceed 2^32. */
-       const loff_t upper_limit = 0x1ff7fffd000LL;
+        * does not exceed 2^48 -1
+        * __u32 i_blocks_lo and _u16 i_blocks_high representing the
+        * total number of  512 bytes blocks of the file
+        */
+
+       if (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
+                */
+               upper_limit = (1LL << 32) - 1;
+
+               /* total blocks in file system block size */
+               upper_limit >>= (bits - 9);
+
+       } else {
+               /*
+                * We use 48 bit ext4_inode i_blocks
+                * With EXT4_HUGE_FILE_FL set the i_blocks
+                * represent total number of blocks in
+                * file system block size
+                */
+               upper_limit = (1LL << 48) - 1;
+
+       }
+
+       /* indirect blocks */
+       meta_blocks = 1;
+       /* double indirect blocks */
+       meta_blocks += 1 + (1LL << (bits-2));
+       /* tripple indirect blocks */
+       meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
+
+       upper_limit -= meta_blocks;
+       upper_limit <<= bits;
 
        res += 1LL << (bits-2);
        res += 1LL << (2*(bits-2));
@@ -1431,6 +1733,10 @@ static loff_t ext4_max_size(int bits)
        res <<= bits;
        if (res > upper_limit)
                res = upper_limit;
+
+       if (res > MAX_LFS_FILESIZE)
+               res = MAX_LFS_FILESIZE;
+
        return res;
 }
 
@@ -1438,7 +1744,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
                                ext4_fsblk_t logical_sb_block, int nr)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       unsigned long bg, first_meta_bg;
+       ext4_group_t bg, first_meta_bg;
        int has_super = 0;
 
        first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
@@ -1452,8 +1758,39 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
        return (has_super + ext4_group_first_block_no(sb, bg));
 }
 
+/**
+ * ext4_get_stripe_size: Get the stripe size.
+ * @sbi: In memory super block info
+ *
+ * If we have specified it via mount option, then
+ * use the mount option value. If the value specified at mount time is
+ * greater than the blocks per group use the super block value.
+ * If the super block value is greater than blocks per group return 0.
+ * Allocator needs it be less than blocks per group.
+ *
+ */
+static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+{
+       unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride);
+       unsigned long stripe_width =
+                       le32_to_cpu(sbi->s_es->s_raid_stripe_width);
+
+       if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group)
+               return sbi->s_stripe;
+
+       if (stripe_width <= sbi->s_blocks_per_group)
+               return stripe_width;
+
+       if (stride <= sbi->s_blocks_per_group)
+               return stride;
+
+       return 0;
+}
 
 static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+                               __releases(kernel_sem)
+                               __acquires(kernel_sem)
+
 {
        struct buffer_head * bh;
        struct ext4_super_block *es = NULL;
@@ -1466,13 +1803,14 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
+       int ret = -EINVAL;
        int blocksize;
-       int hblock;
        int db_count;
        int i;
        int needs_recovery;
        __le32 features;
        __u64 blocks_count;
+       int err;
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
@@ -1481,6 +1819,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_sb_block = sb_block;
 
        unlock_kernel();
 
@@ -1490,6 +1829,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto out_fail;
        }
 
+       if (!sb_set_blocksize(sb, blocksize)) {
+               printk(KERN_ERR "EXT4-fs: bad blocksize %d.\n", blocksize);
+               goto out_fail;
+       }
+
        /*
         * The ext4 superblock will not be buffer aligned for other than 1kB
         * block sizes.  We need to calculate the offset from buffer start.
@@ -1540,16 +1884,27 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
 
        if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
                set_opt(sbi->s_mount_opt, ERRORS_PANIC);
-       else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_RO)
-               set_opt(sbi->s_mount_opt, ERRORS_RO);
-       else
+       else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
                set_opt(sbi->s_mount_opt, ERRORS_CONT);
+       else
+               set_opt(sbi->s_mount_opt, ERRORS_RO);
 
        sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
        sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
 
        set_opt(sbi->s_mount_opt, RESERVATION);
 
+       /*
+        * turn on extents feature by default in ext4 filesystem
+        * User -o noextents to turn it off
+        */
+       set_opt(sbi->s_mount_opt, EXTENTS);
+       /*
+        * turn on mballoc feature by default in ext4 filesystem
+        * User -o nomballoc to turn it off
+        */
+       set_opt(sbi->s_mount_opt, MBALLOC);
+
        if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
                            NULL, 0))
                goto failed_mount;
@@ -1564,6 +1919,17 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                printk(KERN_WARNING
                       "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,
@@ -1583,6 +1949,19 @@ 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)) {
+               /*
+                * Large file size enabled file system can only be
+                * mount if kernel is build with CONFIG_LSF
+                */
+               if (sizeof(root->i_blocks) < sizeof(u64) &&
+                               !(sb->s_flags & MS_RDONLY)) {
+                       printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge "
+                                       "files cannot be mounted read-write "
+                                       "without CONFIG_LSF.\n", sb->s_id);
+                       goto failed_mount;
+               }
+       }
        blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
 
        if (blocksize < EXT4_MIN_BLOCK_SIZE ||
@@ -1593,20 +1972,16 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       hblock = bdev_hardsect_size(sb->s_bdev);
        if (sb->s_blocksize != blocksize) {
-               /*
-                * Make sure the blocksize for the filesystem is larger
-                * than the hardware sectorsize for the machine.
-                */
-               if (blocksize < hblock) {
-                       printk(KERN_ERR "EXT4-fs: blocksize %d too small for "
-                              "device blocksize %d.\n", blocksize, hblock);
+
+               /* Validate the filesystem blocksize */
+               if (!sb_set_blocksize(sb, blocksize)) {
+                       printk(KERN_ERR "EXT4-fs: bad block size %d.\n",
+                                       blocksize);
                        goto failed_mount;
                }
 
                brelse (bh);
-               sb_set_blocksize(sb, blocksize);
                logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
                offset = do_div(logical_sb_block, blocksize);
                bh = sb_bread(sb, logical_sb_block);
@@ -1624,6 +1999,7 @@ 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);
 
        if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
@@ -1633,27 +2009,21 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
                sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
                if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
-                   (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+                   (!is_power_of_2(sbi->s_inode_size)) ||
                    (sbi->s_inode_size > blocksize)) {
                        printk (KERN_ERR
                                "EXT4-fs: unsupported inode size: %d\n",
                                sbi->s_inode_size);
                        goto failed_mount;
                }
-       }
-       sbi->s_frag_size = EXT4_MIN_FRAG_SIZE <<
-                                  le32_to_cpu(es->s_log_frag_size);
-       if (blocksize != sbi->s_frag_size) {
-               printk(KERN_ERR
-                      "EXT4-fs: fragsize %lu != blocksize %u (unsupported)\n",
-                      sbi->s_frag_size, blocksize);
-               goto failed_mount;
+               if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
+                       sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
        }
        sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
                if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
                    sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
-                   sbi->s_desc_size & (sbi->s_desc_size - 1)) {
+                   !is_power_of_2(sbi->s_desc_size)) {
                        printk(KERN_ERR
                               "EXT4-fs: unsupported descriptor size %lu\n",
                               sbi->s_desc_size);
@@ -1662,9 +2032,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        } else
                sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
        sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
-       sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
        sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-       if (EXT4_INODE_SIZE(sb) == 0)
+       if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
                goto cantfind_ext4;
        sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
        if (sbi->s_inodes_per_block == 0)
@@ -1674,8 +2043,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
        sbi->s_sbh = bh;
        sbi->s_mount_state = le16_to_cpu(es->s_state);
-       sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb));
-       sbi->s_desc_per_block_bits = log2(EXT4_DESC_PER_BLOCK(sb));
+       sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+       sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
        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;
@@ -1686,12 +2055,6 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                        sbi->s_blocks_per_group);
                goto failed_mount;
        }
-       if (sbi->s_frags_per_group > blocksize * 8) {
-               printk (KERN_ERR
-                       "EXT4-fs: #fragments per group too big: %lu\n",
-                       sbi->s_frags_per_group);
-               goto failed_mount;
-       }
        if (sbi->s_inodes_per_group > blocksize * 8) {
                printk (KERN_ERR
                        "EXT4-fs: #inodes per group too big: %lu\n",
@@ -1711,6 +2074,17 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
 
        if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext4;
+
+       /* ensure blocks_count calculation below doesn't sign-extend */
+       if (ext4_blocks_count(es) + EXT4_BLOCKS_PER_GROUP(sb) <
+           le32_to_cpu(es->s_first_data_block) + 1) {
+               printk(KERN_WARNING "EXT4-fs: bad geometry: block count %llu, "
+                      "first data block %u, blocks per group %lu\n",
+                       ext4_blocks_count(es),
+                       le32_to_cpu(es->s_first_data_block),
+                       EXT4_BLOCKS_PER_GROUP(sb));
+               goto failed_mount;
+       }
        blocks_count = (ext4_blocks_count(es) -
                        le32_to_cpu(es->s_first_data_block) +
                        EXT4_BLOCKS_PER_GROUP(sb) - 1);
@@ -1745,12 +2119,20 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
 
-       percpu_counter_init(&sbi->s_freeblocks_counter,
-               ext4_count_free_blocks(sb));
-       percpu_counter_init(&sbi->s_freeinodes_counter,
-               ext4_count_free_inodes(sb));
-       percpu_counter_init(&sbi->s_dirs_counter,
-               ext4_count_dirs(sb));
+       err = percpu_counter_init(&sbi->s_freeblocks_counter,
+                       ext4_count_free_blocks(sb));
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_freeinodes_counter,
+                               ext4_count_free_inodes(sb));
+       }
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_dirs_counter,
+                               ext4_count_dirs(sb));
+       }
+       if (err) {
+               printk(KERN_ERR "EXT4-fs: insufficient memory\n");
+               goto failed_mount3;
+       }
 
        /* per fileystem reservation list head & lock */
        spin_lock_init(&sbi->s_rsv_window_lock);
@@ -1765,6 +2147,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        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);
+
        /*
         * set up enough so that it can read an inode
         */
@@ -1802,6 +2186,28 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount3;
        }
 
+       if (ext4_blocks_count(es) > 0xffffffffULL &&
+           !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
+                                      JBD2_FEATURE_INCOMPAT_64BIT)) {
+               printk(KERN_ERR "ext4: Failed to set 64-bit journal feature\n");
+               goto failed_mount4;
+       }
+
+       if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
+               jbd2_journal_clear_features(sbi->s_journal, 0, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       } else {
+               jbd2_journal_clear_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       }
+
        /* We have now updated the journal if required, so we can
         * validate the data journaling mode. */
        switch (test_opt(sb, DATA_FLAGS)) {
@@ -1841,21 +2247,52 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
         * so we can safely mount the rest of the filesystem now.
         */
 
-       root = iget(sb, EXT4_ROOT_INO);
-       sb->s_root = d_alloc_root(root);
-       if (!sb->s_root) {
+       root = ext4_iget(sb, EXT4_ROOT_INO);
+       if (IS_ERR(root)) {
                printk(KERN_ERR "EXT4-fs: get root inode failed\n");
-               iput(root);
+               ret = PTR_ERR(root);
                goto failed_mount4;
        }
        if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
-               dput(sb->s_root);
-               sb->s_root = NULL;
+               iput(root);
                printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n");
                goto failed_mount4;
        }
+       sb->s_root = d_alloc_root(root);
+       if (!sb->s_root) {
+               printk(KERN_ERR "EXT4-fs: get root dentry failed\n");
+               iput(root);
+               ret = -ENOMEM;
+               goto failed_mount4;
+       }
 
        ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
+
+       /* determine the minimum size of new large inodes, if present */
+       if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
+               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+                                                    EXT4_GOOD_OLD_INODE_SIZE;
+               if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+                                      EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) {
+                       if (sbi->s_want_extra_isize <
+                           le16_to_cpu(es->s_want_extra_isize))
+                               sbi->s_want_extra_isize =
+                                       le16_to_cpu(es->s_want_extra_isize);
+                       if (sbi->s_want_extra_isize <
+                           le16_to_cpu(es->s_min_extra_isize))
+                               sbi->s_want_extra_isize =
+                                       le16_to_cpu(es->s_min_extra_isize);
+               }
+       }
+       /* Check if enough inode space is available */
+       if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
+                                                       sbi->s_inode_size) {
+               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+                                                      EXT4_GOOD_OLD_INODE_SIZE;
+               printk(KERN_INFO "EXT4-fs: required extra inode space not"
+                       "available.\n");
+       }
+
        /*
         * akpm: core read_super() calls in here with the superblock locked.
         * That deadlocks, because orphan cleanup needs to lock the superblock
@@ -1876,6 +2313,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                "writeback");
 
        ext4_ext_init(sb);
+       ext4_mb_init(sb, needs_recovery);
 
        lock_kernel();
        return 0;
@@ -1907,7 +2345,7 @@ out_fail:
        sb->s_fs_info = NULL;
        kfree(sbi);
        lock_kernel();
-       return -EINVAL;
+       return ret;
 }
 
 /*
@@ -1943,8 +2381,8 @@ static journal_t *ext4_get_journal(struct super_block *sb,
         * things happen if we iget() an unused inode, as the subsequent
         * iput() will try to delete it. */
 
-       journal_inode = iget(sb, journal_inum);
-       if (!journal_inode) {
+       journal_inode = ext4_iget(sb, journal_inum);
+       if (IS_ERR(journal_inode)) {
                printk(KERN_ERR "EXT4-fs: no journal found.\n");
                return NULL;
        }
@@ -1957,7 +2395,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
 
        jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
                  journal_inode, journal_inode->i_size);
-       if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {
+       if (!S_ISREG(journal_inode->i_mode)) {
                printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
                iput(journal_inode);
                return NULL;
@@ -2504,8 +2942,8 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
 
        if (test_opt(sb, MINIX_DF)) {
                sbi->s_overhead_last = 0;
-       } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
-               unsigned long ngroups = sbi->s_groups_count, i;
+       } else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
+               ext4_group_t ngroups = sbi->s_groups_count, i;
                ext4_fsblk_t overhead = 0;
                smp_rmb();
 
@@ -2539,19 +2977,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
                overhead += ngroups * (2 + sbi->s_itb_per_group);
                sbi->s_overhead_last = overhead;
                smp_wmb();
-               sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
+               sbi->s_blocks_last = ext4_blocks_count(es);
        }
 
        buf->f_type = EXT4_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
-       buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
-       es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
+       buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
+       ext4_free_blocks_count_set(es, buf->f_bfree);
        buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
        if (buf->f_bfree < ext4_r_blocks_count(es))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
-       buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+       buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
        es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
        buf->f_namelen = EXT4_NAME_LEN;
        fsid = le64_to_cpup((void *)es->s_uuid) ^
@@ -2651,8 +3089,11 @@ static int ext4_release_dquot(struct dquot *dquot)
 
        handle = ext4_journal_start(dquot_to_inode(dquot),
                                        EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
-       if (IS_ERR(handle))
+       if (IS_ERR(handle)) {
+               /* Release dquot anyway to avoid endless cycle in dqput() */
+               dquot_release(dquot);
                return PTR_ERR(handle);
+       }
        ret = dquot_release(dquot);
        err = ext4_journal_stop(handle);
        if (!ret)
@@ -2717,12 +3158,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
        if (err)
                return err;
        /* Quotafile not on the same filesystem? */
-       if (nd.mnt->mnt_sb != sb) {
+       if (nd.path.mnt->mnt_sb != sb) {
                path_release(&nd);
                return -EXDEV;
        }
        /* Quotafile not of fs root? */
-       if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
+       if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
                printk(KERN_WARNING
                        "EXT4-fs: Quota file not on filesystem root. "
                        "Journalled quota will not work.\n");
@@ -2738,7 +3179,7 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
                               size_t len, loff_t off)
 {
        struct inode *inode = sb_dqopt(sb)->files[type];
-       sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+       ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
        int err = 0;
        int offset = off & (sb->s_blocksize - 1);
        int tocopy;
@@ -2776,7 +3217,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                                const char *data, size_t len, loff_t off)
 {
        struct inode *inode = sb_dqopt(sb)->files[type];
-       sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+       ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
        int err = 0;
        int offset = off & (sb->s_blocksize - 1);
        int tocopy;
@@ -2785,6 +3226,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
+       if (!handle) {
+               printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)"
+                       " cancelled because transaction is not started.\n",
+                       (unsigned long long)off, (unsigned long long)len);
+               return -EIO;
+       }
        mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
        while (towrite > 0) {
                tocopy = sb->s_blocksize - offset < towrite ?
@@ -2825,7 +3272,6 @@ out:
                i_size_write(inode, off+len-towrite);
                EXT4_I(inode)->i_disksize = inode->i_size;
        }
-       inode->i_version++;
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        ext4_mark_inode_dirty(handle, inode);
        mutex_unlock(&inode->i_mutex);
@@ -2850,9 +3296,15 @@ static struct file_system_type ext4dev_fs_type = {
 
 static int __init init_ext4_fs(void)
 {
-       int err = init_ext4_xattr();
+       int err;
+
+       err = init_ext4_mballoc();
        if (err)
                return err;
+
+       err = init_ext4_xattr();
+       if (err)
+               goto out2;
        err = init_inodecache();
        if (err)
                goto out1;
@@ -2864,6 +3316,8 @@ out:
        destroy_inodecache();
 out1:
        exit_ext4_xattr();
+out2:
+       exit_ext4_mballoc();
        return err;
 }
 
@@ -2872,6 +3326,7 @@ static void __exit exit_ext4_fs(void)
        unregister_filesystem(&ext4dev_fs_type);
        destroy_inodecache();
        exit_ext4_xattr();
+       exit_ext4_mballoc();
 }
 
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");