member.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /******************************************************************************
  2. *******************************************************************************
  3. **
  4. ** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
  5. **
  6. ** This copyrighted material is made available to anyone wishing to use,
  7. ** modify, copy, or redistribute it subject to the terms and conditions
  8. ** of the GNU General Public License v.2.
  9. **
  10. *******************************************************************************
  11. ******************************************************************************/
  12. #include "dlm_internal.h"
  13. #include "lockspace.h"
  14. #include "member.h"
  15. #include "recoverd.h"
  16. #include "recover.h"
  17. #include "lowcomms.h"
  18. #include "rcom.h"
  19. #include "config.h"
  20. /*
  21. * Following called by dlm_recoverd thread
  22. */
  23. static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new)
  24. {
  25. struct dlm_member *memb = NULL;
  26. struct list_head *tmp;
  27. struct list_head *newlist = &new->list;
  28. struct list_head *head = &ls->ls_nodes;
  29. list_for_each(tmp, head) {
  30. memb = list_entry(tmp, struct dlm_member, list);
  31. if (new->nodeid < memb->nodeid)
  32. break;
  33. }
  34. if (!memb)
  35. list_add_tail(newlist, head);
  36. else {
  37. /* FIXME: can use list macro here */
  38. newlist->prev = tmp->prev;
  39. newlist->next = tmp;
  40. tmp->prev->next = newlist;
  41. tmp->prev = newlist;
  42. }
  43. }
  44. static int dlm_add_member(struct dlm_ls *ls, int nodeid)
  45. {
  46. struct dlm_member *memb;
  47. int w;
  48. memb = kzalloc(sizeof(struct dlm_member), GFP_KERNEL);
  49. if (!memb)
  50. return -ENOMEM;
  51. w = dlm_node_weight(ls->ls_name, nodeid);
  52. if (w < 0)
  53. return w;
  54. memb->nodeid = nodeid;
  55. memb->weight = w;
  56. add_ordered_member(ls, memb);
  57. ls->ls_num_nodes++;
  58. return 0;
  59. }
  60. static void dlm_remove_member(struct dlm_ls *ls, struct dlm_member *memb)
  61. {
  62. list_move(&memb->list, &ls->ls_nodes_gone);
  63. ls->ls_num_nodes--;
  64. }
  65. static int dlm_is_member(struct dlm_ls *ls, int nodeid)
  66. {
  67. struct dlm_member *memb;
  68. list_for_each_entry(memb, &ls->ls_nodes, list) {
  69. if (memb->nodeid == nodeid)
  70. return 1;
  71. }
  72. return 0;
  73. }
  74. int dlm_is_removed(struct dlm_ls *ls, int nodeid)
  75. {
  76. struct dlm_member *memb;
  77. list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
  78. if (memb->nodeid == nodeid)
  79. return 1;
  80. }
  81. return 0;
  82. }
  83. static void clear_memb_list(struct list_head *head)
  84. {
  85. struct dlm_member *memb;
  86. while (!list_empty(head)) {
  87. memb = list_entry(head->next, struct dlm_member, list);
  88. list_del(&memb->list);
  89. kfree(memb);
  90. }
  91. }
  92. void dlm_clear_members(struct dlm_ls *ls)
  93. {
  94. clear_memb_list(&ls->ls_nodes);
  95. ls->ls_num_nodes = 0;
  96. }
  97. void dlm_clear_members_gone(struct dlm_ls *ls)
  98. {
  99. clear_memb_list(&ls->ls_nodes_gone);
  100. }
  101. static void make_member_array(struct dlm_ls *ls)
  102. {
  103. struct dlm_member *memb;
  104. int i, w, x = 0, total = 0, all_zero = 0, *array;
  105. kfree(ls->ls_node_array);
  106. ls->ls_node_array = NULL;
  107. list_for_each_entry(memb, &ls->ls_nodes, list) {
  108. if (memb->weight)
  109. total += memb->weight;
  110. }
  111. /* all nodes revert to weight of 1 if all have weight 0 */
  112. if (!total) {
  113. total = ls->ls_num_nodes;
  114. all_zero = 1;
  115. }
  116. ls->ls_total_weight = total;
  117. array = kmalloc(sizeof(int) * total, GFP_KERNEL);
  118. if (!array)
  119. return;
  120. list_for_each_entry(memb, &ls->ls_nodes, list) {
  121. if (!all_zero && !memb->weight)
  122. continue;
  123. if (all_zero)
  124. w = 1;
  125. else
  126. w = memb->weight;
  127. DLM_ASSERT(x < total, printk("total %d x %d\n", total, x););
  128. for (i = 0; i < w; i++)
  129. array[x++] = memb->nodeid;
  130. }
  131. ls->ls_node_array = array;
  132. }
  133. /* send a status request to all members just to establish comms connections */
  134. static void ping_members(struct dlm_ls *ls)
  135. {
  136. struct dlm_member *memb;
  137. list_for_each_entry(memb, &ls->ls_nodes, list)
  138. dlm_rcom_status(ls, memb->nodeid);
  139. }
  140. int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
  141. {
  142. struct dlm_member *memb, *safe;
  143. int i, error, found, pos = 0, neg = 0, low = -1;
  144. /* move departed members from ls_nodes to ls_nodes_gone */
  145. list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) {
  146. found = 0;
  147. for (i = 0; i < rv->node_count; i++) {
  148. if (memb->nodeid == rv->nodeids[i]) {
  149. found = 1;
  150. break;
  151. }
  152. }
  153. if (!found) {
  154. neg++;
  155. dlm_remove_member(ls, memb);
  156. log_debug(ls, "remove member %d", memb->nodeid);
  157. }
  158. }
  159. /* add new members to ls_nodes */
  160. for (i = 0; i < rv->node_count; i++) {
  161. if (dlm_is_member(ls, rv->nodeids[i]))
  162. continue;
  163. dlm_add_member(ls, rv->nodeids[i]);
  164. pos++;
  165. log_debug(ls, "add member %d", rv->nodeids[i]);
  166. }
  167. list_for_each_entry(memb, &ls->ls_nodes, list) {
  168. if (low == -1 || memb->nodeid < low)
  169. low = memb->nodeid;
  170. }
  171. ls->ls_low_nodeid = low;
  172. make_member_array(ls);
  173. dlm_set_recover_status(ls, DLM_RS_NODES);
  174. *neg_out = neg;
  175. ping_members(ls);
  176. error = dlm_recover_members_wait(ls);
  177. log_debug(ls, "total members %d", ls->ls_num_nodes);
  178. return error;
  179. }
  180. /*
  181. * Following called from lockspace.c
  182. */
  183. int dlm_ls_stop(struct dlm_ls *ls)
  184. {
  185. int new;
  186. /*
  187. * A stop cancels any recovery that's in progress (see RECOVERY_STOP,
  188. * dlm_recovery_stopped()) and prevents any new locks from being
  189. * processed (see RUNNING, dlm_locking_stopped()).
  190. */
  191. spin_lock(&ls->ls_recover_lock);
  192. set_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
  193. new = test_and_clear_bit(LSFL_RUNNING, &ls->ls_flags);
  194. ls->ls_recover_seq++;
  195. spin_unlock(&ls->ls_recover_lock);
  196. /*
  197. * This in_recovery lock does two things:
  198. *
  199. * 1) Keeps this function from returning until all threads are out
  200. * of locking routines and locking is truely stopped.
  201. * 2) Keeps any new requests from being processed until it's unlocked
  202. * when recovery is complete.
  203. */
  204. if (new)
  205. down_write(&ls->ls_in_recovery);
  206. /*
  207. * The recoverd suspend/resume makes sure that dlm_recoverd (if
  208. * running) has noticed the clearing of RUNNING above and quit
  209. * processing the previous recovery. This will be true for all nodes
  210. * before any nodes start the new recovery.
  211. */
  212. dlm_recoverd_suspend(ls);
  213. ls->ls_recover_status = 0;
  214. dlm_recoverd_resume(ls);
  215. return 0;
  216. }
  217. int dlm_ls_start(struct dlm_ls *ls)
  218. {
  219. struct dlm_recover *rv = NULL, *rv_old;
  220. int *ids = NULL;
  221. int error, count;
  222. rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
  223. if (!rv)
  224. return -ENOMEM;
  225. error = count = dlm_nodeid_list(ls->ls_name, &ids);
  226. if (error <= 0)
  227. goto fail;
  228. spin_lock(&ls->ls_recover_lock);
  229. /* the lockspace needs to be stopped before it can be started */
  230. if (!dlm_locking_stopped(ls)) {
  231. spin_unlock(&ls->ls_recover_lock);
  232. log_error(ls, "start ignored: lockspace running");
  233. error = -EINVAL;
  234. goto fail;
  235. }
  236. rv->nodeids = ids;
  237. rv->node_count = count;
  238. rv->seq = ++ls->ls_recover_seq;
  239. rv_old = ls->ls_recover_args;
  240. ls->ls_recover_args = rv;
  241. spin_unlock(&ls->ls_recover_lock);
  242. if (rv_old) {
  243. kfree(rv_old->nodeids);
  244. kfree(rv_old);
  245. }
  246. dlm_recoverd_kick(ls);
  247. return 0;
  248. fail:
  249. kfree(rv);
  250. kfree(ids);
  251. return error;
  252. }