Merge tag '4.9/mtd-pairing-scheme' of github.com:linux-nand/linux
[linux-2.6-block.git] / include / linux / rculist.h
index 17d4f849c65e3dcf5dfbbd8100abf1236073ad55..8beb98dcf14f066fc4e9075ed0b94cc29998c9bc 100644 (file)
@@ -487,6 +487,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.