Patch "ext4: only call ext4_truncate when size <= isize" has been added to the 3.18-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ext4: only call ext4_truncate when size <= isize
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ext4-only-call-ext4_truncate-when-size-isize.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
3da40c7b089810ac9cf2bb1e59633f619f3a7312Mon Sep 17 00:00:00 2001
From: Josef Bacik <[email protected]>
Date: Mon, 22 Jun 2015 00:31:26 -0400
Subject: ext4: only call ext4_truncate when size <= isize
From: Josef Bacik <[email protected]>
commit 3da40c7b089810ac9cf2bb1e59633f619f3a7312 upstream.
At LSF we decided that if we truncate up from isize we shouldn't trim fallocated blocks that were fallocated with KEEP_SIZE and are past the new i_size. This patch fixes ext4 to do this.
[ Completely reworked patch so that i_disksize would actually get set
when truncating up. Also reworked the code for handling truncate so that it's easier to handle. -- tytso ]
--- fs/ext4/inode.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-)
fs/ext4/inode.c +19 -21
@@ -4534,8 +4534,10 @@ int ext4_setattr(struct dentry *dentry,ext4_journal_stop (handle); } -if (attr->ia_valid &ATTR_SIZE && attr->ia_size != inode->i_size) { +if (attr->ia_valid &ATTR_SIZE ) {handle_t *handle; +loff_t oldsize = inode->i_size; +int shrink = (attr->ia_size <= inode->i_size);if (!(ext4_test_inode_flag (inode,EXT4_INODE_EXTENTS ))) {struct ext4_sb_info *sbi =EXT4_SB (inode->i_sb);
@@ -4543,24 +4545,26 @@ int ext4_setattr(struct dentry *dentry,if (attr->ia_size > sbi->s_bitmap_maxbytes)return -EFBIG ; } +if (!S_ISREG (inode->i_mode)) +return -EINVAL ;if (IS_I_VERSION (inode) && attr->ia_size != inode->i_size)inode_inc_iversion (inode); -if (S_ISREG (inode->i_mode) && +if (ext4_should_order_data (inode) && (attr->ia_size < inode->i_size)) { -if (ext4_should_order_data (inode)) { - error =ext4_begin_ordered_truncate (inode, + error =ext4_begin_ordered_truncate (inode, attr->ia_size); -if (error) - goto err_out; - } +if (error) + goto err_out; + } +if (attr->ia_size != inode->i_size) { handle =ext4_journal_start (inode,EXT4_HT_INODE ,3 );if (IS_ERR (handle)) { error =PTR_ERR (handle); goto err_out; } -if (ext4_handle_valid (handle)) { +if (ext4_handle_valid (handle) && shrink) { error =ext4_orphan_add (handle, inode); orphan =1 ; }
@@ -4579,15 +4583,13 @@ int ext4_setattr(struct dentry *dentry,up_write (&EXT4_I (inode)->i_data_sem);ext4_journal_stop (handle);if (error) { -ext4_orphan_del (NULL , inode); +if (orphan) +ext4_orphan_del (NULL , inode); goto err_out; } - }else { -loff_t oldsize = inode->i_size; - -i_size_write (inode, attr->ia_size); -pagecache_isize_extended (inode, oldsize, inode->i_size); } +if (!shrink) +pagecache_isize_extended (inode, oldsize, inode->i_size);/* * Blocks are going to be removed from the inode. Wait
@@ -4606,14 +4608,10 @@ int ext4_setattr(struct dentry *dentry,* Truncate pagecache after we've waited for commit * in data=journal mode to make pages freeable. */ -truncate_pagecache (inode, inode->i_size); +truncate_pagecache (inode, inode->i_size); +if (shrink) +ext4_truncate (inode); } -/* -* We want to call ext4_truncate() even if attr->ia_size == -* inode->i_size for cases like truncation of fallocated space -*/ -if (attr->ia_valid &ATTR_SIZE ) -ext4_truncate (inode);if (!rc) {setattr_copy (inode, attr);
Patches currently in stable-queue which might be from [email protected] are
queue-3.18/ext4-only-call-ext4_truncate-when-size-isize.patch