Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[sfrench/cifs-2.6.git] / fs / ext4 / super.c
index eef0a7d81e0d6b7879682cf3797ec1ab5af0923d..2fe141ff3c7e602162a9da361fd8f7b825564179 100644 (file)
@@ -66,10 +66,10 @@ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
                             unsigned long journal_devnum);
 static int ext4_show_options(struct seq_file *seq, struct dentry *root);
 static int ext4_commit_super(struct super_block *sb, int sync);
-static void ext4_mark_recovery_complete(struct super_block *sb,
+static int ext4_mark_recovery_complete(struct super_block *sb,
                                        struct ext4_super_block *es);
-static void ext4_clear_journal_err(struct super_block *sb,
-                                  struct ext4_super_block *es);
+static int ext4_clear_journal_err(struct super_block *sb,
+                                 struct ext4_super_block *es);
 static int ext4_sync_fs(struct super_block *sb, int wait);
 static int ext4_remount(struct super_block *sb, int *flags, char *data);
 static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
@@ -141,27 +141,115 @@ MODULE_ALIAS_FS("ext3");
 MODULE_ALIAS("ext3");
 #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 
+
+static inline void __ext4_read_bh(struct buffer_head *bh, int op_flags,
+                                 bh_end_io_t *end_io)
+{
+       /*
+        * buffer's verified bit is no longer valid after reading from
+        * disk again due to write out error, clear it to make sure we
+        * recheck the buffer contents.
+        */
+       clear_buffer_verified(bh);
+
+       bh->b_end_io = end_io ? end_io : end_buffer_read_sync;
+       get_bh(bh);
+       submit_bh(REQ_OP_READ, op_flags, bh);
+}
+
+void ext4_read_bh_nowait(struct buffer_head *bh, int op_flags,
+                        bh_end_io_t *end_io)
+{
+       BUG_ON(!buffer_locked(bh));
+
+       if (ext4_buffer_uptodate(bh)) {
+               unlock_buffer(bh);
+               return;
+       }
+       __ext4_read_bh(bh, op_flags, end_io);
+}
+
+int ext4_read_bh(struct buffer_head *bh, int op_flags, bh_end_io_t *end_io)
+{
+       BUG_ON(!buffer_locked(bh));
+
+       if (ext4_buffer_uptodate(bh)) {
+               unlock_buffer(bh);
+               return 0;
+       }
+
+       __ext4_read_bh(bh, op_flags, end_io);
+
+       wait_on_buffer(bh);
+       if (buffer_uptodate(bh))
+               return 0;
+       return -EIO;
+}
+
+int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, bool wait)
+{
+       if (trylock_buffer(bh)) {
+               if (wait)
+                       return ext4_read_bh(bh, op_flags, NULL);
+               ext4_read_bh_nowait(bh, op_flags, NULL);
+               return 0;
+       }
+       if (wait) {
+               wait_on_buffer(bh);
+               if (buffer_uptodate(bh))
+                       return 0;
+               return -EIO;
+       }
+       return 0;
+}
+
 /*
- * This works like sb_bread() except it uses ERR_PTR for error
+ * This works like __bread_gfp() except it uses ERR_PTR for error
  * returns.  Currently with sb_bread it's impossible to distinguish
  * between ENOMEM and EIO situations (since both result in a NULL
  * return.
  */
-struct buffer_head *
-ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
+static struct buffer_head *__ext4_sb_bread_gfp(struct super_block *sb,
+                                              sector_t block, int op_flags,
+                                              gfp_t gfp)
 {
-       struct buffer_head *bh = sb_getblk(sb, block);
+       struct buffer_head *bh;
+       int ret;
 
+       bh = sb_getblk_gfp(sb, block, gfp);
        if (bh == NULL)
                return ERR_PTR(-ENOMEM);
        if (ext4_buffer_uptodate(bh))
                return bh;
-       ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
-       wait_on_buffer(bh);
-       if (buffer_uptodate(bh))
-               return bh;
-       put_bh(bh);
-       return ERR_PTR(-EIO);
+
+       ret = ext4_read_bh_lock(bh, REQ_META | op_flags, true);
+       if (ret) {
+               put_bh(bh);
+               return ERR_PTR(ret);
+       }
+       return bh;
+}
+
+struct buffer_head *ext4_sb_bread(struct super_block *sb, sector_t block,
+                                  int op_flags)
+{
+       return __ext4_sb_bread_gfp(sb, block, op_flags, __GFP_MOVABLE);
+}
+
+struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb,
+                                           sector_t block)
+{
+       return __ext4_sb_bread_gfp(sb, block, 0, 0);
+}
+
+void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block)
+{
+       struct buffer_head *bh = sb_getblk_gfp(sb, block, 0);
+
+       if (likely(bh)) {
+               ext4_read_bh_lock(bh, REQ_RAHEAD, false);
+               brelse(bh);
+       }
 }
 
 static int ext4_verify_csum_type(struct super_block *sb,
@@ -201,7 +289,18 @@ void ext4_superblock_csum_set(struct super_block *sb)
        if (!ext4_has_metadata_csum(sb))
                return;
 
+       /*
+        * Locking the superblock prevents the scenario
+        * where:
+        *  1) a first thread pauses during checksum calculation.
+        *  2) a second thread updates the superblock, recalculates
+        *     the checksum, and updates s_checksum
+        *  3) the first thread resumes and finishes its checksum calculation
+        *     and updates s_checksum with a potentially stale or torn value.
+        */
+       lock_buffer(EXT4_SB(sb)->s_sbh);
        es->s_checksum = ext4_superblock_csum(sb, es);
+       unlock_buffer(EXT4_SB(sb)->s_sbh);
 }
 
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
@@ -472,6 +571,89 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
        spin_unlock(&sbi->s_md_lock);
 }
 
