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

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

Merge branch 'rxrpc-fixes'



David Howells says:

====================
rxrpc: Fixes

Here is a collection of fixes for rxrpc:

 (1) rxrpc_error_report() needs to call sock_error() to clear the error
     code from the UDP transport socket, lest it be unexpectedly revisited
     on the next kernel_sendmsg() call.  This has been causing all sorts of
     weird effects in AFS as the effects have typically been felt by the
     wrong RxRPC call.

 (2) Allow a kernel user of AF_RXRPC to easily detect if an rxrpc call has
     completed.

 (3) Allow errors incurred by attempting to transmit data through the UDP
     socket to get back up the stack to AFS.

 (4) Make AFS use (2) to abort the synchronous-mode call waiting loop if
     the rxrpc-level call completed.

 (5) Add a missing tracepoint case for tracing abort reception.

 (6) Fix detection and handling of out-of-order ACKs.

====================

Tested-by: default avatarJonathan Billings <jsbillin@umich.edu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1dc2b3d6 1a2391c3
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -1009,16 +1009,18 @@ The kernel interface functions are as follows:

 (*) Check call still alive.

	u32 rxrpc_kernel_check_life(struct socket *sock,
				    struct rxrpc_call *call);
	bool rxrpc_kernel_check_life(struct socket *sock,
				     struct rxrpc_call *call,
				     u32 *_life);
	void rxrpc_kernel_probe_life(struct socket *sock,
				     struct rxrpc_call *call);

     The first function returns a number that is updated when ACKs are received
     from the peer (notably including PING RESPONSE ACKs which we can elicit by
     sending PING ACKs to see if the call still exists on the server).  The
     caller should compare the numbers of two calls to see if the call is still
     alive after waiting for a suitable interval.
     The first function passes back in *_life a number that is updated when
     ACKs are received from the peer (notably including PING RESPONSE ACKs
     which we can elicit by sending PING ACKs to see if the call still exists
     on the server).  The caller should compare the numbers of two calls to see
     if the call is still alive after waiting for a suitable interval.  It also
     returns true as long as the call hasn't yet reached the completed state.

     This allows the caller to work out if the server is still contactable and
     if the call is still alive on the server while waiting for the server to
+17 −7
Original line number Diff line number Diff line
@@ -610,6 +610,7 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
	bool stalled = false;
	u64 rtt;
	u32 life, last_life;
	bool rxrpc_complete = false;

	DECLARE_WAITQUEUE(myself, current);

@@ -621,7 +622,7 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
		rtt2 = 2;

	timeout = rtt2;
	last_life = rxrpc_kernel_check_life(call->net->socket, call->rxcall);
	rxrpc_kernel_check_life(call->net->socket, call->rxcall, &last_life);

	add_wait_queue(&call->waitq, &myself);
	for (;;) {
@@ -639,7 +640,12 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
			break;

		life = rxrpc_kernel_check_life(call->net->socket, call->rxcall);
		if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall, &life)) {
			/* rxrpc terminated the call. */
			rxrpc_complete = true;
			break;
		}

		if (timeout == 0 &&
		    life == last_life && signal_pending(current)) {
			if (stalled)
@@ -663,13 +669,17 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
	remove_wait_queue(&call->waitq, &myself);
	__set_current_state(TASK_RUNNING);

	/* Kill off the call if it's still live. */
	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
		if (rxrpc_complete) {
			afs_set_call_complete(call, call->error, call->abort_code);
		} else {
			/* Kill off the call if it's still live. */
			_debug("call interrupted");
			if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
						    RX_USER_ABORT, -EINTR, "KWI"))
				afs_set_call_complete(call, -EINTR, 0);
		}
	}

	spin_lock_bh(&call->state_lock);
	ac->abort_code = call->abort_code;
+3 −1
Original line number Diff line number Diff line
@@ -61,10 +61,12 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
			       rxrpc_user_attach_call_t, unsigned long, gfp_t,
			       unsigned int);
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *,
			     u32 *);
void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *);
u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *,
				 ktime_t *);
bool rxrpc_kernel_call_is_complete(struct rxrpc_call *);

#endif /* _NET_RXRPC_H */
+9 −5
Original line number Diff line number Diff line
@@ -371,18 +371,22 @@ EXPORT_SYMBOL(rxrpc_kernel_end_call);
 * rxrpc_kernel_check_life - Check to see whether a call is still alive
 * @sock: The socket the call is on
 * @call: The call to check
 * @_life: Where to store the life value
 *
 * Allow a kernel service to find out whether a call is still alive - ie. we're
 * getting ACKs from the server.  Returns a number representing the life state
 * which can be compared to that returned by a previous call.
 * getting ACKs from the server.  Passes back in *_life a number representing
 * the life state which can be compared to that returned by a previous call and
 * return true if the call is still alive.
 *
 * If the life state stalls, rxrpc_kernel_probe_life() should be called and
 * then 2RTT waited.
 */
u32 rxrpc_kernel_check_life(const struct socket *sock,
			    const struct rxrpc_call *call)
bool rxrpc_kernel_check_life(const struct socket *sock,
			     const struct rxrpc_call *call,
			     u32 *_life)
{
	return call->acks_latest;
	*_life = call->acks_latest;
	return call->state != RXRPC_CALL_COMPLETE;
}
EXPORT_SYMBOL(rxrpc_kernel_check_life);

+1 −0
Original line number Diff line number Diff line
@@ -654,6 +654,7 @@ struct rxrpc_call {
	u8			ackr_reason;	/* reason to ACK */
	u16			ackr_skew;	/* skew on packet being ACK'd */
	rxrpc_serial_t		ackr_serial;	/* serial of packet being ACK'd */
	rxrpc_serial_t		ackr_first_seq;	/* first sequence number received */
	rxrpc_seq_t		ackr_prev_seq;	/* previous sequence number received */
	rxrpc_seq_t		ackr_consumed;	/* Highest packet shown consumed */
	rxrpc_seq_t		ackr_seen;	/* Highest packet shown seen */
Loading