[PATCH] Support for >= 16 SCSI disks (looking for TESTERS)

Jakub Jelinek (jj@sunsite.ms.mff.cuni.cz)
Fri, 4 Sep 1998 16:34:03 +0200 (MET DST)


Hi!

This patch adds support for >= 16 SCSI disks (up to 128 SCSI disks in one
box). As Linus did not like the approach of enlargering kdev_t, this patch
adds 7 new SCSI majors (already registered in devices.tex).
Please test it if you can, not only in >= 16 sd configurations, but in
configurations with fewer disks as well, if nothing broke.
I've been using it for nearly a month on a single SCSI disk machine and it
now works on my 39 SCSI disk server without any problems.

(The patch is against current vger CVS, but I think it should apply cleanly
to 119 and other kernels as well - if you'll get any rejects, tell me and
I'll make another patch relative to kernel.org tree).

--- linux/drivers/block/acsi.c.jj Fri Sep 4 10:50:02 1998
+++ linux/drivers/block/acsi.c Fri Sep 4 13:35:47 1998
@@ -3,7 +3,7 @@
*
* Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
- * Some parts are based on hd.c by Linus Thorvalds
+ * Some parts are based on hd.c by Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
--- linux/drivers/block/genhd.c.jj Fri Sep 4 10:50:13 1998
+++ linux/drivers/block/genhd.c Fri Sep 4 13:35:47 1998
@@ -69,7 +69,7 @@ char *disk_name (struct gendisk *hd, int
{
unsigned int part;
const char *maj = hd->major_name;
- char unit = (minor >> hd->minor_shift) + 'a';
+ int unit = (minor >> hd->minor_shift) + 'a';

/*
* IDE devices use multiple major numbers, but the drives
@@ -85,8 +85,19 @@ char *disk_name (struct gendisk *hd, int
unit += 2;
case IDE0_MAJOR:
maj = "hd";
+ break;
}
part = minor & ((1 << hd->minor_shift) - 1);
+ if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+ unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+ if (unit > 'z') {
+ unit -= 'z' + 1;
+ sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
+ if (part)
+ sprintf(buf + 4, "%d", part);
+ return buf;
+ }
+ }
if (part)
sprintf(buf, "%s%c%d", maj, unit, part);
else
--- linux/drivers/block/ll_rw_blk.c.jj Fri Sep 4 10:50:41 1998
+++ linux/drivers/block/ll_rw_blk.c Fri Sep 4 13:35:47 1998
@@ -93,8 +93,8 @@ int * blksize_size[MAX_BLKDEV] = { NULL,
* then 512 bytes is assumed.
* else
* sector_size is hardsect_size[MAJOR][MINOR]
- * This is currently set by some scsi device and read by the msdos fs driver
- * This might be a some uses later.
+ * This is currently set by some scsi devices and read by the msdos fs driver.
+ * Other uses may appear later.
*/
int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };

@@ -297,8 +297,8 @@ void add_request(struct blk_dev_struct *
int queue_new_request = 0;

switch (MAJOR(req->rq_dev)) {
- case SCSI_DISK_MAJOR:
- disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
+ case SCSI_DISK0_MAJOR:
+ disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
if (disk_index < 4)
drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
break;
@@ -479,7 +479,14 @@ void make_request(int major,int rw, stru
break;
/* fall through */

- case SCSI_DISK_MAJOR:
+ case SCSI_DISK0_MAJOR:
+ case SCSI_DISK1_MAJOR:
+ case SCSI_DISK2_MAJOR:
+ case SCSI_DISK3_MAJOR:
+ case SCSI_DISK4_MAJOR:
+ case SCSI_DISK5_MAJOR:
+ case SCSI_DISK6_MAJOR:
+ case SCSI_DISK7_MAJOR:
case SCSI_CDROM_MAJOR:

do {
--- linux/drivers/char/sysrq.c.jj Fri Sep 4 10:56:12 1998
+++ linux/drivers/char/sysrq.c Fri Sep 4 13:35:47 1998
@@ -168,7 +168,14 @@ static int is_local_disk(kdev_t dev)
case IDE1_MAJOR:
case IDE2_MAJOR:
case IDE3_MAJOR:
- case SCSI_DISK_MAJOR:
+ case SCSI_DISK0_MAJOR:
+ case SCSI_DISK1_MAJOR:
+ case SCSI_DISK2_MAJOR:
+ case SCSI_DISK3_MAJOR:
+ case SCSI_DISK4_MAJOR:
+ case SCSI_DISK5_MAJOR:
+ case SCSI_DISK6_MAJOR:
+ case SCSI_DISK7_MAJOR:
return 1;
default:
return 0;
--- linux/drivers/scsi/scsi.c.jj Fri Sep 4 11:19:52 1998
+++ linux/drivers/scsi/scsi.c Fri Sep 4 13:35:47 1998
@@ -1739,8 +1739,7 @@ scsi_finish_command(Scsi_Cmnd * SCpnt)
host_active = NULL;

/* For block devices "wake_up" is done in end_scsi_request */
- if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
- MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+ if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
struct Scsi_Host * next;

for (next = host->block; next != host; next = next->block)
--- linux/drivers/scsi/scsi_obsolete.c.jj Fri Sep 4 11:20:00 1998
+++ linux/drivers/scsi/scsi_obsolete.c Fri Sep 4 13:35:47 1998
@@ -655,8 +655,7 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
host_active = NULL;

/* For block devices "wake_up" is done in end_scsi_request */
- if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
- MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+ if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
struct Scsi_Host * next;

for (next = host->block; next != host; next = next->block)
--- linux/drivers/scsi/sd.c.jj Fri Sep 4 11:20:18 1998
+++ linux/drivers/scsi/sd.c Fri Sep 4 13:41:05 1998
@@ -14,8 +14,11 @@
*
* Modified by Eric Youngdale eric@aib.com to support loadable
* low-level scsi drivers.
+ *
+ * Modified by Jirka Hanika geo@ff.cuni.cz to support more
+ * scsi disks using eight major numbers.
*/
-
+
#include <linux/module.h>
#ifdef MODULE
/*
@@ -41,7 +44,7 @@
#include <asm/system.h>
#include <asm/io.h>

-#define MAJOR_NR SCSI_DISK_MAJOR
+#define MAJOR_NR SCSI_DISK0_MAJOR
#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
@@ -54,6 +57,15 @@
/*
* static const char RCSid[] = "$Header:";
*/
+
+#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+
+#define SCSI_DISKS_PER_MAJOR 16
+#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i) ((i) & 255)
+#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), (i) & 255)
+#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4)
+#define N_USED_SD_MAJORS ((sd_template.dev_max + SCSI_DISKS_PER_MAJOR - 1) / SCSI_DISKS_PER_MAJOR)

#define MAX_RETRIES 5

@@ -91,12 +103,9 @@ static void sd_detach(Scsi_Device *);

static void sd_devname(unsigned int disknum, char * buffer)
{
- if( disknum <= 26 )
- {
+ if( disknum < 26 )
sprintf(buffer, "sd%c", 'a' + disknum);
- }
- else
- {
+ else {
unsigned int min1;
unsigned int min2;
/*
@@ -105,13 +114,13 @@ static void sd_devname(unsigned int disk
*/
min1 = disknum / 26;
min2 = disknum % 26;
- sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2);
+ sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
}
}

struct Scsi_Device_Template sd_template =
{ NULL, "disk", "sd", NULL, TYPE_DISK,
- SCSI_DISK_MAJOR, 0, 0, 0, 1,
+ SCSI_DISK0_MAJOR, 0, 0, 0, 1,
sd_detect, sd_init,
sd_finish, sd_attach, sd_detach
};
@@ -175,7 +184,7 @@ static int sd_open(struct inode * inode,
* See if we are requesting a non-existent partition. Do this
* after checking for disk change.
*/
- if(sd_sizes[MINOR(inode->i_rdev)] == 0)
+ if(sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)
return -ENXIO;

if(rscsi_disks[target].device->removable)
@@ -230,8 +239,13 @@ static struct file_operations sd_fops =
fop_revalidate_scsidisk /* revalidate */
};

+/*
+ * If we need more than one SCSI disk major (i.e. more than
+ * 16 SCSI disks), we'll have to kmalloc() more gendisks later.
+ */
+
static struct gendisk sd_gendisk = {
- MAJOR_NR, /* Major number */
+ SCSI_DISK0_MAJOR, /* Major number */
"sd", /* Major name */
4, /* Bits to shift to get real from partition */
1 << 4, /* Number of partitions per real */
@@ -242,7 +256,12 @@ static struct gendisk sd_gendisk = {
0, /* number */
NULL, /* internal */
NULL /* next */
-};
+};
+
+static struct gendisk *sd_gendisks = &sd_gendisk;
+
+#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+#define LAST_SD_GENDISK sd_gendisks[N_USED_SD_MAJORS - 1]

static void sd_geninit (struct gendisk *ignored)
{
@@ -251,10 +270,6 @@ static void sd_geninit (struct gendisk *
for (i = 0; i < sd_template.dev_max; ++i)
if(rscsi_disks[i].device)
sd[i << 4].nr_sects = rscsi_disks[i].capacity;
-#if 0
- /* No longer needed - we keep track of this as we attach/detach */
- sd_gendisk.nr_real = sd_template.dev_max;
-#endif
}

/*
@@ -271,7 +286,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
int good_sectors = (result == 0 ? this_count : 0);
int block_sectors = 1;

- sd_devname(MINOR(SCpnt->request.rq_dev) >> 4, nbuff);
+ sd_devname(DEVICE_NR(SCpnt->request.rq_dev), nbuff);

SCSI_LOG_HLCOMPLETE(1,printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff,
SCpnt->host->host_no,
@@ -309,7 +324,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
}
else if (sector_size == 256)
error_sector >>= 1;
- error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+ error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;
error_sector &= ~ (block_sectors - 1);
good_sectors = error_sector - SCpnt->request.sector;
if (good_sectors < 0 || good_sectors >= this_count)
@@ -524,7 +539,7 @@ static void do_sd_request (void)
}

INIT_SCSI_REQUEST;
- SDev = rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device;
+ SDev = rscsi_disks[CURRENT_DEV].device;

/*
* If the host for this device is in error recovery mode, don't
@@ -578,7 +593,7 @@ static void do_sd_request (void)

if (flag++ == 0)
SCpnt = scsi_allocate_device(&CURRENT,
- rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0);
+ rscsi_disks[CURRENT_DEV].device, 0);
else SCpnt = NULL;

/*
@@ -643,7 +658,7 @@ static void requeue_sd_request (Scsi_Cmn
return;
}

- devm = MINOR(SCpnt->request.rq_dev);
+ devm = SD_PARTITION(SCpnt->request.rq_dev);
dev = DEVICE_NR(SCpnt->request.rq_dev);

block = SCpnt->request.sector;
@@ -1329,7 +1344,7 @@ static int sd_init_onedisk(int i)
printk ("scsi : deleting disk entry.\n");
rscsi_disks[i].device = NULL;
sd_template.nr_dev--;
- sd_gendisk.nr_real--;
+ SD_GENDISK(i).nr_real--;

/* Wake up a process waiting for device */
wake_up(&SCpnt->device->device_wait);
@@ -1463,67 +1478,99 @@ static int sd_init()

if (sd_template.dev_noticed == 0) return 0;

+ if (!rscsi_disks)
+ sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
+
+ /* 128 disks is our current limit (8 majors, 16 disks per major) */
+ if(sd_template.dev_max > 128)
+ sd_template.dev_max = 128;
+
if(!sd_registered) {
- if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) {
- printk("Unable to get major %d for SCSI disk\n",MAJOR_NR);
- return 1;
- }
- sd_registered++;
- }
+ for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) {
+ printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
+ return 1;
+ }
+ }
+ sd_registered++;
+ }

/* We do not support attaching loadable devices yet. */
if(rscsi_disks) return 0;

- sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
-
rscsi_disks = (Scsi_Disk *)
scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
-
- sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
- sizeof(int), GFP_ATOMIC);
+
+ /* for every (necessary) major: */
+ sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));

- sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
- sizeof(int), GFP_ATOMIC);
+ sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+ sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);

- sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
- sizeof(int), GFP_ATOMIC);
-
- for(i=0;i<(sd_template.dev_max << 4);i++)
- {
- sd_blocksizes[i] = 1024;
- sd_hardsizes[i] = 512;
- }
+ for(i=0; i < sd_template.dev_max << 4; i++) {
+ sd_blocksizes[i] = 1024;
+ sd_hardsizes[i] = 512;
+ }

- blksize_size[MAJOR_NR] = sd_blocksizes;
- hardsect_size[MAJOR_NR] = sd_hardsizes;
+ for (i=0; i < N_USED_SD_MAJORS; i++) {
+ blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+ hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+ }
sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(struct hd_struct),
GFP_ATOMIC);

-
- sd_gendisk.max_nr = sd_template.dev_max;
- sd_gendisk.part = sd;
- sd_gendisk.sizes = sd_sizes;
- sd_gendisk.real_devices = (void *) rscsi_disks;
+ if (N_USED_SD_MAJORS > 1)
+ sd_gendisks = (struct gendisk *)
+ kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+ for (i=0; i < N_USED_SD_MAJORS; i++) {
+ sd_gendisks[i].major = SD_MAJOR(i);
+ sd_gendisks[i].major_name = "sd";
+ sd_gendisks[i].minor_shift = 4;
+ sd_gendisks[i].max_p = 1 << 4;
+ sd_gendisks[i].max_nr = SCSI_DISKS_PER_MAJOR;
+ sd_gendisks[i].init = sd_geninit;
+ sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4);
+ sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4);
+ sd_gendisks[i].nr_real = 0;
+ sd_gendisks[i].next = sd_gendisks + i + 1;
+ sd_gendisks[i].real_devices =
+ (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
+ }
+ LAST_SD_GENDISK.max_nr =
+ sd_template.dev_max % SCSI_DISKS_PER_MAJOR;
+ LAST_SD_GENDISK.next = NULL;
return 0;
}

+/*
+ * sd_get_queue() returns the queue which corresponds to a given device.
+ */
+static struct request **sd_get_queue (kdev_t dev)
+{
+ return &blk_dev[MAJOR_NR].current_request;
+}
+
static void sd_finish()
{
struct gendisk *gendisk;
int i;

- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ /* FIXME: After 2.2 we should implement multiple sd queues */
+ blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST;
+ if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue;
+ }

for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next)
- if (gendisk == &sd_gendisk)
+ if (gendisk == sd_gendisks)
break;
if (gendisk == NULL)
{
- sd_gendisk.next = gendisk_head;
- gendisk_head = &sd_gendisk;
+ LAST_SD_GENDISK.next = gendisk_head;
+ gendisk_head = sd_gendisks;
}

for (i = 0; i < sd_template.dev_max; ++i)
@@ -1534,7 +1581,7 @@ static void sd_finish()
&& !rscsi_disks[i].has_part_table) {
sd_sizes[i << 4] = rscsi_disks[i].capacity;
/* revalidate does sd_init_onedisk via MAYBE_REINIT*/
- revalidate_scsidisk(MKDEV(MAJOR_NR, i << 4), 0);
+ revalidate_scsidisk(MKDEV_SD(i), 0);
}
else
i=sd_init_onedisk(i);
@@ -1542,13 +1589,17 @@ static void sd_finish()
}

