From c65bbe486de863ec31404178e103fe02fff11754 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Oct 2022 20:51:10 +0200 Subject: [PATCH] drop sbitmap patches --- ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-4.19/series | 2 - ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-5.10/series | 2 - ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-5.15/series | 2 - ...tmap-fix-batched-wait_cnt-accounting.patch | 142 ------------------ ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...tmap-fix-batched-wait_cnt-accounting.patch | 141 ----------------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-5.19/series | 4 - ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-5.4/series | 2 - ...aving-waitqueue-in-invalid-state-in-.patch | 77 ---------- ...-possible-io-hung-due-to-lost-wakeup.patch | 141 ----------------- queue-6.0/series | 2 - 20 files changed, 1605 deletions(-) delete mode 100644 queue-4.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-4.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch delete mode 100644 queue-5.10/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-5.10/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch delete mode 100644 queue-5.15/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-5.15/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch delete mode 100644 queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch delete mode 100644 queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch delete mode 100644 queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch delete mode 100644 queue-5.4/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-5.4/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch delete mode 100644 queue-6.0/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch delete mode 100644 queue-6.0/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch diff --git a/queue-4.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-4.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index 92010260be9..00000000000 --- a/queue-4.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e0483e76e17af926690bb0151e2e7a83ad2e9a88 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 474e014a2b6e..6913f2c4f2c8 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -463,6 +463,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -473,12 +474,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -507,7 +519,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-4.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-4.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index 71cdb506bd0..00000000000 --- a/queue-4.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From ff0fe7d067ce297123456fb491d402905450ddd0 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 0572ac340325..474e014a2b6e 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -469,32 +469,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-4.19/series b/queue-4.19/series index 7092370e2c0..2eaaffb2b54 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -125,7 +125,6 @@ clk-berlin-add-of_node_put-for-of_get_parent.patch clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch @@ -135,7 +134,6 @@ rdma-rxe-fix-kernel-null-pointer-dereference-error.patch rdma-rxe-fix-the-error-caused-by-qp-sk.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch ata-fix-ata_id_has_devslp.patch diff --git a/queue-5.10/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-5.10/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index bf095318717..00000000000 --- a/queue-5.10/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e3b91089200a0c4c3fdfe150a167b9916b4b5220 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index f5213ac07da3..0658ea4bd930 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -516,6 +516,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -526,12 +527,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -560,7 +572,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-5.10/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-5.10/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index 11e312fd0f4..00000000000 --- a/queue-5.10/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 6f431a716bcc47b7389973a5928e558016ddcb21 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 267aa7709416..f5213ac07da3 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -522,32 +522,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-5.10/series b/queue-5.10/series index 55a22ecbfb2..2fa340b3df6 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -208,7 +208,6 @@ clk-sprd-hold-reference-returned-by-of_get_parent.patch clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hid-uclogic-make-template-placeholder-ids-generic.patch hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch @@ -232,7 +231,6 @@ dyndbg-fix-static_branch-manipulation.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch dyndbg-drop-exported-dynamic_debug_exec_queries.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch mtd-rawnand-fsl_elbc-fix-none-ecc-mode.patch rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch diff --git a/queue-5.15/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-5.15/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index 24a5caa7ef8..00000000000 --- a/queue-5.15/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 660fdc0abb22d8d104a9ced7e4455f40c2eb27d7 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index fa30f1645366..fc545994d2eb 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -534,6 +534,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -544,12 +545,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -578,7 +590,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-5.15/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-5.15/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index 0fb53baec83..00000000000 --- a/queue-5.15/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 9169eebf547869e1e560ce8ad702206ae9bdbee2 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index b25db9be938a..fa30f1645366 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -540,32 +540,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-5.15/series b/queue-5.15/series index e437fc2c88a..cdb0b8174c6 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -291,7 +291,6 @@ clk-sprd-hold-reference-returned-by-of_get_parent.patch clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hid-uclogic-make-template-placeholder-ids-generic.patch hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch @@ -317,7 +316,6 @@ dyndbg-fix-static_branch-manipulation.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch dyndbg-drop-exported-dynamic_debug_exec_queries.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch clk-qcom-sm6115-select-qcom_gdsc.patch scsi-nvme-fc-add-new-routine-nvme_fc_io_getuuid.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch diff --git a/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch b/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch deleted file mode 100644 index b09177087a0..00000000000 --- a/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0457860446369e63cb410d6590d32f1a99647e6e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sun, 4 Sep 2022 06:39:25 -0600 -Subject: Revert "sbitmap: fix batched wait_cnt accounting" - -From: Jens Axboe - -[ Upstream commit bce1b56c73826fec8caf6187f0c922ede397a5a8 ] - -This reverts commit 16ede66973c84f890c03584f79158dd5b2d725f5. - -This is causing issues with CPU stalls on my test box, revert it for -now until we understand what is going on. It looks like infinite -looping off sbitmap_queue_wake_up(), but hard to tell with a lot of -CPUs hitting this issue and the console scrolling infinitely. - -Link: https://lore.kernel.org/linux-block/e742813b-ce5c-0d58-205b-1626f639b1bd@kernel.dk/ -Signed-off-by: Jens Axboe -Stable-dep-of: 48c033314f37 ("sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up()") -Signed-off-by: Sasha Levin ---- - block/blk-mq-tag.c | 2 +- - include/linux/sbitmap.h | 3 +-- - lib/sbitmap.c | 31 ++++++++++++++----------------- - 3 files changed, 16 insertions(+), 20 deletions(-) - -diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c -index 7aea93047caf..2dcd738c6952 100644 ---- a/block/blk-mq-tag.c -+++ b/block/blk-mq-tag.c -@@ -200,7 +200,7 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) - * other allocations on previous queue won't be starved. - */ - if (bt != bt_prev) -- sbitmap_queue_wake_up(bt_prev, 1); -+ sbitmap_queue_wake_up(bt_prev); - - ws = bt_wait_ptr(bt, data->hctx); - } while (1); -diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h -index 4d2d5205ab58..8f5a86e210b9 100644 ---- a/include/linux/sbitmap.h -+++ b/include/linux/sbitmap.h -@@ -575,9 +575,8 @@ void sbitmap_queue_wake_all(struct sbitmap_queue *sbq); - * sbitmap_queue_wake_up() - Wake up some of waiters in one waitqueue - * on a &struct sbitmap_queue. - * @sbq: Bitmap queue to wake up. -- * @nr: Number of bits cleared. - */ --void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr); -+void sbitmap_queue_wake_up(struct sbitmap_queue *sbq); - - /** - * sbitmap_queue_show() - Dump &struct sbitmap_queue information to a &struct -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index a8aae1fc5206..1f31147872e6 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -600,38 +600,34 @@ static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) - return NULL; - } - --static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) -+static bool __sbq_wake_up(struct sbitmap_queue *sbq) - { - struct sbq_wait_state *ws; -- int wake_batch, wait_cnt, cur; -+ unsigned int wake_batch; -+ int wait_cnt; - - ws = sbq_wake_ptr(sbq); -- if (!ws || !nr) -+ if (!ws) - return false; - -- wake_batch = READ_ONCE(sbq->wake_batch); -- cur = atomic_read(&ws->wait_cnt); -- do { -- if (cur <= 0) -- return true; -- wait_cnt = cur - nr; -- } while (!atomic_try_cmpxchg(&ws->wait_cnt, &cur, wait_cnt)); -- -+ wait_cnt = atomic_dec_return(&ws->wait_cnt); - /* - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (!waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) - return true; - - if (wait_cnt > 0) - return false; - -+ wake_batch = READ_ONCE(sbq->wake_batch); -+ - /* - * Wake up first in case that concurrent callers decrease wait_cnt - * while waitqueue is empty. - */ -- wake_up_nr(&ws->wait, max(wake_batch, nr)); -+ wake_up_nr(&ws->wait, wake_batch); - - /* - * Pairs with the memory barrier in sbitmap_queue_resize() to -@@ -656,11 +652,12 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) - return false; - } - --void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr) -+void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) - { -- while (__sbq_wake_up(sbq, nr)) -+ while (__sbq_wake_up(sbq)) - ; - } -+EXPORT_SYMBOL_GPL(sbitmap_queue_wake_up); - - static inline void sbitmap_update_cpu_hint(struct sbitmap *sb, int cpu, int tag) - { -@@ -697,7 +694,7 @@ void sbitmap_queue_clear_batch(struct sbitmap_queue *sbq, int offset, - atomic_long_andnot(mask, (atomic_long_t *) addr); - - smp_mb__after_atomic(); -- sbitmap_queue_wake_up(sbq, nr_tags); -+ sbitmap_queue_wake_up(sbq); - sbitmap_update_cpu_hint(&sbq->sb, raw_smp_processor_id(), - tags[nr_tags - 1] - offset); - } -@@ -725,7 +722,7 @@ void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr, - * waiter. See the comment on waitqueue_active(). - */ - smp_mb__after_atomic(); -- sbitmap_queue_wake_up(sbq, 1); -+ sbitmap_queue_wake_up(sbq); - sbitmap_update_cpu_hint(&sbq->sb, cpu, nr); - } - EXPORT_SYMBOL_GPL(sbitmap_queue_clear); --- -2.35.1 - diff --git a/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index 4f6848fe34f..00000000000 --- a/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From c1fc79d079bd7a0ceec512ee7946ce8150c046ef Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 1f31147872e6..bb1970ad4875 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -605,6 +605,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -615,12 +616,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -649,7 +661,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch b/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch deleted file mode 100644 index ebbeff6e57f..00000000000 --- a/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 3551abd659b4be2344b67cfd036151bd6c6363e2 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 25 Aug 2022 07:53:12 -0700 -Subject: sbitmap: fix batched wait_cnt accounting - -From: Keith Busch - -[ Upstream commit 16ede66973c84f890c03584f79158dd5b2d725f5 ] - -Batched completions can clear multiple bits, but we're only decrementing -the wait_cnt by one each time. This can cause waiters to never be woken, -stalling IO. Use the batched count instead. - -Link: https://bugzilla.kernel.org/show_bug.cgi?id=215679 -Signed-off-by: Keith Busch -Link: https://lore.kernel.org/r/20220825145312.1217900-1-kbusch@fb.com -Signed-off-by: Jens Axboe -Stable-dep-of: 48c033314f37 ("sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up()") -Signed-off-by: Sasha Levin ---- - block/blk-mq-tag.c | 2 +- - include/linux/sbitmap.h | 3 ++- - lib/sbitmap.c | 31 +++++++++++++++++-------------- - 3 files changed, 20 insertions(+), 16 deletions(-) - -diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c -index 2dcd738c6952..7aea93047caf 100644 ---- a/block/blk-mq-tag.c -+++ b/block/blk-mq-tag.c -@@ -200,7 +200,7 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) - * other allocations on previous queue won't be starved. - */ - if (bt != bt_prev) -- sbitmap_queue_wake_up(bt_prev); -+ sbitmap_queue_wake_up(bt_prev, 1); - - ws = bt_wait_ptr(bt, data->hctx); - } while (1); -diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h -index 8f5a86e210b9..4d2d5205ab58 100644 ---- a/include/linux/sbitmap.h -+++ b/include/linux/sbitmap.h -@@ -575,8 +575,9 @@ void sbitmap_queue_wake_all(struct sbitmap_queue *sbq); - * sbitmap_queue_wake_up() - Wake up some of waiters in one waitqueue - * on a &struct sbitmap_queue. - * @sbq: Bitmap queue to wake up. -+ * @nr: Number of bits cleared. - */ --void sbitmap_queue_wake_up(struct sbitmap_queue *sbq); -+void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr); - - /** - * sbitmap_queue_show() - Dump &struct sbitmap_queue information to a &struct -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 1f31147872e6..a8aae1fc5206 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -600,34 +600,38 @@ static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) - return NULL; - } - --static bool __sbq_wake_up(struct sbitmap_queue *sbq) -+static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) - { - struct sbq_wait_state *ws; -- unsigned int wake_batch; -- int wait_cnt; -+ int wake_batch, wait_cnt, cur; - - ws = sbq_wake_ptr(sbq); -- if (!ws) -+ if (!ws || !nr) - return false; - -- wait_cnt = atomic_dec_return(&ws->wait_cnt); -+ wake_batch = READ_ONCE(sbq->wake_batch); -+ cur = atomic_read(&ws->wait_cnt); -+ do { -+ if (cur <= 0) -+ return true; -+ wait_cnt = cur - nr; -+ } while (!atomic_try_cmpxchg(&ws->wait_cnt, &cur, wait_cnt)); -+ - /* - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (!waitqueue_active(&ws->wait)) - return true; - - if (wait_cnt > 0) - return false; - -- wake_batch = READ_ONCE(sbq->wake_batch); -- - /* - * Wake up first in case that concurrent callers decrease wait_cnt - * while waitqueue is empty. - */ -- wake_up_nr(&ws->wait, wake_batch); -+ wake_up_nr(&ws->wait, max(wake_batch, nr)); - - /* - * Pairs with the memory barrier in sbitmap_queue_resize() to -@@ -652,12 +656,11 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - } - --void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) -+void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr) - { -- while (__sbq_wake_up(sbq)) -+ while (__sbq_wake_up(sbq, nr)) - ; - } --EXPORT_SYMBOL_GPL(sbitmap_queue_wake_up); - - static inline void sbitmap_update_cpu_hint(struct sbitmap *sb, int cpu, int tag) - { -@@ -694,7 +697,7 @@ void sbitmap_queue_clear_batch(struct sbitmap_queue *sbq, int offset, - atomic_long_andnot(mask, (atomic_long_t *) addr); - - smp_mb__after_atomic(); -- sbitmap_queue_wake_up(sbq); -+ sbitmap_queue_wake_up(sbq, nr_tags); - sbitmap_update_cpu_hint(&sbq->sb, raw_smp_processor_id(), - tags[nr_tags - 1] - offset); - } -@@ -722,7 +725,7 @@ void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr, - * waiter. See the comment on waitqueue_active(). - */ - smp_mb__after_atomic(); -- sbitmap_queue_wake_up(sbq); -+ sbitmap_queue_wake_up(sbq, 1); - sbitmap_update_cpu_hint(&sbq->sb, cpu, nr); - } - EXPORT_SYMBOL_GPL(sbitmap_queue_clear); --- -2.35.1 - diff --git a/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index f743495eb25..00000000000 --- a/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 4cb065659e053366d6113a3526580558897ea8fc Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 29eb0484215a..1f31147872e6 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -611,32 +611,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-5.19/series b/queue-5.19/series index b5142f6bd22..60aaa7fc660 100644 --- a/queue-5.19/series +++ b/queue-5.19/series @@ -405,7 +405,6 @@ clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch clk-samsung-exynosautov9-correct-register-offsets-of.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hid-uclogic-make-template-placeholder-ids-generic.patch hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch @@ -440,9 +439,6 @@ dyndbg-fix-static_branch-manipulation.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch dyndbg-drop-exported-dynamic_debug_exec_queries.patch -sbitmap-fix-batched-wait_cnt-accounting.patch -revert-sbitmap-fix-batched-wait_cnt-accounting.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch clk-qcom-sm6115-select-qcom_gdsc.patch scsi-lpfc-fix-various-issues-reported-by-tools.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch diff --git a/queue-5.4/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-5.4/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index 2d4069736f8..00000000000 --- a/queue-5.4/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 6edafbfeb613a3a163eaaff3d1f18bfcc189a627 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 7df295a15c3d..fe67d6da7156 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -530,6 +530,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -540,12 +541,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -574,7 +586,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-5.4/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-5.4/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index 3e01ae87697..00000000000 --- a/queue-5.4/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From dcef8b05380b764e2ab4cd87bc9b5472dc3ee5f8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index ee3ce1494568..7df295a15c3d 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -536,32 +536,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-5.4/series b/queue-5.4/series index 966186c5f6d..1e445ca9882 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -127,7 +127,6 @@ clk-berlin-add-of_node_put-for-of_get_parent.patch clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch @@ -138,7 +137,6 @@ rdma-rxe-fix-the-error-caused-by-qp-sk.patch misc-ocxl-fix-possible-refcount-leak-in-afu_ioctl.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch diff --git a/queue-6.0/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-6.0/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch deleted file mode 100644 index bbb0fa0665a..00000000000 --- a/queue-6.0/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 67e50b0c78052157df4c79c8ba8ad177ca45f0a9 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 8 Sep 2022 15:09:37 +0200 -Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() - -From: Jan Kara - -[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] - -When __sbq_wake_up() decrements wait_cnt to 0 but races with someone -else waking the waiter on the waitqueue (so the waitqueue becomes -empty), it exits without reseting wait_cnt to wake_batch number. Once -wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new -waiters resulting in possible deadlocks or busyloops. Fix the problem by -making sure we reset wait_cnt even if we didn't wake up anybody in the -end. - -Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") -Reported-by: Keith Busch -Signed-off-by: Jan Kara -Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 1f31147872e6..bb1970ad4875 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -605,6 +605,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - struct sbq_wait_state *ws; - unsigned int wake_batch; - int wait_cnt; -+ bool ret; - - ws = sbq_wake_ptr(sbq); - if (!ws) -@@ -615,12 +616,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - * For concurrent callers of this, callers should call this function - * again to wakeup a new batch on a different 'ws'. - */ -- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ if (wait_cnt < 0) - return true; - -+ /* -+ * If we decremented queue without waiters, retry to avoid lost -+ * wakeups. -+ */ - if (wait_cnt > 0) -- return false; -+ return !waitqueue_active(&ws->wait); - -+ /* -+ * When wait_cnt == 0, we have to be particularly careful as we are -+ * responsible to reset wait_cnt regardless whether we've actually -+ * woken up anybody. But in case we didn't wakeup anybody, we still -+ * need to retry. -+ */ -+ ret = !waitqueue_active(&ws->wait); - wake_batch = READ_ONCE(sbq->wake_batch); - - /* -@@ -649,7 +661,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - sbq_index_atomic_inc(&sbq->wake_index); - atomic_set(&ws->wait_cnt, wake_batch); - -- return false; -+ return ret; - } - - void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) --- -2.35.1 - diff --git a/queue-6.0/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-6.0/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch deleted file mode 100644 index 86216b79298..00000000000 --- a/queue-6.0/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 6a6fe39fb947ccbe768f23442c2bf11596c4e1dc Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 3 Aug 2022 20:15:04 +0800 -Subject: sbitmap: fix possible io hung due to lost wakeup - -From: Yu Kuai - -[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] - -There are two problems can lead to lost wakeup: - -1) invalid wakeup on the wrong waitqueue: - -For example, 2 * wake_batch tags are put, while only wake_batch threads -are woken: - -__sbq_wake_up - atomic_cmpxchg -> reset wait_cnt - __sbq_wake_up -> decrease wait_cnt - ... - __sbq_wake_up -> wait_cnt is decreased to 0 again - atomic_cmpxchg - sbq_index_atomic_inc -> increase wake_index - wake_up_nr -> wake up and waitqueue might be empty - sbq_index_atomic_inc -> increase again, one waitqueue is skipped - wake_up_nr -> invalid wake up because old wakequeue might be empty - -To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. - -2) 'wait_cnt' can be decreased while waitqueue is empty - -As pointed out by Jan Kara, following race is possible: - -CPU1 CPU2 -__sbq_wake_up __sbq_wake_up - sbq_wake_ptr() sbq_wake_ptr() -> the same - wait_cnt = atomic_dec_return() - /* decreased to 0 */ - sbq_index_atomic_inc() - /* move to next waitqueue */ - atomic_set() - /* reset wait_cnt */ - wake_up_nr() - /* wake up on the old waitqueue */ - wait_cnt = atomic_dec_return() - /* - * decrease wait_cnt in the old - * waitqueue, while it can be - * empty. - */ - -Fix the problem by waking up before updating 'wake_index' and -'wait_cnt'. - -With this patch, noted that 'wait_cnt' is still decreased in the old -empty waitqueue, however, the wakeup is redirected to a active waitqueue, -and the extra decrement on the old empty waitqueue is not handled. - -Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") -Signed-off-by: Yu Kuai -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com -Signed-off-by: Jens Axboe -Signed-off-by: Sasha Levin ---- - lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/lib/sbitmap.c b/lib/sbitmap.c -index 29eb0484215a..1f31147872e6 100644 ---- a/lib/sbitmap.c -+++ b/lib/sbitmap.c -@@ -611,32 +611,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) - return false; - - wait_cnt = atomic_dec_return(&ws->wait_cnt); -- if (wait_cnt <= 0) { -- int ret; -+ /* -+ * For concurrent callers of this, callers should call this function -+ * again to wakeup a new batch on a different 'ws'. -+ */ -+ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) -+ return true; - -- wake_batch = READ_ONCE(sbq->wake_batch); -+ if (wait_cnt > 0) -+ return false; - -- /* -- * Pairs with the memory barrier in sbitmap_queue_resize() to -- * ensure that we see the batch size update before the wait -- * count is reset. -- */ -- smp_mb__before_atomic(); -+ wake_batch = READ_ONCE(sbq->wake_batch); - -- /* -- * For concurrent callers of this, the one that failed the -- * atomic_cmpxhcg() race should call this function again -- * to wakeup a new batch on a different 'ws'. -- */ -- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); -- if (ret == wait_cnt) { -- sbq_index_atomic_inc(&sbq->wake_index); -- wake_up_nr(&ws->wait, wake_batch); -- return false; -- } -+ /* -+ * Wake up first in case that concurrent callers decrease wait_cnt -+ * while waitqueue is empty. -+ */ -+ wake_up_nr(&ws->wait, wake_batch); - -- return true; -- } -+ /* -+ * Pairs with the memory barrier in sbitmap_queue_resize() to -+ * ensure that we see the batch size update before the wait -+ * count is reset. -+ * -+ * Also pairs with the implicit barrier between decrementing wait_cnt -+ * and checking for waitqueue_active() to make sure waitqueue_active() -+ * sees result of the wakeup if atomic_dec_return() has seen the result -+ * of atomic_set(). -+ */ -+ smp_mb__before_atomic(); -+ -+ /* -+ * Increase wake_index before updating wait_cnt, otherwise concurrent -+ * callers can see valid wait_cnt in old waitqueue, which can cause -+ * invalid wakeup on the old waitqueue. -+ */ -+ sbq_index_atomic_inc(&sbq->wake_index); -+ atomic_set(&ws->wait_cnt, wake_batch); - - return false; - } --- -2.35.1 - diff --git a/queue-6.0/series b/queue-6.0/series index acb56eeb883..9724780b05e 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -475,7 +475,6 @@ clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch clk-samsung-exynosautov9-correct-register-offsets-of.patch -sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch hid-uclogic-add-missing-suffix-for-digitalizers.patch hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch @@ -513,7 +512,6 @@ dyndbg-fix-static_branch-manipulation.patch dyndbg-fix-module.dyndbg-handling.patch dyndbg-let-query-modname-override-actual-module-name.patch dyndbg-drop-exported-dynamic_debug_exec_queries.patch -sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch clk-qcom-sm6115-select-qcom_gdsc.patch scsi-lpfc-fix-various-issues-reported-by-tools.patch mtd-devices-docg3-check-the-return-value-of-devm_ior.patch -- 2.47.3