From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Ming Lei <ming.lei@redhat.com>,
John Garry <john.garry@huawei.com>,
David Jeffery <djeffery@redhat.com>,
Bart Van Assche <bvanassche@acm.org>,
Jens Axboe <axboe@kernel.dk>, Sasha Levin <sashal@kernel.org>,
linux-block@vger.kernel.org
Subject: [PATCH AUTOSEL 5.12 13/52] blk-mq: clear stale request in tags->rq[] before freeing one request pool
Date: Mon, 5 Jul 2021 11:28:34 -0400 [thread overview]
Message-ID: <20210705152913.1521036-13-sashal@kernel.org> (raw)
In-Reply-To: <20210705152913.1521036-1-sashal@kernel.org>
From: Ming Lei <ming.lei@redhat.com>
[ Upstream commit bd63141d585bef14f4caf111f6d0e27fe2300ec6 ]
refcount_inc_not_zero() in bt_tags_iter() still may read one freed
request.
Fix the issue by the following approach:
1) hold a per-tags spinlock when reading ->rqs[tag] and calling
refcount_inc_not_zero in bt_tags_iter()
2) clearing stale request referred via ->rqs[tag] before freeing
request pool, the per-tags spinlock is held for clearing stale
->rq[tag]
So after we cleared stale requests, bt_tags_iter() won't observe
freed request any more, also the clearing will wait for pending
request reference.
The idea of clearing ->rqs[] is borrowed from John Garry's previous
patch and one recent David's patch.
Tested-by: John Garry <john.garry@huawei.com>
Reviewed-by: David Jeffery <djeffery@redhat.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20210511152236.763464-4-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
block/blk-mq-tag.c | 9 +++++++--
block/blk-mq-tag.h | 6 ++++++
block/blk-mq.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 6772c3728865..c4f2f6c123ae 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -202,10 +202,14 @@ struct bt_iter_data {
static struct request *blk_mq_find_and_get_req(struct blk_mq_tags *tags,
unsigned int bitnr)
{
- struct request *rq = tags->rqs[bitnr];
+ struct request *rq;
+ unsigned long flags;
+ spin_lock_irqsave(&tags->lock, flags);
+ rq = tags->rqs[bitnr];
if (!rq || !refcount_inc_not_zero(&rq->ref))
- return NULL;
+ rq = NULL;
+ spin_unlock_irqrestore(&tags->lock, flags);
return rq;
}
@@ -538,6 +542,7 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
tags->nr_tags = total_tags;
tags->nr_reserved_tags = reserved_tags;
+ spin_lock_init(&tags->lock);
if (flags & BLK_MQ_F_TAG_HCTX_SHARED)
return tags;
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
index 7d3e6b333a4a..f887988e5ef6 100644
--- a/block/blk-mq-tag.h
+++ b/block/blk-mq-tag.h
@@ -20,6 +20,12 @@ struct blk_mq_tags {
struct request **rqs;
struct request **static_rqs;
struct list_head page_list;
+
+ /*
+ * used to clear request reference in rqs[] before freeing one
+ * request pool
+ */
+ spinlock_t lock;
};
extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags,
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d5370ab2eb31..d06ff908f3d9 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2291,6 +2291,45 @@ blk_qc_t blk_mq_submit_bio(struct bio *bio)
return BLK_QC_T_NONE;
}
+static size_t order_to_size(unsigned int order)
+{
+ return (size_t)PAGE_SIZE << order;
+}
+
+/* called before freeing request pool in @tags */
+static void blk_mq_clear_rq_mapping(struct blk_mq_tag_set *set,
+ struct blk_mq_tags *tags, unsigned int hctx_idx)
+{
+ struct blk_mq_tags *drv_tags = set->tags[hctx_idx];
+ struct page *page;
+ unsigned long flags;
+
+ list_for_each_entry(page, &tags->page_list, lru) {
+ unsigned long start = (unsigned long)page_address(page);
+ unsigned long end = start + order_to_size(page->private);
+ int i;
+
+ for (i = 0; i < set->queue_depth; i++) {
+ struct request *rq = drv_tags->rqs[i];
+ unsigned long rq_addr = (unsigned long)rq;
+
+ if (rq_addr >= start && rq_addr < end) {
+ WARN_ON_ONCE(refcount_read(&rq->ref) != 0);
+ cmpxchg(&drv_tags->rqs[i], rq, NULL);
+ }
+ }
+ }
+
+ /*
+ * Wait until all pending iteration is done.
+ *
+ * Request reference is cleared and it is guaranteed to be observed
+ * after the ->lock is released.
+ */
+ spin_lock_irqsave(&drv_tags->lock, flags);
+ spin_unlock_irqrestore(&drv_tags->lock, flags);
+}
+
void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
unsigned int hctx_idx)
{
@@ -2309,6 +2348,8 @@ void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
}
}
+ blk_mq_clear_rq_mapping(set, tags, hctx_idx);
+
while (!list_empty(&tags->page_list)) {
page = list_first_entry(&tags->page_list, struct page, lru);
list_del_init(&page->lru);
@@ -2368,11 +2409,6 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
return tags;
}
-static size_t order_to_size(unsigned int order)
-{
- return (size_t)PAGE_SIZE << order;
-}
-
static int blk_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
unsigned int hctx_idx, int node)
{
--
2.30.2
next prev parent reply other threads:[~2021-07-05 15:30 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-05 15:28 [PATCH AUTOSEL 5.12 01/52] HID: do not use down_interruptible() when unbinding devices Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 02/52] EDAC/ti: Add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 03/52] ACPI: PM: s2idle: Add missing LPS0 functions for AMD Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 04/52] ACPI: processor idle: Fix up C-state latency if not ordered Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 05/52] hv_utils: Fix passing zero to 'PTR_ERR' warning Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 06/52] lib: vsprintf: Fix handling of number field widths in vsscanf Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 07/52] Input: goodix - platform/x86: touchscreen_dmi - Move upside down quirks to touchscreen_dmi.c Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 08/52] platform/x86: touchscreen_dmi: Add an extra entry for the upside down Goodix touchscreen on Teclast X89 tablets Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 09/52] platform/x86: touchscreen_dmi: Add info for the Goodix GT912 panel of TM800A550L tablets Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 10/52] ACPI: EC: Make more Asus laptops use ECDT _GPE Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 11/52] block_dump: remove block_dump feature in mark_inode_dirty() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 12/52] blk-mq: grab rq->refcount before calling ->fn in blk_mq_tagset_busy_iter Sasha Levin
2021-07-05 15:28 ` Sasha Levin [this message]
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 14/52] fs: dlm: reconnect if socket error report occurs Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 15/52] fs: dlm: cancel work sync othercon Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 16/52] random32: Fix implicit truncation warning in prandom_seed_state() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 17/52] open: don't silently ignore unknown O-flags in openat2() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 18/52] drivers: hv: Fix missing error code in vmbus_connect() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 19/52] fs: dlm: fix lowcomms_start error case Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 20/52] fs: dlm: fix memory leak when fenced Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 21/52] ACPICA: Fix memory leak caused by _CID repair function Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 22/52] ACPI: bus: Call kobject_put() in acpi_init() error path Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 23/52] ACPI: resources: Add checks for ACPI IRQ override Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 24/52] HID: hid-input: add Surface Go battery quirk Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 25/52] HID: sony: fix freeze when inserting ghlive ps3/wii dongles Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 26/52] block: fix race between adding/removing rq qos and normal IO Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 27/52] platform/x86: asus-nb-wmi: Revert "Drop duplicate DMI quirk structures" Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 28/52] platform/x86: asus-nb-wmi: Revert "add support for ASUS ROG Zephyrus G14 and G15" Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 29/52] platform/x86: toshiba_acpi: Fix missing error code in toshiba_acpi_setup_keyboard() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 30/52] nvme-pci: fix var. type for increasing cq_head Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 31/52] nvmet-fc: do not check for invalid target port in nvmet_fc_handle_fcp_rqst() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 32/52] EDAC/Intel: Do not load EDAC driver when running as a guest Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 33/52] tools/power/x86/intel-speed-select: Fix uncore memory frequency display Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 34/52] PCI: hv: Add check for hyperv_initialized in init_hv_pci_drv() Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 35/52] cifs: improve fallocate emulation Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 36/52] cifs: fix check of dfs interlinks Sasha Levin
2021-07-05 15:28 ` [PATCH AUTOSEL 5.12 37/52] smb3: fix uninitialized value for port in witness protocol move Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210705152913.1521036-13-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=axboe@kernel.dk \
--cc=bvanassche@acm.org \
--cc=djeffery@redhat.com \
--cc=john.garry@huawei.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ming.lei@redhat.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).