]> git.baikalelectronics.ru Git - kernel.git/commit
btrfs: inode: Don't compress if NODATASUM or NODATACOW set
authorQu Wenruo <wqu@suse.com>
Mon, 1 Jul 2019 05:12:46 +0000 (05:12 +0000)
committerDavid Sterba <dsterba@suse.com>
Wed, 17 Jul 2019 15:03:28 +0000 (17:03 +0200)
commit9e45b2ccd63a74a3b10eba8ed77d52c57c293c2d
treefa1892839dfeb4163901a3789a4bc589f2216f38
parentf1657ffac40dae5ba9e3615ca54716bcf78c397c
btrfs: inode: Don't compress if NODATASUM or NODATACOW set

As btrfs(5) specified:

Note
If nodatacow or nodatasum are enabled, compression is disabled.

If NODATASUM or NODATACOW set, we should not compress the extent.

Normally NODATACOW is detected properly in run_delalloc_range() so
compression won't happen for NODATACOW.

However for NODATASUM we don't have any check, and it can cause
compressed extent without csum pretty easily, just by:
  mkfs.btrfs -f $dev
  mount $dev $mnt -o nodatasum
  touch $mnt/foobar
  mount -o remount,datasum,compress $mnt
  xfs_io -f -c "pwrite 0 128K" $mnt/foobar

And in fact, we have a bug report about corrupted compressed extent
without proper data checksum so even RAID1 can't recover the corruption.
(https://bugzilla.kernel.org/show_bug.cgi?id=199707)

Running compression without proper checksum could cause more damage when
corruption happens, as compressed data could make the whole extent
unreadable, so there is no need to allow compression for
NODATACSUM.

The fix will refactor the inode compression check into two parts:

- inode_can_compress()
  As the hard requirement, checked at btrfs_run_delalloc_range(), so no
  compression will happen for NODATASUM inode at all.

- inode_need_compress()
  As the soft requirement, checked at btrfs_run_delalloc_range() and
  compress_file_range().

Reported-by: James Harvey <jamespharvey20@gmail.com>
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c