macos: kernel socket upcall
[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 #ifndef RXK_LISTENER_ENV
148         afs_initState = AFSOP_START_AFS;
149         afs_osi_Wakeup(&afs_initState);
150 #else
151         while (afs_RX_Running != 2)
152             afs_osi_Sleep(&afs_RX_Running);
153 #endif
154         afs_RXCallBackServer();
155         AFS_GUNLOCK();
156         thread_terminate(current_thread());
157         break;
158     case AFSOP_START_AFS:
159         AFS_GLOCK();
160         wakeup(arg);
161         AFS_Running = 1;
162         while (afs_initState < AFSOP_START_AFS)
163             afs_osi_Sleep(&afs_initState);
164         afs_initState = AFSOP_START_BKG;
165         afs_osi_Wakeup(&afs_initState);
166         afs_Daemon();
167         AFS_GUNLOCK();
168         thread_terminate(current_thread());
169         break;
170     case AFSOP_START_BKG:
171         afs_warn("Install matching afsd! Old background daemons not supported.\n");
172         thread_terminate(current_thread());
173         break;
174     case AFSOP_START_TRUNCDAEMON:
175         AFS_GLOCK();
176         wakeup(arg);
177         while (afs_initState < AFSOP_GO)
178             afs_osi_Sleep(&afs_initState);
179         afs_CacheTruncateDaemon();
180         AFS_GUNLOCK();
181         thread_terminate(current_thread());
182         break;
183     case AFSOP_START_CS:
184         AFS_GLOCK();
185         wakeup(arg);
186         afs_CheckServerDaemon();
187         AFS_GUNLOCK();
188         thread_terminate(current_thread());
189         break;
190     case AFSOP_RXEVENT_DAEMON:
191         AFS_GLOCK();
192         wakeup(arg);
193         while (afs_initState < AFSOP_START_BKG)
194             afs_osi_Sleep(&afs_initState);
195         afs_rxevent_daemon();
196         AFS_GUNLOCK();
197         thread_terminate(current_thread());
198         break;
199 #ifdef RXK_LISTENER_ENV
200     case AFSOP_RXLISTENER_DAEMON:
201         AFS_GLOCK();
202         wakeup(arg);
203         afs_initState = AFSOP_START_AFS;
204         afs_osi_Wakeup(&afs_initState);
205         afs_RX_Running = 2;
206         afs_osi_Wakeup(&afs_RX_Running);
207         afs_osi_RxkRegister();
208         rxk_Listener();
209         AFS_GUNLOCK();
210         thread_terminate(current_thread());
211         break;
212 #endif
213     default:
214         afs_warn("Unknown op %ld in StartDaemon()\n", (long)parm);
215         break;
216     }
217 }
218
219 void
220 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
221              long parm6)
222 {
223     int code;
224     struct afsd_thread_info info;
225     thread_t thread;
226     if (parm == AFSOP_START_RXCALLBACK) {
227         if (afs_CB_Running)
228             return;
229 #ifdef RXK_LISTENER_ENV
230     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
231         if (afs_RX_Running)
232             return;
233         afs_RX_Running = 1;
234 #endif
235         code = afs_InitSetup(parm2);
236         if (parm3) {
237             rx_enablePeerRPCStats();
238         }
239         if (parm4) {
240             rx_enableProcessRPCStats();
241         }
242         if (code)
243             return;
244     } else if (parm == AFSOP_START_AFS) {
245         if (AFS_Running)
246             return;
247     }                           /* other functions don't need setup in the parent */
248     info.parm = parm;
249     kernel_thread_start((thread_continue_t)afsd_thread, &info, &thread);
250     AFS_GUNLOCK();
251     /* we need to wait cause we passed stack pointers around.... */
252     msleep(&info, NULL, PVFS, "afs_DaemonOp", NULL);
253     AFS_GLOCK();
254     thread_deallocate(thread);
255 }
256 #endif
257
258
259 #if defined(AFS_LINUX24_ENV) && defined(HAVE_LINUX_COMPLETION_H)
260 struct afsd_thread_info {
261 #if defined(AFS_LINUX26_ENV) && !defined(INIT_WORK_HAS_DATA)
262     struct work_struct tq;
263 #endif
264     unsigned long parm;
265     struct completion *complete;
266 };
267
268 static int
269 afsd_thread(void *rock)
270 {
271     struct afsd_thread_info *arg = rock;
272     unsigned long parm = arg->parm;
273 #ifdef SYS_SETPRIORITY_EXPORTED
274     int (*sys_setpriority) (int, int, int) = sys_call_table[__NR_setpriority];
275 #endif
276 #if defined(AFS_LINUX26_ENV)
277     daemonize("afsd");
278 #else
279     daemonize();
280 #endif
281                                 /* doesn't do much, since we were forked from keventd, but
282                                  * does call mm_release, which wakes up our parent (since it
283                                  * used CLONE_VFORK) */
284 #if !defined(AFS_LINUX26_ENV)
285     reparent_to_init();
286 #endif
287     afs_osi_MaskSignals();
288     switch (parm) {
289     case AFSOP_START_RXCALLBACK:
290         sprintf(current->comm, "afs_cbstart");
291         AFS_GLOCK();
292         complete(arg->complete);
293         afs_CB_Running = 1;
294 #if !defined(RXK_LISTENER_ENV)
295         afs_initState = AFSOP_START_AFS;
296         afs_osi_Wakeup(&afs_initState);
297 #else
298         while (afs_RX_Running != 2)
299             afs_osi_Sleep(&afs_RX_Running);
300 #endif
301         sprintf(current->comm, "afs_callback");
302         afs_RXCallBackServer();
303         AFS_GUNLOCK();
304         complete_and_exit(0, 0);
305         break;
306     case AFSOP_START_AFS:
307         sprintf(current->comm, "afs_afsstart");
308         AFS_GLOCK();
309         complete(arg->complete);
310         AFS_Running = 1;
311         while (afs_initState < AFSOP_START_AFS)
312             afs_osi_Sleep(&afs_initState);
313         afs_initState = AFSOP_START_BKG;
314         afs_osi_Wakeup(&afs_initState);
315         sprintf(current->comm, "afsd");
316         afs_Daemon();
317         AFS_GUNLOCK();
318         complete_and_exit(0, 0);
319         break;
320     case AFSOP_START_BKG:
321         sprintf(current->comm, "afs_bkgstart");
322         AFS_GLOCK();
323         complete(arg->complete);
324         while (afs_initState < AFSOP_START_BKG)
325             afs_osi_Sleep(&afs_initState);
326         if (afs_initState < AFSOP_GO) {
327             afs_initState = AFSOP_GO;
328             afs_osi_Wakeup(&afs_initState);
329         }
330         sprintf(current->comm, "afs_background");
331         afs_BackgroundDaemon();
332         AFS_GUNLOCK();
333         complete_and_exit(0, 0);
334         break;
335     case AFSOP_START_TRUNCDAEMON:
336         sprintf(current->comm, "afs_trimstart");
337         AFS_GLOCK();
338         complete(arg->complete);
339         while (afs_initState < AFSOP_GO)
340             afs_osi_Sleep(&afs_initState);
341         sprintf(current->comm, "afs_cachetrim");
342         afs_CacheTruncateDaemon();
343         AFS_GUNLOCK();
344         complete_and_exit(0, 0);
345         break;
346     case AFSOP_START_CS:
347         sprintf(current->comm, "afs_checkserver");
348         AFS_GLOCK();
349         complete(arg->complete);
350         afs_CheckServerDaemon();
351         AFS_GUNLOCK();
352         complete_and_exit(0, 0);
353         break;
354     case AFSOP_RXEVENT_DAEMON:
355         sprintf(current->comm, "afs_evtstart");
356 #ifdef SYS_SETPRIORITY_EXPORTED
357         sys_setpriority(PRIO_PROCESS, 0, -10);
358 #else
359 #ifdef CURRENT_INCLUDES_NICE
360         current->nice = -10;
361 #endif
362 #endif
363         AFS_GLOCK();
364         complete(arg->complete);
365         while (afs_initState < AFSOP_START_BKG)
366             afs_osi_Sleep(&afs_initState);
367         sprintf(current->comm, "afs_rxevent");
368         afs_rxevent_daemon();
369         AFS_GUNLOCK();
370         complete_and_exit(0, 0);
371         break;
372 #ifdef RXK_LISTENER_ENV
373     case AFSOP_RXLISTENER_DAEMON:
374         sprintf(current->comm, "afs_lsnstart");
375 #ifdef SYS_SETPRIORITY_EXPORTED
376         sys_setpriority(PRIO_PROCESS, 0, -10);
377 #else
378 #ifdef CURRENT_INCLUDES_NICE
379         current->nice = -10;
380 #endif
381 #endif
382         AFS_GLOCK();
383         complete(arg->complete);
384         afs_initState = AFSOP_START_AFS;
385         afs_osi_Wakeup(&afs_initState);
386         afs_RX_Running = 2;
387         afs_osi_Wakeup(&afs_RX_Running);
388         afs_osi_RxkRegister();
389         sprintf(current->comm, "afs_rxlistener");
390         rxk_Listener();
391         AFS_GUNLOCK();
392         complete_and_exit(0, 0);
393         break;
394 #endif
395     default:
396         afs_warn("Unknown op %ld in StartDaemon()\n", (long)parm);
397         break;
398     }
399     return 0;
400 }
401
402 void
403 #if defined(AFS_LINUX26_ENV) && !defined(INIT_WORK_HAS_DATA)
404 afsd_launcher(struct work_struct *work)
405 #else
406 afsd_launcher(void *rock)
407 #endif
408 {
409 #if defined(AFS_LINUX26_ENV) && !defined(INIT_WORK_HAS_DATA)
410     struct afsd_thread_info *rock = container_of(work, struct afsd_thread_info, tq);
411 #endif
412
413     if (!kernel_thread(afsd_thread, (void *)rock, CLONE_VFORK | SIGCHLD))
414         afs_warn("kernel_thread failed. afs startup will not complete\n");
415 }
416
417 void
418 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
419              long parm6)
420 {
421     int code;
422     DECLARE_COMPLETION(c);
423 #if defined(AFS_LINUX26_ENV)
424 #if defined(INIT_WORK_HAS_DATA)
425     struct work_struct tq;
426 #endif
427 #else
428     struct tq_struct tq;
429 #endif
430     struct afsd_thread_info info;
431     if (parm == AFSOP_START_RXCALLBACK) {
432         if (afs_CB_Running)
433             return;
434 #ifdef RXK_LISTENER_ENV
435     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
436         if (afs_RX_Running)
437             return;
438         afs_RX_Running = 1;
439 #endif
440         code = afs_InitSetup(parm2);
441         if (parm3) {
442             rx_enablePeerRPCStats();
443         }
444         if (parm4) {
445             rx_enableProcessRPCStats();
446         }
447         if (code)
448             return;
449     } else if (parm == AFSOP_START_AFS) {
450         if (AFS_Running)
451             return;
452     }                           /* other functions don't need setup in the parent */
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 #if ((defined(AFS_LINUX24_ENV) && defined(HAVE_LINUX_COMPLETION_H)) || defined(AFS_DARWIN80_ENV)) && !defined(UKERNEL)
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_LINUX24_ENV && !UKERNEL) */
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_LINUX24_ENV && !UKERNEL */
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 }