From: Hannes Reinecke <hare@suse.de>
To: Linux Kernel <linux-kernel@vger.kernel.org>
Cc: SCSI Mailing List <linux-scsi@vger.kernel.org>
Subject: [PATCH] Use proper seq_file api for /proc/scsi/scsi
Date: Thu, 07 Apr 2005 11:46:27 +0200 [thread overview]
Message-ID: <42550173.1040503@suse.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 787 bytes --]
Hi all,
/proc/scsi/scsi currently has a very dumb implementation of the seq_file
api which causes 'cat /proc/scsi/scsi' to return with -ENOMEM when a
large amount of devices are connected.
This patch impelements the proper seq_file interface which prints out
all devices sequentially.
The use of 'get_device()/put_device()' is interesting, as it relies on
->show being called after a successful call to ->start / ->next.
But the current seq_file implementation does it that way; and using
->stop doesn't quite work as it's end up being called several times for
no appearent reason.
But I'm all ears for a better solution.
Cheers,
Hannes
--
Dr. Hannes Reinecke hare@suse.de
SuSE Linux AG S390 & zSeries
Maxfeldstraße 5 +49 911 74053 688
90409 Nürnberg http://www.suse.de
[-- Attachment #2: scsi-use-seq_file-for-proc.patch --]
[-- Type: text/plain, Size: 4060 bytes --]
From: Hannes Reinecke <hare@suse.de>
Subject: cat /proc/scsi/scsi crashes with 'out of memory'
Reference: 75899
'cat /proc/scsi/scsi' returns 'out of memory' when a large number of devices
is connected. This is due to the use of the simple interface into seq_file
which tries to allocate a buffer holding _all_ devices.
This patch converts the proc interface to use the seq_file API properly.
Signed-off-by: Hannes Reinecke <hare@suse.de>
--- linux-2.6.5/drivers/scsi/scsi_proc.c.orig 2004-04-04 05:36:17.000000000 +0200
+++ linux-2.6.5/drivers/scsi/scsi_proc.c 2005-04-07 11:08:16.877718912 +0200
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/blkdev.h>
#include <linux/seq_file.h>
+#include <linux/list.h>
#include <asm/uaccess.h>
#include <scsi/scsi_host.h>
@@ -141,10 +142,90 @@ void scsi_proc_host_rm(struct Scsi_Host
remove_proc_entry(name, shost->hostt->proc_dir);
}
-static int proc_print_scsidevice(struct device *dev, void *data)
+/*
+ * Simple selector for the next device in list.
+ * We take a reference on the current device to
+ * avoid it having vanished underneath us.
+ */
+static int proc_print_sdev_select( struct device *d, void *p)
+{
+ struct device **t = p;
+ struct list_head *l;
+
+ if (!*t) {
+ get_device(d);
+ *t = d;
+ return 1;
+ }
+
+ l = &((*t)->bus_list);
+ if (list_entry(l->next, struct device, bus_list) == d ) {
+ get_device(d);
+ *t = d;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * seq_file interface
+ * The iterator is of type 'struct device *' and points to the
+ * current device. A reference to the current device is taken
+ * by the selector function above and must be dropped during
+ * the show function.
+ */
+static void *proc_print_sdev_start(struct seq_file *s, loff_t *pos)
+{
+ struct device *d = NULL;
+
+ if (*pos != 0)
+ return NULL;
+
+ seq_printf(s, "Attached devices:\n");
+
+ if ( bus_for_each_dev(&scsi_bus_type, NULL, &d,
+ proc_print_sdev_select) > 0 )
+ return d;
+
+ return NULL;
+}
+
+/*
+ * fetch next device.
+ * We don't actually need the pos argument but seq_file is unhappy
+ * without it.
+ */
+static void *proc_print_sdev_next(struct seq_file *s, void *p, loff_t *pos)
+{
+ struct device *d = p;
+
+ (*pos)++;
+
+ if ( bus_for_each_dev(&scsi_bus_type, p, &d,
+ proc_print_sdev_select) > 0 )
+ return d;
+
+ return NULL;
+}
+
+/*
+ * Stop device iteration.
+ * Nothing to be done here.
+ */
+static void proc_print_sdev_stop(struct seq_file *s, void *p)
+{
+ return;
+}
+
+/*
+ * Show selected device.
+ * We have to dereference the device here.
+ */
+static int proc_print_sdev_show(struct seq_file *s, void *p)
{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct seq_file *s = data;
+ struct device *d = p;
+ struct scsi_device *sdev = to_scsi_device(d);
int i;
seq_printf(s,
@@ -186,9 +267,18 @@ static int proc_print_scsidevice(struct
else
seq_printf(s, "\n");
+ put_device(d);
+
return 0;
}
+struct seq_operations scsi_proc_print_op = {
+ .start = proc_print_sdev_start,
+ .next = proc_print_sdev_next,
+ .stop = proc_print_sdev_stop,
+ .show = proc_print_sdev_show
+};
+
static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{
struct Scsi_Host *shost;
@@ -283,20 +373,13 @@ static ssize_t proc_scsi_write(struct fi
return err;
}
-static int proc_scsi_show(struct seq_file *s, void *p)
-{
- seq_printf(s, "Attached devices:\n");
- bus_for_each_dev(&scsi_bus_type, NULL, s, proc_print_scsidevice);
- return 0;
-}
-
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, &scsi_proc_print_op);
}
static struct file_operations proc_scsi_operations = {
@@ -304,7 +387,7 @@ static struct file_operations proc_scsi_
.read = seq_read,
.write = proc_scsi_write,
.llseek = seq_lseek,
- .release = single_release,
+ .release = seq_release,
};
int __init scsi_init_procfs(void)
next reply other threads:[~2005-04-07 9:46 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-04-07 9:46 Hannes Reinecke [this message]
2005-04-07 10:31 ` [PATCH] Use proper seq_file api for /proc/scsi/scsi Christoph Hellwig
2005-04-07 11:21 ` Hannes Reinecke
2005-04-07 11:24 ` Christoph Hellwig
2005-04-08 7:23 ` Jeremy Higdon
2005-04-08 7:56 ` Christoph Hellwig
2005-04-08 7:59 ` Arjan van de Ven
2005-04-08 8:10 ` Jeremy Higdon
2005-04-08 14:27 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=42550173.1040503@suse.de \
--to=hare@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox