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_client_conn_reap_timeout(struct timer_list *timer) |
14 | { | |
15 | struct rxrpc_net *rxnet = | |
16 | container_of(timer, struct rxrpc_net, client_conn_reap_timer); | |
17 | ||
18 | if (rxnet->live) | |
19 | rxrpc_queue_work(&rxnet->client_conn_reaper); | |
20 | } | |
21 | ||
22 | static void rxrpc_service_conn_reap_timeout(struct timer_list *timer) | |
23 | { | |
24 | struct rxrpc_net *rxnet = | |
25 | container_of(timer, struct rxrpc_net, service_conn_reap_timer); | |
26 | ||
27 | if (rxnet->live) | |
28 | rxrpc_queue_work(&rxnet->service_conn_reaper); | |
29 | } | |
30 | ||
ace45bec DH |
31 | static void rxrpc_peer_keepalive_timeout(struct timer_list *timer) |
32 | { | |
33 | struct rxrpc_net *rxnet = | |
34 | container_of(timer, struct rxrpc_net, peer_keepalive_timer); | |
35 | ||
36 | if (rxnet->live) | |
37 | rxrpc_queue_work(&rxnet->peer_keepalive_work); | |
38 | } | |
39 | ||
2baec2c3 DH |
40 | /* |
41 | * Initialise a per-network namespace record. | |
42 | */ | |
43 | static __net_init int rxrpc_init_net(struct net *net) | |
44 | { | |
45 | struct rxrpc_net *rxnet = rxrpc_net(net); | |
ace45bec | 46 | int ret, i; |
2baec2c3 | 47 | |
f859ab61 | 48 | rxnet->live = true; |
2baec2c3 DH |
49 | get_random_bytes(&rxnet->epoch, sizeof(rxnet->epoch)); |
50 | rxnet->epoch |= RXRPC_RANDOM_EPOCH; | |
51 | ||
52 | INIT_LIST_HEAD(&rxnet->calls); | |
53 | rwlock_init(&rxnet->call_lock); | |
d3be4d24 | 54 | atomic_set(&rxnet->nr_calls, 1); |
2baec2c3 | 55 | |
31f5f9a1 | 56 | atomic_set(&rxnet->nr_conns, 1); |
2baec2c3 DH |
57 | INIT_LIST_HEAD(&rxnet->conn_proc_list); |
58 | INIT_LIST_HEAD(&rxnet->service_conns); | |
59 | rwlock_init(&rxnet->conn_lock); | |
3d18cbb7 DH |
60 | INIT_WORK(&rxnet->service_conn_reaper, |
61 | rxrpc_service_connection_reaper); | |
62 | timer_setup(&rxnet->service_conn_reap_timer, | |
63 | rxrpc_service_conn_reap_timeout, 0); | |
2baec2c3 | 64 | |
245500d8 | 65 | atomic_set(&rxnet->nr_client_conns, 0); |
2baec2c3 DH |
66 | rxnet->kill_all_client_conns = false; |
67 | spin_lock_init(&rxnet->client_conn_cache_lock); | |
68 | spin_lock_init(&rxnet->client_conn_discard_lock); | |
2baec2c3 | 69 | INIT_LIST_HEAD(&rxnet->idle_client_conns); |
3d18cbb7 DH |
70 | INIT_WORK(&rxnet->client_conn_reaper, |
71 | rxrpc_discard_expired_client_conns); | |
72 | timer_setup(&rxnet->client_conn_reap_timer, | |
73 | rxrpc_client_conn_reap_timeout, 0); | |
2baec2c3 DH |
74 | |
75 | INIT_LIST_HEAD(&rxnet->local_endpoints); | |
76 | mutex_init(&rxnet->local_mutex); | |
ace45bec | 77 | |
2baec2c3 DH |
78 | hash_init(rxnet->peer_hash); |
79 | spin_lock_init(&rxnet->peer_hash_lock); | |
ace45bec | 80 | for (i = 0; i < ARRAY_SIZE(rxnet->peer_keepalive); i++) |
330bdcfa DH |
81 | INIT_LIST_HEAD(&rxnet->peer_keepalive[i]); |
82 | INIT_LIST_HEAD(&rxnet->peer_keepalive_new); | |
ace45bec DH |
83 | timer_setup(&rxnet->peer_keepalive_timer, |
84 | rxrpc_peer_keepalive_timeout, 0); | |
85 | INIT_WORK(&rxnet->peer_keepalive_work, rxrpc_peer_keepalive_worker); | |
330bdcfa | 86 | rxnet->peer_keepalive_base = ktime_get_seconds(); |
2baec2c3 DH |
87 | |
88 | ret = -ENOMEM; | |
89 | rxnet->proc_net = proc_net_mkdir(net, "rxrpc", net->proc_net); | |
90 | if (!rxnet->proc_net) | |
91 | goto err_proc; | |
92 | ||
c3506372 CH |
93 | proc_create_net("calls", 0444, rxnet->proc_net, &rxrpc_call_seq_ops, |
94 | sizeof(struct seq_net_private)); | |
95 | proc_create_net("conns", 0444, rxnet->proc_net, | |
96 | &rxrpc_connection_seq_ops, | |
97 | sizeof(struct seq_net_private)); | |
bc0e7cf4 DH |
98 | proc_create_net("peers", 0444, rxnet->proc_net, |
99 | &rxrpc_peer_seq_ops, | |
100 | sizeof(struct seq_net_private)); | |
2baec2c3 DH |
101 | return 0; |
102 | ||
2baec2c3 | 103 | err_proc: |
f859ab61 | 104 | rxnet->live = false; |
2baec2c3 DH |
105 | return ret; |
106 | } | |
107 | ||
108 | /* | |
109 | * Clean up a per-network namespace record. | |
110 | */ | |
111 | static __net_exit void rxrpc_exit_net(struct net *net) | |
112 | { | |
113 | struct rxrpc_net *rxnet = rxrpc_net(net); | |
114 | ||
f859ab61 | 115 | rxnet->live = false; |
ace45bec | 116 | cancel_work_sync(&rxnet->peer_keepalive_work); |
1946014c | 117 | del_timer_sync(&rxnet->peer_keepalive_timer); |
2baec2c3 DH |
118 | rxrpc_destroy_all_calls(rxnet); |
119 | rxrpc_destroy_all_connections(rxnet); | |
17226f12 | 120 | rxrpc_destroy_all_peers(rxnet); |
2baec2c3 DH |
121 | rxrpc_destroy_all_locals(rxnet); |
122 | proc_remove(rxnet->proc_net); | |
123 | } | |
124 | ||
125 | struct pernet_operations rxrpc_net_ops = { | |
126 | .init = rxrpc_init_net, | |
127 | .exit = rxrpc_exit_net, | |
128 | .id = &rxrpc_net_id, | |
129 | .size = sizeof(struct rxrpc_net), | |
130 | }; |