]> git.hungrycats.org Git - linux/log
linux
5 years agozygo: config: unexpected 'make oldconfig' while testing fdmanana unexpected-oldconfig
Zygo Blaxell [Sat, 6 Mar 2021 14:38:54 +0000 (09:38 -0500)]
zygo: config: unexpected 'make oldconfig' while testing fdmanana

5 years agobtrfs: tree mod log vs zoned fix 2 from fdmanana tree-mod-test
Zygo Blaxell [Sat, 6 Mar 2021 14:31:03 +0000 (09:31 -0500)]
btrfs: tree mod log vs zoned fix 2 from fdmanana

Great!

Ok, so that seems to confirm what I suspected and made me run into
other sorts of weirdness during logical ino calls (returning
unexpected results).
I haven't hit the BUG_ON() as you do, but if this is indeed caused by
allowing to reuse unwritten extent buffers in the same transaction,
it's no wonder that BUG_ON() and many other weird issues happen.

Can you now try the following version?

https://pastebin.com/raw/5VHjzdn6

Leave it for at least as many days as you tested the previous patch,
hell, even a week or more if you can.

Thanks, much appreciated.

5 years agoRevert "btrfs: tree mod log fix for fdmanana"
Zygo Blaxell [Sat, 6 Mar 2021 14:30:15 +0000 (09:30 -0500)]
Revert "btrfs: tree mod log fix for fdmanana"

This reverts commit 7979e557fa1dd6937722e3b44d7d7c7642d9a4d5.

5 years agobtrfs: tree mod log fix for fdmanana
Zygo Blaxell [Tue, 2 Mar 2021 17:41:50 +0000 (12:41 -0500)]
btrfs: tree mod log fix for fdmanana

Different bugs causing similar problems.

Try this:   https://pastebin.com/VkesNs4R

Thanks.

(cherry picked from commit 858e9a14df8f6d5052d871b1917705d09a77dfa7)

5 years agozygo: make oldconfig for misc-next 2021-02-14
Zygo Blaxell [Sun, 14 Feb 2021 17:30:53 +0000 (12:30 -0500)]
zygo: make oldconfig for misc-next 2021-02-14

5 years agozygo: make oldconfig for zygo-misc-next-zb64 from zygo-for-next-zb64
Zygo Blaxell [Mon, 25 Jan 2021 22:35:06 +0000 (17:35 -0500)]
zygo: make oldconfig for zygo-misc-next-zb64 from zygo-for-next-zb64

5 years agobtrfs: do not allow data to be allocated on the wrong device type
Zygo Blaxell [Wed, 13 Jan 2021 03:31:22 +0000 (22:31 -0500)]
btrfs: do not allow data to be allocated on the wrong device type

If any device is marked preferred_metadata, then:

- permit metadata chunk allocations only on preferred devices,
to avoid losing the performance gain of the preferred devices.

- permit data chunk allocations only on non-preferred devices,
to avoid polluting the preferred devices with data, and starving
the filesystem of metadata space.

If no device is marked preferred_metadata, then allocate any data or
metadata chunk on any device with available space.

Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
(cherry picked from commit 6d6f51c4e4bd7cc3c082d9fd3bba211c550dc473)
(cherry picked from commit c95261fa6a81e69091d1ba190c964f015c261011)

5 years agobtrfs: fixup btrfs_find_device 4 arguments
Goffredo Baroncelli [Thu, 28 May 2020 18:34:51 +0000 (20:34 +0200)]
btrfs: fixup btrfs_find_device 4 arguments

5 years agobtrfs: add preferred_metadata mode (with last btrfs_find_device argument, without...
Goffredo Baroncelli [Thu, 28 May 2020 18:34:51 +0000 (20:34 +0200)]
btrfs: add preferred_metadata mode (with last btrfs_find_device argument, without mount option)

When this mode is enabled, the allocation policy of the chunk
is so modified:
- allocation of metadata chunk: priority is given to preferred_metadata
  disks.
- allocation of data chunk: priority is given to a non preferred_metadata
  disk.

When a striped profile is involved (like RAID0,5,6), the logic
is a bit more complex. If there are enough disks, the data profiles
are stored on the non preferred_metadata disks; instead the metadata
profiles are stored on the preferred_metadata disk.
If the disks are not enough, then the profile is allocated on all
the disks.

Example: assuming that sda, sdb, sdc are ssd disks, and sde, sdf are
non preferred_metadata ones.
A data profile raid6, will be stored on sda, sdb, sdc, sde, sdf (sde
and sdf are not enough to host a raid5 profile).
A metadata profile raid6, will be stored on sda, sdb, sdc (these
are enough to host a raid6 profile).

To enable this mode pass -o dedicated_metadata at mount time.

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
(cherry picked from commit fc8c568d8d1982558aca72dada291dd087d6cb7a)
(cherry picked from commit 1d4c7f65a47eadff2ce33d1562cbb65a58996138)
(cherry picked from commit b2a92a3bc07a05907626f4d518a6af0c53a2a9d2)

zygo: btrfs: fix btrfs_ioctl_dev_properties extra argument for btrfs_find_device

(cherry picked from commit dbd08fd8d91377423abee53cce4de95249825c71)

zygo: btrfs: remove unnecessary preferred_metadata mount option

(cherry picked from commit 3d3b483295ab700874fc492ebfa944674e32f95e)

Revert "zygo: btrfs: fix btrfs_ioctl_dev_properties extra argument for btrfs_find_device"

This reverts commit dbd08fd8d91377423abee53cce4de95249825c71.

(cherry picked from commit 7ff6cdcc37319fd4407f4ec92cb962c0114ac53f)

5 years agoExport dev_item.type in sysfs /sys/fs/btrfs/<uuid>/devinfo/<devid>/type
Goffredo Baroncelli [Thu, 28 May 2020 18:34:50 +0000 (20:34 +0200)]
Export dev_item.type in sysfs /sys/fs/btrfs/<uuid>/devinfo/<devid>/type

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
(cherry picked from commit 35c9b7a7469c616af39ddae46d7645918f53bbda)
(cherry picked from commit af8e3c07b2fba9c917be34558baf1ef387bf4d45)
(cherry picked from commit 75b1249019e1045f85ec9644ee411a8ff48017e4)

5 years agoAdd flags for dedicated metadata disks
Goffredo Baroncelli [Thu, 28 May 2020 18:34:49 +0000 (20:34 +0200)]
Add flags for dedicated metadata disks

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
(cherry picked from commit a0e2f5625bab99013343ec2333bfa584c267a828)
(cherry picked from commit 25a8cc321128095fd3b58f73208dd217cfd5fb59)
(cherry picked from commit 54f447a3dbaa6f344195f42357dd18f5b8c579bf)

5 years agoAdd an ioctl to set/retrive the device properties
Goffredo Baroncelli [Thu, 28 May 2020 18:34:48 +0000 (20:34 +0200)]
Add an ioctl to set/retrive the device properties

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
(cherry picked from commit 6ea419396b107061c491c53385bd3931fdff7669)
(cherry picked from commit e47c1e792870d932a3b92d83e494a0a38f1175bc)
(cherry picked from commit e1ad99696bbb6345fe4dcb6ce9ee2543add73cde)

5 years agozygo: config: enable BRCMFMAC and some other brcm's
Zygo Blaxell [Mon, 7 Dec 2020 04:39:29 +0000 (23:39 -0500)]
zygo: config: enable BRCMFMAC and some other brcm's

(cherry picked from commit 8593bdb1a570c75bb7edd96a80d6556ea5418379)
(cherry picked from commit 5c90f2aa7b2c9af3b6cbdc4a059751d1808188f3)

5 years agozygo: config: default performance
Zygo Blaxell [Mon, 7 Dec 2020 04:58:28 +0000 (23:58 -0500)]
zygo: config: default performance

(cherry picked from commit 81990f433230511b97a0824e45e746fa99346364)

5 years agozygo: config: enable BRCMFMAC and some other brcm's, make oldconfig for v5.11-rc2
Zygo Blaxell [Mon, 7 Dec 2020 04:39:29 +0000 (23:39 -0500)]
zygo: config: enable BRCMFMAC and some other brcm's, make oldconfig for v5.11-rc2

(cherry picked from commit 8593bdb1a570c75bb7edd96a80d6556ea5418379)
(cherry picked from commit 5c90f2aa7b2c9af3b6cbdc4a059751d1808188f3)
(cherry picked from commit e2597a34ca4b4f34a9430c7a5f4d2082e2ce1c75)
(cherry picked from commit a6378ded2442690d538e27a9e4cd452dac97389d)

5 years agobtrfs: bump LOGICAL_INO_V2 size limit to 1G
Zygo Blaxell [Thu, 24 Dec 2020 19:09:21 +0000 (14:09 -0500)]
btrfs: bump LOGICAL_INO_V2 size limit to 1G

(cherry picked from commit 958b47f36b155b6d255f13f5a4213e0559ba5d68)
(cherry picked from commit 8ba22a5381d6eb7b94a7a5751038dd8a644f6585)
(cherry picked from commit 478fd6ad0c19b12c723b2fa2d67c944020b01313)

5 years agozygo: make-kernel: apparently if we don't override KSRC, we don't override anything
Zygo Blaxell [Mon, 28 Dec 2020 12:25:52 +0000 (07:25 -0500)]
zygo: make-kernel: apparently if we don't override KSRC, we don't override anything

(cherry picked from commit b9c11139ef2b3856f60a8dbfab5930985e9f0c4a)
(cherry picked from commit 89644f0e49db957f72459a0096f655d5a0d5fa73)
(cherry picked from commit b4a02ecc4f10ea8a0600e43839ced832eccb302e)

5 years agozygo: make-kernel: time the builds
Zygo Blaxell [Fri, 25 Dec 2020 10:53:53 +0000 (05:53 -0500)]
zygo: make-kernel: time the builds

(cherry picked from commit 2101cdfaa8b0c9b49546536c229d3fe2154b99d1)

5 years agozygo: make-kernel: build the modules again in 2020
Zygo Blaxell [Fri, 25 Dec 2020 10:07:19 +0000 (05:07 -0500)]
zygo: make-kernel: build the modules again in 2020

zygo: make-kernel: build the modules in parallel with separate make.logs

zygo: make-kernel: modules need fakeroot

zygo: make-kernel: target is binary_modules
(cherry picked from commit 4e1a4954d9df12a200ee9227effffaab4c6f324f)

5 years agozygo: preserve build artifacts between builds
Zygo Blaxell [Thu, 24 Dec 2020 05:27:50 +0000 (00:27 -0500)]
zygo: preserve build artifacts between builds

(cherry picked from commit 2461e8c8918b0c06b0beed09a4463ecc32e9fa52)

5 years agozygo: OK maybe 96 kernel jobs at once is a bit excessive
Zygo Blaxell [Thu, 2 Apr 2020 15:04:32 +0000 (11:04 -0400)]
zygo: OK maybe 96 kernel jobs at once is a bit excessive

(cherry picked from commit 024c282a872f25b471b45cb14ba27dd7d6f5f0ec)
(cherry picked from commit 838da32fd5848271ee85de80017600cbc151e0ff)

5 years agobtrfs: fix race between dedupe and mmap
Josef Bacik [Fri, 11 Dec 2020 22:12:52 +0000 (17:12 -0500)]
btrfs: fix race between dedupe and mmap

Darrick asked how btrfs currently protects against mmap modifying a page
during dedupe, and when I checked I realized it doesn't.  Previously we
did the following dance

lock page ranges in both files
  lock extent
    flush ordered
      validate pages are the same
        dedupe

However Filipe moved us to use the generic checks, which instead does
this dance

lock inode
  flush everything, check for ordered extents
  lock page in both corresponding inodes
    validate pages are the same
  unlock pages
  lock extent
  dedupe

The problem here is we're not doing our normal page lock -> extent lock
-> validate check.  The generic checks assume we've blocked everybody
from modifying the file, which we have with the exception of mmap.

There are two ways we can fix this, and I've chosen the simplest.

The more complicated way is to add a flag to the generic checks to tell
it that we'll do the page verification ourselves.  Then we add back the
checks to btrfs_extent_same() to do the proper lock ordering in order to
validate the pages.

The simpler way to do this is to simply add a mechanism to block mmap
from happening while we're doing dedupe.  I've opted for this strategy,
because it's more straightforward and allows us to continue using the
generic infrastructure.

Ext4 and xfs do not have this problem because they have an inode lock
that they use to block mmap from happening, the i_mmap_sem in ext4's
case and the ilock for xfs.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
5 years agobtrfs: balance RAID1/RAID10 mirror selection
louis@waffle.tech [Fri, 16 Oct 2020 05:59:19 +0000 (05:59 +0000)]
btrfs: balance RAID1/RAID10 mirror selection

Balance RAID1/RAID10 mirror selection via plain round-robin scheduling. This should roughly double throughput for large reads.

Signed-off-by: Louis Jencka <louis@waffle.tech>
5 years agozygo: config: make oldconfig for misc-next 2020-11-20
Zygo Blaxell [Sun, 18 Oct 2020 02:53:41 +0000 (22:53 -0400)]
zygo: config: make oldconfig for misc-next 2020-11-20

zygo: config: make oldconfig for misc-next 2020-10-17

zygo: config: make oldconfig for misc-next v5.9 2020-10-20

zygo: config: make oldconfig for misc-next 5.9.0 2020-10-24

zygo: config: make oldconfig for misc-next 2020-11-06

5 years agozygo: config: enable btrfs DEBUG, ASSERT, REF_VERIFY, CHECK_INTEGRITY; KASAN, poisoning
Zygo Blaxell [Fri, 15 May 2020 07:05:26 +0000 (03:05 -0400)]
zygo: config: enable btrfs DEBUG, ASSERT, REF_VERIFY, CHECK_INTEGRITY; KASAN, poisoning

zygo: config: enable KASAN, dammit

5 years agozygo: build-kernel: add misc-next tag
Zygo Blaxell [Thu, 8 Oct 2020 17:08:12 +0000 (13:08 -0400)]
zygo: build-kernel: add misc-next tag

5 years agozygo: btrfs: use a stable rolling average (1000 sec, 1000 refs, 0.75 decay, with...
Zygo Blaxell [Tue, 25 Feb 2020 18:14:19 +0000 (13:14 -0500)]
zygo: btrfs: use a stable rolling average (1000 sec, 1000 refs, 0.75 decay, with noisy debug)

zygo: btrfs: use a stable rolling average (300 sec, 0.75 decay, with noisy debug)

zygo: btrfs: what does the _kernel_ think the delayed ref runtime is?

zygo: btrfs: slow down the swings

zygo: btrfs: proper rolling average

zygo: btrfs: weight older data more

zygo: btrfs: less noisy rolling average
Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
zygo: btrfs: average over 300 sec

zygo: btrfs: slow down average calculations (1000 seconds or 1000 delayed refs)
(cherry picked from commit d26a857e08612d7dce8fa665bcce6fe6c0598e5e)
(cherry picked from commit 052469e5fd52d6353dd25f6efe2f4f8c37b81bdc)
(cherry picked from commit a30caddd802bd79f7c45756de36d8a9616b92d99)

5 years agozygo: fs/fs-writeback.c: WARN_ON_ONCE, this is a test kernel after all
Zygo Blaxell [Mon, 1 Jun 2020 03:52:32 +0000 (23:52 -0400)]
zygo: fs/fs-writeback.c: WARN_ON_ONCE, this is a test kernel after all

5 years agozygo: btrfs: count balance loops
Zygo Blaxell [Tue, 12 May 2020 01:56:32 +0000 (21:56 -0400)]
zygo: btrfs: count balance loops

5 years agoRevert "zygo: btrfs: test BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT"
Zygo Blaxell [Mon, 27 Apr 2020 20:16:07 +0000 (16:16 -0400)]
Revert "zygo: btrfs: test BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT"

This reverts commit be08df290d04b3d8f3d485a0b860f26e9b0e5aec.

5 years agobtrfs: allow balance usage filter to select full block groups
Zygo Blaxell [Mon, 16 Mar 2020 03:55:28 +0000 (23:55 -0400)]
btrfs: allow balance usage filter to select full block groups

There's a gap in what we can specify with the current balance usage
filter.  This command doesn't balance all data block groups:

        1.  btrfs balance start -dusage=0..100 /fs

and neither does this one:

        2.  btrfs balance start -dusage=100 /fs

and since commit a105bb88f46b6 in 2013, we can't work around with:

        3.  btrfs balance start -dusage=101 /fs/that/is/raid1

and there's a related problem when resuming paused balances, e.g. during
a mount.

Commands #1 and #2 fail as documented in the btrfs-balance man page:

       usage=<percent>, usage=<range>
           Balances only block groups with usage under the given
           percentage.

Since completely full block groups are not "under" 100%, the filter
expression "usage=100" covers any block group with at least 1 unused byte,
but not completely full block groups.

Command #3 fails because of commit a105bb88f46b6 "Btrfs: fix a regression
in balance usage filter" which removed the ability to specify percentage
values over 100; however, we don't want to revert that because we do
want to guard against integer overflows and other surprises that arise
from truly bad user inputs.

There are a few ways to fix this.  This patch implements one that does not
alter any existing behavior:  we allow 'usage=101' with the meaning "100%
+ 1 byte".  This leaves "usage=100" referring to any block group that is
not completely full, in case anyone relies on that filter behavior, while
allowing a method for accepting completely full blocks in the filter.
It also allows 'usage=101' to work around the balance recovery issue
below.

Starting with commit 596410151e "Btrfs: recover balance on mount",
btrfs will insert a 'usage=90' filter when resuming a balance if no
'usage' filter was used on the original balance.  If the original balance
does not use 'convert' or 'usage', then 'usage=90' will be inserted.
This can be surprising when pausing balances to let snapshot deletes run,
as in this log:

        BTRFS info (device dm-0): balance: start -dlimit=999
        BTRFS info (device dm-0): relocating block group 1776771137536 flags data
        BTRFS info (device dm-0): found 18 extents, stage: move data extents
        BTRFS info (device dm-0): found 18 extents, stage: update data pointers
        BTRFS info (device dm-0): balance: paused
        BTRFS debug (device dm-0): cleaner removing 2649
        BTRFS info (device dm-0): balance: resume -dusage=90,limit=998
        BTRFS info (device dm-0): balance: ended with status: 0

We expected to balance 999 block groups, instead we got one, because the
resumed balance used a very different filter than the original.  If we set
'usage=100', we avoid this behavior on balance resume, but we also fail
to balance all but one of the full block groups.  To work around this,
we need a way to set the BTRFS_BALANCE_ARGS_USAGE flag without losing
the ability to select full block groups.

Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
(cherry picked from commit f8392690b5fb1010484f7fa33b36e37c4a894de2)

5 years agozygo: btrfs: test BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT
Zygo Blaxell [Sun, 5 Apr 2020 21:04:46 +0000 (17:04 -0400)]
zygo: btrfs: test BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT

(cherry picked from commit 089c927a4b8edde89903667daef4ff7edf5f5428)
(cherry picked from commit 02a74429e93bedfe70218a8f164f227ef14ef7ad)

5 years agobtrfs: introduce BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT to trade latency for accur...
Zygo Blaxell [Sun, 22 Mar 2020 20:57:42 +0000 (16:57 -0400)]
btrfs: introduce BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT to trade latency for accuracy (v2)

The LOGICAL_INO ioctl is a simple wrapper around an internal btrfs kernel
function which iterates over references to a data extent.  This function
can operate in two modes:

#1 joins the current transaction to get up to date information
on uncommitted references.  LOGICAL_INO can run for a long
time--seconds to minutes on deduped filesystems--and all that
time gets added to the latency of transaction commits. This slows
down other threads writing to the filesystem, as well as reducing
concurrency in LOGICAL_INO itself.

#2 doesn't join a transaction, and just searches commit roots
instead.  This loses access to backref data from uncommitted
references, but doesn't add latency to all other users of the
filesystem while it runs.

Userspace has no mechanism to prevent concurrent changes on the
filesystem, so userspace must tolerate out-of-date backref information
e.g.  looping removing extent refs until LOGICAL_INO gives no more
reachable references.  With a switch from the #1 mode to the #2 mode,
userspace must ensure a commit occurs between loops, either by calling
fssync itself, or by finding something else to do between loop iterations
until a commit occurs naturally.

This is a change in behavior, so we don't do it by default.  Add a new
flag SEARCH_COMMIT_ROOT for LOGICAL_INO_V2 so that users can request
the faster, lower-latency version.

Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
(cherry picked from commit f35030f24f09ae428a3c069151ee8aaac5d5d041)
(cherry picked from commit 32c0c08a2c7cb65131c2679add5a302eb24c01f2)
(cherry picked from commit d753020b163b1b2ccba6fc39009a11e2c13633e4)
(cherry picked from commit 6c8b74540686d3096f8f0a85749eb71ae0c5e629)

v2: fixed logic to verify that all flags are supported.
(cherry picked from commit 403cd2651289de590d098dce433671eecc092cad)

5 years agozygo: btrfs: Revert "btrfs: don't report readahead errors and don't update statistics...
Zygo Blaxell [Fri, 10 Jan 2020 17:02:07 +0000 (12:02 -0500)]
zygo: btrfs: Revert "btrfs: don't report readahead errors and don't update statistics" because we don't want read errors to be silently ignored.

This reverts commit 0cc068e6ee59c1fffbfa977d8bf868b7551d80ac.

(cherry picked from commit ddda8c5edea780edd997e2736d40198f8dbb39bf)
(cherry picked from commit dc2c37f049f4b272b620349ed2f7d719cd28993f)
(cherry picked from commit eba51d4755242c6203951ed4bbeff765b17242bd)

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)
(cherry picked from commit 961e8b0c95f57ce37fb04945621116bee049a31f)
(cherry picked from commit a1b16e408c0231e6b2fb33ec28828ccd7e7a03ee)

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)
(cherry picked from commit 155c85ff96b3bc2caaf561604a28b337fca19022)
(cherry picked from commit a573ae419c83a3a45952a97b5aae0e322218bf0e)

