Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ab16d24 authored by Steve French's avatar Steve French
Browse files

[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: default avatarSteve French <sfrench@us.ibm.com>
parent 6473a559
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/seq_file.h>
#include <linux/vfs.h>
#include <linux/mempool.h>
#include <linux/delay.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
@@ -429,6 +430,11 @@ static void cifs_umount_begin(struct super_block * sblock)
	{
		cFYI(1,("wake up tasks now - umount begin not complete"));
		wake_up_all(&tcon->ses->server->request_q);
		wake_up_all(&tcon->ses->server->response_q);
		msleep(1); /* yield */
		/* we have to kick the requests once more */
		wake_up_all(&tcon->ses->server->response_q);
		msleep(1);
	}
/* BB FIXME - finish add checks for tidStatus BB */

@@ -895,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg)

static int cifs_dnotify_thread(void * dummyarg)
{
	struct list_head *tmp;
	struct cifsSesInfo *ses;

	daemonize("cifsdnotifyd");
	allow_signal(SIGTERM);

@@ -903,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg)
		if(try_to_freeze())
			continue;
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(39*HZ);
		schedule_timeout(15*HZ);
		read_lock(&GlobalSMBSeslock);
		/* check if any stuck requests that need
		   to be woken up and wakeq so the
		   thread can wake up and error out */
		list_for_each(tmp, &GlobalSMBSessionList) {
			ses = list_entry(tmp, struct cifsSesInfo, 
				cifsSessionList);
			if(ses && ses->server && 
			     atomic_read(&ses->server->inSend))
				wake_up_all(&ses->server->response_q);
		}
		read_unlock(&GlobalSMBSeslock);
	} while(!signal_pending(current));
	complete_and_exit (&cifs_dnotify_exited, 0);
}
+25 −0
Original line number Diff line number Diff line
@@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
	   check for tcp and smb session status done differently
	   for those three - in the calling routine */
	if(tcon) {
		if(tcon->tidStatus == CifsExiting) {
			/* only tree disconnect, open, and write,
			(and ulogoff which does not have tcon)
			are allowed as we start force umount */
			if((smb_command != SMB_COM_WRITE_ANDX) && 
			   (smb_command != SMB_COM_OPEN_ANDX) && 
			   (smb_command != SMB_COM_TREE_DISCONNECT)) {
				cFYI(1,("can not send cmd %d while umounting",
					smb_command));
				return -ENODEV;
			}
		}
		if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
				  (tcon->ses->server)){
			struct nls_table *nls_codepage;
@@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
	   check for tcp and smb session status done differently
	   for those three - in the calling routine */
	if(tcon) {
		if(tcon->tidStatus == CifsExiting) {
			/* only tree disconnect, open, and write,
			  (and ulogoff which does not have tcon)
			  are allowed as we start force umount */
			if((smb_command != SMB_COM_WRITE_ANDX) &&
			   (smb_command != SMB_COM_OPEN_ANDX) &&
			   (smb_command != SMB_COM_TREE_DISCONNECT)) {
				cFYI(1,("can not send cmd %d while umounting",
					smb_command));
				return -ENODEV;
			}
		}

		if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
				  (tcon->ses->server)){
			struct nls_table *nls_codepage;
+12 −5
Original line number Diff line number Diff line
@@ -451,9 +451,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
		cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
		/* Windows XP can return a few bytes too much, presumably
		an illegal pad, at the end of byte range lock responses 
		so we allow for up to eight byte pad, as long as actual
		so we allow for that three byte pad, as long as actual
		received length is as long or longer than calculated length */
		if((4+len > clc_len) && (len <= clc_len + 3))
		/* We have now had to extend this more, since there is a 
		case in which it needs to be bigger still to handle a
		malformed response to transact2 findfirst from WinXP when
		access denied is returned and thus bcc and wct are zero
		but server says length is 0x21 bytes too long as if the server
		forget to reset the smb rfc1001 length when it reset the
		wct and bcc to minimum size and drop the t2 parms and data */
		if((4+len > clc_len) && (len <= clc_len + 512))
			return 0;
		else
			return 1;
+2 −2
Original line number Diff line number Diff line
@@ -330,7 +330,7 @@ static const struct {
	ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
	ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
	ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
	ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
	ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
	ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
	ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
@@ -676,7 +676,7 @@ static const struct {
	ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
	ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
	ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
	ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
	ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, {
	ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
	ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
	ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
+1 −0
Original line number Diff line number Diff line
@@ -515,6 +515,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
			*pbytes_returned = in_buf->smb_buf_length;

			/* BB special case reconnect tid and uid here? */
			/* BB special case Errbadpassword and pwdexpired here */
			rc = map_smb_to_linux_error(in_buf);

			/* convert ByteCount if necessary */