]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] NFS/RPC modprobe -r sunrpc causes an oops
authorAndrew Morton <akpm@osdl.org>
Tue, 20 Jan 2004 11:17:23 +0000 (03:17 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 20 Jan 2004 11:17:23 +0000 (03:17 -0800)
From: Steve Dickson <SteveD@redhat.com>

Here is a patch for the 2.6.1 kernel that fixes an oops that occurs when
the sunrpc module is unloaded.

The problem was the RPC cache_register() call was not saving entry pointers
to the procfs entries it was creating.  So when it came time to dismantle
the entires, a BUG_ON() was tripped in remove_proc_entry() since the tree
was not broken down completely.

(acked by neilb)

include/linux/sunrpc/cache.h
net/sunrpc/cache.c

index a9575c349cfe7f6de022f3e6998f3126d904625f..299b31438ffcbe89a53626606cf24fd0e508fb1f 100644 (file)
@@ -94,6 +94,8 @@ struct cache_detail {
        /* fields for communication over channel */
        struct list_head        queue;
        struct proc_dir_entry   *proc_ent;
+       struct proc_dir_entry   *flush_ent, *channel_ent, *content_ent;
+
        atomic_t                readers;                /* how many time is /chennel open */
        time_t                  last_close;             /* it no readers, when did last close */
 };
index 1f671f8069519fedd5a76b40ca0a60d42513bb37..80f4e44a0f8b3241cc1ac7b051165a9ff32b9a31 100644 (file)
@@ -175,9 +175,11 @@ void cache_register(struct cache_detail *cd)
        if (cd->proc_ent) {
                struct proc_dir_entry *p;
                cd->proc_ent->owner = THIS_MODULE;
+               cd->channel_ent = cd->content_ent = NULL;
                
                p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
                                      cd->proc_ent);
+               cd->flush_ent =  p;
                if (p) {
                        p->proc_fops = &cache_flush_operations;
                        p->owner = THIS_MODULE;
@@ -187,6 +189,7 @@ void cache_register(struct cache_detail *cd)
                if (cd->cache_request || cd->cache_parse) {
                        p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
                                              cd->proc_ent);
+                       cd->channel_ent = p;
                        if (p) {
                                p->proc_fops = &cache_file_operations;
                                p->owner = THIS_MODULE;
@@ -196,6 +199,7 @@ void cache_register(struct cache_detail *cd)
                if (cd->cache_show) {
                        p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
                                              cd->proc_ent);
+                       cd->content_ent = p;
                        if (p) {
                                p->proc_fops = &content_file_operations;
                                p->owner = THIS_MODULE;
@@ -233,6 +237,13 @@ int cache_unregister(struct cache_detail *cd)
        write_unlock(&cd->hash_lock);
        spin_unlock(&cache_list_lock);
        if (cd->proc_ent) {
+               if (cd->flush_ent)
+                       remove_proc_entry("flush", cd->proc_ent);
+               if (cd->channel_ent)
+                       remove_proc_entry("channel", cd->proc_ent);
+               if (cd->content_ent)
+                       remove_proc_entry("content", cd->proc_ent);
+
                cd->proc_ent = NULL;
                remove_proc_entry(cd->name, proc_net_rpc);
        }