Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Driver core: driver_find() drops reference before returning

As part of the removal of get_driver()/put_driver(), this patch
(as1510) changes driver_find(); it now drops the reference it acquires
before returning. The patch also adjusts all the callers of
driver_find() to remove the now unnecessary calls to put_driver().

In addition, the patch adds a warning to driver_find(): Callers must
make sure the driver they are searching for does not get unloaded
while they are using it. This has always been the case; driver_find()
has never prevented a driver from being unregistered or unloaded.
Hence the patch will not introduce any new bugs. The existing callers
all seem to be okay in this respect, however I don't understand the
video drivers well enough to be certain about them.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Dmitry Torokhov <dmitry.torokhov@gmail.com>
CC: Kyungmin Park <kyungmin.park@samsung.com>
CC: Andy Walls <awalls@md.metrocast.net>
CC: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
fde25a9b 2b31594a

+10 -17
+5 -2
drivers/base/driver.c
··· 234 234 235 235 other = driver_find(drv->name, drv->bus); 236 236 if (other) { 237 - put_driver(other); 238 237 printk(KERN_ERR "Error: Driver '%s' is already registered, " 239 238 "aborting...\n", drv->name); 240 239 return -EBUSY; ··· 274 275 * Call kset_find_obj() to iterate over list of drivers on 275 276 * a bus to find driver by name. Return driver if found. 276 277 * 277 - * Note that kset_find_obj increments driver's reference count. 278 + * This routine provides no locking to prevent the driver it returns 279 + * from being unregistered or unloaded while the caller is using it. 280 + * The caller is responsible for preventing this. 278 281 */ 279 282 struct device_driver *driver_find(const char *name, struct bus_type *bus) 280 283 { ··· 284 283 struct driver_private *priv; 285 284 286 285 if (k) { 286 + /* Drop reference added by kset_find_obj() */ 287 + kobject_put(k); 287 288 priv = to_driver(k); 288 289 return priv->driver; 289 290 }
-1
drivers/input/gameport/gameport.c
··· 449 449 } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { 450 450 gameport_disconnect_port(gameport); 451 451 error = gameport_bind_driver(gameport, to_gameport_driver(drv)); 452 - put_driver(drv); 453 452 } else { 454 453 error = -EINVAL; 455 454 }
-1
drivers/input/serio/serio.c
··· 441 441 } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { 442 442 serio_disconnect_port(serio); 443 443 error = serio_bind_driver(serio, to_serio_driver(drv)); 444 - put_driver(drv); 445 444 serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); 446 445 } else { 447 446 error = -EINVAL;
-1
drivers/media/video/cx18/cx18-alsa-main.c
··· 285 285 286 286 drv = driver_find("cx18", &pci_bus_type); 287 287 ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); 288 - put_driver(drv); 289 288 290 289 cx18_ext_init = NULL; 291 290 printk(KERN_INFO "cx18-alsa: module unload complete\n");
-2
drivers/media/video/ivtv/ivtvfb.c
··· 1293 1293 1294 1294 drv = driver_find("ivtv", &pci_bus_type); 1295 1295 err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init); 1296 - put_driver(drv); 1297 1296 if (!registered) { 1298 1297 printk(KERN_ERR "ivtvfb: no cards found\n"); 1299 1298 return -ENODEV; ··· 1309 1310 1310 1311 drv = driver_find("ivtv", &pci_bus_type); 1311 1312 err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); 1312 - put_driver(drv); 1313 1313 } 1314 1314 1315 1315 module_init(ivtvfb_init);
+1 -4
drivers/media/video/s5p-fimc/fimc-mdevice.c
··· 344 344 return -ENODEV; 345 345 ret = driver_for_each_device(driver, NULL, fmd, 346 346 fimc_register_callback); 347 - put_driver(driver); 348 347 if (ret) 349 348 return ret; 350 349 351 350 driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); 352 - if (driver) { 351 + if (driver) 353 352 ret = driver_for_each_device(driver, NULL, fmd, 354 353 csis_register_callback); 355 - put_driver(driver); 356 - } 357 354 return ret; 358 355 } 359 356
-1
drivers/media/video/s5p-tv/mixer_video.c
··· 58 58 } 59 59 60 60 done: 61 - put_driver(drv); 62 61 return sd; 63 62 } 64 63
+4 -5
drivers/s390/net/smsgiucv_app.c
··· 168 168 rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); 169 169 if (rc) { 170 170 kfree(smsg_app_dev); 171 - goto fail_put_driver; 171 + goto fail; 172 172 } 173 173 smsg_app_dev->bus = &iucv_bus; 174 174 smsg_app_dev->parent = iucv_root; ··· 177 177 rc = device_register(smsg_app_dev); 178 178 if (rc) { 179 179 put_device(smsg_app_dev); 180 - goto fail_put_driver; 180 + goto fail; 181 181 } 182 182 183 183 /* convert sender to uppercase characters */ ··· 191 191 rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); 192 192 if (rc) { 193 193 device_unregister(smsg_app_dev); 194 - goto fail_put_driver; 194 + goto fail; 195 195 } 196 196 197 197 rc = 0; 198 - fail_put_driver: 199 - put_driver(smsgiucv_drv); 198 + fail: 200 199 return rc; 201 200 } 202 201 module_init(smsgiucv_app_init);