Commit 2e26b412 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] alloc_disk/put_disk

Beginning of proper refcounting.  New helpers introduced, several drivers
switched to using them for dynamic allocation of gendisks.  Once everything
is switched (and that will be way easier than per-drive gendisks series)
we will be able to add sane reference counts on gendisk, at which point
we can safely put pointer to gendisk in struct block_device / struct request
and we had pretty much won - from that point it's pretty straightforward
crapectomy in drivers.
parent db5605b2
......@@ -236,3 +236,18 @@ int __init device_init(void)
__initcall(device_init);
EXPORT_SYMBOL(disk_devclass);
struct gendisk *alloc_disk(void)
{
struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
if (disk)
memset(disk, 0, sizeof(struct gendisk));
return disk;
}
void put_disk(struct gendisk *disk)
{
kfree(disk);
}
EXPORT_SYMBOL(alloc_disk);
EXPORT_SYMBOL(put_disk);
......@@ -954,20 +954,20 @@ EXPORT_SYMBOL(init_irq);
*/
static void init_gendisk (ide_hwif_t *hwif)
{
struct gendisk *gd;
unsigned int unit, units, minors;
unsigned int unit, units;
extern devfs_handle_t ide_devfs_handle;
struct gendisk *disks[MAX_DRIVES];
units = MAX_DRIVES;
minors = units * (1<<PARTN_BITS);
gd = kmalloc(MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL);
if (!gd)
goto err_kmalloc_gd;
memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
for (unit = 0; unit < MAX_DRIVES; unit++) {
disks[unit] = alloc_disk();
if (!disks[unit])
goto err_kmalloc_gd;
}
for (unit = 0; unit < units; ++unit) {
struct gendisk *disk = &gd[unit];
struct gendisk *disk = disks[unit];
disk->major = hwif->major;
disk->first_minor = unit << PARTN_BITS;
sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
......@@ -997,10 +997,10 @@ static void init_gendisk (ide_hwif_t *hwif)
}
return;
err_kmalloc_gd_names:
kfree(gd);
err_kmalloc_gd:
printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
while (unit--)
put_disk(disks[unit]);
}
EXPORT_SYMBOL(init_gendisk);
......
......@@ -1741,7 +1741,6 @@ extern void init_hwif_data(unsigned int index);
void ide_unregister (unsigned int index)
{
struct gendisk *gd;
ide_drive_t *drive, *d;
ide_hwif_t *hwif, *g;
ide_hwgroup_t *hwgroup;
......@@ -1863,12 +1862,10 @@ void ide_unregister (unsigned int index)
unregister_blkdev(hwif->major, hwif->name);
blk_dev[hwif->major].data = NULL;
blk_dev[hwif->major].queue = NULL;
gd = hwif->drives[0].disk;
if (gd) {
int i;
for (i = 0; i < MAX_DRIVES; i++)
hwif->drives[i].disk = NULL;
kfree(gd);
for (i = 0; i < MAX_DRIVES; i++) {
struct gendisk *disk = hwif->drives[i].disk;
hwif->drives[i].disk = NULL;
put_disk(disk);
}
old_hwif = *hwif;
init_hwif_data(index); /* restore hwif data to pristine status */
......
......@@ -1298,26 +1298,22 @@ static int sd_attach(Scsi_Device * sdp)
Scsi_Disk *sdkp;
int dsk_nr;
unsigned long iflags;
struct {
struct gendisk disk;
} *p;
struct gendisk *gd;
if ((NULL == sdp) ||
((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
return 0;
gd = kmalloc(sizeof(*p), GFP_KERNEL);
gd = alloc_disk();
if (!gd)
return 1;
memset(gd, 0, sizeof(*p));
SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n",
sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
if (sd_template.nr_dev >= sd_template.dev_max) {
sdp->attached--;
printk(KERN_ERR "sd_init: no more room for device\n");
kfree(gd);
put_disk(gd);
return 1;
}
......@@ -1337,7 +1333,7 @@ static int sd_attach(Scsi_Device * sdp)
if (dsk_nr >= sd_template.dev_max) {
/* panic("scsi_devices corrupt (sd)"); overkill */
printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n");
kfree(gd);
put_disk(gd);
return 1;
}
......@@ -1417,7 +1413,7 @@ static void sd_detach(Scsi_Device * sdp)
sdp->attached--;
sd_template.dev_noticed--;
sd_template.nr_dev--;
kfree(sd_disks[dsk_nr]);
put_disk(sd_disks[dsk_nr]);
sd_disks[dsk_nr] = NULL;
}
......
......@@ -749,14 +749,13 @@ void sr_finish()
* with loadable modules. */
if (cd->disk)
continue;
disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
disk = alloc_disk();
if (!disk)
continue;
if (cd->disk) {
kfree(disk);
put_disk(disk);
continue;
}
memset(disk, 0, sizeof(struct gendisk));
disk->major = MAJOR_NR;
disk->first_minor = i;
disk->minor_shift = 0;
......@@ -826,7 +825,7 @@ static void sr_detach(Scsi_Device * SDp)
* We should be kind to our buffer cache, however.
*/
del_gendisk(cpnt->disk);
kfree(cpnt->disk);
put_disk(cpnt->disk);
cpnt->disk = NULL;
/*
......
......@@ -262,6 +262,9 @@ char *disk_name (struct gendisk *hd, int part, char *buf);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void update_partition(struct gendisk *disk, int part);
extern struct gendisk *alloc_disk(void);
extern void put_disk(struct gendisk *disk);
/* will go away */
extern void blk_set_probe(int major, struct gendisk *(p)(int));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment