public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* 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