]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] split "gendisk" to be per-disk, part 2
authorAlexander Viro <viro@math.psu.edu>
Thu, 1 Aug 2002 06:33:24 +0000 (23:33 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Thu, 1 Aug 2002 06:33:24 +0000 (23:33 -0700)
we are starting to split gendisks - now we can do that.  Done for
ide, sd, pd, hd and mfm

It's in transit - what we are aiming at is getting ->nr_real to 1 for
all gendisks.  Once that will be done we will be able to simplify a lot
stuff and remove ad-hackery.  First thing that will happen after that
is death of ->nr_real, obviouslye.  Then we
(a) will merge ->major and ->first_minor into ->dev
(b) strip one level of indirection from  ->driverfs_dev_arr, ->de_arr
and ->flags - they turn into single-element arrays and we will simply pull
the (only) element into struct gendisk.  Kills a lot of ad-hackery in splitup
code (fewer things to allocate).
(c) replace ->major_name with ->disk_name; kills most of the crap in
disk_name(9) - it only has to care about adding partition number to the name.

drivers/acorn/block/mfmhd.c
drivers/block/genhd.c
drivers/block/paride/pd.c
drivers/ide/hd.c
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
drivers/ide/main.c
drivers/ide/probe.c
drivers/scsi/sd.c
include/linux/ide.h

index b2a1c64a1467b3ea429d360a084bce385dae2259..d29f53874d08e7c12eb3e598a09c5e4babd9daee 100644 (file)
@@ -1253,11 +1253,20 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
        }
 }
 
-static struct gendisk mfm_gendisk = {
+static struct gendisk mfm_gendisk[2] = {
+{
        major:          MAJOR_NR,
+       first_minor:    0,
        major_name:     "mfm",
        minor_shift:    6,
        part:           mfm,
+},
+{
+       major:          MAJOR_NR,
+       first_minor:    64,
+       major_name:     "mfm",
+       minor_shift:    6,
+       part:           mfm + 64,
 };
 
 static struct block_device_operations mfm_fops =
@@ -1275,8 +1284,6 @@ static void mfm_geninit (void)
 
        printk("mfm: detected %d hard drive%s\n", mfm_drives,
                                mfm_drives == 1 ? "" : "s");
-       mfm_gendisk.nr_real = mfm_drives;
-
        if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
                printk("mfm: unable to get IRQ%d\n", mfm_irq);
 
@@ -1284,8 +1291,10 @@ static void mfm_geninit (void)
                outw(0x80, mfm_irqenable);      /* Required to enable IRQs from MFM podule */
 
        for (i = 0; i < mfm_drives; i++) {
+               mfm_gendisk[i].nr_real = 1;
+               add_gendisk(mfm_gendisk + i);
                mfm_geometry (i);
-               register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6,
+               register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
                                &mfm_fops,
                                mfm_info[i].cylinders * mfm_info[i].heads *
                                mfm_info[i].sectors / 2);
@@ -1380,8 +1389,6 @@ int mfm_init (void)
 
        blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
 
-       add_gendisk(&mfm_gendisk);
-
        Busy = 0;
        lastspecifieddrive = -1;
 
@@ -1419,11 +1426,13 @@ int init_module(void)
 
 void cleanup_module(void)
 {
+       int i;
        if (ecs && mfm_irqenable)
                outw (0, mfm_irqenable);        /* Required to enable IRQs from MFM podule */
        free_irq(mfm_irq, NULL);
        unregister_blkdev(MAJOR_NR, "mfm");
-       del_gendisk(&mfm_gendisk);
+       for (i = 0; i < mfm_drives; i++)
+               del_gendisk(mfm_gendisk + i);
        if (ecs)
                ecard_release(ecs);
        if (mfm_addr)
index 0917d42da972cbfd1405becac2ec78ea54f89ab0..bf9ceb8fe403674d6540f84b6c9a1ea2a63771d2 100644 (file)
@@ -55,8 +55,8 @@ add_gendisk(struct gendisk *gp)
        {
                if (sgp == gp)
                {
-//                     printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
-//                             sgp->major)
+                       printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
+                               sgp->major)
                        goto out;
                }
        }
index 2daf420f0ebeab9d1bc4a7eb931e038ec8091ba1..746da3ccd3a9dc8493380d6141dbdc66df553216 100644 (file)
@@ -291,6 +291,7 @@ struct pd_unit {
        int alt_geom;
        int present;
        char name[PD_NAMELEN];          /* pda, pdb, etc ... */
+       struct gendisk gd;
 };
 
 struct pd_unit pd[PD_UNITS];
@@ -330,8 +331,8 @@ static struct gendisk pd_gendisk = {
        major:          PD_MAJOR,
        major_name:     PD_NAME,
        minor_shift:    PD_BITS,
-       part:           pd_hd,
        fops:           &pd_fops,
+       nr_real:        1,
 };
 
 static struct block_device_operations pd_fops = {
@@ -680,8 +681,8 @@ static int pd_probe_drive( int unit )
 }
 
 static int pd_detect( void )
-
-{       int    k, unit;
+{
+       int     k, unit;
 
        k = 0;
        if (pd_drive_count == 0) {  /* nothing spec'd - so autoprobe for 1 */
@@ -703,18 +704,19 @@ static int pd_detect( void )
                         k = unit+1;
                 } else pi_release(PI);
             }
-       for (unit=0;unit<PD_UNITS;unit++)
-               register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS),
-                               PD_PARTNS,&pd_fops,
-                               PD.present?PD.capacity:0);
-
-/* We lie about the number of drives found, as the generic partition
-   scanner assumes that the drives are numbered sequentially from 0.
-   This can result in some bogus error messages if non-sequential
-   drive numbers are used.
-*/
+       for (unit=0;unit<PD_UNITS;unit++) {
+               if (PD.present) {
+                       PD.gd = pd_gendisk;
+                       PD.gd.first_minor = unit << PD_BITS;
+                       PD.gd.part = pd_hd + (unit << PD_BITS);
+                       add_gendisk(&PD.gd);
+                       register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
+                                       PD_PARTNS,&pd_fops,
+                                       PD.capacity);
+               }
+       }
        if (k)
-               return k
+               return 1
         printk("%s: no valid drive found\n",name);
         return 0;
 }
@@ -935,8 +937,6 @@ static void do_pd_write_done( void )
 static int __init pd_init(void)
 {
        request_queue_t * q;
-       int unit;
-
        if (disable) return -1;
         if (register_blkdev(MAJOR_NR,name,&pd_fops)) {
                 printk("%s: unable to get major number %d\n",
@@ -949,18 +949,11 @@ static int __init pd_init(void)
 
        pd_gendisk.major = major;
        pd_gendisk.major_name = name;
-       add_gendisk(&pd_gendisk);
-
        printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
                name,name,PD_VERSION,major,cluster,nice);
        pd_init_units();
-       pd_gendisk.nr_real = pd_detect();
-        if (!pd_gendisk.nr_real) {
+        if (!pd_detect()) {
                unregister_blkdev(MAJOR_NR, name);
-               del_gendisk(&pd_gendisk);
-               for (unit=0; unit<PD_UNITS; unit++) 
-                       if (PD.present)
-                               pi_release(PI);
                return -1;
        }
         return 0;
@@ -970,10 +963,11 @@ static void __exit pd_exit(void)
 {
        int unit;
        unregister_blkdev(MAJOR_NR, name);
-       del_gendisk(&pd_gendisk);
        for (unit=0; unit<PD_UNITS; unit++) 
-               if (PD.present)
+               if (PD.present) {
+                       del_gendisk(&PD.gd);
                        pi_release(PI);
+               }
 }
 
 MODULE_LICENSE("GPL");
index 07c83415f5877cded14df7c49e57ca5236475574..91403c27419f00e9f0735040615dd528e33f1242 100644 (file)
@@ -708,12 +708,22 @@ static int hd_open(struct inode * inode, struct file * filp)
 
 extern struct block_device_operations hd_fops;
 
-static struct gendisk hd_gendisk = {
+static struct gendisk hd_gendisk[2] = {
+{
        .major =        MAJOR_NR,
+       .first_minor =  0,
        .major_name =   "hd",
        .minor_shift =  6,
        .part =         hd,
        .fops =         &hd_fops,
+},{
+       .major =        MAJOR_NR,
+       .first_minor =  64,
+       .major_name =   "hd",
+       .minor_shift =  6,
+       .part =         hd + 64,
+       .fops =         &hd_fops,
+}
 };
        
 static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -845,12 +855,14 @@ static void __init hd_geninit(void)
                return;
        }
 
-       hd_gendisk.nr_real = NR_HD;
-
-       for(drive=0; drive < NR_HD; drive++)
-               register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6,
+       for(drive=0; drive < NR_HD; drive++) {
+               hd_gendisk[i].nr_real = 1;
+               add_gendisk(hd_gendisk + drive);
+               register_disk(hd_gendisk + drive,
+                       mk_kdev(MAJOR_NR,drive<<6), 1<<6,
                        &hd_fops, hd_info[drive].head * hd_info[drive].sect *
                        hd_info[drive].cyl);
+       }
 }
 
 int __init hd_init(void)
@@ -861,7 +873,6 @@ int __init hd_init(void)
        }
        blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
        blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
-       add_gendisk(&hd_gendisk);
        init_timer(&device_timer);
        device_timer.function = hd_times_out;
        hd_geninit();
index 739f634fa69c2c643c04605db9ca44b94212a0d2..58499ebbfa4ed31269eba41d40f4eae2484cdf64 100644 (file)
@@ -1064,9 +1064,9 @@ static void idedisk_setup(struct ata_device *drive)
                if (drive != &ch->drives[i])
                    continue;
                drvid = i;
-               ch->gd->de_arr[i] = drive->de;
+               ch->gd[i]->de_arr[0] = drive->de;
                if (drive->removable)
-                       ch->gd->flags[i] |= GENHD_FL_REMOVABLE;
+                       ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
                break;
        }
 
