Commit 53aeeaaf authored by Steve French's avatar Steve French Committed by Steve French

Do not loop in cifsd demultiplex thread when someone sigkills it.

On unmount of second user on same tcp session, make sure that we
do not kill cifsd prematurely.

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent 0e9f1916
......@@ -6,7 +6,8 @@ is the usual maximum active multiplex SMB/CIFS requests per server).
Do not kill cifsd (and thus hurt the other SMB session) when more than one
session to the same server (but with different userids) exists and one
of the two user's smb sessions is being removed while leaving the other.
Do not loop reconnecting in cifsd demultiplex thread when admin
kills the thread without going through unmount.
Version 1.18
------------
......
......@@ -315,8 +315,6 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
return 0;
}
/* BB remove (from server) list of shares - but with smp safety BB */
/* BB is ses active - do we need to check here - but how? BB */
if((tcon->ses == 0) || (tcon->ses->server == 0)) {
up(&tcon->tconSem);
return -EIO;
......
......@@ -253,13 +253,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* 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 */
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
wake_up(&server->response_q);
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;
......@@ -292,11 +291,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* if nack on negprot (rather than
ret of smb negprot error) reconnecting
not going to help, ret error to mount */
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
/* wake up thread doing negprot */
wake_up(&server->response_q);
break;
} else {
/* give server a second to
......@@ -407,15 +401,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
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);
server->tsk = NULL;
/* give those requests time to exit */
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/8);
if(server->ssocket) {
sock_release(csocket);
server->ssocket = NULL;
......@@ -1358,31 +1356,37 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
}
if(pSesInfo) {
if (pSesInfo->capabilities & CAP_LARGE_FILES) {
cFYI(0, ("Large files supported "));
sb->s_maxbytes = (u64) 1 << 63;
} else
sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
}
/* on error free sesinfo and tcon struct if needed */
if (rc) {
/* if session setup failed, use count is zero but
we still need to free cifsd thread */
if(atomic_read(&srvTcp->socketUseCount) == 0) {
spin_lock(&GlobalMid_Lock);
srvTcp->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
if(srvTcp->tsk)
send_sig(SIGKILL,srvTcp->tsk,1);
}
/* If find_unc succeeded then rc == 0 so we can not end */
if (tcon) /* up here accidently freeing someone elses tcon struct */
if (tcon) /* up accidently freeing someone elses tcon struct */
tconInfoFree(tcon);
if (existingCifsSes == 0) {
if (pSesInfo) {
if (pSesInfo->server) {
if (pSesInfo->Suid)
CIFSSMBLogoff(xid, pSesInfo);
if(pSesInfo->server->tsk)
if ((pSesInfo->server) &&
(pSesInfo->status == CifsGood)) {
int temp_rc;
temp_rc = CIFSSMBLogoff(xid, pSesInfo);
/* if the socketUseCount is now zero */
if((temp_rc == -ESHUTDOWN) &&
(pSesInfo->server->tsk))
send_sig(SIGKILL,pSesInfo->server->tsk,1);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 4); /* give captive thread time to exit */
} else
cFYI(1, ("No session or bad tcon"));
sesInfoFree(pSesInfo);
......@@ -2791,12 +2795,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
FreeXid(xid);
return 0;
} else if (rc == -ESHUTDOWN) {
/* should we add wake_up_all(&server->request_q);
and add a check in the check inFlight loop
for the session ending */
set_current_state(TASK_INTERRUPTIBLE);
/* give captive thread time to exit */
schedule_timeout(HZ / 4);
cFYI(1,("Waking up socket by sending it signal"));
send_sig(SIGKILL,cifsd_task,1);
rc = 0;
......
......@@ -627,7 +627,6 @@ cifs_write(struct file * file, const char *write_data,
while we blocked so return what we managed to write */
return total_written;
}
open_file = (struct cifsFileInfo *) file->private_data;
if(open_file->closePend) {
FreeXid(xid);
if(total_written)
......
......@@ -215,8 +215,14 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
< CIFS_MAX_REQ);
spin_lock(&GlobalMid_Lock);
} else {
if(ses->server->tcpStatus == CifsExiting) {
spin_unlock(&GlobalMid_Lock);
return -ENOENT;
}
/* can not count locking commands against total since
they are allowed to block on server */
if(long_op < 3) {
/* update # of requests on the wire to server */
atomic_inc(&ses->server->inFlight);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment