All of lore.kernel.org
 help / color / mirror / Atom feed
* Please backport to 3.18: ext4: only call ext4_truncate when size <= isize
@ 2017-10-07 20:33 Theodore Ts'o
  2017-10-10 18:02 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: Theodore Ts'o @ 2017-10-07 20:33 UTC (permalink / raw)
  To: stable


Hi, I'd appreciate it if you could backport upstream commit:

   3da40c7b0898: ext4: only call ext4_truncate when size <= isize

to the 3.18.xstable kernel series.  This fixes an xfstests test
failure: generic/092

Enclosed is the backport for 3.18, since the upstream commit doesn't
apply automatically.

This commit is also needed for the 4.1 LTS kernel, although it also
doesn't apply cleanly from the upstream commit and requires a slightly
different backport.  I'll send that under separate cover.

Thanks,

	  	     	       	    	  - Ted


>From dbc77025fb72f337d529c9033453ec467aa111cc Mon Sep 17 00:00:00 2001
From: Josef Bacik <jbacik@fb.com>
Date: Mon, 22 Jun 2015 00:31:26 -0400
Subject: [PATCH] ext4: only call ext4_truncate when size <= isize

[ Upstream commit 3da40c7b089810ac9cf2bb1e59633f619f3a7312 ]

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 ]

Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Lukas Czerner <lczerner@redhat.com>
---
 fs/ext4/inode.c | 40 +++++++++++++++++++---------------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 39a263ecca18..876cd195995a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4534,8 +4534,10 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 		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, struct iattr *attr)
 			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, struct iattr *attr)
 			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, struct iattr *attr)
 		 * 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);
-- 
2.11.0.rc0.7.gbe5a750

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: Please backport to 3.18: ext4: only call ext4_truncate when size <= isize
  2017-10-07 20:33 Please backport to 3.18: ext4: only call ext4_truncate when size <= isize Theodore Ts'o
@ 2017-10-10 18:02 ` Greg KH
  0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2017-10-10 18:02 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: stable

On Sat, Oct 07, 2017 at 04:33:44PM -0400, Theodore Ts'o wrote:
> 
> Hi, I'd appreciate it if you could backport upstream commit:
> 
>    3da40c7b0898: ext4: only call ext4_truncate when size <= isize
> 
> to the 3.18.xstable kernel series.  This fixes an xfstests test
> failure: generic/092

Now applied, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-10-10 18:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-07 20:33 Please backport to 3.18: ext4: only call ext4_truncate when size <= isize Theodore Ts'o
2017-10-10 18:02 ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.