index 4651a53199354a696fbf68e1d593627a4789221b..56d076b902ffd1c7beace2d3dc1c241343100acc 100644 (file)
@@ -1712,9 +1712,9 @@ static void idefloppy_setup(struct ata_device *drive, idefloppy_floppy_t *floppy
                struct ata_channel *hwif = drive->channel;
 
                if (drive != &hwif->drives[i]) continue;
-               hwif->gd->de_arr[i] = drive->de;
+               hwif->gd[i]->de_arr[0] = drive->de;
                if (drive->removable)
-                       hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
+                       hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
                break;
        }
 }
index 38541845345edd4ca1476ea3049474dd690feb99..e37abbb65c91f5436001d4d6cb0b1bf4470f0e2a 100644 (file)
@@ -488,16 +488,19 @@ void ide_unregister(struct ata_channel *ch)
        blk_dev[ch->major].data = NULL;
        blk_dev[ch->major].queue = NULL;
        blk_clear(ch->major);
-       gd = ch->gd;
+       gd = ch->gd[0];
        if (gd) {
-               del_gendisk(gd);
+               int i;
+               for (i = 0; i < MAX_DRIVES; i++)
+                       del_gendisk(gd + i);
                kfree(gd->part);
                if (gd->de_arr)
                        kfree (gd->de_arr);
                if (gd->flags)
                        kfree (gd->flags);
                kfree(gd);
-               ch->gd = NULL;
+               for (i = 0; i < MAX_DRIVES; i++)
+                       ch->gd[i] = NULL;
        }
 
        /*
index 08113bc0e4e5475ce90ab4b622d2506dbecc9550..701317fbdd308ea1a78d1d917f0c94e380fc4db7 100644 (file)
@@ -1043,6 +1043,9 @@ static request_queue_t *ata_get_queue(kdev_t dev)
 static void channel_init(struct ata_channel *ch)
 {
        struct gendisk *gd;
+       struct hd_struct *part;
+       devfs_handle_t *de_arr;
+       char *flags;
        unsigned int unit;
        extern devfs_handle_t ide_devfs_handle;
 
@@ -1103,39 +1106,42 @@ static void channel_init(struct ata_channel *ch)
        /* Initialize partition and global device data.
         */
 
