stale bdev reference in quotactl
PATCH 1/1 stale bdev reference in quotactl
sys_quotacl tries to do a get_super on a struct block_device * to which it doesn't hold a reference (nor does it actually have to be non-NULL).
As lookup bdev by name is a rather common operation I splitted out a new helper, lookup_bdev() that does this out of open_bdev_excl and switched quota.c to use it. lookup_bdev() holds a proper reference that needs to be dropped by bdput(), and it's well documented.
fs/block_dev.c +38 -19
@@ -799,24 +799,20 @@ }/** -* open_bdev_excl - open a block device by name and set it up for use +* lookup_bdev - lookup a struct block_device by name * * @path: special file representing the block device -* @flags: %MS_RDONLY for opening read-only -* @kind: usage (same as the 4th paramter to blkdev_get) -* @holder: owner for exclusion * -* Open the blockdevice described by the special file at @path, claim it -* for the @holder and properly set it up for @kind usage. +* Get a reference to the blockdevice at @path in the current +* namespace if possible and return it. Return ERR_PTR(error) +* otherwise. */ -struct block_device *open_bdev_excl (const char *path,int flags, -int kind,void *holder) +struct block_device *lookup_bdev (const char *path) { -struct inode *inode;struct block_device *bdev; +struct inode *inode;struct nameidata nd; -mode_t mode =FMODE_READ ; -int error =0 ; +int error;if (!path || !*path)return ERR_PTR (-EINVAL );
@@ -828,17 +824,44 @@ inode = nd.dentry->d_inode; error = -ENOTBLK ;if (!S_ISBLK (inode->i_mode)) - goto path_release; + goto fail; error = -EACCES ;if (nd.mnt->mnt_flags &MNT_NODEV ) - goto path_release; + goto fail; error =bd_acquire (inode);if (error) - goto path_release; + goto fail; bdev = inode->i_bdev; -/* Done with lookups */ +out:path_release (&nd); +return bdev; +fail: + bdev =ERR_PTR (error); + goto out; +} + +/** +* open_bdev_excl - open a block device by name and set it up for use +* +* @path: special file representing the block device +* @flags: %MS_RDONLY for opening read-only +* @kind: usage (same as the 4th paramter to blkdev_get) +* @holder: owner for exclusion +* +* Open the blockdevice described by the special file at @path, claim it +* for the @holder and properly set it up for @kind usage. +*/ +struct block_device *open_bdev_excl (const char *path,int flags, +int kind,void *holder) +{ +struct block_device *bdev; +mode_t mode =FMODE_READ ; +int error =0 ; + + bdev =lookup_bdev (path); +if (IS_ERR (bdev)) +return bdev;if (!(flags &MS_RDONLY )) mode |=FMODE_WRITE ;
@@ -856,10 +879,6 @@ blkdev_put:blkdev_put (bdev,BDEV_FS ); -return ERR_PTR (error); - -path_release: -path_release (&nd);return ERR_PTR (error); }
fs/quota.c +14 -40
70 lines not on this page · raw message
include/linux/fs.h +1 -0
@@ -1103,6 +1100,7 @@ {return __bdevname (bdev->bd_dev); } +extern struct block_device *lookup_bdev (const char *);extern struct block_device *open_bdev_excl (const char *,int ,int ,void *);extern void close_bdev_excl (struct block_device *,int );