Re: [PATCH][RFC] Driverfs support for SCSI devices (updated)

sullivan (sullivan@austin.ibm.com)
Tue, 18 Jun 2002 16:56:39 -0500


--2oS5YaxWCcQjTEyO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Jun 17, 2002 at 06:16:53PM -0500, James Bottomley wrote:
> I get a BUG in device.h:213 trying to insert the st.o module, but other than
> that, it seems to be running OK.

Thanks James. Attached is an updated patch that fixes the st.o module and incorporates your other suggestions. The updated patch is also available at
http://www-124.ibm.com/devreg/linux-2.5.22-driverfs.patch.gz

--2oS5YaxWCcQjTEyO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="linux-2.5.22-driverfs.patch"

diff -Naur linux-2.5.22.orig/drivers/cdrom/cdrom.c linux-2.5.22-driverfs/drivers/cdrom/cdrom.c
--- linux-2.5.22.orig/drivers/cdrom/cdrom.c Sun Jun 16 21:31:26 2002
+++ linux-2.5.22-driverfs/drivers/cdrom/cdrom.c Mon Jun 17 21:14:07 2002
@@ -431,6 +431,11 @@
topCdromPtr = cdi->next;
cdi->ops->n_minors--;
devfs_unregister (cdi->de);
+ if (atomic_read (&cdi->cdrom_driverfs_dev.refcount)) {
+ device_remove_file (&cdi->cdrom_driverfs_dev, "name");
+ device_remove_file (&cdi->cdrom_driverfs_dev, "kdev");
+ put_device (&cdi->cdrom_driverfs_dev);
+ }
devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
return 0;
diff -Naur linux-2.5.22.orig/drivers/scsi/hosts.h linux-2.5.22-driverfs/drivers/scsi/hosts.h
--- linux-2.5.22.orig/drivers/scsi/hosts.h Sun Jun 16 21:31:29 2002
+++ linux-2.5.22-driverfs/drivers/scsi/hosts.h Mon Jun 17 21:14:07 2002
@@ -418,6 +418,11 @@
*/
struct pci_dev *pci_dev;

+ /*
+ * Support for driverfs filesystem
+ */
+ struct device host_driverfs_dev;
+
/*
* We should ensure that this is aligned, both for better performance
* and also because some compilers (m68k) don't automatically force
@@ -478,6 +483,7 @@
struct pci_dev *pdev)
{
SHpnt->pci_dev = pdev;
+ SHpnt->host_driverfs_dev.parent=&pdev->dev;
}


@@ -516,6 +522,7 @@
void (*detach)(Scsi_Device *);
int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code.
Selects command for blkdevs */
+ struct device_driver scsi_driverfs_driver;
};

void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi.c linux-2.5.22-driverfs/drivers/scsi/scsi.c
--- linux-2.5.22.orig/drivers/scsi/scsi.c Sun Jun 16 21:31:33 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi.c Tue Jun 18 21:15:19 2002
@@ -1939,6 +1939,11 @@
}
printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */
shpnt->host_no, name);
+ strncpy(shpnt->host_driverfs_dev.name,name,
+ DEVICE_NAME_SIZE-1);
+ sprintf(shpnt->host_driverfs_dev.bus_id,
+ "scsi%d",
+ shpnt->host_no);
}
}

@@ -1947,6 +1952,8 @@
*/
for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
if (shpnt->hostt == tpnt) {
+ /* first register parent with driverfs */
+ device_register(&shpnt->host_driverfs_dev);
scan_scsis(shpnt, 0, 0, 0, 0);
if (shpnt->select_queue_depths != NULL) {
(shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
@@ -2101,6 +2108,7 @@
goto err_out;
}
devfs_unregister (SDpnt->de);
+ put_device(&SDpnt->sdev_driverfs_dev);
}
}

@@ -2151,6 +2159,7 @@
/* Remove the /proc/scsi directory entry */
sprintf(name,"%d",shpnt->host_no);
remove_proc_entry(name, tpnt->proc_dir);
+ put_device(&shpnt->host_driverfs_dev);
if (tpnt->release)
(*tpnt->release) (shpnt);
else {
@@ -2499,6 +2508,34 @@
mempool_free(sgl, sgp->pool);
}

+static int scsi_bus_match(struct device *scsi_driverfs_dev,
+ struct device_driver *scsi_driverfs_drv)
+{
+ char *p=0;
+
+ if (!strcmp("sd", scsi_driverfs_drv->name)) {
+ if ((p = strstr(scsi_driverfs_dev->bus_id, ":disc")) ||
+ (p = strstr(scsi_driverfs_dev->bus_id, ":p"))) {
+ return 1;
+ }
+ } else if (!strcmp("sg", scsi_driverfs_drv->name)) {
+ if (strstr(scsi_driverfs_dev->bus_id, ":gen"))
+ return 1;
+ } else if (!strcmp("sr",scsi_driverfs_drv->name)) {
+ if (strstr(scsi_driverfs_dev->bus_id,":cd"))
+ return 1;
+ } else if (!strcmp("st",scsi_driverfs_drv->name)) {
+ if (strstr(scsi_driverfs_dev->bus_id,":mt"))
+ return 1;
+ }
+ return 0;
+}
+
+struct bus_type scsi_driverfs_bus_type = {
+ name: "scsi",
+ match: scsi_bus_match,
+};
+
static int __init init_scsi(void)
{
struct proc_dir_entry *generic;
@@ -2544,6 +2581,8 @@
if (scsihosts)
printk(KERN_INFO "scsi: host order: %s\n", scsihosts);
scsi_host_no_init (scsihosts);
+
+ bus_register(&scsi_driverfs_bus_type);
/*
* This is where the processing takes place for most everything
* when commands are completed.
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi.h linux-2.5.22-driverfs/drivers/scsi/scsi.h
--- linux-2.5.22.orig/drivers/scsi/scsi.h Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi.h Tue Jun 18 18:10:20 2002
@@ -417,6 +417,8 @@
extern volatile int in_scan_scsis;
extern const unsigned char scsi_command_size[8];

+extern struct bus_type scsi_driverfs_bus_type;
+

/*
* These are the error handling functions defined in scsi_error.c
@@ -622,6 +624,7 @@

// Flag to allow revalidate to succeed in sd_open
int allow_revalidate;
+ struct device sdev_driverfs_dev;
};


diff -Naur linux-2.5.22.orig/drivers/scsi/scsi_scan.c linux-2.5.22-driverfs/drivers/scsi/scsi_scan.c
--- linux-2.5.22.orig/drivers/scsi/scsi_scan.c Sun Jun 16 21:31:35 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi_scan.c Tue Jun 18 18:21:26 2002
@@ -54,6 +54,7 @@
char *scsi_result);
static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
struct Scsi_Host *shpnt);
+static void scsi_load_identifier(Scsi_Device *SDpnt, Scsi_Request * SRpnt);

struct dev_info {
const char *vendor;
@@ -288,6 +289,31 @@
}
#endif

+/* Driverfs file content handlers */
+static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page,
+ size_t count, loff_t off)
+{
+ struct scsi_device *SDpnt = list_entry(driverfs_dev,
+ struct scsi_device, sdev_driverfs_dev);
+
+ if ((SDpnt->type <= MAX_SCSI_DEVICE_CODE) &&
+ (scsi_device_types[(int)SDpnt->type] != NULL))
+ return off ? 0 :
+ sprintf(page, "%s\n",
+ scsi_device_types[(int)SDpnt->type]);
+ else
+ return off ? 0 : sprintf(page, "UNKNOWN\n");
+
+ return 0;
+}
+
+static struct driver_file_entry scsi_device_type_file = {
+ name: "type",
+ mode: S_IRUGO,
+ show: scsi_device_type_read,
+};
+/* end content handlers */
+
static void print_inquiry(unsigned char *data)
{
int i;
@@ -786,6 +812,22 @@

print_inquiry(scsi_result);

+ /* interrogate scsi target to provide device identifier */
+ scsi_load_identifier(SDpnt, SRpnt);
+
+ /* create driverfs files */
+ sprintf(SDpnt->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
+ SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun);
+
+ SDpnt->sdev_driverfs_dev.parent = &SDpnt->host->host_driverfs_dev;
+ SDpnt->sdev_driverfs_dev.bus = &scsi_driverfs_bus_type;
+
+ device_register(&SDpnt->sdev_driverfs_dev);
+
+ /* Create driverfs file entries */
+ device_create_file(&SDpnt->sdev_driverfs_dev,
+ &scsi_device_type_file);
+
sprintf (devname, "host%d/bus%d/target%d/lun%d",
SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun);
if (SDpnt->de) printk ("DEBUG: dir: \"%s\" already exists\n", devname);
@@ -1306,3 +1348,374 @@
/* haven't found lun0, should send INQUIRY but take easy route */
return res;
}
+
+#define SCSI_UID_DEV_ID 'U'
+#define SCSI_UID_SER_NUM 'S'
+#define SCSI_UID_UNKNOWN 'Z'
+
+unsigned char *scsi_get_evpd_page(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+ unsigned char *evpd_page = NULL;
+ unsigned char *scsi_cmd = NULL;
+ int lun = SDpnt->lun;
+ int scsi_level = SDpnt->scsi_level;
+
+ evpd_page = kmalloc(255,
+ (SDpnt->host->unchecked_isa_dma ? GFP_DMA : GFP_ATOMIC));
+ if (!evpd_page)
+ return NULL;
+
+ scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+ if (!scsi_cmd) {
+ kfree(evpd_page);
+ return NULL;
+ }
+
+ /* Use vital product pages to determine serial number */
+ /* Try Supported vital product data pages 0x00 first */
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x00;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = 255;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) evpd_page,
+ 255, SCSI_TIMEOUT+4*HZ, 3);
+
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ kfree(evpd_page);
+ return NULL;
+ }
+
+ /* check to see if response was truncated */
+ if (evpd_page[3] > 255) {
+ int max_lgth = evpd_page[3] + 4;
+
+ kfree(evpd_page);
+ evpd_page = kmalloc(max_lgth, (SDpnt->host->unchecked_isa_dma ?
+ GFP_DMA : GFP_ATOMIC));
+ if (!evpd_page) {
+ kfree(scsi_cmd);
+ return NULL;
+ }
+ memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x00;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = max_lgth;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) evpd_page,
+ max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ kfree(evpd_page);
+ return NULL;
+ }
+ }
+ kfree(scsi_cmd);
+ /* some ill behaved devices return the std inquiry here rather than
+ the evpd data. snoop the data to verify */
+ if (evpd_page[3] > 16) {
+ /* if vend id appears in the evpd page assume evpd is invalid */
+ if (!strncmp(&evpd_page[8], SDpnt->vendor, 8)) {
+ kfree(evpd_page);
+ return NULL;
+ }
+ }
+ return evpd_page;
+}
+
+int scsi_get_deviceid(Scsi_Device *SDpnt,Scsi_Request * SRpnt)
+{
+ unsigned char *id_page = NULL;
+ unsigned char *scsi_cmd = NULL;
+ int scnt, i, j, idtype;
+ char * id = SDpnt->sdev_driverfs_dev.name;
+ int lun = SDpnt->lun;
+ int scsi_level = SDpnt->scsi_level;
+
+ id_page = kmalloc(255,
+ (SDpnt->host->unchecked_isa_dma ? GFP_DMA : GFP_ATOMIC));
+ if (!id_page)
+ return 0;
+
+ scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+ if (!scsi_cmd)
+ goto leave;
+
+ /* Use vital product pages to determine serial number */
+ /* Try Supported vital product data pages 0x00 first */
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x83;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = 255;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) id_page,
+ 255, SCSI_TIMEOUT+4*HZ, 3);
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ goto leave;
+ }
+
+ /* check to see if response was truncated */
+ if (id_page[3] > 255) {
+ int max_lgth = id_page[3] + 4;
+
+ kfree(id_page);
+ id_page = kmalloc(max_lgth,
+ (SDpnt->host->unchecked_isa_dma ?
+ GFP_DMA : GFP_ATOMIC));
+ if (!id_page) {
+ kfree(scsi_cmd);
+ return 0;
+ }
+ memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x83;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = max_lgth;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) id_page,
+ max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ goto leave;
+ }
+ }
+ kfree(scsi_cmd);
+
+ idtype = 3;
+ while (idtype > 0) {
+ for(scnt = 4; scnt <= id_page[3] + 3;
+ scnt += id_page[scnt + 3] + 4) {
+ if ((id_page[scnt + 1] & 0x0f) != idtype) {
+ continue;
+ }
+ if ((id_page[scnt] & 0x0f) == 2) {
+ for(i = scnt + 4, j = 1;
+ i < scnt + 4 + id_page[scnt + 3];
+ i++) {
+ if (id_page[i] > 0x20) {
+ if (j == DEVICE_NAME_SIZE) {
+ memset(id, 0,
+ DEVICE_NAME_SIZE);
+ break;
+ }
+ id[j++] = id_page[i];
+ }
+ }
+ } else if ((id_page[scnt] & 0x0f) == 1) {
+ static const char hex_str[]="0123456789abcdef";
+ for(i = scnt + 4, j = 1;
+ i < scnt + 4 + id_page[scnt + 3];
+ i++) {
+ if ((j + 1) == DEVICE_NAME_SIZE) {
+ memset(id, 0, DEVICE_NAME_SIZE);
+ break;
+ }
+ id[j++] = hex_str[(id_page[i] & 0xf0) >>
+ 4];
+ id[j++] = hex_str[id_page[i] & 0x0f];
+ }
+ }
+ if (id[1] != 0) goto leave;
+ }
+ idtype--;
+ }
+ leave:
+ kfree(id_page);
+ if (id[1] != 0) {
+ id[0] = SCSI_UID_DEV_ID;
+ return 1;
+ }
+ return 0;
+}
+
+int scsi_get_serialnumber(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+ unsigned char *serialnumber_page = NULL;
+ unsigned char *scsi_cmd = NULL;
+ int lun = SDpnt->lun;
+ int scsi_level = SDpnt->scsi_level;
+ int i, j;
+
+ serialnumber_page = kmalloc(255, (SDpnt->host->unchecked_isa_dma ?
+ GFP_DMA : GFP_ATOMIC));
+ if (!serialnumber_page)
+ return 0;
+
+ scsi_cmd = kmalloc(MAX_COMMAND_SIZE, GFP_ATOMIC);
+ if (!scsi_cmd)
+ goto leave;
+
+ /* Use vital product pages to determine serial number */
+ /* Try Supported vital product data pages 0x00 first */
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x80;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = 255;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd, (void *) serialnumber_page,
+ 255, SCSI_TIMEOUT+4*HZ, 3);
+
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ goto leave;
+ }
+ /* check to see if response was truncated */
+ if (serialnumber_page[3] > 255) {
+ int max_lgth = serialnumber_page[3] + 4;
+
+ kfree(serialnumber_page);
+ serialnumber_page = kmalloc(max_lgth,
+ (SDpnt->host->unchecked_isa_dma ?
+ GFP_DMA : GFP_ATOMIC));
+ if (!serialnumber_page) {
+ kfree(scsi_cmd);
+ return 0;
+ }
+ memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
+ scsi_cmd[0] = INQUIRY;
+ if ((lun > 0) && (scsi_level <= SCSI_2))
+ scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
+ else
+ scsi_cmd[1] = 0x01; /* SCSI_3 and higher, don't touch */
+ scsi_cmd[2] = 0x80;
+ scsi_cmd[3] = 0;
+ scsi_cmd[4] = max_lgth;
+ scsi_cmd[5] = 0;
+ SRpnt->sr_cmd_len = 0;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ scsi_wait_req(SRpnt, (void *) scsi_cmd,
+ (void *) serialnumber_page,
+ max_lgth, SCSI_TIMEOUT+4*HZ, 3);
+ if (SRpnt->sr_result) {
+ kfree(scsi_cmd);
+ goto leave;
+ }
+ }
+ kfree(scsi_cmd);
+
+ SDpnt->sdev_driverfs_dev.name[0] = SCSI_UID_SER_NUM;
+ for(i = 0, j = 1; i < serialnumber_page[3]; i++) {
+ if (serialnumber_page[4 + i] > 0x20)
+ SDpnt->sdev_driverfs_dev.name[j++] =
+ serialnumber_page[4 + i];
+ }
+ for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name); i < 8; i++) {
+ if (SDpnt->vendor[i] > 0x20) {
+ SDpnt->sdev_driverfs_dev.name[j++] = SDpnt->vendor[i];
+ }
+ }
+ kfree(serialnumber_page);
+ return 1;
+ leave:
+ memset(SDpnt->sdev_driverfs_dev.name, 0, DEVICE_NAME_SIZE);
+ kfree(serialnumber_page);
+ return 0;
+}
+
+int scsi_get_default_name(Scsi_Device *SDpnt)
+{
+ int i, j;
+
+ SDpnt->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN;
+ for(i = 0, j = 1; i < 8; i++) {
+ if (SDpnt->vendor[i] > 0x20) {
+ SDpnt->sdev_driverfs_dev.name[j++] =
+ SDpnt->vendor[i];
+ }
+ }
+ for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name);
+ i < 16; i++) {
+ if (SDpnt->model[i] > 0x20) {
+ SDpnt->sdev_driverfs_dev.name[j++] =
+ SDpnt->model[i];
+ }
+ }
+ for(i = 0, j = strlen(SDpnt->sdev_driverfs_dev.name); i < 4; i++) {
+ if (SDpnt->rev[i] > 0x20) {
+ SDpnt->sdev_driverfs_dev.name[j++] = SDpnt->rev[i];
+ }
+ }
+ return 1;
+}
+
+
+static void scsi_load_identifier(Scsi_Device *SDpnt, Scsi_Request * SRpnt)
+{
+ unsigned char *evpd_page = NULL;
+ int cnt;
+
+ memset(SDpnt->sdev_driverfs_dev.name, 0, DEVICE_NAME_SIZE);
+ evpd_page = scsi_get_evpd_page(SDpnt, SRpnt);
+ if (!evpd_page) {
+ /* try to obtain serial number anyway */
+ if (!scsi_get_serialnumber(SDpnt, SRpnt))
+ goto leave;
+ goto leave;
+ }
+
+ for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) {
+ if (evpd_page[cnt] == 0x83) {
+ if (scsi_get_deviceid(SDpnt, SRpnt))
+ goto leave;
+ }
+ }
+
+ for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) {
+ if (evpd_page[cnt] == 0x80) {
+ if (scsi_get_serialnumber(SDpnt, SRpnt))
+ goto leave;
+ }
+ }
+
+leave:
+ if (SDpnt->sdev_driverfs_dev.name[0] == 0)
+ scsi_get_default_name(SDpnt);
+
+ if (evpd_page) kfree(evpd_page);
+ return;
+}
diff -Naur linux-2.5.22.orig/drivers/scsi/scsi_syms.c linux-2.5.22-driverfs/drivers/scsi/scsi_syms.c
--- linux-2.5.22.orig/drivers/scsi/scsi_syms.c Sun Jun 16 21:31:32 2002
+++ linux-2.5.22-driverfs/drivers/scsi/scsi_syms.c Tue Jun 18 21:13:34 2002
@@ -101,3 +101,8 @@
extern int scsi_delete_timer(Scsi_Cmnd *);
EXPORT_SYMBOL(scsi_add_timer);
EXPORT_SYMBOL(scsi_delete_timer);
+
+/*
+ * driverfs support for determining driver types
+ */
+EXPORT_SYMBOL(scsi_driverfs_bus_type);
diff -Naur linux-2.5.22.orig/drivers/scsi/sd.c linux-2.5.22-driverfs/drivers/scsi/sd.c
--- linux-2.5.22.orig/drivers/scsi/sd.c Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sd.c Tue Jun 18 22:45:19 2002
@@ -128,6 +128,7 @@

