]> git.hungrycats.org Git - linux/log
linux
5 years agozygo: make oldconfig for kdave-github/misc-5.5 2019-12-13
Zygo Blaxell [Sat, 14 Dec 2019 04:58:10 +0000 (23:58 -0500)]
zygo: make oldconfig for kdave-github/misc-5.5

5 years agoRevert "zygo: btrfs: check for dead roots"
Zygo Blaxell [Tue, 10 Dec 2019 17:29:18 +0000 (12:29 -0500)]
Revert "zygo: btrfs: check for dead roots"

This reverts commit 1d9c5ddd8e5e71c9aeeca8cc516ed713ce0281b9.

(cherry picked from commit 937df746f670f25c4f0b606279f21fe0c3351d0c)

5 years agoRevert "zygo: btrfs: more debugging from Qu"
Zygo Blaxell [Tue, 10 Dec 2019 17:29:16 +0000 (12:29 -0500)]
Revert "zygo: btrfs: more debugging from Qu"

This reverts commit 77fc783e4d70918b453c7f2ba03f5d18d3a31ba3.

(cherry picked from commit 3657bd8b240de97aa527a27919a23efbb001604d)

5 years agoRevert "zygo: btrfs: check for DEAD_RELOC_TREE in fs/btrfs/relocation.c"
Zygo Blaxell [Tue, 10 Dec 2019 17:29:16 +0000 (12:29 -0500)]
Revert "zygo: btrfs: check for DEAD_RELOC_TREE in fs/btrfs/relocation.c"

This reverts commit 92038017ebf650b7dacce333ff7e6b91d296997c.

(cherry picked from commit 69b54a88bfcec2b90d99699185f381fdbf20bb1d)

5 years agoRevert "Revert "Btrfs: do not start a transaction at iterate_extent_inodes()""
Zygo Blaxell [Tue, 10 Dec 2019 17:26:54 +0000 (12:26 -0500)]
Revert "Revert "Btrfs: do not start a transaction at iterate_extent_inodes()""

This reverts commit 9ad6e14f3f1ad6a90c8530b8c8f925e99dd4062f.

(cherry picked from commit 87853d040f5785fe1a8707210d0ce3a4d355b01f)

5 years agoRevert "Btrfs: do not start a transaction at iterate_extent_inodes()"
Zygo Blaxell [Fri, 6 Dec 2019 20:16:08 +0000 (15:16 -0500)]
Revert "Btrfs: do not start a transaction at iterate_extent_inodes()"

This reverts commit bfc61c36260ca990937539cd648ede3cd749bc10.

(cherry picked from commit 9ad6e14f3f1ad6a90c8530b8c8f925e99dd4062f)

5 years agozygo: btrfs: more debugging from Qu
Zygo Blaxell [Fri, 6 Dec 2019 16:46:26 +0000 (11:46 -0500)]
zygo: btrfs: more debugging from Qu

Mind to apply this snippet?

It's not a poking around fixes, but a debug output for:
- Which block group is being balanced, and when it finishes
- Which subvolume (including reloc tree) is being dropped and when it
finishes

It's going to hit all those bugs again, but with the debug patch, I can
see how impossible things happens.

After some discussion in SUSE internal IRC, it proves one nightmare:
- root->reloc_root assignment is not atomic
- fs_info->reloc_cntl assigment is not atomic

So despite that, would you like to test it on a single core VM or
disabling all other cores of a baremetal to see if it can be reproduced?

Thanks,
Qu

(cherry picked from commit 77fc783e4d70918b453c7f2ba03f5d18d3a31ba3)

5 years agozygo: btrfs: get rid of this WARN_ON, it just triggers useless KASANs and slab-oobs
Zygo Blaxell [Thu, 5 Dec 2019 16:16:17 +0000 (11:16 -0500)]
zygo: btrfs: get rid of this WARN_ON, it just triggers useless KASANs and slab-oobs

(cherry picked from commit e211f1a58b80b8b752f0e6054af945d20f1a2f86)

5 years agozygo: btrfs: get rid of this WARN_ON, it just triggers useless KASANs
Zygo Blaxell [Thu, 5 Dec 2019 16:16:17 +0000 (11:16 -0500)]
zygo: btrfs: get rid of this WARN_ON, it just triggers useless KASANs

(cherry picked from commit 5ff6289d3448990376cff625882caff854f13363)

5 years agobtrfs: relocation: Introduce error injection points for cancelling balance
Qu Wenruo [Tue, 3 Dec 2019 06:42:51 +0000 (14:42 +0800)]
btrfs: relocation: Introduce error injection points for cancelling balance

Introduce a new error injection point, should_cancel_balance().

It's just a wrapper of atomic_read(&fs_info->balance_cancel_req), but
allows us to override the return value.

Currently there are only one locations using this function:
- btrfs_balance()
  It checks cancel before each block group.

There are other locations checking fs_info->balance_cancel_req, but they
are not used as an indicator to exit, so there is no need to use the
wrapper.

But there will be more locations coming, and some locations can cause
kernel panic if not handled properly.

So introduce this error injection to provide better test interface.

Signed-off-by: Qu Wenruo <wqu@suse.com>
(cherry picked from commit 6d2751364569f885ca795e37882690a78ac9f149)

5 years agobtrfs: relocation: Work around dead relocation stage loop
Qu Wenruo [Tue, 3 Dec 2019 06:42:54 +0000 (14:42 +0800)]
btrfs: relocation: Work around dead relocation stage loop

There are some reports of dead relocation stage loop, where dmesg is
flooded by "Found X extents".

The root cause of it is still uncertain, but we can work around such bug
by checking cancelling request so user can at least cancel such dead
loop.

Signed-off-by: Qu Wenruo <wqu@suse.com>
(cherry picked from commit 51e1987039e8138615d7da1e52aa53a3fb332612)

5 years agobtrfs: relocation: Check cancel request after each extent found
Qu Wenruo [Tue, 3 Dec 2019 06:42:53 +0000 (14:42 +0800)]
btrfs: relocation: Check cancel request after each extent found

When relocating data block groups with tons of small extents, or
large metadata block groups, there can be over 200,000 extents.

We will iterate all extents of such block group in relocate_block_group(),
where iteration itself can be kinda time-consuming.

So when user want to cancel the balance, the extent iteration loop can
be another target.

This patch will add the cancelling check in the extent iteration loop of
relocate_block_group() to make balance cancelling faster.

Signed-off-by: Qu Wenruo <wqu@suse.com>
(cherry picked from commit 400faee53af2f9f1d0d4a0e0f92ea3d08fe53d59)

5 years agobtrfs: relocation: Check cancel request after each data page read
Qu Wenruo [Tue, 3 Dec 2019 06:42:52 +0000 (14:42 +0800)]
btrfs: relocation: Check cancel request after each data page read

When relocating a data extents with large large data extents, we spend
most of our time in relocate_file_extent_cluster() at stage "moving data
extents":
 1)               |  btrfs_relocate_block_group [btrfs]() {
 1)               |    relocate_file_extent_cluster [btrfs]() {
 1) $ 6586769 us  |    }
 1) + 18.260 us   |    relocate_file_extent_cluster [btrfs]();
 1) + 15.770 us   |    relocate_file_extent_cluster [btrfs]();
 1) $ 8916340 us  |  }
 1)               |  btrfs_relocate_block_group [btrfs]() {
 1)               |    relocate_file_extent_cluster [btrfs]() {
 1) $ 11611586 us |    }
 1) + 16.930 us   |    relocate_file_extent_cluster [btrfs]();
 1) + 15.870 us   |    relocate_file_extent_cluster [btrfs]();
 1) $ 14986130 us |  }

So to make data relocation cancelling quicker, here add extra balance
cancelling check after each page read in relocate_file_extent_cluster().

Signed-off-by: Qu Wenruo <wqu@suse.com>
(cherry picked from commit 34bb874930d1d6fecec7927101041884fe695aa7)

5 years agozygo: btrfs: check for DEAD_RELOC_TREE in fs/btrfs/relocation.c
Zygo Blaxell [Wed, 4 Dec 2019 06:39:41 +0000 (01:39 -0500)]
zygo: btrfs: check for DEAD_RELOC_TREE in fs/btrfs/relocation.c

(cherry picked from commit de97fa43b71a6515cb574419e97c921878547752)
(cherry picked from commit 92038017ebf650b7dacce333ff7e6b91d296997c)

5 years agobtrfs: relocation: Output current relocation stage at btrfs_relocate_block_group()
Qu Wenruo [Fri, 29 Nov 2019 04:40:59 +0000 (12:40 +0800)]
btrfs: relocation: Output current relocation stage at btrfs_relocate_block_group()

There are several reports of hanging relocation, populating the dmesg
with things like:
  BTRFS info (device dm-5): found 1 extents

The investigation is still on going, but will never hurt to output a
little more info.

This patch will also output the current relocation stage, making that
output something like:

  BTRFS info (device dm-5): balance: start -d -m -s
  BTRFS info (device dm-5): relocating block group 30408704 flags metadata|dup
  BTRFS info (device dm-5): found 2 extents, stage: move data extents
  BTRFS info (device dm-5): relocating block group 22020096 flags system|dup
  BTRFS info (device dm-5): found 1 extents, stage: move data extents
  BTRFS info (device dm-5): relocating block group 13631488 flags data
  BTRFS info (device dm-5): found 1 extents, stage: move data extents
  BTRFS info (device dm-5): found 1 extents, stage: update data pointers
  BTRFS info (device dm-5): balance: ended with status: 0

This patch will not increase the number of lines, but with extra info
for us to debug the reported problem.
(Although it's very likely the bug is sticking at "update data pointers"
stage, even without the patch)

Signed-off-by: Qu Wenruo <wqu@suse.com>
(cherry picked from commit b04bb3a0ee5916885cb989f904d0168ac181e649)