-       gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
+       gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL);
        if (!gd)
                goto err_kmalloc_gd;
 
-       memset(gd, 0, sizeof(struct gendisk));
+       memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
 
-       gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
-       if (!gd->part)
+       part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
+       if (!part)
                goto err_kmalloc_gd_part;
-       memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct));
+       memset(part, 0, ATA_MINORS * sizeof(struct hd_struct));
 
-       gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
-       if (!gd->de_arr)
+       de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL);
+       if (!de_arr)
                goto err_kmalloc_gd_de_arr;
-       memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
+       memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES);
 
-       gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
-       if (!gd->flags)
+       flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL);
+       if (!flags)
                goto err_kmalloc_gd_flags;
-       memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
+       memset(flags, 0, sizeof(char) * MAX_DRIVES);
 
-       for (unit = 0; unit < MAX_DRIVES; ++unit)
-               ch->drives[unit].part = &gd->part[unit << PARTN_BITS];
-
-       gd->major       = ch->major;            /* our major device number */
-       gd->major_name  = IDE_MAJOR_NAME;       /* treated special in genhd.c */
-       gd->minor_shift = PARTN_BITS;           /* num bits for partitions */
-       gd->nr_real     = MAX_DRIVES;           /* current num real drives */
-       gd->next        = NULL;                 /* linked list of major devs */
-       gd->fops        = ide_fops;             /* file operations */
-
-       ch->gd = gd;
-       add_gendisk(gd);
+       for (unit = 0; unit < MAX_DRIVES; ++unit) {
+               gd[unit].part = part + (unit << PARTN_BITS);
+               gd[unit].de_arr = de_arr + unit;
+               gd[unit].flags = flags + unit;
+               ch->drives[unit].part = gd[unit].part;
+               gd[unit].major  = ch->major;
+               gd[unit].first_minor = unit << PARTN_BITS;
+               /* treated special in genhd.c */
+               gd[unit].major_name = IDE_MAJOR_NAME;
+               gd[unit].minor_shift = PARTN_BITS;
+               gd[unit].nr_real = 1;
+               gd[unit].fops = ide_fops;
+               ch->gd[unit] = gd + unit;
+               add_gendisk(gd + unit);
+       }
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                char name[80];
@@ -1156,9 +1162,9 @@ static void channel_init(struct ata_channel *ch)
        return;
 
 err_kmalloc_gd_flags:
-       kfree(gd->de_arr);
+       kfree(de_arr);
 err_kmalloc_gd_de_arr:
-       kfree(gd->part);
+       kfree(part);
 err_kmalloc_gd_part:
        kfree(gd);
 err_kmalloc_gd:
index 67addc14739c0135b950576f8267ddc2835f2509..911deaf7e380b95b9be13ddc8131148318223677 100644 (file)
@@ -90,8 +90,6 @@ struct hd_struct *sd;
 static Scsi_Disk ** sd_dsk_arr;
 static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
 
-static int *sd_max_sectors;
-
 static int check_scsidisk_media_change(kdev_t);
 static int fop_revalidate_scsidisk(kdev_t);
 
@@ -605,22 +603,7 @@ static struct block_device_operations sd_fops =
        revalidate:             fop_revalidate_scsidisk
 };
 
