[ovs-dev] [PATCH V2] ofproto-dpif-upcall: Remove the dispatcher thread.

Alex Wang alexw at nicira.com
Thu Feb 13 04:24:11 UTC 2014


Hey Han,

I'd very much like to get a full review from you.  Are you planning to do
that?

Also want to ask about your timetable, do you think you could finish review
this week?

Appreciate your help, ;D
Alex Wang,


On Wed, Feb 12, 2014 at 6:37 AM, Zhou, Han <hzhou8 at ebay.com> wrote:

> Hi Alex,
>
> On Fri, 2014-02-07 at 17:17 -0800, Alex Wang wrote:
> > This commit removes the 'dispatcher' thread by allowing 'handler'
> > threads to read upcalls directly from dpif.  vport in dpif will
> > open netlink sockets for each handler and will use the 5-tuple
> > hash from the missed packet to choose which socket (handler) to
> > send the upcall.
>
> It is very nice to see this improvement implemented. I just started the
> review and now have a comment:
>
> > +int ovs_vport_set_upcall_pids(struct vport *vport,  struct nlattr *pids)
> > +{
> > +     struct vport_pids *old;
> > +
> > +     if (pids && nla_len(pids) % sizeof(u32))
> > +             return -EINVAL;
> > +
> > +     rcu_read_lock();
>
> The rcu_read_lock here doesn't make sense. Real lock (e.g. spin-lock)
> should be used instead if we want to protect concurrent execution of
> this code.
>
> > +     old = vport->upcall_pids ? ovsl_dereference(vport->upcall_pids)
> > +             : NULL;
> > +
> Assume that you have no spin-lock/mutex hold before calling this
> function, then two threads can dereference vport->upcall_pids, and save
> in "old".
>
> > +     if (pids) {
> > +             struct vport_pids *vport_pids;
> > +
> > +             vport_pids = kmalloc(sizeof *vport_pids, GFP_KERNEL);
> > +             vport_pids->pids = kmalloc(nla_len(pids), GFP_KERNEL);
> > +             vport_pids->n_pids = nla_len(pids)
> > +                     / (sizeof *vport_pids->pids);
> > +             memcpy(vport_pids->pids, nla_data(pids), nla_len(pids));
> > +
> > +             rcu_assign_pointer(vport->upcall_pids, vport_pids);
> > +     } else if (old) {
> > +             rcu_assign_pointer(vport->upcall_pids, NULL);
> > +     }
> > +
> > +     if (old)
> > +             call_rcu(&old->rcu, vport_pids_destroy_rcu_cb);
>
> And then both threads will call this call_rcu, leading to double free.
>
> > +
> > +     rcu_read_unlock();
> > +     return 0;
> > +}
> > +
>
> So, if updating upcall_pids need protection, we'd better use spin-lock
> here. If we are sure concurrent execution is already prevented in
> calling code, then no locks needed here.
>
> Best regards,
> Han
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20140212/5d56e9ef/attachment-0005.html>


More information about the dev mailing list