162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 9P entry point 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 662306a36Sopenharmony_ci * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 762306a36Sopenharmony_ci * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/kmod.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci#include <linux/sched.h> 1662306a36Sopenharmony_ci#include <linux/moduleparam.h> 1762306a36Sopenharmony_ci#include <net/9p/9p.h> 1862306a36Sopenharmony_ci#include <linux/fs.h> 1962306a36Sopenharmony_ci#include <linux/parser.h> 2062306a36Sopenharmony_ci#include <net/9p/client.h> 2162306a36Sopenharmony_ci#include <net/9p/transport.h> 2262306a36Sopenharmony_ci#include <linux/list.h> 2362306a36Sopenharmony_ci#include <linux/spinlock.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#ifdef CONFIG_NET_9P_DEBUG 2662306a36Sopenharmony_ciunsigned int p9_debug_level; /* feature-rific global debug level */ 2762306a36Sopenharmony_ciEXPORT_SYMBOL(p9_debug_level); 2862306a36Sopenharmony_cimodule_param_named(debug, p9_debug_level, uint, 0); 2962306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "9P debugging level"); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_civoid _p9_debug(enum p9_debug_flags level, const char *func, 3262306a36Sopenharmony_ci const char *fmt, ...) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct va_format vaf; 3562306a36Sopenharmony_ci va_list args; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if ((p9_debug_level & level) != level) 3862306a36Sopenharmony_ci return; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci va_start(args, fmt); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci vaf.fmt = fmt; 4362306a36Sopenharmony_ci vaf.va = &args; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (level == P9_DEBUG_9P) 4662306a36Sopenharmony_ci pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf); 4762306a36Sopenharmony_ci else 4862306a36Sopenharmony_ci pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci va_end(args); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ciEXPORT_SYMBOL(_p9_debug); 5362306a36Sopenharmony_ci#endif 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* Dynamic Transport Registration Routines */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic DEFINE_SPINLOCK(v9fs_trans_lock); 5862306a36Sopenharmony_cistatic LIST_HEAD(v9fs_trans_list); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * v9fs_register_trans - register a new transport with 9p 6262306a36Sopenharmony_ci * @m: structure describing the transport module and entry points 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_civoid v9fs_register_trans(struct p9_trans_module *m) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci spin_lock(&v9fs_trans_lock); 6862306a36Sopenharmony_ci list_add_tail(&m->list, &v9fs_trans_list); 6962306a36Sopenharmony_ci spin_unlock(&v9fs_trans_lock); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ciEXPORT_SYMBOL(v9fs_register_trans); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/** 7462306a36Sopenharmony_ci * v9fs_unregister_trans - unregister a 9p transport 7562306a36Sopenharmony_ci * @m: the transport to remove 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_civoid v9fs_unregister_trans(struct p9_trans_module *m) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci spin_lock(&v9fs_trans_lock); 8162306a36Sopenharmony_ci list_del_init(&m->list); 8262306a36Sopenharmony_ci spin_unlock(&v9fs_trans_lock); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ciEXPORT_SYMBOL(v9fs_unregister_trans); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic struct p9_trans_module *_p9_get_trans_by_name(const char *s) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct p9_trans_module *t, *found = NULL; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci spin_lock(&v9fs_trans_lock); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci list_for_each_entry(t, &v9fs_trans_list, list) 9362306a36Sopenharmony_ci if (strcmp(t->name, s) == 0 && 9462306a36Sopenharmony_ci try_module_get(t->owner)) { 9562306a36Sopenharmony_ci found = t; 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci spin_unlock(&v9fs_trans_lock); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return found; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/** 10562306a36Sopenharmony_ci * v9fs_get_trans_by_name - get transport with the matching name 10662306a36Sopenharmony_ci * @s: string identifying transport 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_cistruct p9_trans_module *v9fs_get_trans_by_name(const char *s) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct p9_trans_module *found = NULL; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci found = _p9_get_trans_by_name(s); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#ifdef CONFIG_MODULES 11662306a36Sopenharmony_ci if (!found) { 11762306a36Sopenharmony_ci request_module("9p-%s", s); 11862306a36Sopenharmony_ci found = _p9_get_trans_by_name(s); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return found; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ciEXPORT_SYMBOL(v9fs_get_trans_by_name); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic const char * const v9fs_default_transports[] = { 12762306a36Sopenharmony_ci "virtio", "tcp", "fd", "unix", "xen", "rdma", 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/** 13162306a36Sopenharmony_ci * v9fs_get_default_trans - get the default transport 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistruct p9_trans_module *v9fs_get_default_trans(void) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct p9_trans_module *t, *found = NULL; 13862306a36Sopenharmony_ci int i; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci spin_lock(&v9fs_trans_lock); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci list_for_each_entry(t, &v9fs_trans_list, list) 14362306a36Sopenharmony_ci if (t->def && try_module_get(t->owner)) { 14462306a36Sopenharmony_ci found = t; 14562306a36Sopenharmony_ci break; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (!found) 14962306a36Sopenharmony_ci list_for_each_entry(t, &v9fs_trans_list, list) 15062306a36Sopenharmony_ci if (try_module_get(t->owner)) { 15162306a36Sopenharmony_ci found = t; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci spin_unlock(&v9fs_trans_lock); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci for (i = 0; !found && i < ARRAY_SIZE(v9fs_default_transports); i++) 15862306a36Sopenharmony_ci found = v9fs_get_trans_by_name(v9fs_default_transports[i]); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return found; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ciEXPORT_SYMBOL(v9fs_get_default_trans); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/** 16562306a36Sopenharmony_ci * v9fs_put_trans - put trans 16662306a36Sopenharmony_ci * @m: transport to put 16762306a36Sopenharmony_ci * 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_civoid v9fs_put_trans(struct p9_trans_module *m) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci if (m) 17262306a36Sopenharmony_ci module_put(m->owner); 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/** 17662306a36Sopenharmony_ci * init_p9 - Initialize module 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_cistatic int __init init_p9(void) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci int ret; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci ret = p9_client_init(); 18462306a36Sopenharmony_ci if (ret) 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci p9_error_init(); 18862306a36Sopenharmony_ci pr_info("Installing 9P2000 support\n"); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/** 19462306a36Sopenharmony_ci * exit_p9 - shutdown module 19562306a36Sopenharmony_ci * 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic void __exit exit_p9(void) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci pr_info("Unloading 9P2000 support\n"); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci p9_client_exit(); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cimodule_init(init_p9) 20662306a36Sopenharmony_cimodule_exit(exit_p9) 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ciMODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); 20962306a36Sopenharmony_ciMODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 21062306a36Sopenharmony_ciMODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 21162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 21262306a36Sopenharmony_ciMODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)"); 213