• Filipe Manana's avatar
    Btrfs: fix extent_same allowing destination offset beyond i_size · f4dfe687
    Filipe Manana authored
    When using the same file as the source and destination for a dedup
    (extent_same ioctl) operation we were allowing it to dedup to a
    destination offset beyond the file's size, which doesn't make sense and
    it's not allowed for the case where the source and destination files are
    not the same file. This made de deduplication operation successful only
    when the source range corresponded to a hole, a prealloc extent or an
    extent with all bytes having a value of 0x00. This was also leaving a
    file hole (between i_size and destination offset) without the
    corresponding file extent items, which can be reproduced with the
    following steps for example:
    
      $ mkfs.btrfs -f /dev/sdi
      $ mount /dev/sdi /mnt/sdi
    
      $ xfs_io -f -c "pwrite -S 0xab 304457 404990" /mnt/sdi/foobar
      wrote 404990/404990 bytes at offset 304457
      395 KiB, 99 ops; 0.0000 sec (31.150 MiB/sec and 7984.5149 ops/sec)
    
      $ /git/hub/duperemove/btrfs-extent-same 24576 /mnt/sdi/foobar 28672 /mnt/sdi/foobar 929792
      Deduping 2 total files
      (28672, 24576): /mnt/sdi/foobar
      (929792, 24576): /mnt/sdi/foobar
      1 files asked to be deduped
      i: 0, status: 0, bytes_deduped: 24576
      24576 total bytes deduped in this operation
    
      $ umount /mnt/sdi
      $ btrfsck /dev/sdi
      Checking filesystem on /dev/sdi
      UUID: 98c528aa-0833-427d-9403-b98032ffbf9d
      checking extents
      checking free space cache
      checking fs roots
      root 5 inode 257 errors 100, file extent discount
      Found file extent holes:
              start: 712704, len: 217088
      found 540673 bytes used err is 1
      total csum bytes: 400
      total tree bytes: 131072
      total fs tree bytes: 32768
      total extent tree bytes: 16384
      btree space waste bytes: 123675
      file data blocks allocated: 671744
        referenced 671744
      btrfs-progs v4.2.3
    
    So fix this by not allowing the destination to go beyond the file's size,
    just as we do for the same where the source and destination files are not
    the same.
    
    A test for xfstests follows.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    f4dfe687
ioctl.c 135 KB