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