summary refs log tree commit diff
diff options
context:
space:
mode:
authorBharath SM <bharathsm@microsoft.com>2023-06-18 19:02:24 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-07-19 16:21:43 +0200
commit1bf709b9625001eefdd41048c5f4c7544ee33394 (patch)
treed0d82b534775c583c5213b16c7dea1d849c3c22d
parentc2bf8d7b8f025f4f8583daf8e6977ef742452b58 (diff)
downloadlinux-1bf709b9625001eefdd41048c5f4c7544ee33394.tar.gz
SMB3: Do not send lease break acknowledgment if all file handles have been closed
[ Upstream commit da787d5b74983f7525d1eb4b9c0b4aff2821511a ]

In case if all existing file handles are deferred handles and if all of
them gets closed due to handle lease break then we dont need to send
lease break acknowledgment to server, because last handle close will be
considered as lease break ack.
After closing deferred handels, we check for openfile list of inode,
if its empty then we skip sending lease break ack.

Fixes: 59a556aebc43 ("SMB3: drop reference to cfile before sending oplock break")
Reviewed-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/smb/client/file.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 87dcffece762..9a367d4c74e4 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -5140,20 +5140,19 @@ oplock_break_ack:
 
 	_cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
 	/*
-	 * releasing stale oplock after recent reconnect of smb session using
-	 * a now incorrect file handle is not a data integrity issue but do
-	 * not bother sending an oplock release if session to server still is
-	 * disconnected since oplock already released by the server
+	 * MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) do not require
+	 * an acknowledgment to be sent when the file has already been closed.
+	 * check for server null, since can race with kill_sb calling tree disconnect.
 	 */
-	if (!oplock_break_cancelled) {
-		/* check for server null since can race with kill_sb calling tree disconnect */
-		if (tcon->ses && tcon->ses->server) {
-			rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
-				volatile_fid, net_fid, cinode);
-			cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
-		} else
-			pr_warn_once("lease break not sent for unmounted share\n");
-	}
+	spin_lock(&cinode->open_file_lock);
+	if (tcon->ses && tcon->ses->server && !oplock_break_cancelled &&
+					!list_empty(&cinode->openFileList)) {
+		spin_unlock(&cinode->open_file_lock);
+		rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
+						volatile_fid, net_fid, cinode);
+		cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+	} else
+		spin_unlock(&cinode->open_file_lock);
 
 	cifs_done_oplock_break(cinode);
 }