/* If our host adapter is capable of scatter-gather, then we increase
- * the read-ahead to 16 blocks (32 sectors). If not, we use
- * a two block (4 sector) read ahead.
+ * the read-ahead to 60 blocks (120 sectors). If not, we use
+ * a two block (4 sector) read ahead. We can only respect this with the
+ * granularity of every 16 disks (one device major).
*/
- if(rscsi_disks[0].device && rscsi_disks[0].device->host->sg_tablesize)
- read_ahead[MAJOR_NR] = 120; /* 120 sector read-ahead */
- else
- read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
+ for (i=0; i < N_USED_SD_MAJORS; i++) {
+ read_ahead[SD_MAJOR(i)] =
+ (rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device
+ && rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device->host->sg_tablesize)
+ ? 120 /* 120 sector read-ahead */
+ : 4; /* 4 sector read-ahead */
+ }

return;
}
@@ -1586,7 +1637,7 @@ static int sd_attach(Scsi_Device * SDp){
rscsi_disks[i].device = SDp;
rscsi_disks[i].has_part_table = 0;
sd_template.nr_dev++;
- sd_gendisk.nr_real++;
+ SD_GENDISK(i).nr_real++;
return 0;
}

@@ -1594,7 +1645,6 @@ static int sd_attach(Scsi_Device * SDp){
#define USAGE rscsi_disks[target].device->access_count
#define CAPACITY rscsi_disks[target].capacity
#define MAYBE_REINIT sd_init_onedisk(target)
-#define GENDISK_STRUCT sd_gendisk

/* This routine is called to flush all partitions and partition tables
* for a changed scsi disk, and then re-read the new partition table.
@@ -1603,15 +1653,13 @@ static int sd_attach(Scsi_Device * SDp){
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
-int revalidate_scsidisk(kdev_t dev, int maxusage){
+int revalidate_scsidisk(kdev_t dev, int maxusage) {
int target;
- struct gendisk * gdev;
int max_p;
int start;
int i;

target = DEVICE_NR(dev);
- gdev = &GENDISK_STRUCT;

if (DEVICE_BUSY || USAGE > maxusage) {
printk("Device busy for revalidation (usage=%d)\n", USAGE);
@@ -1619,37 +1667,38 @@ int revalidate_scsidisk(kdev_t dev, int
}
DEVICE_BUSY = 1;

- max_p = gdev->max_p;
- start = target << gdev->minor_shift;
+ max_p = sd_gendisks->max_p;
+ start = target << sd_gendisks->minor_shift;

for (i=max_p - 1; i >=0 ; i--) {
- int minor = start+i;
- kdev_t devi = MKDEV(MAJOR_NR, minor);
+ int index = start+i;
+ kdev_t devi = MKDEV_SD_PARTITION(index);
struct super_block *sb = get_super(devi);
sync_dev(devi);
if (sb) invalidate_inodes(sb);
invalidate_buffers(devi);
- gdev->part[minor].start_sect = 0;
- gdev->part[minor].nr_sects = 0;
+ sd_gendisks->part[index].start_sect = 0;
+ sd_gendisks->part[index].nr_sects = 0;
/*
* Reset the blocksize for everything so that we can read
* the partition table. Technically we will determine the
* correct block size when we revalidate, but we do this just
* to make sure that everything remains consistent.
*/
- blksize_size[MAJOR_NR][minor] = 1024;
+ sd_blocksizes[index] = 1024;
if( rscsi_disks[target].sector_size == 2048 )
- blksize_size[MAJOR_NR][minor] = 2048;
+ sd_blocksizes[index] = 2048;
else
- blksize_size[MAJOR_NR][minor] = 1024;
+ sd_blocksizes[index] = 1024;
}

