Commit d2ce4a84 authored by David Howells's avatar David Howells
Browse files

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: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent 98f9fda2
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;

+10 −0
Original line number Diff line number Diff line
@@ -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);
+4 −0
Original line number Diff line number Diff line
@@ -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));
+76 −0
Original line number Diff line number Diff line
@@ -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
 */