From c78346ee56f97b53a27dc1245c381905097c5fc1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 3 Oct 2020 19:25:57 +0200 Subject: [PATCH] 5.4-stable patches added patches: btrfs-fix-filesystem-corruption-after-a-device-replace.patch mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch --- ...em-corruption-after-a-device-replace.patch | 173 ++++++++++++++++++ ...uing-on-intel-glk-based-irbis-models.patch | 43 +++++ queue-5.4/series | 2 + 3 files changed, 218 insertions(+) create mode 100644 queue-5.4/btrfs-fix-filesystem-corruption-after-a-device-replace.patch create mode 100644 queue-5.4/mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch diff --git a/queue-5.4/btrfs-fix-filesystem-corruption-after-a-device-replace.patch b/queue-5.4/btrfs-fix-filesystem-corruption-after-a-device-replace.patch new file mode 100644 index 00000000000..2bbde445873 --- /dev/null +++ b/queue-5.4/btrfs-fix-filesystem-corruption-after-a-device-replace.patch @@ -0,0 +1,173 @@ +From 4c8f353272dd1262013873990c0fafd0e3c8f274 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 23 Sep 2020 15:30:16 +0100 +Subject: btrfs: fix filesystem corruption after a device replace + +From: Filipe Manana + +commit 4c8f353272dd1262013873990c0fafd0e3c8f274 upstream. + +We use a device's allocation state tree to track ranges in a device used +for allocated chunks, and we set ranges in this tree when allocating a new +chunk. However after a device replace operation, we were not setting the +allocated ranges in the new device's allocation state tree, so that tree +is empty after a device replace. + +This means that a fitrim operation after a device replace will trim the +device ranges that have allocated chunks and extents, as we trim every +range for which there is not a range marked in the device's allocation +state tree. It is also important during chunk allocation, since the +device's allocation state is used to determine if a range is already +allocated when allocating a new chunk. + +This is trivial to reproduce and the following script triggers the bug: + + $ cat reproducer.sh + #!/bin/bash + + DEV1="/dev/sdg" + DEV2="/dev/sdh" + DEV3="/dev/sdi" + + wipefs -a $DEV1 $DEV2 $DEV3 &> /dev/null + + # Create a raid1 test fs on 2 devices. + mkfs.btrfs -f -m raid1 -d raid1 $DEV1 $DEV2 > /dev/null + mount $DEV1 /mnt/btrfs + + xfs_io -f -c "pwrite -S 0xab 0 10M" /mnt/btrfs/foo + + echo "Starting to replace $DEV1 with $DEV3" + btrfs replace start -B $DEV1 $DEV3 /mnt/btrfs + echo + + echo "Running fstrim" + fstrim /mnt/btrfs + echo + + echo "Unmounting filesystem" + umount /mnt/btrfs + + echo "Mounting filesystem in degraded mode using $DEV3 only" + wipefs -a $DEV1 $DEV2 &> /dev/null + mount -o degraded $DEV3 /mnt/btrfs + if [ $? -ne 0 ]; then + dmesg | tail + echo + echo "Failed to mount in degraded mode" + exit 1 + fi + + echo + echo "File foo data (expected all bytes = 0xab):" + od -A d -t x1 /mnt/btrfs/foo + + umount /mnt/btrfs + +When running the reproducer: + + $ ./replace-test.sh + wrote 10485760/10485760 bytes at offset 0 + 10 MiB, 2560 ops; 0.0901 sec (110.877 MiB/sec and 28384.5216 ops/sec) + Starting to replace /dev/sdg with /dev/sdi + + Running fstrim + + Unmounting filesystem + Mounting filesystem in degraded mode using /dev/sdi only + mount: /mnt/btrfs: wrong fs type, bad option, bad superblock on /dev/sdi, missing codepage or helper program, or other error. + [19581.748641] BTRFS info (device sdg): dev_replace from /dev/sdg (devid 1) to /dev/sdi started + [19581.803842] BTRFS info (device sdg): dev_replace from /dev/sdg (devid 1) to /dev/sdi finished + [19582.208293] BTRFS info (device sdi): allowing degraded mounts + [19582.208298] BTRFS info (device sdi): disk space caching is enabled + [19582.208301] BTRFS info (device sdi): has skinny extents + [19582.212853] BTRFS warning (device sdi): devid 2 uuid 1f731f47-e1bb-4f00-bfbb-9e5a0cb4ba9f is missing + [19582.213904] btree_readpage_end_io_hook: 25839 callbacks suppressed + [19582.213907] BTRFS error (device sdi): bad tree block start, want 30490624 have 0 + [19582.214780] BTRFS warning (device sdi): failed to read root (objectid=7): -5 + [19582.231576] BTRFS error (device sdi): open_ctree failed + + Failed to mount in degraded mode + +So fix by setting all allocated ranges in the replace target device when +the replace operation is finishing, when we are holding the chunk mutex +and we can not race with new chunk allocations. + +A test case for fstests follows soon. + +Fixes: 1c11b63eff2a67 ("btrfs: replace pending/pinned chunks lists with io tree") +CC: stable@vger.kernel.org # 5.2+ +Reviewed-by: Nikolay Borisov +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/dev-replace.c | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -562,6 +562,37 @@ static void btrfs_rm_dev_replace_unblock + wake_up(&fs_info->dev_replace.replace_wait); + } + ++/* ++ * When finishing the device replace, before swapping the source device with the ++ * target device we must update the chunk allocation state in the target device, ++ * as it is empty because replace works by directly copying the chunks and not ++ * through the normal chunk allocation path. ++ */ ++static int btrfs_set_target_alloc_state(struct btrfs_device *srcdev, ++ struct btrfs_device *tgtdev) ++{ ++ struct extent_state *cached_state = NULL; ++ u64 start = 0; ++ u64 found_start; ++ u64 found_end; ++ int ret = 0; ++ ++ lockdep_assert_held(&srcdev->fs_info->chunk_mutex); ++ ++ while (!find_first_extent_bit(&srcdev->alloc_state, start, ++ &found_start, &found_end, ++ CHUNK_ALLOCATED, &cached_state)) { ++ ret = set_extent_bits(&tgtdev->alloc_state, found_start, ++ found_end, CHUNK_ALLOCATED); ++ if (ret) ++ break; ++ start = found_end + 1; ++ } ++ ++ free_extent_state(cached_state); ++ return ret; ++} ++ + static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, + int scrub_ret) + { +@@ -636,8 +667,14 @@ static int btrfs_dev_replace_finishing(s + dev_replace->time_stopped = ktime_get_real_seconds(); + dev_replace->item_needs_writeback = 1; + +- /* replace old device with new one in mapping tree */ ++ /* ++ * Update allocation state in the new device and replace the old device ++ * with the new one in the mapping tree. ++ */ + if (!scrub_ret) { ++ scrub_ret = btrfs_set_target_alloc_state(src_device, tgt_device); ++ if (scrub_ret) ++ goto error; + btrfs_dev_replace_update_device_in_mapping_tree(fs_info, + src_device, + tgt_device); +@@ -648,6 +685,7 @@ static int btrfs_dev_replace_finishing(s + btrfs_dev_name(src_device), + src_device->devid, + rcu_str_deref(tgt_device->name), scrub_ret); ++error: + up_write(&dev_replace->rwsem); + mutex_unlock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); diff --git a/queue-5.4/mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch b/queue-5.4/mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch new file mode 100644 index 00000000000..5d0616001af --- /dev/null +++ b/queue-5.4/mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch @@ -0,0 +1,43 @@ +From afd7f30886b0b445a4240a99020458a9772f2b89 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 27 Sep 2020 12:48:21 +0200 +Subject: mmc: sdhci: Workaround broken command queuing on Intel GLK based IRBIS models + +From: Hans de Goede + +commit afd7f30886b0b445a4240a99020458a9772f2b89 upstream. + +Commit bedf9fc01ff1 ("mmc: sdhci: Workaround broken command queuing on +Intel GLK"), disabled command-queuing on Intel GLK based LENOVO models +because of it being broken due to what is believed to be a bug in +the BIOS. + +It seems that the BIOS of some IRBIS models, including the IRBIS NB111 +model has the same issue, so disable command queuing there too. + +Fixes: bedf9fc01ff1 ("mmc: sdhci: Workaround broken command queuing on Intel GLK") +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=209397 +Reported-and-tested-by: RussianNeuroMancer +Signed-off-by: Hans de Goede +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20200927104821.5676-1-hdegoede@redhat.com +Cc: stable@vger.kernel.org +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/sdhci-pci-core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -798,7 +798,8 @@ static int byt_emmc_probe_slot(struct sd + static bool glk_broken_cqhci(struct sdhci_pci_slot *slot) + { + return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC && +- dmi_match(DMI_BIOS_VENDOR, "LENOVO"); ++ (dmi_match(DMI_BIOS_VENDOR, "LENOVO") || ++ dmi_match(DMI_SYS_VENDOR, "IRBIS")); + } + + static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) diff --git a/queue-5.4/series b/queue-5.4/series index fa71c184fc5..69a677ee902 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -1,3 +1,5 @@ +btrfs-fix-filesystem-corruption-after-a-device-replace.patch +mmc-sdhci-workaround-broken-command-queuing-on-intel-glk-based-irbis-models.patch vsock-virtio-add-transport-parameter-to-the-virtio_t.patch net-virtio_vsock-enhance-connection-semantics.patch xfs-trim-io-to-found-cow-extent-limit.patch -- 2.47.3