RE: [PATCHv4 3/3] vfio/mdev: Synchronize device create/remove with parent removal

From: Parav Pandit
Date: Thu May 30 2019 - 05:02:33 EST


Hi Alex,

> -----Original Message-----
> From: Alex Williamson <alex.williamson@xxxxxxxxxx>
> Sent: Wednesday, May 29, 2019 8:27 PM

[..]
> >
> > diff --git a/drivers/vfio/mdev/mdev_core.c
> > b/drivers/vfio/mdev/mdev_core.c index 0bef0cae1d4b..c5401a8c6843
> > 100644
> > --- a/drivers/vfio/mdev/mdev_core.c
> > +++ b/drivers/vfio/mdev/mdev_core.c
> > @@ -102,11 +102,36 @@ static void mdev_put_parent(struct mdev_parent
> *parent)
> > kref_put(&parent->ref, mdev_release_parent); }
> >
>
> Some sort of locking semantics comment would be useful here, ex:
>
> /* Caller holds parent unreg_sem read or write lock */
>
Added.

> > +
> > static int mdev_device_remove_cb(struct device *dev, void *data) {
> > - if (dev_is_mdev(dev))
> > - mdev_device_remove(dev);
> > + struct mdev_parent *parent;
> > + struct mdev_device *mdev;
> >
> > + if (!dev_is_mdev(dev))
> > + return 0;
> > +
> > + mdev = to_mdev_device(dev);
> > + parent = mdev->parent;
> > + mdev_device_remove_common(mdev);
>
> 'parent' is unused here and we only use mdev once, so we probably don't need
> to put it in a local variable.
>
Right left out from previous code.
Removed and refactored the code now.

> > return 0;
> > }
> >
> > @@ -148,6 +173,7 @@ int mdev_register_device(struct device *dev, const
> struct mdev_parent_ops *ops)
> > }
> >
> > kref_init(&parent->ref);
> > + init_rwsem(&parent->unreg_sem);
> >
> > parent->dev = dev;
> > parent->ops = ops;
> > @@ -206,13 +232,17 @@ void mdev_unregister_device(struct device *dev)
> > dev_info(dev, "MDEV: Unregistering\n");
> >
> > list_del(&parent->next);
> > + mutex_unlock(&parent_list_lock);
> > +
> > + down_write(&parent->unreg_sem);
> > +
> > class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
> >
> > device_for_each_child(dev, NULL, mdev_device_remove_cb);
> >
> > parent_remove_sysfs_files(parent);
> > + up_write(&parent->unreg_sem);
> >
> > - mutex_unlock(&parent_list_lock);
> > mdev_put_parent(parent);
> > }
> > EXPORT_SYMBOL(mdev_unregister_device);
> > @@ -265,6 +295,12 @@ int mdev_device_create(struct kobject *kobj,
> >
> > mdev->parent = parent;
> >
> > + ret = down_read_trylock(&parent->unreg_sem);
> > + if (!ret) {
> > + ret = -ENODEV;
>
> I would have expected -EAGAIN or -EBUSY here, but I guess that since we
> consider the lock-out to deterministically be the parent going away that -
> ENODEV makes sense. Ok.
>
Yeah, I agree that ENODEV is more accurate error code as we don't want to tell user to retry so EAGAIN is less appropriate.
Sending v5.