]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commit
cifs: Fix cifsInodeInfo lock_sem deadlock when reconnect occurs
authorDave Wysochanski <dwysocha@redhat.com>
Wed, 23 Oct 2019 09:02:33 +0000 (05:02 -0400)
committerStefan Bader <stefan.bader@canonical.com>
Tue, 26 Nov 2019 12:15:57 +0000 (13:15 +0100)
commit08a9932e75eca92e1c178b457c48cfdb778d27f7
tree8f72d3dd501c4f729749457aa7950a088409b311
parentcef3d1d4bd47572c2f14cf4595000e78f3d2f5ef
cifs: Fix cifsInodeInfo lock_sem deadlock when reconnect occurs

BugLink: https://bugs.launchpad.net/bugs/1853208
[ Upstream commit d46b0da7a33dd8c99d969834f682267a45444ab3 ]

There's a deadlock that is possible and can easily be seen with
a test where multiple readers open/read/close of the same file
and a disruption occurs causing reconnect.  The deadlock is due
a reader thread inside cifs_strict_readv calling down_read and
obtaining lock_sem, and then after reconnect inside
cifs_reopen_file calling down_read a second time.  If in
between the two down_read calls, a down_write comes from
another process, deadlock occurs.

        CPU0                    CPU1
        ----                    ----
cifs_strict_readv()
 down_read(&cifsi->lock_sem);
                               _cifsFileInfo_put
                                  OR
                               cifs_new_fileinfo
                                down_write(&cifsi->lock_sem);
cifs_reopen_file()
 down_read(&cifsi->lock_sem);

Fix the above by changing all down_write(lock_sem) calls to
down_write_trylock(lock_sem)/msleep() loop, which in turn
makes the second down_read call benign since it will never
block behind the writer while holding lock_sem.

Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
Suggested-by: Ronnie Sahlberg <lsahlber@redhat.com>
Reviewed--by: Ronnie Sahlberg <lsahlber@redhat.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/file.c
fs/cifs/smb2file.c