ast.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /******************************************************************************
  2. *******************************************************************************
  3. **
  4. ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
  5. ** Copyright (C) 2004-2005 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)
  31. {
  32. if (lkb->lkb_flags & DLM_IFL_USER) {
  33. dlm_user_add_ast(lkb, type);
  34. return;
  35. }
  36. DLM_ASSERT(lkb->lkb_astaddr != DLM_FAKE_USER_AST, dlm_print_lkb(lkb););
  37. spin_lock(&ast_queue_lock);
  38. if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
  39. kref_get(&lkb->lkb_ref);
  40. list_add_tail(&lkb->lkb_astqueue, &ast_queue);
  41. }
  42. lkb->lkb_ast_type |= type;
  43. spin_unlock(&ast_queue_lock);
  44. set_bit(WAKE_ASTS, &astd_wakeflags);
  45. wake_up_process(astd_task);
  46. }
  47. static void process_asts(void)
  48. {
  49. struct dlm_ls *ls = NULL;
  50. struct dlm_rsb *r = NULL;
  51. struct dlm_lkb *lkb;
  52. void (*cast) (long param);
  53. void (*bast) (long param, int mode);
  54. int type = 0, found, bmode;
  55. for (;;) {
  56. found = 0;
  57. spin_lock(&ast_queue_lock);
  58. list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
  59. r = lkb->lkb_resource;
  60. ls = r->res_ls;
  61. if (dlm_locking_stopped(ls))
  62. continue;
  63. list_del(&lkb->lkb_astqueue);
  64. type = lkb->lkb_ast_type;
  65. lkb->lkb_ast_type = 0;
  66. found = 1;
  67. break;
  68. }
  69. spin_unlock(&ast_queue_lock);
  70. if (!found)
  71. break;
  72. cast = lkb->lkb_astaddr;
  73. bast = lkb->lkb_bastaddr;
  74. bmode = lkb->lkb_bastmode;
  75. if ((type & AST_COMP) && cast)
  76. cast(lkb->lkb_astparam);
  77. /* FIXME: Is it safe to look at lkb_grmode here
  78. without doing a lock_rsb() ?
  79. Look at other checks in v1 to avoid basts. */
  80. if ((type & AST_BAST) && bast)
  81. if (!dlm_modes_compat(lkb->lkb_grmode, bmode))
  82. bast(lkb->lkb_astparam, bmode);
  83. /* this removes the reference added by dlm_add_ast
  84. and may result in the lkb being freed */
  85. dlm_put_lkb(lkb);
  86. schedule();
  87. }
  88. }
  89. static inline int no_asts(void)
  90. {
  91. int ret;
  92. spin_lock(&ast_queue_lock);
  93. ret = list_empty(&ast_queue);
  94. spin_unlock(&ast_queue_lock);
  95. return ret;
  96. }
  97. static int dlm_astd(void *data)
  98. {
  99. while (!kthread_should_stop()) {
  100. set_current_state(TASK_INTERRUPTIBLE);
  101. if (!test_bit(WAKE_ASTS, &astd_wakeflags))
  102. schedule();
  103. set_current_state(TASK_RUNNING);
  104. mutex_lock(&astd_running);
  105. if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
  106. process_asts();
  107. mutex_unlock(&astd_running);
  108. }
  109. return 0;
  110. }
  111. void dlm_astd_wake(void)
  112. {
  113. if (!no_asts()) {
  114. set_bit(WAKE_ASTS, &astd_wakeflags);
  115. wake_up_process(astd_task);
  116. }
  117. }
  118. int dlm_astd_start(void)
  119. {
  120. struct task_struct *p;
  121. int error = 0;
  122. INIT_LIST_HEAD(&ast_queue);
  123. spin_lock_init(&ast_queue_lock);
  124. mutex_init(&astd_running);
  125. p = kthread_run(dlm_astd, NULL, "dlm_astd");
  126. if (IS_ERR(p))
  127. error = PTR_ERR(p);
  128. else
  129. astd_task = p;
  130. return error;
  131. }
  132. void dlm_astd_stop(void)
  133. {
  134. kthread_stop(astd_task);
  135. }
  136. void dlm_astd_suspend(void)
  137. {
  138. mutex_lock(&astd_running);
  139. }
  140. void dlm_astd_resume(void)
  141. {
  142. mutex_unlock(&astd_running);
  143. }