mirror of
https://github.com/torvalds/linux.git
synced 2026-08-09 08:57:10 +02:00
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>
|
||
|---|---|---|
| .. | ||
| asn1.c | ||
| cache.c | ||
| cifs_debug.c | ||
| cifs_debug.h | ||
| cifs_dfs_ref.c | ||
| cifs_fs_sb.h | ||
| cifs_ioctl.h | ||
| cifs_spnego.c | ||
| cifs_spnego.h | ||
| cifs_unicode.c | ||
| cifs_unicode.h | ||
| cifs_uniupr.h | ||
| cifsacl.c | ||
| cifsacl.h | ||
| cifsencrypt.c | ||
| cifsfs.c | ||
| cifsfs.h | ||
| cifsglob.h | ||
| cifspdu.h | ||
| cifsproto.h | ||
| cifsroot.c | ||
| cifssmb.c | ||
| connect.c | ||
| dfs_cache.c | ||
| dfs_cache.h | ||
| dir.c | ||
| dns_resolve.c | ||
| dns_resolve.h | ||
| export.c | ||
| file.c | ||
| fscache.c | ||
| fscache.h | ||
| inode.c | ||
| ioctl.c | ||
| Kconfig | ||
| link.c | ||
| Makefile | ||
| misc.c | ||
| netmisc.c | ||
| nterr.c | ||
| nterr.h | ||
| ntlmssp.h | ||
| readdir.c | ||
| rfc1002pdu.h | ||
| sess.c | ||
| smb1ops.c | ||
| smb2file.c | ||
| smb2glob.h | ||
| smb2inode.c | ||
| smb2maperror.c | ||
| smb2misc.c | ||
| smb2ops.c | ||
| smb2pdu.c | ||
| smb2pdu.h | ||
| smb2proto.h | ||
| smb2status.h | ||
| smb2transport.c | ||
| smbdirect.c | ||
| smbdirect.h | ||
| smbencrypt.c | ||
| smberr.h | ||
| smbfsctl.h | ||
| trace.c | ||
| trace.h | ||
| transport.c | ||
| winucase.c | ||
| xattr.c | ||