Skip to content

Commit 35fc0e3

Browse files
committed
rculist: Add hlists_swap_heads_rcu
Using the struct pid to refer to two tasks in de_thread was a clever idea and ultimately too clever, as it has lead to proc_flush_task being called inconsistently. To support rectifying this add hlists_swap_heads_rcu. An hlist primitive that just swaps the hlist heads of two lists. This is exactly what is needed for exchanging the pids of two tasks. Only consideration of correctness of the code has been given, as the caller is expected to be a slowpath. Link: https://lore.kernel.org/lkml/[email protected]/ Acked-by: Linus Torvalds <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 3147d8a commit 35fc0e3

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

include/linux/rculist.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,27 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
506506
WRITE_ONCE(old->pprev, LIST_POISON2);
507507
}
508508

509+
/**
510+
* hlists_swap_heads_rcu - swap the lists the hlist heads point to
511+
* @left: The hlist head on the left
512+
* @right: The hlist head on the right
513+
*
514+
* The lists start out as [@left ][node1 ... ] and
515+
[@right ][node2 ... ]
516+
* The lists end up as [@left ][node2 ... ]
517+
* [@right ][node1 ... ]
518+
*/
519+
static inline void hlists_swap_heads_rcu(struct hlist_head *left, struct hlist_head *right)
520+
{
521+
struct hlist_node *node1 = left->first;
522+
struct hlist_node *node2 = right->first;
523+
524+
rcu_assign_pointer(left->first, node2);
525+
rcu_assign_pointer(right->first, node1);
526+
WRITE_ONCE(node2->pprev, &left->first);
527+
WRITE_ONCE(node1->pprev, &right->first);
528+
}
529+
509530
/*
510531
* return the first or the next element in an RCU protected hlist
511532
*/

0 commit comments

Comments
 (0)