Commit | Line | Data |
---|---|---|
b4d0d230 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2baec2c3 DH |
2 | /* rxrpc network namespace handling. |
3 | * | |
4 | * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. | |
5 | * Written by David Howells (dhowells@redhat.com) | |
2baec2c3 DH |
6 | */ |
7 | ||
8 | #include <linux/proc_fs.h> | |
9 | #include "ar-internal.h" | |
10 | ||
11 | unsigned int rxrpc_net_id; | |
12 | ||
3d18cbb7 DH |
13 | static void rxrpc_service_conn_reap_timeout(struct timer_list *timer) |
14 | { | |
15 | struct rxrpc_net *rxnet = | |
16 | container_of(timer, struct rxrpc_net, service_conn_reap_timer); | |
17 | ||
18 | if (rxnet->live) | |
19 | rxrpc_queue_work(&rxnet->service_conn_reaper); | |
20 | } | |
21 | ||
ace45bec DH |
22 | static void rxrpc_peer_keepalive_timeout(struct timer_list *timer) |
23 | { | |
24 | struct rxrpc_net *rxnet = | |
25 | container_of(timer, struct rxrpc_net, peer_keepalive_timer); | |
26 | ||
27 | if (rxnet->live) | |
28 | rxrpc_queue_work(&rxnet->peer_keepalive_work); | |
29 | } | |
30 | ||
2baec2c3 DH |
31 | /* |
32 | * Initialise a per-network namespace record. | |
33 | */ | |
34 | static __net_init int rxrpc_init_net(struct net *net) | |
35 | { | |
36 | struct rxrpc_net *rxnet = rxrpc_net(net); | |
ace45bec | 37 | int ret, i; |
2baec2c3 | 38 | |
f859ab61 | 39 | rxnet->live = true; |
2baec2c3 DH |
40 | get_random_bytes(&rxnet->epoch, sizeof(rxnet->epoch)); |
41 | rxnet->epoch |= RXRPC_RANDOM_EPOCH; | |
42 | ||
43 | INIT_LIST_HEAD(&rxnet->calls); | |
ad25f5cb | 44 | spin_lock_init(&rxnet->call_lock); |
d3be4d24 | 45 | atomic_set(&rxnet->nr_calls, 1); |
2baec2c3 | 46 | |
31f5f9a1 | 47 | atomic_set(&rxnet->nr_conns, 1); |
2baec2c3 DH |
48 | INIT_LIST_HEAD(&rxnet->conn_proc_list); |
49 | INIT_LIST_HEAD(&rxnet->service_conns); | |
50 | rwlock_init(&rxnet->conn_lock); | |
3d18cbb7 DH |
51 | INIT_WORK(&rxnet->service_conn_reaper, |
52 | rxrpc_service_connection_reaper); | |
53 | timer_setup(&rxnet->service_conn_reap_timer, | |
54 | rxrpc_service_conn_reap_timeout, 0); | |
2baec2c3 | 55 | |
245500d8 | 56 | atomic_set(&rxnet->nr_client_conns, 0); |
2baec2c3 | 57 | |
33912c26 | 58 | INIT_HLIST_HEAD(&rxnet->local_endpoints); |
2baec2c3 | 59 | mutex_init(&rxnet->local_mutex); |
ace45bec | 60 | |
2baec2c3 DH |
61 | hash_init(rxnet->peer_hash); |
62 | spin_lock_init(&rxnet->peer_hash_lock); | |
ace45bec | 63 | for (i = 0; i < ARRAY_SIZE(rxnet->peer_keepalive); i++) |
330bdcfa DH |
64 | INIT_LIST_HEAD(&rxnet->peer_keepalive[i]); |
65 | INIT_LIST_HEAD(&rxnet->peer_keepalive_new); | |
ace45bec DH |
66 | timer_setup(&rxnet->peer_keepalive_timer, |
67 | rxrpc_peer_keepalive_timeout, 0); | |
68 | INIT_WORK(&rxnet->peer_keepalive_work, rxrpc_peer_keepalive_worker); | |
330bdcfa | 69 | rxnet->peer_keepalive_base = ktime_get_seconds(); |
2baec2c3 DH |
70 | |
71 | ret = -ENOMEM; | |
72 | rxnet->proc_net = proc_net_mkdir(net, "rxrpc", net->proc_net); | |
73 | if (!rxnet->proc_net) | |
74 | goto err_proc; | |
75 | ||
c3506372 CH |
76 | proc_create_net("calls", 0444, rxnet->proc_net, &rxrpc_call_seq_ops, |
77 | sizeof(struct seq_net_private)); | |
78 | proc_create_net("conns", 0444, rxnet->proc_net, | |
79 | &rxrpc_connection_seq_ops, | |
80 | sizeof(struct seq_net_private)); | |
bc0e7cf4 DH |
81 | proc_create_net("peers", 0444, rxnet->proc_net, |
82 | &rxrpc_peer_seq_ops, | |
83 | sizeof(struct seq_net_private)); | |
33912c26 DH |
84 | proc_create_net("locals", 0444, rxnet->proc_net, |
85 | &rxrpc_local_seq_ops, | |
86 | sizeof(struct seq_net_private)); | |
b0154246 DH |
87 | proc_create_net_single_write("stats", S_IFREG | 0644, rxnet->proc_net, |
88 | rxrpc_stats_show, rxrpc_stats_clear, NULL); | |
2baec2c3 DH |
89 | return 0; |
90 | ||
2baec2c3 | 91 | err_proc: |
f859ab61 | 92 | rxnet->live = false; |
2baec2c3 DH |
93 | return ret; |
94 | } | |
95 | ||
96 | /* | |
97 | * Clean up a per-network namespace record. | |
98 | */ | |
99 | static __net_exit void rxrpc_exit_net(struct net *net) | |
100 | { | |
101 | struct rxrpc_net *rxnet = rxrpc_net(net); | |
102 | ||
f859ab61 | 103 | rxnet->live = false; |
ee3b0826 | 104 | del_timer_sync(&rxnet->peer_keepalive_timer); |
ace45bec | 105 | cancel_work_sync(&rxnet->peer_keepalive_work); |
ee3b0826 | 106 | /* Remove the timer again as the worker may have restarted it. */ |
1946014c | 107 | del_timer_sync(&rxnet->peer_keepalive_timer); |
2baec2c3 DH |
108 | rxrpc_destroy_all_calls(rxnet); |
109 | rxrpc_destroy_all_connections(rxnet); | |
17226f12 | 110 | rxrpc_destroy_all_peers(rxnet); |
2baec2c3 DH |
111 | rxrpc_destroy_all_locals(rxnet); |
112 | proc_remove(rxnet->proc_net); | |
113 | } | |
114 | ||
115 | struct pernet_operations rxrpc_net_ops = { | |
116 | .init = rxrpc_init_net, | |
117 | .exit = rxrpc_exit_net, | |
118 | .id = &rxrpc_net_id, | |
119 | .size = sizeof(struct rxrpc_net), | |
120 | }; |