ast.c 3.6 KB

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