Commit b0346843 authored by David Howells's avatar David Howells

rxrpc: Transmit ACKs at the point of generation

For ACKs generated inside the I/O thread, transmit the ACK at the point of
generation.  Where the ACK is generated outside of the I/O thread, it's
offloaded to the I/O thread to transmit it.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent a2cf3264
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
EM(rxrpc_local_put_peer, "PUT peer ") \ EM(rxrpc_local_put_peer, "PUT peer ") \
EM(rxrpc_local_put_prealloc_conn, "PUT conn-pre") \ EM(rxrpc_local_put_prealloc_conn, "PUT conn-pre") \
EM(rxrpc_local_put_release_sock, "PUT rel-sock") \ EM(rxrpc_local_put_release_sock, "PUT rel-sock") \
EM(rxrpc_local_see_tx_ack, "SEE tx-ack ") \
EM(rxrpc_local_stop, "STOP ") \ EM(rxrpc_local_stop, "STOP ") \
EM(rxrpc_local_stopped, "STOPPED ") \ EM(rxrpc_local_stopped, "STOPPED ") \
EM(rxrpc_local_unuse_bind, "UNU bind ") \ EM(rxrpc_local_unuse_bind, "UNU bind ") \
...@@ -156,7 +155,6 @@ ...@@ -156,7 +155,6 @@
EM(rxrpc_call_get_recvmsg, "GET recvmsg ") \ EM(rxrpc_call_get_recvmsg, "GET recvmsg ") \
EM(rxrpc_call_get_release_sock, "GET rel-sock") \ EM(rxrpc_call_get_release_sock, "GET rel-sock") \
EM(rxrpc_call_get_sendmsg, "GET sendmsg ") \ EM(rxrpc_call_get_sendmsg, "GET sendmsg ") \
EM(rxrpc_call_get_send_ack, "GET send-ack") \
EM(rxrpc_call_get_userid, "GET user-id ") \ EM(rxrpc_call_get_userid, "GET user-id ") \
EM(rxrpc_call_new_client, "NEW client ") \ EM(rxrpc_call_new_client, "NEW client ") \
EM(rxrpc_call_new_prealloc_service, "NEW prealloc") \ EM(rxrpc_call_new_prealloc_service, "NEW prealloc") \
...@@ -168,7 +166,6 @@ ...@@ -168,7 +166,6 @@
EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \ EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \
EM(rxrpc_call_put_release_sock, "PUT rls-sock") \ EM(rxrpc_call_put_release_sock, "PUT rls-sock") \
EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \ EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \
EM(rxrpc_call_put_send_ack, "PUT send-ack") \
EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \ EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \
EM(rxrpc_call_put_unnotify, "PUT unnotify") \ EM(rxrpc_call_put_unnotify, "PUT unnotify") \
EM(rxrpc_call_put_userid_exists, "PUT u-exists") \ EM(rxrpc_call_put_userid_exists, "PUT u-exists") \
......
...@@ -287,8 +287,6 @@ struct rxrpc_local { ...@@ -287,8 +287,6 @@ struct rxrpc_local {
struct hlist_node link; struct hlist_node link;
struct socket *socket; /* my UDP socket */ struct socket *socket; /* my UDP socket */
struct task_struct *io_thread; struct task_struct *io_thread;
struct list_head ack_tx_queue; /* List of ACKs that need sending */
spinlock_t ack_tx_lock; /* ACK list lock */
struct rxrpc_sock __rcu *service; /* Service(s) listening on this endpoint */ struct rxrpc_sock __rcu *service; /* Service(s) listening on this endpoint */
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */ struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */
struct sk_buff_head rx_queue; /* Received packets */ struct sk_buff_head rx_queue; /* Received packets */
...@@ -762,7 +760,6 @@ struct rxrpc_txbuf { ...@@ -762,7 +760,6 @@ struct rxrpc_txbuf {
struct rcu_head rcu; struct rcu_head rcu;
struct list_head call_link; /* Link in call->tx_sendmsg/tx_buffer */ struct list_head call_link; /* Link in call->tx_sendmsg/tx_buffer */
struct list_head tx_link; /* Link in live Enc queue or Tx queue */ struct list_head tx_link; /* Link in live Enc queue or Tx queue */
struct rxrpc_call *call; /* Call to which belongs */
ktime_t last_sent; /* Time at which last transmitted */ ktime_t last_sent; /* Time at which last transmitted */
refcount_t ref; refcount_t ref;
rxrpc_seq_t seq; /* Sequence number of this packet */ rxrpc_seq_t seq; /* Sequence number of this packet */
...@@ -1047,7 +1044,7 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net) ...@@ -1047,7 +1044,7 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
/* /*
* output.c * output.c
*/ */
void rxrpc_transmit_ack_packets(struct rxrpc_local *); int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb);
int rxrpc_send_abort_packet(struct rxrpc_call *); int rxrpc_send_abort_packet(struct rxrpc_call *);
int rxrpc_send_data_packet(struct rxrpc_call *, struct rxrpc_txbuf *); int rxrpc_send_data_packet(struct rxrpc_call *, struct rxrpc_txbuf *);
void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb); void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb);
......
...@@ -69,7 +69,6 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial, ...@@ -69,7 +69,6 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial,
void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason, void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why) rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
{ {
struct rxrpc_local *local = call->conn->local;
struct rxrpc_txbuf *txb; struct rxrpc_txbuf *txb;
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
...@@ -96,17 +95,9 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason, ...@@ -96,17 +95,9 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
txb->ack.reason = ack_reason; txb->ack.reason = ack_reason;
txb->ack.nAcks = 0; txb->ack.nAcks = 0;
if (!rxrpc_try_get_call(call, rxrpc_call_get_send_ack)) {
rxrpc_put_txbuf(txb, rxrpc_txbuf_put_nomem);
return;
}
spin_lock(&local->ack_tx_lock);
list_add_tail(&txb->tx_link, &local->ack_tx_queue);
spin_unlock(&local->ack_tx_lock);
trace_rxrpc_send_ack(call, why, ack_reason, serial); trace_rxrpc_send_ack(call, why, ack_reason, serial);
rxrpc_send_ack_packet(call, txb);
rxrpc_wake_up_io_thread(local); rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx);
} }
/* /*
...@@ -294,10 +285,6 @@ static void rxrpc_decant_prepared_tx(struct rxrpc_call *call) ...@@ -294,10 +285,6 @@ static void rxrpc_decant_prepared_tx(struct rxrpc_call *call)
rxrpc_transmit_one(call, txb); rxrpc_transmit_one(call, txb);
// TODO: Drain the transmission buffers. Do this somewhere better
if (after(call->acks_hard_ack, call->tx_bottom + 16))
rxrpc_shrink_call_tx_buffer(call);
if (!rxrpc_tx_window_has_space(call)) if (!rxrpc_tx_window_has_space(call))
break; break;
} }
......
...@@ -447,11 +447,6 @@ int rxrpc_io_thread(void *data) ...@@ -447,11 +447,6 @@ int rxrpc_io_thread(void *data)
continue; continue;
} }
if (!list_empty(&local->ack_tx_queue)) {
rxrpc_transmit_ack_packets(local);
continue;
}
/* Process received packets and errors. */ /* Process received packets and errors. */
if ((skb = __skb_dequeue(&rx_queue))) { if ((skb = __skb_dequeue(&rx_queue))) {
switch (skb->mark) { switch (skb->mark) {
......
...@@ -96,8 +96,6 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, ...@@ -96,8 +96,6 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
atomic_set(&local->active_users, 1); atomic_set(&local->active_users, 1);
local->rxnet = rxnet; local->rxnet = rxnet;
INIT_HLIST_NODE(&local->link); INIT_HLIST_NODE(&local->link);
INIT_LIST_HEAD(&local->ack_tx_queue);
spin_lock_init(&local->ack_tx_lock);
init_rwsem(&local->defrag_sem); init_rwsem(&local->defrag_sem);
skb_queue_head_init(&local->rx_queue); skb_queue_head_init(&local->rx_queue);
INIT_LIST_HEAD(&local->call_attend_q); INIT_LIST_HEAD(&local->call_attend_q);
......
...@@ -203,12 +203,11 @@ static void rxrpc_cancel_rtt_probe(struct rxrpc_call *call, ...@@ -203,12 +203,11 @@ static void rxrpc_cancel_rtt_probe(struct rxrpc_call *call,
} }
/* /*
* Send an ACK call packet. * Transmit an ACK packet.
*/ */
static int rxrpc_send_ack_packet(struct rxrpc_local *local, struct rxrpc_txbuf *txb) int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
{ {
struct rxrpc_connection *conn; struct rxrpc_connection *conn;
struct rxrpc_call *call = txb->call;
struct msghdr msg; struct msghdr msg;
struct kvec iov[1]; struct kvec iov[1];
rxrpc_serial_t serial; rxrpc_serial_t serial;
...@@ -271,43 +270,6 @@ static int rxrpc_send_ack_packet(struct rxrpc_local *local, struct rxrpc_txbuf * ...@@ -271,43 +270,6 @@ static int rxrpc_send_ack_packet(struct rxrpc_local *local, struct rxrpc_txbuf *
return ret; return ret;
} }
/*
* ACK transmitter for a local endpoint. The UDP socket locks around each
* transmission, so we can only transmit one packet at a time, ACK, DATA or
* otherwise.
*/
void rxrpc_transmit_ack_packets(struct rxrpc_local *local)
{
LIST_HEAD(queue);
int ret;
rxrpc_see_local(local, rxrpc_local_see_tx_ack);
if (list_empty(&local->ack_tx_queue))
return;
spin_lock(&local->ack_tx_lock);
list_splice_tail_init(&local->ack_tx_queue, &queue);
spin_unlock(&local->ack_tx_lock);
while (!list_empty(&queue)) {
struct rxrpc_txbuf *txb =
list_entry(queue.next, struct rxrpc_txbuf, tx_link);
ret = rxrpc_send_ack_packet(local, txb);
if (ret < 0 && ret != -ECONNRESET) {
spin_lock(&local->ack_tx_lock);
list_splice_init(&queue, &local->ack_tx_queue);
spin_unlock(&local->ack_tx_lock);
break;
}
list_del_init(&txb->tx_link);
rxrpc_put_call(txb->call, rxrpc_call_put_send_ack);
rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx);
}
}
/* /*
* Send an ABORT call packet. * Send an ABORT call packet.
*/ */
......
...@@ -320,7 +320,6 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, ...@@ -320,7 +320,6 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
ret = ret2; ret = ret2;
goto out; goto out;
} }
rxrpc_transmit_ack_packets(call->peer->local);
} else { } else {
trace_rxrpc_recvdata(call, rxrpc_recvmsg_cont, seq, trace_rxrpc_recvdata(call, rxrpc_recvmsg_cont, seq,
rx_pkt_offset, rx_pkt_len, 0); rx_pkt_offset, rx_pkt_len, 0);
...@@ -502,7 +501,6 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -502,7 +501,6 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
if (ret == -EAGAIN) if (ret == -EAGAIN)
ret = 0; ret = 0;
rxrpc_transmit_ack_packets(call->peer->local);
if (!skb_queue_empty(&call->recvmsg_queue)) if (!skb_queue_empty(&call->recvmsg_queue))
rxrpc_notify_socket(call); rxrpc_notify_socket(call);
break; break;
...@@ -632,7 +630,6 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, ...@@ -632,7 +630,6 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
read_phase_complete: read_phase_complete:
ret = 1; ret = 1;
out: out:
rxrpc_transmit_ack_packets(call->peer->local);
if (_service) if (_service)
*_service = call->dest_srx.srx_service; *_service = call->dest_srx.srx_service;
mutex_unlock(&call->user_mutex); mutex_unlock(&call->user_mutex);
......
...@@ -276,8 +276,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -276,8 +276,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
rxrpc_see_txbuf(txb, rxrpc_txbuf_see_send_more); rxrpc_see_txbuf(txb, rxrpc_txbuf_see_send_more);
do { do {
rxrpc_transmit_ack_packets(call->peer->local);
if (!txb) { if (!txb) {
size_t remain, bufsize, chunk, offset; size_t remain, bufsize, chunk, offset;
......
...@@ -26,7 +26,6 @@ struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type, ...@@ -26,7 +26,6 @@ struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type,
INIT_LIST_HEAD(&txb->call_link); INIT_LIST_HEAD(&txb->call_link);
INIT_LIST_HEAD(&txb->tx_link); INIT_LIST_HEAD(&txb->tx_link);
refcount_set(&txb->ref, 1); refcount_set(&txb->ref, 1);
txb->call = call;
txb->call_debug_id = call->debug_id; txb->call_debug_id = call->debug_id;
txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids); txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids);
txb->space = sizeof(txb->data); txb->space = sizeof(txb->data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment