diff options
author | Steve French <sfrench@us.ibm.com> | 2006-03-04 22:39:55 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-03-04 22:39:55 -0500 |
commit | e77e6f3be93763ef88ccbaa9e0ebda5360d92f7c (patch) | |
tree | 35260c1d1968c448af77c267814d925d3c62f475 /fs/cifs | |
parent | 501f74f29498543c27f4f9697f5c1e980dd2de0d (diff) |
[CIFS] Always match oplock break (cache notification) to the right tcp
session when multiply mounted.
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@austin.ibm.com)
Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 | ||||
-rw-r--r-- | fs/cifs/misc.c | 4 |
3 files changed, 4 insertions, 4 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 3c03aadaff0c..7b25463d3c14 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -52,7 +52,7 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, | |||
52 | int * /* type of buf returned */ , const int long_op); | 52 | int * /* type of buf returned */ , const int long_op); |
53 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); | 53 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); |
54 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); | 54 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); |
55 | extern int is_valid_oplock_break(struct smb_hdr *smb); | 55 | extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); |
56 | extern int is_size_safe_to_change(struct cifsInodeInfo *); | 56 | extern int is_size_safe_to_change(struct cifsInodeInfo *); |
57 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); | 57 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); |
58 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 58 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ef5ae6f93c75..2a0c1f4ca0ae 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -630,7 +630,7 @@ multi_t2_fnd: | |||
630 | smallbuf = NULL; | 630 | smallbuf = NULL; |
631 | } | 631 | } |
632 | wake_up_process(task_to_wake); | 632 | wake_up_process(task_to_wake); |
633 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) | 633 | } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) |
634 | && (isMultiRsp == FALSE)) { | 634 | && (isMultiRsp == FALSE)) { |
635 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 635 | cERROR(1, ("No task to wake, unknown frame rcvd!")); |
636 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, | 636 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 812c6bb0fe38..432ba15e2c2d 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -475,7 +475,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
475 | return 0; | 475 | return 0; |
476 | } | 476 | } |
477 | int | 477 | int |
478 | is_valid_oplock_break(struct smb_hdr *buf) | 478 | is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) |
479 | { | 479 | { |
480 | struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; | 480 | struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; |
481 | struct list_head *tmp; | 481 | struct list_head *tmp; |
@@ -535,7 +535,7 @@ is_valid_oplock_break(struct smb_hdr *buf) | |||
535 | read_lock(&GlobalSMBSeslock); | 535 | read_lock(&GlobalSMBSeslock); |
536 | list_for_each(tmp, &GlobalTreeConnectionList) { | 536 | list_for_each(tmp, &GlobalTreeConnectionList) { |
537 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 537 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
538 | if (tcon->tid == buf->Tid) { | 538 | if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) { |
539 | cifs_stats_inc(&tcon->num_oplock_brks); | 539 | cifs_stats_inc(&tcon->num_oplock_brks); |
540 | list_for_each(tmp1,&tcon->openFileList){ | 540 | list_for_each(tmp1,&tcon->openFileList){ |
541 | netfile = list_entry(tmp1,struct cifsFileInfo, | 541 | netfile = list_entry(tmp1,struct cifsFileInfo, |