--- /dev/null
+From d0e185616a0331c87ce3aa1d7dfde8df39d6d002 Mon Sep 17 00:00:00 2001
+From: Chris Chiu <chris.chiu@canonical.com>
+Date: Fri, 26 Feb 2021 09:04:40 +0800
+Subject: ALSA: hda/realtek: Enable headset mic of Acer SWIFT with ALC256
+
+From: Chris Chiu <chris.chiu@canonical.com>
+
+commit d0e185616a0331c87ce3aa1d7dfde8df39d6d002 upstream.
+
+The Acer SWIFT Swift SF314-54/55 laptops with ALC256 cannot detect
+both the headset mic and the internal mic. Introduce new fixup
+to enable the jack sense and the headset mic. However, the internal
+mic actually connects to Intel SST audio. It still needs Intel SST
+support to make internal mic capture work.
+
+Signed-off-by: Chris Chiu <chris.chiu@canonical.com>
+Acked-by: Jian-Hong Pan <jhp@endlessos.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210226010440.8474-1-chris.chiu@canonical.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6408,6 +6408,7 @@ enum {
+ ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
+ ALC282_FIXUP_ACER_DISABLE_LINEOUT,
+ ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
++ ALC256_FIXUP_ACER_HEADSET_MIC,
+ };
+
+ static const struct hda_fixup alc269_fixups[] = {
+@@ -7864,6 +7865,16 @@ static const struct hda_fixup alc269_fix
+ .chained = true,
+ .chain_id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
+ },
++ [ALC256_FIXUP_ACER_HEADSET_MIC] = {
++ .type = HDA_FIXUP_PINS,
++ .v.pins = (const struct hda_pintbl[]) {
++ { 0x19, 0x02a1113c }, /* use as headset mic, without its own jack detect */
++ { 0x1a, 0x90a1092f }, /* use as internal mic */
++ { }
++ },
++ .chained = true,
++ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -7890,9 +7901,11 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK),
+ SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
+ SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1025, 0x1269, "Acer SWIFT SF314-54", ALC256_FIXUP_ACER_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
++ SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
--- /dev/null
+From 5f5e6a3e8b1df52f79122e447855cffbf1710540 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 28 Feb 2021 09:01:38 +0100
+Subject: ALSA: usb-audio: Allow modifying parameters with succeeding hw_params calls
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 5f5e6a3e8b1df52f79122e447855cffbf1710540 upstream.
+
+The recent fix for the hw constraints for implicit feedback streams
+via commit e4ea77f8e53f ("ALSA: usb-audio: Always apply the hw
+constraints for implicit fb sync") added the check of the matching
+endpoints and whether those EPs are already opened. This is needed
+and correct, per se, even for the normal streams without the implicit
+feedback, as the endpoint setup is exclusive.
+
+However, it's reported that there seem applications that behave in
+unexpected ways to update the hw_params without clearing the previous
+setup via hw_free, and those hit a problem now: then hw_params is
+called with still the previous EP setup kept, hence it's restricted
+with the previous own setup. Although the obvious fix is to call
+snd_pcm_hw_free() API in the application side, it's a kind of
+unwelcome change.
+
+This patch tries to ease the situation: in the endpoint check, we add
+a couple of more conditions and now skip the endpoint that is being
+used only by the stream in question itself. That is, in addition to
+the presence check of ep (ep->cur_audiofmt is non-NULL), when the
+following conditions are met, we skip such an ep:
+- ep->opened == 1, and
+- ep->cur_audiofmt == subs->cur_audiofmt.
+
+subs->cur_audiofmt is non-NULL only if it's a re-setup of hw_params,
+and ep->cur_audiofmt points to the currently set up parameters. So if
+those match, it must be this stream itself.
+
+Fixes: e4ea77f8e53f ("ALSA: usb-audio: Always apply the hw constraints for implicit fb sync")
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211941
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210228080138.9936-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/pcm.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -845,13 +845,19 @@ get_sync_ep_from_substream(struct snd_us
+
+ list_for_each_entry(fp, &subs->fmt_list, list) {
+ ep = snd_usb_get_endpoint(chip, fp->endpoint);
+- if (ep && ep->cur_rate)
+- return ep;
++ if (ep && ep->cur_audiofmt) {
++ /* if EP is already opened solely for this substream,
++ * we still allow us to change the parameter; otherwise
++ * this substream has to follow the existing parameter
++ */
++ if (ep->cur_audiofmt != subs->cur_audiofmt || ep->opened > 1)
++ return ep;
++ }
+ if (!fp->implicit_fb)
+ continue;
+ /* for the implicit fb, check the sync ep as well */
+ ep = snd_usb_get_endpoint(chip, fp->sync_ep);
+- if (ep && ep->cur_rate)
++ if (ep && ep->cur_audiofmt)
+ return ep;
+ }
+ return NULL;
--- /dev/null
+From dcf269b3f703f5dbc2101824d9dbe95feed87b3d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 27 Feb 2021 09:20:02 +0100
+Subject: ALSA: usb-audio: Don't abort even if the clock rate differs
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit dcf269b3f703f5dbc2101824d9dbe95feed87b3d upstream.
+
+The commit 93db51d06b32 ("ALSA: usb-audio: Check valid altsetting at
+parsing rates for UAC2/3") changed the behavior of the function
+set_sample_rate_v2v3() slightly to treat the inconsistent sample rate
+as an error. It was done by assumption that the sample rate
+validation should have been done at the parser phase as implemented in
+that patch. But the validation is later selectively enabled only for
+certain devices as it causes a regression (the commit fe773b8711e3
+"ALSA: usb-audio: workaround for iface reset issue"), and now the
+inconsistency surfaced as a fatal error while it worked in the past as
+is, as reported for FiiO M3K DAC.
+
+For recovering from the regression, change set_sample_rate_v2v3()
+again to ignore the sample rate difference as non-error.
+
+BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1182633
+Fixes: 93db51d06b32 ("ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3")
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210227082002.21185-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/clock.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/sound/usb/clock.c
++++ b/sound/usb/clock.c
+@@ -646,10 +646,10 @@ static int set_sample_rate_v2v3(struct s
+ cur_rate = prev_rate;
+
+ if (cur_rate != rate) {
+- usb_audio_warn(chip,
+- "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
+- fmt->iface, fmt->altsetting, rate, cur_rate);
+- return -ENXIO;
++ usb_audio_dbg(chip,
++ "%d:%d: freq mismatch: req %d, clock runs @%d\n",
++ fmt->iface, fmt->altsetting, rate, cur_rate);
++ /* continue processing */
+ }
+
+ validation:
--- /dev/null
+From 21cba9c5359dd9d1bffe355336cfec0b66d1ee52 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 27 Feb 2021 11:57:37 +0100
+Subject: ALSA: usb-audio: Drop bogus dB range in too low level
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 21cba9c5359dd9d1bffe355336cfec0b66d1ee52 upstream.
+
+Some USB audio firmware seem to report broken dB values for the volume
+controls, and this screws up applications like PulseAudio who blindly
+trusts the given data. For example, Edifier G2000 reports a PCM
+volume from -128dB to -127dB, and this results in barely inaudible
+sound.
+
+This patch adds a sort of sanity check at parsing the dB values in
+USB-audio driver and disables the dB reporting if the range looks
+bogus. Here, we assume -96dB as the bottom line of the max dB.
+
+Note that, if one can figure out that proper dB range later, it can be
+patched in the mixer maps.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211929
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210227105737.3656-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -1301,6 +1301,17 @@ no_res_check:
+ /* totally crap, return an error */
+ return -EINVAL;
+ }
++ } else {
++ /* if the max volume is too low, it's likely a bogus range;
++ * here we use -96dB as the threshold
++ */
++ if (cval->dBmax <= -9600) {
++ usb_audio_info(cval->head.mixer->chip,
++ "%d:%d: bogus dB values (%d/%d), disabling dB reporting\n",
++ cval->head.id, mixer_ctrl_intf(cval->head.mixer),
++ cval->dBmin, cval->dBmax);
++ cval->dBmin = cval->dBmax = 0;
++ }
+ }
+
+ return 0;
--- /dev/null
+From 11302bb69e72d0526bc626ee5c451a3d22cde904 Mon Sep 17 00:00:00 2001
+From: Andrea Fagiani <andfagiani@gmail.com>
+Date: Tue, 19 Jan 2021 08:47:44 +0000
+Subject: ALSA: usb-audio: use Corsair Virtuoso mapping for Corsair Virtuoso SE
+
+From: Andrea Fagiani <andfagiani@gmail.com>
+
+commit 11302bb69e72d0526bc626ee5c451a3d22cde904 upstream.
+
+The Corsair Virtuoso SE RGB Wireless is a USB headset with a mic and a
+sidetone feature. Assign the Corsair Virtuoso name map to the SE product
+ids as well, in order to label its mixer appropriately and allow
+userspace to pick the correct volume controls.
+
+Signed-off-by: Andrea Fagiani <andfagiani@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/40bbdf55-f854-e2ee-87b4-183e6451352c@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_maps.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/sound/usb/mixer_maps.c
++++ b/sound/usb/mixer_maps.c
+@@ -537,6 +537,16 @@ static const struct usbmix_ctl_map usbmi
+ .map = bose_companion5_map,
+ },
+ {
++ /* Corsair Virtuoso SE (wired mode) */
++ .id = USB_ID(0x1b1c, 0x0a3d),
++ .map = corsair_virtuoso_map,
++ },
++ {
++ /* Corsair Virtuoso SE (wireless mode) */
++ .id = USB_ID(0x1b1c, 0x0a3e),
++ .map = corsair_virtuoso_map,
++ },
++ {
+ /* Corsair Virtuoso (wired mode) */
+ .id = USB_ID(0x1b1c, 0x0a41),
+ .map = corsair_virtuoso_map,
--- /dev/null
+From 95c85fba1f64c3249c67f0078a29f8a125078189 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Mon, 25 Jan 2021 16:42:35 -0500
+Subject: btrfs: avoid double put of block group when emptying cluster
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 95c85fba1f64c3249c67f0078a29f8a125078189 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/free-space-cache.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -2708,8 +2708,10 @@ static void __btrfs_return_cluster_to_fr
+ struct rb_node *node;
+
+ spin_lock(&cluster->lock);
+- if (cluster->block_group != block_group)
+- goto out;
++ if (cluster->block_group != block_group) {
++ spin_unlock(&cluster->lock);
++ return;
++ }
+
+ cluster->block_group = NULL;
+ cluster->window_start = 0;
+@@ -2747,8 +2749,6 @@ static void __btrfs_return_cluster_to_fr
+ entry->offset, &entry->offset_index, bitmap);
+ }
+ cluster->root = RB_ROOT;
+-
+-out:
+ spin_unlock(&cluster->lock);
+ btrfs_put_block_group(block_group);
+ }
--- /dev/null
+From 3c17916510428dbccdf657de050c34e208347089 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Mon, 8 Feb 2021 10:26:54 +0200
+Subject: btrfs: fix race between extent freeing/allocation when using bitmaps
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 3c17916510428dbccdf657de050c34e208347089 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/free-space-cache.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -3028,8 +3028,6 @@ u64 btrfs_alloc_from_cluster(struct btrf
+ entry->bytes -= bytes;
+ }
+
+- if (entry->bytes == 0)
+- rb_erase(&entry->offset_index, &cluster->root);
+ break;
+ }
+ out:
+@@ -3046,7 +3044,10 @@ out:
+ ctl->free_space -= bytes;
+ if (!entry->bitmap && !btrfs_free_space_trimmed(entry))
+ ctl->discardable_bytes[BTRFS_STAT_CURR] -= bytes;
++
++ spin_lock(&cluster->lock);
+ if (entry->bytes == 0) {
++ rb_erase(&entry->offset_index, &cluster->root);
+ ctl->free_extents--;
+ if (entry->bitmap) {
+ kmem_cache_free(btrfs_free_space_bitmap_cachep,
+@@ -3059,6 +3060,7 @@ out:
+ kmem_cache_free(btrfs_free_space_cachep, entry);
+ }
+
++ spin_unlock(&cluster->lock);
+ spin_unlock(&ctl->tree_lock);
+
+ return ret;
--- /dev/null
+From dd0734f2a866f9d619d4abf97c3d71bcdee40ea9 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 5 Feb 2021 12:55:38 +0000
+Subject: btrfs: fix race between swap file activation and snapshot creation
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit dd0734f2a866f9d619d4abf97c3d71bcdee40ea9 upstream.
+
+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")
+CC: stable@vger.kernel.org # 5.4+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/inode.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -10099,7 +10099,8 @@ static int btrfs_swap_activate(struct sw
+ sector_t *span)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
++ struct btrfs_root *root = BTRFS_I(inode)->root;
++ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
+ struct extent_state *cached_state = NULL;
+ struct extent_map *em = NULL;
+@@ -10150,13 +10151,27 @@ static int btrfs_swap_activate(struct sw
+ "cannot activate swapfile while exclusive operation is running");
+ return -EBUSY;
+ }
++
++ /*
++ * Prevent snapshot creation while we are activating the swap file.
++ * We do not want to race with snapshot creation. If snapshot creation
++ * already started before we bumped nr_swapfiles from 0 to 1 and
++ * completes before the first write into the swap file after it is
++ * activated, than that write would fallback to COW.
++ */
++ if (!btrfs_drew_try_write_lock(&root->snapshot_lock)) {
++ btrfs_exclop_finish(fs_info);
++ btrfs_warn(fs_info,
++ "cannot activate swapfile because snapshot creation is in progress");
++ return -EINVAL;
++ }
+ /*
+ * Snapshots can create extents which require COW even if NODATACOW is
+ * set. We use this counter to prevent snapshots. We must increment it
+ * before walking the extents because we don't want a concurrent
+ * snapshot to run after we've already checked the extents.
+ */
+- atomic_inc(&BTRFS_I(inode)->root->nr_swapfiles);
++ atomic_inc(&root->nr_swapfiles);
+
+ isize = ALIGN_DOWN(inode->i_size, fs_info->sectorsize);
+
+@@ -10302,6 +10317,8 @@ out:
+ if (ret)
+ btrfs_swap_deactivate(file);
+
++ btrfs_drew_write_unlock(&root->snapshot_lock);
++
+ btrfs_exclop_finish(fs_info);
+
+ if (ret)
--- /dev/null
+From 195a49eaf655eb914896c92cecd96bc863c9feb3 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 5 Feb 2021 12:55:37 +0000
+Subject: btrfs: fix race between writes to swap files and scrub
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 195a49eaf655eb914896c92cecd96bc863c9feb3 upstream.
+
+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")
+CC: stable@vger.kernel.org # 5.4+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/block-group.c | 33 ++++++++++++++++++++++++++++++++-
+ fs/btrfs/block-group.h | 9 +++++++++
+ fs/btrfs/ctree.h | 5 +++++
+ fs/btrfs/inode.c | 19 ++++++++++++++++++-
+ fs/btrfs/scrub.c | 9 ++++++++-
+ 5 files changed, 72 insertions(+), 3 deletions(-)
+
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -1150,6 +1150,11 @@ static int inc_block_group_ro(struct btr
+ spin_lock(&sinfo->lock);
+ spin_lock(&cache->lock);
+
++ if (cache->swap_extents) {
++ ret = -ETXTBSY;
++ goto out;
++ }
++
+ if (cache->ro) {
+ cache->ro++;
+ ret = 0;
+@@ -2253,7 +2258,7 @@ again:
+ }
+
+ ret = inc_block_group_ro(cache, 0);
+- if (!do_chunk_alloc)
++ if (!do_chunk_alloc || ret == -ETXTBSY)
+ goto unlock_out;
+ if (!ret)
+ goto out;
+@@ -2262,6 +2267,8 @@ again:
+ if (ret < 0)
+ goto out;
+ ret = inc_block_group_ro(cache, 0);
++ if (ret == -ETXTBSY)
++ goto unlock_out;
+ out:
+ if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
+ alloc_flags = btrfs_get_alloc_profile(fs_info, cache->flags);
+@@ -3345,6 +3352,7 @@ int btrfs_free_block_groups(struct btrfs
+ ASSERT(list_empty(&block_group->io_list));
+ ASSERT(list_empty(&block_group->bg_list));
+ ASSERT(refcount_read(&block_group->refs) == 1);
++ ASSERT(block_group->swap_extents == 0);
+ btrfs_put_block_group(block_group);
+
+ spin_lock(&info->block_group_cache_lock);
+@@ -3411,3 +3419,26 @@ void btrfs_unfreeze_block_group(struct b
+ __btrfs_remove_free_space_cache(block_group->free_space_ctl);
+ }
+ }
++
++bool btrfs_inc_block_group_swap_extents(struct btrfs_block_group *bg)
++{
++ bool ret = true;
++
++ spin_lock(&bg->lock);
++ if (bg->ro)
++ ret = false;
++ else
++ bg->swap_extents++;
++ spin_unlock(&bg->lock);
++
++ return ret;
++}
++
++void btrfs_dec_block_group_swap_extents(struct btrfs_block_group *bg, int amount)
++{
++ spin_lock(&bg->lock);
++ ASSERT(!bg->ro);
++ ASSERT(bg->swap_extents >= amount);
++ bg->swap_extents -= amount;
++ spin_unlock(&bg->lock);
++}
+--- a/fs/btrfs/block-group.h
++++ b/fs/btrfs/block-group.h
+@@ -181,6 +181,12 @@ struct btrfs_block_group {
+ */
+ int needs_free_space;
+
++ /*
++ * Number of extents in this block group used for swap files.
++ * All accesses protected by the spinlock 'lock'.
++ */
++ int swap_extents;
++
+ /* Record locked full stripes for RAID5/6 block group */
+ struct btrfs_full_stripe_locks_tree full_stripe_locks_root;
+ };
+@@ -301,4 +307,7 @@ int btrfs_rmap_block(struct btrfs_fs_inf
+ u64 physical, u64 **logical, int *naddrs, int *stripe_len);
+ #endif
+
++bool btrfs_inc_block_group_swap_extents(struct btrfs_block_group *bg);
++void btrfs_dec_block_group_swap_extents(struct btrfs_block_group *bg, int amount);
++
+ #endif /* BTRFS_BLOCK_GROUP_H */
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -523,6 +523,11 @@ struct btrfs_swapfile_pin {
+ * points to a struct btrfs_device.
+ */
+ bool is_block_group;
++ /*
++ * Only used when 'is_block_group' is true and it is the number of
++ * extents used by a swapfile for this block group ('ptr' field).
++ */
++ int bg_extent_count;
+ };
+
+ bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -9993,6 +9993,7 @@ static int btrfs_add_swapfile_pin(struct
+ sp->ptr = ptr;
+ sp->inode = inode;
+ sp->is_block_group = is_block_group;
++ sp->bg_extent_count = 1;
+
+ spin_lock(&fs_info->swapfile_pins_lock);
+ p = &fs_info->swapfile_pins.rb_node;
+@@ -10006,6 +10007,8 @@ static int btrfs_add_swapfile_pin(struct
+ (sp->ptr == entry->ptr && sp->inode > entry->inode)) {
+ p = &(*p)->rb_right;
+ } else {
++ if (is_block_group)
++ entry->bg_extent_count++;
+ spin_unlock(&fs_info->swapfile_pins_lock);
+ kfree(sp);
+ return 1;
+@@ -10031,8 +10034,11 @@ static void btrfs_free_swapfile_pins(str
+ sp = rb_entry(node, struct btrfs_swapfile_pin, node);
+ if (sp->inode == inode) {
+ rb_erase(&sp->node, &fs_info->swapfile_pins);
+- if (sp->is_block_group)
++ if (sp->is_block_group) {
++ btrfs_dec_block_group_swap_extents(sp->ptr,
++ sp->bg_extent_count);
+ btrfs_put_block_group(sp->ptr);
++ }
+ kfree(sp);
+ }
+ node = next;
+@@ -10246,6 +10252,17 @@ static int btrfs_swap_activate(struct sw
+ ret = -EINVAL;
+ goto out;
+ }
++
++ if (!btrfs_inc_block_group_swap_extents(bg)) {
++ btrfs_warn(fs_info,
++ "block group for swapfile at %llu is read-only%s",
++ bg->start,
++ atomic_read(&fs_info->scrubs_running) ?
++ " (scrub running)" : "");
++ btrfs_put_block_group(bg);
++ ret = -EINVAL;
++ goto out;
++ }
+
+ ret = btrfs_add_swapfile_pin(inode, bg, true);
+ if (ret) {
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -3630,6 +3630,13 @@ int scrub_enumerate_chunks(struct scrub_
+ * commit_transactions.
+ */
+ ro_set = 0;
++ } else if (ret == -ETXTBSY) {
++ btrfs_warn(fs_info,
++ "skipping scrub of block group %llu due to active swapfile",
++ cache->start);
++ scrub_pause_off(fs_info);
++ ret = 0;
++ goto skip_unfreeze;
+ } else {
+ btrfs_warn(fs_info,
+ "failed setting block group ro: %d", ret);
+@@ -3719,7 +3726,7 @@ int scrub_enumerate_chunks(struct scrub_
+ } else {
+ spin_unlock(&cache->lock);
+ }
+-
++skip_unfreeze:
+ btrfs_unfreeze_block_group(cache);
+ btrfs_put_block_group(cache);
+ if (ret)
--- /dev/null
+From d70cef0d46729808dc53f145372c02b145c92604 Mon Sep 17 00:00:00 2001
+From: Ira Weiny <ira.weiny@intel.com>
+Date: Wed, 27 Jan 2021 22:15:03 -0800
+Subject: btrfs: fix raid6 qstripe kmap
+
+From: Ira Weiny <ira.weiny@intel.com>
+
+commit d70cef0d46729808dc53f145372c02b145c92604 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/raid56.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -2363,16 +2363,21 @@ static noinline void finish_parity_scrub
+ SetPageUptodate(p_page);
+
+ if (has_qstripe) {
++ /* RAID6, allocate and map temp space for the Q stripe */
+ q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+ if (!q_page) {
+ __free_page(p_page);
+ goto cleanup;
+ }
+ SetPageUptodate(q_page);
++ pointers[rbio->real_stripes - 1] = kmap(q_page);
+ }
+
+ atomic_set(&rbio->error, 0);
+
++ /* Map the parity stripe just once */
++ pointers[nr_data] = kmap(p_page);
++
+ for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
+ struct page *p;
+ void *parity;
+@@ -2382,16 +2387,8 @@ static noinline void finish_parity_scrub
+ pointers[stripe] = kmap(p);
+ }
+
+- /* then add the parity stripe */
+- pointers[stripe++] = kmap(p_page);
+-
+ if (has_qstripe) {
+- /*
+- * raid6, add the qstripe and call the
+- * library function to fill in our p/q
+- */
+- pointers[stripe++] = kmap(q_page);
+-
++ /* RAID6, call the library function to fill in our P/Q */
+ raid6_call.gen_syndrome(rbio->real_stripes, PAGE_SIZE,
+ pointers);
+ } else {
+@@ -2412,12 +2409,14 @@ static noinline void finish_parity_scrub
+
+ for (stripe = 0; stripe < nr_data; stripe++)
+ kunmap(page_in_rbio(rbio, stripe, pagenr, 0));
+- kunmap(p_page);
+ }
+
++ kunmap(p_page);
+ __free_page(p_page);
+- if (q_page)
++ if (q_page) {
++ kunmap(q_page);
+ __free_page(q_page);
++ }
+
+ writeback:
+ /*
--- /dev/null
+From c55a4319c4f2c3ba0a385b1ebc454fa283cfe920 Mon Sep 17 00:00:00 2001
+From: Boris Burkov <boris@bur.io>
+Date: Tue, 23 Feb 2021 10:22:32 -0800
+Subject: btrfs: fix spurious free_space_tree remount warning
+
+From: Boris Burkov <boris@bur.io>
+
+commit c55a4319c4f2c3ba0a385b1ebc454fa283cfe920 upstream.
+
+The intended logic of the check is to catch cases where the desired
+free_space_tree setting doesn't match the mounted setting, and the
+remount is anything but ro->rw. However, it makes the mistake of
+checking equality on a masked integer (btrfs_test_opt) against a boolean
+(btrfs_fs_compat_ro).
+
+If you run the reproducer:
+ $ mount -o space_cache=v2 dev mnt
+ $ mount -o remount,ro mnt
+
+you would expect no warning, because the remount is not attempting to
+change the free space tree setting, but we do see the warning.
+
+To fix this, add explicit bool type casts to the condition.
+
+I tested a variety of transitions:
+sudo mount -o space_cache=v2 /dev/vg0/lv0 mnt/lol
+(fst enabled)
+mount -o remount,ro mnt/lol
+(no warning, no fst change)
+sudo mount -o remount,rw,space_cache=v1,clear_cache
+(no warning, ro->rw)
+sudo mount -o remount,rw,space_cache=v2 mnt
+(warning, rw->rw with change)
+sudo mount -o remount,ro mnt
+(no warning, no fst change)
+sudo mount -o remount,rw,space_cache=v2 mnt
+(no warning, no fst change)
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+CC: stable@vger.kernel.org # 5.11
+Signed-off-by: Boris Burkov <boris@bur.io>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/super.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -1919,8 +1919,8 @@ static int btrfs_remount(struct super_bl
+ btrfs_resize_thread_pool(fs_info,
+ fs_info->thread_pool_size, old_thread_pool_size);
+
+- if (btrfs_test_opt(fs_info, FREE_SPACE_TREE) !=
+- btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
++ if ((bool)btrfs_test_opt(fs_info, FREE_SPACE_TREE) !=
++ (bool)btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
+ (!sb_rdonly(sb) || (*flags & SB_RDONLY))) {
+ btrfs_warn(fs_info,
+ "remount supports changing free space tree only from ro to rw");
--- /dev/null
+From 3660d0bcdb82807d434da9d2e57d88b37331182d Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Tue, 16 Feb 2021 11:09:25 +0000
+Subject: btrfs: fix stale data exposure after cloning a hole with NO_HOLES enabled
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 3660d0bcdb82807d434da9d2e57d88b37331182d upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/reflink.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/fs/btrfs/reflink.c
++++ b/fs/btrfs/reflink.c
+@@ -550,6 +550,24 @@ process_slot:
+ */
+ btrfs_release_path(path);
+
++ /*
++ * When using NO_HOLES and we are cloning a range that covers
++ * only a hole (no extents) into a range beyond the current
++ * i_size, punching a hole in the target range will not create
++ * an extent map defining a hole, because the range starts at or
++ * beyond current i_size. If the file previously had an i_size
++ * greater than the new i_size set by this clone operation, we
++ * need to make sure the next fsync is a full fsync, so that it
++ * detects and logs a hole covering a range from the current
++ * i_size to the new i_size. If the clone range covers extents,
++ * besides a hole, then we know the full sync flag was already
++ * set by previous calls to btrfs_replace_file_extents() that
++ * replaced file extent items.
++ */
++ if (last_dest_end >= i_size_read(inode))
++ set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
++ &BTRFS_I(inode)->runtime_flags);
++
+ ret = btrfs_replace_file_extents(inode, path, last_dest_end,
+ destoff + len - 1, NULL, &trans);
+ if (ret)
--- /dev/null
+From fd57a98d6f0c98fa295813087f13afb26c224e73 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 26 Feb 2021 17:51:44 +0000
+Subject: btrfs: fix warning when creating a directory with smack enabled
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit fd57a98d6f0c98fa295813087f13afb26c224e73 upstream.
+
+When we have smack enabled, during the creation of a directory smack may
+attempt to add a "smack transmute" xattr on the inode, which results in
+the following warning and trace:
+
+ WARNING: CPU: 3 PID: 2548 at fs/btrfs/transaction.c:537 start_transaction+0x489/0x4f0
+ Modules linked in: nft_objref nf_conntrack_netbios_ns (...)
+ CPU: 3 PID: 2548 Comm: mkdir Not tainted 5.9.0-rc2smack+ #81
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
+ RIP: 0010:start_transaction+0x489/0x4f0
+ Code: e9 be fc ff ff (...)
+ RSP: 0018:ffffc90001887d10 EFLAGS: 00010202
+ RAX: ffff88816f1e0000 RBX: 0000000000000201 RCX: 0000000000000003
+ RDX: 0000000000000201 RSI: 0000000000000002 RDI: ffff888177849000
+ RBP: ffff888177849000 R08: 0000000000000001 R09: 0000000000000004
+ R10: ffffffff825e8f7a R11: 0000000000000003 R12: ffffffffffffffe2
+ R13: 0000000000000000 R14: ffff88803d884270 R15: ffff8881680d8000
+ FS: 00007f67317b8440(0000) GS:ffff88817bcc0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007f67247a22a8 CR3: 000000004bfbc002 CR4: 0000000000370ee0
+ DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+ Call Trace:
+ ? slab_free_freelist_hook+0xea/0x1b0
+ ? trace_hardirqs_on+0x1c/0xe0
+ btrfs_setxattr_trans+0x3c/0xf0
+ __vfs_setxattr+0x63/0x80
+ smack_d_instantiate+0x2d3/0x360
+ security_d_instantiate+0x29/0x40
+ d_instantiate_new+0x38/0x90
+ btrfs_mkdir+0x1cf/0x1e0
+ vfs_mkdir+0x14f/0x200
+ do_mkdirat+0x6d/0x110
+ do_syscall_64+0x2d/0x40
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+ RIP: 0033:0x7f673196ae6b
+ Code: 8b 05 11 (...)
+ RSP: 002b:00007ffc3c679b18 EFLAGS: 00000246 ORIG_RAX: 0000000000000053
+ RAX: ffffffffffffffda RBX: 00000000000001ff RCX: 00007f673196ae6b
+ RDX: 0000000000000000 RSI: 00000000000001ff RDI: 00007ffc3c67a30d
+ RBP: 00007ffc3c67a30d R08: 00000000000001ff R09: 0000000000000000
+ R10: 000055d3e39fe930 R11: 0000000000000246 R12: 0000000000000000
+ R13: 00007ffc3c679cd8 R14: 00007ffc3c67a30d R15: 00007ffc3c679ce0
+ irq event stamp: 11029
+ hardirqs last enabled at (11037): [<ffffffff81153fe6>] console_unlock+0x486/0x670
+ hardirqs last disabled at (11044): [<ffffffff81153c01>] console_unlock+0xa1/0x670
+ softirqs last enabled at (8864): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+ softirqs last disabled at (8851): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+
+This happens because at btrfs_mkdir() we call d_instantiate_new() while
+holding a transaction handle, which results in the following call chain:
+
+ btrfs_mkdir()
+ trans = btrfs_start_transaction(root, 5);
+
+ d_instantiate_new()
+ smack_d_instantiate()
+ __vfs_setxattr()
+ btrfs_setxattr_trans()
+ btrfs_start_transaction()
+ start_transaction()
+ WARN_ON()
+ --> a tansaction start has TRANS_EXTWRITERS
+ set in its type
+ h->orig_rsv = h->block_rsv
+ h->block_rsv = NULL
+
+ btrfs_end_transaction(trans)
+
+Besides the warning triggered at start_transaction, we set the handle's
+block_rsv to NULL which may cause some surprises later on.
+
+So fix this by making btrfs_setxattr_trans() not start a transaction when
+we already have a handle on one, stored in current->journal_info, and use
+that handle. We are good to use the handle because at btrfs_mkdir() we did
+reserve space for the xattr and the inode item.
+
+Reported-by: Casey Schaufler <casey@schaufler-ca.com>
+CC: stable@vger.kernel.org # 5.4+
+Acked-by: Casey Schaufler <casey@schaufler-ca.com>
+Tested-by: Casey Schaufler <casey@schaufler-ca.com>
+Link: https://lore.kernel.org/linux-btrfs/434d856f-bd7b-4889-a6ec-e81aaebfa735@schaufler-ca.com/
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/xattr.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/xattr.c
++++ b/fs/btrfs/xattr.c
+@@ -229,11 +229,33 @@ int btrfs_setxattr_trans(struct inode *i
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_trans_handle *trans;
++ const bool start_trans = (current->journal_info == NULL);
+ int ret;
+
+- trans = btrfs_start_transaction(root, 2);
+- if (IS_ERR(trans))
+- return PTR_ERR(trans);
++ if (start_trans) {
++ /*
++ * 1 unit for inserting/updating/deleting the xattr
++ * 1 unit for the inode item update
++ */
++ trans = btrfs_start_transaction(root, 2);
++ if (IS_ERR(trans))
++ return PTR_ERR(trans);
++ } else {
++ /*
++ * This can happen when smack is enabled and a directory is being
++ * created. It happens through d_instantiate_new(), which calls
++ * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
++ * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
++ * inode. We have already reserved space for the xattr and inode
++ * update at btrfs_mkdir(), so just use the transaction handle.
++ * We don't join or start a transaction, as that will reset the
++ * block_rsv of the handle and trigger a warning for the start
++ * case.
++ */
++ ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
++ XATTR_SECURITY_PREFIX_LEN) == 0);
++ trans = current->journal_info;
++ }
+
+ ret = btrfs_setxattr(trans, inode, name, value, size, flags);
+ if (ret)
+@@ -244,7 +266,8 @@ int btrfs_setxattr_trans(struct inode *i
+ ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
+ BUG_ON(ret);
+ out:
+- btrfs_end_transaction(trans);
++ if (start_trans)
++ btrfs_end_transaction(trans);
+ return ret;
+ }
+
--- /dev/null
+From 0f9c03d824f6f522d3bc43629635c9765546ebc5 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Mon, 22 Feb 2021 18:40:42 +0200
+Subject: btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 0f9c03d824f6f522d3bc43629635c9765546ebc5 upstream.
+
+Following commit f218ea6c4792 ("btrfs: delayed-inode: Remove wrong
+qgroup meta reservation calls") this function now reserves num_bytes,
+rather than the fixed amount of nodesize. As such this requires the
+same amount to be freed in case of failure. Fix this by adjusting
+the amount we are freeing.
+
+Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls")
+CC: stable@vger.kernel.org # 4.19+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/delayed-inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -649,7 +649,7 @@ static int btrfs_delayed_inode_reserve_m
+ btrfs_ino(inode),
+ num_bytes, 1);
+ } else {
+- btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize);
++ btrfs_qgroup_free_meta_prealloc(root, num_bytes);
+ }
+ return ret;
+ }
--- /dev/null
+From 1119a72e223f3073a604f8fccb3a470ccd8a4416 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Tue, 16 Feb 2021 15:43:22 -0500
+Subject: btrfs: tree-checker: do not error out if extent ref hash doesn't match
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 1119a72e223f3073a604f8fccb3a470ccd8a4416 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/tree-checker.c | 16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -1453,22 +1453,14 @@ static int check_extent_data_ref(struct
+ return -EUCLEAN;
+ }
+ for (; ptr < end; ptr += sizeof(*dref)) {
+- u64 root_objectid;
+- u64 owner;
+ u64 offset;
+- u64 hash;
+
++ /*
++ * We cannot check the extent_data_ref hash due to possible
++ * overflow from the leaf due to hash collisions.
++ */
+ dref = (struct btrfs_extent_data_ref *)ptr;
+- root_objectid = btrfs_extent_data_ref_root(leaf, dref);
+- owner = btrfs_extent_data_ref_objectid(leaf, dref);
+ offset = btrfs_extent_data_ref_offset(leaf, dref);
+- hash = hash_extent_data_ref(root_objectid, owner, offset);
+- if (unlikely(hash != key->offset)) {
+- extent_err(leaf, slot,
+- "invalid extent data ref hash, item has 0x%016llx key has 0x%016llx",
+- hash, key->offset);
+- return -EUCLEAN;
+- }
+ if (unlikely(!IS_ALIGNED(offset, leaf->fs_info->sectorsize))) {
+ extent_err(leaf, slot,
+ "invalid extent data backref offset, have %llu expect aligned to %u",
--- /dev/null
+From 4f6a49de64fd1b1dba5229c02047376da7cf24fd Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Tue, 23 Feb 2021 15:20:42 +0200
+Subject: btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 4f6a49de64fd1b1dba5229c02047376da7cf24fd upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/file.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -3264,8 +3264,11 @@ reserve_space:
+ goto out;
+ ret = btrfs_qgroup_reserve_data(BTRFS_I(inode), &data_reserved,
+ alloc_start, bytes_to_reserve);
+- if (ret)
++ if (ret) {
++ unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
++ lockend, &cached_state);
+ goto out;
++ }
+ ret = btrfs_prealloc_file_range(inode, mode, alloc_start,
+ alloc_end - alloc_start,
+ i_blocksize(inode),
--- /dev/null
+From 5011c5a663b9c6d6aff3d394f11049b371199627 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dancarpenter@oracle.com>
+Date: Wed, 17 Feb 2021 09:04:34 +0300
+Subject: btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+
+From: Dan Carpenter <dancarpenter@oracle.com>
+
+commit 5011c5a663b9c6d6aff3d394f11049b371199627 upstream.
+
+The problem is we're copying "inherit" from user space but we don't
+necessarily know that we're copying enough data for a 64 byte
+struct. Then the next problem is that 'inherit' has a variable size
+array at the end, and we have to verify that array is the size we
+expected.
+
+Fixes: 6f72c7e20dba ("Btrfs: add qgroup inheritance")
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ioctl.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1926,7 +1926,10 @@ static noinline int btrfs_ioctl_snap_cre
+ if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
+ readonly = true;
+ if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+- if (vol_args->size > PAGE_SIZE) {
++ u64 nums;
++
++ if (vol_args->size < sizeof(*inherit) ||
++ vol_args->size > PAGE_SIZE) {
+ ret = -EINVAL;
+ goto free_args;
+ }
+@@ -1935,6 +1938,20 @@ static noinline int btrfs_ioctl_snap_cre
+ ret = PTR_ERR(inherit);
+ goto free_args;
+ }
++
++ if (inherit->num_qgroups > PAGE_SIZE ||
++ inherit->num_ref_copies > PAGE_SIZE ||
++ inherit->num_excl_copies > PAGE_SIZE) {
++ ret = -EINVAL;
++ goto free_inherit;
++ }
++
++ nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
++ 2 * inherit->num_excl_copies;
++ if (vol_args->size != struct_size(inherit, qgroups, nums)) {
++ ret = -EINVAL;
++ goto free_inherit;
++ }
+ }
+
+ ret = __btrfs_ioctl_snap_create(file, vol_args->name, vol_args->fd,
--- /dev/null
+From a14e5ec66a7a66e57b24e2469f9212a78460207e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 23 Feb 2021 21:21:20 +0100
+Subject: dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit a14e5ec66a7a66e57b24e2469f9212a78460207e upstream.
+
+dm_bufio_get_device_size returns the device size in blocks. Before
+returning the value, we must subtract the nubmer of starting
+sectors. The number of starting sectors may not be divisible by block
+size.
+
+Note that currently, no target is using dm_bufio_set_sector_offset and
+dm_bufio_get_device_size simultaneously, so this change has no effect.
+However, an upcoming dm-verity-fec fix needs this change.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reviewed-by: Milan Broz <gmazyland@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-bufio.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1526,6 +1526,10 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_siz
+ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+ {
+ sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
++ if (s >= c->start)
++ s -= c->start;
++ else
++ s = 0;
+ if (likely(c->sectors_per_block_bits >= 0))
+ s >>= c->sectors_per_block_bits;
+ else
--- /dev/null
+From df7b59ba9245c4a3115ebaa905e3e5719a3810da Mon Sep 17 00:00:00 2001
+From: Milan Broz <gmazyland@gmail.com>
+Date: Tue, 23 Feb 2021 21:21:21 +0100
+Subject: dm verity: fix FEC for RS roots unaligned to block size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Milan Broz <gmazyland@gmail.com>
+
+commit df7b59ba9245c4a3115ebaa905e3e5719a3810da upstream.
+
+Optional Forward Error Correction (FEC) code in dm-verity uses
+Reed-Solomon code and should support roots from 2 to 24.
+
+The error correction parity bytes (of roots lengths per RS block) are
+stored on a separate device in sequence without any padding.
+
+Currently, to access FEC device, the dm-verity-fec code uses dm-bufio
+client with block size set to verity data block (usually 4096 or 512
+bytes).
+
+Because this block size is not divisible by some (most!) of the roots
+supported lengths, data repair cannot work for partially stored parity
+bytes.
+
+This fix changes FEC device dm-bufio block size to "roots << SECTOR_SHIFT"
+where we can be sure that the full parity data is always available.
+(There cannot be partial FEC blocks because parity must cover whole
+sectors.)
+
+Because the optional FEC starting offset could be unaligned to this
+new block size, we have to use dm_bufio_set_sector_offset() to
+configure it.
+
+The problem is easily reproduced using veritysetup, e.g. for roots=13:
+
+ # create verity device with RS FEC
+ dd if=/dev/urandom of=data.img bs=4096 count=8 status=none
+ veritysetup format data.img hash.img --fec-device=fec.img --fec-roots=13 | awk '/^Root hash/{ print $3 }' >roothash
+
+ # create an erasure that should be always repairable with this roots setting
+ dd if=/dev/zero of=data.img conv=notrunc bs=1 count=8 seek=4088 status=none
+
+ # try to read it through dm-verity
+ veritysetup open data.img test hash.img --fec-device=fec.img --fec-roots=13 $(cat roothash)
+ dd if=/dev/mapper/test of=/dev/null bs=4096 status=noxfer
+ # wait for possible recursive recovery in kernel
+ udevadm settle
+ veritysetup close test
+
+With this fix, errors are properly repaired.
+ device-mapper: verity-fec: 7:1: FEC 0: corrected 8 errors
+ ...
+
+Without it, FEC code usually ends on unrecoverable failure in RS decoder:
+ device-mapper: verity-fec: 7:1: FEC 0: failed to correct: -74
+ ...
+
+This problem is present in all kernels since the FEC code's
+introduction (kernel 4.5).
+
+It is thought that this problem is not visible in Android ecosystem
+because it always uses a default RS roots=2.
+
+Depends-on: a14e5ec66a7a ("dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size")
+Signed-off-by: Milan Broz <gmazyland@gmail.com>
+Tested-by: Jérôme Carretero <cJ-ko@zougloub.eu>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Cc: stable@vger.kernel.org # 4.5+
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-verity-fec.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/drivers/md/dm-verity-fec.c
++++ b/drivers/md/dm-verity-fec.c
+@@ -61,19 +61,18 @@ static int fec_decode_rs8(struct dm_veri
+ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
+ unsigned *offset, struct dm_buffer **buf)
+ {
+- u64 position, block;
++ u64 position, block, rem;
+ u8 *res;
+
+ position = (index + rsb) * v->fec->roots;
+- block = position >> v->data_dev_block_bits;
+- *offset = (unsigned)(position - (block << v->data_dev_block_bits));
++ block = div64_u64_rem(position, v->fec->roots << SECTOR_SHIFT, &rem);
++ *offset = (unsigned)rem;
+
+- res = dm_bufio_read(v->fec->bufio, v->fec->start + block, buf);
++ res = dm_bufio_read(v->fec->bufio, block, buf);
+ if (IS_ERR(res)) {
+ DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
+ v->data_dev->name, (unsigned long long)rsb,
+- (unsigned long long)(v->fec->start + block),
+- PTR_ERR(res));
++ (unsigned long long)block, PTR_ERR(res));
+ *buf = NULL;
+ }
+
+@@ -155,7 +154,7 @@ static int fec_decode_bufs(struct dm_ver
+
+ /* read the next block when we run out of parity bytes */
+ offset += v->fec->roots;
+- if (offset >= 1 << v->data_dev_block_bits) {
++ if (offset >= v->fec->roots << SECTOR_SHIFT) {
+ dm_bufio_release(buf);
+
+ par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
+@@ -674,7 +673,7 @@ int verity_fec_ctr(struct dm_verity *v)
+ {
+ struct dm_verity_fec *f = v->fec;
+ struct dm_target *ti = v->ti;
+- u64 hash_blocks;
++ u64 hash_blocks, fec_blocks;
+ int ret;
+
+ if (!verity_fec_is_enabled(v)) {
+@@ -744,15 +743,17 @@ int verity_fec_ctr(struct dm_verity *v)
+ }
+
+ f->bufio = dm_bufio_client_create(f->dev->bdev,
+- 1 << v->data_dev_block_bits,
++ f->roots << SECTOR_SHIFT,
+ 1, 0, NULL, NULL);
+ if (IS_ERR(f->bufio)) {
+ ti->error = "Cannot initialize FEC bufio client";
+ return PTR_ERR(f->bufio);
+ }
+
+- if (dm_bufio_get_device_size(f->bufio) <
+- ((f->start + f->rounds * f->roots) >> v->data_dev_block_bits)) {
++ dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));
++
++ fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
++ if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
+ ti->error = "FEC device is too small";
+ return -E2BIG;
+ }
--- /dev/null
+From 6efda1671312e8432216ee8b106e71fa3102e1d3 Mon Sep 17 00:00:00 2001
+From: Evan Quan <evan.quan@amd.com>
+Date: Fri, 19 Feb 2021 16:18:47 +0800
+Subject: drm/amd/pm: correct Arcturus mmTHM_BACO_CNTL register address
+
+From: Evan Quan <evan.quan@amd.com>
+
+commit 6efda1671312e8432216ee8b106e71fa3102e1d3 upstream.
+
+Arcturus has a different register address from other SMU V11
+ASICs.
+
+Signed-off-by: Evan Quan <evan.quan@amd.com>
+Acked-by: Guchun Chen <guchun.chen@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+@@ -78,6 +78,9 @@ MODULE_FIRMWARE("amdgpu/dimgrey_cavefish
+ #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000
+ #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE
+
++#define mmTHM_BACO_CNTL_ARCT 0xA7
++#define mmTHM_BACO_CNTL_ARCT_BASE_IDX 0
++
+ static int link_width[] = {0, 1, 2, 4, 8, 12, 16};
+ static int link_speed[] = {25, 50, 80, 160};
+
+@@ -1581,9 +1584,15 @@ int smu_v11_0_baco_set_state(struct smu_
+ break;
+ default:
+ if (!ras || !ras->supported) {
+- data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+- data |= 0x80000000;
+- WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
++ if (adev->asic_type == CHIP_ARCTURUS) {
++ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT);
++ data |= 0x80000000;
++ WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT, data);
++ } else {
++ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
++ data |= 0x80000000;
++ WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
++ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
+ } else {
--- /dev/null
+From 0c61ac8134ffc851681ce5d4bd60d97c3d5aed27 Mon Sep 17 00:00:00 2001
+From: "Asher.Song" <Asher.Song@amd.com>
+Date: Wed, 24 Feb 2021 18:41:34 +0800
+Subject: drm/amdgpu:disable VCN for Navi12 SKU
+
+From: Asher.Song <Asher.Song@amd.com>
+
+commit 0c61ac8134ffc851681ce5d4bd60d97c3d5aed27 upstream.
+
+Navi12 0x7360/C7 SKU has no video support, so remove it.
+
+Reviewed-by: Guchun Chen <guchun.chen@amd.com>
+Signed-off-by: Asher.Song <Asher.Song@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/nv.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/nv.c
++++ b/drivers/gpu/drm/amd/amdgpu/nv.c
+@@ -498,7 +498,8 @@ static bool nv_is_headless_sku(struct pc
+ {
+ if ((pdev->device == 0x731E &&
+ (pdev->revision == 0xC6 || pdev->revision == 0xC7)) ||
+- (pdev->device == 0x7340 && pdev->revision == 0xC9))
++ (pdev->device == 0x7340 && pdev->revision == 0xC9) ||
++ (pdev->device == 0x7360 && pdev->revision == 0xC7))
+ return true;
+ return false;
+ }
+@@ -568,7 +569,8 @@ int nv_set_ip_blocks(struct amdgpu_devic
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
+ !amdgpu_sriov_vf(adev))
+ amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
+- amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
++ if (!nv_is_headless_sku(adev->pdev))
++ amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
+ if (!amdgpu_sriov_vf(adev))
+ amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
+ break;
--- /dev/null
+From 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff Mon Sep 17 00:00:00 2001
+From: Kevin Wang <kevin1.wang@amd.com>
+Date: Tue, 2 Mar 2021 15:54:00 +0800
+Subject: drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+
+From: Kevin Wang <kevin1.wang@amd.com>
+
+commit 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff upstream.
+
+the register offset isn't needed division by 4 to pass RREG32_PCIE()
+
+Signed-off-by: Kevin Wang <kevin1.wang@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -356,7 +356,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+ while (size) {
+ uint32_t value;
+
+- value = RREG32_PCIE(*pos >> 2);
++ value = RREG32_PCIE(*pos);
+ r = put_user(value, (uint32_t *)buf);
+ if (r) {
+ pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
+@@ -423,7 +423,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+ return r;
+ }
+
+- WREG32_PCIE(*pos >> 2, value);
++ WREG32_PCIE(*pos, value);
+
+ result += 4;
+ buf += 4;
--- /dev/null
+From 31ada99bdd1b4d6b80462eeb87d383f374409e2a Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 25 Feb 2021 10:21:49 -0500
+Subject: drm/amdgpu: Only check for S0ix if AMD_PMC is configured
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 31ada99bdd1b4d6b80462eeb87d383f374409e2a upstream.
+
+The S0ix check only makes sense if the AMD PMC driver is
+present. We need to use the legacy S3 pathes when the
+PMC driver is not present.
+
+Reviewed-by: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+@@ -903,10 +903,11 @@ void amdgpu_acpi_fini(struct amdgpu_devi
+ */
+ bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
+ {
++#if defined(CONFIG_AMD_PMC)
+ if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
+ if (adev->flags & AMD_IS_APU)
+ return true;
+ }
+-
++#endif
+ return false;
+ }
--- /dev/null
+From 1c3b3e6527e57156bf4082f11c2151957560fe6a Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Sun, 28 Feb 2021 16:07:30 -0700
+Subject: io_uring: ignore double poll add on the same waitqueue head
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit 1c3b3e6527e57156bf4082f11c2151957560fe6a upstream.
+
+syzbot reports a deadlock, attempting to lock the same spinlock twice:
+
+============================================
+WARNING: possible recursive locking detected
+5.11.0-syzkaller #0 Not tainted
+--------------------------------------------
+swapper/1/0 is trying to acquire lock:
+ffff88801b2b1130 (&runtime->sleep){..-.}-{2:2}, at: spin_lock include/linux/spinlock.h:354 [inline]
+ffff88801b2b1130 (&runtime->sleep){..-.}-{2:2}, at: io_poll_double_wake+0x25f/0x6a0 fs/io_uring.c:4960
+
+but task is already holding lock:
+ffff88801b2b3130 (&runtime->sleep){..-.}-{2:2}, at: __wake_up_common_lock+0xb4/0x130 kernel/sched/wait.c:137
+
+other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+ CPU0
+ ----
+ lock(&runtime->sleep);
+ lock(&runtime->sleep);
+
+ *** DEADLOCK ***
+
+ May be due to missing lock nesting notation
+
+2 locks held by swapper/1/0:
+ #0: ffff888147474908 (&group->lock){..-.}-{2:2}, at: _snd_pcm_stream_lock_irqsave+0x9f/0xd0 sound/core/pcm_native.c:170
+ #1: ffff88801b2b3130 (&runtime->sleep){..-.}-{2:2}, at: __wake_up_common_lock+0xb4/0x130 kernel/sched/wait.c:137
+
+stack backtrace:
+CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.11.0-syzkaller #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+Call Trace:
+ <IRQ>
+ __dump_stack lib/dump_stack.c:79 [inline]
+ dump_stack+0xfa/0x151 lib/dump_stack.c:120
+ print_deadlock_bug kernel/locking/lockdep.c:2829 [inline]
+ check_deadlock kernel/locking/lockdep.c:2872 [inline]
+ validate_chain kernel/locking/lockdep.c:3661 [inline]
+ __lock_acquire.cold+0x14c/0x3b4 kernel/locking/lockdep.c:4900
+ lock_acquire kernel/locking/lockdep.c:5510 [inline]
+ lock_acquire+0x1ab/0x730 kernel/locking/lockdep.c:5475
+ __raw_spin_lock include/linux/spinlock_api_smp.h:142 [inline]
+ _raw_spin_lock+0x2a/0x40 kernel/locking/spinlock.c:151
+ spin_lock include/linux/spinlock.h:354 [inline]
+ io_poll_double_wake+0x25f/0x6a0 fs/io_uring.c:4960
+ __wake_up_common+0x147/0x650 kernel/sched/wait.c:108
+ __wake_up_common_lock+0xd0/0x130 kernel/sched/wait.c:138
+ snd_pcm_update_state+0x46a/0x540 sound/core/pcm_lib.c:203
+ snd_pcm_update_hw_ptr0+0xa75/0x1a50 sound/core/pcm_lib.c:464
+ snd_pcm_period_elapsed+0x160/0x250 sound/core/pcm_lib.c:1805
+ dummy_hrtimer_callback+0x94/0x1b0 sound/drivers/dummy.c:378
+ __run_hrtimer kernel/time/hrtimer.c:1519 [inline]
+ __hrtimer_run_queues+0x609/0xe40 kernel/time/hrtimer.c:1583
+ hrtimer_run_softirq+0x17b/0x360 kernel/time/hrtimer.c:1600
+ __do_softirq+0x29b/0x9f6 kernel/softirq.c:345
+ invoke_softirq kernel/softirq.c:221 [inline]
+ __irq_exit_rcu kernel/softirq.c:422 [inline]
+ irq_exit_rcu+0x134/0x200 kernel/softirq.c:434
+ sysvec_apic_timer_interrupt+0x93/0xc0 arch/x86/kernel/apic/apic.c:1100
+ </IRQ>
+ asm_sysvec_apic_timer_interrupt+0x12/0x20 arch/x86/include/asm/idtentry.h:632
+RIP: 0010:native_save_fl arch/x86/include/asm/irqflags.h:29 [inline]
+RIP: 0010:arch_local_save_flags arch/x86/include/asm/irqflags.h:70 [inline]
+RIP: 0010:arch_irqs_disabled arch/x86/include/asm/irqflags.h:137 [inline]
+RIP: 0010:acpi_safe_halt drivers/acpi/processor_idle.c:111 [inline]
+RIP: 0010:acpi_idle_do_entry+0x1c9/0x250 drivers/acpi/processor_idle.c:516
+Code: dd 38 6e f8 84 db 75 ac e8 54 32 6e f8 e8 0f 1c 74 f8 e9 0c 00 00 00 e8 45 32 6e f8 0f 00 2d 4e 4a c5 00 e8 39 32 6e f8 fb f4 <9c> 5b 81 e3 00 02 00 00 fa 31 ff 48 89 de e8 14 3a 6e f8 48 85 db
+RSP: 0018:ffffc90000d47d18 EFLAGS: 00000293
+RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
+RDX: ffff8880115c3780 RSI: ffffffff89052537 RDI: 0000000000000000
+RBP: ffff888141127064 R08: 0000000000000001 R09: 0000000000000001
+R10: ffffffff81794168 R11: 0000000000000000 R12: 0000000000000001
+R13: ffff888141127000 R14: ffff888141127064 R15: ffff888143331804
+ acpi_idle_enter+0x361/0x500 drivers/acpi/processor_idle.c:647
+ cpuidle_enter_state+0x1b1/0xc80 drivers/cpuidle/cpuidle.c:237
+ cpuidle_enter+0x4a/0xa0 drivers/cpuidle/cpuidle.c:351
+ call_cpuidle kernel/sched/idle.c:158 [inline]
+ cpuidle_idle_call kernel/sched/idle.c:239 [inline]
+ do_idle+0x3e1/0x590 kernel/sched/idle.c:300
+ cpu_startup_entry+0x14/0x20 kernel/sched/idle.c:397
+ start_secondary+0x274/0x350 arch/x86/kernel/smpboot.c:272
+ secondary_startup_64_no_verify+0xb0/0xbb
+
+which is due to the driver doing poll_wait() twice on the same
+wait_queue_head. That is perfectly valid, but from checking the rest
+of the kernel tree, it's the only driver that does this.
+
+We can handle this just fine, we just need to ignore the second addition
+as we'll get woken just fine on the first one.
+
+Cc: stable@vger.kernel.org # 5.8+
+Fixes: 18bceab101ad ("io_uring: allow POLL_ADD with double poll_wait() users")
+Reported-by: syzbot+28abd693db9e92c160d8@syzkaller.appspotmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -5316,6 +5316,9 @@ static void __io_queue_proc(struct io_po
+ pt->error = -EINVAL;
+ return;
+ }
++ /* double add on the same waitqueue head, ignore */
++ if (poll->head == head)
++ return;
+ poll = kmalloc(sizeof(*poll), GFP_ATOMIC);
+ if (!poll) {
+ pt->error = -ENOMEM;
--- /dev/null
+From 44cc89f764646b2f1f2ea5d1a08b230131707851 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 25 Feb 2021 19:23:27 +0100
+Subject: PM: runtime: Update device status before letting suppliers suspend
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 44cc89f764646b2f1f2ea5d1a08b230131707851 upstream.
+
+Because the PM-runtime status of the device is not updated in
+__rpm_callback(), attempts to suspend the suppliers of the given
+device triggered by rpm_put_suppliers() called by it may fail.
+
+Fix this by making __rpm_callback() update the device's status to
+RPM_SUSPENDED before calling rpm_put_suppliers() if the current
+status of the device is RPM_SUSPENDING and the callback just invoked
+by it has returned 0 (success).
+
+While at it, modify the code in __rpm_callback() to always check
+the device's PM-runtime status under its PM lock.
+
+Link: https://lore.kernel.org/linux-pm/CAPDyKFqm06KDw_p8WXsM4dijDbho4bb6T4k50UqqvR1_COsp8g@mail.gmail.com/
+Fixes: 21d5c57b3726 ("PM / runtime: Use device links")
+Reported-by: Elaine Zhang <zhangqing@rock-chips.com>
+Diagnosed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Tested-by: Elaine Zhang <zhangiqng@rock-chips.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/power/runtime.c | 62 +++++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 25 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct dev
+ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+ __releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+- int retval, idx;
+ bool use_links = dev->power.links_count > 0;
++ bool get = false;
++ int retval, idx;
++ bool put;
+
+ if (dev->power.irq_safe) {
+ spin_unlock(&dev->power.lock);
++ } else if (!use_links) {
++ spin_unlock_irq(&dev->power.lock);
+ } else {
++ get = dev->power.runtime_status == RPM_RESUMING;
++
+ spin_unlock_irq(&dev->power.lock);
+
+- /*
+- * Resume suppliers if necessary.
+- *
+- * The device's runtime PM status cannot change until this
+- * routine returns, so it is safe to read the status outside of
+- * the lock.
+- */
+- if (use_links && dev->power.runtime_status == RPM_RESUMING) {
++ /* Resume suppliers if necessary. */
++ if (get) {
+ idx = device_links_read_lock();
+
+ retval = rpm_get_suppliers(dev);
+@@ -355,24 +355,36 @@ static int __rpm_callback(int (*cb)(stru
+
+ if (dev->power.irq_safe) {
+ spin_lock(&dev->power.lock);
+- } else {
+- /*
+- * If the device is suspending and the callback has returned
+- * success, drop the usage counters of the suppliers that have
+- * been reference counted on its resume.
+- *
+- * Do that if resume fails too.
+- */
+- if (use_links
+- && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
+- || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+- idx = device_links_read_lock();
++ return retval;
++ }
+
+- fail:
+- rpm_put_suppliers(dev);
++ spin_lock_irq(&dev->power.lock);
+
+- device_links_read_unlock(idx);
+- }
++ if (!use_links)
++ return retval;
++
++ /*
++ * If the device is suspending and the callback has returned success,
++ * drop the usage counters of the suppliers that have been reference
++ * counted on its resume.
++ *
++ * Do that if the resume fails too.
++ */
++ put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
++ if (put)
++ __update_runtime_status(dev, RPM_SUSPENDED);
++ else
++ put = get && retval;
++
++ if (put) {
++ spin_unlock_irq(&dev->power.lock);
++
++ idx = device_links_read_lock();
++
++fail:
++ rpm_put_suppliers(dev);
++
++ device_links_read_unlock(idx);
+
+ spin_lock_irq(&dev->power.lock);
+ }
--- /dev/null
+From 6f6be606e763f2da9fc21de00538c97fe4ca1492 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
+Date: Wed, 3 Mar 2021 18:03:52 -0500
+Subject: ring-buffer: Force before_stamp and write_stamp to be different on discard
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+commit 6f6be606e763f2da9fc21de00538c97fe4ca1492 upstream.
+
+Part of the logic of the new time stamp code depends on the before_stamp and
+the write_stamp to be different if the write_stamp does not match the last
+event on the buffer, as it will be used to calculate the delta of the next
+event written on the buffer.
+
+The discard logic depends on this, as the next event to come in needs to
+inject a full timestamp as it can not rely on the last event timestamp in
+the buffer because it is unknown due to events after it being discarded. But
+by changing the write_stamp back to the time before it, it forces the next
+event to use a full time stamp, instead of relying on it.
+
+The issue came when a full time stamp was used for the event, and
+rb_time_delta() returns zero in that case. The update to the write_stamp
+(which subtracts delta) made it not change. Then when the event is removed
+from the buffer, because the before_stamp and write_stamp still match, the
+next event written would calculate its delta from the write_stamp, but that
+would be wrong as the write_stamp is of the time of the event that was
+discarded.
+
+In the case that the delta change being made to write_stamp is zero, set the
+before_stamp to zero as well, and this will force the next event to inject a
+full timestamp and not use the current write_stamp.
+
+Cc: stable@vger.kernel.org
+Fixes: a389d86f7fd09 ("ring-buffer: Have nested events still record running time stamp")
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ring_buffer.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -2822,6 +2822,17 @@ rb_try_to_discard(struct ring_buffer_per
+ return 0;
+
+ /*
++ * It's possible that the event time delta is zero
++ * (has the same time stamp as the previous event)
++ * in which case write_stamp and before_stamp could
++ * be the same. In such a case, force before_stamp
++ * to be different than write_stamp. It doesn't
++ * matter what it is, as long as its different.
++ */
++ if (!delta)
++ rb_time_set(&cpu_buffer->before_stamp, 0);
++
++ /*
+ * If an event were to come in now, it would see that the
+ * write_stamp and the before_stamp are different, and assume
+ * that this event just added itself before updating
btrfs-fix-race-between-extent-freeing-allocation-when-using-bitmaps.patch
btrfs-validate-qgroup-inherit-for-snap_create_v2-ioctl.patch
btrfs-free-correct-amount-of-space-in-btrfs_delayed_inode_reserve_metadata.patch
-btrfs-don-t-flush-from-btrfs_delayed_inode_reserve_metadata.patch
btrfs-fix-spurious-free_space_tree-remount-warning.patch
btrfs-unlock-extents-in-btrfs_zero_range-in-case-of-quota-reservation-errors.patch
btrfs-fix-warning-when-creating-a-directory-with-smack-enabled.patch
--- /dev/null
+From a5665ec2affdba21bff3b0d4d3aed83b3951e8ff Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Sat, 20 Feb 2021 00:55:59 +0200
+Subject: tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit a5665ec2affdba21bff3b0d4d3aed83b3951e8ff upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[ 4.324298] TPM returned invalid status
+[ 4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_get_timeouts() with request_locality() and release_locality().
+
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: stable@vger.kernel.org
+Reported-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -1029,11 +1029,21 @@ int tpm_tis_core_init(struct device *dev
+ init_waitqueue_head(&priv->read_queue);
+ init_waitqueue_head(&priv->int_queue);
+ if (irq != -1) {
+- /* Before doing irq testing issue a command to the TPM in polling mode
++ /*
++ * Before doing irq testing issue a command to the TPM in polling mode
+ * to make sure it works. May as well use that command to set the
+ * proper timeouts for the driver.
+ */
+- if (tpm_get_timeouts(chip)) {
++
++ rc = request_locality(chip, 0);
++ if (rc < 0)
++ goto out_err;
++
++ rc = tpm_get_timeouts(chip);
++
++ release_locality(chip, 0);
++
++ if (rc) {
+ dev_err(dev, "Could not get TPM timeouts and durations\n");
+ rc = -ENODEV;
+ goto out_err;
--- /dev/null
+From d53a6adfb553969809eb2b736a976ebb5146cd95 Mon Sep 17 00:00:00 2001
+From: Lukasz Majczak <lma@semihalf.com>
+Date: Tue, 16 Feb 2021 10:17:49 +0200
+Subject: tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+
+From: Lukasz Majczak <lma@semihalf.com>
+
+commit d53a6adfb553969809eb2b736a976ebb5146cd95 upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[ 4.324298] TPM returned invalid status
+[ 4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_tis_gen_interrupt() with request_locality() and
+release_locality().
+
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: stable@vger.kernel.org
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Signed-off-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -707,12 +707,22 @@ static int tpm_tis_gen_interrupt(struct
+ const char *desc = "attempting to generate an interrupt";
+ u32 cap2;
+ cap_t cap;
++ int ret;
+
++ /* TPM 2.0 */
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
+- else
+- return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
+- 0);
++
++ /* TPM 1.2 */
++ ret = request_locality(chip, 0);
++ if (ret < 0)
++ return ret;
++
++ ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
++
++ release_locality(chip, 0);
++
++ return ret;
+ }
+
+ /* Register the IRQ and issue a command that will cause an interrupt. If an