18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  net/9p/9p.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  9P entry point
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
88c2ecf20Sopenharmony_ci *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
98c2ecf20Sopenharmony_ci *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/errno.h>
168c2ecf20Sopenharmony_ci#include <linux/sched.h>
178c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
188c2ecf20Sopenharmony_ci#include <net/9p/9p.h>
198c2ecf20Sopenharmony_ci#include <linux/fs.h>
208c2ecf20Sopenharmony_ci#include <linux/parser.h>
218c2ecf20Sopenharmony_ci#include <net/9p/client.h>
228c2ecf20Sopenharmony_ci#include <net/9p/transport.h>
238c2ecf20Sopenharmony_ci#include <linux/list.h>
248c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_9P_DEBUG
278c2ecf20Sopenharmony_ciunsigned int p9_debug_level = 0;	/* feature-rific global debug level  */
288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(p9_debug_level);
298c2ecf20Sopenharmony_cimodule_param_named(debug, p9_debug_level, uint, 0);
308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "9P debugging level");
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_civoid _p9_debug(enum p9_debug_flags level, const char *func,
338c2ecf20Sopenharmony_ci		const char *fmt, ...)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	struct va_format vaf;
368c2ecf20Sopenharmony_ci	va_list args;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	if ((p9_debug_level & level) != level)
398c2ecf20Sopenharmony_ci		return;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	va_start(args, fmt);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
448c2ecf20Sopenharmony_ci	vaf.va = &args;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	if (level == P9_DEBUG_9P)
478c2ecf20Sopenharmony_ci		pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf);
488c2ecf20Sopenharmony_ci	else
498c2ecf20Sopenharmony_ci		pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	va_end(args);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(_p9_debug);
548c2ecf20Sopenharmony_ci#endif
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/*
578c2ecf20Sopenharmony_ci * Dynamic Transport Registration Routines
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(v9fs_trans_lock);
628c2ecf20Sopenharmony_cistatic LIST_HEAD(v9fs_trans_list);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/**
658c2ecf20Sopenharmony_ci * v9fs_register_trans - register a new transport with 9p
668c2ecf20Sopenharmony_ci * @m: structure describing the transport module and entry points
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_civoid v9fs_register_trans(struct p9_trans_module *m)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	spin_lock(&v9fs_trans_lock);
728c2ecf20Sopenharmony_ci	list_add_tail(&m->list, &v9fs_trans_list);
738c2ecf20Sopenharmony_ci	spin_unlock(&v9fs_trans_lock);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v9fs_register_trans);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci/**
788c2ecf20Sopenharmony_ci * v9fs_unregister_trans - unregister a 9p transport
798c2ecf20Sopenharmony_ci * @m: the transport to remove
808c2ecf20Sopenharmony_ci *
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_civoid v9fs_unregister_trans(struct p9_trans_module *m)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	spin_lock(&v9fs_trans_lock);
858c2ecf20Sopenharmony_ci	list_del_init(&m->list);
868c2ecf20Sopenharmony_ci	spin_unlock(&v9fs_trans_lock);
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v9fs_unregister_trans);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/**
918c2ecf20Sopenharmony_ci * v9fs_get_trans_by_name - get transport with the matching name
928c2ecf20Sopenharmony_ci * @s: string identifying transport
938c2ecf20Sopenharmony_ci *
948c2ecf20Sopenharmony_ci */
958c2ecf20Sopenharmony_cistruct p9_trans_module *v9fs_get_trans_by_name(char *s)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	struct p9_trans_module *t, *found = NULL;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	spin_lock(&v9fs_trans_lock);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	list_for_each_entry(t, &v9fs_trans_list, list)
1028c2ecf20Sopenharmony_ci		if (strcmp(t->name, s) == 0 &&
1038c2ecf20Sopenharmony_ci		    try_module_get(t->owner)) {
1048c2ecf20Sopenharmony_ci			found = t;
1058c2ecf20Sopenharmony_ci			break;
1068c2ecf20Sopenharmony_ci		}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	spin_unlock(&v9fs_trans_lock);
1098c2ecf20Sopenharmony_ci	return found;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v9fs_get_trans_by_name);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/**
1148c2ecf20Sopenharmony_ci * v9fs_get_default_trans - get the default transport
1158c2ecf20Sopenharmony_ci *
1168c2ecf20Sopenharmony_ci */
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistruct p9_trans_module *v9fs_get_default_trans(void)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct p9_trans_module *t, *found = NULL;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	spin_lock(&v9fs_trans_lock);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	list_for_each_entry(t, &v9fs_trans_list, list)
1258c2ecf20Sopenharmony_ci		if (t->def && try_module_get(t->owner)) {
1268c2ecf20Sopenharmony_ci			found = t;
1278c2ecf20Sopenharmony_ci			break;
1288c2ecf20Sopenharmony_ci		}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (!found)
1318c2ecf20Sopenharmony_ci		list_for_each_entry(t, &v9fs_trans_list, list)
1328c2ecf20Sopenharmony_ci			if (try_module_get(t->owner)) {
1338c2ecf20Sopenharmony_ci				found = t;
1348c2ecf20Sopenharmony_ci				break;
1358c2ecf20Sopenharmony_ci			}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	spin_unlock(&v9fs_trans_lock);
1388c2ecf20Sopenharmony_ci	return found;
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v9fs_get_default_trans);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/**
1438c2ecf20Sopenharmony_ci * v9fs_put_trans - put trans
1448c2ecf20Sopenharmony_ci * @m: transport to put
1458c2ecf20Sopenharmony_ci *
1468c2ecf20Sopenharmony_ci */
1478c2ecf20Sopenharmony_civoid v9fs_put_trans(struct p9_trans_module *m)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	if (m)
1508c2ecf20Sopenharmony_ci		module_put(m->owner);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/**
1548c2ecf20Sopenharmony_ci * init_p9 - Initialize module
1558c2ecf20Sopenharmony_ci *
1568c2ecf20Sopenharmony_ci */
1578c2ecf20Sopenharmony_cistatic int __init init_p9(void)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	int ret;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	ret = p9_client_init();
1628c2ecf20Sopenharmony_ci	if (ret)
1638c2ecf20Sopenharmony_ci		return ret;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	p9_error_init();
1668c2ecf20Sopenharmony_ci	pr_info("Installing 9P2000 support\n");
1678c2ecf20Sopenharmony_ci	p9_trans_fd_init();
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	return ret;
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/**
1738c2ecf20Sopenharmony_ci * exit_p9 - shutdown module
1748c2ecf20Sopenharmony_ci *
1758c2ecf20Sopenharmony_ci */
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic void __exit exit_p9(void)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	pr_info("Unloading 9P2000 support\n");
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	p9_trans_fd_exit();
1828c2ecf20Sopenharmony_ci	p9_client_exit();
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cimodule_init(init_p9)
1868c2ecf20Sopenharmony_cimodule_exit(exit_p9)
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ciMODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
1898c2ecf20Sopenharmony_ciMODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
1908c2ecf20Sopenharmony_ciMODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
1918c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1928c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)");
193