-/*
- *    If we need more than one SCSI disk major (i.e. more than
- *      16 SCSI disks), we'll have to vmalloc() more gendisks later.
- */
-
-static struct gendisk sd_gendisk =
-{
-       major:          SCSI_DISK0_MAJOR,
-       major_name:     "sd",
-       minor_shift:    4,
-       fops:           &sd_fops,
-};
-
-static struct gendisk *sd_gendisks = &sd_gendisk;
-
-#define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+static struct gendisk **sd_disks;
 
 /**
  *     sd_rw_intr - bottom half handler: called when the lower level
@@ -1224,62 +1207,23 @@ static int sd_init()
                        sd_dsk_arr[k] = sdkp;
                }
        }
+       init_mem_lth(sd_disks, sd_template.dev_max);
+       if (sd_disks)
+               zero_mem_lth(sd_disks, sd_template.dev_max);
        init_mem_lth(sd, maxparts);
-       init_mem_lth(sd_gendisks, N_USED_SD_MAJORS);
-       init_mem_lth(sd_max_sectors, sd_template.dev_max << 4);
 
-       if (!sd_dsk_arr || !sd || !sd_gendisks)
+       if (!sd_dsk_arr || !sd || !sd_disks)
                goto cleanup_mem;
 
        zero_mem_lth(sd, maxparts);
-
-       for (k = 0; k < maxparts; k++) {
-               /*
-                * Allow lowlevel device drivers to generate 512k large scsi
-                * commands if they know what they're doing and they ask for it
-                * explicitly via the SHpnt->max_sectors API.
-                */
-               sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8;
-       }
-
-       for (k = 0; k < N_USED_SD_MAJORS; k++) {
-               int N = SCSI_DISKS_PER_MAJOR;
-
-               sd_gendisks[k] = sd_gendisk;
-
-               init_mem_lth(sd_gendisks[k].de_arr, N);
-               init_mem_lth(sd_gendisks[k].flags, N);
-               init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
-               if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
-                               !sd_gendisks[k].driverfs_dev_arr)
-                       goto cleanup_gendisks;
-
-               zero_mem_lth(sd_gendisks[k].de_arr, N);
-               zero_mem_lth(sd_gendisks[k].flags, N);
-               zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
-               sd_gendisks[k].major = SD_MAJOR(k);
-               sd_gendisks[k].major_name = "sd";
-               sd_gendisks[k].minor_shift = 4;
-               sd_gendisks[k].part = sd + k * (N << 4);
-               sd_gendisks[k].nr_real = 0;
-       }
        return 0;
 
 #undef init_mem_lth
 #undef zero_mem_lth
 
-cleanup_gendisks:
-       /* vfree can handle NULL, so no test is required here */
-       for (k = 0; k < N_USED_SD_MAJORS; k++) {
-               vfree(sd_gendisks[k].de_arr);
-               vfree(sd_gendisks[k].flags);
-               vfree(sd_gendisks[k].driverfs_dev_arr);
-       }
 cleanup_mem:
