From nobody Fri Dec 19 04:58:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77DD81FA152 for ; Wed, 4 Dec 2024 07:49:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733298580; cv=none; b=gUfgIbq+6NwIJA8ZTa3bG+fdY0uaC5nH+EPeyoBQR1cw679ymkbMfClLrFT9j/4TzPy1PJuz9CqTVVfgdMLroVvks0GFemGLMyeNvGginfAwZRA/4+tl94JGFHDwcvaVAvGkG5KFdBG4z0O9e1QoztGEzBuVRg4QC0PxrIIjwVA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733298580; c=relaxed/simple; bh=r6XxiMorSB7iCxcRmjAn6I0MmLgfybiYXyywp/2AbvA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QHez/0ox0OaBrDVwJFiaw6mmDWT9oaTel8t/DGKjN+pPlhBYlF8nULyy8t4HckiVCKI1tb72QPMwDq2PPskrFau3IwE5Xe8TRc198F9RFAOA5lkt9bJuPNiovOB0h9C2lafRiP9FRgVCsT1WiEax44l9Own3PYKweV136ynmZSo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=gTVWyWG3; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gTVWyWG3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733298577; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1fNoQdyhV9AAcRe00YDnSdUYOhhnLt52W/9/eqOE1q8=; b=gTVWyWG33EiWmqBS0TxtVX2mMIRxL3EDMCCr7q03MkP7ezlzupkNhnhZOXV14jLkdbuXgR HNi8DgAGld9WuuyXIg8IMjhX0QqflcVuPTc0ygFFrPASscftyUZKozq38f9zN7hsbMpVJ6 MCdmVxs3kIXC/BQff1ArnVaphcx0zG0= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-57-JPgeBJCgMCeNmsFB1B_1iQ-1; Wed, 04 Dec 2024 02:49:31 -0500 X-MC-Unique: JPgeBJCgMCeNmsFB1B_1iQ-1 X-Mimecast-MFC-AGG-ID: JPgeBJCgMCeNmsFB1B_1iQ Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 55D6E1956055; Wed, 4 Dec 2024 07:49:30 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.42.28.48]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C76083000197; Wed, 4 Dec 2024 07:49:27 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Yunsheng Lin , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 32/39] rxrpc: Don't allocate a txbuf for an ACK transmission Date: Wed, 4 Dec 2024 07:47:00 +0000 Message-ID: <20241204074710.990092-33-dhowells@redhat.com> In-Reply-To: <20241204074710.990092-1-dhowells@redhat.com> References: <20241204074710.990092-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" 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 cc: Marc Dionne cc: "David S. Miller" cc: Eric Dumazet cc: Jakub Kicinski cc: Paolo Abeni cc: linux-afs@lists.infradead.org cc: netdev@vger.kernel.org --- include/trace/events/rxrpc.h | 2 - net/rxrpc/ar-internal.h | 5 +- net/rxrpc/output.c | 210 ++++++++++++++++++++++------------- net/rxrpc/txbuf.c | 76 ------------- 4 files changed, 131 insertions(+), 162 deletions(-) diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 7681c67f7d65..326a4c257aea 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -462,13 +462,11 @@ /* ---- Must update size of stat_why_req_ack[] if more are added! */ =20 #define rxrpc_txbuf_traces \ - EM(rxrpc_txbuf_alloc_ack, "ALLOC ACK ") \ EM(rxrpc_txbuf_alloc_data, "ALLOC DATA ") \ EM(rxrpc_txbuf_free, "FREE ") \ EM(rxrpc_txbuf_get_buffer, "GET BUFFER ") \ EM(rxrpc_txbuf_get_trans, "GET TRANS ") \ EM(rxrpc_txbuf_get_retrans, "GET RETRANS") \ - EM(rxrpc_txbuf_put_ack_tx, "PUT ACK TX ") \ EM(rxrpc_txbuf_put_cleaned, "PUT CLEANED") \ EM(rxrpc_txbuf_put_nomem, "PUT NOMEM ") \ EM(rxrpc_txbuf_put_rotated, "PUT ROTATED") \ diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 1307749a1a74..db93d7f78902 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -834,11 +834,9 @@ struct rxrpc_txbuf { #define RXRPC_TXBUF_WIRE_FLAGS 0xff /* The wire protocol flags */ #define RXRPC_TXBUF_RESENT 0x100 /* Set if has been resent */ __be16 cksum; /* Checksum to go in header */ - unsigned short ack_rwind; /* ACK receive window */ - u8 /*enum rxrpc_propose_ack_trace*/ ack_why; /* If ack, why */ bool jumboable; /* Can be non-terminal jumbo subpacket */ u8 nr_kvec; /* Amount of kvec[] used */ - struct kvec kvec[3]; + struct kvec kvec[1]; }; =20 static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb) @@ -1364,7 +1362,6 @@ static inline void rxrpc_sysctl_exit(void) {} extern atomic_t rxrpc_nr_txbuf; struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t= data_size, size_t data_align, gfp_t gfp); -struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t = sack_size); void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what); void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what); void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what); diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 20bf45317264..a7de8a02f419 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c @@ -71,22 +71,97 @@ static void rxrpc_set_keepalive(struct rxrpc_call *call= , ktime_t now) trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_keepalive); } =20 +/* + * Allocate transmission buffers for an ACK and attach them to local->kv[]. + */ +static int rxrpc_alloc_ack(struct rxrpc_call *call, size_t sack_size) +{ + struct rxrpc_wire_header *whdr; + struct rxrpc_acktrailer *trailer; + struct rxrpc_ackpacket *ack; + struct kvec *kv =3D call->local->kvec; + gfp_t gfp =3D rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS; + void *buf, *buf2 =3D NULL; + u8 *filler; + + buf =3D page_frag_alloc(&call->local->tx_alloc, + sizeof(*whdr) + sizeof(*ack) + 1 + 3 + sizeof(*trailer), gfp); + if (!buf) + return -ENOMEM; + + if (sack_size) { + buf2 =3D page_frag_alloc(&call->local->tx_alloc, sack_size, gfp); + if (!buf2) { + page_frag_free(buf); + return -ENOMEM; + } + } + + whdr =3D buf; + ack =3D buf + sizeof(*whdr); + filler =3D buf + sizeof(*whdr) + sizeof(*ack) + 1; + trailer =3D buf + sizeof(*whdr) + sizeof(*ack) + 1 + 3; + + kv[0].iov_base =3D whdr; + kv[0].iov_len =3D sizeof(*whdr) + sizeof(*ack); + kv[1].iov_base =3D buf2; + kv[1].iov_len =3D sack_size; + kv[2].iov_base =3D filler; + kv[2].iov_len =3D 3 + sizeof(*trailer); + return 3; /* Number of kvec[] used. */ +} + +static void rxrpc_free_ack(struct rxrpc_call *call) +{ + page_frag_free(call->local->kvec[0].iov_base); + if (call->local->kvec[1].iov_base) + page_frag_free(call->local->kvec[1].iov_base); +} + +/* + * Record the beginning of an RTT probe. + */ +static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t = serial, + ktime_t now, enum rxrpc_rtt_tx_trace why) +{ + unsigned long avail =3D call->rtt_avail; + int rtt_slot =3D 9; + + if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK)) + goto no_slot; + + rtt_slot =3D __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK); + if (!test_and_clear_bit(rtt_slot, &call->rtt_avail)) + goto no_slot; + + call->rtt_serial[rtt_slot] =3D serial; + call->rtt_sent_at[rtt_slot] =3D now; + smp_wmb(); /* Write data before avail bit */ + set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); + + trace_rxrpc_rtt_tx(call, why, rtt_slot, serial); + return; + +no_slot: + trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial); +} + /* * Fill out an ACK packet. */ -static void rxrpc_fill_out_ack(struct rxrpc_call *call, - struct rxrpc_txbuf *txb, - u8 ack_reason, - rxrpc_serial_t serial) +static int rxrpc_fill_out_ack(struct rxrpc_call *call, int nr_kv, u8 ack_r= eason, + rxrpc_serial_t serial_to_ack, rxrpc_serial_t *_ack_serial) { - struct rxrpc_wire_header *whdr =3D txb->kvec[0].iov_base; - struct rxrpc_acktrailer *trailer =3D txb->kvec[2].iov_base + 3; + struct kvec *kv =3D call->local->kvec; + struct rxrpc_wire_header *whdr =3D kv[0].iov_base; + struct rxrpc_acktrailer *trailer =3D kv[2].iov_base + 3; struct rxrpc_ackpacket *ack =3D (struct rxrpc_ackpacket *)(whdr + 1); unsigned int qsize, sack, wrap, to, max_mtu, if_mtu; rxrpc_seq_t window, wtop; + ktime_t now =3D ktime_get_real(); int rsize; - u8 *filler =3D txb->kvec[2].iov_base; - u8 *sackp =3D txb->kvec[1].iov_base; + u8 *filler =3D kv[2].iov_base; + u8 *sackp =3D kv[1].iov_base; =20 rxrpc_inc_stat(call->rxnet, stat_tx_ack_fill); =20 @@ -94,14 +169,25 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call, wtop =3D call->ackr_wtop; sack =3D call->ackr_sack_base % RXRPC_SACK_SIZE; =20 + *_ack_serial =3D rxrpc_get_next_serial(call->conn); + + whdr->epoch =3D htonl(call->conn->proto.epoch); + whdr->cid =3D htonl(call->cid); + whdr->callNumber =3D htonl(call->call_id); + whdr->serial =3D htonl(*_ack_serial); whdr->seq =3D 0; whdr->type =3D RXRPC_PACKET_TYPE_ACK; - txb->flags |=3D RXRPC_SLOW_START_OK; + whdr->flags =3D call->conn->out_clientflag | RXRPC_SLOW_START_OK; + whdr->userStatus =3D 0; + whdr->securityIndex =3D call->security_ix; + whdr->_rsvd =3D 0; + whdr->serviceId =3D htons(call->dest_srx.srx_service); + ack->bufferSpace =3D 0; ack->maxSkew =3D 0; ack->firstPacket =3D htonl(window); ack->previousPacket =3D htonl(call->rx_highest_seq); - ack->serial =3D htonl(serial); + ack->serial =3D htonl(serial_to_ack); ack->reason =3D ack_reason; ack->nAcks =3D wtop - window; filler[0] =3D 0; @@ -109,12 +195,10 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *cal= l, filler[2] =3D 0; =20 if (ack_reason =3D=3D RXRPC_ACK_PING) - txb->flags |=3D RXRPC_REQUEST_ACK; + whdr->flags |=3D RXRPC_REQUEST_ACK; =20 if (after(wtop, window)) { - txb->len +=3D ack->nAcks; - txb->kvec[1].iov_base =3D sackp; - txb->kvec[1].iov_len =3D ack->nAcks; + kv[1].iov_len =3D ack->nAcks; =20 wrap =3D RXRPC_SACK_SIZE - sack; to =3D umin(ack->nAcks, RXRPC_SACK_SIZE); @@ -133,7 +217,6 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call, =20 qsize =3D (window - 1) - call->rx_consumed; rsize =3D max_t(int, call->rx_winsize - qsize, 0); - txb->ack_rwind =3D rsize; =20 if_mtu =3D call->peer->if_mtu - call->peer->hdrsize; if (call->peer->ackr_adv_pmtud) { @@ -147,48 +230,27 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *cal= l, trailer->ifMTU =3D htonl(if_mtu); trailer->rwind =3D htonl(rsize); trailer->jumbo_max =3D 0; /* Advertise pmtu discovery */ -} - -/* - * Record the beginning of an RTT probe. - */ -static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t = serial, - ktime_t now, enum rxrpc_rtt_tx_trace why) -{ - unsigned long avail =3D call->rtt_avail; - int rtt_slot =3D 9; =20 - if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK)) - goto no_slot; - - rtt_slot =3D __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK); - if (!test_and_clear_bit(rtt_slot, &call->rtt_avail)) - goto no_slot; - - call->rtt_serial[rtt_slot] =3D serial; - call->rtt_sent_at[rtt_slot] =3D now; - smp_wmb(); /* Write data before avail bit */ - set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); - - trace_rxrpc_rtt_tx(call, why, rtt_slot, serial); - return; - -no_slot: - trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial); + if (ack_reason =3D=3D RXRPC_ACK_PING) + rxrpc_begin_rtt_probe(call, *_ack_serial, now, rxrpc_rtt_tx_ping); + if (whdr->flags & RXRPC_REQUEST_ACK) + call->peer->rtt_last_req =3D now; + rxrpc_set_keepalive(call, now); + return nr_kv; } =20 /* * Transmit an ACK packet. */ -static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_tx= buf *txb, - int nr_kv, enum rxrpc_propose_ack_trace why) +static void rxrpc_send_ack_packet(struct rxrpc_call *call, int nr_kv, size= _t len, + rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why) { struct kvec *kv =3D call->local->kvec; struct rxrpc_wire_header *whdr =3D kv[0].iov_base; + struct rxrpc_acktrailer *trailer =3D kv[2].iov_base + 3; struct rxrpc_connection *conn; struct rxrpc_ackpacket *ack =3D (struct rxrpc_ackpacket *)(whdr + 1); struct msghdr msg; - ktime_t now; int ret; =20 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 msg.msg_controllen =3D 0; msg.msg_flags =3D MSG_SPLICE_PAGES; =20 - whdr->flags =3D txb->flags & RXRPC_TXBUF_WIRE_FLAGS; - - txb->serial =3D rxrpc_get_next_serial(conn); - whdr->serial =3D htonl(txb->serial); - trace_rxrpc_tx_ack(call->debug_id, txb->serial, + trace_rxrpc_tx_ack(call->debug_id, serial, ntohl(ack->firstPacket), ntohl(ack->serial), ack->reason, ack->nAcks, - txb->ack_rwind); + ntohl(trailer->rwind)); =20 rxrpc_inc_stat(call->rxnet, stat_tx_ack_send); =20 - iov_iter_kvec(&msg.msg_iter, WRITE, kv, nr_kv, txb->len); + iov_iter_kvec(&msg.msg_iter, WRITE, kv, nr_kv, len); rxrpc_local_dont_fragment(conn->local, why =3D=3D rxrpc_propose_ack_ping_= for_mtu_probe); =20 - ret =3D do_udp_sendmsg(conn->local->socket, &msg, txb->len); + ret =3D do_udp_sendmsg(conn->local->socket, &msg, len); call->peer->last_tx_at =3D ktime_get_seconds(); if (ret < 0) { - trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret, + trace_rxrpc_tx_fail(call->debug_id, serial, ret, rxrpc_tx_point_call_ack); if (why =3D=3D rxrpc_propose_ack_ping_for_mtu_probe && ret =3D=3D -EMSGSIZE) - rxrpc_input_probe_for_pmtud(conn, txb->serial, true); + rxrpc_input_probe_for_pmtud(conn, serial, true); } else { trace_rxrpc_tx_packet(call->debug_id, whdr, rxrpc_tx_point_call_ack); - now =3D ktime_get_real(); - if (ack->reason =3D=3D RXRPC_ACK_PING) - rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_ping); - if (txb->flags & RXRPC_REQUEST_ACK) - call->peer->rtt_last_req =3D now; - rxrpc_set_keepalive(call, now); if (why =3D=3D rxrpc_propose_ack_ping_for_mtu_probe) { call->peer->pmtud_pending =3D false; call->peer->pmtud_probing =3D true; - call->conn->pmtud_probe =3D txb->serial; + call->conn->pmtud_probe =3D serial; call->conn->pmtud_call =3D call->debug_id; trace_rxrpc_pmtud_tx(call); } @@ -248,10 +300,11 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *= call, struct rxrpc_txbuf *t * Queue an ACK for immediate transmission. */ 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_to_ack, enum rxrpc_propose_ack_trace why) { - struct rxrpc_txbuf *txb; struct kvec *kv =3D call->local->kvec; + rxrpc_serial_t ack_serial; + size_t len; int nr_kv; =20 if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) @@ -259,32 +312,29 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_r= eason, =20 rxrpc_inc_stat(call->rxnet, stat_tx_acks[ack_reason]); =20 - txb =3D rxrpc_alloc_ack_txbuf(call, call->ackr_wtop - call->ackr_window); - if (!txb) { + nr_kv =3D rxrpc_alloc_ack(call, call->ackr_wtop - call->ackr_window); + if (nr_kv < 0) { kleave(" =3D -ENOMEM"); return; } =20 - txb->ack_why =3D why; - - rxrpc_fill_out_ack(call, txb, ack_reason, serial); + nr_kv =3D rxrpc_fill_out_ack(call, nr_kv, ack_reason, serial_to_ack, &ack= _serial); + len =3D kv[0].iov_len; + len +=3D kv[1].iov_len; + len +=3D kv[2].iov_len; =20 /* Extend a path MTU probe ACK. */ - nr_kv =3D txb->nr_kvec; - kv[0] =3D txb->kvec[0]; - kv[1] =3D txb->kvec[1]; - kv[2] =3D txb->kvec[2]; if (why =3D=3D rxrpc_propose_ack_ping_for_mtu_probe) { size_t probe_mtu =3D call->peer->pmtud_trial + sizeof(struct rxrpc_wire_= header); =20 - if (txb->len > probe_mtu) + if (len > probe_mtu) goto skip; - while (txb->len < probe_mtu) { - size_t part =3D umin(probe_mtu - txb->len, PAGE_SIZE); + while (len < probe_mtu) { + size_t part =3D umin(probe_mtu - len, PAGE_SIZE); =20 kv[nr_kv].iov_base =3D page_address(ZERO_PAGE(0)); kv[nr_kv].iov_len =3D part; - txb->len +=3D part; + len +=3D part; nr_kv++; } } @@ -293,10 +343,10 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_r= eason, atomic_set(&call->ackr_nr_consumed, 0); clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags); =20 - trace_rxrpc_send_ack(call, why, ack_reason, serial); - rxrpc_send_ack_packet(call, txb, nr_kv, why); + trace_rxrpc_send_ack(call, why, ack_reason, ack_serial); + rxrpc_send_ack_packet(call, nr_kv, len, ack_serial, why); skip: - rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx); + rxrpc_free_ack(call); } =20 /* diff --git a/net/rxrpc/txbuf.c b/net/rxrpc/txbuf.c index 067223c8c35f..131d9e55c8e9 100644 --- a/net/rxrpc/txbuf.c +++ b/net/rxrpc/txbuf.c @@ -73,82 +73,6 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_= call *call, size_t data_ return txb; } =20 -/* - * Allocate and partially initialise an ACK packet. - */ -struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t = sack_size) -{ - struct rxrpc_wire_header *whdr; - struct rxrpc_acktrailer *trailer; - struct rxrpc_ackpacket *ack; - struct rxrpc_txbuf *txb; - gfp_t gfp =3D rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS; - void *buf, *buf2 =3D NULL; - u8 *filler; - - txb =3D kmalloc(sizeof(*txb), gfp); - if (!txb) - return NULL; - - buf =3D page_frag_alloc(&call->local->tx_alloc, - sizeof(*whdr) + sizeof(*ack) + 1 + 3 + sizeof(*trailer), gfp); - if (!buf) { - kfree(txb); - return NULL; - } - - if (sack_size) { - buf2 =3D page_frag_alloc(&call->local->tx_alloc, sack_size, gfp); - if (!buf2) { - page_frag_free(buf); - kfree(txb); - return NULL; - } - } - - whdr =3D buf; - ack =3D buf + sizeof(*whdr); - filler =3D buf + sizeof(*whdr) + sizeof(*ack) + 1; - trailer =3D buf + sizeof(*whdr) + sizeof(*ack) + 1 + 3; - - refcount_set(&txb->ref, 1); - txb->call_debug_id =3D call->debug_id; - txb->debug_id =3D atomic_inc_return(&rxrpc_txbuf_debug_ids); - txb->space =3D 0; - txb->len =3D sizeof(*whdr) + sizeof(*ack) + 3 + sizeof(*trailer); - txb->offset =3D 0; - txb->flags =3D call->conn->out_clientflag; - txb->ack_rwind =3D 0; - txb->seq =3D 0; - txb->serial =3D 0; - txb->cksum =3D 0; - txb->nr_kvec =3D 3; - txb->kvec[0].iov_base =3D whdr; - txb->kvec[0].iov_len =3D sizeof(*whdr) + sizeof(*ack); - txb->kvec[1].iov_base =3D buf2; - txb->kvec[1].iov_len =3D sack_size; - txb->kvec[2].iov_base =3D filler; - txb->kvec[2].iov_len =3D 3 + sizeof(*trailer); - - whdr->epoch =3D htonl(call->conn->proto.epoch); - whdr->cid =3D htonl(call->cid); - whdr->callNumber =3D htonl(call->call_id); - whdr->seq =3D 0; - whdr->type =3D RXRPC_PACKET_TYPE_ACK; - whdr->flags =3D 0; - whdr->userStatus =3D 0; - whdr->securityIndex =3D call->security_ix; - whdr->_rsvd =3D 0; - whdr->serviceId =3D htons(call->dest_srx.srx_service); - - get_page(virt_to_head_page(trailer)); - - trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 1, - rxrpc_txbuf_alloc_ack); - atomic_inc(&rxrpc_nr_txbuf); - return txb; -} - void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what) { int r;