]> git.karo-electronics.de Git - karo-tx-linux.git/commit
ufs: avoid grabbing ->truncate_mutex if possible
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 15 Jun 2017 04:17:30 +0000 (00:17 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 15 Jun 2017 04:41:18 +0000 (00:41 -0400)
commit09bf4f5b6e6013f0ad6b090d4a8deebd4e56d878
tree9fdf602d8c5ce36c60e12f3363658882b138c15f
parent267309f394bf3cd8db001992890b1fa52b97974e
ufs: avoid grabbing ->truncate_mutex if possible

tail unpacking is done in a wrong place; the deadlocks galore
is best dealt with by doing that in ->write_iter() (and switching
to iomap, while we are at it), but that's rather painful to
backport.  The trouble comes from grabbing pages that cover
the beginning of tail from inside of ufs_new_fragments(); ongoing
pageout of any of those is going to deadlock on ->truncate_mutex
with process that got around to extending the tail holding that
and waiting for page to get unlocked, while ->writepage() on
that page is waiting on ->truncate_mutex.

The thing is, we don't need ->truncate_mutex when the fragment
we are trying to map is within the tail - the damn thing is
allocated (tail can't contain holes).

Let's do a plain lookup and if the fragment is present, we can
just pretend that we'd won the race in almost all cases.  The
only exception is a fragment between the end of tail and the
end of block containing tail.

Protect ->i_lastfrag with ->meta_lock - read_seqlock_excl() is
sufficient.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ufs/balloc.c
fs/ufs/inode.c