Hand-Over-Hand SRCU Use Case?

Again, the code fragment is as follows:

  1 struct foo {
  2   struct list_head list;
  3   ...
  4 };
  5 
  6 LIST_HEAD(mylist);
  7 struct srcu_struct mysrcu;
  8 
  9 void process(void)
 10 {
 11   int i1, i2;
 12   struct foo *p;
 13 
 14   i1 = srcu_read_lock(&mysrcu);
 15   list_for_each_entry_rcu(p, &mylist, list) {
 16     do_something_with(p);
 17     i2 = srcu_read_lock(&mysrcu);
 18     srcu_read_unlock(&mysrcu, i1);
 19     i1 = i2;
 20   }
 21   srcu_read_unlock(&mysrcu, i1);
 22 }

As is customary with SRCU, the list is manipulated using list_add_rcu(), list_del_rcu, and friends.

What are the advantages and disadvantages of this hand-over-hand SRCU list traversal?

The biggest disadvantage is that it is totally broken. To see this, note the definition of list_for_each_rcu():

  1 #define list_for_each_entry_rcu(pos, head, member) \
  2   for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
  3     prefetch(pos->member.next), &pos->member != (head); \
  4     pos = list_entry_rcu(pos->member.next, typeof(*pos), member))

The bug is that the nth list_for_each_entry_rcu() fetches SRCU-protected pointer p in one SRCU read-side critical section, but then the n+1th list_for_each_entry_rcu() uses p after that SRCU read-side critical section has ended.

We can fix that bug by changing process() so as to open-code list_for_each_entry_rcu(), advancing the pointer while under the protection of both of the SRCU read-side critical sections (and dispensing with the prefetching):

  1 void process(void)
  2 {
  3   int i1, i2;
  4   struct foo *p;
  5 
  6   i1 = srcu_read_lock(&mysrcu);
  7   p = list_entry_rcu(mylist.next, struct foo, list);
  8   while (&p->list != &mylist) {
  9     do_something_with(p);
 10     i2 = srcu_read_lock(&mysrcu);
 11     p = list_entry_rcu(p->list.next, struct foo, list);
 12     srcu_read_unlock(&mysrcu, i1);
 13     i1 = i2;
 14   }
 15   srcu_read_unlock(&mysrcu, i1);
 16 }

What are the advantages and disadvantages of this version of hand-over-hand SRCU list traversal?