On Thu, 16 Feb 2017, Ajay Kaher wrote: > > On Thu, 14 Feb 2017, Alan Stern wrote: > > > > I think Ajay's argument is correct and a patch is needed. But this > > patch misses the race between init_usb_class() and release_usb_class(). > > Thanks Alan for your comments, in patch v2 I have taken care for > release_usb_class() also. Please review again. > > > The basic problem is that reference counting doesn't work when you try > > to use the same global pointer (usb_class) to refer to multiple > > generations of a dynamically allocated entity. We had the same sort of > > problem many years ago with the usb_interface structure (and we > > ultimately fixed it by creating a separate usb_interface_cache > > structure). > > > > The best approach here would be to forget about all the reference > > counting. Get rid of usb_class entirely, and create the "usbmisc" > > class structure just once, when usbcore initializes. Or, if you > > prefer, use a mutex to protect a routine that allocates the class > > structure dynamically, just once. Either way, don't deallocate it > > until usbcore is unloaded. > > usbmisc class creation should not require everytime when USB core > initializes. So better to keep usbmisc class creation as it is. > And to prevent the race conditions just protect it with Mutex locking > as per patch v2. > > thanks, > ajay kaher > > Signed-off-by: Ajay Kaher > > --- > > drivers/usb/core/file.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c > index 822ced9..56a151b 100644 > --- a/drivers/usb/core/file.c > +++ b/drivers/usb/core/file.c > @@ -27,6 +27,7 @@ > #define MAX_USB_MINORS 256 > static const struct file_operations *usb_minors[MAX_USB_MINORS]; > static DECLARE_RWSEM(minor_rwsem); > +static DEFINE_MUTEX(init_usb_class_mutex); > > static int usb_open(struct inode *inode, struct file *file) > { > @@ -102,9 +103,11 @@ static int init_usb_class(void) > static void release_usb_class(struct kref *kref) > { > /* Ok, we cheat as we know we only have one usb_class */ > + mutex_lock(&init_usb_class_mutex); > class_destroy(usb_class->class); > kfree(usb_class); > usb_class = NULL; > + mutex_unlock(&init_usb_class_mutex); > } > > static void destroy_usb_class(void) > @@ -171,7 +174,10 @@ int usb_register_dev(struct usb_interface *intf, > if (intf->minor >= 0) > return -EADDRINUSE; > > + mutex_lock(&init_usb_class_mutex); > retval = init_usb_class(); > + mutex_unlock(&init_usb_class_mutex); > + > if (retval) > return retval; This is not right. What happens if usb_register_dev() runs just before release_usb_class() calls mutex_lock()? Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html