File Index
Files and directories
Sign in
FILE

txbuf.c

File preview with syntax highlighting.

linux-6.19.14/net/rxrpc/txbuf.c C
 1// SPDX-License-Identifier: GPL-2.0-or-later
 2/* RxRPC Tx data buffering.
 3 *
 4 * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
 5 * Written by David Howells (dhowells@redhat.com)
 6 */
 7
 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 9
10#include <linux/slab.h>
11#include "ar-internal.h"
12
13static atomic_t rxrpc_txbuf_debug_ids;
14atomic_t rxrpc_nr_txbuf;
15
16/*
17 * Allocate and partially initialise a data transmission buffer.
18 */
19struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size,
20					   size_t data_align, gfp_t gfp)
21{
22	struct rxrpc_txbuf *txb;
23	size_t total, doff, jsize = sizeof(struct rxrpc_jumbo_header);
24	void *buf;
25
26	txb = kzalloc(sizeof(*txb), gfp);
27	if (!txb)
28		return NULL;
29
30	/* We put a jumbo header in the buffer, but not a full wire header to
31	 * avoid delayed-corruption problems with zerocopy.
32	 */
33	doff = round_up(jsize, data_align);
34	total = doff + data_size;
35
36	data_align = umax(data_align, L1_CACHE_BYTES);
37	mutex_lock(&call->conn->tx_data_alloc_lock);
38	buf = page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
39				    data_align);
40	mutex_unlock(&call->conn->tx_data_alloc_lock);
41	if (!buf) {
42		kfree(txb);
43		return NULL;
44	}
45
46	refcount_set(&txb->ref, 1);
47	txb->call_debug_id	= call->debug_id;
48	txb->debug_id		= atomic_inc_return(&rxrpc_txbuf_debug_ids);
49	txb->alloc_size		= data_size;
50	txb->space		= data_size;
51	txb->offset		= 0;
52	txb->flags		= call->conn->out_clientflag;
53	txb->seq		= call->send_top + 1;
54	txb->data		= buf + doff;
55
56	trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 1,
57			  rxrpc_txbuf_alloc_data);
58
59	atomic_inc(&rxrpc_nr_txbuf);
60	return txb;
61}
62
63void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
64{
65	int r = refcount_read(&txb->ref);
66
67	trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r, what);
68}
69
70static void rxrpc_free_txbuf(struct rxrpc_txbuf *txb)
71{
72	trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0,
73			  rxrpc_txbuf_free);
74	if (txb->data)
75		page_frag_free(txb->data);
76	kfree(txb);
77	atomic_dec(&rxrpc_nr_txbuf);
78}
79
80void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
81{
82	unsigned int debug_id, call_debug_id;
83	rxrpc_seq_t seq;
84	bool dead;
85	int r;
86
87	if (txb) {
88		debug_id = txb->debug_id;
89		call_debug_id = txb->call_debug_id;
90		seq = txb->seq;
91		dead = __refcount_dec_and_test(&txb->ref, &r);
92		trace_rxrpc_txbuf(debug_id, call_debug_id, seq, r - 1, what);
93		if (dead)
94			rxrpc_free_txbuf(txb);
95	}
96}
~/ Read-only file preview.