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

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

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

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



David Howells says:

====================
rxrpc: Fixes & miscellany

Here are some more AF_RXRPC fix patches with a couple of miscellaneous
changes also.  Fixes include:

 (1) Make RxRPC IPv6 support conditional on IPv6 being available.

 (2) Move the condition check in rxrpc_locate_data() into the caller and
     check the error return.

 (3) Fix the detection of the last received packet in recvmsg.

 (4) Account calls that need acceptance and clean up any unaccepted ones if
     the socket gets closed.

 (5) Fix the cleanup of client connections.

 (6) Fix the soft-ACK parsing and the retransmission of packets based on
     those ACKs.

 (7) Suppress transmission of an ACK when there's no pending ACK to
     transmit because another thread stole it.

And some miscellany:

 (8) Whitespace removal.

 (9) Switch-value consistency in rxrpc_send_call_packet().

(10) Fix the basic transmission packet size to allow for spur-of-the-moment
     jumbo DATA packet production.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 029ac211 182f5056
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -369,6 +369,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,

	if (rx->notify_new_call)
		rx->notify_new_call(&rx->sk, call, call->user_call_ID);
	else
		sk_acceptq_added(&rx->sk);

	spin_lock(&conn->state_lock);
	switch (conn->state) {
+5 −9
Original line number Diff line number Diff line
@@ -163,8 +163,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
	 */
	now = jiffies;
	resend_at = now + rxrpc_resend_timeout;
	seq = cursor + 1;
	do {
	for (seq = cursor + 1; before_eq(seq, top); seq++) {
		ix = seq & RXRPC_RXTX_BUFF_MASK;
		annotation = call->rxtx_annotations[ix];
		if (annotation == RXRPC_TX_ANNO_ACK)
@@ -184,8 +183,7 @@ static void rxrpc_resend(struct rxrpc_call *call)

		/* Okay, we need to retransmit a packet. */
		call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS;
		seq++;
	} while (before_eq(seq, top));
	}

	call->resend_at = resend_at;

@@ -194,8 +192,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
	 * lock is dropped, it may clear some of the retransmission markers for
	 * packets that it soft-ACKs.
	 */
	seq = cursor + 1;
	do {
	for (seq = cursor + 1; before_eq(seq, top); seq++) {
		ix = seq & RXRPC_RXTX_BUFF_MASK;
		annotation = call->rxtx_annotations[ix];
		if (annotation != RXRPC_TX_ANNO_RETRANS)
@@ -237,8 +234,7 @@ static void rxrpc_resend(struct rxrpc_call *call)

		if (after(call->tx_hard_ack, seq))
			seq = call->tx_hard_ack;
		seq++;
	} while (before_eq(seq, top));
	}

out_unlock:
	spin_unlock_bh(&call->lock);
+22 −24
Original line number Diff line number Diff line
@@ -226,9 +226,6 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
			 (const void *)user_call_ID);

	/* Publish the call, even though it is incompletely set up as yet */
	call->user_call_ID = user_call_ID;
	__set_bit(RXRPC_CALL_HAS_USERID, &call->flags);

	write_lock(&rx->call_lock);

	pp = &rx->calls.rb_node;
@@ -242,10 +239,12 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
		else if (user_call_ID > xcall->user_call_ID)
			pp = &(*pp)->rb_right;
		else
			goto found_user_ID_now_present;
			goto error_dup_user_ID;
	}

	rcu_assign_pointer(call->socket, rx);
	call->user_call_ID = user_call_ID;
	__set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
	rxrpc_get_call(call, rxrpc_call_got_userid);
	rb_link_node(&call->sock_node, parent, pp);
	rb_insert_color(&call->sock_node, &rx->calls);
@@ -276,33 +275,22 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
	_leave(" = %p [new]", call);
	return call;

error:
	write_lock(&rx->call_lock);
	rb_erase(&call->sock_node, &rx->calls);
	write_unlock(&rx->call_lock);
	rxrpc_put_call(call, rxrpc_call_put_userid);

	write_lock(&rxrpc_call_lock);
	list_del_init(&call->link);
	write_unlock(&rxrpc_call_lock);

