NFS/RPC modprobe -r sunrpc causes an oops
Subsystems (3)
PATCH 1/1 NFS/RPC modprobe -r sunrpc causes an oops
Hello,
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.
Hopefully this will be a candidate for the next release.....
SteveD.
include/linux/sunrpc/cache.h renamed from include/linux/sunrpc/cache.h.org +2 -0
@@ -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 */ };
net/sunrpc/cache.c renamed from net/sunrpc/cache.c.org +11 -0
@@ -175,9 +175,11 @@ void cache_register(struct cache_detailif (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_detailif (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_detailif (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_detailwrite_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); }