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