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

Commit f3344303 authored by David Howells's avatar David Howells
Browse files

rxrpc: Fix error distribution



Fix error distribution by immediately delivering the errors to all the
affected calls rather than deferring them to a worker thread.  The problem
with the latter is that retries and things can happen in the meantime when we
want to stop that sooner.

To this end:

 (1) Stop the error distributor from removing calls from the error_targets
     list so that peer->lock isn't needed to synchronise against other adds
     and removals.

 (2) Require the peer's error_targets list to be accessed with RCU, thereby
     avoiding the need to take peer->lock over distribution.

 (3) Don't attempt to affect a call's state if it is already marked complete.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 37a675e7
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ enum rxrpc_peer_trace {
	rxrpc_peer_new,
	rxrpc_peer_processing,
	rxrpc_peer_put,
	rxrpc_peer_queued_error,
};

enum rxrpc_conn_trace {
@@ -257,8 +256,7 @@ enum rxrpc_tx_point {
	EM(rxrpc_peer_got,			"GOT") \
	EM(rxrpc_peer_new,			"NEW") \
	EM(rxrpc_peer_processing,		"PRO") \
	EM(rxrpc_peer_put,			"PUT") \
	E_(rxrpc_peer_queued_error,		"QER")
	E_(rxrpc_peer_put,			"PUT")

#define rxrpc_conn_traces \
	EM(rxrpc_conn_got,			"GOT") \
+0 −5
Original line number Diff line number Diff line
@@ -288,7 +288,6 @@ struct rxrpc_peer {
	struct hlist_node	hash_link;
	struct rxrpc_local	*local;
	struct hlist_head	error_targets;	/* targets for net error distribution */
	struct work_struct	error_distributor;
	struct rb_root		service_conns;	/* Service connections */
	struct list_head	keepalive_link;	/* Link in net->peer_keepalive[] */
	time64_t		last_tx_at;	/* Last time packet sent here */
@@ -299,8 +298,6 @@ struct rxrpc_peer {
	unsigned int		maxdata;	/* data size (MTU - hdrsize) */
	unsigned short		hdrsize;	/* header size (IP + UDP + RxRPC) */
	int			debug_id;	/* debug ID for printks */
	int			error_report;	/* Net (+0) or local (+1000000) to distribute */
#define RXRPC_LOCAL_ERROR_OFFSET 1000000
	struct sockaddr_rxrpc	srx;		/* remote address */

	/* calculated RTT cache */
@@ -1039,7 +1036,6 @@ void rxrpc_send_keepalive(struct rxrpc_peer *);
 * peer_event.c
 */
void rxrpc_error_report(struct sock *);
void rxrpc_peer_error_distributor(struct work_struct *);
void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace,
			rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
void rxrpc_peer_keepalive_worker(struct work_struct *);
@@ -1057,7 +1053,6 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *);
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
void rxrpc_put_peer(struct rxrpc_peer *);
void __rxrpc_queue_peer_error(struct rxrpc_peer *);

/*
 * proc.c
+1 −1
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx,
	rcu_assign_pointer(conn->channels[chan].call, call);

	spin_lock(&conn->params.peer->lock);
	hlist_add_head(&call->error_link, &conn->params.peer->error_targets);
	hlist_add_head_rcu(&call->error_link, &conn->params.peer->error_targets);
	spin_unlock(&conn->params.peer->lock);

	_net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id);
+2 −2
Original line number Diff line number Diff line
@@ -710,7 +710,7 @@ int rxrpc_connect_call(struct rxrpc_call *call,
	}

	spin_lock_bh(&call->conn->params.peer->lock);
	hlist_add_head(&call->error_link,
	hlist_add_head_rcu(&call->error_link,
			   &call->conn->params.peer->error_targets);
	spin_unlock_bh(&call->conn->params.peer->lock);

+1 −1
Original line number Diff line number Diff line
@@ -216,7 +216,7 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
	call->peer->cong_cwnd = call->cong_cwnd;

	spin_lock_bh(&conn->params.peer->lock);
	hlist_del_init(&call->error_link);
	hlist_del_rcu(&call->error_link);
	spin_unlock_bh(&conn->params.peer->lock);

	if (rxrpc_is_client_call(call))
Loading