From: Mike Christie <michaelc@cs.wisc.edu>

The ram disk driver allocates its queue but never releases it.  The
attached patch fixes this in the module exit case, and during
initialization failures.



---

 drivers/block/rd.c |   48 +++++++++++++++++++++++++-----------------------
 1 files changed, 25 insertions(+), 23 deletions(-)

diff -puN drivers/block/rd.c~ramdisk-leak-fix drivers/block/rd.c
--- 25/drivers/block/rd.c~ramdisk-leak-fix	2004-01-07 19:09:36.000000000 -0800
+++ 25-akpm/drivers/block/rd.c	2004-01-07 19:09:36.000000000 -0800
@@ -307,6 +307,7 @@ static void __exit rd_cleanup (void)
 			invalidate_bdev(bdev, 1);
 			blkdev_put(bdev, BDEV_FILE);
 		}
+		blk_put_queue(rd_queue[i]);
 		del_gendisk(rd_disks[i]);
 		put_disk(rd_disks[i]);
 	}
@@ -327,36 +328,32 @@ static int __init rd_init (void)
 		rd_blocksize = BLOCK_SIZE;
 	}
 
-	for (i = 0; i < NUM_RAMDISKS; i++) {
-		rd_disks[i] = alloc_disk(1);
-		if (!rd_disks[i])
-			goto out;
-	}
-
-	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
-		err = -EIO;
-		goto out;
-	}
+	if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
+		return -EIO;
 
 	devfs_mk_dir("rd");
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
-		struct gendisk *disk = rd_disks[i];
-
 		rd_queue[i] = blk_alloc_queue(GFP_KERNEL);
 		if (!rd_queue[i])
-			goto out_queue;
+			goto out;
 
 		blk_queue_make_request(rd_queue[i], &rd_make_request);
 
+		rd_disks[i] = alloc_disk(1);
+		if (!rd_disks[i]) {
+			blk_put_queue(rd_queue[i]);
+			goto out;
+		}
+
 		/* rd_size is given in kB */
-		disk->major = RAMDISK_MAJOR;
-		disk->first_minor = i;
-		disk->fops = &rd_bd_op;
-		disk->queue = rd_queue[i];
-		sprintf(disk->disk_name, "ram%d", i);
-		sprintf(disk->devfs_name, "rd/%d", i);
-		set_capacity(disk, rd_size * 2);
+		rd_disks[i]->major = RAMDISK_MAJOR;
+		rd_disks[i]->first_minor = i;
+		rd_disks[i]->fops = &rd_bd_op;
+		rd_disks[i]->queue = rd_queue[i];
+		sprintf(rd_disks[i]->disk_name, "ram%d", i);
+		sprintf(rd_disks[i]->devfs_name, "rd/%d", i);
+		set_capacity(rd_disks[i], rd_size * 2);
 		add_disk(rd_disks[i]);
 	}
 
@@ -366,11 +363,16 @@ static int __init rd_init (void)
 	       NUM_RAMDISKS, rd_size, rd_blocksize);
 
 	return 0;
-out_queue:
-	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
 out:
-	while (i--)
+	for (i--; i >= 0; i--) {
+		blk_put_queue(rd_queue[i]);
+		del_gendisk(rd_disks[i]);
 		put_disk(rd_disks[i]);
+	}
+
+	devfs_remove("rd");
+	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
+
 	return err;
 }
 

_