static Scsi_Disk * sd_get_sdisk(int index);

+extern void driverfs_remove_partitions(struct gendisk *hd, int minor);

#if defined(CONFIG_PPC32)
/**
@@ -1276,12 +1277,15 @@

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)
+ 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";
@@ -1290,7 +1294,6 @@
sd_gendisks[k].sizes = sd_sizes + k * (N << 4);
sd_gendisks[k].nr_real = 0;
}
-
return 0;

#undef init_mem_lth
@@ -1301,6 +1304,7 @@
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);
@@ -1435,6 +1439,8 @@
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;
if (sdp->removable)
SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
sd_dskname(dsk_nr, diskname);
@@ -1534,6 +1540,8 @@
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);
for (j = max_p - 1; j >= 0; j--)
sd_sizes[start + j] = 0;
@@ -1555,9 +1563,16 @@
**/
static int __init init_sd(void)
{
+ int rc;
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
sd_template.module = THIS_MODULE;
- return scsi_register_device(&sd_template);
+ rc = scsi_register_device(&sd_template);
+ if (!rc) {
+ sd_template.scsi_driverfs_driver.name = (char *)sd_template.tag;
+ sd_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+ driver_register(&sd_template.scsi_driverfs_driver);
+ }
+ return rc;
}

/**
@@ -1590,6 +1605,7 @@
sd_template.dev_max = 0;
if (sd_gendisks != &sd_gendisk)
vfree(sd_gendisks);
+ remove_driver(&sd_template.scsi_driverfs_driver);
}

static Scsi_Disk * sd_get_sdisk(int index)
diff -Naur linux-2.5.22.orig/drivers/scsi/sg.c linux-2.5.22-driverfs/drivers/scsi/sg.c
--- linux-2.5.22.orig/drivers/scsi/sg.c Sun Jun 16 21:31:31 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sg.c Tue Jun 18 22:43:06 2002
@@ -194,6 +194,7 @@
volatile char detached; /* 0->attached, 1->detached pending removal */
volatile char exclude; /* opened for exclusive access */
char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
+ struct device sg_driverfs_dev;
} Sg_device; /* 36 bytes long on i386 */