5 years agozygo: btrfs: reloc_root might be NULL, adapt, #2
Zygo Blaxell [Tue, 3 Dec 2019 18:08:47 +0000 (13:08 -0500)]
zygo: btrfs: reloc_root might be NULL, adapt, #2

(cherry picked from commit 3acb2fb64807af3fddc5a5bccb86449b6d2bbac3)

5 years agozygo: btrfs: reloc_root might be NULL, adapt
Zygo Blaxell [Tue, 3 Dec 2019 17:42:58 +0000 (12:42 -0500)]
zygo: btrfs: reloc_root might be NULL, adapt

(cherry picked from commit 33ef2d3ce4c1830291a9bcbee499230b1d5937e8)

5 years agozygo: btrfs: check for dead roots
Zygo Blaxell [Tue, 3 Dec 2019 16:31:55 +0000 (11:31 -0500)]
zygo: btrfs: check for dead roots

(cherry picked from commit 1d9c5ddd8e5e71c9aeeca8cc516ed713ce0281b9)

5 years agozygo: btrfs: add some WARN_ONs to chase KASAN stack traces
Zygo Blaxell [Tue, 3 Dec 2019 16:20:44 +0000 (11:20 -0500)]
zygo: btrfs: add some WARN_ONs to chase KASAN stack traces

(cherry picked from commit 7bc46196ca4d31da287f151b905babbdb429c444)

5 years agozygo: config: add KASAN and page poisoning
Zygo Blaxell [Sun, 1 Dec 2019 05:04:16 +0000 (00:04 -0500)]
zygo: config: add KASAN and page poisoning

(cherry picked from commit 31ab8afa446ef1504d95ec2cb8997f717ea059f3)

5 years agozygo: move VIRTIO_FS to builtin
Zygo Blaxell [Thu, 28 Nov 2019 04:22:33 +0000 (23:22 -0500)]
zygo: move VIRTIO_FS to builtin

(cherry picked from commit 4319e8c0671717369d9e266760defc384228f40a)

5 years agozygo: make oldconfig for v5.4
Zygo Blaxell [Thu, 28 Nov 2019 04:20:39 +0000 (23:20 -0500)]
zygo: make oldconfig for v5.4

(cherry picked from commit cb3c402a018565579c86dec3f4c8249edabc37a7)

5 years agozygo: add 'config-kernel' script to run 'make oldconfig' with KCONFIG_NOTIMESTAMP
Zygo Blaxell [Thu, 28 Nov 2019 03:39:16 +0000 (22:39 -0500)]
zygo: add 'config-kernel' script to run 'make oldconfig' with KCONFIG_NOTIMESTAMP

(cherry picked from commit 4cc38d103bc42929ef42f3df5a344b27ab3fda45)

5 years agozygo: make oldconfig for v5.3.11
Zygo Blaxell [Wed, 17 Jul 2019 02:49:05 +0000 (22:49 -0400)]
zygo: make oldconfig for v5.3.11

(cherry picked from commit 611173fe9f440ddc1e685590a1d9ae6605c7feff)
(cherry picked from commit 6e759716c74585121d6bf5d16196f3595d499207)
(cherry picked from commit 78f29c5cce696e0bce8eac427295c5a3baecec4f)

zygo: make oldconfig for v5.3.0

(cherry picked from commit 1c95c736e902a7000cf56e54a601ec9c582eceeb)

zygo: make oldconfig for 5.3.11

(cherry picked from commit 40d85aaa82b74e98ae431b0f861e918a4f9f4162)
(cherry picked from commit 72baa51e35dc3560c14af9248b19f11533651c27)

5 years agozygo: silence WARN_ON(!rwsem_is_locked(&sb->s_umount));
Zygo Blaxell [Thu, 21 Mar 2019 14:51:09 +0000 (10:51 -0400)]
zygo: silence WARN_ON(!rwsem_is_locked(&sb->s_umount));

(cherry picked from commit f4220b603990b1404d138ba3e99af7992d6def82)
(cherry picked from commit df85af7244c128d115ff46a669e51f3923ede522)
(cherry picked from commit 6fa149dea2f57bff5c5c4416aa42f8089e743d17)
(cherry picked from commit 056b77c2bd566a07e9c4dcb12c1304d1f01d63c5)
(cherry picked from commit 69602a72b10db4dc103c977629557ba9526db6ad)

5 years agoRevert "docs: Makefile: remove no-ops targets"
Zygo Blaxell [Sun, 22 Sep 2019 15:29:42 +0000 (11:29 -0400)]
Revert "docs: Makefile: remove no-ops targets"

This reverts commit 18afab8c1d3c2a463eece561e9f15a1704b5eff9.

(cherry picked from commit 697451f51e136db9a8d373726701ffbe2440ecf0)
(cherry picked from commit 250887f1296220d5dd87eb312de6bbe9083d8c18)

5 years agozygo: btrfs: get a call trace when we hit ghost parent transid verify failures
Zygo Blaxell [Sat, 18 May 2019 21:48:59 +0000 (17:48 -0400)]
zygo: btrfs: get a call trace when we hit ghost parent transid verify failures

(cherry picked from commit 5abbed1af5570f1317f31736e3862e8b7df1ca8b)
(cherry picked from commit bdfb7a5429475b12a8a1c817b4e9e452c1fc9bea)
(cherry picked from commit abe0b4452dd22410eeda535bcfab25f5a6e8b6de)
(cherry picked from commit 983d9f3319e1e38dd85bcc66cfc04fdbf7627fc0)

5 years agozygo: btrfs: set super_num_devices
Zygo Blaxell [Tue, 23 Apr 2019 21:25:03 +0000 (17:25 -0400)]
zygo: btrfs: set super_num_devices

(cherry picked from commit ac5c7d500c60c460ebc659bb794c2b46c1a31497)
(cherry picked from commit 253cbcb7e19750240362a156c517b6213b958d4d)
(cherry picked from commit 8fa40c4f82c637969b2bac80ef5c524017ce054e)
(cherry picked from commit edf2d8af02e7fb727b466e1018b5c5d2fc48f5a0)
(cherry picked from commit 62f701457f2a1f4cad83353cde134caefbb1a354)

5 years agozygo: from zygo-5.0.x-zb64
Zygo Blaxell [Sun, 12 Aug 2018 22:21:54 +0000 (18:21 -0400)]
zygo: from zygo-5.0.x-zb64

zygo: from zygo-4.17.x-zb64

(cherry picked from commit c45b6fb9ce9315c056288bfb5a755fd7eec9a197)

zygo: make oldconfig for v4.18

(cherry picked from commit cc3d6d815e6415c1157435e3f63270e4137b6608)
(cherry picked from commit f44fa222fc6a7df75b02a77e1d663bd8bee67fc5)

zygo: make oldconfig for 4.19.1

(cherry picked from commit 9c6ad550267932f5a4992c5d1f46980793c6a9a6)

zygo: make oldconfig for 4.19.7

(cherry picked from commit 002c486977a9a83a1e1385ec6de2746668de02f9)
(cherry picked from commit 63f6b068f316598eade19e31a1095ad7dbc700ba)

zygo: make oldconfig for v4.20

(cherry picked from commit 9a1ea99f7eada69738307d2898161a82e27310e2)
(cherry picked from commit db51f3f667ac3d5fa0851e4a49fce64f2a46ebf6)
(cherry picked from commit e0d2aa5082fcad29770f5786ae2a41fd100bdcde)
(cherry picked from commit d117937ed23d27b41faf7a4c2d16ebe463459d21)
(cherry picked from commit fedf2d15fd89d82cd73d431cae24f9318be6f869)
(cherry picked from commit d70c0dcaa12a9f5e1f483367b5798136a2d4dff5)

5 years agoSnapshot create NULL pointer dereference
Qu WenRuo [Tue, 10 Dec 2019 08:55:00 +0000 (08:55 +0000)]
Snapshot create NULL pointer dereference

--YVy2ZwhygmFTft9qf4qxad0AgZTGdqI77
Content-Type: text/plain; charset=utf-8
Content-Language: en-US
Content-Transfer-Encoding: quoted-printable

Hi,

With reproducer, I got my new fixes for all the mess I created.

Yep, that's definitely that lifespan patch caused all these problems.

I got a fix for it to pass the super fast crash script, would you please
try to test it?

Currently the only problem is, I have observed cases where metadata
balance could fall into dead loop. But since it's also reported before,
so I'm not sure if it's my fix worsen the situation.

And since I have only seen 3 different KASAN reports, with some not
reported by you, so I'm not 100% sure if all cases are covered.

Your test would help a lot to verify the fix.

Thanks,
Qu

(cherry picked from commit d595e06eefca762e4c5937d9a83b300f7c06ff31)

5 years agobtrfs: send: remove WARN_ON for readonly mount
Anand Jain [Thu, 5 Dec 2019 11:39:07 +0000 (19:39 +0800)]
btrfs: send: remove WARN_ON for readonly mount

We log warning if root::orphan_cleanup_state is not set to
ORPHAN_CLEANUP_DONE in btrfs_ioctl_send(). However if the filesystem is
mounted as readonly we skip the orphan item cleanup during the lookup
and root::orphan_cleanup_state remains at the init state 0 instead of
ORPHAN_CLEANUP_DONE (2). So during send in btrfs_ioctl_send() we hit the
warning as below.

  WARN_ON(send_root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE);

WARNING: CPU: 0 PID: 2616 at /Volumes/ws/btrfs-devel/fs/btrfs/send.c:7090 btrfs_ioctl_send+0xb2f/0x18c0 [btrfs]
::
RIP: 0010:btrfs_ioctl_send+0xb2f/0x18c0 [btrfs]
::
Call Trace:
::
_btrfs_ioctl_send+0x7b/0x110 [btrfs]
btrfs_ioctl+0x150a/0x2b00 [btrfs]
::
do_vfs_ioctl+0xa9/0x620
? __fget+0xac/0xe0
ksys_ioctl+0x60/0x90
__x64_sys_ioctl+0x16/0x20
do_syscall_64+0x49/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9

