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;
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,