server->workstation_RFC1001_name);
}
if(rc) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(3 * HZ);
+ msleep(3000);
} else {
atomic_inc(&tcpSesReconnectCount);
spin_lock(&GlobalMid_Lock);
if(server->tcpStatus == CifsExiting) {
break;
} else if (server->tcpStatus == CifsNeedReconnect) {
- cFYI(1,("Reconnecting after server stopped responding"));
+ cFYI(1,("Reconnect after server stopped responding"));
cifs_reconnect(server);
cFYI(1,("call to reconnect done"));
csocket = server->ssocket;
continue;
} else if (length <= 0) {
if(server->tcpStatus == CifsNew) {
- cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
+ cFYI(1,("tcp session abend after SMBnegprot"));
/* some servers kill the TCP session rather than
returning an SMB negprot error, in which
case reconnecting here is not going to help,
cFYI(1,("cifsd thread killed"));
break;
}
- cFYI(1,("Reconnecting after unexpected peek error %d",length));
+ cFYI(1,("Reconnect after unexpected peek error %d",
+ length));
cifs_reconnect(server);
csocket = server->ssocket;
wake_up(&server->response_q);
continue;
} else if (length < 4) {
cFYI(1,
- ("Frame less than four bytes received %d bytes long.",
+ ("Frame under four bytes received (%d bytes long)",
length));
cifs_reconnect(server);
csocket = server->ssocket;
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", mid_entry->mid));
-
if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
/* We have a multipart transact2 resp */
+ isMultiRsp = TRUE;
if(mid_entry->resp_buf) {
/* merge response - fix up 1st*/
if(coalesce_t2(smb_buffer,
mid_entry->resp_buf)) {
- isMultiRsp = TRUE;
break;
} else {
/* all parts received */
/* BB maybe we can fix this up, switch
to already allocated large buffer? */
} else {
+ /* Have first buffer */
mid_entry->resp_buf =
smb_buffer;
mid_entry->largeBuf = 1;
- isMultiRsp = TRUE;
bigbuf = NULL;
}
}
}
spin_unlock(&GlobalMid_Lock);
if (task_to_wake) {
- if(isLargeBuf)
- bigbuf = NULL;
- else
- smallbuf = NULL;
- /* smb buffer freed by user thread when done */
+ /* Was previous buf put in mpx struct for multi-rsp? */
+ if(!isMultiRsp) {
+ /* smb buffer will be freed by user thread */
+ if(isLargeBuf) {
+ bigbuf = NULL;
+ } else
+ smallbuf = NULL;
+ }
wake_up_process(task_to_wake);
- } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
+ } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
&& (isMultiRsp == FALSE)) {
cERROR(1, ("No task to wake, unknown frame rcvd!"));
cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
server->tsk = NULL;
- atomic_set(&server->inFlight, 0);
+ /* check if we have blocked requests that need to free */
+ /* Note that cifs_max_pending is normally 50, but
+ can be set at module install time to as little as two */
+ if(atomic_read(&server->inFlight) >= cifs_max_pending)
+ atomic_set(&server->inFlight, cifs_max_pending - 1);
+ /* We do not want to set the max_pending too low or we
+ could end up with the counter going negative */
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
}
read_unlock(&GlobalSMBSeslock);
} else {
+ /* although we can not zero the server struct pointer yet,
+ since there are active requests which may depnd on them,
+ mark the corresponding SMB sessions as exiting too */
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ ses = list_entry(tmp, struct cifsSesInfo,
+ cifsSessionList);
+ if (ses->server == server) {
+ ses->status = CifsExiting;
+ }
+ }
+
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
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 */
+ /* due to delays on oplock break requests, we need
+ to wait at least 45 seconds before giving up
+ on a request getting a response and going ahead
+ and killing cifsd */
cFYI(1, ("Wait for exit from demultiplex thread"));
- msleep(46);
+ msleep(46000);
/* 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;
+
+ /* last chance to mark ses pointers invalid
+ if there are any pointing to this (e.g
+ if a crazy root user tried to kill cifsd
+ kernel thread explicitly this might happen) */
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ ses = list_entry(tmp, struct cifsSesInfo,
+ cifsSessionList);
+ if (ses->server == server) {
+ ses->server = NULL;
+ }
+ }
write_unlock(&GlobalSMBSeslock);
+
+ kfree(server);
if(length > 0) {
mempool_resize(cifs_req_poolp,
length + cifs_min_rcv,