diff -uNr linux-2.4.18.S18.scsimany3/drivers/ide/ide-probe.c linux-2.4.18.S18.scsimany/drivers/ide/ide-probe.c --- linux-2.4.18.S18.scsimany3/drivers/ide/ide-probe.c Wed Jun 12 11:37:15 2002 +++ linux-2.4.18.S18.scsimany/drivers/ide/ide-probe.c Wed Jul 17 14:49:29 2002 @@ -779,6 +779,7 @@ gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); if (!gd) goto err_kmalloc_gd; + memset (gd, 0, sizeof(struct gendisk)); gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); if (!gd->sizes) goto err_kmalloc_gd_sizes; diff -uNr linux-2.4.18.S18.scsimany3/drivers/scsi/sd.c linux-2.4.18.S18.scsimany/drivers/scsi/sd.c --- linux-2.4.18.S18.scsimany3/drivers/scsi/sd.c Tue Jul 16 13:52:21 2002 +++ linux-2.4.18.S18.scsimany/drivers/scsi/sd.c Wed Jul 17 15:16:35 2002 @@ -146,7 +146,7 @@ midx = MAJOR_TO_MIDX(MAJOR(dev)); didx = MINOR_TO_DIDX(MINOR(dev)); - if (midx == -1) + if (midx == SD_NO_MIDX) return -ENODEV; sd_major = SD_MAJOR_PTR(midx); scsi_disk = SD_DISK_PTR(sd_major,didx); @@ -252,20 +252,30 @@ } } -static void sd_devname(unsigned int disknum, char *buffer) +int sd_devname(kdev_t dev, char *buffer) { + const unsigned int disknum = KDEV_TO_DISKNO(dev); + const unsigned int part = MINOR(dev) & (SCSI_DISK_MAX_PART-1); + if (disknum >= SD_NO_MIDX << SCSI_DISK_DISK_SHIFT) + return -1; if (disknum < 26) sprintf(buffer, "sd%c", 'a' + disknum); else if (disknum < (26*27)) { - unsigned int min1 = disknum / 26 - 1; - unsigned int min2 = disknum % 26; + const unsigned int min1 = disknum / 26 - 1; + const unsigned int min2 = disknum % 26; sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2); } else { - unsigned int min1 = (disknum / 26 - 1) / 26 - 1; - unsigned int min2 = (disknum / 26 - 1) % 26; - unsigned int min3 = disknum % 26; + const unsigned int min1 = (disknum / 26 - 1) / 26 - 1; + const unsigned int min2 = (disknum / 26 - 1) % 26; + const unsigned int min3 = disknum % 26; sprintf(buffer, "sd%c%c%c", 'a' + min1, 'a' + min2, 'a' + min3); } + /* Used by fs/partition/check.c */ + if (part) { + const int pos = strlen(buffer); + sprintf (buffer+pos, "%d", part); + } + return 0; } static int sd_find_kdev(Scsi_Device *sdp, char* nm, kdev_t *dev) @@ -278,8 +288,8 @@ sd_major = SD_MAJOR_PTR(midx); for (didx = 0; didx < SCSI_DISKS_PER_MAJOR; ++didx) { if (SD_DISK_PTR(sd_major, didx)->device == sdp) { - sd_devname(MDIDX_TO_DISKNO(midx, didx), nm); *dev = MDIDX_TO_KDEV(midx, didx); + sd_devname(*dev, nm); return 0; } } @@ -295,7 +305,7 @@ midx = MAJOR_TO_MIDX (MAJOR(dev)); didx = MINOR_TO_DIDX (MINOR(dev)); - if (midx == -1) { + if (midx == SD_NO_MIDX) { printk (KERN_ERR "sd_find_queue %02x:%02x not found!\n", MAJOR(dev), MINOR(dev)); return NULL; @@ -309,7 +319,7 @@ static int sd_drives_dev(kdev_t dev) { int midx = MAJOR_TO_MIDX(MAJOR(dev)); - if (midx == -1) + if (midx == SD_NO_MIDX) return 0; else return 1; @@ -321,14 +331,14 @@ struct hd_struct *ppnt; Scsi_Disk *dpnt; #if CONFIG_SCSI_LOGGING - char nbuff[8]; + char nbuff[10]; #endif int midx, didx; SD_Major *sd_major; midx = MAJOR_TO_MIDX(MAJOR(SCpnt->request.rq_dev)); didx = MINOR_TO_DIDX(MINOR(SCpnt->request.rq_dev)); - if (midx == -1) { + if (midx == SD_NO_MIDX) { printk ("Can not sd_init_command for dev %02x:%02x!\n", MAJOR(SCpnt->request.rq_dev), MINOR(SCpnt->request.rq_dev)); @@ -366,7 +376,7 @@ /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ return 0; } - SCSI_LOG_HLQUEUE(2, sd_devname(MDIDX_TO_DISKNO(midx, didx), nbuff)); + SCSI_LOG_HLQUEUE(2, sd_devname(SCpnt->request.rq_dev, nbuff)); SCSI_LOG_HLQUEUE(2, printk("%s : %02x:%02x, block = %d\n", nbuff, MAJOR(SCpnt->request.rq_dev), MINOR(SCpnt->request.rq_dev), block)); @@ -494,7 +504,7 @@ SCSI_LOG_HLQUEUE(1, printk("target=%d\n", MDIDX_TO_DISKNO(midx, didx))); - if (midx == -1) + if (midx == SD_NO_MIDX) return -ENXIO; sd_major = SD_MAJOR_PTR(midx); scsi_disk = SD_DISK_PTR(sd_major, didx); @@ -595,7 +605,7 @@ midx = MAJOR_TO_MIDX(MAJOR(inode->i_rdev)); didx = MINOR_TO_DIDX(MINOR(inode->i_rdev)); - if (midx == -1) { + if (midx == SD_NO_MIDX) { printk (KERN_ERR "sd_release: dev %02x:%02x does not belong to sd!\n", MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); return -ENODEV; @@ -640,7 +650,7 @@ { int result = SCpnt->result; #if CONFIG_SCSI_LOGGING - char nbuff[8]; + char nbuff[10]; #endif int this_count = SCpnt->bufflen >> 9; int good_sectors = (result == 0 ? this_count : 0); @@ -651,7 +661,7 @@ midx = MAJOR_TO_MIDX(MAJOR(SCpnt->request.rq_dev)); didx = MINOR_TO_DIDX(MINOR(SCpnt->request.rq_dev)); - SCSI_LOG_HLCOMPLETE(1, sd_devname(MDIDX_TO_DISKNO(midx,didx), nbuff)); + SCSI_LOG_HLCOMPLETE(1, sd_devname(SCpnt->request.rq_dev, nbuff)); SCSI_LOG_HLCOMPLETE(1, printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff, SCpnt->host->host_no, @@ -756,7 +766,7 @@ midx = MAJOR_TO_MIDX(MAJOR(full_dev)); didx = MINOR_TO_DIDX(MINOR(full_dev)); - if (midx == -1) { + if (midx == SD_NO_MIDX) { printk("SCSI disk request error: invalid major.\n"); return 0; } @@ -836,7 +846,7 @@ /* * Get the name of the disk, in case we need to log it somewhere. */ - sd_devname(MDIDX_TO_DISKNO(midx,didx), nbuff); + sd_devname(MDIDX_TO_KDEV(midx,didx), nbuff); /* * If the device is offline, don't try and read capacity or any @@ -1160,7 +1170,7 @@ err = sd_alloc_major (); } SD_UNLOCK_W; - if (err == -1) { + if (err == SD_NO_MAJOR) { sd_template.dev_noticed = 0; return 1; } else { @@ -1250,7 +1260,7 @@ if (SDp->removable) gdp->flags[didx] |= GENHD_FL_REMOVABLE; - sd_devname(MDIDX_TO_DISKNO(midx,didx), nbuff); + sd_devname(MDIDX_TO_KDEV(midx,didx), nbuff); printk("Attached scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n", SDp->removable ? "removable " : "", nbuff, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); diff -uNr linux-2.4.18.S18.scsimany3/drivers/scsi/sd.h linux-2.4.18.S18.scsimany/drivers/scsi/sd.h --- linux-2.4.18.S18.scsimany3/drivers/scsi/sd.h Tue Jul 16 13:22:21 2002 +++ linux-2.4.18.S18.scsimany/drivers/scsi/sd.h Wed Jul 17 14:06:17 2002 @@ -42,5 +42,6 @@ } Scsi_Disk; extern struct block_device_operations sd_fops; +extern int sd_devname(kdev_t dev, char *buffer); #endif diff -uNr linux-2.4.18.S18.scsimany3/drivers/scsi/sd_dynalloc.c linux-2.4.18.S18.scsimany/drivers/scsi/sd_dynalloc.c --- linux-2.4.18.S18.scsimany3/drivers/scsi/sd_dynalloc.c Tue Jul 16 13:53:11 2002 +++ linux-2.4.18.S18.scsimany/drivers/scsi/sd_dynalloc.c Wed Jul 17 15:19:23 2002 @@ -3,18 +3,28 @@ * (c) Kurt Garloff , 7/2002 * License: GNU GPL v2 */ -/* 2002-07-14: Initial write. +/* 2002-07-14: Initial write. (sd_many-2) + * + * 2002-07-15: Fixes (sd_many-3) + * Fix dynamic block major allocation to work with + * non-devfs systems. + * + * 2002-07-17: Reversed major mapping array: (sd_many-4) + * We now map majors to an index in our ptr array. + * Fix /proc/partitions by calling sd_devname() via gendisk + * * TODO: - Check locking issues. - * - Intelligent reuse of sd slots + * - More intelligent reuse of sd slots * - Proofread code * - Remove debug printks - * - midx[major] array to speed up major_to_midx + * */ #include "sd_dynalloc.h" #include +#define SD_REUSE_SLOTS 1 #define SD_DYN_DEBUG 1 # define SDD_PRINTK(ARGS...) printk(KERN_WARNING "sd: " ARGS) @@ -26,7 +36,7 @@ /* Locking: * We protect the following variables by a spinlock: - * sd_majors, sd_per_major_ptrs, sd_major_list, next_sd + * sd_majors, sd_per_major_ptrs, sd_major_to_midx, next_sd * Actually, we try to only use the locks for writing. * This should be possible, as we do build and fill * structs before we link them into a list and we never @@ -41,17 +51,16 @@ /* Index into the last sd_major struct for next free sd */ static int sd_next = SCSI_DISKS_PER_MAJOR; -int sd_major_list[MAX_SCSI_DYN_MAJORS]; +/* Maps majors to indices into sd_major_ptrs */ +unsigned char sd_major_to_midx[MAJORS]; +/* List of pointers to SD_Major structs */ struct sd_per_major *sd_major_ptrs[MAX_SCSI_DYN_MAJORS]; -int major_to_midx (const int maj) +int sd_midx_to_major (const int midx) { - int i; - for (i = 0; i < sd_majors; ++i) - if (maj == sd_major_list[i]) - return i; - SDD_PRINTK("major %i not registered for sd\n", maj); - return -1; + if (midx < 0 || midx >= sd_majors) + return SD_NO_MAJOR; + return SD_MAJOR_PTR(midx)->sd_gendisk.major; } /* Fill in defaults (except 0) */ @@ -84,6 +93,7 @@ gdp->minor_shift = SCSI_DISK_PART_BITS; //? gdp->max_p = SCSI_DISK_MAX_PART; gdp->fops = &sd_fops; + gdp->devname = sd_devname; } /* Fill in gendisk */ @@ -107,22 +117,26 @@ /* This has the nasty side-effect of triggering kmod on blockdevs * after FIRST_MAJOR. However, this also makes it safe not to * use the major of sb. else. And: there is nobody ... KG. */ - while (++maj < 255) + while (++maj < (MAJORS-1)) if (!get_blkfops(maj)) return maj; - return -1; + return SD_NO_MAJOR; } #endif -request_queue_t *sd_find_queue(kdev_t dev); +extern request_queue_t *sd_find_queue(kdev_t dev); /* We should already have the lock in write mode when entering */ int sd_alloc_major (void) { int major; SD_Major *sd_major; + /* Initialize sd_major_to_midx array */ + if (sd_majors == 0) + memset (sd_major_to_midx, SD_NO_MIDX, MAJORS); + if (sd_majors >= MAX_SCSI_DYN_MAJORS) - return -1; + return SD_NO_MAJOR; if (!sd_majors) major = SCSI_DISK0_MAJOR; else if (sd_majors < 8) @@ -133,7 +147,7 @@ #else major = sd_find_major (); #endif - if (major == -1) { + if (major == SD_NO_MAJOR) { SDD_PRINTK("alloc_major: could not get major\n"); return major; } @@ -160,7 +174,7 @@ sd_fill_in_gendisk (sd_major); blk_dev[major].queue = sd_find_queue; sd_major_ptrs[sd_majors] = sd_major; - sd_major_list[sd_majors++] = major; + sd_major_to_midx[major] = sd_majors++; sd_next = 0; /* FIXME: used to be done at finish time, should be OK here. KG. */ add_gendisk(&sd_major->sd_gendisk); @@ -171,26 +185,32 @@ kfree (sd_major); dealloc_major: +#ifdef CONFIG_DEVFS_FS if (sd_majors >= 8) devfs_dealloc_major(DEVFS_SPECIAL_BLK, major); - return -1; +#endif + return SD_NO_MAJOR; } /* Deallocate one major */ void sd_dealloc_major (const int midx) { SD_Major *sd_major = SD_MAJOR_PTR(midx); - int major = MIDX_TO_MAJOR(midx); + const int major = MIDX_TO_MAJOR(midx); del_gendisk(&sd_major->sd_gendisk); devfs_unregister_blkdev(major, "sd"); sd_major_ptrs[midx] = NULL; - sd_major_list[midx] = 0; + sd_major_to_midx[major] = SD_NO_MIDX; read_ahead[major] = 0; blksize_size[major] = NULL; hardsect_size[major] = NULL; max_sectors[major] = NULL; blkdev_varyio[major] = NULL; blk_dev[major].queue = NULL; +#ifdef CONFIG_DEVFS_FS + if (midx >= 8) + devfs_dealloc_major(DEVFS_SPECIAL_BLK, major); +#endif kfree (sd_major); SDD_PRINTK("deallocated major %i\n", major); } @@ -214,7 +234,7 @@ SDD_DPRINTK("find_free_slot ..."); SD_LOCK_W; #ifdef SD_REUSE_SLOTS - for (*midx = 0; *midx < scsi_majors; ++*midx) { + for (*midx = 0; *midx < sd_majors; ++*midx) { sd_major = SD_MAJOR_PTR(*midx); for (*didx = 0; *didx < SCSI_DISKS_PER_MAJOR; ++*didx) { scsi_disk = SD_DISK_PTR(sd_major, *didx); @@ -232,7 +252,7 @@ /* OK, we need to allocate a new major */ if (sd_alloc_major () == -1) { SD_UNLOCK_W; - return -1; + return SD_NO_MAJOR; } *midx = sd_majors-1; *didx = sd_next; /* 0 */ diff -uNr linux-2.4.18.S18.scsimany3/drivers/scsi/sd_dynalloc.h linux-2.4.18.S18.scsimany/drivers/scsi/sd_dynalloc.h --- linux-2.4.18.S18.scsimany3/drivers/scsi/sd_dynalloc.h Tue Jul 16 13:31:44 2002 +++ linux-2.4.18.S18.scsimany/drivers/scsi/sd_dynalloc.h Wed Jul 17 14:08:13 2002 @@ -10,12 +10,13 @@ #include #include "sd.h" -#define MINORS (1U<>SCSI_DISK_PART_BITS) @@ -53,23 +54,24 @@ char flags[SCSI_DISKS_PER_MAJOR]; struct gendisk sd_gendisk; struct hd_struct sd_hds[MINORS]; - int major; } SD_Major; /* The dynamically allocated majors */ extern int sd_majors; -extern int sd_major_list[MAX_SCSI_DYN_MAJORS]; +extern unsigned char sd_major_to_midx[MAJORS]; extern struct sd_per_major *sd_major_ptrs[MAX_SCSI_DYN_MAJORS]; +#define SD_NO_MIDX 255 +#define SD_NO_MAJOR -1 extern rwlock_t sd_dyn_lock; #define SD_LOCK_W write_lock(&sd_dyn_lock) #define SD_UNLOCK_W write_unlock(&sd_dyn_lock) -int major_to_sdgen (const int maj); -int sd_alloc_major (void); -void sd_dealloc_major (const int idx); +int sd_midx_to_major (const int midex); +int sd_alloc_major (void); +void sd_dealloc_major (const int idx); void sd_deallocate_all (void); -int sd_find_free_slot (Scsi_Device *SDp, int *midx, int *didx); +int sd_find_free_slot (Scsi_Device *SDp, int *midx, int *didx); #endif /* _SD_DYNALLOC_H */ diff -uNr linux-2.4.18.S18.scsimany3/fs/partitions/check.c linux-2.4.18.S18.scsimany/fs/partitions/check.c --- linux-2.4.18.S18.scsimany3/fs/partitions/check.c Wed Jun 12 11:37:11 2002 +++ linux-2.4.18.S18.scsimany/fs/partitions/check.c Wed Jul 17 14:52:16 2002 @@ -107,6 +107,16 @@ return buf + pos; } + /* The device driver can provide its own naming */ + if (hd->devname) { + kdev_t dev = MKDEV(hd->major, minor); + *buf = 0; + if ((hd->devname)(dev, buf)) + printk (KERN_ERR "disk_name():devname() failed!\n"); + else + return buf; + } + #ifdef CONFIG_ARCH_S390 if (genhd_dasd_name && genhd_dasd_name (buf, unit, part, hd) == 0) @@ -143,16 +153,9 @@ sprintf(buf, "%s%d", maj, unit); return buf; } - if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) { - unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16; - if (unit+'a' > 'z') { - unit -= 26; - sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26); - if (part) - sprintf(buf + 4, "%d", part); - return buf; - } - } + + /* SCSI uses (*devname)() */ + if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) { int ctlr = hd->major - COMPAQ_SMART2_MAJOR; if (part == 0) diff -uNr linux-2.4.18.S18.scsimany3/include/linux/genhd.h linux-2.4.18.S18.scsimany/include/linux/genhd.h --- linux-2.4.18.S18.scsimany3/include/linux/genhd.h Tue Jul 16 13:21:37 2002 +++ linux-2.4.18.S18.scsimany/include/linux/genhd.h Wed Jul 17 13:17:07 2002 @@ -101,6 +101,7 @@ devfs_handle_t *de_arr; /* one per physical disc */ char *flags; /* one per physical disc */ + int (*devname) (kdev_t dev, char *buffer); }; /* drivers/block/genhd.c */