@@ -52,6 +52,14 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n)
52
52
#define hlist_nulls_next_rcu (node ) \
53
53
(*((struct hlist_nulls_node __rcu __force **)&(node)->next))
54
54
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
+
55
63
/**
56
64
* hlist_nulls_del_rcu - deletes entry from hash list without re-initialization
57
65
* @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,
145
153
}
146
154
}
147
155
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
+
148
190
/* after that hlist_nulls_del will work */
149
191
static inline void hlist_nulls_add_fake (struct hlist_nulls_node * n )
150
192
{
0 commit comments