Reproducer:
  mkfs.btrfs -fq /dev/sdb
  mount /dev/sdb /btrfs
  btrfs subvolume create /btrfs/sv1
  btrfs subvolume snapshot -r /btrfs/sv1 /btrfs/ss1
  umount /btrfs
  mount -o ro /dev/sdb /btrfs
  btrfs send /btrfs/ss1 -f /tmp/f

The warning exists because having orphan inodes could confuse send and
cause it to fail or produce incorrect streams.  The two cases that would
cause such send failures, which are already fixed are:

1) Inodes that were unlinked - these are orphanized and remain with a
   link count of 0. These caused send operations to fail because it
   expected to always find at least one path for an inode. However this
   is no longer a problem since send is now able to deal with such
   inodes since commit 46b2f4590aab ("Btrfs: fix send failure when root
   has deleted files still open") and treats them as having been
   completely removed (the state after an orphan cleanup is performed).

2) Inodes that were in the process of being truncated. These resulted in
   send not knowing about the truncation and potentially issue write
   operations full of zeroes for the range from the new file size to the
   old file size. This is no longer a problem because we no longer
   create orphan items for truncation since commit f7e9e8fc792f ("Btrfs:
   stop creating orphan items for truncate").

As such before these commits, the WARN_ON here provided a clue in case
something went wrong. Instead of being a warning against the
root::orphan_cleanup_state value, it could have been more accurate by
checking if there were actually any orphan items, and then issue a
warning only if any exists, but that would be more expensive to check.
Since orphanized inodes no longer cause problems for send, just remove
the warning.

Reported-by: Christoph Anton Mitterer <calestyo@scientia.net>
Link: https://lore.kernel.org/linux-btrfs/21cb5e8d059f6e1496a903fa7bfc0a297e2f5370.camel@scientia.net/
CC: stable@vger.kernel.org # 4.19+
Suggested-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: do not leak reloc root if we fail to read the fs root
Josef Bacik [Fri, 6 Dec 2019 14:37:18 +0000 (09:37 -0500)]
btrfs: do not leak reloc root if we fail to read the fs root

If we fail to read the fs root corresponding with a reloc root we'll
just break out and free the reloc roots.  But we remove our current
reloc_root from this list higher up, which means we'll leak this
reloc_root.  Fix this by adding ourselves back to the reloc_roots list
so we are properly cleaned up.

CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: skip log replay on orphaned roots
Josef Bacik [Fri, 6 Dec 2019 14:37:17 +0000 (09:37 -0500)]
btrfs: skip log replay on orphaned roots

My fsstress modifications coupled with generic/475 uncovered a failure
to mount and replay the log if we hit a orphaned root.  We do not want
to replay the log for an orphan root, but it's completely legitimate to
have an orphaned root with a log attached.  Fix this by simply skipping
replaying the log.  We still need to pin it's root node so that we do
not overwrite it while replaying other logs, as we re-read the log root
at every stage of the replay.

CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: handle ENOENT in btrfs_uuid_tree_iterate
Josef Bacik [Fri, 6 Dec 2019 16:39:00 +0000 (11:39 -0500)]
btrfs: handle ENOENT in btrfs_uuid_tree_iterate

If we get an -ENOENT back from btrfs_uuid_iter_rem when iterating the
uuid tree we'll just continue and do btrfs_next_item().  However we've
done a btrfs_release_path() at this point and no longer have a valid
path.  So increment the key and go back and do a normal search.

CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: abort transaction after failed inode updates in create_subvol
Josef Bacik [Fri, 6 Dec 2019 14:37:15 +0000 (09:37 -0500)]
btrfs: abort transaction after failed inode updates in create_subvol

We can just abort the transaction here, and in fact do that for every
other failure in this function except these two cases.

CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: fix hole extent items with a zero size after range cloning
Filipe Manana [Thu, 5 Dec 2019 16:58:41 +0000 (16:58 +0000)]
Btrfs: fix hole extent items with a zero size after range cloning

Normally when cloning a file range if we find an implicit hole at the end
of the range we assume it is because the NO_HOLES feature is enabled.
However that is not always the case. One well known case [1] is when we
have a power failure after mixing buffered and direct IO writes against
the same file.

In such cases we need to punch a hole in the destination file, and if
the NO_HOLES feature is not enabled, we need to insert explicit file
extent items to represent the hole. After commit 690a5dbfc51315
("Btrfs: fix ENOSPC errors, leading to transaction aborts, when cloning
extents"), we started to insert file extent items representing the hole
with an item size of 0, which is invalid and should be 53 bytes (the size
of a btrfs_file_extent_item structure), resulting in all sorts of
corruptions and invalid memory accesses. This is detected by the tree
checker when we attempt to write a leaf to disk.

The problem can be sporadically triggered by test case generic/561 from
fstests. That test case does not exercise power failure and creates a new
filesystem when it starts, so it does not use a filesystem created by any
previous test that tests power failure. However the test does both
buffered and direct IO writes (through fsstress) and it's precisely that
which is creating the implicit holes in files. That happens even before
the commit mentioned earlier. I need to investigate why we get those
implicit holes to check if there is a real problem or not. For now this
change fixes the regression of introducing file extent items with an item
size of 0 bytes.

Fix the issue by calling btrfs_punch_hole_range() without passing a
btrfs_clone_extent_info structure, which ensures file extent items are
inserted to represent the hole with a correct item size. We were passing
a btrfs_clone_extent_info with a value of 0 for its 'item_size' field,
which was causing the insertion of file extent items with an item size
of 0.

[1] https://www.spinics.net/lists/linux-btrfs/msg75350.html

Reported-by: David Sterba <dsterba@suse.com>
Fixes: 690a5dbfc51315 ("Btrfs: fix ENOSPC errors, leading to transaction aborts, when cloning extents")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: fix removal logic of the tree mod log that leads to use-after-free issues
Filipe Manana [Fri, 6 Dec 2019 12:27:39 +0000 (12:27 +0000)]
Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues

When a tree mod log user no longer needs to use the tree it calls
btrfs_put_tree_mod_seq() to remove itself from the list of users and
delete all no longer used elements of the tree's red black tree, which
should be all elements with a sequence number less then our equals to
the caller's sequence number. However the logic is broken because it
can delete and free elements from the red black tree that have a
sequence number greater then the caller's sequence number:

1) At a point in time we have sequence numbers 1, 2, 3 and 4 in the
   tree mod log;

2) The task which got assigned the sequence number 1 calls
   btrfs_put_tree_mod_seq();

3) Sequence number 1 is deleted from the list of sequence numbers;

4) The current minimum sequence number is computed to be the sequence
   number 2;

5) A task using sequence number 2 is at tree_mod_log_rewind() and gets
   a pointer to one of its elements from the red black tree through
   a call to tree_mod_log_search();

6) The task with sequence number 1 iterates the red black tree of tree
   modification elements and deletes (and frees) all elements with a
   sequence number less then or equals to 2 (the computed minimum sequence
   number) - it ends up only leaving elements with sequence numbers of 3
   and 4;

7) The task with sequence number 2 now uses the pointer to its element,
   already freed by the other task, at __tree_mod_log_rewind(), resulting
   in a use-after-free issue. When CONFIG_DEBUG_PAGEALLOC=y it produces
   a trace like the following:

  [16804.546854] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
  [16804.547451] CPU: 0 PID: 28257 Comm: pool Tainted: G        W         5.4.0-rc8-btrfs-next-51 #1
  [16804.548059] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014
  [16804.548666] RIP: 0010:rb_next+0x16/0x50
  (...)
  [16804.550581] RSP: 0018:ffffb948418ef9b0 EFLAGS: 00010202
  [16804.551227] RAX: 6b6b6b6b6b6b6b6b RBX: ffff90e0247f6600 RCX: 6b6b6b6b6b6b6b6b
  [16804.551873] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff90e0247f6600
  [16804.552504] RBP: ffff90dffe0d4688 R08: 0000000000000001 R09: 0000000000000000
  [16804.553136] R10: ffff90dffa4a0040 R11: 0000000000000000 R12: 000000000000002e
  [16804.553768] R13: ffff90e0247f6600 R14: 0000000000001663 R15: ffff90dff77862b8
  [16804.554399] FS:  00007f4b197ae700(0000) GS:ffff90e036a00000(0000) knlGS:0000000000000000
  [16804.555039] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  [16804.555683] CR2: 00007f4b10022000 CR3: 00000002060e2004 CR4: 00000000003606f0
  [16804.556336] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
  [16804.556968] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
  [16804.557583] Call Trace:
  [16804.558207]  __tree_mod_log_rewind+0xbf/0x280 [btrfs]
  [16804.558835]  btrfs_search_old_slot+0x105/0xd00 [btrfs]
  [16804.559468]  resolve_indirect_refs+0x1eb/0xc70 [btrfs]
  [16804.560087]  ? free_extent_buffer.part.19+0x5a/0xc0 [btrfs]
  [16804.560700]  find_parent_nodes+0x388/0x1120 [btrfs]
  [16804.561310]  btrfs_check_shared+0x115/0x1c0 [btrfs]
  [16804.561916]  ? extent_fiemap+0x59d/0x6d0 [btrfs]
  [16804.562518]  extent_fiemap+0x59d/0x6d0 [btrfs]
  [16804.563112]  ? __might_fault+0x11/0x90
  [16804.563706]  do_vfs_ioctl+0x45a/0x700
  [16804.564299]  ksys_ioctl+0x70/0x80
  [16804.564885]  ? trace_hardirqs_off_thunk+0x1a/0x20
  [16804.565461]  __x64_sys_ioctl+0x16/0x20
  [16804.566020]  do_syscall_64+0x5c/0x250
  [16804.566580]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
  [16804.567153] RIP: 0033:0x7f4b1ba2add7
  (...)
  [16804.568907] RSP: 002b:00007f4b197adc88 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
  [16804.569513] RAX: ffffffffffffffda RBX: 00007f4b100210d8 RCX: 00007f4b1ba2add7
  [16804.570133] RDX: 00007f4b100210d8 RSI: 00000000c020660b RDI: 0000000000000003
  [16804.570726] RBP: 000055de05a6cfe0 R08: 0000000000000000 R09: 00007f4b197add44
  [16804.571314] R10: 0000000000000000 R11: 0000000000000246 R12: 00007f4b197add48
  [16804.571905] R13: 00007f4b197add40 R14: 00007f4b100210d0 R15: 00007f4b197add50
  (...)
  [16804.575623] ---[ end trace 87317359aad4ba50 ]---