#ifdef MAYBE_REINIT
MAYBE_REINIT;
#endif

- gdev->part[start].nr_sects = CAPACITY;
- resetup_one_dev(gdev, target);
+ sd_gendisks->part[start].nr_sects = CAPACITY;
+ resetup_one_dev(&SD_GENDISK(target),
+ target % SCSI_DISKS_PER_MAJOR);

DEVICE_BUSY = 0;
return 0;
@@ -1676,15 +1725,15 @@ static void sd_detach(Scsi_Device * SDp)
start = i << sd_gendisk.minor_shift;

for (i=max_p - 1; i >=0 ; i--) {
- int minor = start+i;
- kdev_t devi = MKDEV(MAJOR_NR, minor);
+ int index = start+i;
+ kdev_t devi = MKDEV_SD_PARTITION(index);
struct super_block *sb = get_super(devi);
sync_dev(devi);
if (sb) invalidate_inodes(sb);
invalidate_buffers(devi);
- sd_gendisk.part[minor].start_sect = 0;
- sd_gendisk.part[minor].nr_sects = 0;
- sd_sizes[minor] = 0;
+ sd_gendisks->part[index].start_sect = 0;
+ sd_gendisks->part[index].nr_sects = 0;
+ sd_sizes[index] = 0;
}

dpnt->has_part_table = 0;
@@ -1693,7 +1742,7 @@ static void sd_detach(Scsi_Device * SDp)
SDp->attached--;
sd_template.dev_noticed--;
sd_template.nr_dev--;
- sd_gendisk.nr_real--;
+ SD_GENDISK(start).nr_real--;
return;
}
return;
@@ -1710,48 +1759,45 @@ void cleanup_module( void)
{
struct gendisk * prev_sdgd;
struct gendisk * sdgd;
+
+ int removed = 0;

scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
unregister_blkdev(SCSI_DISK_MAJOR, "sd");
sd_registered--;
if( rscsi_disks != NULL )
{
- scsi_init_free((char *) rscsi_disks,
- (sd_template.dev_noticed + SD_EXTRA_DEVS)
- * sizeof(Scsi_Disk));
-
+ scsi_init_free((char *) rscsi_disks,
+ sd_template.dev_max * sizeof(Scsi_Disk));
scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int));
scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int));
scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int));
scsi_init_free((char *) sd,
(sd_template.dev_max << 4) * sizeof(struct hd_struct));
/*
- * Now remove sd_gendisk from the linked list
+ * Now remove sd_gendisks from the linked list
*/
- sdgd = gendisk_head;
- prev_sdgd = NULL;
- while(sdgd != &sd_gendisk)
- {
- prev_sdgd = sdgd;
- sdgd = sdgd->next;
- }

