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