summaryrefslogtreecommitdiff
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-28 22:41:11 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-28 22:41:11 -0700
commit31ca3bc3c569f9fe02aae6974ac3a9126f14902f (patch)
tree1ee90350d3ad6c2c3d59fa598c1440fcdf5a34e8 /fs/cifs/connect.c
parent57337e42f1393941d59d5154eed27a63988ff2be (diff)
downloadlwn-31ca3bc3c569f9fe02aae6974ac3a9126f14902f.tar.gz
lwn-31ca3bc3c569f9fe02aae6974ac3a9126f14902f.zip
[PATCH] cifs: Do not init smb requests or block when sending requests
if cifsd thread is no longer running to demultixplex responses. Do not send FindClose request when FindFirst failed without reaching end of search. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 437be1efe99e..ac1f970e5369 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -604,7 +604,13 @@ multi_t2_fnd:
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
@@ -640,6 +646,17 @@ multi_t2_fnd:
}
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);
@@ -661,17 +678,34 @@ multi_t2_fnd:
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,