mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 06:01:23 +00:00
9p: implement proper trans module refcounting and unregistration
9p trans modules aren't refcounted nor were they unregistered properly. Fix it. * Add 9p_trans_module->owner and reference the module on each trans instance creation and put it on destruction. * Protect v9fs_trans_list with a spinlock. This isn't strictly necessary as the list is manipulated only during module loading / unloading but it's a good idea to make the API safe. * Unregister trans modules when the corresponding module is being unloaded. * While at it, kill unnecessary EXPORT_SYMBOL on p9_trans_fd_init(). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
This commit is contained in:
parent
72d31053f6
commit
72029fe85d
6 changed files with 95 additions and 30 deletions
92
net/9p/mod.c
92
net/9p/mod.c
|
@ -31,6 +31,7 @@
|
|||
#include <linux/parser.h>
|
||||
#include <net/9p/transport.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_NET_9P_DEBUG
|
||||
unsigned int p9_debug_level = 0; /* feature-rific global debug level */
|
||||
|
@ -44,8 +45,8 @@ MODULE_PARM_DESC(debug, "9P debugging level");
|
|||
*
|
||||
*/
|
||||
|
||||
static DEFINE_SPINLOCK(v9fs_trans_lock);
|
||||
static LIST_HEAD(v9fs_trans_list);
|
||||
static struct p9_trans_module *v9fs_default_transport;
|
||||
|
||||
/**
|
||||
* v9fs_register_trans - register a new transport with 9p
|
||||
|
@ -54,48 +55,87 @@ static struct p9_trans_module *v9fs_default_transport;
|
|||
*/
|
||||
void v9fs_register_trans(struct p9_trans_module *m)
|
||||
{
|
||||
spin_lock(&v9fs_trans_lock);
|
||||
list_add_tail(&m->list, &v9fs_trans_list);
|
||||
if (m->def)
|
||||
v9fs_default_transport = m;
|
||||
spin_unlock(&v9fs_trans_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(v9fs_register_trans);
|
||||
|
||||
/**
|
||||
* v9fs_match_trans - match transport versus registered transports
|
||||
* v9fs_unregister_trans - unregister a 9p transport
|
||||
* @m: the transport to remove
|
||||
*
|
||||
*/
|
||||
void v9fs_unregister_trans(struct p9_trans_module *m)
|
||||
{
|
||||
spin_lock(&v9fs_trans_lock);
|
||||
list_del_init(&m->list);
|
||||
spin_unlock(&v9fs_trans_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(v9fs_unregister_trans);
|
||||
|
||||
/**
|
||||
* v9fs_get_trans_by_name - get transport with the matching name
|
||||
* @name: string identifying transport
|
||||
*
|
||||
*/
|
||||
struct p9_trans_module *v9fs_match_trans(const substring_t *name)
|
||||
struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct p9_trans_module *t = NULL;
|
||||
struct p9_trans_module *t, *found = NULL;
|
||||
|
||||
list_for_each(p, &v9fs_trans_list) {
|
||||
t = list_entry(p, struct p9_trans_module, list);
|
||||
if (strncmp(t->name, name->from, name->to-name->from) == 0)
|
||||
return t;
|
||||
}
|
||||
return NULL;
|
||||
spin_lock(&v9fs_trans_lock);
|
||||
|
||||
list_for_each_entry(t, &v9fs_trans_list, list)
|
||||
if (strncmp(t->name, name->from, name->to-name->from) == 0 &&
|
||||
try_module_get(t->owner)) {
|
||||
found = t;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&v9fs_trans_lock);
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL(v9fs_match_trans);
|
||||
EXPORT_SYMBOL(v9fs_get_trans_by_name);
|
||||
|
||||
/**
|
||||
* v9fs_default_trans - returns pointer to default transport
|
||||
* v9fs_get_default_trans - get the default transport
|
||||
*
|
||||
*/
|
||||
|
||||
struct p9_trans_module *v9fs_default_trans(void)
|
||||
struct p9_trans_module *v9fs_get_default_trans(void)
|
||||
{
|
||||
if (v9fs_default_transport)
|
||||
return v9fs_default_transport;
|
||||
else if (!list_empty(&v9fs_trans_list))
|
||||
return list_first_entry(&v9fs_trans_list,
|
||||
struct p9_trans_module, list);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(v9fs_default_trans);
|
||||
struct p9_trans_module *t, *found = NULL;
|
||||
|
||||
spin_lock(&v9fs_trans_lock);
|
||||
|
||||
list_for_each_entry(t, &v9fs_trans_list, list)
|
||||
if (t->def && try_module_get(t->owner)) {
|
||||
found = t;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
list_for_each_entry(t, &v9fs_trans_list, list)
|
||||
if (try_module_get(t->owner)) {
|
||||
found = t;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&v9fs_trans_lock);
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL(v9fs_get_default_trans);
|
||||
|
||||
/**
|
||||
* v9fs_put_trans - put trans
|
||||
* @m: transport to put
|
||||
*
|
||||
*/
|
||||
void v9fs_put_trans(struct p9_trans_module *m)
|
||||
{
|
||||
if (m)
|
||||
module_put(m->owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_init - Initialize module
|
||||
|
@ -120,6 +160,8 @@ static int __init init_p9(void)
|
|||
static void __exit exit_p9(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading 9P2000 support\n");
|
||||
|
||||
p9_trans_fd_exit();
|
||||
}
|
||||
|
||||
module_init(init_p9)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue