Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2087

kernel-2.6.18-128.1.10.el5.src.rpm

Date: Thu, 7 Sep 2006 17:11:43 -0400 (EDT)
From: Chip Coldwell <coldwell@redhat.com>
Subject: [RHEL5 beta2 PATCH REPOST]: BZ#200299 'Cannot allocate memory' when
 cat /proc/scsi/scsi


--- linux-2.6.17.i686/drivers/scsi/scsi_proc.c.orig	2006-09-07 13:00:21.000000000 -0400
+++ linux-2.6.17.i686/drivers/scsi/scsi_proc.c	2006-09-07 12:58:21.000000000 -0400
@@ -144,10 +144,12 @@ 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)
+static int proc_scsi_show(struct seq_file *s, void *data)
 {
+	struct klist_iter *iter = data;
+	struct klist_node *node = iter->i_cur;
+	struct device *dev = container_of(node, struct device, knode_bus);
 	struct scsi_device *sdev = to_scsi_device(dev);
-	struct seq_file *s = data;
 	int i;
 
 	seq_printf(s,
@@ -294,20 +296,72 @@ static ssize_t proc_scsi_write(struct fi
 	return err;
 }
 
-static int proc_scsi_show(struct seq_file *s, void *p)
+static void *proc_scsi_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);
-	return 0;
+	struct klist_iter *iter;
+	loff_t n;
+
+	iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+	if (iter == NULL)
+		return ERR_PTR(-ENOMEM);
+	klist_iter_init(&scsi_bus_type.klist_devices, iter);
+
+	if (*pos == 0)
+		seq_puts(s, "Attached devices:\n");
+
+	n = *pos;
+	do {
+		struct klist_node *node = klist_next(iter);
+		if (node == NULL) {
+			klist_iter_exit(iter);
+			kfree(iter);
+			return NULL;
+		}
+	} while (n-- != 0);
+
+	return iter;
+}
+
+static void *proc_scsi_next(struct seq_file *s, void *p, loff_t *pos)
+{
+	struct klist_iter *iter = p;
+	struct klist_node *node = klist_next(iter);
+
+	if (node == NULL) {
+		klist_iter_exit(iter);
+		kfree(iter);
+		return NULL;
+	}
+
+	*pos += 1;
+	return iter;
 }
 
+static void proc_scsi_stop(struct seq_file *s, void *p)
+{
+	struct klist_iter *iter = p;
+
+	if (iter != NULL && !IS_ERR_VALUE((unsigned long)iter)) {
+		klist_iter_exit(iter);
+		kfree(iter);
+	}
+}
+
+
+static struct seq_operations proc_scsi_op = {
+	.start  = proc_scsi_start,
+	.next   = proc_scsi_next,
+	.stop   = proc_scsi_stop,
+	.show   = proc_scsi_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_scsi_op);
 }
 
 static struct file_operations proc_scsi_operations = {
@@ -315,7 +369,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)