vserver 1.9.5.x5
[linux-2.6.git] / fs / afs / kafsasyncd.c
1 /* kafsasyncd.c: AFS asynchronous operation 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  *
12  * The AFS async daemon is used to the following:
13  * - probe "dead" servers to see whether they've come back to life yet.
14  * - probe "live" servers that we haven't talked to for a while to see if they are better
15  *   candidates for serving than what we're currently using
16  * - poll volume location servers to keep up to date volume location lists
17  */
18
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/sched.h>
22 #include <linux/completion.h>
23 #include "cell.h"
24 #include "server.h"
25 #include "volume.h"
26 #include "kafsasyncd.h"
27 #include "kafstimod.h"
28 #include <rxrpc/call.h>
29 #include <asm/errno.h>
30 #include "internal.h"
31
32 static DECLARE_COMPLETION(kafsasyncd_alive);
33 static DECLARE_COMPLETION(kafsasyncd_dead);
34 static DECLARE_WAIT_QUEUE_HEAD(kafsasyncd_sleepq);
35 static struct task_struct *kafsasyncd_task;
36 static int kafsasyncd_die;
37
38 static int kafsasyncd(void *arg);
39
40 static LIST_HEAD(kafsasyncd_async_attnq);
41 static LIST_HEAD(kafsasyncd_async_busyq);
42 static DEFINE_SPINLOCK(kafsasyncd_async_lock);
43
44 static void kafsasyncd_null_call_attn_func(struct rxrpc_call *call)
45 {
46 }
47
48 static void kafsasyncd_null_call_error_func(struct rxrpc_call *call)
49 {
50 }
51
52 /*****************************************************************************/
53 /*
54  * start the async daemon
55  */
56 int afs_kafsasyncd_start(void)
57 {
58         int ret;
59
60         ret = kernel_thread(kafsasyncd, NULL, 0);
61         if (ret < 0)
62                 return ret;
63
64         wait_for_completion(&kafsasyncd_alive);
65
66         return ret;
67 } /* end afs_kafsasyncd_start() */
68
69 /*****************************************************************************/
70 /*
71  * stop the async daemon
72  */
73 void afs_kafsasyncd_stop(void)
74 {
75         /* get rid of my daemon */
76         kafsasyncd_die = 1;
77         wake_up(&kafsasyncd_sleepq);
78         wait_for_completion(&kafsasyncd_dead);
79
80 } /* end afs_kafsasyncd_stop() */
81
82 /*****************************************************************************/
83 /*
84  * probing daemon
85  */
86 static int kafsasyncd(void *arg)
87 {
88         struct afs_async_op *op;
89         int die;
90
91         DECLARE_WAITQUEUE(myself, current);
92
93         kafsasyncd_task = current;
94
95         printk("kAFS: Started kafsasyncd %d\n", current->pid);
96
97         daemonize("kafsasyncd");
98
99         complete(&kafsasyncd_alive);
100
101         /* loop around looking for things to attend to */
102         do {
103                 set_current_state(TASK_INTERRUPTIBLE);
104                 add_wait_queue(&kafsasyncd_sleepq, &myself);
105
106                 for (;;) {
107                         if (!list_empty(&kafsasyncd_async_attnq) ||
108                             signal_pending(current) ||
109                             kafsasyncd_die)
110                                 break;
111
112                         schedule();
113                         set_current_state(TASK_INTERRUPTIBLE);
114                 }
115
116                 remove_wait_queue(&kafsasyncd_sleepq, &myself);
117                 set_current_state(TASK_RUNNING);
118
119                 /* discard pending signals */
120                 afs_discard_my_signals();
121
122                 die = kafsasyncd_die;
123
124                 /* deal with the next asynchronous operation requiring
125                  * attention */
126                 if (!list_empty(&kafsasyncd_async_attnq)) {
127                         struct afs_async_op *op;
128
129                         _debug("@@@ Begin Asynchronous Operation");
130
131                         op = NULL;
132                         spin_lock(&kafsasyncd_async_lock);
133
134                         if (!list_empty(&kafsasyncd_async_attnq)) {
135                                 op = list_entry(kafsasyncd_async_attnq.next,
136                                                 struct afs_async_op, link);
137                                 list_del(&op->link);
138                                 list_add_tail(&op->link,
139                                               &kafsasyncd_async_busyq);
140                         }
141
142                         spin_unlock(&kafsasyncd_async_lock);
143
144                         _debug("@@@ Operation %p {%p}\n",
145                                op, op ? op->ops : NULL);
146
147                         if (op)
148                                 op->ops->attend(op);
149
150                         _debug("@@@ End Asynchronous Operation");
151                 }
152
153         } while(!die);
154
155         /* need to kill all outstanding asynchronous operations before
156          * exiting */
157         kafsasyncd_task = NULL;
158         spin_lock(&kafsasyncd_async_lock);
159
160         /* fold the busy and attention queues together */
161         list_splice_init(&kafsasyncd_async_busyq,
162                          &kafsasyncd_async_attnq);
163
164         /* dequeue kafsasyncd from all their wait queues */
165         list_for_each_entry(op, &kafsasyncd_async_attnq, link) {
166                 op->call->app_attn_func = kafsasyncd_null_call_attn_func;
167                 op->call->app_error_func = kafsasyncd_null_call_error_func;
168                 remove_wait_queue(&op->call->waitq, &op->waiter);
169         }
170
171         spin_unlock(&kafsasyncd_async_lock);
172
173         /* abort all the operations */
174         while (!list_empty(&kafsasyncd_async_attnq)) {
175                 op = list_entry(kafsasyncd_async_attnq.next, struct afs_async_op, link);
176                 list_del_init(&op->link);
177
178                 rxrpc_call_abort(op->call, -EIO);
179                 rxrpc_put_call(op->call);
180                 op->call = NULL;
181
182                 op->ops->discard(op);
183         }
184
185         /* and that's all */
186         _leave("");
187         complete_and_exit(&kafsasyncd_dead, 0);
188
189 } /* end kafsasyncd() */
190
191 /*****************************************************************************/
192 /*
193  * begin an operation
194  * - place operation on busy queue
195  */
196 void afs_kafsasyncd_begin_op(struct afs_async_op *op)
197 {
198         _enter("");
199
200         spin_lock(&kafsasyncd_async_lock);
201
202         init_waitqueue_entry(&op->waiter, kafsasyncd_task);
203         add_wait_queue(&op->call->waitq, &op->waiter);
204
205         list_del(&op->link);
206         list_add_tail(&op->link, &kafsasyncd_async_busyq);
207
208         spin_unlock(&kafsasyncd_async_lock);
209
210         _leave("");
211 } /* end afs_kafsasyncd_begin_op() */
212
213 /*****************************************************************************/
214 /*
215  * request attention for an operation
216  * - move to attention queue
217  */
218 void afs_kafsasyncd_attend_op(struct afs_async_op *op)
219 {
220         _enter("");
221
222         spin_lock(&kafsasyncd_async_lock);
223
224         list_del(&op->link);
225         list_add_tail(&op->link, &kafsasyncd_async_attnq);
226
227         spin_unlock(&kafsasyncd_async_lock);
228
229         wake_up(&kafsasyncd_sleepq);
230
231         _leave("");
232 } /* end afs_kafsasyncd_attend_op() */
233
234 /*****************************************************************************/
235 /*
236  * terminate an operation
237  * - remove from either queue
238  */
239 void afs_kafsasyncd_terminate_op(struct afs_async_op *op)
240 {
241         _enter("");
242
243         spin_lock(&kafsasyncd_async_lock);
244
245         if (!list_empty(&op->link)) {
246                 list_del_init(&op->link);
247                 remove_wait_queue(&op->call->waitq, &op->waiter);
248         }
249
250         spin_unlock(&kafsasyncd_async_lock);
251
252         wake_up(&kafsasyncd_sleepq);
253
254         _leave("");
255 } /* end afs_kafsasyncd_terminate_op() */