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) ...@@ -236,3 +236,18 @@ int __init device_init(void)
__initcall(device_init); __initcall(device_init);
EXPORT_SYMBOL(disk_devclass); 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); ...@@ -954,20 +954,20 @@ EXPORT_SYMBOL(init_irq);
*/ */
static void init_gendisk (ide_hwif_t *hwif) static void init_gendisk (ide_hwif_t *hwif)
{ {
struct gendisk *gd; unsigned int unit, units;
unsigned int unit, units, minors;
extern devfs_handle_t ide_devfs_handle; extern devfs_handle_t ide_devfs_handle;
struct gendisk *disks[MAX_DRIVES];
units = MAX_DRIVES; units = MAX_DRIVES;
minors = units * (1<<PARTN_BITS); for (unit = 0; unit < MAX_DRIVES; unit++) {
gd = kmalloc(MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL); disks[unit] = alloc_disk();
if (!gd) if (!disks[unit])
goto err_kmalloc_gd; goto err_kmalloc_gd;
memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk)); }
for (unit = 0; unit < units; ++unit) { for (unit = 0; unit < units; ++unit) {
struct gendisk *disk = &gd[unit]; struct gendisk *disk = disks[unit];
disk->major = hwif->major; disk->major = hwif->major;
disk->first_minor = unit << PARTN_BITS; disk->first_minor = unit << PARTN_BITS;
sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit); sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
...@@ -997,10 +997,10 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -997,10 +997,10 @@ static void init_gendisk (ide_hwif_t *hwif)
} }
return; return;
err_kmalloc_gd_names:
kfree(gd);
err_kmalloc_gd: err_kmalloc_gd:
printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n"); printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
while (unit--)
put_disk(disks[unit]);
} }
EXPORT_SYMBOL(init_gendisk); EXPORT_SYMBOL(init_gendisk);
......
...@@ -1741,7 +1741,6 @@ extern void init_hwif_data(unsigned int index); ...@@ -1741,7 +1741,6 @@ extern void init_hwif_data(unsigned int index);
void ide_unregister (unsigned int index) void ide_unregister (unsigned int index)
{ {
struct gendisk *gd;
ide_drive_t *drive, *d; ide_drive_t *drive, *d;
ide_hwif_t *hwif, *g; ide_hwif_t *hwif, *g;
ide_hwgroup_t *hwgroup; ide_hwgroup_t *hwgroup;
...@@ -1863,12 +1862,10 @@ void ide_unregister (unsigned int index) ...@@ -1863,12 +1862,10 @@ void ide_unregister (unsigned int index)
unregister_blkdev(hwif->major, hwif->name); unregister_blkdev(hwif->major, hwif->name);
blk_dev[hwif->major].data = NULL; blk_dev[hwif->major].data = NULL;
blk_dev[hwif->major].queue = NULL; blk_dev[hwif->major].queue = NULL;
gd = hwif->drives[0].disk; for (i = 0; i < MAX_DRIVES; i++) {
if (gd) { struct gendisk *disk = hwif->drives[i].disk;
int i; hwif->drives[i].disk = NULL;
for (i = 0; i < MAX_DRIVES; i++) put_disk(disk);
hwif->drives[i].disk = NULL;
kfree(gd);
} }
old_hwif = *hwif; old_hwif = *hwif;
init_hwif_data(index); /* restore hwif data to pristine status */ init_hwif_data(index); /* restore hwif data to pristine status */
......
...@@ -1298,26 +1298,22 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1298,26 +1298,22 @@ static int sd_attach(Scsi_Device * sdp)
Scsi_Disk *sdkp; Scsi_Disk *sdkp;
int dsk_nr; int dsk_nr;
unsigned long iflags; unsigned long iflags;
struct {
struct gendisk disk;
} *p;
struct gendisk *gd; struct gendisk *gd;
if ((NULL == sdp) || if ((NULL == sdp) ||
((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))) ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
return 0; return 0;
gd = kmalloc(sizeof(*p), GFP_KERNEL); gd = alloc_disk();
if (!gd) if (!gd)
return 1; return 1;
memset(gd, 0, sizeof(*p));
SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n",
sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
if (sd_template.nr_dev >= sd_template.dev_max) { if (sd_template.nr_dev >= sd_template.dev_max) {
sdp->attached--; sdp->attached--;
printk(KERN_ERR "sd_init: no more room for device\n"); printk(KERN_ERR "sd_init: no more room for device\n");
kfree(gd); put_disk(gd);
return 1; return 1;
} }
...@@ -1337,7 +1333,7 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1337,7 +1333,7 @@ static int sd_attach(Scsi_Device * sdp)
if (dsk_nr >= sd_template.dev_max) { if (dsk_nr >= sd_template.dev_max) {
/* panic("scsi_devices corrupt (sd)"); overkill */ /* panic("scsi_devices corrupt (sd)"); overkill */
printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n"); printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n");
kfree(gd); put_disk(gd);
return 1; return 1;
} }
...@@ -1417,7 +1413,7 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1417,7 +1413,7 @@ static void sd_detach(Scsi_Device * sdp)
sdp->attached--; sdp->attached--;
sd_template.dev_noticed--; sd_template.dev_noticed--;
sd_template.nr_dev--; sd_template.nr_dev--;
kfree(sd_disks[dsk_nr]); put_disk(sd_disks[dsk_nr]);
sd_disks[dsk_nr] = NULL; sd_disks[dsk_nr] = NULL;
} }
......
...@@ -749,14 +749,13 @@ void sr_finish() ...@@ -749,14 +749,13 @@ void sr_finish()
* with loadable modules. */ * with loadable modules. */
if (cd->disk) if (cd->disk)
continue; continue;
disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); disk = alloc_disk();
if (!disk) if (!disk)
continue; continue;
if (cd->disk) { if (cd->disk) {
kfree(disk); put_disk(disk);
continue; continue;
} }
memset(disk, 0, sizeof(struct gendisk));
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = i; disk->first_minor = i;
disk->minor_shift = 0; disk->minor_shift = 0;
...@@ -826,7 +825,7 @@ static void sr_detach(Scsi_Device * SDp) ...@@ -826,7 +825,7 @@ static void sr_detach(Scsi_Device * SDp)
* We should be kind to our buffer cache, however. * We should be kind to our buffer cache, however.
*/ */
del_gendisk(cpnt->disk); del_gendisk(cpnt->disk);
kfree(cpnt->disk); put_disk(cpnt->disk);
cpnt->disk = NULL; cpnt->disk = NULL;
/* /*
......
...@@ -262,6 +262,9 @@ char *disk_name (struct gendisk *hd, int part, char *buf); ...@@ -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 int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void update_partition(struct gendisk *disk, int part); 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 */ /* will go away */
extern void blk_set_probe(int major, struct gendisk *(p)(int)); 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