Fix this by making btrfs_put_tree_mod_seq() skip deletion of elements that
have a sequence number equals to the computed minimum sequence number, and
not just elements with a sequence number greater then that minimum.

Fixes: bd989ba359f2ac ("Btrfs: add tree modification log functions")
CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: make tree checker detect checksum items with overlapping ranges
Filipe Manana [Mon, 2 Dec 2019 11:01:03 +0000 (11:01 +0000)]
Btrfs: make tree checker detect checksum items with overlapping ranges

Having checksum items, either on the checksums tree or in a log tree, that
represent ranges that overlap each other is a sign of a corruption. Such
case confuses the checksum lookup code and can result in not being able to
find checksums or find stale checksums.

So add a check for such case.

This is motivated by a recent fix for a case where a log tree had checksum
items covering ranges that overlap each other due to extent cloning, and
resulted in missing checksums after replaying the log tree. It also helps
detect past issues such as stale and outdated checksums due to overlapping,
commit 27b9a8122ff71a ("Btrfs: fix csum tree corruption, duplicate and
outdated checksums").

CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: fix missing data checksums after replaying a log tree
Filipe Manana [Thu, 5 Dec 2019 16:58:30 +0000 (16:58 +0000)]
Btrfs: fix missing data checksums after replaying a log tree

When logging a file that has shared extents (reflinked with other files or
with itself), we can end up logging multiple checksum items that cover
overlapping ranges. This confuses the search for checksums at log replay
time causing some checksums to never be added to the fs/subvolume tree.

Consider the following example of a file that shares the same extent at
offsets 0 and 256Kb:

   [ bytenr 13893632, offset 64Kb, len 64Kb  ]
   0                                         64Kb

   [ bytenr 13631488, offset 64Kb, len 192Kb ]
   64Kb                                      256Kb

   [ bytenr 13893632, offset 0, len 256Kb    ]
   256Kb                                     512Kb

When logging the inode, at tree-log.c:copy_items(), when processing the
file extent item at offset 0, we log a checksum item covering the range
13959168 to 14024704, which corresponds to 13893632 + 64Kb and 13893632 +
64Kb + 64Kb, respectively.

Later when processing the extent item at offset 256K, we log the checksums
for the range from 13893632 to 14155776 (which corresponds to 13893632 +
256Kb). These checksums get merged with the checksum item for the range
from 13631488 to 13893632 (13631488 + 256Kb), logged by a previous fsync.
So after this we get the two following checksum items in the log tree:

   (...)
   item 6 key (EXTENT_CSUM EXTENT_CSUM 13631488) itemoff 3095 itemsize 512
           range start 13631488 end 14155776 length 524288
   item 7 key (EXTENT_CSUM EXTENT_CSUM 13959168) itemoff 3031 itemsize 64
           range start 13959168 end 14024704 length 65536

The first one covers the range from the second one, they overlap.

So far this does not cause a problem after replaying the log, because
when replaying the file extent item for offset 256K, we copy all the
checksums for the extent 13893632 from the log tree to the fs/subvolume
tree, since searching for an checksum item for bytenr 13893632 leaves us
at the first checksum item, which covers the whole range of the extent.

However if we write 64Kb to file offset 256Kb for example, we will
not be able to find and copy the checksums for the last 128Kb of the
extent at bytenr 13893632, referenced by the file range 384Kb to 512Kb.

After writing 64Kb into file offset 256Kb we get the following extent
layout for our file:

   [ bytenr 13893632, offset 64K, len 64Kb   ]
   0                                         64Kb

   [ bytenr 13631488, offset 64Kb, len 192Kb ]
   64Kb                                      256Kb

   [ bytenr 14155776, offset 0, len 64Kb     ]
   256Kb                                     320Kb

   [ bytenr 13893632, offset 64Kb, len 192Kb ]
   320Kb                                     512Kb

After fsync'ing the file, if we have a power failure and then mount
the filesystem to replay the log, the following happens:

1) When replaying the file extent item for file offset 320Kb, we
   lookup for the checksums for the extent range from 13959168
   (13893632 + 64Kb) to 14155776 (13893632 + 256Kb), through a call
   to btrfs_lookup_csums_range();

2) btrfs_lookup_csums_range() finds the checksum item that starts
   precisely at offset 13959168 (item 7 in the log tree, shown before);

3) However that checksum item only covers 64Kb of data, and not 192Kb
   of data;

4) As a result only the checksums for the first 64Kb of data referenced
   by the file extent item are found and copied to the fs/subvolume tree.
   The remaining 128Kb of data, file range 384Kb to 512Kb, doesn't get
   the corresponding data checksums found and copied to the fs/subvolume
   tree.

5) After replaying the log userspace will not be able to read the file
   range from 384Kb to 512Kb, because the checksums are missing and
   resulting in an -EIO error.

The following steps reproduce this scenario:

  $ mkfs.btrfs -f /dev/sdc
  $ mount /dev/sdc /mnt/sdc

  $ xfs_io -f -c "pwrite -S 0xa3 0 256K" /mnt/sdc/foobar
  $ xfs_io -c "fsync" /mnt/sdc/foobar
  $ xfs_io -c "pwrite -S 0xc7 256K 256K" /mnt/sdc/foobar

  $ xfs_io -c "reflink /mnt/sdc/foobar 320K 0 64K" /mnt/sdc/foobar
  $ xfs_io -c "fsync" /mnt/sdc/foobar

  $ xfs_io -c "pwrite -S 0xe5 256K 64K" /mnt/sdc/foobar
  $ xfs_io -c "fsync" /mnt/sdc/foobar

  <power failure>

  $ mount /dev/sdc /mnt/sdc
  $ md5sum /mnt/sdc/foobar
  md5sum: /mnt/sdc/foobar: Input/output error

  $ dmesg | tail
  [165305.003464] BTRFS info (device sdc): no csum found for inode 257 start 401408
  [165305.004014] BTRFS info (device sdc): no csum found for inode 257 start 405504
  [165305.004559] BTRFS info (device sdc): no csum found for inode 257 start 409600
  [165305.005101] BTRFS info (device sdc): no csum found for inode 257 start 413696
  [165305.005627] BTRFS info (device sdc): no csum found for inode 257 start 417792
  [165305.006134] BTRFS info (device sdc): no csum found for inode 257 start 421888
  [165305.006625] BTRFS info (device sdc): no csum found for inode 257 start 425984
  [165305.007278] BTRFS info (device sdc): no csum found for inode 257 start 430080
  [165305.008248] BTRFS warning (device sdc): csum failed root 5 ino 257 off 393216 csum 0x1337385e expected csum 0x00000000 mirror 1
  [165305.009550] BTRFS warning (device sdc): csum failed root 5 ino 257 off 393216 csum 0x1337385e expected csum 0x00000000 mirror 1

Fix this simply by deleting first any checksums, from the log tree, for the
range of the extent we are logging at copy_items(). This ensures we do not
get checksum items in the log tree that have overlapping ranges.

This is a long time issue that has been present since we have the clone
(and deduplication) ioctl, and can happen both when an extent is shared
between different files and within the same file.

A test case for fstests follows soon.

CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: return error pointer from alloc_test_extent_buffer
Dan Carpenter [Tue, 3 Dec 2019 11:24:58 +0000 (14:24 +0300)]
btrfs: return error pointer from alloc_test_extent_buffer

Callers of alloc_test_extent_buffer have not correctly interpreted the
return value as error pointer, as alloc_test_extent_buffer should behave
as alloc_extent_buffer. The self-tests were unaffected but
btrfs_find_create_tree_block could call both functions and that would
cause problems up in the call chain.

Fixes: faa2dbf004e8 ("Btrfs: add sanity tests for new qgroup accounting code")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: fix devs_max constraints for raid1c3 and raid1c4
David Sterba [Wed, 27 Nov 2019 15:10:54 +0000 (16:10 +0100)]
btrfs: fix devs_max constraints for raid1c3 and raid1c4

The value 0 for devs_max means to spread the allocated chunks over all
available devices, eg. stripe for RAID0 or RAID5. This got mistakenly
copied to the RAID1C3/4 profiles. The intention is to have exactly 3 and
4 copies respectively.

Fixes: 47e6f7423b91 ("btrfs: add support for 3-copy replication (raid1c3)")
Fixes: 8d6fac0087e5 ("btrfs: add support for 4-copy replication (raid1c4)")
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: tree-checker: Fix error format string for size_t
Andreas Färber [Fri, 8 Nov 2019 21:38:52 +0000 (22:38 +0100)]
btrfs: tree-checker: Fix error format string for size_t

Argument BTRFS_FILE_EXTENT_INLINE_DATA_START is defined as offsetof(),
which returns type size_t, so we need %zu instead of %lu.

This fixes a build warning on 32-bit ARM:

  ../fs/btrfs/tree-checker.c: In function 'check_extent_data_item':
  ../fs/btrfs/tree-checker.c:230:43: warning: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'unsigned int' [-Wformat=]
    230 |     "invalid item size, have %u expect [%lu, %u)",
        |                                         ~~^
        |                                           long unsigned int
        |                                         %u

Fixes: 153a6d299956 ("btrfs: tree-checker: Check item size before reading file extent type")
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andreas Färber <afaerber@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: don't double lock the subvol_sem for rename exchange
Josef Bacik [Tue, 19 Nov 2019 18:59:20 +0000 (13:59 -0500)]
btrfs: don't double lock the subvol_sem for rename exchange