5 years agozygo: config: make oldconfig for post-5.9 misc-next
Zygo Blaxell [Tue, 14 Jan 2020 23:57:22 +0000 (18:57 -0500)]
zygo: config: make oldconfig for post-5.9 misc-next

zygo: config: make oldconfig for misc-next v5.8-rc1

zygo: make oldconfig for zygo-5.6.x-zb64

zygo: make oldconfig for v5.5-rc6

(cherry picked from commit bd98f79494a989051a85f16937f022511f2270bc)
(cherry picked from commit 348d742ca04cadc1a157d0c6c279ec4aaf4b39ae)

zygo: make oldconfig for 5.6-rc1 (btrfs-next/zygo-debugging)

zygo: config: build enough in to run btrfs tests on a VM without modules

(cherry picked from commit d282979a89e18d2a54903d4f6d4c22be69af18e7)
(cherry picked from commit 6d39bfb5352db50f662882cd6b19d95fe10b2c97)

zygo: fixup config for v5.6 release
(cherry picked from commit 8aa6656271a302c3e5c7b929c8144861ad93f9f2)

zygo: make oldconfig for v5.7-rc1

zygo: make oldconfig for misc-next 2020-04-27 (VDPA)

zygo: make oldconfig for misc-next v5.8-rc2

zygo: make oldconfig for misc-next 2020-08-11

zygo: config: make oldconfig for misc-next v5.9-rc1

zygo: make oldconfig for misc-next 2020-09-09, 5.9-rc4

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

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)

zygo: add 'config-kernel' script to run 'make oldconfig' with KCONFIG_NOTIMESTAMP

(cherry picked from commit 4cc38d103bc42929ef42f3df5a344b27ab3fda45)

zygo: no .config
(cherry picked from commit 19241c180c3474423e9ec395494161ae87cc16dd)

zygo: build-kernel: lightweight build-and-deploy script inspired by Raspberry Pi and occasionally useful for bisection testing

(cherry picked from commit b43dc869686c996118ee7a879698013648f5dc22)

zygo: remove obsolete (and a little bit dangerous) cherry-pick scripts

(cherry picked from commit 3ec46e9b8830f60617d195b04c0df35890820dd5)

zygo: build-kernel: support no-modules builds instead of extraversion tag

zygo: build-kernel: support "extraversion" tag to rebuild bzimage without modules

zygo: fixup build-kernel

zygo: build-kernel: support no-modules builds instead of extraversion tag?

zygo: switch from kernel-package to bindeb-pkg (v2, no nested fakeroot)

(cherry picked from commit 9f0897f2bd10304eaece6c011725c3481595e4e0)

zygo: no nested fakeroot

23:54:06 O:   LD [M]  virt/lib/irqbypass.ko
23:54:07 E:  fakeroot -u debian/rules binary
23:54:07 E: fakeroot: FAKEROOTKEY set to 108604309
23:54:07 E: fakeroot: nested operation not yet supported
23:54:07 E: dpkg-buildpackage: error: fakeroot -u debian/rules binary subprocess returned exit status 1
23:54:08 E: make[1]: *** [scripts/package/Makefile:80: bindeb-pkg] Error 1
23:54:08 E: make: *** [Makefile:1365: bindeb-pkg] Error 2
23:54:08 I: Finished with exitcode 2
(cherry picked from commit 0ad8aded2bdba7c063ce7c9cbebdc4d11290155a)
(cherry picked from commit 93ab45f488366ca7a4c3c61ca8b7c47b9ad59336)

5 years agobtrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
Nikolay Borisov [Tue, 23 Feb 2021 13:20:42 +0000 (15:20 +0200)]
btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors

If btrfs_qgroup_reserve_data returns an error (i.e quota limit reached)
the handling logic directly goes to the 'out' label without first
unlocking the extent range between lockstart, lockend. This results in
deadlocks as other processes try to lock the same extent.

Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
CC: stable@vger.kernel.org # 5.10+
Reviewed-by: Qu Wenruo <wqu@suse.com>
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: ref-verify: use 'inline void' keyword ordering
Randy Dunlap [Fri, 19 Feb 2021 06:54:17 +0000 (22:54 -0800)]
btrfs: ref-verify: use 'inline void' keyword ordering

Fix build warnings of function signature when CONFIG_STACKTRACE is not
enabled by reordering the 'inline' and 'void' keywords.

../fs/btrfs/ref-verify.c:221:1: warning: â€˜inline’ is not at beginning of declaration [-Wold-style-declaration]
 static void inline __save_stack_trace(struct ref_action *ra)
../fs/btrfs/ref-verify.c:225:1: warning: â€˜inline’ is not at beginning of declaration [-Wold-style-declaration]
 static void inline __print_stack_trace(struct btrfs_fs_info *fs_info,

Fixes: fd708b81d972 ("Btrfs: add a extent ref verify tool")
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: fix deadlock on log sync
Johannes Thumshirn [Wed, 17 Feb 2021 07:06:18 +0000 (16:06 +0900)]
btrfs: zoned: fix deadlock on log sync

Lockdep with fstests test case btrfs/041 detected a unsafe locking
scenario when we allocate the log node on a zoned filesystem.

btrfs/041
 ============================================
 WARNING: possible recursive locking detected
 5.11.0-rc7+ #939 Not tainted
 --------------------------------------------
 xfs_io/698 is trying to acquire lock:
 ffff88810cd673a0 (&root->log_mutex){+.+.}-{3:3}, at: btrfs_sync_log+0x3d1/0xee0 [btrfs]

 but task is already holding lock:
 ffff88810b0fc3a0 (&root->log_mutex){+.+.}-{3:3}, at: btrfs_sync_log+0x313/0xee0 [btrfs]

 other info that might help us debug this:
  Possible unsafe locking scenario:

        CPU0
        ----
   lock(&root->log_mutex);
   lock(&root->log_mutex);

  *** DEADLOCK ***

  May be due to missing lock nesting notation

 2 locks held by xfs_io/698:
  #0: ffff88810cd66620 (sb_internal){.+.+}-{0:0}, at: btrfs_sync_file+0x2c3/0x570 [btrfs]
  #1: ffff88810b0fc3a0 (&root->log_mutex){+.+.}-{3:3}, at: btrfs_sync_log+0x313/0xee0 [btrfs]

 stack backtrace:
 CPU: 0 PID: 698 Comm: xfs_io Not tainted 5.11.0-rc7+ #939
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4-rebuilt.opensuse.org 04/01/2014
 Call Trace:
  dump_stack+0x77/0x97
  __lock_acquire.cold+0xb9/0x32a
  lock_acquire+0xb5/0x400
  ? btrfs_sync_log+0x3d1/0xee0 [btrfs]
  __mutex_lock+0x7b/0x8d0
  ? btrfs_sync_log+0x3d1/0xee0 [btrfs]
  ? btrfs_sync_log+0x3d1/0xee0 [btrfs]
  ? find_first_extent_bit+0x9f/0x100 [btrfs]
  ? __mutex_unlock_slowpath+0x35/0x270
  btrfs_sync_log+0x3d1/0xee0 [btrfs]
  btrfs_sync_file+0x3a8/0x570 [btrfs]
  __x64_sys_fsync+0x34/0x60
  do_syscall_64+0x33/0x40
  entry_SYSCALL_64_after_hwframe+0x44/0xa9
 RIP: 0033:0x7f1e856b8ecb
 RSP: 002b:00007ffde89011b0 EFLAGS: 00000293 ORIG_RAX: 000000000000004a
 RAX: ffffffffffffffda RBX: 0000557ef97886c0 RCX: 00007f1e856b8ecb
 RDX: 0000000000000002 RSI: 0000557ef97886e0 RDI: 0000000000000003
 RBP: 0000557ef97886e0 R08: 0000000000000000 R09: 0000000000000003
 R10: fffffffffffff50e R11: 0000000000000293 R12: 0000000000000001
 R13: 0000557ef97886c0 R14: 0000000000000001 R15: 0000557ef976e2a0

This happens, because we are taking the ->log_mutex albeit it has already
been locked.

Also while at it, fix the bogus unlock of the tree_log_mutex in the error
handling.

Fixes: 3ddebf27fcd3 ("btrfs: zoned: reorder log node allocation on zoned filesystem")
Cc: Filipe Manana <fdmanana@suse.com>
Cc: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: avoid double put of block group when emptying cluster
Josef Bacik [Mon, 25 Jan 2021 21:42:35 +0000 (16:42 -0500)]
btrfs: avoid double put of block group when emptying cluster

It's wrong calling btrfs_put_block_group in
__btrfs_return_cluster_to_free_space if the block group passed is
different than the block group the cluster represents. As this means the
cluster doesn't have a reference to the passed block group. This results
in double put and a use-after-free bug.

Fix this by simply bailing if the block group we passed in does not
match the block group on the cluster.

Fixes: fa9c0d795f7b ("Btrfs: rework allocation clustering")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: fix stale data exposure after cloning a hole with NO_HOLES enabled
Filipe Manana [Tue, 16 Feb 2021 11:09:25 +0000 (11:09 +0000)]
btrfs: fix stale data exposure after cloning a hole with NO_HOLES enabled

When using the NO_HOLES feature, if we clone a file range that spans only
a hole into a range that is at or beyond the current i_size of the
destination file, we end up not setting the full sync runtime flag on the
inode. As a result, if we then fsync the destination file and have a power
failure, after log replay we can end up exposing stale data instead of
having a hole for that range.

The conditions for this to happen are the following:

1) We have a file with a size of, for example, 1280K;

