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