ast.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /******************************************************************************
  2. *******************************************************************************
  3. **
  4. ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
  5. ** Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
  6. **
  7. ** This copyrighted material is made available to anyone wishing to use,
  8. ** modify, copy, or redistribute it subject to the terms and conditions
  9. ** of the GNU General Public License v.2.
  10. **
  11. *******************************************************************************
  12. ******************************************************************************/
  13. #include "dlm_internal.h"
  14. #include "lock.h"
  15. #include "user.h"
  16. #include "ast.h"
  17. #define WAKE_ASTS 0
  18. static struct list_head ast_queue;
  19. static spinlock_t ast_queue_lock;
  20. static struct task_struct * astd_task;
  21. static unsigned long astd_wakeflags;
  22. static struct mutex astd_running;
  23. void dlm_del_ast(struct dlm_lkb *lkb)
  24. {
  25. spin_lock(&ast_queue_lock);
  26. if (lkb->lkb_ast_type & (AST_COMP | AST_BAST))
  27. list_del(&lkb->lkb_astqueue);
  28. spin_unlock(&ast_queue_lock);
  29. }
  30. void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode)
  31. {
  32. if (lkb->lkb_flags & DLM_IFL_USER) {
  33. dlm_user_add_ast(lkb, type, mode);
  34. return;
  35. }
  36. spin_lock(&ast_queue_lock);
  37. if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
  38. kref_get(&lkb->lkb_ref);
  39. list_add_tail(&lkb->lkb_astqueue, &ast_queue);
  40. lkb->lkb_ast_first = type;
  41. }
  42. /* sanity check, this should not happen */
  43. if ((type == AST_COMP) && (lkb->lkb_ast_type & AST_COMP))
  44. log_print("repeat cast %d castmode %d lock %x %s",
  45. mode, lkb->lkb_castmode,
  46. lkb->lkb_id, lkb->lkb_resource->res_name);
  47. lkb->lkb_ast_type |= type;
  48. if (type == AST_BAST)
  49. lkb->lkb_bastmode = mode;
  50. else
  51. lkb->lkb_castmode = mode;
  52. spin_unlock(&ast_queue_lock);
  53. set_bit(WAKE_ASTS, &astd_wakeflags);
  54. wake_up_process(astd_task);
  55. }
  56. static void process_asts(void)
  57. {
  58. struct dlm_ls *ls = NULL;
  59. struct dlm_rsb *r = NULL;
  60. struct dlm_lkb *lkb;
  61. void (*castfn) (void *astparam);
  62. void (*bastfn) (void *astparam, int mode);
  63. int type, first, bastmode, castmode, do_bast, do_cast, last_castmode;
  64. repeat:
  65. spin_lock(&ast_queue_lock);
  66. list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
  67. r = lkb->lkb_resource;
  68. ls = r->res_ls;
  69. if (dlm_locking_stopped(ls))
  70. continue;
  71. list_del(&lkb->lkb_astqueue);
  72. type = lkb->lkb_ast_type;
  73. lkb->lkb_ast_type = 0;
  74. first = lkb->lkb_ast_first;
  75. lkb->lkb_ast_first = 0;
  76. bastmode = lkb->lkb_bastmode;
  77. castmode = lkb->lkb_castmode;
  78. castfn = lkb->lkb_astfn;
  79. bastfn = lkb->lkb_bastfn;
  80. spin_unlock(&ast_queue_lock);
  81. do_cast = (type & AST_COMP) && castfn;
  82. do_bast = (type & AST_BAST) && bastfn;
  83. /* Skip a bast if its blocking mode is compatible with the
  84. granted mode of the preceding cast. */
  85. if (do_bast) {
  86. if (first == AST_COMP)
  87. last_castmode = castmode;
  88. else
  89. last_castmode = lkb->lkb_castmode_done;
  90. if (dlm_modes_compat(bastmode, last_castmode))
  91. do_bast = 0;
  92. }
  93. if (first == AST_COMP) {
  94. if (do_cast)
  95. castfn(lkb->lkb_astparam);
  96. if (do_bast)
  97. bastfn(lkb->lkb_astparam, bastmode);
  98. } else if (first == AST_BAST) {
  99. if (do_bast)
  100. bastfn(lkb->lkb_astparam, bastmode);
  101. if (do_cast)
  102. castfn(lkb->lkb_astparam);
  103. } else {
  104. log_error(ls, "bad ast_first %d ast_type %d",
  105. first, type);
  106. }
  107. if (do_cast)
  108. lkb->lkb_castmode_done = castmode;
  109. if (do_bast)
  110. lkb->lkb_bastmode_done = bastmode;
  111. /* this removes the reference added by dlm_add_ast
  112. and may result in the lkb being freed */
  113. dlm_put_lkb(lkb);
  114. cond_resched();
  115. goto repeat;
  116. }
  117. spin_unlock(&ast_queue_lock);
  118. }
  119. static inline int no_asts(void)
  120. {
  121. int ret;
  122. spin_lock(&ast_queue_lock);
  123. ret = list_empty(&ast_queue);
  124. spin_unlock(&ast_queue_lock);
  125. return ret;
  126. }
  127. static int dlm_astd(void *data)
  128. {
  129. while (!kthread_should_stop()) {
  130. set_current_state(TASK_INTERRUPTIBLE);
  131. if (!test_bit(WAKE_ASTS, &astd_wakeflags))
  132. schedule();
  133. set_current_state(TASK_RUNNING);
  134. mutex_lock(&astd_running);
  135. if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
  136. process_asts();
  137. mutex_unlock(&astd_running);
  138. }
  139. return 0;
  140. }
  141. void dlm_astd_wake(void)
  142. {
  143. if (!no_asts()) {
  144. set_bit(WAKE_ASTS, &astd_wakeflags);
  145. wake_up_process(astd_task);
  146. }
  147. }
  148. int dlm_astd_start(void)
  149. {
  150. struct task_struct *p;
  151. int error = 0;
  152. INIT_LIST_HEAD(&ast_queue);
  153. spin_lock_init(&ast_queue_lock);
  154. mutex_init(&astd_running);
  155. p = kthread_run(dlm_astd, NULL, "dlm_astd");
  156. if (IS_ERR(p))
  157. error = PTR_ERR(p);
  158. else
  159. astd_task = p;
  160. return error;
  161. }
  162. void dlm_astd_stop(void)
  163. {
  164. kthread_stop(astd_task);
  165. }
  166. void dlm_astd_suspend(void)
  167. {
  168. mutex_lock(&astd_running);
  169. }
  170. void dlm_astd_resume(void)
  171. {
  172. mutex_unlock(&astd_running);
  173. }