gfs2: Fix mmap + page fault deadlocks for buffered I/O
authorAndreas Gruenbacher <agruenba@redhat.com>
Mon, 18 Oct 2021 17:21:44 +0000 (19:21 +0200)
committerAndreas Gruenbacher <agruenba@redhat.com>
Sun, 24 Oct 2021 13:26:05 +0000 (15:26 +0200)
commit00bfe02f479688a67a29019d1228f1470e26f014
tree971e8a104c7a8a7329cb19b37e2005844cafcb8e
parent1b223f7065bc7d89c4677c27381817cc95b117a8
gfs2: Fix mmap + page fault deadlocks for buffered I/O

In the .read_iter and .write_iter file operations, we're accessing
user-space memory while holding the inode glock.  There is a possibility
that the memory is mapped to the same file, in which case we'd recurse
on the same glock.

We could detect and work around this simple case of recursive locking,
but more complex scenarios exist that involve multiple glocks,
processes, and cluster nodes, and working around all of those cases
isn't practical or even possible.

Avoid these kinds of problems by disabling page faults while holding the
inode glock.  If a page fault would occur, we either end up with a
partial read or write or with -EFAULT if nothing could be read or
written.  In either case, we know that we're not done with the
operation, so we indicate that we're willing to give up the inode glock
and then we fault in the missing pages.  If that made us lose the inode
glock, we return a partial read or write.  Otherwise, we resume the
operation.

This locking problem was originally reported by Jan Kara.  Linus came up
with the idea of disabling page faults.  Many thanks to Al Viro and
Matthew Wilcox for their feedback.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/file.c