blob: 3f4585765cbfcc4d23e7ec43e3b1e6c54f2bcc39 [file] [log] [blame]
David Howellsec268152007-04-26 15:49:28 -07001/* AFS Cache Manager Service
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
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#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/sched.h>
15#include <linux/completion.h>
16#include "server.h"
17#include "cell.h"
18#include "transport.h"
19#include <rxrpc/rxrpc.h>
20#include <rxrpc/transport.h>
21#include <rxrpc/connection.h>
22#include <rxrpc/call.h>
23#include "cmservice.h"
24#include "internal.h"
25
26static unsigned afscm_usage; /* AFS cache manager usage count */
27static struct rw_semaphore afscm_sem; /* AFS cache manager start/stop semaphore */
28
29static int afscm_new_call(struct rxrpc_call *call);
30static void afscm_attention(struct rxrpc_call *call);
31static void afscm_error(struct rxrpc_call *call);
32static void afscm_aemap(struct rxrpc_call *call);
33
34static void _SRXAFSCM_CallBack(struct rxrpc_call *call);
35static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call);
36static void _SRXAFSCM_Probe(struct rxrpc_call *call);
37
38typedef void (*_SRXAFSCM_xxxx_t)(struct rxrpc_call *call);
39
40static const struct rxrpc_operation AFSCM_ops[] = {
41 {
42 .id = 204,
43 .asize = RXRPC_APP_MARK_EOF,
44 .name = "CallBack",
45 .user = _SRXAFSCM_CallBack,
46 },
47 {
48 .id = 205,
49 .asize = RXRPC_APP_MARK_EOF,
50 .name = "InitCallBackState",
51 .user = _SRXAFSCM_InitCallBackState,
52 },
53 {
54 .id = 206,
55 .asize = RXRPC_APP_MARK_EOF,
56 .name = "Probe",
57 .user = _SRXAFSCM_Probe,
58 },
59#if 0
60 {
61 .id = 207,
62 .asize = RXRPC_APP_MARK_EOF,
63 .name = "GetLock",
64 .user = _SRXAFSCM_GetLock,
65 },
66 {
67 .id = 208,
68 .asize = RXRPC_APP_MARK_EOF,
69 .name = "GetCE",
70 .user = _SRXAFSCM_GetCE,
71 },
72 {
73 .id = 209,
74 .asize = RXRPC_APP_MARK_EOF,
75 .name = "GetXStatsVersion",
76 .user = _SRXAFSCM_GetXStatsVersion,
77 },
78 {
79 .id = 210,
80 .asize = RXRPC_APP_MARK_EOF,
81 .name = "GetXStats",
82 .user = _SRXAFSCM_GetXStats,
83 }
84#endif
85};
86
87static struct rxrpc_service AFSCM_service = {
88 .name = "AFS/CM",
89 .owner = THIS_MODULE,
90 .link = LIST_HEAD_INIT(AFSCM_service.link),
91 .new_call = afscm_new_call,
92 .service_id = 1,
93 .attn_func = afscm_attention,
94 .error_func = afscm_error,
95 .aemap_func = afscm_aemap,
96 .ops_begin = &AFSCM_ops[0],
Tobias Klausere8c96f82006-03-24 03:15:34 -080097 .ops_end = &AFSCM_ops[ARRAY_SIZE(AFSCM_ops)],
Linus Torvalds1da177e2005-04-16 15:20:36 -070098};
99
100static DECLARE_COMPLETION(kafscmd_alive);
101static DECLARE_COMPLETION(kafscmd_dead);
102static DECLARE_WAIT_QUEUE_HEAD(kafscmd_sleepq);
103static LIST_HEAD(kafscmd_attention_list);
104static LIST_HEAD(afscm_calls);
105static DEFINE_SPINLOCK(afscm_calls_lock);
106static DEFINE_SPINLOCK(kafscmd_attention_lock);
107static int kafscmd_die;
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/*
110 * AFS Cache Manager kernel thread
111 */
112static int kafscmd(void *arg)
113{
114 DECLARE_WAITQUEUE(myself, current);
115
116 struct rxrpc_call *call;
117 _SRXAFSCM_xxxx_t func;
118 int die;
119
Jesper Juhle8d2a422006-01-11 01:52:40 +0100120 printk(KERN_INFO "kAFS: Started kafscmd %d\n", current->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122 daemonize("kafscmd");
123
124 complete(&kafscmd_alive);
125
126 /* loop around looking for things to attend to */
127 do {
128 if (list_empty(&kafscmd_attention_list)) {
129 set_current_state(TASK_INTERRUPTIBLE);
130 add_wait_queue(&kafscmd_sleepq, &myself);
131
132 for (;;) {
133 set_current_state(TASK_INTERRUPTIBLE);
134 if (!list_empty(&kafscmd_attention_list) ||
135 signal_pending(current) ||
136 kafscmd_die)
137 break;
138
139 schedule();
140 }
141
142 remove_wait_queue(&kafscmd_sleepq, &myself);
143 set_current_state(TASK_RUNNING);
144 }
145
146 die = kafscmd_die;
147
148 /* dequeue the next call requiring attention */
149 call = NULL;
150 spin_lock(&kafscmd_attention_lock);
151
152 if (!list_empty(&kafscmd_attention_list)) {
153 call = list_entry(kafscmd_attention_list.next,
154 struct rxrpc_call,
155 app_attn_link);
156 list_del_init(&call->app_attn_link);
157 die = 0;
158 }
159
160 spin_unlock(&kafscmd_attention_lock);
161
162 if (call) {
163 /* act upon it */
164 _debug("@@@ Begin Attend Call %p", call);
165
166 func = call->app_user;
167 if (func)
168 func(call);
169
170 rxrpc_put_call(call);
171
172 _debug("@@@ End Attend Call %p", call);
173 }
174
175 } while(!die);
176
177 /* and that's all */
178 complete_and_exit(&kafscmd_dead, 0);
David Howellsec268152007-04-26 15:49:28 -0700179}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181/*
182 * handle a call coming in to the cache manager
183 * - if I want to keep the call, I must increment its usage count
184 * - the return value will be negated and passed back in an abort packet if
185 * non-zero
186 * - serialised by virtue of there only being one krxiod
187 */
188static int afscm_new_call(struct rxrpc_call *call)
189{
190 _enter("%p{cid=%u u=%d}",
191 call, ntohl(call->call_id), atomic_read(&call->usage));
192
193 rxrpc_get_call(call);
194
195 /* add to my current call list */
196 spin_lock(&afscm_calls_lock);
197 list_add(&call->app_link,&afscm_calls);
198 spin_unlock(&afscm_calls_lock);
199
200 _leave(" = 0");
201 return 0;
David Howellsec268152007-04-26 15:49:28 -0700202}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/*
205 * queue on the kafscmd queue for attention
206 */
207static void afscm_attention(struct rxrpc_call *call)
208{
209 _enter("%p{cid=%u u=%d}",
210 call, ntohl(call->call_id), atomic_read(&call->usage));
211
212 spin_lock(&kafscmd_attention_lock);
213
214 if (list_empty(&call->app_attn_link)) {
215 list_add_tail(&call->app_attn_link, &kafscmd_attention_list);
216 rxrpc_get_call(call);
217 }
218
219 spin_unlock(&kafscmd_attention_lock);
220
221 wake_up(&kafscmd_sleepq);
222
223 _leave(" {u=%d}", atomic_read(&call->usage));
David Howellsec268152007-04-26 15:49:28 -0700224}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226/*
227 * handle my call being aborted
228 * - clean up, dequeue and put my ref to the call
229 */
230static void afscm_error(struct rxrpc_call *call)
231{
232 int removed;
233
234 _enter("%p{est=%s ac=%u er=%d}",
235 call,
236 rxrpc_call_error_states[call->app_err_state],
237 call->app_abort_code,
238 call->app_errno);
239
240 spin_lock(&kafscmd_attention_lock);
241
242 if (list_empty(&call->app_attn_link)) {
243 list_add_tail(&call->app_attn_link, &kafscmd_attention_list);
244 rxrpc_get_call(call);
245 }
246
247 spin_unlock(&kafscmd_attention_lock);
248
249 removed = 0;
250 spin_lock(&afscm_calls_lock);
251 if (!list_empty(&call->app_link)) {
252 list_del_init(&call->app_link);
253 removed = 1;
254 }
255 spin_unlock(&afscm_calls_lock);
256
257 if (removed)
258 rxrpc_put_call(call);
259
260 wake_up(&kafscmd_sleepq);
261
262 _leave("");
David Howellsec268152007-04-26 15:49:28 -0700263}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265/*
266 * map afs abort codes to/from Linux error codes
267 * - called with call->lock held
268 */
269static void afscm_aemap(struct rxrpc_call *call)
270{
271 switch (call->app_err_state) {
272 case RXRPC_ESTATE_LOCAL_ABORT:
273 call->app_abort_code = -call->app_errno;
274 break;
275 case RXRPC_ESTATE_PEER_ABORT:
276 call->app_errno = -ECONNABORTED;
277 break;
278 default:
279 break;
280 }
David Howellsec268152007-04-26 15:49:28 -0700281}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283/*
284 * start the cache manager service if not already started
285 */
286int afscm_start(void)
287{
288 int ret;
289
290 down_write(&afscm_sem);
291 if (!afscm_usage) {
292 ret = kernel_thread(kafscmd, NULL, 0);
293 if (ret < 0)
294 goto out;
295
296 wait_for_completion(&kafscmd_alive);
297
298 ret = rxrpc_add_service(afs_transport, &AFSCM_service);
299 if (ret < 0)
300 goto kill;
301
302 afs_kafstimod_add_timer(&afs_mntpt_expiry_timer,
303 afs_mntpt_expiry_timeout * HZ);
304 }
305
306 afscm_usage++;
307 up_write(&afscm_sem);
308
309 return 0;
310
David Howellsec268152007-04-26 15:49:28 -0700311kill:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 kafscmd_die = 1;
313 wake_up(&kafscmd_sleepq);
314 wait_for_completion(&kafscmd_dead);
315
David Howellsec268152007-04-26 15:49:28 -0700316out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 up_write(&afscm_sem);
318 return ret;
David Howellsec268152007-04-26 15:49:28 -0700319}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321/*
322 * stop the cache manager service
323 */
324void afscm_stop(void)
325{
326 struct rxrpc_call *call;
327
328 down_write(&afscm_sem);
329
330 BUG_ON(afscm_usage == 0);
331 afscm_usage--;
332
333 if (afscm_usage == 0) {
334 /* don't want more incoming calls */
335 rxrpc_del_service(afs_transport, &AFSCM_service);
336
337 /* abort any calls I've still got open (the afscm_error() will
338 * dequeue them) */
339 spin_lock(&afscm_calls_lock);
340 while (!list_empty(&afscm_calls)) {
341 call = list_entry(afscm_calls.next,
342 struct rxrpc_call,
343 app_link);
344
345 list_del_init(&call->app_link);
346 rxrpc_get_call(call);
347 spin_unlock(&afscm_calls_lock);
348
349 rxrpc_call_abort(call, -ESRCH); /* abort, dequeue and
350 * put */
351
352 _debug("nuking active call %08x.%d",
353 ntohl(call->conn->conn_id),
354 ntohl(call->call_id));
355 rxrpc_put_call(call);
356 rxrpc_put_call(call);
357
358 spin_lock(&afscm_calls_lock);
359 }
360 spin_unlock(&afscm_calls_lock);
361
362 /* get rid of my daemon */
363 kafscmd_die = 1;
364 wake_up(&kafscmd_sleepq);
365 wait_for_completion(&kafscmd_dead);
366
367 /* dispose of any calls waiting for attention */
368 spin_lock(&kafscmd_attention_lock);
369 while (!list_empty(&kafscmd_attention_list)) {
370 call = list_entry(kafscmd_attention_list.next,
371 struct rxrpc_call,
372 app_attn_link);
373
374 list_del_init(&call->app_attn_link);
375 spin_unlock(&kafscmd_attention_lock);
376
377 rxrpc_put_call(call);
378
379 spin_lock(&kafscmd_attention_lock);
380 }
381 spin_unlock(&kafscmd_attention_lock);
382
383 afs_kafstimod_del_timer(&afs_mntpt_expiry_timer);
384 }
385
386 up_write(&afscm_sem);
David Howellsec268152007-04-26 15:49:28 -0700387}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389/*
390 * handle the fileserver breaking a set of callbacks
391 */
392static void _SRXAFSCM_CallBack(struct rxrpc_call *call)
393{
394 struct afs_server *server;
395 size_t count, qty, tmp;
396 int ret = 0, removed;
397
398 _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
399
400 server = afs_server_get_from_peer(call->conn->peer);
401
402 switch (call->app_call_state) {
403 /* we've received the last packet
404 * - drain all the data from the call and send the reply
405 */
406 case RXRPC_CSTATE_SRVR_GOT_ARGS:
407 ret = -EBADMSG;
408 qty = call->app_ready_qty;
409 if (qty < 8 || qty > 50 * (6 * 4) + 8)
410 break;
411
412 {
413 struct afs_callback *cb, *pcb;
414 int loop;
415 __be32 *fp, *bp;
416
417 fp = rxrpc_call_alloc_scratch(call, qty);
418
419 /* drag the entire argument block out to the scratch
420 * space */
421 ret = rxrpc_call_read_data(call, fp, qty, 0);
422 if (ret < 0)
423 break;
424
425 /* and unmarshall the parameter block */
426 ret = -EBADMSG;
427 count = ntohl(*fp++);
428 if (count>AFSCBMAX ||
429 (count * (3 * 4) + 8 != qty &&
430 count * (6 * 4) + 8 != qty))
431 break;
432
433 bp = fp + count*3;
434 tmp = ntohl(*bp++);
435 if (tmp > 0 && tmp != count)
436 break;
437 if (tmp == 0)
438 bp = NULL;
439
440 pcb = cb = rxrpc_call_alloc_scratch_s(
441 call, struct afs_callback);
442
443 for (loop = count - 1; loop >= 0; loop--) {
444 pcb->fid.vid = ntohl(*fp++);
445 pcb->fid.vnode = ntohl(*fp++);
446 pcb->fid.unique = ntohl(*fp++);
447 if (bp) {
448 pcb->version = ntohl(*bp++);
449 pcb->expiry = ntohl(*bp++);
450 pcb->type = ntohl(*bp++);
David Howellsec268152007-04-26 15:49:28 -0700451 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 pcb->version = 0;
453 pcb->expiry = 0;
454 pcb->type = AFSCM_CB_UNTYPED;
455 }
456 pcb++;
457 }
458
459 /* invoke the actual service routine */
460 ret = SRXAFSCM_CallBack(server, count, cb);
461 if (ret < 0)
462 break;
463 }
464
465 /* send the reply */
466 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
467 GFP_KERNEL, 0, &count);
468 if (ret < 0)
469 break;
470 break;
471
472 /* operation complete */
473 case RXRPC_CSTATE_COMPLETE:
474 call->app_user = NULL;
475 removed = 0;
476 spin_lock(&afscm_calls_lock);
477 if (!list_empty(&call->app_link)) {
478 list_del_init(&call->app_link);
479 removed = 1;
480 }
481 spin_unlock(&afscm_calls_lock);
482
483 if (removed)
484 rxrpc_put_call(call);
485 break;
486
487 /* operation terminated on error */
488 case RXRPC_CSTATE_ERROR:
489 call->app_user = NULL;
490 break;
491
492 default:
493 break;
494 }
495
496 if (ret < 0)
497 rxrpc_call_abort(call, ret);
498
499 afs_put_server(server);
500
501 _leave(" = %d", ret);
David Howellsec268152007-04-26 15:49:28 -0700502}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504/*
505 * handle the fileserver asking us to initialise our callback state
506 */
507static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call)
508{
509 struct afs_server *server;
510 size_t count;
511 int ret = 0, removed;
512
513 _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
514
515 server = afs_server_get_from_peer(call->conn->peer);
516
517 switch (call->app_call_state) {
518 /* we've received the last packet - drain all the data from the
519 * call */
520 case RXRPC_CSTATE_SRVR_GOT_ARGS:
521 /* shouldn't be any args */
522 ret = -EBADMSG;
523 break;
524
525 /* send the reply when asked for it */
526 case RXRPC_CSTATE_SRVR_SND_REPLY:
527 /* invoke the actual service routine */
528 ret = SRXAFSCM_InitCallBackState(server);
529 if (ret < 0)
530 break;
531
532 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
533 GFP_KERNEL, 0, &count);
534 if (ret < 0)
535 break;
536 break;
537
538 /* operation complete */
539 case RXRPC_CSTATE_COMPLETE:
540 call->app_user = NULL;
541 removed = 0;
542 spin_lock(&afscm_calls_lock);
543 if (!list_empty(&call->app_link)) {
544 list_del_init(&call->app_link);
545 removed = 1;
546 }
547 spin_unlock(&afscm_calls_lock);
548
549 if (removed)
550 rxrpc_put_call(call);
551 break;
552
553 /* operation terminated on error */
554 case RXRPC_CSTATE_ERROR:
555 call->app_user = NULL;
556 break;
557
558 default:
559 break;
560 }
561
562 if (ret < 0)
563 rxrpc_call_abort(call, ret);
564
565 afs_put_server(server);
566
567 _leave(" = %d", ret);
David Howellsec268152007-04-26 15:49:28 -0700568}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570/*
571 * handle a probe from a fileserver
572 */
573static void _SRXAFSCM_Probe(struct rxrpc_call *call)
574{
575 struct afs_server *server;
576 size_t count;
577 int ret = 0, removed;
578
579 _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
580
581 server = afs_server_get_from_peer(call->conn->peer);
582
583 switch (call->app_call_state) {
584 /* we've received the last packet - drain all the data from the
585 * call */
586 case RXRPC_CSTATE_SRVR_GOT_ARGS:
587 /* shouldn't be any args */
588 ret = -EBADMSG;
589 break;
590
591 /* send the reply when asked for it */
592 case RXRPC_CSTATE_SRVR_SND_REPLY:
593 /* invoke the actual service routine */
594 ret = SRXAFSCM_Probe(server);
595 if (ret < 0)
596 break;
597
598 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
599 GFP_KERNEL, 0, &count);
600 if (ret < 0)
601 break;
602 break;
603
604 /* operation complete */
605 case RXRPC_CSTATE_COMPLETE:
606 call->app_user = NULL;
607 removed = 0;
608 spin_lock(&afscm_calls_lock);
609 if (!list_empty(&call->app_link)) {
610 list_del_init(&call->app_link);
611 removed = 1;
612 }
613 spin_unlock(&afscm_calls_lock);
614
615 if (removed)
616 rxrpc_put_call(call);
617 break;
618
619 /* operation terminated on error */
620 case RXRPC_CSTATE_ERROR:
621 call->app_user = NULL;
622 break;
623
624 default:
625 break;
626 }
627
628 if (ret < 0)
629 rxrpc_call_abort(call, ret);
630
631 afs_put_server(server);
632
633 _leave(" = %d", ret);
David Howellsec268152007-04-26 15:49:28 -0700634}