diff options
author | Tejun Heo <tj@kernel.org> | 2008-09-03 03:06:42 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:07 -0400 |
commit | b5d0b9df0ba5d9a044f3a21e7544f53d90bd1465 (patch) | |
tree | d3347c1cfc59cf5d38c2c9adc2423f9d9b4cf818 | |
parent | ed9e1982347b36573cd622ee5f4e2a7ccd79b3fd (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.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; |