blk-mq: clear stale request in tags->rq[] before freeing one request pool
authorMing Lei <ming.lei@redhat.com>
Tue, 11 May 2021 15:22:35 +0000 (23:22 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jul 2021 14:55:58 +0000 (16:55 +0200)
commit747b654e406922b0c892a5c9ffb81bbb497fa648
treea6c0df2cb31ac85b887d4272f6c71a0a95a82137
parenta3362ff0433b9cbd545c35baae59c5788b766e53
blk-mq: clear stale request in tags->rq[] before freeing one request pool

[ 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
block/blk-mq-tag.h
block/blk-mq.c