Skip to content

Commit 08d55d7

Browse files
dhowellskuba-moo
authored andcommitted
rxrpc: Don't allocate a txbuf for an ACK transmission
Don't allocate an rxrpc_txbuf struct for an ACK transmission. There's now no need as the memory to hold the ACK content is allocated with a page frag allocator. The allocation and freeing of a txbuf is just unnecessary overhead. Signed-off-by: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent fe24a54 commit 08d55d7

File tree

4 files changed

+131
-162
lines changed

4 files changed

+131
-162
lines changed

include/trace/events/rxrpc.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,13 +462,11 @@
462462
/* ---- Must update size of stat_why_req_ack[] if more are added! */
463463

464464
#define rxrpc_txbuf_traces \
465-
EM(rxrpc_txbuf_alloc_ack, "ALLOC ACK ") \
466465
EM(rxrpc_txbuf_alloc_data, "ALLOC DATA ") \
467466
EM(rxrpc_txbuf_free, "FREE ") \
468467
EM(rxrpc_txbuf_get_buffer, "GET BUFFER ") \
469468
EM(rxrpc_txbuf_get_trans, "GET TRANS ") \
470469
EM(rxrpc_txbuf_get_retrans, "GET RETRANS") \
471-
EM(rxrpc_txbuf_put_ack_tx, "PUT ACK TX ") \
472470
EM(rxrpc_txbuf_put_cleaned, "PUT CLEANED") \
473471
EM(rxrpc_txbuf_put_nomem, "PUT NOMEM ") \
474472
EM(rxrpc_txbuf_put_rotated, "PUT ROTATED") \

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,11 +834,9 @@ struct rxrpc_txbuf {
834834
#define RXRPC_TXBUF_WIRE_FLAGS 0xff /* The wire protocol flags */
835835
#define RXRPC_TXBUF_RESENT 0x100 /* Set if has been resent */
836836
__be16 cksum; /* Checksum to go in header */
837-
unsigned short ack_rwind; /* ACK receive window */
838-
u8 /*enum rxrpc_propose_ack_trace*/ ack_why; /* If ack, why */
839837
bool jumboable; /* Can be non-terminal jumbo subpacket */
840838
u8 nr_kvec; /* Amount of kvec[] used */
841-
struct kvec kvec[3];
839+
struct kvec kvec[1];
842840
};
843841

844842
static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb)
@@ -1364,7 +1362,6 @@ static inline void rxrpc_sysctl_exit(void) {}
13641362
extern atomic_t rxrpc_nr_txbuf;
13651363
struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size,
13661364
size_t data_align, gfp_t gfp);
1367-
struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t sack_size);
13681365
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
13691366
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
13701367
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);

net/rxrpc/output.c

Lines changed: 130 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -71,50 +71,134 @@ static void rxrpc_set_keepalive(struct rxrpc_call *call, ktime_t now)
7171
trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_keepalive);
7272
}
7373

