aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-09-03 03:06:42 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:07 -0400
commitb5d0b9df0ba5d9a044f3a21e7544f53d90bd1465 (patch)
treed3347c1cfc59cf5d38c2c9adc2423f9d9b4cf818
parented9e1982347b36573cd622ee5f4e2a7ccd79b3fd (diff)
block: introduce partition 0
genhd and partition code handled disk and partitions separately. All information about the whole disk was in struct genhd and partitions in struct hd_struct. However, the whole disk (part0) and other partitions have a lot in common and the data structures end up having good number of common fields and thus separate code paths doing the same thing. Also, the partition array was indexed by partno - 1 which gets pretty confusing at times. This patch introduces partition 0 and makes the partition array indexed by partno. Following patches will unify the handling of disk and parts piece-by-piece. This patch also implements disk_partitionable() which tests whether a disk is partitionable. With coming dynamic partition array change, the most common usage of disk_max_parts() will be testing whether a disk is partitionable and the number of max partitions will become much less important. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-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;