1 /* peer.c: Rx RPC peer management
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/sched.h>
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <rxrpc/rxrpc.h>
16 #include <rxrpc/transport.h>
17 #include <rxrpc/peer.h>
18 #include <rxrpc/connection.h>
19 #include <rxrpc/call.h>
20 #include <rxrpc/message.h>
21 #include <linux/udp.h>
24 #include <asm/uaccess.h>
25 #include <asm/div64.h>
28 __RXACCT_DECL(atomic_t rxrpc_peer_count
);
29 LIST_HEAD(rxrpc_peers
);
30 DECLARE_RWSEM(rxrpc_peers_sem
);
31 unsigned long rxrpc_peer_timeout
= 12 * 60 * 60;
33 static void rxrpc_peer_do_timeout(struct rxrpc_peer
*peer
);
35 static void __rxrpc_peer_timeout(rxrpc_timer_t
*timer
)
37 struct rxrpc_peer
*peer
=
38 list_entry(timer
, struct rxrpc_peer
, timeout
);
40 _debug("Rx PEER TIMEOUT [%p{u=%d}]", peer
, atomic_read(&peer
->usage
));
42 rxrpc_peer_do_timeout(peer
);
45 static const struct rxrpc_timer_ops rxrpc_peer_timer_ops
= {
46 .timed_out
= __rxrpc_peer_timeout
,
49 /*****************************************************************************/
51 * create a peer record
53 static int __rxrpc_create_peer(struct rxrpc_transport
*trans
, __be32 addr
,
54 struct rxrpc_peer
**_peer
)
56 struct rxrpc_peer
*peer
;
58 _enter("%p,%08x", trans
, ntohl(addr
));
60 /* allocate and initialise a peer record */
61 peer
= kzalloc(sizeof(struct rxrpc_peer
), GFP_KERNEL
);
67 atomic_set(&peer
->usage
, 1);
69 INIT_LIST_HEAD(&peer
->link
);
70 INIT_LIST_HEAD(&peer
->proc_link
);
71 INIT_LIST_HEAD(&peer
->conn_idlist
);
72 INIT_LIST_HEAD(&peer
->conn_active
);
73 INIT_LIST_HEAD(&peer
->conn_graveyard
);
74 spin_lock_init(&peer
->conn_gylock
);
75 init_waitqueue_head(&peer
->conn_gy_waitq
);
76 rwlock_init(&peer
->conn_idlock
);
77 rwlock_init(&peer
->conn_lock
);
78 atomic_set(&peer
->conn_count
, 0);
79 spin_lock_init(&peer
->lock
);
80 rxrpc_timer_init(&peer
->timeout
, &rxrpc_peer_timer_ops
);
82 peer
->addr
.s_addr
= addr
;
85 peer
->ops
= trans
->peer_ops
;
87 __RXACCT(atomic_inc(&rxrpc_peer_count
));
89 _leave(" = 0 (%p)", peer
);
92 } /* end __rxrpc_create_peer() */
94 /*****************************************************************************/
96 * find a peer record on the specified transport
97 * - returns (if successful) with peer record usage incremented
98 * - resurrects it from the graveyard if found there
100 int rxrpc_peer_lookup(struct rxrpc_transport
*trans
, __be32 addr
,
101 struct rxrpc_peer
**_peer
)
103 struct rxrpc_peer
*peer
, *candidate
= NULL
;
104 struct list_head
*_p
;
107 _enter("%p{%hu},%08x", trans
, trans
->port
, ntohl(addr
));
109 /* [common case] search the transport's active list first */
110 read_lock(&trans
->peer_lock
);
111 list_for_each(_p
, &trans
->peer_active
) {
112 peer
= list_entry(_p
, struct rxrpc_peer
, link
);
113 if (peer
->addr
.s_addr
== addr
)
116 read_unlock(&trans
->peer_lock
);
118 /* [uncommon case] not active - create a candidate for a new record */
119 ret
= __rxrpc_create_peer(trans
, addr
, &candidate
);
121 _leave(" = %d", ret
);
125 /* search the active list again, just in case it appeared whilst we
127 write_lock(&trans
->peer_lock
);
128 list_for_each(_p
, &trans
->peer_active
) {
129 peer
= list_entry(_p
, struct rxrpc_peer
, link
);
130 if (peer
->addr
.s_addr
== addr
)
131 goto found_active_second_chance
;
134 /* search the transport's graveyard list */
135 spin_lock(&trans
->peer_gylock
);
136 list_for_each(_p
, &trans
->peer_graveyard
) {
137 peer
= list_entry(_p
, struct rxrpc_peer
, link
);
138 if (peer
->addr
.s_addr
== addr
)
139 goto found_in_graveyard
;
141 spin_unlock(&trans
->peer_gylock
);
143 /* we can now add the new candidate to the list
144 * - tell the application layer that this peer has been added
146 rxrpc_get_transport(trans
);
150 if (peer
->ops
&& peer
->ops
->adding
) {
151 ret
= peer
->ops
->adding(peer
);
153 write_unlock(&trans
->peer_lock
);
154 __RXACCT(atomic_dec(&rxrpc_peer_count
));
156 rxrpc_put_transport(trans
);
157 _leave(" = %d", ret
);
162 atomic_inc(&trans
->peer_count
);
165 list_add_tail(&peer
->link
, &trans
->peer_active
);
168 write_unlock(&trans
->peer_lock
);
171 __RXACCT(atomic_dec(&rxrpc_peer_count
));
175 if (list_empty(&peer
->proc_link
)) {
176 down_write(&rxrpc_peers_sem
);
177 list_add_tail(&peer
->proc_link
, &rxrpc_peers
);
178 up_write(&rxrpc_peers_sem
);
184 _leave(" = 0 (%p{u=%d cc=%d})",
186 atomic_read(&peer
->usage
),
187 atomic_read(&peer
->conn_count
));
190 /* handle the peer being found in the active list straight off */
192 rxrpc_get_peer(peer
);
193 read_unlock(&trans
->peer_lock
);
196 /* handle resurrecting a peer from the graveyard */
198 rxrpc_get_peer(peer
);
199 rxrpc_get_transport(peer
->trans
);
200 rxrpc_krxtimod_del_timer(&peer
->timeout
);
201 list_del_init(&peer
->link
);
202 spin_unlock(&trans
->peer_gylock
);
205 /* handle finding the peer on the second time through the active
207 found_active_second_chance
:
208 rxrpc_get_peer(peer
);
211 } /* end rxrpc_peer_lookup() */
213 /*****************************************************************************/
215 * finish with a peer record
216 * - it gets sent to the graveyard from where it can be resurrected or timed
219 void rxrpc_put_peer(struct rxrpc_peer
*peer
)
221 struct rxrpc_transport
*trans
= peer
->trans
;
223 _enter("%p{cc=%d a=%08x}",
225 atomic_read(&peer
->conn_count
),
226 ntohl(peer
->addr
.s_addr
));
229 if (atomic_read(&peer
->usage
) <= 0)
232 write_lock(&trans
->peer_lock
);
233 spin_lock(&trans
->peer_gylock
);
234 if (likely(!atomic_dec_and_test(&peer
->usage
))) {
235 spin_unlock(&trans
->peer_gylock
);
236 write_unlock(&trans
->peer_lock
);
241 /* move to graveyard queue */
242 list_del(&peer
->link
);
243 write_unlock(&trans
->peer_lock
);
245 list_add_tail(&peer
->link
, &trans
->peer_graveyard
);
247 BUG_ON(!list_empty(&peer
->conn_active
));
249 rxrpc_krxtimod_add_timer(&peer
->timeout
, rxrpc_peer_timeout
* HZ
);
251 spin_unlock(&trans
->peer_gylock
);
253 rxrpc_put_transport(trans
);
256 } /* end rxrpc_put_peer() */
258 /*****************************************************************************/
260 * handle a peer timing out in the graveyard
261 * - called from krxtimod
263 static void rxrpc_peer_do_timeout(struct rxrpc_peer
*peer
)
265 struct rxrpc_transport
*trans
= peer
->trans
;
267 _enter("%p{u=%d cc=%d a=%08x}",
269 atomic_read(&peer
->usage
),
270 atomic_read(&peer
->conn_count
),
271 ntohl(peer
->addr
.s_addr
));
273 BUG_ON(atomic_read(&peer
->usage
) < 0);
275 /* remove from graveyard if still dead */
276 spin_lock(&trans
->peer_gylock
);
277 if (atomic_read(&peer
->usage
) == 0)
278 list_del_init(&peer
->link
);
281 spin_unlock(&trans
->peer_gylock
);
285 return; /* resurrected */
288 /* clear all connections on this peer */
289 rxrpc_conn_clearall(peer
);
291 BUG_ON(!list_empty(&peer
->conn_active
));
292 BUG_ON(!list_empty(&peer
->conn_graveyard
));
294 /* inform the application layer */
295 if (peer
->ops
&& peer
->ops
->discarding
)
296 peer
->ops
->discarding(peer
);
298 if (!list_empty(&peer
->proc_link
)) {
299 down_write(&rxrpc_peers_sem
);
300 list_del(&peer
->proc_link
);
301 up_write(&rxrpc_peers_sem
);
304 __RXACCT(atomic_dec(&rxrpc_peer_count
));
307 /* if the graveyard is now empty, wake up anyone waiting for that */
308 if (atomic_dec_and_test(&trans
->peer_count
))
309 wake_up(&trans
->peer_gy_waitq
);
311 _leave(" [destroyed]");
312 } /* end rxrpc_peer_do_timeout() */
314 /*****************************************************************************/
316 * clear all peer records from a transport endpoint
318 void rxrpc_peer_clearall(struct rxrpc_transport
*trans
)
320 DECLARE_WAITQUEUE(myself
,current
);
322 struct rxrpc_peer
*peer
;
327 /* there shouldn't be any active peers remaining */
328 BUG_ON(!list_empty(&trans
->peer_active
));
330 /* manually timeout all peers in the graveyard */
331 spin_lock(&trans
->peer_gylock
);
332 while (!list_empty(&trans
->peer_graveyard
)) {
333 peer
= list_entry(trans
->peer_graveyard
.next
,
334 struct rxrpc_peer
, link
);
335 _debug("Clearing peer %p\n", peer
);
336 err
= rxrpc_krxtimod_del_timer(&peer
->timeout
);
337 spin_unlock(&trans
->peer_gylock
);
340 rxrpc_peer_do_timeout(peer
);
342 spin_lock(&trans
->peer_gylock
);
344 spin_unlock(&trans
->peer_gylock
);
346 /* wait for the the peer graveyard to be completely cleared */
347 set_current_state(TASK_UNINTERRUPTIBLE
);
348 add_wait_queue(&trans
->peer_gy_waitq
, &myself
);
350 while (atomic_read(&trans
->peer_count
) != 0) {
352 set_current_state(TASK_UNINTERRUPTIBLE
);
355 remove_wait_queue(&trans
->peer_gy_waitq
, &myself
);
356 set_current_state(TASK_RUNNING
);
359 } /* end rxrpc_peer_clearall() */
361 /*****************************************************************************/
363 * calculate and cache the Round-Trip-Time for a message and its response
365 void rxrpc_peer_calculate_rtt(struct rxrpc_peer
*peer
,
366 struct rxrpc_message
*msg
,
367 struct rxrpc_message
*resp
)
369 unsigned long long rtt
;
372 _enter("%p,%p,%p", peer
, msg
, resp
);
374 /* calculate the latest RTT */
375 rtt
= resp
->stamp
.tv_sec
- msg
->stamp
.tv_sec
;
377 rtt
+= resp
->stamp
.tv_usec
- msg
->stamp
.tv_usec
;
380 peer
->rtt_cache
[peer
->rtt_point
] = rtt
;
382 peer
->rtt_point
%= RXRPC_RTT_CACHE_SIZE
;
384 if (peer
->rtt_usage
< RXRPC_RTT_CACHE_SIZE
)
387 /* recalculate RTT */
389 for (loop
= peer
->rtt_usage
- 1; loop
>= 0; loop
--)
390 rtt
+= peer
->rtt_cache
[loop
];
392 do_div(rtt
, peer
->rtt_usage
);
395 _leave(" RTT=%lu.%lums",
396 (long) (peer
->rtt
/ 1000), (long) (peer
->rtt
% 1000));
398 } /* end rxrpc_peer_calculate_rtt() */