74+
/*
75+
* Allocate transmission buffers for an ACK and attach them to local->kv[].
76+
*/
77+
static int rxrpc_alloc_ack(struct rxrpc_call *call, size_t sack_size)
78+
{
79+
struct rxrpc_wire_header *whdr;
80+
struct rxrpc_acktrailer *trailer;
81+
struct rxrpc_ackpacket *ack;
82+
struct kvec *kv = call->local->kvec;
83+
gfp_t gfp = rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS;
84+
void *buf, *buf2 = NULL;
85+
u8 *filler;
86+
87+
buf = page_frag_alloc(&call->local->tx_alloc,
88+
sizeof(*whdr) + sizeof(*ack) + 1 + 3 + sizeof(*trailer), gfp);
89+
if (!buf)
90+
return -ENOMEM;
91+
92+
if (sack_size) {
93+
buf2 = page_frag_alloc(&call->local->tx_alloc, sack_size, gfp);
94+
if (!buf2) {
95+
page_frag_free(buf);
96+
return -ENOMEM;
97+
}
98+
}
99+
100+
whdr = buf;
101+
ack = buf + sizeof(*whdr);
102+
filler = buf + sizeof(*whdr) + sizeof(*ack) + 1;
103+
trailer = buf + sizeof(*whdr) + sizeof(*ack) + 1 + 3;
104+
105+
kv[0].iov_base = whdr;
106+
kv[0].iov_len = sizeof(*whdr) + sizeof(*ack);
107+
kv[1].iov_base = buf2;
108+
kv[1].iov_len = sack_size;
109+
kv[2].iov_base = filler;
110+
kv[2].iov_len = 3 + sizeof(*trailer);
111+
return 3; /* Number of kvec[] used. */
112+
}
113+
114+
static void rxrpc_free_ack(struct rxrpc_call *call)
115+
{
116+
page_frag_free(call->local->kvec[0].iov_base);
117+
if (call->local->kvec[1].iov_base)
118+
page_frag_free(call->local->kvec[1].iov_base);
119+
}
120+
121+
/*
122+
* Record the beginning of an RTT probe.
123+
*/
124+
static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
125+
ktime_t now, enum rxrpc_rtt_tx_trace why)
126+
{
127+
unsigned long avail = call->rtt_avail;
128+
int rtt_slot = 9;
129+
130+
if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK))
131+
goto no_slot;
132+
133+
rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK);
134+
if (!test_and_clear_bit(rtt_slot, &call->rtt_avail))
135+
goto no_slot;
136+
137+
call->rtt_serial[rtt_slot] = serial;
138+
call->rtt_sent_at[rtt_slot] = now;
139+
smp_wmb(); /* Write data before avail bit */
140+
set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
141+
142+
trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
143+
return;
144+
145+
no_slot:
146+
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
147+
}
148+
74149
/*
75150
* Fill out an ACK packet.
76151
*/
77-
static void rxrpc_fill_out_ack(struct rxrpc_call *call,
78-
struct rxrpc_txbuf *txb,
79-
u8 ack_reason,
80-
rxrpc_serial_t serial)
152+
static int rxrpc_fill_out_ack(struct rxrpc_call *call, int nr_kv, u8 ack_reason,
153+
rxrpc_serial_t serial_to_ack, rxrpc_serial_t *_ack_serial)
81154
{
82-
struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
83-
struct rxrpc_acktrailer *trailer = txb->kvec[2].iov_base + 3;
155+
struct kvec *kv = call->local->kvec;
156+
struct rxrpc_wire_header *whdr = kv[0].iov_base;
157+
struct rxrpc_acktrailer *trailer = kv[2].iov_base + 3;
84158
struct rxrpc_ackpacket *ack = (struct rxrpc_ackpacket *)(whdr + 1);
85159
unsigned int qsize, sack, wrap, to, max_mtu, if_mtu;
86160
rxrpc_seq_t window, wtop;
161+
ktime_t now = ktime_get_real();
87162
int rsize;
88-
u8 *filler = txb->kvec[2].iov_base;
89-
u8 *sackp = txb->kvec[1].iov_base;
163+
u8 *filler = kv[2].iov_base;
164+
u8 *sackp = kv[1].iov_base;
90165

91166
rxrpc_inc_stat(call->rxnet, stat_tx_ack_fill);
92167

93168
window = call->ackr_window;
94169
wtop = call->ackr_wtop;
95170
sack = call->ackr_sack_base % RXRPC_SACK_SIZE;
96171

172+
*_ack_serial = rxrpc_get_next_serial(call->conn);
173+
174+
whdr->epoch = htonl(call->conn->proto.epoch);
175+
whdr->cid = htonl(call->cid);
176+
whdr->callNumber = htonl(call->call_id);
177+
whdr->serial = htonl(*_ack_serial);
97178
whdr->seq = 0;
98179
whdr->type = RXRPC_PACKET_TYPE_ACK;
99-
txb->flags |= RXRPC_SLOW_START_OK;
180+
whdr->flags = call->conn->out_clientflag | RXRPC_SLOW_START_OK;
181+
whdr->userStatus = 0;
182+
whdr->securityIndex = call->security_ix;
183+
whdr->_rsvd = 0;
184+
whdr->serviceId = htons(call->dest_srx.srx_service);
185+
100186
ack->bufferSpace = 0;
101187
ack->maxSkew = 0;
102188
ack->firstPacket = htonl(window);
103189
ack->previousPacket = htonl(call->rx_highest_seq);
104-
ack->serial = htonl(serial);
190+
ack->serial = htonl(serial_to_ack);
105191
ack->reason = ack_reason;
106192
ack->nAcks = wtop - window;
107193
filler[0] = 0;
108194
filler[1] = 0;
109195
filler[2] = 0;
110196

111197
if (ack_reason == RXRPC_ACK_PING)
112-
txb->flags |= RXRPC_REQUEST_ACK;
198+
whdr->flags |= RXRPC_REQUEST_ACK;
113199

114200
if (after(wtop, window)) {
115-
txb->len += ack->nAcks;
116-
txb->kvec[1].iov_base = sackp;
117-
txb->kvec[1].iov_len = ack->nAcks;
201+
kv[1].iov_len = ack->nAcks;
118202

119203
wrap = RXRPC_SACK_SIZE - sack;
120204
to = umin(ack->nAcks, RXRPC_SACK_SIZE);
@@ -133,7 +217,6 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
133217

134218
qsize = (window - 1) - call->rx_consumed;
135219
rsize = max_t(int, call->rx_winsize - qsize, 0);
136-
txb->ack_rwind = rsize;
137220

138221
if_mtu = call->peer->if_mtu - call->peer->hdrsize;
139222
if (call->peer->ackr_adv_pmtud) {
@@ -147,48 +230,27 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
147230
trailer->ifMTU = htonl(if_mtu);
148231
trailer->rwind = htonl(rsize);
149232
trailer->jumbo_max = 0; /* Advertise pmtu discovery */
150-
}
151-
152-
/*
153-
* Record the beginning of an RTT probe.
154-
*/
155-
static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
156-
ktime_t now, enum rxrpc_rtt_tx_trace why)
157-
{
158-
unsigned long avail = call->rtt_avail;
159-
int rtt_slot = 9;
160233

161-
if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK))
162-
goto no_slot;
163-
164-
rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK);
165-
if (!test_and_clear_bit(rtt_slot, &call->rtt_avail))
166-
goto no_slot;
167-
168-
call->rtt_serial[rtt_slot] = serial;
169-
call->rtt_sent_at[rtt_slot] = now;
170-
smp_wmb(); /* Write data before avail bit */
171-
set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
172-
173-
trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
174-
return;
175-
176-
no_slot:
177-
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
234+
if (ack_reason == RXRPC_ACK_PING)
235+
rxrpc_begin_rtt_probe(call, *_ack_serial, now, rxrpc_rtt_tx_ping);
236+
if (whdr->flags & RXRPC_REQUEST_ACK)
237+
call->peer->rtt_last_req = now;
238+
rxrpc_set_keepalive(call, now);
239+
return nr_kv;
178240
}
179241

