Unverified Commit 0e8f4e8e authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12223 [sync] PR-11910: ext4: dax: Fix inconsistent isize during writing

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/11910 
 
PR sync from: Zhihao Cheng <chengzhihao@huaweicloud.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/E6NTY3E72MOOC534KCWL2HSQG7VBVPK7/ 
From: Zhihao Cheng <chengzhihao1@huawei.com>

Zhihao Cheng (1):
  ext4: dax: fix overflowing extents beyond inode size when partially
    writing

yangerkun (1):
  ext4: dax: keep orphan list before truncate overflow allocated blocks


-- 
2.39.2
 
https://gitee.com/openeuler/kernel/issues/IAU1DM 
 
Link:https://gitee.com/openeuler/kernel/pulls/12223

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents b1bdb805 7b9259de
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -328,7 +328,7 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,
}

static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
					   ssize_t count)
					   ssize_t written, ssize_t count)
{
	handle_t *handle;

@@ -337,7 +337,7 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
	if (IS_ERR(handle))
		return PTR_ERR(handle);

	if (ext4_update_inode_size(inode, offset + count)) {
	if (ext4_update_inode_size(inode, offset + written)) {
		int ret = ext4_mark_inode_dirty(handle, inode);
		if (unlikely(ret)) {
			ext4_journal_stop(handle);
@@ -345,21 +345,21 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
		}
	}

	if (inode->i_nlink)
	if ((written == count) && inode->i_nlink)
		ext4_orphan_del(handle, inode);
	ext4_journal_stop(handle);

	return count;
	return written;
}

/*
 * Clean up the inode after DIO or DAX extending write has completed and the
 * inode size has been updated using ext4_handle_inode_extension().
 */
static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
static void ext4_inode_extension_cleanup(struct inode *inode, bool need_trunc)
{
	lockdep_assert_held_write(&inode->i_rwsem);
	if (count < 0) {
	if (need_trunc) {
		ext4_truncate_failed_write(inode);
		/*
		 * If the truncate operation failed early, then the inode may
@@ -415,7 +415,7 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
	if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize) &&
	    pos + size <= i_size_read(inode))
		return size;
	return ext4_handle_inode_extension(inode, pos, size);
	return ext4_handle_inode_extension(inode, pos, size, size);
}

static const struct iomap_dio_ops ext4_dio_write_ops = {
@@ -608,7 +608,7 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
		 * writeback of delalloc blocks.
		 */
		WARN_ON_ONCE(ret == -EIOCBQUEUED);
		ext4_inode_extension_cleanup(inode, ret);
		ext4_inode_extension_cleanup(inode, ret < 0);
	}

out:
@@ -691,8 +691,8 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
	ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops);

	if (extend) {
		ret = ext4_handle_inode_extension(inode, offset, ret);
		ext4_inode_extension_cleanup(inode, ret);
		ret = ext4_handle_inode_extension(inode, offset, ret, count);
		ext4_inode_extension_cleanup(inode, ret < (ssize_t)count);
	}
out:
	inode_unlock(inode);