| From 181830a31022d258ecddd0418e7040b651b1705f Mon Sep 17 00:00:00 2001 |
| From: Pavel Shilovsky <pshilov@microsoft.com> |
| Date: Thu, 31 Oct 2019 14:18:57 -0700 |
| Subject: [PATCH] CIFS: Fix SMB2 oplock break processing |
| |
| commit fa9c2362497fbd64788063288dc4e74daf977ebb upstream. |
| |
| 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 <stable@vger.kernel.org> |
| Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c |
| index e311f58dc1c8..449d1584ff72 100644 |
| --- a/fs/cifs/smb2misc.c |
| +++ b/fs/cifs/smb2misc.c |
| @@ -673,10 +673,10 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) |
| spin_lock(&cifs_tcp_ses_lock); |
| list_for_each(tmp, &server->smb_ses_list) { |
| ses = list_entry(tmp, struct cifs_ses, smb_ses_list); |
| + |
| list_for_each(tmp1, &ses->tcon_list) { |
| tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); |
| |
| - cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); |
| spin_lock(&tcon->open_file_lock); |
| list_for_each(tmp2, &tcon->openFileList) { |
| cfile = list_entry(tmp2, struct cifsFileInfo, |
| @@ -688,6 +688,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) |
| continue; |
| |
| cifs_dbg(FYI, "file id match, oplock break\n"); |
| + cifs_stats_inc( |
| + &tcon->stats.cifs_stats.num_oplock_brks); |
| cinode = CIFS_I(d_inode(cfile->dentry)); |
| spin_lock(&cfile->file_info_lock); |
| if (!CIFS_CACHE_WRITE(cinode) && |
| @@ -720,9 +722,6 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) |
| return true; |
| } |
| spin_unlock(&tcon->open_file_lock); |
| - spin_unlock(&cifs_tcp_ses_lock); |
| - cifs_dbg(FYI, "No matching file for oplock break\n"); |
| - return true; |
| } |
| } |
| spin_unlock(&cifs_tcp_ses_lock); |
| -- |
| 2.7.4 |
| |