Commit 620bde45 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sunrpc: connection dropping tweaks

From: Olaf Kirch <okir@suse.de>

Some NFS clients respond badly to a TCP connection being reset immediately
after it has been accepted so:

- Accept more connections before starting to drop them

- Always drop the oldest connection - Random Early Drop doesn't really help
  here, and can hurt

- ratelimit the friendly warnings.
parent d1e069e2
...@@ -828,21 +828,38 @@ svc_tcp_accept(struct svc_sock *svsk) ...@@ -828,21 +828,38 @@ svc_tcp_accept(struct svc_sock *svsk)
/* make sure that we don't have too many active connections. /* make sure that we don't have too many active connections.
* If we have, something must be dropped. * If we have, something must be dropped.
* We randomly choose between newest and oldest (in terms *
* of recent activity) and drop it. * There's no point in trying to do random drop here for
* DoS prevention. The NFS clients does 1 reconnect in 15
* seconds. An attacker can easily beat that.
*
* The only somewhat efficient mechanism would be if drop
* old connections from the same IP first. But right now
* we don't even record the client IP in svc_sock.
*/ */
if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*5) { if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) {
struct svc_sock *svsk = NULL; struct svc_sock *svsk = NULL;
spin_lock_bh(&serv->sv_lock); spin_lock_bh(&serv->sv_lock);
if (!list_empty(&serv->sv_tempsocks)) { if (!list_empty(&serv->sv_tempsocks)) {
if (net_random()&1) if (net_ratelimit()) {
/* Try to help the admin */
printk(KERN_NOTICE "%s: too many open TCP "
"sockets, consider increasing the "
"number of nfsd threads\n",
serv->sv_name);
printk(KERN_NOTICE "%s: last TCP connect from "
"%u.%u.%u.%u:%d\n",
serv->sv_name,
NIPQUAD(sin.sin_addr.s_addr),
ntohs(sin.sin_port));
}
/*
* Always select the oldest socket. It's not fair,
* but so is life
*/
svsk = list_entry(serv->sv_tempsocks.prev, svsk = list_entry(serv->sv_tempsocks.prev,
struct svc_sock, struct svc_sock,
sk_list); sk_list);
else
svsk = list_entry(serv->sv_tempsocks.next,
struct svc_sock,
sk_list);
set_bit(SK_CLOSE, &svsk->sk_flags); set_bit(SK_CLOSE, &svsk->sk_flags);
svsk->sk_inuse ++; svsk->sk_inuse ++;
} }
......
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