-       vfree(sd_gendisks);
-       sd_gendisks = NULL;
+       vfree(sd_disks);
+       sd_disks = NULL;
        vfree(sd);
        sd = NULL;
        if (sd_dsk_arr) {
@@ -1310,17 +1254,16 @@ static void sd_finish()
        Scsi_Disk * sdkp;
 
        SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
-       for (k = 0; k < N_USED_SD_MAJORS; k++) {
+       for (k = 0; k < N_USED_SD_MAJORS; k++)
                blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
-               add_gendisk(&(sd_gendisks[k]));
-       }
 
        for (k = 0; k < sd_template.dev_max; ++k) {
                sdkp = sd_get_sdisk(k);
                if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
                        sd_init_onedisk(sdkp, k);
                        if (!sdkp->has_been_registered) {
-                               register_disk(&SD_GENDISK(k), MKDEV_SD(k),
+                               add_gendisk(sd_disks[k]);
+                               register_disk(sd_disks[k], MKDEV_SD(k),
                                                1<<4, &sd_fops,
                                                sdkp->capacity);
                                sdkp->has_been_registered = 1;
@@ -1366,21 +1309,36 @@ static int sd_detect(Scsi_Device * sdp)
  **/
 static int sd_attach(Scsi_Device * sdp)
 {
-        unsigned int devnum;
        Scsi_Disk *sdkp;
        int dsk_nr;
        char diskname[6];
        unsigned long iflags;
+       struct {
+               struct gendisk disk;
+               devfs_handle_t de;
+               struct device *dev;
+               char flags;
+       } *p;
+       struct gendisk *gd;
 
        if ((NULL == sdp) ||
            ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
                return 0;
 
+       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return 1;
+       gd = &p->disk;
+       gd->de_arr = &p->de;
+       gd->flags = &p->flags;
+       gd->driverfs_dev_arr = &p->dev;
+
        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(p);
                return 1;
        }
 
@@ -1400,17 +1358,23 @@ 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(p);
                return 1;
        }
 
        sd_template.nr_dev++;
-       SD_GENDISK(dsk_nr).nr_real++;
-        devnum = dsk_nr % SCSI_DISKS_PER_MAJOR;
-        SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
-        SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] = 
-               &sdp->sdev_driverfs_dev;
+       gd->nr_real = 1;
+        gd->de_arr[0] = sdp->de;
+        gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev;
+       gd->major = SD_MAJOR(dsk_nr>>4);
+       gd->first_minor = (dsk_nr & 15)<<4;
+       gd->major_name = "sd";
+       gd->minor_shift = 4;
+       gd->part = sd + (dsk_nr << 4);
+       gd->fops = &sd_fops;
         if (sdp->removable)
-               SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
+               gd->flags[0] |= GENHD_FL_REMOVABLE;
+       sd_disks[dsk_nr] = gd;
        sd_dskname(dsk_nr, diskname);
        printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
               "id %d, lun %d\n", sdp->removable ? "removable " : "",
@@ -1480,8 +1444,6 @@ static void sd_detach(Scsi_Device * sdp)
        Scsi_Disk *sdkp = NULL;
        kdev_t dev;
        int dsk_nr;
-       int max_p;
-       int start;
        unsigned long iflags;
 
        SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", 
@@ -1491,7 +1453,6 @@ static void sd_detach(Scsi_Device * sdp)
        for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
                sdkp = sd_dsk_arr[dsk_nr];
                if (sdkp->device == sdp) {
-                       sdkp->has_been_registered = 0;
                        sdkp->device = NULL;
                        sdkp->capacity = 0;
                        /* sdkp->detaching = 1; */
@@ -1502,19 +1463,20 @@ static void sd_detach(Scsi_Device * sdp)
        if (dsk_nr >= sd_template.dev_max)
                return;
 
-       max_p = 1 << sd_gendisk.minor_shift;
-       start = dsk_nr << sd_gendisk.minor_shift;
-       dev = MKDEV_SD_PARTITION(start);
-       driverfs_remove_partitions(&SD_GENDISK (dsk_nr), 
-                                       SD_MINOR_NUMBER (start));
-       wipe_partitions(dev);
-       devfs_register_partitions (&SD_GENDISK (dsk_nr),
-                                  SD_MINOR_NUMBER (start), 1);
-       /* unregister_disk() */
+       if (sdkp->has_been_registered) {
+               sdkp->has_been_registered = 0;
+               dev = MKDEV_SD(dsk_nr);
+               driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev));
+               wipe_partitions(dev);
+               devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1);
+               /* unregister_disk() */
+               del_gendisk(sd_disks[dsk_nr]);
+       }
        sdp->attached--;
        sd_template.dev_noticed--;
        sd_template.nr_dev--;
-       SD_GENDISK(dsk_nr).nr_real--;
+       kfree(sd_disks[dsk_nr]);
+       sd_disks[dsk_nr] = NULL;
 }
 
 /**
@@ -1560,12 +1522,9 @@ static void __exit exit_sd(void)
        vfree((char *) sd);
        for (k = 0; k < N_USED_SD_MAJORS; k++) {
                blk_dev[SD_MAJOR(k)].queue = NULL;
-               del_gendisk(&(sd_gendisks[k]));
                blk_clear(SD_MAJOR(k));
        }
        sd_template.dev_max = 0;
-       if (sd_gendisks != &sd_gendisk)
-               vfree(sd_gendisks);
        remove_driver(&sd_template.scsi_driverfs_driver);
 }
 
index f65e5649c0e0f8503bf7470bd7af2661c8e5a6ed..6de4ad25531cde33a2e67fc2f8cb4a68d72e76c5 100644 (file)
@@ -894,7 +894,7 @@ struct ata_channel {
        struct pci_dev *pci_dev;                /* for pci chipsets */
 #endif
        struct ata_device drives[MAX_DRIVES];   /* drive info */
-       struct gendisk *gd;                     /* gendisk structure */
+       struct gendisk *gd[MAX_DRIVES];         /* gendisk structure */
 
        /*
         * Routines to tune PIO and DMA mode for drives.