summaryrefslogtreecommitdiffstats
path: root/crypto/ripemd.h
diff options
context:
space:
mode:
authorWang Xiaoguang <wangxg.fnst@cn.fujitsu.com>2016-06-22 09:57:01 +0800
committerChris Mason <clm@fb.com>2016-06-23 10:44:41 -0700
commitc0d2f6104e8ab2eb75e58e72494ad4b69c5227f8 (patch)
tree073eb178e3bcd74405321ddd40284b06771b8f12 /crypto/ripemd.h
parent415b35a55b57a701afe7391d32a6bb0193b7d3da (diff)
downloadlinux-c0d2f6104e8ab2eb75e58e72494ad4b69c5227f8.tar.gz
linux-c0d2f6104e8ab2eb75e58e72494ad4b69c5227f8.tar.bz2
linux-c0d2f6104e8ab2eb75e58e72494ad4b69c5227f8.zip
btrfs: fix disk_i_size update bug when fallocate() fails
When doing truncate operation, btrfs_setsize() will first call truncate_setsize() to set new inode->i_size, but if later btrfs_truncate() fails, btrfs_setsize() will call "i_size_write(inode, BTRFS_I(inode)->disk_i_size)" to reset the inmemory inode size, now bug occurs. It's because for truncate case btrfs_ordered_update_i_size() directly uses inode->i_size to update BTRFS_I(inode)->disk_i_size, indeed we should use the "offset" argument to update disk_i_size. Here is the call graph: ==>btrfs_truncate() ====>btrfs_truncate_inode_items() ======>btrfs_ordered_update_i_size(inode, last_size, NULL); Here btrfs_ordered_update_i_size()'s offset argument is last_size. And below test case can reveal this bug: dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100 dev=$(losetup --show -f fs.img) mkdir -p /mnt/mntpoint mkfs.btrfs -f $dev mount $dev /mnt/mntpoint cd /mnt/mntpoint echo "workdir is: /mnt/mntpoint" blocksize=$((128 * 1024)) dd if=/dev/zero of=testfile bs=$blocksize count=1 sync count=$((17*1024*1024*1024/blocksize)) echo "file size is:" $((count*blocksize)) for ((i = 1; i <= $count; i++)); do i=$((i + 1)) dst_offset=$((blocksize * i)) xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\ testfile > /dev/null done sync truncate --size 0 testfile ls -l testfile du -sh testfile exit In this case, truncate operation will fail for enospc reason and "du -sh testfile" returns value greater than 0, but testfile's size is 0, we need to reflect correct inode->i_size. Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'crypto/ripemd.h')
0 files changed, 0 insertions, 0 deletions