I'm not sure if people care about /proc/scsi, but here is a patch so you
can cat /proc/scsi/scsi when you have a large number of scsi devices. I
have over 4000 devices configured and when I would cat /proc/scsi/scsi I
would see a memory allocation error. I instead used the seq_file
iterator to display the devices. The patch is a little brute force, but
it only took about 2.5 seconds to display 4000 devices.
Applies to scsi-misc-2.6 git tree
Signed-off-by: Mark Haverkamp <[EMAIL PROTECTED]>
Index: scsi-misc-aac-2/drivers/scsi/scsi_proc.c
===================================================================
--- scsi-misc-aac-2.orig/drivers/scsi/scsi_proc.c 2005-08-22
11:53:41.000000000 -0700
+++ scsi-misc-aac-2/drivers/scsi/scsi_proc.c 2005-08-23 08:45:09.000000000
-0700
@@ -43,6 +43,10 @@
/* Protect sht->present and sht->proc_dir */
static DECLARE_MUTEX(global_host_template_sem);
+static struct device *proc_dev;
+static loff_t dev_skip;
+static DECLARE_MUTEX(proc_dev_sem);
+
static int proc_scsi_read(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
{
@@ -142,53 +146,6 @@
remove_proc_entry(name, shost->hostt->proc_dir);
}
-static int proc_print_scsidevice(struct device *dev, void *data)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct seq_file *s = data;
- int i;
-
- seq_printf(s,
- "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
- sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
- for (i = 0; i < 8; i++) {
- if (sdev->vendor[i] >= 0x20)
- seq_printf(s, "%c", sdev->vendor[i]);
- else
- seq_printf(s, " ");
- }
-
- seq_printf(s, " Model: ");
- for (i = 0; i < 16; i++) {
- if (sdev->model[i] >= 0x20)
- seq_printf(s, "%c", sdev->model[i]);
- else
- seq_printf(s, " ");
- }
-
- seq_printf(s, " Rev: ");
- for (i = 0; i < 4; i++) {
- if (sdev->rev[i] >= 0x20)
- seq_printf(s, "%c", sdev->rev[i]);
- else
- seq_printf(s, " ");
- }
-
- seq_printf(s, "\n");
-
- seq_printf(s, " Type: %s ",
- sdev->type < MAX_SCSI_DEVICE_CODE ?
- scsi_device_types[(int) sdev->type] : "Unknown ");
- seq_printf(s, " ANSI"
- " SCSI revision: %02x", (sdev->scsi_level - 1) ?
- sdev->scsi_level - 1 : 1);
- if (sdev->scsi_level == 2)
- seq_printf(s, " CCS\n");
- else
- seq_printf(s, "\n");
-
- return 0;
-}
static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{
@@ -284,20 +241,101 @@
return err;
}
-static int proc_scsi_show(struct seq_file *s, void *p)
+
+static int proc_set_scsidevice(struct device *dev, void *data)
+{
+ if (dev_skip--)
+ return 0;
+
+ proc_dev = dev;
+ return -ENXIO;
+}
+
+static void *proc_dev_start(struct seq_file *s, loff_t *pos)
{
- seq_printf(s, "Attached devices:\n");
- bus_for_each_dev(&scsi_bus_type, NULL, s, proc_print_scsidevice);
+ down(&proc_dev_sem);
+ proc_dev = NULL;
+ dev_skip = *pos;
+ bus_for_each_dev(&scsi_bus_type, NULL,
+ NULL, proc_set_scsidevice);
+ return proc_dev;
+}
+
+static void *proc_dev_next(struct seq_file *part, void *v, loff_t *pos)
+{
+ dev_skip = ++*pos;
+ proc_dev = NULL;
+ bus_for_each_dev(&scsi_bus_type, NULL,
+ NULL, proc_set_scsidevice);
+ return proc_dev;
+}
+
+static void proc_dev_stop(struct seq_file *part, void *v)
+{
+ up(&proc_dev_sem);
+}
+
+static int proc_dev_show(struct seq_file *s, void *data)
+{
+ struct scsi_device *sdev = to_scsi_device((struct device*)data);
+ int i;
+
+ seq_printf(s,
+ "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
+ sdev->host->host_no, sdev->channel,
+ sdev->id, sdev->lun);
+ for (i = 0; i < 8; i++) {
+ if (sdev->vendor[i] >= 0x20)
+ seq_printf(s, "%c", sdev->vendor[i]);
+ else
+ seq_printf(s, " ");
+ }
+
+ seq_printf(s, " Model: ");
+ for (i = 0; i < 16; i++) {
+ if (sdev->model[i] >= 0x20)
+ seq_printf(s, "%c", sdev->model[i]);
+ else
+ seq_printf(s, " ");
+ }
+
+ seq_printf(s, " Rev: ");
+ for (i = 0; i < 4; i++) {
+ if (sdev->rev[i] >= 0x20)
+ seq_printf(s, "%c", sdev->rev[i]);
+ else
+ seq_printf(s, " ");
+ }
+
+ seq_printf(s, "\n");
+
+ seq_printf(s, " Type: %s ",
+ sdev->type < MAX_SCSI_DEVICE_CODE ?
+ scsi_device_types[(int) sdev->type] : "Unknown ");
+ seq_printf(s, " ANSI"
+ " SCSI revision: %02x", (sdev->scsi_level - 1) ?
+ sdev->scsi_level - 1 : 1);
+ if (sdev->scsi_level == 2)
+ seq_printf(s, " CCS\n");
+ else
+ seq_printf(s, "\n");
+
return 0;
}
+struct seq_operations proc_dev_op = {
+ .start =proc_dev_start,
+ .next = proc_dev_next,
+ .stop = proc_dev_stop,
+ .show = proc_dev_show
+};
static int proc_scsi_open(struct inode *inode, struct file *file)
{
/*
* We don't really needs this for the write case but it doesn't
* harm either.
*/
- return single_open(file, proc_scsi_show, NULL);
+ return seq_open(file, &proc_dev_op);
}
static struct file_operations proc_scsi_operations = {
@@ -305,7 +343,7 @@
.read = seq_read,
.write = proc_scsi_write,
.llseek = seq_lseek,
- .release = single_release,
+ .release = seq_release
};
int __init scsi_init_procfs(void)
--
Mark Haverkamp <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html