@@ -1370,6 +1371,29 @@
__setup("sg_def_reserved_size=", sg_def_reserved_size_setup);
#endif

+/* Driverfs file support */
+static ssize_t sg_device_kdev_read(struct device *driverfs_dev, char *page,
+ size_t count, loff_t off)
+{
+ Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
+ return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value);
+}
+static struct driver_file_entry sg_device_kdev_file = {
+ name: "kdev",
+ mode: S_IRUGO,
+ show: sg_device_kdev_read,
+};
+
+static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page,
+ size_t count, loff_t off)
+{
+ return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry sg_device_type_file = {
+ name: "type",
+ mode: S_IRUGO,
+ show: sg_device_type_read,
+};

static int sg_attach(Scsi_Device * scsidp)
{
@@ -1428,6 +1452,18 @@
sdp->detached = 0;
sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
+
+ memset(&sdp->sg_driverfs_dev, 0, sizeof(struct device));
+ sprintf(sdp->sg_driverfs_dev.bus_id, "%s:gen",
+ scsidp->sdev_driverfs_dev.bus_id);
+ sprintf(sdp->sg_driverfs_dev.name, "%sgeneric",
+ scsidp->sdev_driverfs_dev.name);
+ sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
+ sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type;
+ device_register(&sdp->sg_driverfs_dev);
+ device_create_file(&sdp->sg_driverfs_dev, &sg_device_type_file);
+ device_create_file(&sdp->sg_driverfs_dev, &sg_device_kdev_file);
+
sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
SCSI_GENERIC_MAJOR, k,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
@@ -1496,6 +1532,9 @@
}
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k));
devfs_unregister (sdp->de);
+ device_remove_file(&sdp->sg_driverfs_dev,sg_device_type_file.name);
+ device_remove_file(&sdp->sg_driverfs_dev,sg_device_kdev_file.name);
+ put_device(&sdp->sg_driverfs_dev);
sdp->de = NULL;
if (NULL == sdp->headfp) {
kfree((char *)sdp);
@@ -1505,6 +1544,7 @@
else { /* nothing active, simple case */
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
devfs_unregister (sdp->de);
+ put_device(&sdp->sg_driverfs_dev);
kfree((char *)sdp);
sg_dev_arr[k] = NULL;
}
@@ -1529,9 +1569,16 @@
MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");

static int __init init_sg(void) {
+ int rc;
if (def_reserved_size >= 0)
sg_big_buff = def_reserved_size;
- return scsi_register_device(&sg_template);
+ rc = scsi_register_device(&sg_template);
+ if (!rc) {
+ sg_template.scsi_driverfs_driver.name = (char *)sg_template.tag;
+ sg_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+ driver_register(&sg_template.scsi_driverfs_driver);
+ }
+ return rc;
}

static void __exit exit_sg( void)
@@ -1546,6 +1593,7 @@
sg_dev_arr = NULL;
}
sg_template.dev_max = 0;
+ remove_driver(&sg_template.scsi_driverfs_driver);
}


