Commit afdb4fa2 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] PATCH 15/16: NFSD: TCP: Limit number of active tcp connections to an RPC service

Limit number of active tcp connections to an RPC service

If a connection comes in and that results in number of
connections being more than 5 times the number of threads,
then we close a connection.

We randomly drop with the oldest or the newest connection.

Thus if we are flooded with connection requests, some will
get in and hopefully stay long enough to service at least one request.
parent 4e2f6bfe
......@@ -38,6 +38,7 @@ struct svc_serv {
struct list_head sv_permsocks; /* all permanent sockets */
struct list_head sv_tempsocks; /* all temporary sockets */
int sv_tmpcnt; /* count of temporary sockets */
char * sv_name; /* service name */
};
......
......@@ -243,10 +243,25 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
* Release a socket after use.
*/
static inline void
svc_sock_put(struct svc_sock *svsk)
{
struct svc_serv *serv = svsk->sk_server;
spin_lock_bh(&serv->sv_lock);
if (!--(svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) {
spin_unlock_bh(&serv->sv_lock);
dprintk("svc: releasing dead socket\n");
sock_release(svsk->sk_sock);
kfree(svsk);
}
else
spin_unlock_bh(&serv->sv_lock);
}
static void
svc_sock_release(struct svc_rqst *rqstp)
{
struct svc_sock *svsk = rqstp->rq_sock;
struct svc_serv *serv = svsk->sk_server;
svc_release_skb(rqstp);
......@@ -265,15 +280,7 @@ svc_sock_release(struct svc_rqst *rqstp)
svc_reserve(rqstp, 0);
rqstp->rq_sock = NULL;
spin_lock_bh(&serv->sv_lock);
if (!--(svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) {
spin_unlock_bh(&serv->sv_lock);
dprintk("svc: releasing dead socket\n");
sock_release(svsk->sk_sock);
kfree(svsk);
}
else
spin_unlock_bh(&serv->sv_lock);
svc_sock_put(svsk);
}
/*
......@@ -698,6 +705,35 @@ svc_tcp_accept(struct svc_sock *svsk)
set_bit(SK_DATA, &newsvsk->sk_flags);
svc_sock_enqueue(newsvsk);
/* make sure that we don't have too many active connections.
* If we have, something must be dropped.
* We randomly choose between newest and oldest (in terms
* of recent activity) and drop it.
*/
if (serv->sv_tmpcnt > serv->sv_nrthreads*5) {
struct svc_sock *svsk = NULL;
spin_lock_bh(&serv->sv_lock);
if (!list_empty(&serv->sv_tempsocks)) {
if (net_random()&1)
svsk = list_entry(serv->sv_tempsocks.prev,
struct svc_sock,
sk_list);
else
svsk = list_entry(serv->sv_tempsocks.next,
struct svc_sock,
sk_list);
set_bit(SK_CLOSE, &svsk->sk_flags);
svsk->sk_inuse ++;
}
spin_unlock_bh(&serv->sv_lock);
if (svsk) {
svc_sock_enqueue(svsk);
svc_sock_put(svsk);
}
}
if (serv->sv_stats)
serv->sv_stats->nettcpconn++;
......@@ -1138,6 +1174,7 @@ if (svsk->sk_sk == NULL)
if (!pmap_register) {
set_bit(SK_TEMP, &svsk->sk_flags);
list_add(&svsk->sk_list, &serv->sv_tempsocks);
serv->sv_tmpcnt++;
} else {
clear_bit(SK_TEMP, &svsk->sk_flags);
list_add(&svsk->sk_list, &serv->sv_permsocks);
......@@ -1217,6 +1254,8 @@ svc_delete_socket(struct svc_sock *svsk)
spin_lock_bh(&serv->sv_lock);
list_del(&svsk->sk_list);
if (test_bit(SK_TEMP, &svsk->sk_flags))
serv->sv_tmpcnt--;
if (test_bit(SK_QUED, &svsk->sk_flags))
list_del(&svsk->sk_ready);
......
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