File systems can and often do allocate memory in the read-write path.
If these allocations are done with __GFP_IO or __GFP_FS set they can
recurse into the file system or swap device on top of the loop device
and cause deadlocks.  Prevent this by forcing a noio scope over the
calls into the file system.

Signed-off-by: Christoph Hellwig <[email protected]>
---
 drivers/block/loop.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 1ec7417c7f00..71eccc5cfffb 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1905,6 +1905,15 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
        int ret = 0;
        struct mem_cgroup *old_memcg = NULL;
        const bool use_aio = cmd->use_aio;
+       unsigned int memflags;
+
+       /*
+        * We're calling into file system which could do be doing memory
+        * allocations.  Ensure the memory reclaim does not cause I/O,
+        * because that could end up in the user of this loop devices again and
+        * deadlock.
+        */
+       memflags = memalloc_noio_save();
 
        if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
                ret = -EIO;
@@ -1942,6 +1951,7 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
                if (likely(!blk_should_fake_timeout(rq->q)))
                        blk_mq_complete_request(rq);
        }
+       memalloc_noio_restore(memflags);
 }
 
 static void loop_process_work(struct loop_worker *worker,
-- 
2.45.2


Reply via email to