+/*
+ * This writepage callback for write_cache_pages()
+ * takes care of a few cases after page cleaning.
+ *
+ * write_cache_pages() already checks for dirty pages
+ * and calls clear_page_dirty_for_io(), which we want,
+ * to write protect the pages.
+ *
+ * However, we may have to redirty a page (see below.)
+ */
+static int ext4_journalled_writepage_callback(struct page *page,
+                                             struct writeback_control *wbc,
+                                             void *data)
+{
+       transaction_t *transaction = (transaction_t *) data;
+       struct buffer_head *bh, *head;
+       struct journal_head *jh;
+
+       bh = head = page_buffers(page);
+       do {
+               /*
+                * We have to redirty a page in these cases:
+                * 1) If buffer is dirty, it means the page was dirty because it
+                * contains a buffer that needs checkpointing. So the dirty bit
+                * needs to be preserved so that checkpointing writes the buffer
+                * properly.
+                * 2) If buffer is not part of the committing transaction
+                * (we may have just accidentally come across this buffer because
+                * inode range tracking is not exact) or if the currently running
+                * transaction already contains this buffer as well, dirty bit
+                * needs to be preserved so that the buffer gets writeprotected
+                * properly on running transaction's commit.
+                */
+               jh = bh2jh(bh);
+               if (buffer_dirty(bh) ||
+                   (jh && (jh->b_transaction != transaction ||
+                           jh->b_next_transaction))) {
+                       redirty_page_for_writepage(wbc, page);
+                       goto out;
+               }
+       } while ((bh = bh->b_this_page) != head);
+
+out:
+       return AOP_WRITEPAGE_ACTIVATE;
+}
+
+static int ext4_journalled_submit_inode_data_buffers(struct jbd2_inode *jinode)
+{
+       struct address_space *mapping = jinode->i_vfs_inode->i_mapping;
+       struct writeback_control wbc = {
+               .sync_mode =  WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .range_start = jinode->i_dirty_start,
+               .range_end = jinode->i_dirty_end,
+        };
+
+       return write_cache_pages(mapping, &wbc,
+                                ext4_journalled_writepage_callback,
+                                jinode->i_transaction);
+}
+
+static int ext4_journal_submit_inode_data_buffers(struct jbd2_inode *jinode)
+{
+       int ret;
+
+       if (ext4_should_journal_data(jinode->i_vfs_inode))
+               ret = ext4_journalled_submit_inode_data_buffers(jinode);
+       else
+               ret = jbd2_journal_submit_inode_data_buffers(jinode);
+
+       return ret;
+}
+
+static int ext4_journal_finish_inode_data_buffers(struct jbd2_inode *jinode)
+{
+       int ret = 0;
+
+       if (!ext4_should_journal_data(jinode->i_vfs_inode))
+               ret = jbd2_journal_finish_inode_data_buffers(jinode);
+
+       return ret;
+}
+
 static bool system_going_down(void)
 {
        return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
@@ -744,6 +926,7 @@ void __ext4_msg(struct super_block *sb,
        struct va_format vaf;
        va_list args;
 
+       atomic_inc(&EXT4_SB(sb)->s_msg_count);
        if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
                return;
 
@@ -754,9 +937,12 @@ void __ext4_msg(struct super_block *sb,
        va_end(args);
 }
 
-#define ext4_warning_ratelimit(sb)                                     \
-               ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), \
-                            "EXT4-fs warning")
+static int ext4_warning_ratelimit(struct super_block *sb)
+{
+       atomic_inc(&EXT4_SB(sb)->s_warning_count);
+       return ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
+                           "EXT4-fs warning");
+}
 
 void __ext4_warning(struct super_block *sb, const char *function,
                    unsigned int line, const char *fmt, ...)
@@ -935,10 +1121,10 @@ static void ext4_blkdev_put(struct block_device *bdev)
 static void ext4_blkdev_remove(struct ext4_sb_info *sbi)
 {
        struct block_device *bdev;
-       bdev = sbi->journal_bdev;
+       bdev = sbi->s_journal_bdev;
        if (bdev) {
                ext4_blkdev_put(bdev);
-               sbi->journal_bdev = NULL;
+               sbi->s_journal_bdev = NULL;
        }
 }
 
@@ -1069,14 +1255,14 @@ static void ext4_put_super(struct super_block *sb)
 
        sync_blockdev(sb->s_bdev);
        invalidate_bdev(sb->s_bdev);
-       if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
+       if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) {
                /*
                 * Invalidate the journal device's buffers.  We don't want them
                 * floating about in memory - the physical journal device may
                 * hotswapped, and it breaks the `ro-after' testing code.
                 */
-               sync_blockdev(sbi->journal_bdev);
-               invalidate_bdev(sbi->journal_bdev);
+               sync_blockdev(sbi->s_journal_bdev);
+               invalidate_bdev(sbi->s_journal_bdev);
                ext4_blkdev_remove(sbi);
        }
 
@@ -1100,7 +1286,7 @@ static void ext4_put_super(struct super_block *sb)
                crypto_free_shash(sbi->s_chksum_driver);
        kfree(sbi->s_blockgroup_lock);
        fs_put_dax(sbi->s_daxdev);
-       fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
+       fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
 #ifdef CONFIG_UNICODE
        utf8_unload(sbi->s_encoding);
 #endif
