From: john cooper <john.cooper@redhat.com> Date: Sat, 4 Apr 2009 16:28:12 -0400 Subject: [misc] introduce list_del_init_rcu Message-id: 49D7C2DC.6050008@redhat.com O-Subject: [RHEL5.4 PATCH] implement mmu_notifier mechanism V3, [1/5] BZ#485718 Bugzilla: 485718 RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> BZ#485718 https://bugzilla.redhat.com/show_bug.cgi?id=485718 Introduce list_del_init_rcu() and document it. diff --git a/include/linux/list.h b/include/linux/list.h index 7ff5183..0107208 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -781,6 +781,34 @@ static inline void hlist_del_init(struct hlist_node *n) } } +/** + * hlist_del_init_rcu - deletes entry from hash list with re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on the node return true after this. It is + * useful for RCU based read lockfree traversal if the writer side + * must know if the list entry is still hashed or already unhashed. + * + * In particular, it means that we can not poison the forward pointers + * that may still be used for walking the hash list and we can only + * zero the pprev pointer so list_unhashed() will return true after + * this. + * + * The caller must take whatever precautions are necessary (such as + * holding appropriate locks) to avoid racing with another + * list-mutation primitive, such as hlist_add_head_rcu() or + * hlist_del_rcu(), running on this same list. However, it is + * perfectly legal to run concurrently with the _rcu list-traversal + * primitives, such as hlist_for_each_entry_rcu(). + */ +static inline void hlist_del_init_rcu(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + n->pprev = NULL; + } +} + /* * hlist_replace_rcu - replace old entry by new one * @old : the element to be replaced