diff options
-rw-r--r-- | block/genhd.c | 40 | ||||
-rw-r--r-- | block/ioctl.c | 4 | ||||
-rw-r--r-- | fs/block_dev.c | 2 | ||||
-rw-r--r-- | fs/partitions/check.c | 12 | ||||
-rw-r--r-- | include/linux/genhd.h | 11 |
5 files changed, 41 insertions, 28 deletions
diff --git a/block/genhd.c b/block/genhd.c index 0a2f16bd54b7..65b7386c26d8 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -54,10 +54,10 @@ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) | |||
54 | { | 54 | { |
55 | struct hd_struct *part; | 55 | struct hd_struct *part; |
56 | 56 | ||
57 | if (unlikely(partno < 1 || partno > disk_max_parts(disk))) | 57 | if (unlikely(partno < 0 || partno >= disk_max_parts(disk))) |
58 | return NULL; | 58 | return NULL; |
59 | rcu_read_lock(); | 59 | rcu_read_lock(); |
60 | part = rcu_dereference(disk->__part[partno - 1]); | 60 | part = rcu_dereference(disk->__part[partno]); |
61 | if (part) | 61 | if (part) |
62 | get_device(part_to_dev(part)); | 62 | get_device(part_to_dev(part)); |
63 | rcu_read_unlock(); | 63 | rcu_read_unlock(); |
@@ -85,8 +85,10 @@ void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, | |||
85 | 85 | ||
86 | if (flags & DISK_PITER_REVERSE) | 86 | if (flags & DISK_PITER_REVERSE) |
87 | piter->idx = disk_max_parts(piter->disk) - 1; | 87 | piter->idx = disk_max_parts(piter->disk) - 1; |
88 | else | 88 | else if (flags & DISK_PITER_INCL_PART0) |
89 | piter->idx = 0; | 89 | piter->idx = 0; |
90 | else | ||
91 | piter->idx = 1; | ||
90 | 92 | ||
91 | piter->flags = flags; | 93 | piter->flags = flags; |
92 | } | 94 | } |
@@ -114,7 +116,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) | |||
114 | /* determine iteration parameters */ | 116 | /* determine iteration parameters */ |
115 | if (piter->flags & DISK_PITER_REVERSE) { | 117 | if (piter->flags & DISK_PITER_REVERSE) { |
116 | inc = -1; | 118 | inc = -1; |
117 | end = -1; | 119 | if (piter->flags & DISK_PITER_INCL_PART0) |
120 | end = -1; | ||
121 | else | ||
122 | end = 0; | ||
118 | } else { | 123 | } else { |
119 | inc = 1; | 124 | inc = 1; |
120 | end = disk_max_parts(piter->disk); | 125 | end = disk_max_parts(piter->disk); |
@@ -177,7 +182,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) | |||
177 | { | 182 | { |
178 | int i; | 183 | int i; |
179 | 184 | ||
180 | for (i = 0; i < disk_max_parts(disk); i++) { | 185 | for (i = 1; i < disk_max_parts(disk); i++) { |
181 | struct hd_struct *part = rcu_dereference(disk->__part[i]); | 186 | struct hd_struct *part = rcu_dereference(disk->__part[i]); |
182 | 187 | ||
183 | if (part && part->start_sect <= sector && | 188 | if (part && part->start_sect <= sector && |
@@ -669,7 +674,7 @@ static int show_partition(struct seq_file *seqf, void *v) | |||
669 | char buf[BDEVNAME_SIZE]; | 674 | char buf[BDEVNAME_SIZE]; |
670 | 675 | ||
671 | /* Don't show non-partitionable removeable devices or empty devices */ | 676 | /* Don't show non-partitionable removeable devices or empty devices */ |
672 | if (!get_capacity(sgp) || (!disk_max_parts(sgp) && | 677 | if (!get_capacity(sgp) || (!disk_partitionable(sgp) && |
673 | (sgp->flags & GENHD_FL_REMOVABLE))) | 678 | (sgp->flags & GENHD_FL_REMOVABLE))) |
674 | return 0; | 679 | return 0; |
675 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) | 680 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) |
@@ -742,7 +747,7 @@ static ssize_t disk_ext_range_show(struct device *dev, | |||
742 | { | 747 | { |
743 | struct gendisk *disk = dev_to_disk(dev); | 748 | struct gendisk *disk = dev_to_disk(dev); |
744 | 749 | ||
745 | return sprintf(buf, "%d\n", disk_max_parts(disk) + 1); | 750 | return sprintf(buf, "%d\n", disk_max_parts(disk)); |
746 | } | 751 | } |
747 | 752 | ||
748 | static ssize_t disk_removable_show(struct device *dev, | 753 | static ssize_t disk_removable_show(struct device *dev, |
@@ -998,7 +1003,7 @@ dev_t blk_lookup_devt(const char *name, int partno) | |||
998 | 1003 | ||
999 | if (strcmp(dev->bus_id, name)) | 1004 | if (strcmp(dev->bus_id, name)) |
1000 | continue; | 1005 | continue; |
1001 | if (partno < 0 || partno > disk_max_parts(disk)) | 1006 | if (partno < 0 || partno >= disk_max_parts(disk)) |
1002 | continue; | 1007 | continue; |
1003 | 1008 | ||
1004 | if (partno == 0) | 1009 | if (partno == 0) |
@@ -1045,21 +1050,22 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) | |||
1045 | GFP_KERNEL | __GFP_ZERO, node_id); | 1050 | GFP_KERNEL | __GFP_ZERO, node_id); |
1046 | if (disk) { | 1051 | if (disk) { |
1047 | int tot_minors = minors + ext_minors; | 1052 | int tot_minors = minors + ext_minors; |
1053 | int size = tot_minors * sizeof(struct hd_struct *); | ||
1048 | 1054 | ||
1049 | if (!init_disk_stats(disk)) { | 1055 | if (!init_disk_stats(disk)) { |
1050 | kfree(disk); | 1056 | kfree(disk); |
1051 | return NULL; | 1057 | return NULL; |
1052 | } | 1058 | } |
1053 | if (tot_minors > 1) { | 1059 | |
1054 | int size = (tot_minors - 1) * sizeof(struct hd_struct *); | 1060 | disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, |
1055 | disk->__part = kmalloc_node(size, | 1061 | node_id); |
1056 | GFP_KERNEL | __GFP_ZERO, node_id); | 1062 | if (!disk->__part) { |
1057 | if (!disk->__part) { | 1063 | free_disk_stats(disk); |
1058 | free_disk_stats(disk); | 1064 | kfree(disk); |
1059 | kfree(disk); | 1065 | return NULL; |
1060 | return NULL; | ||
1061 | } | ||
1062 | } | 1066 | } |
1067 | disk->__part[0] = &disk->part0; | ||
1068 | |||
1063 | disk->minors = minors; | 1069 | disk->minors = minors; |
1064 | disk->ext_minors = ext_minors; | 1070 | disk->ext_minors = ext_minors; |
1065 | rand_initialize_disk(disk); | 1071 | rand_initialize_disk(disk); |
diff --git a/block/ioctl.c b/block/ioctl.c index a5f672ad55f6..64e7c67a64b0 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
30 | if (bdev != bdev->bd_contains) | 30 | if (bdev != bdev->bd_contains) |
31 | return -EINVAL; | 31 | return -EINVAL; |
32 | partno = p.pno; | 32 | partno = p.pno; |
33 | if (partno <= 0 || partno > disk_max_parts(disk)) | 33 | if (partno <= 0 || partno >= disk_max_parts(disk)) |
34 | return -EINVAL; | 34 | return -EINVAL; |
35 | switch (a.op) { | 35 | switch (a.op) { |
36 | case BLKPG_ADD_PARTITION: | 36 | case BLKPG_ADD_PARTITION: |
@@ -102,7 +102,7 @@ static int blkdev_reread_part(struct block_device *bdev) | |||
102 | struct gendisk *disk = bdev->bd_disk; | 102 | struct gendisk *disk = bdev->bd_disk; |
103 | int res; | 103 | int res; |
104 | 104 | ||
105 | if (!disk_max_parts(disk) || bdev != bdev->bd_contains) | 105 | if (!disk_partitionable(disk) || bdev != bdev->bd_contains) |
106 | return -EINVAL; | 106 | return -EINVAL; |
107 | if (!capable(CAP_SYS_ADMIN)) | 107 | if (!capable(CAP_SYS_ADMIN)) |
108 | return -EACCES; | 108 | return -EACCES; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index a02df22f37c3..c982a9107979 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev) | |||
892 | 892 | ||
893 | if (bdops->revalidate_disk) | 893 | if (bdops->revalidate_disk) |
894 | bdops->revalidate_disk(bdev->bd_disk); | 894 | bdops->revalidate_disk(bdev->bd_disk); |
895 | if (disk_max_parts(bdev->bd_disk)) | 895 | if (disk_partitionable(bdev->bd_disk)) |
896 | bdev->bd_invalidated = 1; | 896 | bdev->bd_invalidated = 1; |
897 | return 1; | 897 | return 1; |
898 | } | 898 | } |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ac0df3acdcda..b60699c271ac 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -173,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) | |||
173 | if (isdigit(state->name[strlen(state->name)-1])) | 173 | if (isdigit(state->name[strlen(state->name)-1])) |
174 | sprintf(state->name, "p"); | 174 | sprintf(state->name, "p"); |
175 | 175 | ||
176 | state->limit = disk_max_parts(hd) + 1; | 176 | state->limit = disk_max_parts(hd); |
177 | i = res = err = 0; | 177 | i = res = err = 0; |
178 | while (!res && check_part[i]) { | 178 | while (!res && check_part[i]) { |
179 | memset(&state->parts, 0, sizeof(state->parts)); | 179 | memset(&state->parts, 0, sizeof(state->parts)); |
@@ -329,12 +329,12 @@ void delete_partition(struct gendisk *disk, int partno) | |||
329 | { | 329 | { |
330 | struct hd_struct *part; | 330 | struct hd_struct *part; |
331 | 331 | ||
332 | part = disk->__part[partno-1]; | 332 | part = disk->__part[partno]; |
333 | if (!part) | 333 | if (!part) |
334 | return; | 334 | return; |
335 | 335 | ||
336 | blk_free_devt(part_devt(part)); | 336 | blk_free_devt(part_devt(part)); |
337 | rcu_assign_pointer(disk->__part[partno-1], NULL); | 337 | rcu_assign_pointer(disk->__part[partno], NULL); |
338 | kobject_put(part->holder_dir); | 338 | kobject_put(part->holder_dir); |
339 | device_del(part_to_dev(part)); | 339 | device_del(part_to_dev(part)); |
340 | 340 | ||
@@ -359,7 +359,7 @@ int add_partition(struct gendisk *disk, int partno, | |||
359 | const char *dname; | 359 | const char *dname; |
360 | int err; | 360 | int err; |
361 | 361 | ||
362 | if (disk->__part[partno - 1]) | 362 | if (disk->__part[partno]) |
363 | return -EBUSY; | 363 | return -EBUSY; |
364 | 364 | ||
365 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 365 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
@@ -413,7 +413,7 @@ int add_partition(struct gendisk *disk, int partno, | |||
413 | 413 | ||
414 | /* everything is up and running, commence */ | 414 | /* everything is up and running, commence */ |
415 | INIT_RCU_HEAD(&p->rcu_head); | 415 | INIT_RCU_HEAD(&p->rcu_head); |
416 | rcu_assign_pointer(disk->__part[partno - 1], p); | 416 | rcu_assign_pointer(disk->__part[partno], p); |
417 | 417 | ||
418 | /* suppress uevent if the disk supresses it */ | 418 | /* suppress uevent if the disk supresses it */ |
419 | if (!ddev->uevent_suppress) | 419 | if (!ddev->uevent_suppress) |
@@ -467,7 +467,7 @@ void register_disk(struct gendisk *disk) | |||
467 | disk_sysfs_add_subdirs(disk); | 467 | disk_sysfs_add_subdirs(disk); |
468 | 468 | ||
469 | /* No minors to use for partitions */ | 469 | /* No minors to use for partitions */ |
470 | if (!disk_max_parts(disk)) | 470 | if (!disk_partitionable(disk)) |
471 | goto exit; | 471 | goto exit; |
472 | 472 | ||
473 | /* No such device (e.g., media were just removed) */ | 473 | /* No such device (e.g., media were just removed) */ |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e4e18c509ac5..9e866a2aee50 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -127,12 +127,13 @@ struct gendisk { | |||
127 | 127 | ||
128 | char disk_name[32]; /* name of major driver */ | 128 | char disk_name[32]; /* name of major driver */ |
129 | 129 | ||
130 | /* Array of pointers to partitions indexed by partno - 1. | 130 | /* Array of pointers to partitions indexed by partno. |
131 | * Protected with matching bdev lock but stat and other | 131 | * Protected with matching bdev lock but stat and other |
132 | * non-critical accesses use RCU. Always access through | 132 | * non-critical accesses use RCU. Always access through |
133 | * helpers. | 133 | * helpers. |
134 | */ | 134 | */ |
135 | struct hd_struct **__part; | 135 | struct hd_struct **__part; |
136 | struct hd_struct part0; | ||
136 | 137 | ||
137 | struct block_device_operations *fops; | 138 | struct block_device_operations *fops; |
138 | struct request_queue *queue; | 139 | struct request_queue *queue; |
@@ -171,7 +172,12 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) | |||
171 | 172 | ||
172 | static inline int disk_max_parts(struct gendisk *disk) | 173 | static inline int disk_max_parts(struct gendisk *disk) |
173 | { | 174 | { |
174 | return disk->minors + disk->ext_minors - 1; | 175 | return disk->minors + disk->ext_minors; |
176 | } | ||
177 | |||
178 | static inline bool disk_partitionable(struct gendisk *disk) | ||
179 | { | ||
180 | return disk_max_parts(disk) > 1; | ||
175 | } | 181 | } |
176 | 182 | ||
177 | static inline dev_t disk_devt(struct gendisk *disk) | 183 | static inline dev_t disk_devt(struct gendisk *disk) |
@@ -197,6 +203,7 @@ static inline void disk_put_part(struct hd_struct *part) | |||
197 | */ | 203 | */ |
198 | #define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ | 204 | #define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ |
199 | #define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ | 205 | #define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ |
206 | #define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */ | ||
200 | 207 | ||
201 | struct disk_part_iter { | 208 | struct disk_part_iter { |
202 | struct gendisk *disk; | 209 | struct gendisk *disk; |