Commit dddac6a7 authored by Alan Jenkins's avatar Alan Jenkins Committed by Rafael J. Wysocki

PM / Hibernate: Replace bdget call with simple atomic_inc of i_count

Create bdgrab().  This function copies an existing reference to a
block_device.  It is safe to call from any context.

Hibernation code wishes to copy a reference to the active swap device.
Right now it calls bdget() under a spinlock, but this is wrong because
bdget() can sleep.  It doesn't need a full bdget() because we already
hold a reference to active swap devices (and the spinlock protects
against swapoff).

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13827Signed-off-by: default avatarAlan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
parent ec79be26
...@@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev) ...@@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev)
EXPORT_SYMBOL(bdget); EXPORT_SYMBOL(bdget);
/**
* bdgrab -- Grab a reference to an already referenced block device
* @bdev: Block device to grab a reference to.
*/
struct block_device *bdgrab(struct block_device *bdev)
{
atomic_inc(&bdev->bd_inode->i_count);
return bdev;
}
long nr_blockdev_pages(void) long nr_blockdev_pages(void)
{ {
struct block_device *bdev; struct block_device *bdev;
......
...@@ -1946,6 +1946,7 @@ extern void putname(const char *name); ...@@ -1946,6 +1946,7 @@ extern void putname(const char *name);
extern int register_blkdev(unsigned int, const char *); extern int register_blkdev(unsigned int, const char *);
extern void unregister_blkdev(unsigned int, const char *); extern void unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t); extern struct block_device *bdget(dev_t);
extern struct block_device *bdgrab(struct block_device *bdev);
extern void bd_set_size(struct block_device *, loff_t size); extern void bd_set_size(struct block_device *, loff_t size);
extern void bd_forget(struct inode *inode); extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *); extern void bdput(struct block_device *);
......
...@@ -753,7 +753,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) ...@@ -753,7 +753,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
if (!bdev) { if (!bdev) {
if (bdev_p) if (bdev_p)
*bdev_p = bdget(sis->bdev->bd_dev); *bdev_p = bdgrab(sis->bdev);
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
return i; return i;
...@@ -765,7 +765,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) ...@@ -765,7 +765,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
struct swap_extent, list); struct swap_extent, list);
if (se->start_block == offset) { if (se->start_block == offset) {
if (bdev_p) if (bdev_p)
*bdev_p = bdget(sis->bdev->bd_dev); *bdev_p = bdgrab(sis->bdev);
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
bdput(bdev); bdput(bdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment