diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index f738b5ba02e065fbd202167d693b44300a3c73dc..943b0c672646934ec63599f3d4d10af4dfaccf1f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -415,8 +415,7 @@ static struct floppy_drive_params drive_params[N_DRIVE]; static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE]; -static struct gendisk disks[N_DRIVE]; -static char names[N_DRIVE][4]; +static struct gendisk *disks[N_DRIVE]; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; /* @@ -3772,7 +3771,7 @@ static int floppy_open(struct inode * inode, struct file * filp) } UDRS->fd_device = minor(inode->i_rdev); - set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]); + set_capacity(disks[drive], floppy_sizes[minor(inode->i_rdev)]); if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (buffer_drive == drive) buffer_track = -1; @@ -3952,7 +3951,7 @@ static int floppy_revalidate(kdev_t dev) process_fd_request(); } } - set_capacity(&disks[drive], floppy_sizes[minor(dev)]); + set_capacity(disks[drive], floppy_sizes[minor(dev)]); return res; } @@ -4230,26 +4229,34 @@ static struct gendisk *floppy_find(int minor) !(allowed_drive_mask & (1 << drive)) || fdc_state[FDC(drive)].version == FDC_NONE) return NULL; - return &disks[drive]; + return disks[drive]; } int __init floppy_init(void) { int i,unit,drive; + int err; raw_cmd = NULL; + for (i=0; i<N_DRIVE; i++) { + disks[i] = alloc_disk(); + if (!disks[i]) + goto Enomem; + } + devfs_handle = devfs_mk_dir (NULL, "floppy", NULL); if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { printk("Unable to get major %d for floppy\n",MAJOR_NR); - return -EBUSY; + err = -EBUSY; + goto out; } for (i=0; i<N_DRIVE; i++) { - disks[i].major = MAJOR_NR; - disks[i].first_minor = TOMINOR(i); - disks[i].fops = &floppy_fops; - sprintf(disks[i].disk_name, "fd%d", i); + disks[i]->major = MAJOR_NR; + disks[i]->first_minor = TOMINOR(i); + disks[i]->fops = &floppy_fops; + sprintf(disks[i]->disk_name, "fd%d", i); } blk_set_probe(MAJOR_NR, floppy_find); @@ -4281,11 +4288,8 @@ int __init floppy_init(void) use_virtual_dma = can_use_virtual_dma & 1; fdc_state[0].address = FDC1; if (fdc_state[0].address == -1) { - unregister_blkdev(MAJOR_NR,"fd"); - del_timer(&fd_timeout); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - blk_set_probe(MAJOR_NR, NULL); - return -ENODEV; + err = -ENODEV; + goto out1; } #if N_FDC > 1 fdc_state[1].address = FDC2; @@ -4293,11 +4297,8 @@ int __init floppy_init(void) fdc = 0; /* reset fdc in case of unexpected interrupt */ if (floppy_grab_irq_and_dma()){ - del_timer(&fd_timeout); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - unregister_blkdev(MAJOR_NR,"fd"); - blk_set_probe(MAJOR_NR, NULL); - return -EBUSY; + err = -EBUSY; + goto out1; } /* initialise drive state */ @@ -4352,15 +4353,13 @@ int __init floppy_init(void) current_drive = 0; floppy_release_irq_and_dma(); initialising=0; - if (have_no_fdc) - { + if (have_no_fdc) { DPRINT("no floppy controllers found\n"); flush_scheduled_work(); if (usage_count) floppy_release_irq_and_dma(); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - unregister_blkdev(MAJOR_NR,"fd"); - blk_set_probe(MAJOR_NR, NULL); + err = have_no_fdc; + goto out2; } for (drive = 0; drive < N_DRIVE; drive++) { @@ -4370,12 +4369,27 @@ int __init floppy_init(void) continue; if (fdc_state[FDC(drive)].version == FDC_NONE) continue; - add_disk(disks + drive); + add_disk(disks[drive]); } platform_device_register(&floppy_device); + return 0; - return have_no_fdc; +out1: + del_timer(&fd_timeout); +out2: + unregister_blkdev(MAJOR_NR,"fd"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + blk_set_probe(MAJOR_NR, NULL); +out: + for (i=0; i<N_DRIVE; i++) + put_disk(disks[i]); + return err; + +Enomem: + while (i--) + put_disk(disks[i]); + return -ENOMEM; } static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED; @@ -4564,7 +4578,8 @@ void cleanup_module(void) for (drive = 0; drive < N_DRIVE; drive++) { if ((allowed_drive_mask & (1 << drive)) && fdc_state[FDC(drive)].version != FDC_NONE) - del_gendisk(disks + drive); + del_gendisk(disks[drive]); + put_disk(disks[drive]); } blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f5585acc12f68f55fcb75779f40055ea0072e1a8..090917c43969f869bc076b0ea35fbd81ab62507b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -83,7 +83,7 @@ static int max_loop = 8; static struct loop_device *loop_dev; -static struct gendisk *disks; +static struct gendisk **disks; static devfs_handle_t devfs_handle; /* For the directory */ /* @@ -159,9 +159,7 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { static void figure_loop_size(struct loop_device *lo) { loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_size; - - set_capacity(disks + lo->lo_number, - (size - lo->lo_offset) >> 9); + set_capacity(disks[lo->lo_number], (size - lo->lo_offset) >> 9); } static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, @@ -809,7 +807,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev, 0); - set_capacity(disks + lo->lo_number, 0); + set_capacity(disks[lo->lo_number], 0); filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; lo->lo_state = Lo_unbound; fput(filp); @@ -1048,20 +1046,25 @@ int __init loop_init(void) if (!loop_dev) return -ENOMEM; - disks = kmalloc(max_loop * sizeof(struct gendisk), GFP_KERNEL); + disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); if (!disks) goto out_mem; + for (i = 0; i < max_loop; i++) { + disks[i] = alloc_disk(); + if (!disks[i]) + goto out_mem2; + } + for (i = 0; i < max_loop; i++) { struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks + i; + struct gendisk *disk = disks[i]; memset(lo, 0, sizeof(struct loop_device)); init_MUTEX(&lo->lo_ctl_mutex); init_MUTEX_LOCKED(&lo->lo_sem); init_MUTEX_LOCKED(&lo->lo_bh_mutex); lo->lo_number = i; spin_lock_init(&lo->lo_lock); - memset(disk, 0, sizeof(struct gendisk)); disk->major = LOOP_MAJOR; disk->first_minor = i; disk->fops = &lo_fops; @@ -1074,6 +1077,9 @@ int __init loop_init(void) printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; +out_mem2: + while (i--) + put_disk(disks[i]); out_mem: kfree(disks); kfree(loop_dev); @@ -1084,8 +1090,10 @@ int __init loop_init(void) void loop_exit(void) { int i; - for (i = 0; i < max_loop; i++) - del_gendisk(disks + i); + for (i = 0; i < max_loop; i++) { + del_gendisk(disks[i]); + put_disk(disks[i]); + } devfs_unregister(devfs_handle); if (unregister_blkdev(MAJOR_NR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index f6aec9fe3ef54eabc8d92918b7d24faa8e7783b3..7fdf4a3e4b2a4bc42286703889ce6135fcc0d0db 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -276,7 +276,7 @@ struct pd_unit { int alt_geom; int present; char name[PD_NAMELEN]; /* pda, pdb, etc ... */ - struct gendisk gd; + struct gendisk *gd; }; struct pd_unit pd[PD_UNITS]; @@ -287,8 +287,6 @@ static void pd_doorlock(struct pd_unit *disk, int func); static int pd_check_media(kdev_t dev); static void pd_eject(struct pd_unit *disk); -/* 'unit' must be defined in all functions - either as a local or a param */ - static char pd_scratch[512]; /* scratch block buffer */ /* the variables below are used mainly in the I/O request engine, which @@ -368,11 +366,8 @@ static int pd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hd_geometry *geo = (struct hd_geometry *) arg; - int err, unit = DEVICE_NR(inode->i_rdev); - struct pd_unit *disk = pd + unit; - - if (!disk->present) - return -ENODEV; + struct hd_geometry g; + struct pd_unit *disk = pd + DEVICE_NR(inode->i_rdev); switch (cmd) { case CDROMEJECT: @@ -380,23 +375,18 @@ static int pd_ioctl(struct inode *inode, struct file *file, pd_eject(disk); return 0; case HDIO_GETGEO: - if (!geo) - return -EINVAL; - err = verify_area(VERIFY_WRITE, geo, sizeof (*geo)); - if (err) - return err; - if (disk->alt_geom) { - put_user(disk->capacity / (PD_LOG_HEADS * PD_LOG_SECTS), - (short *) &geo->cylinders); - put_user(PD_LOG_HEADS, (char *) &geo->heads); - put_user(PD_LOG_SECTS, (char *) &geo->sectors); + g.heads = PD_LOG_HEADS; + g.sectors = PD_LOG_SECTS; + g.cylinders = disk->capacity / (g.heads * g.sectors); } else { - put_user(disk->cylinders, (short *) &geo->cylinders); - put_user(disk->heads, (char *) &geo->heads); - put_user(disk->sectors, (char *) &geo->sectors); + g.heads = disk->heads; + g.sectors = disk->sectors; + g.cylinders = disk->cylinders; } - put_user(get_start_sect(inode->i_bdev), (long *) &geo->start); + g.start = get_start_sect(inode->i_bdev); + if (copy_to_user(geo, &g, sizeof(struct hd_geometry))) + return -EFAULT; return 0; default: return -EINVAL; @@ -418,8 +408,6 @@ static int pd_check_media(kdev_t dev) { int r, unit = DEVICE_NR(dev); struct pd_unit *disk = pd + unit; - if (unit >= PD_UNITS || (!disk->present)) - return -ENODEV; if (!disk->removable) return 0; pd_media_check(disk); @@ -432,12 +420,10 @@ static int pd_revalidate(kdev_t dev) { int unit = DEVICE_NR(dev); struct pd_unit *disk = pd + unit; - if (unit >= PD_UNITS || !disk->present) - return -ENODEV; if (pd_identify(disk)) - set_capacity(&disk->gd, disk->capacity); + set_capacity(disk->gd, disk->capacity); else - set_capacity(&disk->gd, 0); + set_capacity(disk->gd, 0); return 0; } @@ -717,13 +703,20 @@ static int pd_detect(void) } for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { if (disk->present) { - strcpy(disk->gd.disk_name, disk->name); - disk->gd.minor_shift = PD_BITS; - disk->gd.fops = &pd_fops; - disk->gd.major = major; - disk->gd.first_minor = unit << PD_BITS; - set_capacity(&disk->gd, disk->capacity); - add_disk(&disk->gd); + struct gendisk *p = alloc_disk(); + if (!p) { + disk->present = 0; + k--; + continue; + } + strcpy(p->disk_name, disk->name); + p->minor_shift = PD_BITS; + p->fops = &pd_fops; + p->major = major; + p->first_minor = unit << PD_BITS; + set_capacity(p, disk->capacity); + disk->gd = p; + add_disk(p); } } if (k) @@ -760,7 +753,7 @@ static void do_pd_request(request_queue_t * q) pd_run = pd_req->nr_sectors; pd_count = pd_req->current_nr_sectors; pd_current = pd + unit; - if (pd_block + pd_count > get_capacity(&pd_current->gd)) { + if (pd_block + pd_count > get_capacity(pd_current->gd)) { end_request(pd_req, 0); goto repeat; } @@ -942,7 +935,10 @@ static void __exit pd_exit(void) unregister_blkdev(MAJOR_NR, name); for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { if (disk->present) { - del_gendisk(&disk->gd); + struct gendisk *p = disk->gd; + disk->gd = NULL; + del_gendisk(p); + put_disk(p); pi_release(disk->pi); } } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 6e7ffb54f016a28901e8adef1fdde18153d8d8cb..4ebb02d724ee592774e57069644e29b997962b8c 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -77,7 +77,7 @@ int initrd_below_start_ok; */ static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */ -static struct gendisk rd_disks[NUM_RAMDISKS]; +static struct gendisk *rd_disks[NUM_RAMDISKS]; static devfs_handle_t devfs_handle; static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ @@ -310,13 +310,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un #ifdef CONFIG_BLK_DEV_INITRD static struct block_device_operations rd_bd_op; -static struct gendisk initrd_disk = { - .major = MAJOR_NR, - .first_minor = INITRD_MINOR, - .minor_shift = 0, - .fops = &rd_bd_op, - .disk_name = "initrd" -}; +static struct gendisk *initrd_disk; static ssize_t initrd_read(struct file *file, char *buf, size_t count, loff_t *ppos) @@ -340,7 +334,7 @@ static int initrd_release(struct inode *inode,struct file *file) spin_lock(&initrd_users_lock); if (!--initrd_users) { spin_unlock(&initrd_users_lock); - del_gendisk(&initrd_disk); + del_gendisk(initrd_disk); free_initrd_mem(initrd_start, initrd_end); initrd_start = 0; } else { @@ -412,8 +406,12 @@ static void __exit rd_cleanup (void) invalidate_bdev(bdev, 1); blkdev_put(bdev, BDEV_FILE); } - del_gendisk(rd_disks + i); + del_gendisk(rd_disks[i]); + put_disk(rd_disks[i]); } +#ifdef CONFIG_BLK_DEV_INITRD + put_disk(initrd_disk); +#endif devfs_unregister (devfs_handle); unregister_blkdev( MAJOR_NR, "ramdisk" ); @@ -423,6 +421,7 @@ static void __exit rd_cleanup (void) static int __init rd_init (void) { int i; + int err = -ENOMEM; if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || (rd_blocksize & (rd_blocksize-1))) { @@ -431,15 +430,32 @@ static int __init rd_init (void) rd_blocksize = BLOCK_SIZE; } +#ifdef CONFIG_BLK_DEV_INITRD + initrd_disk = alloc_disk(); + if (!initrd_disk) + return -ENOMEM; + initrd_disk->major = MAJOR_NR; + initrd_disk->first_minor = INITRD_MINOR; + initrd_disk->minor_shift = 0; + initrd_disk->fops = &rd_bd_op; + sprintf(initrd_disk->disk_name, "initrd"); +#endif + for (i = 0; i < NUM_RAMDISKS; i++) { + rd_disks[i] = alloc_disk(); + if (!rd_disks[i]) + goto out; + } + if (register_blkdev(MAJOR_NR, "ramdisk", &rd_bd_op)) { printk("RAMDISK: Could not get major %d", MAJOR_NR); - return -EIO; + err = -EIO; + goto out; } blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request); for (i = 0; i < NUM_RAMDISKS; i++) { - struct gendisk *disk = rd_disks + i; + struct gendisk *disk = rd_disks[i]; /* rd_size is given in kB */ rd_length[i] = rd_size << 10; disk->major = MAJOR_NR; @@ -456,11 +472,11 @@ static int __init rd_init (void) &rd_bd_op, NULL); for (i = 0; i < NUM_RAMDISKS; i++) - add_disk(rd_disks + i); + add_disk(rd_disks[i]); #ifdef CONFIG_BLK_DEV_INITRD /* We ought to separate initrd operations here */ - add_disk(&initrd_disk); + add_disk(initrd_disk); devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR, INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL); #endif @@ -471,6 +487,13 @@ static int __init rd_init (void) NUM_RAMDISKS, rd_size, rd_blocksize); return 0; +out: + while (i--) + put_disk(rd_disks[i]); +#ifdef CONFIG_BLK_DEV_INITRD + put_disk(initrd_disk); +#endif + return err; } module_init(rd_init); diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c index 59148c11e1f7be76b914cfadf4b1e4cb4c9f7786..53f8fe2bafe2062c621259606a617671ee353166 100644 --- a/drivers/cdrom/aztcd.c +++ b/drivers/cdrom/aztcd.c @@ -1690,13 +1690,7 @@ static int aztcd_release(struct inode *inode, struct file *file) return 0; } -static struct gendisk azt_disk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .fops = &azt_fops, - .disk_name = "aztcd" -}; +static struct gendisk *azt_disk; /* * Test for presence of drive and initialize it. Called at boot time. @@ -1844,6 +1838,7 @@ static int __init aztcd_init(void) for (count = 0; count < AZT_TIMEOUT; count++) barrier(); /* Stop gcc 2.96 being smart */ + /* use udelay(), damnit -- AV */ if ((st = getAztStatus()) == -1) { printk(KERN_WARNING "aztcd: Drive Status" @@ -1913,21 +1908,33 @@ static int __init aztcd_init(void) } devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); + azt_disk = alloc_disk(); + if (!azt_disk) + goto err_out2; if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" " CD-ROM\n", MAJOR_NR); ret = -EIO; - goto err_out; + goto err_out3; } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); - add_disk(&azt_disk); + azt_disk->major = MAJOR_NR; + azt_disk->first_minor = 0; + azt_disk->minor_shift = 0; + azt_disk->fops = &azt_fops; + sprintf(azt_disk->disk_name, "aztcd"); + add_disk(azt_disk); azt_invalidate_buffers(); aztPresent = 1; aztCloseDoor(); return (0); - err_out: +err_out3: + put_disk(azt_disk); +err_out2: + devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0); +err_out: if ((azt_port == 0x1f0) || (azt_port == 0x170)) { SWITCH_IDE_MASTER; release_region(azt_port, 8); /*IDE-interface */ @@ -1940,7 +1947,8 @@ static int __init aztcd_init(void) static void __exit aztcd_exit(void) { devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0); - del_gendisk(&azt_disk); + del_gendisk(azt_disk); + put_disk(azt_disk); if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { printk("What's that: can't unregister aztcd\n"); return; diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 572af9fca9266975b3ed162c1308a01bf0398970..8863cb1254de7631333fb98f9763088d7892f868 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -3188,14 +3188,7 @@ static struct cdrom_device_info scd_info = { .name = "cdu31a" }; -static struct gendisk scd_gendisk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .disk_name = "cdu31a", - .fops = &scd_bdops, - .flags = GENHD_FL_CD, -}; +static struct gendisk *scd_gendisk; /* The different types of disc loading mechanisms supported */ static char *load_mech[] __initdata = @@ -3299,7 +3292,8 @@ __setup("cdu31a=", cdu31a_setup); int __init cdu31a_init(void) { struct s_sony_drive_config drive_config; - struct gendisk *disk = &scd_gendisk; + struct gendisk *disk; + int deficiency = 0; unsigned int res_size; char msg[255]; char buf[40]; @@ -3360,115 +3354,119 @@ int __init cdu31a_init(void) } } - if (drive_found) { - int deficiency = 0; + if (!drive_found) + goto errout3; - if (!request_region(cdu31a_port, 4, "cdu31a")) - goto errout3; + if (!request_region(cdu31a_port, 4, "cdu31a")) + goto errout3; - if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { - printk("Unable to get major %d for CDU-31a\n", - MAJOR_NR); - goto errout2; - } + if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { + printk("Unable to get major %d for CDU-31a\n", + MAJOR_NR); + goto errout2; + } - if (SONY_HWC_DOUBLE_SPEED(drive_config)) { - is_double_speed = 1; - } + disk = alloc_disk(); + if (!disk) + goto errout1; + disk->major = MAJOR_NR; + disk->first_minor = 0; + disk->minor_shift = 0; + sprintf(disk->disk_name, "cdu31a"); + disk->fops = &scd_bdops; + disk->flags = GENHD_FL_CD; - tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ - cdu31a_irq = 0; + if (SONY_HWC_DOUBLE_SPEED(drive_config)) + is_double_speed = 1; - set_drive_params(sony_speed); + tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ + cdu31a_irq = 0; - cdu31a_irq = tmp_irq; + set_drive_params(sony_speed); - if (cdu31a_irq > 0) { - if (request_irq - (cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, - "cdu31a", NULL)) { - printk - ("Unable to grab IRQ%d for the CDU31A driver\n", - cdu31a_irq); - cdu31a_irq = 0; - } - } + cdu31a_irq = tmp_irq; - sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", - drive_config.vendor_id, - drive_config.product_id, - drive_config.product_rev_level); - sprintf(buf, " Capabilities: %s", - load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); - strcat(msg, buf); - if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) { - strcat(msg, ", audio"); - } else - deficiency |= CDC_PLAY_AUDIO; - if (SONY_HWC_EJECT(drive_config)) { - strcat(msg, ", eject"); - } else - deficiency |= CDC_OPEN_TRAY; - if (SONY_HWC_LED_SUPPORT(drive_config)) { - strcat(msg, ", LED"); - } - if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) { - strcat(msg, ", elec. Vol"); - } - if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) { - strcat(msg, ", sep. Vol"); - } - if (is_double_speed) { - strcat(msg, ", double speed"); - } else - deficiency |= CDC_SELECT_SPEED; - if (cdu31a_irq > 0) { - sprintf(buf, ", irq %d", cdu31a_irq); - strcat(msg, buf); + if (cdu31a_irq > 0) { + if (request_irq + (cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, + "cdu31a", NULL)) { + printk + ("Unable to grab IRQ%d for the CDU31A driver\n", + cdu31a_irq); + cdu31a_irq = 0; } - strcat(msg, "\n"); + } - is_a_cdu31a = - strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; + sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", + drive_config.vendor_id, + drive_config.product_id, + drive_config.product_rev_level); + sprintf(buf, " Capabilities: %s", + load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); + strcat(msg, buf); + if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) + strcat(msg, ", audio"); + else + deficiency |= CDC_PLAY_AUDIO; + if (SONY_HWC_EJECT(drive_config)) + strcat(msg, ", eject"); + else + deficiency |= CDC_OPEN_TRAY; + if (SONY_HWC_LED_SUPPORT(drive_config)) + strcat(msg, ", LED"); + if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) + strcat(msg, ", elec. Vol"); + if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) + strcat(msg, ", sep. Vol"); + if (is_double_speed) + strcat(msg, ", double speed"); + else + deficiency |= CDC_SELECT_SPEED; + if (cdu31a_irq > 0) { + sprintf(buf, ", irq %d", cdu31a_irq); + strcat(msg, buf); + } + strcat(msg, "\n"); - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), - do_cdu31a_request, - &cdu31a_lock); + is_a_cdu31a = + strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; - init_timer(&cdu31a_abort_timer); - cdu31a_abort_timer.function = handle_abort_timeout; + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), + do_cdu31a_request, + &cdu31a_lock); - scd_info.dev = mk_kdev(MAJOR_NR, 0); - scd_info.mask = deficiency; - if (register_cdrom(&scd_info)) - goto errout0; - add_disk(disk); - } + init_timer(&cdu31a_abort_timer); + cdu31a_abort_timer.function = handle_abort_timeout; + scd_info.dev = mk_kdev(MAJOR_NR, 0); + scd_info.mask = deficiency; + scd_gendisk = disk; + if (register_cdrom(&scd_info)) + goto errout0; + add_disk(disk); disk_changed = 1; + return (0); - if (drive_found) { - return (0); - } else { - goto errout3; - } - errout0: +errout0: printk("Unable to register CDU-31a with Uniform cdrom driver\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + put_disk(disk); +errout1: if (unregister_blkdev(MAJOR_NR, "cdu31a")) { printk("Can't unregister block device for cdu31a\n"); } - errout2: +errout2: release_region(cdu31a_port, 4); - errout3: +errout3: return -EIO; } void __exit cdu31a_exit(void) { - del_gendisk(&scd_gendisk); + del_gendisk(scd_gendisk); + put_disk(scd_gendisk); if (unregister_cdrom(&scd_info)) { printk ("Can't unregister cdu31a from Uniform cdrom driver\n"); diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index c1074b4149143d25d120af9c7ff19aaab9dfe254..0da8b3bcdf30f2d0208ddc290eb2d3ff29e448f2 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -1357,14 +1357,7 @@ static struct cdrom_device_info cm206_info = { .name = "cm206", }; -static struct gendisk cm206_gendisk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .disk_name = "cm206", - .fops = &cm206_bdops, - .flags = GENHD_FL_CD, -}; +static struct gendisk *cm206_gendisk; /* This function probes for the adapter card. It returns the base address if it has found the adapter card. One can specify a base @@ -1419,7 +1412,7 @@ int __init cm206_init(void) { uch e = 0; long int size = sizeof(struct cm206_struct); - struct gendisk *disk = &cm206_gendisk; + struct gendisk *disk; printk(KERN_INFO "cm206 cdrom driver " REVISION); cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); @@ -1477,6 +1470,16 @@ int __init cm206_init(void) printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); goto out_blkdev; } + disk = alloc_disk(); + if (!disk) + goto out_disk; + disk->major = MAJOR_NR; + disk->first_minor = 0; + disk->minor_shift = 0; + sprintf(disk->disk_name, "cm206"); + disk->fops = &cm206_bdops; + disk->flags = GENHD_FL_CD; + cm206_gendisk = disk; cm206_info.dev = mk_kdev(MAJOR_NR, 0); if (register_cdrom(&cm206_info) != 0) { printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR); @@ -1498,6 +1501,8 @@ int __init cm206_init(void) return 0; out_cdrom: + put_disk(disk); +out_disk: unregister_blkdev(MAJOR_NR, "cm206"); out_blkdev: free_irq(cm206_irq, NULL); @@ -1536,7 +1541,8 @@ int __cm206_init(void) void __exit cm206_exit(void) { - del_gendisk(&cm206_gendisk); + del_gendisk(cm206_gendisk); + put_disk(cm206_gendisk); if (unregister_cdrom(&cm206_info)) { printk("Can't unregister cdrom cm206\n"); return; diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c index c80cd3ca77351ce8539bbffa8f887202bcbe0534..9e8a14ce9374fc4b56c99b5b2b722a57f2c07467 100644 --- a/drivers/cdrom/gscd.c +++ b/drivers/cdrom/gscd.c @@ -898,20 +898,15 @@ static void update_state(void) } #endif -static struct gendisk gscd_disk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .fops = &gscd_fops, - .disk_name = "gscd" -}; +static struct gendisk *gscd_disk; static void __exit gscd_exit(void) { CLEAR_TIMER; devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0); - del_gendisk(&gscd_disk); + del_gendisk(gscd_disk); + put_disk(gscd_disk); if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { printk("What's that: can't unregister GoldStar-module\n"); return; @@ -977,11 +972,20 @@ static int __init gscd_init(void) i++; } + gscd_disk = alloc_disk(); + if (!gscd_disk) + goto err_out1; + gscd_disk->major = MAJOR_NR; + gscd_disk->first_minor = 0; + gscd_disk->minor_shift = 0; + gscd_disk->fops = &gscd_fops; + sprintf(gscd_disk->disk_name, "gscd"); + if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " "CD-ROM\n", MAJOR_NR); ret = -EIO; - goto err_out1; + goto err_out2; } devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); @@ -991,10 +995,13 @@ static int __init gscd_init(void) disk_state = 0; gscdPresent = 1; - add_disk(&gscd_disk); + add_disk(gscd_disk); printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); return 0; + +err_out2: + put_disk(gscd_disk); err_out1: release_region(gscd_port, GSCD_IO_EXTENT); return ret; diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index 1b2a958968b0344c0631ed5d88f12fc6cf0c2587..39eff9436cbfee5b2869ff9f67d470a57cd444b1 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -221,14 +221,7 @@ static struct cdrom_device_info mcd_info = { .name = "mcd", }; -static struct gendisk mcd_gendisk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .disk_name = "mcd", - .fops = &mcd_bdops, - .flags = GENHD_FL_CD, -}; +static struct gendisk *mcd_gendisk; #ifndef MODULE static int __init mcd_setup(char *str) @@ -1038,18 +1031,23 @@ static void mcd_release(struct cdrom_device_info *cdi) int __init mcd_init(void) { - struct gendisk *disk = &mcd_gendisk; + struct gendisk *disk = alloc_disk(); int count; unsigned char result[3]; char msg[80]; + if (!disk) { + printk(KERN_INFO "mcd: can't allocated disk.\n"); + return -ENOMEM; + } if (mcd_port <= 0 || mcd_irq <= 0) { printk(KERN_INFO "mcd: not probing.\n"); + put_disk(disk); return -EIO; } - if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); + put_disk(disk); return -EIO; } if (!request_region(mcd_port, 4, "mcd")) { @@ -1124,6 +1122,13 @@ int __init mcd_init(void) mcd_invalidate_buffers(); mcdPresent = 1; + disk->major = MAJOR_NR; + disk->first_minor = 0; + disk->minor_shift = 0; + sprintf(disk->disk_name, "mcd"); + disk->fops = &mcd_bdops; + disk->flags = GENHD_FL_CD; + mcd_gendisk = disk; mcd_info.dev = mk_kdev(MAJOR_NR, 0); if (register_cdrom(&mcd_info) != 0) { @@ -1141,6 +1146,7 @@ int __init mcd_init(void) out_region: unregister_blkdev(MAJOR_NR, "mcd"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + put_disk(disk); return -EIO; } @@ -1506,7 +1512,8 @@ static int GetToc(void) void __exit mcd_exit(void) { - del_gendisk(&mcd_gendisk); + del_gendisk(mcd_gendisk); + put_disk(mcd_gendisk); if (unregister_cdrom(&mcd_info)) { printk(KERN_WARNING "Can't unregister cdrom mcd\n"); return; diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index 85eeb621ba0c8e423de0724f50bae986d4414563..7b6aaace0be1db6bda0e627eb63a5c8bc1a572e6 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -206,7 +206,7 @@ struct s_drive_stuff { int status; /* last operation's error / status */ int readerrs; /* # of blocks read w/o error */ struct cdrom_device_info info; - struct gendisk disk; + struct gendisk *disk; }; @@ -1021,11 +1021,12 @@ void __exit mcdx_exit(void) struct s_drive_stuff *stuffp = mcdx_stuffp[i]; if (!stuffp) continue; - del_gendisk(&stuffp->disk); + del_gendisk(stuffp->disk); if (unregister_cdrom(&stuffp->info)) { printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); - return; + continue; } + put_disk(stuffp->disk); release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); @@ -1075,6 +1076,13 @@ int __init mcdx_init_drive(int drive) return 1; } + disk = alloc_disk(); + if (!disk) { + xwarn("init() malloc failed\n"); + kfree(stuffp); + return 1; + } + xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp); @@ -1106,6 +1114,7 @@ int __init mcdx_init_drive(int drive) stuffp->wreg_data + MCDX_IO_SIZE - 1); xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); kfree(stuffp); + put_disk(disk); xtrace(INIT, "init() continue at next drive\n"); return 0; /* next drive */ } @@ -1124,6 +1133,7 @@ int __init mcdx_init_drive(int drive) MCDX, stuffp->wreg_data, stuffp->irq); xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); kfree(stuffp); + put_disk(disk); xtrace(INIT, "init() continue at next drive\n"); return 0; } @@ -1154,6 +1164,7 @@ int __init mcdx_init_drive(int drive) xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n", MCDX, stuffp->wreg_data, stuffp->irq); kfree(stuffp); + put_disk(disk); return 0; /* next drive */ } @@ -1164,6 +1175,7 @@ int __init mcdx_init_drive(int drive) xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR); kfree(stuffp); + put_disk(disk); return 1; } @@ -1180,6 +1192,7 @@ int __init mcdx_init_drive(int drive) stuffp->irq = 0; blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(stuffp); + put_disk(disk); return 0; } @@ -1206,13 +1219,13 @@ int __init mcdx_init_drive(int drive) stuffp->info.handle = stuffp; sprintf(stuffp->info.name, "mcdx%d", drive); stuffp->info.dev = mk_kdev(MAJOR_NR, drive); - disk = &stuffp->disk; disk->major = MAJOR_NR; disk->first_minor = drive; disk->minor_shift = 0; strcpy(disk->disk_name, stuffp->info.name); disk->fops = &mcdx_bdops; disk->flags = GENHD_FL_CD; + stuffp->disk = disk; sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d." " (Firmware version %c %x)\n", @@ -1225,6 +1238,7 @@ int __init mcdx_init_drive(int drive) MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); kfree(stuffp); + put_disk(disk); if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) xwarn("cleanup() unregister_blkdev() failed\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c index 8b1da1b5b5f9298e14c3b9e8ad7c536d494e53c6..baf39fd6f7080f89c9ffdbea94c03d02c974d90b 100644 --- a/drivers/cdrom/optcd.c +++ b/drivers/cdrom/optcd.c @@ -1997,13 +1997,7 @@ __setup("optcd=", optcd_setup); #endif /* MODULE */ -static struct gendisk optcd_disk = { - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .fops = &opt_fops, - .disk_name = "optcd" -}; +static struct gendisk *optcd_disk; /* Test for presence of drive and initialize it. Called at boot time or during module initialisation. */ @@ -2016,20 +2010,33 @@ static int __init optcd_init(void) "optcd: no Optics Storage CDROM Initialization\n"); return -EIO; } + optcd_disk = alloc_disk(); + if (!optcd_disk) { + printk(KERN_ERR "optcd: can't allocate disk\n"); + return -ENOMEM; + } + optcd_disk->major = MAJOR_NR; + optcd_disk->first_minor = 0; + optcd_disk->minor_shift = 0; + optcd_disk->fops = &opt_fops; + sprintf(optcd_disk->disk_name, "optcd"); if (!request_region(optcd_port, 4, "optcd")) { printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n", optcd_port); + put_disk(optcd_disk); return -EIO; } if (!reset_drive()) { printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port); release_region(optcd_port, 4); + put_disk(optcd_disk); return -EIO; } if (!version_ok()) { printk(KERN_ERR "optcd: unknown drive detected; aborting\n"); release_region(optcd_port, 4); + put_disk(optcd_disk); return -EIO; } status = exec_cmd(COMINITDOUBLE); @@ -2037,11 +2044,13 @@ static int __init optcd_init(void) printk(KERN_ERR "optcd: cannot init double speed mode\n"); release_region(optcd_port, 4); DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status)); + put_disk(optcd_disk); return -EIO; } if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR); release_region(optcd_port, 4); + put_disk(optcd_disk); return -EIO; } devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, @@ -2049,7 +2058,7 @@ static int __init optcd_init(void) blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request, &optcd_lock); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); - add_disk(&optcd_disk); + add_disk(optcd_disk); printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port); return 0; @@ -2059,7 +2068,8 @@ static int __init optcd_init(void) static void __exit optcd_exit(void) { devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0); - del_gendisk(&optcd_disk); + del_gendisk(optcd_disk); + put_disk(optcd_disk); if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { printk(KERN_ERR "optcd: what's that: can't unregister\n"); return; diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 37c1e773fb04e9de7fe3163f91237d14609d1815..409aea0c4f0fca3d30215568b6aa4c13f9102f0f 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -722,7 +722,7 @@ static struct sbpcd_drive { u_char mode_xb_8; u_char delay; struct cdrom_device_info *sbpcd_infop; - struct gendisk disk; + struct gendisk *disk; } D_S[NR_SBPCD]; static struct sbpcd_drive *current_drive = D_S; @@ -5609,6 +5609,7 @@ static int __init config_spea(void) static devfs_handle_t devfs_handle; +/* FIXME: cleanups after failed allocations are too ugly for words */ #ifdef MODULE int __init __sbpcd_init(void) #else @@ -5830,7 +5831,7 @@ int __init sbpcd_init(void) sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); sbpcd_infop->handle = p; p->sbpcd_infop = sbpcd_infop; - disk = &p->disk; + disk = alloc_disk(); disk->major = MAJOR_NR; disk->first_minor = j; disk->minor_shift = 0; @@ -5839,6 +5840,7 @@ int __init sbpcd_init(void) disk->flags = GENHD_FL_CD; sprintf(nbuff, "c0t%d", p->drv_id); disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL); + p->disk = disk; if (register_cdrom(sbpcd_infop)) { printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); @@ -5869,7 +5871,8 @@ void sbpcd_exit(void) for (j=0;j<NR_SBPCD;j++) { if (D_S[j].drv_id==-1) continue; - del_gendisk(&D_S[j].disk); + del_gendisk(D_S[j].disk); + put_disk(D_S[j].disk); vfree(D_S[j].sbp_buf); if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf); devfs_unregister(D_S[j].disk.de); diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c index edceb3a3dc856edd3ce05c0e2d101e26fc006ec5..c0464754862503eac818a1bae5b51a12cf4bdd0a 100644 --- a/drivers/cdrom/sjcd.c +++ b/drivers/cdrom/sjcd.c @@ -159,8 +159,6 @@ static struct timer_list sjcd_delay_timer; #define CLEAR_TIMER del_timer( &sjcd_delay_timer ) -static int sjcd_cleanup(void); - /* * Set up device, i.e., use command line data to set * base address. @@ -1664,14 +1662,7 @@ static struct { unsigned char major, minor; } sjcd_version; -static struct gendisk sjcd_disk = -{ - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .fops = &sjcd_fops, - .disk_name = "sjcd" -}; +static struct gendisk *sjcd_disk; /* * Test for presence of drive and initialize it. Called at boot time. @@ -1698,12 +1689,22 @@ static int __init sjcd_init(void) blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); + sjcd_disk = alloc_disk(); + if (!sjcd_disk) { + printk(KERN_ERR "SJCD: can't allocate disk"); + goto out1; + } + sjcd_disk->major = MAJOR_NR, + sjcd_disk->first_minor = 0, + sjcd_disk->minor_shift = 0, + sjcd_disk->fops = &sjcd_fops, + sprintf(sjcd_disk->disk_name, "sjcd"); + if (check_region(sjcd_base, 4)) { printk ("SJCD: Init failed, I/O port (%X) is already in use\n", sjcd_base); - sjcd_cleanup(); - return (-EIO); + goto out2; } /* @@ -1725,8 +1726,7 @@ static int __init sjcd_init(void) } if (i == 0 || sjcd_command_failed) { printk(" reset failed, no drive found.\n"); - sjcd_cleanup(); - return (-EIO); + goto out3; } else printk("\n"); @@ -1748,8 +1748,7 @@ static int __init sjcd_init(void) } if (i == 0 || sjcd_command_failed) { printk(" get version failed, no drive found.\n"); - sjcd_cleanup(); - return (-EIO); + goto out3; } if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { @@ -1757,8 +1756,7 @@ static int __init sjcd_init(void) (int) sjcd_version.minor); } else { printk(" read version failed, no drive found.\n"); - sjcd_cleanup(); - return (-EIO); + goto out3; } /* @@ -1781,8 +1779,7 @@ static int __init sjcd_init(void) } if (i == 0 || sjcd_command_failed) { printk(" get status failed, no drive found.\n"); - sjcd_cleanup(); - return (-EIO); + goto out3; } else printk("\n"); } @@ -1790,33 +1787,32 @@ static int __init sjcd_init(void) printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); - add_disk(&sjcd_disk); + add_disk(sjcd_disk); sjcd_present++; return (0); -} - -static int sjcd_cleanup(void) -{ +out3: + release_region(sjcd_base, 4); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); +out2: + put_disk(sjcd_disk); +out1: if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) printk("SJCD: cannot unregister device.\n"); - else { - release_region(sjcd_base, 4); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - } - - return (0); + return (-EIO); } - static void __exit sjcd_exit(void) { devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0); - del_gendisk(&sjcd_disk); - if (sjcd_cleanup()) - printk("SJCD: module: cannot be removed.\n"); - else - printk(KERN_INFO "SJCD: module: removed.\n"); + del_gendisk(sjcd_disk); + put_disk(sjcd_disk); + release_region(sjcd_base, 4); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) + printk("SJCD: cannot unregister device.\n"); + printk(KERN_INFO "SJCD: module: removed.\n"); + return (0); } module_init(sjcd_init); diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index cd28b4f1b3d26ab4815bed6581a126ca56d8abed..d73013c02bada67391d3effb4bf1d68d7bd9fd59 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -1454,14 +1454,7 @@ static struct block_device_operations cdu_fops = .check_media_change = cdu535_check_media_change, }; -static struct gendisk cdu_disk = -{ - .major = MAJOR_NR, - .first_minor = 0, - .minor_shift = 0, - .fops = &cdu_fops, - .disk_name = "cdu", -}; +static struct gendisk *cdu_disk; /* * Initialize the driver. @@ -1477,6 +1470,7 @@ static int __init sony535_init(void) int tmp_irq; int i; devfs_handle_t sony_devfs_handle; + int err; /* Setting the base I/O address to 0 will disable it. */ if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0)) @@ -1518,145 +1512,142 @@ static int __init sony535_init(void) sony_sleep(); } - if (got_result && (check_drive_status() != TIME_OUT)) { - /* CD-ROM drive responded -- get the drive configuration */ - cmd_buff[0] = SONY535_INQUIRY; - if (do_sony_cmd(cmd_buff, 1, status, - (Byte *)&drive_config, 28, 1) == 0) { - /* was able to get the configuration, - * set drive mode as rest of init - */ + if (!got_result || check_drive_status() == TIME_OUT) + goto Enodev; + + /* CD-ROM drive responded -- get the drive configuration */ + cmd_buff[0] = SONY535_INQUIRY; + if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0) + goto Enodev; + + /* was able to get the configuration, + * set drive mode as rest of init + */ #if DEBUG > 0 - /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */ - if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 ) - printk(CDU535_MESSAGE_NAME - "Inquiry command returned status = 0x%x\n", status[0]); + /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */ + if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 ) + printk(CDU535_MESSAGE_NAME + "Inquiry command returned status = 0x%x\n", status[0]); #endif - /* now ready to use interrupts, if available */ - sony535_irq_used = tmp_irq; + /* now ready to use interrupts, if available */ + sony535_irq_used = tmp_irq; - /* A negative sony535_irq_used will attempt an autoirq. */ - if (sony535_irq_used < 0) { - unsigned long irq_mask, delay; + /* A negative sony535_irq_used will attempt an autoirq. */ + if (sony535_irq_used < 0) { + unsigned long irq_mask, delay; - irq_mask = probe_irq_on(); - enable_interrupts(); - outb(0, read_status_reg); /* does a reset? */ - delay = jiffies + HZ/10; - while (time_before(jiffies, delay)) ; + irq_mask = probe_irq_on(); + enable_interrupts(); + outb(0, read_status_reg); /* does a reset? */ + delay = jiffies + HZ/10; + while (time_before(jiffies, delay)) ; - sony535_irq_used = probe_irq_off(irq_mask); - disable_interrupts(); - } - if (sony535_irq_used > 0) { - if (request_irq(sony535_irq_used, cdu535_interrupt, - SA_INTERRUPT, CDU535_HANDLE, NULL)) { - printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME - " driver; polling instead.\n", sony535_irq_used); - sony535_irq_used = 0; - } - } - cmd_buff[0] = SONY535_SET_DRIVE_MODE; - cmd_buff[1] = 0x0; /* default audio */ - if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) { - /* set the drive mode successful, we are set! */ - sony_buffer_size = SONY535_BUFFER_SIZE; - sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE; - - printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s", - drive_config.vendor_id, - drive_config.product_id, - drive_config.product_rev_level); - printk(" base address %03X, ", sony535_cd_base_io); - if (tmp_irq > 0) - printk("IRQ%d, ", tmp_irq); - printk("using %d byte buffer\n", sony_buffer_size); - - sony_devfs_handle = devfs_register (NULL, CDU535_HANDLE, - DEVFS_FL_DEFAULT, - MAJOR_NR, 0, - S_IFBLK | S_IRUGO | S_IWUGO, - &cdu_fops, NULL); - if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { - printk("Unable to get major %d for %s\n", - MAJOR_NR, CDU535_MESSAGE_NAME); - return -EIO; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), - do_cdu535_request, - &sonycd535_lock); - blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE); - sony_toc = (struct s535_sony_toc *) - kmalloc(sizeof *sony_toc, GFP_KERNEL); - if (sony_toc == NULL) { - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - unregister_blkdev(MAJOR_NR, CDU535_HANDLE); - devfs_unregister(sony_devfs_handle); - return -ENOMEM; - } - last_sony_subcode = (struct s535_sony_subcode *) - kmalloc(sizeof *last_sony_subcode, GFP_KERNEL); - if (last_sony_subcode == NULL) { - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - kfree(sony_toc); - unregister_blkdev(MAJOR_NR, CDU535_HANDLE); - devfs_unregister(sony_devfs_handle); - return -ENOMEM; - } - sony_buffer = (Byte **) - kmalloc(4 * sony_buffer_sectors, GFP_KERNEL); - if (sony_buffer == NULL) { - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - kfree(sony_toc); - kfree(last_sony_subcode); - unregister_blkdev(MAJOR_NR, CDU535_HANDLE); - devfs_unregister(sony_devfs_handle); - return -ENOMEM; - } - for (i = 0; i < sony_buffer_sectors; i++) { - sony_buffer[i] = - (Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL); - if (sony_buffer[i] == NULL) { - while (--i>=0) - kfree(sony_buffer[i]); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - kfree(sony_buffer); - kfree(sony_toc); - kfree(last_sony_subcode); - unregister_blkdev(MAJOR_NR, CDU535_HANDLE); - devfs_unregister(sony_devfs_handle); - return -ENOMEM; - } - } - initialized = 1; - } + sony535_irq_used = probe_irq_off(irq_mask); + disable_interrupts(); + } + if (sony535_irq_used > 0) { + if (request_irq(sony535_irq_used, cdu535_interrupt, + SA_INTERRUPT, CDU535_HANDLE, NULL)) { + printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME + " driver; polling instead.\n", sony535_irq_used); + sony535_irq_used = 0; } } - - if (!initialized) { - printk("Did not find a " CDU535_MESSAGE_NAME " drive\n"); - return -EIO; + cmd_buff[0] = SONY535_SET_DRIVE_MODE; + cmd_buff[1] = 0x0; /* default audio */ + if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0) + goto Enodev_irq; + + /* set the drive mode successful, we are set! */ + sony_buffer_size = SONY535_BUFFER_SIZE; + sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE; + + printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s", + drive_config.vendor_id, + drive_config.product_id, + drive_config.product_rev_level); + printk(" base address %03X, ", sony535_cd_base_io); + if (tmp_irq > 0) + printk("IRQ%d, ", tmp_irq); + printk("using %d byte buffer\n", sony_buffer_size); + + sony_devfs_handle = devfs_register (NULL, CDU535_HANDLE, + DEVFS_FL_DEFAULT, + MAJOR_NR, 0, + S_IFBLK | S_IRUGO | S_IWUGO, + &cdu_fops, NULL); + if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { + printk("Unable to get major %d for %s\n", + MAJOR_NR, CDU535_MESSAGE_NAME); + err = -EIO; + goto out1; } - if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) - { - printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n", - sony535_cd_base_io); - for (i = 0; i < sony_buffer_sectors; i++) - if (sony_buffer[i]) + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cdu535_request, + &sonycd535_lock); + blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE); + sony_toc = kamlloc(sizeof(struct s535_sony_toc), GFP_KERNEL); + err = -ENOMEM; + if (!sony_toc) + goto out2; + last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL); + if (!last_sony_subcode) + goto out3; + sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL); + if (!sony_buffer) + goto out4; + for (i = 0; i < sony_buffer_sectors; i++) { + sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL); + if (!sony_buffer[i]) { + while (--i>=0) kfree(sony_buffer[i]); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - kfree(sony_buffer); - kfree(sony_toc); - kfree(last_sony_subcode); - unregister_blkdev(MAJOR_NR, CDU535_HANDLE); - devfs_unregister(sony_devfs_handle); - if (sony535_irq_used) - free_irq(sony535_irq_used, NULL); - - return -EIO; + goto out5; } - add_disk(&cdu_disk); + } + initialized = 1; + + cdu_disk = alloc_disk(); + if (!cdu_disk) + goto out6; + cdu_disk->major = MAJOR_NR; + cdu_disk->first_minor = 0; + cdu_disk->minor_shift = 0; + cdu_disk->fops = &cdu_fops; + sprintf(cdu_disk->disk_name, "cdu"); + + if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) { + printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n", + sony535_cd_base_io); + goto out7; + } + add_disk(cdu_disk); return 0; + +out7: + put_disk(cdu_disk); +out6: + for (i = 0; i < sony_buffer_sectors; i++) + if (sony_buffer[i]) + kfree(sony_buffer[i]); +out5: + kfree(sony_buffer); +out4: + kfree(last_sony_subcode); +out3: + kfree(sony_toc); +out2: + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); +out1: + devfs_unregister(sony_devfs_handle); + if (sony535_irq_used) + free_irq(sony535_irq_used, NULL); + return err; +Enodev_irq: + if (sony535_irq_used) + free_irq(sony535_irq_used, NULL); +Enodev: + printk("Did not find a " CDU535_MESSAGE_NAME " drive\n"); + return -EIO; } #ifndef MODULE @@ -1707,7 +1698,8 @@ static sony535_exit(void) kfree(sony_toc); devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0, DEVFS_SPECIAL_BLK, 0); - del_gendisk(&cdu_disk); + del_gendisk(cdu_disk); + put_disk(cdu_disk); if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); else diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 48614c3cebd7586a715841dae4f311eccb3f948a..b8d75434b316c00a273e8ded2e28f57d7c91ab80 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -138,6 +138,8 @@ static struct hd_i_struct hd_info[MAX_HD]; static int NR_HD; #endif +static struct gendisk *hd_gendisk[MAX_HD]; + static struct timer_list device_timer; #define TIMEOUT_VALUE (6*HZ) @@ -590,14 +592,15 @@ static void hd_request(void) dev = DEVICE_NR(CURRENT->rq_dev); block = CURRENT->sector; nsect = CURRENT->nr_sectors; - if (dev >= NR_HD || block >= get_capacity(hd_gendisk+dev) || - ((block+nsect) > get_capacity(hd_gendisk+unit))) { - if (dev >= NR_HD) - printk("hd: bad minor number: device=%s\n", - kdevname(CURRENT->rq_dev)); - else - printk("hd%c: bad access: block=%d, count=%d\n", - dev+'a', block, nsect); + if (dev >= NR_HD) { + printk("hd: bad disk number: %d\n", dev); + end_request(CURRENT, 0); + goto repeat; + } + if (block >= get_capacity(hd_gendisk[dev]) || + ((block+nsect) > get_capacity(hd_gendisk[dev]))) { + printk("%s: bad access: block=%d, count=%d\n", + hd_gendisk[dev]->disk_name, block, nsect); end_request(CURRENT, 0); goto repeat; } @@ -691,22 +694,6 @@ static int hd_open(struct inode * inode, struct file * filp) extern struct block_device_operations hd_fops; -static struct gendisk hd_gendisk[2] = { -{ - .major = MAJOR_NR, - .first_minor = 0, - .disk_name = "hda", - .minor_shift = 6, - .fops = &hd_fops, -},{ - .major = MAJOR_NR, - .first_minor = 64, - .disk_name = "hdb", - .minor_shift = 6, - .fops = &hd_fops, -} -}; - static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) { void (*handler)(void) = do_hd; @@ -733,10 +720,18 @@ static struct block_device_operations hd_fops = { * We enable interrupts in some of the routines after making sure it's * safe. */ -static void __init hd_geninit(void) + +static int __init hd_init(void) { int drive; - + if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { + printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); + return -1; + } + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); + blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); + init_timer(&device_timer); + device_timer.function = hd_times_out; blk_queue_hardsect_size(QUEUE, 512); #ifdef __i386__ @@ -805,57 +800,68 @@ static void __init hd_geninit(void) " on kernel command line\n"); } #endif + if (!NR_HD) + goto out; + for (drive=0 ; drive < NR_HD ; drive++) { + struct gendisk *disk = alloc_disk(); + if (!disk) + goto Enomem; + disk->major = MAJOR_NR; + disk->first_minor = drive << 6; + disk->minor_shift = 6; + disk->fops = &hd_fops; + sprintf(disk->disk_name, "hd%c", 'a'+drive); + hd_gendisk[drive] = disk; + } for (drive=0 ; drive < NR_HD ; drive++) { sector_t size = hd_info[drive].head * hd_info[drive].sect * hd_info[drive].cyl; - set_capacity(hd_gendisk + drive, size); - printk ("%s: %ldMB, CHS=%d/%d/%d\n", hd_gendisk[drive].disk_name, + set_capacity(hd_gendisk[drive], size); + printk ("%s: %ldMB, CHS=%d/%d/%d\n", + hd_gendisk[drive]->disk_name, size / 2048, hd_info[drive].cyl, hd_info[drive].head, hd_info[drive].sect); } - if (!NR_HD) - return; if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { printk("hd: unable to get IRQ%d for the hard disk driver\n", HD_IRQ); - NR_HD = 0; - return; + goto out1; } if (!request_region(HD_DATA, 8, "hd")) { printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - NR_HD = 0; - free_irq(HD_IRQ, NULL); - return; + goto out2; } if (!request_region(HD_CMD, 1, "hd(cmd)")) { printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); - NR_HD = 0; - free_irq(HD_IRQ, NULL); - release_region(HD_DATA, 8); - return; + goto out3; } for(drive=0; drive < NR_HD; drive++) { struct hd_i_struct *p = hd_info + drive; - set_capacity(hd_gendisk + drive, p->head * p->sect * p->cyl); - add_disk(hd_gendisk + drive); + set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl); + add_disk(hd_gendisk[drive]); } -} - -static int __init hd_init(void) -{ - if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); - return -1; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); - blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); - init_timer(&device_timer); - device_timer.function = hd_times_out; - hd_geninit(); return 0; + +out3: + release_region(HD_DATA, 8); +out2: + free_irq(HD_IRQ, NULL); +out1: + for (drive = 0; drive < NR_HD; drive++) + put_disk(hd_gendisk[drive]); + NR_HD = 0; +out: + del_timer(&device_timer); + unregister_blkdev(MAJOR_NR,"hd"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + return -1; +Enomem: + while (drive--) + put_disk(hd_gendisk[drive]); + goto out; } static int parse_hd_setup (char *line) { diff --git a/drivers/md/md.c b/drivers/md/md.c index 3038454374ded3af12a59765f4c6226c5e33950e..b5bf141935d0cf4b48c173ec03e5821febc7f119 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1389,10 +1389,9 @@ static int do_md_run(mddev_t * mddev) #endif } - disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + disk = alloc_disk(); if (!disk) return -ENOMEM; - memset(disk, 0, sizeof(struct gendisk)); disk->major = MD_MAJOR; disk->first_minor = mdidx(mddev); disk->minor_shift = 0; @@ -1408,7 +1407,7 @@ static int do_md_run(mddev_t * mddev) if (err) { printk(KERN_ERR "md: pers->run() failed ...\n"); mddev->pers = NULL; - kfree(disk); + put_disk(disk); return -EINVAL; } @@ -1538,7 +1537,7 @@ static int do_md_stop(mddev_t * mddev, int ro) if (disk) { del_gendisk(disk); - kfree(disk); + put_disk(disk); } } else diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index c1536e9416ab798a130c7deb8fa7e20a6e027b65..341ad2252885b40df5efa2e466789d805d5799ee 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -1223,18 +1223,17 @@ static void ftl_notify_add(struct mtd_info *mtd) } partition = kmalloc(sizeof(partition_t), GFP_KERNEL); - disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + disk = alloc_disk(); if (!partition||!disk) { printk(KERN_WARNING "No memory to scan for FTL on %s\n", mtd->name); kfree(partition); - kfree(disk); + put_disk(disk); return; } memset(partition, 0, sizeof(partition_t)); - memset(disk, 0, sizeof(struct gendisk)); sprintf(disk->disk_name, "ftl%c", 'a' + device); disk->major = FTL_MAJOR; disk->first_minor = device << 4; @@ -1255,7 +1254,7 @@ static void ftl_notify_add(struct mtd_info *mtd) #endif } else { kfree(partition); - kfree(disk); + put_disk(disk); } } @@ -1281,7 +1280,7 @@ static void ftl_notify_remove(struct mtd_info *mtd) myparts[i]->state = 0; del_gendisk(myparts[i]->disk); - kfree(myparts[i]->disk); + put_disk(myparts[i]->disk); kfree(myparts[i]); myparts[i] = NULL; } diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 9ceb545791b2bcf19b0eab7688c818c45914f9c4..1ad148bd3364f1f49e22e0f4282242764b51f57a 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -42,7 +42,7 @@ static struct mtdblk_dev { unsigned long cache_offset; unsigned int cache_size; enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; - struct gendisk disk; + struct gendisk *disk; } *mtdblks[MAX_MTD_DEVICES]; static spinlock_t mtdblks_lock; @@ -263,6 +263,7 @@ static int mtdblock_open(struct inode *inode, struct file *file) struct mtdblk_dev *mtdblk; struct mtd_info *mtd; int dev = minor(inode->i_rdev); + struct gendisk *disk; DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); @@ -294,10 +295,9 @@ static int mtdblock_open(struct inode *inode, struct file *file) spin_unlock(&mtdblks_lock); mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); - if (!mtdblk) { - put_mtd_device(mtd); - return -ENOMEM; - } + disk = alloc_disk(); + if (!mtdblk || !disk) + goto Enomem; memset(mtdblk, 0, sizeof(*mtdblk)); mtdblk->count = 1; mtdblk->mtd = mtd; @@ -308,17 +308,15 @@ static int mtdblock_open(struct inode *inode, struct file *file) mtdblk->mtd->erasesize) { mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); - if (!mtdblk->cache_data) { - put_mtd_device(mtdblk->mtd); - kfree(mtdblk); - return -ENOMEM; - } + if (!mtdblk->cache_data) + goto Enomem; } - mtdblk->disk.major = MAJOR_NR; - mtdblk->disk.first_minor = dev; - mtdblk->disk.minor_shift = 0; - mtdblk->disk.fops = &mtd_fops; - sprintf(mtdblk->disk.disk_name, "mtd%d", dev); + disk->major = MAJOR_NR; + disk->first_minor = dev; + disk->minor_shift = 0; + disk->fops = &mtd_fops; + sprintf(disk->disk_name, "mtd%d", dev); + mtdblk->disk = disk; /* OK, we've created a new one. Add it to the list. */ @@ -331,19 +329,25 @@ static int mtdblock_open(struct inode *inode, struct file *file) put_mtd_device(mtdblk->mtd); vfree(mtdblk->cache_data); kfree(mtdblk); + put_disk(disk); return 0; } mtdblks[dev] = mtdblk; - set_capacity(&mtdblk->disk, mtdblk->mtd->size/512); - add_disk(&mtdblk->disk); + set_capacity(disk, mtdblk->mtd->size/512); + add_disk(disk); set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); - + spin_unlock(&mtdblks_lock); - + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; +Enomem: + put_mtd_device(mtd); + put_disk(disk); + kfree(mtdblk); + return -ENOMEM; } static release_t mtdblock_release(struct inode *inode, struct file *file) @@ -367,7 +371,8 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) /* It was the last usage. Free the device */ mtdblks[dev] = NULL; spin_unlock(&mtdblks_lock); - del_gendisk(&mtdblk->disk); + del_gendisk(mtdblk->disk); + put_disk(mtdblk->disk); if (mtdblk->mtd->sync) mtdblk->mtd->sync(mtdblk->mtd); put_mtd_device(mtdblk->mtd); diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index a3de7d77ebd70d74f95355007695598c53ddf687..81b4daf4889cb443b179195d1073b4238871e1ba 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -29,13 +29,13 @@ static int debug = MTDBLOCK_DEBUG; MODULE_PARM(debug, "i"); #endif -static struct gendisk mtd_disks[MAX_MTD_DEVICES]; +static struct gendisk *mtd_disks[MAX_MTD_DEVICES]; static int mtdblock_open(struct inode *inode, struct file *file) { struct mtd_info *mtd = NULL; int dev = minor(inode->i_rdev); - struct gendisk *disk = mtd_disks + dev; + struct gendisk *disk = mtd_disks[dev]; DEBUG(1,"mtdblock_open\n"); @@ -73,7 +73,7 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) release_return(-ENODEV); } - del_gendisk(mtd_disks + dev); + del_gendisk(mtd_disks[dev]); if (mtd->sync) mtd->sync(mtd); @@ -218,30 +218,42 @@ static struct block_device_operations mtd_fops = int __init init_mtdblock(void) { + int err = -ENOMEM; int i; - if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); - return -EAGAIN; - } - - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); - for (i = 0; i < MAX_MTD_DEVICES; i++) { - struct gendisk *disk = mtd_disks + i; + struct gendisk *disk = alloc_disk(); + if (!disk) + goto out; disk->major = MAJOR_NR; disk->first_minor = i; sprintf(disk->disk_name, "mtdblock%d", i); disk->fops = &mtd_fops; + mtd_disks[i] = disk; } + + if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_BLOCK_MAJOR); + err = -EAGAIN; + goto out; + } + + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); return 0; +out: + while (i--) + put_disk(mtd_disks[i]); + return err; } static void __exit cleanup_mtdblock(void) { + int i; unregister_blkdev(MAJOR_NR,DEVICE_NAME); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + for (i = 0; i < MAX_MTD_DEVICES; i++) + put_disk(mtd_disks[i]); } module_init(init_mtdblock); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index f60f79f5f0ecd4978d924765f62bf70a19e9c04e..d886b917c852e7527bcf74511c70566675c8fe4b 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -74,10 +74,10 @@ static void NFTL_setup(struct mtd_info *mtd) } nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); - gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + gd = alloc_disk(); if (!nftl || !gd) { kfree(nftl); - kfree(gd); + put_disk(gd); printk(KERN_WARNING "Out of memory for NFTL data structures\n"); return; } @@ -92,7 +92,7 @@ static void NFTL_setup(struct mtd_info *mtd) if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "Could not mount NFTL device\n"); kfree(nftl); - kfree(gd); + put_disk(gd); return; } @@ -129,7 +129,6 @@ static void NFTL_setup(struct mtd_info *mtd) /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ } NFTLs[firstfree] = nftl; - memset(gd, 0, sizeof(struct gendisk)); sprintf(gd->disk_name, "nftl%c", 'a' + firstfree); gd->major = MAJOR_NR; gd->first_minor = firstfree << NFTL_PARTN_BITS; @@ -152,7 +151,7 @@ static void NFTL_unsetup(int i) if (nftl->EUNtable) kfree(nftl->EUNtable); del_gendisk(nftl->disk); - kfree(nftl->disk); + put_disk(nftl->disk); kfree(nftl); }