I'm a bit confused about such code:
struct a {
// ...
struct list_head some_list;
// ...
};
struct e {
struct list_head next;
// ...
};
static void *traverse(struct a *a)
{
struct e *e;
rcu_read_lock();
list_for_each_entry_rcu(e, &a->some_list, next) {
if (...) {
rcu_read_unlock();
return e;
}
}
rcu_read_unlock();
return NULL;
}
In the function traverse
we take a lock rcu_read_lock
and then iterate over some list until some condition is met, but after this condition is met we unlock rcu_read_unlock
RCU and return the e
pointer.
The key point that is confusing me is that we unlock RCU read-side critical section, but keep pointer from the list, what if write-side will remove this element and it seems that this pointer e
will be broken, isn't it?
AFAIK, the pointer is valid only inside read-side critical section, i.e. between rcu_read_lock
and rcu_read_unlock
, am I wrong?
P.S.: traverse
is called without holding any locks.