sched: Prevent recursion in io_schedule()
authorNeilBrown <neilb@suse.de>
Fri, 13 Feb 2015 04:49:17 +0000 (15:49 +1100)
committerDanny Wood <danwood76@gmail.com>
Mon, 8 Apr 2019 09:21:15 +0000 (10:21 +0100)
commit19d0e7ea41f1683872ad9adc2cfc5328007541f2
tree8d63be135b02b24e36730c55b45496d2b78a683c
parent98ab2f7432e234f40256172474ba41f29d69de82
sched: Prevent recursion in io_schedule()

commit 9cff8adeaa34b5d2802f03f89803da57856b3b72 upstream.

io_schedule() calls blk_flush_plug() which, depending on the
contents of current->plug, can initiate arbitrary blk-io requests.

Note that this contrasts with blk_schedule_flush_plug() which requires
all non-trivial work to be handed off to a separate thread.

This makes it possible for io_schedule() to recurse, and initiating
block requests could possibly call mempool_alloc() which, in times of
memory pressure, uses io_schedule().

Apart from any stack usage issues, io_schedule() will not behave
correctly when called recursively as delayacct_blkio_start() does
not allow for repeated calls.

So:
 - use ->in_iowait to detect recursion.  Set it earlier, and restore
   it to the old value.
 - move the call to "raw_rq" after the call to blk_flush_plug().
   As this is some sort of per-cpu thing, we want some chance that
   we are on the right CPU
 - When io_schedule() is called recurively, use blk_schedule_flush_plug()
   which cannot further recurse.
 - as this makes io_schedule() a lot more complex and as io_schedule()
   must match io_schedule_timeout(), but all the changes in io_schedule_timeout()
   and make io_schedule a simple wrapper for that.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
[ Moved the now rudimentary io_schedule() into sched.h. ]
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Tony Battersby <tonyb@cybernetics.com>
Link: http://lkml.kernel.org/r/20150213162600.059fffb2@notabene.brown
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Change-Id: Ic32d78863e35db89c3e8f0b29dcf20cb563dc70f
include/linux/sched.h
kernel/sched/core.c