Skip to content

Commit 06ab8b5

Browse files
htbeginKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
rculist: add hlist_nulls_replace_rcu() helper
Add hlist_nulls_replace_rcu() to replace an existing element in the hash list. For the concurrent list traversal, the replace is atomic, it will find either the old element or the new element. Signed-off-by: Hou Tao <[email protected]>
1 parent 43059e3 commit 06ab8b5

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

include/linux/rculist_nulls.h

+42
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n)
5252
#define hlist_nulls_next_rcu(node) \
5353
(*((struct hlist_nulls_node __rcu __force **)&(node)->next))
5454

55+
56+
/**
57+
* hlist_nulls_pprev_rcu - returns the element of the list before @node.
58+
* @node: element of the list.
59+
*/
60+
#define hlist_nulls_pprev_rcu(node) \
61+
(*((struct hlist_nulls_node __rcu __force **)(node)->pprev))
62+
5563
/**
5664
* hlist_nulls_del_rcu - deletes entry from hash list without re-initialization
5765
* @n: the element to delete from the hash list.
@@ -145,6 +153,40 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
145153
}
146154
}
147155

156+
/**
157+
* hlist_nulls_replace_rcu - replace an element in hash list
158+
* @n: new element to add
159+
* @o: old element to replace
160+
*
161+
* Description:
162+
* Replace an existing element in a hash list with a new one,
163+
* while permitting racing traversals.
164+
*
165+
* The caller must take whatever precautions are necessary
166+
* (such as holding appropriate locks) to avoid racing
167+
* with another list-mutation primitive, such as hlist_nulls_add_head_rcu()
168+
* or hlist_nulls_del_rcu(), running on this same list.
169+
* However, it is perfectly legal to run concurrently with
170+
* the _rcu list-traversal primitives, such as
171+
* hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency
172+
* problems on Alpha CPUs. Regardless of the type of CPU, the
173+
* list-traversal primitive must be guarded by rcu_read_lock().
174+
*/
175+
static inline void hlist_nulls_replace_rcu(struct hlist_nulls_node *n,
176+
struct hlist_nulls_node *o)
177+
{
178+
struct hlist_nulls_node *next = o->next;
179+
struct hlist_nulls_node **pprev = o->pprev;
180+
181+
WRITE_ONCE(n->next, next);
182+
WRITE_ONCE(n->pprev, pprev);
183+
rcu_assign_pointer(hlist_nulls_pprev_rcu(o), n);
184+
185+
if (!is_a_nulls(next))
186+
WRITE_ONCE(next->pprev, &n->next);
187+
WRITE_ONCE(o->pprev, LIST_POISON2);
188+
}
189+
148190
/* after that hlist_nulls_del will work */
149191
static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n)
150192
{

0 commit comments

Comments
 (0)