linux/fs/btrfs
Filipe Manana 089699ed8b Btrfs: update fix for read corruption of compressed and shared extents
[ Upstream commit 808f80b467 ]

My previous fix in commit 005efedf2c ("Btrfs: fix read corruption of
compressed and shared extents") was effective only if the compressed
extents cover a file range with a length that is not a multiple of 16
pages. That's because the detection of when we reached a different range
of the file that shares the same compressed extent as the previously
processed range was done at extent_io.c:__do_contiguous_readpages(),
which covers subranges with a length up to 16 pages, because
extent_readpages() groups the pages in clusters no larger than 16 pages.
So fix this by tracking the start of the previously processed file
range's extent map at extent_readpages().

The following test case for fstests reproduces the issue:

  seq=`basename $0`
  seqres=$RESULT_DIR/$seq
  echo "QA output created by $seq"
  tmp=/tmp/$$
  status=1	# failure is the default!
  trap "_cleanup; exit \$status" 0 1 2 3 15

  _cleanup()
  {
      rm -f $tmp.*
  }

  # get standard environment, filters and checks
  . ./common/rc
  . ./common/filter

  # real QA test starts here
  _need_to_be_root
  _supported_fs btrfs
  _supported_os Linux
  _require_scratch
  _require_cloner

  rm -f $seqres.full

  test_clone_and_read_compressed_extent()
  {
      local mount_opts=$1

      _scratch_mkfs >>$seqres.full 2>&1
      _scratch_mount $mount_opts

      # Create our test file with a single extent of 64Kb that is going to
      # be compressed no matter which compression algo is used (zlib/lzo).
      $XFS_IO_PROG -f -c "pwrite -S 0xaa 0K 64K" \
          $SCRATCH_MNT/foo | _filter_xfs_io

      # Now clone the compressed extent into an adjacent file offset.
      $CLONER_PROG -s 0 -d $((64 * 1024)) -l $((64 * 1024)) \
          $SCRATCH_MNT/foo $SCRATCH_MNT/foo

      echo "File digest before unmount:"
      md5sum $SCRATCH_MNT/foo | _filter_scratch

      # Remount the fs or clear the page cache to trigger the bug in
      # btrfs. Because the extent has an uncompressed length that is a
      # multiple of 16 pages, all the pages belonging to the second range
      # of the file (64K to 128K), which points to the same extent as the
      # first range (0K to 64K), had their contents full of zeroes instead
      # of the byte 0xaa. This was a bug exclusively in the read path of
      # compressed extents, the correct data was stored on disk, btrfs
      # just failed to fill in the pages correctly.
      _scratch_remount

      echo "File digest after remount:"
      # Must match the digest we got before.
      md5sum $SCRATCH_MNT/foo | _filter_scratch
  }

  echo -e "\nTesting with zlib compression..."
  test_clone_and_read_compressed_extent "-o compress=zlib"

  _scratch_unmount

  echo -e "\nTesting with lzo compression..."
  test_clone_and_read_compressed_extent "-o compress=lzo"

  status=0
  exit

Cc: stable@vger.kernel.org
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Tested-by: Timofey Titovets <nefelim4ag@gmail.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
History 2015-10-27 22:13:27 -04:00
..
tests Btrfs: remove empty block groups automatically 2014-09-22 17:13:21 -07:00
acl.c btrfs: remove useless ACL check 2014-06-09 17:20:42 -07:00
async-thread.c btrfs: remove unlikely from NULL checks 2014-10-02 16:06:19 +02:00
async-thread.h Btrfs: implement repair function when direct read fails 2014-09-17 13:39:01 -07:00
backref.c btrfs: remove parameter blocksize from read_tree_block 2014-10-02 17:14:50 +02:00
backref.h Btrfs: make fiemap not blow when you have lots of snapshots 2014-09-17 13:38:24 -07:00
btrfs_inode.h Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs 2014-10-11 08:03:52 -04:00
check-integrity.c Btrfs: fix wrong disk size when writing super blocks 2014-09-17 13:38:33 -07:00
check-integrity.h block: submit_bio_wait() conversions 2013-11-24 16:33:41 -07:00
compression.c btrfs: zero out left over bytes after processing compression streams 2014-11-30 09:33:51 -08:00
compression.h btrfs: zero out left over bytes after processing compression streams 2014-11-30 09:33:51 -08:00
ctree.c Btrfs: make xattr replace operations atomic 2015-07-13 08:50:06 -04:00
ctree.h Btrfs: make xattr replace operations atomic 2015-07-13 08:50:06 -04:00
delayed-inode.c Btrfs: don't delay inode ref updates during log replay 2015-01-16 06:59:56 -08:00
delayed-inode.h Btrfs: introduce the delayed inode ref deletion for the single link inode 2014-01-28 13:20:09 -08:00
delayed-ref.c Btrfs: rework qgroup accounting 2014-06-09 17:20:48 -07:00
delayed-ref.h Btrfs: rework qgroup accounting 2014-06-09 17:20:48 -07:00
dev-replace.c Btrfs: make the logic of source device removing more clear 2014-09-17 13:38:46 -07:00
dev-replace.h Btrfs: add new sources for device replace code 2012-12-12 17:15:41 -05:00
dir-item.c Btrfs: make xattr replace operations atomic 2015-07-13 08:50:06 -04:00
disk-io.c btrfs: fix leak of path in btrfs_find_item 2015-03-06 14:53:05 -08:00
disk-io.h Merge branch 'cleanup/blocksize-diet-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus 2014-10-04 09:57:14 -07:00
export.c btrfs: kill the key type accessor helpers 2014-09-17 13:37:12 -07:00
export.h NFS support for btrfs - v3 2008-09-25 11:04:06 -04:00
extent-tree.c Btrfs: fix log tree corruption when fs mounted with -o discard 2015-05-17 19:11:46 -04:00
extent_io.c Btrfs: update fix for read corruption of compressed and shared extents 2015-10-27 22:13:27 -04:00
extent_io.h Btrfs: fix compiles when CONFIG_BTRFS_FS_RUN_SANITY_TESTS is off 2014-10-07 13:24:20 -07:00
extent_map.c Btrfs: do not move em to modified list when unpinning 2015-01-08 10:30:30 -08:00
extent_map.h Btrfs: fix NULL pointer crash when running balance and scrub concurrently 2014-06-19 14:20:55 -07:00
file-item.c Btrfs: fix kfree on list_head in btrfs_lookup_csums_range error cleanup 2014-11-04 06:59:04 -08:00
file.c Btrfs: fix data loss in the fast fsync path 2015-03-14 15:37:22 -04:00
free-space-cache.c Btrfs: improve free space cache management and space allocation 2014-09-17 13:38:13 -07:00
free-space-cache.h Btrfs: remove path arg from btrfs_truncate_free_space_cache 2013-11-11 21:51:33 -05:00
hash.c btrfs: LLVMLinux: Remove VLAIS 2014-10-14 10:51:22 +02:00
hash.h Btrfs: fix btrfs boot when compiled as built-in 2014-01-28 13:20:31 -08:00
inode-item.c btrfs: kill the key type accessor helpers 2014-09-17 13:37:12 -07:00
inode-map.c Btrfs: use kmem_cache_free when freeing entry in inode cache 2015-08-04 14:32:21 -04:00
inode-map.h Btrfs: Support reading/writing on disk free ino cache 2011-04-25 16:46:11 +08:00
inode.c btrfs: skip waiting on ordered range for special files 2015-10-27 22:13:25 -04:00
ioctl.c Btrfs: fix memory leak in the extent_same ioctl 2015-08-04 14:32:42 -04:00
Kconfig Btrfs: fix btrfs boot when compiled as built-in 2014-01-28 13:20:31 -08:00
locking.c btrfs: fix lockups from btrfs_clear_path_blocking 2014-11-19 10:34:35 -08:00
locking.h btrfs: fix lockups from btrfs_clear_path_blocking 2014-11-19 10:34:35 -08:00
lzo.c btrfs: zero out left over bytes after processing compression streams 2014-11-30 09:33:51 -08:00
Makefile Btrfs: add sanity tests for new qgroup accounting code 2014-06-09 17:20:49 -07:00
math.h Btrfs: cleanup duplicated division functions 2012-12-11 13:31:30 -05:00
ordered-data.c Btrfs: fix fsync race leading to ordered extent memory leaks 2015-03-14 15:37:21 -04:00
ordered-data.h Btrfs: make sure logged extents complete in the current transaction V3 2015-01-08 10:30:30 -08:00
orphan.c btrfs: kill the key type accessor helpers 2014-09-17 13:37:12 -07:00
print-tree.c btrfs: remove parameter blocksize from read_tree_block 2014-10-02 17:14:50 +02:00
print-tree.h btrfs: make static code static & remove dead code 2013-05-06 15:55:23 -04:00
props.c Btrfs: add support for inode properties 2014-01-28 13:20:24 -08:00
props.h Btrfs: add support for inode properties 2014-01-28 13:20:24 -08:00
qgroup.c btrfs: move checks for DUMMY_ROOT into a helper 2014-10-02 17:30:33 +02:00
qgroup.h btrfs: qgroup: account shared subtrees during snapshot delete 2014-08-15 07:43:14 -07:00
raid56.c btrfs: use DIV_ROUND_UP instead of open-coded variants 2014-09-17 13:37:17 -07:00
raid56.h Btrfs: RAID5 and RAID6 2013-02-01 14:24:23 -05:00
rcu-string.h Btrfs: use rcu to protect device->name 2012-06-14 21:29:16 -04:00
reada.c btrfs: use nodesize everywhere, kill leafsize 2014-09-17 13:37:14 -07:00
relocation.c Merge branch 'cleanup/blocksize-diet-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus 2014-10-04 09:57:14 -07:00
root-tree.c Btrfs: use bitfield instead of integer data type for the some variants in btrfs_root 2014-06-09 17:20:40 -07:00
scrub.c btrfs: remove unused members from struct scrub_warning 2014-10-02 17:30:30 +02:00
send.c Merge branch 'cleanup/misc-for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus 2014-10-04 09:56:45 -07:00
send.h btrfs: make static code static & remove dead code 2013-05-06 15:55:23 -04:00
struct-funcs.c Btrfs: rewrite BTRFS_SETGET_FUNCS 2012-07-23 16:28:06 -04:00
super.c btrfs: cleanup orphans while looking up default subvolume 2015-08-27 13:25:56 -04:00
sysfs.c btrfs: sysfs label interface should check for read only FS 2014-09-17 13:38:01 -07:00
sysfs.h btrfs: code optimize: BTRFS_ATTR_RW could set the mode 2014-09-17 13:37:59 -07:00
transaction.c Btrfs: check if previous transaction aborted to avoid fs corruption 2015-10-07 10:16:46 -04:00
transaction.h Btrfs: make sure logged extents complete in the current transaction V3 2015-01-08 10:30:30 -08:00
tree-defrag.c Btrfs: use bitfield instead of integer data type for the some variants in btrfs_root 2014-06-09 17:20:40 -07:00
tree-log.c btrfs: simplify insert_orphan_item 2015-04-23 14:58:24 -04:00
tree-log.h Btrfs: fix data corruption after fast fsync and writeback error 2014-09-19 06:57:51 -07:00
ulist.c Btrfs: do not export ulist functions 2014-01-29 07:06:27 -08:00
ulist.h Btrfs: Fix memory corruption by ulist_add_merge() on 32bit arch 2014-08-15 07:43:19 -07:00
uuid-tree.c Btrfs: make btrfs_search_forward return with nodes unlocked 2014-09-17 13:38:02 -07:00
volumes.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs 2014-10-11 08:03:52 -04:00
volumes.h Btrfs: remove empty block groups automatically 2014-09-22 17:13:21 -07:00
xattr.c Btrfs: make xattr replace operations atomic 2015-07-13 08:50:06 -04:00
xattr.h btrfs: use generic posix ACL infrastructure 2014-01-25 23:58:18 -05:00
zlib.c btrfs: zero out left over bytes after processing compression streams 2014-11-30 09:33:51 -08:00