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 <[email protected]>
  6. * Copyright (C) 2004 by Eric Van Hensbergen <[email protected]>
  7. * Copyright (C) 2002 by Ron Minnich <[email protected]>
  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 <linux/parser.h>
  18. #include <net/9p/client.h>
  19. #include <net/9p/transport.h>
  20. #include <linux/list.h>
  21. #include <linux/spinlock.h>
  22. #ifdef CONFIG_NET_9P_DEBUG
  23. unsigned int p9_debug_level; /* feature-rific global debug level */
  24. EXPORT_SYMBOL(p9_debug_level);
  25. module_param_named(debug, p9_debug_level, uint, 0);
  26. MODULE_PARM_DESC(debug, "9P debugging level");
  27. void _p9_debug(enum p9_debug_flags level, const char *func,
  28. const char *fmt, ...)
  29. {
  30. struct va_format vaf;
  31. va_list args;
  32. if ((p9_debug_level & level) != level)
  33. return;
  34. va_start(args, fmt);
  35. vaf.fmt = fmt;
  36. vaf.va = &args;
  37. if (level == P9_DEBUG_9P)
  38. pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf);
  39. else
  40. pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf);
  41. va_end(args);
  42. }
  43. EXPORT_SYMBOL(_p9_debug);
  44. #endif
  45. /* Dynamic Transport Registration Routines */
  46. static DEFINE_SPINLOCK(v9fs_trans_lock);
  47. static LIST_HEAD(v9fs_trans_list);
  48. /**
  49. * v9fs_register_trans - register a new transport with 9p
  50. * @m: structure describing the transport module and entry points
  51. *
  52. */
  53. void v9fs_register_trans(struct p9_trans_module *m)
  54. {
  55. spin_lock(&v9fs_trans_lock);
  56. list_add_tail(&m->list, &v9fs_trans_list);
  57. spin_unlock(&v9fs_trans_lock);
  58. }
  59. EXPORT_SYMBOL(v9fs_register_trans);
  60. /**
  61. * v9fs_unregister_trans - unregister a 9p transport
  62. * @m: the transport to remove
  63. *
  64. */
  65. void v9fs_unregister_trans(struct p9_trans_module *m)
  66. {
  67. spin_lock(&v9fs_trans_lock);
  68. list_del_init(&m->list);
  69. spin_unlock(&v9fs_trans_lock);
  70. }
  71. EXPORT_SYMBOL(v9fs_unregister_trans);
  72. static struct p9_trans_module *_p9_get_trans_by_name(const char *s)
  73. {
  74. struct p9_trans_module *t, *found = NULL;
  75. spin_lock(&v9fs_trans_lock);
  76. list_for_each_entry(t, &v9fs_trans_list, list)
  77. if (strcmp(t->name, s) == 0 &&
  78. try_module_get(t->owner)) {
  79. found = t;
  80. break;
  81. }
  82. spin_unlock(&v9fs_trans_lock);
  83. return found;
  84. }
  85. /**
  86. * v9fs_get_trans_by_name - get transport with the matching name
  87. * @s: string identifying transport
  88. *
  89. */
  90. struct p9_trans_module *v9fs_get_trans_by_name(const char *s)
  91. {
  92. struct p9_trans_module *found = NULL;
  93. found = _p9_get_trans_by_name(s);
  94. #ifdef CONFIG_MODULES
  95. if (!found) {
  96. request_module("9p-%s", s);
  97. found = _p9_get_trans_by_name(s);
  98. }
  99. #endif
  100. return found;
  101. }
  102. EXPORT_SYMBOL(v9fs_get_trans_by_name);
  103. static const char * const v9fs_default_transports[] = {
  104. "virtio", "tcp", "fd", "unix", "xen", "rdma",
  105. };
  106. /**
  107. * v9fs_get_default_trans - get the default transport
  108. *
  109. */
  110. struct p9_trans_module *v9fs_get_default_trans(void)
  111. {
  112. struct p9_trans_module *t, *found = NULL;
  113. int i;
  114. spin_lock(&v9fs_trans_lock);
  115. list_for_each_entry(t, &v9fs_trans_list, list)
  116. if (t->def && try_module_get(t->owner)) {
  117. found = t;
  118. break;
  119. }
  120. if (!found)
  121. list_for_each_entry(t, &v9fs_trans_list, list)
  122. if (try_module_get(t->owner)) {
  123. found = t;
  124. break;
  125. }
  126. spin_unlock(&v9fs_trans_lock);
  127. for (i = 0; !found && i < ARRAY_SIZE(v9fs_default_transports); i++)
  128. found = v9fs_get_trans_by_name(v9fs_default_transports[i]);
  129. return found;
  130. }
  131. EXPORT_SYMBOL(v9fs_get_default_trans);
  132. /**
  133. * v9fs_put_trans - put trans
  134. * @m: transport to put
  135. *
  136. */
  137. void v9fs_put_trans(struct p9_trans_module *m)
  138. {
  139. if (m)
  140. module_put(m->owner);
  141. }
  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 <[email protected]>");
  168. MODULE_AUTHOR("Eric Van Hensbergen <[email protected]>");
  169. MODULE_AUTHOR("Ron Minnich <[email protected]>");
  170. MODULE_LICENSE("GPL");
  171. MODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)");