2) There is a written (non-prealloc) extent for the file range from 1024K
   to 1280K with a length of 256K;

3) This particular file extent layout is durably persisted, so that the
   existing superblock persisted on disk points to a subvolume root where
   the file has that exact file extent layout and state;

4) The file is truncated to a smaller size, to an offset lower than the
   start offset of its last extent, for example to 800K. The truncate sets
   the full sync runtime flag on the inode;

6) Fsync the file to log it and clear the full sync runtime flag;

7) Clone a region that covers only a hole (implicit hole due to NO_HOLES)
   into the file with a destination offset that starts at or beyond the
   256K file extent item we had - for example to offset 1024K;

8) Since the clone operation does not find extents in the source range,
   we end up in the if branch at the bottom of btrfs_clone() where we
   punch a hole for the file range starting at offset 1024K by calling
   btrfs_replace_file_extents(). There we end up not setting the full
   sync flag on the inode, because we don't know we are being called in
   a clone context (and not fallocate's punch hole operation), and
   neither do we create an extent map to represent a hole because the
   requested range is beyond eof;

9) A further fsync to the file will be a fast fsync, since the clone
   operation did not set the full sync flag, and therefore it relies on
   modified extent maps to correctly log the file layout. But since
   it does not find any extent map marking the range from 1024K (the
   previous eof) to the new eof, it does not log a file extent item
   for that range representing the hole;

10) After a power failure no hole for the range starting at 1024K is
   punched and we end up exposing stale data from the old 256K extent.

Turning this into exact steps:

  $ mkfs.btrfs -f -O no-holes /dev/sdi
  $ mount /dev/sdi /mnt

  # Create our test file with 3 extents of 256K and a 256K hole at offset
  # 256K. The file has a size of 1280K.
  $ xfs_io -f -s \
              -c "pwrite -S 0xab -b 256K 0 256K" \
              -c "pwrite -S 0xcd -b 256K 512K 256K" \
              -c "pwrite -S 0xef -b 256K 768K 256K" \
              -c "pwrite -S 0x73 -b 256K 1024K 256K" \
              /mnt/sdi/foobar

  # Make sure it's durably persisted. We want the last committed super
  # block to point to this particular file extent layout.
  sync

  # Now truncate our file to a smaller size, falling within a position of
  # the second extent. This sets the full sync runtime flag on the inode.
  # Then fsync the file to log it and clear the full sync flag from the
  # inode. The third extent is no longer part of the file and therefore
  # it is not logged.
  $ xfs_io -c "truncate 800K" -c "fsync" /mnt/foobar

  # Now do a clone operation that only clones the hole and sets back the
  # file size to match the size it had before the truncate operation
  # (1280K).
  $ xfs_io \
        -c "reflink /mnt/foobar 256K 1024K 256K" \
        -c "fsync" \
        /mnt/foobar

  # File data before power failure:
  $ od -A d -t x1 /mnt/foobar
  0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  *
  0262144 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  *
  0524288 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
  *
  0786432 ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
  *
  0819200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  *
  1310720

  <power fail>

  # Mount the fs again to replay the log tree.
  $ mount /dev/sdi /mnt

  # File data after power failure:
  $ od -A d -t x1 /mnt/foobar
  0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
  *
  0262144 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  *
  0524288 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
  *
  0786432 ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
  *
  0819200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  *
  1048576 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73
  *
  1310720

The range from 1024K to 1280K should correspond to a hole but instead it
points to stale data, to the 256K extent that should not exist after the
truncate operation.

The issue does not exists when not using NO_HOLES, because for that case
we use file extent items to represent holes, these are found and copied
during the loop that iterates over extents at btrfs_clone(), and that
causes btrfs_replace_file_extents() to be called with a non-NULL
extent_info argument and therefore set the full sync runtime flag on the
inode.

So fix this by making the code that deals with a trailing hole during
cloning, at btrfs_clone(), to set the full sync flag on the inode, if the
range starts at or beyond the current i_size.

A test case for fstests will follow soon.

Backporting notes: for kernel 5.4 the change goes to ioctl.c into
btrfs_clone before the last call to btrfs_punch_hole_range.

CC: stable@vger.kernel.org # 5.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: tree-checker: do not error out if extent ref hash doesn't match
Josef Bacik [Tue, 16 Feb 2021 20:43:22 +0000 (15:43 -0500)]
btrfs: tree-checker: do not error out if extent ref hash doesn't match

The tree checker checks the extent ref hash at read and write time to
make sure we do not corrupt the file system.  Generally extent
references go inline, but if we have enough of them we need to make an
item, which looks like

key.objectid = <bytenr>
key.type = <BTRFS_EXTENT_DATA_REF_KEY|BTRFS_TREE_BLOCK_REF_KEY>
key.offset = hash(tree, owner, offset)

However if key.offset collide with an unrelated extent reference we'll
simply key.offset++ until we get something that doesn't collide.
Obviously this doesn't match at tree checker time, and thus we error
while writing out the transaction.  This is relatively easy to
reproduce, simply do something like the following

  xfs_io -f -c "pwrite 0 1M" file
  offset=2

  for i in {0..10000}
  do
  xfs_io -c "reflink file 0 ${offset}M 1M" file
  offset=$(( offset + 2 ))
  done

  xfs_io -c "reflink file 0 17999258914816 1M" file
  xfs_io -c "reflink file 0 35998517829632 1M" file
  xfs_io -c "reflink file 0 53752752058368 1M" file

  btrfs filesystem sync

And the sync will error out because we'll abort the transaction.  The
magic values above are used because they generate hash collisions with
the first file in the main subvol.

The fix for this is to remove the hash value check from tree checker, as
we have no idea which offset ours should belong to.

Reported-by: Tuomas Lähdekorpi <tuomas.lahdekorpi@gmail.com>
Fixes: 0785a9aacf9d ("btrfs: tree-checker: Add EXTENT_DATA_REF check")
CC: stable@vger.kernel.org # 5.4+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ add comment]
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: fix comment for btrfs ordered extent flag bits
Qu Wenruo [Thu, 11 Feb 2021 08:14:05 +0000 (16:14 +0800)]
btrfs: fix comment for btrfs ordered extent flag bits

There is small error in comment about BTRFS_ORDERED_* flags, added in
commit 3c198fe06449 ("btrfs: rework the order of
btrfs_ordered_extent::flags") but the fixup did not get merged in time.

The 4 types are for ordered extent itself, not for direct io.
Only 3 types support direct io, REGULAR/NOCOW/PREALLOC.

Fix the comment to reflect that.

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: fix race between swap file activation and snapshot creation
Filipe Manana [Fri, 5 Feb 2021 12:55:38 +0000 (12:55 +0000)]
btrfs: fix race between swap file activation and snapshot creation

When creating a snapshot we check if the current number of swap files, in
the root, is non-zero, and if it is, we error out and warn that we can not
create the snapshot because there are active swap files.

However this is racy because when a task started activation of a swap
file, another task might have started already snapshot creation and might
have seen the counter for the number of swap files as zero. This means
that after the swap file is activated we may end up with a snapshot of the
same root successfully created, and therefore when the first write to the
swap file happens it has to fall back into COW mode, which should never
happen for active swap files.

Basically what can happen is:

1) Task A starts snapshot creation and enters ioctl.c:create_snapshot().
   There it sees that root->nr_swapfiles has a value of 0 so it continues;

2) Task B enters btrfs_swap_activate(). It is not aware that another task
   started snapshot creation but it did not finish yet. It increments
   root->nr_swapfiles from 0 to 1;

3) Task B checks that the file meets all requirements to be an active
   swap file - it has NOCOW set, there are no snapshots for the inode's
   root at the moment, no file holes, no reflinked extents, etc;

4) Task B returns success and now the file is an active swap file;

5) Task A commits the transaction to create the snapshot and finishes.
   The swap file's extents are now shared between the original root and
   the snapshot;

6) A write into an extent of the swap file is attempted - there is a
   snapshot of the file's root, so we fall back to COW mode and therefore
   the physical location of the extent changes on disk.

So fix this by taking the snapshot lock during swap file activation before
locking the extent range, as that is the order in which we lock these
during buffered writes.

Fixes: ed46ff3d42378 ("Btrfs: support swap files")
Reviewed-by: Anand Jain <anand.jain@oracle.com>
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: fix race between writes to swap files and scrub
Filipe Manana [Fri, 5 Feb 2021 12:55:37 +0000 (12:55 +0000)]
btrfs: fix race between writes to swap files and scrub

When we active a swap file, at btrfs_swap_activate(), we acquire the
exclusive operation lock to prevent the physical location of the swap
file extents to be changed by operations such as balance and device
replace/resize/remove. We also call there can_nocow_extent() which,
among other things, checks if the block group of a swap file extent is
currently RO, and if it is we can not use the extent, since a write
into it would result in COWing the extent.

However we have no protection against a scrub operation running after we
activate the swap file, which can result in the swap file extents to be
COWed while the scrub is running and operating on the respective block
group, because scrub turns a block group into RO before it processes it
and then back again to RW mode after processing it. That means an attempt
to write into a swap file extent while scrub is processing the respective
block group, will result in COWing the extent, changing its physical
location on disk.

