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

Commit f4a2f4c5 authored by Miao Xie's avatar Miao Xie Committed by Chris Mason
Browse files

Btrfs: fix wrong i_size when truncating a file to a larger size



Btrfsck report error 100 after the 83th case of xfstests was run, it means
the i_size of the file is wrong.

The reason of this bug is that:
Btrfs increased i_size of the file at the beginning, but it failed to expand
the file, and failed to update the i_size to the old size because there is no
enough space in the file system, so we found a wrong i_size.

This patch fixes this bug by updating the i_size just when we pass the file
expanding and get enough space to update i-node.

Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 5dbc8fca
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -3370,6 +3370,8 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)

static int btrfs_setsize(struct inode *inode, loff_t newsize)
{
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_trans_handle *trans;
	loff_t oldsize = i_size_read(inode);
	int ret;

@@ -3377,16 +3379,20 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize)
		return 0;

	if (newsize > oldsize) {
		i_size_write(inode, newsize);
		btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
		truncate_pagecache(inode, oldsize, newsize);
		ret = btrfs_cont_expand(inode, oldsize, newsize);
		if (ret) {
			btrfs_setsize(inode, oldsize);
		if (ret)
			return ret;
		}

		mark_inode_dirty(inode);
		trans = btrfs_start_transaction(root, 1);
		if (IS_ERR(trans))
			return PTR_ERR(trans);

		i_size_write(inode, newsize);
		btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
		ret = btrfs_update_inode(trans, root, inode);

		btrfs_end_transaction_throttle(trans, root);
	} else {

		/*