Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[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>

+62 -8
+22 -1
fs/cifs/cifsfs.c
··· 32 32 #include <linux/seq_file.h> 33 33 #include <linux/vfs.h> 34 34 #include <linux/mempool.h> 35 + #include <linux/delay.h> 35 36 #include "cifsfs.h" 36 37 #include "cifspdu.h" 37 38 #define DECLARE_GLOBALS_HERE ··· 430 429 { 431 430 cFYI(1,("wake up tasks now - umount begin not complete")); 432 431 wake_up_all(&tcon->ses->server->request_q); 432 + wake_up_all(&tcon->ses->server->response_q); 433 + msleep(1); /* yield */ 434 + /* we have to kick the requests once more */ 435 + wake_up_all(&tcon->ses->server->response_q); 436 + msleep(1); 433 437 } 434 438 /* BB FIXME - finish add checks for tidStatus BB */ 435 439 ··· 901 895 902 896 static int cifs_dnotify_thread(void * dummyarg) 903 897 { 898 + struct list_head *tmp; 899 + struct cifsSesInfo *ses; 900 + 904 901 daemonize("cifsdnotifyd"); 905 902 allow_signal(SIGTERM); 906 903 ··· 912 903 if(try_to_freeze()) 913 904 continue; 914 905 set_current_state(TASK_INTERRUPTIBLE); 915 - schedule_timeout(39*HZ); 906 + schedule_timeout(15*HZ); 907 + read_lock(&GlobalSMBSeslock); 908 + /* check if any stuck requests that need 909 + to be woken up and wakeq so the 910 + thread can wake up and error out */ 911 + list_for_each(tmp, &GlobalSMBSessionList) { 912 + ses = list_entry(tmp, struct cifsSesInfo, 913 + cifsSessionList); 914 + if(ses && ses->server && 915 + atomic_read(&ses->server->inSend)) 916 + wake_up_all(&ses->server->response_q); 917 + } 918 + read_unlock(&GlobalSMBSeslock); 916 919 } while(!signal_pending(current)); 917 920 complete_and_exit (&cifs_dnotify_exited, 0); 918 921 }
+25
fs/cifs/cifssmb.c
··· 90 90 check for tcp and smb session status done differently 91 91 for those three - in the calling routine */ 92 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 105 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 94 106 (tcon->ses->server)){ 95 107 struct nls_table *nls_codepage; ··· 199 187 check for tcp and smb session status done differently 200 188 for those three - in the calling routine */ 201 189 if(tcon) { 190 + if(tcon->tidStatus == CifsExiting) { 191 + /* only tree disconnect, open, and write, 192 + (and ulogoff which does not have tcon) 193 + are allowed as we start force umount */ 194 + if((smb_command != SMB_COM_WRITE_ANDX) && 195 + (smb_command != SMB_COM_OPEN_ANDX) && 196 + (smb_command != SMB_COM_TREE_DISCONNECT)) { 197 + cFYI(1,("can not send cmd %d while umounting", 198 + smb_command)); 199 + return -ENODEV; 200 + } 201 + } 202 + 202 203 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 203 204 (tcon->ses->server)){ 204 205 struct nls_table *nls_codepage;
+12 -5
fs/cifs/misc.c
··· 397 397 if(smb->Command == SMB_COM_LOCKING_ANDX) 398 398 return 0; 399 399 else 400 - cERROR(1, ("Rcvd Request not response ")); 400 + cERROR(1, ("Rcvd Request not response")); 401 401 } 402 402 } else { /* bad signature or mid */ 403 403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) 404 404 cERROR(1, 405 - ("Bad protocol string signature header %x ", 405 + ("Bad protocol string signature header %x", 406 406 *(unsigned int *) smb->Protocol)); 407 407 if (mid != smb->Mid) 408 408 cERROR(1, ("Mids do not match")); ··· 417 417 __u32 len = smb->smb_buf_length; 418 418 __u32 clc_len; /* calculated length */ 419 419 cFYI(0, 420 - ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 420 + ("Entering checkSMB with Length: %x, smb_buf_length: %x", 421 421 length, len)); 422 422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || 423 423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { ··· 451 451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); 452 452 /* Windows XP can return a few bytes too much, presumably 453 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 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 464 return 0; 458 465 else 459 466 return 1;
+2 -2
fs/cifs/netmisc.c
··· 330 330 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { 331 331 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { 332 332 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { 333 - ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { 333 + ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { 334 334 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { 335 335 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { 336 336 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { ··· 676 676 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { 677 677 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { 678 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 680 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { 681 681 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { 682 682 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
+1
fs/cifs/transport.c
··· 515 515 *pbytes_returned = in_buf->smb_buf_length; 516 516 517 517 /* BB special case reconnect tid and uid here? */ 518 + /* BB special case Errbadpassword and pwdexpired here */ 518 519 rc = map_smb_to_linux_error(in_buf); 519 520 520 521 /* convert ByteCount if necessary */