aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/block_dev.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 045f98854f14..8cc144ffc382 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -543,11 +543,11 @@ static struct kobject *bdev_get_holder(struct block_device *bdev)
543 return kobject_get(bdev->bd_disk->holder_dir); 543 return kobject_get(bdev->bd_disk->holder_dir);
544} 544}
545 545
546static void add_symlink(struct kobject *from, struct kobject *to) 546static int add_symlink(struct kobject *from, struct kobject *to)
547{ 547{
548 if (!from || !to) 548 if (!from || !to)
549 return; 549 return 0;
550 sysfs_create_link(from, to, kobject_name(to)); 550 return sysfs_create_link(from, to, kobject_name(to));
551} 551}
552 552
553static void del_symlink(struct kobject *from, struct kobject *to) 553static void del_symlink(struct kobject *from, struct kobject *to)
@@ -648,30 +648,38 @@ static void free_bd_holder(struct bd_holder *bo)
648 * If there is no matching entry with @bo in @bdev->bd_holder_list, 648 * If there is no matching entry with @bo in @bdev->bd_holder_list,
649 * add @bo to the list, create symlinks. 649 * add @bo to the list, create symlinks.
650 * 650 *
651 * Returns 1 if @bo was added to the list. 651 * Returns 0 if symlinks are created or already there.
652 * Returns 0 if @bo wasn't used by any reason and should be freed. 652 * Returns -ve if something fails and @bo can be freed.
653 */ 653 */
654static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) 654static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
655{ 655{
656 struct bd_holder *tmp; 656 struct bd_holder *tmp;
657 int ret;
657 658
658 if (!bo) 659 if (!bo)
659 return 0; 660 return -EINVAL;
660 661
661 list_for_each_entry(tmp, &bdev->bd_holder_list, list) { 662 list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
662 if (tmp->sdir == bo->sdir) { 663 if (tmp->sdir == bo->sdir) {
663 tmp->count++; 664 tmp->count++;
665 /* We've already done what we need to do here. */
666 free_bd_holder(bo);
664 return 0; 667 return 0;
665 } 668 }
666 } 669 }
667 670
668 if (!bd_holder_grab_dirs(bdev, bo)) 671 if (!bd_holder_grab_dirs(bdev, bo))
669 return 0; 672 return -EBUSY;
670 673
671 add_symlink(bo->sdir, bo->sdev); 674 ret = add_symlink(bo->sdir, bo->sdev);
672 add_symlink(bo->hdir, bo->hdev); 675 if (ret == 0) {
673 list_add_tail(&bo->list, &bdev->bd_holder_list); 676 ret = add_symlink(bo->hdir, bo->hdev);
674 return 1; 677 if (ret)
678 del_symlink(bo->sdir, bo->sdev);
679 }
680 if (ret == 0)
681 list_add_tail(&bo->list, &bdev->bd_holder_list);
682 return ret;
675} 683}
676 684
677/** 685/**
@@ -741,7 +749,9 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
741 749
742 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); 750 mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
743 res = bd_claim(bdev, holder); 751 res = bd_claim(bdev, holder);
744 if (res || !add_bd_holder(bdev, bo)) 752 if (res == 0)
753 res = add_bd_holder(bdev, bo);
754 if (res)
745 free_bd_holder(bo); 755 free_bd_holder(bo);
746 mutex_unlock(&bdev->bd_mutex); 756 mutex_unlock(&bdev->bd_mutex);
747 757