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