aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/cell.c169
-rw-r--r--fs/afs/internal.h10
-rw-r--r--fs/afs/vl_rotate.c26
3 files changed, 130 insertions, 75 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 47f96be05163..9c3b07ba2222 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -152,8 +152,6 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
152 152
153 atomic_set(&cell->usage, 2); 153 atomic_set(&cell->usage, 2);
154 INIT_WORK(&cell->manager, afs_manage_cell); 154 INIT_WORK(&cell->manager, afs_manage_cell);
155 cell->flags = ((1 << AFS_CELL_FL_NOT_READY) |
156 (1 << AFS_CELL_FL_NO_LOOKUP_YET));
157 INIT_LIST_HEAD(&cell->proc_volumes); 155 INIT_LIST_HEAD(&cell->proc_volumes);
158 rwlock_init(&cell->proc_lock); 156 rwlock_init(&cell->proc_lock);
159 rwlock_init(&cell->vl_servers_lock); 157 rwlock_init(&cell->vl_servers_lock);
@@ -170,17 +168,25 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
170 goto parse_failed; 168 goto parse_failed;
171 } 169 }
172 170
171 vllist->source = DNS_RECORD_FROM_CONFIG;
172 vllist->status = DNS_LOOKUP_NOT_DONE;
173 cell->dns_expiry = TIME64_MAX; 173 cell->dns_expiry = TIME64_MAX;
174 } else { 174 } else {
175 ret = -ENOMEM; 175 ret = -ENOMEM;
176 vllist = afs_alloc_vlserver_list(0); 176 vllist = afs_alloc_vlserver_list(0);
177 if (!vllist) 177 if (!vllist)
178 goto error; 178 goto error;
179 vllist->source = DNS_RECORD_UNAVAILABLE;
180 vllist->status = DNS_LOOKUP_NOT_DONE;
179 cell->dns_expiry = ktime_get_real_seconds(); 181 cell->dns_expiry = ktime_get_real_seconds();
180 } 182 }
181 183
182 rcu_assign_pointer(cell->vl_servers, vllist); 184 rcu_assign_pointer(cell->vl_servers, vllist);
183 185
186 cell->dns_source = vllist->source;
187 cell->dns_status = vllist->status;
188 smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
189
184 _leave(" = %p", cell); 190 _leave(" = %p", cell);
185 return cell; 191 return cell;
186 192
@@ -212,6 +218,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
212{ 218{
213 struct afs_cell *cell, *candidate, *cursor; 219 struct afs_cell *cell, *candidate, *cursor;
214 struct rb_node *parent, **pp; 220 struct rb_node *parent, **pp;
221 enum afs_cell_state state;
215 int ret, n; 222 int ret, n;
216 223
217 _enter("%s,%s", name, vllist); 224 _enter("%s,%s", name, vllist);
@@ -271,18 +278,16 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
271 278
272wait_for_cell: 279wait_for_cell:
273 _debug("wait_for_cell"); 280 _debug("wait_for_cell");
274 ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NOT_READY, TASK_INTERRUPTIBLE); 281 wait_var_event(&cell->state,
275 smp_rmb(); 282 ({
276 283 state = smp_load_acquire(&cell->state); /* vs error */
277 switch (READ_ONCE(cell->state)) { 284 state == AFS_CELL_ACTIVE || state == AFS_CELL_FAILED;
278 case AFS_CELL_FAILED: 285 }));
286
287 /* Check the state obtained from the wait check. */
288 if (state == AFS_CELL_FAILED) {
279 ret = cell->error; 289 ret = cell->error;
280 goto error; 290 goto error;
281 default:
282 _debug("weird %u %d", cell->state, cell->error);
283 goto error;
284 case AFS_CELL_ACTIVE:
285 break;
286 } 291 }
287 292
288 _leave(" = %p [cell]", cell); 293 _leave(" = %p [cell]", cell);
@@ -364,16 +369,46 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
364/* 369/*
365 * Update a cell's VL server address list from the DNS. 370 * Update a cell's VL server address list from the DNS.
366 */ 371 */
367static void afs_update_cell(struct afs_cell *cell) 372static int afs_update_cell(struct afs_cell *cell)
368{ 373{
369 struct afs_vlserver_list *vllist, *old; 374 struct afs_vlserver_list *vllist, *old = NULL, *p;
370 unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl); 375 unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
371 unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl); 376 unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
372 time64_t now, expiry = 0; 377 time64_t now, expiry = 0;
378 int ret = 0;
373 379
374 _enter("%s", cell->name); 380 _enter("%s", cell->name);
375 381
376 vllist = afs_dns_query(cell, &expiry); 382 vllist = afs_dns_query(cell, &expiry);
383 if (IS_ERR(vllist)) {
384 ret = PTR_ERR(vllist);
385
386 _debug("%s: fail %d", cell->name, ret);
387 if (ret == -ENOMEM)
388 goto out_wake;
389
390 ret = -ENOMEM;
391 vllist = afs_alloc_vlserver_list(0);
392 if (!vllist)
393 goto out_wake;
394
395 switch (ret) {
396 case -ENODATA:
397 case -EDESTADDRREQ:
398 vllist->status = DNS_LOOKUP_GOT_NOT_FOUND;
399 break;
400 case -EAGAIN:
401 case -ECONNREFUSED:
402 vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE;
403 break;
404 default:
405 vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE;
406 break;
407 }
408 }
409
410 _debug("%s: got list %d %d", cell->name, vllist->source, vllist->status);
411 cell->dns_status = vllist->status;
377 412
378 now = ktime_get_real_seconds(); 413 now = ktime_get_real_seconds();
379 if (min_ttl > max_ttl) 414 if (min_ttl > max_ttl)
@@ -383,46 +418,47 @@ static void afs_update_cell(struct afs_cell *cell)
383 else if (expiry > now + max_ttl) 418 else if (expiry > now + max_ttl)
384 expiry = now + max_ttl; 419 expiry = now + max_ttl;
385 420
386 if (IS_ERR(vllist)) { 421 _debug("%s: status %d", cell->name, vllist->status);
387 switch (PTR_ERR(vllist)) { 422 if (vllist->source == DNS_RECORD_UNAVAILABLE) {
388 case -ENODATA: 423 switch (vllist->status) {
389 case -EDESTADDRREQ: 424 case DNS_LOOKUP_GOT_NOT_FOUND:
390 /* The DNS said that the cell does not exist or there 425 /* The DNS said that the cell does not exist or there
391 * weren't any addresses to be had. 426 * weren't any addresses to be had.
392 */ 427 */
393 set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
394 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
395 cell->dns_expiry = expiry; 428 cell->dns_expiry = expiry;
396 break; 429 break;
397 430
398 case -EAGAIN: 431 case DNS_LOOKUP_BAD:
399 case -ECONNREFUSED: 432 case DNS_LOOKUP_GOT_LOCAL_FAILURE:
433 case DNS_LOOKUP_GOT_TEMP_FAILURE:
434 case DNS_LOOKUP_GOT_NS_FAILURE:
400 default: 435 default:
401 set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
402 cell->dns_expiry = now + 10; 436 cell->dns_expiry = now + 10;
403 break; 437 break;
404 } 438 }
405
406 cell->error = -EDESTADDRREQ;
407 } else { 439 } else {
408 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
409 clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
410
411 write_lock(&cell->vl_servers_lock);
412 old = rcu_dereference_protected(cell->vl_servers, true);
413 rcu_assign_pointer(cell->vl_servers, vllist);
414 cell->dns_expiry = expiry; 440 cell->dns_expiry = expiry;
415 write_unlock(&cell->vl_servers_lock);
416
417 afs_put_vlserverlist(cell->net, old);
418 } 441 }
419 442
420 if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags)) 443 /* Replace the VL server list if the new record has servers or the old
421 wake_up_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET); 444 * record doesn't.
445 */
446 write_lock(&cell->vl_servers_lock);
447 p = rcu_dereference_protected(cell->vl_servers, true);
448 if (vllist->nr_servers > 0 || p->nr_servers == 0) {
449 rcu_assign_pointer(cell->vl_servers, vllist);
450 cell->dns_source = vllist->source;
451 old = p;
452 }
453 write_unlock(&cell->vl_servers_lock);
454 afs_put_vlserverlist(cell->net, old);
422 455
423 now = ktime_get_real_seconds(); 456out_wake:
424 afs_set_cell_timer(cell->net, cell->dns_expiry - now); 457 smp_store_release(&cell->dns_lookup_count,
425 _leave(""); 458 cell->dns_lookup_count + 1); /* vs source/status */
459 wake_up_var(&cell->dns_lookup_count);
460 _leave(" = %d", ret);
461 return ret;
426} 462}
427 463
428/* 464/*
@@ -493,8 +529,7 @@ void afs_put_cell(struct afs_net *net, struct afs_cell *cell)
493 now = ktime_get_real_seconds(); 529 now = ktime_get_real_seconds();
494 cell->last_inactive = now; 530 cell->last_inactive = now;
495 expire_delay = 0; 531 expire_delay = 0;
496 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) && 532 if (cell->vl_servers->nr_servers)
497 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
498 expire_delay = afs_cell_gc_delay; 533 expire_delay = afs_cell_gc_delay;
499 534
500 if (atomic_dec_return(&cell->usage) > 1) 535 if (atomic_dec_return(&cell->usage) > 1)
@@ -625,11 +660,13 @@ again:
625 goto final_destruction; 660 goto final_destruction;
626 if (cell->state == AFS_CELL_FAILED) 661 if (cell->state == AFS_CELL_FAILED)
627 goto done; 662 goto done;
628 cell->state = AFS_CELL_UNSET; 663 smp_store_release(&cell->state, AFS_CELL_UNSET);
664 wake_up_var(&cell->state);
629 goto again; 665 goto again;
630 666
631 case AFS_CELL_UNSET: 667 case AFS_CELL_UNSET:
632 cell->state = AFS_CELL_ACTIVATING; 668 smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
669 wake_up_var(&cell->state);
633 goto again; 670 goto again;
634 671
635 case AFS_CELL_ACTIVATING: 672 case AFS_CELL_ACTIVATING:
@@ -637,28 +674,29 @@ again:
637 if (ret < 0) 674 if (ret < 0)
638 goto activation_failed; 675 goto activation_failed;
639 676
640 cell->state = AFS_CELL_ACTIVE; 677 smp_store_release(&cell->state, AFS_CELL_ACTIVE);
641 smp_wmb(); 678 wake_up_var(&cell->state);
642 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
643 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
644 goto again; 679 goto again;
645 680
646 case AFS_CELL_ACTIVE: 681 case AFS_CELL_ACTIVE:
647 if (atomic_read(&cell->usage) > 1) { 682 if (atomic_read(&cell->usage) > 1) {
648 time64_t now = ktime_get_real_seconds(); 683 if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
649 if (cell->dns_expiry <= now && net->live) 684 ret = afs_update_cell(cell);
650 afs_update_cell(cell); 685 if (ret < 0)
686 cell->error = ret;
687 }
651 goto done; 688 goto done;
652 } 689 }
653 cell->state = AFS_CELL_DEACTIVATING; 690 smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
691 wake_up_var(&cell->state);
654 goto again; 692 goto again;
655 693
656 case AFS_CELL_DEACTIVATING: 694 case AFS_CELL_DEACTIVATING:
657 set_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
658 if (atomic_read(&cell->usage) > 1) 695 if (atomic_read(&cell->usage) > 1)
659 goto reverse_deactivation; 696 goto reverse_deactivation;
660 afs_deactivate_cell(net, cell); 697 afs_deactivate_cell(net, cell);
661 cell->state = AFS_CELL_INACTIVE; 698 smp_store_release(&cell->state, AFS_CELL_INACTIVE);
699 wake_up_var(&cell->state);
662 goto again; 700 goto again;
663 701
664 default: 702 default:
@@ -671,17 +709,13 @@ activation_failed:
671 cell->error = ret; 709 cell->error = ret;
672 afs_deactivate_cell(net, cell); 710 afs_deactivate_cell(net, cell);
673 711
674 cell->state = AFS_CELL_FAILED; 712 smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
675 smp_wmb(); 713 wake_up_var(&cell->state);
676 if (test_and_clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags))
677 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
678 goto again; 714 goto again;
679 715
680reverse_deactivation: 716reverse_deactivation:
681 cell->state = AFS_CELL_ACTIVE; 717 smp_store_release(&cell->state, AFS_CELL_ACTIVE);
682 smp_wmb(); 718 wake_up_var(&cell->state);
683 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
684 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
685 _leave(" [deact->act]"); 719 _leave(" [deact->act]");
686 return; 720 return;
687 721
@@ -741,11 +775,16 @@ void afs_manage_cells(struct work_struct *work)
741 } 775 }
742 776
743 if (usage == 1) { 777 if (usage == 1) {
778 struct afs_vlserver_list *vllist;
744 time64_t expire_at = cell->last_inactive; 779 time64_t expire_at = cell->last_inactive;
745 780
746 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) && 781 read_lock(&cell->vl_servers_lock);
747 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags)) 782 vllist = rcu_dereference_protected(
783 cell->vl_servers,
784 lockdep_is_held(&cell->vl_servers_lock));
785 if (vllist->nr_servers > 0)
748 expire_at += afs_cell_gc_delay; 786 expire_at += afs_cell_gc_delay;
787 read_unlock(&cell->vl_servers_lock);
749 if (purging || expire_at <= now) 788 if (purging || expire_at <= now)
750 sched_cell = true; 789 sched_cell = true;
751 else if (expire_at < next_manage) 790 else if (expire_at < next_manage)
@@ -753,10 +792,8 @@ void afs_manage_cells(struct work_struct *work)
753 } 792 }
754 793
755 if (!purging) { 794 if (!purging) {
756 if (cell->dns_expiry <= now) 795 if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
757 sched_cell = true; 796 sched_cell = true;
758 else if (cell->dns_expiry <= next_manage)
759 next_manage = cell->dns_expiry;
760 } 797 }
761 798
762 if (sched_cell) 799 if (sched_cell)
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 74ee0f8ef8dd..50d925f0a556 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -367,13 +367,13 @@ struct afs_cell {
367 time64_t last_inactive; /* Time of last drop of usage count */ 367 time64_t last_inactive; /* Time of last drop of usage count */
368 atomic_t usage; 368 atomic_t usage;
369 unsigned long flags; 369 unsigned long flags;
370#define AFS_CELL_FL_NOT_READY 0 /* The cell record is not ready for use */ 370#define AFS_CELL_FL_NO_GC 0 /* The cell was added manually, don't auto-gc */
371#define AFS_CELL_FL_NO_GC 1 /* The cell was added manually, don't auto-gc */ 371#define AFS_CELL_FL_DO_LOOKUP 1 /* DNS lookup requested */
372#define AFS_CELL_FL_NOT_FOUND 2 /* Permanent DNS error */
373#define AFS_CELL_FL_DNS_FAIL 3 /* Failed to access DNS */
374#define AFS_CELL_FL_NO_LOOKUP_YET 4 /* Not completed first DNS lookup yet */
375 enum afs_cell_state state; 372 enum afs_cell_state state;
376 short error; 373 short error;
374 enum dns_record_source dns_source:8; /* Latest source of data from lookup */
375 enum dns_lookup_status dns_status:8; /* Latest status of data from lookup */
376 unsigned int dns_lookup_count; /* Counter of DNS lookups */
377 377
378 /* Active fileserver interaction state. */ 378 /* Active fileserver interaction state. */
379 struct list_head proc_volumes; /* procfs volume list */ 379 struct list_head proc_volumes; /* procfs volume list */
diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c
index 65629d73ad9d..3f845489a9f0 100644
--- a/fs/afs/vl_rotate.c
+++ b/fs/afs/vl_rotate.c
@@ -43,11 +43,29 @@ bool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cel
43static bool afs_start_vl_iteration(struct afs_vl_cursor *vc) 43static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
44{ 44{
45 struct afs_cell *cell = vc->cell; 45 struct afs_cell *cell = vc->cell;
46 unsigned int dns_lookup_count;
47
48 if (cell->dns_source == DNS_RECORD_UNAVAILABLE ||
49 cell->dns_expiry <= ktime_get_real_seconds()) {
50 dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
51 set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
52 queue_work(afs_wq, &cell->manager);
53
54 if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
55 if (wait_var_event_interruptible(
56 &cell->dns_lookup_count,
57 smp_load_acquire(&cell->dns_lookup_count)
58 != dns_lookup_count) < 0) {
59 vc->error = -ERESTARTSYS;
60 return false;
61 }
62 }
46 63
47 if (wait_on_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET, 64 /* Status load is ordered after lookup counter load */
48 TASK_INTERRUPTIBLE)) { 65 if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
49 vc->error = -ERESTARTSYS; 66 vc->error = -EDESTADDRREQ;
50 return false; 67 return false;
68 }
51 } 69 }
52 70
53 read_lock(&cell->vl_servers_lock); 71 read_lock(&cell->vl_servers_lock);