On Fri 18-03-16 15:44:01, Waiman Long wrote:
> +static __always_inline bool
> +__pcpu_list_next_cpu(struct pcpu_list_head *head, struct pcpu_list_state 
> *state)
> +{
> +     if (state->lock)
> +             spin_unlock(state->lock);
> +next_cpu:
> +     /*
> +      * for_each_possible_cpu(cpu)
> +      */
> +     state->cpu = cpumask_next(state->cpu, cpu_possible_mask);
> +     if (state->cpu >= nr_cpu_ids)
> +             return false;   /* All the per-cpu lists iterated */
> +
> +     state->head = &per_cpu_ptr(head, state->cpu)->list;
> +     if (list_empty(state->head))
> +             goto next_cpu;
> +
> +     state->lock = &per_cpu_ptr(head, state->cpu)->lock;
> +     spin_lock(state->lock);
> +     state->curr = list_entry(state->head->next,
> +                              struct pcpu_list_node, list);
> +     return true;

Waiman, I repeat it for the third time as you keep ignoring it: This is
*racy*. The list for state->cpu can be empty by the time you acquire
state->lock and thus state->curr will point somewhere around the head of
the list but definitely not to a list member where it should.

                                                                Honza
-- 
Jan Kara <j...@suse.com>
SUSE Labs, CR

Reply via email to