reiserfs: fix deadlock in umount
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 5 Aug 2013 13:37:37 +0000 (17:37 +0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Aug 2013 05:59:10 +0000 (22:59 -0700)
commit71986ee029bada49f4517dbc6b0caf2243a566a2
tree02e002528032a0777ae0aa67ac998cca2f0ea11c
parenta9800654317a89b0224edbe51edcde8c54be2acc
reiserfs: fix deadlock in umount

commit 672fe15d091ce76d6fb98e489962e9add7c1ba4c upstream.

Since remove_proc_entry() started to wait for IO in progress (i.e.
since 2007 or so), the locking in fs/reiserfs/proc.c became wrong;
if procfs read happens between the moment when umount() locks the
victim superblock and removal of /proc/fs/reiserfs/<device>/*,
we'll get a deadlock - read will wait for s_umount (in sget(),
called by r_start()), while umount will wait in remove_proc_entry()
for that read to finish, holding s_umount all along.

Fortunately, the same change allows a much simpler race avoidance -
all we need to do is remove the procfs entries in the very beginning
of reiserfs ->kill_sb(); that'll guarantee that pointer to superblock
will remain valid for the duration for procfs IO, so we don't need
sget() to keep the sucker alive.  As the matter of fact, we can
get rid of the home-grown iterator completely, and use single_open()
instead.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/reiserfs/procfs.c
fs/reiserfs/super.c