ext4: fix incorect journal credits reservation in ext4_zero_range
[linux-2.6-microblaze.git] / fs / ext4 / extents.c
index 76c2df3..0e9de23 100644 (file)
@@ -4731,6 +4731,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        loff_t new_size = 0;
        int ret = 0;
        int flags;
+       int credits;
        int partial;
        loff_t start, end;
        ext4_lblk_t lblk;
@@ -4830,8 +4831,14 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                if (ret)
                        goto out_dio;
        }
-
-       handle = ext4_journal_start(inode, EXT4_HT_MISC, 4);
+       /*
+        * In worst case we have to writeout two nonadjacent unwritten
+        * blocks and update the inode
+        */
+       credits = (2 * ext4_ext_index_trans_blocks(inode, 2)) + 1;
+       if (ext4_should_journal_data(inode))
+               credits += 2;
+       handle = ext4_journal_start(inode, EXT4_HT_MISC, credits);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                ext4_std_error(inode->i_sb, ret);
@@ -4839,12 +4846,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        }
 
        inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-
        if (new_size) {
-               if (new_size > i_size_read(inode))
-                       i_size_write(inode, new_size);
-               if (new_size > EXT4_I(inode)->i_disksize)
-                       ext4_update_i_disksize(inode, new_size);
+               ext4_update_inode_size(inode, new_size);
        } else {
                /*
                * Mark that we allocate beyond EOF so the subsequent truncate
@@ -4886,7 +4889,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        int ret = 0;
        int flags;
        ext4_lblk_t lblk;
-       struct timespec tv;
        unsigned int blkbits = inode->i_blkbits;
 
        /* Return error if mode is not supported */
@@ -4945,15 +4947,11 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (IS_ERR(handle))
                goto out;
 
-       tv = inode->i_ctime = ext4_current_time(inode);
+       inode->i_ctime = ext4_current_time(inode);
 
        if (new_size) {
-               if (new_size > i_size_read(inode)) {
-                       i_size_write(inode, new_size);
-                       inode->i_mtime = tv;
-               }
-               if (new_size > EXT4_I(inode)->i_disksize)
-                       ext4_update_i_disksize(inode, new_size);
+               if (ext4_update_inode_size(inode, new_size) & 0x1)
+                       inode->i_mtime = inode->i_ctime;
        } else {
                /*
                * Mark that we allocate beyond EOF so the subsequent truncate