summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2025-04-28 11:05:00 -0300
committerSteve French <stfrench@microsoft.com>2025-05-14 19:26:42 -0500
commitc94ef99937ec2add5e524f77bf777aef21acc201 (patch)
treeff37646fc0d1fa2e57a609619a82054079f3fc3d
parent3965c23773e81c476f6de30ccc5d201c59ff9714 (diff)
downloadlinux-c94ef99937ec2add5e524f77bf777aef21acc201.tar.gz
linux-c94ef99937ec2add5e524f77bf777aef21acc201.tar.bz2
linux-c94ef99937ec2add5e524f77bf777aef21acc201.zip
smb: client: fix delay on concurrent opens
Customers have reported open(2) calls being delayed by 30s or so, and looking through the network traces, it is related to the client not sending lease break acks to the server when a lease is being downgraded from RWH to RW while having an open handle, causing concurrent opens to be delayed and then impacting performance. MS-SMB2 3.2.5.19.2: | If all open handles on this file are closed (that is, File.OpenTable | is empty for this file), the client SHOULD consider it as an implicit | acknowledgment of the lease break. No explicit acknowledgment is | required. Since we hold an active reference of the open file to process the lease break, then we should always send a lease break ack if required by the server. Cc: linux-cifs@vger.kernel.org Cc: David Howells <dhowells@redhat.com> Reported-by: Pierguido Lambri <plambri@redhat.com> Fixes: da787d5b7498 ("SMB3: Do not send lease break acknowledgment if all file handles have been closed") Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/client/file.c32
1 files changed, 10 insertions, 22 deletions
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 950aa4f912f5..a9233b33a002 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -3085,11 +3085,10 @@ void cifs_oplock_break(struct work_struct *work)
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
+ bool purge_cache = false;
struct tcon_link *tlink;
+ struct cifs_fid *fid;
int rc = 0;
- bool purge_cache = false, oplock_break_cancelled;
- __u64 persistent_fid, volatile_fid;
- __u16 net_fid;
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
TASK_UNINTERRUPTIBLE);
@@ -3136,32 +3135,21 @@ oplock_break_ack:
* file handles but cached, then schedule deferred close immediately.
* So, new open will not use cached handle.
*/
-
if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
cifs_close_deferred_file(cinode);
- persistent_fid = cfile->fid.persistent_fid;
- volatile_fid = cfile->fid.volatile_fid;
- net_fid = cfile->fid.netfid;
- oplock_break_cancelled = cfile->oplock_break_cancelled;
-
- _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
- /*
- * 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.
- */
- spin_lock(&cinode->open_file_lock);
- /* check list empty since can race with kill_sb calling tree disconnect */
- if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) {
- spin_unlock(&cinode->open_file_lock);
- rc = server->ops->oplock_response(tcon, persistent_fid,
- volatile_fid, net_fid, cinode);
+ fid = &cfile->fid;
+ /* MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) */
+ if (!cfile->oplock_break_cancelled) {
+ rc = server->ops->oplock_response(tcon, fid->persistent_fid,
+ fid->volatile_fid,
+ fid->netfid, cinode);
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
- } else
- spin_unlock(&cinode->open_file_lock);
+ }
cifs_put_tlink(tlink);
out:
+ _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
cifs_done_oplock_break(cinode);
}