Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rculist: avoid __rcu annotations

This avoids warnings from missing __rcu annotations
in the rculist implementation, making it possible to
use the same lists in both RCU and non-RCU cases.

We can add rculist annotations later, together with
lockdep support for rculist, which is missing as well,
but that may involve changing all the users.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>

authored by

Arnd Bergmann and committed by
Paul E. McKenney
67bdbffd ca5ecddf

+46 -25
+34 -19
include/linux/rculist.h
··· 10 10 #include <linux/rcupdate.h> 11 11 12 12 /* 13 + * return the ->next pointer of a list_head in an rcu safe 14 + * way, we must not access it directly 15 + */ 16 + #define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next))) 17 + 18 + /* 13 19 * Insert a new entry between two known consecutive entries. 14 20 * 15 21 * This is only for internal list manipulation where we know ··· 26 20 { 27 21 new->next = next; 28 22 new->prev = prev; 29 - rcu_assign_pointer(prev->next, new); 23 + rcu_assign_pointer(list_next_rcu(prev), new); 30 24 next->prev = new; 31 25 } 32 26 ··· 144 138 { 145 139 new->next = old->next; 146 140 new->prev = old->prev; 147 - rcu_assign_pointer(new->prev->next, new); 141 + rcu_assign_pointer(list_next_rcu(new->prev), new); 148 142 new->next->prev = new; 149 143 old->prev = LIST_POISON2; 150 144 } ··· 199 193 */ 200 194 201 195 last->next = at; 202 - rcu_assign_pointer(head->next, first); 196 + rcu_assign_pointer(list_next_rcu(head), first); 203 197 first->prev = head; 204 198 at->prev = last; 205 199 } ··· 214 208 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). 215 209 */ 216 210 #define list_entry_rcu(ptr, type, member) \ 217 - container_of(rcu_dereference_raw(ptr), type, member) 211 + ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \ 212 + container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ 213 + }) 218 214 219 215 /** 220 216 * list_first_entry_rcu - get the first element from a list ··· 233 225 list_entry_rcu((ptr)->next, type, member) 234 226 235 227 #define __list_for_each_rcu(pos, head) \ 236 - for (pos = rcu_dereference_raw((head)->next); \ 228 + for (pos = rcu_dereference_raw(list_next_rcu(head)); \ 237 229 pos != (head); \ 238 - pos = rcu_dereference_raw(pos->next)) 230 + pos = rcu_dereference_raw(list_next_rcu((pos))) 239 231 240 232 /** 241 233 * list_for_each_entry_rcu - iterate over rcu list of given type ··· 265 257 * as long as the traversal is guarded by rcu_read_lock(). 266 258 */ 267 259 #define list_for_each_continue_rcu(pos, head) \ 268 - for ((pos) = rcu_dereference_raw((pos)->next); \ 260 + for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \ 269 261 prefetch((pos)->next), (pos) != (head); \ 270 - (pos) = rcu_dereference_raw((pos)->next)) 262 + (pos) = rcu_dereference_raw(list_next_rcu(pos))) 271 263 272 264 /** 273 265 * list_for_each_entry_continue_rcu - continue iteration over list of given type ··· 322 314 323 315 new->next = next; 324 316 new->pprev = old->pprev; 325 - rcu_assign_pointer(*new->pprev, new); 317 + rcu_assign_pointer(*(struct hlist_node __rcu **)new->pprev, new); 326 318 if (next) 327 319 new->next->pprev = &new->next; 328 320 old->pprev = LIST_POISON2; 329 321 } 322 + 323 + /* 324 + * return the first or the next element in an RCU protected hlist 325 + */ 326 + #define hlist_first_rcu(head) (*((struct hlist_node __rcu **)(&(head)->first))) 327 + #define hlist_next_rcu(node) (*((struct hlist_node __rcu **)(&(node)->next))) 328 + #define hlist_pprev_rcu(node) (*((struct hlist_node __rcu **)((node)->pprev))) 330 329 331 330 /** 332 331 * hlist_add_head_rcu ··· 361 346 362 347 n->next = first; 363 348 n->pprev = &h->first; 364 - rcu_assign_pointer(h->first, n); 349 + rcu_assign_pointer(hlist_first_rcu(h), n); 365 350 if (first) 366 351 first->pprev = &n->next; 367 352 } ··· 389 374 { 390 375 n->pprev = next->pprev; 391 376 n->next = next; 392 - rcu_assign_pointer(*(n->pprev), n); 377 + rcu_assign_pointer(hlist_pprev_rcu(n), n); 393 378 next->pprev = &n->next; 394 379 } 395 380 ··· 416 401 { 417 402 n->next = prev->next; 418 403 n->pprev = &prev->next; 419 - rcu_assign_pointer(prev->next, n); 404 + rcu_assign_pointer(hlist_next_rcu(prev), n); 420 405 if (n->next) 421 406 n->next->pprev = &n->next; 422 407 } 423 408 424 - #define __hlist_for_each_rcu(pos, head) \ 425 - for (pos = rcu_dereference((head)->first); \ 426 - pos && ({ prefetch(pos->next); 1; }); \ 427 - pos = rcu_dereference(pos->next)) 409 + #define __hlist_for_each_rcu(pos, head) \ 410 + for (pos = rcu_dereference(hlist_first_rcu(head)); \ 411 + pos && ({ prefetch(pos->next); 1; }); \ 412 + pos = rcu_dereference(hlist_next_rcu(pos))) 428 413 429 414 /** 430 415 * hlist_for_each_entry_rcu - iterate over rcu list of given type ··· 437 422 * the _rcu list-mutation primitives such as hlist_add_head_rcu() 438 423 * as long as the traversal is guarded by rcu_read_lock(). 439 424 */ 440 - #define hlist_for_each_entry_rcu(tpos, pos, head, member) \ 441 - for (pos = rcu_dereference_raw((head)->first); \ 425 + #define hlist_for_each_entry_rcu(tpos, pos, head, member) \ 426 + for (pos = rcu_dereference_raw(hlist_first_rcu(head)); \ 442 427 pos && ({ prefetch(pos->next); 1; }) && \ 443 428 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ 444 - pos = rcu_dereference_raw(pos->next)) 429 + pos = rcu_dereference_raw(hlist_next_rcu(pos))) 445 430 446 431 /** 447 432 * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type
+11 -5
include/linux/rculist_nulls.h
··· 37 37 } 38 38 } 39 39 40 + #define hlist_nulls_first_rcu(head) \ 41 + (*((struct hlist_nulls_node __rcu __force **)&(head)->first)) 42 + 43 + #define hlist_nulls_next_rcu(node) \ 44 + (*((struct hlist_nulls_node __rcu __force **)&(node)->next)) 45 + 40 46 /** 41 47 * hlist_nulls_del_rcu - deletes entry from hash list without re-initialization 42 48 * @n: the element to delete from the hash list. ··· 94 88 95 89 n->next = first; 96 90 n->pprev = &h->first; 97 - rcu_assign_pointer(h->first, n); 91 + rcu_assign_pointer(hlist_nulls_first_rcu(h), n); 98 92 if (!is_a_nulls(first)) 99 93 first->pprev = &n->next; 100 94 } ··· 106 100 * @member: the name of the hlist_nulls_node within the struct. 107 101 * 108 102 */ 109 - #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \ 110 - for (pos = rcu_dereference_raw((head)->first); \ 111 - (!is_a_nulls(pos)) && \ 103 + #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \ 104 + for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ 105 + (!is_a_nulls(pos)) && \ 112 106 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \ 113 - pos = rcu_dereference_raw(pos->next)) 107 + pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos))) 114 108 115 109 #endif 116 110 #endif
+1 -1
kernel/pid.c
··· 401 401 struct task_struct *result = NULL; 402 402 if (pid) { 403 403 struct hlist_node *first; 404 - first = rcu_dereference_check(pid->tasks[type].first, 404 + first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]), 405 405 rcu_read_lock_held() || 406 406 lockdep_tasklist_lock_is_held()); 407 407 if (first)