180242
/*
181243
* Transmit an ACK packet.
182244
*/
183-
static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb,
184-
int nr_kv, enum rxrpc_propose_ack_trace why)
245+
static void rxrpc_send_ack_packet(struct rxrpc_call *call, int nr_kv, size_t len,
246+
rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
185247
{
186248
struct kvec *kv = call->local->kvec;
187249
struct rxrpc_wire_header *whdr = kv[0].iov_base;
250+
struct rxrpc_acktrailer *trailer = kv[2].iov_base + 3;
188251
struct rxrpc_connection *conn;
189252
struct rxrpc_ackpacket *ack = (struct rxrpc_ackpacket *)(whdr + 1);
190253
struct msghdr msg;
191-
ktime_t now;
192254
int ret;
193255

194256
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
@@ -202,41 +264,31 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
202264
msg.msg_controllen = 0;
203265
msg.msg_flags = MSG_SPLICE_PAGES;
204266

205-
whdr->flags = txb->flags & RXRPC_TXBUF_WIRE_FLAGS;
206-
207-
txb->serial = rxrpc_get_next_serial(conn);
208-
whdr->serial = htonl(txb->serial);
209-
trace_rxrpc_tx_ack(call->debug_id, txb->serial,
267+
trace_rxrpc_tx_ack(call->debug_id, serial,
210268
ntohl(ack->firstPacket),
211269
ntohl(ack->serial), ack->reason, ack->nAcks,
212-
txb->ack_rwind);
270+
ntohl(trailer->rwind));
213271

214272
rxrpc_inc_stat(call->rxnet, stat_tx_ack_send);
215273

216-
iov_iter_kvec(&msg.msg_iter, WRITE, kv, nr_kv, txb->len);
274+
iov_iter_kvec(&msg.msg_iter, WRITE, kv, nr_kv, len);
217275
rxrpc_local_dont_fragment(conn->local, why == rxrpc_propose_ack_ping_for_mtu_probe);
218276

219-
ret = do_udp_sendmsg(conn->local->socket, &msg, txb->len);
277+
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
220278
call->peer->last_tx_at = ktime_get_seconds();
221279
if (ret < 0) {
222-
trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret,
280+
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
223281
rxrpc_tx_point_call_ack);
224282
if (why == rxrpc_propose_ack_ping_for_mtu_probe &&
225283
ret == -EMSGSIZE)
226-
rxrpc_input_probe_for_pmtud(conn, txb->serial, true);
284+
rxrpc_input_probe_for_pmtud(conn, serial, true);
227285
} else {
228286
trace_rxrpc_tx_packet(call->debug_id, whdr,
229287
rxrpc_tx_point_call_ack);
230-
now = ktime_get_real();
231-
if (ack->reason == RXRPC_ACK_PING)
232-
rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_ping);
233-
if (txb->flags & RXRPC_REQUEST_ACK)
234-
call->peer->rtt_last_req = now;
235-
rxrpc_set_keepalive(call, now);
236288
if (why == rxrpc_propose_ack_ping_for_mtu_probe) {
237289
call->peer->pmtud_pending = false;
238290
call->peer->pmtud_probing = true;
239-
call->conn->pmtud_probe = txb->serial;
291+
call->conn->pmtud_probe = serial;
240292
call->conn->pmtud_call = call->debug_id;
241293
trace_rxrpc_pmtud_tx(call);
242294
}
@@ -248,43 +300,41 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
248300
* Queue an ACK for immediate transmission.
249301
*/
250302
void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
251-
rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
303+
rxrpc_serial_t serial_to_ack, enum rxrpc_propose_ack_trace why)
252304
{
253-
struct rxrpc_txbuf *txb;
254305
struct kvec *kv = call->local->kvec;
306+
rxrpc_serial_t ack_serial;
307+
size_t len;
255308
int nr_kv;
256309

257310
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
258311
return;
259312

260313
rxrpc_inc_stat(call->rxnet, stat_tx_acks[ack_reason]);
261314

262-
txb = rxrpc_alloc_ack_txbuf(call, call->ackr_wtop - call->ackr_window);
263-
if (!txb) {
315+
nr_kv = rxrpc_alloc_ack(call, call->ackr_wtop - call->ackr_window);
316+
if (nr_kv < 0) {
264317
kleave(" = -ENOMEM");
265318
return;
266319
}
267320

268-
txb->ack_why = why;
269-
270-
rxrpc_fill_out_ack(call, txb, ack_reason, serial);
321+
nr_kv = rxrpc_fill_out_ack(call, nr_kv, ack_reason, serial_to_ack, &ack_serial);
322+
len = kv[0].iov_len;
323+
len += kv[1].iov_len;
324+
len += kv[2].iov_len;
271325

272326
/* Extend a path MTU probe ACK. */
273-
nr_kv = txb->nr_kvec;
274-
kv[0] = txb->kvec[0];
275-
kv[1] = txb->kvec[1];
276-
kv[2] = txb->kvec[2];
277327
if (why == rxrpc_propose_ack_ping_for_mtu_probe) {
278328
size_t probe_mtu = call->peer->pmtud_trial + sizeof(struct rxrpc_wire_header);
279329

280-
if (txb->len > probe_mtu)
330+
if (len > probe_mtu)
281331
goto skip;
282-
while (txb->len < probe_mtu) {
283-
size_t part = umin(probe_mtu - txb->len, PAGE_SIZE);
332+
while (len < probe_mtu) {
333+
size_t part = umin(probe_mtu - len, PAGE_SIZE);
284334

285335
kv[nr_kv].iov_base = page_address(ZERO_PAGE(0));
286336
kv[nr_kv].iov_len = part;
287-
txb->len += part;
337+
len += part;
288338
nr_kv++;
289339
}
290340
}
@@ -293,10 +343,10 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
293343
atomic_set(&call->ackr_nr_consumed, 0);
294344
clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags);
295345

296-
trace_rxrpc_send_ack(call, why, ack_reason, serial);
297-
rxrpc_send_ack_packet(call, txb, nr_kv, why);
346+
trace_rxrpc_send_ack(call, why, ack_reason, ack_serial);
347+
rxrpc_send_ack_packet(call, nr_kv, len, ack_serial, why);
298348
skip:
299-
rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx);
349+
rxrpc_free_ack(call);
300350
}
301351

302352
/*

0 commit comments

Comments
 (0)