diff -Naur linux-2.5.22.orig/drivers/scsi/sr.c linux-2.5.22-driverfs/drivers/scsi/sr.c
--- linux-2.5.22.orig/drivers/scsi/sr.c Sun Jun 16 21:31:27 2002
+++ linux-2.5.22-driverfs/drivers/scsi/sr.c Tue Jun 18 22:44:21 2002
@@ -730,6 +730,32 @@
return 1;
}

+/* Driverfs file support */
+static ssize_t sr_device_kdev_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ kdev_t kdev;
+ kdev.value=(int)driverfs_dev->driver_data;
+ return off ? 0 : sprintf(page, "%x\n",kdev.value);
+}
+static struct driver_file_entry sr_device_kdev_file = {
+ name: "kdev",
+ mode: S_IRUGO,
+ show: sr_device_kdev_read,
+};
+
+static ssize_t sr_device_type_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry sr_device_type_file = {
+ name: "type",
+ mode: S_IRUGO,
+ show: sr_device_type_read,
+};
+
+
void sr_finish()
{
int i;
@@ -775,6 +801,20 @@

sprintf(name, "sr%d", i);
strcpy(SCp->cdi.name, name);
+ sprintf(SCp->cdi.cdrom_driverfs_dev.bus_id, "%s:cd",
+ SCp->device->sdev_driverfs_dev.bus_id);
+ sprintf(SCp->cdi.cdrom_driverfs_dev.name, "%scdrom",
+ SCp->device->sdev_driverfs_dev.name);
+ SCp->cdi.cdrom_driverfs_dev.parent =
+ &SCp->device->sdev_driverfs_dev;
+ SCp->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type;
+ SCp->cdi.cdrom_driverfs_dev.driver_data =
+ (void *)__mkdev(MAJOR_NR, i);
+ device_register(&SCp->cdi.cdrom_driverfs_dev);
+ device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+ &sr_device_type_file);
+ device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+ &sr_device_kdev_file);
SCp->cdi.de = devfs_register(SCp->device->de, "cd",
DEVFS_FL_DEFAULT, MAJOR_NR, i,
S_IFBLK | S_IRUGO | S_IWUGO,
@@ -815,7 +855,14 @@

static int __init init_sr(void)
{
- return scsi_register_device(&sr_template);
+ int rc;
+ rc = scsi_register_device(&sr_template);
+ if (!rc) {
+ sr_template.scsi_driverfs_driver.name = (char *)sr_template.tag;
+ sr_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
+ driver_register(&sr_template.scsi_driverfs_driver);
+ }
+ return rc;
}

static void __exit exit_sr(void)
@@ -832,6 +879,7 @@
blk_clear(MAJOR_NR);

sr_template.dev_max = 0;
+ remove_driver(&sr_template.scsi_driverfs_driver);
}

module_init(init_sr);
diff -Naur linux-2.5.22.orig/drivers/scsi/st.c linux-2.5.22-driverfs/drivers/scsi/st.c
--- linux-2.5.22.orig/drivers/scsi/st.c Sun Jun 16 21:31:34 2002
+++ linux-2.5.22-driverfs/drivers/scsi/st.c Tue Jun 18 18:09:33 2002
@@ -3677,6 +3677,31 @@

#endif

+/* Driverfs file support */
+static ssize_t st_device_kdev_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ kdev_t kdev;
+ kdev.value=(int)driverfs_dev->driver_data;
+ return off ? 0 : sprintf(page, "%x\n",kdev.value);
+}
+static struct driver_file_entry st_device_kdev_file = {
+ name: "kdev",
+ mode: S_IRUGO,
+ show: st_device_kdev_read,
+};
+
+static ssize_t st_device_type_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ return off ? 0 : sprintf (page, "CHR\n");
+}
+static struct driver_file_entry st_device_type_file = {
+ name: "type",
+ mode: S_IRUGO,
+ show: st_device_type_read,
+};
+

static struct file_operations st_fops =
{
@@ -3779,6 +3804,18 @@

/* Rewind entry */
sprintf (name, "mt%s", formats[mode]);
+ sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s",
+ SDp->sdev_driverfs_dev.name, name);
+ sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s",
+ SDp->sdev_driverfs_dev.name, name);
+ tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
+ tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type;
+ tpnt->driverfs_dev_r[mode].driver_data =
+ (void *)__mkdev(MAJOR_NR, i + (mode << 5));
+ device_register(&tpnt->driverfs_dev_r[mode]);
+ device_create_file(&tpnt->driverfs_dev_r[mode],
+ &st_device_type_file);
+ device_create_file(&tpnt->driverfs_dev_r[mode], &st_device_kdev_file);
tpnt->de_r[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, i + (mode << 5),
@@ -3786,6 +3823,19 @@
&st_fops, NULL);
/* No-rewind entry */
sprintf (name, "mt%sn", formats[mode]);
+ sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s",
+ SDp->sdev_driverfs_dev.name, name);
+ sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s",
+ SDp->sdev_driverfs_dev.name, name);
+ tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
+ tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type;
+ tpnt->driverfs_dev_n[mode].driver_data =
+ (void *)__mkdev(MAJOR_NR, i + (mode << 5) + 128);
+ device_register(&tpnt->driverfs_dev_n[mode]);
+ device_create_file(&tpnt->driverfs_dev_n[mode],
+ &st_device_type_file);
+ device_create_file(&tpnt->driverfs_dev_n[mode],
+ &st_device_kdev_file);
tpnt->de_n[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, i + (mode << 5) + 128,
@@ -3894,8 +3944,18 @@
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_unregister (tpnt->de_r[mode]);
tpnt->de_r[mode] = NULL;
+ device_remove_file(&tpnt->driverfs_dev_r[mode],
+ st_device_type_file.name);
+ device_remove_file(&tpnt->driverfs_dev_r[mode],
+ st_device_kdev_file.name);
+ put_device(&tpnt->driverfs_dev_r[mode]);
devfs_unregister (tpnt->de_n[mode]);
tpnt->de_n[mode] = NULL;
+ device_remove_file(&tpnt->driverfs_dev_n[mode],
+ st_device_type_file.name);
+ device_remove_file(&tpnt->driverfs_dev_n[mode],
+ st_device_kdev_file.name);
+ put_device(&tpnt->driverfs_dev_n[mode]);
}
kfree(tpnt);
scsi_tapes[i] = 0;
@@ -3921,8 +3981,16 @@
verstr, st_buffer_size, st_write_threshold,
st_max_buffers, st_max_sg_segs);

- if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0)
- return scsi_register_device(&st_template);
+ if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
+ if (scsi_register_device(&st_template) == 0) {
+ st_template.scsi_driverfs_driver.name =
+ (char *)st_template.tag;
+ st_template.scsi_driverfs_driver.bus =
+ &scsi_driverfs_bus_type;
+ driver_register(&st_template.scsi_driverfs_driver);
+ return 0;
+ }
+ }

printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR);
return 1;
@@ -3951,6 +4019,7 @@
}
}
st_template.dev_max = 0;
+ remove_driver(&st_template.scsi_driverfs_driver);
printk(KERN_INFO "st: Unloaded.\n");
}

diff -Naur linux-2.5.22.orig/drivers/scsi/st.h linux-2.5.22-driverfs/drivers/scsi/st.h
--- linux-2.5.22.orig/drivers/scsi/st.h Sun Jun 16 21:31:28 2002
+++ linux-2.5.22-driverfs/drivers/scsi/st.h Mon Jun 17 21:14:07 2002
@@ -94,6 +94,8 @@
int current_mode;
devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */
devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */
+ struct device driverfs_dev_r[ST_NBR_MODES];
+ struct device driverfs_dev_n[ST_NBR_MODES];

/* Status variables */
int partition;
diff -Naur linux-2.5.22.orig/fs/partitions/check.c linux-2.5.22-driverfs/fs/partitions/check.c
--- linux-2.5.22.orig/fs/partitions/check.c Sun Jun 16 21:31:30 2002
+++ linux-2.5.22-driverfs/fs/partitions/check.c Mon Jun 17 21:14:07 2002
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/raid/md.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
+#include <linux/kmod.h>

#include "check.h"

@@ -221,6 +222,136 @@
#endif
}

+/* Driverfs file support */
+static ssize_t partition_device_kdev_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ kdev_t kdev;
+ kdev.value=(int)driverfs_dev->driver_data;
+ return off ? 0 : sprintf (page, "%x\n",kdev.value);
+}
+static struct driver_file_entry partition_device_kdev_file = {
+ name: "kdev",
+ mode: S_IRUGO,
+ show: partition_device_kdev_read,
+};
+
+static ssize_t partition_device_type_read(struct device *driverfs_dev,
+ char *page, size_t count, loff_t off)
+{
+ return off ? 0 : sprintf (page, "BLK\n");
+}
+static struct driver_file_entry partition_device_type_file = {
+ name: "type",
+ mode: S_IRUGO,
+ show: partition_device_type_read,
+};
+
+void driverfs_create_partitions(struct gendisk *hd, int minor)
+{
+ int pos = -1;
+ int devnum = minor >> hd->minor_shift;
+ char dirname[256];
+ struct device *parent = 0;
+ int max_p;
+ int part;
+ devfs_handle_t dir = 0;
+
+ /* get parent driverfs device structure */
+ if (hd->driverfs_dev_arr)
+ parent = hd->driverfs_dev_arr[devnum];
+ else /* if driverfs not supported by subsystem, skip partitions */
+ return;
+
+ /* get parent device node directory name */
+ if (hd->de_arr) {
+ dir = hd->de_arr[devnum];
+ if (dir)
+ pos = devfs_generate_path (dir, dirname,
+ sizeof dirname);
+ }
+
+ if (pos < 0) {
+ disk_name(hd, minor, dirname);
+ pos = 0;
+ }
+
+ max_p = (1 << hd->minor_shift);
+
+ /* for all partitions setup parents and device node names */
+ for(part=0; part < max_p; part++) {
+ if ((part == 0) || (hd->part[minor + part].nr_sects >= 1)) {
+ struct device * current_driverfs_dev =
+ &hd->part[minor+part].hd_driverfs_dev;
+ current_driverfs_dev->parent = parent;
+ /* handle disc case */
+ current_driverfs_dev->driver_data =
+ (void *)__mkdev(hd->major, minor+part);
+ if (part == 0) {
+ if (parent) {
+ sprintf(current_driverfs_dev->name,
+ "%sdisc", parent->name);
+ sprintf(current_driverfs_dev->bus_id,
+ "%s:disc", parent->bus_id);
+ } else {
+ sprintf(current_driverfs_dev->name,
+ "disc");
+ sprintf(current_driverfs_dev->bus_id,
+ "disc");
+ }
+ } else { /* this is a partition */
+ if (parent) {
+ sprintf(current_driverfs_dev->name,
+ "%spart%d", parent->name, part);
+ sprintf(current_driverfs_dev->bus_id,
+ "%s:p%d", parent->bus_id, part);
+ } else {
+ sprintf(current_driverfs_dev->name,
+ "part%d", part);
+ sprintf(current_driverfs_dev->bus_id,
+ "p%d" ,part);
+ }
+ }
+ if (parent) current_driverfs_dev->bus = parent->bus;
+ device_register(current_driverfs_dev);
+ device_create_file(current_driverfs_dev,
+ &partition_device_type_file);
+ device_create_file(current_driverfs_dev,
+ &partition_device_kdev_file);
+ }
+ }
+ return;
+}
+
+void driverfs_remove_partitions(struct gendisk *hd, int minor)
+{
+ int max_p;
+ int part;
+ struct device * current_driverfs_dev;
+
+ max_p=(1 << hd->minor_shift);
+
+ /* for all parts setup parent relationships and device node names */
+ for(part=1; part < max_p; part++) {
+ if ((hd->part[minor + part].nr_sects >= 1)) {
+ current_driverfs_dev =
+ &hd->part[minor + part].hd_driverfs_dev;
+ device_remove_file(current_driverfs_dev,
+ partition_device_type_file.name);
+ device_remove_file(current_driverfs_dev,
+ partition_device_kdev_file.name);
+ put_device(current_driverfs_dev);
+ }
+ }
+ current_driverfs_dev = &hd->part[minor].hd_driverfs_dev;
+ device_remove_file(current_driverfs_dev,
+ partition_device_type_file.name);
+ device_remove_file(current_driverfs_dev,
+ partition_device_kdev_file.name);
+ put_device(current_driverfs_dev);
+ return;
+}
+
static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
{
devfs_handle_t de = NULL;
@@ -281,6 +412,13 @@
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
bdput(bdev);
i = first_part_minor - 1;
+
+ /* Setup driverfs tree */
+ if (hd->sizes)
+ driverfs_create_partitions(hd, i);
+ else
+ driverfs_remove_partitions(hd, i);
+
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
}

diff -Naur linux-2.5.22.orig/include/linux/cdrom.h linux-2.5.22-driverfs/include/linux/cdrom.h
--- linux-2.5.22.orig/include/linux/cdrom.h Sun Jun 16 21:31:23 2002
+++ linux-2.5.22-driverfs/include/linux/cdrom.h Mon Jun 17 21:14:07 2002
@@ -716,6 +716,7 @@

#ifdef __KERNEL__
#include <linux/devfs_fs_kernel.h>
+#include <linux/device.h>

struct cdrom_write_settings {
unsigned char fpacket; /* fixed/variable packets */
@@ -730,6 +731,7 @@
struct cdrom_device_info *next; /* next device_info for this major */
void *handle; /* driver-dependent data */
devfs_handle_t de; /* real driver should create this */
+ struct device cdrom_driverfs_dev; /* driverfs implementation */
int number; /* generic driver updates this */
/* specifications */
kdev_t dev; /* device number */
diff -Naur linux-2.5.22.orig/include/linux/genhd.h linux-2.5.22-driverfs/include/linux/genhd.h
--- linux-2.5.22.orig/include/linux/genhd.h Sun Jun 16 21:31:26 2002
+++ linux-2.5.22-driverfs/include/linux/genhd.h Mon Jun 17 21:14:07 2002
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
+#include <linux/device.h>

enum {
/* These three have identical behaviour; use the second one if DOS fdisk gets
@@ -62,6 +63,7 @@
unsigned long nr_sects;
devfs_handle_t de; /* primary (master) devfs entry */
int number; /* stupid old code wastes space */
+ struct device hd_driverfs_dev; /* support driverfs hiearchy */
};

#define GENHD_FL_REMOVABLE 1
@@ -80,6 +82,7 @@
struct block_device_operations *fops;

devfs_handle_t *de_arr; /* one per physical disc */
+ struct device **driverfs_dev_arr;/* support driverfs hierarchy */
char *flags; /* one per physical disc */
};

@@ -241,6 +244,7 @@

extern void devfs_register_partitions (struct gendisk *dev, int minor,
int unregister);
+extern void driverfs_remove_partitions (struct gendisk *hd, int minor);

static inline unsigned int disk_index (kdev_t dev)
{
diff -Naur linux-2.5.22.orig/kernel/ksyms.c linux-2.5.22-driverfs/kernel/ksyms.c
--- linux-2.5.22.orig/kernel/ksyms.c Sun Jun 16 21:31:23 2002
+++ linux-2.5.22-driverfs/kernel/ksyms.c Mon Jun 17 21:14:07 2002
@@ -335,6 +335,7 @@
EXPORT_SYMBOL(set_device_ro);
EXPORT_SYMBOL(bmap);
EXPORT_SYMBOL(devfs_register_partitions);
+EXPORT_SYMBOL(driverfs_remove_partitions);
EXPORT_SYMBOL(blkdev_open);
EXPORT_SYMBOL(blkdev_get);
EXPORT_SYMBOL(blkdev_put);

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