patch-2.4.15 linux/kernel/module.c

Next file: linux/kernel/printk.c
Previous file: linux/kernel/ksyms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.14/linux/kernel/module.c linux/kernel/module.c
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
+#include <linux/seq_file.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -1156,51 +1157,83 @@
  * Called by the /proc file system to return a current list of ksyms.
  */
 
-int
-get_ksyms_list(char *buf, char **start, off_t offset, int length)
-{
+struct mod_sym {
 	struct module *mod;
-	char *p = buf;
-	int len     = 0;	/* code from  net/ipv4/proc.c */
-	off_t pos   = 0;
-	off_t begin = 0;
-
-	for (mod = module_list; mod; mod = mod->next) {
-		unsigned i;
-		struct module_symbol *sym;
+	int index;
+};
 
-		if (!MOD_CAN_QUERY(mod))
-			continue;
+/* iterator */
 
-		for (i = mod->nsyms, sym = mod->syms; i > 0; --i, ++sym) {
-			p = buf + len;
-			if (*mod->name) {
-				len += sprintf(p, "%0*lx %s\t[%s]\n",
-					       (int)(2*sizeof(void*)),
-					       sym->value, sym->name,
-					       mod->name);
-			} else {
-				len += sprintf(p, "%0*lx %s\n",
-					       (int)(2*sizeof(void*)),
-					       sym->value, sym->name);
-			}
-			pos = begin + len;
-			if (pos < offset) {
-				len = 0;
-				begin = pos;
-			}
-			pos = begin + len;
-			if (pos > offset+length)
-				goto leave_the_loop;
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+	struct mod_sym *p = kmalloc(sizeof(*p), GFP_KERNEL);
+	struct module *v;
+	loff_t n = *pos;
+
+	if (!p)
+		return ERR_PTR(-ENOMEM);
+	lock_kernel();
+	for (v = module_list, n = *pos; v; n -= v->nsyms, v = v->next) {
+		if (n < v->nsyms) {
+			p->mod = v;
+			p->index = n;
+			return p;
 		}
 	}
-leave_the_loop:
-	*start = buf + (offset - begin);
-	len -= (offset - begin);
-	if (len > length)
-		len = length;
-	return len;
+	unlock_kernel();
+	kfree(p);
+	return NULL;
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	struct mod_sym *v = p;
+	(*pos)++;
+	if (++v->index >= v->mod->nsyms) {
+		do {
+			v->mod = v->mod->next;
+			if (!v->mod) {
+				unlock_kernel();
+				kfree(p);
+				return NULL;
+			}
+		} while (!v->mod->nsyms);
+		v->index = 0;
+	}
+	return p;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+	if (p && !IS_ERR(p)) {
+		unlock_kernel();
+		kfree(p);
+	}
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+	struct mod_sym *v = p;
+	struct module_symbol *sym;
+
+	if (!MOD_CAN_QUERY(v->mod))
+		return 0;
+	sym = &v->mod->syms[v->index];
+	if (*v->mod->name)
+		seq_printf(m, "%0*lx %s\t[%s]\n", (int)(2*sizeof(void*)),
+			       sym->value, sym->name, v->mod->name);
+	else
+		seq_printf(m, "%0*lx %s\n", (int)(2*sizeof(void*)),
+			       sym->value, sym->name);
+	return 0;
 }
+
+struct seq_operations ksyms_op = {
+	start:	s_start,
+	next:	s_next,
+	stop:	s_stop,
+	show:	s_show
+};
 
 #else		/* CONFIG_MODULES */
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)