kafstimod.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* kafstimod.c: AFS timeout daemon
  2. *
  3. * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/sched.h>
  14. #include <linux/completion.h>
  15. #include <linux/freezer.h>
  16. #include "cell.h"
  17. #include "volume.h"
  18. #include "kafstimod.h"
  19. #include <asm/errno.h>
  20. #include "internal.h"
  21. static DECLARE_COMPLETION(kafstimod_alive);
  22. static DECLARE_COMPLETION(kafstimod_dead);
  23. static DECLARE_WAIT_QUEUE_HEAD(kafstimod_sleepq);
  24. static int kafstimod_die;
  25. static LIST_HEAD(kafstimod_list);
  26. static DEFINE_SPINLOCK(kafstimod_lock);
  27. static int kafstimod(void *arg);
  28. /*****************************************************************************/
  29. /*
  30. * start the timeout daemon
  31. */
  32. int afs_kafstimod_start(void)
  33. {
  34. int ret;
  35. ret = kernel_thread(kafstimod, NULL, 0);
  36. if (ret < 0)
  37. return ret;
  38. wait_for_completion(&kafstimod_alive);
  39. return ret;
  40. } /* end afs_kafstimod_start() */
  41. /*****************************************************************************/
  42. /*
  43. * stop the timeout daemon
  44. */
  45. void afs_kafstimod_stop(void)
  46. {
  47. /* get rid of my daemon */
  48. kafstimod_die = 1;
  49. wake_up(&kafstimod_sleepq);
  50. wait_for_completion(&kafstimod_dead);
  51. } /* end afs_kafstimod_stop() */
  52. /*****************************************************************************/
  53. /*
  54. * timeout processing daemon
  55. */
  56. static int kafstimod(void *arg)
  57. {
  58. struct afs_timer *timer;
  59. DECLARE_WAITQUEUE(myself, current);
  60. printk("kAFS: Started kafstimod %d\n", current->pid);
  61. daemonize("kafstimod");
  62. complete(&kafstimod_alive);
  63. /* loop around looking for things to attend to */
  64. loop:
  65. set_current_state(TASK_INTERRUPTIBLE);
  66. add_wait_queue(&kafstimod_sleepq, &myself);
  67. for (;;) {
  68. unsigned long jif;
  69. signed long timeout;
  70. /* deal with the server being asked to die */
  71. if (kafstimod_die) {
  72. remove_wait_queue(&kafstimod_sleepq, &myself);
  73. _leave("");
  74. complete_and_exit(&kafstimod_dead, 0);
  75. }
  76. try_to_freeze();
  77. /* discard pending signals */
  78. afs_discard_my_signals();
  79. /* work out the time to elapse before the next event */
  80. spin_lock(&kafstimod_lock);
  81. if (list_empty(&kafstimod_list)) {
  82. timeout = MAX_SCHEDULE_TIMEOUT;
  83. }
  84. else {
  85. timer = list_entry(kafstimod_list.next,
  86. struct afs_timer, link);
  87. timeout = timer->timo_jif;
  88. jif = jiffies;
  89. if (time_before_eq((unsigned long) timeout, jif))
  90. goto immediate;
  91. else {
  92. timeout = (long) timeout - (long) jiffies;
  93. }
  94. }
  95. spin_unlock(&kafstimod_lock);
  96. schedule_timeout(timeout);
  97. set_current_state(TASK_INTERRUPTIBLE);
  98. }
  99. /* the thing on the front of the queue needs processing
  100. * - we come here with the lock held and timer pointing to the expired
  101. * entry
  102. */
  103. immediate:
  104. remove_wait_queue(&kafstimod_sleepq, &myself);
  105. set_current_state(TASK_RUNNING);
  106. _debug("@@@ Begin Timeout of %p", timer);
  107. /* dequeue the timer */
  108. list_del_init(&timer->link);
  109. spin_unlock(&kafstimod_lock);
  110. /* call the timeout function */
  111. timer->ops->timed_out(timer);
  112. _debug("@@@ End Timeout");
  113. goto loop;
  114. } /* end kafstimod() */
  115. /*****************************************************************************/
  116. /*
  117. * (re-)queue a timer
  118. */
  119. void afs_kafstimod_add_timer(struct afs_timer *timer, unsigned long timeout)
  120. {
  121. struct afs_timer *ptimer;
  122. struct list_head *_p;
  123. _enter("%p,%lu", timer, timeout);
  124. spin_lock(&kafstimod_lock);
  125. list_del(&timer->link);
  126. /* the timer was deferred or reset - put it back in the queue at the
  127. * right place */
  128. timer->timo_jif = jiffies + timeout;
  129. list_for_each(_p, &kafstimod_list) {
  130. ptimer = list_entry(_p, struct afs_timer, link);
  131. if (time_before(timer->timo_jif, ptimer->timo_jif))
  132. break;
  133. }
  134. list_add_tail(&timer->link, _p); /* insert before stopping point */
  135. spin_unlock(&kafstimod_lock);
  136. wake_up(&kafstimod_sleepq);
  137. _leave("");
  138. } /* end afs_kafstimod_add_timer() */
  139. /*****************************************************************************/
  140. /*
  141. * dequeue a timer
  142. * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
  143. */
  144. int afs_kafstimod_del_timer(struct afs_timer *timer)
  145. {
  146. int ret = 0;
  147. _enter("%p", timer);
  148. spin_lock(&kafstimod_lock);
  149. if (list_empty(&timer->link))
  150. ret = -ENOENT;
  151. else
  152. list_del_init(&timer->link);
  153. spin_unlock(&kafstimod_lock);
  154. wake_up(&kafstimod_sleepq);
  155. _leave(" = %d", ret);
  156. return ret;
  157. } /* end afs_kafstimod_del_timer() */