Skip to content

Commit fa9c236

Browse files
piastrysmfrench
authored andcommitted
CIFS: Fix SMB2 oplock break processing
Even when mounting modern protocol version the server may be configured without supporting SMB2.1 leases and the client uses SMB2 oplock to optimize IO performance through local caching. However there is a problem in oplock break handling that leads to missing a break notification on the client who has a file opened. It latter causes big latencies to other clients that are trying to open the same file. The problem reproduces when there are multiple shares from the same server mounted on the client. The processing code tries to match persistent and volatile file ids from the break notification with an open file but it skips all share besides the first one. Fix this by looking up in all shares belonging to the server that issued the oplock break. Cc: Stable <[email protected]> Signed-off-by: Pavel Shilovsky <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 3591bb8 commit fa9c236

File tree

1 file changed

+3
-4
lines changed

1 file changed

+3
-4
lines changed

fs/cifs/smb2misc.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -667,10 +667,10 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
667667
spin_lock(&cifs_tcp_ses_lock);
668668
list_for_each(tmp, &server->smb_ses_list) {
669669
ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
670+
670671
list_for_each(tmp1, &ses->tcon_list) {
671672
tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
672673

673-
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
674674
spin_lock(&tcon->open_file_lock);
675675
list_for_each(tmp2, &tcon->openFileList) {
676676
cfile = list_entry(tmp2, struct cifsFileInfo,
@@ -682,6 +682,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
682682
continue;
683683

684684
cifs_dbg(FYI, "file id match, oplock break\n");
685+
cifs_stats_inc(
686+
&tcon->stats.cifs_stats.num_oplock_brks);
685687
cinode = CIFS_I(d_inode(cfile->dentry));
686688
spin_lock(&cfile->file_info_lock);
687689
if (!CIFS_CACHE_WRITE(cinode) &&
@@ -714,9 +716,6 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
714716
return true;
715717
}
716718
spin_unlock(&tcon->open_file_lock);
717-
spin_unlock(&cifs_tcp_ses_lock);
718-
cifs_dbg(FYI, "No matching file for oplock break\n");
719-
return true;
720719
}
721720
}
722721
spin_unlock(&cifs_tcp_ses_lock);

0 commit comments

Comments
 (0)