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

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

Merge tag 'rxrpc-rewrite-20160913-1' of...

Merge tag 'rxrpc-rewrite-20160913-1' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs



David Howells says:

====================
rxrpc: Miscellaneous fixes

Here's a set of miscellaneous fix patches.  There are a couple of points of
note:

 (1) There is one non-fix patch that adjusts the call ref tracking
     tracepoint to make kernel API-held refs on calls more obvious.  This
     is a prerequisite for the patch that fixes prealloc refcounting.

 (2) The final patch alters how jumbo packets that partially exceed the
     receive window are handled.  Previously, space was being left in the
     Rx buffer for them, but this significantly hurts performance as the Rx
     window can't be increased to match the OpenAFS Tx window size.

     Instead, the excess subpackets are discarded and an EXCEEDS_WINDOW ACK
     is generated for the first.  To avoid the problem of someone trying to
     run the kernel out of space by feeding the kernel a series of
     overlapping maximal jumbo packets, we stop allowing jumbo packets on a
     call if we encounter more than three jumbo packets with duplicate or
     excessive subpackets.
====================

Reviewed-by: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 09f090d8 75e42126
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -299,7 +299,7 @@ void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call)
{
	_enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
	rxrpc_release_call(rxrpc_sk(sock->sk), call);
	rxrpc_put_call(call, rxrpc_call_put);
	rxrpc_put_call(call, rxrpc_call_put_kernel);
}
EXPORT_SYMBOL(rxrpc_kernel_end_call);

+4 −1
Original line number Diff line number Diff line
@@ -498,6 +498,7 @@ struct rxrpc_call {
	 */
#define RXRPC_RXTX_BUFF_SIZE	64
#define RXRPC_RXTX_BUFF_MASK	(RXRPC_RXTX_BUFF_SIZE - 1)
#define RXRPC_INIT_RX_WINDOW_SIZE 32
	struct sk_buff		**rxtx_buffer;
	u8			*rxtx_annotations;
#define RXRPC_TX_ANNO_ACK	0
@@ -518,7 +519,7 @@ struct rxrpc_call {
	rxrpc_seq_t		rx_expect_next;	/* Expected next packet sequence number */
	u8			rx_winsize;	/* Size of Rx window */
	u8			tx_winsize;	/* Maximum size of Tx window */
	u8			nr_jumbo_dup;	/* Number of jumbo duplicates */
	u8			nr_jumbo_bad;	/* Number of jumbo dups/exceeds-windows */

	/* receive-phase ACK management */
	u8			ackr_reason;	/* reason to ACK */
@@ -540,8 +541,10 @@ enum rxrpc_call_trace {
	rxrpc_call_seen,
	rxrpc_call_got,
	rxrpc_call_got_userid,
	rxrpc_call_got_kernel,
	rxrpc_call_put,
	rxrpc_call_put_userid,
	rxrpc_call_put_kernel,
	rxrpc_call_put_noqueue,
	rxrpc_call__nr_trace
};
+15 −5
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,

		call->user_call_ID = user_call_ID;
		call->notify_rx = notify_rx;
		rxrpc_get_call(call, rxrpc_call_got);
		rxrpc_get_call(call, rxrpc_call_got_kernel);
		user_attach_call(call, user_call_ID);
		rxrpc_get_call(call, rxrpc_call_got_userid);
		rb_link_node(&call->sock_node, parent, pp);
@@ -221,6 +221,7 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
		if (rx->discard_new_call) {
			_debug("discard %lx", call->user_call_ID);
			rx->discard_new_call(call, call->user_call_ID);
			rxrpc_put_call(call, rxrpc_call_put_kernel);
		}
		rxrpc_call_completed(call);
		rxrpc_release_call(rx, call);
@@ -300,6 +301,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
	smp_store_release(&b->call_backlog_tail,
			  (call_tail + 1) & (RXRPC_BACKLOG_MAX - 1));

	rxrpc_see_call(call);
	call->conn = conn;
	call->peer = rxrpc_get_peer(conn->params.peer);
	return call;
@@ -401,6 +403,13 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
	if (call->state == RXRPC_CALL_SERVER_ACCEPTING)
		rxrpc_notify_socket(call);

	/* We have to discard the prealloc queue's ref here and rely on a
	 * combination of the RCU read lock and refs held either by the socket
	 * (recvmsg queue, to-be-accepted queue or user ID tree) or the kernel
	 * service to prevent the call from being deallocated too early.
	 */
	rxrpc_put_call(call, rxrpc_call_put);

	_leave(" = %p{%d}", call, call->debug_id);
out:
	spin_unlock(&rx->incoming_lock);
@@ -425,9 +434,11 @@ struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,

	write_lock(&rx->call_lock);

	ret = -ENODATA;
	if (list_empty(&rx->to_be_accepted))
		goto out;
	if (list_empty(&rx->to_be_accepted)) {
		write_unlock(&rx->call_lock);
		kleave(" = -ENODATA [empty]");
		return ERR_PTR(-ENODATA);
	}

	/* check the user ID isn't already in use */
	pp = &rx->calls.rb_node;
@@ -466,7 +477,6 @@ struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,
	}

	/* formalise the acceptance */
	rxrpc_get_call(call, rxrpc_call_got);
	call->notify_rx = notify_rx;
	call->user_call_ID = user_call_ID;
	rxrpc_get_call(call, rxrpc_call_got_userid);
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
		break;

	case RXRPC_ACK_IDLE:
		if (rxrpc_soft_ack_delay < expiry)
		if (rxrpc_idle_ack_delay < expiry)
			expiry = rxrpc_idle_ack_delay;
		break;

+3 −4
Original line number Diff line number Diff line
@@ -56,8 +56,10 @@ const char rxrpc_call_traces[rxrpc_call__nr_trace][4] = {
	[rxrpc_call_seen]		= "SEE",
	[rxrpc_call_got]		= "GOT",
	[rxrpc_call_got_userid]		= "Gus",
	[rxrpc_call_got_kernel]		= "Gke",
	[rxrpc_call_put]		= "PUT",
	[rxrpc_call_put_userid]		= "Pus",
	[rxrpc_call_put_kernel]		= "Pke",
	[rxrpc_call_put_noqueue]	= "PNQ",
};

@@ -150,7 +152,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
	memset(&call->sock_node, 0xed, sizeof(call->sock_node));

	/* Leave space in the ring to handle a maxed-out jumbo packet */
	call->rx_winsize = RXRPC_RXTX_BUFF_SIZE - 1 - 46;
	call->rx_winsize = rxrpc_rx_window_size;
	call->tx_winsize = 16;
	call->rx_expect_next = 1;
	return call;
@@ -462,9 +464,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
		call->rxtx_buffer[i] = NULL;
	}

	/* We have to release the prealloc backlog ref */
	if (rxrpc_is_service_call(call))
		rxrpc_put_call(call, rxrpc_call_put);
	_leave("");
}

Loading