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