- if(sdgd != &sd_gendisk)
- printk("sd_gendisk not in disk chain.\n");
- else {
- if(prev_sdgd != NULL)
- prev_sdgd->next = sdgd->next;
- else
- gendisk_head = sdgd->next;
- }
+ for (sdgd = gendisk_head; sdgd; sdgd = sdgd->next)
+ {
+ if (sdgd->next >= sd_gendisks && sdgd->next <= LAST_SD_GENDISK)
+ removed++, sdgd->next = sdgd->next->next;
+ else sdgd = sdgd->next;
+ }
+ if (removed != N_USED_SCSI_DISKS)
+ printk("%s %d sd_gendisks in disk chain",
+ removed > N_USED_SCSI_DISKS ? "total" : "just", removed);
+
}

- blksize_size[MAJOR_NR] = NULL;
- blk_dev[MAJOR_NR].request_fn = NULL;
- blk_size[MAJOR_NR] = NULL;
- hardsect_size[MAJOR_NR] = NULL;
- read_ahead[MAJOR_NR] = 0;
+ for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ blk_dev[SD_MAJOR(i)].request_fn = NULL;
+ blk_size[SD_MAJOR(i)] = NULL;
+ hardsect_size[SD_MAJOR(i)] = NULL;
+ read_ahead[SD_MAJOR(i)] = 0;
+ }
sd_template.dev_max = 0;
+ if (sd_gendisks != &sd_gendisk) kfree(sd_gendisks);
}
#endif /* MODULE */

--- linux/drivers/scsi/scsi.h.jj Fri Sep 4 12:55:55 1998
+++ linux/drivers/scsi/scsi.h Fri Sep 4 13:35:47 1998
@@ -684,16 +684,22 @@ static Scsi_Cmnd * end_scsi_request(Scsi
* that an interrupt may start another request, so we run this with interrupts
* turned off
*/
-#define INIT_SCSI_REQUEST \
- if (!CURRENT) { \
- CLEAR_INTR; \
- return; \
- } \
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
- panic(DEVICE_NAME ": request list destroyed");\
- if (CURRENT->bh) { \
- if (!buffer_locked(CURRENT->bh)) \
- panic(DEVICE_NAME ": block not locked"); \
+#if MAJOR_NR == SCSI_DISK0_MAJOR
+#define CHECK_INITREQ_SD_MAJOR(major) SCSI_DISK_MAJOR(major)
+#else
+#define CHECK_INITREQ_SD_MAJOR(major) ((major) == MAJOR_NR)
+#endif
+
+#define INIT_SCSI_REQUEST \
+ if (!CURRENT) { \
+ CLEAR_INTR; \
+ return; \
+ } \
+ if (!CHECK_INITREQ_SD_MAJOR(MAJOR(CURRENT->rq_dev)))\
+ panic(DEVICE_NAME ": request list destroyed"); \
+ if (CURRENT->bh) { \
+ if (!buffer_locked(CURRENT->bh)) \
+ panic(DEVICE_NAME ": block not locked"); \
}
#endif

--- linux/drivers/scsi/scsi_debug.c.jj Fri Sep 4 11:19:53 1998
+++ linux/drivers/scsi/scsi_debug.c Fri Sep 4 13:35:47 1998
@@ -43,8 +43,8 @@ struct proc_dir_entry proc_scsi_scsi_deb

/* A few options that we want selected */

-#define NR_HOSTS_PRESENT 1
-#define NR_FAKE_DISKS 3
+#define NR_HOSTS_PRESENT 20
+#define NR_FAKE_DISKS 6
#define N_HEAD 32
#define N_SECTOR 64
#define DISK_READONLY(TGT) (1)
@@ -56,6 +56,8 @@ struct proc_dir_entry proc_scsi_scsi_deb

/* Skip some consistency checking. Good for benchmarking */
#define SPEEDY
+/* Read return zeros. Undefine for benchmarking */
+#define CLEAR

/* Number of real scsi disks that will be detected ahead of time */
static int NR_REAL=-1;
@@ -300,11 +302,8 @@ int scsi_debug_queuecommand(Scsi_Cmnd *
#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
{
int delay = SCSI_SETUP_LATENCY;
- double usec;

- usec = 0.0;
- usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
- delay += usec;
+ delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
if(delay) usleep(delay);
};
#endif
@@ -324,29 +323,31 @@ int scsi_debug_queuecommand(Scsi_Cmnd *
do{
VERIFY1_DEBUG(READ);
/* For the speedy test, we do not even want to fill the buffer with anything */
-#ifndef SPEEDY
+#ifdef CLEAR
memset(buff, 0, bufflen);
#endif
/* If this is block 0, then we want to read the partition table for this
* device. Let's make one up */
- if(block == 0 && target == 0) {
+ if(block == 0) {
+ int i;
memset(buff, 0, bufflen);
*((unsigned short *) (buff+510)) = 0xAA55;
p = (struct partition* ) (buff + 0x1be);
- npart = 0;
- while(starts[npart+1]){
- p->start_sect = starts[npart];
- p->nr_sects = starts[npart+1] - starts [npart];
+ i = 0;
+ while(starts[i+1]){
+ p->start_sect = starts[i];
+ p->nr_sects = starts[i+1] - starts [i];
p->sys_ind = 0x81; /* Linux partition */
- p->head = (npart == 0 ? 1 : 0);
+ p->head = (i == 0 ? 1 : 0);
p->sector = 1;
- p->cyl = starts[npart] / N_HEAD / N_SECTOR;
+ p->cyl = starts[i] / N_HEAD / N_SECTOR;
p->end_head = N_HEAD - 1;
p->end_sector = N_SECTOR;
- p->end_cyl = starts[npart + 1] / N_HEAD / N_SECTOR;
+ p->end_cyl = starts[i + 1] / N_HEAD / N_SECTOR;
p++;
- npart++;
+ i++;
};
+ if (!npart) npart = i;
scsi_debug_errsts = 0;
break;
};
@@ -377,7 +378,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd *
} /* End phony disk change code */
#endif

-#ifndef SPEEDY
+#ifdef CLEAR
memcpy(buff, &target, sizeof(target));
memcpy(buff+sizeof(target), cmd, 24);
memcpy(buff+60, &block, sizeof(block));
@@ -385,7 +386,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd *
#endif
nbytes -= bufflen;
if(SCpnt->use_sg){
-#ifndef SPEEDY
+#ifdef CLEAR
memcpy(buff+128, bh, sizeof(struct buffer_head));
#endif
block += bufflen >> 9;
--- linux/drivers/scsi/fdomain.c.jj Fri Sep 4 11:18:00 1998
+++ linux/drivers/scsi/fdomain.c Fri Sep 4 13:35:47 1998
@@ -107,6 +107,7 @@
2.0.12 5.44 8 Aug 1996 Use ID 7 for all PCI cards
2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x
2.1.97 5.46 23 Apr 1998 Rewritten PCI detection routines [mj]
+ 2.1.11x 5.47 9 Aug 1998 Touched for 8 SCSI disk majors support



@@ -1891,7 +1892,11 @@ int fdomain_16x0_biosparam( Scsi_Disk *d
0x0a bytes long. Heads are one less than we need to report.
*/

- drive = MINOR(dev) / 16;
+ if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+ printk("fdomain_16x0_biosparam: too many disks");
+ return 0;
+ }
+ drive = MINOR(dev) >> 4;

if (bios_major == 2) {
switch (Quantum) {
--- linux/drivers/scsi/sd.h.jj Fri Sep 4 12:55:55 1998
+++ linux/drivers/scsi/sd.h Fri Sep 4 13:35:47 1998
@@ -42,6 +42,11 @@ extern Scsi_Disk * rscsi_disks;

extern int revalidate_scsidisk(kdev_t dev, int maxusage);

+#define N_SD_MAJORS 8
+
+#define SD_MAJOR_MASK (N_SD_MAJORS - 1)
+#define SD_PARTITION(i) (((MAJOR(i) & SD_MAJOR_MASK) << 8) | (MINOR(i) & 255))
+
#endif

/*
--- linux/drivers/scsi/sd_ioctl.c.jj Fri Sep 4 11:20:18 1998
+++ linux/drivers/scsi/sd_ioctl.c Fri Sep 4 13:35:47 1998
@@ -13,6 +13,7 @@

#include <asm/uaccess.h>

+#define MAJOR_NR SCSI_DISK0_MAJOR
#include <linux/blk.h>
#include "scsi.h"
#include <scsi/scsi_ioctl.h>
@@ -29,7 +30,7 @@ int sd_ioctl(struct inode * inode, struc
int diskinfo[4];
struct hd_geometry *loc = (struct hd_geometry *) arg;

- SDev = rscsi_disks[MINOR(dev) >> 4].device;
+ SDev = rscsi_disks[DEVICE_NR(dev)].device;
/*
* If we are in the middle of error recovery, don't let anyone
* else try and use this device. Also, if error recovery fails, it
@@ -47,34 +48,34 @@ int sd_ioctl(struct inode * inode, struc
error = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
if (error)
return error;
- host = rscsi_disks[MINOR(dev) >> 4].device->host;
+ host = rscsi_disks[DEVICE_NR(dev)].device->host;

/* default to most commonly used values */

diskinfo[0] = 0x40;
diskinfo[1] = 0x20;
- diskinfo[2] = rscsi_disks[MINOR(dev) >> 4].capacity >> 11;
+ diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;

/* override with calculated, extended default, or driver values */

if(host->hostt->bios_param != NULL)
- host->hostt->bios_param(&rscsi_disks[MINOR(dev) >> 4],
+ host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
dev,
&diskinfo[0]);
- else scsicam_bios_param(&rscsi_disks[MINOR(dev) >> 4],
+ else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
dev, &diskinfo[0]);

put_user(diskinfo[0], &loc->heads);
put_user(diskinfo[1], &loc->sectors);
put_user(diskinfo[2], &loc->cylinders);
- put_user(sd[MINOR(inode->i_rdev)].start_sect, &loc->start);
+ put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start);
return 0;
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (error)
return error;
- put_user(sd[MINOR(inode->i_rdev)].nr_sects,
+ put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects,
(long *) arg);
return 0;

@@ -110,7 +111,7 @@ int sd_ioctl(struct inode * inode, struc
RO_IOCTLS(dev, arg);

default:
- return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg);
+ return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
}
}

--- linux/include/linux/blk.h.jj Fri Sep 4 12:43:59 1998
+++ linux/include/linux/blk.h Fri Sep 4 13:35:47 1998
@@ -147,13 +147,13 @@ static void floppy_off(unsigned int nr);
#define DEVICE_ON(device)
#define DEVICE_OFF(device)

-#elif (MAJOR_NR == SCSI_DISK_MAJOR)
+#elif (SCSI_DISK_MAJOR(MAJOR_NR))

#define DEVICE_NAME "scsidisk"
#define DEVICE_INTR do_sd
#define TIMEOUT_VALUE (2*HZ)
#define DEVICE_REQUEST do_sd_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)

--- linux/include/linux/major.h.jj Fri Sep 4 11:59:02 1998
+++ linux/include/linux/major.h Fri Sep 4 13:40:22 1998
@@ -28,7 +28,7 @@
#define LP_MAJOR 6
#define VCS_MAJOR 7
#define LOOP_MAJOR 7
-#define SCSI_DISK_MAJOR 8
+#define SCSI_DISK0_MAJOR 8
#define SCSI_TAPE_MAJOR 9
#define MD_MAJOR 9
#define MISC_MAJOR 10
@@ -81,6 +81,14 @@
#define IDE4_MAJOR 56
#define IDE5_MAJOR 57

+#define SCSI_DISK1_MAJOR 65
+#define SCSI_DISK2_MAJOR 66
+#define SCSI_DISK3_MAJOR 67
+#define SCSI_DISK4_MAJOR 68
+#define SCSI_DISK5_MAJOR 69
+#define SCSI_DISK6_MAJOR 70
+#define SCSI_DISK7_MAJOR 71
+
#define SPECIALIX_NORMAL_MAJOR 75
#define SPECIALIX_CALLOUT_MAJOR 76

@@ -92,8 +100,11 @@
* Tests for SCSI devices.
*/

+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+ ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+
#define SCSI_BLK_MAJOR(M) \
- ((M) == SCSI_DISK_MAJOR \
+ (SCSI_DISK_MAJOR(M) \
|| (M) == SCSI_CDROM_MAJOR)

static __inline__ int scsi_blk_major(int m) {

Cheers,
Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
Ultralinux - first 64bit OS to take full power of the UltraSparc
Linux version 2.1.119 on a sparc64 machine (498.80 BogoMips).
___________________________________________________________________

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html