Fix this by making sure that block groups that have extents that are used
by active swap files can not be turned into RO mode, therefore making it
not possible for a scrub to turn them into RO mode. When a scrub finds a
block group that can not be turned to RO due to the existence of extents
used by swap files, it proceeds to the next block group and logs a warning
message that mentions the block group was skipped due to active swap
files - this is the same approach we currently use for balance.

Fixes: ed46ff3d42378 ("Btrfs: support swap files")
Reviewed-by: Anand Jain <anand.jain@oracle.com>
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: avoid checking for RO block group twice during nocow writeback
Filipe Manana [Fri, 5 Feb 2021 12:55:36 +0000 (12:55 +0000)]
btrfs: avoid checking for RO block group twice during nocow writeback

During the nocow writeback path, we currently iterate the rbtree of block
groups twice: once for checking if the target block group is RO with the
call to btrfs_extent_readonly()), and once again for getting a nocow
reference on the block group with a call to btrfs_inc_nocow_writers().

Since btrfs_inc_nocow_writers() already returns false when the target
block group is RO, remove the call to btrfs_extent_readonly(). Not only
we avoid searching the blocks group rbtree twice, it also helps reduce
contention on the lock that protects it (specially since it is a spin
lock and not a read-write lock). That may make a noticeable difference
on very large filesystems, with thousands of allocated block groups.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
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: fix race between extent freeing/allocation when using bitmaps
Nikolay Borisov [Mon, 8 Feb 2021 08:26:54 +0000 (10:26 +0200)]
btrfs: fix race between extent freeing/allocation when using bitmaps

During allocation the allocator will try to allocate an extent using
cluster policy. Once the current cluster is exhausted it will remove the
entry under btrfs_free_cluster::lock and subsequently acquire
btrfs_free_space_ctl::tree_lock to dispose of the already-deleted entry
and adjust btrfs_free_space_ctl::total_bitmap. This poses a problem
because there exists a race condition between removing the entry under
one lock and doing the necessary accounting holding a different lock
since extent freeing only uses the 2nd lock. This can result in the
following situation:

T1:                                    T2:
btrfs_alloc_from_cluster               insert_into_bitmap <holds tree_lock>
 if (entry->bytes == 0)                   if (block_group && !list_empty(&block_group->cluster_list)) {
    rb_erase(entry)

 spin_unlock(&cluster->lock);
   (total_bitmaps is still 4)           spin_lock(&cluster->lock);
                                         <doesn't find entry in cluster->root>
 spin_lock(&ctl->tree_lock);             <goes to new_bitmap label, adds
<blocked since T2 holds tree_lock>       <a new entry and calls add_new_bitmap>
    recalculate_thresholds  <crashes,
                                              due to total_bitmaps
      becoming 5 and triggering
      an ASSERT>

To fix this ensure that once depleted, the cluster entry is deleted when
both cluster lock and tree locks are held in the allocator (T1), this
ensures that even if there is a race with a concurrent
insert_into_bitmap call it will correctly find the entry in the cluster
and add the new space to it.

CC: <stable@vger.kernel.org> # 4.4+
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: make check_compressed_csum() to be subpage compatible
Qu Wenruo [Thu, 4 Feb 2021 07:03:24 +0000 (15:03 +0800)]
btrfs: make check_compressed_csum() to be subpage compatible

Currently check_compressed_csum() completely relies on sectorsize ==
PAGE_SIZE to do checksum verification for compressed extents.

To make it subpage compatible, this patch will:
- Do extra calculation for the csum range
  Since we have multiple sectors inside a page, we need to only hash
  the range we want, not the full page anymore.

- Do sector-by-sector hash inside the page

With this patch and previous conversion on
btrfs_submit_compressed_read(), now we can read subpage compressed
extents properly, and do proper csum verification.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: make btrfs_submit_compressed_read() subpage compatible
Qu Wenruo [Thu, 4 Feb 2021 07:03:23 +0000 (15:03 +0800)]
btrfs: make btrfs_submit_compressed_read() subpage compatible

For compressed read, we always submit page read using page size.  This
doesn't work well with subpage, as for subpage one page can contain
several sectors.  Such submission will read range out of what we want,
and cause problems.

Thankfully to make it subpage compatible, we only need to change how the
last page of the compressed extent is read.

Instead of always adding a full page to the compressed read bio, if we're
at the last page, calculate the size using compressed length, so that we
only add part of the range into the compressed read bio.

Since we are here, also change the PAGE_SIZE used in
lookup_extent_mapping() to sectorsize.
This modification won't cause any functional change, as
lookup_extent_mapping() can handle the case where the search range is
larger than found extent range.

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: fix raid6 qstripe kmap
Ira Weiny [Thu, 28 Jan 2021 06:15:03 +0000 (22:15 -0800)]
btrfs: fix raid6 qstripe kmap

When a qstripe is required an extra page is allocated and mapped.  There
were 3 problems:

1) There is no corresponding call of kunmap() for the qstripe page.
2) There is no reason to map the qstripe page more than once if the
   number of bits set in rbio->dbitmap is greater than one.
3) There is no reason to map the parity page and unmap it each time
   through the loop.

The page memory can continue to be reused with a single mapping on each
iteration by raid6_call.gen_syndrome() without remapping.  So map the
page for the duration of the loop.

Similarly, improve the algorithm by mapping the parity page just 1 time.

Fixes: 5a6ac9eacb49 ("Btrfs, raid56: support parity scrub on raid56")
CC: stable@vger.kernel.org # 4.4.x: c17af96554a8: btrfs: raid56: simplify tracking of Q stripe presence
CC: stable@vger.kernel.org # 4.4.x
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: enable to mount ZONED incompat flag
Naohiro Aota [Thu, 4 Feb 2021 10:22:21 +0000 (19:22 +0900)]
btrfs: zoned: enable to mount ZONED incompat flag

This final patch adds the ZONED incompat flag to the supported flags
and enables to mount ZONED flagged file system.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: deal with holes writing out tree-log pages
Naohiro Aota [Fri, 5 Feb 2021 14:58:36 +0000 (23:58 +0900)]
btrfs: zoned: deal with holes writing out tree-log pages

Since the zoned filesystem requires sequential write out of metadata, we
cannot proceed with a hole in tree-log pages. When such a hole exists,
btree_write_cache_pages() will return -EAGAIN. This happens when someone,
e.g., a concurrent transaction commit, writes a dirty extent in this
tree-log commit.

If we are not going to wait for the extents, we can hope the concurrent
writing fills the hole for us. So, we can ignore the error in this case and
hope the next write will succeed.

If we want to wait for them and got the error, we cannot wait for them
because it will cause a deadlock. So, let's bail out to a full commit in
this case.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: reorder log node allocation on zoned filesystem
Naohiro Aota [Thu, 4 Feb 2021 10:22:20 +0000 (19:22 +0900)]
btrfs: zoned: reorder log node allocation on zoned filesystem

This is the 3/3 patch to enable tree-log on zoned filesystems.

The allocation order of nodes of "fs_info->log_root_tree" and nodes of
"root->log_root" is not the same as the writing order of them. So, the
writing causes unaligned write errors.

Reorder the allocation of them by delaying allocation of the root node of
"fs_info->log_root_tree," so that the node buffers can go out sequentially
to devices.

Cc: Filipe Manana <fdmanana@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: serialize log transaction on zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:22:19 +0000 (19:22 +0900)]
btrfs: zoned: serialize log transaction on zoned filesystems

This is the 2/3 patch to enable tree-log on zoned filesystems.

Since we can start more than one log transactions per subvolume
simultaneously, nodes from multiple transactions can be allocated
interleaved. Such mixed allocation results in non-sequential writes at
the time of a log transaction commit. The nodes of the global log root
tree (fs_info->log_root_tree), also have the same problem with mixed
allocation.

Serializes log transactions by waiting for a committing transaction when
someone tries to start a new transaction, to avoid the mixed allocation
problem. We must also wait for running log transactions from another
subvolume, but there is no easy way to detect which subvolume root is
running a log transaction. So, this patch forbids starting a new log
transaction when other subvolumes already allocated the global log root
tree.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: extend zoned allocator to use dedicated tree-log block group
Naohiro Aota [Thu, 4 Feb 2021 10:22:18 +0000 (19:22 +0900)]
btrfs: zoned: extend zoned allocator to use dedicated tree-log block group

This is the 1/3 patch to enable tree log on zoned filesystems.

The tree-log feature does not work on a zoned filesystem as is. Blocks for
a tree-log tree are allocated mixed with other metadata blocks and btrfs
writes and syncs the tree-log blocks to devices at the time of fsync(),
which has a different timing than a global transaction commit. As a
result, both writing tree-log blocks and writing other metadata blocks
become non-sequential writes that zoned filesystems must avoid.

Introduce a dedicated block group for tree-log blocks, so that tree-log
blocks and other metadata blocks can be separate write streams.  As a
result, each write stream can now be written to devices separately.
"fs_info->treelog_bg" tracks the dedicated block group and assigns
"treelog_bg" on-demand on tree-log block allocation time.

This commit extends the zoned block allocator to use the block group.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: split alloc_log_tree()
Naohiro Aota [Thu, 4 Feb 2021 10:22:17 +0000 (19:22 +0900)]
btrfs: split alloc_log_tree()

This is a preparation patch for the next patch. Split alloc_log_tree()
into two parts. The first one allocating the tree structure, remains in
alloc_log_tree() and the second part allocating the tree node, which is
moved into btrfs_alloc_log_tree_node().

Also export the latter part is to be used in the next patch.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: relocate block group to repair IO failure in zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:22:16 +0000 (19:22 +0900)]
btrfs: zoned: relocate block group to repair IO failure in zoned filesystems

When a bad checksum is found and if the filesystem has a mirror of the
damaged data, we read the correct data from the mirror and writes it to
damaged blocks. This however, violates the sequential write constraints
of a zoned block device.

We can consider three methods to repair an IO failure in zoned filesystems:

(1) Reset and rewrite the damaged zone
(2) Allocate new device extent and replace the damaged device extent to
    the new extent
(3) Relocate the corresponding block group

Method (1) is most similar to a behavior done with regular devices.
However, it also wipes non-damaged data in the same device extent, and
so it unnecessary degrades non-damaged data.

Method (2) is much like device replacing but done in the same device. It
is safe because it keeps the device extent until the replacing finish.
However, extending device replacing is non-trivial. It assumes
"src_dev->physical == dst_dev->physical". Also, the extent mapping
replacing function should be extended to support replacing device extent
position in one device.

Method (3) invokes relocation of the damaged block group and is
straightforward to implement. It relocates all the mirrored device
extents, so it potentially is a more costly operation than method (1) or
(2). But it relocates only used extents which reduce the total IO size.

Let's apply method (3) for now. In the future, we can extend device-replace
and apply method (2).

For protecting a block group gets relocated multiple time with multiple
IO errors, this commit introduces "relocating_repair" bit to show it's
now relocating to repair IO failures. Also it uses a new kthread
"btrfs-relocating-repair", not to block IO path with relocating process.

This commit also supports repairing in the scrub process.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: enable relocation on a zoned filesystem
Naohiro Aota [Thu, 4 Feb 2021 10:22:15 +0000 (19:22 +0900)]
btrfs: zoned: enable relocation on a zoned filesystem

Currently fallocate() is disabled on a zoned filesystem. Since current
relocation process relies on preallocation to move file data extents, it
must be handled differently.

On a zoned filesystem, we just truncate the inode to the size that we
wanted to pre-allocate. Then, we flush dirty pages on the file before
finishing the relocation process. run_delalloc_zoned() will handle all
the allocations and submit IOs to the underlying layers.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: support dev-replace in zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:22:14 +0000 (19:22 +0900)]
btrfs: zoned: support dev-replace in zoned filesystems

This is 4/4 patch to implement device-replace on zoned filesystems.

Even after the copying is done, the write pointers of the source device
and the destination device may not be synchronized. For example, when
the last allocated extent is freed before device-replace process, the
extent is not copied, leaving a hole there.

Synchronize the write pointers by writing zeroes to the destination
device.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: implement copying for zoned device-replace
Naohiro Aota [Thu, 4 Feb 2021 10:22:13 +0000 (19:22 +0900)]
btrfs: zoned: implement copying for zoned device-replace

This is 3/4 patch to implement device-replace on zoned filesystems.

This commit implements copying. To do this, it tracks the write pointer
during the device replace process. As device-replace's copy process is
smart enough to only copy used extents on the source device, we have to
fill the gap to honor the sequential write requirement in the target
device.

The device-replace process on zoned filesystems must copy or clone all
the extents in the source device exactly once. So, we need to ensure
allocations started just before the dev-replace process to have their
corresponding extent information in the B-trees.
finish_extent_writes_for_zoned() implements that functionality, which
basically is the removed code in the commit 042528f8d840 ("Btrfs: fix
block group remaining RO forever after error during device replace").

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: implement cloning for zoned device-replace
Naohiro Aota [Thu, 4 Feb 2021 10:22:12 +0000 (19:22 +0900)]
btrfs: zoned: implement cloning for zoned device-replace

This is 2/4 patch to implement device replace for zoned filesystems.

In zoned mode, a block group must be either copied (from the source
device to the target device) or cloned (to both devices).

Implement the cloning part. If a block group targeted by an IO is marked
to copy, we should not clone the IO to the destination device, because
the block group is eventually copied by the replace process.

This commit also handles cloning of device reset.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: mark block groups to copy for device-replace
Naohiro Aota [Thu, 4 Feb 2021 10:22:11 +0000 (19:22 +0900)]
btrfs: zoned: mark block groups to copy for device-replace

This is the 1/4 patch to support device-replace on zoned filesystems.

We have two types of IOs during the device replace process. One is an IO
to "copy" (by the scrub functions) all the device extents from the source
device to the destination device. The other one is an IO to "clone" (by
handle_ops_on_dev_replace()) new incoming write IOs from users to the
source device into the target device.

Cloning incoming IOs can break the sequential write rule in on target
device. When a write is mapped in the middle of a block group, the IO is
directed to the middle of a target device zone, which breaks the
sequential write requirement.

However, the cloning function cannot be disabled since incoming IOs
targeting already copied device extents must be cloned so that the IO is
executed on the target device.

We cannot use dev_replace->cursor_{left,right} to determine whether a bio
is going to a not yet copied region. Since we have a time gap between
finishing btrfs_scrub_dev() and rewriting the mapping tree in
btrfs_dev_replace_finishing(), we can have a newly allocated device extent
which is never cloned nor copied.

So the point is to copy only already existing device extents. This patch
introduces mark_block_group_to_copy() to mark existing block groups as a
target of copying. Then, handle_ops_on_dev_replace() and dev-replace can
check the flag to do their job.

Also, btrfs_finish_block_group_to_copy() will check if the copied stripe
is the last stripe in the block group. With the last stripe copied,
the to_copy flag is finally disabled. Afterwards we can safely clone
incoming IOs on this block group.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: do not use async metadata checksum on zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:22:10 +0000 (19:22 +0900)]
btrfs: zoned: do not use async metadata checksum on zoned filesystems

On zoned filesystems, btrfs uses per-fs zoned_meta_io_lock to serialize
the metadata write IOs.

Even with this serialization, write bios sent from btree_write_cache_pages
can be reordered by async checksum workers as these workers are per CPU
and not per zone.

To preserve write bio ordering, we disable async metadata checksum on a
zoned filesystem. This does not result in lower performance with HDDs as
a single CPU core is fast enough to do checksum for a single zone write
stream with the maximum possible bandwidth of the device. If multiple
zones are being written simultaneously, HDD seek overhead lowers the
achievable maximum bandwidth, resulting again in a per zone checksum
serialization not affecting the performance.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: wait for existing extents before truncating
Naohiro Aota [Thu, 4 Feb 2021 10:22:09 +0000 (19:22 +0900)]
btrfs: zoned: wait for existing extents before truncating

When truncating a file, file buffers which have already been allocated
but not yet written may be truncated. Truncating these buffers could
cause breakage of a sequential write pattern in a block group if the
truncated blocks are for example followed by blocks allocated to another
file. To avoid this problem, always wait for write out of all unwritten
buffers before proceeding with the truncate execution.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: serialize metadata IO
Naohiro Aota [Thu, 4 Feb 2021 10:22:08 +0000 (19:22 +0900)]
btrfs: zoned: serialize metadata IO

We cannot use zone append for writing metadata, because the B-tree nodes
have references to each other using logical address. Without knowing
the address in advance, we cannot construct the tree in the first place.
So we need to serialize write IOs for metadata.

We cannot add a mutex around allocation and submission because metadata
blocks are allocated in an earlier stage to build up B-trees.

Add a zoned_meta_io_lock and hold it during metadata IO submission in
btree_write_cache_pages() to serialize IOs.

Furthermore, this adds a per-block group metadata IO submission pointer
"meta_write_pointer" to ensure sequential writing, which can break when
attempting to write back blocks in an unfinished transaction. If the
writing out failed because of a hole and the write out is for data
integrity (WB_SYNC_ALL), it returns EAGAIN.

A caller like fsync() code should handle this properly e.g. by falling
back to a full transaction commit.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: introduce dedicated data write path for zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:22:07 +0000 (19:22 +0900)]
btrfs: zoned: introduce dedicated data write path for zoned filesystems

If more than one IO is issued for one file extent, these IO can be
written to separate regions on a device. Since we cannot map one file
extent to such a separate area on a zoned filesystem, we need to follow
the "one IO == one ordered extent" rule.

The normal buffered, uncompressed and not pre-allocated write path (used
by cow_file_range()) sometimes does not follow this rule. It can write a
part of an ordered extent when specified a region to write e.g., when
its called from fdatasync().

Introduce a dedicated (uncompressed buffered) data write path for zoned
filesystems, that will COW the region and write it at once.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: enable zone append writing for direct IO
Naohiro Aota [Thu, 4 Feb 2021 10:22:06 +0000 (19:22 +0900)]
btrfs: zoned: enable zone append writing for direct IO

Likewise to buffered IO, enable zone append writing for direct IO when
its used on a zoned block device.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: use ZONE_APPEND write for zoned mode
Naohiro Aota [Thu, 4 Feb 2021 10:22:05 +0000 (19:22 +0900)]
btrfs: zoned: use ZONE_APPEND write for zoned mode

Enable zone append writing for zoned mode. When using zone append, a
bio is issued to the start of a target zone and the device decides to
place it inside the zone. Upon completion the device reports the actual
written position back to the host.

Three parts are necessary to enable zone append mode. First, modify the
bio to use REQ_OP_ZONE_APPEND in btrfs_submit_bio_hook() and adjust the
bi_sector to point the beginning of the zone.

Second, record the returned physical address (and disk/partno) to the
ordered extent in end_bio_extent_writepage() after the bio has been
completed. We cannot resolve the physical address to the logical address
because we can neither take locks nor allocate a buffer in this end_bio
context. So, we need to record the physical address to resolve it later
in btrfs_finish_ordered_io().

And finally, rewrite the logical addresses of the extent mapping and
checksum data according to the physical address using btrfs_rmap_block.
If the returned address matches the originally allocated address, we can
skip this rewriting process.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: save irq flags when looking up an ordered extent
Johannes Thumshirn [Thu, 4 Feb 2021 10:22:04 +0000 (19:22 +0900)]
btrfs: save irq flags when looking up an ordered extent

A following patch will add another caller of
btrfs_lookup_ordered_extent(), but from a bio's endio context.

btrfs_lookup_ordered_extent() uses spin_lock_irq() which unconditionally
disables interrupts. Change this to spin_lock_irqsave() so interrupts
aren't disabled and re-enabled unconditionally.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: cache if block group is on a sequential zone
Johannes Thumshirn [Thu, 4 Feb 2021 10:22:03 +0000 (19:22 +0900)]
btrfs: zoned: cache if block group is on a sequential zone

On a zoned filesystem, cache if a block group is on a sequential write
only zone.

On sequential write only zones, we can use REQ_OP_ZONE_APPEND for
writing data, therefore provide btrfs_use_zone_append() to figure out if
IO is targeting a sequential write only zone and we can use
REQ_OP_ZONE_APPEND for data writing.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: extend btrfs_rmap_block for specifying a device
Naohiro Aota [Thu, 4 Feb 2021 10:22:02 +0000 (19:22 +0900)]
btrfs: extend btrfs_rmap_block for specifying a device

