xref: /linux/net/9p/mod.c (revision 024b7d6a435a450819f112690052f2923fa5ffdd)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  9P entry point
4  *
5  *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
6  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8  */
9 
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 
12 #include <linux/module.h>
13 #include <linux/kmod.h>
14 #include <linux/errno.h>
15 #include <linux/sched.h>
16 #include <linux/moduleparam.h>
17 #include <net/9p/9p.h>
18 #include <linux/fs.h>
19 #include <linux/parser.h>
20 #include <net/9p/client.h>
21 #include <net/9p/transport.h>
22 #include <linux/list.h>
23 #include <linux/spinlock.h>
24 
25 #ifdef CONFIG_NET_9P_DEBUG
26 unsigned int p9_debug_level = 0;	/* feature-rific global debug level  */
27 EXPORT_SYMBOL(p9_debug_level);
28 module_param_named(debug, p9_debug_level, uint, 0);
29 MODULE_PARM_DESC(debug, "9P debugging level");
30 
31 void _p9_debug(enum p9_debug_flags level, const char *func,
32 		const char *fmt, ...)
33 {
34 	struct va_format vaf;
35 	va_list args;
36 
37 	if ((p9_debug_level & level) != level)
38 		return;
39 
40 	va_start(args, fmt);
41 
42 	vaf.fmt = fmt;
43 	vaf.va = &args;
44 
45 	if (level == P9_DEBUG_9P)
46 		pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf);
47 	else
48 		pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf);
49 
50 	va_end(args);
51 }
52 EXPORT_SYMBOL(_p9_debug);
53 #endif
54 
55 /*
56  * Dynamic Transport Registration Routines
57  *
58  */
59 
60 static DEFINE_SPINLOCK(v9fs_trans_lock);
61 static LIST_HEAD(v9fs_trans_list);
62 
63 /**
64  * v9fs_register_trans - register a new transport with 9p
65  * @m: structure describing the transport module and entry points
66  *
67  */
68 void v9fs_register_trans(struct p9_trans_module *m)
69 {
70 	spin_lock(&v9fs_trans_lock);
71 	list_add_tail(&m->list, &v9fs_trans_list);
72 	spin_unlock(&v9fs_trans_lock);
73 }
74 EXPORT_SYMBOL(v9fs_register_trans);
75 
76 /**
77  * v9fs_unregister_trans - unregister a 9p transport
78  * @m: the transport to remove
79  *
80  */
81 void v9fs_unregister_trans(struct p9_trans_module *m)
82 {
83 	spin_lock(&v9fs_trans_lock);
84 	list_del_init(&m->list);
85 	spin_unlock(&v9fs_trans_lock);
86 }
87 EXPORT_SYMBOL(v9fs_unregister_trans);
88 
89 static struct p9_trans_module *_p9_get_trans_by_name(char *s)
90 {
91 	struct p9_trans_module *t, *found = NULL;
92 
93 	spin_lock(&v9fs_trans_lock);
94 
95 	list_for_each_entry(t, &v9fs_trans_list, list)
96 		if (strcmp(t->name, s) == 0 &&
97 		    try_module_get(t->owner)) {
98 			found = t;
99 			break;
100 		}
101 
102 	spin_unlock(&v9fs_trans_lock);
103 
104 	return found;
105 }
106 
107 /**
108  * v9fs_get_trans_by_name - get transport with the matching name
109  * @s: string identifying transport
110  *
111  */
112 struct p9_trans_module *v9fs_get_trans_by_name(char *s)
113 {
114 	struct p9_trans_module *found = NULL;
115 
116 	found = _p9_get_trans_by_name(s);
117 
118 #ifdef CONFIG_MODULES
119 	if (!found) {
120 		request_module("9p-%s", s);
121 		found = _p9_get_trans_by_name(s);
122 	}
123 #endif
124 
125 	return found;
126 }
127 EXPORT_SYMBOL(v9fs_get_trans_by_name);
128 
129 /**
130  * v9fs_get_default_trans - get the default transport
131  *
132  */
133 
134 struct p9_trans_module *v9fs_get_default_trans(void)
135 {
136 	struct p9_trans_module *t, *found = NULL;
137 
138 	spin_lock(&v9fs_trans_lock);
139 
140 	list_for_each_entry(t, &v9fs_trans_list, list)
141 		if (t->def && try_module_get(t->owner)) {
142 			found = t;
143 			break;
144 		}
145 
146 	if (!found)
147 		list_for_each_entry(t, &v9fs_trans_list, list)
148 			if (try_module_get(t->owner)) {
149 				found = t;
150 				break;
151 			}
152 
153 	spin_unlock(&v9fs_trans_lock);
154 	return found;
155 }
156 EXPORT_SYMBOL(v9fs_get_default_trans);
157 
158 /**
159  * v9fs_put_trans - put trans
160  * @m: transport to put
161  *
162  */
163 void v9fs_put_trans(struct p9_trans_module *m)
164 {
165 	if (m)
166 		module_put(m->owner);
167 }
168 
169 /**
170  * init_p9 - Initialize module
171  *
172  */
173 static int __init init_p9(void)
174 {
175 	int ret;
176 
177 	ret = p9_client_init();
178 	if (ret)
179 		return ret;
180 
181 	p9_error_init();
182 	pr_info("Installing 9P2000 support\n");
183 	p9_trans_fd_init();
184 
185 	return ret;
186 }
187 
188 /**
189  * exit_p9 - shutdown module
190  *
191  */
192 
193 static void __exit exit_p9(void)
194 {
195 	pr_info("Unloading 9P2000 support\n");
196 
197 	p9_trans_fd_exit();
198 	p9_client_exit();
199 }
200 
201 module_init(init_p9)
202 module_exit(exit_p9)
203 
204 MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
205 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
206 MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
207 MODULE_LICENSE("GPL");
208 MODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)");
209