diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 34 |
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 | ||
546 | static void add_symlink(struct kobject *from, struct kobject *to) | 546 | static 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 | ||
553 | static void del_symlink(struct kobject *from, struct kobject *to) | 553 | static 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 | */ |
654 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | 654 | static 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 | ||