summaryrefslogtreecommitdiff
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)
{
struct hd_struct *part;
- if (unlikely(partno < 1 || partno > disk_max_parts(disk)))
+ if (unlikely(partno < 0 || partno >= disk_max_parts(disk)))
return NULL;
rcu_read_lock();
- part = rcu_dereference(disk->__part[partno - 1]);
+ part = rcu_dereference(disk->__part[partno]);
if (part)
get_device(part_to_dev(part));
rcu_read_unlock();
@@ -85,8 +85,10 @@ void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
if (flags & DISK_PITER_REVERSE)
piter->idx = disk_max_parts(piter->disk) - 1;
- else
+ else if (flags & DISK_PITER_INCL_PART0)
piter->idx = 0;
+ else
+ piter->idx = 1;
piter->flags = flags;
}
@@ -114,7 +116,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
/* determine iteration parameters */
if (piter->flags & DISK_PITER_REVERSE) {
inc = -1;
- end = -1;
+ if (piter->flags & DISK_PITER_INCL_PART0)
+ end = -1;
+ else
+ end = 0;
} else {
inc = 1;
end = disk_max_parts(piter->disk);
@@ -177,7 +182,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector)
{
int i;
- for (i = 0; i < disk_max_parts(disk); i++) {
+ for (i = 1; i < disk_max_parts(disk); i++) {
struct hd_struct *part = rcu_dereference(disk->__part[i]);
if (part && part->start_sect <= sector &&
@@ -669,7 +674,7 @@ static int show_partition(struct seq_file *seqf, void *v)
char buf[BDEVNAME_SIZE];
/* Don't show non-partitionable removeable devices or empty devices */
- if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
+ if (!get_capacity(sgp) || (!disk_partitionable(sgp) &&
(sgp->flags & GENHD_FL_REMOVABLE)))
return 0;
if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
@@ -742,7 +747,7 @@ static ssize_t disk_ext_range_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n", disk_max_parts(disk) + 1);
+ return sprintf(buf, "%d\n", disk_max_parts(disk));
}
static ssize_t disk_removable_show(struct device *dev,
@@ -998,7 +1003,7 @@ dev_t blk_lookup_devt(const char *name, int partno)
if (strcmp(dev->bus_id, name))
continue;
- if (partno < 0 || partno > disk_max_parts(disk))
+ if (partno < 0 || partno >= disk_max_parts(disk))
continue;
if (partno == 0)
@@ -1045,21 +1050,22 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id)
GFP_KERNEL | __GFP_ZERO, node_id);
if (disk) {
int tot_minors = minors + ext_minors;
+ int size = tot_minors * sizeof(struct hd_struct *);
if (!init_disk_stats(disk)) {
kfree(disk);
return NULL;
}
- if (tot_minors > 1) {
- int size = (tot_minors - 1) * sizeof(struct hd_struct *);
- disk->__part = kmalloc_node(size,
- GFP_KERNEL | __GFP_ZERO, node_id);
- if (!disk->__part) {
- free_disk_stats(disk);
- kfree(disk);
- return NULL;
- }
+
+ disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO,
+ node_id);
+ if (!disk->__part) {
+ free_disk_stats(disk);
+ kfree(disk);
+ return NULL;
}
+ disk->__part[0] = &disk->part0;
+
disk->minors = minors;
disk->ext_minors = ext_minors;
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
if (bdev != bdev->bd_contains)
return -EINVAL;
partno = p.pno;
- if (partno <= 0 || partno > disk_max_parts(disk))
+ if (partno <= 0 || partno >= disk_max_parts(disk))
return -EINVAL;
switch (a.op) {
case BLKPG_ADD_PARTITION:
@@ -102,7 +102,7 @@ static int blkdev_reread_part(struct block_device *bdev)
struct gendisk *disk = bdev->bd_disk;
int res;
- if (!disk_max_parts(disk) || bdev != bdev->bd_contains)
+ if (!disk_partitionable(disk) || bdev != bdev->bd_contains)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
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)
if (bdops->revalidate_disk)
bdops->revalidate_disk(bdev->bd_disk);
- if (disk_max_parts(bdev->bd_disk))
+ if (disk_partitionable(bdev->bd_disk))
bdev->bd_invalidated = 1;
return 1;
}
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)
if (isdigit(state->name[strlen(state->name)-1]))
sprintf(state->name, "p");
- state->limit = disk_max_parts(hd) + 1;
+ state->limit = disk_max_parts(hd);
i = res = err = 0;
while (!res && check_part[i]) {
memset(&state->parts, 0, sizeof(state->parts));
@@ -329,12 +329,12 @@ void delete_partition(struct gendisk *disk, int partno)
{
struct hd_struct *part;
- part = disk->__part[partno-1];
+ part = disk->__part[partno];
if (!part)
return;
blk_free_devt(part_devt(part));
- rcu_assign_pointer(disk->__part[partno-1], NULL);
+ rcu_assign_pointer(disk->__part[partno], NULL);
kobject_put(part->holder_dir);
device_del(part_to_dev(part));
@@ -359,7 +359,7 @@ int add_partition(struct gendisk *disk, int partno,
const char *dname;
int err;
- if (disk->__part[partno - 1])
+ if (disk->__part[partno])
return -EBUSY;
p = kzalloc(sizeof(*p), GFP_KERNEL);
@@ -413,7 +413,7 @@ int add_partition(struct gendisk *disk, int partno,
/* everything is up and running, commence */
INIT_RCU_HEAD(&p->rcu_head);
- rcu_assign_pointer(disk->__part[partno - 1], p);
+ rcu_assign_pointer(disk->__part[partno], p);
/* suppress uevent if the disk supresses it */
if (!ddev->uevent_suppress)
@@ -467,7 +467,7 @@ void register_disk(struct gendisk *disk)
disk_sysfs_add_subdirs(disk);
/* No minors to use for partitions */
- if (!disk_max_parts(disk))
+ if (!disk_partitionable(disk))
goto exit;
/* 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 {
char disk_name[32]; /* name of major driver */
- /* Array of pointers to partitions indexed by partno - 1.
+ /* Array of pointers to partitions indexed by partno.
* Protected with matching bdev lock but stat and other
* non-critical accesses use RCU. Always access through
* helpers.
*/
struct hd_struct **__part;
+ struct hd_struct part0;
struct block_device_operations *fops;
struct request_queue *queue;
@@ -171,7 +172,12 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part)
static inline int disk_max_parts(struct gendisk *disk)
{
- return disk->minors + disk->ext_minors - 1;
+ return disk->minors + disk->ext_minors;
+}
+
+static inline bool disk_partitionable(struct gendisk *disk)
+{
+ return disk_max_parts(disk) > 1;
}
static inline dev_t disk_devt(struct gendisk *disk)
@@ -197,6 +203,7 @@ static inline void disk_put_part(struct hd_struct *part)
*/
#define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */
#define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */
+#define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */
struct disk_part_iter {
struct gendisk *disk;