user_reg.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * net/tipc/user_reg.c: TIPC user registry code
  3. *
  4. * Copyright (c) 2003-2005, Ericsson Research Canada
  5. * Copyright (c) 2004-2005, Wind River Systems
  6. * Copyright (c) 2005-2006, Ericsson AB
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the names of the copyright holders nor the names of its
  18. * contributors may be used to endorse or promote products derived from
  19. * this software without specific prior written permission.
  20. *
  21. * Alternatively, this software may be distributed under the terms of the
  22. * GNU General Public License ("GPL") version 2 as published by the Free
  23. * Software Foundation.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include "core.h"
  38. #include "user_reg.h"
  39. /*
  40. * TIPC user registry keeps track of users of the tipc_port interface.
  41. *
  42. * The registry utilizes an array of "TIPC user" entries;
  43. * a user's ID is the index of their associated array entry.
  44. * Array entry 0 is not used, so userid 0 is not valid;
  45. * TIPC sometimes uses this value to denote an anonymous user.
  46. * The list of free entries is initially chained from last entry to entry 1.
  47. */
  48. /**
  49. * struct tipc_user - registered TIPC user info
  50. * @next: index of next free registry entry (or -1 for an allocated entry)
  51. * @callback: ptr to routine to call when TIPC mode changes (NULL if none)
  52. * @usr_handle: user-defined value passed to callback routine
  53. * @ports: list of user ports owned by the user
  54. */
  55. struct tipc_user {
  56. int next;
  57. tipc_mode_event callback;
  58. void *usr_handle;
  59. struct list_head ports;
  60. };
  61. #define MAX_USERID 64
  62. #define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user))
  63. static struct tipc_user *users = 0;
  64. static u32 next_free_user = MAX_USERID + 1;
  65. static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
  66. /**
  67. * reg_init - create TIPC user registry (but don't activate it)
  68. *
  69. * If registry has been pre-initialized it is left "as is".
  70. * NOTE: This routine may be called when TIPC is inactive.
  71. */
  72. static int reg_init(void)
  73. {
  74. u32 i;
  75. spin_lock_bh(&reg_lock);
  76. if (!users) {
  77. users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC);
  78. if (users) {
  79. memset(users, 0, USER_LIST_SIZE);
  80. for (i = 1; i <= MAX_USERID; i++) {
  81. users[i].next = i - 1;
  82. }
  83. next_free_user = MAX_USERID;
  84. }
  85. }
  86. spin_unlock_bh(&reg_lock);
  87. return users ? TIPC_OK : -ENOMEM;
  88. }
  89. /**
  90. * reg_callback - inform TIPC user about current operating mode
  91. */
  92. static void reg_callback(struct tipc_user *user_ptr)
  93. {
  94. tipc_mode_event cb;
  95. void *arg;
  96. spin_lock_bh(&reg_lock);
  97. cb = user_ptr->callback;
  98. arg = user_ptr->usr_handle;
  99. spin_unlock_bh(&reg_lock);
  100. if (cb)
  101. cb(arg, tipc_mode, tipc_own_addr);
  102. }
  103. /**
  104. * reg_start - activate TIPC user registry
  105. */
  106. int reg_start(void)
  107. {
  108. u32 u;
  109. int res;
  110. if ((res = reg_init()))
  111. return res;
  112. for (u = 1; u <= MAX_USERID; u++) {
  113. if (users[u].callback)
  114. k_signal((Handler)reg_callback,
  115. (unsigned long)&users[u]);
  116. }
  117. return TIPC_OK;
  118. }
  119. /**
  120. * reg_stop - shut down & delete TIPC user registry
  121. */
  122. void reg_stop(void)
  123. {
  124. int id;
  125. if (!users)
  126. return;
  127. for (id = 1; id <= MAX_USERID; id++) {
  128. if (users[id].callback)
  129. reg_callback(&users[id]);
  130. }
  131. kfree(users);
  132. users = 0;
  133. }
  134. /**
  135. * tipc_attach - register a TIPC user
  136. *
  137. * NOTE: This routine may be called when TIPC is inactive.
  138. */
  139. int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle)
  140. {
  141. struct tipc_user *user_ptr;
  142. if ((tipc_mode == TIPC_NOT_RUNNING) && !cb)
  143. return -ENOPROTOOPT;
  144. if (!users)
  145. reg_init();
  146. spin_lock_bh(&reg_lock);
  147. if (!next_free_user) {
  148. spin_unlock_bh(&reg_lock);
  149. return -EBUSY;
  150. }
  151. user_ptr = &users[next_free_user];
  152. *userid = next_free_user;
  153. next_free_user = user_ptr->next;
  154. user_ptr->next = -1;
  155. spin_unlock_bh(&reg_lock);
  156. user_ptr->callback = cb;
  157. user_ptr->usr_handle = usr_handle;
  158. INIT_LIST_HEAD(&user_ptr->ports);
  159. atomic_inc(&tipc_user_count);
  160. if (cb && (tipc_mode != TIPC_NOT_RUNNING))
  161. k_signal((Handler)reg_callback, (unsigned long)user_ptr);
  162. return TIPC_OK;
  163. }
  164. /**
  165. * tipc_detach - deregister a TIPC user
  166. */
  167. void tipc_detach(u32 userid)
  168. {
  169. struct tipc_user *user_ptr;
  170. struct list_head ports_temp;
  171. struct user_port *up_ptr, *temp_up_ptr;
  172. if ((userid == 0) || (userid > MAX_USERID))
  173. return;
  174. spin_lock_bh(&reg_lock);
  175. if ((!users) || (users[userid].next >= 0)) {
  176. spin_unlock_bh(&reg_lock);
  177. return;
  178. }
  179. user_ptr = &users[userid];
  180. user_ptr->callback = NULL;
  181. INIT_LIST_HEAD(&ports_temp);
  182. list_splice(&user_ptr->ports, &ports_temp);
  183. user_ptr->next = next_free_user;
  184. next_free_user = userid;
  185. spin_unlock_bh(&reg_lock);
  186. atomic_dec(&tipc_user_count);
  187. list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
  188. tipc_deleteport(up_ptr->ref);
  189. }
  190. }
  191. /**
  192. * reg_add_port - register a user's driver port
  193. */
  194. int reg_add_port(struct user_port *up_ptr)
  195. {
  196. struct tipc_user *user_ptr;
  197. if (up_ptr->user_ref == 0)
  198. return TIPC_OK;
  199. if (up_ptr->user_ref > MAX_USERID)
  200. return -EINVAL;
  201. if ((tipc_mode == TIPC_NOT_RUNNING) || !users )
  202. return -ENOPROTOOPT;
  203. spin_lock_bh(&reg_lock);
  204. user_ptr = &users[up_ptr->user_ref];
  205. list_add(&up_ptr->uport_list, &user_ptr->ports);
  206. spin_unlock_bh(&reg_lock);
  207. return TIPC_OK;
  208. }
  209. /**
  210. * reg_remove_port - deregister a user's driver port
  211. */
  212. int reg_remove_port(struct user_port *up_ptr)
  213. {
  214. if (up_ptr->user_ref == 0)
  215. return TIPC_OK;
  216. if (up_ptr->user_ref > MAX_USERID)
  217. return -EINVAL;
  218. if (!users )
  219. return -ENOPROTOOPT;
  220. spin_lock_bh(&reg_lock);
  221. list_del_init(&up_ptr->uport_list);
  222. spin_unlock_bh(&reg_lock);
  223. return TIPC_OK;
  224. }