diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 2a6d0193f139..e59440c7e1cf 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -661,41 +661,70 @@ void bd_forget(struct inode *inode) | |||
661 | iput(bdev->bd_inode); | 661 | iput(bdev->bd_inode); |
662 | } | 662 | } |
663 | 663 | ||
664 | int bd_claim(struct block_device *bdev, void *holder) | 664 | /** |
665 | * bd_may_claim - test whether a block device can be claimed | ||
666 | * @bdev: block device of interest | ||
667 | * @whole: whole block device containing @bdev, may equal @bdev | ||
668 | * @holder: holder trying to claim @bdev | ||
669 | * | ||
670 | * Test whther @bdev can be claimed by @holder. | ||
671 | * | ||
672 | * CONTEXT: | ||
673 | * spin_lock(&bdev_lock). | ||
674 | * | ||
675 | * RETURNS: | ||
676 | * %true if @bdev can be claimed, %false otherwise. | ||
677 | */ | ||
678 | static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, | ||
679 | void *holder) | ||
665 | { | 680 | { |
666 | int res; | ||
667 | spin_lock(&bdev_lock); | ||
668 | |||
669 | /* first decide result */ | ||
670 | if (bdev->bd_holder == holder) | 681 | if (bdev->bd_holder == holder) |
671 | res = 0; /* already a holder */ | 682 | return true; /* already a holder */ |
672 | else if (bdev->bd_holder != NULL) | 683 | else if (bdev->bd_holder != NULL) |
673 | res = -EBUSY; /* held by someone else */ | 684 | return false; /* held by someone else */ |
674 | else if (bdev->bd_contains == bdev) | 685 | else if (bdev->bd_contains == bdev) |
675 | res = 0; /* is a whole device which isn't held */ | 686 | return true; /* is a whole device which isn't held */ |
676 | 687 | ||
677 | else if (bdev->bd_contains->bd_holder == bd_claim) | 688 | else if (whole->bd_holder == bd_claim) |
678 | res = 0; /* is a partition of a device that is being partitioned */ | 689 | return true; /* is a partition of a device that is being partitioned */ |
679 | else if (bdev->bd_contains->bd_holder != NULL) | 690 | else if (whole->bd_holder != NULL) |
680 | res = -EBUSY; /* is a partition of a held device */ | 691 | return false; /* is a partition of a held device */ |
681 | else | 692 | else |
682 | res = 0; /* is a partition of an un-held device */ | 693 | return true; /* is a partition of an un-held device */ |
694 | } | ||
683 | 695 | ||
684 | /* now impose change */ | 696 | /** |
685 | if (res==0) { | 697 | * bd_claim - claim a block device |
698 | * @bdev: block device to claim | ||
699 | * @holder: holder trying to claim @bdev | ||
700 | * | ||
701 | * Try to claim @bdev. | ||
702 | * | ||
703 | * RETURNS: | ||
704 | * 0 if successful, -EBUSY if @bdev is already claimed. | ||
705 | */ | ||
706 | int bd_claim(struct block_device *bdev, void *holder) | ||
707 | { | ||
708 | struct block_device *whole = bdev->bd_contains; | ||
709 | int res = -EBUSY; | ||
710 | |||
711 | spin_lock(&bdev_lock); | ||
712 | |||
713 | if (bd_may_claim(bdev, whole, holder)) { | ||
686 | /* note that for a whole device bd_holders | 714 | /* note that for a whole device bd_holders |
687 | * will be incremented twice, and bd_holder will | 715 | * will be incremented twice, and bd_holder will |
688 | * be set to bd_claim before being set to holder | 716 | * be set to bd_claim before being set to holder |
689 | */ | 717 | */ |
690 | bdev->bd_contains->bd_holders ++; | 718 | whole->bd_holders++; |
691 | bdev->bd_contains->bd_holder = bd_claim; | 719 | whole->bd_holder = bd_claim; |
692 | bdev->bd_holders++; | 720 | bdev->bd_holders++; |
693 | bdev->bd_holder = holder; | 721 | bdev->bd_holder = holder; |
722 | res = 0; | ||
694 | } | 723 | } |
724 | |||
695 | spin_unlock(&bdev_lock); | 725 | spin_unlock(&bdev_lock); |
696 | return res; | 726 | return res; |
697 | } | 727 | } |
698 | |||
699 | EXPORT_SYMBOL(bd_claim); | 728 | EXPORT_SYMBOL(bd_claim); |
700 | 729 | ||
701 | void bd_release(struct block_device *bdev) | 730 | void bd_release(struct block_device *bdev) |