aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2011-09-18 10:20:46 -0400
committerChris Mason <chris.mason@oracle.com>2011-09-18 10:20:46 -0400
commit0e7b824c4ef9f5bcf5e48cdce164a7b349dde969 (patch)
treed2f11b5f8ddde4bda00798a09b5e2233766f3874
parent71ef07861080418d125dcf454af41baafa409a2c (diff)
Btrfs: don't make a file partly checksummed through file clone
To reproduce the bug: # mount /dev/sda7 /mnt # dd if=/dev/zero of=/mnt/src bs=4K count=1 # umount /mnt # mount -o nodatasum /dev/sda7 /mnt # dd if=/dev/zero of=/mnt/dst bs=4K count=1 # clone_range -s 4K -l 4K /mnt/src /mnt/dst # echo 3 > /proc/sys/vm/drop_caches # cat /mnt/dst # dmesg ... btrfs no csum found for inode 258 start 0 btrfs csum failed ino 258 off 0 csum 2566472073 private 0 It's because part of the file is checksummed and the other part is not, and then btrfs will complain checksum is not found when we read the file. Disallow file clone if src and dst file have different checksum flag, so we ensure a file is completely checksummed or unchecksummed. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ioctl.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 8bfb514b26c9..1e766e86f334 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2185,6 +2185,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2185 if (!(src_file->f_mode & FMODE_READ)) 2185 if (!(src_file->f_mode & FMODE_READ))
2186 goto out_fput; 2186 goto out_fput;
2187 2187
2188 /* don't make the dst file partly checksummed */
2189 if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
2190 (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
2191 goto out_fput;
2192
2188 ret = -EISDIR; 2193 ret = -EISDIR;
2189 if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) 2194 if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
2190 goto out_fput; 2195 goto out_fput;