ext4: recalculate journal credits as inode depth changes
[firefly-linux-kernel-4.4.55.git] / fs / ext4 / extents.c
index 08f5afc95c88893c33a50cf37ea74deb434e35cc..fc76bda13852546fabfe3c1ddac96850e0b119b4 100644 (file)
@@ -4663,6 +4663,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
        int ret = 0;
        int ret2 = 0;
        int retries = 0;
+       int depth = 0;
        struct ext4_map_blocks map;
        unsigned int credits;
        loff_t epos;
@@ -4681,9 +4682,24 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
         * credits to insert 1 extent into extent tree
         */
        credits = ext4_chunk_trans_blocks(inode, len);
+       /*
+        * We can only call ext_depth() on extent based inodes
+        */
+       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+               depth = ext_depth(inode);
+       else
+               depth = -1;
 
 retry:
        while (ret >= 0 && len) {
+               /*
+                * Recalculate credits when extent tree depth changes.
+                */
+               if (depth >= 0 && depth != ext_depth(inode)) {
+                       credits = ext4_chunk_trans_blocks(inode, len);
+                       depth = ext_depth(inode);
+               }
+
                handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
                                            credits);
                if (IS_ERR(handle)) {