Commit dddac6a7b445de95515f64fdf82fe5dc36c02f26

Authored by Alan Jenkins
Committed by Rafael J. Wysocki
1 parent ec79be2687

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=13827

Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Showing 3 changed files with 13 additions and 2 deletions Side-by-side Diff

... ... @@ -564,6 +564,16 @@
564 564  
565 565 EXPORT_SYMBOL(bdget);
566 566  
  567 +/**
  568 + * bdgrab -- Grab a reference to an already referenced block device
  569 + * @bdev: Block device to grab a reference to.
  570 + */
  571 +struct block_device *bdgrab(struct block_device *bdev)
  572 +{
  573 + atomic_inc(&bdev->bd_inode->i_count);
  574 + return bdev;
  575 +}
  576 +
567 577 long nr_blockdev_pages(void)
568 578 {
569 579 struct block_device *bdev;
... ... @@ -1946,6 +1946,7 @@
1946 1946 extern int register_blkdev(unsigned int, const char *);
1947 1947 extern void unregister_blkdev(unsigned int, const char *);
1948 1948 extern struct block_device *bdget(dev_t);
  1949 +extern struct block_device *bdgrab(struct block_device *bdev);
1949 1950 extern void bd_set_size(struct block_device *, loff_t size);
1950 1951 extern void bd_forget(struct inode *inode);
1951 1952 extern void bdput(struct block_device *);
... ... @@ -753,7 +753,7 @@
753 753  
754 754 if (!bdev) {
755 755 if (bdev_p)
756   - *bdev_p = bdget(sis->bdev->bd_dev);
  756 + *bdev_p = bdgrab(sis->bdev);
757 757  
758 758 spin_unlock(&swap_lock);
759 759 return i;
... ... @@ -765,7 +765,7 @@
765 765 struct swap_extent, list);
766 766 if (se->start_block == offset) {
767 767 if (bdev_p)
768   - *bdev_p = bdget(sis->bdev->bd_dev);
  768 + *bdev_p = bdgrab(sis->bdev);
769 769  
770 770 spin_unlock(&swap_lock);
771 771 bdput(bdev);