ast.c 3.7 KB

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