11f327613SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bd238fb4SLatchesar Ionkov /*
3bd238fb4SLatchesar Ionkov * 9P entry point
4bd238fb4SLatchesar Ionkov *
5bd238fb4SLatchesar Ionkov * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
6bd238fb4SLatchesar Ionkov * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7bd238fb4SLatchesar Ionkov * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8bd238fb4SLatchesar Ionkov */
9bd238fb4SLatchesar Ionkov
105d385153SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
115d385153SJoe Perches
12bd238fb4SLatchesar Ionkov #include <linux/module.h>
134cd82a5bSThomas Weißschuh #include <linux/kmod.h>
145d385153SJoe Perches #include <linux/errno.h>
155d385153SJoe Perches #include <linux/sched.h>
16bd238fb4SLatchesar Ionkov #include <linux/moduleparam.h>
17bd238fb4SLatchesar Ionkov #include <net/9p/9p.h>
18fb0466c3SEric Van Hensbergen #include <linux/fs.h>
19fb0466c3SEric Van Hensbergen #include <linux/parser.h>
208b81ef58SEric Van Hensbergen #include <net/9p/client.h>
21fb0466c3SEric Van Hensbergen #include <net/9p/transport.h>
22fb0466c3SEric Van Hensbergen #include <linux/list.h>
2372029fe8STejun Heo #include <linux/spinlock.h>
24bd238fb4SLatchesar Ionkov
25bd238fb4SLatchesar Ionkov #ifdef CONFIG_NET_9P_DEBUG
266e195b0fSDominique Martinet unsigned int p9_debug_level; /* feature-rific global debug level */
27bd238fb4SLatchesar Ionkov EXPORT_SYMBOL(p9_debug_level);
28bd238fb4SLatchesar Ionkov module_param_named(debug, p9_debug_level, uint, 0);
29bd238fb4SLatchesar Ionkov MODULE_PARM_DESC(debug, "9P debugging level");
305d385153SJoe Perches
_p9_debug(enum p9_debug_flags level,const char * func,const char * fmt,...)315d385153SJoe Perches void _p9_debug(enum p9_debug_flags level, const char *func,
325d385153SJoe Perches const char *fmt, ...)
335d385153SJoe Perches {
345d385153SJoe Perches struct va_format vaf;
355d385153SJoe Perches va_list args;
365d385153SJoe Perches
375d385153SJoe Perches if ((p9_debug_level & level) != level)
385d385153SJoe Perches return;
395d385153SJoe Perches
405d385153SJoe Perches va_start(args, fmt);
415d385153SJoe Perches
425d385153SJoe Perches vaf.fmt = fmt;
435d385153SJoe Perches vaf.va = &args;
445d385153SJoe Perches
455d385153SJoe Perches if (level == P9_DEBUG_9P)
465d385153SJoe Perches pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf);
475d385153SJoe Perches else
485d385153SJoe Perches pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf);
495d385153SJoe Perches
505d385153SJoe Perches va_end(args);
515d385153SJoe Perches }
525d385153SJoe Perches EXPORT_SYMBOL(_p9_debug);
53bd238fb4SLatchesar Ionkov #endif
54bd238fb4SLatchesar Ionkov
556e195b0fSDominique Martinet /* Dynamic Transport Registration Routines */
56fb0466c3SEric Van Hensbergen
5772029fe8STejun Heo static DEFINE_SPINLOCK(v9fs_trans_lock);
58fb0466c3SEric Van Hensbergen static LIST_HEAD(v9fs_trans_list);
59fb0466c3SEric Van Hensbergen
60fb0466c3SEric Van Hensbergen /**
61fb0466c3SEric Van Hensbergen * v9fs_register_trans - register a new transport with 9p
62ee443996SEric Van Hensbergen * @m: structure describing the transport module and entry points
63fb0466c3SEric Van Hensbergen *
64fb0466c3SEric Van Hensbergen */
v9fs_register_trans(struct p9_trans_module * m)65fb0466c3SEric Van Hensbergen void v9fs_register_trans(struct p9_trans_module *m)
66fb0466c3SEric Van Hensbergen {
6772029fe8STejun Heo spin_lock(&v9fs_trans_lock);
68fb0466c3SEric Van Hensbergen list_add_tail(&m->list, &v9fs_trans_list);
6972029fe8STejun Heo spin_unlock(&v9fs_trans_lock);
70fb0466c3SEric Van Hensbergen }
71fb0466c3SEric Van Hensbergen EXPORT_SYMBOL(v9fs_register_trans);
72fb0466c3SEric Van Hensbergen
73fb0466c3SEric Van Hensbergen /**
7472029fe8STejun Heo * v9fs_unregister_trans - unregister a 9p transport
7572029fe8STejun Heo * @m: the transport to remove
7672029fe8STejun Heo *
7772029fe8STejun Heo */
v9fs_unregister_trans(struct p9_trans_module * m)7872029fe8STejun Heo void v9fs_unregister_trans(struct p9_trans_module *m)
7972029fe8STejun Heo {
8072029fe8STejun Heo spin_lock(&v9fs_trans_lock);
8172029fe8STejun Heo list_del_init(&m->list);
8272029fe8STejun Heo spin_unlock(&v9fs_trans_lock);
8372029fe8STejun Heo }
8472029fe8STejun Heo EXPORT_SYMBOL(v9fs_unregister_trans);
8572029fe8STejun Heo
_p9_get_trans_by_name(const char * s)86*019641d1SThomas Weißschuh static struct p9_trans_module *_p9_get_trans_by_name(const char *s)
87fb0466c3SEric Van Hensbergen {
8872029fe8STejun Heo struct p9_trans_module *t, *found = NULL;
89fb0466c3SEric Van Hensbergen
9072029fe8STejun Heo spin_lock(&v9fs_trans_lock);
9172029fe8STejun Heo
9272029fe8STejun Heo list_for_each_entry(t, &v9fs_trans_list, list)
934d63055fSPrem Karat if (strcmp(t->name, s) == 0 &&
9472029fe8STejun Heo try_module_get(t->owner)) {
9572029fe8STejun Heo found = t;
9672029fe8STejun Heo break;
97fb0466c3SEric Van Hensbergen }
9872029fe8STejun Heo
9972029fe8STejun Heo spin_unlock(&v9fs_trans_lock);
1004cd82a5bSThomas Weißschuh
1014cd82a5bSThomas Weißschuh return found;
1024cd82a5bSThomas Weißschuh }
1034cd82a5bSThomas Weißschuh
1044cd82a5bSThomas Weißschuh /**
1054cd82a5bSThomas Weißschuh * v9fs_get_trans_by_name - get transport with the matching name
1064cd82a5bSThomas Weißschuh * @s: string identifying transport
1074cd82a5bSThomas Weißschuh *
1084cd82a5bSThomas Weißschuh */
v9fs_get_trans_by_name(const char * s)109*019641d1SThomas Weißschuh struct p9_trans_module *v9fs_get_trans_by_name(const char *s)
1104cd82a5bSThomas Weißschuh {
1114cd82a5bSThomas Weißschuh struct p9_trans_module *found = NULL;
1124cd82a5bSThomas Weißschuh
1134cd82a5bSThomas Weißschuh found = _p9_get_trans_by_name(s);
1144cd82a5bSThomas Weißschuh
1154cd82a5bSThomas Weißschuh #ifdef CONFIG_MODULES
1164cd82a5bSThomas Weißschuh if (!found) {
1174cd82a5bSThomas Weißschuh request_module("9p-%s", s);
1184cd82a5bSThomas Weißschuh found = _p9_get_trans_by_name(s);
1194cd82a5bSThomas Weißschuh }
1204cd82a5bSThomas Weißschuh #endif
1214cd82a5bSThomas Weißschuh
12272029fe8STejun Heo return found;
123dd1a4584SLatchesar Ionkov }
12472029fe8STejun Heo EXPORT_SYMBOL(v9fs_get_trans_by_name);
125fb0466c3SEric Van Hensbergen
126*019641d1SThomas Weißschuh static const char * const v9fs_default_transports[] = {
127*019641d1SThomas Weißschuh "virtio", "tcp", "fd", "unix", "xen", "rdma",
128*019641d1SThomas Weißschuh };
129*019641d1SThomas Weißschuh
130fb0466c3SEric Van Hensbergen /**
13172029fe8STejun Heo * v9fs_get_default_trans - get the default transport
132fb0466c3SEric Van Hensbergen *
133fb0466c3SEric Van Hensbergen */
134fb0466c3SEric Van Hensbergen
v9fs_get_default_trans(void)13572029fe8STejun Heo struct p9_trans_module *v9fs_get_default_trans(void)
136fb0466c3SEric Van Hensbergen {
13772029fe8STejun Heo struct p9_trans_module *t, *found = NULL;
138*019641d1SThomas Weißschuh int i;
139fb0466c3SEric Van Hensbergen
14072029fe8STejun Heo spin_lock(&v9fs_trans_lock);
14172029fe8STejun Heo
14272029fe8STejun Heo list_for_each_entry(t, &v9fs_trans_list, list)
14372029fe8STejun Heo if (t->def && try_module_get(t->owner)) {
14472029fe8STejun Heo found = t;
14572029fe8STejun Heo break;
14672029fe8STejun Heo }
14772029fe8STejun Heo
14872029fe8STejun Heo if (!found)
14972029fe8STejun Heo list_for_each_entry(t, &v9fs_trans_list, list)
15072029fe8STejun Heo if (try_module_get(t->owner)) {
15172029fe8STejun Heo found = t;
15272029fe8STejun Heo break;
15372029fe8STejun Heo }
15472029fe8STejun Heo
15572029fe8STejun Heo spin_unlock(&v9fs_trans_lock);
156*019641d1SThomas Weißschuh
157*019641d1SThomas Weißschuh for (i = 0; !found && i < ARRAY_SIZE(v9fs_default_transports); i++)
158*019641d1SThomas Weißschuh found = v9fs_get_trans_by_name(v9fs_default_transports[i]);
159*019641d1SThomas Weißschuh
16072029fe8STejun Heo return found;
16172029fe8STejun Heo }
16272029fe8STejun Heo EXPORT_SYMBOL(v9fs_get_default_trans);
16372029fe8STejun Heo
16472029fe8STejun Heo /**
16572029fe8STejun Heo * v9fs_put_trans - put trans
16672029fe8STejun Heo * @m: transport to put
16772029fe8STejun Heo *
16872029fe8STejun Heo */
v9fs_put_trans(struct p9_trans_module * m)16972029fe8STejun Heo void v9fs_put_trans(struct p9_trans_module *m)
17072029fe8STejun Heo {
17172029fe8STejun Heo if (m)
17272029fe8STejun Heo module_put(m->owner);
17372029fe8STejun Heo }
174fb0466c3SEric Van Hensbergen
175bd238fb4SLatchesar Ionkov /**
176961a5a50SRob Landley * init_p9 - Initialize module
177bd238fb4SLatchesar Ionkov *
178bd238fb4SLatchesar Ionkov */
init_p9(void)179bd238fb4SLatchesar Ionkov static int __init init_p9(void)
180bd238fb4SLatchesar Ionkov {
181996d5b4dSMatthew Wilcox int ret;
182996d5b4dSMatthew Wilcox
183996d5b4dSMatthew Wilcox ret = p9_client_init();
184996d5b4dSMatthew Wilcox if (ret)
185996d5b4dSMatthew Wilcox return ret;
186996d5b4dSMatthew Wilcox
187bd238fb4SLatchesar Ionkov p9_error_init();
1885d385153SJoe Perches pr_info("Installing 9P2000 support\n");
189bd238fb4SLatchesar Ionkov
190996d5b4dSMatthew Wilcox return ret;
191bd238fb4SLatchesar Ionkov }
192bd238fb4SLatchesar Ionkov
193bd238fb4SLatchesar Ionkov /**
194961a5a50SRob Landley * exit_p9 - shutdown module
195bd238fb4SLatchesar Ionkov *
196bd238fb4SLatchesar Ionkov */
197bd238fb4SLatchesar Ionkov
exit_p9(void)198bd238fb4SLatchesar Ionkov static void __exit exit_p9(void)
199bd238fb4SLatchesar Ionkov {
2005d385153SJoe Perches pr_info("Unloading 9P2000 support\n");
20172029fe8STejun Heo
202996d5b4dSMatthew Wilcox p9_client_exit();
203bd238fb4SLatchesar Ionkov }
204bd238fb4SLatchesar Ionkov
205bd238fb4SLatchesar Ionkov module_init(init_p9)
206bd238fb4SLatchesar Ionkov module_exit(exit_p9)
207bd238fb4SLatchesar Ionkov
208bd238fb4SLatchesar Ionkov MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
209bd238fb4SLatchesar Ionkov MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
210bd238fb4SLatchesar Ionkov MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
211bd238fb4SLatchesar Ionkov MODULE_LICENSE("GPL");
21267c20de3SRob Gill MODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)");
213