From a3c84f47c5b76ba6cfbef64b32f1be21cef30b8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 15 Dec 2019 13:12:26 +0100 Subject: [PATCH] 4.9-stable patches added patches: btrfs-check-page-mapping-when-loading-free-space-cache.patch btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch btrfs-remove-btrfs_bio-flags-member.patch btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch lib-raid6-fix-awk-build-warnings.patch mtd-spear_smi-fix-write-burst-mode.patch rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch usb-core-urb-fix-urb-structure-initialization-function.patch usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch --- ...fix-pending-unsol-events-at-shutdown.patch | 13 +- ...apping-when-loading-free-space-cache.patch | 76 +++++++++ ...oots-for-rename-exchange-on-a-subvol.patch | 43 +++++ .../btrfs-remove-btrfs_bio-flags-member.patch | 36 ++++ ...ing-for-extents-with-many-references.patch | 89 ++++++++++ .../lib-raid6-fix-awk-build-warnings.patch | 38 +++++ .../mtd-spear_smi-fix-write-burst-mode.patch | 107 ++++++++++++ ...-that-tests-for-hw-release-of-buffer.patch | 72 ++++++++ ...g-code-to-retrieve-rx-buffer-address.patch | 46 +++++ ...de-fix-missing-enable-interrupt-flag.patch | 67 ++++++++ queue-4.9/series | 14 ++ ...rb-structure-initialization-function.patch | 34 ++++ ...lock-in-usbmon-between-mmap-and-read.patch | 104 ++++++++++++ ...s-when-migrating-pages-between-zones.patch | 159 ++++++++++++++++++ ...e-fix-pwq-ref-leak-in-rescuer_thread.patch | 60 +++++++ ...-check-failures-in-destroy_workqueue.patch | 83 +++++++++ 16 files changed, 1031 insertions(+), 10 deletions(-) create mode 100644 queue-4.9/btrfs-check-page-mapping-when-loading-free-space-cache.patch create mode 100644 queue-4.9/btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch create mode 100644 queue-4.9/btrfs-remove-btrfs_bio-flags-member.patch create mode 100644 queue-4.9/btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch create mode 100644 queue-4.9/lib-raid6-fix-awk-build-warnings.patch create mode 100644 queue-4.9/mtd-spear_smi-fix-write-burst-mode.patch create mode 100644 queue-4.9/rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch create mode 100644 queue-4.9/rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch create mode 100644 queue-4.9/rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch create mode 100644 queue-4.9/usb-core-urb-fix-urb-structure-initialization-function.patch create mode 100644 queue-4.9/usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch create mode 100644 queue-4.9/virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch create mode 100644 queue-4.9/workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch create mode 100644 queue-4.9/workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch diff --git a/queue-4.9/alsa-hda-fix-pending-unsol-events-at-shutdown.patch b/queue-4.9/alsa-hda-fix-pending-unsol-events-at-shutdown.patch index e1870e0f9ca..d515d6e8f39 100644 --- a/queue-4.9/alsa-hda-fix-pending-unsol-events-at-shutdown.patch +++ b/queue-4.9/alsa-hda-fix-pending-unsol-events-at-shutdown.patch @@ -21,15 +21,13 @@ Link: https://lore.kernel.org/r/s5h1ruxt9cz.wl-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- - sound/pci/hda/hda_bind.c | 4 ++++ - sound/pci/hda/hda_intel.c | 3 +++ + sound/pci/hda/hda_bind.c | 4 ++++ + sound/pci/hda/hda_intel.c | 3 +++ 2 files changed, 7 insertions(+) -diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c -index 7ea201c05e5da..d0d6dfbfcfdf8 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c -@@ -42,6 +42,10 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) +@@ -42,6 +42,10 @@ static void hda_codec_unsol_event(struct { struct hda_codec *codec = container_of(dev, struct hda_codec, core); @@ -40,8 +38,6 @@ index 7ea201c05e5da..d0d6dfbfcfdf8 100644 if (codec->patch_ops.unsol_event) codec->patch_ops.unsol_event(codec, ev); } -diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c -index f2f1d9fd848c8..3234e9ca02cec 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1275,8 +1275,11 @@ static int azx_free(struct azx *chip) @@ -56,6 +52,3 @@ index f2f1d9fd848c8..3234e9ca02cec 100644 return 0; } --- -2.20.1 - diff --git a/queue-4.9/btrfs-check-page-mapping-when-loading-free-space-cache.patch b/queue-4.9/btrfs-check-page-mapping-when-loading-free-space-cache.patch new file mode 100644 index 00000000000..7d955eed234 --- /dev/null +++ b/queue-4.9/btrfs-check-page-mapping-when-loading-free-space-cache.patch @@ -0,0 +1,76 @@ +From 3797136b626ad4b6582223660c041efdea8f26b2 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Tue, 24 Sep 2019 16:50:43 -0400 +Subject: btrfs: check page->mapping when loading free space cache + +From: Josef Bacik + +commit 3797136b626ad4b6582223660c041efdea8f26b2 upstream. + +While testing 5.2 we ran into the following panic + +[52238.017028] BUG: kernel NULL pointer dereference, address: 0000000000000001 +[52238.105608] RIP: 0010:drop_buffers+0x3d/0x150 +[52238.304051] Call Trace: +[52238.308958] try_to_free_buffers+0x15b/0x1b0 +[52238.317503] shrink_page_list+0x1164/0x1780 +[52238.325877] shrink_inactive_list+0x18f/0x3b0 +[52238.334596] shrink_node_memcg+0x23e/0x7d0 +[52238.342790] ? do_shrink_slab+0x4f/0x290 +[52238.350648] shrink_node+0xce/0x4a0 +[52238.357628] balance_pgdat+0x2c7/0x510 +[52238.365135] kswapd+0x216/0x3e0 +[52238.371425] ? wait_woken+0x80/0x80 +[52238.378412] ? balance_pgdat+0x510/0x510 +[52238.386265] kthread+0x111/0x130 +[52238.392727] ? kthread_create_on_node+0x60/0x60 +[52238.401782] ret_from_fork+0x1f/0x30 + +The page we were trying to drop had a page->private, but had no +page->mapping and so called drop_buffers, assuming that we had a +buffer_head on the page, and then panic'ed trying to deref 1, which is +our page->private for data pages. + +This is happening because we're truncating the free space cache while +we're trying to load the free space cache. This isn't supposed to +happen, and I'll fix that in a followup patch. However we still +shouldn't allow those sort of mistakes to result in messing with pages +that do not belong to us. So add the page->mapping check to verify that +we still own this page after dropping and re-acquiring the page lock. + +This page being unlocked as: +btrfs_readpage + extent_read_full_page + __extent_read_full_page + __do_readpage + if (!nr) + unlock_page <-- nr can be 0 only if submit_extent_page + returns an error + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +[ add callchain ] +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/free-space-cache.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -391,6 +391,12 @@ static int io_ctl_prepare_pages(struct b + if (uptodate && !PageUptodate(page)) { + btrfs_readpage(NULL, page); + lock_page(page); ++ if (page->mapping != inode->i_mapping) { ++ btrfs_err(BTRFS_I(inode)->root->fs_info, ++ "free space cache page truncated"); ++ io_ctl_drop_pages(io_ctl); ++ return -EIO; ++ } + if (!PageUptodate(page)) { + btrfs_err(BTRFS_I(inode)->root->fs_info, + "error reading free space cache"); diff --git a/queue-4.9/btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch b/queue-4.9/btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch new file mode 100644 index 00000000000..b485fd2cb05 --- /dev/null +++ b/queue-4.9/btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch @@ -0,0 +1,43 @@ +From 3e1740993e43116b3bc71b0aad1e6872f6ccf341 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 15 Nov 2019 15:43:06 -0500 +Subject: btrfs: record all roots for rename exchange on a subvol + +From: Josef Bacik + +commit 3e1740993e43116b3bc71b0aad1e6872f6ccf341 upstream. + +Testing with the new fsstress support for subvolumes uncovered a pretty +bad problem with rename exchange on subvolumes. We're modifying two +different subvolumes, but we only start the transaction on one of them, +so the other one is not added to the dirty root list. This is caught by +btrfs_cow_block() with a warning because the root has not been updated, +however if we do not modify this root again we'll end up pointing at an +invalid root because the root item is never updated. + +Fix this by making sure we add the destination root to the trans list, +the same as we do with normal renames. This fixes the corruption. + +Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT") +CC: stable@vger.kernel.org # 4.9+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -9616,6 +9616,9 @@ static int btrfs_rename_exchange(struct + goto out_notrans; + } + ++ if (dest != root) ++ btrfs_record_root_in_trans(trans, dest); ++ + /* + * We need to find a free sequence number both in the source and + * in the destination directory for the exchange. diff --git a/queue-4.9/btrfs-remove-btrfs_bio-flags-member.patch b/queue-4.9/btrfs-remove-btrfs_bio-flags-member.patch new file mode 100644 index 00000000000..4831f25c31b --- /dev/null +++ b/queue-4.9/btrfs-remove-btrfs_bio-flags-member.patch @@ -0,0 +1,36 @@ +From 34b127aecd4fe8e6a3903e10f204a7b7ffddca22 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Thu, 24 Oct 2019 09:38:29 +0800 +Subject: btrfs: Remove btrfs_bio::flags member + +From: Qu Wenruo + +commit 34b127aecd4fe8e6a3903e10f204a7b7ffddca22 upstream. + +The last user of btrfs_bio::flags was removed in commit 326e1dbb5736 +("block: remove management of bi_remaining when restoring original +bi_end_io"), remove it. + +(Tagged for stable as the structure is heavily used and space savings +are desirable.) + +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.h | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -312,7 +312,6 @@ struct btrfs_bio { + u64 map_type; /* get from map_lookup->type */ + bio_end_io_t *end_io; + struct bio *orig_bio; +- unsigned long flags; + void *private; + atomic_t error; + int max_errors; diff --git a/queue-4.9/btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch b/queue-4.9/btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch new file mode 100644 index 00000000000..596af9f3cfa --- /dev/null +++ b/queue-4.9/btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch @@ -0,0 +1,89 @@ +From fd0ddbe2509568b00df364156f47561e9f469f15 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 30 Oct 2019 12:23:01 +0000 +Subject: Btrfs: send, skip backreference walking for extents with many references + +From: Filipe Manana + +commit fd0ddbe2509568b00df364156f47561e9f469f15 upstream. + +Backreference walking, which is used by send to figure if it can issue +clone operations instead of write operations, can be very slow and use +too much memory when extents have many references. This change simply +skips backreference walking when an extent has more than 64 references, +in which case we fallback to a write operation instead of a clone +operation. This limit is conservative and in practice I observed no +signicant slowdown with up to 100 references and still low memory usage +up to that limit. + +This is a temporary workaround until there are speedups in the backref +walking code, and as such it does not attempt to add extra interfaces or +knobs to tweak the threshold. + +Reported-by: Atemu +Link: https://lore.kernel.org/linux-btrfs/CAE4GHgkvqVADtS4AzcQJxo0Q1jKQgKaW3JGp3SGdoinVo=C9eQ@mail.gmail.com/T/#me55dc0987f9cc2acaa54372ce0492c65782be3fa +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Qu Wenruo +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -37,6 +37,14 @@ + #include "compression.h" + + /* ++ * Maximum number of references an extent can have in order for us to attempt to ++ * issue clone operations instead of write operations. This currently exists to ++ * avoid hitting limitations of the backreference walking code (taking a lot of ++ * time and using too much memory for extents with large number of references). ++ */ ++#define SEND_MAX_EXTENT_REFS 64 ++ ++/* + * A fs_path is a helper to dynamically build path names with unknown size. + * It reallocates the internal buffer on demand. + * It allows fast adding of path elements on the right side (normal path) and +@@ -1327,6 +1335,7 @@ static int find_extent_clone(struct send + struct clone_root *cur_clone_root; + struct btrfs_key found_key; + struct btrfs_path *tmp_path; ++ struct btrfs_extent_item *ei; + int compressed; + u32 i; + +@@ -1376,7 +1385,6 @@ static int find_extent_clone(struct send + ret = extent_from_logical(fs_info, disk_byte, tmp_path, + &found_key, &flags); + up_read(&fs_info->commit_root_sem); +- btrfs_release_path(tmp_path); + + if (ret < 0) + goto out; +@@ -1385,6 +1393,21 @@ static int find_extent_clone(struct send + goto out; + } + ++ ei = btrfs_item_ptr(tmp_path->nodes[0], tmp_path->slots[0], ++ struct btrfs_extent_item); ++ /* ++ * Backreference walking (iterate_extent_inodes() below) is currently ++ * too expensive when an extent has a large number of references, both ++ * in time spent and used memory. So for now just fallback to write ++ * operations instead of clone operations when an extent has more than ++ * a certain amount of references. ++ */ ++ if (btrfs_extent_refs(tmp_path->nodes[0], ei) > SEND_MAX_EXTENT_REFS) { ++ ret = -ENOENT; ++ goto out; ++ } ++ btrfs_release_path(tmp_path); ++ + /* + * Setup the clone roots. + */ diff --git a/queue-4.9/lib-raid6-fix-awk-build-warnings.patch b/queue-4.9/lib-raid6-fix-awk-build-warnings.patch new file mode 100644 index 00000000000..009d71d6d9b --- /dev/null +++ b/queue-4.9/lib-raid6-fix-awk-build-warnings.patch @@ -0,0 +1,38 @@ +From 702600eef73033ddd4eafcefcbb6560f3e3a90f7 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 6 Dec 2019 16:26:00 +0100 +Subject: lib: raid6: fix awk build warnings + +From: Greg Kroah-Hartman + +commit 702600eef73033ddd4eafcefcbb6560f3e3a90f7 upstream. + +Newer versions of awk spit out these fun warnings: + awk: ../lib/raid6/unroll.awk:16: warning: regexp escape sequence `\#' is not a known regexp operator + +As commit 700c1018b86d ("x86/insn: Fix awk regexp warnings") showed, it +turns out that there are a number of awk strings that do not need to be +escaped and newer versions of awk now warn about this. + +Fix the string up so that no warning is produced. The exact same kernel +module gets created before and after this patch, showing that it wasn't +needed. + +Link: https://lore.kernel.org/r/20191206152600.GA75093@kroah.com +Signed-off-by: Greg Kroah-Hartman + +--- + lib/raid6/unroll.awk | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/lib/raid6/unroll.awk ++++ b/lib/raid6/unroll.awk +@@ -13,7 +13,7 @@ BEGIN { + for (i = 0; i < rep; ++i) { + tmp = $0 + gsub(/\$\$/, i, tmp) +- gsub(/\$\#/, n, tmp) ++ gsub(/\$#/, n, tmp) + gsub(/\$\*/, "$", tmp) + print tmp + } diff --git a/queue-4.9/mtd-spear_smi-fix-write-burst-mode.patch b/queue-4.9/mtd-spear_smi-fix-write-burst-mode.patch new file mode 100644 index 00000000000..12e89aecd95 --- /dev/null +++ b/queue-4.9/mtd-spear_smi-fix-write-burst-mode.patch @@ -0,0 +1,107 @@ +From 69c7f4618c16b4678f8a4949b6bb5ace259c0033 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 22 Oct 2019 16:58:59 +0200 +Subject: mtd: spear_smi: Fix Write Burst mode + +From: Miquel Raynal + +commit 69c7f4618c16b4678f8a4949b6bb5ace259c0033 upstream. + +Any write with either dd or flashcp to a device driven by the +spear_smi.c driver will pass through the spear_smi_cpy_toio() +function. This function will get called for chunks of up to 256 bytes. +If the amount of data is smaller, we may have a problem if the data +length is not 4-byte aligned. In this situation, the kernel panics +during the memcpy: + + # dd if=/dev/urandom bs=1001 count=1 of=/dev/mtd6 + spear_smi_cpy_toio [620] dest c9070000, src c7be8800, len 256 + spear_smi_cpy_toio [620] dest c9070100, src c7be8900, len 256 + spear_smi_cpy_toio [620] dest c9070200, src c7be8a00, len 256 + spear_smi_cpy_toio [620] dest c9070300, src c7be8b00, len 233 + Unhandled fault: external abort on non-linefetch (0x808) at 0xc90703e8 + [...] + PC is at memcpy+0xcc/0x330 + +The above error occurs because the implementation of memcpy_toio() +tries to optimize the number of I/O by writing 4 bytes at a time as +much as possible, until there are less than 4 bytes left and then +switches to word or byte writes. + +Unfortunately, the specification states about the Write Burst mode: + + "the next AHB Write request should point to the next + incremented address and should have the same size (byte, + half-word or word)" + +This means ARM architecture implementation of memcpy_toio() cannot +reliably be used blindly here. Workaround this situation by update the +write path to stick to byte access when the burst length is not +multiple of 4. + +Fixes: f18dbbb1bfe0 ("mtd: ST SPEAr: Add SMI driver for serial NOR flash") +Cc: Russell King +Cc: Boris Brezillon +Cc: stable@vger.kernel.org +Signed-off-by: Miquel Raynal +Reviewed-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/devices/spear_smi.c | 38 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 37 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/devices/spear_smi.c ++++ b/drivers/mtd/devices/spear_smi.c +@@ -595,6 +595,26 @@ static int spear_mtd_read(struct mtd_inf + return 0; + } + ++/* ++ * The purpose of this function is to ensure a memcpy_toio() with byte writes ++ * only. Its structure is inspired from the ARM implementation of _memcpy_toio() ++ * which also does single byte writes but cannot be used here as this is just an ++ * implementation detail and not part of the API. Not mentioning the comment ++ * stating that _memcpy_toio() should be optimized. ++ */ ++static void spear_smi_memcpy_toio_b(volatile void __iomem *dest, ++ const void *src, size_t len) ++{ ++ const unsigned char *from = src; ++ ++ while (len) { ++ len--; ++ writeb(*from, dest); ++ from++; ++ dest++; ++ } ++} ++ + static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank, + void __iomem *dest, const void *src, size_t len) + { +@@ -617,7 +637,23 @@ static inline int spear_smi_cpy_toio(str + ctrlreg1 = readl(dev->io_base + SMI_CR1); + writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1); + +- memcpy_toio(dest, src, len); ++ /* ++ * In Write Burst mode (WB_MODE), the specs states that writes must be: ++ * - incremental ++ * - of the same size ++ * The ARM implementation of memcpy_toio() will optimize the number of ++ * I/O by using as much 4-byte writes as possible, surrounded by ++ * 2-byte/1-byte access if: ++ * - the destination is not 4-byte aligned ++ * - the length is not a multiple of 4-byte. ++ * Avoid this alternance of write access size by using our own 'byte ++ * access' helper if at least one of the two conditions above is true. ++ */ ++ if (IS_ALIGNED(len, sizeof(u32)) && ++ IS_ALIGNED((uintptr_t)dest, sizeof(u32))) ++ memcpy_toio(dest, src, len); ++ else ++ spear_smi_memcpy_toio_b(dest, src, len); + + writel(ctrlreg1, dev->io_base + SMI_CR1); + diff --git a/queue-4.9/rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch b/queue-4.9/rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch new file mode 100644 index 00000000000..c3c01f3a848 --- /dev/null +++ b/queue-4.9/rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch @@ -0,0 +1,72 @@ +From 3155db7613edea8fb943624062baf1e4f9cfbfd6 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 11 Nov 2019 13:40:45 -0600 +Subject: rtlwifi: rtl8192de: Fix missing callback that tests for hw release of buffer + +From: Larry Finger + +commit 3155db7613edea8fb943624062baf1e4f9cfbfd6 upstream. + +In commit 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for +new drivers"), a callback needed to check if the hardware has released +a buffer indicating that a DMA operation is completed was not added. + +Fixes: 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for new drivers") +Cc: Stable # v3.18+ +Signed-off-by: Larry Finger +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 1 + + drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 17 +++++++++++++++++ + drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h | 2 ++ + 3 files changed, 20 insertions(+) + +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +@@ -243,6 +243,7 @@ static struct rtl_hal_ops rtl8192de_hal_ + .led_control = rtl92de_led_control, + .set_desc = rtl92de_set_desc, + .get_desc = rtl92de_get_desc, ++ .is_tx_desc_closed = rtl92de_is_tx_desc_closed, + .tx_polling = rtl92de_tx_polling, + .enable_hw_sec = rtl92de_enable_hw_security_config, + .set_key = rtl92de_set_key, +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +@@ -862,6 +862,23 @@ u32 rtl92de_get_desc(u8 *p_desc, bool is + return ret; + } + ++bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, ++ u8 hw_queue, u16 index) ++{ ++ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); ++ struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; ++ u8 *entry = (u8 *)(&ring->desc[ring->idx]); ++ u8 own = (u8)rtl92de_get_desc(entry, true, HW_DESC_OWN); ++ ++ /* a beacon packet will only use the first ++ * descriptor by defaut, and the own bit may not ++ * be cleared by the hardware ++ */ ++ if (own) ++ return false; ++ return true; ++} ++ + void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h +@@ -740,6 +740,8 @@ bool rtl92de_rx_query_desc(struct ieee80 + void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); + u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name); ++bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, ++ u8 hw_queue, u16 index); + void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); + void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, diff --git a/queue-4.9/rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch b/queue-4.9/rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch new file mode 100644 index 00000000000..4bd3ae39d44 --- /dev/null +++ b/queue-4.9/rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch @@ -0,0 +1,46 @@ +From 0e531cc575c4e9e3dd52ad287b49d3c2dc74c810 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 11 Nov 2019 13:40:44 -0600 +Subject: rtlwifi: rtl8192de: Fix missing code to retrieve RX buffer address + +From: Larry Finger + +commit 0e531cc575c4e9e3dd52ad287b49d3c2dc74c810 upstream. + +In commit 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for +new drivers"), a callback to get the RX buffer address was added to +the PCI driver. Unfortunately, driver rtl8192de was not modified +appropriately and the code runs into a WARN_ONCE() call. The use +of an incorrect array is also fixed. + +Fixes: 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for new drivers") +Cc: Stable # 3.18+ +Signed-off-by: Larry Finger +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +@@ -843,13 +843,15 @@ u32 rtl92de_get_desc(u8 *p_desc, bool is + break; + } + } else { +- struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + switch (desc_name) { + case HW_DESC_OWN: +- ret = GET_RX_DESC_OWN(pdesc); ++ ret = GET_RX_DESC_OWN(p_desc); + break; + case HW_DESC_RXPKT_LEN: +- ret = GET_RX_DESC_PKT_LEN(pdesc); ++ ret = GET_RX_DESC_PKT_LEN(p_desc); ++ break; ++ case HW_DESC_RXBUFF_ADDR: ++ ret = GET_RX_DESC_BUFF_ADDR(p_desc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", diff --git a/queue-4.9/rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch b/queue-4.9/rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch new file mode 100644 index 00000000000..b608a7427cd --- /dev/null +++ b/queue-4.9/rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch @@ -0,0 +1,67 @@ +From 330bb7117101099c687e9c7f13d48068670b9c62 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 11 Nov 2019 13:40:46 -0600 +Subject: rtlwifi: rtl8192de: Fix missing enable interrupt flag + +From: Larry Finger + +commit 330bb7117101099c687e9c7f13d48068670b9c62 upstream. + +In commit 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for +new drivers"), the flag that indicates that interrupts are enabled was +never set. + +In addition, there are several places when enable/disable interrupts +were commented out are restored. A sychronize_interrupts() call is +removed. + +Fixes: 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for new drivers") +Cc: Stable # v3.18+ +Signed-off-by: Larry Finger +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c +@@ -1209,6 +1209,7 @@ void rtl92de_enable_interrupt(struct iee + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); ++ rtlpci->irq_enabled = true; + } + + void rtl92de_disable_interrupt(struct ieee80211_hw *hw) +@@ -1218,7 +1219,7 @@ void rtl92de_disable_interrupt(struct ie + + rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); +- synchronize_irq(rtlpci->pdev->irq); ++ rtlpci->irq_enabled = false; + } + + static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) +@@ -1389,7 +1390,7 @@ void rtl92de_set_beacon_related_register + + bcn_interval = mac->beacon_interval; + atim_window = 2; +- /*rtl92de_disable_interrupt(hw); */ ++ rtl92de_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); +@@ -1409,9 +1410,9 @@ void rtl92de_set_beacon_interval(struct + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); +- /* rtl92de_disable_interrupt(hw); */ ++ rtl92de_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); +- /* rtl92de_enable_interrupt(hw); */ ++ rtl92de_enable_interrupt(hw); + } + + void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, diff --git a/queue-4.9/series b/queue-4.9/series index 3f6587f1bdf..e8fa55c4295 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -109,4 +109,18 @@ usb-atm-ueagle-atm-add-missing-endpoint-check.patch usb-idmouse-fix-interface-sanity-checks.patch usb-serial-io_edgeport-fix-epic-endpoint-lookup.patch usb-adutux-fix-interface-sanity-check.patch +usb-core-urb-fix-urb-structure-initialization-function.patch +usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch +mtd-spear_smi-fix-write-burst-mode.patch +virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch +btrfs-check-page-mapping-when-loading-free-space-cache.patch +btrfs-remove-btrfs_bio-flags-member.patch +btrfs-send-skip-backreference-walking-for-extents-with-many-references.patch +btrfs-record-all-roots-for-rename-exchange-on-a-subvol.patch +rtlwifi-rtl8192de-fix-missing-code-to-retrieve-rx-buffer-address.patch +rtlwifi-rtl8192de-fix-missing-callback-that-tests-for-hw-release-of-buffer.patch +rtlwifi-rtl8192de-fix-missing-enable-interrupt-flag.patch +lib-raid6-fix-awk-build-warnings.patch alsa-hda-fix-pending-unsol-events-at-shutdown.patch +workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch +workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch diff --git a/queue-4.9/usb-core-urb-fix-urb-structure-initialization-function.patch b/queue-4.9/usb-core-urb-fix-urb-structure-initialization-function.patch new file mode 100644 index 00000000000..d7e95aa5256 --- /dev/null +++ b/queue-4.9/usb-core-urb-fix-urb-structure-initialization-function.patch @@ -0,0 +1,34 @@ +From 1cd17f7f0def31e3695501c4f86cd3faf8489840 Mon Sep 17 00:00:00 2001 +From: Emiliano Ingrassia +Date: Wed, 27 Nov 2019 17:03:55 +0100 +Subject: usb: core: urb: fix URB structure initialization function + +From: Emiliano Ingrassia + +commit 1cd17f7f0def31e3695501c4f86cd3faf8489840 upstream. + +Explicitly initialize URB structure urb_list field in usb_init_urb(). +This field can be potentially accessed uninitialized and its +initialization is coherent with the usage of list_del_init() in +usb_hcd_unlink_urb_from_ep() and usb_giveback_urb_bh() and its +explicit initialization in usb_hcd_submit_urb() error path. + +Signed-off-by: Emiliano Ingrassia +Cc: stable +Link: https://lore.kernel.org/r/20191127160355.GA27196@ingrassia.epigenesys.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/urb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -40,6 +40,7 @@ void usb_init_urb(struct urb *urb) + if (urb) { + memset(urb, 0, sizeof(*urb)); + kref_init(&urb->kref); ++ INIT_LIST_HEAD(&urb->urb_list); + INIT_LIST_HEAD(&urb->anchor_list); + } + } diff --git a/queue-4.9/usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch b/queue-4.9/usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch new file mode 100644 index 00000000000..c78ee966c6a --- /dev/null +++ b/queue-4.9/usb-mon-fix-a-deadlock-in-usbmon-between-mmap-and-read.patch @@ -0,0 +1,104 @@ +From 19e6317d24c25ee737c65d1ffb7483bdda4bb54a Mon Sep 17 00:00:00 2001 +From: Pete Zaitcev +Date: Wed, 4 Dec 2019 20:39:41 -0600 +Subject: usb: mon: Fix a deadlock in usbmon between mmap and read + +From: Pete Zaitcev + +commit 19e6317d24c25ee737c65d1ffb7483bdda4bb54a upstream. + +The problem arises because our read() function grabs a lock of the +circular buffer, finds something of interest, then invokes copy_to_user() +straight from the buffer, which in turn takes mm->mmap_sem. In the same +time, the callback mon_bin_vma_fault() is invoked under mm->mmap_sem. +It attempts to take the fetch lock and deadlocks. + +This patch does away with protecting of our page list with any +semaphores, and instead relies on the kernel not close the device +while mmap is active in a process. + +In addition, we prohibit re-sizing of a buffer while mmap is active. +This way, when (now unlocked) fault is processed, it works with the +page that is intended to be mapped-in, and not some other random page. +Note that this may have an ABI impact, but hopefully no legitimate +program is this wrong. + +Signed-off-by: Pete Zaitcev +Reported-by: syzbot+56f9673bb4cdcbeb0e92@syzkaller.appspotmail.com +Reviewed-by: Alan Stern +Fixes: 46eb14a6e158 ("USB: fix usbmon BUG trigger") +Cc: +Link: https://lore.kernel.org/r/20191204203941.3503452b@suzdal.zaitcev.lan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/mon/mon_bin.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +--- a/drivers/usb/mon/mon_bin.c ++++ b/drivers/usb/mon/mon_bin.c +@@ -1036,12 +1036,18 @@ static long mon_bin_ioctl(struct file *f + + mutex_lock(&rp->fetch_lock); + spin_lock_irqsave(&rp->b_lock, flags); +- mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); +- kfree(rp->b_vec); +- rp->b_vec = vec; +- rp->b_size = size; +- rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0; +- rp->cnt_lost = 0; ++ if (rp->mmap_active) { ++ mon_free_buff(vec, size/CHUNK_SIZE); ++ kfree(vec); ++ ret = -EBUSY; ++ } else { ++ mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); ++ kfree(rp->b_vec); ++ rp->b_vec = vec; ++ rp->b_size = size; ++ rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0; ++ rp->cnt_lost = 0; ++ } + spin_unlock_irqrestore(&rp->b_lock, flags); + mutex_unlock(&rp->fetch_lock); + } +@@ -1213,13 +1219,21 @@ mon_bin_poll(struct file *file, struct p + static void mon_bin_vma_open(struct vm_area_struct *vma) + { + struct mon_reader_bin *rp = vma->vm_private_data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&rp->b_lock, flags); + rp->mmap_active++; ++ spin_unlock_irqrestore(&rp->b_lock, flags); + } + + static void mon_bin_vma_close(struct vm_area_struct *vma) + { ++ unsigned long flags; ++ + struct mon_reader_bin *rp = vma->vm_private_data; ++ spin_lock_irqsave(&rp->b_lock, flags); + rp->mmap_active--; ++ spin_unlock_irqrestore(&rp->b_lock, flags); + } + + /* +@@ -1231,16 +1245,12 @@ static int mon_bin_vma_fault(struct vm_a + unsigned long offset, chunk_idx; + struct page *pageptr; + +- mutex_lock(&rp->fetch_lock); + offset = vmf->pgoff << PAGE_SHIFT; +- if (offset >= rp->b_size) { +- mutex_unlock(&rp->fetch_lock); ++ if (offset >= rp->b_size) + return VM_FAULT_SIGBUS; +- } + chunk_idx = offset / CHUNK_SIZE; + pageptr = rp->b_vec[chunk_idx].pg; + get_page(pageptr); +- mutex_unlock(&rp->fetch_lock); + vmf->page = pageptr; + return 0; + } diff --git a/queue-4.9/virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch b/queue-4.9/virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch new file mode 100644 index 00000000000..199000d5b68 --- /dev/null +++ b/queue-4.9/virtio-balloon-fix-managed-page-counts-when-migrating-pages-between-zones.patch @@ -0,0 +1,159 @@ +From 63341ab03706e11a31e3dd8ccc0fbc9beaf723f0 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 11 Dec 2019 12:11:52 +0100 +Subject: virtio-balloon: fix managed page counts when migrating pages between zones + +From: David Hildenbrand + +commit 63341ab03706e11a31e3dd8ccc0fbc9beaf723f0 upstream. + +In case we have to migrate a ballon page to a newpage of another zone, the +managed page count of both zones is wrong. Paired with memory offlining +(which will adjust the managed page count), we can trigger kernel crashes +and all kinds of different symptoms. + +One way to reproduce: +1. Start a QEMU guest with 4GB, no NUMA +2. Hotplug a 1GB DIMM and online the memory to ZONE_NORMAL +3. Inflate the balloon to 1GB +4. Unplug the DIMM (be quick, otherwise unmovable data ends up on it) +5. Observe /proc/zoneinfo + Node 0, zone Normal + pages free 16810 + min 24848885473806 + low 18471592959183339 + high 36918337032892872 + spanned 262144 + present 262144 + managed 18446744073709533486 +6. Do anything that requires some memory (e.g., inflate the balloon some +more). The OOM goes crazy and the system crashes + [ 238.324946] Out of memory: Killed process 537 (login) total-vm:27584kB, anon-rss:860kB, file-rss:0kB, shmem-rss:00 + [ 238.338585] systemd invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0 + [ 238.339420] CPU: 0 PID: 1 Comm: systemd Tainted: G D W 5.4.0-next-20191204+ #75 + [ 238.340139] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu4 + [ 238.341121] Call Trace: + [ 238.341337] dump_stack+0x8f/0xd0 + [ 238.341630] dump_header+0x61/0x5ea + [ 238.341942] oom_kill_process.cold+0xb/0x10 + [ 238.342299] out_of_memory+0x24d/0x5a0 + [ 238.342625] __alloc_pages_slowpath+0xd12/0x1020 + [ 238.343024] __alloc_pages_nodemask+0x391/0x410 + [ 238.343407] pagecache_get_page+0xc3/0x3a0 + [ 238.343757] filemap_fault+0x804/0xc30 + [ 238.344083] ? ext4_filemap_fault+0x28/0x42 + [ 238.344444] ext4_filemap_fault+0x30/0x42 + [ 238.344789] __do_fault+0x37/0x1a0 + [ 238.345087] __handle_mm_fault+0x104d/0x1ab0 + [ 238.345450] handle_mm_fault+0x169/0x360 + [ 238.345790] do_user_addr_fault+0x20d/0x490 + [ 238.346154] do_page_fault+0x31/0x210 + [ 238.346468] async_page_fault+0x43/0x50 + [ 238.346797] RIP: 0033:0x7f47eba4197e + [ 238.347110] Code: Bad RIP value. + [ 238.347387] RSP: 002b:00007ffd7c0c1890 EFLAGS: 00010293 + [ 238.347834] RAX: 0000000000000002 RBX: 000055d196a20a20 RCX: 00007f47eba4197e + [ 238.348437] RDX: 0000000000000033 RSI: 00007ffd7c0c18c0 RDI: 0000000000000004 + [ 238.349047] RBP: 00007ffd7c0c1c20 R08: 0000000000000000 R09: 0000000000000033 + [ 238.349660] R10: 00000000ffffffff R11: 0000000000000293 R12: 0000000000000001 + [ 238.350261] R13: ffffffffffffffff R14: 0000000000000000 R15: 00007ffd7c0c18c0 + [ 238.350878] Mem-Info: + [ 238.351085] active_anon:3121 inactive_anon:51 isolated_anon:0 + [ 238.351085] active_file:12 inactive_file:7 isolated_file:0 + [ 238.351085] unevictable:0 dirty:0 writeback:0 unstable:0 + [ 238.351085] slab_reclaimable:5565 slab_unreclaimable:10170 + [ 238.351085] mapped:3 shmem:111 pagetables:155 bounce:0 + [ 238.351085] free:720717 free_pcp:2 free_cma:0 + [ 238.353757] Node 0 active_anon:12484kB inactive_anon:204kB active_file:48kB inactive_file:28kB unevictable:0kB iss + [ 238.355979] Node 0 DMA free:11556kB min:36kB low:48kB high:60kB reserved_highatomic:0KB active_anon:152kB inactivB + [ 238.358345] lowmem_reserve[]: 0 2955 2884 2884 2884 + [ 238.358761] Node 0 DMA32 free:2677864kB min:7004kB low:10028kB high:13052kB reserved_highatomic:0KB active_anon:0B + [ 238.361202] lowmem_reserve[]: 0 0 72057594037927865 72057594037927865 72057594037927865 + [ 238.361888] Node 0 Normal free:193448kB min:99395541895224kB low:73886371836733356kB high:147673348131571488kB reB + [ 238.364765] lowmem_reserve[]: 0 0 0 0 0 + [ 238.365101] Node 0 DMA: 7*4kB (U) 5*8kB (UE) 6*16kB (UME) 2*32kB (UM) 1*64kB (U) 2*128kB (UE) 3*256kB (UME) 2*512B + [ 238.366379] Node 0 DMA32: 0*4kB 1*8kB (U) 2*16kB (UM) 2*32kB (UM) 2*64kB (UM) 1*128kB (U) 1*256kB (U) 1*512kB (U)B + [ 238.367654] Node 0 Normal: 1985*4kB (UME) 1321*8kB (UME) 844*16kB (UME) 524*32kB (UME) 300*64kB (UME) 138*128kB (B + [ 238.369184] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB + [ 238.369915] 130 total pagecache pages + [ 238.370241] 0 pages in swap cache + [ 238.370533] Swap cache stats: add 0, delete 0, find 0/0 + [ 238.370981] Free swap = 0kB + [ 238.371239] Total swap = 0kB + [ 238.371488] 1048445 pages RAM + [ 238.371756] 0 pages HighMem/MovableOnly + [ 238.372090] 306992 pages reserved + [ 238.372376] 0 pages cma reserved + [ 238.372661] 0 pages hwpoisoned + +In another instance (older kernel), I was able to observe this +(negative page count :/): + [ 180.896971] Offlined Pages 32768 + [ 182.667462] Offlined Pages 32768 + [ 184.408117] Offlined Pages 32768 + [ 186.026321] Offlined Pages 32768 + [ 187.684861] Offlined Pages 32768 + [ 189.227013] Offlined Pages 32768 + [ 190.830303] Offlined Pages 32768 + [ 190.833071] Built 1 zonelists, mobility grouping on. Total pages: -36920272750453009 + +In another instance (older kernel), I was no longer able to start any +process: + [root@vm ~]# [ 214.348068] Offlined Pages 32768 + [ 215.973009] Offlined Pages 32768 + cat /proc/meminfo + -bash: fork: Cannot allocate memory + [root@vm ~]# cat /proc/meminfo + -bash: fork: Cannot allocate memory + +Fix it by properly adjusting the managed page count when migrating if +the zone changed. The managed page count of the zones now looks after +unplug of the DIMM (and after deflating the balloon) just like before +inflating the balloon (and plugging+onlining the DIMM). + +We'll temporarily modify the totalram page count. If this ever becomes a +problem, we can fine tune by providing helpers that don't touch +the totalram pages (e.g., adjust_zone_managed_page_count()). + +Please note that fixing up the managed page count is only necessary when +we adjusted the managed page count when inflating - only if we +don't have VIRTIO_BALLOON_F_DEFLATE_ON_OOM. With that feature, the +managed page count is not touched when inflating/deflating. + +Reported-by: Yumei Huang +Fixes: 3dcc0571cd64 ("mm: correctly update zone->managed_pages") +Cc: # v3.11+ +Cc: "Michael S. Tsirkin" +Cc: Jason Wang +Cc: Jiang Liu +Cc: Andrew Morton +Cc: Igor Mammedov +Cc: virtualization@lists.linux-foundation.org +Signed-off-by: David Hildenbrand +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/virtio/virtio_balloon.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/virtio/virtio_balloon.c ++++ b/drivers/virtio/virtio_balloon.c +@@ -482,6 +482,17 @@ static int virtballoon_migratepage(struc + + get_page(newpage); /* balloon reference */ + ++ /* ++ * When we migrate a page to a different zone and adjusted the ++ * managed page count when inflating, we have to fixup the count of ++ * both involved zones. ++ */ ++ if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) && ++ page_zone(page) != page_zone(newpage)) { ++ adjust_managed_page_count(page, 1); ++ adjust_managed_page_count(newpage, -1); ++ } ++ + /* balloon's page migration 1st step -- inflate "newpage" */ + spin_lock_irqsave(&vb_dev_info->pages_lock, flags); + balloon_page_insert(vb_dev_info, newpage); diff --git a/queue-4.9/workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch b/queue-4.9/workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch new file mode 100644 index 00000000000..8124981bad5 --- /dev/null +++ b/queue-4.9/workqueue-fix-pwq-ref-leak-in-rescuer_thread.patch @@ -0,0 +1,60 @@ +From e66b39af00f426b3356b96433d620cb3367ba1ff Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 25 Sep 2019 06:59:15 -0700 +Subject: workqueue: Fix pwq ref leak in rescuer_thread() + +From: Tejun Heo + +commit e66b39af00f426b3356b96433d620cb3367ba1ff upstream. + +008847f66c3 ("workqueue: allow rescuer thread to do more work.") made +the rescuer worker requeue the pwq immediately if there may be more +work items which need rescuing instead of waiting for the next mayday +timer expiration. Unfortunately, it doesn't check whether the pwq is +already on the mayday list and unconditionally gets the ref and moves +it onto the list. This doesn't corrupt the list but creates an +additional reference to the pwq. It got queued twice but will only be +removed once. + +This leak later can trigger pwq refcnt warning on workqueue +destruction and prevent freeing of the workqueue. + +Signed-off-by: Tejun Heo +Cc: "Williams, Gerald S" +Cc: NeilBrown +Cc: stable@vger.kernel.org # v3.19+ +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2344,8 +2344,14 @@ repeat: + */ + if (need_to_create_worker(pool)) { + spin_lock(&wq_mayday_lock); +- get_pwq(pwq); +- list_move_tail(&pwq->mayday_node, &wq->maydays); ++ /* ++ * Queue iff we aren't racing destruction ++ * and somebody else hasn't queued it already. ++ */ ++ if (wq->rescuer && list_empty(&pwq->mayday_node)) { ++ get_pwq(pwq); ++ list_add_tail(&pwq->mayday_node, &wq->maydays); ++ } + spin_unlock(&wq_mayday_lock); + } + } +@@ -4358,7 +4364,8 @@ static void show_pwq(struct pool_workque + pr_info(" pwq %d:", pool->id); + pr_cont_pool_info(pool); + +- pr_cont(" active=%d/%d%s\n", pwq->nr_active, pwq->max_active, ++ pr_cont(" active=%d/%d refcnt=%d%s\n", ++ pwq->nr_active, pwq->max_active, pwq->refcnt, + !list_empty(&pwq->mayday_node) ? " MAYDAY" : ""); + + hash_for_each(pool->busy_hash, bkt, worker, hentry) { diff --git a/queue-4.9/workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch b/queue-4.9/workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch new file mode 100644 index 00000000000..99428cef0fd --- /dev/null +++ b/queue-4.9/workqueue-fix-spurious-sanity-check-failures-in-destroy_workqueue.patch @@ -0,0 +1,83 @@ +From def98c84b6cdf2eeea19ec5736e90e316df5206b Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 18 Sep 2019 18:43:40 -0700 +Subject: workqueue: Fix spurious sanity check failures in destroy_workqueue() + +From: Tejun Heo + +commit def98c84b6cdf2eeea19ec5736e90e316df5206b upstream. + +Before actually destrying a workqueue, destroy_workqueue() checks +whether it's actually idle. If it isn't, it prints out a bunch of +warning messages and leaves the workqueue dangling. It unfortunately +has a couple issues. + +* Mayday list queueing increments pwq's refcnts which gets detected as + busy and fails the sanity checks. However, because mayday list + queueing is asynchronous, this condition can happen without any + actual work items left in the workqueue. + +* Sanity check failure leaves the sysfs interface behind too which can + lead to init failure of newer instances of the workqueue. + +This patch fixes the above two by + +* If a workqueue has a rescuer, disable and kill the rescuer before + sanity checks. Disabling and killing is guaranteed to flush the + existing mayday list. + +* Remove sysfs interface before sanity checks. + +Signed-off-by: Tejun Heo +Reported-by: Marcin Pawlowski +Reported-by: "Williams, Gerald S" +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -4031,9 +4031,28 @@ void destroy_workqueue(struct workqueue_ + struct pool_workqueue *pwq; + int node; + ++ /* ++ * Remove it from sysfs first so that sanity check failure doesn't ++ * lead to sysfs name conflicts. ++ */ ++ workqueue_sysfs_unregister(wq); ++ + /* drain it before proceeding with destruction */ + drain_workqueue(wq); + ++ /* kill rescuer, if sanity checks fail, leave it w/o rescuer */ ++ if (wq->rescuer) { ++ struct worker *rescuer = wq->rescuer; ++ ++ /* this prevents new queueing */ ++ spin_lock_irq(&wq_mayday_lock); ++ wq->rescuer = NULL; ++ spin_unlock_irq(&wq_mayday_lock); ++ ++ /* rescuer will empty maydays list before exiting */ ++ kthread_stop(rescuer->task); ++ } ++ + /* sanity checks */ + mutex_lock(&wq->mutex); + for_each_pwq(pwq, wq) { +@@ -4063,11 +4082,6 @@ void destroy_workqueue(struct workqueue_ + list_del_rcu(&wq->list); + mutex_unlock(&wq_pool_mutex); + +- workqueue_sysfs_unregister(wq); +- +- if (wq->rescuer) +- kthread_stop(wq->rescuer->task); +- + if (!(wq->flags & WQ_UNBOUND)) { + /* + * The base ref is never dropped on per-cpu pwqs. Directly -- 2.47.3