Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
3e1d1d28 | 119 | try_to_freeze(); |
1da177e4 LT |
120 | |
121 | /* discard pending signals */ | |
122 | afs_discard_my_signals(); | |
123 | ||
124 | die = kafsasyncd_die; | |
125 | ||
126 | /* deal with the next asynchronous operation requiring | |
127 | * attention */ | |
128 | if (!list_empty(&kafsasyncd_async_attnq)) { | |
129 | struct afs_async_op *op; | |
130 | ||
131 | _debug("@@@ Begin Asynchronous Operation"); | |
132 | ||
133 | op = NULL; | |
134 | spin_lock(&kafsasyncd_async_lock); | |
135 | ||
136 | if (!list_empty(&kafsasyncd_async_attnq)) { | |
137 | op = list_entry(kafsasyncd_async_attnq.next, | |
138 | struct afs_async_op, link); | |
f116629d | 139 | list_move_tail(&op->link, |
1da177e4 LT |
140 | &kafsasyncd_async_busyq); |
141 | } | |
142 | ||
143 | spin_unlock(&kafsasyncd_async_lock); | |
144 | ||
145 | _debug("@@@ Operation %p {%p}\n", | |
146 | op, op ? op->ops : NULL); | |
147 | ||
148 | if (op) | |
149 | op->ops->attend(op); | |
150 | ||
151 | _debug("@@@ End Asynchronous Operation"); | |
152 | } | |
153 | ||
154 | } while(!die); | |
155 | ||
156 | /* need to kill all outstanding asynchronous operations before | |
157 | * exiting */ | |
158 | kafsasyncd_task = NULL; | |
159 | spin_lock(&kafsasyncd_async_lock); | |
160 | ||
161 | /* fold the busy and attention queues together */ | |
162 | list_splice_init(&kafsasyncd_async_busyq, | |
163 | &kafsasyncd_async_attnq); | |
164 | ||
165 | /* dequeue kafsasyncd from all their wait queues */ | |
166 | list_for_each_entry(op, &kafsasyncd_async_attnq, link) { | |
167 | op->call->app_attn_func = kafsasyncd_null_call_attn_func; | |
168 | op->call->app_error_func = kafsasyncd_null_call_error_func; | |
169 | remove_wait_queue(&op->call->waitq, &op->waiter); | |
170 | } | |
171 | ||
172 | spin_unlock(&kafsasyncd_async_lock); | |
173 | ||
174 | /* abort all the operations */ | |
175 | while (!list_empty(&kafsasyncd_async_attnq)) { | |
176 | op = list_entry(kafsasyncd_async_attnq.next, struct afs_async_op, link); | |
177 | list_del_init(&op->link); | |
178 | ||
179 | rxrpc_call_abort(op->call, -EIO); | |
180 | rxrpc_put_call(op->call); | |
181 | op->call = NULL; | |
182 | ||
183 | op->ops->discard(op); | |
184 | } | |
185 | ||
186 | /* and that's all */ | |
187 | _leave(""); | |
188 | complete_and_exit(&kafsasyncd_dead, 0); | |
189 | ||
190 | } /* end kafsasyncd() */ | |
191 | ||
192 | /*****************************************************************************/ | |
193 | /* | |
194 | * begin an operation | |
195 | * - place operation on busy queue | |
196 | */ | |
197 | void afs_kafsasyncd_begin_op(struct afs_async_op *op) | |
198 | { | |
199 | _enter(""); | |
200 | ||
201 | spin_lock(&kafsasyncd_async_lock); | |
202 | ||
203 | init_waitqueue_entry(&op->waiter, kafsasyncd_task); | |
204 | add_wait_queue(&op->call->waitq, &op->waiter); | |
205 | ||
f116629d | 206 | list_move_tail(&op->link, &kafsasyncd_async_busyq); |
1da177e4 LT |
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 | ||
f116629d | 224 | list_move_tail(&op->link, &kafsasyncd_async_attnq); |
1da177e4 LT |
225 | |
226 | spin_unlock(&kafsasyncd_async_lock); | |
227 | ||
228 | wake_up(&kafsasyncd_sleepq); | |
229 | ||
230 | _leave(""); | |
231 | } /* end afs_kafsasyncd_attend_op() */ | |
232 | ||
233 | /*****************************************************************************/ | |
234 | /* | |
235 | * terminate an operation | |
236 | * - remove from either queue | |
237 | */ | |
238 | void afs_kafsasyncd_terminate_op(struct afs_async_op *op) | |
239 | { | |
240 | _enter(""); | |
241 | ||
242 | spin_lock(&kafsasyncd_async_lock); | |
243 | ||
244 | if (!list_empty(&op->link)) { | |
245 | list_del_init(&op->link); | |
246 | remove_wait_queue(&op->call->waitq, &op->waiter); | |
247 | } | |
248 | ||
249 | spin_unlock(&kafsasyncd_async_lock); | |
250 | ||
251 | wake_up(&kafsasyncd_sleepq); | |
252 | ||
253 | _leave(""); | |
254 | } /* end afs_kafsasyncd_terminate_op() */ |