To implement the multicast list callback in mac80211 we need to do partial list iteration. Since I want to convert the interface list to an RCU list, I need a new list walking primitive: list_for_each_entry_continue_rcu(). Additional help text was provided by Paul McKenney. Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx> --- John, I don't know if you want to merge this or not. There's no clear list.h maintainer and this patch is requisite for the bugfix I'm going to send in a minute so it'd probably be best if this goes into the tree together. If you don't want to take it, however, I have no idea how to handle the situation :) include/linux/list.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) --- wireless-dev.orig/include/linux/list.h 2007-09-07 22:00:41.234425862 +0200 +++ wireless-dev/include/linux/list.h 2007-09-07 22:05:08.184425862 +0200 @@ -665,6 +665,32 @@ static inline void list_splice_init_rcu( prefetch(rcu_dereference((pos))->next), (pos) != (head); \ (pos) = (pos)->next) + +/** + * list_for_each_entry_continue_rcu - continue iteration over rcu list + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over rcu list of given type, continuing after + * the current position. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + * + * Note that the caller is responsible for making sure that + * the element remains in place between the earlier iterator + * and this one. One way to do this is to ensure that + * both iterators are covered by the same rcu_read_lock(), + * while others involve reference counts, flags, or mutexes. + */ +#define list_for_each_entry_continue_rcu(pos, head, member) \ + for ((pos) = list_entry((pos)->member.next, typeof(*pos), member); \ + prefetch(rcu_dereference((pos))->member.next), \ + &pos->member != (head); \ + (pos) = list_entry(pos->member.next, typeof(*pos), member)) + /* * Double linked lists with a single pointer list head. * Mostly useful for hash tables where the two pointer list head is - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html