DEVEL15-linux-afs-translator-xen-20060731
[openafs.git] / src / afs / afs_call.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13 RCSID
14     ("$Header$");
15
16 #include "afs/sysincludes.h"    /* Standard vendor system headers */
17 #include "afsincludes.h"        /* Afs-based standard headers */
18 #include "afs/afs_stats.h"
19 #include "rx/rx_globals.h"
20 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
21 #include "net/if.h"
22 #ifdef AFS_SGI62_ENV
23 #include "h/hashing.h"
24 #endif
25 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
26 #include "netinet/in_var.h"
27 #endif
28 #endif /* !defined(UKERNEL) */
29 #ifdef AFS_LINUX22_ENV
30 #include "h/smp_lock.h"
31 #endif
32
33
34 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_HPUX_ENV)
35 #define AFS_MINBUFFERS  100
36 #else
37 #define AFS_MINBUFFERS  50
38 #endif
39
40 struct afsop_cell {
41     afs_int32 hosts[MAXCELLHOSTS];
42     char cellName[100];
43 };
44
45 char afs_zeros[AFS_ZEROS];
46 char afs_rootVolumeName[64] = "";
47 afs_uint32 rx_bindhost;
48
49 afs_int32 afs_initState = 0;
50 afs_int32 afs_termState = 0;
51 afs_int32 afs_setTime = 0;
52 int afs_cold_shutdown = 0;
53 char afs_SynchronousCloses = '\0';
54 static int afs_CB_Running = 0;
55 static int AFS_Running = 0;
56 static int afs_CacheInit_Done = 0;
57 static int afs_Go_Done = 0;
58 extern struct interfaceAddr afs_cb_interface;
59 static int afs_RX_Running = 0;
60 static int afs_InitSetup_done = 0;
61
62 afs_int32 afs_rx_deadtime = AFS_RXDEADTIME;
63 afs_int32 afs_rx_harddead = AFS_HARDDEADTIME;
64
65 static int afscall_set_rxpck_received = 0;
66
67 #if defined(AFS_HPUX_ENV)
68 extern int afs_vfs_mount();
69 #endif /* defined(AFS_HPUX_ENV) */
70
71 /* This is code which needs to be called once when the first daemon enters
72  * the client. A non-zero return means an error and AFS should not start.
73  */
74 static int
75 afs_InitSetup(int preallocs)
76 {
77     extern void afs_InitStats();
78     int code;
79
80     if (afs_InitSetup_done)
81         return EAGAIN;
82
83 #ifndef AFS_NOSTATS
84     /*
85      * Set up all the AFS statistics variables.  This should be done
86      * exactly once, and it should be done here, the first resource-setting
87      * routine to be called by the CM/RX.
88      */
89     afs_InitStats();
90 #endif /* AFS_NOSTATS */
91
92     memset(afs_zeros, 0, AFS_ZEROS);
93
94     /* start RX */
95     if(!afscall_set_rxpck_received)
96     rx_extraPackets = AFS_NRXPACKETS;   /* smaller # of packets */
97     code = rx_InitHost(rx_bindhost, htons(7001));
98     if (code) {
99         printf("AFS: RX failed to initialize %d).\n", code);
100         return code;
101     }
102     rx_SetRxDeadTime(afs_rx_deadtime);
103     /* resource init creates the services */
104     afs_ResourceInit(preallocs);
105
106     afs_InitSetup_done = 1;
107     afs_osi_Wakeup(&afs_InitSetup_done);
108
109     return code;
110 }
111 #if defined(AFS_DARWIN80_ENV)
112 struct afsd_thread_info {
113     unsigned long parm;
114 };
115 static int
116 afsd_thread(int *rock)
117 {
118     struct afsd_thread_info *arg = (struct afsd_thread_info *)rock;
119     unsigned long parm = arg->parm;
120
121     switch (parm) {
122     case AFSOP_START_RXCALLBACK:
123         AFS_GLOCK();
124         wakeup(arg);
125         afs_CB_Running = 1;
126         while (afs_RX_Running != 2)
127             afs_osi_Sleep(&afs_RX_Running);
128         afs_RXCallBackServer();
129         AFS_GUNLOCK();
130         thread_terminate(current_thread());
131         break;
132     case AFSOP_START_AFS:
133         AFS_GLOCK();
134         wakeup(arg);
135         AFS_Running = 1;
136         while (afs_initState < AFSOP_START_AFS)
137             afs_osi_Sleep(&afs_initState);
138         afs_initState = AFSOP_START_BKG;
139         afs_osi_Wakeup(&afs_initState);
140         afs_Daemon();
141         AFS_GUNLOCK();
142         thread_terminate(current_thread());
143         break;
144     case AFSOP_START_BKG:
145         AFS_GLOCK();
146         wakeup(arg);
147         while (afs_initState < AFSOP_START_BKG)
148             afs_osi_Sleep(&afs_initState);
149         if (afs_initState < AFSOP_GO) {
150             afs_initState = AFSOP_GO;
151             afs_osi_Wakeup(&afs_initState);
152         }
153         afs_BackgroundDaemon();
154         AFS_GUNLOCK();
155         thread_terminate(current_thread());
156         break;
157     case AFSOP_START_TRUNCDAEMON:
158         AFS_GLOCK();
159         wakeup(arg);
160         while (afs_initState < AFSOP_GO)
161             afs_osi_Sleep(&afs_initState);
162         afs_CacheTruncateDaemon();
163         AFS_GUNLOCK();
164         thread_terminate(current_thread());
165         break;
166     case AFSOP_START_CS:
167         AFS_GLOCK();
168         wakeup(arg);
169         afs_CheckServerDaemon();
170         AFS_GUNLOCK();
171         thread_terminate(current_thread());
172         break;
173     case AFSOP_RXEVENT_DAEMON:
174         AFS_GLOCK();
175         wakeup(arg);
176         while (afs_initState < AFSOP_START_BKG)
177             afs_osi_Sleep(&afs_initState);
178         afs_rxevent_daemon();
179         AFS_GUNLOCK();
180         thread_terminate(current_thread());
181         break;
182     case AFSOP_RXLISTENER_DAEMON:
183         AFS_GLOCK();
184         wakeup(arg);
185         afs_initState = AFSOP_START_AFS;
186         afs_osi_Wakeup(&afs_initState);
187         afs_RX_Running = 2;
188         afs_osi_Wakeup(&afs_RX_Running);
189         afs_osi_RxkRegister();
190         rxk_Listener();
191         AFS_GUNLOCK();
192         thread_terminate(current_thread());
193         break;
194     default:
195         printf("Unknown op %ld in StartDaemon()\n", (long)parm);
196         break;
197     }
198 }
199
200 void
201 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
202              long parm6)
203 {
204     int code;
205     struct afsd_thread_info info;
206     thread_t thread;
207
208     if (parm == AFSOP_START_RXCALLBACK) {
209         if (afs_CB_Running)
210             return;
211     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
212         if (afs_RX_Running)
213             return;
214         afs_RX_Running = 1;
215         code = afs_InitSetup(parm2);
216         if (parm3) {
217             rx_enablePeerRPCStats();
218         }
219         if (parm4) {
220             rx_enableProcessRPCStats();
221         }
222         if (code)
223             return;
224     } else if (parm == AFSOP_START_AFS) {
225         if (AFS_Running)
226             return;
227     }                           /* other functions don't need setup in the parent */
228     info.parm = parm;
229     kernel_thread_start((thread_continue_t)afsd_thread, &info, &thread);
230     AFS_GUNLOCK();
231     /* we need to wait cause we passed stack pointers around.... */
232     msleep(&info, NULL, PVFS, "afs_DaemonOp", NULL);
233     AFS_GLOCK();
234     thread_deallocate(thread);
235 }
236 #endif
237
238
239 #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)
240 struct afsd_thread_info {
241     unsigned long parm;
242     struct completion *complete;
243 };
244
245 static int
246 afsd_thread(void *rock)
247 {
248     struct afsd_thread_info *arg = rock;
249     unsigned long parm = arg->parm;
250 #ifdef SYS_SETPRIORITY_EXPORTED
251     int (*sys_setpriority) (int, int, int) = sys_call_table[__NR_setpriority];
252 #endif
253 #if defined(AFS_LINUX26_ENV)
254     daemonize("afsd");
255 #else
256     daemonize();
257 #endif
258                                 /* doesn't do much, since we were forked from keventd, but
259                                  * does call mm_release, which wakes up our parent (since it
260                                  * used CLONE_VFORK) */
261 #if !defined(AFS_LINUX26_ENV)
262     reparent_to_init();
263 #endif
264     afs_osi_MaskSignals();
265     switch (parm) {
266     case AFSOP_START_RXCALLBACK:
267         sprintf(current->comm, "afs_cbstart");
268         AFS_GLOCK();
269         complete(arg->complete);
270         afs_CB_Running = 1;
271         while (afs_RX_Running != 2)
272             afs_osi_Sleep(&afs_RX_Running);
273         sprintf(current->comm, "afs_callback");
274         afs_RXCallBackServer();
275         AFS_GUNLOCK();
276         complete_and_exit(0, 0);
277         break;
278     case AFSOP_START_AFS:
279         sprintf(current->comm, "afs_afsstart");
280         AFS_GLOCK();
281         complete(arg->complete);
282         AFS_Running = 1;
283         while (afs_initState < AFSOP_START_AFS)
284             afs_osi_Sleep(&afs_initState);
285         afs_initState = AFSOP_START_BKG;
286         afs_osi_Wakeup(&afs_initState);
287         sprintf(current->comm, "afsd");
288         afs_Daemon();
289         AFS_GUNLOCK();
290         complete_and_exit(0, 0);
291         break;
292     case AFSOP_START_BKG:
293         sprintf(current->comm, "afs_bkgstart");
294         AFS_GLOCK();
295         complete(arg->complete);
296         while (afs_initState < AFSOP_START_BKG)
297             afs_osi_Sleep(&afs_initState);
298         if (afs_initState < AFSOP_GO) {
299             afs_initState = AFSOP_GO;
300             afs_osi_Wakeup(&afs_initState);
301         }
302         sprintf(current->comm, "afs_background");
303         afs_BackgroundDaemon();
304         AFS_GUNLOCK();
305         complete_and_exit(0, 0);
306         break;
307     case AFSOP_START_TRUNCDAEMON:
308         sprintf(current->comm, "afs_trimstart");
309         AFS_GLOCK();
310         complete(arg->complete);
311         while (afs_initState < AFSOP_GO)
312             afs_osi_Sleep(&afs_initState);
313         sprintf(current->comm, "afs_cachetrim");
314         afs_CacheTruncateDaemon();
315         AFS_GUNLOCK();
316         complete_and_exit(0, 0);
317         break;
318     case AFSOP_START_CS:
319         sprintf(current->comm, "afs_checkserver");
320         AFS_GLOCK();
321         complete(arg->complete);
322         afs_CheckServerDaemon();
323         AFS_GUNLOCK();
324         complete_and_exit(0, 0);
325         break;
326     case AFSOP_RXEVENT_DAEMON:
327         sprintf(current->comm, "afs_evtstart");
328 #ifdef SYS_SETPRIORITY_EXPORTED
329         sys_setpriority(PRIO_PROCESS, 0, -10);
330 #else
331 #ifdef CURRENT_INCLUDES_NICE
332         current->nice = -10;
333 #endif
334 #endif
335         AFS_GLOCK();
336         complete(arg->complete);
337         while (afs_initState < AFSOP_START_BKG)
338             afs_osi_Sleep(&afs_initState);
339         sprintf(current->comm, "afs_rxevent");
340         afs_rxevent_daemon();
341         AFS_GUNLOCK();
342         complete_and_exit(0, 0);
343         break;
344     case AFSOP_RXLISTENER_DAEMON:
345         sprintf(current->comm, "afs_lsnstart");
346 #ifdef SYS_SETPRIORITY_EXPORTED
347         sys_setpriority(PRIO_PROCESS, 0, -10);
348 #else
349 #ifdef CURRENT_INCLUDES_NICE
350         current->nice = -10;
351 #endif
352 #endif
353         AFS_GLOCK();
354         complete(arg->complete);
355         afs_initState = AFSOP_START_AFS;
356         afs_osi_Wakeup(&afs_initState);
357         afs_RX_Running = 2;
358         afs_osi_Wakeup(&afs_RX_Running);
359         afs_osi_RxkRegister();
360         sprintf(current->comm, "afs_rxlistener");
361         rxk_Listener();
362         AFS_GUNLOCK();
363         complete_and_exit(0, 0);
364         break;
365     default:
366         printf("Unknown op %ld in StartDaemon()\n", (long)parm);
367         break;
368     }
369     return 0;
370 }
371
372 void
373 afsd_launcher(void *rock)
374 {
375     if (!kernel_thread(afsd_thread, rock, CLONE_VFORK | SIGCHLD))
376         printf("kernel_thread failed. afs startup will not complete\n");
377 }
378
379 void
380 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
381              long parm6)
382 {
383     int code;
384     DECLARE_COMPLETION(c);
385 #if defined(AFS_LINUX26_ENV)
386     struct work_struct tq;
387 #else
388     struct tq_struct tq;
389 #endif
390     struct afsd_thread_info info;
391     if (parm == AFSOP_START_RXCALLBACK) {
392         if (afs_CB_Running)
393             return;
394     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
395         if (afs_RX_Running)
396             return;
397         afs_RX_Running = 1;
398         code = afs_InitSetup(parm2);
399         if (parm3) {
400             rx_enablePeerRPCStats();
401         }
402         if (parm4) {
403             rx_enableProcessRPCStats();
404         }
405         if (code)
406             return;
407     } else if (parm == AFSOP_START_AFS) {
408         if (AFS_Running)
409             return;
410     }                           /* other functions don't need setup in the parent */
411     info.complete = &c;
412     info.parm = parm;
413 #if defined(AFS_LINUX26_ENV)
414     INIT_WORK(&tq, afsd_launcher, &info);
415     schedule_work(&tq);
416 #else
417     tq.sync = 0;
418     INIT_LIST_HEAD(&tq.list);
419     tq.routine = afsd_launcher;
420     tq.data = &info;
421     schedule_task(&tq);
422 #endif
423     AFS_GUNLOCK();
424     /* we need to wait cause we passed stack pointers around.... */
425     wait_for_completion(&c);
426     AFS_GLOCK();
427 }
428 #endif
429
430 /* leaving as is, probably will barf if we add prototypes here since it's likely being called
431 with partial list */
432 int
433 afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
434      long parm, parm2, parm3, parm4, parm5, parm6;
435 {
436     afs_int32 code = 0;
437 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
438     size_t bufferSize;
439 #else /* AFS_SGI61_ENV */
440     u_int bufferSize;
441 #endif /* AFS_SGI61_ENV */
442
443     AFS_STATCNT(afs_syscall_call);
444 #ifdef  AFS_SUN5_ENV
445     if (!afs_suser(CRED()) && (parm != AFSOP_GETMTU)
446         && (parm != AFSOP_GETMASK)) {
447         /* only root can run this code */
448         return (EACCES);
449 #else
450     if (!afs_suser(NULL) && (parm != AFSOP_GETMTU)
451         && (parm != AFSOP_GETMASK)) {
452         /* only root can run this code */
453 #if defined(KERNEL_HAVE_UERROR)
454         setuerror(EACCES);
455         return (EACCES);
456 #else
457 #if defined(AFS_OSF_ENV)
458         return EACCES;
459 #else /* AFS_OSF_ENV */
460         return EPERM;
461 #endif /* AFS_OSF_ENV */
462 #endif
463 #endif
464     }
465     AFS_GLOCK();
466 #ifdef AFS_DARWIN80_ENV
467     put_vfs_context();
468 #endif
469 #if ((defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)) || defined(AFS_DARWIN80_ENV)) && !defined(UKERNEL)
470     if (parm < AFSOP_ADDCELL || parm == AFSOP_RXEVENT_DAEMON
471         || parm == AFSOP_RXLISTENER_DAEMON) {
472         afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
473     }
474 #else /* !(AFS_LINUX24_ENV && !UKERNEL) */
475     if (parm == AFSOP_START_RXCALLBACK) {
476         if (afs_CB_Running)
477             goto out;
478         afs_CB_Running = 1;
479 #ifndef RXK_LISTENER_ENV
480         code = afs_InitSetup(parm2);
481         if (!code)
482 #endif /* !RXK_LISTENER_ENV */
483         {
484 #ifdef RXK_LISTENER_ENV
485             while (afs_RX_Running != 2)
486                 afs_osi_Sleep(&afs_RX_Running);
487 #else /* !RXK_LISTENER_ENV */
488             afs_initState = AFSOP_START_AFS;
489             afs_osi_Wakeup(&afs_initState);
490 #endif /* RXK_LISTENER_ENV */
491             afs_osi_Invisible();
492             afs_RXCallBackServer();
493         }
494 #ifdef AFS_SGI_ENV
495         AFS_GUNLOCK();
496         exit(CLD_EXITED, code);
497 #endif /* AFS_SGI_ENV */
498     }
499 #ifdef RXK_LISTENER_ENV
500     else if (parm == AFSOP_RXLISTENER_DAEMON) {
501         if (afs_RX_Running)
502             goto out;
503         afs_RX_Running = 1;
504         code = afs_InitSetup(parm2);
505         if (parm3) {
506             rx_enablePeerRPCStats();
507         }
508         if (parm4) {
509             rx_enableProcessRPCStats();
510         }
511         if (!code) {
512             afs_initState = AFSOP_START_AFS;
513             afs_osi_Wakeup(&afs_initState);
514             afs_osi_Invisible();
515             afs_RX_Running = 2;
516             afs_osi_Wakeup(&afs_RX_Running);
517 #ifndef UKERNEL
518             afs_osi_RxkRegister();
519 #endif /* !UKERNEL */
520             rxk_Listener();
521         }
522 #ifdef  AFS_SGI_ENV
523         AFS_GUNLOCK();
524         exit(CLD_EXITED, code);
525 #endif /* AFS_SGI_ENV */
526     }
527 #endif /* RXK_LISTENER_ENV */
528     else if (parm == AFSOP_START_AFS) {
529         /* afs daemon */
530         if (AFS_Running)
531             goto out;
532         AFS_Running = 1;
533         while (afs_initState < AFSOP_START_AFS)
534             afs_osi_Sleep(&afs_initState);
535
536         afs_initState = AFSOP_START_BKG;
537         afs_osi_Wakeup(&afs_initState);
538         afs_osi_Invisible();
539         afs_Daemon();
540 #ifdef AFS_SGI_ENV
541         AFS_GUNLOCK();
542         exit(CLD_EXITED, 0);
543 #endif /* AFS_SGI_ENV */
544     } else if (parm == AFSOP_START_CS) {
545         afs_osi_Invisible();
546         afs_CheckServerDaemon();
547 #ifdef AFS_SGI_ENV
548         AFS_GUNLOCK();
549         exit(CLD_EXITED, 0);
550 #endif /* AFS_SGI_ENV */
551     } else if (parm == AFSOP_START_BKG) {
552         while (afs_initState < AFSOP_START_BKG)
553             afs_osi_Sleep(&afs_initState);
554         if (afs_initState < AFSOP_GO) {
555             afs_initState = AFSOP_GO;
556             afs_osi_Wakeup(&afs_initState);
557         }
558         /* start the bkg daemon */
559         afs_osi_Invisible();
560 #ifdef AFS_AIX32_ENV
561         if (parm2)
562             afs_BioDaemon(parm2);
563         else
564 #endif /* AFS_AIX32_ENV */
565             afs_BackgroundDaemon();
566 #ifdef AFS_SGI_ENV
567         AFS_GUNLOCK();
568         exit(CLD_EXITED, 0);
569 #endif /* AFS_SGI_ENV */
570     } else if (parm == AFSOP_START_TRUNCDAEMON) {
571         while (afs_initState < AFSOP_GO)
572             afs_osi_Sleep(&afs_initState);
573         /* start the bkg daemon */
574         afs_osi_Invisible();
575         afs_CacheTruncateDaemon();
576 #ifdef  AFS_SGI_ENV
577         AFS_GUNLOCK();
578         exit(CLD_EXITED, 0);
579 #endif /* AFS_SGI_ENV */
580     }
581 #if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
582     else if (parm == AFSOP_RXEVENT_DAEMON) {
583         while (afs_initState < AFSOP_START_BKG)
584             afs_osi_Sleep(&afs_initState);
585         afs_osi_Invisible();
586         afs_rxevent_daemon();
587 #ifdef AFS_SGI_ENV
588         AFS_GUNLOCK();
589         exit(CLD_EXITED, 0);
590 #endif /* AFS_SGI_ENV */
591     }
592 #endif /* AFS_SUN5_ENV || RXK_LISTENER_ENV */
593 #endif /* AFS_LINUX24_ENV && !UKERNEL */
594     else if (parm == AFSOP_BASIC_INIT) {
595         afs_int32 temp;
596
597         while (!afs_InitSetup_done)
598             afs_osi_Sleep(&afs_InitSetup_done);
599
600 #if defined(AFS_SGI_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_SUN5_ENV)
601         temp = AFS_MINBUFFERS;  /* Should fix this soon */
602 #else
603         /* number of 2k buffers we could get from all of the buffer space */
604         temp = ((afs_bufferpages * NBPG) >> 11);
605         temp = temp >> 2;       /* don't take more than 25% (our magic parameter) */
606         if (temp < AFS_MINBUFFERS)
607             temp = AFS_MINBUFFERS;      /* though we really should have this many */
608 #endif
609         DInit(temp);
610         afs_rootFid.Fid.Volume = 0;
611         code = 0;
612     } else if (parm == AFSOP_BUCKETPCT) {
613         /* need to enable this now, will disable again before GO
614            if we don't have 100% */
615         splitdcache = 1;
616         switch (parm2) {
617         case 1:
618             afs_tpct1 = parm3;
619             break;
620         case 2:
621             afs_tpct2 = parm3;
622             break;
623         }           
624     } else if (parm == AFSOP_ADDCELL) {
625         /* add a cell.  Parameter 2 is 8 hosts (in net order),  parm 3 is the null-terminated
626          * name.  Parameter 4 is the length of the name, including the null.  Parm 5 is the
627          * home cell flag (0x1 bit) and the nosuid flag (0x2 bit) */
628         struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
629
630         code = afs_InitDynroot();
631         if (!code) {
632             AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
633                        code);
634         }
635         if (!code) {
636             if (parm4 > sizeof(tcell->cellName))
637                 code = EFAULT;
638             else {
639                 AFS_COPYIN((char *)parm3, tcell->cellName, parm4, code);
640                 if (!code)
641                     afs_NewCell(tcell->cellName, tcell->hosts, parm5, NULL, 0,
642                                 0, 0);
643             }
644         }
645         afs_osi_Free(tcell, sizeof(struct afsop_cell));
646     } else if (parm == AFSOP_ADDCELL2) {
647         struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
648         char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ), *lcnamep = 0;
649         char *tbuffer1 = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
650         int cflags = parm4;
651
652         code = afs_InitDynroot();
653         if (!code) {
654 #if 0
655             /* wait for basic init - XXX can't find any reason we need this? */
656             while (afs_initState < AFSOP_START_BKG)
657                 afs_osi_Sleep(&afs_initState);
658 #endif
659
660             AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
661                        code);
662         }
663         if (!code) {
664             AFS_COPYINSTR((char *)parm3, tbuffer1, AFS_SMALLOCSIZ,
665                           &bufferSize, code);
666             if (!code) {
667                 if (parm4 & 4) {
668                     AFS_COPYINSTR((char *)parm5, tbuffer, AFS_SMALLOCSIZ,
669                                   &bufferSize, code);
670                     if (!code) {
671                         lcnamep = tbuffer;
672                         cflags |= CLinkedCell;
673                     }
674                 }
675                 if (!code)
676                     code =
677                         afs_NewCell(tbuffer1, tcell->hosts, cflags, lcnamep,
678                                     0, 0, 0);
679             }
680         }
681         afs_osi_Free(tcell, sizeof(struct afsop_cell));
682         osi_FreeSmallSpace(tbuffer);
683         osi_FreeSmallSpace(tbuffer1);
684     } else if (parm == AFSOP_ADDCELLALIAS) {
685         /*
686          * Call arguments:
687          * parm2 is the alias name
688          * parm3 is the real cell name
689          */
690         char *aliasName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
691         char *cellName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
692
693         code = afs_InitDynroot();
694         if (!code) {
695             AFS_COPYINSTR((char *)parm2, aliasName, AFS_SMALLOCSIZ, &bufferSize,
696                           code);
697         }
698         if (!code)
699             AFS_COPYINSTR((char *)parm3, cellName, AFS_SMALLOCSIZ,
700                           &bufferSize, code);
701         if (!code)
702             afs_NewCellAlias(aliasName, cellName);
703         osi_FreeSmallSpace(aliasName);
704         osi_FreeSmallSpace(cellName);
705     } else if (parm == AFSOP_SET_THISCELL) {
706         /*
707          * Call arguments:
708          * parm2 is the primary cell name
709          */
710         char *cell = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
711
712         code = afs_InitDynroot();
713         if (!code) {
714             AFS_COPYINSTR((char *)parm2, cell, AFS_SMALLOCSIZ, &bufferSize, code);
715         }
716         if (!code)
717             afs_SetPrimaryCell(cell);
718         osi_FreeSmallSpace(cell);
719     } else if (parm == AFSOP_CACHEINIT) {
720         struct afs_cacheParams cparms;
721
722         if (afs_CacheInit_Done)
723             goto out;
724
725         AFS_COPYIN((char *)parm2, (caddr_t) & cparms, sizeof(cparms), code);
726         if (code) {
727 #if defined(KERNEL_HAVE_UERROR)
728             setuerror(code);
729             code = -1;
730 #endif
731             goto out;
732         }
733         afs_CacheInit_Done = 1;
734         code = afs_icl_InitLogs();
735         afs_setTime = cparms.setTimeFlag;
736
737         code =
738             afs_CacheInit(cparms.cacheScaches, cparms.cacheFiles,
739                           cparms.cacheBlocks, cparms.cacheDcaches,
740                           cparms.cacheVolumes, cparms.chunkSize,
741                           cparms.memCacheFlag, cparms.inodes, cparms.users);
742
743     } else if (parm == AFSOP_CACHEINODE) {
744         ino_t ainode = parm2;
745         /* wait for basic init */
746         while (afs_initState < AFSOP_START_BKG)
747             afs_osi_Sleep(&afs_initState);
748
749 #ifdef AFS_DARWIN80_ENV
750     get_vfs_context();
751 #endif
752         /* do it by inode */
753 #ifdef AFS_SGI62_ENV
754         ainode = (ainode << 32) | (parm3 & 0xffffffff);
755 #endif
756         code = afs_InitCacheFile(NULL, ainode);
757 #ifdef AFS_DARWIN80_ENV
758     put_vfs_context();
759 #endif
760     } else if (parm == AFSOP_ROOTVOLUME) {
761         /* wait for basic init */
762         while (afs_initState < AFSOP_START_BKG)
763             afs_osi_Sleep(&afs_initState);
764
765         if (parm2) {
766             AFS_COPYINSTR((char *)parm2, afs_rootVolumeName,
767                           sizeof(afs_rootVolumeName), &bufferSize, code);
768             afs_rootVolumeName[sizeof(afs_rootVolumeName) - 1] = 0;
769         } else
770             code = 0;
771     } else if (parm == AFSOP_CACHEFILE || parm == AFSOP_CACHEINFO
772                || parm == AFSOP_VOLUMEINFO || parm == AFSOP_AFSLOG
773                || parm == AFSOP_CELLINFO) {
774         char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
775
776         code = 0;
777         AFS_COPYINSTR((char *)parm2, tbuffer, AFS_SMALLOCSIZ, &bufferSize,
778                       code);
779         if (code) {
780             osi_FreeSmallSpace(tbuffer);
781             goto out;
782         }
783         if (!code) {
784             tbuffer[AFS_SMALLOCSIZ - 1] = '\0'; /* null-terminate the name */
785             /* We have the cache dir copied in.  Call the cache init routine */
786 #ifdef AFS_DARWIN80_ENV
787     get_vfs_context();
788 #endif
789             if (parm == AFSOP_CACHEFILE)
790                 code = afs_InitCacheFile(tbuffer, 0);
791             else if (parm == AFSOP_CACHEINFO)
792                 code = afs_InitCacheInfo(tbuffer);
793             else if (parm == AFSOP_VOLUMEINFO)
794                 code = afs_InitVolumeInfo(tbuffer);
795             else if (parm == AFSOP_CELLINFO)
796                 code = afs_InitCellInfo(tbuffer);
797 #ifdef AFS_DARWIN80_ENV
798     put_vfs_context();
799 #endif
800         }
801         osi_FreeSmallSpace(tbuffer);
802     } else if (parm == AFSOP_GO) {
803         /* the generic initialization calls come here.  One parameter: should we do the
804          * set-time operation on this workstation */
805         if (afs_Go_Done)
806             goto out;
807         afs_Go_Done = 1;
808         while (afs_initState < AFSOP_GO)
809             afs_osi_Sleep(&afs_initState);
810         afs_initState = 101;
811         afs_setTime = parm2;
812         if (afs_tpct1 + afs_tpct2 != 100) {
813             afs_tpct1 = 0;
814             afs_tpct2 = 0;
815             splitdcache = 0;
816         } else {        
817             splitdcache = 1;
818         }
819         afs_osi_Wakeup(&afs_initState);
820 #if     (!defined(AFS_NONFSTRANS)) || defined(AFS_AIX_IAUTH_ENV)
821         afs_nfsclient_init();
822 #endif
823         printf("found %d non-empty cache files (%d%%).\n",
824                afs_stats_cmperf.cacheFilesReused,
825                (100 * afs_stats_cmperf.cacheFilesReused) /
826                (afs_stats_cmperf.cacheNumEntries ? afs_stats_cmperf.
827                 cacheNumEntries : 1));
828     } else if (parm == AFSOP_ADVISEADDR) {
829         /* pass in the host address to the rx package */
830         int rxbind = 0;
831         afs_int32 count = parm2;
832         afs_int32 *buffer =
833             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
834         afs_int32 *maskbuffer =
835             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
836         afs_int32 *mtubuffer =
837             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
838         int i;
839
840         /* Bind, but only if there's only one address configured */ 
841         if ( count & 0x80000000) {
842             count &= ~0x80000000;
843             if (count == 1)
844                 rxbind=1;
845         }
846
847         if (count > AFS_MAX_INTERFACE_ADDR) {
848             code = ENOMEM;
849             count = AFS_MAX_INTERFACE_ADDR;
850         }
851
852         AFS_COPYIN((char *)parm3, (char *)buffer, count * sizeof(afs_int32),
853                    code);
854         if (parm4)
855             AFS_COPYIN((char *)parm4, (char *)maskbuffer,
856                        count * sizeof(afs_int32), code);
857         if (parm5)
858             AFS_COPYIN((char *)parm5, (char *)mtubuffer,
859                        count * sizeof(afs_int32), code);
860
861         afs_cb_interface.numberOfInterfaces = count;
862         for (i = 0; i < count; i++) {
863             afs_cb_interface.addr_in[i] = buffer[i];
864 #ifdef AFS_USERSPACE_IP_ADDR
865             /* AFS_USERSPACE_IP_ADDR means we have no way of finding the
866              * machines IP addresses when in the kernel (the in_ifaddr
867              * struct is not available), so we pass the info in at
868              * startup. We also pass in the subnetmask and mtu size. The
869              * subnetmask is used when setting the rank:
870              * afsi_SetServerIPRank(); and the mtu size is used when
871              * finding the best mtu size. rxi_FindIfnet() is replaced
872              * with rxi_Findcbi().
873              */
874             afs_cb_interface.subnetmask[i] =
875                 (parm4 ? maskbuffer[i] : 0xffffffff);
876             afs_cb_interface.mtu[i] = (parm5 ? mtubuffer[i] : htonl(1500));
877 #endif
878         }
879         afs_uuid_create(&afs_cb_interface.uuid);
880         rxi_setaddr(buffer[0]);
881         if (rxbind)
882             rx_bindhost = buffer[0];
883         else
884             rx_bindhost = htonl(INADDR_ANY);
885
886         afs_osi_Free(buffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
887         afs_osi_Free(maskbuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
888         afs_osi_Free(mtubuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
889     }
890 #ifdef  AFS_SGI53_ENV
891     else if (parm == AFSOP_NFSSTATICADDR) {
892         extern int (*nfs_rfsdisptab_v2) ();
893         nfs_rfsdisptab_v2 = (int (*)())parm2;
894     } else if (parm == AFSOP_NFSSTATICADDR2) {
895         extern int (*nfs_rfsdisptab_v2) ();
896 #ifdef _K64U64
897         nfs_rfsdisptab_v2 = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
898 #else /* _K64U64 */
899         nfs_rfsdisptab_v2 = (int (*)())(parm3 & 0xffffffff);
900 #endif /* _K64U64 */
901     }
902 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
903     else if (parm == AFSOP_SBLOCKSTATICADDR2) {
904         extern int (*afs_sblockp) ();
905         extern void (*afs_sbunlockp) ();
906 #ifdef _K64U64
907         afs_sblockp = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
908         afs_sbunlockp = (void (*)())((parm4 << 32) | (parm5 & 0xffffffff));
909 #else
910         afs_sblockp = (int (*)())(parm3 & 0xffffffff);
911         afs_sbunlockp = (void (*)())(parm5 & 0xffffffff);
912 #endif /* _K64U64 */
913     }
914 #endif /* AFS_SGI62_ENV && !AFS_SGI65_ENV */
915 #endif /* AFS_SGI53_ENV */
916     else if (parm == AFSOP_SHUTDOWN) {
917         afs_cold_shutdown = 0;
918         if (parm2 == 1)
919             afs_cold_shutdown = 1;
920 #ifndef AFS_DARWIN_ENV
921         if (afs_globalVFS != 0) {
922             afs_warn("AFS isn't unmounted yet! Call aborted\n");
923             code = EACCES;
924         } else
925 #endif
926             afs_shutdown();
927     } else if (parm == AFSOP_AFS_VFSMOUNT) {
928 #ifdef  AFS_HPUX_ENV
929         vfsmount(parm2, parm3, parm4, parm5);
930 #else /* defined(AFS_HPUX_ENV) */
931 #if defined(KERNEL_HAVE_UERROR)
932         setuerror(EINVAL);
933 #else
934         code = EINVAL;
935 #endif
936 #endif /* defined(AFS_HPUX_ENV) */
937     } else if (parm == AFSOP_CLOSEWAIT) {
938         afs_SynchronousCloses = 'S';
939     } else if (parm == AFSOP_GETMTU) {
940         afs_uint32 mtu = 0;
941 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
942 #ifdef AFS_USERSPACE_IP_ADDR
943         afs_int32 i;
944         i = rxi_Findcbi(parm2);
945         mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
946 #else /* AFS_USERSPACE_IP_ADDR */
947         AFS_IFNET_T tifnp;
948
949         tifnp = rxi_FindIfnet(parm2, NULL);     /*  make iterative */
950         mtu = (tifnp ? ifnet_mtu(tifnp) : htonl(1500));
951 #endif /* else AFS_USERSPACE_IP_ADDR */
952 #endif /* !AFS_SUN5_ENV */
953         if (!code)
954             AFS_COPYOUT((caddr_t) & mtu, (caddr_t) parm3, sizeof(afs_int32),
955                         code);
956 #ifdef AFS_AIX32_ENV
957 /* this is disabled for now because I can't figure out how to get access
958  * to these kernel variables.  It's only for supporting user-mode rx
959  * programs -- it makes a huge difference on the 220's in my testbed,
960  * though I don't know why. The bosserver does this with /etc/no, so it's
961  * being handled a different way for the servers right now.  */
962 /*      {
963         static adjusted = 0;
964         extern u_long sb_max_dflt;
965         if (!adjusted) {
966           adjusted = 1;
967           if (sb_max_dflt < 131072) sb_max_dflt = 131072; 
968           if (sb_max < 131072) sb_max = 131072; 
969         }
970       } */
971 #endif /* AFS_AIX32_ENV */
972     } else if (parm == AFSOP_GETMASK) { /* parm2 == addr in net order */
973         afs_uint32 mask = 0;
974 #if     !defined(AFS_SUN5_ENV)
975 #ifdef AFS_USERSPACE_IP_ADDR
976         afs_int32 i;
977         i = rxi_Findcbi(parm2);
978         if (i != -1) {
979             mask = afs_cb_interface.subnetmask[i];
980         } else {
981             code = -1;
982         }
983 #else /* AFS_USERSPACE_IP_ADDR */
984         AFS_IFNET_T tifnp;
985
986         tifnp = rxi_FindIfnet(parm2, &mask);    /* make iterative */
987         if (!tifnp)
988             code = -1;
989 #endif /* else AFS_USERSPACE_IP_ADDR */
990 #endif /* !AFS_SUN5_ENV */
991         if (!code)
992             AFS_COPYOUT((caddr_t) & mask, (caddr_t) parm3, sizeof(afs_int32),
993                         code);
994     }
995 #ifdef AFS_AFSDB_ENV
996     else if (parm == AFSOP_AFSDB_HANDLER) {
997         int sizeArg = (int)parm4;
998         int kmsgLen = sizeArg & 0xffff;
999         int cellLen = (sizeArg & 0xffff0000) >> 16;
1000         afs_int32 *kmsg = afs_osi_Alloc(kmsgLen);
1001         char *cellname = afs_osi_Alloc(cellLen);
1002
1003 #ifndef UKERNEL
1004         afs_osi_MaskUserLoop();
1005 #endif
1006         AFS_COPYIN((afs_int32 *) parm2, cellname, cellLen, code);
1007         AFS_COPYIN((afs_int32 *) parm3, kmsg, kmsgLen, code);
1008         if (!code) {
1009             code = afs_AFSDBHandler(cellname, cellLen, kmsg);
1010             if (*cellname == 1)
1011                 *cellname = 0;
1012             if (code == -2) {   /* Shutting down? */
1013                 *cellname = 1;
1014                 code = 0;
1015             }
1016         }
1017         if (!code)
1018             AFS_COPYOUT(cellname, (char *)parm2, cellLen, code);
1019         afs_osi_Free(kmsg, kmsgLen);
1020         afs_osi_Free(cellname, cellLen);
1021     }
1022 #endif
1023     else if (parm == AFSOP_SET_DYNROOT) {
1024         code = afs_SetDynrootEnable(parm2);
1025     } else if (parm == AFSOP_SET_FAKESTAT) {
1026         afs_fakestat_enable = parm2;
1027         code = 0;
1028     } else if (parm == AFSOP_SET_BACKUPTREE) {
1029         afs_bkvolpref = parm2;
1030     } else if (parm == AFSOP_SET_RXPCK) {
1031         rx_extraPackets = parm2;
1032         afscall_set_rxpck_received = 1;
1033     } else
1034         code = EINVAL;
1035
1036   out:
1037 #ifdef AFS_DARWIN80_ENV /* to balance the put in afs3_syscall() */
1038     get_vfs_context();
1039 #endif
1040     AFS_GUNLOCK();
1041 #ifdef AFS_LINUX20_ENV
1042     return -code;
1043 #else
1044     return code;
1045 #endif
1046 }
1047
1048 /*
1049  * Initstate in the range 0 < x < 100 are early initialization states.
1050  * Initstate of 100 means a AFSOP_START operation has been done.  After this,
1051  *  the cache may be initialized.
1052  * Initstate of 101 means a AFSOP_GO operation has been done.  This operation
1053  *  is done after all the cache initialization has been done.
1054  * Initstate of 200 means that the volume has been looked up once, possibly
1055  *  incorrectly.
1056  * Initstate of 300 means that the volume has been *successfully* looked up.
1057  */
1058 int
1059 afs_CheckInit(void)
1060 {
1061     register int code = 0;
1062
1063     AFS_STATCNT(afs_CheckInit);
1064     if (afs_initState <= 100)
1065         code = ENXIO;           /* never finished init phase */
1066     else if (afs_initState == 101) {    /* init done, wait for afs_daemon */
1067         while (afs_initState < 200)
1068             afs_osi_Sleep(&afs_initState);
1069     } else if (afs_initState == 200)
1070         code = ETIMEDOUT;       /* didn't find root volume */
1071     return code;
1072 }
1073
1074 int afs_shuttingdown = 0;
1075 void
1076 afs_shutdown(void)
1077 {
1078     extern short afs_brsDaemons;
1079     extern afs_int32 afs_CheckServerDaemonStarted;
1080     extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
1081     extern struct osi_file *afs_cacheInodep;
1082
1083     AFS_STATCNT(afs_shutdown);
1084     if (afs_initState == 0) {
1085         afs_warn("AFS not initialized - not shutting down\n");
1086       return;
1087     }
1088
1089     if (afs_shuttingdown)
1090         return;
1091     afs_shuttingdown = 1;
1092     if (afs_cold_shutdown)
1093         afs_warn("COLD ");
1094     else
1095         afs_warn("WARM ");
1096     afs_warn("shutting down of: CB... ");
1097
1098     afs_termState = AFSOP_STOP_RXCALLBACK;
1099     rx_WakeupServerProcs();
1100 #ifdef AFS_AIX51_ENV
1101     shutdown_rxkernel();
1102 #endif
1103     /* shutdown_rxkernel(); */
1104     while (afs_termState == AFSOP_STOP_RXCALLBACK)
1105         afs_osi_Sleep(&afs_termState);
1106
1107     afs_warn("afs... ");
1108     while (afs_termState == AFSOP_STOP_AFS) {
1109         afs_osi_CancelWait(&AFS_WaitHandler);
1110         afs_osi_Sleep(&afs_termState);
1111     }
1112     if (afs_CheckServerDaemonStarted) {
1113         while (afs_termState == AFSOP_STOP_CS) {
1114             afs_osi_CancelWait(&AFS_CSWaitHandler);
1115             afs_osi_Sleep(&afs_termState);
1116         }
1117     }
1118     afs_warn("BkG... ");
1119     /* Wake-up afs_brsDaemons so that we don't have to wait for a bkg job! */
1120     while (afs_termState == AFSOP_STOP_BKG) {
1121         afs_osi_Wakeup(&afs_brsDaemons);
1122         afs_osi_Sleep(&afs_termState);
1123     }
1124     afs_warn("CTrunc... ");
1125     /* Cancel cache truncate daemon. */
1126     while (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
1127         afs_osi_Wakeup((char *)&afs_CacheTruncateDaemon);
1128         afs_osi_Sleep(&afs_termState);
1129     }
1130 #ifdef AFS_AFSDB_ENV
1131     afs_warn("AFSDB... ");
1132     afs_StopAFSDB();
1133     while (afs_termState == AFSOP_STOP_AFSDB)
1134         afs_osi_Sleep(&afs_termState);
1135 #endif
1136 #if     defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
1137     afs_warn("RxEvent... ");
1138     /* cancel rx event daemon */
1139     while (afs_termState == AFSOP_STOP_RXEVENT)
1140         afs_osi_Sleep(&afs_termState);
1141 #if defined(RXK_LISTENER_ENV)
1142 #ifndef UKERNEL
1143     afs_warn("UnmaskRxkSignals... ");
1144     afs_osi_UnmaskRxkSignals();
1145 #endif
1146     /* cancel rx listener */
1147     afs_warn("RxListener... ");
1148     osi_StopListener();         /* This closes rx_socket. */
1149     while (afs_termState == AFSOP_STOP_RXK_LISTENER) {
1150         afs_warn("Sleep... ");
1151         afs_osi_Sleep(&afs_termState);
1152     }
1153 #endif
1154 #else
1155     afs_termState = AFSOP_STOP_COMPLETE;
1156 #endif
1157     afs_warn("\n");
1158
1159     /* Close file only after daemons which can write to it are stopped. */
1160     if (afs_cacheInodep) {      /* memcache won't set this */
1161         osi_UFSClose(afs_cacheInodep);  /* Since we always leave it open */
1162         afs_cacheInodep = 0;
1163     }
1164     return;                     /* Just kill daemons for now */
1165 #ifdef notdef
1166     shutdown_CB();
1167     shutdown_AFS();
1168     shutdown_rxkernel();
1169     shutdown_rxevent();
1170     shutdown_rx();
1171     afs_shutdown_BKG();
1172     shutdown_bufferpackage();
1173 #endif
1174 #ifdef AFS_AIX51_ENV
1175     shutdown_daemons();
1176 #endif
1177 #ifdef notdef
1178     shutdown_cache();
1179     shutdown_osi();
1180     shutdown_osinet();
1181     shutdown_osifile();
1182     shutdown_vnodeops();
1183     shutdown_vfsops();
1184     shutdown_exporter();
1185     shutdown_memcache();
1186 #if (!defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)) && !defined(AFS_OSF_ENV)
1187     shutdown_nfsclnt();
1188 #endif
1189     shutdown_afstest();
1190     /* The following hold the cm stats */
1191 /*
1192     memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));
1193     memset(&afs_stats_cmperf, 0, sizeof(struct afs_stats_CMPerf));
1194     memset(&afs_stats_cmfullperf, 0, sizeof(struct afs_stats_CMFullPerf));
1195 */
1196     afs_warn(" ALL allocated tables\n");
1197     afs_shuttingdown = 0;
1198 #endif
1199 }
1200
1201 void
1202 shutdown_afstest(void)
1203 {
1204     AFS_STATCNT(shutdown_afstest);
1205     afs_initState = afs_termState = afs_setTime = 0;
1206     AFS_Running = afs_CB_Running = 0;
1207     afs_CacheInit_Done = afs_Go_Done = 0;
1208     if (afs_cold_shutdown) {
1209         *afs_rootVolumeName = 0;
1210     }
1211 }
1212
1213
1214 /* In case there is a bunch of dynamically build bkg daemons to free */
1215 void
1216 afs_shutdown_BKG(void)
1217 {
1218     AFS_STATCNT(shutdown_BKG);
1219 }