initial commit with v2.6.9
[linux-2.6.9-moxart.git] / fs / afs / kafstimod.c
blobd7c8826b52a8e42d6f97bc78585c427475c247a0
1 /* kafstimod.c: AFS timeout daemon
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/completion.h>
16 #include "cell.h"
17 #include "volume.h"
18 #include "kafstimod.h"
19 #include <asm/errno.h>
20 #include "internal.h"
22 static DECLARE_COMPLETION(kafstimod_alive);
23 static DECLARE_COMPLETION(kafstimod_dead);
24 static DECLARE_WAIT_QUEUE_HEAD(kafstimod_sleepq);
25 static int kafstimod_die;
27 static LIST_HEAD(kafstimod_list);
28 static spinlock_t kafstimod_lock = SPIN_LOCK_UNLOCKED;
30 static int kafstimod(void *arg);
32 /*****************************************************************************/
34 * start the timeout daemon
36 int afs_kafstimod_start(void)
38 int ret;
40 ret = kernel_thread(kafstimod, NULL, 0);
41 if (ret < 0)
42 return ret;
44 wait_for_completion(&kafstimod_alive);
46 return ret;
47 } /* end afs_kafstimod_start() */
49 /*****************************************************************************/
51 * stop the timeout daemon
53 void afs_kafstimod_stop(void)
55 /* get rid of my daemon */
56 kafstimod_die = 1;
57 wake_up(&kafstimod_sleepq);
58 wait_for_completion(&kafstimod_dead);
60 } /* end afs_kafstimod_stop() */
62 /*****************************************************************************/
64 * timeout processing daemon
66 static int kafstimod(void *arg)
68 struct afs_timer *timer;
70 DECLARE_WAITQUEUE(myself, current);
72 printk("kAFS: Started kafstimod %d\n", current->pid);
74 daemonize("kafstimod");
76 complete(&kafstimod_alive);
78 /* loop around looking for things to attend to */
79 loop:
80 set_current_state(TASK_INTERRUPTIBLE);
81 add_wait_queue(&kafstimod_sleepq, &myself);
83 for (;;) {
84 unsigned long jif;
85 signed long timeout;
87 /* deal with the server being asked to die */
88 if (kafstimod_die) {
89 remove_wait_queue(&kafstimod_sleepq, &myself);
90 _leave("");
91 complete_and_exit(&kafstimod_dead, 0);
94 /* discard pending signals */
95 afs_discard_my_signals();
97 /* work out the time to elapse before the next event */
98 spin_lock(&kafstimod_lock);
99 if (list_empty(&kafstimod_list)) {
100 timeout = MAX_SCHEDULE_TIMEOUT;
102 else {
103 timer = list_entry(kafstimod_list.next,
104 struct afs_timer, link);
105 timeout = timer->timo_jif;
106 jif = jiffies;
108 if (time_before_eq((unsigned long) timeout, jif))
109 goto immediate;
111 else {
112 timeout = (long) timeout - (long) jiffies;
115 spin_unlock(&kafstimod_lock);
117 schedule_timeout(timeout);
119 set_current_state(TASK_INTERRUPTIBLE);
122 /* the thing on the front of the queue needs processing
123 * - we come here with the lock held and timer pointing to the expired
124 * entry
126 immediate:
127 remove_wait_queue(&kafstimod_sleepq, &myself);
128 set_current_state(TASK_RUNNING);
130 _debug("@@@ Begin Timeout of %p", timer);
132 /* dequeue the timer */
133 list_del_init(&timer->link);
134 spin_unlock(&kafstimod_lock);
136 /* call the timeout function */
137 timer->ops->timed_out(timer);
139 _debug("@@@ End Timeout");
140 goto loop;
142 } /* end kafstimod() */
144 /*****************************************************************************/
146 * (re-)queue a timer
148 void afs_kafstimod_add_timer(struct afs_timer *timer, unsigned long timeout)
150 struct afs_timer *ptimer;
151 struct list_head *_p;
153 _enter("%p,%lu", timer, timeout);
155 spin_lock(&kafstimod_lock);
157 list_del(&timer->link);
159 /* the timer was deferred or reset - put it back in the queue at the
160 * right place */
161 timer->timo_jif = jiffies + timeout;
163 list_for_each(_p, &kafstimod_list) {
164 ptimer = list_entry(_p, struct afs_timer, link);
165 if (time_before(timer->timo_jif, ptimer->timo_jif))
166 break;
169 list_add_tail(&timer->link, _p); /* insert before stopping point */
171 spin_unlock(&kafstimod_lock);
173 wake_up(&kafstimod_sleepq);
175 _leave("");
176 } /* end afs_kafstimod_add_timer() */
178 /*****************************************************************************/
180 * dequeue a timer
181 * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
183 int afs_kafstimod_del_timer(struct afs_timer *timer)
185 int ret = 0;
187 _enter("%p", timer);
189 spin_lock(&kafstimod_lock);
191 if (list_empty(&timer->link))
192 ret = -ENOENT;
193 else
194 list_del_init(&timer->link);
196 spin_unlock(&kafstimod_lock);
198 wake_up(&kafstimod_sleepq);
200 _leave(" = %d", ret);
201 return ret;
202 } /* end afs_kafstimod_del_timer() */