server.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /* AFS server record management
  2. *
  3. * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/sched.h>
  12. #include <linux/slab.h>
  13. #include "internal.h"
  14. static unsigned afs_server_timeout = 10; /* server timeout in seconds */
  15. static void afs_reap_server(struct work_struct *);
  16. /* tree of all the servers, indexed by IP address */
  17. static struct rb_root afs_servers = RB_ROOT;
  18. static DEFINE_RWLOCK(afs_servers_lock);
  19. /* LRU list of all the servers not currently in use */
  20. static LIST_HEAD(afs_server_graveyard);
  21. static DEFINE_SPINLOCK(afs_server_graveyard_lock);
  22. static DECLARE_DELAYED_WORK(afs_server_reaper, afs_reap_server);
  23. /*
  24. * install a server record in the master tree
  25. */
  26. static int afs_install_server(struct afs_server *server)
  27. {
  28. struct afs_server *xserver;
  29. struct rb_node **pp, *p;
  30. int ret;
  31. _enter("%p", server);
  32. write_lock(&afs_servers_lock);
  33. ret = -EEXIST;
  34. pp = &afs_servers.rb_node;
  35. p = NULL;
  36. while (*pp) {
  37. p = *pp;
  38. _debug("- consider %p", p);
  39. xserver = rb_entry(p, struct afs_server, master_rb);
  40. if (server->addr.s_addr < xserver->addr.s_addr)
  41. pp = &(*pp)->rb_left;
  42. else if (server->addr.s_addr > xserver->addr.s_addr)
  43. pp = &(*pp)->rb_right;
  44. else
  45. goto error;
  46. }
  47. rb_link_node(&server->master_rb, p, pp);
  48. rb_insert_color(&server->master_rb, &afs_servers);
  49. ret = 0;
  50. error:
  51. write_unlock(&afs_servers_lock);
  52. return ret;
  53. }
  54. /*
  55. * allocate a new server record
  56. */
  57. static struct afs_server *afs_alloc_server(struct afs_cell *cell,
  58. const struct in_addr *addr)
  59. {
  60. struct afs_server *server;
  61. _enter("");
  62. server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
  63. if (server) {
  64. atomic_set(&server->usage, 1);
  65. server->cell = cell;
  66. INIT_LIST_HEAD(&server->link);
  67. INIT_LIST_HEAD(&server->grave);
  68. init_rwsem(&server->sem);
  69. spin_lock_init(&server->fs_lock);
  70. server->fs_vnodes = RB_ROOT;
  71. server->cb_promises = RB_ROOT;
  72. spin_lock_init(&server->cb_lock);
  73. init_waitqueue_head(&server->cb_break_waitq);
  74. INIT_DELAYED_WORK(&server->cb_break_work,
  75. afs_dispatch_give_up_callbacks);
  76. memcpy(&server->addr, addr, sizeof(struct in_addr));
  77. server->addr.s_addr = addr->s_addr;
  78. _leave(" = %p{%d}", server, atomic_read(&server->usage));
  79. } else {
  80. _leave(" = NULL [nomem]");
  81. }
  82. return server;
  83. }
  84. /*
  85. * get an FS-server record for a cell
  86. */
  87. struct afs_server *afs_lookup_server(struct afs_cell *cell,
  88. const struct in_addr *addr)
  89. {
  90. struct afs_server *server, *candidate;
  91. _enter("%p,%pI4", cell, &addr->s_addr);
  92. /* quick scan of the list to see if we already have the server */
  93. read_lock(&cell->servers_lock);
  94. list_for_each_entry(server, &cell->servers, link) {
  95. if (server->addr.s_addr == addr->s_addr)
  96. goto found_server_quickly;
  97. }
  98. read_unlock(&cell->servers_lock);
  99. candidate = afs_alloc_server(cell, addr);
  100. if (!candidate) {
  101. _leave(" = -ENOMEM");
  102. return ERR_PTR(-ENOMEM);
  103. }
  104. write_lock(&cell->servers_lock);
  105. /* check the cell's server list again */
  106. list_for_each_entry(server, &cell->servers, link) {
  107. if (server->addr.s_addr == addr->s_addr)
  108. goto found_server;
  109. }
  110. _debug("new");
  111. server = candidate;
  112. if (afs_install_server(server) < 0)
  113. goto server_in_two_cells;
  114. afs_get_cell(cell);
  115. list_add_tail(&server->link, &cell->servers);
  116. write_unlock(&cell->servers_lock);
  117. _leave(" = %p{%d}", server, atomic_read(&server->usage));
  118. return server;
  119. /* found a matching server quickly */
  120. found_server_quickly:
  121. _debug("found quickly");
  122. afs_get_server(server);
  123. read_unlock(&cell->servers_lock);
  124. no_longer_unused:
  125. if (!list_empty(&server->grave)) {
  126. spin_lock(&afs_server_graveyard_lock);
  127. list_del_init(&server->grave);
  128. spin_unlock(&afs_server_graveyard_lock);
  129. }
  130. _leave(" = %p{%d}", server, atomic_read(&server->usage));
  131. return server;
  132. /* found a matching server on the second pass */
  133. found_server:
  134. _debug("found");
  135. afs_get_server(server);
  136. write_unlock(&cell->servers_lock);
  137. kfree(candidate);
  138. goto no_longer_unused;
  139. /* found a server that seems to be in two cells */
  140. server_in_two_cells:
  141. write_unlock(&cell->servers_lock);
  142. kfree(candidate);
  143. printk(KERN_NOTICE "kAFS: Server %pI4 appears to be in two cells\n",
  144. addr);
  145. _leave(" = -EEXIST");
  146. return ERR_PTR(-EEXIST);
  147. }
  148. /*
  149. * look up a server by its IP address
  150. */
  151. struct afs_server *afs_find_server(const struct in_addr *_addr)
  152. {
  153. struct afs_server *server = NULL;
  154. struct rb_node *p;
  155. struct in_addr addr = *_addr;
  156. _enter("%pI4", &addr.s_addr);
  157. read_lock(&afs_servers_lock);
  158. p = afs_servers.rb_node;
  159. while (p) {
  160. server = rb_entry(p, struct afs_server, master_rb);
  161. _debug("- consider %p", p);
  162. if (addr.s_addr < server->addr.s_addr) {
  163. p = p->rb_left;
  164. } else if (addr.s_addr > server->addr.s_addr) {
  165. p = p->rb_right;
  166. } else {
  167. afs_get_server(server);
  168. goto found;
  169. }
  170. }
  171. server = NULL;
  172. found:
  173. read_unlock(&afs_servers_lock);
  174. ASSERTIFCMP(server, server->addr.s_addr, ==, addr.s_addr);
  175. _leave(" = %p", server);
  176. return server;
  177. }
  178. /*
  179. * destroy a server record
  180. * - removes from the cell list
  181. */
  182. void afs_put_server(struct afs_server *server)
  183. {
  184. if (!server)
  185. return;
  186. _enter("%p{%d}", server, atomic_read(&server->usage));
  187. _debug("PUT SERVER %d", atomic_read(&server->usage));
  188. ASSERTCMP(atomic_read(&server->usage), >, 0);
  189. if (likely(!atomic_dec_and_test(&server->usage))) {
  190. _leave("");
  191. return;
  192. }
  193. afs_flush_callback_breaks(server);
  194. spin_lock(&afs_server_graveyard_lock);
  195. if (atomic_read(&server->usage) == 0) {
  196. list_move_tail(&server->grave, &afs_server_graveyard);
  197. server->time_of_death = ktime_get_real_seconds();
  198. queue_delayed_work(afs_wq, &afs_server_reaper,
  199. afs_server_timeout * HZ);
  200. }
  201. spin_unlock(&afs_server_graveyard_lock);
  202. _leave(" [dead]");
  203. }
  204. /*
  205. * destroy a dead server
  206. */
  207. static void afs_destroy_server(struct afs_server *server)
  208. {
  209. _enter("%p", server);
  210. ASSERTIF(server->cb_break_head != server->cb_break_tail,
  211. delayed_work_pending(&server->cb_break_work));
  212. ASSERTCMP(server->fs_vnodes.rb_node, ==, NULL);
  213. ASSERTCMP(server->cb_promises.rb_node, ==, NULL);
  214. ASSERTCMP(server->cb_break_head, ==, server->cb_break_tail);
  215. ASSERTCMP(atomic_read(&server->cb_break_n), ==, 0);
  216. afs_put_cell(server->cell);
  217. kfree(server);
  218. }
  219. /*
  220. * reap dead server records
  221. */
  222. static void afs_reap_server(struct work_struct *work)
  223. {
  224. LIST_HEAD(corpses);
  225. struct afs_server *server;
  226. unsigned long delay, expiry;
  227. time64_t now;
  228. now = ktime_get_real_seconds();
  229. spin_lock(&afs_server_graveyard_lock);
  230. while (!list_empty(&afs_server_graveyard)) {
  231. server = list_entry(afs_server_graveyard.next,
  232. struct afs_server, grave);
  233. /* the queue is ordered most dead first */
  234. expiry = server->time_of_death + afs_server_timeout;
  235. if (expiry > now) {
  236. delay = (expiry - now) * HZ;
  237. mod_delayed_work(afs_wq, &afs_server_reaper, delay);
  238. break;
  239. }
  240. write_lock(&server->cell->servers_lock);
  241. write_lock(&afs_servers_lock);
  242. if (atomic_read(&server->usage) > 0) {
  243. list_del_init(&server->grave);
  244. } else {
  245. list_move_tail(&server->grave, &corpses);
  246. list_del_init(&server->link);
  247. rb_erase(&server->master_rb, &afs_servers);
  248. }
  249. write_unlock(&afs_servers_lock);
  250. write_unlock(&server->cell->servers_lock);
  251. }
  252. spin_unlock(&afs_server_graveyard_lock);
  253. /* now reap the corpses we've extracted */
  254. while (!list_empty(&corpses)) {
  255. server = list_entry(corpses.next, struct afs_server, grave);
  256. list_del(&server->grave);
  257. afs_destroy_server(server);
  258. }
  259. }
  260. /*
  261. * discard all the server records for rmmod
  262. */
  263. void __exit afs_purge_servers(void)
  264. {
  265. afs_server_timeout = 0;
  266. mod_delayed_work(afs_wq, &afs_server_reaper, 0);
  267. }