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