Skip to content

Commit eb5ce84

Browse files
committed
rxrpc: Allow list of in-use local UDP endpoints to be viewed in /proc
jira LE-1907 Rebuild_History Non-Buildable kernel-5.14.0-284.30.1.el9_2 commit-author David Howells <[email protected]> commit 33912c2 Allow the list of in-use local UDP endpoints in the current network namespace to be viewed in /proc. To aid with this, the endpoint list is converted to an hlist and RCU-safe manipulation is used so that the list can be read with only the RCU read lock held. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected] Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 33912c2) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 566764e commit eb5ce84

File tree

4 files changed

+94
-22
lines changed

4 files changed

+94
-22
lines changed

net/rxrpc/ar-internal.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct rxrpc_net {
8888
struct work_struct client_conn_reaper;
8989
struct timer_list client_conn_reap_timer;
9090

91-
struct list_head local_endpoints;
91+
struct hlist_head local_endpoints;
9292
struct mutex local_mutex; /* Lock for ->local_endpoints */
9393

9494
DECLARE_HASHTABLE (peer_hash, 10);
@@ -281,7 +281,7 @@ struct rxrpc_local {
281281
atomic_t active_users; /* Number of users of the local endpoint */
282282
atomic_t usage; /* Number of references to the structure */
283283
struct rxrpc_net *rxnet; /* The network ns in which this resides */
284-
struct list_head link;
284+
struct hlist_node link;
285285
struct socket *socket; /* my UDP socket */
286286
struct work_struct processor;
287287
struct rxrpc_sock __rcu *service; /* Service(s) listening on this endpoint */
@@ -1014,6 +1014,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *);
10141014
extern const struct seq_operations rxrpc_call_seq_ops;
10151015
extern const struct seq_operations rxrpc_connection_seq_ops;
10161016
extern const struct seq_operations rxrpc_peer_seq_ops;
1017+
extern const struct seq_operations rxrpc_local_seq_ops;
10171018

10181019
/*
10191020
* recvmsg.c

net/rxrpc/local_object.c

+18-19
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
8282
atomic_set(&local->usage, 1);
8383
atomic_set(&local->active_users, 1);
8484
local->rxnet = rxnet;
85-
INIT_LIST_HEAD(&local->link);
85+
INIT_HLIST_NODE(&local->link);
8686
INIT_WORK(&local->processor, rxrpc_local_processor);
8787
init_rwsem(&local->defrag_sem);
8888
skb_queue_head_init(&local->reject_queue);
@@ -180,7 +180,7 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
180180
{
181181
struct rxrpc_local *local;
182182
struct rxrpc_net *rxnet = rxrpc_net(net);
183-
struct list_head *cursor;
183+
struct hlist_node *cursor;
184184
const char *age;
185185
long diff;
186186
int ret;
@@ -190,16 +190,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
190190

191191
mutex_lock(&rxnet->local_mutex);
192192

193-
for (cursor = rxnet->local_endpoints.next;
194-
cursor != &rxnet->local_endpoints;
195-
cursor = cursor->next) {
196-
local = list_entry(cursor, struct rxrpc_local, link);
193+
hlist_for_each(cursor, &rxnet->local_endpoints) {
194+
local = hlist_entry(cursor, struct rxrpc_local, link);
197195

198196
diff = rxrpc_local_cmp_key(local, srx);
199-
if (diff < 0)
197+
if (diff != 0)
200198
continue;
201-
if (diff > 0)
202-
break;
203199

204200
/* Services aren't allowed to share transport sockets, so
205201
* reject that here. It is possible that the object is dying -
@@ -211,9 +207,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
211207
goto addr_in_use;
212208
}
213209

214-
/* Found a match. We replace a dying object. Attempting to
215-
* bind the transport socket may still fail if we're attempting
216-
* to use a local address that the dying object is still using.
210+
/* Found a match. We want to replace a dying object.
211+
* Attempting to bind the transport socket may still fail if
212+
* we're attempting to use a local address that the dying
213+
* object is still using.
217214
*/
218215
if (!rxrpc_use_local(local))
219216
break;
@@ -230,10 +227,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
230227
if (ret < 0)
231228
goto sock_error;
232229

233-
if (cursor != &rxnet->local_endpoints)
234-
list_replace_init(cursor, &local->link);
235-
else
236-
list_add_tail(&local->link, cursor);
230+
if (cursor) {
231+
hlist_replace_rcu(cursor, &local->link);
232+
cursor->pprev = NULL;
233+
} else {
234+
hlist_add_head_rcu(&local->link, &rxnet->local_endpoints);
235+
}
237236
age = "new";
238237

239238
found:
@@ -374,7 +373,7 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
374373
local->dead = true;
375374

376375
mutex_lock(&rxnet->local_mutex);
377-
list_del_init(&local->link);
376+
hlist_del_init_rcu(&local->link);
378377
mutex_unlock(&rxnet->local_mutex);
379378

380379
rxrpc_clean_up_local_conns(local);
@@ -458,9 +457,9 @@ void rxrpc_destroy_all_locals(struct rxrpc_net *rxnet)
458457

459458
flush_workqueue(rxrpc_workqueue);
460459

461-
if (!list_empty(&rxnet->local_endpoints)) {
460+
if (!hlist_empty(&rxnet->local_endpoints)) {
462461
mutex_lock(&rxnet->local_mutex);
463-
list_for_each_entry(local, &rxnet->local_endpoints, link) {
462+
hlist_for_each_entry(local, &rxnet->local_endpoints, link) {
464463
pr_err("AF_RXRPC: Leaked local %p {%d}\n",
465464
local, atomic_read(&local->usage));
466465
}

net/rxrpc/net_ns.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static __net_init int rxrpc_init_net(struct net *net)
7272
timer_setup(&rxnet->client_conn_reap_timer,
7373
rxrpc_client_conn_reap_timeout, 0);
7474

75-
INIT_LIST_HEAD(&rxnet->local_endpoints);
75+
INIT_HLIST_HEAD(&rxnet->local_endpoints);
7676
mutex_init(&rxnet->local_mutex);
7777

7878
hash_init(rxnet->peer_hash);
@@ -98,6 +98,9 @@ static __net_init int rxrpc_init_net(struct net *net)
9898
proc_create_net("peers", 0444, rxnet->proc_net,
9999
&rxrpc_peer_seq_ops,
100100
sizeof(struct seq_net_private));
101+
proc_create_net("locals", 0444, rxnet->proc_net,
102+
&rxrpc_local_seq_ops,
103+
sizeof(struct seq_net_private));
101104
return 0;
102105

103106
err_proc:

net/rxrpc/proc.c

+69
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,72 @@ const struct seq_operations rxrpc_peer_seq_ops = {
334334
.stop = rxrpc_peer_seq_stop,
335335
.show = rxrpc_peer_seq_show,
336336
};
337+
338+
/*
339+
* Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals
340+
*/
341+
static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
342+
{
343+
struct rxrpc_local *local;
344+
char lbuff[50];
345+
346+
if (v == SEQ_START_TOKEN) {
347+
seq_puts(seq,
348+
"Proto Local "
349+
" Use Act\n");
350+
return 0;
351+
}
352+
353+
local = hlist_entry(v, struct rxrpc_local, link);
354+
355+
sprintf(lbuff, "%pISpc", &local->srx.transport);
356+
357+
seq_printf(seq,
358+
"UDP %-47.47s %3u %3u\n",
359+
lbuff,
360+
atomic_read(&local->usage),
361+
atomic_read(&local->active_users));
362+
363+
return 0;
364+
}
365+
366+
static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos)
367+
__acquires(rcu)
368+
{
369+
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
370+
unsigned int n;
371+
372+
rcu_read_lock();
373+
374+
if (*_pos >= UINT_MAX)
375+
return NULL;
376+
377+
n = *_pos;
378+
if (n == 0)
379+
return SEQ_START_TOKEN;
380+
381+
return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1);
382+
}
383+
384+
static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
385+
{
386+
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
387+
388+
if (*_pos >= UINT_MAX)
389+
return NULL;
390+
391+
return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos);
392+
}
393+
394+
static void rxrpc_local_seq_stop(struct seq_file *seq, void *v)
395+
__releases(rcu)
396+
{
397+
rcu_read_unlock();
398+
}
399+
400+
const struct seq_operations rxrpc_local_seq_ops = {
401+
.start = rxrpc_local_seq_start,
402+
.next = rxrpc_local_seq_next,
403+
.stop = rxrpc_local_seq_stop,
404+
.show = rxrpc_local_seq_show,
405+
};

0 commit comments

Comments
 (0)