History

afs: Simplify cell record handling

Simplify afs_cell record handling to avoid very occasional races that cause module removal to hang (it waits for all cell records to be removed). There are two things that particularly contribute to the difficulty: firstly, the code tries to pass a ref on the cell to the cell's maintenance work item (which gets awkward if the work item is already queued); and, secondly, there's an overall cell manager that tries to use just one timer for the entire cell collection (to avoid having loads of timers). However, both of these are probably unnecessarily restrictive. To simplify this, the following changes are made: (1) The cell record collection manager is removed. Each cell record manages itself individually. (2) Each afs_cell is given a second work item (cell->destroyer) that is queued when its refcount reaches zero. This is not done in the context of the putting thread as it might be in an inconvenient place to sleep. (3) Each afs_cell is given its own timer. The timer is used to expire the cell record after a period of unuse if not otherwise pinned and can also be used for other maintenance tasks if necessary (of which there are currently none as DNS refresh is triggered by filesystem operations). (4) The afs_cell manager work item (cell->manager) is no longer given a ref on the cell when queued; rather, the manager must be deleted. This does away with the need to deal with the consequences of losing a race to queue cell->manager. Clean up of extra queuing is deferred to the destroyer. (5) The cell destroyer work item makes sure the cell timer is removed and that the normal cell work is cancelled before farming the actual destruction off to RCU. (6) When a network namespace is destroyed or the kafs module is unloaded, it's now a simple matter of marking the namespace as dead then just waking up all the cell work items. They will then remove and destroy themselves once all remaining activity counts and/or a ref counts are dropped. This makes sure that all server records are dropped first. (7) The cell record state set is reduced to just four states: SETTING_UP, ACTIVE, REMOVING and DEAD. The record persists in the active state even when it's not being used until the time comes to remove it rather than downgrading it to an inactive state from whence it can be restored. This means that the cell still appears in /proc and /afs when not in use until it switches to the REMOVING state - at which point it is removed. Note that the REMOVING state is included so that someone wanting to resurrect the cell record is forced to wait whilst the cell is torn down in that state. Once it's in the DEAD state, it has been removed from net->cells tree and is no longer findable and can be replaced.

David Howells committed 1 year ago

Commit e2c2cb81 parent 4882ba77 files · +187 −273Browse files

Unified · Split

7 files
  1. fs/afs/cell.c +163 −241
  2. fs/afs/dynroot.c +2 −2
  3. fs/afs/internal.h +6 −10
  4. fs/afs/main.c +0 −3
  5. fs/afs/server.c +4 −4
  6. fs/afs/vl_rotate.c +1 −1
  7. include/trace/events/afs.h +11 −12