btrfs_rmap_block currently reverse-maps the physical addresses on all
devices to the corresponding logical addresses.

Extend the function to match to a specified device. The old functionality
of querying all devices is left intact by specifying NULL as target
device.

A block_device instead of a btrfs_device is passed into btrfs_rmap_block,
as this function is intended to reverse-map the result of a bio, which
only has a block_device.

Also export the function for later use.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: check if bio spans across an ordered extent
Johannes Thumshirn [Thu, 4 Feb 2021 10:22:01 +0000 (19:22 +0900)]
btrfs: zoned: check if bio spans across an ordered extent

To ensure that an ordered extent maps to a contiguous region on disk, we
need to maintain a "one bio == one ordered extent" rule.

Ensure that constructing bio does not span more than an ordered extent.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: split ordered extent when bio is sent
Naohiro Aota [Thu, 4 Feb 2021 10:22:00 +0000 (19:22 +0900)]
btrfs: zoned: split ordered extent when bio is sent

For a zone append write, the device decides the location the data is being
written to. Therefore we cannot ensure that two bios are written
consecutively on the device. In order to ensure that an ordered extent
maps to a contiguous region on disk, we need to maintain a "one bio ==
one ordered extent" rule.

Implement splitting of an ordered extent and extent map on bio submission
to adhere to the rule.

extract_ordered_extent() hooks into btrfs_submit_data_bio() and splits the
corresponding ordered extent so that the ordered extent's region fits into
one bio and the corresponding device limits.

Several sanity checks need to be done in extract_ordered_extent() e.g.

- We cannot split once end_bio'd ordered extent because we cannot divide
  ordered->bytes_left for the split ones
- We do not expect a compressed ordered extent
- We should not have checksum list because we omit the list splitting.
  Since the function is called before btrfs_wq_submit_bio() or
  btrfs_csum_one_bio(), this should be always ensured.

We also need to split an extent map by creating a new one. If not,
unpin_extent_cache() complains about the difference between the start of
the extent map and the file's logical offset.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: handle REQ_OP_ZONE_APPEND as writing
Naohiro Aota [Thu, 4 Feb 2021 10:21:59 +0000 (19:21 +0900)]
btrfs: zoned: handle REQ_OP_ZONE_APPEND as writing

Zoned filesystems use REQ_OP_ZONE_APPEND bios for writing to actual
devices.

Let btrfs_end_bio() and btrfs_op be aware of it, by mapping
REQ_OP_ZONE_APPEND to BTRFS_MAP_WRITE and using btrfs_op() instead of
bio_op().

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: use bio_add_zone_append_page
Naohiro Aota [Thu, 4 Feb 2021 10:21:58 +0000 (19:21 +0900)]
btrfs: zoned: use bio_add_zone_append_page

A zoned device has its own hardware restrictions e.g. max_zone_append_size
when using REQ_OP_ZONE_APPEND. To follow these restrictions, use
bio_add_zone_append_page() instead of bio_add_page(). We need target device
to use bio_add_zone_append_page(), so this commit reads the chunk
information to cache the target device to btrfs_io_bio(bio)->device.

Caching only the target device is sufficient here as zoned filesystems
only supports the single profile at the moment. Once more profiles will be
supported btrfs_io_bio can hold an extent_map to be able to check for the
restrictions of all devices the btrfs_bio will be mapped to.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: factor out helper adding a page to bio
Naohiro Aota [Thu, 4 Feb 2021 10:21:57 +0000 (19:21 +0900)]
btrfs: factor out helper adding a page to bio

Factor out adding a page to a bio from submit_extent_page().  The page
is added only when bio_flags are the same, contiguous and the added page
fits in the same stripe as pages in the bio.

Condition checks are reordered to allow early return to avoid possibly
heavy btrfs_bio_fits_in_stripe() calling.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: reset zones of unused block groups
Naohiro Aota [Thu, 4 Feb 2021 10:21:56 +0000 (19:21 +0900)]
btrfs: zoned: reset zones of unused block groups

We must reset the zones of a deleted unused block group to rewind the
zones' write pointers to the zones' start.

To do this, we can use the DISCARD_SYNC code to do the reset when the
filesystem is running on zoned devices.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: advance allocation pointer after tree log node
Naohiro Aota [Thu, 4 Feb 2021 10:21:55 +0000 (19:21 +0900)]
btrfs: zoned: advance allocation pointer after tree log node

Since the allocation info of a tree log node is not recorded in the extent
tree, calculate_alloc_pointer() cannot detect this node, so the pointer
can be over a tree node.

Replaying the log calls btrfs_remove_free_space() for each node in the
log tree.

So, advance the pointer after the node to not allocate over it.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: redirty released extent buffers
Naohiro Aota [Thu, 4 Feb 2021 10:21:54 +0000 (19:21 +0900)]
btrfs: zoned: redirty released extent buffers

Tree manipulating operations like merging nodes often release
once-allocated tree nodes. Such nodes are cleaned so that pages in the
node are not uselessly written out. On zoned volumes, however, such
optimization blocks the following IOs as the cancellation of the write
out of the freed blocks breaks the sequential write sequence expected by
the device.

Introduce a list of clean and unwritten extent buffers that have been
released in a transaction. Redirty the buffers so that
btree_write_cache_pages() can send proper bios to the devices.

Besides it clears the entire content of the extent buffer not to confuse
raw block scanners e.g. 'btrfs check'. By clearing the content,
csum_dirty_buffer() complains about bytenr mismatch, so avoid the
checking and checksum using newly introduced buffer flag
EXTENT_BUFFER_NO_CHECK.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: implement sequential extent allocation
Naohiro Aota [Thu, 4 Feb 2021 10:21:53 +0000 (19:21 +0900)]
btrfs: zoned: implement sequential extent allocation

Implement a sequential extent allocator for zoned filesystems. This
allocator only needs to check if there is enough space in the block group
after the allocation pointer to satisfy the extent allocation request.
Therefore the allocator never manages bitmaps or clusters. Also, add
assertions to the corresponding functions.

As zone append writing is used, it would be unnecessary to track the
allocation offset, as the allocator only needs to check available space.
But by tracking and returning the offset as an allocated region, we can
skip modification of ordered extents and checksum information when there
is no IO reordering.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: track unusable bytes for zones
Naohiro Aota [Thu, 4 Feb 2021 10:21:52 +0000 (19:21 +0900)]
btrfs: zoned: track unusable bytes for zones

In a zoned filesystem a once written then freed region is not usable
until the underlying zone has been reset. So we need to distinguish such
unusable space from usable free space.

Therefore we need to introduce the "zone_unusable" field to the block
group structure, and "bytes_zone_unusable" to the space_info structure
to track the unusable space.

Pinned bytes are always reclaimed to the unusable space. But, when an
allocated region is returned before using e.g., the block group becomes
read-only between allocation time and reservation time, we can safely
return the region to the block group. For the situation, this commit
introduces "btrfs_add_free_space_unused". This behaves the same as
btrfs_add_free_space() on regular filesystem. On zoned filesystems, it
rewinds the allocation offset.

Because the read-only bytes tracks free but unusable bytes when the block
group is read-only, we need to migrate the zone_unusable bytes to
read-only bytes when a block group is marked read-only.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: calculate allocation offset for conventional zones
Naohiro Aota [Thu, 4 Feb 2021 10:21:51 +0000 (19:21 +0900)]
btrfs: zoned: calculate allocation offset for conventional zones

Conventional zones do not have a write pointer, so we cannot use it to
determine the allocation offset for sequential allocation if a block
group contains a conventional zone.

But instead, we can consider the end of the highest addressed extent in
the block group for the allocation offset.

For new block group, we cannot calculate the allocation offset by
consulting the extent tree, because it can cause deadlock by taking
extent buffer lock after chunk mutex, which is already taken in
btrfs_make_block_group(). Since it is a new block group anyways, we can
simply set the allocation offset to 0.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: load zone's allocation offset
Naohiro Aota [Thu, 4 Feb 2021 10:21:50 +0000 (19:21 +0900)]
btrfs: zoned: load zone's allocation offset

A zoned filesystem must allocate blocks at the zones' write pointer. The
device's write pointer position can be mapped to a logical address within
a block group. To facilitate this, add an "alloc_offset" to the
block-group to track the logical addresses of the write pointer.

This logical address is populated in btrfs_load_block_group_zone_info()
from the write pointers of corresponding zones.

For now, zoned filesystems the single profile. Supporting non-single
profile with zone append writing is not trivial. For example, in the DUP
profile, we send a zone append writing IO to two zones on a device. The
device reply with written LBAs for the IOs. If the offsets of the
returned addresses from the beginning of the zone are different, then it
results in different logical addresses.

We need fine-grained logical to physical mapping to support such separated
physical address issue. Since it should require additional metadata type,
disable non-single profiles for now.

This commit supports the case all the zones in a block group are
sequential. The next patch will handle the case having a conventional
zone.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: verify device extent is aligned to zone
Naohiro Aota [Thu, 4 Feb 2021 10:21:49 +0000 (19:21 +0900)]
btrfs: zoned: verify device extent is aligned to zone

Add a check in verify_one_dev_extent() to ensure that a device extent on
a zoned block device is aligned to the respective zone boundary.

If it isn't, mark the filesystem as unclean.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: implement zoned chunk allocator
Naohiro Aota [Thu, 4 Feb 2021 10:21:48 +0000 (19:21 +0900)]
btrfs: zoned: implement zoned chunk allocator

Implement a zoned chunk and device extent allocator. One device zone
becomes a device extent so that a zone reset affects only this device
extent and does not change the state of blocks in the neighbor device
extents.

To implement the allocator, we need to extend the following functions for
a zoned filesystem.

- init_alloc_chunk_ctl
- dev_extent_search_start
- dev_extent_hole_check
- decide_stripe_size

init_alloc_chunk_ctl_zoned() is mostly the same as regular one. It always
set the stripe_size to the zone size and aligns the parameters to the zone
size.

dev_extent_search_start() only aligns the start offset to zone boundaries.
We don't care about the first 1MB like in regular filesystem because we
anyway reserve the first two zones for superblock logging.

