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