rxrpc: Create a procfile to display outstanding client conn bundles

Create /proc/net/rxrpc/bundles to display outstanding rxrpc client
connection bundles.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
This commit is contained in:
David Howells 2023-10-26 22:53:02 +01:00
parent 98f9fda205
commit d2ce4a84c2
4 changed files with 94 additions and 0 deletions

View File

@ -68,6 +68,7 @@ struct rxrpc_net {
atomic_t nr_calls; /* Count of allocated calls */
atomic_t nr_conns;
struct list_head bundle_proc_list; /* List of bundles for proc */
struct list_head conn_proc_list; /* List of conns in this namespace for proc */
struct list_head service_conns; /* Service conns in this namespace */
rwlock_t conn_lock; /* Lock for ->conn_proc_list, ->service_conns */
@ -432,6 +433,7 @@ struct rxrpc_bundle {
struct rxrpc_local *local; /* Representation of local endpoint */
struct rxrpc_peer *peer; /* Remote endpoint */
struct key *key; /* Security details */
struct list_head proc_link; /* Link in net->bundle_proc_list */
const struct rxrpc_security *security; /* applied security module */
refcount_t ref;
atomic_t active; /* Number of active users */
@ -445,6 +447,7 @@ struct rxrpc_bundle {
struct rb_node local_node; /* Node in local->client_conns */
struct list_head waiting_calls; /* Calls waiting for channels */
unsigned long avail_chans; /* Mask of available channels */
unsigned int conn_ids[4]; /* Connection IDs. */
struct rxrpc_connection *conns[4]; /* The connections in the bundle (max 4) */
};
@ -1167,6 +1170,7 @@ void rxrpc_put_peer(struct rxrpc_peer *, enum rxrpc_peer_trace);
*/
extern const struct seq_operations rxrpc_call_seq_ops;
extern const struct seq_operations rxrpc_connection_seq_ops;
extern const struct seq_operations rxrpc_bundle_seq_ops;
extern const struct seq_operations rxrpc_peer_seq_ops;
extern const struct seq_operations rxrpc_local_seq_ops;

View File

@ -91,6 +91,10 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
atomic_set(&bundle->active, 1);
INIT_LIST_HEAD(&bundle->waiting_calls);
trace_rxrpc_bundle(bundle->debug_id, 1, rxrpc_bundle_new);
write_lock(&bundle->local->rxnet->conn_lock);
list_add_tail(&bundle->proc_link, &bundle->local->rxnet->bundle_proc_list);
write_unlock(&bundle->local->rxnet->conn_lock);
}
return bundle;
}
@ -109,6 +113,9 @@ static void rxrpc_free_bundle(struct rxrpc_bundle *bundle)
{
trace_rxrpc_bundle(bundle->debug_id, refcount_read(&bundle->ref),
rxrpc_bundle_free);
write_lock(&bundle->local->rxnet->conn_lock);
list_del(&bundle->proc_link);
write_unlock(&bundle->local->rxnet->conn_lock);
rxrpc_put_peer(bundle->peer, rxrpc_peer_put_bundle);
key_put(bundle->key);
kfree(bundle);
@ -338,6 +345,7 @@ static bool rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle,
old = bundle->conns[slot];
if (old) {
bundle->conns[slot] = NULL;
bundle->conn_ids[slot] = 0;
trace_rxrpc_client(old, -1, rxrpc_client_replace);
rxrpc_put_connection(old, rxrpc_conn_put_noreuse);
}
@ -351,6 +359,7 @@ static bool rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle,
rxrpc_activate_bundle(bundle);
conn->bundle_shift = shift;
bundle->conns[slot] = conn;
bundle->conn_ids[slot] = conn->debug_id;
for (i = 0; i < RXRPC_MAXCALLS; i++)
set_bit(shift + i, &bundle->avail_chans);
return true;
@ -671,6 +680,7 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)
if (bundle->conns[bindex] == conn) {
_debug("clear slot %u", bindex);
bundle->conns[bindex] = NULL;
bundle->conn_ids[bindex] = 0;
for (i = 0; i < RXRPC_MAXCALLS; i++)
clear_bit(conn->bundle_shift + i, &bundle->avail_chans);
rxrpc_put_client_connection_id(bundle->local, conn);

View File

@ -45,6 +45,7 @@ static __net_init int rxrpc_init_net(struct net *net)
atomic_set(&rxnet->nr_calls, 1);
atomic_set(&rxnet->nr_conns, 1);
INIT_LIST_HEAD(&rxnet->bundle_proc_list);
INIT_LIST_HEAD(&rxnet->conn_proc_list);
INIT_LIST_HEAD(&rxnet->service_conns);
rwlock_init(&rxnet->conn_lock);
@ -78,6 +79,9 @@ static __net_init int rxrpc_init_net(struct net *net)
proc_create_net("conns", 0444, rxnet->proc_net,
&rxrpc_connection_seq_ops,
sizeof(struct seq_net_private));
proc_create_net("bundles", 0444, rxnet->proc_net,
&rxrpc_bundle_seq_ops,
sizeof(struct seq_net_private));
proc_create_net("peers", 0444, rxnet->proc_net,
&rxrpc_peer_seq_ops,
sizeof(struct seq_net_private));

View File

@ -198,6 +198,82 @@ const struct seq_operations rxrpc_connection_seq_ops = {
.show = rxrpc_connection_seq_show,
};
/*
* generate a list of extant virtual bundles in /proc/net/rxrpc/bundles
*/
static void *rxrpc_bundle_seq_start(struct seq_file *seq, loff_t *_pos)
__acquires(rxnet->conn_lock)
{
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
read_lock(&rxnet->conn_lock);
return seq_list_start_head(&rxnet->bundle_proc_list, *_pos);
}
static void *rxrpc_bundle_seq_next(struct seq_file *seq, void *v,
loff_t *pos)
{
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
return seq_list_next(v, &rxnet->bundle_proc_list, pos);
}
static void rxrpc_bundle_seq_stop(struct seq_file *seq, void *v)
__releases(rxnet->conn_lock)
{
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
read_unlock(&rxnet->conn_lock);
}
static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v)
{
struct rxrpc_bundle *bundle;
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
char lbuff[50], rbuff[50];
if (v == &rxnet->bundle_proc_list) {
seq_puts(seq,
"Proto Local "
" Remote "
" SvID Ref Act Flg Key |"
" Bundle Conn_0 Conn_1 Conn_2 Conn_3\n"
);
return 0;
}
bundle = list_entry(v, struct rxrpc_bundle, proc_link);
sprintf(lbuff, "%pISpc", &bundle->local->srx.transport);
sprintf(rbuff, "%pISpc", &bundle->peer->srx.transport);
seq_printf(seq,
"UDP %-47.47s %-47.47s %4x %3u %3d"
" %c%c%c %08x | %08x %08x %08x %08x %08x\n",
lbuff,
rbuff,
bundle->service_id,
refcount_read(&bundle->ref),
atomic_read(&bundle->active),
bundle->try_upgrade ? 'U' : '-',
bundle->exclusive ? 'e' : '-',
bundle->upgrade ? 'u' : '-',
key_serial(bundle->key),
bundle->debug_id,
bundle->conn_ids[0],
bundle->conn_ids[1],
bundle->conn_ids[2],
bundle->conn_ids[3]);
return 0;
}
const struct seq_operations rxrpc_bundle_seq_ops = {
.start = rxrpc_bundle_seq_start,
.next = rxrpc_bundle_seq_next,
.stop = rxrpc_bundle_seq_stop,
.show = rxrpc_bundle_seq_show,
};
/*
* generate a list of extant virtual peers in /proc/net/rxrpc/peers
*/