Commit d54eb723 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] NFS/RPC modprobe -r sunrpc causes an oops

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)
parent 31e43b1b
...@@ -94,6 +94,8 @@ struct cache_detail { ...@@ -94,6 +94,8 @@ struct cache_detail {
/* fields for communication over channel */ /* fields for communication over channel */
struct list_head queue; struct list_head queue;
struct proc_dir_entry *proc_ent; 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 */ atomic_t readers; /* how many time is /chennel open */
time_t last_close; /* it no readers, when did last close */ time_t last_close; /* it no readers, when did last close */
}; };
......
...@@ -175,9 +175,11 @@ void cache_register(struct cache_detail *cd) ...@@ -175,9 +175,11 @@ void cache_register(struct cache_detail *cd)
if (cd->proc_ent) { if (cd->proc_ent) {
struct proc_dir_entry *p; struct proc_dir_entry *p;
cd->proc_ent->owner = THIS_MODULE; cd->proc_ent->owner = THIS_MODULE;
cd->channel_ent = cd->content_ent = NULL;
p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
cd->proc_ent); cd->proc_ent);
cd->flush_ent = p;
if (p) { if (p) {
p->proc_fops = &cache_flush_operations; p->proc_fops = &cache_flush_operations;
p->owner = THIS_MODULE; p->owner = THIS_MODULE;
...@@ -187,6 +189,7 @@ void cache_register(struct cache_detail *cd) ...@@ -187,6 +189,7 @@ void cache_register(struct cache_detail *cd)
if (cd->cache_request || cd->cache_parse) { if (cd->cache_request || cd->cache_parse) {
p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR, p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
cd->proc_ent); cd->proc_ent);
cd->channel_ent = p;
if (p) { if (p) {
p->proc_fops = &cache_file_operations; p->proc_fops = &cache_file_operations;
p->owner = THIS_MODULE; p->owner = THIS_MODULE;
...@@ -196,6 +199,7 @@ void cache_register(struct cache_detail *cd) ...@@ -196,6 +199,7 @@ void cache_register(struct cache_detail *cd)
if (cd->cache_show) { if (cd->cache_show) {
p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR, p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
cd->proc_ent); cd->proc_ent);
cd->content_ent = p;
if (p) { if (p) {
p->proc_fops = &content_file_operations; p->proc_fops = &content_file_operations;
p->owner = THIS_MODULE; p->owner = THIS_MODULE;
...@@ -233,6 +237,13 @@ int cache_unregister(struct cache_detail *cd) ...@@ -233,6 +237,13 @@ int cache_unregister(struct cache_detail *cd)
write_unlock(&cd->hash_lock); write_unlock(&cd->hash_lock);
spin_unlock(&cache_list_lock); spin_unlock(&cache_list_lock);
if (cd->proc_ent) { 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; cd->proc_ent = NULL;
remove_proc_entry(cd->name, proc_net_rpc); remove_proc_entry(cd->name, proc_net_rpc);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment