Messages in this thread Patch in this message | | | Subject | [RFC PATCH 1/8] rxrpc: List open sockets in /proc/net/rxrpc/sockets | From | David Howells <> | Date | Thu, 23 Jun 2022 14:28:58 +0100 |
| |
Provide a list of open sockets in /proc/net/rxrpc/sockets, providing a few useful stats.
Signed-off-by: David Howells <dhowells@redhat.com> ---
net/rxrpc/af_rxrpc.c | 9 +++++ net/rxrpc/ar-internal.h | 5 ++- net/rxrpc/net_ns.c | 4 ++ net/rxrpc/proc.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index ceba28e9dce6..5519c2bef7f5 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -787,6 +787,10 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol, memset(&rx->srx, 0, sizeof(rx->srx)); rxnet = rxrpc_net(sock_net(&rx->sk)); + mutex_lock(&rxnet->local_mutex); + hlist_add_head_rcu(&rx->ns_link, &rxnet->sockets); + mutex_unlock(&rxnet->local_mutex); + timer_reduce(&rxnet->peer_keepalive_timer, jiffies + 1); _leave(" = 0 [%p]", rx); @@ -851,6 +855,7 @@ static void rxrpc_sock_destructor(struct sock *sk) static int rxrpc_release_sock(struct sock *sk) { struct rxrpc_sock *rx = rxrpc_sk(sk); + struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); @@ -887,6 +892,10 @@ static int rxrpc_release_sock(struct sock *sk) flush_workqueue(rxrpc_workqueue); rxrpc_purge_queue(&sk->sk_receive_queue); + mutex_lock(&rxnet->local_mutex); + hlist_del_rcu(&rx->ns_link); + mutex_unlock(&rxnet->local_mutex); + rxrpc_unuse_local(rx->local); rxrpc_put_local(rx->local); rx->local = NULL; diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 571436064cd6..68d269598305 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -80,8 +80,9 @@ struct rxrpc_net { struct work_struct client_conn_reaper; struct timer_list client_conn_reap_timer; + struct hlist_head sockets; /* List of sockets */ struct hlist_head local_endpoints; - struct mutex local_mutex; /* Lock for ->local_endpoints */ + struct mutex local_mutex; /* Lock for ->local_endpoints, ->sockets */ DECLARE_HASHTABLE (peer_hash, 10); spinlock_t peer_hash_lock; /* Lock for ->peer_hash */ @@ -130,6 +131,7 @@ struct rxrpc_sock { struct list_head sock_calls; /* List of calls owned by this socket */ struct list_head to_be_accepted; /* calls awaiting acceptance */ struct list_head recvmsg_q; /* Calls awaiting recvmsg's attention */ + struct hlist_node ns_link; /* Link in net->sockets */ rwlock_t recvmsg_lock; /* Lock for recvmsg_q */ struct key *key; /* security for this socket */ struct key *securities; /* list of server security descriptors */ @@ -1008,6 +1010,7 @@ extern const struct seq_operations rxrpc_call_seq_ops; extern const struct seq_operations rxrpc_connection_seq_ops; extern const struct seq_operations rxrpc_peer_seq_ops; extern const struct seq_operations rxrpc_local_seq_ops; +extern const struct seq_operations rxrpc_socket_seq_ops; /* * recvmsg.c diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c index bb4c25d6df64..4107099a259c 100644 --- a/net/rxrpc/net_ns.c +++ b/net/rxrpc/net_ns.c @@ -72,6 +72,7 @@ static __net_init int rxrpc_init_net(struct net *net) timer_setup(&rxnet->client_conn_reap_timer, rxrpc_client_conn_reap_timeout, 0); + INIT_HLIST_HEAD(&rxnet->sockets); INIT_HLIST_HEAD(&rxnet->local_endpoints); mutex_init(&rxnet->local_mutex); @@ -101,6 +102,9 @@ static __net_init int rxrpc_init_net(struct net *net) proc_create_net("locals", 0444, rxnet->proc_net, &rxrpc_local_seq_ops, sizeof(struct seq_net_private)); + proc_create_net("sockets", 0444, rxnet->proc_net, + &rxrpc_socket_seq_ops, + sizeof(struct seq_net_private)); return 0; err_proc: diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c index 245418943e01..b92303012338 100644 --- a/net/rxrpc/proc.c +++ b/net/rxrpc/proc.c @@ -397,3 +397,95 @@ const struct seq_operations rxrpc_local_seq_ops = { .stop = rxrpc_local_seq_stop, .show = rxrpc_local_seq_show, }; + +/* + * Generate a list of extant sockets in /proc/net/rxrpc/sockets + */ +static int rxrpc_socket_seq_show(struct seq_file *seq, void *v) +{ + struct rxrpc_local *local; + struct rxrpc_sock *rx; + struct list_head *p; + char lbuff[50]; + unsigned int nr_calls = 0, nr_acc = 0, nr_attend = 0; + + if (v == SEQ_START_TOKEN) { + seq_puts(seq, + "Proto Local " + " Use Svc1 Svc2 nCal nAcc nAtn\n"); + return 0; + } + + rx = hlist_entry(v, struct rxrpc_sock, ns_link); + local = rx->local; + + if (local) + sprintf(lbuff, "%pISpc", &local->srx.transport); + else + sprintf(lbuff, "-"); + + read_lock(&rx->call_lock); + list_for_each(p, &rx->sock_calls) { + nr_calls++; + } + list_for_each(p, &rx->to_be_accepted) { + nr_acc++; + } + read_unlock(&rx->call_lock); + + read_lock_bh(&rx->recvmsg_lock); + list_for_each(p, &rx->recvmsg_q) { + nr_attend++; + } + read_unlock_bh(&rx->recvmsg_lock); + + seq_printf(seq, + "UDP %-47.47s %3d %4x %4x %4u %4u %4u\n", + lbuff, + refcount_read(&rx->sk.sk_refcnt), + rx->srx.srx_service, rx->second_service, + nr_calls, nr_acc, nr_attend); + + return 0; +} + +static void *rxrpc_socket_seq_start(struct seq_file *seq, loff_t *_pos) + __acquires(rcu) +{ + struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); + unsigned int n; + + rcu_read_lock(); + + if (*_pos >= UINT_MAX) + return NULL; + + n = *_pos; + if (n == 0) + return SEQ_START_TOKEN; + + return seq_hlist_start_rcu(&rxnet->sockets, n - 1); +} + +static void *rxrpc_socket_seq_next(struct seq_file *seq, void *v, loff_t *_pos) +{ + struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); + + if (*_pos >= UINT_MAX) + return NULL; + + return seq_hlist_next_rcu(v, &rxnet->sockets, _pos); +} + +static void rxrpc_socket_seq_stop(struct seq_file *seq, void *v) + __releases(rcu) +{ + rcu_read_unlock(); +} + +const struct seq_operations rxrpc_socket_seq_ops = { + .start = rxrpc_socket_seq_start, + .next = rxrpc_socket_seq_next, + .stop = rxrpc_socket_seq_stop, + .show = rxrpc_socket_seq_show, +};
| |