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