Thread (10 messages) 10 messages, 4 authors, 2005-02-24

Re: Frequent Oops on Shutdown 2.6.10

From: YOSHIFUJI Hideaki / 吉藤英明 <hidden>
Date: 2005-02-21 07:22:41

Hello.

In article [ref] (at Sun, 20 Feb 2005 22:03:04 -0800), Andrew Morton [off-list ref] says:
EIP is at remove_proc_entry+0x2a/0x166
:
[<f8c4f051>] snmp6_unregister_dev+0x41/0x57  [ipv6]
[<f8c2cc7b>] in6_dev_finish_destroy+0x35/0xb6  [ipv6]
[<c0289967>] dst_destroy+0xa2/0xcd
Would you test this patch, please?
Thanks.

------
[IPV6] Don't remove dev_snmp6 procfs entry until all users gone.

Signed-off-by: Hideaki YOSHIFUJI <redacted>

===== net/ipv6/proc.c 1.25 vs edited =====
--- 1.25/net/ipv6/proc.c	2004-07-08 07:17:29 +09:00
+++ edited/net/ipv6/proc.c	2005-02-21 16:05:49 +09:00
@@ -31,7 +31,9 @@
 #include <net/ipv6.h>
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_net_devsnmp6;
+struct proc_dir_entry *proc_net_devsnmp6;
+static DECLARE_MUTEX(proc_net_devsnmp6_sem);
+static unsigned int proc_net_devsnmp6_users;
 
 static int fold_prot_inuse(struct proto *proto)
 {
@@ -211,13 +213,26 @@
 			   __alignof__(struct icmpv6_mib)) < 0)
 		goto err_icmp;
 
-	if (!proc_net_devsnmp6) {
-		err = -ENOENT;
-		goto err_proc;
+	down(&proc_net_devsnmp6_sem);
+	if (!proc_net_devsnmp6_users) {
+		proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
+		if (!proc_net_devsnmp6) {
+			err = -ENOMEM;
+			printk(KERN_ERR "%s(): failed to create dev_snmp6.\n",
+			       __FUNCTION__);
+			goto err_proc;
+		}
 	}
 	p = create_proc_entry(idev->dev->name, S_IRUGO, proc_net_devsnmp6);
-	if (!p)
+	if (!p) {
+		if (!proc_net_devsnmp6_users)
+			proc_net_remove("dev_snmp6");
 		goto err_proc;
+	}
+
+	proc_net_devsnmp6_users++;
+	up(&proc_net_devsnmp6_sem);
+
 	p->data = idev;
 	p->proc_fops = &snmp6_seq_fops;
 
@@ -225,6 +240,7 @@
 	return 0;
 
 err_proc:
+	up(&proc_net_devsnmp6_sem);
 	snmp6_mib_free((void **)idev->stats.icmpv6);
 err_icmp:
 	return err;
@@ -232,12 +248,23 @@
 
 int snmp6_unregister_dev(struct inet6_dev *idev)
 {
-	if (!proc_net_devsnmp6)
+	down(&proc_net_devsnmp6_sem);
+	if (!proc_net_devsnmp6) {
+		up(&proc_net_devsnmp6_sem);
 		return -ENOENT;
-	if (!idev || !idev->stats.proc_dir_entry)
+	}
+	if (!idev || !idev->stats.proc_dir_entry) {
+		up(&proc_net_devsnmp6_sem);
 		return -EINVAL;
+	}
 	remove_proc_entry(idev->stats.proc_dir_entry->name,
 			  proc_net_devsnmp6);
+	if (!--proc_net_devsnmp6_users) {
+		proc_net_remove("dev_snmp6");
+		proc_net_devsnmp6 = NULL;
+	}
+	up(&proc_net_devsnmp6_sem);
+
 	snmp6_mib_free((void **)idev->stats.icmpv6);
 
 	return 0;
@@ -250,18 +277,12 @@
 	if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops))
 		goto proc_snmp6_fail;
 
-	proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
-	if (!proc_net_devsnmp6)
-		goto proc_dev_snmp6_fail;
-
 	if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops))
 		goto proc_sockstat6_fail;
 out:
 	return rc;
 
 proc_sockstat6_fail:
-	proc_net_remove("dev_snmp6");
-proc_dev_snmp6_fail:
 	proc_net_remove("snmp6");
 proc_snmp6_fail:
 	rc = -ENOMEM;
@@ -271,7 +292,6 @@
 void ipv6_misc_proc_exit(void)
 {
 	proc_net_remove("sockstat6");
-	proc_net_remove("dev_snmp6");
 	proc_net_remove("snmp6");
 }
 
-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help