aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c72
1 files changed, 48 insertions, 24 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 204a7632c511..a1642ef60197 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -706,8 +706,13 @@ retry:
706 * @bdev is about to be opened exclusively. Check @bdev can be opened 706 * @bdev is about to be opened exclusively. Check @bdev can be opened
707 * exclusively and mark that an exclusive open is in progress. Each 707 * exclusively and mark that an exclusive open is in progress. Each
708 * successful call to this function must be matched with a call to 708 * successful call to this function must be matched with a call to
709 * either bd_claim() or bd_abort_claiming(). If this function 709 * either bd_finish_claiming() or bd_abort_claiming() (which do not
710 * succeeds, the matching bd_claim() is guaranteed to succeed. 710 * fail).
711 *
712 * This function is used to gain exclusive access to the block device
713 * without actually causing other exclusive open attempts to fail. It
714 * should be used when the open sequence itself requires exclusive
715 * access but may subsequently fail.
711 * 716 *
712 * CONTEXT: 717 * CONTEXT:
713 * Might sleep. 718 * Might sleep.
@@ -783,15 +788,47 @@ static void bd_abort_claiming(struct block_device *whole, void *holder)
783 __bd_abort_claiming(whole, holder); /* releases bdev_lock */ 788 __bd_abort_claiming(whole, holder); /* releases bdev_lock */
784} 789}
785 790
791/* increment holders when we have a legitimate claim. requires bdev_lock */
792static void __bd_claim(struct block_device *bdev, struct block_device *whole,
793 void *holder)
794{
795 /* note that for a whole device bd_holders
796 * will be incremented twice, and bd_holder will
797 * be set to bd_claim before being set to holder
798 */
799 whole->bd_holders++;
800 whole->bd_holder = bd_claim;
801 bdev->bd_holders++;
802 bdev->bd_holder = holder;
803}
804
805/**
806 * bd_finish_claiming - finish claiming a block device
807 * @bdev: block device of interest (passed to bd_start_claiming())
808 * @whole: whole block device returned by bd_start_claiming()
809 * @holder: holder trying to claim @bdev
810 *
811 * Finish a claiming block started by bd_start_claiming().
812 *
813 * CONTEXT:
814 * Grabs and releases bdev_lock.
815 */
816static void bd_finish_claiming(struct block_device *bdev,
817 struct block_device *whole, void *holder)
818{
819 spin_lock(&bdev_lock);
820 BUG_ON(whole->bd_claiming != holder);
821 BUG_ON(!bd_may_claim(bdev, whole, holder));
822 __bd_claim(bdev, whole, holder);
823 __bd_abort_claiming(whole, holder); /* not actually an abort */
824}
825
786/** 826/**
787 * bd_claim - claim a block device 827 * bd_claim - claim a block device
788 * @bdev: block device to claim 828 * @bdev: block device to claim
789 * @holder: holder trying to claim @bdev 829 * @holder: holder trying to claim @bdev
790 * 830 *
791 * Try to claim @bdev which must have been opened successfully. This 831 * Try to claim @bdev which must have been opened successfully.
792 * function may be called with or without preceding
793 * blk_start_claiming(). In the former case, this function is always
794 * successful and terminates the claiming block.
795 * 832 *
796 * CONTEXT: 833 * CONTEXT:
797 * Might sleep. 834 * Might sleep.
@@ -807,23 +844,10 @@ int bd_claim(struct block_device *bdev, void *holder)
807 might_sleep(); 844 might_sleep();
808 845
809 spin_lock(&bdev_lock); 846 spin_lock(&bdev_lock);
810
811 res = bd_prepare_to_claim(bdev, whole, holder); 847 res = bd_prepare_to_claim(bdev, whole, holder);
812 if (res == 0) { 848 if (res == 0)
813 /* note that for a whole device bd_holders 849 __bd_claim(bdev, whole, holder);
814 * will be incremented twice, and bd_holder will 850 spin_unlock(&bdev_lock);
815 * be set to bd_claim before being set to holder
816 */
817 whole->bd_holders++;
818 whole->bd_holder = bd_claim;
819 bdev->bd_holders++;
820 bdev->bd_holder = holder;
821 }
822
823 if (whole->bd_claiming)
824 __bd_abort_claiming(whole, holder); /* releases bdev_lock */
825 else
826 spin_unlock(&bdev_lock);
827 851
828 return res; 852 return res;
829} 853}
@@ -1477,7 +1501,7 @@ static int blkdev_open(struct inode * inode, struct file * filp)
1477 1501
1478 if (whole) { 1502 if (whole) {
1479 if (res == 0) 1503 if (res == 0)
1480 BUG_ON(bd_claim(bdev, filp) != 0); 1504 bd_finish_claiming(bdev, whole, filp);
1481 else 1505 else
1482 bd_abort_claiming(whole, filp); 1506 bd_abort_claiming(whole, filp);
1483 } 1507 }
@@ -1713,7 +1737,7 @@ struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *h
1713 if ((mode & FMODE_WRITE) && bdev_read_only(bdev)) 1737 if ((mode & FMODE_WRITE) && bdev_read_only(bdev))
1714 goto out_blkdev_put; 1738 goto out_blkdev_put;
1715 1739
1716 BUG_ON(bd_claim(bdev, holder) != 0); 1740 bd_finish_claiming(bdev, whole, holder);
1717 return bdev; 1741 return bdev;
1718 1742
1719out_blkdev_put: 1743out_blkdev_put: