diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-02-25 14:28:24 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-02-25 14:28:24 -0500 |
commit | 8fed43684174b68f04d01d1210fd00536af790df (patch) | |
tree | df8d5f87c68526267d0ae320173814ed3f417fd5 /drivers/ide/ide-cd.c | |
parent | d3dd7107f4d843d0f01d0f77d49a7c5449130577 (diff) |
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>
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 690475b834de..ddfbea41d296 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -55,7 +55,7 @@ | |||
55 | 55 | ||
56 | static DEFINE_MUTEX(idecd_ref_mutex); | 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 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) | 60 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) |
61 | { | 61 | { |
@@ -67,7 +67,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk) | |||
67 | if (ide_device_get(cd->drive)) | 67 | if (ide_device_get(cd->drive)) |
68 | cd = NULL; | 68 | cd = NULL; |
69 | else | 69 | else |
70 | kref_get(&cd->kref); | 70 | get_device(&cd->dev); |
71 | 71 | ||
72 | } | 72 | } |
73 | mutex_unlock(&idecd_ref_mutex); | 73 | mutex_unlock(&idecd_ref_mutex); |
@@ -79,7 +79,7 @@ static void ide_cd_put(struct cdrom_info *cd) | |||
79 | ide_drive_t *drive = cd->drive; | 79 | ide_drive_t *drive = cd->drive; |
80 | 80 | ||
81 | mutex_lock(&idecd_ref_mutex); | 81 | mutex_lock(&idecd_ref_mutex); |
82 | kref_put(&cd->kref, ide_cd_release); | 82 | put_device(&cd->dev); |
83 | ide_device_put(drive); | 83 | ide_device_put(drive); |
84 | mutex_unlock(&idecd_ref_mutex); | 84 | mutex_unlock(&idecd_ref_mutex); |
85 | } | 85 | } |
@@ -1798,15 +1798,17 @@ static void ide_cd_remove(ide_drive_t *drive) | |||
1798 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | 1798 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); |
1799 | 1799 | ||
1800 | ide_proc_unregister_driver(drive, info->driver); | 1800 | ide_proc_unregister_driver(drive, info->driver); |
1801 | 1801 | device_del(&info->dev); | |
1802 | del_gendisk(info->disk); | 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 | struct cdrom_device_info *devinfo = &info->devinfo; | 1812 | struct cdrom_device_info *devinfo = &info->devinfo; |
1811 | ide_drive_t *drive = info->drive; | 1813 | ide_drive_t *drive = info->drive; |
1812 | struct gendisk *g = info->disk; | 1814 | struct gendisk *g = info->disk; |
@@ -2005,7 +2007,12 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
2005 | 2007 | ||
2006 | ide_init_disk(g, drive); | 2008 | ide_init_disk(g, drive); |
2007 | 2009 | ||
2008 | kref_init(&info->kref); | 2010 | info->dev.parent = &drive->gendev; |
2011 | info->dev.release = ide_cd_release; | ||
2012 | dev_set_name(&info->dev, dev_name(&drive->gendev)); | ||
2013 | |||
2014 | if (device_register(&info->dev)) | ||
2015 | goto out_free_disk; | ||
2009 | 2016 | ||
2010 | info->drive = drive; | 2017 | info->drive = drive; |
2011 | info->driver = &ide_cdrom_driver; | 2018 | info->driver = &ide_cdrom_driver; |
@@ -2019,7 +2026,7 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
2019 | g->driverfs_dev = &drive->gendev; | 2026 | g->driverfs_dev = &drive->gendev; |
2020 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; | 2027 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; |
2021 | if (ide_cdrom_setup(drive)) { | 2028 | if (ide_cdrom_setup(drive)) { |
2022 | ide_cd_release(&info->kref); | 2029 | put_device(&info->dev); |
2023 | goto failed; | 2030 | goto failed; |
2024 | } | 2031 | } |
2025 | 2032 | ||
@@ -2029,6 +2036,8 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
2029 | add_disk(g); | 2036 | add_disk(g); |
2030 | return 0; | 2037 | return 0; |
2031 | 2038 | ||
2039 | out_free_disk: | ||
2040 | put_disk(g); | ||
2032 | out_free_cd: | 2041 | out_free_cd: |
2033 | kfree(info); | 2042 | kfree(info); |
2034 | failed: | 2043 | failed: |