If we're rename exchanging two subvols we'll try to lock this lock
twice, which is bad.  Just lock once if either of the ino's are subvols.

Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: handle error in btrfs_cache_block_group
Josef Bacik [Tue, 19 Nov 2019 18:59:00 +0000 (13:59 -0500)]
btrfs: handle error in btrfs_cache_block_group

We have a BUG_ON(ret < 0) in find_free_extent from
btrfs_cache_block_group.  If we fail to allocate our ctl we'll just
panic, which is not good.  Instead just go on to another block group.
If we fail to find a block group we don't want to return ENOSPC, because
really we got a ENOMEM and that's the root of the problem.  Save our
return from btrfs_cache_block_group(), and then if we still fail to make
our allocation return that ret so we get the right error back.

Tested with inject-error.py from bcc.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: do not call synchronize_srcu() in inode_tree_del
Josef Bacik [Tue, 19 Nov 2019 18:59:35 +0000 (13:59 -0500)]
btrfs: do not call synchronize_srcu() in inode_tree_del

Testing with the new fsstress uncovered a pretty nasty deadlock with
lookup and snapshot deletion.

Process A
unlink
 -> final iput
   -> inode_tree_del
     -> synchronize_srcu(subvol_srcu)

Process B
btrfs_lookup  <- srcu_read_lock() acquired here
  -> btrfs_iget
    -> find inode that has I_FREEING set
      -> __wait_on_freeing_inode()

We're holding the srcu_read_lock() while doing the iget in order to make
sure our fs root doesn't go away, and then we are waiting for the inode
to finish freeing.  However because the free'ing process is doing a
synchronize_srcu() we deadlock.

Fix this by dropping the synchronize_srcu() in inode_tree_del().  We
don't need people to stop accessing the fs root at this point, we're
only adding our empty root to the dead roots list.

A larger much more invasive fix is forthcoming to address how we deal
with fs roots, but this fixes the immediate problem.

Fixes: 76dda93c6ae2 ("Btrfs: add snapshot/subvolume destroy ioctl")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: fix cloning range with a hole when using the NO_HOLES feature
Filipe Manana [Thu, 5 Dec 2019 16:57:39 +0000 (16:57 +0000)]
Btrfs: fix cloning range with a hole when using the NO_HOLES feature

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: 690a5dbfc51315 ("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>
5 years agobtrfs: Fix error messages in qgroup_rescan_init
Nikolay Borisov [Mon, 18 Nov 2019 12:16:44 +0000 (14:16 +0200)]
btrfs: Fix error messages in qgroup_rescan_init

The branch of qgroup_rescan_init which is executed from the mount
path prints wrong errors messages. The textual print out in case
BTRFS_QGROUP_STATUS_FLAG_RESCAN/BTRFS_QGROUP_STATUS_FLAG_ON are not
set are transposed. Fix it by exchanging their place.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: drop bdev argument from submit_extent_page
David Sterba [Thu, 3 Oct 2019 15:29:05 +0000 (17:29 +0200)]
btrfs: drop bdev argument from submit_extent_page

After previous patches removing bdev being passed around to set it to
bio, it has become unused in submit_extent_page. So it now has "only" 13
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: remove extent_map::bdev
David Sterba [Fri, 30 Aug 2019 13:40:53 +0000 (15:40 +0200)]
btrfs: remove extent_map::bdev

We can now remove the bdev from extent_map. Previous patches made sure
that bio_set_dev is correctly in all places and that we don't need to
grab it from latest_bdev or pass it around inside the extent map.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: drop bio_set_dev where not needed
David Sterba [Fri, 30 Aug 2019 17:39:19 +0000 (19:39 +0200)]
btrfs: drop bio_set_dev where not needed

bio_set_dev sets a bdev to a bio and is not only setting a pointer bug
also changing some state bits if there was a different bdev set before.
This is one thing that's not needed.

Another thing is that setting a bdev at bio allocation time is too early
and actually does not work with plain redundancy profiles, where each
time we submit a bio to a device, the bdev is set correctly.

In many places the bio bdev is set to latest_bdev that seems to serve as
a stub pointer "just to put something to bio". But we don't have to do
that.

Where do we know which bdev to set:

* for regular IO: submit_stripe_bio that's called by btrfs_map_bio

* repair IO: repair_io_failure, read or write from specific device

* super block write (using buffer_heads but uses raw bdev) and barriers

* scrub: this does not use all regular IO paths as it needs to reach all
  copies, verify and fixup eventually, and for that all bdev management
  is independent

* raid56: rbio_add_io_page, for the RMW write

* integrity-checker: does it's own low-level block tracking

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: get bdev directly from fs_devices in submit_extent_page
David Sterba [Mon, 18 Nov 2019 22:27:55 +0000 (23:27 +0100)]
btrfs: get bdev directly from fs_devices in submit_extent_page

This is preparatory patch to remove @bdev parameter from
submit_extent_page. It can't be removed completely, because the cgroups
need it for wbc when initializing the bio

wbc_init_bio
  bio_associate_blkg_from_css
    dereference bdev->bi_disk->queue

The bdev pointer is the same as latest_bdev, thus no functional change.
We can retrieve it from fs_devices that's reachable through several
dereferences. The local variable shadows the parameter, but that's only
temporary.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: record all roots for rename exchange on a subvol
Josef Bacik [Fri, 15 Nov 2019 20:43:06 +0000 (15:43 -0500)]
btrfs: record all roots for rename exchange on a subvol

Testing with the new fsstress support for subvolumes uncovered a pretty
bad problem with rename exchange on subvolumes.  We're modifying two
different subvolumes, but we only start the transaction on one of them,
so the other one is not added to the dirty root list.  This is caught by
btrfs_cow_block() with a warning because the root has not been updated,
however if we do not modify this root again we'll end up pointing at an
invalid root because the root item is never updated.

Fix this by making sure we add the destination root to the trans list,
the same as we do with normal renames.  This fixes the corruption.

Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT")
CC: stable@vger.kernel.org # 4.9+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: fix block group remaining RO forever after error during device replace
Filipe Manana [Thu, 14 Nov 2019 18:02:43 +0000 (18:02 +0000)]
Btrfs: fix block group remaining RO forever after error during device replace

When doing a device replace, while at scrub.c:scrub_enumerate_chunks(), we
set the block group to RO mode and then wait for any ongoing writes into
extents of the block group to complete. While doing that wait we overwrite
the value of the variable 'ret' and can break out of the loop if an error
happens without turning the block group back into RW mode. So what happens
is the following:

1) btrfs_inc_block_group_ro() returns 0, meaning it set the block group
   to RO mode (its ->ro field set to 1 or incremented to some value > 1);

2) Then btrfs_wait_ordered_roots() returns a value > 0;

3) Then if either joining or committing the transaction fails, we break
   out of the loop wihtout calling btrfs_dec_block_group_ro(), leaving
   the block group in RO mode forever.

To fix this, just remove the code that waits for ongoing writes to extents
of the block group, since it's not needed because in the initial setup
phase of a device replace operation, before starting to find all chunks
and their extents, we set the target device for replace while holding
fs_info->dev_replace->rwsem, which ensures that after releasing that
semaphore, any writes into the source device are made to the target device
as well (__btrfs_map_block() guarantees that). So while at
scrub_enumerate_chunks() we only need to worry about finding and copying
extents (from the source device to the target device) that were written
before we started the device replace operation.

Fixes: f0e9b7d6401959 ("Btrfs: fix race setting block group readonly during device replace")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: scrub: Don't check free space before marking a block group RO
Qu Wenruo [Fri, 15 Nov 2019 02:09:00 +0000 (10:09 +0800)]
btrfs: scrub: Don't check free space before marking a block group RO

