1 /* AFS server record management
3 * Copyright (C) 2002, 2007 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>
17 static unsigned afs_server_gc_delay
= 10; /* Server record timeout in seconds */
18 static unsigned afs_server_update_delay
= 30; /* Time till VLDB recheck in secs */
20 static void afs_inc_servers_outstanding(struct afs_net
*net
)
22 atomic_inc(&net
->servers_outstanding
);
25 static void afs_dec_servers_outstanding(struct afs_net
*net
)
27 if (atomic_dec_and_test(&net
->servers_outstanding
))
28 wake_up_atomic_t(&net
->servers_outstanding
);
32 * Find a server by one of its addresses.
34 struct afs_server
*afs_find_server(struct afs_net
*net
,
35 const struct sockaddr_rxrpc
*srx
)
37 const struct sockaddr_in6
*a
= &srx
->transport
.sin6
, *b
;
38 const struct afs_addr_list
*alist
;
39 struct afs_server
*server
= NULL
;
44 if (srx
->transport
.sin6
.sin6_addr
.s6_addr32
[0] == 0 ||
45 srx
->transport
.sin6
.sin6_addr
.s6_addr32
[1] == 0 ||
46 srx
->transport
.sin6
.sin6_addr
.s6_addr32
[2] == htonl(0xffff))
53 afs_put_server(net
, server
);
55 read_seqbegin_or_lock(&net
->fs_addr_lock
, &seq
);
58 hlist_for_each_entry_rcu(server
, &net
->fs_addresses6
, addr6_link
) {
59 alist
= rcu_dereference(server
->addresses
);
60 for (i
= alist
->nr_ipv4
; i
< alist
->nr_addrs
; i
++) {
61 b
= &alist
->addrs
[i
].transport
.sin6
;
62 diff
= (u16
)a
->sin6_port
- (u16
)b
->sin6_port
;
64 diff
= memcmp(&a
->sin6_addr
,
66 sizeof(struct in6_addr
));
70 // TODO: Sort the list
71 //if (i == alist->nr_ipv4)
78 hlist_for_each_entry_rcu(server
, &net
->fs_addresses4
, addr4_link
) {
79 alist
= rcu_dereference(server
->addresses
);
80 for (i
= 0; i
< alist
->nr_ipv4
; i
++) {
81 b
= &alist
->addrs
[i
].transport
.sin6
;
82 diff
= (u16
)a
->sin6_port
- (u16
)b
->sin6_port
;
84 diff
= ((u32
)a
->sin6_addr
.s6_addr32
[3] -
85 (u32
)b
->sin6_addr
.s6_addr32
[3]);
89 // TODO: Sort the list
101 if (server
&& !atomic_inc_not_zero(&server
->usage
))
104 } while (need_seqretry(&net
->fs_addr_lock
, seq
));
106 done_seqretry(&net
->fs_addr_lock
, seq
);
113 * Look up a server by its UUID
115 struct afs_server
*afs_find_server_by_uuid(struct afs_net
*net
, const uuid_t
*uuid
)
117 struct afs_server
*server
= NULL
;
124 /* Unfortunately, rbtree walking doesn't give reliable results
125 * under just the RCU read lock, so we have to check for
129 afs_put_server(net
, server
);
132 read_seqbegin_or_lock(&net
->fs_lock
, &seq
);
134 p
= net
->fs_servers
.rb_node
;
136 server
= rb_entry(p
, struct afs_server
, uuid_rb
);
138 diff
= memcmp(uuid
, &server
->uuid
, sizeof(*uuid
));
141 } else if (diff
> 0) {
144 afs_get_server(server
);
150 } while (need_seqretry(&net
->fs_lock
, seq
));
152 done_seqretry(&net
->fs_lock
, seq
);
154 _leave(" = %p", server
);
159 * Install a server record in the namespace tree
161 static struct afs_server
*afs_install_server(struct afs_net
*net
,
162 struct afs_server
*candidate
)
164 const struct afs_addr_list
*alist
;
165 struct afs_server
*server
;
166 struct rb_node
**pp
, *p
;
167 int ret
= -EEXIST
, diff
;
169 _enter("%p", candidate
);
171 write_seqlock(&net
->fs_lock
);
173 /* Firstly install the server in the UUID lookup tree */
174 pp
= &net
->fs_servers
.rb_node
;
178 _debug("- consider %p", p
);
179 server
= rb_entry(p
, struct afs_server
, uuid_rb
);
180 diff
= memcmp(&candidate
->uuid
, &server
->uuid
, sizeof(uuid_t
));
182 pp
= &(*pp
)->rb_left
;
184 pp
= &(*pp
)->rb_right
;
190 rb_link_node(&server
->uuid_rb
, p
, pp
);
191 rb_insert_color(&server
->uuid_rb
, &net
->fs_servers
);
192 hlist_add_head_rcu(&server
->proc_link
, &net
->fs_proc
);
194 write_seqlock(&net
->fs_addr_lock
);
195 alist
= rcu_dereference_protected(server
->addresses
,
196 lockdep_is_held(&net
->fs_addr_lock
.lock
));
198 /* Secondly, if the server has any IPv4 and/or IPv6 addresses, install
199 * it in the IPv4 and/or IPv6 reverse-map lists.
201 * TODO: For speed we want to use something other than a flat list
202 * here; even sorting the list in terms of lowest address would help a
203 * bit, but anything we might want to do gets messy and memory
206 if (alist
->nr_ipv4
> 0)
207 hlist_add_head_rcu(&server
->addr4_link
, &net
->fs_addresses4
);
208 if (alist
->nr_addrs
> alist
->nr_ipv4
)
209 hlist_add_head_rcu(&server
->addr6_link
, &net
->fs_addresses6
);
211 write_sequnlock(&net
->fs_addr_lock
);
215 afs_get_server(server
);
216 write_sequnlock(&net
->fs_lock
);
221 * allocate a new server record
223 static struct afs_server
*afs_alloc_server(struct afs_net
*net
,
225 struct afs_addr_list
*alist
)
227 struct afs_server
*server
;
231 server
= kzalloc(sizeof(struct afs_server
), GFP_KERNEL
);
235 atomic_set(&server
->usage
, 1);
236 RCU_INIT_POINTER(server
->addresses
, alist
);
237 server
->addr_version
= alist
->version
;
238 server
->uuid
= *uuid
;
239 server
->flags
= (1UL << AFS_SERVER_FL_NEW
);
240 server
->update_at
= ktime_get_real_seconds() + afs_server_update_delay
;
241 rwlock_init(&server
->fs_lock
);
242 INIT_LIST_HEAD(&server
->cb_interests
);
243 rwlock_init(&server
->cb_break_lock
);
245 afs_inc_servers_outstanding(net
);
246 _leave(" = %p", server
);
250 _leave(" = NULL [nomem]");
255 * Look up an address record for a server
257 static struct afs_addr_list
*afs_vl_lookup_addrs(struct afs_cell
*cell
,
258 struct key
*key
, const uuid_t
*uuid
)
260 struct afs_addr_cursor ac
;
261 struct afs_addr_list
*alist
;
264 ret
= afs_set_vl_cursor(&ac
, cell
);
268 while (afs_iterate_addresses(&ac
)) {
269 if (test_bit(ac
.index
, &ac
.alist
->yfs
))
270 alist
= afs_yfsvl_get_endpoints(cell
->net
, &ac
, key
, uuid
);
272 alist
= afs_vl_get_addrs_u(cell
->net
, &ac
, key
, uuid
);
278 ac
.error
= afs_abort_to_error(ac
.abort_code
);
294 return ERR_PTR(afs_end_cursor(&ac
));
298 * Get or create a fileserver record.
300 struct afs_server
*afs_lookup_server(struct afs_cell
*cell
, struct key
*key
,
303 struct afs_addr_list
*alist
;
304 struct afs_server
*server
, *candidate
;
306 _enter("%p,%pU", cell
->net
, uuid
);
308 server
= afs_find_server_by_uuid(cell
->net
, uuid
);
312 alist
= afs_vl_lookup_addrs(cell
, key
, uuid
);
314 return ERR_CAST(alist
);
316 candidate
= afs_alloc_server(cell
->net
, uuid
, alist
);
318 afs_put_addrlist(alist
);
319 return ERR_PTR(-ENOMEM
);
322 server
= afs_install_server(cell
->net
, candidate
);
323 if (server
!= candidate
) {
324 afs_put_addrlist(alist
);
328 _leave(" = %p{%d}", server
, atomic_read(&server
->usage
));
333 * Set the server timer to fire after a given delay, assuming it's not already
334 * set for an earlier time.
336 static void afs_set_server_timer(struct afs_net
*net
, time64_t delay
)
339 afs_inc_servers_outstanding(net
);
340 if (timer_reduce(&net
->fs_timer
, jiffies
+ delay
* HZ
))
341 afs_dec_servers_outstanding(net
);
346 * Server management timer. We have an increment on fs_outstanding that we
347 * need to pass along to the work item.
349 void afs_servers_timer(struct timer_list
*timer
)
351 struct afs_net
*net
= container_of(timer
, struct afs_net
, fs_timer
);
354 if (!queue_work(afs_wq
, &net
->fs_manager
))
355 afs_dec_servers_outstanding(net
);
359 * Release a reference on a server record.
361 void afs_put_server(struct afs_net
*net
, struct afs_server
*server
)
368 server
->put_time
= ktime_get_real_seconds();
370 usage
= atomic_dec_return(&server
->usage
);
372 _enter("{%u}", usage
);
374 if (likely(usage
> 0))
377 afs_set_server_timer(net
, afs_server_gc_delay
);
380 static void afs_server_rcu(struct rcu_head
*rcu
)
382 struct afs_server
*server
= container_of(rcu
, struct afs_server
, rcu
);
384 afs_put_addrlist(server
->addresses
);
389 * destroy a dead server
391 static void afs_destroy_server(struct afs_net
*net
, struct afs_server
*server
)
393 struct afs_addr_list
*alist
= server
->addresses
;
394 struct afs_addr_cursor ac
= {
396 .addr
= &alist
->addrs
[0],
397 .start
= alist
->index
,
398 .index
= alist
->index
,
401 _enter("%p", server
);
403 afs_fs_give_up_all_callbacks(net
, server
, &ac
, NULL
);
404 call_rcu(&server
->rcu
, afs_server_rcu
);
405 afs_dec_servers_outstanding(net
);
409 * Garbage collect any expired servers.
411 static void afs_gc_servers(struct afs_net
*net
, struct afs_server
*gc_list
)
413 struct afs_server
*server
;
417 while ((server
= gc_list
)) {
418 gc_list
= server
->gc_next
;
420 write_seqlock(&net
->fs_lock
);
422 deleted
= atomic_try_cmpxchg(&server
->usage
, &usage
, 0);
424 rb_erase(&server
->uuid_rb
, &net
->fs_servers
);
425 hlist_del_rcu(&server
->proc_link
);
427 write_sequnlock(&net
->fs_lock
);
430 afs_destroy_server(net
, server
);
435 * Manage the records of servers known to be within a network namespace. This
436 * includes garbage collecting unused servers.
438 * Note also that we were given an increment on net->servers_outstanding by
439 * whoever queued us that we need to deal with before returning.
441 void afs_manage_servers(struct work_struct
*work
)
443 struct afs_net
*net
= container_of(work
, struct afs_net
, fs_manager
);
444 struct afs_server
*gc_list
= NULL
;
445 struct rb_node
*cursor
;
446 time64_t now
= ktime_get_real_seconds(), next_manage
= TIME64_MAX
;
447 bool purging
= !net
->live
;
451 /* Trawl the server list looking for servers that have expired from
454 read_seqlock_excl(&net
->fs_lock
);
456 for (cursor
= rb_first(&net
->fs_servers
); cursor
; cursor
= rb_next(cursor
)) {
457 struct afs_server
*server
=
458 rb_entry(cursor
, struct afs_server
, uuid_rb
);
459 int usage
= atomic_read(&server
->usage
);
461 _debug("manage %pU %u", &server
->uuid
, usage
);
463 ASSERTCMP(usage
, >=, 1);
464 ASSERTIFCMP(purging
, usage
, ==, 1);
467 time64_t expire_at
= server
->put_time
;
469 if (!test_bit(AFS_SERVER_FL_VL_FAIL
, &server
->flags
) &&
470 !test_bit(AFS_SERVER_FL_NOT_FOUND
, &server
->flags
))
471 expire_at
+= afs_server_gc_delay
;
472 if (purging
|| expire_at
<= now
) {
473 server
->gc_next
= gc_list
;
475 } else if (expire_at
< next_manage
) {
476 next_manage
= expire_at
;
481 read_sequnlock_excl(&net
->fs_lock
);
483 /* Update the timer on the way out. We have to pass an increment on
484 * servers_outstanding in the namespace that we are in to the timer or
485 * the work scheduler.
487 if (!purging
&& next_manage
< TIME64_MAX
) {
488 now
= ktime_get_real_seconds();
490 if (next_manage
- now
<= 0) {
491 if (queue_work(afs_wq
, &net
->fs_manager
))
492 afs_inc_servers_outstanding(net
);
494 afs_set_server_timer(net
, next_manage
- now
);
498 afs_gc_servers(net
, gc_list
);
500 afs_dec_servers_outstanding(net
);
501 _leave(" [%d]", atomic_read(&net
->servers_outstanding
));
504 static void afs_queue_server_manager(struct afs_net
*net
)
506 afs_inc_servers_outstanding(net
);
507 if (!queue_work(afs_wq
, &net
->fs_manager
))
508 afs_dec_servers_outstanding(net
);
512 * Purge list of servers.
514 void afs_purge_servers(struct afs_net
*net
)
518 if (del_timer_sync(&net
->fs_timer
))
519 atomic_dec(&net
->servers_outstanding
);
521 afs_queue_server_manager(net
);
524 wait_on_atomic_t(&net
->servers_outstanding
, atomic_t_wait
,
525 TASK_UNINTERRUPTIBLE
);
530 * Probe a fileserver to find its capabilities.
532 * TODO: Try service upgrade.
534 static bool afs_do_probe_fileserver(struct afs_fs_cursor
*fc
)
539 fc
->ac
.start
= READ_ONCE(fc
->ac
.alist
->index
);
540 fc
->ac
.index
= fc
->ac
.start
;
542 fc
->ac
.begun
= false;
544 while (afs_iterate_addresses(&fc
->ac
)) {
545 afs_fs_get_capabilities(afs_v2net(fc
->vnode
), fc
->cbi
->server
,
547 switch (fc
->ac
.error
) {
549 afs_end_cursor(&fc
->ac
);
550 set_bit(AFS_SERVER_FL_PROBED
, &fc
->cbi
->server
->flags
);
553 fc
->ac
.error
= afs_abort_to_error(fc
->ac
.abort_code
);
571 afs_end_cursor(&fc
->ac
);
576 * If we haven't already, try probing the fileserver to get its capabilities.
577 * We try not to instigate parallel probes, but it's possible that the parallel
578 * probes will fail due to authentication failure when ours would succeed.
580 * TODO: Try sending an anonymous probe if an authenticated probe fails.
582 bool afs_probe_fileserver(struct afs_fs_cursor
*fc
)
585 int ret
, retries
= 0;
590 if (test_bit(AFS_SERVER_FL_PROBED
, &fc
->cbi
->server
->flags
)) {
595 if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING
, &fc
->cbi
->server
->flags
)) {
596 success
= afs_do_probe_fileserver(fc
);
597 clear_bit_unlock(AFS_SERVER_FL_PROBING
, &fc
->cbi
->server
->flags
);
598 wake_up_bit(&fc
->cbi
->server
->flags
, AFS_SERVER_FL_PROBING
);
604 ret
= wait_on_bit(&fc
->cbi
->server
->flags
, AFS_SERVER_FL_PROBING
,
606 if (ret
== -ERESTARTSYS
) {
608 _leave(" = f [%d]", ret
);
614 fc
->ac
.error
= -ESTALE
;
615 _leave(" = f [stale]");
623 * Get an update for a server's address list.
625 static noinline
bool afs_update_server_record(struct afs_fs_cursor
*fc
, struct afs_server
*server
)
627 struct afs_addr_list
*alist
, *discard
;
631 alist
= afs_vl_lookup_addrs(fc
->vnode
->volume
->cell
, fc
->key
,
634 fc
->ac
.error
= PTR_ERR(alist
);
635 _leave(" = f [%d]", fc
->ac
.error
);
640 if (server
->addr_version
!= alist
->version
) {
641 write_lock(&server
->fs_lock
);
642 discard
= rcu_dereference_protected(server
->addresses
,
643 lockdep_is_held(&server
->fs_lock
));
644 rcu_assign_pointer(server
->addresses
, alist
);
645 server
->addr_version
= alist
->version
;
646 write_unlock(&server
->fs_lock
);
649 server
->update_at
= ktime_get_real_seconds() + afs_server_update_delay
;
650 afs_put_addrlist(discard
);
656 * See if a server's address list needs updating.
658 bool afs_check_server_record(struct afs_fs_cursor
*fc
, struct afs_server
*server
)
660 time64_t now
= ktime_get_real_seconds();
663 int ret
, retries
= 0;
670 diff
= READ_ONCE(server
->update_at
) - now
;
672 _leave(" = t [not now %ld]", diff
);
676 if (!test_and_set_bit_lock(AFS_SERVER_FL_UPDATING
, &server
->flags
)) {
677 success
= afs_update_server_record(fc
, server
);
678 clear_bit_unlock(AFS_SERVER_FL_UPDATING
, &server
->flags
);
679 wake_up_bit(&server
->flags
, AFS_SERVER_FL_UPDATING
);
680 _leave(" = %d", success
);
684 ret
= wait_on_bit(&server
->flags
, AFS_SERVER_FL_UPDATING
,
686 if (ret
== -ERESTARTSYS
) {
688 _leave(" = f [intr]");
694 _leave(" = f [stale]");