Re: [PATCH v3 3/3] block: avoid to call .bi_end_io() recursively

From: Jens Axboe
Date: Mon May 02 2016 - 12:22:24 EST


On 04/27/2016 07:09 PM, Ming Lei wrote:
There were reports about heavy stack use by recursive calling
.bi_end_io()([1][2][3]). For example, more than 16K stack is
consumed in a single bio complete path[3], and in [2] stack
overflow can be triggered if 20 nested dm-crypt is used.

Also patches[1] [2] [3] were posted for addressing the issue,
but never be merged. And the idea in these patches is basically
similar, all serializes the recursive calling of .bi_end_io() by
percpu list.

This patch still takes the same idea, but uses bio_list to
implement it, which turns out more simple and the code becomes
more readable meantime.

One corner case which wasn't covered before is that
bi_endio() may be scheduled to run in process context(such
as btrfs), and this patch just bypasses the optimizing for
that case because one new context should have enough stack space,
and this approach isn't capable of optimizing it too because
there isn't easy way to get a per-task linked list head.

xfstests(-g auto) is run with this patch and no regression is
found on ext4, xfs and btrfs.

I don't like this at all, it's going about fixing this the completely wrong way. For the fast path, single device, we don't have an issue. Yet this patch slows down that part unnecessarily.

Fix this for the fat dm/md stacks, and don't add unwarranted fat in the normal fast path. The dm/md stacks won't notice a bit of extra overhead, whereas the core path is pretty well optimized.

--
Jens Axboe