[ovs-dev] [netdev 27/27] netdev: Make netdev access thread-safe.

Ben Pfaff blp at nicira.com
Thu Aug 8 06:12:50 UTC 2013


On Wed, Aug 07, 2013 at 05:31:57PM -0700, Andy Zhou wrote:
> On Thu, Aug 1, 2013 at 2:29 PM, Ben Pfaff <blp at nicira.com> wrote:
> > diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
> >  netdev_dummy_get_ifindex(const struct netdev *netdev)
> >  {
> >      struct netdev_dummy *dev = netdev_dummy_cast(netdev);
> > +    int ifindex;
> > +
> > +    ovs_mutex_lock(&dev->mutex);
> > +    ifindex = dev->ifindex;
> > +    ovs_mutex_unlock(&dev->mutex);
> >
> > -    return dev->ifindex;
> > +    return ifindex;
> >  }
> >
> Is mutex lock necessary?  same for netdev_dummy_get_mtu().

In the real world, I doubt that the mutex lock is necessary here.  But
it's not a fast path so I see no reason to try to optimize it.

> >  static unsigned int
> > -netdev_dummy_change_seq(const struct netdev *netdev)
> > +netdev_dummy_change_seq(const struct netdev *netdev_)
> >  {
> > -    return netdev_dummy_cast(netdev)->change_seq;
> > +    struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
> > +    unsigned int change_seq;
> > +
> > +    ovs_mutex_lock(&netdev->mutex);
> > +    change_seq = netdev->change_seq;
> > +    ovs_mutex_unlock(&netdev->mutex);
> > +
> > +    return change_seq;
> >  }
> >
> > Same here. Not sure mutex lock is necessary.

Same answer ;-)

> > @@ -1874,15 +1927,17 @@ netdev_linux_get_qos(const struct netdev *netdev_,
> >      struct netdev_linux *netdev = netdev_linux_cast(netdev_);
> >      int error;
> >
> > +    ovs_mutex_lock(&netdev->mutex);
> >      error = tc_query_qdisc(netdev_);
> > -    if (error) {
> > -        return error;
> > +    if (!error) {
> > +        *typep = netdev->tc->ops->ovs_name;
> > +        error = (netdev->tc->ops->qdisc_get
> > +                 ? netdev->tc->ops->qdisc_get(netdev_, details)
> > +                 : 0);
> >      }
> > +    ovs_mutex_unlock(&netdev->mutex);
> >
> How to reason that acccess to *typep outside after mutex unlock will be
> safe?

The values currently used are, I believe, all constant string literals,
so they are safe.  Maybe we will introduce some other non-constant
strings later; I agree that to make this safe requires an API change.

> > +static void
> > +netdev_class_foreach(void (*cb)(const struct netdev_class *))
> > +{
> > +    struct netdev_registered_class *rc_to_unref = NULL;
> > +    struct netdev_registered_class *rc;
> > +
> > +    ovs_mutex_lock(&netdev_mutex);
> > +    HMAP_FOR_EACH (rc, hmap_node, &netdev_classes) {
> > +        netdev_registered_class_unref(rc_to_unref);
> > +        rc_to_unref = rc;
> > +        rc->ref_cnt++;
> > +
> > +        ovs_mutex_unlock(&netdev_mutex);
> >
> How to reason this unlock is safe?

This function takes a reference on 'rc', so we can be sure that the
class won't be freed while the mutex is unlocked.

> > +        cb(rc->class);
> > +        ovs_mutex_lock(&netdev_mutex);
> > +    }
> > +    netdev_registered_class_unref(rc_to_unref);
> > +    ovs_mutex_unlock(&netdev_mutex);
> > +}

Thanks,

Ben.



More information about the dev mailing list