hc
2024-02-20 e636c8d336489bf3eed5878299e6cc045bbad077
kernel/fs/afs/server.c
....@@ -1,32 +1,22 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* AFS server record management
23 *
34 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
45 * 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.
106 */
117
128 #include <linux/sched.h>
139 #include <linux/slab.h>
1410 #include "afs_fs.h"
1511 #include "internal.h"
12
+#include "protocol_yfs.h"
1613
1714 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 */
15
+static atomic_t afs_server_debug_id;
1916
20
-static void afs_inc_servers_outstanding(struct afs_net *net)
21
-{
22
- atomic_inc(&net->servers_outstanding);
23
-}
24
-
25
-static void afs_dec_servers_outstanding(struct afs_net *net)
26
-{
27
- if (atomic_dec_and_test(&net->servers_outstanding))
28
- wake_up_var(&net->servers_outstanding);
29
-}
17
+static struct afs_server *afs_maybe_use_server(struct afs_server *,
18
+ enum afs_server_trace);
19
+static void __afs_put_server(struct afs_net *, struct afs_server *);
3020
3121 /*
3222 * Find a server by one of its addresses.
....@@ -43,7 +33,7 @@
4333
4434 do {
4535 if (server)
46
- afs_put_server(net, server);
36
+ afs_unuse_server_notime(net, server, afs_server_trace_put_find_rsq);
4737 server = NULL;
4838 read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
4939
....@@ -81,9 +71,9 @@
8171 }
8272
8373 server = NULL;
74
+ continue;
8475 found:
85
- if (server && !atomic_inc_not_zero(&server->usage))
86
- server = NULL;
76
+ server = afs_maybe_use_server(server, afs_server_trace_get_by_addr);
8777
8878 } while (need_seqretry(&net->fs_addr_lock, seq));
8979
....@@ -94,7 +84,7 @@
9484 }
9585
9686 /*
97
- * Look up a server by its UUID
87
+ * Look up a server by its UUID and mark it active.
9888 */
9989 struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uuid)
10090 {
....@@ -110,7 +100,7 @@
110100 * changes.
111101 */
112102 if (server)
113
- afs_put_server(net, server);
103
+ afs_unuse_server(net, server, afs_server_trace_put_uuid_rsq);
114104 server = NULL;
115105
116106 read_seqbegin_or_lock(&net->fs_lock, &seq);
....@@ -125,7 +115,7 @@
125115 } else if (diff > 0) {
126116 p = p->rb_right;
127117 } else {
128
- afs_get_server(server);
118
+ afs_use_server(server, afs_server_trace_get_by_uuid);
129119 break;
130120 }
131121
....@@ -140,15 +130,18 @@
140130 }
141131
142132 /*
143
- * Install a server record in the namespace tree
133
+ * Install a server record in the namespace tree. If there's a clash, we stick
134
+ * it into a list anchored on whichever afs_server struct is actually in the
135
+ * tree.
144136 */
145
-static struct afs_server *afs_install_server(struct afs_net *net,
137
+static struct afs_server *afs_install_server(struct afs_cell *cell,
146138 struct afs_server *candidate)
147139 {
148140 const struct afs_addr_list *alist;
149
- struct afs_server *server;
141
+ struct afs_server *server, *next;
142
+ struct afs_net *net = cell->net;
150143 struct rb_node **pp, *p;
151
- int ret = -EEXIST, diff;
144
+ int diff;
152145
153146 _enter("%p", candidate);
154147
....@@ -162,12 +155,30 @@
162155 _debug("- consider %p", p);
163156 server = rb_entry(p, struct afs_server, uuid_rb);
164157 diff = memcmp(&candidate->uuid, &server->uuid, sizeof(uuid_t));
165
- if (diff < 0)
158
+ if (diff < 0) {
166159 pp = &(*pp)->rb_left;
167
- else if (diff > 0)
160
+ } else if (diff > 0) {
168161 pp = &(*pp)->rb_right;
169
- else
170
- goto exists;
162
+ } else {
163
+ if (server->cell == cell)
164
+ goto exists;
165
+
166
+ /* We have the same UUID representing servers in
167
+ * different cells. Append the new server to the list.
168
+ */
169
+ for (;;) {
170
+ next = rcu_dereference_protected(
171
+ server->uuid_next,
172
+ lockdep_is_held(&net->fs_lock.lock));
173
+ if (!next)
174
+ break;
175
+ server = next;
176
+ }
177
+ rcu_assign_pointer(server->uuid_next, candidate);
178
+ candidate->uuid_prev = server;
179
+ server = candidate;
180
+ goto added_dup;
181
+ }
171182 }
172183
173184 server = candidate;
....@@ -175,6 +186,7 @@
175186 rb_insert_color(&server->uuid_rb, &net->fs_servers);
176187 hlist_add_head_rcu(&server->proc_link, &net->fs_proc);
177188
189
+added_dup:
178190 write_seqlock(&net->fs_addr_lock);
179191 alist = rcu_dereference_protected(server->addresses,
180192 lockdep_is_held(&net->fs_addr_lock.lock));
....@@ -193,22 +205,22 @@
193205 hlist_add_head_rcu(&server->addr6_link, &net->fs_addresses6);
194206
195207 write_sequnlock(&net->fs_addr_lock);
196
- ret = 0;
197208
198209 exists:
199
- afs_get_server(server);
210
+ afs_get_server(server, afs_server_trace_get_install);
200211 write_sequnlock(&net->fs_lock);
201212 return server;
202213 }
203214
204215 /*
205
- * allocate a new server record
216
+ * Allocate a new server record and mark it active.
206217 */
207
-static struct afs_server *afs_alloc_server(struct afs_net *net,
218
+static struct afs_server *afs_alloc_server(struct afs_cell *cell,
208219 const uuid_t *uuid,
209220 struct afs_addr_list *alist)
210221 {
211222 struct afs_server *server;
223
+ struct afs_net *net = cell->net;
212224
213225 _enter("");
214226
....@@ -216,17 +228,21 @@
216228 if (!server)
217229 goto enomem;
218230
219
- atomic_set(&server->usage, 1);
231
+ atomic_set(&server->ref, 1);
232
+ atomic_set(&server->active, 1);
233
+ server->debug_id = atomic_inc_return(&afs_server_debug_id);
220234 RCU_INIT_POINTER(server->addresses, alist);
221235 server->addr_version = alist->version;
222236 server->uuid = *uuid;
223
- server->flags = (1UL << AFS_SERVER_FL_NEW);
224
- server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
225237 rwlock_init(&server->fs_lock);
226
- INIT_HLIST_HEAD(&server->cb_volumes);
227
- rwlock_init(&server->cb_break_lock);
238
+ init_waitqueue_head(&server->probe_wq);
239
+ INIT_LIST_HEAD(&server->probe_link);
240
+ spin_lock_init(&server->probe_lock);
241
+ server->cell = cell;
242
+ server->rtt = UINT_MAX;
228243
229244 afs_inc_servers_outstanding(net);
245
+ trace_afs_server(server, 1, 1, afs_server_trace_alloc);
230246 _leave(" = %p", server);
231247 return server;
232248
....@@ -241,48 +257,30 @@
241257 static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell,
242258 struct key *key, const uuid_t *uuid)
243259 {
244
- struct afs_addr_cursor ac;
245
- struct afs_addr_list *alist;
260
+ struct afs_vl_cursor vc;
261
+ struct afs_addr_list *alist = NULL;
246262 int ret;
247263
248
- ret = afs_set_vl_cursor(&ac, cell);
249
- if (ret < 0)
250
- return ERR_PTR(ret);
251
-
252
- while (afs_iterate_addresses(&ac)) {
253
- if (test_bit(ac.index, &ac.alist->yfs))
254
- alist = afs_yfsvl_get_endpoints(cell->net, &ac, key, uuid);
255
- else
256
- alist = afs_vl_get_addrs_u(cell->net, &ac, key, uuid);
257
- switch (ac.error) {
258
- case 0:
259
- afs_end_cursor(&ac);
260
- return alist;
261
- case -ECONNABORTED:
262
- ac.error = afs_abort_to_error(ac.abort_code);
263
- goto error;
264
- case -ENOMEM:
265
- case -ENONET:
266
- goto error;
267
- case -ENETUNREACH:
268
- case -EHOSTUNREACH:
269
- case -ECONNREFUSED:
270
- break;
271
- default:
272
- ac.error = -EIO;
273
- goto error;
264
+ ret = -ERESTARTSYS;
265
+ if (afs_begin_vlserver_operation(&vc, cell, key)) {
266
+ while (afs_select_vlserver(&vc)) {
267
+ if (test_bit(AFS_VLSERVER_FL_IS_YFS, &vc.server->flags))
268
+ alist = afs_yfsvl_get_endpoints(&vc, uuid);
269
+ else
270
+ alist = afs_vl_get_addrs_u(&vc, uuid);
274271 }
272
+
273
+ ret = afs_end_vlserver_operation(&vc);
275274 }
276275
277
-error:
278
- return ERR_PTR(afs_end_cursor(&ac));
276
+ return ret < 0 ? ERR_PTR(ret) : alist;
279277 }
280278
281279 /*
282280 * Get or create a fileserver record.
283281 */
284282 struct afs_server *afs_lookup_server(struct afs_cell *cell, struct key *key,
285
- const uuid_t *uuid)
283
+ const uuid_t *uuid, u32 addr_version)
286284 {
287285 struct afs_addr_list *alist;
288286 struct afs_server *server, *candidate;
....@@ -290,26 +288,34 @@
290288 _enter("%p,%pU", cell->net, uuid);
291289
292290 server = afs_find_server_by_uuid(cell->net, uuid);
293
- if (server)
291
+ if (server) {
292
+ if (server->addr_version != addr_version)
293
+ set_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags);
294294 return server;
295
+ }
295296
296297 alist = afs_vl_lookup_addrs(cell, key, uuid);
297298 if (IS_ERR(alist))
298299 return ERR_CAST(alist);
299300
300
- candidate = afs_alloc_server(cell->net, uuid, alist);
301
+ candidate = afs_alloc_server(cell, uuid, alist);
301302 if (!candidate) {
302303 afs_put_addrlist(alist);
303304 return ERR_PTR(-ENOMEM);
304305 }
305306
306
- server = afs_install_server(cell->net, candidate);
307
+ server = afs_install_server(cell, candidate);
307308 if (server != candidate) {
308309 afs_put_addrlist(alist);
309310 kfree(candidate);
311
+ } else {
312
+ /* Immediately dispatch an asynchronous probe to each interface
313
+ * on the fileserver. This will make sure the repeat-probing
314
+ * service is started.
315
+ */
316
+ afs_fs_probe_fileserver(cell->net, server, key, true);
310317 }
311318
312
- _leave(" = %p{%d}", server, atomic_read(&server->usage));
313319 return server;
314320 }
315321
....@@ -340,33 +346,117 @@
340346 }
341347
342348 /*
349
+ * Get a reference on a server object.
350
+ */
351
+struct afs_server *afs_get_server(struct afs_server *server,
352
+ enum afs_server_trace reason)
353
+{
354
+ unsigned int u = atomic_inc_return(&server->ref);
355
+
356
+ trace_afs_server(server, u, atomic_read(&server->active), reason);
357
+ return server;
358
+}
359
+
360
+/*
361
+ * Try to get a reference on a server object.
362
+ */
363
+static struct afs_server *afs_maybe_use_server(struct afs_server *server,
364
+ enum afs_server_trace reason)
365
+{
366
+ unsigned int r = atomic_fetch_add_unless(&server->ref, 1, 0);
367
+ unsigned int a;
368
+
369
+ if (r == 0)
370
+ return NULL;
371
+
372
+ a = atomic_inc_return(&server->active);
373
+ trace_afs_server(server, r, a, reason);
374
+ return server;
375
+}
376
+
377
+/*
378
+ * Get an active count on a server object.
379
+ */
380
+struct afs_server *afs_use_server(struct afs_server *server, enum afs_server_trace reason)
381
+{
382
+ unsigned int r = atomic_inc_return(&server->ref);
383
+ unsigned int a = atomic_inc_return(&server->active);
384
+
385
+ trace_afs_server(server, r, a, reason);
386
+ return server;
387
+}
388
+
389
+/*
343390 * Release a reference on a server record.
344391 */
345
-void afs_put_server(struct afs_net *net, struct afs_server *server)
392
+void afs_put_server(struct afs_net *net, struct afs_server *server,
393
+ enum afs_server_trace reason)
346394 {
347395 unsigned int usage;
348396
349397 if (!server)
350398 return;
351399
352
- server->put_time = ktime_get_real_seconds();
400
+ usage = atomic_dec_return(&server->ref);
401
+ trace_afs_server(server, usage, atomic_read(&server->active), reason);
402
+ if (unlikely(usage == 0))
403
+ __afs_put_server(net, server);
404
+}
353405
354
- usage = atomic_dec_return(&server->usage);
406
+/*
407
+ * Drop an active count on a server object without updating the last-unused
408
+ * time.
409
+ */
410
+void afs_unuse_server_notime(struct afs_net *net, struct afs_server *server,
411
+ enum afs_server_trace reason)
412
+{
413
+ if (server) {
414
+ unsigned int active = atomic_dec_return(&server->active);
355415
356
- _enter("{%u}", usage);
416
+ if (active == 0)
417
+ afs_set_server_timer(net, afs_server_gc_delay);
418
+ afs_put_server(net, server, reason);
419
+ }
420
+}
357421
358
- if (likely(usage > 0))
359
- return;
360
-
361
- afs_set_server_timer(net, afs_server_gc_delay);
422
+/*
423
+ * Drop an active count on a server object.
424
+ */
425
+void afs_unuse_server(struct afs_net *net, struct afs_server *server,
426
+ enum afs_server_trace reason)
427
+{
428
+ if (server) {
429
+ server->unuse_time = ktime_get_real_seconds();
430
+ afs_unuse_server_notime(net, server, reason);
431
+ }
362432 }
363433
364434 static void afs_server_rcu(struct rcu_head *rcu)
365435 {
366436 struct afs_server *server = container_of(rcu, struct afs_server, rcu);
367437
438
+ trace_afs_server(server, atomic_read(&server->ref),
439
+ atomic_read(&server->active), afs_server_trace_free);
368440 afs_put_addrlist(rcu_access_pointer(server->addresses));
369441 kfree(server);
442
+}
443
+
444
+static void __afs_put_server(struct afs_net *net, struct afs_server *server)
445
+{
446
+ call_rcu(&server->rcu, afs_server_rcu);
447
+ afs_dec_servers_outstanding(net);
448
+}
449
+
450
+static void afs_give_up_callbacks(struct afs_net *net, struct afs_server *server)
451
+{
452
+ struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
453
+ struct afs_addr_cursor ac = {
454
+ .alist = alist,
455
+ .index = alist->preferred,
456
+ .error = 0,
457
+ };
458
+
459
+ afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
370460 }
371461
372462 /*
....@@ -374,21 +464,10 @@
374464 */
375465 static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
376466 {
377
- struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
378
- struct afs_addr_cursor ac = {
379
- .alist = alist,
380
- .start = alist->index,
381
- .index = 0,
382
- .addr = &alist->addrs[alist->index],
383
- .error = 0,
384
- };
385
- _enter("%p", server);
386
-
387467 if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
388
- afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
468
+ afs_give_up_callbacks(net, server);
389469
390
- call_rcu(&server->rcu, afs_server_rcu);
391
- afs_dec_servers_outstanding(net);
470
+ afs_put_server(net, server, afs_server_trace_destroy);
392471 }
393472
394473 /*
....@@ -396,31 +475,49 @@
396475 */
397476 static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
398477 {
399
- struct afs_server *server;
400
- bool deleted;
401
- int usage;
478
+ struct afs_server *server, *next, *prev;
479
+ int active;
402480
403481 while ((server = gc_list)) {
404482 gc_list = server->gc_next;
405483
406484 write_seqlock(&net->fs_lock);
407
- usage = 1;
408
- deleted = atomic_try_cmpxchg(&server->usage, &usage, 0);
409
- if (deleted) {
410
- rb_erase(&server->uuid_rb, &net->fs_servers);
411
- hlist_del_rcu(&server->proc_link);
412
- }
413
- write_sequnlock(&net->fs_lock);
414485
415
- if (deleted) {
416
- write_seqlock(&net->fs_addr_lock);
486
+ active = atomic_read(&server->active);
487
+ if (active == 0) {
488
+ trace_afs_server(server, atomic_read(&server->ref),
489
+ active, afs_server_trace_gc);
490
+ next = rcu_dereference_protected(
491
+ server->uuid_next, lockdep_is_held(&net->fs_lock.lock));
492
+ prev = server->uuid_prev;
493
+ if (!prev) {
494
+ /* The one at the front is in the tree */
495
+ if (!next) {
496
+ rb_erase(&server->uuid_rb, &net->fs_servers);
497
+ } else {
498
+ rb_replace_node_rcu(&server->uuid_rb,
499
+ &next->uuid_rb,
500
+ &net->fs_servers);
501
+ next->uuid_prev = NULL;
502
+ }
503
+ } else {
504
+ /* This server is not at the front */
505
+ rcu_assign_pointer(prev->uuid_next, next);
506
+ if (next)
507
+ next->uuid_prev = prev;
508
+ }
509
+
510
+ list_del(&server->probe_link);
511
+ hlist_del_rcu(&server->proc_link);
417512 if (!hlist_unhashed(&server->addr4_link))
418513 hlist_del_rcu(&server->addr4_link);
419514 if (!hlist_unhashed(&server->addr6_link))
420515 hlist_del_rcu(&server->addr6_link);
421
- write_sequnlock(&net->fs_addr_lock);
422
- afs_destroy_server(net, server);
423516 }
517
+ write_sequnlock(&net->fs_lock);
518
+
519
+ if (active == 0)
520
+ afs_destroy_server(net, server);
424521 }
425522 }
426523
....@@ -449,15 +546,19 @@
449546 for (cursor = rb_first(&net->fs_servers); cursor; cursor = rb_next(cursor)) {
450547 struct afs_server *server =
451548 rb_entry(cursor, struct afs_server, uuid_rb);
452
- int usage = atomic_read(&server->usage);
549
+ int active = atomic_read(&server->active);
453550
454
- _debug("manage %pU %u", &server->uuid, usage);
551
+ _debug("manage %pU %u", &server->uuid, active);
455552
456
- ASSERTCMP(usage, >=, 1);
457
- ASSERTIFCMP(purging, usage, ==, 1);
553
+ if (purging) {
554
+ trace_afs_server(server, atomic_read(&server->ref),
555
+ active, afs_server_trace_purging);
556
+ if (active != 0)
557
+ pr_notice("Can't purge s=%08x\n", server->debug_id);
558
+ }
458559
459
- if (usage == 1) {
460
- time64_t expire_at = server->put_time;
560
+ if (active == 0) {
561
+ time64_t expire_at = server->unuse_time;
461562
462563 if (!test_bit(AFS_SERVER_FL_VL_FAIL, &server->flags) &&
463564 !test_bit(AFS_SERVER_FL_NOT_FOUND, &server->flags))
....@@ -509,123 +610,41 @@
509610 _enter("");
510611
511612 if (del_timer_sync(&net->fs_timer))
512
- atomic_dec(&net->servers_outstanding);
613
+ afs_dec_servers_outstanding(net);
513614
514615 afs_queue_server_manager(net);
515616
516617 _debug("wait");
618
+ atomic_dec(&net->servers_outstanding);
517619 wait_var_event(&net->servers_outstanding,
518620 !atomic_read(&net->servers_outstanding));
519621 _leave("");
520622 }
521623
522624 /*
523
- * Probe a fileserver to find its capabilities.
524
- *
525
- * TODO: Try service upgrade.
526
- */
527
-static bool afs_do_probe_fileserver(struct afs_fs_cursor *fc)
528
-{
529
- _enter("");
530
-
531
- fc->ac.addr = NULL;
532
- fc->ac.start = READ_ONCE(fc->ac.alist->index);
533
- fc->ac.index = fc->ac.start;
534
- fc->ac.error = 0;
535
- fc->ac.begun = false;
536
-
537
- while (afs_iterate_addresses(&fc->ac)) {
538
- afs_fs_get_capabilities(afs_v2net(fc->vnode), fc->cbi->server,
539
- &fc->ac, fc->key);
540
- switch (fc->ac.error) {
541
- case 0:
542
- afs_end_cursor(&fc->ac);
543
- set_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags);
544
- return true;
545
- case -ECONNABORTED:
546
- fc->ac.error = afs_abort_to_error(fc->ac.abort_code);
547
- goto error;
548
- case -ENOMEM:
549
- case -ENONET:
550
- goto error;
551
- case -ENETUNREACH:
552
- case -EHOSTUNREACH:
553
- case -ECONNREFUSED:
554
- case -ETIMEDOUT:
555
- case -ETIME:
556
- break;
557
- default:
558
- fc->ac.error = -EIO;
559
- goto error;
560
- }
561
- }
562
-
563
-error:
564
- afs_end_cursor(&fc->ac);
565
- return false;
566
-}
567
-
568
-/*
569
- * If we haven't already, try probing the fileserver to get its capabilities.
570
- * We try not to instigate parallel probes, but it's possible that the parallel
571
- * probes will fail due to authentication failure when ours would succeed.
572
- *
573
- * TODO: Try sending an anonymous probe if an authenticated probe fails.
574
- */
575
-bool afs_probe_fileserver(struct afs_fs_cursor *fc)
576
-{
577
- bool success;
578
- int ret, retries = 0;
579
-
580
- _enter("");
581
-
582
-retry:
583
- if (test_bit(AFS_SERVER_FL_PROBED, &fc->cbi->server->flags)) {
584
- _leave(" = t");
585
- return true;
586
- }
587
-
588
- if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags)) {
589
- success = afs_do_probe_fileserver(fc);
590
- clear_bit_unlock(AFS_SERVER_FL_PROBING, &fc->cbi->server->flags);
591
- wake_up_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING);
592
- _leave(" = t");
593
- return success;
594
- }
595
-
596
- _debug("wait");
597
- ret = wait_on_bit(&fc->cbi->server->flags, AFS_SERVER_FL_PROBING,
598
- TASK_INTERRUPTIBLE);
599
- if (ret == -ERESTARTSYS) {
600
- fc->ac.error = ret;
601
- _leave(" = f [%d]", ret);
602
- return false;
603
- }
604
-
605
- retries++;
606
- if (retries == 4) {
607
- fc->ac.error = -ESTALE;
608
- _leave(" = f [stale]");
609
- return false;
610
- }
611
- _debug("retry");
612
- goto retry;
613
-}
614
-
615
-/*
616625 * Get an update for a server's address list.
617626 */
618
-static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct afs_server *server)
627
+static noinline bool afs_update_server_record(struct afs_operation *op,
628
+ struct afs_server *server)
619629 {
620630 struct afs_addr_list *alist, *discard;
621631
622632 _enter("");
623633
624
- alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key,
625
- &server->uuid);
634
+ trace_afs_server(server, atomic_read(&server->ref), atomic_read(&server->active),
635
+ afs_server_trace_update);
636
+
637
+ alist = afs_vl_lookup_addrs(op->volume->cell, op->key, &server->uuid);
626638 if (IS_ERR(alist)) {
627
- fc->ac.error = PTR_ERR(alist);
628
- _leave(" = f [%d]", fc->ac.error);
639
+ if ((PTR_ERR(alist) == -ERESTARTSYS ||
640
+ PTR_ERR(alist) == -EINTR) &&
641
+ (op->flags & AFS_OPERATION_UNINTR) &&
642
+ server->addresses) {
643
+ _leave(" = t [intr]");
644
+ return true;
645
+ }
646
+ op->error = PTR_ERR(alist);
647
+ _leave(" = f [%d]", op->error);
629648 return false;
630649 }
631650
....@@ -639,7 +658,6 @@
639658 write_unlock(&server->fs_lock);
640659 }
641660
642
- server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
643661 afs_put_addrlist(discard);
644662 _leave(" = t");
645663 return true;
....@@ -648,10 +666,8 @@
648666 /*
649667 * See if a server's address list needs updating.
650668 */
651
-bool afs_check_server_record(struct afs_fs_cursor *fc, struct afs_server *server)
669
+bool afs_check_server_record(struct afs_operation *op, struct afs_server *server)
652670 {
653
- time64_t now = ktime_get_real_seconds();
654
- long diff;
655671 bool success;
656672 int ret, retries = 0;
657673
....@@ -660,24 +676,29 @@
660676 ASSERT(server);
661677
662678 retry:
663
- diff = READ_ONCE(server->update_at) - now;
664
- if (diff > 0) {
665
- _leave(" = t [not now %ld]", diff);
666
- return true;
667
- }
679
+ if (test_bit(AFS_SERVER_FL_UPDATING, &server->flags))
680
+ goto wait;
681
+ if (test_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags))
682
+ goto update;
683
+ _leave(" = t [good]");
684
+ return true;
668685
686
+update:
669687 if (!test_and_set_bit_lock(AFS_SERVER_FL_UPDATING, &server->flags)) {
670
- success = afs_update_server_record(fc, server);
688
+ clear_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags);
689
+ success = afs_update_server_record(op, server);
671690 clear_bit_unlock(AFS_SERVER_FL_UPDATING, &server->flags);
672691 wake_up_bit(&server->flags, AFS_SERVER_FL_UPDATING);
673692 _leave(" = %d", success);
674693 return success;
675694 }
676695
696
+wait:
677697 ret = wait_on_bit(&server->flags, AFS_SERVER_FL_UPDATING,
678
- TASK_INTERRUPTIBLE);
698
+ (op->flags & AFS_OPERATION_UNINTR) ?
699
+ TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
679700 if (ret == -ERESTARTSYS) {
680
- fc->ac.error = ret;
701
+ op->error = ret;
681702 _leave(" = f [intr]");
682703 return false;
683704 }