Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5208386c authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o
Browse files

ext4: simplify truncation code in ext4_setattr()



Merge conditions in ext4_setattr() handling inode size changes, also
move ext4_begin_ordered_truncate() call somewhat earlier because it
simplifies error recovery in case of failure. Also add error handling in
case i_disksize update fails.

Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
parent 5f1132b2
Loading
Loading
Loading
Loading
+49 −60
Original line number Diff line number Diff line
@@ -4600,7 +4600,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
		ext4_journal_stop(handle);
	}

	if (attr->ia_valid & ATTR_SIZE) {
	if (attr->ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
		handle_t *handle;
		loff_t oldsize = inode->i_size;

		if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
			struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -4608,13 +4610,14 @@ 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) &&
	    attr->ia_valid & ATTR_SIZE &&
		    (attr->ia_size < inode->i_size)) {
		handle_t *handle;

			if (ext4_should_order_data(inode)) {
				error = ext4_begin_ordered_truncate(inode,
							    attr->ia_size);
				if (error)
					goto err_out;
			}
			handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
			if (IS_ERR(handle)) {
				error = PTR_ERR(handle);
@@ -4629,29 +4632,11 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
			if (!error)
				error = rc;
			ext4_journal_stop(handle);

		if (ext4_should_order_data(inode)) {
			error = ext4_begin_ordered_truncate(inode,
							    attr->ia_size);
			if (error) {
				/* Do as much error cleanup as possible */
				handle = ext4_journal_start(inode,
							    EXT4_HT_INODE, 3);
				if (IS_ERR(handle)) {
				ext4_orphan_del(NULL, inode);
				goto err_out;
			}
				ext4_orphan_del(handle, inode);
				orphan = 0;
				ext4_journal_stop(handle);
				goto err_out;
			}
		}
	}

	if (attr->ia_valid & ATTR_SIZE) {
		if (attr->ia_size != inode->i_size) {
			loff_t oldsize = inode->i_size;

		i_size_write(inode, attr->ia_size);
		/*
@@ -4673,8 +4658,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
		 */
		truncate_pagecache(inode, oldsize, inode->i_size);
	}
	/*
	 * 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);