summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-04-20 00:29:12 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-20 00:29:12 -0700
commit5fb58500eec7e5afab139a6b3825c55fbbeff48c (patch)
tree2d5274d558729b4d8cb3842f58d310ad6a5c728a
parent88bdd4c3d1faed465755e2b0f5b9c34352693ac5 (diff)
[PATCH] Allocate hd_structs dynamically
From: Badari Pulavarty <pbadari@us.ibm.com> Here is the patch to allocate hd_struct dynamically as we find partitions. There are 3 things I didn't like in the patch. 1) The patch allocates 15 pointers instead of 15 hd_structs. (incase of s= csi). I was really hoping to get rid of "15" and make it really dynamic. (In ca= se if we ever want to support more than 15 partitions per disk etc..).=20 I was thought about making it a linked list, but blk_partition_remap() needs to get to hd_struct for a given partition everytime we do IO. So linked list would be bad, we really need direct access to partition in= fo. 2) I had to add "partno" to hd_struct, since part_dev_read() used to calc= ulate partition number from the address before. 3) kmalloc() failure in add_partition() will be silently ignored. It saves 2048 bytes per disk.
-rw-r--r--drivers/block/cciss.c9
-rw-r--r--drivers/block/genhd.c19
-rw-r--r--drivers/block/ioctl.c11
-rw-r--r--drivers/block/ll_rw_blk.c2
-rw-r--r--fs/block_dev.c4
-rw-r--r--fs/partitions/check.c17
-rw-r--r--include/linux/genhd.h4
7 files changed, 44 insertions, 22 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8987b67272cd..f566e20e2094 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -599,9 +599,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
luninfo.num_opens = drv->usage_count;
luninfo.num_parts = 0;
/* count partitions 1 to 15 with sizes > 0 */
- for(i=1; i <MAX_PART; i++)
- if (disk->part[i].nr_sects != 0)
- luninfo.num_parts++;
+ for(i=1; i <MAX_PART; i++) {
+ if (!disk->part[i])
+ continue;
+ if (disk->part[i]->nr_sects != 0)
+ luninfo.num_parts++;
+ }
if (copy_to_user((void *) arg, &luninfo,
sizeof(LogvolInfo_struct)))
return -EFAULT;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 032739646da9..af193deee80c 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -365,11 +365,13 @@ static int show_partition(struct seq_file *part, void *v)
(unsigned long long)get_capacity(sgp) >> 1,
disk_name(sgp, 0, buf));
for (n = 0; n < sgp->minors - 1; n++) {
- if (sgp->part[n].nr_sects == 0)
+ if (!sgp->part[n])
+ continue;
+ if (sgp->part[n]->nr_sects == 0)
continue;
seq_printf(part, "%4d %4d %10llu %s\n",
sgp->major, n + 1 + sgp->first_minor,
- (unsigned long long)sgp->part[n].nr_sects >> 1 ,
+ (unsigned long long)sgp->part[n]->nr_sects >> 1 ,
disk_name(sgp, n + 1, buf));
}
@@ -552,7 +554,7 @@ struct gendisk *alloc_disk(int minors)
return NULL;
}
if (minors > 1) {
- int size = (minors - 1) * sizeof(struct hd_struct);
+ int size = (minors - 1) * sizeof(struct hd_struct *);
disk->part = kmalloc(size, GFP_KERNEL);
if (!disk->part) {
kfree(disk);
@@ -604,8 +606,8 @@ void set_device_ro(struct block_device *bdev, int flag)
struct gendisk *disk = bdev->bd_disk;
if (bdev->bd_contains != bdev) {
int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor);
- struct hd_struct *p = &disk->part[part-1];
- p->policy = flag;
+ struct hd_struct *p = disk->part[part-1];
+ if (p) p->policy = flag;
} else
disk->policy = flag;
}
@@ -615,7 +617,7 @@ void set_disk_ro(struct gendisk *disk, int flag)
int i;
disk->policy = flag;
for (i = 0; i < disk->minors - 1; i++)
- disk->part[i].policy = flag;
+ if (disk->part[i]) disk->part[i]->policy = flag;
}
int bdev_read_only(struct block_device *bdev)
@@ -626,8 +628,9 @@ int bdev_read_only(struct block_device *bdev)
disk = bdev->bd_disk;
if (bdev->bd_contains != bdev) {
int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor);
- struct hd_struct *p = &disk->part[part-1];
- return p->policy;
+ struct hd_struct *p = disk->part[part-1];
+ if (p) return p->policy;
+ return 0;
} else
return disk->policy;
}
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 538c8a04a2d3..3dbd0824319b 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -41,11 +41,14 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
return -EINVAL;
}
/* partition number in use? */
- if (disk->part[part - 1].nr_sects != 0)
+ if (disk->part[part - 1])
return -EBUSY;
/* overlap? */
for (i = 0; i < disk->minors - 1; i++) {
- struct hd_struct *s = &disk->part[i];
+ struct hd_struct *s = disk->part[i];
+
+ if (!s)
+ continue;
if (!(start+length <= s->start_sect ||
start >= s->start_sect + s->nr_sects))
return -EBUSY;
@@ -54,7 +57,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
add_partition(disk, part, start, length);
return 0;
case BLKPG_DEL_PARTITION:
- if (disk->part[part - 1].nr_sects == 0)
+ if (!disk->part[part-1])
+ return -ENXIO;
+ if (disk->part[part - 1]->nr_sects == 0)
return -ENXIO;
/* partition in use? Incomplete check for now. */
bdevp = bdget(MKDEV(disk->major, disk->first_minor) + part);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index e14210308577..9e2fd26ce0ed 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1841,7 +1841,7 @@ static inline void blk_partition_remap(struct bio *bio)
if (bdev == bdev->bd_contains)
return;
- p = &disk->part[bdev->bd_dev-MKDEV(disk->major,disk->first_minor)-1];
+ p = disk->part[bdev->bd_dev-MKDEV(disk->major,disk->first_minor)-1];
switch (bio->bi_rw) {
case READ:
p->read_sectors += bio_sectors(bio);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 948864b885b5..9a974170a10b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -559,10 +559,10 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
bdev->bd_contains = whole;
down(&whole->bd_sem);
whole->bd_part_count++;
- p = disk->part + part - 1;
+ p = disk->part[part - 1];
bdev->bd_inode->i_data.backing_dev_info =
whole->bd_inode->i_data.backing_dev_info;
- if (!(disk->flags & GENHD_FL_UP) || !p->nr_sects) {
+ if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) {
whole->bd_part_count--;
up(&whole->bd_sem);
ret = -ENXIO;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 647f0357e30c..aa0646e44598 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -182,7 +182,7 @@ static struct sysfs_ops part_sysfs_ops = {
static ssize_t part_dev_read(struct hd_struct * p, char *page)
{
struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
- int part = p - disk->part + 1;
+ int part = p->partno;
dev_t base = MKDEV(disk->major, disk->first_minor);
return sprintf(page, "%04x\n", (unsigned)(base + part));
}
@@ -234,7 +234,9 @@ struct kobj_type ktype_part = {
void delete_partition(struct gendisk *disk, int part)
{
- struct hd_struct *p = disk->part + part - 1;
+ struct hd_struct *p = disk->part[part-1];
+ if (!p)
+ return;
if (!p->nr_sects)
return;
p->start_sect = 0;
@@ -242,14 +244,23 @@ void delete_partition(struct gendisk *disk, int part)
p->reads = p->writes = p->read_sectors = p->write_sectors = 0;
devfs_remove("%s/part%d", disk->devfs_name, part);
kobject_unregister(&p->kobj);
+ disk->part[part-1] = NULL;
+ kfree(p);
}
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
{
- struct hd_struct *p = disk->part + part - 1;
+ struct hd_struct *p;
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memset(p, 0, sizeof(*p));
p->start_sect = start;
p->nr_sects = len;
+ p->partno = part;
+ disk->part[part-1] = p;
devfs_register_partition(disk, part);
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
p->kobj.parent = &disk->kobj;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index c2432bd349e5..ac8fc9ef5bdb 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -64,7 +64,7 @@ struct hd_struct {
sector_t nr_sects;
struct kobject kobj;
unsigned reads, read_sectors, writes, write_sectors;
- int policy;
+ int policy, partno;
};
#define GENHD_FL_REMOVABLE 1
@@ -89,7 +89,7 @@ struct gendisk {
int minor_shift; /* number of times minor is shifted to
get real minor */
char disk_name[16]; /* name of major driver */
- struct hd_struct *part; /* [indexed by minor] */
+ struct hd_struct **part; /* [indexed by minor] */
struct block_device_operations *fops;
struct request_queue *queue;
void *private_data;