diff options
-rw-r--r-- | block/ioctl.c | 4 | ||||
-rw-r--r-- | drivers/md/md.c | 6 | ||||
-rw-r--r-- | fs/block_dev.c | 180 | ||||
-rw-r--r-- | include/linux/fs.h | 17 |
4 files changed, 60 insertions, 147 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index 58aab630dfc1..9fddb99c3efb 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
72 | bdevp = bdget_disk(disk, part); | 72 | bdevp = bdget_disk(disk, part); |
73 | if (!bdevp) | 73 | if (!bdevp) |
74 | return -ENOMEM; | 74 | return -ENOMEM; |
75 | mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION); | 75 | mutex_lock(&bdevp->bd_mutex); |
76 | if (bdevp->bd_openers) { | 76 | if (bdevp->bd_openers) { |
77 | mutex_unlock(&bdevp->bd_mutex); | 77 | mutex_unlock(&bdevp->bd_mutex); |
78 | bdput(bdevp); | 78 | bdput(bdevp); |
@@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
82 | fsync_bdev(bdevp); | 82 | fsync_bdev(bdevp); |
83 | invalidate_bdev(bdevp, 0); | 83 | invalidate_bdev(bdevp, 0); |
84 | 84 | ||
85 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE); | 85 | mutex_lock(&bdev->bd_mutex); |
86 | delete_partition(disk, part); | 86 | delete_partition(disk, part); |
87 | mutex_unlock(&bdev->bd_mutex); | 87 | mutex_unlock(&bdev->bd_mutex); |
88 | mutex_unlock(&bdevp->bd_mutex); | 88 | mutex_unlock(&bdevp->bd_mutex); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 6c4345bde07e..d2bcb410e3ab 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1413,7 +1413,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | |||
1413 | struct block_device *bdev; | 1413 | struct block_device *bdev; |
1414 | char b[BDEVNAME_SIZE]; | 1414 | char b[BDEVNAME_SIZE]; |
1415 | 1415 | ||
1416 | bdev = open_partition_by_devnum(dev, FMODE_READ|FMODE_WRITE); | 1416 | bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); |
1417 | if (IS_ERR(bdev)) { | 1417 | if (IS_ERR(bdev)) { |
1418 | printk(KERN_ERR "md: could not open %s.\n", | 1418 | printk(KERN_ERR "md: could not open %s.\n", |
1419 | __bdevname(dev, b)); | 1419 | __bdevname(dev, b)); |
@@ -1423,7 +1423,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | |||
1423 | if (err) { | 1423 | if (err) { |
1424 | printk(KERN_ERR "md: could not bd_claim %s.\n", | 1424 | printk(KERN_ERR "md: could not bd_claim %s.\n", |
1425 | bdevname(bdev, b)); | 1425 | bdevname(bdev, b)); |
1426 | blkdev_put_partition(bdev); | 1426 | blkdev_put(bdev); |
1427 | return err; | 1427 | return err; |
1428 | } | 1428 | } |
1429 | rdev->bdev = bdev; | 1429 | rdev->bdev = bdev; |
@@ -1437,7 +1437,7 @@ static void unlock_rdev(mdk_rdev_t *rdev) | |||
1437 | if (!bdev) | 1437 | if (!bdev) |
1438 | MD_BUG(); | 1438 | MD_BUG(); |
1439 | bd_release(bdev); | 1439 | bd_release(bdev); |
1440 | blkdev_put_partition(bdev); | 1440 | blkdev_put(bdev); |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | void md_autodetect_dev(dev_t dev); | 1443 | void md_autodetect_dev(dev_t dev); |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 13816b4d76f6..36c38f48a4ed 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -762,7 +762,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
762 | if (!bo) | 762 | if (!bo) |
763 | return -ENOMEM; | 763 | return -ENOMEM; |
764 | 764 | ||
765 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 765 | mutex_lock(&bdev->bd_mutex); |
766 | res = bd_claim(bdev, holder); | 766 | res = bd_claim(bdev, holder); |
767 | if (res == 0) { | 767 | if (res == 0) { |
768 | found = find_bd_holder(bdev, bo); | 768 | found = find_bd_holder(bdev, bo); |
@@ -796,7 +796,7 @@ static void bd_release_from_kobject(struct block_device *bdev, | |||
796 | if (!kobj) | 796 | if (!kobj) |
797 | return; | 797 | return; |
798 | 798 | ||
799 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 799 | mutex_lock(&bdev->bd_mutex); |
800 | bd_release(bdev); | 800 | bd_release(bdev); |
801 | if ((bo = del_bd_holder(bdev, kobj))) | 801 | if ((bo = del_bd_holder(bdev, kobj))) |
802 | free_bd_holder(bo); | 802 | free_bd_holder(bo); |
@@ -854,22 +854,6 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) | |||
854 | 854 | ||
855 | EXPORT_SYMBOL(open_by_devnum); | 855 | EXPORT_SYMBOL(open_by_devnum); |
856 | 856 | ||
857 | static int | ||
858 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags); | ||
859 | |||
860 | struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode) | ||
861 | { | ||
862 | struct block_device *bdev = bdget(dev); | ||
863 | int err = -ENOMEM; | ||
864 | int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY; | ||
865 | if (bdev) | ||
866 | err = blkdev_get_partition(bdev, mode, flags); | ||
867 | return err ? ERR_PTR(err) : bdev; | ||
868 | } | ||
869 | |||
870 | EXPORT_SYMBOL(open_partition_by_devnum); | ||
871 | |||
872 | |||
873 | /* | 857 | /* |
874 | * This routine checks whether a removable media has been changed, | 858 | * This routine checks whether a removable media has been changed, |
875 | * and invalidates all buffer-cache-entries in that case. This | 859 | * and invalidates all buffer-cache-entries in that case. This |
@@ -916,66 +900,7 @@ void bd_set_size(struct block_device *bdev, loff_t size) | |||
916 | } | 900 | } |
917 | EXPORT_SYMBOL(bd_set_size); | 901 | EXPORT_SYMBOL(bd_set_size); |
918 | 902 | ||
919 | static int __blkdev_put(struct block_device *bdev, unsigned int subclass) | 903 | static int do_open(struct block_device *bdev, struct file *file) |
920 | { | ||
921 | int ret = 0; | ||
922 | struct inode *bd_inode = bdev->bd_inode; | ||
923 | struct gendisk *disk = bdev->bd_disk; | ||
924 | |||
925 | mutex_lock_nested(&bdev->bd_mutex, subclass); | ||
926 | lock_kernel(); | ||
927 | if (!--bdev->bd_openers) { | ||
928 | sync_blockdev(bdev); | ||
929 | kill_bdev(bdev); | ||
930 | } | ||
931 | if (bdev->bd_contains == bdev) { | ||
932 | if (disk->fops->release) | ||
933 | ret = disk->fops->release(bd_inode, NULL); | ||
934 | } else { | ||
935 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, | ||
936 | subclass + 1); | ||
937 | bdev->bd_contains->bd_part_count--; | ||
938 | mutex_unlock(&bdev->bd_contains->bd_mutex); | ||
939 | } | ||
940 | if (!bdev->bd_openers) { | ||
941 | struct module *owner = disk->fops->owner; | ||
942 | |||
943 | put_disk(disk); | ||
944 | module_put(owner); | ||
945 | |||
946 | if (bdev->bd_contains != bdev) { | ||
947 | kobject_put(&bdev->bd_part->kobj); | ||
948 | bdev->bd_part = NULL; | ||
949 | } | ||
950 | bdev->bd_disk = NULL; | ||
951 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | ||
952 | if (bdev != bdev->bd_contains) | ||
953 | __blkdev_put(bdev->bd_contains, subclass + 1); | ||
954 | bdev->bd_contains = NULL; | ||
955 | } | ||
956 | unlock_kernel(); | ||
957 | mutex_unlock(&bdev->bd_mutex); | ||
958 | bdput(bdev); | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | int blkdev_put(struct block_device *bdev) | ||
963 | { | ||
964 | return __blkdev_put(bdev, BD_MUTEX_NORMAL); | ||
965 | } | ||
966 | EXPORT_SYMBOL(blkdev_put); | ||
967 | |||
968 | int blkdev_put_partition(struct block_device *bdev) | ||
969 | { | ||
970 | return __blkdev_put(bdev, BD_MUTEX_PARTITION); | ||
971 | } | ||
972 | EXPORT_SYMBOL(blkdev_put_partition); | ||
973 | |||
974 | static int | ||
975 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); | ||
976 | |||
977 | static int | ||
978 | do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | ||
979 | { | 904 | { |
980 | struct module *owner = NULL; | 905 | struct module *owner = NULL; |
981 | struct gendisk *disk; | 906 | struct gendisk *disk; |
@@ -992,8 +917,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
992 | } | 917 | } |
993 | owner = disk->fops->owner; | 918 | owner = disk->fops->owner; |
994 | 919 | ||
995 | mutex_lock_nested(&bdev->bd_mutex, subclass); | 920 | mutex_lock(&bdev->bd_mutex); |
996 | |||
997 | if (!bdev->bd_openers) { | 921 | if (!bdev->bd_openers) { |
998 | bdev->bd_disk = disk; | 922 | bdev->bd_disk = disk; |
999 | bdev->bd_contains = bdev; | 923 | bdev->bd_contains = bdev; |
@@ -1020,11 +944,11 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
1020 | ret = -ENOMEM; | 944 | ret = -ENOMEM; |
1021 | if (!whole) | 945 | if (!whole) |
1022 | goto out_first; | 946 | goto out_first; |
1023 | ret = blkdev_get_whole(whole, file->f_mode, file->f_flags); | 947 | ret = blkdev_get(whole, file->f_mode, file->f_flags); |
1024 | if (ret) | 948 | if (ret) |
1025 | goto out_first; | 949 | goto out_first; |
1026 | bdev->bd_contains = whole; | 950 | bdev->bd_contains = whole; |
1027 | mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE); | 951 | mutex_lock(&whole->bd_mutex); |
1028 | whole->bd_part_count++; | 952 | whole->bd_part_count++; |
1029 | p = disk->part[part - 1]; | 953 | p = disk->part[part - 1]; |
1030 | bdev->bd_inode->i_data.backing_dev_info = | 954 | bdev->bd_inode->i_data.backing_dev_info = |
@@ -1052,8 +976,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
1052 | if (bdev->bd_invalidated) | 976 | if (bdev->bd_invalidated) |
1053 | rescan_partitions(bdev->bd_disk, bdev); | 977 | rescan_partitions(bdev->bd_disk, bdev); |
1054 | } else { | 978 | } else { |
1055 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, | 979 | mutex_lock(&bdev->bd_contains->bd_mutex); |
1056 | BD_MUTEX_WHOLE); | ||
1057 | bdev->bd_contains->bd_part_count++; | 980 | bdev->bd_contains->bd_part_count++; |
1058 | mutex_unlock(&bdev->bd_contains->bd_mutex); | 981 | mutex_unlock(&bdev->bd_contains->bd_mutex); |
1059 | } | 982 | } |
@@ -1067,7 +990,7 @@ out_first: | |||
1067 | bdev->bd_disk = NULL; | 990 | bdev->bd_disk = NULL; |
1068 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 991 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
1069 | if (bdev != bdev->bd_contains) | 992 | if (bdev != bdev->bd_contains) |
1070 | __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE); | 993 | blkdev_put(bdev->bd_contains); |
1071 | bdev->bd_contains = NULL; | 994 | bdev->bd_contains = NULL; |
1072 | put_disk(disk); | 995 | put_disk(disk); |
1073 | module_put(owner); | 996 | module_put(owner); |
@@ -1094,49 +1017,11 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) | |||
1094 | fake_file.f_dentry = &fake_dentry; | 1017 | fake_file.f_dentry = &fake_dentry; |
1095 | fake_dentry.d_inode = bdev->bd_inode; | 1018 | fake_dentry.d_inode = bdev->bd_inode; |
1096 | 1019 | ||
1097 | return do_open(bdev, &fake_file, BD_MUTEX_NORMAL); | 1020 | return do_open(bdev, &fake_file); |
1098 | } | 1021 | } |
1099 | 1022 | ||
1100 | EXPORT_SYMBOL(blkdev_get); | 1023 | EXPORT_SYMBOL(blkdev_get); |
1101 | 1024 | ||
1102 | static int | ||
1103 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags) | ||
1104 | { | ||
1105 | /* | ||
1106 | * This crockload is due to bad choice of ->open() type. | ||
1107 | * It will go away. | ||
1108 | * For now, block device ->open() routine must _not_ | ||
1109 | * examine anything in 'inode' argument except ->i_rdev. | ||
1110 | */ | ||
1111 | struct file fake_file = {}; | ||
1112 | struct dentry fake_dentry = {}; | ||
1113 | fake_file.f_mode = mode; | ||
1114 | fake_file.f_flags = flags; | ||
1115 | fake_file.f_dentry = &fake_dentry; | ||
1116 | fake_dentry.d_inode = bdev->bd_inode; | ||
1117 | |||
1118 | return do_open(bdev, &fake_file, BD_MUTEX_WHOLE); | ||
1119 | } | ||
1120 | |||
1121 | static int | ||
1122 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags) | ||
1123 | { | ||
1124 | /* | ||
1125 | * This crockload is due to bad choice of ->open() type. | ||
1126 | * It will go away. | ||
1127 | * For now, block device ->open() routine must _not_ | ||
1128 | * examine anything in 'inode' argument except ->i_rdev. | ||
1129 | */ | ||
1130 | struct file fake_file = {}; | ||
1131 | struct dentry fake_dentry = {}; | ||
1132 | fake_file.f_mode = mode; | ||
1133 | fake_file.f_flags = flags; | ||
1134 | fake_file.f_dentry = &fake_dentry; | ||
1135 | fake_dentry.d_inode = bdev->bd_inode; | ||
1136 | |||
1137 | return do_open(bdev, &fake_file, BD_MUTEX_PARTITION); | ||
1138 | } | ||
1139 | |||
1140 | static int blkdev_open(struct inode * inode, struct file * filp) | 1025 | static int blkdev_open(struct inode * inode, struct file * filp) |
1141 | { | 1026 | { |
1142 | struct block_device *bdev; | 1027 | struct block_device *bdev; |
@@ -1154,7 +1039,7 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1154 | if (bdev == NULL) | 1039 | if (bdev == NULL) |
1155 | return -ENOMEM; | 1040 | return -ENOMEM; |
1156 | 1041 | ||
1157 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); | 1042 | res = do_open(bdev, filp); |
1158 | if (res) | 1043 | if (res) |
1159 | return res; | 1044 | return res; |
1160 | 1045 | ||
@@ -1168,6 +1053,51 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1168 | return res; | 1053 | return res; |
1169 | } | 1054 | } |
1170 | 1055 | ||
1056 | int blkdev_put(struct block_device *bdev) | ||
1057 | { | ||
1058 | int ret = 0; | ||
1059 | struct inode *bd_inode = bdev->bd_inode; | ||
1060 | struct gendisk *disk = bdev->bd_disk; | ||
1061 | |||
1062 | mutex_lock(&bdev->bd_mutex); | ||
1063 | lock_kernel(); | ||
1064 | if (!--bdev->bd_openers) { | ||
1065 | sync_blockdev(bdev); | ||
1066 | kill_bdev(bdev); | ||
1067 | } | ||
1068 | if (bdev->bd_contains == bdev) { | ||
1069 | if (disk->fops->release) | ||
1070 | ret = disk->fops->release(bd_inode, NULL); | ||
1071 | } else { | ||
1072 | mutex_lock(&bdev->bd_contains->bd_mutex); | ||
1073 | bdev->bd_contains->bd_part_count--; | ||
1074 | mutex_unlock(&bdev->bd_contains->bd_mutex); | ||
1075 | } | ||
1076 | if (!bdev->bd_openers) { | ||
1077 | struct module *owner = disk->fops->owner; | ||
1078 | |||
1079 | put_disk(disk); | ||
1080 | module_put(owner); | ||
1081 | |||
1082 | if (bdev->bd_contains != bdev) { | ||
1083 | kobject_put(&bdev->bd_part->kobj); | ||
1084 | bdev->bd_part = NULL; | ||
1085 | } | ||
1086 | bdev->bd_disk = NULL; | ||
1087 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | ||
1088 | if (bdev != bdev->bd_contains) { | ||
1089 | blkdev_put(bdev->bd_contains); | ||
1090 | } | ||
1091 | bdev->bd_contains = NULL; | ||
1092 | } | ||
1093 | unlock_kernel(); | ||
1094 | mutex_unlock(&bdev->bd_mutex); | ||
1095 | bdput(bdev); | ||
1096 | return ret; | ||
1097 | } | ||
1098 | |||
1099 | EXPORT_SYMBOL(blkdev_put); | ||
1100 | |||
1171 | static int blkdev_close(struct inode * inode, struct file * filp) | 1101 | static int blkdev_close(struct inode * inode, struct file * filp) |
1172 | { | 1102 | { |
1173 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); | 1103 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 70b99fbb560b..45f2cabb8c75 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -482,21 +482,6 @@ struct block_device { | |||
482 | }; | 482 | }; |
483 | 483 | ||
484 | /* | 484 | /* |
485 | * bdev->bd_mutex nesting subclasses for the lock validator: | ||
486 | * | ||
487 | * 0: normal | ||
488 | * 1: 'whole' | ||
489 | * 2: 'partition' | ||
490 | */ | ||
491 | enum bdev_bd_mutex_lock_class | ||
492 | { | ||
493 | BD_MUTEX_NORMAL, | ||
494 | BD_MUTEX_WHOLE, | ||
495 | BD_MUTEX_PARTITION | ||
496 | }; | ||
497 | |||
498 | |||
499 | /* | ||
500 | * Radix-tree tags, for tagging dirty and writeback pages within the pagecache | 485 | * Radix-tree tags, for tagging dirty and writeback pages within the pagecache |
501 | * radix trees | 486 | * radix trees |
502 | */ | 487 | */ |
@@ -1499,7 +1484,6 @@ extern void bd_set_size(struct block_device *, loff_t size); | |||
1499 | extern void bd_forget(struct inode *inode); | 1484 | extern void bd_forget(struct inode *inode); |
1500 | extern void bdput(struct block_device *); | 1485 | extern void bdput(struct block_device *); |
1501 | extern struct block_device *open_by_devnum(dev_t, unsigned); | 1486 | extern struct block_device *open_by_devnum(dev_t, unsigned); |
1502 | extern struct block_device *open_partition_by_devnum(dev_t, unsigned); | ||
1503 | extern const struct address_space_operations def_blk_aops; | 1487 | extern const struct address_space_operations def_blk_aops; |
1504 | #else | 1488 | #else |
1505 | static inline void bd_forget(struct inode *inode) {} | 1489 | static inline void bd_forget(struct inode *inode) {} |
@@ -1517,7 +1501,6 @@ extern int blkdev_driver_ioctl(struct inode *inode, struct file *file, | |||
1517 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); | 1501 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); |
1518 | extern int blkdev_get(struct block_device *, mode_t, unsigned); | 1502 | extern int blkdev_get(struct block_device *, mode_t, unsigned); |
1519 | extern int blkdev_put(struct block_device *); | 1503 | extern int blkdev_put(struct block_device *); |
1520 | extern int blkdev_put_partition(struct block_device *); | ||
1521 | extern int bd_claim(struct block_device *, void *); | 1504 | extern int bd_claim(struct block_device *, void *); |
1522 | extern void bd_release(struct block_device *); | 1505 | extern void bd_release(struct block_device *); |
1523 | #ifdef CONFIG_SYSFS | 1506 | #ifdef CONFIG_SYSFS |