diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 4a181fcb5175..fe09ef9c21f3 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1058,6 +1058,27 @@ retry: | |||
1058 | return 0; | 1058 | return 0; |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno) | ||
1062 | { | ||
1063 | struct gendisk *disk = get_gendisk(bdev->bd_dev, partno); | ||
1064 | |||
1065 | if (!disk) | ||
1066 | return NULL; | ||
1067 | /* | ||
1068 | * Now that we hold gendisk reference we make sure bdev we looked up is | ||
1069 | * not stale. If it is, it means device got removed and created before | ||
1070 | * we looked up gendisk and we fail open in such case. Associating | ||
1071 | * unhashed bdev with newly created gendisk could lead to two bdevs | ||
1072 | * (and thus two independent caches) being associated with one device | ||
1073 | * which is bad. | ||
1074 | */ | ||
1075 | if (inode_unhashed(bdev->bd_inode)) { | ||
1076 | put_disk_and_module(disk); | ||
1077 | return NULL; | ||
1078 | } | ||
1079 | return disk; | ||
1080 | } | ||
1081 | |||
1061 | /** | 1082 | /** |
1062 | * bd_start_claiming - start claiming a block device | 1083 | * bd_start_claiming - start claiming a block device |
1063 | * @bdev: block device of interest | 1084 | * @bdev: block device of interest |
@@ -1094,7 +1115,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev, | |||
1094 | * @bdev might not have been initialized properly yet, look up | 1115 | * @bdev might not have been initialized properly yet, look up |
1095 | * and grab the outer block device the hard way. | 1116 | * and grab the outer block device the hard way. |
1096 | */ | 1117 | */ |
1097 | disk = get_gendisk(bdev->bd_dev, &partno); | 1118 | disk = bdev_get_gendisk(bdev, &partno); |
1098 | if (!disk) | 1119 | if (!disk) |
1099 | return ERR_PTR(-ENXIO); | 1120 | return ERR_PTR(-ENXIO); |
1100 | 1121 | ||
@@ -1111,8 +1132,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev, | |||
1111 | else | 1132 | else |
1112 | whole = bdgrab(bdev); | 1133 | whole = bdgrab(bdev); |
1113 | 1134 | ||
1114 | module_put(disk->fops->owner); | 1135 | put_disk_and_module(disk); |
1115 | put_disk(disk); | ||
1116 | if (!whole) | 1136 | if (!whole) |
1117 | return ERR_PTR(-ENOMEM); | 1137 | return ERR_PTR(-ENOMEM); |
1118 | 1138 | ||
@@ -1407,10 +1427,10 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part); | |||
1407 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | 1427 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) |
1408 | { | 1428 | { |
1409 | struct gendisk *disk; | 1429 | struct gendisk *disk; |
1410 | struct module *owner; | ||
1411 | int ret; | 1430 | int ret; |
1412 | int partno; | 1431 | int partno; |
1413 | int perm = 0; | 1432 | int perm = 0; |
1433 | bool first_open = false; | ||
1414 | 1434 | ||
1415 | if (mode & FMODE_READ) | 1435 | if (mode & FMODE_READ) |
1416 | perm |= MAY_READ; | 1436 | perm |= MAY_READ; |
@@ -1430,14 +1450,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1430 | restart: | 1450 | restart: |
1431 | 1451 | ||
1432 | ret = -ENXIO; | 1452 | ret = -ENXIO; |
1433 | disk = get_gendisk(bdev->bd_dev, &partno); | 1453 | disk = bdev_get_gendisk(bdev, &partno); |
1434 | if (!disk) | 1454 | if (!disk) |
1435 | goto out; | 1455 | goto out; |
1436 | owner = disk->fops->owner; | ||
1437 | 1456 | ||
1438 | disk_block_events(disk); | 1457 | disk_block_events(disk); |
1439 | mutex_lock_nested(&bdev->bd_mutex, for_part); | 1458 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
1440 | if (!bdev->bd_openers) { | 1459 | if (!bdev->bd_openers) { |
1460 | first_open = true; | ||
1441 | bdev->bd_disk = disk; | 1461 | bdev->bd_disk = disk; |
1442 | bdev->bd_queue = disk->queue; | 1462 | bdev->bd_queue = disk->queue; |
1443 | bdev->bd_contains = bdev; | 1463 | bdev->bd_contains = bdev; |
@@ -1463,8 +1483,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1463 | bdev->bd_queue = NULL; | 1483 | bdev->bd_queue = NULL; |
1464 | mutex_unlock(&bdev->bd_mutex); | 1484 | mutex_unlock(&bdev->bd_mutex); |
1465 | disk_unblock_events(disk); | 1485 | disk_unblock_events(disk); |
1466 | put_disk(disk); | 1486 | put_disk_and_module(disk); |
1467 | module_put(owner); | ||
1468 | goto restart; | 1487 | goto restart; |
1469 | } | 1488 | } |
1470 | } | 1489 | } |
@@ -1524,15 +1543,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1524 | if (ret) | 1543 | if (ret) |
1525 | goto out_unlock_bdev; | 1544 | goto out_unlock_bdev; |
1526 | } | 1545 | } |
1527 | /* only one opener holds refs to the module and disk */ | ||
1528 | put_disk(disk); | ||
1529 | module_put(owner); | ||
1530 | } | 1546 | } |
1531 | bdev->bd_openers++; | 1547 | bdev->bd_openers++; |
1532 | if (for_part) | 1548 | if (for_part) |
1533 | bdev->bd_part_count++; | 1549 | bdev->bd_part_count++; |
1534 | mutex_unlock(&bdev->bd_mutex); | 1550 | mutex_unlock(&bdev->bd_mutex); |
1535 | disk_unblock_events(disk); | 1551 | disk_unblock_events(disk); |
1552 | /* only one opener holds refs to the module and disk */ | ||
1553 | if (!first_open) | ||
1554 | put_disk_and_module(disk); | ||
1536 | return 0; | 1555 | return 0; |
1537 | 1556 | ||
1538 | out_clear: | 1557 | out_clear: |
@@ -1546,8 +1565,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1546 | out_unlock_bdev: | 1565 | out_unlock_bdev: |
1547 | mutex_unlock(&bdev->bd_mutex); | 1566 | mutex_unlock(&bdev->bd_mutex); |
1548 | disk_unblock_events(disk); | 1567 | disk_unblock_events(disk); |
1549 | put_disk(disk); | 1568 | put_disk_and_module(disk); |
1550 | module_put(owner); | ||
1551 | out: | 1569 | out: |
1552 | bdput(bdev); | 1570 | bdput(bdev); |
1553 | 1571 | ||
@@ -1770,8 +1788,6 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) | |||
1770 | disk->fops->release(disk, mode); | 1788 | disk->fops->release(disk, mode); |
1771 | } | 1789 | } |
1772 | if (!bdev->bd_openers) { | 1790 | if (!bdev->bd_openers) { |
1773 | struct module *owner = disk->fops->owner; | ||
1774 | |||
1775 | disk_put_part(bdev->bd_part); | 1791 | disk_put_part(bdev->bd_part); |
1776 | bdev->bd_part = NULL; | 1792 | bdev->bd_part = NULL; |
1777 | bdev->bd_disk = NULL; | 1793 | bdev->bd_disk = NULL; |
@@ -1779,8 +1795,7 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) | |||
1779 | victim = bdev->bd_contains; | 1795 | victim = bdev->bd_contains; |
1780 | bdev->bd_contains = NULL; | 1796 | bdev->bd_contains = NULL; |
1781 | 1797 | ||
1782 | put_disk(disk); | 1798 | put_disk_and_module(disk); |
1783 | module_put(owner); | ||
1784 | } | 1799 | } |
1785 | mutex_unlock(&bdev->bd_mutex); | 1800 | mutex_unlock(&bdev->bd_mutex); |
1786 | bdput(bdev); | 1801 | bdput(bdev); |