From d498b2ddda99eed28cde177b1620dbcea246a1c4 Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Mon, 21 Sep 2026 09:49:20 +0800 Subject: [PATCH] mtd: block: prevent reclaim I/O during request processing The blktrans request callbacks run under dev->lock and may allocate memory with GFP_KERNEL. For example, mtdblock_writesect() uses vmalloc() to allocate its eraseblock cache. Direct reclaim can then recurse into block I/O and deadlock on resources held by the request being processed. syzbot reports a circular locking dependency involving the device mutex and fs_reclaim. Commit d5ba1c8ffd0b ("mtd: don't use PF_MEMALLOC") removed PF_MEMALLOC from the MTD request thread. That flag had prevented direct reclaim, so its removal made allocations during request processing eligible for reclaim without excluding I/O. Wrap request processing in mtd_queue_rq() in a NOIO scope. This covers both the request and background callbacks, including allocations made by lower MTD drivers, and prevents reclaim from initiating filesystem or block I/O. Fixes: d5ba1c8ffd0b ("mtd: don't use PF_MEMALLOC") Assisted-by: Codex:gpt-6-astra Reported-by: syzbot+e08e0a15269eefa87790@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e08e0a15269eefa87790 Signed-off-by: Qingfang Deng Signed-off-by: Miquel Raynal --- drivers/mtd/mtd_blkdevs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 4d2e7b7774e9..42f250344f0c 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "mtdcore.h" @@ -167,6 +168,7 @@ static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { struct mtd_blktrans_dev *dev; + unsigned int noio_flags; dev = hctx->queue->queuedata; if (!dev) { @@ -174,10 +176,13 @@ static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_STS_IOERR; } + /* Reclaim must not recurse into I/O while processing requests. */ + noio_flags = memalloc_noio_save(); spin_lock_irq(&dev->queue_lock); list_add_tail(&bd->rq->queuelist, &dev->rq_list); mtd_blktrans_work(dev); spin_unlock_irq(&dev->queue_lock); + memalloc_noio_restore(noio_flags); return BLK_STS_OK; }