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.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b54b0a1b7c68..aaa8301f43f1 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -642,16 +642,38 @@ static void free_bd_holder(struct bd_holder *bo)
642} 642}
643 643
644/** 644/**
645 * find_bd_holder - find matching struct bd_holder from the block device
646 *
647 * @bdev: struct block device to be searched
648 * @bo: target struct bd_holder
649 *
650 * Returns matching entry with @bo in @bdev->bd_holder_list.
651 * If found, increment the reference count and return the pointer.
652 * If not found, returns NULL.
653 */
654static int find_bd_holder(struct block_device *bdev, struct bd_holder *bo)
655{
656 struct bd_holder *tmp;
657
658 list_for_each_entry(tmp, &bdev->bd_holder_list, list)
659 if (tmp->sdir == bo->sdir) {
660 tmp->count++;
661 return tmp;
662 }
663
664 return NULL;
665}
666
667/**
645 * add_bd_holder - create sysfs symlinks for bd_claim() relationship 668 * add_bd_holder - create sysfs symlinks for bd_claim() relationship
646 * 669 *
647 * @bdev: block device to be bd_claimed 670 * @bdev: block device to be bd_claimed
648 * @bo: preallocated and initialized by alloc_bd_holder() 671 * @bo: preallocated and initialized by alloc_bd_holder()
649 * 672 *
650 * If there is no matching entry with @bo in @bdev->bd_holder_list, 673 * Add @bo to @bdev->bd_holder_list, create symlinks.
651 * add @bo to the list, create symlinks.
652 * 674 *
653 * Returns 0 if symlinks are created or already there. 675 * Returns 0 if symlinks are created.
654 * Returns -ve if something fails and @bo can be freed. 676 * Returns -ve if something fails.
655 */ 677 */
656static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) 678static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
657{ 679{
@@ -661,15 +683,6 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
661 if (!bo) 683 if (!bo)
662 return -EINVAL; 684 return -EINVAL;
663 685
664 list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
665 if (tmp->sdir == bo->sdir) {
666 tmp->count++;
667 /* We've already done what we need to do here. */
668 free_bd_holder(bo);
669 return 0;
670 }
671 }
672
673 if (!bd_holder_grab_dirs(bdev, bo)) 686 if (!bd_holder_grab_dirs(bdev, bo))
674 return -EBUSY; 687 return -EBUSY;
675 688
@@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
740 struct kobject *kobj) 753 struct kobject *kobj)
741{ 754{
742 int res; 755 int res;
743 struct bd_holder *bo; 756 struct bd_holder *bo, *found;
744 757
745 if (!kobj) 758 if (!kobj)
746 return -EINVAL; 759 return -EINVAL;
@@ -752,11 +765,15 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
752 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); 765 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
753 res = bd_claim(bdev, holder); 766 res = bd_claim(bdev, holder);
754 if (res == 0) { 767 if (res == 0) {
755 res = add_bd_holder(bdev, bo); 768 found = find_bd_holder(bdev, bo);
756 if (res) 769 if (found == NULL) {
757 bd_release(bdev); 770 res = add_bd_holder(bdev, bo);
771 if (res)
772 bd_release(bdev);
773 }
758 } 774 }
759 if (res) 775
776 if (res || found)
760 free_bd_holder(bo); 777 free_bd_holder(bo);
761 mutex_unlock(&bdev->bd_mutex); 778 mutex_unlock(&bdev->bd_mutex);
762 779