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

ide: fix refcounting in device drivers

During host driver module removal del_gendisk() results in a final
put on drive->gendev and freeing the drive by drive_release_dev().

Convert device drivers from using struct kref to use struct device
so device driver's object holds reference on ->gendev and prevents
drive from prematurely going away.

Also fix ->remove methods to not erroneously drop reference on a
host driver by using only put_device() instead of ide*_put().

Reported-by: Stanislaw Gruszka <stf_xl@wp.pl>
Tested-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>

+57 -31
+18 -9
drivers/ide/ide-cd.c
··· 55 55 56 56 static DEFINE_MUTEX(idecd_ref_mutex); 57 57 58 - static void ide_cd_release(struct kref *); 58 + static void ide_cd_release(struct device *); 59 59 60 60 static struct cdrom_info *ide_cd_get(struct gendisk *disk) 61 61 { ··· 67 67 if (ide_device_get(cd->drive)) 68 68 cd = NULL; 69 69 else 70 - kref_get(&cd->kref); 70 + get_device(&cd->dev); 71 71 72 72 } 73 73 mutex_unlock(&idecd_ref_mutex); ··· 79 79 ide_drive_t *drive = cd->drive; 80 80 81 81 mutex_lock(&idecd_ref_mutex); 82 - kref_put(&cd->kref, ide_cd_release); 82 + put_device(&cd->dev); 83 83 ide_device_put(drive); 84 84 mutex_unlock(&idecd_ref_mutex); 85 85 } ··· 1798 1798 ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); 1799 1799 1800 1800 ide_proc_unregister_driver(drive, info->driver); 1801 - 1801 + device_del(&info->dev); 1802 1802 del_gendisk(info->disk); 1803 1803 1804 - ide_cd_put(info); 1804 + mutex_lock(&idecd_ref_mutex); 1805 + put_device(&info->dev); 1806 + mutex_unlock(&idecd_ref_mutex); 1805 1807 } 1806 1808 1807 - static void ide_cd_release(struct kref *kref) 1809 + static void ide_cd_release(struct device *dev) 1808 1810 { 1809 - struct cdrom_info *info = to_ide_drv(kref, cdrom_info); 1811 + struct cdrom_info *info = to_ide_drv(dev, cdrom_info); 1810 1812 struct cdrom_device_info *devinfo = &info->devinfo; 1811 1813 ide_drive_t *drive = info->drive; 1812 1814 struct gendisk *g = info->disk; ··· 2007 2005 2008 2006 ide_init_disk(g, drive); 2009 2007 2010 - kref_init(&info->kref); 2008 + info->dev.parent = &drive->gendev; 2009 + info->dev.release = ide_cd_release; 2010 + dev_set_name(&info->dev, dev_name(&drive->gendev)); 2011 + 2012 + if (device_register(&info->dev)) 2013 + goto out_free_disk; 2011 2014 2012 2015 info->drive = drive; 2013 2016 info->driver = &ide_cdrom_driver; ··· 2026 2019 g->driverfs_dev = &drive->gendev; 2027 2020 g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; 2028 2021 if (ide_cdrom_setup(drive)) { 2029 - ide_cd_release(&info->kref); 2022 + put_device(&info->dev); 2030 2023 goto failed; 2031 2024 } 2032 2025 ··· 2036 2029 add_disk(g); 2037 2030 return 0; 2038 2031 2032 + out_free_disk: 2033 + put_disk(g); 2039 2034 out_free_cd: 2040 2035 kfree(info); 2041 2036 failed:
+1 -1
drivers/ide/ide-cd.h
··· 80 80 ide_drive_t *drive; 81 81 struct ide_driver *driver; 82 82 struct gendisk *disk; 83 - struct kref kref; 83 + struct device dev; 84 84 85 85 /* Buffer for table of contents. NULL if we haven't allocated 86 86 a TOC buffer for this device yet. */
+17 -9
drivers/ide/ide-gd.c
··· 25 25 26 26 static DEFINE_MUTEX(ide_disk_ref_mutex); 27 27 28 - static void ide_disk_release(struct kref *); 28 + static void ide_disk_release(struct device *); 29 29 30 30 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) 31 31 { ··· 37 37 if (ide_device_get(idkp->drive)) 38 38 idkp = NULL; 39 39 else 40 - kref_get(&idkp->kref); 40 + get_device(&idkp->dev); 41 41 } 42 42 mutex_unlock(&ide_disk_ref_mutex); 43 43 return idkp; ··· 48 48 ide_drive_t *drive = idkp->drive; 49 49 50 50 mutex_lock(&ide_disk_ref_mutex); 51 - kref_put(&idkp->kref, ide_disk_release); 51 + put_device(&idkp->dev); 52 52 ide_device_put(drive); 53 53 mutex_unlock(&ide_disk_ref_mutex); 54 54 } ··· 66 66 struct gendisk *g = idkp->disk; 67 67 68 68 ide_proc_unregister_driver(drive, idkp->driver); 69 - 69 + device_del(&idkp->dev); 70 70 del_gendisk(g); 71 - 72 71 drive->disk_ops->flush(drive); 73 72 74 - ide_disk_put(idkp); 73 + mutex_lock(&ide_disk_ref_mutex); 74 + put_device(&idkp->dev); 75 + mutex_unlock(&ide_disk_ref_mutex); 75 76 } 76 77 77 - static void ide_disk_release(struct kref *kref) 78 + static void ide_disk_release(struct device *dev) 78 79 { 79 - struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj); 80 + struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj); 80 81 ide_drive_t *drive = idkp->drive; 81 82 struct gendisk *g = idkp->disk; 82 83 ··· 349 348 350 349 ide_init_disk(g, drive); 351 350 352 - kref_init(&idkp->kref); 351 + idkp->dev.parent = &drive->gendev; 352 + idkp->dev.release = ide_disk_release; 353 + dev_set_name(&idkp->dev, dev_name(&drive->gendev)); 354 + 355 + if (device_register(&idkp->dev)) 356 + goto out_free_disk; 353 357 354 358 idkp->drive = drive; 355 359 idkp->driver = &ide_gd_driver; ··· 379 373 add_disk(g); 380 374 return 0; 381 375 376 + out_free_disk: 377 + put_disk(g); 382 378 out_free_idkp: 383 379 kfree(idkp); 384 380 failed:
+1 -1
drivers/ide/ide-gd.h
··· 17 17 ide_drive_t *drive; 18 18 struct ide_driver *driver; 19 19 struct gendisk *disk; 20 - struct kref kref; 20 + struct device dev; 21 21 unsigned int openers; /* protected by BKL for now */ 22 22 23 23 /* Last failed packet command */
+19 -10
drivers/ide/ide-tape.c
··· 169 169 ide_drive_t *drive; 170 170 struct ide_driver *driver; 171 171 struct gendisk *disk; 172 - struct kref kref; 172 + struct device dev; 173 173 174 174 /* 175 175 * failed_pc points to the last failed packet command, or contains ··· 267 267 268 268 static struct class *idetape_sysfs_class; 269 269 270 - static void ide_tape_release(struct kref *); 270 + static void ide_tape_release(struct device *); 271 271 272 272 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) 273 273 { ··· 279 279 if (ide_device_get(tape->drive)) 280 280 tape = NULL; 281 281 else 282 - kref_get(&tape->kref); 282 + get_device(&tape->dev); 283 283 } 284 284 mutex_unlock(&idetape_ref_mutex); 285 285 return tape; ··· 290 290 ide_drive_t *drive = tape->drive; 291 291 292 292 mutex_lock(&idetape_ref_mutex); 293 - kref_put(&tape->kref, ide_tape_release); 293 + put_device(&tape->dev); 294 294 ide_device_put(drive); 295 295 mutex_unlock(&idetape_ref_mutex); 296 296 } ··· 308 308 mutex_lock(&idetape_ref_mutex); 309 309 tape = idetape_devs[i]; 310 310 if (tape) 311 - kref_get(&tape->kref); 311 + get_device(&tape->dev); 312 312 mutex_unlock(&idetape_ref_mutex); 313 313 return tape; 314 314 } ··· 2256 2256 idetape_tape_t *tape = drive->driver_data; 2257 2257 2258 2258 ide_proc_unregister_driver(drive, tape->driver); 2259 - 2259 + device_del(&tape->dev); 2260 2260 ide_unregister_region(tape->disk); 2261 2261 2262 - ide_tape_put(tape); 2262 + mutex_lock(&idetape_ref_mutex); 2263 + put_device(&tape->dev); 2264 + mutex_unlock(&idetape_ref_mutex); 2263 2265 } 2264 2266 2265 - static void ide_tape_release(struct kref *kref) 2267 + static void ide_tape_release(struct device *dev) 2266 2268 { 2267 - struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj); 2269 + struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj); 2268 2270 ide_drive_t *drive = tape->drive; 2269 2271 struct gendisk *g = tape->disk; 2270 2272 ··· 2409 2407 2410 2408 ide_init_disk(g, drive); 2411 2409 2412 - kref_init(&tape->kref); 2410 + tape->dev.parent = &drive->gendev; 2411 + tape->dev.release = ide_tape_release; 2412 + dev_set_name(&tape->dev, dev_name(&drive->gendev)); 2413 + 2414 + if (device_register(&tape->dev)) 2415 + goto out_free_disk; 2413 2416 2414 2417 tape->drive = drive; 2415 2418 tape->driver = &idetape_driver; ··· 2443 2436 2444 2437 return 0; 2445 2438 2439 + out_free_disk: 2440 + put_disk(g); 2446 2441 out_free_tape: 2447 2442 kfree(tape); 2448 2443 failed:
+1 -1
include/linux/ide.h
··· 663 663 #define to_ide_device(dev) container_of(dev, ide_drive_t, gendev) 664 664 665 665 #define to_ide_drv(obj, cont_type) \ 666 - container_of(obj, struct cont_type, kref) 666 + container_of(obj, struct cont_type, dev) 667 667 668 668 #define ide_drv_g(disk, cont_type) \ 669 669 container_of((disk)->private_data, struct cont_type, driver)