[PATCH] fix for inode leak in rd.c

From: Alexander Viro (viro@math.psu.edu)
Date: Sun Sep 02 2001 - 22:54:04 EST


        Patch removes inode leak in drivers/block/rd.c. Instead of
grabbing an extra reference to inode upon the first open() we pin
down struct block_device - the real object we want to protect.
        Please, apply.

diff -urN S10-pre4/drivers/block/rd.c S10-pre4-rd/drivers/block/rd.c
--- S10-pre4/drivers/block/rd.c Sun Jul 29 01:54:42 2001
+++ S10-pre4-rd/drivers/block/rd.c Sun Sep 2 23:35:46 2001
@@ -100,7 +100,7 @@
 static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */
 static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
 static devfs_handle_t devfs_handle;
-static struct inode *rd_inode[NUM_RAMDISKS]; /* Protected device inodes */
+static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
 
 /*
  * Parameters for the boot-loading of the RAM disk. These are set by
@@ -259,7 +259,7 @@
                         /* special: we want to release the ramdisk memory,
                            it's not like with the other blockdevices where
                            this ioctl only flushes away the buffer cache. */
- if ((atomic_read(&inode->i_bdev->bd_openers) > 2))
+ if ((atomic_read(rd_bdev[minor]->bd_openers) > 2))
                                 return -EBUSY;
                         destroy_buffers(inode->i_rdev);
                         rd_blocksizes[minor] = 0;
@@ -305,7 +305,6 @@
         lock_kernel();
         if (!--initrd_users) {
                 blkdev_put(inode->i_bdev, BDEV_FILE);
- iput(inode);
                 free_initrd_mem(initrd_start, initrd_end);
                 initrd_start = 0;
         }
@@ -324,8 +323,10 @@
 
 static int rd_open(struct inode * inode, struct file * filp)
 {
+ int unit = DEVICE_NR(inode->i_rdev);
+
 #ifdef CONFIG_BLK_DEV_INITRD
- if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) {
+ if (unit == INITRD_MINOR) {
                 if (!initrd_start) return -ENODEV;
                 initrd_users++;
                 filp->f_op = &initrd_fops;
@@ -333,16 +334,15 @@
         }
 #endif
 
- if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
+ if (unit >= NUM_RAMDISKS)
                 return -ENXIO;
 
         /*
          * Immunize device against invalidate_buffers() and prune_icache().
          */
- if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) {
- if (!inode->i_bdev) return -ENXIO;
- if ((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL)
- atomic_inc(&rd_inode[DEVICE_NR(inode->i_rdev)]->i_bdev->bd_openers);
+ if (rd_bdev[unit] == NULL) {
+ rd_bdev[unit] = bdget(kdev_t_to_nr(inode->i_rdev));
+ atomic_inc(&rd_bdev[unit]->bd_openers);
         }
 
         MOD_INC_USE_COUNT;
@@ -369,12 +369,11 @@
         int i;
 
         for (i = 0 ; i < NUM_RAMDISKS; i++) {
- if (rd_inode[i]) {
- /* withdraw invalidate_buffers() and prune_icache() immunity */
- atomic_dec(&rd_inode[i]->i_bdev->bd_openers);
- /* remove stale pointer to module address space */
- rd_inode[i]->i_bdev->bd_op = NULL;
- iput(rd_inode[i]);
+ struct block_device *bdev = rd_bdev[i];
+ rd_bdev[i] = NULL;
+ if (bdev) {
+ blkdev_put(bdev);
+ bdput(bdev);
                 }
                 destroy_buffers(MKDEV(MAJOR_NR, i));
         }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Sep 07 2001 - 21:00:17 EST