@@ -1123,6 +1309,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        inode_set_iversion(&ei->vfs_inode, 1);
        spin_lock_init(&ei->i_raw_lock);
        INIT_LIST_HEAD(&ei->i_prealloc_list);
+       atomic_set(&ei->i_prealloc_active, 0);
        spin_lock_init(&ei->i_prealloc_lock);
        ext4_es_init_tree(&ei->i_es_tree);
        rwlock_init(&ei->i_es_lock);
@@ -1144,6 +1331,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_datasync_tid = 0;
        atomic_set(&ei->i_unwritten, 0);
        INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
+       ext4_fc_init_inode(&ei->vfs_inode);
+       mutex_init(&ei->i_fc_lock);
        return &ei->vfs_inode;
 }
 
@@ -1161,6 +1350,10 @@ static int ext4_drop_inode(struct inode *inode)
 static void ext4_free_in_core_inode(struct inode *inode)
 {
        fscrypt_free_inode(inode);
+       if (!list_empty(&(EXT4_I(inode)->i_fc_list))) {
+               pr_warn("%s: inode %ld still in fc list",
+                       __func__, inode->i_ino);
+       }
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
@@ -1186,6 +1379,7 @@ static void init_once(void *foo)
        init_rwsem(&ei->i_data_sem);
        init_rwsem(&ei->i_mmap_sem);
        inode_init_once(&ei->vfs_inode);
+       ext4_fc_init_inode(&ei->vfs_inode);
 }
 
 static int __init init_inodecache(void)
@@ -1214,9 +1408,10 @@ static void destroy_inodecache(void)
 
 void ext4_clear_inode(struct inode *inode)
 {
+       ext4_fc_del(inode);
        invalidate_inode_buffers(inode);
        clear_inode(inode);
-       ext4_discard_preallocations(inode);
+       ext4_discard_preallocations(inode, 0);
        ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
        dquot_drop(inode);
        if (EXT4_I(inode)->jinode) {
@@ -1288,8 +1483,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
        if (!page_has_buffers(page))
                return 0;
        if (journal)
-               return jbd2_journal_try_to_free_buffers(journal, page,
-                                               wait & ~__GFP_DIRECT_RECLAIM);
+               return jbd2_journal_try_to_free_buffers(journal, page);
+
        return try_to_free_buffers(page);
 }
 
@@ -1387,10 +1582,9 @@ retry:
        return res;
 }
 
-static const union fscrypt_context *
-ext4_get_dummy_context(struct super_block *sb)
+static const union fscrypt_policy *ext4_get_dummy_policy(struct super_block *sb)
 {
-       return EXT4_SB(sb)->s_dummy_enc_ctx.ctx;
+       return EXT4_SB(sb)->s_dummy_enc_policy.policy;
 }
 
 static bool ext4_has_stable_inodes(struct super_block *sb)