error_out:
	__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
				    RX_CALL_DEAD, ret);
	set_bit(RXRPC_CALL_RELEASED, &call->flags);
	rxrpc_put_call(call, rxrpc_call_put);
	_leave(" = %d", ret);
	return ERR_PTR(ret);

	/* We unexpectedly found the user ID in the list after taking
	 * the call_lock.  This shouldn't happen unless the user races
	 * with itself and tries to add the same user ID twice at the
	 * same time in different threads.
	 */
found_user_ID_now_present:
error_dup_user_ID:
	write_unlock(&rx->call_lock);
	ret = -EEXIST;
	goto error_out;

error:
	__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
				    RX_CALL_DEAD, ret);
	rxrpc_release_call(rx, call);
	rxrpc_put_call(call, rxrpc_call_put);
	_leave(" = %d", ret);
	return ERR_PTR(ret);
}

/*
@@ -476,6 +464,16 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)

	_enter("%p", rx);

	while (!list_empty(&rx->to_be_accepted)) {
		call = list_entry(rx->to_be_accepted.next,
				  struct rxrpc_call, accept_link);
		list_del(&call->accept_link);
		rxrpc_abort_call("SKR", call, 0, RX_CALL_DEAD, ECONNRESET);
		rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT);
		rxrpc_release_call(rx, call);
		rxrpc_put_call(call, rxrpc_call_put);
	}

	while (!list_empty(&rx->sock_calls)) {
		call = list_entry(rx->sock_calls.next,
				  struct rxrpc_call, sock_link);
+13 −16
Original line number Diff line number Diff line
@@ -721,7 +721,6 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
	}

	ASSERTCMP(rcu_access_pointer(chan->call), ==, call);
	ASSERTCMP(atomic_read(&conn->usage), >=, 2);

	/* If a client call was exposed to the world, we save the result for
	 * retransmission.
@@ -818,7 +817,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
static struct rxrpc_connection *
rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
{
	struct rxrpc_connection *next;
	struct rxrpc_connection *next = NULL;
	struct rxrpc_local *local = conn->params.local;
	unsigned int nr_conns;

@@ -834,13 +833,10 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn)

	ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_INACTIVE);

	if (!test_bit(RXRPC_CONN_COUNTED, &conn->flags))
		return NULL;

	if (test_bit(RXRPC_CONN_COUNTED, &conn->flags)) {
		spin_lock(&rxrpc_client_conn_cache_lock);
		nr_conns = --rxrpc_nr_client_conns;

	next = NULL;
		if (nr_conns < rxrpc_max_client_connections &&
		    !list_empty(&rxrpc_waiting_client_conns)) {
			next = list_entry(rxrpc_waiting_client_conns.next,
@@ -850,8 +846,9 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
		}

		spin_unlock(&rxrpc_client_conn_cache_lock);
	rxrpc_kill_connection(conn);
	}

	rxrpc_kill_connection(conn);
	if (next)
		rxrpc_activate_channels(next);

+4 −2
Original line number Diff line number Diff line
@@ -238,7 +238,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
		len = RXRPC_JUMBO_DATALEN;

	if (flags & RXRPC_LAST_PACKET) {
		if (test_and_set_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
		if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
		    seq != call->rx_top)
			return rxrpc_proto_abort("LSN", call, seq);
	} else {
@@ -282,6 +282,8 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
	call->rxtx_buffer[ix] = skb;
	if (after(seq, call->rx_top))
		smp_store_release(&call->rx_top, seq);
	if (flags & RXRPC_LAST_PACKET)
		set_bit(RXRPC_CALL_RX_LAST, &call->flags);
	queued = true;

	if (after_eq(seq, call->rx_expect_next)) {
@@ -382,7 +384,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,

	for (; nr_acks > 0; nr_acks--, seq++) {
		ix = seq & RXRPC_RXTX_BUFF_MASK;
		switch (*acks) {
		switch (*acks++) {
		case RXRPC_ACK_TYPE_ACK:
			call->rxtx_annotations[ix] = RXRPC_TX_ANNO_ACK;
			break;
Loading