garbage collection is a common method used in kernel. When a object(struct,memeory) become invalid, we need free them, but the object maybe reference by others.
such as a dst_entry is not invalid, and it is still referenced(used) by others.
then __dst_free will be called for this case. It will first set dst to dirty(dead), and then put it into dst_garbage.list by dst->next.
Then a workqueue task will check the dst‘s reference, and free(destory) it when no reference on it.
Two key struct struct dst_garbage and dst_gc_work
struct dst_garbage
1 2 3 4 5 6 7 8 9 10 11 12 13 14
38/* 39 * We want to keep lock & list close together 40 * to dirty as few cache lines as possible in __dst_free(). 41 * As this is not a very strong hint, we dont force an alignment on SMP. 42 */ 43staticstruct { 44spinlock_t lock; 45structdst_entry *list; 46unsignedlong timer_inc; 47unsignedlong timer_expires; 48 } dst_garbage = { 49 .lock = __SPIN_LOCK_UNLOCKED(dst_garbage.lock), 50 .timer_inc = DST_GC_MAX, 51 };
Eeach round, dst_gc_task will check this list. The dst has no reference will be free(destroy). the others will be appended to dst_busy_list. So after a round , the list will be empty.
dst_busy_list
After dst_gc_task finish, all the referenced dst nodes are in this list.
head
This is temporary list. All the referenced dst nodes during dst_gc_task are in this list. Before dst_gc_task finish, they will be moved to dst_busy_list.
the main function of workqueue dst_gc_task
check the old dst nodes,
for the un-referenced node, free(destory) it. or put them to the temp list head.
for the node in dst_garbage.list do the same operation like 2
move tmp list head to dst_busy_list.
schedule gc task.
NOTE: BH lock are needed because TX softirq also aceess dst_garbage.