summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilov@microsoft.com>2019-09-26 12:31:20 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-10-05 13:14:16 +0200
commit5bd1ab51d4c7b9b1eda9e125a386ec6b7596ffe5 (patch)
tree26ee844d68a7643f306fe000c95a47a247b87da4
parentb90f653c964e53808ca94413f37846193682041c (diff)
downloadlinux-stable-5bd1ab51d4c7b9b1eda9e125a386ec6b7596ffe5.tar.gz
linux-stable-5bd1ab51d4c7b9b1eda9e125a386ec6b7596ffe5.tar.bz2
linux-stable-5bd1ab51d4c7b9b1eda9e125a386ec6b7596ffe5.zip
CIFS: Fix oplock handling for SMB 2.1+ protocols
commit a016e2794fc3a245a91946038dd8f34d65e53cc3 upstream. There may be situations when a server negotiates SMB 2.1 protocol version or higher but responds to a CREATE request with an oplock rather than a lease. Currently the client doesn't handle such a case correctly: when another CREATE comes in the server sends an oplock break to the initial CREATE and the client doesn't send an ack back due to a wrong caching level being set (READ instead of RWH). Missing an oplock break ack makes the server wait until the break times out which dramatically increases the latency of the second CREATE. Fix this by properly detecting oplocks when using SMB 2.1 protocol version and higher. Cc: <stable@vger.kernel.org> Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/cifs/smb2ops.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b3eeb94f8b8b..0011e6bdaa9a 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -3254,6 +3254,11 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
return;
+ /* Check if the server granted an oplock rather than a lease */
+ if (oplock & SMB2_OPLOCK_LEVEL_EXCLUSIVE)
+ return smb2_set_oplock_level(cinode, oplock, epoch,
+ purge_cache);
+
if (oplock & SMB2_LEASE_READ_CACHING_HE) {
new_oplock |= CIFS_CACHE_READ_FLG;
strcat(message, "R");