diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-04-20 00:29:12 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-04-20 00:29:12 -0700 |
| commit | 5fb58500eec7e5afab139a6b3825c55fbbeff48c (patch) | |
| tree | 2d5274d558729b4d8cb3842f58d310ad6a5c728a | |
| parent | 88bdd4c3d1faed465755e2b0f5b9c34352693ac5 (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.c | 9 | ||||
| -rw-r--r-- | drivers/block/genhd.c | 19 | ||||
| -rw-r--r-- | drivers/block/ioctl.c | 11 | ||||
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 2 | ||||
| -rw-r--r-- | fs/block_dev.c | 4 | ||||
| -rw-r--r-- | fs/partitions/check.c | 17 | ||||
| -rw-r--r-- | include/linux/genhd.h | 4 |
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; |
