rxrpc: Fix warning by splitting rxrpc_send_call_packet()

Split rxrpc_send_data_packet() to separate ACK generation (which is more
complicated) from ABORT generation.  This simplifies the code a bit and
fixes the following warning:

In file included from ../net/rxrpc/output.c:20:0:
net/rxrpc/output.c: In function 'rxrpc_send_call_packet':
net/rxrpc/ar-internal.h:1187:27: error: 'top' may be used uninitialized in this function [-Werror=maybe-uninitialized]
net/rxrpc/output.c:103:24: note: 'top' was declared here
net/rxrpc/output.c:225:25: error: 'hard_ack' may be used uninitialized in this function [-Werror=maybe-uninitialized]

Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells
2016-10-06 08:11:49 +01:00
parent a9f312d98a
commit 26cb02aa6d
8 changed files with 102 additions and 84 deletions

View File

@@ -19,24 +19,24 @@
#include <net/af_rxrpc.h>
#include "ar-internal.h"
struct rxrpc_pkt_buffer {
struct rxrpc_ack_buffer {
struct rxrpc_wire_header whdr;
union {
struct {
struct rxrpc_ackpacket ack;
u8 acks[255];
u8 pad[3];
};
__be32 abort_code;
};
struct rxrpc_ackpacket ack;
u8 acks[255];
u8 pad[3];
struct rxrpc_ackinfo ackinfo;
};
struct rxrpc_abort_buffer {
struct rxrpc_wire_header whdr;
__be32 abort_code;
};
/*
* Fill out an ACK packet.
*/
static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
struct rxrpc_pkt_buffer *pkt,
struct rxrpc_ack_buffer *pkt,
rxrpc_seq_t *_hard_ack,
rxrpc_seq_t *_top)
{
@@ -91,22 +91,19 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
}
/*
* Send an ACK or ABORT call packet.
* Send an ACK call packet.
*/
int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
int rxrpc_send_ack_packet(struct rxrpc_call *call)
{
struct rxrpc_connection *conn = NULL;
struct rxrpc_pkt_buffer *pkt;
struct rxrpc_ack_buffer *pkt;
struct msghdr msg;
struct kvec iov[2];
rxrpc_serial_t serial;
rxrpc_seq_t hard_ack, top;
size_t len, n;
bool ping = false;
int ioc, ret;
u32 abort_code;
_enter("%u,%s", call->debug_id, rxrpc_pkts[type]);
int ret;
spin_lock_bh(&call->lock);
if (call->conn)
@@ -131,65 +128,37 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
pkt->whdr.cid = htonl(call->cid);
pkt->whdr.callNumber = htonl(call->call_id);
pkt->whdr.seq = 0;
pkt->whdr.type = type;
pkt->whdr.flags = conn->out_clientflag;
pkt->whdr.type = RXRPC_PACKET_TYPE_ACK;
pkt->whdr.flags = RXRPC_SLOW_START_OK | conn->out_clientflag;
pkt->whdr.userStatus = 0;
pkt->whdr.securityIndex = call->security_ix;
pkt->whdr._rsvd = 0;
pkt->whdr.serviceId = htons(call->service_id);
iov[0].iov_base = pkt;
iov[0].iov_len = sizeof(pkt->whdr);
len = sizeof(pkt->whdr);
switch (type) {
case RXRPC_PACKET_TYPE_ACK:
spin_lock_bh(&call->lock);
if (!call->ackr_reason) {
spin_unlock_bh(&call->lock);
ret = 0;
goto out;
}
ping = (call->ackr_reason == RXRPC_ACK_PING);
n = rxrpc_fill_out_ack(call, pkt, &hard_ack, &top);
call->ackr_reason = 0;
spin_lock_bh(&call->lock);
if (!call->ackr_reason) {
spin_unlock_bh(&call->lock);
pkt->whdr.flags |= RXRPC_SLOW_START_OK;
iov[0].iov_len += sizeof(pkt->ack) + n;
iov[1].iov_base = &pkt->ackinfo;
iov[1].iov_len = sizeof(pkt->ackinfo);
len += sizeof(pkt->ack) + n + sizeof(pkt->ackinfo);
ioc = 2;
break;
case RXRPC_PACKET_TYPE_ABORT:
abort_code = call->abort_code;
pkt->abort_code = htonl(abort_code);
iov[0].iov_len += sizeof(pkt->abort_code);
len += sizeof(pkt->abort_code);
ioc = 1;
break;
default:
BUG();
ret = -ENOANO;
ret = 0;
goto out;
}
ping = (call->ackr_reason == RXRPC_ACK_PING);
n = rxrpc_fill_out_ack(call, pkt, &hard_ack, &top);
call->ackr_reason = 0;
spin_unlock_bh(&call->lock);
iov[0].iov_base = pkt;
iov[0].iov_len = sizeof(pkt->whdr) + sizeof(pkt->ack) + n;
iov[1].iov_base = &pkt->ackinfo;
iov[1].iov_len = sizeof(pkt->ackinfo);
len = iov[0].iov_len + iov[1].iov_len;
serial = atomic_inc_return(&conn->serial);
pkt->whdr.serial = htonl(serial);
switch (type) {
case RXRPC_PACKET_TYPE_ACK:
trace_rxrpc_tx_ack(call, serial,
ntohl(pkt->ack.firstPacket),
ntohl(pkt->ack.serial),
pkt->ack.reason, pkt->ack.nAcks);
break;
}
trace_rxrpc_tx_ack(call, serial,
ntohl(pkt->ack.firstPacket),
ntohl(pkt->ack.serial),
pkt->ack.reason, pkt->ack.nAcks);
if (ping) {
call->ackr_ping = serial;
@@ -205,13 +174,12 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
set_bit(RXRPC_CALL_PINGING, &call->flags);
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_ping, serial);
}
ret = kernel_sendmsg(conn->params.local->socket,
&msg, iov, ioc, len);
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
if (ping)
call->ackr_ping_time = ktime_get_real();
if (type == RXRPC_PACKET_TYPE_ACK &&
call->state < RXRPC_CALL_COMPLETE) {
if (call->state < RXRPC_CALL_COMPLETE) {
if (ret < 0) {
clear_bit(RXRPC_CALL_PINGING, &call->flags);
rxrpc_propose_ACK(call, pkt->ack.reason,
@@ -235,6 +203,56 @@ out:
return ret;
}
/*
* Send an ABORT call packet.
*/
int rxrpc_send_abort_packet(struct rxrpc_call *call)
{
struct rxrpc_connection *conn = NULL;
struct rxrpc_abort_buffer pkt;
struct msghdr msg;
struct kvec iov[1];
rxrpc_serial_t serial;
int ret;
spin_lock_bh(&call->lock);
if (call->conn)
conn = rxrpc_get_connection_maybe(call->conn);
spin_unlock_bh(&call->lock);
if (!conn)
return -ECONNRESET;
msg.msg_name = &call->peer->srx.transport;
msg.msg_namelen = call->peer->srx.transport_len;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
pkt.whdr.epoch = htonl(conn->proto.epoch);
pkt.whdr.cid = htonl(call->cid);
pkt.whdr.callNumber = htonl(call->call_id);
pkt.whdr.seq = 0;
pkt.whdr.type = RXRPC_PACKET_TYPE_ABORT;
pkt.whdr.flags = conn->out_clientflag;
pkt.whdr.userStatus = 0;
pkt.whdr.securityIndex = call->security_ix;
pkt.whdr._rsvd = 0;
pkt.whdr.serviceId = htons(call->service_id);
pkt.abort_code = htonl(call->abort_code);
iov[0].iov_base = &pkt;
iov[0].iov_len = sizeof(pkt);
serial = atomic_inc_return(&conn->serial);
pkt.whdr.serial = htonl(serial);
ret = kernel_sendmsg(conn->params.local->socket,
&msg, iov, 1, sizeof(pkt));
rxrpc_put_connection(conn);
return ret;
}
/*
* send a packet through the transport endpoint
*/