]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/proc-scsi-scsi-fix.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / proc-scsi-scsi-fix.diff
1 From: Jeff Mahoney <jeffm@suse.com>
2 Subject: [PATCH] scsi: iterate over devices individually for /proc/scsi/scsi
3 References: 263731
4 Patch-mainline: Probably never, hch wants to kill /proc/scsi/scsi anyway.
5
6 On systems with very large numbers (> 1600 or so) of SCSI devices,
7 cat /proc/scsi/scsi ends up failing with -ENOMEM. This is due to
8 the show routine simply iterating over all of the devices with
9 bus_for_each_dev(), and trying to dump all of them into the buffer
10 at the same time. On my test system (using scsi_debug with 4064 devices),
11 the output ends up being ~ 632k, far more than kmalloc will typically allow.
12
13 This patch defines its own seq_file opreations to iterate over the scsi
14 devices.The result is that each show() operation only dumps ~ 180 bytes
15 into the buffer at a time so we don't run out of memory.
16
17 If the "Attached devices" header isn't required, we can dump the
18 sfile->private bit completely.
19
20 Signed-off-by: Jeff Mahoney <jeffm@suse.com>
21
22 ---
23
24 drivers/scsi/scsi_proc.c | 58 ++++++++++++++++++++++++++++++++++++++++++-----
25 1 file changed, 52 insertions(+), 6 deletions(-)
26
27 --- a/drivers/scsi/scsi_proc.c
28 +++ b/drivers/scsi/scsi_proc.c
29 @@ -389,13 +389,59 @@ static ssize_t proc_scsi_write(struct fi
30 * @s: output goes here
31 * @p: not used
32 */
33 -static int proc_scsi_show(struct seq_file *s, void *p)
34 +static int always_match(struct device *dev, void *data)
35 {
36 - seq_printf(s, "Attached devices:\n");
37 - bus_for_each_dev(&scsi_bus_type, NULL, s, proc_print_scsidevice);
38 - return 0;
39 + return 1;
40 }
41
42 +static inline struct device *next_scsi_device(struct device *start)
43 +{
44 + struct device *next = bus_find_device(&scsi_bus_type, start, NULL,
45 + always_match);
46 + put_device(start);
47 + return next;
48 +}
49 +
50 +static void *scsi_seq_start(struct seq_file *sfile, loff_t *pos)
51 +{
52 + struct device *dev = NULL;
53 + loff_t n = *pos;
54 +
55 + while ((dev = next_scsi_device(dev))) {
56 + if (!n--)
57 + break;
58 + sfile->private++;
59 + }
60 + return dev;
61 +}
62 +
63 +static void *scsi_seq_next(struct seq_file *sfile, void *v, loff_t *pos)
64 +{
65 + (*pos)++;
66 + sfile->private++;
67 + return next_scsi_device(v);
68 +}
69 +
70 +static void scsi_seq_stop(struct seq_file *sfile, void *v)
71 +{
72 + put_device(v);
73 +}
74 +
75 +static int scsi_seq_show(struct seq_file *sfile, void *dev)
76 +{
77 + if (!sfile->private)
78 + seq_puts(sfile, "Attached devices:\n");
79 +
80 + return proc_print_scsidevice(dev, sfile);
81 +}
82 +
83 +static struct seq_operations scsi_seq_ops = {
84 + .start = scsi_seq_start,
85 + .next = scsi_seq_next,
86 + .stop = scsi_seq_stop,
87 + .show = scsi_seq_show
88 +};
89 +
90 /**
91 * proc_scsi_open - glue function
92 * @inode: not used
93 @@ -409,7 +455,7 @@ static int proc_scsi_open(struct inode *
94 * We don't really need this for the write case but it doesn't
95 * harm either.
96 */
97 - return single_open(file, proc_scsi_show, NULL);
98 + return seq_open(file, &scsi_seq_ops);
99 }
100
101 static const struct file_operations proc_scsi_operations = {
102 @@ -418,7 +464,7 @@ static const struct file_operations proc
103 .read = seq_read,
104 .write = proc_scsi_write,
105 .llseek = seq_lseek,
106 - .release = single_release,
107 + .release = seq_release,
108 };
109
110 /**