* Bug fixes for floppy driver @ 2012-08-08 18:24 Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 1/2] floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 2/2] floppy: error handling fixes on do_floppy_init Herton Ronaldo Krzesinski 0 siblings, 2 replies; 5+ messages in thread From: Herton Ronaldo Krzesinski @ 2012-08-08 18:24 UTC (permalink / raw) To: Jiri Kosina Cc: Andrew Morton, Jens Axboe, Tejun Heo, linux-kernel, Vivek Goyal, Ben Hutchings Following this are two fixes for bugs I noticed on floppy driver. -- []'s Herton ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop 2012-08-08 18:24 Bug fixes for floppy driver Herton Ronaldo Krzesinski @ 2012-08-08 18:24 ` Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 2/2] floppy: error handling fixes on do_floppy_init Herton Ronaldo Krzesinski 1 sibling, 0 replies; 5+ messages in thread From: Herton Ronaldo Krzesinski @ 2012-08-08 18:24 UTC (permalink / raw) To: Jiri Kosina Cc: Andrew Morton, Jens Axboe, Tejun Heo, linux-kernel, Vivek Goyal, Ben Hutchings Since commit 070ad7e ("floppy: convert to delayed work and single-thread wq"), we end up calling alloc_ordered_workqueue multiple times inside the loop, which shouldn't be intended. Besides the leak, other side effect in the current code is if blk_init_queue fails, we would end up calling unregister_blkdev even if we didn't call yet register_blkdev. Just moved the allocation of floppy_wq before the loop, and adjusted the code accordingly. Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> Cc: stable@vger.kernel.org # 3.5+ --- drivers/block/floppy.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a7d6347..c8d9e68 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4138,6 +4138,10 @@ static int __init do_floppy_init(void) raw_cmd = NULL; + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) + return -ENOMEM; + for (dr = 0; dr < N_DRIVE; dr++) { disks[dr] = alloc_disk(1); if (!disks[dr]) { @@ -4145,16 +4149,10 @@ static int __init do_floppy_init(void) goto out_put_disk; } - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) { - err = -ENOMEM; - goto out_put_disk; - } - disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { err = -ENOMEM; - goto out_destroy_workq; + goto out_put_disk; } blk_queue_max_hw_sectors(disks[dr]->queue, 64); @@ -4318,8 +4316,6 @@ out_release_dma: out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); platform_driver_unregister(&floppy_driver); -out_destroy_workq: - destroy_workqueue(floppy_wq); out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: @@ -4335,6 +4331,7 @@ out_put_disk: } put_disk(disks[dr]); } + destroy_workqueue(floppy_wq); return err; } -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] floppy: error handling fixes on do_floppy_init 2012-08-08 18:24 Bug fixes for floppy driver Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 1/2] floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop Herton Ronaldo Krzesinski @ 2012-08-08 18:24 ` Herton Ronaldo Krzesinski 2012-08-08 19:57 ` Vivek Goyal 1 sibling, 1 reply; 5+ messages in thread From: Herton Ronaldo Krzesinski @ 2012-08-08 18:24 UTC (permalink / raw) To: Jiri Kosina Cc: Andrew Morton, Jens Axboe, Tejun Heo, linux-kernel, Vivek Goyal, Ben Hutchings While looking at commit 3f9a5aa ("floppy: Cleanup disk->queue before caling put_disk() if add_disk() was never called") I noticed some problems with the error handling and cleanup: * missing cleanup (put_disk) if blk_init_queue fails, dr is decremented first in the error handling loop * if something fails in the add_disk loop, there is no cleanup of previous iterations in the error handling. * "if (disks[dr]->queue)" check is bogus, when reaching there for each dr should exist an queue allocated, and it doesn't take into account iterations where add_disk wasn't done, if failure happens in add_disk loop. * floppy_module_exit doesn't reset queue pointer if add_disk wasn't done. Later commit 4609dff (floppy: Fix a crash during rmmod) fixed the last item, this change should handle the remaining problems on do_floppy_init. Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> Cc: stable@vger.kernel.org --- drivers/block/floppy.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index c8d9e68..0854113 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4127,6 +4127,7 @@ static int __init do_floppy_init(void) { int i, unit, drive; int err, dr; + int registered = -1; set_debugt(); interruptjiffies = resultjiffies = jiffies; @@ -4151,6 +4152,7 @@ static int __init do_floppy_init(void) disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { + put_disk(disks[dr]); err = -ENOMEM; goto out_put_disk; } @@ -4292,7 +4294,7 @@ static int __init do_floppy_init(void) err = platform_device_register(&floppy_device[drive]); if (err) - goto out_release_dma; + goto out_remove_drives; err = device_create_file(&floppy_device[drive].dev, &dev_attr_cmos); @@ -4310,6 +4312,16 @@ static int __init do_floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); +out_remove_drives: + registered = drive - 1; + while (drive--) { + if ((allowed_drive_mask & (1 << drive)) && + fdc_state[FDC(drive)].version != FDC_NONE) { + del_gendisk(disks[drive]); + device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); + platform_device_unregister(&floppy_device[drive]); + } + } out_release_dma: if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); @@ -4321,14 +4333,14 @@ out_unreg_blkdev: out_put_disk: while (dr--) { del_timer_sync(&motor_off_timer[dr]); - if (disks[dr]->queue) { - blk_cleanup_queue(disks[dr]->queue); - /* - * put_disk() is not paired with add_disk() and - * will put queue reference one extra time. fix it. - */ + blk_cleanup_queue(disks[dr]->queue); + /* + * put_disk() may not be paired with add_disk() and + * will put queue reference one extra time. fix it. + */ + if (dr > registered || !(allowed_drive_mask & (1 << dr)) || + fdc_state[FDC(dr)].version == FDC_NONE) disks[dr]->queue = NULL; - } put_disk(disks[dr]); } destroy_workqueue(floppy_wq); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] floppy: error handling fixes on do_floppy_init 2012-08-08 18:24 ` [PATCH 2/2] floppy: error handling fixes on do_floppy_init Herton Ronaldo Krzesinski @ 2012-08-08 19:57 ` Vivek Goyal 2012-08-09 17:32 ` Herton Ronaldo Krzesinski 0 siblings, 1 reply; 5+ messages in thread From: Vivek Goyal @ 2012-08-08 19:57 UTC (permalink / raw) To: Herton Ronaldo Krzesinski Cc: Jiri Kosina, Andrew Morton, Jens Axboe, Tejun Heo, linux-kernel, Ben Hutchings On Wed, Aug 08, 2012 at 03:24:53PM -0300, Herton Ronaldo Krzesinski wrote: > While looking at commit 3f9a5aa ("floppy: Cleanup disk->queue before > caling put_disk() if add_disk() was never called") I noticed some > problems with the error handling and cleanup: > > * missing cleanup (put_disk) if blk_init_queue fails, dr is decremented > first in the error handling loop > * if something fails in the add_disk loop, there is no cleanup of > previous iterations in the error handling. > * "if (disks[dr]->queue)" check is bogus, when reaching there for each > dr should exist an queue allocated, and it doesn't take into account > iterations where add_disk wasn't done, if failure happens in add_disk > loop. > * floppy_module_exit doesn't reset queue pointer if add_disk wasn't > done. Hey, these seem to be multiple cleanups. Can you break these down into individual patches. Review becomes easy. [..] > + blk_cleanup_queue(disks[dr]->queue); > + /* > + * put_disk() may not be paired with add_disk() and > + * will put queue reference one extra time. fix it. > + */ > + if (dr > registered || !(allowed_drive_mask & (1 << dr)) || > + fdc_state[FDC(dr)].version == FDC_NONE) > disks[dr]->queue = NULL; I think checking for FDC_NONE and allowed_drive_mask() in multiple places is becoming unreadable now. Can we just maintain a separate array to keep track of disks on which we have called add_disk() and do the cleanup accordingly. static unsigned short disk_registered[N_DRIVE]; /* do add_disk */ disk_registered[drive] = 1; out_put_disk: while(dr--) { if (disks[dr]->queue && !disk_registered[dr]) { blk_cleanup_queue() disks[dr]->queue = NULL; } } Same disk_registered[] can be used for your other loop of remove drives. Also it can be used in cleaning up code in floppy_module_exit(). I think this will make code much more readable. Right now this error handling loop is just getting too complicated. Thanks Vivek ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] floppy: error handling fixes on do_floppy_init 2012-08-08 19:57 ` Vivek Goyal @ 2012-08-09 17:32 ` Herton Ronaldo Krzesinski 0 siblings, 0 replies; 5+ messages in thread From: Herton Ronaldo Krzesinski @ 2012-08-09 17:32 UTC (permalink / raw) To: Vivek Goyal Cc: Jiri Kosina, Andrew Morton, Jens Axboe, Tejun Heo, linux-kernel, Ben Hutchings On Wed, Aug 08, 2012 at 03:57:30PM -0400, Vivek Goyal wrote: > On Wed, Aug 08, 2012 at 03:24:53PM -0300, Herton Ronaldo Krzesinski wrote: > > While looking at commit 3f9a5aa ("floppy: Cleanup disk->queue before > > caling put_disk() if add_disk() was never called") I noticed some > > problems with the error handling and cleanup: > > > > * missing cleanup (put_disk) if blk_init_queue fails, dr is decremented > > first in the error handling loop > > * if something fails in the add_disk loop, there is no cleanup of > > previous iterations in the error handling. > > * "if (disks[dr]->queue)" check is bogus, when reaching there for each > > dr should exist an queue allocated, and it doesn't take into account > > iterations where add_disk wasn't done, if failure happens in add_disk > > loop. > > * floppy_module_exit doesn't reset queue pointer if add_disk wasn't > > done. > > Hey, these seem to be multiple cleanups. Can you break these down into > individual patches. Review becomes easy. I'll resend with the fixes broken up. > > [..] > > + blk_cleanup_queue(disks[dr]->queue); > > + /* > > + * put_disk() may not be paired with add_disk() and > > + * will put queue reference one extra time. fix it. > > + */ > > + if (dr > registered || !(allowed_drive_mask & (1 << dr)) || > > + fdc_state[FDC(dr)].version == FDC_NONE) > > disks[dr]->queue = NULL; > > I think checking for FDC_NONE and allowed_drive_mask() in multiple places > is becoming unreadable now. Can we just maintain a separate array to keep > track of disks on which we have called add_disk() and do the cleanup > accordingly. > > static unsigned short disk_registered[N_DRIVE]; > > /* do add_disk */ > disk_registered[drive] = 1; > > > out_put_disk: > while(dr--) { > if (disks[dr]->queue && !disk_registered[dr]) { > blk_cleanup_queue() > disks[dr]->queue = NULL; > } > } > > Same disk_registered[] can be used for your other loop of remove drives. > Also it can be used in cleaning up code in floppy_module_exit(). > > I think this will make code much more readable. Right now this error > handling loop is just getting too complicated. Complicated as many other code in the kernel :), but yes, we can do better here, your proposed solution looks good, I'll redo the changes with it, thanks for the review. > > Thanks > Vivek > -- []'s Herton ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-08-09 17:33 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-08-08 18:24 Bug fixes for floppy driver Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 1/2] floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop Herton Ronaldo Krzesinski 2012-08-08 18:24 ` [PATCH 2/2] floppy: error handling fixes on do_floppy_init Herton Ronaldo Krzesinski 2012-08-08 19:57 ` Vivek Goyal 2012-08-09 17:32 ` Herton Ronaldo Krzesinski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox