Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* cmservice.c: AFS Cache Manager Service
  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 #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 
 26 static unsigned afscm_usage;            /* AFS cache manager usage count */
 27 static struct rw_semaphore afscm_sem;   /* AFS cache manager start/stop semaphore */
 28 
 29 static int afscm_new_call(struct rxrpc_call *call);
 30 static void afscm_attention(struct rxrpc_call *call);
 31 static void afscm_error(struct rxrpc_call *call);
 32 static void afscm_aemap(struct rxrpc_call *call);
 33 
 34 static void _SRXAFSCM_CallBack(struct rxrpc_call *call);
 35 static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call);
 36 static void _SRXAFSCM_Probe(struct rxrpc_call *call);
 37 
 38 typedef void (*_SRXAFSCM_xxxx_t)(struct rxrpc_call *call);
 39 
 40 static 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 
 87 static 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],
 97         .ops_end        = &AFSCM_ops[sizeof(AFSCM_ops) / sizeof(AFSCM_ops[0])],
 98 };
 99 
100 static DECLARE_COMPLETION(kafscmd_alive);
101 static DECLARE_COMPLETION(kafscmd_dead);
102 static DECLARE_WAIT_QUEUE_HEAD(kafscmd_sleepq);
103 static LIST_HEAD(kafscmd_attention_list);
104 static LIST_HEAD(afscm_calls);
105 static DEFINE_SPINLOCK(afscm_calls_lock);
106 static DEFINE_SPINLOCK(kafscmd_attention_lock);
107 static int kafscmd_die;
108 
109 /*****************************************************************************/
110 /*
111  * AFS Cache Manager kernel thread
112  */
113 static int kafscmd(void *arg)
114 {
115         DECLARE_WAITQUEUE(myself, current);
116 
117         struct rxrpc_call *call;
118         _SRXAFSCM_xxxx_t func;
119         int die;
120 
121         printk("kAFS: Started kafscmd %d\n", current->pid);
122 
123         daemonize("kafscmd");
124 
125         complete(&kafscmd_alive);
126 
127         /* loop around looking for things to attend to */
128         do {
129                 if (list_empty(&kafscmd_attention_list)) {
130                         set_current_state(TASK_INTERRUPTIBLE);
131                         add_wait_queue(&kafscmd_sleepq, &myself);
132 
133                         for (;;) {
134                                 set_current_state(TASK_INTERRUPTIBLE);
135                                 if (!list_empty(&kafscmd_attention_list) ||
136                                     signal_pending(current) ||
137                                     kafscmd_die)
138                                         break;
139 
140                                 schedule();
141                         }
142 
143                         remove_wait_queue(&kafscmd_sleepq, &myself);
144                         set_current_state(TASK_RUNNING);
145                 }
146 
147                 die = kafscmd_die;
148 
149                 /* dequeue the next call requiring attention */
150                 call = NULL;
151                 spin_lock(&kafscmd_attention_lock);
152 
153                 if (!list_empty(&kafscmd_attention_list)) {
154                         call = list_entry(kafscmd_attention_list.next,
155                                           struct rxrpc_call,
156                                           app_attn_link);
157                         list_del_init(&call->app_attn_link);
158                         die = 0;
159                 }
160 
161                 spin_unlock(&kafscmd_attention_lock);
162 
163                 if (call) {
164                         /* act upon it */
165                         _debug("@@@ Begin Attend Call %p", call);
166 
167                         func = call->app_user;
168                         if (func)
169                                 func(call);
170 
171                         rxrpc_put_call(call);
172 
173                         _debug("@@@ End Attend Call %p", call);
174                 }
175 
176         } while(!die);
177 
178         /* and that's all */
179         complete_and_exit(&kafscmd_dead, 0);
180 
181 } /* end kafscmd() */
182 
183 /*****************************************************************************/
184 /*
185  * handle a call coming in to the cache manager
186  * - if I want to keep the call, I must increment its usage count
187  * - the return value will be negated and passed back in an abort packet if
188  *   non-zero
189  * - serialised by virtue of there only being one krxiod
190  */
191 static int afscm_new_call(struct rxrpc_call *call)
192 {
193         _enter("%p{cid=%u u=%d}",
194                call, ntohl(call->call_id), atomic_read(&call->usage));
195 
196         rxrpc_get_call(call);
197 
198         /* add to my current call list */
199         spin_lock(&afscm_calls_lock);
200         list_add(&call->app_link,&afscm_calls);
201         spin_unlock(&afscm_calls_lock);
202 
203         _leave(" = 0");
204         return 0;
205 
206 } /* end afscm_new_call() */
207 
208 /*****************************************************************************/
209 /*
210  * queue on the kafscmd queue for attention
211  */
212 static void afscm_attention(struct rxrpc_call *call)
213 {
214         _enter("%p{cid=%u u=%d}",
215                call, ntohl(call->call_id), atomic_read(&call->usage));
216 
217         spin_lock(&kafscmd_attention_lock);
218 
219         if (list_empty(&call->app_attn_link)) {
220                 list_add_tail(&call->app_attn_link, &kafscmd_attention_list);
221                 rxrpc_get_call(call);
222         }
223 
224         spin_unlock(&kafscmd_attention_lock);
225 
226         wake_up(&kafscmd_sleepq);
227 
228         _leave(" {u=%d}", atomic_read(&call->usage));
229 } /* end afscm_attention() */
230 
231 /*****************************************************************************/
232 /*
233  * handle my call being aborted
234  * - clean up, dequeue and put my ref to the call
235  */
236 static void afscm_error(struct rxrpc_call *call)
237 {
238         int removed;
239 
240         _enter("%p{est=%s ac=%u er=%d}",
241                call,
242                rxrpc_call_error_states[call->app_err_state],
243                call->app_abort_code,
244                call->app_errno);
245 
246         spin_lock(&kafscmd_attention_lock);
247 
248         if (list_empty(&call->app_attn_link)) {
249                 list_add_tail(&call->app_attn_link, &kafscmd_attention_list);
250                 rxrpc_get_call(call);
251         }
252 
253         spin_unlock(&kafscmd_attention_lock);
254 
255         removed = 0;
256         spin_lock(&afscm_calls_lock);
257         if (!list_empty(&call->app_link)) {
258                 list_del_init(&call->app_link);
259                 removed = 1;
260         }
261         spin_unlock(&afscm_calls_lock);
262 
263         if (removed)
264                 rxrpc_put_call(call);
265 
266         wake_up(&kafscmd_sleepq);
267 
268         _leave("");
269 } /* end afscm_error() */
270 
271 /*****************************************************************************/
272 /*
273  * map afs abort codes to/from Linux error codes
274  * - called with call->lock held
275  */
276 static void afscm_aemap(struct rxrpc_call *call)
277 {
278         switch (call->app_err_state) {
279         case RXRPC_ESTATE_LOCAL_ABORT:
280                 call->app_abort_code = -call->app_errno;
281                 break;
282         case RXRPC_ESTATE_PEER_ABORT:
283                 call->app_errno = -ECONNABORTED;
284                 break;
285         default:
286                 break;
287         }
288 } /* end afscm_aemap() */
289 
290 /*****************************************************************************/
291 /*
292  * start the cache manager service if not already started
293  */
294 int afscm_start(void)
295 {
296         int ret;
297 
298         down_write(&afscm_sem);
299         if (!afscm_usage) {
300                 ret = kernel_thread(kafscmd, NULL, 0);
301                 if (ret < 0)
302                         goto out;
303 
304                 wait_for_completion(&kafscmd_alive);
305 
306                 ret = rxrpc_add_service(afs_transport, &AFSCM_service);
307                 if (ret < 0)
308                         goto kill;
309 
310                 afs_kafstimod_add_timer(&afs_mntpt_expiry_timer,
311                                         afs_mntpt_expiry_timeout * HZ);
312         }
313 
314         afscm_usage++;
315         up_write(&afscm_sem);
316 
317         return 0;
318 
319  kill:
320         kafscmd_die = 1;
321         wake_up(&kafscmd_sleepq);
322         wait_for_completion(&kafscmd_dead);
323 
324  out:
325         up_write(&afscm_sem);
326         return ret;
327 
328 } /* end afscm_start() */
329 
330 /*****************************************************************************/
331 /*
332  * stop the cache manager service
333  */
334 void afscm_stop(void)
335 {
336         struct rxrpc_call *call;
337 
338         down_write(&afscm_sem);
339 
340         BUG_ON(afscm_usage == 0);
341         afscm_usage--;
342 
343         if (afscm_usage == 0) {
344                 /* don't want more incoming calls */
345                 rxrpc_del_service(afs_transport, &AFSCM_service);
346 
347                 /* abort any calls I've still got open (the afscm_error() will
348                  * dequeue them) */
349                 spin_lock(&afscm_calls_lock);
350                 while (!list_empty(&afscm_calls)) {
351                         call = list_entry(afscm_calls.next,
352                                           struct rxrpc_call,
353                                           app_link);
354 
355                         list_del_init(&call->app_link);
356                         rxrpc_get_call(call);
357                         spin_unlock(&afscm_calls_lock);
358 
359                         rxrpc_call_abort(call, -ESRCH); /* abort, dequeue and
360                                                          * put */
361 
362                         _debug("nuking active call %08x.%d",
363                                ntohl(call->conn->conn_id),
364                                ntohl(call->call_id));
365                         rxrpc_put_call(call);
366                         rxrpc_put_call(call);
367 
368                         spin_lock(&afscm_calls_lock);
369                 }
370                 spin_unlock(&afscm_calls_lock);
371 
372                 /* get rid of my daemon */
373                 kafscmd_die = 1;
374                 wake_up(&kafscmd_sleepq);
375                 wait_for_completion(&kafscmd_dead);
376 
377                 /* dispose of any calls waiting for attention */
378                 spin_lock(&kafscmd_attention_lock);
379                 while (!list_empty(&kafscmd_attention_list)) {
380                         call = list_entry(kafscmd_attention_list.next,
381                                           struct rxrpc_call,
382                                           app_attn_link);
383 
384                         list_del_init(&call->app_attn_link);
385                         spin_unlock(&kafscmd_attention_lock);
386 
387                         rxrpc_put_call(call);
388 
389                         spin_lock(&kafscmd_attention_lock);
390                 }
391                 spin_unlock(&kafscmd_attention_lock);
392 
393                 afs_kafstimod_del_timer(&afs_mntpt_expiry_timer);
394         }
395 
396         up_write(&afscm_sem);
397 
398 } /* end afscm_stop() */
399 
400 /*****************************************************************************/
401 /*
402  * handle the fileserver breaking a set of callbacks
403  */
404 static void _SRXAFSCM_CallBack(struct rxrpc_call *call)
405 {
406         struct afs_server *server;
407         size_t count, qty, tmp;
408         int ret = 0, removed;
409 
410         _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
411 
412         server = afs_server_get_from_peer(call->conn->peer);
413 
414         switch (call->app_call_state) {
415                 /* we've received the last packet
416                  * - drain all the data from the call and send the reply
417                  */
418         case RXRPC_CSTATE_SRVR_GOT_ARGS:
419                 ret = -EBADMSG;
420                 qty = call->app_ready_qty;
421                 if (qty < 8 || qty > 50 * (6 * 4) + 8)
422                         break;
423 
424                 {
425                         struct afs_callback *cb, *pcb;
426                         int loop;
427                         __be32 *fp, *bp;
428 
429                         fp = rxrpc_call_alloc_scratch(call, qty);
430 
431                         /* drag the entire argument block out to the scratch
432                          * space */
433                         ret = rxrpc_call_read_data(call, fp, qty, 0);
434                         if (ret < 0)
435                                 break;
436 
437                         /* and unmarshall the parameter block */
438                         ret = -EBADMSG;
439                         count = ntohl(*fp++);
440                         if (count>AFSCBMAX ||
441                             (count * (3 * 4) + 8 != qty &&
442                              count * (6 * 4) + 8 != qty))
443                                 break;
444 
445                         bp = fp + count*3;
446                         tmp = ntohl(*bp++);
447                         if (tmp > 0 && tmp != count)
448                                 break;
449                         if (tmp == 0)
450                                 bp = NULL;
451 
452                         pcb = cb = rxrpc_call_alloc_scratch_s(
453                                 call, struct afs_callback);
454 
455                         for (loop = count - 1; loop >= 0; loop--) {
456                                 pcb->fid.vid    = ntohl(*fp++);
457                                 pcb->fid.vnode  = ntohl(*fp++);
458                                 pcb->fid.unique = ntohl(*fp++);
459                                 if (bp) {
460                                         pcb->version    = ntohl(*bp++);
461                                         pcb->expiry     = ntohl(*bp++);
462                                         pcb->type       = ntohl(*bp++);
463                                 }
464                                 else {
465                                         pcb->version    = 0;
466                                         pcb->expiry     = 0;
467                                         pcb->type       = AFSCM_CB_UNTYPED;
468                                 }
469                                 pcb++;
470                         }
471 
472                         /* invoke the actual service routine */
473                         ret = SRXAFSCM_CallBack(server, count, cb);
474                         if (ret < 0)
475                                 break;
476                 }
477 
478                 /* send the reply */
479                 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
480                                             GFP_KERNEL, 0, &count);
481                 if (ret < 0)
482                         break;
483                 break;
484 
485                 /* operation complete */
486         case RXRPC_CSTATE_COMPLETE:
487                 call->app_user = NULL;
488                 removed = 0;
489                 spin_lock(&afscm_calls_lock);
490                 if (!list_empty(&call->app_link)) {
491                         list_del_init(&call->app_link);
492                         removed = 1;
493                 }
494                 spin_unlock(&afscm_calls_lock);
495 
496                 if (removed)
497                         rxrpc_put_call(call);
498                 break;
499 
500                 /* operation terminated on error */
501         case RXRPC_CSTATE_ERROR:
502                 call->app_user = NULL;
503                 break;
504 
505         default:
506                 break;
507         }
508 
509         if (ret < 0)
510                 rxrpc_call_abort(call, ret);
511 
512         afs_put_server(server);
513 
514         _leave(" = %d", ret);
515 
516 } /* end _SRXAFSCM_CallBack() */
517 
518 /*****************************************************************************/
519 /*
520  * handle the fileserver asking us to initialise our callback state
521  */
522 static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call)
523 {
524         struct afs_server *server;
525         size_t count;
526         int ret = 0, removed;
527 
528         _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
529 
530         server = afs_server_get_from_peer(call->conn->peer);
531 
532         switch (call->app_call_state) {
533                 /* we've received the last packet - drain all the data from the
534                  * call */
535         case RXRPC_CSTATE_SRVR_GOT_ARGS:
536                 /* shouldn't be any args */
537                 ret = -EBADMSG;
538                 break;
539 
540                 /* send the reply when asked for it */
541         case RXRPC_CSTATE_SRVR_SND_REPLY:
542                 /* invoke the actual service routine */
543                 ret = SRXAFSCM_InitCallBackState(server);
544                 if (ret < 0)
545                         break;
546 
547                 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
548                                             GFP_KERNEL, 0, &count);
549                 if (ret < 0)
550                         break;
551                 break;
552 
553                 /* operation complete */
554         case RXRPC_CSTATE_COMPLETE:
555                 call->app_user = NULL;
556                 removed = 0;
557                 spin_lock(&afscm_calls_lock);
558                 if (!list_empty(&call->app_link)) {
559                         list_del_init(&call->app_link);
560                         removed = 1;
561                 }
562                 spin_unlock(&afscm_calls_lock);
563 
564                 if (removed)
565                         rxrpc_put_call(call);
566                 break;
567 
568                 /* operation terminated on error */
569         case RXRPC_CSTATE_ERROR:
570                 call->app_user = NULL;
571                 break;
572 
573         default:
574                 break;
575         }
576 
577         if (ret < 0)
578                 rxrpc_call_abort(call, ret);
579 
580         afs_put_server(server);
581 
582         _leave(" = %d", ret);
583 
584 } /* end _SRXAFSCM_InitCallBackState() */
585 
586 /*****************************************************************************/
587 /*
588  * handle a probe from a fileserver
589  */
590 static void _SRXAFSCM_Probe(struct rxrpc_call *call)
591 {
592         struct afs_server *server;
593         size_t count;
594         int ret = 0, removed;
595 
596         _enter("%p{acs=%s}", call, rxrpc_call_states[call->app_call_state]);
597 
598         server = afs_server_get_from_peer(call->conn->peer);
599 
600         switch (call->app_call_state) {
601                 /* we've received the last packet - drain all the data from the
602                  * call */
603         case RXRPC_CSTATE_SRVR_GOT_ARGS:
604                 /* shouldn't be any args */
605                 ret = -EBADMSG;
606                 break;
607 
608                 /* send the reply when asked for it */
609         case RXRPC_CSTATE_SRVR_SND_REPLY:
610                 /* invoke the actual service routine */
611                 ret = SRXAFSCM_Probe(server);
612                 if (ret < 0)
613                         break;
614 
615                 ret = rxrpc_call_write_data(call, 0, NULL, RXRPC_LAST_PACKET,
616                                             GFP_KERNEL, 0, &count);
617                 if (ret < 0)
618                         break;
619                 break;
620 
621                 /* operation complete */
622         case RXRPC_CSTATE_COMPLETE:
623                 call->app_user = NULL;
624                 removed = 0;
625                 spin_lock(&afscm_calls_lock);
626                 if (!list_empty(&call->app_link)) {
627                         list_del_init(&call->app_link);
628                         removed = 1;
629                 }
630                 spin_unlock(&afscm_calls_lock);
631 
632                 if (removed)
633                         rxrpc_put_call(call);
634                 break;
635 
636                 /* operation terminated on error */
637         case RXRPC_CSTATE_ERROR:
638                 call->app_user = NULL;
639                 break;
640 
641         default:
642                 break;
643         }
644 
645         if (ret < 0)
646                 rxrpc_call_abort(call, ret);
647 
648         afs_put_server(server);
649 
650         _leave(" = %d", ret);
651 
652 } /* end _SRXAFSCM_Probe() */
653 
  This page was automatically generated by the LXR engine.