dev_extent_hole_check_zoned() checks if zones in given hole are either
conventional or empty sequential zones. Also, it skips zones reserved for
superblock logging.

With the change to the hole, the new hole may now contain pending extents.
So, in this case, loop again to check that.

Finally, decide_stripe_size_zoned() should shrink the number of devices
instead of stripe size because we need to honor stripe_size == zone_size.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: allow zoned filesystems on non-zoned block devices
Johannes Thumshirn [Thu, 4 Feb 2021 10:21:47 +0000 (19:21 +0900)]
btrfs: zoned: allow zoned filesystems on non-zoned block devices

Run a zoned filesystem on non-zoned devices. This is done by "slicing up"
the block device into static sized chunks and fake a conventional zone on
each of them. The emulated zone size is determined from the size of device
extent.

This is mainly aimed at testing of zoned filesystems, i.e. the zoned
chunk allocator, on regular block devices.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: disallow fitrim on zoned filesystems
Naohiro Aota [Thu, 4 Feb 2021 10:21:46 +0000 (19:21 +0900)]
btrfs: zoned: disallow fitrim on zoned filesystems

The implementation of fitrim depends on space cache, which is not used
and disabled for zoned extent allocator. So the current code does not
work with zoned filesystem.

In the future, we can implement fitrim for zoned filesystems by enabling
space cache (but, only for fitrim) or scanning the extent tree at fitrim
time.  For now, disallow fitrim on zoned filesystems.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: do not load fs_info::zoned from incompat flag
Johannes Thumshirn [Thu, 4 Feb 2021 10:21:45 +0000 (19:21 +0900)]
btrfs: zoned: do not load fs_info::zoned from incompat flag

Don't set the zoned flag in fs_info as soon as we're encountering the
incompat filesystem flag for a zoned filesystem on mount. The zoned flag
in fs_info is in a union together with the zone_size, so setting it too
early will result in setting an incorrect zone_size as well.

Once the correct zone_size is read from the device, we can rely on the
zoned flag in fs_info as well to determine if the filesystem is zoned.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: release path before calling to btrfs_load_block_group_zone_info
Johannes Thumshirn [Thu, 4 Feb 2021 10:21:44 +0000 (19:21 +0900)]
btrfs: release path before calling to btrfs_load_block_group_zone_info

Since we have no write pointer in conventional zones, we cannot
determine the allocation offset from it. Instead, we set the allocation
offset after the highest addressed extent. This is done by reading the
extent tree in btrfs_load_block_group_zone_info().

However, this function is called from btrfs_read_block_groups(), so the
read lock for the tree node could be recursively taken.

To avoid this unsafe locking scenario, release the path before reading
the extent tree to get the allocation offset.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: use regular super block location on zone emulation
Naohiro Aota [Thu, 4 Feb 2021 10:21:43 +0000 (19:21 +0900)]
btrfs: zoned: use regular super block location on zone emulation

A zoned filesystem currently has a superblock at the beginning of the
superblock logging zones if the zones are conventional. This difference
in superblock position causes a chicken-and-egg problem for filesystems
with emulated zones. Since the device is a regular (non-zoned) device,
we cannot know if the filesystem is regular or zoned while reading the
superblock. But, to load the superblock, we need to see if it is
emulated zoned or not.

Place the superblocks at the same location as they are on regular
filesystem on regular devices to solve the problem. It is possible
because it's ensured that all the superblock locations are at an
(emulated) conventional zone on regular devices.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: zoned: defer loading zone info after opening trees
Naohiro Aota [Thu, 4 Feb 2021 10:21:42 +0000 (19:21 +0900)]
btrfs: zoned: defer loading zone info after opening trees

This is a preparation patch to implement zone emulation on a regular
device.

To emulate a zoned filesystem on a regular (non-zoned) device, we need to
decide an emulated zone size. Instead of making it a compile-time static
value, we'll make it configurable at mkfs time. Since we have one zone ==
one device extent restriction, we can determine the emulated zone size
from the size of a device extent. We can extend btrfs_get_dev_zone_info()
to show a regular device filled with conventional zones once the zone size
is decided.

The current call site of btrfs_get_dev_zone_info() during the mount process
is earlier than loading the file system trees so that we don't know the
size of a device extent at this point. Thus we can't slice a regular device
to conventional zones.

This patch introduces btrfs_get_dev_zone_info_all_devices to load the zone
info for all the devices. And, it places this function in open_ctree()
after loading the trees.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoiomap: support REQ_OP_ZONE_APPEND
Naohiro Aota [Thu, 4 Feb 2021 10:21:41 +0000 (19:21 +0900)]
iomap: support REQ_OP_ZONE_APPEND

A ZONE_APPEND bio must follow hardware restrictions (e.g. not exceeding
max_zone_append_sectors) not to be split. bio_iov_iter_get_pages builds
such restricted bio using __bio_iov_append_get_pages if bio_op(bio) ==
REQ_OP_ZONE_APPEND.

To utilize it, we need to set the bio_op before calling
bio_iov_iter_get_pages(). This commit introduces IOMAP_F_ZONE_APPEND, so
that iomap user can set the flag to indicate they want REQ_OP_ZONE_APPEND
and restricted bio.

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agoblock: add bio_add_zone_append_page
Johannes Thumshirn [Thu, 4 Feb 2021 10:21:40 +0000 (19:21 +0900)]
block: add bio_add_zone_append_page

Add bio_add_zone_append_page(), a wrapper around bio_add_hw_page() which
is intended to be used by file systems that directly add pages to a bio
instead of using bio_iov_iter_get_pages().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Acked-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
5 years agobtrfs: fix extent buffer leak on failure to copy root
Filipe Manana [Thu, 4 Feb 2021 14:35:44 +0000 (14:35 +0000)]
btrfs: fix extent buffer leak on failure to copy root

At btrfs_copy_root(), if the call to btrfs_inc_ref() fails we end up
returning without unlocking and releasing our reference on the extent
buffer named "cow" we previously allocated with btrfs_alloc_tree_block().

So fix that by unlocking the extent buffer and dropping our reference on
it before returning.

Fixes: be20aa9dbadc8c ("Btrfs: Add mount option to turn off data cow")
CC: stable@vger.kernel.org # 4.4+
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: explain page locking and readahead in read_extent_buffer_pages()
Qu Wenruo [Thu, 28 Jan 2021 11:25:08 +0000 (19:25 +0800)]
btrfs: explain page locking and readahead in read_extent_buffer_pages()

In read_extent_buffer_pages(), if we failed to lock the page atomically,
we just exit with return value 0.

This is counter-intuitive, as normally if we can't lock what we need, we
would return something like EAGAIN.

But that return hides under (wait == WAIT_NONE) branch, which only gets
triggered for readahead.

And for readahead, if we failed to lock the page, it means the extent
buffer is either being read by other thread, or has been read and is
under modification.  Either way the eb will or has been cached, thus
readahead has no need to wait for it.

Add comment on this counter-intuitive behavior.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
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: allow read-only mount of 4K sector size fs on 64K page system
Qu Wenruo [Tue, 26 Jan 2021 08:34:02 +0000 (16:34 +0800)]
btrfs: allow read-only mount of 4K sector size fs on 64K page system

This adds the basic RO mount ability for 4K sector size on 64K page
system.

Currently we only plan to support 4K and 64K page system.

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: integrate page status update for data read path into begin/end_page_read
Qu Wenruo [Tue, 2 Feb 2021 02:28:36 +0000 (10:28 +0800)]
btrfs: integrate page status update for data read path into begin/end_page_read

In btrfs data page read path, the page status update are handled in two
different locations:

  btrfs_do_read_page()
  {
while (cur <= end) {
/* No need to read from disk */
if (HOLE/PREALLOC/INLINE){
memset();
set_extent_uptodate();
continue;
}
/* Read from disk */
ret = submit_extent_page(end_bio_extent_readpage);
  }

  end_bio_extent_readpage()
  {
endio_readpage_uptodate_page_status();
  }

This is fine for sectorsize == PAGE_SIZE case, as for above loop we
should only hit one branch and then exit.

But for subpage, there is more work to be done in page status update:

- Page Unlock condition
  Unlike regular page size == sectorsize case, we can no longer just
  unlock a page.
  Only the last reader of the page can unlock the page.
  This means, we can unlock the page either in the while() loop, or in
  the endio function.

- Page uptodate condition
  Since we have multiple sectors to read for a page, we can only mark
  the full page uptodate if all sectors are uptodate.

To handle both subpage and regular cases, introduce a pair of functions
to help handling page status update:

- begin_page_read()
  For regular case, it does nothing.
  For subpage case, it updates the reader counters so that later
  end_page_read() can know who is the last one to unlock the page.

- end_page_read()
  This is just endio_readpage_uptodate_page_status() renamed.
  The original name is a little too long and too specific for endio.

  The new thing added is the condition for page unlock.
  Now for subpage data, we unlock the page if we're the last reader.

This does not only provide the basis for subpage data read, but also
hide the special handling of page read from the main read loop.

Also, since we're changing how the page lock is handled, there are two
existing error paths where we need to manually unlock the page before
calling begin_page_read().

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: introduce btrfs_subpage for data inodes
Qu Wenruo [Tue, 26 Jan 2021 08:34:00 +0000 (16:34 +0800)]
btrfs: introduce btrfs_subpage for data inodes

To support subpage sector size, data also need extra info to make sure
which sectors in a page are uptodate/dirty/...

This patch will make pages for data inodes get btrfs_subpage structure
attached, and detached when the page is freed.

This patch also slightly changes the timing when
set_page_extent_mapped() is called to make sure:

- We have page->mapping set
  page->mapping->host is used to grab btrfs_fs_info, thus we can only
  call this function after page is mapped to an inode.

  One call site attaches pages to inode manually, thus we have to modify
  the timing of set_page_extent_mapped() a bit.

- As soon as possible, before other operations
  Since memory allocation can fail, we have to do extra error handling.
  Calling set_page_extent_mapped() as soon as possible can simply the
  error handling for several call sites.

The idea is pretty much the same as iomap_page, but with more bitmaps
for btrfs specific cases.

Currently the plan is to switch iomap if iomap can provide sector
aligned write back (only write back dirty sectors, but not the full
page, data balance require this feature).

So we will stick to btrfs specific bitmap for now.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>