aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/genhd.c40
-rw-r--r--block/ioctl.c4
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/partitions/check.c12
-rw-r--r--include/linux/genhd.h11
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
748static ssize_t disk_removable_show(struct device *dev, 753static 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
172static inline int disk_max_parts(struct gendisk *disk) 173static 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
178static inline bool disk_partitionable(struct gendisk *disk)
179{
180 return disk_max_parts(disk) > 1;
175} 181}
176 182
177static inline dev_t disk_devt(struct gendisk *disk) 183static 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
201struct disk_part_iter { 208struct disk_part_iter {
202 struct gendisk *disk; 209 struct gendisk *disk;