Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52841430 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'listener_refactor_part_12'



Eric Dumazet says:

====================
inet: tcp listener refactoring, part 12

By adding a pointer back to listener, we are preparing synack rtx
handling to no longer be governed by listener keepalive timer,
as this is the most problematic source of contention on listener
spinlock. Note that TCP FastOpen had such pointer anyway, so we
make it generic.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9f2dbdd9 0470c8ca
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ struct tcp_request_sock_ops;
struct tcp_request_sock {
	struct inet_request_sock 	req;
	const struct tcp_request_sock_ops *af_specific;
	struct sock			*listener; /* needed for TFO */
	bool				tfo_listener;
	u32				rcv_isn;
	u32				snt_isn;
	u32				snt_synack; /* synack sent time */
+0 −5
Original line number Diff line number Diff line
@@ -275,11 +275,6 @@ static inline void inet_csk_reqsk_queue_add(struct sock *sk,
					    struct sock *child)
{
	reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
	/* before letting lookups find us, make sure all req fields
	 * are committed to memory.
	 */
	smp_wmb();
	atomic_set(&req->rsk_refcnt, 1);
}

void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
+2 −20
Original line number Diff line number Diff line
@@ -81,7 +81,6 @@ struct inet_request_sock {
#define ir_cookie		req.__req_common.skc_cookie
#define ireq_net		req.__req_common.skc_net
#define ireq_state		req.__req_common.skc_state
#define ireq_refcnt		req.__req_common.skc_refcnt
#define ireq_family		req.__req_common.skc_family

	kmemcheck_bitfield_begin(flags);
@@ -244,25 +243,8 @@ static inline unsigned int __inet_ehashfn(const __be32 laddr,
			    initval);
}

static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops)
{
	struct request_sock *req = reqsk_alloc(ops);
	struct inet_request_sock *ireq = inet_rsk(req);

	if (req != NULL) {
		kmemcheck_annotate_bitfield(ireq, flags);
		ireq->opt = NULL;
		atomic64_set(&ireq->ir_cookie, 0);
		ireq->ireq_state = TCP_NEW_SYN_RECV;

		/* Following is temporary. It is coupled with debugging
		 * helpers in reqsk_put() & reqsk_free()
		 */
		atomic_set(&ireq->ireq_refcnt, 0);
	}

	return req;
}
struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
				      struct sock *sk_listener);

static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
{
+20 −3
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct request_sock {
#define rsk_refcnt			__req_common.skc_refcnt

	struct request_sock		*dl_next;
	struct sock			*rsk_listener;
	u16				mss;
	u8				num_retrans; /* number of retransmits */
	u8				cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
@@ -67,13 +68,21 @@ struct request_sock {
	u32				peer_secid;
};

static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops)
static inline struct request_sock *
reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener)
{
	struct request_sock *req = kmem_cache_alloc(ops->slab, GFP_ATOMIC);

	if (req != NULL)
	if (req) {
		req->rsk_ops = ops;
		sock_hold(sk_listener);
		req->rsk_listener = sk_listener;

		/* Following is temporary. It is coupled with debugging
		 * helpers in reqsk_put() & reqsk_free()
		 */
		atomic_set(&req->rsk_refcnt, 0);
	}
	return req;
}

@@ -88,6 +97,8 @@ static inline void reqsk_free(struct request_sock *req)
	WARN_ON_ONCE(atomic_read(&req->rsk_refcnt) != 0);

	req->rsk_ops->destructor(req);
	if (req->rsk_listener)
		sock_put(req->rsk_listener);
	kmem_cache_free(req->rsk_ops->slab, req);
}

@@ -286,6 +297,12 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
	req->sk = NULL;
	req->dl_next = lopt->syn_table[hash];

	/* before letting lookups find us, make sure all req fields
	 * are committed to memory and refcnt initialized.
	 */
	smp_wmb();
	atomic_set(&req->rsk_refcnt, 1);

	write_lock(&queue->syn_wait_lock);
	lopt->syn_table[hash] = req;
	write_unlock(&queue->syn_wait_lock);
+7 −11
Original line number Diff line number Diff line
@@ -153,24 +153,22 @@ void reqsk_queue_destroy(struct request_sock_queue *queue)
 * case might also exist in tcp_v4_hnd_req() that will trigger this locking
 * order.
 *
 * When a TFO req is created, it needs to sock_hold its listener to prevent
 * the latter data structure from going away.
 *
 * This function also sets "treq->listener" to NULL and unreference listener
 * socket. treq->listener is used by the listener so it is protected by the
 * This function also sets "treq->tfo_listener" to false.
 * treq->tfo_listener is used by the listener so it is protected by the
 * fastopenq->lock in this function.
 */
void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
			   bool reset)
{
	struct sock *lsk = tcp_rsk(req)->listener;
	struct fastopen_queue *fastopenq =
	    inet_csk(lsk)->icsk_accept_queue.fastopenq;
	struct sock *lsk = req->rsk_listener;
	struct fastopen_queue *fastopenq;

	fastopenq = inet_csk(lsk)->icsk_accept_queue.fastopenq;

	tcp_sk(sk)->fastopen_rsk = NULL;
	spin_lock_bh(&fastopenq->lock);
	fastopenq->qlen--;
	tcp_rsk(req)->listener = NULL;
	tcp_rsk(req)->tfo_listener = false;
	if (req->sk)	/* the child socket hasn't been accepted yet */
		goto out;

@@ -179,7 +177,6 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
		 * special RST handling below.
		 */
		spin_unlock_bh(&fastopenq->lock);
		sock_put(lsk);
		reqsk_put(req);
		return;
	}
@@ -201,5 +198,4 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
	fastopenq->qlen++;
out:
	spin_unlock_bh(&fastopenq->lock);
	sock_put(lsk);
}
Loading