} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { /* we get this from Windows 98 instead of error on SMB negprot response */ 
} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { /* we get this from Windows 98 instead of an error on SMB negprot response */ 
cifs_demultiplex_thread(struct TCP_Server_Info *server){	int length;	unsigned int pdu_length, total_read;	struct smb_hdr *smb_buffer = NULL;	struct smb_hdr *bigbuf = NULL;	struct smb_hdr *smallbuf = NULL;	struct msghdr smb_msg;	struct kvec iov;	struct socket *csocket = server->ssocket;	struct list_head *tmp;	struct cifsSesInfo *ses;	struct task_struct *task_to_wake = NULL;	struct mid_q_entry *mid_entry;	char *temp;	int isLargeBuf = FALSE;	daemonize("cifsd");	allow_signal(SIGKILL);	current->flags |= PF_MEMALLOC;	server->tsk = current;	/* save process info to wake at shutdown */	cFYI(1, ("Demultiplex PID: %d", current->pid));	write_lock(&GlobalSMBSeslock); 	atomic_inc(&tcpSesAllocCount);	length = tcpSesAllocCount.counter;	write_unlock(&GlobalSMBSeslock);	if(length  > 1) {		mempool_resize(cifs_req_poolp,			length + cifs_min_rcv,			GFP_KERNEL);	}	while (server->tcpStatus != CifsExiting) {		if (bigbuf == NULL) {			bigbuf = cifs_buf_get();			if(bigbuf == NULL) {				cERROR(1,("No memory for large SMB response"));				msleep(3000);				/* retry will check if exiting */				continue;			}		} else if(isLargeBuf) {			/* we are reusing a dirtry large buf, clear its start */			memset(bigbuf, 0, sizeof (struct smb_hdr));		}		if (smallbuf == NULL) {			smallbuf = cifs_small_buf_get();			if(smallbuf == NULL) {				cERROR(1,("No memory for SMB response"));				msleep(1000);				/* retry will check if exiting */				continue;			}			/* beginning of smb buffer is cleared in our buf_get */		} else /* if existing small buf clear beginning */			memset(smallbuf, 0, sizeof (struct smb_hdr));		isLargeBuf = FALSE;		smb_buffer = smallbuf;		iov.iov_base = smb_buffer;		iov.iov_len = 4;		smb_msg.msg_control = NULL;		smb_msg.msg_controllen = 0;		length =		    kernel_recvmsg(csocket, &smb_msg,				 &iov, 1, 4, 0 /* BB see socket.h flags */);		if(server->tcpStatus == CifsExiting) {			break;		} else if (server->tcpStatus == CifsNeedReconnect) {			cFYI(1,("Reconnecting after server stopped responding"));			cifs_reconnect(server);			cFYI(1,("call to reconnect done"));			csocket = server->ssocket;			continue;		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {			msleep(1); /* minimum sleep to prevent looping				allowing socket to clear and app threads to set				tcpStatus CifsNeedReconnect if server hung */			continue;		} else if (length <= 0) {			if(server->tcpStatus == CifsNew) {				cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));				/* some servers kill tcp session rather than returning					smb negprot error in which case reconnecting here is					not going to help - return error to mount */				break;			}			if(length == -EINTR) { 				cFYI(1,("cifsd thread killed"));				break;			}			cFYI(1,("Reconnecting after unexpected peek error %d",length));			cifs_reconnect(server);			csocket = server->ssocket;			wake_up(&server->response_q);			continue;		} else if (length > 3) {			pdu_length = ntohl(smb_buffer->smb_buf_length);		/* Only read pdu_length after below checks for too short (due		   to e.g. int overflow) and too long ie beyond end of buf */			cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));			temp = (char *) smb_buffer;			if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {				cFYI(0,("Received 4 byte keep alive packet"));			} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {					cFYI(1,("Good RFC 1002 session rsp"));			} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {				/* we get this from Windows 98 instead of error on SMB negprot response */				cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));				if(server->tcpStatus == CifsNew) {					/* if nack on negprot (rather than 					ret of smb negprot error) reconnecting					not going to help, ret error to mount */					break;				} else {					/* give server a second to					clean up before reconnect attempt */					msleep(1000);					/* always try 445 first on reconnect					since we get NACK on some if we ever					connected to port 139 (the NACK is 					since we do not begin with RFC1001					session initialize frame) */					server->addr.sockAddr.sin_port = htons(CIFS_PORT);					cifs_reconnect(server);					csocket = server->ssocket;					wake_up(&server->response_q);					continue;				}			} else if (temp[0] != (char) 0) {				cERROR(1,("Unknown RFC 1002 frame"));				cifs_dump_mem(" Received Data: ", temp, length);				cifs_reconnect(server);				csocket = server->ssocket;				continue;			} else {				if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)				    || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {					cERROR(1,					    ("Invalid size SMB length %d and pdu_length %d",						length, pdu_length+4));					cifs_reconnect(server);					csocket = server->ssocket;					wake_up(&server->response_q);					continue;				} else { /* length ok */					if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {						isLargeBuf = TRUE;						memcpy(bigbuf, smallbuf, 4);						smb_buffer = bigbuf;					}					length = 0;					iov.iov_base = 4 + (char *)smb_buffer;					iov.iov_len = pdu_length;					for (total_read = 0; 					     total_read < pdu_length;					     total_read += length) {						length = kernel_recvmsg(csocket, &smb_msg, 							&iov, 1,							pdu_length - total_read, 0);						if (length == 0) {							cERROR(1,							       ("Zero length receive when expecting %d ",								pdu_length - total_read));							cifs_reconnect(server);							csocket = server->ssocket;							wake_up(&server->response_q);							continue;						}					}					length += 4; /* account for rfc1002 hdr */				}				dump_smb(smb_buffer, length);				if (checkSMB				    (smb_buffer, smb_buffer->Mid, total_read+4)) {					cERROR(1, ("Bad SMB Received "));					continue;				}				task_to_wake = NULL;				spin_lock(&GlobalMid_Lock);				list_for_each(tmp, &server->pending_mid_q) {					mid_entry = list_entry(tmp, struct							       mid_q_entry,							       qhead);					if ((mid_entry->mid == smb_buffer->Mid)						&& (mid_entry->midState == 							MID_REQUEST_SUBMITTED) 						&& (mid_entry->command == 							smb_buffer->Command)) {						cFYI(1,("Found Mid 0x%x wake up"							,mid_entry->mid));						task_to_wake = mid_entry->tsk;						mid_entry->resp_buf =						    smb_buffer;						mid_entry->midState =						    MID_RESPONSE_RECEIVED;						if(isLargeBuf)							mid_entry->largeBuf = 1;						else							mid_entry->largeBuf = 0;					}				}				spin_unlock(&GlobalMid_Lock);				if (task_to_wake) {					if(isLargeBuf)						bigbuf = NULL;					else						smallbuf = NULL;					smb_buffer = NULL;	/* will be freed by users thread after he is done */					wake_up_process(task_to_wake);				} else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          					cERROR(1, ("No task to wake, unknown frame rcvd!"));					cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));				}			}		} else {			cFYI(1,			    ("Frame less than four bytes received  %d bytes long.",			      length));			cifs_reconnect(server);			csocket = server->ssocket;			wake_up(&server->response_q);			continue;		}	}	spin_lock(&GlobalMid_Lock);	server->tcpStatus = CifsExiting;	server->tsk = NULL;	atomic_set(&server->inFlight, 0);	spin_unlock(&GlobalMid_Lock);	/* Although there should not be any requests blocked on 	this queue it can not hurt to be paranoid and try to wake up requests	that may haven been blocked when more than 50 at time were on the wire 	to the same server - they now will see the session is in exit state	and get out of SendReceive.  */	wake_up_all(&server->request_q);	/* give those requests time to exit */	msleep(125);		if(server->ssocket) {		sock_release(csocket);		server->ssocket = NULL;	}	/* buffer usuallly freed in free_mid - need to free it here on exit */	if (bigbuf != NULL)		cifs_buf_release(bigbuf);	if (smallbuf != NULL)		cifs_small_buf_release(smallbuf);	read_lock(&GlobalSMBSeslock);	if (list_empty(&server->pending_mid_q)) {		/* loop through server session structures attached to this and mark them dead */		list_for_each(tmp, &GlobalSMBSessionList) {			ses =			    list_entry(tmp, struct cifsSesInfo,				       cifsSessionList);			if (ses->server == server) {				ses->status = CifsExiting;				ses->server = NULL;			}		}		read_unlock(&GlobalSMBSeslock);	} else {		spin_lock(&GlobalMid_Lock);		list_for_each(tmp, &server->pending_mid_q) {		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);			if (mid_entry->midState == MID_REQUEST_SUBMITTED) {				cFYI(1,					 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));				task_to_wake = mid_entry->tsk;				if(task_to_wake) {					wake_up_process(task_to_wake);				}			}		}		spin_unlock(&GlobalMid_Lock);		read_unlock(&GlobalSMBSeslock);		/* 1/8th of sec is more than enough time for them to exit */		msleep(125);	}	if (list_empty(&server->pending_mid_q)) {		/* mpx threads have not exited yet give them 		at least the smb send timeout time for long ops */		cFYI(1, ("Wait for exit from demultiplex thread"));		msleep(46);		/* if threads still have not exited they are probably never		coming home not much else we can do but free the memory */	}	kfree(server);	write_lock(&GlobalSMBSeslock);	atomic_dec(&tcpSesAllocCount);	length = tcpSesAllocCount.counter;	write_unlock(&GlobalSMBSeslock);	if(length  > 0) {		mempool_resize(cifs_req_poolp,			length + cifs_min_rcv,			GFP_KERNEL);	}		msleep(250);	return 0;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/09d1db5c6131232f764046160c29118cd4e5e646/connect.c/buggy/fs/cifs/connect.c