Commit f120b7b2 authored by Steve French's avatar Steve French Committed by Steve French

Keep number of active (on the network at one time) requests (to a single cifs...

Keep number of active (on the network at one time) requests (to a single cifs server) below SMB maxmpx
parent 37a93ba7
......@@ -110,7 +110,8 @@ struct TCP_Server_Info {
struct sockaddr_in sockAddr;
struct sockaddr_in6 sockAddr6;
} addr;
wait_queue_head_t response_q;
wait_queue_head_t response_q;
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
struct list_head pending_mid_q;
void *Server_NlsInfo; /* BB - placeholder for future NLS info */
unsigned short server_codepage; /* codepage for the server */
......@@ -119,7 +120,8 @@ struct TCP_Server_Info {
char versionMajor;
char versionMinor;
int svlocal:1; /* local server or remote */
atomic_t socketUseCount; /* indicates if the server has any open cifs sessions */
atomic_t socketUseCount; /* number of open cifs sessions on socket */
atomic_t inFlight; /* number of requests on the wire to server */
enum statusEnum tcpStatus; /* what we think the status is */
struct semaphore tcpSem;
struct task_struct *tsk;
......@@ -163,7 +165,7 @@ struct cifsSesInfo {
struct semaphore sesSem;
struct cifsUidInfo *uidInfo; /* pointer to user info */
struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of CURRENT users of this ses */
atomic_t inUse; /* # of mounts (tree connections) on this ses */
enum statusEnum status;
__u32 sequence_number; /* needed for CIFS PDU signature */
__u16 ipc_tid; /* special tid for connection to IPC share */
......
......@@ -165,6 +165,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} else {
atomic_inc(&tcpSesReconnectCount);
server->tcpStatus = CifsGood;
atomic_set(&server->inFlight,0);
wake_up(&server->response_q);
}
}
......@@ -390,8 +391,14 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
}
}
server->tcpStatus = CifsExiting;
atomic_set(&server->inFlight, 0);
/* 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;
if(server->ssocket) {
sock_release(csocket);
......@@ -1211,8 +1218,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return rc;
} else {
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
/* BB Add code for ipv6 case too */
memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
atomic_set(&srvTcp->inFlight,0);
/* BB Add code for ipv6 case too */
srvTcp->ssocket = csocket;
srvTcp->protocolType = IPV4;
init_waitqueue_head(&srvTcp->response_q);
......@@ -2752,6 +2760,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
FreeXid(xid);
return 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 4); /* give captive thread time to exit */
if((ses->server) && (ses->server->ssocket)) {
......
......@@ -182,14 +182,34 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
long timeout;
struct mid_q_entry *midQ;
if ((ses == NULL) || (ses->server == NULL)) {
cERROR(1,("Null tcp session or smb session: %p",ses));
if (ses == NULL) {
cERROR(1,("Null smb session"));
return -EIO;
}
if(ses->server == NULL) {
cERROR(1,("Null tcp session"));
return -EIO;
}
/* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or
use ses->maxReq */
/* can not count locking commands against the total since
they are allowed to block on server */
if(long_op < 3) {
/* update # of requests on the wire to this server */
atomic_inc(&ses->server->inFlight);
}
if(atomic_read(&ses->server->inFlight) > 50) {
wait_event(ses->server->request_q,atomic_read(&ses->server->inFlight) <= 50);
}
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
if (ses->server->tcpStatus == CifsExiting) {
......@@ -210,6 +230,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL) {
up(&ses->server->tcpSem);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return -EIO;
}
......@@ -219,6 +244,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
("Illegal length, greater than maximum frame, %d ",
in_buf->smb_buf_length));
DeleteMidQEntry(midQ);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return -EIO;
}
......@@ -289,6 +319,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
}
spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return rc;
}
......@@ -341,12 +376,22 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
}
}
cifs_no_response_exit:
DeleteMidQEntry(midQ); /* BB what if process is killed?
- BB add background daemon to clean up Mid entries from
killed processes & test killing process with active mid */
DeleteMidQEntry(midQ);
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return rc;
out_unlock:
up(&ses->server->tcpSem);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return rc;
}
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