aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-11-29 23:55:11 -0500
committerSteve French <sfrench@us.ibm.com>2005-11-29 23:55:11 -0500
commit6ab16d249513a50bef3f1b275cea6aa8d3f51832 (patch)
tree6440fb91b6336e3dc988f06d951ab272610000fb /fs/cifs
parent6473a559c336d5c407f9df412ca2f55357767ff8 (diff)
[CIFS] Fix umount --force to wake up the pending response queue, not just
the request queue. Also periodically wakeup response_q so threads can check if stuck requests have timed out. Workaround Windows server illegal smb length on transact2 findfirst response. Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.c23
-rw-r--r--fs/cifs/cifssmb.c25
-rw-r--r--fs/cifs/misc.c17
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/transport.c1
5 files changed, 62 insertions, 8 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 51548ed2e9cc..f4974b41e485 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -32,6 +32,7 @@
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/vfs.h> 33#include <linux/vfs.h>
34#include <linux/mempool.h> 34#include <linux/mempool.h>
35#include <linux/delay.h>
35#include "cifsfs.h" 36#include "cifsfs.h"
36#include "cifspdu.h" 37#include "cifspdu.h"
37#define DECLARE_GLOBALS_HERE 38#define DECLARE_GLOBALS_HERE
@@ -429,6 +430,11 @@ static void cifs_umount_begin(struct super_block * sblock)
429 { 430 {
430 cFYI(1,("wake up tasks now - umount begin not complete")); 431 cFYI(1,("wake up tasks now - umount begin not complete"));
431 wake_up_all(&tcon->ses->server->request_q); 432 wake_up_all(&tcon->ses->server->request_q);
433 wake_up_all(&tcon->ses->server->response_q);
434 msleep(1); /* yield */
435 /* we have to kick the requests once more */
436 wake_up_all(&tcon->ses->server->response_q);
437 msleep(1);
432 } 438 }
433/* BB FIXME - finish add checks for tidStatus BB */ 439/* BB FIXME - finish add checks for tidStatus BB */
434 440
@@ -895,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg)
895 901
896static int cifs_dnotify_thread(void * dummyarg) 902static int cifs_dnotify_thread(void * dummyarg)
897{ 903{
904 struct list_head *tmp;
905 struct cifsSesInfo *ses;
906
898 daemonize("cifsdnotifyd"); 907 daemonize("cifsdnotifyd");
899 allow_signal(SIGTERM); 908 allow_signal(SIGTERM);
900 909
@@ -903,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg)
903 if(try_to_freeze()) 912 if(try_to_freeze())
904 continue; 913 continue;
905 set_current_state(TASK_INTERRUPTIBLE); 914 set_current_state(TASK_INTERRUPTIBLE);
906 schedule_timeout(39*HZ); 915 schedule_timeout(15*HZ);
916 read_lock(&GlobalSMBSeslock);
917 /* check if any stuck requests that need
918 to be woken up and wakeq so the
919 thread can wake up and error out */
920 list_for_each(tmp, &GlobalSMBSessionList) {
921 ses = list_entry(tmp, struct cifsSesInfo,
922 cifsSessionList);
923 if(ses && ses->server &&
924 atomic_read(&ses->server->inSend))
925 wake_up_all(&ses->server->response_q);
926 }
927 read_unlock(&GlobalSMBSeslock);
907 } while(!signal_pending(current)); 928 } while(!signal_pending(current));
908 complete_and_exit (&cifs_dnotify_exited, 0); 929 complete_and_exit (&cifs_dnotify_exited, 0);
909} 930}
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d179b0c3eee4..6867e556d37e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
90 check for tcp and smb session status done differently 90 check for tcp and smb session status done differently
91 for those three - in the calling routine */ 91 for those three - in the calling routine */
92 if(tcon) { 92 if(tcon) {
93 if(tcon->tidStatus == CifsExiting) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command != SMB_COM_WRITE_ANDX) &&
98 (smb_command != SMB_COM_OPEN_ANDX) &&
99 (smb_command != SMB_COM_TREE_DISCONNECT)) {
100 cFYI(1,("can not send cmd %d while umounting",
101 smb_command));
102 return -ENODEV;
103 }
104 }
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 105 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){ 106 (tcon->ses->server)){
95 struct nls_table *nls_codepage; 107 struct nls_table *nls_codepage;
@@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
187 check for tcp and smb session status done differently 199 check for tcp and smb session status done differently
188 for those three - in the calling routine */ 200 for those three - in the calling routine */
189 if(tcon) { 201 if(tcon) {
202 if(tcon->tidStatus == CifsExiting) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command != SMB_COM_WRITE_ANDX) &&
207 (smb_command != SMB_COM_OPEN_ANDX) &&
208 (smb_command != SMB_COM_TREE_DISCONNECT)) {
209 cFYI(1,("can not send cmd %d while umounting",
210 smb_command));
211 return -ENODEV;
212 }
213 }
214
190 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 215 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
191 (tcon->ses->server)){ 216 (tcon->ses->server)){
192 struct nls_table *nls_codepage; 217 struct nls_table *nls_codepage;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index ca27a82c54cd..94baf6c8ecbd 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -397,12 +397,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
397 if(smb->Command == SMB_COM_LOCKING_ANDX) 397 if(smb->Command == SMB_COM_LOCKING_ANDX)
398 return 0; 398 return 0;
399 else 399 else
400 cERROR(1, ("Rcvd Request not response ")); 400 cERROR(1, ("Rcvd Request not response"));
401 } 401 }
402 } else { /* bad signature or mid */ 402 } else { /* bad signature or mid */
403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) 403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
404 cERROR(1, 404 cERROR(1,
405 ("Bad protocol string signature header %x ", 405 ("Bad protocol string signature header %x",
406 *(unsigned int *) smb->Protocol)); 406 *(unsigned int *) smb->Protocol));
407 if (mid != smb->Mid) 407 if (mid != smb->Mid)
408 cERROR(1, ("Mids do not match")); 408 cERROR(1, ("Mids do not match"));
@@ -417,7 +417,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
417 __u32 len = smb->smb_buf_length; 417 __u32 len = smb->smb_buf_length;
418 __u32 clc_len; /* calculated length */ 418 __u32 clc_len; /* calculated length */
419 cFYI(0, 419 cFYI(0,
420 ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 420 ("Entering checkSMB with Length: %x, smb_buf_length: %x",
421 length, len)); 421 length, len));
422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || 422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { 423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
@@ -451,9 +451,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); 451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
452 /* Windows XP can return a few bytes too much, presumably 452 /* Windows XP can return a few bytes too much, presumably
453 an illegal pad, at the end of byte range lock responses 453 an illegal pad, at the end of byte range lock responses
454 so we allow for up to eight byte pad, as long as actual 454 so we allow for that three byte pad, as long as actual
455 received length is as long or longer than calculated length */ 455 received length is as long or longer than calculated length */
456 if((4+len > clc_len) && (len <= clc_len + 3)) 456 /* We have now had to extend this more, since there is a
457 case in which it needs to be bigger still to handle a
458 malformed response to transact2 findfirst from WinXP when
459 access denied is returned and thus bcc and wct are zero
460 but server says length is 0x21 bytes too long as if the server
461 forget to reset the smb rfc1001 length when it reset the
462 wct and bcc to minimum size and drop the t2 parms and data */
463 if((4+len > clc_len) && (len <= clc_len + 512))
457 return 0; 464 return 0;
458 else 465 else
459 return 1; 466 return 1;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index f7814689844b..5de74d216fdd 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -330,7 +330,7 @@ static const struct {
330 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { 330 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
331 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { 331 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
332 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { 332 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
333 ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { 333 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
334 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { 334 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
335 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { 335 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
336 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { 336 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
@@ -676,7 +676,7 @@ static const struct {
676 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { 676 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
677 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { 677 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
678 ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { 678 ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
679 ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, { 679 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, {
680 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { 680 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
681 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { 681 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
682 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { 682 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 41a9659c16bc..f8871196098c 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -515,6 +515,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
515 *pbytes_returned = in_buf->smb_buf_length; 515 *pbytes_returned = in_buf->smb_buf_length;
516 516
517 /* BB special case reconnect tid and uid here? */ 517 /* BB special case reconnect tid and uid here? */
518 /* BB special case Errbadpassword and pwdexpired here */
518 rc = map_smb_to_linux_error(in_buf); 519 rc = map_smb_to_linux_error(in_buf);
519 520
520 /* convert ByteCount if necessary */ 521 /* convert ByteCount if necessary */