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