On Sun, 17 May 2020 22:45:10 -0400 Yan Zhao <yan.y.zhao@xxxxxxxxx> wrote: > vendor modules call macro module_vfio_pci_register_vendor_handler to > generate module_init and module_exit. > It is necessary to ensure that vendor modules always call > vfio_pci_register_vendor_driver() on driver loading and > vfio_pci_unregister_vendor_driver on driver unloading, > because > (1) at compiling time, there's only a dependency of vendor modules on > vfio_pci. > (2) at runtime, > - vendor modules add refs of vfio_pci on a successful calling of > vfio_pci_register_vendor_driver() and deref of vfio_pci on a > successful calling of vfio_pci_unregister_vendor_driver(). > - vfio_pci only adds refs of vendor module on a successful probe of vendor > driver. > vfio_pci derefs vendor module when unbinding from a device. > > So, after vfio_pci is unbound from a device, the vendor module to that > device is free to get unloaded. However, if that vendor module does not > call vfio_pci_unregister_vendor_driver() in its module_exit, vfio_pci may > hold a stale pointer to vendor module. > > Cc: Kevin Tian <kevin.tian@xxxxxxxxx> > Suggested-by: Alex Williamson <alex.williamson@xxxxxxxxxx> > Signed-off-by: Yan Zhao <yan.y.zhao@xxxxxxxxx> > --- > include/linux/vfio.h | 27 +++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > > diff --git a/include/linux/vfio.h b/include/linux/vfio.h > index 3e53deb012b6..f3746608c2d9 100644 > --- a/include/linux/vfio.h > +++ b/include/linux/vfio.h > @@ -223,4 +223,31 @@ struct vfio_pci_vendor_driver_ops { > }; > int __vfio_pci_register_vendor_driver(struct vfio_pci_vendor_driver_ops *ops); > void vfio_pci_unregister_vendor_driver(struct vfio_device_ops *device_ops); > + > +#define vfio_pci_register_vendor_driver(__name, __probe, __remove, \ > + __device_ops) \ > +static struct vfio_pci_vendor_driver_ops __ops ## _node = { \ > + .owner = THIS_MODULE, \ > + .name = __name, \ > + .probe = __probe, \ > + .remove = __remove, \ > + .device_ops = __device_ops, \ > +}; \ > +__vfio_pci_register_vendor_driver(&__ops ## _node) > + > +#define module_vfio_pci_register_vendor_handler(name, probe, remove, \ > + device_ops) \ > +static int __init device_ops ## _module_init(void) \ > +{ \ > + vfio_pci_register_vendor_driver(name, probe, remove, \ > + device_ops); \ What if this function fails (e.g. with -ENOMEM)? > + return 0; \ > +}; \ > +static void __exit device_ops ## _module_exit(void) \ > +{ \ > + vfio_pci_unregister_vendor_driver(device_ops); \ > +}; \ > +module_init(device_ops ## _module_init); \ > +module_exit(device_ops ## _module_exit) > + > #endif /* VFIO_H */