test suite warning safety
[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 (!code)
784                     code =
785                         afs_NewCell(tbuffer1, tcell->hosts, cflags, lcnamep,
786                                     0, 0, 0);
787             }
788         }
789         afs_osi_Free(tcell, sizeof(struct afsop_cell));
790         osi_FreeSmallSpace(tbuffer);
791         osi_FreeSmallSpace(tbuffer1);
792     } else if (parm == AFSOP_ADDCELLALIAS) {
793         /*
794          * Call arguments:
795          * parm2 is the alias name
796          * parm3 is the real cell name
797          */
798         char *aliasName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
799         char *cellName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
800
801         code = afs_InitDynroot();
802         if (!code) {
803             AFS_COPYINSTR(AFSKPTR(parm2), aliasName, AFS_SMALLOCSIZ, &bufferSize,
804                           code);
805         }
806         if (!code)
807             AFS_COPYINSTR(AFSKPTR(parm3), cellName, AFS_SMALLOCSIZ,
808                           &bufferSize, code);
809         if (!code)
810             afs_NewCellAlias(aliasName, cellName);
811         osi_FreeSmallSpace(aliasName);
812         osi_FreeSmallSpace(cellName);
813     } else if (parm == AFSOP_SET_THISCELL) {
814         /*
815          * Call arguments:
816          * parm2 is the primary cell name
817          */
818         char *cell = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
819
820         afs_CellInit();
821         AFS_COPYINSTR(AFSKPTR(parm2), cell, AFS_SMALLOCSIZ, &bufferSize, code);
822         if (!code)
823             afs_SetPrimaryCell(cell);
824         osi_FreeSmallSpace(cell);
825         if (!code) {
826             code = afs_InitDynroot();
827         }
828     } else if (parm == AFSOP_CACHEINIT) {
829         struct afs_cacheParams cparms;
830
831         if (afs_CacheInit_Done)
832             goto out;
833
834         AFS_COPYIN(AFSKPTR(parm2), (caddr_t) & cparms, sizeof(cparms), code);
835         if (code) {
836 #if defined(KERNEL_HAVE_UERROR)
837             setuerror(code);
838             code = -1;
839 #endif
840             goto out;
841         }
842         afs_CacheInit_Done = 1;
843         code = afs_icl_InitLogs();
844         afs_setTime = cparms.setTimeFlag;
845
846         code =
847             afs_CacheInit(cparms.cacheScaches, cparms.cacheFiles,
848                           cparms.cacheBlocks, cparms.cacheDcaches,
849                           cparms.cacheVolumes, cparms.chunkSize,
850                           cparms.memCacheFlag, cparms.inodes, cparms.users, 
851                           cparms.dynamic_vcaches);
852
853     } else if (parm == AFSOP_CACHEINODE) {
854         ino_t ainode = parm2;
855         /* wait for basic init */
856         while (afs_initState < AFSOP_START_BKG)
857             afs_osi_Sleep(&afs_initState);
858
859 #ifdef AFS_DARWIN80_ENV
860         get_vfs_context();
861 #endif
862         /* do it by inode */
863 #ifdef AFS_SGI62_ENV
864         ainode = (ainode << 32) | (parm3 & 0xffffffff);
865 #endif
866         code = afs_InitCacheFile(NULL, ainode);
867 #ifdef AFS_DARWIN80_ENV
868         put_vfs_context();
869 #endif
870     } else if (parm == AFSOP_CACHEDIRS) {
871         afs_numfilesperdir = parm2;
872         afs_osi_Wakeup(&afs_initState);
873     } else if (parm == AFSOP_CACHEFILES) {
874         afs_numcachefiles = parm2;
875         afs_osi_Wakeup(&afs_initState);
876     } else if (parm == AFSOP_ROOTVOLUME) {
877         /* wait for basic init */
878         while (afs_initState < AFSOP_START_BKG)
879             afs_osi_Sleep(&afs_initState);
880
881         if (parm2) {
882             AFS_COPYINSTR(AFSKPTR(parm2), afs_rootVolumeName,
883                           sizeof(afs_rootVolumeName), &bufferSize, code);
884             afs_rootVolumeName[sizeof(afs_rootVolumeName) - 1] = 0;
885         } else
886             code = 0;
887     } else if (parm == AFSOP_CACHEFILE || parm == AFSOP_CACHEINFO
888                || parm == AFSOP_VOLUMEINFO || parm == AFSOP_CELLINFO) {
889         char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
890
891         code = 0;
892         AFS_COPYINSTR(AFSKPTR(parm2), tbuffer, AFS_SMALLOCSIZ, &bufferSize,
893                       code);
894         if (code) {
895             osi_FreeSmallSpace(tbuffer);
896             goto out;
897         }
898         if (!code) {
899             tbuffer[AFS_SMALLOCSIZ - 1] = '\0'; /* null-terminate the name */
900             /* We have the cache dir copied in.  Call the cache init routine */
901 #ifdef AFS_DARWIN80_ENV
902             get_vfs_context();
903 #endif
904             if (parm == AFSOP_CACHEFILE) {
905                 code = afs_InitCacheFile(tbuffer, 0);
906             } else if (parm == AFSOP_CACHEINFO) {
907                 code = afs_InitCacheInfo(tbuffer);
908             } else if (parm == AFSOP_VOLUMEINFO) {
909                 code = afs_InitVolumeInfo(tbuffer);
910             } else if (parm == AFSOP_CELLINFO) {
911                 code = afs_InitCellInfo(tbuffer);
912             }
913 #ifdef AFS_DARWIN80_ENV
914             put_vfs_context();
915 #endif
916         }
917         osi_FreeSmallSpace(tbuffer);
918     } else if (parm == AFSOP_GO) {
919         /* the generic initialization calls come here.  One parameter: should we do the
920          * set-time operation on this workstation */
921         if (afs_Go_Done)
922             goto out;
923         afs_Go_Done = 1;
924         while (afs_initState < AFSOP_GO)
925             afs_osi_Sleep(&afs_initState);
926         afs_initState = 101;
927         afs_setTime = parm2;
928         if (afs_tpct1 + afs_tpct2 != 100) {
929             afs_tpct1 = 0;
930             afs_tpct2 = 0;
931             splitdcache = 0;
932         } else {        
933             splitdcache = 1;
934         }
935         afs_osi_Wakeup(&afs_initState);
936 #if     (!defined(AFS_NONFSTRANS)) || defined(AFS_AIX_IAUTH_ENV)
937         afs_nfsclient_init();
938 #endif
939         afs_uuid_create(&afs_cb_interface.uuid);
940         printf("found %d non-empty cache files (%d%%).\n",
941                afs_stats_cmperf.cacheFilesReused,
942                (100 * afs_stats_cmperf.cacheFilesReused) /
943                (afs_stats_cmperf.cacheNumEntries ? afs_stats_cmperf.
944                 cacheNumEntries : 1));
945     } else if (parm == AFSOP_ADVISEADDR) {
946         /* pass in the host address to the rx package */
947         int rxbind = 0;
948         int refresh = 0;
949
950         afs_int32 count = parm2;
951         afs_int32 *buffer =
952             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
953         afs_int32 *maskbuffer =
954             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
955         afs_int32 *mtubuffer =
956             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
957         int i;
958
959         /* This is a refresh */
960         if (count & 0x40000000) {
961             count &= ~0x40000000;
962             /* Can't bind after we start. Fix? */
963             count &= ~0x80000000;
964             refresh = 1;
965         }
966
967         /* Bind, but only if there's only one address configured */ 
968         if ( count & 0x80000000) {
969             count &= ~0x80000000;
970             if (count == 1)
971                 rxbind=1;
972         }
973
974         if (count > AFS_MAX_INTERFACE_ADDR) {
975             code = ENOMEM;
976             count = AFS_MAX_INTERFACE_ADDR;
977         }
978
979         AFS_COPYIN(AFSKPTR(parm3), (caddr_t)buffer, count * sizeof(afs_int32),
980                    code);
981         if (parm4 && !code)
982             AFS_COPYIN(AFSKPTR(parm4), (caddr_t)maskbuffer,
983                        count * sizeof(afs_int32), code);
984         if (parm5 && !code)
985             AFS_COPYIN(AFSKPTR(parm5), (caddr_t)mtubuffer,
986                        count * sizeof(afs_int32), code);
987
988         if (!code) {
989             afs_cb_interface.numberOfInterfaces = count;
990             for (i = 0; i < count; i++) {
991                 afs_cb_interface.addr_in[i] = buffer[i];
992 #ifdef AFS_USERSPACE_IP_ADDR
993                 /* AFS_USERSPACE_IP_ADDR means we have no way of finding the
994                  * machines IP addresses when in the kernel (the in_ifaddr
995                  * struct is not available), so we pass the info in at
996                  * startup. We also pass in the subnetmask and mtu size. The
997                  * subnetmask is used when setting the rank:
998                  * afsi_SetServerIPRank(); and the mtu size is used when
999                  * finding the best mtu size. rxi_FindIfnet() is replaced
1000                  * with rxi_Findcbi().
1001                  */
1002                 afs_cb_interface.subnetmask[i] =
1003                     (parm4 ? maskbuffer[i] : 0xffffffff);
1004                 afs_cb_interface.mtu[i] = (parm5 ? mtubuffer[i] : htonl(1500));
1005 #endif
1006             }
1007             rxi_setaddr(buffer[0]);
1008             if (!refresh) {
1009                 if (rxbind)
1010                     rx_bindhost = buffer[0];
1011                 else
1012                     rx_bindhost = htonl(INADDR_ANY);
1013             }
1014         } else {
1015             refresh = 0;
1016         }
1017
1018         afs_osi_Free(buffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
1019         afs_osi_Free(maskbuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
1020         afs_osi_Free(mtubuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
1021
1022         if (refresh) {
1023             afs_CheckServers(1, NULL);     /* check down servers */
1024             afs_CheckServers(0, NULL);     /* check down servers */
1025         }
1026     }
1027 #ifdef  AFS_SGI53_ENV
1028     else if (parm == AFSOP_NFSSTATICADDR) {
1029         extern int (*nfs_rfsdisptab_v2) ();
1030         nfs_rfsdisptab_v2 = (int (*)())parm2;
1031     } else if (parm == AFSOP_NFSSTATICADDR2) {
1032         extern int (*nfs_rfsdisptab_v2) ();
1033 #ifdef _K64U64
1034         nfs_rfsdisptab_v2 = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
1035 #else /* _K64U64 */
1036         nfs_rfsdisptab_v2 = (int (*)())(parm3 & 0xffffffff);
1037 #endif /* _K64U64 */
1038     }
1039 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
1040     else if (parm == AFSOP_SBLOCKSTATICADDR2) {
1041         extern int (*afs_sblockp) ();
1042         extern void (*afs_sbunlockp) ();
1043 #ifdef _K64U64
1044         afs_sblockp = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
1045         afs_sbunlockp = (void (*)())((parm4 << 32) | (parm5 & 0xffffffff));
1046 #else
1047         afs_sblockp = (int (*)())(parm3 & 0xffffffff);
1048         afs_sbunlockp = (void (*)())(parm5 & 0xffffffff);
1049 #endif /* _K64U64 */
1050     }
1051 #endif /* AFS_SGI62_ENV && !AFS_SGI65_ENV */
1052 #endif /* AFS_SGI53_ENV */
1053     else if (parm == AFSOP_SHUTDOWN) {
1054         afs_cold_shutdown = 0;
1055         if (parm2 == 1)
1056             afs_cold_shutdown = 1;
1057         if (afs_globalVFS != 0) {
1058             afs_warn("AFS isn't unmounted yet! Call aborted\n");
1059             code = EACCES;
1060         } else
1061             afs_shutdown();
1062     } else if (parm == AFSOP_AFS_VFSMOUNT) {
1063 #ifdef  AFS_HPUX_ENV
1064         vfsmount(parm2, parm3, parm4, parm5);
1065 #else /* defined(AFS_HPUX_ENV) */
1066 #if defined(KERNEL_HAVE_UERROR)
1067         setuerror(EINVAL);
1068 #else
1069         code = EINVAL;
1070 #endif
1071 #endif /* defined(AFS_HPUX_ENV) */
1072     } else if (parm == AFSOP_CLOSEWAIT) {
1073         afs_SynchronousCloses = 'S';
1074     } else if (parm == AFSOP_GETMTU) {
1075         afs_uint32 mtu = 0;
1076 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
1077 #ifdef AFS_USERSPACE_IP_ADDR
1078         afs_int32 i;
1079         i = rxi_Findcbi(parm2);
1080         mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
1081 #else /* AFS_USERSPACE_IP_ADDR */
1082         rx_ifnet_t tifnp;
1083
1084         tifnp = rxi_FindIfnet(parm2, NULL);     /*  make iterative */
1085         mtu = (tifnp ? rx_ifnet_mtu(tifnp) : htonl(1500));
1086 #endif /* else AFS_USERSPACE_IP_ADDR */
1087 #endif /* !AFS_SUN5_ENV */
1088         if (!code)
1089             AFS_COPYOUT((caddr_t) & mtu, AFSKPTR(parm3),
1090                         sizeof(afs_int32), code);
1091 #ifdef AFS_AIX32_ENV
1092 /* this is disabled for now because I can't figure out how to get access
1093  * to these kernel variables.  It's only for supporting user-mode rx
1094  * programs -- it makes a huge difference on the 220's in my testbed,
1095  * though I don't know why. The bosserver does this with /etc/no, so it's
1096  * being handled a different way for the servers right now.  */
1097 /*      {
1098         static adjusted = 0;
1099         extern u_long sb_max_dflt;
1100         if (!adjusted) {
1101           adjusted = 1;
1102           if (sb_max_dflt < 131072) sb_max_dflt = 131072; 
1103           if (sb_max < 131072) sb_max = 131072; 
1104         }
1105       } */
1106 #endif /* AFS_AIX32_ENV */
1107     } else if (parm == AFSOP_GETMASK) { /* parm2 == addr in net order */
1108         afs_uint32 mask = 0;
1109 #if     !defined(AFS_SUN5_ENV)
1110 #ifdef AFS_USERSPACE_IP_ADDR
1111         afs_int32 i;
1112         i = rxi_Findcbi(parm2);
1113         if (i != -1) {
1114             mask = afs_cb_interface.subnetmask[i];
1115         } else {
1116             code = -1;
1117         }
1118 #else /* AFS_USERSPACE_IP_ADDR */
1119         rx_ifnet_t tifnp;
1120
1121         tifnp = rxi_FindIfnet(parm2, &mask);    /* make iterative */
1122         if (!tifnp)
1123             code = -1;
1124 #endif /* else AFS_USERSPACE_IP_ADDR */
1125 #endif /* !AFS_SUN5_ENV */
1126         if (!code)
1127             AFS_COPYOUT((caddr_t) & mask, AFSKPTR(parm3),
1128                         sizeof(afs_int32), code);
1129     }
1130     else if (parm == AFSOP_AFSDB_HANDLER) {
1131         int sizeArg = (int)parm4;
1132         int kmsgLen = sizeArg & 0xffff;
1133         int cellLen = (sizeArg & 0xffff0000) >> 16;
1134         afs_int32 *kmsg = afs_osi_Alloc(kmsgLen);
1135         char *cellname = afs_osi_Alloc(cellLen);
1136
1137 #ifndef UKERNEL
1138         afs_osi_MaskUserLoop();
1139 #endif
1140         AFS_COPYIN(AFSKPTR(parm2), cellname, cellLen, code);
1141         AFS_COPYIN(AFSKPTR(parm3), kmsg, kmsgLen, code);
1142         if (!code) {
1143             code = afs_AFSDBHandler(cellname, cellLen, kmsg);
1144             if (*cellname == 1)
1145                 *cellname = 0;
1146             if (code == -2) {   /* Shutting down? */
1147                 *cellname = 1;
1148                 code = 0;
1149             }
1150         }
1151         if (!code)
1152             AFS_COPYOUT(cellname, AFSKPTR(parm2), cellLen, code);
1153         afs_osi_Free(kmsg, kmsgLen);
1154         afs_osi_Free(cellname, cellLen);
1155     }
1156     else if (parm == AFSOP_SET_DYNROOT) {
1157         code = afs_SetDynrootEnable(parm2);
1158     } else if (parm == AFSOP_SET_FAKESTAT) {
1159         afs_fakestat_enable = parm2;
1160         code = 0;
1161     } else if (parm == AFSOP_SET_BACKUPTREE) {
1162         afs_bkvolpref = parm2;
1163     } else if (parm == AFSOP_SET_RXPCK) {
1164         rx_extraPackets = parm2;
1165         afscall_set_rxpck_received = 1;
1166     } else if (parm == AFSOP_SET_RXMAXMTU) {
1167         rx_MyMaxSendSize = rx_maxReceiveSizeUser = rx_maxReceiveSize = parm2;
1168     } else {
1169         code = EINVAL;
1170     }
1171
1172   out:
1173     AFS_GUNLOCK();
1174 #ifdef AFS_LINUX20_ENV
1175     return -code;
1176 #else
1177     return code;
1178 #endif
1179 }
1180
1181 /*
1182  * Initstate in the range 0 < x < 100 are early initialization states.
1183  * Initstate of 100 means a AFSOP_START operation has been done.  After this,
1184  *  the cache may be initialized.
1185  * Initstate of 101 means a AFSOP_GO operation has been done.  This operation
1186  *  is done after all the cache initialization has been done.
1187  * Initstate of 200 means that the volume has been looked up once, possibly
1188  *  incorrectly.
1189  * Initstate of 300 means that the volume has been *successfully* looked up.
1190  */
1191 int
1192 afs_CheckInit(void)
1193 {
1194     register int code = 0;
1195
1196     AFS_STATCNT(afs_CheckInit);
1197     if (afs_initState <= 100)
1198         code = ENXIO;           /* never finished init phase */
1199     else if (afs_initState == 101) {    /* init done, wait for afs_daemon */
1200         while (afs_initState < 200)
1201             afs_osi_Sleep(&afs_initState);
1202     } else if (afs_initState == 200)
1203         code = ETIMEDOUT;       /* didn't find root volume */
1204     return code;
1205 }
1206
1207 int afs_shuttingdown = 0;
1208 void
1209 afs_shutdown(void)
1210 {
1211     extern short afs_brsDaemons;
1212     extern afs_int32 afs_CheckServerDaemonStarted;
1213     extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
1214     extern struct osi_file *afs_cacheInodep;
1215
1216     AFS_STATCNT(afs_shutdown);
1217     if (afs_initState == 0) {
1218         afs_warn("AFS not initialized - not shutting down\n");
1219       return;
1220     }
1221
1222     if (afs_shuttingdown)
1223         return;
1224     afs_shuttingdown = 1;
1225     if (afs_cold_shutdown)
1226         afs_warn("afs: COLD ");
1227     else
1228         afs_warn("afs: WARM ");
1229     afs_warn("shutting down of: CB... ");
1230
1231     afs_termState = AFSOP_STOP_RXCALLBACK;
1232     rx_WakeupServerProcs();
1233 #ifdef AFS_AIX51_ENV
1234     shutdown_rxkernel();
1235 #endif
1236     /* close rx server connections here? */
1237     while (afs_termState == AFSOP_STOP_RXCALLBACK)
1238         afs_osi_Sleep(&afs_termState);
1239
1240     afs_warn("afs... ");
1241     while (afs_termState == AFSOP_STOP_AFS) {
1242         afs_osi_CancelWait(&AFS_WaitHandler);
1243         afs_osi_Sleep(&afs_termState);
1244     }
1245     if (afs_CheckServerDaemonStarted) {
1246         while (afs_termState == AFSOP_STOP_CS) {
1247             afs_osi_CancelWait(&AFS_CSWaitHandler);
1248             afs_osi_Sleep(&afs_termState);
1249         }
1250     }
1251     afs_warn("BkG... ");
1252     /* Wake-up afs_brsDaemons so that we don't have to wait for a bkg job! */
1253     while (afs_termState == AFSOP_STOP_BKG) {
1254         afs_osi_Wakeup(&afs_brsDaemons);
1255         afs_osi_Sleep(&afs_termState);
1256     }
1257     afs_warn("CTrunc... ");
1258     /* Cancel cache truncate daemon. */
1259     while (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
1260         afs_osi_Wakeup((char *)&afs_CacheTruncateDaemon);
1261         afs_osi_Sleep(&afs_termState);
1262     }
1263     afs_warn("AFSDB... ");
1264     afs_StopAFSDB();
1265     while (afs_termState == AFSOP_STOP_AFSDB)
1266         afs_osi_Sleep(&afs_termState);
1267 #if     defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
1268     afs_warn("RxEvent... ");
1269     /* cancel rx event daemon */
1270     while (afs_termState == AFSOP_STOP_RXEVENT)
1271         afs_osi_Sleep(&afs_termState);
1272 #if defined(RXK_LISTENER_ENV)
1273 #ifndef UKERNEL
1274     afs_warn("UnmaskRxkSignals... ");
1275     afs_osi_UnmaskRxkSignals();
1276 #endif
1277     /* cancel rx listener */
1278     afs_warn("RxListener... ");
1279     osi_StopListener();         /* This closes rx_socket. */
1280     while (afs_termState == AFSOP_STOP_RXK_LISTENER) {
1281         afs_warn("Sleep... ");
1282         afs_osi_Sleep(&afs_termState);
1283     }
1284 #endif
1285 #endif
1286
1287 #ifdef AFS_SUN510_ENV
1288     afs_warn("NetIfPoller... ");
1289     osi_StopNetIfPoller();
1290 #endif
1291
1292     afs_termState = AFSOP_STOP_COMPLETE;
1293
1294 #ifdef AFS_AIX51_ENV
1295     shutdown_daemons();
1296 #endif
1297     shutdown_CB();
1298     shutdown_bufferpackage();
1299     shutdown_cache();
1300     shutdown_osi();
1301     /*
1302      * Close file only after daemons which can write to it are stopped.
1303      * Need to close before the osinet shutdown to avoid failing check
1304      * for dangling memory allocations.
1305      */
1306     if (afs_cacheInodep) {      /* memcache won't set this */
1307         osi_UFSClose(afs_cacheInodep);  /* Since we always leave it open */
1308         afs_cacheInodep = 0;
1309     }
1310     /*
1311      * Shutdown the ICL logs - needed to free allocated memory space and avoid
1312      * warnings from shutdown_osinet
1313      */
1314     shutdown_icl();
1315     shutdown_osinet();
1316     shutdown_osifile();
1317     shutdown_vnodeops();
1318     shutdown_memcache();
1319     shutdown_xscache();
1320 #if (!defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV))
1321     shutdown_exporter();
1322     shutdown_nfsclnt();
1323 #endif
1324     shutdown_afstest();
1325     shutdown_AFS();
1326     /* The following hold the cm stats */
1327     memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));
1328     memset(&afs_stats_cmperf, 0, sizeof(struct afs_stats_CMPerf));
1329     memset(&afs_stats_cmfullperf, 0, sizeof(struct afs_stats_CMFullPerf));
1330     afs_warn(" ALL allocated tables... ");
1331
1332     afs_shuttingdown = 0;
1333     afs_warn("done\n");
1334
1335     return;                     /* Just kill daemons for now */
1336 }
1337
1338 void
1339 shutdown_afstest(void)
1340 {
1341     AFS_STATCNT(shutdown_afstest);
1342     afs_initState = afs_termState = afs_setTime = 0;
1343     AFS_Running = afs_CB_Running = 0;
1344     afs_CacheInit_Done = afs_Go_Done = 0;
1345     if (afs_cold_shutdown) {
1346         *afs_rootVolumeName = 0;
1347     }
1348 }