]> git.baikalelectronics.ru Git - kernel.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)
commit1821ae0d3f40bb179a263b2e1b6319b54d6d019f
tree9fdf602d8c5ce36c60e12f3363658882b138c15f
parent97e53206459bf3b79a7fec46b4b3c1aac5cdf751
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