-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rxrpc: Define rxrpc_txbuf struct to carry data to be transmitted
Define a struct, rxrpc_txbuf, to carry data to be transmitted instead of a socket buffer so that it can be placed onto multiple queues at once. This also allows the data buffer to be in the same allocation as the internal data. Signed-off-by: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org
- Loading branch information
David Howells
committed
Nov 8, 2022
1 parent
a11e6ff
commit 02a1935
Showing
5 changed files
with
201 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* RxRPC Tx data buffering. | ||
* | ||
* Copyright (C) 2022 Red Hat, Inc. All Rights Reserved. | ||
* Written by David Howells (dhowells@redhat.com) | ||
*/ | ||
|
||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
|
||
#include <linux/slab.h> | ||
#include "ar-internal.h" | ||
|
||
static atomic_t rxrpc_txbuf_debug_ids; | ||
atomic_t rxrpc_nr_txbuf; | ||
|
||
/* | ||
* Allocate and partially initialise an I/O request structure. | ||
*/ | ||
struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type, | ||
gfp_t gfp) | ||
{ | ||
struct rxrpc_txbuf *txb; | ||
|
||
txb = kmalloc(sizeof(*txb), gfp); | ||
if (txb) { | ||
INIT_LIST_HEAD(&txb->call_link); | ||
INIT_LIST_HEAD(&txb->tx_link); | ||
refcount_set(&txb->ref, 1); | ||
txb->call = call; | ||
txb->call_debug_id = call->debug_id; | ||
txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids); | ||
txb->space = sizeof(txb->data); | ||
txb->len = 0; | ||
txb->offset = 0; | ||
txb->flags = 0; | ||
txb->seq = call->tx_top + 1; | ||
txb->wire.epoch = htonl(call->conn->proto.epoch); | ||
txb->wire.cid = htonl(call->cid); | ||
txb->wire.callNumber = htonl(call->call_id); | ||
txb->wire.seq = htonl(txb->seq); | ||
txb->wire.type = packet_type; | ||
txb->wire.flags = call->conn->out_clientflag; | ||
txb->wire.userStatus = 0; | ||
txb->wire.securityIndex = call->security_ix; | ||
txb->wire._rsvd = 0; | ||
txb->wire.serviceId = htons(call->service_id); | ||
|
||
trace_rxrpc_txbuf(txb->debug_id, | ||
txb->call_debug_id, txb->seq, 1, | ||
packet_type == RXRPC_PACKET_TYPE_DATA ? | ||
rxrpc_txbuf_alloc_data : | ||
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; | ||
|
||
__refcount_inc(&txb->ref, &r); | ||
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r + 1, what); | ||
} | ||
|
||
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what) | ||
{ | ||
int r = refcount_read(&txb->ref); | ||
|
||
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r, what); | ||
} | ||
|
||
static void rxrpc_free_txbuf(struct rcu_head *rcu) | ||
{ | ||
struct rxrpc_txbuf *txb = container_of(rcu, struct rxrpc_txbuf, rcu); | ||
|
||
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0, | ||
rxrpc_txbuf_free); | ||
kfree(txb); | ||
atomic_dec(&rxrpc_nr_txbuf); | ||
} | ||
|
||
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what) | ||
{ | ||
unsigned int debug_id, call_debug_id; | ||
rxrpc_seq_t seq; | ||
bool dead; | ||
int r; | ||
|
||
if (txb) { | ||
debug_id = txb->debug_id; | ||
call_debug_id = txb->call_debug_id; | ||
seq = txb->seq; | ||
dead = __refcount_dec_and_test(&txb->ref, &r); | ||
trace_rxrpc_txbuf(debug_id, call_debug_id, seq, r - 1, what); | ||
if (dead) | ||
call_rcu(&txb->rcu, rxrpc_free_txbuf); | ||
} | ||
} |