virtiofs: schedule blocking async replies in separate worker
authorVivek Goyal <vgoyal@redhat.com>
Mon, 20 Apr 2020 15:01:34 +0000 (17:01 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Jun 2020 15:48:35 +0000 (17:48 +0200)
commite4d94478e2d786d0ad2b1fafd170d3d65d9105b6
treeee7d3f43ffa57beb8c7ec0e3554709345aca9723
parent8c1027c3ee0bbfcbe99a867228658b70a7c6fa40
virtiofs: schedule blocking async replies in separate worker

[ Upstream commit bb737bbe48bea9854455cb61ea1dc06e92ce586c ]

In virtiofs (unlike in regular fuse) processing of async replies is
serialized.  This can result in a deadlock in rare corner cases when
there's a circular dependency between the completion of two or more async
replies.

Such a deadlock can be reproduced with xfstests:generic/503 if TEST_DIR ==
SCRATCH_MNT (which is a misconfiguration):

 - Process A is waiting for page lock in worker thread context and blocked
   (virtio_fs_requests_done_work()).
 - Process B is holding page lock and waiting for pending writes to
   finish (fuse_wait_on_page_writeback()).
 - Write requests are waiting in virtqueue and can't complete because
   worker thread is blocked on page lock (process A).

Fix this by creating a unique work_struct for each async reply that can
block (O_DIRECT read).

Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem")
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/virtio_fs.c