[ICSK]: Introduce reqsk_queue_prune from code in tcp_synack_timer

With this we're very close to getting all of the current TCP
refactorings in my dccp-2.6 tree merged, next changeset will export
some functions needed by the current DCCP code and then dccp-2.6.git
will be born!

Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index c03930c..b614ad4 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -424,16 +424,12 @@
 	sock_put(sk);
 }
 
-/*
- *	Timer for listening sockets
- */
-
-static void tcp_synack_timer(struct sock *sk)
+void reqsk_queue_prune(struct request_sock_queue *queue, struct sock *parent,
+		       const unsigned long interval, const unsigned long timeout,
+		       const unsigned long max_rto, int max_retries)
 {
-	struct tcp_sock *tp = tcp_sk(sk);
-	struct inet_connection_sock *icsk = inet_csk(sk);
-	struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
-	int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+	struct inet_connection_sock *icsk = inet_csk(parent);
+	struct listen_sock *lopt = queue->listen_opt;
 	int thresh = max_retries;
 	unsigned long now = jiffies;
 	struct request_sock **reqp, *req;
@@ -470,10 +466,10 @@
 		}
 	}
 
-	if (tp->defer_accept)
-		max_retries = tp->defer_accept;
+	if (queue->rskq_defer_accept)
+		max_retries = queue->rskq_defer_accept;
 
-	budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
+	budget = 2 * (lopt->nr_table_entries / (timeout / interval));
 	i = lopt->clock_hand;
 
 	do {
@@ -482,20 +478,19 @@
 			if (time_after_eq(now, req->expires)) {
 				if ((req->retrans < thresh ||
 				     (inet_rsk(req)->acked && req->retrans < max_retries))
-				    && !req->rsk_ops->rtx_syn_ack(sk, req, NULL)) {
+				    && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) {
 					unsigned long timeo;
 
 					if (req->retrans++ == 0)
 						lopt->qlen_young--;
-					timeo = min((TCP_TIMEOUT_INIT << req->retrans),
-						    TCP_RTO_MAX);
+					timeo = min((timeout << req->retrans), max_rto);
 					req->expires = now + timeo;
 					reqp = &req->dl_next;
 					continue;
 				}
 
 				/* Drop this request */
-				inet_csk_reqsk_queue_unlink(sk, req, reqp);
+				inet_csk_reqsk_queue_unlink(parent, req, reqp);
 				reqsk_queue_removed(&icsk->icsk_accept_queue, req);
 				reqsk_free(req);
 				continue;
@@ -503,14 +498,29 @@
 			reqp = &req->dl_next;
 		}
 
-		i = (i+1)&(TCP_SYNQ_HSIZE-1);
+		i = (i + 1) & (lopt->nr_table_entries - 1);
 
 	} while (--budget > 0);
 
 	lopt->clock_hand = i;
 
 	if (lopt->qlen)
-		inet_csk_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
+		inet_csk_reset_keepalive_timer(parent, interval);
+}
+
+EXPORT_SYMBOL_GPL(reqsk_queue_prune);
+
+/*
+ *	Timer for listening sockets
+ */
+
+static void tcp_synack_timer(struct sock *sk)
+{
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	const int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+
+	reqsk_queue_prune(&icsk->icsk_accept_queue, sk, TCP_SYNQ_INTERVAL,
+			  TCP_TIMEOUT_INIT, TCP_RTO_MAX, max_retries);
 }
 
 void tcp_set_keepalive(struct sock *sk, int val)