No description
  • C 98.2%
  • Assembly 1%
  • Makefile 0.3%
  • Shell 0.2%
  • Python 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Filipe Manana e167468cc4 Btrfs: fix cloning range with a hole when using the NO_HOLES feature
[ Upstream commit fcb970581dd900675c4371c2b688a57924a8368c ]

When using the NO_HOLES feature if we clone a range that contains a hole
and a temporary ENOSPC happens while dropping extents from the target
inode's range, we can end up failing and aborting the transaction with
-EEXIST or with a corrupt file extent item, that has a length greater
than it should and overlaps with other extents. For example when cloning
the following range from inode A to inode B:

  Inode A:

    extent A1                                          extent A2
  [ ----------- ]  [ hole, implicit, 4MB length ]  [ ------------- ]
  0            1MB                                 5MB            6MB

  Range to clone: [1MB, 6MB)

  Inode B:

    extent B1       extent B2        extent B3         extent B4
  [ ---------- ]  [ --------- ]    [ ---------- ]    [ ---------- ]
  0           1MB 1MB        2MB   2MB        5MB    5MB         6MB

  Target range: [1MB, 6MB) (same as source, to make it easier to explain)

The following can happen:

1) btrfs_punch_hole_range() gets -ENOSPC from __btrfs_drop_extents();

2) At that point, 'cur_offset' is set to 1MB and __btrfs_drop_extents()
   set 'drop_end' to 2MB, meaning it was able to drop only extent B2;

3) We then compute 'clone_len' as 'drop_end' - 'cur_offset' = 2MB - 1MB =
   1MB;

4) We then attempt to insert a file extent item at inode B with a file
   offset of 5MB, which is the value of clone_info->file_offset. This
   fails with error -EEXIST because there's already an extent at that
   offset (extent B4);

5) We abort the current transaction with -EEXIST and return that error
   to user space as well.

Another example, for extent corruption:

  Inode A:

    extent A1                                           extent A2
  [ ----------- ]   [ hole, implicit, 10MB length ]  [ ------------- ]
  0            1MB                                  11MB            12MB

  Inode B:

    extent B1         extent B2
  [ ----------- ]   [ --------- ]    [ ----------------------------- ]
  0            1MB 1MB         5MB  5MB                             12MB

  Target range: [1MB, 12MB) (same as source, to make it easier to explain)

1) btrfs_punch_hole_range() gets -ENOSPC from __btrfs_drop_extents();

2) At that point, 'cur_offset' is set to 1MB and __btrfs_drop_extents()
   set 'drop_end' to 5MB, meaning it was able to drop only extent B2;

3) We then compute 'clone_len' as 'drop_end' - 'cur_offset' = 5MB - 1MB =
   4MB;

4) We then insert a file extent item at inode B with a file offset of 11MB
   which is the value of clone_info->file_offset, and a length of 4MB (the
   value of 'clone_len'). So we get 2 extents items with ranges that
   overlap and an extent length of 4MB, larger then the extent A2 from
   inode A (1MB length);

5) After that we end the transaction, balance the btree dirty pages and
   then start another or join the previous transaction. It might happen
   that the transaction which inserted the incorrect extent was committed
   by another task so we end up with extent corruption if a power failure
   happens.

So fix this by making sure we attempt to insert the extent to clone at
the destination inode only if we are past dropping the sub-range that
corresponds to a hole.

Fixes: 690a5dbfc5 ("Btrfs: fix ENOSPC errors, leading to transaction aborts, when cloning extents")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-01-12 12:21:29 +01:00
arch powerpc: Ensure that swiotlb buffer is allocated from low memory 2020-01-12 12:21:28 +01:00
block compat_ioctl: block: handle BLKGETZONESZ/BLKGETNRZONES 2020-01-09 10:19:58 +01:00
certs
crypto KEYS: asymmetric: return ENOMEM if akcipher_request_alloc() fails 2019-12-31 16:46:07 +01:00
Documentation dt-bindings: clock: renesas: rcar-usb2-clock-sel: Fix typo in example 2020-01-09 10:20:05 +01:00
drivers pinctrl: pinmux: fix a possible null pointer in pinmux_can_be_used_for_gpio 2020-01-12 12:21:28 +01:00
fs Btrfs: fix cloning range with a hole when using the NO_HOLES feature 2020-01-12 12:21:29 +01:00
include netfilter: uapi: Avoid undefined left-shift in xt_sctp.h 2020-01-12 12:21:17 +01:00
init
ipc
kernel locking/spinlock/debug: Fix various data races 2020-01-12 12:21:13 +01:00
lib lib/ubsan: don't serialize UBSAN report 2020-01-09 10:20:07 +01:00
LICENSES
mm mm/hugetlb: defer freeing of huge pages if in non-task context 2020-01-09 10:20:07 +01:00
net cfg80211: fix double-free after changing network namespace 2020-01-12 12:21:28 +01:00
samples samples: bpf: fix syscall_tp due to unused syscall 2020-01-12 12:21:26 +01:00
scripts gcc-plugins: make it possible to disable CONFIG_GCC_PLUGINS again 2020-01-09 10:19:57 +01:00
security apparmor: fix aa_xattrs_match() may sleep while holding a RCU lock 2020-01-09 10:20:00 +01:00
sound ASoC: SOF: Intel: split cht and byt debug window sizes 2020-01-12 12:21:22 +01:00
tools kselftest: Support old perl versions 2020-01-12 12:21:26 +01:00
usr gen_initramfs_list.sh: fix 'bad variable name' error 2020-01-09 10:20:00 +01:00
virt KVM: arm/arm64: Properly handle faulting of device mappings 2019-12-31 16:46:24 +01:00
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap ARM: SoC fixes 2019-11-10 13:41:59 -08:00
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2019-11-22 14:28:14 -08:00
Makefile Linux 5.4.10 2020-01-09 10:25:53 +01:00
README

Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``.  The formatted documentation can also be read online at:

    https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.