1818static unsigned __read_mostly afs_cell_gc_delay = 10 ;
1919static unsigned __read_mostly afs_cell_min_ttl = 10 * 60 ;
2020static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60 ;
21+ static atomic_t cell_debug_id ;
2122
2223static void afs_queue_cell_manager (struct afs_net * );
2324static void afs_manage_cell_work (struct work_struct * );
@@ -48,7 +49,8 @@ static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
4849 * hold net->cells_lock at least read-locked.
4950 */
5051static struct afs_cell * afs_find_cell_locked (struct afs_net * net ,
51- const char * name , unsigned int namesz )
52+ const char * name , unsigned int namesz ,
53+ enum afs_cell_trace reason )
5254{
5355 struct afs_cell * cell = NULL ;
5456 struct rb_node * p ;
@@ -87,19 +89,20 @@ static struct afs_cell *afs_find_cell_locked(struct afs_net *net,
8789 return ERR_PTR (- ENOENT );
8890
8991found :
90- return afs_use_cell (cell );
92+ return afs_use_cell (cell , reason );
9193}
9294
9395/*
9496 * Look up and get an activation reference on a cell record.
9597 */
9698struct afs_cell * afs_find_cell (struct afs_net * net ,
97- const char * name , unsigned int namesz )
99+ const char * name , unsigned int namesz ,
100+ enum afs_cell_trace reason )
98101{
99102 struct afs_cell * cell ;
100103
101104 down_read (& net -> cells_lock );
102- cell = afs_find_cell_locked (net , name , namesz );
105+ cell = afs_find_cell_locked (net , name , namesz , reason );
103106 up_read (& net -> cells_lock );
104107 return cell ;
105108}
@@ -197,6 +200,8 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
197200 cell -> dns_status = vllist -> status ;
198201 smp_store_release (& cell -> dns_lookup_count , 1 ); /* vs source/status */
199202 atomic_inc (& net -> cells_outstanding );
203+ cell -> debug_id = atomic_inc_return (& cell_debug_id );
204+ trace_afs_cell (cell -> debug_id , 1 , 0 , afs_cell_trace_alloc );
200205
201206 _leave (" = %p" , cell );
202207 return cell ;
@@ -236,7 +241,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
236241 _enter ("%s,%s" , name , vllist );
237242
238243 if (!excl ) {
239- cell = afs_find_cell (net , name , namesz );
244+ cell = afs_find_cell (net , name , namesz , afs_cell_trace_use_lookup );
240245 if (!IS_ERR (cell ))
241246 goto wait_for_cell ;
242247 }
@@ -280,13 +285,16 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
280285 cell = candidate ;
281286 candidate = NULL ;
282287 atomic_set (& cell -> active , 2 );
288+ trace_afs_cell (cell -> debug_id , atomic_read (& cell -> ref ), 2 , afs_cell_trace_insert );
283289 rb_link_node_rcu (& cell -> net_node , parent , pp );
284290 rb_insert_color (& cell -> net_node , & net -> cells );
285291 up_write (& net -> cells_lock );
286292
287- afs_queue_cell (cell );
293+ afs_queue_cell (cell , afs_cell_trace_get_queue_new );
288294
289295wait_for_cell :
296+ trace_afs_cell (cell -> debug_id , atomic_read (& cell -> ref ), atomic_read (& cell -> active ),
297+ afs_cell_trace_wait );
290298 _debug ("wait_for_cell" );
291299 wait_var_event (& cell -> state ,
292300 ({
@@ -309,17 +317,17 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
309317 if (excl ) {
310318 ret = - EEXIST ;
311319 } else {
312- afs_use_cell (cursor );
320+ afs_use_cell (cursor , afs_cell_trace_use_lookup );
313321 ret = 0 ;
314322 }
315323 up_write (& net -> cells_lock );
316324 if (candidate )
317- afs_put_cell (candidate );
325+ afs_put_cell (candidate , afs_cell_trace_put_candidate );
318326 if (ret == 0 )
319327 goto wait_for_cell ;
320328 goto error_noput ;
321329error :
322- afs_unuse_cell (net , cell );
330+ afs_unuse_cell (net , cell , afs_cell_trace_unuse_lookup );
323331error_noput :
324332 _leave (" = %d [error]" , ret );
325333 return ERR_PTR (ret );
@@ -364,15 +372,16 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
364372 }
365373
366374 if (!test_and_set_bit (AFS_CELL_FL_NO_GC , & new_root -> flags ))
367- afs_use_cell (new_root );
375+ afs_use_cell (new_root , afs_cell_trace_use_pin );
368376
369377 /* install the new cell */
370378 down_write (& net -> cells_lock );
379+ afs_see_cell (new_root , afs_cell_trace_see_ws );
371380 old_root = net -> ws_cell ;
372381 net -> ws_cell = new_root ;
373382 up_write (& net -> cells_lock );
374383
375- afs_unuse_cell (net , old_root );
384+ afs_unuse_cell (net , old_root , afs_cell_trace_unuse_ws );
376385 _leave (" = 0" );
377386 return 0 ;
378387}
@@ -485,9 +494,10 @@ static void afs_cell_destroy(struct rcu_head *rcu)
485494
486495 u = atomic_read (& cell -> ref );
487496 ASSERTCMP (u , = = , 0 );
497+ trace_afs_cell (cell -> debug_id , u , atomic_read (& cell -> active ), afs_cell_trace_free );
488498
489499 afs_put_vlserverlist (net , rcu_access_pointer (cell -> vl_servers ));
490- afs_unuse_cell (net , cell -> alias_of );
500+ afs_unuse_cell (net , cell -> alias_of , afs_cell_trace_unuse_alias );
491501 key_put (cell -> anonymous_key );
492502 kfree (cell -> name );
493503 kfree (cell );
@@ -525,24 +535,30 @@ void afs_cells_timer(struct timer_list *timer)
525535/*
526536 * Get a reference on a cell record.
527537 */
528- struct afs_cell * afs_get_cell (struct afs_cell * cell )
538+ struct afs_cell * afs_get_cell (struct afs_cell * cell , enum afs_cell_trace reason )
529539{
540+ int u ;
541+
530542 if (atomic_read (& cell -> ref ) <= 0 )
531543 BUG ();
532544
533- atomic_inc (& cell -> ref );
545+ u = atomic_inc_return (& cell -> ref );
546+ trace_afs_cell (cell -> debug_id , u , atomic_read (& cell -> active ), reason );
534547 return cell ;
535548}
536549
537550/*
538551 * Drop a reference on a cell record.
539552 */
540- void afs_put_cell (struct afs_cell * cell )
553+ void afs_put_cell (struct afs_cell * cell , enum afs_cell_trace reason )
541554{
542555 if (cell ) {
556+ unsigned int debug_id = cell -> debug_id ;
543557 unsigned int u , a ;
544558
559+ a = atomic_read (& cell -> active );
545560 u = atomic_dec_return (& cell -> ref );
561+ trace_afs_cell (debug_id , u , a , reason );
546562 if (u == 0 ) {
547563 a = atomic_read (& cell -> active );
548564 WARN (a != 0 , "Cell active count %u > 0\n" , a );
@@ -554,23 +570,28 @@ void afs_put_cell(struct afs_cell *cell)
554570/*
555571 * Note a cell becoming more active.
556572 */
557- struct afs_cell * afs_use_cell (struct afs_cell * cell )
573+ struct afs_cell * afs_use_cell (struct afs_cell * cell , enum afs_cell_trace reason )
558574{
575+ int u , a ;
576+
559577 if (atomic_read (& cell -> ref ) <= 0 )
560578 BUG ();
561579
562- atomic_inc (& cell -> active );
580+ u = atomic_read (& cell -> ref );
581+ a = atomic_inc_return (& cell -> active );
582+ trace_afs_cell (cell -> debug_id , u , a , reason );
563583 return cell ;
564584}
565585
566586/*
567587 * Record a cell becoming less active. When the active counter reaches 1, it
568588 * is scheduled for destruction, but may get reactivated.
569589 */
570- void afs_unuse_cell (struct afs_net * net , struct afs_cell * cell )
590+ void afs_unuse_cell (struct afs_net * net , struct afs_cell * cell , enum afs_cell_trace reason )
571591{
592+ unsigned int debug_id = cell -> debug_id ;
572593 time64_t now , expire_delay ;
573- int a ;
594+ int u , a ;
574595
575596 if (!cell )
576597 return ;
@@ -583,21 +604,35 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell)
583604 if (cell -> vl_servers -> nr_servers )
584605 expire_delay = afs_cell_gc_delay ;
585606
607+ u = atomic_read (& cell -> ref );
586608 a = atomic_dec_return (& cell -> active );
609+ trace_afs_cell (debug_id , u , a , reason );
587610 WARN_ON (a == 0 );
588611 if (a == 1 )
589612 /* 'cell' may now be garbage collected. */
590613 afs_set_cell_timer (net , expire_delay );
591614}
592615
616+ /*
617+ * Note that a cell has been seen.
618+ */
619+ void afs_see_cell (struct afs_cell * cell , enum afs_cell_trace reason )
620+ {
621+ int u , a ;
622+
623+ u = atomic_read (& cell -> ref );
624+ a = atomic_read (& cell -> active );
625+ trace_afs_cell (cell -> debug_id , u , a , reason );
626+ }
627+
593628/*
594629 * Queue a cell for management, giving the workqueue a ref to hold.
595630 */
596- void afs_queue_cell (struct afs_cell * cell )
631+ void afs_queue_cell (struct afs_cell * cell , enum afs_cell_trace reason )
597632{
598- afs_get_cell (cell );
633+ afs_get_cell (cell , reason );
599634 if (!queue_work (afs_wq , & cell -> manager ))
600- afs_put_cell (cell );
635+ afs_put_cell (cell , afs_cell_trace_put_queue_fail );
601636}
602637
603638/*
@@ -713,6 +748,8 @@ static void afs_manage_cell(struct afs_cell *cell)
713748 active = 1 ;
714749 if (atomic_try_cmpxchg_relaxed (& cell -> active , & active , 0 )) {
715750 rb_erase (& cell -> net_node , & net -> cells );
751+ trace_afs_cell (cell -> debug_id , atomic_read (& cell -> ref ), 0 ,
752+ afs_cell_trace_unuse_delete );
716753 smp_store_release (& cell -> state , AFS_CELL_REMOVED );
717754 }
718755 up_write (& net -> cells_lock );
@@ -792,15 +829,15 @@ static void afs_manage_cell(struct afs_cell *cell)
792829 /* The root volume is pinning the cell */
793830 afs_put_volume (cell -> net , cell -> root_volume , afs_volume_trace_put_cell_root );
794831 cell -> root_volume = NULL ;
795- afs_put_cell (cell );
832+ afs_put_cell (cell , afs_cell_trace_put_destroy );
796833}
797834
798835static void afs_manage_cell_work (struct work_struct * work )
799836{
800837 struct afs_cell * cell = container_of (work , struct afs_cell , manager );
801838
802839 afs_manage_cell (cell );
803- afs_put_cell (cell );
840+ afs_put_cell (cell , afs_cell_trace_put_queue_work );
804841}
805842
806843/*
@@ -838,13 +875,17 @@ void afs_manage_cells(struct work_struct *work)
838875 bool sched_cell = false;
839876
840877 active = atomic_read (& cell -> active );
841- _debug ("manage %s %u %u" , cell -> name , atomic_read (& cell -> ref ), active );
878+ trace_afs_cell (cell -> debug_id , atomic_read (& cell -> ref ),
879+ active , afs_cell_trace_manage );
842880
843881 ASSERTCMP (active , >=, 1 );
844882
845883 if (purging ) {
846- if (test_and_clear_bit (AFS_CELL_FL_NO_GC , & cell -> flags ))
847- atomic_dec (& cell -> active );
884+ if (test_and_clear_bit (AFS_CELL_FL_NO_GC , & cell -> flags )) {
885+ active = atomic_dec_return (& cell -> active );
886+ trace_afs_cell (cell -> debug_id , atomic_read (& cell -> ref ),
887+ active , afs_cell_trace_unuse_pin );
888+ }
848889 }
849890
850891 if (active == 1 ) {
@@ -870,7 +911,7 @@ void afs_manage_cells(struct work_struct *work)
870911 }
871912
872913 if (sched_cell )
873- afs_queue_cell (cell );
914+ afs_queue_cell (cell , afs_cell_trace_get_queue_manage );
874915 }
875916
876917 up_read (& net -> cells_lock );
@@ -907,7 +948,7 @@ void afs_cell_purge(struct afs_net *net)
907948 ws = net -> ws_cell ;
908949 net -> ws_cell = NULL ;
909950 up_write (& net -> cells_lock );
910- afs_unuse_cell (net , ws );
951+ afs_unuse_cell (net , ws , afs_cell_trace_unuse_ws );
911952
912953 _debug ("del timer" );
913954 if (del_timer_sync (& net -> cells_timer ))
0 commit comments