ast.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /******************************************************************************
  2. *******************************************************************************
  3. **
  4. ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
  5. ** Copyright (C) 2004-2008 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 bastmode)
  31. {
  32. if (lkb->lkb_flags & DLM_IFL_USER) {
  33. dlm_user_add_ast(lkb, type, bastmode);
  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. }
  41. lkb->lkb_ast_type |= type;
  42. if (bastmode)
  43. lkb->lkb_bastmode = bastmode;
  44. spin_unlock(&ast_queue_lock);
  45. set_bit(WAKE_ASTS, &astd_wakeflags);
  46. wake_up_process(astd_task);
  47. }
  48. static void process_asts(void)
  49. {
  50. struct dlm_ls *ls = NULL;
  51. struct dlm_rsb *r = NULL;
  52. struct dlm_lkb *lkb;
  53. void (*cast) (void *astparam);
  54. void (*bast) (void *astparam, int mode);
  55. int type = 0, bastmode;
  56. repeat:
  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. bastmode = lkb->lkb_bastmode;
  67. spin_unlock(&ast_queue_lock);
  68. cast = lkb->lkb_astfn;
  69. bast = lkb->lkb_bastfn;
  70. if ((type & AST_COMP) && cast)
  71. cast(lkb->lkb_astparam);
  72. if ((type & AST_BAST) && bast)
  73. bast(lkb->lkb_astparam, bastmode);
  74. /* this removes the reference added by dlm_add_ast
  75. and may result in the lkb being freed */
  76. dlm_put_lkb(lkb);
  77. cond_resched();
  78. goto repeat;
  79. }
  80. spin_unlock(&ast_queue_lock);
  81. }
  82. static inline int no_asts(void)
  83. {
  84. int ret;
  85. spin_lock(&ast_queue_lock);
  86. ret = list_empty(&ast_queue);
  87. spin_unlock(&ast_queue_lock);
  88. return ret;
  89. }
  90. static int dlm_astd(void *data)
  91. {
  92. while (!kthread_should_stop()) {
  93. set_current_state(TASK_INTERRUPTIBLE);
  94. if (!test_bit(WAKE_ASTS, &astd_wakeflags))
  95. schedule();
  96. set_current_state(TASK_RUNNING);
  97. mutex_lock(&astd_running);
  98. if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
  99. process_asts();
  100. mutex_unlock(&astd_running);
  101. }
  102. return 0;
  103. }
  104. void dlm_astd_wake(void)
  105. {
  106. if (!no_asts()) {
  107. set_bit(WAKE_ASTS, &astd_wakeflags);
  108. wake_up_process(astd_task);
  109. }
  110. }
  111. int dlm_astd_start(void)
  112. {
  113. struct task_struct *p;
  114. int error = 0;
  115. INIT_LIST_HEAD(&ast_queue);
  116. spin_lock_init(&ast_queue_lock);
  117. mutex_init(&astd_running);
  118. p = kthread_run(dlm_astd, NULL, "dlm_astd");
  119. if (IS_ERR(p))
  120. error = PTR_ERR(p);
  121. else
  122. astd_task = p;
  123. return error;
  124. }
  125. void dlm_astd_stop(void)
  126. {
  127. kthread_stop(astd_task);
  128. }
  129. void dlm_astd_suspend(void)
  130. {
  131. mutex_lock(&astd_running);
  132. }
  133. void dlm_astd_resume(void)
  134. {
  135. mutex_unlock(&astd_running);
  136. }