Commit 760fbc12 authored by David S. Miller's avatar David S. Miller Committed by DidntRead
Browse files


commit 1602f49b58abcb0d34a5f0a29d68e7c1769547aa upstream.

[This commit was a merge, but it added hlist_add_tail_rcu(), which is what we
 need in this stable tree, so I've changed the subject to be more descriptive
 - gregkh]

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bfe1a25e
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -404,6 +404,42 @@ static inline void hlist_add_head_rcu(struct hlist_node *n,
		first->pprev = &n->next;
}

/**
 * hlist_add_tail_rcu
 * @n: the element to add to the hash list.
 * @h: the list to add to.
 *
 * Description:
 * Adds the specified element to the specified hlist,
 * while permitting racing traversals.
 *
 * 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(), used to prevent memory-consistency
 * problems on Alpha CPUs.  Regardless of the type of CPU, the
 * list-traversal primitive must be guarded by rcu_read_lock().
 */
static inline void hlist_add_tail_rcu(struct hlist_node *n,
				      struct hlist_head *h)
{
	struct hlist_node *i, *last = NULL;

	for (i = hlist_first_rcu(h); i; i = hlist_next_rcu(i))
		last = i;

	if (last) {
		n->next = last->next;
		n->pprev = &last->next;
		rcu_assign_pointer(hlist_next_rcu(last), n);
	} else {
		hlist_add_head_rcu(n, h);
	}
}

/**
 * hlist_add_before_rcu
 * @n: the new element to add to the hash list.