Regarding the second point, I'm sorry, my fingers typed rcu_dereference() whereas my brain was
thinking to rcu_assign_pointer(). rcu_dereference() could be used in update-side code, as you
pointed out, but obviously not in __list_add_rcu().
Therefore __list_add_rcu() could be:
new->next = next;
new->prev = prev;
next->prev = new;
The main advantage of this is readability IMHO.
You said that __list_add_rcu() must be protected by appropriate locking, and a memory barrier
is implied by lock acquisition which should be enough. But __list_add_rcu() has a memory
barrier in its implementation.