@@ -1409,7 +1603,7 @@ static const struct fscrypt_operations ext4_cryptops = {
        .key_prefix             = "ext4:",
        .get_context            = ext4_get_context,
        .set_context            = ext4_set_context,
-       .get_dummy_context      = ext4_get_dummy_context,
+       .get_dummy_policy       = ext4_get_dummy_policy,
        .empty_dir              = ext4_empty_dir,
        .max_namelen            = EXT4_NAME_LEN,
        .has_stable_inodes      = ext4_has_stable_inodes,
@@ -1522,6 +1716,11 @@ enum {
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
        Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
+       Opt_prefetch_block_bitmaps, Opt_no_fc,
+#ifdef CONFIG_EXT4_DEBUG
+       Opt_fc_debug_max_replay,
+#endif
+       Opt_fc_debug_force
 };
 
 static const match_table_t tokens = {
@@ -1608,12 +1807,18 @@ static const match_table_t tokens = {
        {Opt_init_itable, "init_itable=%u"},
        {Opt_init_itable, "init_itable"},
        {Opt_noinit_itable, "noinit_itable"},
+       {Opt_no_fc, "no_fc"},
+       {Opt_fc_debug_force, "fc_debug_force"},
+#ifdef CONFIG_EXT4_DEBUG
+       {Opt_fc_debug_max_replay, "fc_debug_max_replay=%u"},
+#endif
        {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
        {Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
        {Opt_test_dummy_encryption, "test_dummy_encryption"},
        {Opt_inlinecrypt, "inlinecrypt"},
        {Opt_nombcache, "nombcache"},
        {Opt_nombcache, "no_mbcache"},  /* for backward compatibility */
+       {Opt_prefetch_block_bitmaps, "prefetch_block_bitmaps"},
        {Opt_removed, "check=none"},    /* mount option from ext2/3 */
        {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
        {Opt_removed, "reservation"},   /* mount option from ext2/3 */
@@ -1733,6 +1938,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
 #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3)
 #define MOPT_STRING    0x0400
 #define MOPT_SKIP      0x0800
+#define        MOPT_2          0x1000
 
 static const struct mount_opts {
        int     token;
@@ -1831,6 +2037,15 @@ static const struct mount_opts {
        {Opt_max_dir_size_kb, 0, MOPT_GTE0},
        {Opt_test_dummy_encryption, 0, MOPT_STRING},
        {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
+       {Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS,
+        MOPT_SET},
+       {Opt_no_fc, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
+        MOPT_CLEAR | MOPT_2 | MOPT_EXT4_ONLY},
+       {Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
+        MOPT_SET | MOPT_2 | MOPT_EXT4_ONLY},
+#ifdef CONFIG_EXT4_DEBUG
+       {Opt_fc_debug_max_replay, 0, MOPT_GTE0},
+#endif
        {Opt_err, 0, 0}
 };
 
@@ -1879,12 +2094,13 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,
         * needed to allow it to be set or changed during remount.  We do allow
         * it to be specified during remount, but only if there is no change.
         */
-       if (is_remount && !sbi->s_dummy_enc_ctx.ctx) {
+       if (is_remount && !sbi->s_dummy_enc_policy.policy) {
                ext4_msg(sb, KERN_WARNING,
                         "Can't set test_dummy_encryption on remount");
                return -1;
        }
-       err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx);
+       err = fscrypt_set_test_dummy_encryption(sb, arg->from,
+                                               &sbi->s_dummy_enc_policy);
        if (err) {
                if (err == -EEXIST)
                        ext4_msg(sb, KERN_WARNING,
@@ -2039,6 +2255,10 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                sbi->s_li_wait_mult = arg;
        } else if (token == Opt_max_dir_size_kb) {
                sbi->s_max_dir_size_kb = arg;
+#ifdef CONFIG_EXT4_DEBUG
+       } else if (token == Opt_fc_debug_max_replay) {
+               sbi->s_fc_debug_max_replay = arg;
+#endif
        } else if (token == Opt_stripe) {
                sbi->s_stripe = arg;
        } else if (token == Opt_resuid) {
@@ -2207,10 +2427,17 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                        WARN_ON(1);
                        return -1;
                }
-               if (arg != 0)
-                       sbi->s_mount_opt |= m->mount_opt;
-               else
-                       sbi->s_mount_opt &= ~m->mount_opt;
+               if (m->flags & MOPT_2) {
+                       if (arg != 0)
+                               sbi->s_mount_opt2 |= m->mount_opt;
+                       else
+                               sbi->s_mount_opt2 &= ~m->mount_opt;
+               } else {
+                       if (arg != 0)
+                               sbi->s_mount_opt |= m->mount_opt;
+                       else
+                               sbi->s_mount_opt &= ~m->mount_opt;
+               }
        }
        return 1;
 }
@@ -2427,6 +2654,9 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
                SEQ_OPTS_PUTS("dax=inode");
        }
 
+       if (test_opt2(sb, JOURNAL_FAST_COMMIT))
+               SEQ_OPTS_PUTS("fast_commit");
+
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -3213,15 +3443,34 @@ static void print_daily_error_info(struct timer_list *t)
 static int ext4_run_li_request(struct ext4_li_request *elr)
 {
        struct ext4_group_desc *gdp = NULL;
-       ext4_group_t group, ngroups;
-       struct super_block *sb;
+       struct super_block *sb = elr->lr_super;
+       ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+       ext4_group_t group = elr->lr_next_group;
        unsigned long timeout = 0;
+       unsigned int prefetch_ios = 0;
        int ret = 0;
 
-       sb = elr->lr_super;
-       ngroups = EXT4_SB(sb)->s_groups_count;
+       if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) {
+               elr->lr_next_group = ext4_mb_prefetch(sb, group,
+                               EXT4_SB(sb)->s_mb_prefetch, &prefetch_ios);
+               if (prefetch_ios)
+                       ext4_mb_prefetch_fini(sb, elr->lr_next_group,
+                                             prefetch_ios);
+               trace_ext4_prefetch_bitmaps(sb, group, elr->lr_next_group,
+                                           prefetch_ios);
+               if (group >= elr->lr_next_group) {
+                       ret = 1;
+                       if (elr->lr_first_not_zeroed != ngroups &&
+                           !sb_rdonly(sb) && test_opt(sb, INIT_INODE_TABLE)) {
+                               elr->lr_next_group = elr->lr_first_not_zeroed;
+                               elr->lr_mode = EXT4_LI_MODE_ITABLE;
+                               ret = 0;
+                       }
+               }
+               return ret;
+       }
 
-       for (group = elr->lr_next_group; group < ngroups; group++) {
+       for (; group < ngroups; group++) {
                gdp = ext4_get_group_desc(sb, group, NULL);
                if (!gdp) {
                        ret = 1;
@@ -3239,9 +3488,10 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
                timeout = jiffies;
                ret = ext4_init_inode_table(sb, group,
                                            elr->lr_timeout ? 0 : 1);
+               trace_ext4_lazy_itable_init(sb, group);
                if (elr->lr_timeout == 0) {
                        timeout = (jiffies - timeout) *
-                                 elr->lr_sbi->s_li_wait_mult;
+                               EXT4_SB(elr->lr_super)->s_li_wait_mult;
                        elr->lr_timeout = timeout;
                }
                elr->lr_next_sched = jiffies + elr->lr_timeout;
@@ -3256,15 +3506,11 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
  */
 static void ext4_remove_li_request(struct ext4_li_request *elr)
 {
-       struct ext4_sb_info *sbi;
-
        if (!elr)
                return;
 
-       sbi = elr->lr_sbi;
-
        list_del(&elr->lr_request);
-       sbi->s_li_request = NULL;
+       EXT4_SB(elr->lr_super)->s_li_request = NULL;
        kfree(elr);
 }
 
@@ -3473,7 +3719,6 @@ static int ext4_li_info_new(void)
 static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
                                            ext4_group_t start)
 {
-       struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_li_request *elr;
 
        elr = kzalloc(sizeof(*elr), GFP_KERNEL);
@@ -3481,8 +3726,13 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
                return NULL;
 
        elr->lr_super = sb;
-       elr->lr_sbi = sbi;
-       elr->lr_next_group = start;
+       elr->lr_first_not_zeroed = start;
+       if (test_opt(sb, PREFETCH_BLOCK_BITMAPS))
+               elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;
+       else {
+               elr->lr_mode = EXT4_LI_MODE_ITABLE;
+               elr->lr_next_group = start;
+       }
 
        /*
         * Randomize first schedule time of the request to
@@ -3512,8 +3762,9 @@ int ext4_register_li_request(struct super_block *sb,
                goto out;
        }
 
-       if (first_not_zeroed == ngroups || sb_rdonly(sb) ||
-           !test_opt(sb, INIT_INODE_TABLE))
+       if (!test_opt(sb, PREFETCH_BLOCK_BITMAPS) &&
+           (first_not_zeroed == ngroups || sb_rdonly(sb) ||
+            !test_opt(sb, INIT_INODE_TABLE)))
                goto out;
 
        elr = ext4_li_request_new(sb, first_not_zeroed);
@@ -3724,7 +3975,7 @@ int ext4_calculate_overhead(struct super_block *sb)
         * Add the internal journal blocks whether the journal has been
         * loaded or not
         */
-       if (sbi->s_journal && !sbi->journal_bdev)
+       if (sbi->s_journal && !sbi->s_journal_bdev)
                overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen);
        else if (ext4_has_feature_journal(sb) && !sbi->s_journal && j_inum) {
                /* j_inum for internal journal is non-zero */
@@ -3838,8 +4089,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                logical_sb_block = sb_block;
        }
 
-       if (!(bh = sb_bread_unmovable(sb, logical_sb_block))) {
+       bh = ext4_sb_bread_unmovable(sb, logical_sb_block);
+       if (IS_ERR(bh)) {
                ext4_msg(sb, KERN_ERR, "unable to read superblock");
+               ret = PTR_ERR(bh);
+               bh = NULL;
                goto out_fail;
        }
        /*
@@ -3906,6 +4160,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
        set_opt(sb, POSIX_ACL);
 #endif
+       if (ext4_has_feature_fast_commit(sb))
+               set_opt2(sb, JOURNAL_FAST_COMMIT);
        /* don't forget to enable journal_csum when metadata_csum is enabled. */
        if (ext4_has_metadata_csum(sb))
                set_opt(sb, JOURNAL_CHECKSUM);
@@ -4235,10 +4491,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                brelse(bh);
                logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
                offset = do_div(logical_sb_block, blocksize);
-               bh = sb_bread_unmovable(sb, logical_sb_block);
-               if (!bh) {
+               bh = ext4_sb_bread_unmovable(sb, logical_sb_block);
+               if (IS_ERR(bh)) {
                        ext4_msg(sb, KERN_ERR,
                               "Can't read superblock on 2nd try");
+                       ret = PTR_ERR(bh);
+                       bh = NULL;
                        goto failed_mount;
                }
                es = (struct ext4_super_block *)(bh->b_data + offset);
@@ -4450,18 +4708,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        /* Pre-read the descriptors into the buffer cache */
        for (i = 0; i < db_count; i++) {
                block = descriptor_loc(sb, logical_sb_block, i);
-               sb_breadahead_unmovable(sb, block);
+               ext4_sb_breadahead_unmovable(sb, block);
        }
 
        for (i = 0; i < db_count; i++) {
                struct buffer_head *bh;
 
                block = descriptor_loc(sb, logical_sb_block, i);
-               bh = sb_bread_unmovable(sb, block);
-               if (!bh) {
+               bh = ext4_sb_bread_unmovable(sb, block);
+               if (IS_ERR(bh)) {
                        ext4_msg(sb, KERN_ERR,
                               "can't read group descriptor %d", i);
                        db_count = i;
+                       ret = PTR_ERR(bh);
+                       bh = NULL;
                        goto failed_mount2;
                }
                rcu_read_lock();
@@ -4509,6 +4769,26 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
        mutex_init(&sbi->s_orphan_lock);
 
+       /* Initialize fast commit stuff */
+       atomic_set(&sbi->s_fc_subtid, 0);
+       atomic_set(&sbi->s_fc_ineligible_updates, 0);
+       INIT_LIST_HEAD(&sbi->s_fc_q[FC_Q_MAIN]);
+       INIT_LIST_HEAD(&sbi->s_fc_q[FC_Q_STAGING]);
+       INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_MAIN]);
+       INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]);
+       sbi->s_fc_bytes = 0;
+       sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE;
+       sbi->s_mount_state &= ~EXT4_FC_COMMITTING;
+       spin_lock_init(&sbi->s_fc_lock);
+       memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats));
+       sbi->s_fc_replay_state.fc_regions = NULL;
+       sbi->s_fc_replay_state.fc_regions_size = 0;
+       sbi->s_fc_replay_state.fc_regions_used = 0;
+       sbi->s_fc_replay_state.fc_regions_valid = 0;
+       sbi->s_fc_replay_state.fc_modified_inodes = NULL;
+       sbi->s_fc_replay_state.fc_modified_inodes_size = 0;
+       sbi->s_fc_replay_state.fc_modified_inodes_used = 0;
+
        sb->s_root = NULL;
 
        needs_recovery = (es->s_last_orphan != 0 ||
@@ -4558,6 +4838,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM;
                clear_opt(sb, JOURNAL_CHECKSUM);
                clear_opt(sb, DATA_FLAGS);
+               clear_opt2(sb, JOURNAL_FAST_COMMIT);
                sbi->s_journal = NULL;
                needs_recovery = 0;
                goto no_journal;
@@ -4616,6 +4897,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
 
        sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
+       sbi->s_journal->j_submit_inode_data_buffers =
+               ext4_journal_submit_inode_data_buffers;
+       sbi->s_journal->j_finish_inode_data_buffers =
+               ext4_journal_finish_inode_data_buffers;
 
 no_journal:
        if (!test_opt(sb, NO_MBCACHE)) {
@@ -4710,12 +4995,15 @@ no_journal:
 
        ext4_set_resv_clusters(sb);
 
-       err = ext4_setup_system_zone(sb);
-       if (err) {
-               ext4_msg(sb, KERN_ERR, "failed to initialize system "
-                        "zone (%d)", err);
-               goto failed_mount4a;
+       if (test_opt(sb, BLOCK_VALIDITY)) {
+               err = ext4_setup_system_zone(sb);
+               if (err) {
+                       ext4_msg(sb, KERN_ERR, "failed to initialize system "
+                                "zone (%d)", err);
+                       goto failed_mount4a;
+               }
        }
+       ext4_fc_replay_cleanup(sb);
 
        ext4_ext_init(sb);
        err = ext4_mb_init(sb);
@@ -4777,12 +5065,22 @@ no_journal:
        }
 #endif  /* CONFIG_QUOTA */
 
+       /*
+        * Save the original bdev mapping's wb_err value which could be
+        * used to detect the metadata async write error.
+        */
+       spin_lock_init(&sbi->s_bdev_wb_lock);
+       errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err,
+                                &sbi->s_bdev_wb_err);
+       sb->s_bdev->bd_super = sb;
        EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
        ext4_orphan_cleanup(sb, es);
        EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
        if (needs_recovery) {
                ext4_msg(sb, KERN_INFO, "recovery complete");
-               ext4_mark_recovery_complete(sb, es);
+               err = ext4_mark_recovery_complete(sb, es);
+               if (err)
+                       goto failed_mount8;
        }
        if (EXT4_SB(sb)->s_journal) {
                if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
@@ -4816,6 +5114,8 @@ no_journal:
        ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10);
        ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10);
        ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
+       atomic_set(&sbi->s_warning_count, 0);
+       atomic_set(&sbi->s_msg_count, 0);
 
        kfree(orig_data);
        return 0;
@@ -4825,10 +5125,9 @@ cantfind_ext4:
                ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
        goto failed_mount;
 
-#ifdef CONFIG_QUOTA
 failed_mount8:
        ext4_unregister_sysfs(sb);
-#endif
+       kobject_put(&sbi->s_kobj);
 failed_mount7:
        ext4_unregister_li_request(sb);
 failed_mount6:
@@ -4892,7 +5191,7 @@ failed_mount:
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(get_qf_name(sb, sbi, i));
 #endif
-       fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
+       fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
        ext4_blkdev_remove(sbi);
        brelse(bh);
 out_fail:
@@ -4917,6 +5216,7 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
        journal->j_commit_interval = sbi->s_commit_interval;
        journal->j_min_batch_time = sbi->s_min_batch_time;
        journal->j_max_batch_time = sbi->s_max_batch_time;
+       ext4_fc_init(sb, journal);
 
        write_lock(&journal->j_state_lock);
        if (test_opt(sb, BARRIER))
@@ -4968,7 +5268,8 @@ static journal_t *ext4_get_journal(struct super_block *sb,
        struct inode *journal_inode;
        journal_t *journal;
 
-       BUG_ON(!ext4_has_feature_journal(sb));
+       if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
+               return NULL;
 
        journal_inode = ext4_get_journal_inode(sb, journal_inum);
        if (!journal_inode)
@@ -4998,7 +5299,8 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
        struct ext4_super_block *es;
        struct block_device *bdev;
 
-       BUG_ON(!ext4_has_feature_journal(sb));
+       if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
+               return NULL;
 
        bdev = ext4_blkdev_get(j_dev, sb);
        if (bdev == NULL)
@@ -5057,9 +5359,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
                goto out_bdev;
        }
        journal->j_private = sb;
-       ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
-       wait_on_buffer(journal->j_sb_buffer);
-       if (!buffer_uptodate(journal->j_sb_buffer)) {
+       if (ext4_read_bh_lock(journal->j_sb_buffer, REQ_META | REQ_PRIO, true)) {
                ext4_msg(sb, KERN_ERR, "I/O error on journal device");
                goto out_journal;
        }
@@ -5069,7 +5369,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
                        be32_to_cpu(journal->j_superblock->s_nr_users));
                goto out_journal;
        }
-       EXT4_SB(sb)->journal_bdev = bdev;
+       EXT4_SB(sb)->s_journal_bdev = bdev;
        ext4_init_journal_params(sb, journal);
        return journal;
 
@@ -5089,8 +5389,10 @@ static int ext4_load_journal(struct super_block *sb,
        dev_t journal_dev;
        int err = 0;
        int really_read_only;
+       int journal_dev_ro;
 
-       BUG_ON(!ext4_has_feature_journal(sb));
+       if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
+               return -EFSCORRUPTED;
 
        if (journal_devnum &&
            journal_devnum != le32_to_cpu(es->s_journal_dev)) {
@@ -5100,7 +5402,31 @@ static int ext4_load_journal(struct super_block *sb,
        } else
                journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
 
-       really_read_only = bdev_read_only(sb->s_bdev);
+       if (journal_inum && journal_dev) {
+               ext4_msg(sb, KERN_ERR,
+                        "filesystem has both journal inode and journal device!");
+               return -EINVAL;
+       }
+
+       if (journal_inum) {
+               journal = ext4_get_journal(sb, journal_inum);
+               if (!journal)
+                       return -EINVAL;
+       } else {
+               journal = ext4_get_dev_journal(sb, journal_dev);
+               if (!journal)
+                       return -EINVAL;
+       }
+
+       journal_dev_ro = bdev_read_only(journal->j_dev);
+       really_read_only = bdev_read_only(sb->s_bdev) | journal_dev_ro;
+
+       if (journal_dev_ro && !sb_rdonly(sb)) {
+               ext4_msg(sb, KERN_ERR,
+                        "journal device read-only, try mounting with '-o ro'");
+               err = -EROFS;
+               goto err_out;
+       }
 
        /*
         * Are we loading a blank journal or performing recovery after a
@@ -5115,27 +5441,14 @@ static int ext4_load_journal(struct super_block *sb,
                                ext4_msg(sb, KERN_ERR, "write access "
                                        "unavailable, cannot proceed "
                                        "(try mounting with noload)");
-                               return -EROFS;
+                               err = -EROFS;
+                               goto err_out;
                        }
                        ext4_msg(sb, KERN_INFO, "write access will "
                               "be enabled during recovery");
                }
        }
 
-       if (journal_inum && journal_dev) {
-               ext4_msg(sb, KERN_ERR, "filesystem has both journal "
-                      "and inode journals!");
-               return -EINVAL;
-       }
-
-       if (journal_inum) {
-               if (!(journal = ext4_get_journal(sb, journal_inum)))
-                       return -EINVAL;
-       } else {
-               if (!(journal = ext4_get_dev_journal(sb, journal_dev)))
-                       return -EINVAL;
-       }
-
        if (!(journal->j_flags & JBD2_BARRIER))
                ext4_msg(sb, KERN_INFO, "barriers disabled");
 
@@ -5155,12 +5468,16 @@ static int ext4_load_journal(struct super_block *sb,
 
        if (err) {
                ext4_msg(sb, KERN_ERR, "error loading journal");
-               jbd2_journal_destroy(journal);
-               return err;
+               goto err_out;
        }
 
        EXT4_SB(sb)->s_journal = journal;
-       ext4_clear_journal_err(sb, es);
+       err = ext4_clear_journal_err(sb, es);
+       if (err) {
+               EXT4_SB(sb)->s_journal = NULL;
+               jbd2_journal_destroy(journal);
+               return err;
+       }
 
        if (!really_read_only && journal_devnum &&
            journal_devnum != le32_to_cpu(es->s_journal_dev)) {
@@ -5171,6 +5488,10 @@ static int ext4_load_journal(struct super_block *sb,
        }
 
        return 0;
+
+err_out:
+       jbd2_journal_destroy(journal);
+       return err;
 }
 
 static int ext4_commit_super(struct super_block *sb, int sync)
@@ -5182,13 +5503,6 @@ static int ext4_commit_super(struct super_block *sb, int sync)
        if (!sbh || block_device_ejected(sb))
                return error;
 
-       /*
-        * The superblock bh should be mapped, but it might not be if the
-        * device was hot-removed. Not much we can do but fail the I/O.
-        */
-       if (!buffer_mapped(sbh))
-               return error;
-
        /*
         * If the file system is mounted read-only, don't update the
         * superblock write time.  This avoids updating the superblock
@@ -5256,26 +5570,32 @@ static int ext4_commit_super(struct super_block *sb, int sync)
  * remounting) the filesystem readonly, then we will end up with a
  * consistent fs on disk.  Record that fact.
  */
-static void ext4_mark_recovery_complete(struct super_block *sb,
-                                       struct ext4_super_block *es)
+static int ext4_mark_recovery_complete(struct super_block *sb,
+                                      struct ext4_super_block *es)
 {
+       int err;
        journal_t *journal = EXT4_SB(sb)->s_journal;
 
        if (!ext4_has_feature_journal(sb)) {
-               BUG_ON(journal != NULL);
-               return;
+               if (journal != NULL) {
+                       ext4_error(sb, "Journal got removed while the fs was "
+                                  "mounted!");
+                       return -EFSCORRUPTED;
+               }
+               return 0;
        }
        jbd2_journal_lock_updates(journal);
-       if (jbd2_journal_flush(journal) < 0)
+       err = jbd2_journal_flush(journal);
+       if (err < 0)
                goto out;
 
        if (ext4_has_feature_journal_needs_recovery(sb) && sb_rdonly(sb)) {
                ext4_clear_feature_journal_needs_recovery(sb);
                ext4_commit_super(sb, 1);
        }
-
 out:
        jbd2_journal_unlock_updates(journal);
+       return err;
 }
 
 /*
@@ -5283,14 +5603,17 @@ out:
  * has recorded an error from a previous lifetime, move that error to the
  * main filesystem now.
  */
-static void ext4_clear_journal_err(struct super_block *sb,
+static int ext4_clear_journal_err(struct super_block *sb,
                                   struct ext4_super_block *es)
 {
        journal_t *journal;
        int j_errno;
        const char *errstr;
 
-       BUG_ON(!ext4_has_feature_journal(sb));
+       if (!ext4_has_feature_journal(sb)) {
+               ext4_error(sb, "Journal got removed while the fs was mounted!");
+               return -EFSCORRUPTED;
+       }
 
        journal = EXT4_SB(sb)->s_journal;
 
@@ -5315,6 +5638,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
                jbd2_journal_clear_err(journal);
                jbd2_journal_update_sb_errno(journal);
        }
+       return 0;
 }
 
 /*
@@ -5457,7 +5781,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
 {
        struct ext4_super_block *es;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       unsigned long old_sb_flags;
+       unsigned long old_sb_flags, vfs_flags;
        struct ext4_mount_options old_opts;
        int enable_quota = 0;
        ext4_group_t g;
@@ -5500,6 +5824,14 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        if (sbi->s_journal && sbi->s_journal->j_task->io_context)
                journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
 
+       /*
+        * Some options can be enabled by ext4 and/or by VFS mount flag
+        * either way we need to make sure it matches in both *flags and
+        * s_flags. Copy those selected flags from *flags to s_flags
+        */
+       vfs_flags = SB_LAZYTIME | SB_I_VERSION;
+       sb->s_flags = (sb->s_flags & ~vfs_flags) | (*flags & vfs_flags);
+
        if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) {
                err = -EINVAL;
                goto restore_opts;
@@ -5553,9 +5885,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
        }
 
-       if (*flags & SB_LAZYTIME)
-               sb->s_flags |= SB_LAZYTIME;
-
        if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
                if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
                        err = -EROFS;
@@ -5585,8 +5914,13 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                            (sbi->s_mount_state & EXT4_VALID_FS))
                                es->s_state = cpu_to_le16(sbi->s_mount_state);
 
-                       if (sbi->s_journal)
+                       if (sbi->s_journal) {
+                               /*
+                                * We let remount-ro finish even if marking fs
+                                * as clean failed...
+                                */
                                ext4_mark_recovery_complete(sb, es);
+                       }
                        if (sbi->s_mmp_tsk)
                                kthread_stop(sbi->s_mmp_tsk);
                } else {
@@ -5634,8 +5968,11 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                         * been changed by e2fsck since we originally mounted
                         * the partition.)
                         */
-                       if (sbi->s_journal)
-                               ext4_clear_journal_err(sb, es);
+                       if (sbi->s_journal) {
+                               err = ext4_clear_journal_err(sb, es);
+                               if (err)
+                                       goto restore_opts;
+                       }
                        sbi->s_mount_state = le16_to_cpu(es->s_state);
 
                        err = ext4_setup_super(sb, es, 0);
@@ -5665,7 +6002,17 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                ext4_register_li_request(sb, first_not_zeroed);
        }
 
-       ext4_setup_system_zone(sb);
+       /*
+        * Handle creation of system zone data early because it can fail.
+        * Releasing of existing data is done when we are sure remount will
+        * succeed.
+        */
+       if (test_opt(sb, BLOCK_VALIDITY) && !sbi->s_system_blks) {
+               err = ext4_setup_system_zone(sb);
+               if (err)
+                       goto restore_opts;
+       }
+
        if (sbi->s_journal == NULL && !(old_sb_flags & SB_RDONLY)) {
                err = ext4_commit_super(sb, 1);
                if (err)
@@ -5686,8 +6033,16 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                }
        }
 #endif
+       if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+               ext4_release_system_zone(sb);
+
+       /*
+        * Some options can be enabled by ext4 and/or by VFS mount flag
+        * either way we need to make sure it matches in both *flags and
+        * s_flags. Copy those selected flags from s_flags to *flags
+        */
+       *flags = (*flags & ~vfs_flags) | (sb->s_flags & vfs_flags);
 
-       *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
        ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
        kfree(orig_data);
        return 0;
@@ -5701,6 +6056,8 @@ restore_opts:
        sbi->s_commit_interval = old_opts.s_commit_interval;
        sbi->s_min_batch_time = old_opts.s_min_batch_time;
        sbi->s_max_batch_time = old_opts.s_max_batch_time;
+       if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+               ext4_release_system_zone(sb);
 #ifdef CONFIG_QUOTA
        sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
        for (i = 0; i < EXT4_MAXQUOTAS; i++) {
@@ -5931,6 +6288,11 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
        /* Quotafile not on the same filesystem? */
        if (path->dentry->d_sb != sb)
                return -EXDEV;
+
+       /* Quota already enabled for this file? */
+       if (IS_NOQUOTA(d_inode(path->dentry)))
+               return -EBUSY;
+
        /* Journaling quota? */
        if (EXT4_SB(sb)->s_qf_names[type]) {
                /* Quotafile not in fs root? */
@@ -6198,6 +6560,10 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        brelse(bh);
 out:
        if (inode->i_size < off + len) {
+               ext4_fc_track_range(inode,
+                       (inode->i_size > 0 ? inode->i_size - 1 : 0)
+                               >> inode->i_sb->s_blocksize_bits,
+                       (off + len) >> inode->i_sb->s_blocksize_bits);
                i_size_write(inode, off + len);
                EXT4_I(inode)->i_disksize = inode->i_size;
                err2 = ext4_mark_inode_dirty(handle, inode);
@@ -6326,6 +6692,11 @@ static int __init ext4_init_fs(void)
        err = init_inodecache();
        if (err)
                goto out1;
+
+       err = ext4_fc_init_dentry_cache();
+       if (err)
+               goto out05;
+
        register_as_ext3();
        register_as_ext2();
        err = register_filesystem(&ext4_fs_type);
@@ -6336,6 +6707,7 @@ static int __init ext4_init_fs(void)
 out:
        unregister_as_ext2();
        unregister_as_ext3();
+out05:
        destroy_inodecache();
 out1:
        ext4_exit_mballoc();