[linux-cifs-client] [PATCH] [CIFS] Always match oplock break (cache
notification)s to the right tcp session when multiply mounted
Steve French
smfrench at austin.rr.com
Sat Mar 4 23:23:55 GMT 2006
Fixes slow response when cifs client is mounted to shares on multiple
servers and oplock break occurs (usually due to attempt to multiply open
a file). When treeids on mutiple mounted shares match and we find the
wrong match first, we searched for the wrong cached files to send oplock
break response for which usually meant that no matching file was found
and thus the server would have to timeout the notification. Oplock
break timeout is about 20 seconds on some servers so this could cause
significantly slower performance on file open calls in a few cases (in
particular when multiple shares are mounted from multiple servers, tree
ids match, and we have a cached file which is later opened multiple
times). This was the most important of the bugs that was found and
fixed at Connectathon (interoperability testing event) this week.
Acked-by: Shaggy (shaggy at austin.ibm.com)
Signed-off-by: Steve French (sfrench at us.ibm.com)
fs/cifs/cifsproto.h | 2 +-
fs/cifs/connect.c | 2 +-
fs/cifs/misc.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
@@ -52,7 +52,7 @@ extern int SendReceive2(const unsigned i
int * /* type of buf returned */ , const int
long_op);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
-extern int is_valid_oplock_break(struct smb_hdr *smb);
+extern int is_valid_oplock_break(struct smb_hdr *smb, struct
TCP_Server_Info *);
extern int is_size_safe_to_change(struct cifsInodeInfo *);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3651dec..0b86d5c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -630,7 +630,7 @@ multi_t2_fnd:
smallbuf = NULL;
}
wake_up_process(task_to_wake);
- } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
+ } else if ((is_valid_oplock_break(smb_buffer, server) ==
FALSE)
&& (isMultiRsp == FALSE)) {
cERROR(1, ("No task to wake, unknown frame rcvd!"));
cifs_dump_mem("Received Data is: ",(char
*)smb_buffer,
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 5d2fd70..fafd056 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -481,7 +481,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid,
return 0;
}
int
-is_valid_oplock_break(struct smb_hdr *buf)
+is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
{
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
struct list_head *tmp;
@@ -541,7 +541,7 @@ is_valid_oplock_break(struct smb_hdr *bu
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo,
cifsConnectionList);
- if (tcon->tid == buf->Tid) {
+ if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
cifs_stats_inc(&tcon->num_oplock_brks);
list_for_each(tmp1,&tcon->openFileList){
netfile = list_entry(tmp1,struct
cifsFileInfo,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: lost-oplock.diff
Type: text/x-patch
Size: 2096 bytes
Desc: not available
Url : http://lists.samba.org/archive/linux-cifs-client/attachments/20060304/8bd0329e/lost-oplock.bin
More information about the linux-cifs-client
mailing list