fs/afs/cell.c+163−241
@@ -20,8 +20,9 @@ static unsigned __read_mostly afs_cell_min_ttl = 10 * 60; · 19 unmodified lines
2020 static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
2121 static atomic_t cell_debug_id;
2222
23−static void afs_queue_cell_manager(struct afs_net *);
24−static void afs_manage_cell_work(struct work_struct *);
23+static void afs_cell_timer(struct timer_list *timer);
24+static void afs_destroy_cell_work(struct work_struct *work);
25+static void afs_manage_cell_work(struct work_struct *work);
2526
2627 static void afs_dec_cells_outstanding(struct afs_net *net)
2728 {
@@ -29,19 +30,11 @@ static void afs_dec_cells_outstanding(struct afs_net *net) · 1 unmodified line
2930 wake_up_var(&net->cells_outstanding);
3031 }
3132
32−/*
33− * Set the cell timer to fire after a given delay, assuming it's not already
34− * set for an earlier time.
35− */
36−static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
33+static void afs_set_cell_state(struct afs_cell *cell, enum afs_cell_state state)
3734 {
38− if (net->live) {
39− atomic_inc(&net->cells_outstanding);
40− if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
41− afs_dec_cells_outstanding(net);
42− } else {
43− afs_queue_cell_manager(net);
44− }
35+ smp_store_release(&cell->state, state); /* Commit cell changes before state */
36+ smp_wmb(); /* Set cell state before task state */
37+ wake_up_var(&cell->state);
4538 }
4639
4740 /*
@@ -116,7 +109,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, · 68 unmodified lines
116109 const char *name, unsigned int namelen,
117110 const char *addresses)
118111 {
119− struct afs_vlserver_list *vllist;
112+ struct afs_vlserver_list *vllist = NULL;
120113 struct afs_cell *cell;
121114 int i, ret;
122115
@@ -163,7 +156,9 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, · 40 unmodified lines
163156 cell->net = net;
164157 refcount_set(&cell->ref, 1);
165158 atomic_set(&cell->active, 0);
159+ INIT_WORK(&cell->destroyer, afs_destroy_cell_work);
166160 INIT_WORK(&cell->manager, afs_manage_cell_work);
161+ timer_setup(&cell->management_timer, afs_cell_timer, 0);
167162 init_rwsem(&cell->vs_lock);
168163 cell->volumes = RB_ROOT;
169164 INIT_HLIST_HEAD(&cell->proc_volumes);
@@ -220,6 +215,7 @@ parse_failed: · 50 unmodified lines
220215 if (ret == -EINVAL)
221216 printk(KERN_ERR "kAFS: bad VL server IP address\n");
222217 error:
218+ afs_put_vlserverlist(cell->net, vllist);
223219 kfree(cell->name - 1);
224220 kfree(cell);
225221 _leave(" = %d", ret);
@@ -296,26 +292,28 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net, · 70 unmodified lines
296292
297293 cell = candidate;
298294 candidate = NULL;
299− atomic_set(&cell->active, 2);
300− trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 2, afs_cell_trace_insert);
295+ afs_use_cell(cell, trace);
301296 rb_link_node_rcu(&cell->net_node, parent, pp);
302297 rb_insert_color(&cell->net_node, &net->cells);
303298 up_write(&net->cells_lock);
304299
305− afs_queue_cell(cell, afs_cell_trace_get_queue_new);
300+ afs_queue_cell(cell, afs_cell_trace_queue_new);
306301
307302 wait_for_cell:
308− trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), atomic_read(&cell->active),
309− afs_cell_trace_wait);
310303 _debug("wait_for_cell");
311− wait_var_event(&cell->state,
312− ({
313− state = smp_load_acquire(&cell->state); /* vs error */
314− state == AFS_CELL_ACTIVE || state == AFS_CELL_REMOVED;
315− }));
304+ state = smp_load_acquire(&cell->state); /* vs error */
305+ if (state != AFS_CELL_ACTIVE &&
306+ state != AFS_CELL_DEAD) {
307+ afs_see_cell(cell, afs_cell_trace_wait);
308+ wait_var_event(&cell->state,
309+ ({
310+ state = smp_load_acquire(&cell->state); /* vs error */
311+ state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
312+ }));
313+ }
316314
317315 /* Check the state obtained from the wait check. */
318− if (state == AFS_CELL_REMOVED) {
316+ if (state == AFS_CELL_DEAD) {
319317 ret = cell->error;
320318 goto error;
321319 }
@@ -397,7 +395,6 @@ int afs_cell_init(struct afs_net *net, const char *rootcell) · 75 unmodified lines
397395
398396 /* install the new cell */
399397 down_write(&net->cells_lock);
400− afs_see_cell(new_root, afs_cell_trace_see_ws);
401398 old_root = rcu_replace_pointer(net->ws_cell, new_root,
402399 lockdep_is_held(&net->cells_lock));
403400 up_write(&net->cells_lock);
@@ -530,30 +527,14 @@ static void afs_cell_destroy(struct rcu_head *rcu) · 126 unmodified lines
530527 _leave(" [destroyed]");
531528 }
532529
533−/*
534− * Queue the cell manager.
535− */
536−static void afs_queue_cell_manager(struct afs_net *net)
537−{
538− int outstanding = atomic_inc_return(&net->cells_outstanding);
539−
540− _enter("%d", outstanding);
541−
542− if (!queue_work(afs_wq, &net->cells_manager))
543− afs_dec_cells_outstanding(net);
544−}
545−
546−/*
547− * Cell management timer. We have an increment on cells_outstanding that we
548− * need to pass along to the work item.
549− */
550−void afs_cells_timer(struct timer_list *timer)
530+static void afs_destroy_cell_work(struct work_struct *work)
551531 {
552− struct afs_net *net = container_of(timer, struct afs_net, cells_timer);
532+ struct afs_cell *cell = container_of(work, struct afs_cell, destroyer);
553533
554− _enter("");
555− if (!queue_work(afs_wq, &net->cells_manager))
556− afs_dec_cells_outstanding(net);
534+ afs_see_cell(cell, afs_cell_trace_destroy);
535+ timer_delete_sync(&cell->management_timer);
536+ cancel_work_sync(&cell->manager);
537+ call_rcu(&cell->rcu, afs_cell_destroy);
557538 }
558539
559540 /*
@@ -585,7 +566,7 @@ void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason) · 25 unmodified lines
585566 if (zero) {
586567 a = atomic_read(&cell->active);
587568 WARN(a != 0, "Cell active count %u > 0\n", a);
588− call_rcu(&cell->rcu, afs_cell_destroy);
569+ WARN_ON(!queue_work(afs_wq, &cell->destroyer));
589570 }
590571 }
591572 }
@@ -597,10 +578,9 @@ struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason) · 5 unmodified lines
597578 {
598579 int r, a;
599580
600− r = refcount_read(&cell->ref);
601− WARN_ON(r == 0);
581+ __refcount_inc(&cell->ref, &r);
602582 a = atomic_inc_return(&cell->active);
603− trace_afs_cell(cell->debug_id, r, a, reason);
583+ trace_afs_cell(cell->debug_id, r + 1, a, reason);
604584 return cell;
605585 }
606586
@@ -612,6 +592,7 @@ void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason) · 5 unmodified lines
612592 {
613593 unsigned int debug_id;
614594 time64_t now, expire_delay;
595+ bool zero;
615596 int r, a;
616597
617598 if (!cell)
@@ -626,13 +607,15 @@ void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason) · 8 unmodified lines
626607 expire_delay = afs_cell_gc_delay;
627608
628609 debug_id = cell->debug_id;
629− r = refcount_read(&cell->ref);
630610 a = atomic_dec_return(&cell->active);
631− trace_afs_cell(debug_id, r, a, reason);
632− WARN_ON(a == 0);
633− if (a == 1)
611+ if (!a)
634612 /* 'cell' may now be garbage collected. */
635− afs_set_cell_timer(cell->net, expire_delay);
613+ afs_set_cell_timer(cell, expire_delay);
614+
615+ zero = __refcount_dec_and_test(&cell->ref, &r);
616+ trace_afs_cell(debug_id, r - 1, a, reason);
617+ if (zero)
618+ WARN_ON(!queue_work(afs_wq, &cell->destroyer));
636619 }
637620
638621 /*
@@ -652,9 +635,27 @@ void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason) · 13 unmodified lines
652635 */
653636 void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason)
654637 {
655− afs_get_cell(cell, reason);
656− if (!queue_work(afs_wq, &cell->manager))
657− afs_put_cell(cell, afs_cell_trace_put_queue_fail);
638+ queue_work(afs_wq, &cell->manager);
639+}
640+
641+/*
642+ * Cell-specific management timer.
643+ */
644+static void afs_cell_timer(struct timer_list *timer)
645+{
646+ struct afs_cell *cell = container_of(timer, struct afs_cell, management_timer);
647+
648+ afs_see_cell(cell, afs_cell_trace_see_mgmt_timer);
649+ if (refcount_read(&cell->ref) > 0 && cell->net->live)
650+ queue_work(afs_wq, &cell->manager);
651+}
652+
653+/*
654+ * Set/reduce the cell timer.
655+ */
656+void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs)
657+{
658+ timer_reduce(&cell->management_timer, jiffies + delay_secs * HZ);
658659 }
659660
660661 /*
@@ -737,212 +738,125 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell) · 76 unmodified lines
737738 _leave("");
738739 }
739740
741+static bool afs_has_cell_expired(struct afs_cell *cell, time64_t *_next_manage)
742+{
743+ const struct afs_vlserver_list *vllist;
744+ time64_t expire_at = cell->last_inactive;
745+ time64_t now = ktime_get_real_seconds();
746+
747+ if (atomic_read(&cell->active))
748+ return false;
749+ if (!cell->net->live)
750+ return true;
751+
752+ vllist = rcu_dereference_protected(cell->vl_servers, true);
753+ if (vllist && vllist->nr_servers > 0)
754+ expire_at += afs_cell_gc_delay;
755+
756+ if (expire_at <= now)
757+ return true;
758+ if (expire_at < *_next_manage)
759+ *_next_manage = expire_at;
760+ return false;
761+}
762+
740763 /*
741764 * Manage a cell record, initialising and destroying it, maintaining its DNS
742765 * records.
743766 */
744−static void afs_manage_cell(struct afs_cell *cell)
767+static bool afs_manage_cell(struct afs_cell *cell)
745768 {
746769 struct afs_net *net = cell->net;
747− int ret, active;
770+ time64_t next_manage = TIME64_MAX;
771+ int ret;
748772
749773 _enter("%s", cell->name);
750774
751−again:
752775 _debug("state %u", cell->state);
753776 switch (cell->state) {
754− case AFS_CELL_INACTIVE:
755− case AFS_CELL_FAILED:
756− down_write(&net->cells_lock);
757− active = 1;
758− if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) {
759− rb_erase(&cell->net_node, &net->cells);
760− trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 0,
761− afs_cell_trace_unuse_delete);
762− smp_store_release(&cell->state, AFS_CELL_REMOVED);
763− }
764− up_write(&net->cells_lock);
765− if (cell->state == AFS_CELL_REMOVED) {
766− wake_up_var(&cell->state);
767− goto final_destruction;
768− }
769− if (cell->state == AFS_CELL_FAILED)
770− goto done;
771− smp_store_release(&cell->state, AFS_CELL_UNSET);
772− wake_up_var(&cell->state);
773− goto again;
774−
775− case AFS_CELL_UNSET:
776− smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
777− wake_up_var(&cell->state);
778− goto again;
779−
780− case AFS_CELL_ACTIVATING:
781− ret = afs_activate_cell(net, cell);
782− if (ret < 0)
783− goto activation_failed;
777+ case AFS_CELL_SETTING_UP:
778+ goto set_up_cell;
779+ case AFS_CELL_ACTIVE:
780+ goto cell_is_active;
781+ case AFS_CELL_REMOVING:
782+ WARN_ON_ONCE(1);
783+ return false;
784+ case AFS_CELL_DEAD:
785+ return false;
786+ default:
787+ _debug("bad state %u", cell->state);
788+ WARN_ON_ONCE(1); /* Unhandled state */
789+ return false;
790+ }
784791
785− smp_store_release(&cell->state, AFS_CELL_ACTIVE);
786− wake_up_var(&cell->state);
787− goto again;
792+set_up_cell:
793+ ret = afs_activate_cell(net, cell);
794+ if (ret < 0) {
795+ cell->error = ret;
796+ goto remove_cell;
797+ }
788798
789− case AFS_CELL_ACTIVE:
790− if (atomic_read(&cell->active) > 1) {
791− if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
792− ret = afs_update_cell(cell);
793− if (ret < 0)
794− cell->error = ret;
795− }
796− goto done;
797− }
798− smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
799− wake_up_var(&cell->state);
800− goto again;
799+ afs_set_cell_state(cell, AFS_CELL_ACTIVE);
801800
802− case AFS_CELL_DEACTIVATING:
803− if (atomic_read(&cell->active) > 1)
804− goto reverse_deactivation;
805− afs_deactivate_cell(net, cell);
806− smp_store_release(&cell->state, AFS_CELL_INACTIVE);
807− wake_up_var(&cell->state);
808− goto again;
801+cell_is_active:
802+ if (afs_has_cell_expired(cell, &next_manage))
803+ goto remove_cell;
809804
810− case AFS_CELL_REMOVED:
811− goto done;
805+ if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
806+ ret = afs_update_cell(cell);
807+ if (ret < 0)
808+ cell->error = ret;
809+ }
812810
813− default:
814− break;
811+ if (next_manage < TIME64_MAX && cell->net->live) {
812+ time64_t now = ktime_get_real_seconds();
813+
814+ if (next_manage - now <= 0)
815+ afs_queue_cell(cell, afs_cell_trace_queue_again);
816+ else
817+ afs_set_cell_timer(cell, next_manage - now);
815818 }
816− _debug("bad state %u", cell->state);
817− BUG(); /* Unhandled state */
819+ _leave(" [done %u]", cell->state);
820+ return false;
818821
819−activation_failed:
820− cell->error = ret;
821− afs_deactivate_cell(net, cell);
822+remove_cell:
823+ down_write(&net->cells_lock);
822824
823− smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
824− wake_up_var(&cell->state);
825− goto again;
825+ if (atomic_read(&cell->active)) {
826+ up_write(&net->cells_lock);
827+ goto cell_is_active;
828+ }
826829
827−reverse_deactivation:
828− smp_store_release(&cell->state, AFS_CELL_ACTIVE);
829− wake_up_var(&cell->state);
830− _leave(" [deact->act]");
831− return;
830+ /* Make sure that the expiring server records are going to see the fact
831+ * that the cell is caput.
832+ */
833+ afs_set_cell_state(cell, AFS_CELL_REMOVING);
832834
833−done:
834− _leave(" [done %u]", cell->state);
835− return;
835+ afs_deactivate_cell(net, cell);
836+ afs_purge_servers(cell);
837+
838+ rb_erase(&cell->net_node, &net->cells);
839+ afs_see_cell(cell, afs_cell_trace_unuse_delete);
840+ up_write(&net->cells_lock);
836841
837−final_destruction:
838842 /* The root volume is pinning the cell */
839843 afs_put_volume(cell->root_volume, afs_volume_trace_put_cell_root);
840844 cell->root_volume = NULL;
841− afs_purge_servers(cell);
842− afs_put_cell(cell, afs_cell_trace_put_destroy);
845+
846+ afs_set_cell_state(cell, AFS_CELL_DEAD);
847+ return true;
843848 }
844849
845850 static void afs_manage_cell_work(struct work_struct *work)
846851 {
847852 struct afs_cell *cell = container_of(work, struct afs_cell, manager);
853+ bool final_put;
848854
849− afs_manage_cell(cell);
850− afs_put_cell(cell, afs_cell_trace_put_queue_work);
851−}
852−
853−/*
854− * Manage the records of cells known to a network namespace. This includes
855− * updating the DNS records and garbage collecting unused cells that were
856− * automatically added.
857− *
858− * Note that constructed cell records may only be removed from net->cells by
859− * this work item, so it is safe for this work item to stash a cursor pointing
860− * into the tree and then return to caller (provided it skips cells that are
861− * still under construction).
862− *
863− * Note also that we were given an increment on net->cells_outstanding by
864− * whoever queued us that we need to deal with before returning.
865− */
866−void afs_manage_cells(struct work_struct *work)
867−{
868− struct afs_net *net = container_of(work, struct afs_net, cells_manager);
869− struct rb_node *cursor;
870− time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
871− bool purging = !net->live;
872−
873− _enter("");
874−
875− /* Trawl the cell database looking for cells that have expired from
876− * lack of use and cells whose DNS results have expired and dispatch
877− * their managers.
878− */
879− down_read(&net->cells_lock);
880−
881− for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
882− struct afs_cell *cell =
883− rb_entry(cursor, struct afs_cell, net_node);
884− unsigned active;
885− bool sched_cell = false;
886−
887− active = atomic_read(&cell->active);
888− trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
889− active, afs_cell_trace_manage);
890−
891− ASSERTCMP(active, >=, 1);
892−
893− if (purging) {
894− if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) {
895− active = atomic_dec_return(&cell->active);
896− trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
897− active, afs_cell_trace_unuse_pin);
898− }
899− }
900−
901− if (active == 1) {
902− struct afs_vlserver_list *vllist;
903− time64_t expire_at = cell->last_inactive;
904−
905− read_lock(&cell->vl_servers_lock);
906− vllist = rcu_dereference_protected(
907− cell->vl_servers,
908− lockdep_is_held(&cell->vl_servers_lock));
909− if (vllist->nr_servers > 0)
910− expire_at += afs_cell_gc_delay;
911− read_unlock(&cell->vl_servers_lock);
912− if (purging || expire_at <= now)
913− sched_cell = true;
914− else if (expire_at < next_manage)
915− next_manage = expire_at;
916− }
917−
918− if (!purging) {
919− if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
920− sched_cell = true;
921− }
922−
923− if (sched_cell)
924− afs_queue_cell(cell, afs_cell_trace_get_queue_manage);
925− }
926−
927− up_read(&net->cells_lock);
928−
929− /* Update the timer on the way out. We have to pass an increment on
930− * cells_outstanding in the namespace that we are in to the timer or
931− * the work scheduler.
932− */
933− if (!purging && next_manage < TIME64_MAX) {
934− now = ktime_get_real_seconds();
935−
936− if (next_manage - now <= 0) {
937− if (queue_work(afs_wq, &net->cells_manager))
938− atomic_inc(&net->cells_outstanding);
939− } else {
940− afs_set_cell_timer(net, next_manage - now);
941− }
942− }
943−
944− afs_dec_cells_outstanding(net);
945− _leave(" [%d]", atomic_read(&net->cells_outstanding));
855+ afs_see_cell(cell, afs_cell_trace_manage);
856+ final_put = afs_manage_cell(cell);
857+ afs_see_cell(cell, afs_cell_trace_managed);
858+ if (final_put)
859+ afs_put_cell(cell, afs_cell_trace_put_final);
946860 }
947861
948862 /*
@@ -951,6 +865,7 @@ void afs_manage_cells(struct work_struct *work) · 2 unmodified lines
951865 void afs_cell_purge(struct afs_net *net)
952866 {
953867 struct afs_cell *ws;
868+ struct rb_node *cursor;
954869
955870 _enter("");
956871
@@ -960,12 +875,19 @@ void afs_cell_purge(struct afs_net *net) · 3 unmodified lines
960875 up_write(&net->cells_lock);
961876 afs_unuse_cell(ws, afs_cell_trace_unuse_ws);
962877
963− _debug("del timer");
964− if (del_timer_sync(&net->cells_timer))
965− atomic_dec(&net->cells_outstanding);
878+ _debug("kick cells");
879+ down_read(&net->cells_lock);
880+ for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
881+ struct afs_cell *cell = rb_entry(cursor, struct afs_cell, net_node);
882+
883+ afs_see_cell(cell, afs_cell_trace_purge);
966884
967− _debug("kick mgr");
968− afs_queue_cell_manager(net);
885+ if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags))
886+ afs_unuse_cell(cell, afs_cell_trace_unuse_pin);
887+
888+ afs_queue_cell(cell, afs_cell_trace_queue_purge);
889+ }
890+ up_read(&net->cells_lock);
969891
970892 _debug("wait");
971893 wait_var_event(&net->cells_outstanding,
fs/afs/dynroot.c+2−2
@@ -293,8 +293,8 @@ static int afs_dynroot_readdir_cells(struct afs_net *net, struct dir_context *ct · 292 unmodified lines
293293 cell = idr_get_next(&net->cells_dyn_ino, &ix);
294294 if (!cell)
295295 return 0;
296− if (READ_ONCE(cell->state) == AFS_CELL_FAILED ||
297− READ_ONCE(cell->state) == AFS_CELL_REMOVED) {
296+ if (READ_ONCE(cell->state) == AFS_CELL_REMOVING ||
297+ READ_ONCE(cell->state) == AFS_CELL_DEAD) {
298298 ctx->pos += 2;
299299 ctx->pos &= ~1;
300300 continue;
fs/afs/internal.h+6−10
@@ -289,8 +289,6 @@ struct afs_net { · 288 unmodified lines
289289 struct rb_root cells;
290290 struct idr cells_dyn_ino; /* cell->dynroot_ino mapping */
291291 struct afs_cell __rcu *ws_cell;
292− struct work_struct cells_manager;
293− struct timer_list cells_timer;
294292 atomic_t cells_outstanding;
295293 struct rw_semaphore cells_lock;
296294 struct mutex cells_alias_lock;
@@ -339,13 +337,10 @@ struct afs_net { · 42 unmodified lines
339337 extern const char afs_init_sysname[];
340338
341339 enum afs_cell_state {
342− AFS_CELL_UNSET,
343− AFS_CELL_ACTIVATING,
340+ AFS_CELL_SETTING_UP,
344341 AFS_CELL_ACTIVE,
345− AFS_CELL_DEACTIVATING,
346− AFS_CELL_INACTIVE,
347− AFS_CELL_FAILED,
348− AFS_CELL_REMOVED,
342+ AFS_CELL_REMOVING,
343+ AFS_CELL_DEAD,
349344 };
350345
351346 /*
@@ -376,7 +371,9 @@ struct afs_cell { · 24 unmodified lines
376371 struct afs_cell *alias_of; /* The cell this is an alias of */
377372 struct afs_volume *root_volume; /* The root.cell volume if there is one */
378373 struct key *anonymous_key; /* anonymous user key for this cell */
374+ struct work_struct destroyer; /* Destroyer for cell */
379375 struct work_struct manager; /* Manager for init/deinit/dns */
376+ struct timer_list management_timer; /* General management timer */
380377 struct hlist_node proc_link; /* /proc cell list link */
381378 time64_t dns_expiry; /* Time AFSDB/SRV record expires */
382379 time64_t last_inactive; /* Time of last drop of usage count */
@@ -1053,8 +1050,7 @@ extern struct afs_cell *afs_get_cell(struct afs_cell *, enum afs_cell_trace); · 670 unmodified lines
10531050 extern void afs_see_cell(struct afs_cell *, enum afs_cell_trace);
10541051 extern void afs_put_cell(struct afs_cell *, enum afs_cell_trace);
10551052 extern void afs_queue_cell(struct afs_cell *, enum afs_cell_trace);
1056−extern void afs_manage_cells(struct work_struct *);
1057−extern void afs_cells_timer(struct timer_list *);
1053+void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs);
10581054 extern void __net_exit afs_cell_purge(struct afs_net *);
10591055
10601056 /*
fs/afs/main.c+0−3
@@ -78,9 +78,6 @@ static int __net_init afs_net_init(struct net *net_ns) · 77 unmodified lines
7878 net->cells = RB_ROOT;
7979 idr_init(&net->cells_dyn_ino);
8080 init_rwsem(&net->cells_lock);
81− INIT_WORK(&net->cells_manager, afs_manage_cells);
82− timer_setup(&net->cells_timer, afs_cells_timer, 0);
83−
8481 mutex_init(&net->cells_alias_lock);
8582 mutex_init(&net->proc_cells_lock);
8683 INIT_HLIST_HEAD(&net->proc_cells);
fs/afs/server.c+4−4
@@ -103,7 +103,7 @@ static struct afs_server *afs_install_server(struct afs_cell *cell, · 102 unmodified lines
103103 afs_get_cell(cell, afs_cell_trace_get_server);
104104
105105 exists:
106− afs_use_server(server, true, afs_server_trace_get_install);
106+ afs_use_server(server, true, afs_server_trace_use_install);
107107 return server;
108108 }
109109
@@ -356,7 +356,7 @@ void afs_unuse_server_notime(struct afs_net *net, struct afs_server *server, · 246 unmodified lines
356356
357357 if (atomic_dec_and_test(&server->active)) {
358358 if (test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) ||
359− READ_ONCE(server->cell->state) >= AFS_CELL_FAILED)
359+ READ_ONCE(server->cell->state) >= AFS_CELL_REMOVING)
360360 schedule_work(&server->destroyer);
361361 }
362362
@@ -374,7 +374,7 @@ void afs_unuse_server(struct afs_net *net, struct afs_server *server, · 11 unmodified lines
374374
375375 if (atomic_dec_and_test(&server->active)) {
376376 if (!test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) &&
377− READ_ONCE(server->cell->state) < AFS_CELL_FAILED) {
377+ READ_ONCE(server->cell->state) < AFS_CELL_REMOVING) {
378378 time64_t unuse_time = ktime_get_real_seconds();
379379
380380 server->unuse_time = unuse_time;
@@ -424,7 +424,7 @@ static bool afs_has_server_expired(const struct afs_server *server) · 43 unmodified lines
424424 return false;
425425
426426 if (server->cell->net->live ||
427− server->cell->state >= AFS_CELL_FAILED) {
427+ server->cell->state >= AFS_CELL_REMOVING) {
428428 trace_afs_server(server->debug_id, refcount_read(&server->ref),
429429 0, afs_server_trace_purging);
430430 return true;
fs/afs/vl_rotate.c+1−1
@@ -48,7 +48,7 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc) · 47 unmodified lines
4848 cell->dns_expiry <= ktime_get_real_seconds()) {
4949 dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
5050 set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
51− afs_queue_cell(cell, afs_cell_trace_get_queue_dns);
51+ afs_queue_cell(cell, afs_cell_trace_queue_dns);
5252
5353 if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
5454 if (wait_var_event_interruptible(
include/trace/events/afs.h+11−12
@@ -131,7 +131,6 @@ enum yfs_cm_operation { · 130 unmodified lines
131131 EM(afs_server_trace_destroy, "DESTROY ") \
132132 EM(afs_server_trace_free, "FREE ") \
133133 EM(afs_server_trace_gc, "GC ") \
134− EM(afs_server_trace_get_install, "GET inst ") \
135134 EM(afs_server_trace_get_probe, "GET probe") \
136135 EM(afs_server_trace_purging, "PURGE ") \
137136 EM(afs_server_trace_put_cbi, "PUT cbi ") \
@@ -149,6 +148,7 @@ enum yfs_cm_operation { · 11 unmodified lines
149148 EM(afs_server_trace_use_cm_call, "USE cm-cl") \
150149 EM(afs_server_trace_use_get_caps, "USE gcaps") \
151150 EM(afs_server_trace_use_give_up_cb, "USE gvupc") \
151+ EM(afs_server_trace_use_install, "USE inst ") \
152152 E_(afs_server_trace_wait_create, "WAIT crt ")
153153
154154 #define afs_volume_traces \
@@ -171,37 +171,36 @@ enum yfs_cm_operation { · 16 unmodified lines
171171
172172 #define afs_cell_traces \
173173 EM(afs_cell_trace_alloc, "ALLOC ") \
174+ EM(afs_cell_trace_destroy, "DESTROY ") \
174175 EM(afs_cell_trace_free, "FREE ") \
175176 EM(afs_cell_trace_get_atcell, "GET atcell") \
176− EM(afs_cell_trace_get_queue_dns, "GET q-dns ") \
177− EM(afs_cell_trace_get_queue_manage, "GET q-mng ") \
178− EM(afs_cell_trace_get_queue_new, "GET q-new ") \
179177 EM(afs_cell_trace_get_server, "GET server") \
180178 EM(afs_cell_trace_get_vol, "GET vol ") \
181− EM(afs_cell_trace_insert, "INSERT ") \
182− EM(afs_cell_trace_manage, "MANAGE ") \
179+ EM(afs_cell_trace_purge, "PURGE ") \
183180 EM(afs_cell_trace_put_atcell, "PUT atcell") \
184181 EM(afs_cell_trace_put_candidate, "PUT candid") \
185− EM(afs_cell_trace_put_destroy, "PUT destry") \
186− EM(afs_cell_trace_put_queue_work, "PUT q-work") \
187− EM(afs_cell_trace_put_queue_fail, "PUT q-fail") \
182+ EM(afs_cell_trace_put_final, "PUT final ") \
188183 EM(afs_cell_trace_put_server, "PUT server") \
189184 EM(afs_cell_trace_put_vol, "PUT vol ") \
185+ EM(afs_cell_trace_queue_again, "QUE again ") \
186+ EM(afs_cell_trace_queue_dns, "QUE dns ") \
187+ EM(afs_cell_trace_queue_new, "QUE new ") \
188+ EM(afs_cell_trace_queue_purge, "QUE purge ") \
189+ EM(afs_cell_trace_manage, "MANAGE ") \
190+ EM(afs_cell_trace_managed, "MANAGED ") \
190191 EM(afs_cell_trace_see_source, "SEE source") \
191− EM(afs_cell_trace_see_ws, "SEE ws ") \
192+ EM(afs_cell_trace_see_mgmt_timer, "SEE mtimer") \
192193 EM(afs_cell_trace_unuse_alias, "UNU alias ") \
193194 EM(afs_cell_trace_unuse_check_alias, "UNU chk-al") \
194195 EM(afs_cell_trace_unuse_delete, "UNU delete") \
195196 EM(afs_cell_trace_unuse_dynroot_mntpt, "UNU dyn-mp") \
196197 EM(afs_cell_trace_unuse_fc, "UNU fc ") \
197− EM(afs_cell_trace_unuse_lookup, "UNU lookup") \
198198 EM(afs_cell_trace_unuse_lookup_dynroot, "UNU lu-dyn") \
199199 EM(afs_cell_trace_unuse_lookup_error, "UNU lu-err") \
200200 EM(afs_cell_trace_unuse_mntpt, "UNU mntpt ") \
201201 EM(afs_cell_trace_unuse_no_pin, "UNU no-pin") \
202202 EM(afs_cell_trace_unuse_parse, "UNU parse ") \
203203 EM(afs_cell_trace_unuse_pin, "UNU pin ") \
204− EM(afs_cell_trace_unuse_probe, "UNU probe ") \
205204 EM(afs_cell_trace_unuse_sbi, "UNU sbi ") \
206205 EM(afs_cell_trace_unuse_ws, "UNU ws ") \
207206 EM(afs_cell_trace_use_alias, "USE alias ") \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t