[BUG]
When running btrfs/072 with only one online CPU, it has a pretty high
chance to fail:

  btrfs/072 12s ... _check_dmesg: something found in dmesg (see xfstests-dev/results//btrfs/072.dmesg)
  - output mismatch (see xfstests-dev/results//btrfs/072.out.bad)
      --- tests/btrfs/072.out     2019-10-22 15:18:14.008965340 +0800
      +++ /xfstests-dev/results//btrfs/072.out.bad      2019-11-14 15:56:45.877152240 +0800
      @@ -1,2 +1,3 @@
       QA output created by 072
       Silence is golden
      +Scrub find errors in "-m dup -d single" test
      ...

And with the following call trace:

  BTRFS info (device dm-5): scrub: started on devid 1
  ------------[ cut here ]------------
  BTRFS: Transaction aborted (error -27)
  WARNING: CPU: 0 PID: 55087 at fs/btrfs/block-group.c:1890 btrfs_create_pending_block_groups+0x3e6/0x470 [btrfs]
  CPU: 0 PID: 55087 Comm: btrfs Tainted: G        W  O      5.4.0-rc1-custom+ #13
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  RIP: 0010:btrfs_create_pending_block_groups+0x3e6/0x470 [btrfs]
  Call Trace:
   __btrfs_end_transaction+0xdb/0x310 [btrfs]
   btrfs_end_transaction+0x10/0x20 [btrfs]
   btrfs_inc_block_group_ro+0x1c9/0x210 [btrfs]
   scrub_enumerate_chunks+0x264/0x940 [btrfs]
   btrfs_scrub_dev+0x45c/0x8f0 [btrfs]
   btrfs_ioctl+0x31a1/0x3fb0 [btrfs]
   do_vfs_ioctl+0x636/0xaa0
   ksys_ioctl+0x67/0x90
   __x64_sys_ioctl+0x43/0x50
   do_syscall_64+0x79/0xe0
   entry_SYSCALL_64_after_hwframe+0x49/0xbe
  ---[ end trace 166c865cec7688e7 ]---

[CAUSE]
The error number -27 is -EFBIG, returned from the following call chain:
btrfs_end_transaction()
|- __btrfs_end_transaction()
   |- btrfs_create_pending_block_groups()
      |- btrfs_finish_chunk_alloc()
         |- btrfs_add_system_chunk()

This happens because we have used up all space of
btrfs_super_block::sys_chunk_array.

The root cause is, we have the following bad loop of creating tons of
system chunks:

1. The only SYSTEM chunk is being scrubbed
   It's very common to have only one SYSTEM chunk.
2. New SYSTEM bg will be allocated
   As btrfs_inc_block_group_ro() will check if we have enough space
   after marking current bg RO. If not, then allocate a new chunk.
3. New SYSTEM bg is still empty, will be reclaimed
   During the reclaim, we will mark it RO again.
4. That newly allocated empty SYSTEM bg get scrubbed
   We go back to step 2, as the bg is already mark RO but still not
   cleaned up yet.

If the cleaner kthread doesn't get executed fast enough (e.g. only one
CPU), then we will get more and more empty SYSTEM chunks, using up all
the space of btrfs_super_block::sys_chunk_array.

[FIX]
Since scrub/dev-replace doesn't always need to allocate new extent,
especially chunk tree extent, so we don't really need to do chunk
pre-allocation.

To break above spiral, here we introduce a new parameter to
btrfs_inc_block_group(), @do_chunk_alloc, which indicates whether we
need extra chunk pre-allocation.

For relocation, we pass @do_chunk_alloc=true, while for scrub, we pass
@do_chunk_alloc=false.
This should keep unnecessary empty chunks from popping up for scrub.

Also, since there are two parameters for btrfs_inc_block_group_ro(),
add more comment for it.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: change btrfs_fs_devices::rotating to bool
Johannes Thumshirn [Wed, 13 Nov 2019 10:27:28 +0000 (11:27 +0100)]
btrfs: change btrfs_fs_devices::rotating to bool

struct btrfs_fs_devices::rotating currently is declared as an integer
variable but only used as a boolean.

Change the variable definition to bool and update to code touching it to
set 'true' and 'false'.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: change btrfs_fs_devices::seeding to bool
Johannes Thumshirn [Wed, 13 Nov 2019 10:27:27 +0000 (11:27 +0100)]
btrfs: change btrfs_fs_devices::seeding to bool

struct btrfs_fs_devices::seeding currently is declared as an integer
variable but only used as a boolean.

Change the variable definition to bool and update to code touching it to
set 'true' and 'false'.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: rename btrfs_block_group_cache
David Sterba [Tue, 29 Oct 2019 18:20:18 +0000 (19:20 +0100)]
btrfs: rename btrfs_block_group_cache

The type name is misleading, a single entry is named 'cache' while this
normally means a collection of objects. Rename that everywhere. Also the
identifier was quite long, making function prototypes harder to format.

Suggested-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: block-group: Reuse the item key from caller of read_one_block_group()
Qu Wenruo [Tue, 5 Nov 2019 01:35:35 +0000 (09:35 +0800)]
btrfs: block-group: Reuse the item key from caller of read_one_block_group()

For read_one_block_group(), its only caller has already got the item key
to search next block group item.

So we can use that key directly without doing our own convertion on
stack.

Also, since that key used in btrfs_read_block_groups() is vital for
block group item search, add 'const' keyword for that parameter to
prevent read_one_block_group() to modify it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: block-group: Refactor btrfs_read_block_groups()
Qu Wenruo [Thu, 10 Oct 2019 02:39:27 +0000 (10:39 +0800)]
btrfs: block-group: Refactor btrfs_read_block_groups()

Refactor the work inside the loop of btrfs_read_block_groups() into one
separate function, read_one_block_group().

This allows read_one_block_group to be reused for later BG_TREE feature.

The refactor does the following extra fix:
- Use btrfs_fs_incompat() to replace open-coded feature check

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: document extent buffer locking
David Sterba [Wed, 16 Oct 2019 16:29:10 +0000 (18:29 +0200)]
btrfs: document extent buffer locking

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: access eb::blocking_writers according to ACCESS_ONCE policies
David Sterba [Thu, 10 Oct 2019 22:03:14 +0000 (00:03 +0200)]
btrfs: access eb::blocking_writers according to ACCESS_ONCE policies

A nice writeup of the LKMM (Linux Kernel Memory Model) rules for access
once policies can be found here
https://lwn.net/Articles/799218/#Access-Marking%20Policies .

The locked and unlocked access to eb::blocking_writers should be
annotated accordingly, following this:

Writes:

- locked write must use ONCE, may use plain read
- unlocked write must use ONCE

Reads:

- unlocked read must use ONCE
- locked read may use plain read iff not mixed with unlocked read
- unlocked read then locked must use ONCE

There's one difference on the assembly level, where
btrfs_tree_read_lock_atomic and btrfs_try_tree_read_lock used the cached
value and did not reevaluate it after taking the lock. This could have
missed some opportunities to take the lock in case blocking writers
changed between the calls, but the window is just a few instructions
long. As this is in try-lock, the callers handle that.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: set blocking_writers directly, no increment or decrement
David Sterba [Thu, 10 Oct 2019 21:31:19 +0000 (23:31 +0200)]
btrfs: set blocking_writers directly, no increment or decrement

The increment and decrement was inherited from previous version that
used atomics, switched in commit 06297d8cefca ("btrfs: switch
extent_buffer blocking_writers from atomic to int"). The only possible
values are 0 and 1 so we can set them directly.

The generated assembly (gcc 9.x) did the direct value assignment in
btrfs_set_lock_blocking_write (asm diff after change in 06297d8cefca):

     5d:   test   %eax,%eax
     5f:   je     62 <btrfs_set_lock_blocking_write+0x22>
     61:   retq

  -  62:   lock incl 0x44(%rdi)
  -  66:   add    $0x50,%rdi
  -  6a:   jmpq   6f <btrfs_set_lock_blocking_write+0x2f>

  +  62:   movl   $0x1,0x44(%rdi)
  +  69:   add    $0x50,%rdi
  +  6d:   jmpq   72 <btrfs_set_lock_blocking_write+0x32>

The part in btrfs_tree_unlock did a decrement because
BUG_ON(blockers > 1) is probably not a strong hint for the compiler, but
otherwise the output looks safe:

  - lock decl 0x44(%rdi)

  + sub    $0x1,%eax
  + mov    %eax,0x44(%rdi)

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: merge blocking_writers branches in btrfs_tree_read_lock
David Sterba [Thu, 10 Oct 2019 21:29:21 +0000 (23:29 +0200)]
btrfs: merge blocking_writers branches in btrfs_tree_read_lock

There are two ifs that use eb::blocking_writers. As this is a variable
modified inside and outside of locks, we could minimize number of
accesses to avoid problems with getting different results at different
times.

The access here is locked so this can only race with btrfs_tree_unlock
that sets blocking_writers to 0 without lock and unsets the lock owner.

The first branch is taken only if the same thread already holds the
lock, the second if checks for blocking writers. Here we'd either unlock
and wait, or proceed. Both are valid states of the locking protocol.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: drop incompat bit for raid1c34 after last block group is gone
David Sterba [Thu, 31 Oct 2019 14:52:01 +0000 (15:52 +0100)]
btrfs: drop incompat bit for raid1c34 after last block group is gone

When there are no raid1c3 or raid1c4 block groups left after balance
(either convert or with other filters applied), remove the incompat bit.
This is already done for RAID56, do the same for RAID1C34.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add incompat for raid1 with 3, 4 copies
David Sterba [Tue, 10 Jul 2018 16:15:05 +0000 (18:15 +0200)]
btrfs: add incompat for raid1 with 3, 4 copies

The new raid1c3 and raid1c4 profiles are backward incompatible and the
name shall be 'raid1c34', the status can be found in the global
supported features in /sys/fs/btrfs/features or in the per-filesystem
directory.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add support for 4-copy replication (raid1c4)
David Sterba [Fri, 2 Mar 2018 21:56:53 +0000 (22:56 +0100)]
btrfs: add support for 4-copy replication (raid1c4)

Add new block group profile to store 4 copies in a simliar way that
current RAID1 does.  The profile attributes and constraints are defined
in the raid table and used by the same code that already handles the 2-
and 3-copy RAID1.

The minimum number of devices is 4, the maximum number of devices/chunks
that can be lost/damaged is 3. There is no comparable traditional RAID
level, the profile is added for future needs to accompany triple-parity
and beyond.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add support for 3-copy replication (raid1c3)
David Sterba [Fri, 2 Mar 2018 21:56:53 +0000 (22:56 +0100)]
btrfs: add support for 3-copy replication (raid1c3)

Add new block group profile to store 3 copies in a simliar way that
current RAID1 does. The profile attributes and constraints are defined
in the raid table and used by the same code that already handles the
2-copy RAID1.

The minimum number of devices is 3, the maximum number of devices/chunks
that can be lost/damaged is 2. Like RAID6 but with 33% space
utilization.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: sink write flags to cow_file_range_async
David Sterba [Tue, 29 Oct 2019 17:28:57 +0000 (18:28 +0100)]
btrfs: sink write flags to cow_file_range_async

In commit "Btrfs: use REQ_CGROUP_PUNT for worker thread submitted bios",
cow_file_range_async gained wbc as a parameter and this makes passing
write flags redundant. Set it inside the function and remove the
parameter.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: sink write_flags to __extent_writepage_io
David Sterba [Tue, 29 Oct 2019 17:28:55 +0000 (18:28 +0100)]
btrfs: sink write_flags to __extent_writepage_io

__extent_writepage reads write flags from wbc and passes both to
__extent_writepage_io. This makes write_flags redundant and we can
remove it.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: send, skip backreference walking for extents with many references
Filipe Manana [Wed, 30 Oct 2019 12:23:01 +0000 (12:23 +0000)]
Btrfs: send, skip backreference walking for extents with many references

Backreference walking, which is used by send to figure if it can issue
clone operations instead of write operations, can be very slow and use
too much memory when extents have many references. This change simply
skips backreference walking when an extent has more than 64 references,
in which case we fallback to a write operation instead of a clone
operation. This limit is conservative and in practice I observed no
signicant slowdown with up to 100 references and still low memory usage
up to that limit.

This is a temporary workaround until there are speedups in the backref
walking code, and as such it does not attempt to add extra interfaces or
knobs to tweak the threshold.

Reported-by: Atemu <atemu.main@gmail.com>
Link: https://lore.kernel.org/linux-btrfs/CAE4GHgkvqVADtS4AzcQJxo0Q1jKQgKaW3JGp3SGdoinVo=C9eQ@mail.gmail.com/T/#me55dc0987f9cc2acaa54372ce0492c65782be3fa
CC: stable@vger.kernel.org # 4.4+
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: send, allow clone operations within the same file
Filipe Manana [Wed, 30 Oct 2019 12:23:11 +0000 (12:23 +0000)]
Btrfs: send, allow clone operations within the same file

For send we currently skip clone operations when the source and
destination files are the same. This is so because clone didn't support
this case in its early days, but support for it was added back in May
2013 by commit a96fbc72884fcb ("Btrfs: allow file data clone within a
file"). This change adds support for it.

Example:

  $ mkfs.btrfs -f /dev/sdd
  $ mount /dev/sdd /mnt/sdd

  $ xfs_io -f -c "pwrite -S 0xab -b 64K 0 64K" /mnt/sdd/foobar
  $ xfs_io -c "reflink /mnt/sdd/foobar 0 64K 64K" /mnt/sdd/foobar

  $ btrfs subvolume snapshot -r /mnt/sdd /mnt/sdd/snap

  $ mkfs.btrfs -f /dev/sde
  $ mount /dev/sde /mnt/sde

  $ btrfs send /mnt/sdd/snap | btrfs receive /mnt/sde

Without this change file foobar at the destination has a single 128Kb
extent:

  $ filefrag -v /mnt/sde/snap/foobar
  Filesystem type is: 9123683e
  File size of /mnt/sde/snap/foobar is 131072 (32 blocks of 4096 bytes)
   ext:     logical_offset:        physical_offset: length:   expected: flags:
     0:        0..      31:          0..        31:     32:             last,unknown_loc,delalloc,eof
  /mnt/sde/snap/foobar: 1 extent found

With this we get a single 64Kb extent that is shared at file offsets 0
and 64K, just like in the source filesystem:

  $ filefrag -v /mnt/sde/snap/foobar
  Filesystem type is: 9123683e
  File size of /mnt/sde/snap/foobar is 131072 (32 blocks of 4096 bytes)
   ext:     logical_offset:        physical_offset: length:   expected: flags:
     0:        0..      15:       3328..      3343:     16:             shared
     1:       16..      31:       3328..      3343:     16:       3344: last,shared,eof
  /mnt/sde/snap/foobar: 2 extents found

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Ensure we trim ranges across block group boundary
Qu Wenruo [Wed, 23 Oct 2019 13:57:27 +0000 (21:57 +0800)]
btrfs: Ensure we trim ranges across block group boundary

[BUG]
When deleting large files (which cross block group boundary) with
discard mount option, we find some btrfs_discard_extent() calls only
trimmed part of its space, not the whole range:

  btrfs_discard_extent: type=0x1 start=19626196992 len=2144530432 trimmed=1073741824 ratio=50%

type: bbio->map_type, in above case, it's SINGLE DATA.
start: Logical address of this trim
len: Logical length of this trim
trimmed: Physically trimmed bytes
ratio: trimmed / len

Thus leaving some unused space not discarded.

[CAUSE]
When discard mount option is specified, after a transaction is fully
committed (super block written to disk), we begin to cleanup pinned
extents in the following call chain:

btrfs_commit_transaction()
|- btrfs_finish_extent_commit()
   |- find_first_extent_bit(unpin, 0, &start, &end, EXTENT_DIRTY);
   |- btrfs_discard_extent()

However, pinned extents are recorded in an extent_io_tree, which can
merge adjacent extent states.

When a large file gets deleted and it has adjacent file extents across
block group boundary, we will get a large merged range like this:

      |<---    BG1    --->|<---      BG2     --->|
      |//////|<--   Range to discard   --->|/////|

To discard that range, we have the following calls:

  btrfs_discard_extent()
  |- btrfs_map_block()
  |  Returned bbio will end at BG1's end. As btrfs_map_block()
  |  never returns result across block group boundary.
  |- btrfs_issuse_discard()
     Issue discard for each stripe.

So we will only discard the range in BG1, not the remaining part in BG2.

Furthermore, this bug is not that reliably observed, for above case, if
there is no other extent in BG2, BG2 will be empty and btrfs will trim
all space of BG2, covering up the bug.

[FIX]
- Allow __btrfs_map_block_for_discard() to modify @length parameter
  btrfs_map_block() uses its @length paramter to notify the caller how
  many bytes are mapped in current call.
  With __btrfs_map_block_for_discard() also modifing the @length,
  btrfs_discard_extent() now understands when to do extra trim.

- Call btrfs_map_block() in a loop until we hit the range end Since we
  now know how many bytes are mapped each time, we can iterate through
  each block group boundary and issue correct trim for each range.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Tested-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: volumes: Use more straightforward way to calculate map length
Qu Wenruo [Wed, 23 Oct 2019 13:57:26 +0000 (21:57 +0800)]
btrfs: volumes: Use more straightforward way to calculate map length

The old code goes:

  offset = logical - em->start;
length = min_t(u64, em->len - offset, length);

Where @length calculation is dependent on offset, it can take reader
several more seconds to find it's just the same code as:

  offset = logical - em->start;
length = min_t(u64, em->start + em->len - logical, length);

Use above code to make the length calculate independent from other
variable, thus slightly increase the readability.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: tree-checker: Check item size before reading file extent type
Qu Wenruo [Mon, 2 Sep 2019 23:46:19 +0000 (07:46 +0800)]
btrfs: tree-checker: Check item size before reading file extent type

In check_extent_data_item(), we read file extent type without verifying
if the item size is valid.

Add such check to ensure the file extent type we read is correct.

The check is not as accurate as we need to cover both inline and regular
extents, so it only checks if the item size is larger or equal to inline
header.
So the existing size checks on inline/regular extents are still needed.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: clean up locking name in scrub_enumerate_chunks()
Dan Carpenter [Thu, 31 Oct 2019 10:55:01 +0000 (13:55 +0300)]
btrfs: clean up locking name in scrub_enumerate_chunks()

The "&fs_info->dev_replace.rwsem" and "&dev_replace->rwsem" refer to
the same lock but Smatch is not clever enough to figure that out so it
leads to static checker warnings.  It's better to use it consistently
anyway.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Streamline btrfs_fs_info::backup_root_index semantics
Nikolay Borisov [Tue, 15 Oct 2019 15:42:24 +0000 (18:42 +0300)]
btrfs: Streamline btrfs_fs_info::backup_root_index semantics

The backup_root_index member stores the index at which the backup root
should be saved upon next transaction commit. However, there is a
small deviation from this behavior in the form of a check in
backup_super_roots which checks if current root generation equals to the
generation of the previous root. This can trigger in the following
scenario:

slot0: gen-2
slot1: gen-1
slot2: gen
slot3: unused

Now suppose slot3 (which is also the root specified in the super block)
is corrupted hence init_tree_roots chooses to use the backup root at
slot2, meaning read_backup_root will read slot2 and assign the
superblock generation to gen-1. Despite this backup_root_index will
point at slot3 because its init happens in init_backup_root_slot, long
before any parsing of the backup roots occur. Then on next transaction
start, gen-1 will be incremented by 1 making the root's generation
equal gen. Subsequently, on transaction commit the following check
triggers:

  if (btrfs_backup_tree_root_gen(root_backup) ==
           btrfs_header_generation(info->tree_root->node))

This causes the 'next_backup', which is the index at which the backup is
going to be written to, to set to last_backup, which will be slot2.

All of this is a very confusing way of expressing the following
invariant:

 Always write a backup root at the index following the last used backup
 root.

This commit streamlines this logic by setting backup_root_index to the
next index after the one used for mount.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Rename find_oldest_super_backup to init_backup_root_slot
Nikolay Borisov [Tue, 15 Oct 2019 15:42:23 +0000 (18:42 +0300)]
btrfs: Rename find_oldest_super_backup to init_backup_root_slot

The old name name was an awful misnomer because it didn't really find
the oldest super backup per-se but rather its slot. For example if we
have:

slot0: gen - 2
slot1: gen - 1
slot2: gen
slot3: empty

init_backup_root_slot will return slot3 and not slot0.

The new name is more appropriate since the function doesn't care whether
there is a valid backup in the returned slot or not.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Remove unused next_root_backup function
Nikolay Borisov [Tue, 15 Oct 2019 15:42:22 +0000 (18:42 +0300)]
btrfs: Remove unused next_root_backup function

This function has been superseded by previous commits and is no longer
used so just remove it.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Don't use objectid_mutex during mount
Nikolay Borisov [Tue, 15 Oct 2019 15:42:21 +0000 (18:42 +0300)]
btrfs: Don't use objectid_mutex during mount

Since the filesystem is not well formed and no trees are loaded it's
pointless holding the objectid_mutex. Just remove its usage.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Factor out tree roots initialization during mount
Nikolay Borisov [Tue, 15 Oct 2019 15:42:20 +0000 (18:42 +0300)]
btrfs: Factor out tree roots initialization during mount

The code responsible for reading and initializing tree roots is
scattered in open_ctree among 2 labels, emulating a loop. This is rather
confusing to reason about. Instead, factor the code to a new function,
init_tree_roots which implements the same logical flow.

There are a couple of notable differences, namely:

* Instead of using next_backup_root it's using the newly introduced
  read_backup_root.

* If read_backup_root returns an error init_tree_roots propagates the
  error and there is no special handling of that case e.g. the code jumps
  straight to 'fail_tree_roots' label. The old code, however, was
  (erroneously) jumping to 'fail_block_groups' label if next_backup_root
  did fail, this was unnecessary since the tree roots init logic doesn't
  modify the state of block groups.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Add read_backup_root
Nikolay Borisov [Tue, 15 Oct 2019 15:42:19 +0000 (18:42 +0300)]
btrfs: Add read_backup_root

This function will replace next_root_backup with a much saner/cleaner
interface.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Remove newest_gen argument from find_oldest_super_backup
Nikolay Borisov [Tue, 15 Oct 2019 15:42:18 +0000 (18:42 +0300)]
btrfs: Remove newest_gen argument from find_oldest_super_backup

It's no longer needed following cleanups around find_newest_backup_root

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Cleanup and simplify find_newest_super_backup
Nikolay Borisov [Tue, 15 Oct 2019 15:42:17 +0000 (18:42 +0300)]
btrfs: Cleanup and simplify find_newest_super_backup

Backup roots are always written in a circular manner. By definition we
can only ever have 1 backup root whose generation equals to that of the
superblock. Hence, the 'if' in the for loop will trigger at most once.
This is sufficient to return the newest backup root.

Furthermore the newest_gen parameter is always set to the generation of
the superblock. This value can be obtained from the fs_info.

This patch removes the unnecessary code dealing with the wraparound
case and makes 'newest_gen' a local variable.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: remove unnecessary delalloc mutex for inodes
Filipe Manana [Fri, 25 Oct 2019 09:52:42 +0000 (10:52 +0100)]
Btrfs: remove unnecessary delalloc mutex for inodes

The inode delalloc mutex was added a long time ago by commit f248679e86fea
("Btrfs: add a delalloc mutex to inodes for delalloc reservations"), and
the reason for its introduction is not very clear from the change log. It
claims it solves bogus warnings from lockdep, however it lacks an example
report/warning from lockdep, or any explanation.

Since we have enough concurrentcy protection from the locks of the space
info and block reserve objects, and such lockdep warnings don't seem to
exist anymore (at least on a 5.3 kernel I couldn't get them with fstests,
ltp, fs_mark, etc), remove it, simplifying things a bit and decreasing
the size of the btrfs_inode structure. With some quick fio tests doing
direct IO and mmap writes I couldn't observe any significant performance
increase either (direct IO writes that don't increase the file's size
don't hold the inode's lock for their entire duration and mmap writes
don't hold the inode's lock at all), which are the only type of writes
that could see any performance gain due to less serialization.

Review feedback from Josef:

The problem was taking the i_mutex in mmap, which is how I was
protecting delalloc reservations originally.  The delalloc mutex didn't
come with all of the other dependencies.  That's what the lockdep
messages were about, removing the lock isn't going to make them appear
again.

We _had_ to lock around this because we used to do tricks to keep from
over-reserving, and if we didn't serialize delalloc reservations we'd
end up with ugly accounting problems when we tried to clean things up.

However with my recentish changes this isn't the case anymore.  Every
operation is responsible for reserving its space, and then adding it to
the inode.  Then cleaning up is straightforward and can't be mucked up
by other users.  So we no longer need the delalloc mutex to safe us from
ourselves.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoBtrfs: remove wait queue from space_info structure
Filipe Manana [Fri, 25 Oct 2019 09:53:12 +0000 (10:53 +0100)]
Btrfs: remove wait queue from space_info structure

It is not used anymore since commit 957780eb2788d8 ("Btrfs: introduce
ticketed enospc infrastructure"), so just remove it.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: remove cached space_info in btrfs_statfs()
Johannes Thumshirn [Thu, 24 Oct 2019 15:44:54 +0000 (17:44 +0200)]
btrfs: remove cached space_info in btrfs_statfs()

In btrfs_statfs() we cache fs_info::space_info in a local variable only
to use it once in a list_for_each_rcu() statement.

Not only is the local variable unnecessary it even makes the code harder
to follow as it's not clear which list it is iterating.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add dedicated members for start and length of a block group
David Sterba [Wed, 23 Oct 2019 16:48:22 +0000 (18:48 +0200)]
btrfs: add dedicated members for start and length of a block group

The on-disk format of block group item makes use of the key that stores
the offset and length. This is further used in the code, although this
makes thing harder to understand. The key is also packed so the
offset/length is not properly aligned as u64.

Add start (key.objectid) and length (key.offset) members to block group
and remove the embedded key.  When the item is searched or written, a
local variable for key is used.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: rename extent buffer block group item accessors
David Sterba [Wed, 23 Oct 2019 16:48:20 +0000 (18:48 +0200)]
btrfs: rename extent buffer block group item accessors

Accessors defined by BTRFS_SETGET_FUNCS take a raw extent buffer and
manipulate the items there, there's no special prefix required. The
block group accessors had _disk_ because previously the names were
occupied by the on-stack accessors. As this has been addressed in the
previous patch, we can now unify the naming.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: rename block_group_item on-stack accessors to follow naming
David Sterba [Wed, 23 Oct 2019 16:48:18 +0000 (18:48 +0200)]
btrfs: rename block_group_item on-stack accessors to follow naming

All accessors defined by BTRFS_SETGET_STACK_FUNCS contain _stack_ in the
name, the block group ones were not following that scheme, so let's
switch them.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: remove embedded block_group_cache::item
David Sterba [Wed, 23 Oct 2019 16:48:15 +0000 (18:48 +0200)]
btrfs: remove embedded block_group_cache::item

The members ::used and ::flags are now in the block group cache
structure, the last one is chunk_objectid, but that's set to a fixed
value and otherwise unused. The item is constructed from a local
variable before write, so we can remove the embedded one from block
group.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: move block_group_item::flags to block group
David Sterba [Wed, 23 Oct 2019 16:48:13 +0000 (18:48 +0200)]
btrfs: move block_group_item::flags to block group

The flags are read from the item that's embedded to block group struct,
but the item will be removed. Use the ::flags after read and before
write.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: move block_group_item::used to block group
David Sterba [Wed, 23 Oct 2019 16:48:11 +0000 (18:48 +0200)]
btrfs: move block_group_item::used to block group

For unknown reasons, the member 'used' in the block group struct is
stored in the b-tree item and accessed everywhere using the special
accessor helper. Let's unify it and make it a regular member and only
update the item before writing it to the tree.

The item is still being used for flags and chunk_objectid, there's some
duplication until the item is removed in following patches.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: Remove btrfs_bio::flags member
Qu Wenruo [Thu, 24 Oct 2019 01:38:29 +0000 (09:38 +0800)]
btrfs: Remove btrfs_bio::flags member

The last user of btrfs_bio::flags was removed in commit 326e1dbb5736
("block: remove management of bi_remaining when restoring original
bi_end_io"), remove it.

(Tagged for stable as the structure is heavily used and space savings
are desirable.)

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>
5 years agobtrfs: add blake2b to checksumming algorithms
David Sterba [Mon, 7 Oct 2019 09:11:02 +0000 (11:11 +0200)]
btrfs: add blake2b to checksumming algorithms

Add blake2b (with 256 bit digest) to the list of possible checksumming
algorithms used by BTRFS.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add member for a specific checksum driver
David Sterba [Tue, 8 Oct 2019 16:41:33 +0000 (18:41 +0200)]
btrfs: add member for a specific checksum driver

Currently all the checksum algorithms generate a fixed size digest size
and we use it.  The on-disk format can hold up to BTRFS_CSUM_SIZE bytes
and BLAKE2b produces digest of 512 bits by default. We can't do that and
will use the blake2b-256, this needs to be passed to the crypto API.

Separate that from the base algorithm name and add a member to request
specific driver, in this case with the digest size.

The only place that uses the driver name is the crypto API setup.

Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: sysfs: show used checksum driver per filesystem
Johannes Thumshirn [Mon, 7 Oct 2019 09:11:04 +0000 (11:11 +0200)]
btrfs: sysfs: show used checksum driver per filesystem

Show the used driver for the checksum algorithm for the filesystem in
sysfs file /sys/fs/btrfs/UUID/features/checksum, eg.

  crc32c (crc32c-generic)

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: sysfs: export supported checksums
David Sterba [Mon, 7 Oct 2019 09:11:03 +0000 (11:11 +0200)]
btrfs: sysfs: export supported checksums

Export supported checksum algorithms via sysfs in the list of static
features:

  /sys/fs/btrfs/features/supported_checksums

Space spearated list of checksum algorithm names.

Co-developed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add sha256 to checksumming algorithm
Johannes Thumshirn [Mon, 7 Oct 2019 09:11:02 +0000 (11:11 +0200)]
btrfs: add sha256 to checksumming algorithm

Add sha256 to the list of possible checksumming algorithms used by BTRFS.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: add xxhash64 to checksumming algorithms
Johannes Thumshirn [Mon, 7 Oct 2019 09:11:01 +0000 (11:11 +0200)]
btrfs: add xxhash64 to checksumming algorithms

Add xxhash64 to the list of possible checksumming algorithms used by
BTRFS.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: get bdev from latest_dev for dio bh_result
David Sterba [Fri, 30 Aug 2019 13:42:07 +0000 (15:42 +0200)]
btrfs: get bdev from latest_dev for dio bh_result

To remove use of extent_map::bdev we need to find a replacement, and the
latest_bdev is the only one we can use here, because inode::i_bdev and
superblock::s_bdev are NULL.

The DIO code uses bdev in two places:

* to read blocksize to perform alignment checks in
  do_blockdev_direct_IO, but we do them in btrfs code before any call to
  DIO

* in the following call chain:

  do_direct_IO
    get_more_blocks
     sdio->get_block() <-- this is btrfs_get_blocks_direct

  subsequently the map_bh->b_dev member is used in clean_bdev_aliases
  and dio_new_bio to set the bio's bdev to that of the buffer_head.
  However, because we have provided a submit function dio_bio_submit
  calls our submission function and ignores the bdev.

So it's safe to pass any valid bdev that's used within the filesystem.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>