ast.c 3.7 KB

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