mod.c 4.3 KB

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