]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/afs/server.c
drm/i915: Force 2*96 MHz cdclk on glk/cnl when audio power is enabled
[mirror_ubuntu-bionic-kernel.git] / fs / afs / server.c
CommitLineData
ec26815a 1/* AFS server record management
1da177e4 2 *
08e0e7c8 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
1da177e4
LT
4 * Written by David Howells (dhowells@redhat.com)
5 *
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.
10 */
11
12#include <linux/sched.h>
13#include <linux/slab.h>
4d9df986 14#include "afs_fs.h"
1da177e4
LT
15#include "internal.h"
16
d2ddc776
DH
17static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */
18static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */
1da177e4 19
59fa1c4a
DH
20static void afs_inc_servers_outstanding(struct afs_net *net)
21{
22 atomic_inc(&net->servers_outstanding);
23}
24
25static void afs_dec_servers_outstanding(struct afs_net *net)
26{
27 if (atomic_dec_and_test(&net->servers_outstanding))
28 wake_up_atomic_t(&net->servers_outstanding);
29}
30
d2ddc776
DH
31/*
32 * Find a server by one of its addresses.
33 */
34struct afs_server *afs_find_server(struct afs_net *net,
35 const struct sockaddr_rxrpc *srx)
59fa1c4a 36{
d2ddc776
DH
37 const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
38 const struct afs_addr_list *alist;
39 struct afs_server *server = NULL;
40 unsigned int i;
41 bool ipv6 = true;
42 int seq = 0, diff;
43
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))
47 ipv6 = false;
48
49 rcu_read_lock();
50
51 do {
52 if (server)
53 afs_put_server(net, server);
54 server = NULL;
55 read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
56
57 if (ipv6) {
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;
63 if (diff == 0)
64 diff = memcmp(&a->sin6_addr,
65 &b->sin6_addr,
66 sizeof(struct in6_addr));
67 if (diff == 0)
68 goto found;
d2ddc776
DH
69 }
70 }
71 } else {
72 hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
73 alist = rcu_dereference(server->addresses);
74 for (i = 0; i < alist->nr_ipv4; i++) {
75 b = &alist->addrs[i].transport.sin6;
76 diff = (u16)a->sin6_port - (u16)b->sin6_port;
77 if (diff == 0)
78 diff = ((u32)a->sin6_addr.s6_addr32[3] -
79 (u32)b->sin6_addr.s6_addr32[3]);
80 if (diff == 0)
81 goto found;
d2ddc776
DH
82 }
83 }
84 }
59fa1c4a 85
d2ddc776
DH
86 server = NULL;
87 found:
88 if (server && !atomic_inc_not_zero(&server->usage))
89 server = NULL;
90
91 } while (need_seqretry(&net->fs_addr_lock, seq));
92
93 done_seqretry(&net->fs_addr_lock, seq);
94
95 rcu_read_unlock();
96 return server;
59fa1c4a
DH
97}
98
08e0e7c8 99/*
d2ddc776 100 * Look up a server by its UUID
08e0e7c8 101 */
d2ddc776 102struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uuid)
1da177e4 103{
d2ddc776
DH
104 struct afs_server *server = NULL;
105 struct rb_node *p;
106 int diff, seq = 0;
107
108 _enter("%pU", uuid);
109
110 do {
111 /* Unfortunately, rbtree walking doesn't give reliable results
112 * under just the RCU read lock, so we have to check for
113 * changes.
114 */
115 if (server)
116 afs_put_server(net, server);
117 server = NULL;
118
119 read_seqbegin_or_lock(&net->fs_lock, &seq);
120
121 p = net->fs_servers.rb_node;
122 while (p) {
123 server = rb_entry(p, struct afs_server, uuid_rb);
124
125 diff = memcmp(uuid, &server->uuid, sizeof(*uuid));
126 if (diff < 0) {
127 p = p->rb_left;
128 } else if (diff > 0) {
129 p = p->rb_right;
130 } else {
131 afs_get_server(server);
132 break;
133 }
134
135 server = NULL;
136 }
137 } while (need_seqretry(&net->fs_lock, seq));
138
139 done_seqretry(&net->fs_lock, seq);
140
141 _leave(" = %p", server);
142 return server;
143}
144
145/*
146 * Install a server record in the namespace tree
147 */
148static struct afs_server *afs_install_server(struct afs_net *net,
149 struct afs_server *candidate)
150{
151 const struct afs_addr_list *alist;
152 struct afs_server *server;
08e0e7c8 153 struct rb_node **pp, *p;
d2ddc776 154 int ret = -EEXIST, diff;
08e0e7c8 155
d2ddc776 156 _enter("%p", candidate);
1da177e4 157
d2ddc776 158 write_seqlock(&net->fs_lock);
08e0e7c8 159
d2ddc776
DH
160 /* Firstly install the server in the UUID lookup tree */
161 pp = &net->fs_servers.rb_node;
08e0e7c8
DH
162 p = NULL;
163 while (*pp) {
164 p = *pp;
165 _debug("- consider %p", p);
d2ddc776
DH
166 server = rb_entry(p, struct afs_server, uuid_rb);
167 diff = memcmp(&candidate->uuid, &server->uuid, sizeof(uuid_t));
4d9df986 168 if (diff < 0)
08e0e7c8 169 pp = &(*pp)->rb_left;
4d9df986 170 else if (diff > 0)
08e0e7c8
DH
171 pp = &(*pp)->rb_right;
172 else
d2ddc776 173 goto exists;
08e0e7c8 174 }
1da177e4 175
d2ddc776
DH
176 server = candidate;
177 rb_link_node(&server->uuid_rb, p, pp);
178 rb_insert_color(&server->uuid_rb, &net->fs_servers);
179 hlist_add_head_rcu(&server->proc_link, &net->fs_proc);
180
181 write_seqlock(&net->fs_addr_lock);
182 alist = rcu_dereference_protected(server->addresses,
183 lockdep_is_held(&net->fs_addr_lock.lock));
184
185 /* Secondly, if the server has any IPv4 and/or IPv6 addresses, install
186 * it in the IPv4 and/or IPv6 reverse-map lists.
187 *
188 * TODO: For speed we want to use something other than a flat list
189 * here; even sorting the list in terms of lowest address would help a
190 * bit, but anything we might want to do gets messy and memory
191 * intensive.
192 */
193 if (alist->nr_ipv4 > 0)
194 hlist_add_head_rcu(&server->addr4_link, &net->fs_addresses4);
195 if (alist->nr_addrs > alist->nr_ipv4)
196 hlist_add_head_rcu(&server->addr6_link, &net->fs_addresses6);
197
198 write_sequnlock(&net->fs_addr_lock);
08e0e7c8 199 ret = 0;
1da177e4 200
d2ddc776
DH
201exists:
202 afs_get_server(server);
203 write_sequnlock(&net->fs_lock);
204 return server;
08e0e7c8 205}
1da177e4 206
1da177e4 207/*
08e0e7c8 208 * allocate a new server record
1da177e4 209 */
d2ddc776
DH
210static struct afs_server *afs_alloc_server(struct afs_net *net,
211 const uuid_t *uuid,
212 struct afs_addr_list *alist)
1da177e4 213{
08e0e7c8 214 struct afs_server *server;
1da177e4 215
08e0e7c8 216 _enter("");
1da177e4 217
b593e48d 218 server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
8b2a464c
DH
219 if (!server)
220 goto enomem;
8b2a464c
DH
221
222 atomic_set(&server->usage, 1);
d2ddc776
DH
223 RCU_INIT_POINTER(server->addresses, alist);
224 server->addr_version = alist->version;
225 server->uuid = *uuid;
226 server->flags = (1UL << AFS_SERVER_FL_NEW);
227 server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
228 rwlock_init(&server->fs_lock);
8b2a464c
DH
229 INIT_LIST_HEAD(&server->cb_interests);
230 rwlock_init(&server->cb_break_lock);
231
d2ddc776
DH
232 afs_inc_servers_outstanding(net);
233 _leave(" = %p", server);
08e0e7c8 234 return server;
8b2a464c 235
8b2a464c
DH
236enomem:
237 _leave(" = NULL [nomem]");
238 return NULL;
08e0e7c8 239}
1da177e4 240
08e0e7c8 241/*
d2ddc776 242 * Look up an address record for a server
08e0e7c8 243 */
d2ddc776
DH
244static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell,
245 struct key *key, const uuid_t *uuid)
08e0e7c8 246{
d2ddc776
DH
247 struct afs_addr_cursor ac;
248 struct afs_addr_list *alist;
249 int ret;
250
251 ret = afs_set_vl_cursor(&ac, cell);
252 if (ret < 0)
253 return ERR_PTR(ret);
254
255 while (afs_iterate_addresses(&ac)) {
bf99a53c
DH
256 if (test_bit(ac.index, &ac.alist->yfs))
257 alist = afs_yfsvl_get_endpoints(cell->net, &ac, key, uuid);
258 else
259 alist = afs_vl_get_addrs_u(cell->net, &ac, key, uuid);
d2ddc776
DH
260 switch (ac.error) {
261 case 0:
262 afs_end_cursor(&ac);
263 return alist;
264 case -ECONNABORTED:
265 ac.error = afs_abort_to_error(ac.abort_code);
266 goto error;
267 case -ENOMEM:
268 case -ENONET:
269 goto error;
270 case -ENETUNREACH:
271 case -EHOSTUNREACH:
272 case -ECONNREFUSED:
273 break;
274 default:
275 ac.error = -EIO;
276 goto error;
277 }
08e0e7c8 278 }
08e0e7c8 279
d2ddc776
DH
280error:
281 return ERR_PTR(afs_end_cursor(&ac));
08e0e7c8 282}
1da177e4 283
08e0e7c8 284/*
d2ddc776 285 * Get or create a fileserver record.
08e0e7c8 286 */
d2ddc776
DH
287struct afs_server *afs_lookup_server(struct afs_cell *cell, struct key *key,
288 const uuid_t *uuid)
08e0e7c8 289{
d2ddc776
DH
290 struct afs_addr_list *alist;
291 struct afs_server *server, *candidate;
1da177e4 292
d2ddc776 293 _enter("%p,%pU", cell->net, uuid);
8324f0bc 294
d2ddc776
DH
295 server = afs_find_server_by_uuid(cell->net, uuid);
296 if (server)
297 return server;
1da177e4 298
d2ddc776
DH
299 alist = afs_vl_lookup_addrs(cell, key, uuid);
300 if (IS_ERR(alist))
301 return ERR_CAST(alist);
1da177e4 302
d2ddc776
DH
303 candidate = afs_alloc_server(cell->net, uuid, alist);
304 if (!candidate) {
305 afs_put_addrlist(alist);
306 return ERR_PTR(-ENOMEM);
307 }
1da177e4 308
d2ddc776
DH
309 server = afs_install_server(cell->net, candidate);
310 if (server != candidate) {
311 afs_put_addrlist(alist);
312 kfree(candidate);
08e0e7c8 313 }
1da177e4 314
d2ddc776 315 _leave(" = %p{%d}", server, atomic_read(&server->usage));
08e0e7c8 316 return server;
ec26815a 317}
1da177e4 318
d2ddc776
DH
319/*
320 * Set the server timer to fire after a given delay, assuming it's not already
321 * set for an earlier time.
322 */
59fa1c4a
DH
323static void afs_set_server_timer(struct afs_net *net, time64_t delay)
324{
59fa1c4a 325 if (net->live) {
d2ddc776
DH
326 afs_inc_servers_outstanding(net);
327 if (timer_reduce(&net->fs_timer, jiffies + delay * HZ))
59fa1c4a
DH
328 afs_dec_servers_outstanding(net);
329 }
330}
331
1da177e4 332/*
d2ddc776
DH
333 * Server management timer. We have an increment on fs_outstanding that we
334 * need to pass along to the work item.
335 */
336void afs_servers_timer(struct timer_list *timer)
337{
338 struct afs_net *net = container_of(timer, struct afs_net, fs_timer);
339
340 _enter("");
341 if (!queue_work(afs_wq, &net->fs_manager))
342 afs_dec_servers_outstanding(net);
343}
344
345/*
346 * Release a reference on a server record.
1da177e4 347 */
9ed900b1 348void afs_put_server(struct afs_net *net, struct afs_server *server)
1da177e4 349{
d2ddc776
DH
350 unsigned int usage;
351
1da177e4
LT
352 if (!server)
353 return;
354
d2ddc776 355 server->put_time = ktime_get_real_seconds();
1da177e4 356
d2ddc776 357 usage = atomic_dec_return(&server->usage);
260a9803 358
d2ddc776 359 _enter("{%u}", usage);
1da177e4 360
d2ddc776 361 if (likely(usage > 0))
1da177e4 362 return;
1da177e4 363
d2ddc776
DH
364 afs_set_server_timer(net, afs_server_gc_delay);
365}
366
367static void afs_server_rcu(struct rcu_head *rcu)
368{
369 struct afs_server *server = container_of(rcu, struct afs_server, rcu);
370
371 afs_put_addrlist(server->addresses);
372 kfree(server);
ec26815a 373}
1da177e4 374
1da177e4 375/*
08e0e7c8 376 * destroy a dead server
1da177e4 377 */
59fa1c4a 378static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
1da177e4 379{
d2ddc776 380 struct afs_addr_list *alist = server->addresses;
8b2a464c
DH
381 struct afs_addr_cursor ac = {
382 .alist = alist,
383 .addr = &alist->addrs[0],
384 .start = alist->index,
385 .index = alist->index,
386 .error = 0,
387 };
1da177e4
LT
388 _enter("%p", server);
389
d2ddc776
DH
390 afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
391 call_rcu(&server->rcu, afs_server_rcu);
59fa1c4a 392 afs_dec_servers_outstanding(net);
ec26815a 393}
1da177e4 394
1da177e4 395/*
d2ddc776 396 * Garbage collect any expired servers.
1da177e4 397 */
d2ddc776 398static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
1da177e4 399{
08e0e7c8 400 struct afs_server *server;
d2ddc776
DH
401 bool deleted;
402 int usage;
403
404 while ((server = gc_list)) {
405 gc_list = server->gc_next;
406
407 write_seqlock(&net->fs_lock);
408 usage = 1;
409 deleted = atomic_try_cmpxchg(&server->usage, &usage, 0);
410 if (deleted) {
411 rb_erase(&server->uuid_rb, &net->fs_servers);
412 hlist_del_rcu(&server->proc_link);
1da177e4 413 }
d2ddc776 414 write_sequnlock(&net->fs_lock);
1da177e4 415
2d9f9518
DH
416 if (deleted) {
417 write_seqlock(&net->fs_addr_lock);
418 if (!hlist_unhashed(&server->addr4_link))
419 hlist_del_rcu(&server->addr4_link);
420 if (!hlist_unhashed(&server->addr6_link))
421 hlist_del_rcu(&server->addr6_link);
422 write_sequnlock(&net->fs_addr_lock);
d2ddc776 423 afs_destroy_server(net, server);
2d9f9518 424 }
d2ddc776
DH
425 }
426}
427
428/*
429 * Manage the records of servers known to be within a network namespace. This
430 * includes garbage collecting unused servers.
431 *
432 * Note also that we were given an increment on net->servers_outstanding by
433 * whoever queued us that we need to deal with before returning.
434 */
435void afs_manage_servers(struct work_struct *work)
436{
437 struct afs_net *net = container_of(work, struct afs_net, fs_manager);
438 struct afs_server *gc_list = NULL;
439 struct rb_node *cursor;
440 time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
441 bool purging = !net->live;
442
443 _enter("");
444
445 /* Trawl the server list looking for servers that have expired from
446 * lack of use.
447 */
448 read_seqlock_excl(&net->fs_lock);
449
450 for (cursor = rb_first(&net->fs_servers); cursor; cursor = rb_next(cursor)) {
451 struct afs_server *server =
452 rb_entry(cursor, struct afs_server, uuid_rb);
453 int usage = atomic_read(&server->usage);
454
455 _debug("manage %pU %u", &server->uuid, usage);
456
457 ASSERTCMP(usage, >=, 1);
458 ASSERTIFCMP(purging, usage, ==, 1);
459
460 if (usage == 1) {
461 time64_t expire_at = server->put_time;
462
463 if (!test_bit(AFS_SERVER_FL_VL_FAIL, &server->flags) &&
464 !test_bit(AFS_SERVER_FL_NOT_FOUND, &server->flags))
465 expire_at += afs_server_gc_delay;
466 if (purging || expire_at <= now) {
467 server->gc_next = gc_list;
468 gc_list = server;
469 } else if (expire_at < next_manage) {
470 next_manage = expire_at;
471 }
1da177e4
LT
472 }
473 }
474
d2ddc776 475 read_sequnlock_excl(&net->fs_lock);
1da177e4 476
d2ddc776
DH
477 /* Update the timer on the way out. We have to pass an increment on
478 * servers_outstanding in the namespace that we are in to the timer or
479 * the work scheduler.
480 */
481 if (!purging && next_manage < TIME64_MAX) {
482 now = ktime_get_real_seconds();
483
484 if (next_manage - now <= 0) {
485 if (queue_work(afs_wq, &net->fs_manager))
486 afs_inc_servers_outstanding(net);
487 } else {
488 afs_set_server_timer(net, next_manage - now);
489 }
1da177e4 490 }
59fa1c4a 491
d2ddc776
DH
492 afs_gc_servers(net, gc_list);
493
59fa1c4a 494 afs_dec_servers_outstanding(net);
d2ddc776
DH
495 _leave(" [%d]", atomic_read(&net->servers_outstanding));
496}
497
498static void afs_queue_server_manager(struct afs_net *net)
499{
500 afs_inc_servers_outstanding(net);
501 if (!queue_work(afs_wq, &net->fs_manager))
502 afs_dec_servers_outstanding(net);
ec26815a 503}
1da177e4 504
1da177e4 505/*
d2ddc776 506 * Purge list of servers.
1da177e4 507 */
d2ddc776 508void afs_purge_servers(struct afs_net *net)
1da177e4 509{
d2ddc776
DH
510 _enter("");
511
512 if (del_timer_sync(&net->fs_timer))
59fa1c4a
DH
513 atomic_dec(&net->servers_outstanding);
514
d2ddc776 515 afs_queue_server_manager(net);
59fa1c4a 516
d2ddc776 517 _debug("wait");
59fa1c4a
DH
518 wait_on_atomic_t(&net->servers_outstanding, atomic_t_wait,
519 TASK_UNINTERRUPTIBLE);
d2ddc776
DH
520 _leave("");
521}
522
523/*
524 * Probe a fileserver to find its capabilities.
525 *
526 * TODO: Try service upgrade.
527 */
528static bool afs_do_probe_fileserver(struct afs_fs_cursor *fc)
529{
530 _enter("");
531
532 fc->ac.addr = NULL;
533 fc->ac.start = READ_ONCE(fc->ac.alist->index);
534 fc->ac.index = fc->ac.start;
535 fc->ac.error = 0;
536 fc->ac.begun = false;
537
538 while (afs_iterate_addresses(&fc->ac)) {
539 afs_fs_get_capabilities(afs_v2net(fc->vnode), fc->cbi->server,
540 &fc->ac, fc->key);
541 switch (fc->ac.error) {
542 case 0:
543 afs_end_cursor(&fc->ac);
544 set_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags);
545 return true;
546 case -ECONNABORTED:
547 fc->ac.error = afs_abort_to_error(fc->ac.abort_code);
548 goto error;
549 case -ENOMEM:
550 case -ENONET:
551 goto error;
552 case -ENETUNREACH:
553 case -EHOSTUNREACH:
554 case -ECONNREFUSED:
555 case -ETIMEDOUT:
556 case -ETIME:
557 break;
558 default:
559 fc->ac.error = -EIO;
560 goto error;
561 }
562 }
563
564error:
565 afs_end_cursor(&fc->ac);
566 return false;
567}
568
569/*
570 * If we haven't already, try probing the fileserver to get its capabilities.
571 * We try not to instigate parallel probes, but it's possible that the parallel
572 * probes will fail due to authentication failure when ours would succeed.
573 *
574 * TODO: Try sending an anonymous probe if an authenticated probe fails.
575 */
576bool afs_probe_fileserver(struct afs_fs_cursor *fc)
577{
578 bool success;
579 int ret, retries = 0;
580
581 _enter("");
582
583retry:
584 if (test_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags)) {
585 _leave(" = t");
586 return true;
587 }
588
589 if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags)) {
590 success = afs_do_probe_fileserver(fc);
591 clear_bit_unlock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags);
592 wake_up_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING);
593 _leave(" = t");
594 return success;
595 }
596
597 _debug("wait");
598 ret = wait_on_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING,
599 TASK_INTERRUPTIBLE);
600 if (ret == -ERESTARTSYS) {
601 fc->ac.error = ret;
602 _leave(" = f [%d]", ret);
603 return false;
604 }
605
606 retries++;
607 if (retries == 4) {
608 fc->ac.error = -ESTALE;
609 _leave(" = f [stale]");
610 return false;
611 }
612 _debug("retry");
613 goto retry;
614}
615
616/*
617 * Get an update for a server's address list.
618 */
619static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct afs_server *server)
620{
621 struct afs_addr_list *alist, *discard;
622
623 _enter("");
624
625 alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key,
626 &server->uuid);
627 if (IS_ERR(alist)) {
628 fc->ac.error = PTR_ERR(alist);
629 _leave(" = f [%d]", fc->ac.error);
630 return false;
631 }
632
633 discard = alist;
634 if (server->addr_version != alist->version) {
635 write_lock(&server->fs_lock);
636 discard = rcu_dereference_protected(server->addresses,
637 lockdep_is_held(&server->fs_lock));
638 rcu_assign_pointer(server->addresses, alist);
639 server->addr_version = alist->version;
640 write_unlock(&server->fs_lock);
641 }
642
643 server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
644 afs_put_addrlist(discard);
645 _leave(" = t");
646 return true;
647}
648
649/*
650 * See if a server's address list needs updating.
651 */
652bool afs_check_server_record(struct afs_fs_cursor *fc, struct afs_server *server)
653{
654 time64_t now = ktime_get_real_seconds();
655 long diff;
656 bool success;
657 int ret, retries = 0;
658
659 _enter("");
660
661 ASSERT(server);
662
663retry:
664 diff = READ_ONCE(server->update_at) - now;
665 if (diff > 0) {
666 _leave(" = t [not now %ld]", diff);
667 return true;
668 }
669
670 if (!test_and_set_bit_lock(AFS_SERVER_FL_UPDATING, &server->flags)) {
671 success = afs_update_server_record(fc, server);
672 clear_bit_unlock(AFS_SERVER_FL_UPDATING, &server->flags);
673 wake_up_bit(&server->flags, AFS_SERVER_FL_UPDATING);
674 _leave(" = %d", success);
675 return success;
676 }
677
678 ret = wait_on_bit(&server->flags, AFS_SERVER_FL_UPDATING,
679 TASK_INTERRUPTIBLE);
680 if (ret == -ERESTARTSYS) {
681 fc->ac.error = ret;
682 _leave(" = f [intr]");
683 return false;
684 }
685
686 retries++;
687 if (retries == 4) {
688 _leave(" = f [stale]");
689 ret = -ESTALE;
690 return false;
691 }
692 goto retry;
ec26815a 693}