diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index bc8f27cc4483..36c0e7af9d0f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -642,34 +642,47 @@ 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 | */ | ||
| 654 | static struct bd_holder *find_bd_holder(struct block_device *bdev, | ||
| 655 | struct bd_holder *bo) | ||
| 656 | { | ||
| 657 | struct bd_holder *tmp; | ||
| 658 | |||
| 659 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) | ||
| 660 | if (tmp->sdir == bo->sdir) { | ||
| 661 | tmp->count++; | ||
| 662 | return tmp; | ||
| 663 | } | ||
| 664 | |||
| 665 | return NULL; | ||
| 666 | } | ||
| 667 | |||
| 668 | /** | ||
| 645 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship | 669 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship |
| 646 | * | 670 | * |
| 647 | * @bdev: block device to be bd_claimed | 671 | * @bdev: block device to be bd_claimed |
| 648 | * @bo: preallocated and initialized by alloc_bd_holder() | 672 | * @bo: preallocated and initialized by alloc_bd_holder() |
| 649 | * | 673 | * |
| 650 | * If there is no matching entry with @bo in @bdev->bd_holder_list, | 674 | * Add @bo to @bdev->bd_holder_list, create symlinks. |
| 651 | * add @bo to the list, create symlinks. | ||
| 652 | * | 675 | * |
| 653 | * Returns 0 if symlinks are created or already there. | 676 | * Returns 0 if symlinks are created. |
| 654 | * Returns -ve if something fails and @bo can be freed. | 677 | * Returns -ve if something fails. |
| 655 | */ | 678 | */ |
| 656 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | 679 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) |
| 657 | { | 680 | { |
| 658 | struct bd_holder *tmp; | ||
| 659 | int ret; | 681 | int ret; |
| 660 | 682 | ||
| 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; |
| @@ -751,9 +764,16 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
| 751 | 764 | ||
| 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) { |
| 770 | res = add_bd_holder(bdev, bo); | ||
| 771 | if (res) | ||
| 772 | bd_release(bdev); | ||
| 773 | } | ||
| 774 | } | ||
| 775 | |||
| 776 | if (res || found) | ||
| 757 | free_bd_holder(bo); | 777 | free_bd_holder(bo); |
| 758 | mutex_unlock(&bdev->bd_mutex); | 778 | mutex_unlock(&bdev->bd_mutex); |
| 759 | 779 | ||
| @@ -1131,6 +1151,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
| 1131 | filp->f_flags |= O_LARGEFILE; | 1151 | filp->f_flags |= O_LARGEFILE; |
| 1132 | 1152 | ||
| 1133 | bdev = bd_acquire(inode); | 1153 | bdev = bd_acquire(inode); |
| 1154 | if (bdev == NULL) | ||
| 1155 | return -ENOMEM; | ||
| 1134 | 1156 | ||
| 1135 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); | 1157 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); |
| 1136 | if (res) | 1158 | if (res) |
