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