Skip to content

Commit

Permalink
PM / Hibernate: Replace bdget call with simple atomic_inc of i_count
Browse files Browse the repository at this point in the history
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=13827

Signed-off-by: Alan Jenkins <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
Alan Jenkins authored and rjwysocki committed Jul 29, 2009
1 parent ec79be2 commit dddac6a
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 2 deletions.
10 changes: 10 additions & 0 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev)

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)
{
struct block_device *bdev;
Expand Down
1 change: 1 addition & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,7 @@ extern void putname(const char *name);
extern int register_blkdev(unsigned int, const char *);
extern void unregister_blkdev(unsigned int, const char *);
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_forget(struct inode *inode);
extern void bdput(struct block_device *);
Expand Down
4 changes: 2 additions & 2 deletions mm/swapfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)

if (!bdev) {
if (bdev_p)
*bdev_p = bdget(sis->bdev->bd_dev);
*bdev_p = bdgrab(sis->bdev);

spin_unlock(&swap_lock);
return i;
Expand All @@ -765,7 +765,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
struct swap_extent, list);
if (se->start_block == offset) {
if (bdev_p)
*bdev_p = bdget(sis->bdev->bd_dev);
*bdev_p = bdgrab(sis->bdev);

spin_unlock(&swap_lock);
bdput(bdev);
Expand Down

0 comments on commit dddac6a

Please sign in to comment.