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