amd64-update-20040202
[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 RCSID
14     ("$Header$");
15
16 #include "afs/sysincludes.h"    /* Standard vendor system headers */
17 #include "afsincludes.h"        /* Afs-based standard headers */
18 #include "afs/afs_stats.h"
19 #include "rx/rx_globals.h"
20 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
21 #include "net/if.h"
22 #ifdef AFS_SGI62_ENV
23 #include "h/hashing.h"
24 #endif
25 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
26 #include "netinet/in_var.h"
27 #endif
28 #endif /* !defined(UKERNEL) */
29 #ifdef AFS_LINUX22_ENV
30 #include "h/smp_lock.h"
31 #endif
32
33
34 #if     defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV)
35 #define AFS_MINBUFFERS  100
36 #else
37 #define AFS_MINBUFFERS  50
38 #endif
39
40 struct afsop_cell {
41     afs_int32 hosts[MAXCELLHOSTS];
42     char cellName[100];
43 };
44
45 char afs_zeros[AFS_ZEROS];
46 char afs_rootVolumeName[64] = "";
47 struct afs_icl_set *afs_iclSetp = (struct afs_icl_set *)0;
48 struct afs_icl_set *afs_iclLongTermSetp = (struct afs_icl_set *)0;
49
50 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
51 kmutex_t afs_global_lock;
52 kmutex_t afs_rxglobal_lock;
53 #endif
54
55 #if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
56 long afs_global_owner;
57 #endif
58
59 #if defined(AFS_OSF_ENV)
60 simple_lock_data_t afs_global_lock;
61 #endif
62
63 #if defined(AFS_DARWIN_ENV)
64 struct lock__bsd__ afs_global_lock;
65 #endif
66
67 #if defined(AFS_XBSD_ENV)
68 struct lock afs_global_lock;
69 #ifdef AFS_FBSD50_ENV
70 struct thread *afs_global_owner;
71 #else
72 struct proc *afs_global_owner;
73 #endif
74 #endif
75
76 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
77 thread_t afs_global_owner;
78 #endif /* AFS_OSF_ENV */
79
80 #if defined(AFS_AIX41_ENV)
81 simple_lock_data afs_global_lock;
82 #endif
83
84 afs_int32 afs_initState = 0;
85 afs_int32 afs_termState = 0;
86 afs_int32 afs_setTime = 0;
87 int afs_cold_shutdown = 0;
88 char afs_SynchronousCloses = '\0';
89 static int afs_CB_Running = 0;
90 static int AFS_Running = 0;
91 static int afs_CacheInit_Done = 0;
92 static int afs_Go_Done = 0;
93 extern struct interfaceAddr afs_cb_interface;
94 static int afs_RX_Running = 0;
95 static int afs_InitSetup_done = 0;
96
97 afs_int32 afs_rx_deadtime = AFS_RXDEADTIME;
98 afs_int32 afs_rx_harddead = AFS_HARDDEADTIME;
99
100 static int
101   Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval);
102
103 #if defined(AFS_HPUX_ENV)
104 extern int afs_vfs_mount();
105 #endif /* defined(AFS_HPUX_ENV) */
106
107 /* This is code which needs to be called once when the first daemon enters
108  * the client. A non-zero return means an error and AFS should not start.
109  */
110 static int
111 afs_InitSetup(int preallocs)
112 {
113     extern void afs_InitStats();
114     int code;
115
116     if (afs_InitSetup_done)
117         return EAGAIN;
118
119 #ifndef AFS_NOSTATS
120     /*
121      * Set up all the AFS statistics variables.  This should be done
122      * exactly once, and it should be done here, the first resource-setting
123      * routine to be called by the CM/RX.
124      */
125     afs_InitStats();
126 #endif /* AFS_NOSTATS */
127
128     memset(afs_zeros, 0, AFS_ZEROS);
129
130     /* start RX */
131     rx_extraPackets = AFS_NRXPACKETS;   /* smaller # of packets */
132     code = rx_Init(htons(7001));
133     if (code) {
134         printf("AFS: RX failed to initialize.\n");
135         return code;
136     }
137     rx_SetRxDeadTime(afs_rx_deadtime);
138     /* resource init creates the services */
139     afs_ResourceInit(preallocs);
140
141     afs_InitSetup_done = 1;
142     afs_osi_Wakeup(&afs_InitSetup_done);
143
144     return code;
145 }
146
147 #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)
148 struct afsd_thread_info {
149     unsigned long parm;
150     struct completion *complete;
151 };
152
153 static int
154 afsd_thread(void *rock)
155 {
156     struct afsd_thread_info *arg = rock;
157     unsigned long parm = arg->parm;
158 #ifdef SYS_SETPRIORITY_EXPORTED
159     int (*sys_setpriority) (int, int, int) = sys_call_table[__NR_setpriority];
160 #endif
161     daemonize();                /* doesn't do much, since we were forked from keventd, but
162                                  * does call mm_release, which wakes up our parent (since it
163                                  * used CLONE_VFORK) */
164     reparent_to_init();
165     afs_osi_MaskSignals();
166     switch (parm) {
167     case AFSOP_START_RXCALLBACK:
168         sprintf(current->comm, "afs_cbstart");
169         AFS_GLOCK();
170         complete(arg->complete);
171         afs_CB_Running = 1;
172         while (afs_RX_Running != 2)
173             afs_osi_Sleep(&afs_RX_Running);
174         sprintf(current->comm, "afs_callback");
175         afs_RXCallBackServer();
176         AFS_GUNLOCK();
177         complete_and_exit(0, 0);
178         break;
179     case AFSOP_START_AFS:
180         sprintf(current->comm, "afs_afsstart");
181         AFS_GLOCK();
182         complete(arg->complete);
183         AFS_Running = 1;
184         while (afs_initState < AFSOP_START_AFS)
185             afs_osi_Sleep(&afs_initState);
186         afs_initState = AFSOP_START_BKG;
187         afs_osi_Wakeup(&afs_initState);
188         sprintf(current->comm, "afsd");
189         afs_Daemon();
190         AFS_GUNLOCK();
191         complete_and_exit(0, 0);
192         break;
193     case AFSOP_START_BKG:
194         sprintf(current->comm, "afs_bkgstart");
195         AFS_GLOCK();
196         complete(arg->complete);
197         while (afs_initState < AFSOP_START_BKG)
198             afs_osi_Sleep(&afs_initState);
199         if (afs_initState < AFSOP_GO) {
200             afs_initState = AFSOP_GO;
201             afs_osi_Wakeup(&afs_initState);
202         }
203         sprintf(current->comm, "afs_background");
204         afs_BackgroundDaemon();
205         AFS_GUNLOCK();
206         complete_and_exit(0, 0);
207         break;
208     case AFSOP_START_TRUNCDAEMON:
209         sprintf(current->comm, "afs_trimstart");
210         AFS_GLOCK();
211         complete(arg->complete);
212         while (afs_initState < AFSOP_GO)
213             afs_osi_Sleep(&afs_initState);
214         sprintf(current->comm, "afs_cachetrim");
215         afs_CacheTruncateDaemon();
216         AFS_GUNLOCK();
217         complete_and_exit(0, 0);
218         break;
219     case AFSOP_START_CS:
220         sprintf(current->comm, "afs_checkserver");
221         AFS_GLOCK();
222         complete(arg->complete);
223         afs_CheckServerDaemon();
224         AFS_GUNLOCK();
225         complete_and_exit(0, 0);
226         break;
227     case AFSOP_RXEVENT_DAEMON:
228         sprintf(current->comm, "afs_evtstart");
229 #ifdef SYS_SETPRIORITY_EXPORTED
230         sys_setpriority(PRIO_PROCESS, 0, -10);
231 #else
232 #ifdef CURRENT_INCLUDES_NICE
233         current->nice = -10;
234 #endif
235 #endif
236         AFS_GLOCK();
237         complete(arg->complete);
238         while (afs_initState < AFSOP_START_BKG)
239             afs_osi_Sleep(&afs_initState);
240         sprintf(current->comm, "afs_rxevent");
241         afs_rxevent_daemon();
242         AFS_GUNLOCK();
243         complete_and_exit(0, 0);
244         break;
245     case AFSOP_RXLISTENER_DAEMON:
246         sprintf(current->comm, "afs_lsnstart");
247 #ifdef SYS_SETPRIORITY_EXPORTED
248         sys_setpriority(PRIO_PROCESS, 0, -10);
249 #else
250 #ifdef CURRENT_INCLUDES_NICE
251         current->nice = -10;
252 #endif
253 #endif
254         AFS_GLOCK();
255         complete(arg->complete);
256         afs_initState = AFSOP_START_AFS;
257         afs_osi_Wakeup(&afs_initState);
258         afs_RX_Running = 2;
259         afs_osi_Wakeup(&afs_RX_Running);
260         afs_osi_RxkRegister();
261         sprintf(current->comm, "afs_rxlistener");
262         rxk_Listener();
263         AFS_GUNLOCK();
264         complete_and_exit(0, 0);
265         break;
266     default:
267         printf("Unknown op %d in StartDaemon()\n");
268         break;
269     }
270     return 0;
271 }
272
273 void
274 afsd_launcher(void *rock)
275 {
276     if (!kernel_thread(afsd_thread, rock, CLONE_VFORK | SIGCHLD))
277         printf("kernel_thread failed. afs startup will not complete\n");
278 }
279
280 void
281 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
282              long parm6)
283 {
284     int code;
285     DECLARE_COMPLETION(c);
286     struct tq_struct tq;
287     struct afsd_thread_info info;
288     if (parm == AFSOP_START_RXCALLBACK) {
289         if (afs_CB_Running)
290             return;
291     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
292         if (afs_RX_Running)
293             return;
294         afs_RX_Running = 1;
295         code = afs_InitSetup(parm2);
296         if (parm3) {
297             rx_enablePeerRPCStats();
298         }
299         if (parm4) {
300             rx_enableProcessRPCStats();
301         }
302         if (code)
303             return;
304     } else if (parm == AFSOP_START_AFS) {
305         if (AFS_Running)
306             return;
307     }                           /* other functions don't need setup in the parent */
308     info.complete = &c;
309     info.parm = parm;
310     tq.sync = 0;
311     INIT_LIST_HEAD(&tq.list);
312     tq.routine = afsd_launcher;
313     tq.data = &info;
314     schedule_task(&tq);
315     AFS_GUNLOCK();
316     /* we need to wait cause we passed stack pointers around.... */
317     wait_for_completion(&c);
318     AFS_GLOCK();
319 }
320 #endif
321
322 /* leaving as is, probably will barf if we add prototypes here since it's likely being called
323 with partial list */
324 int
325 afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
326      long parm, parm2, parm3, parm4, parm5, parm6;
327 {
328     afs_int32 code = 0;
329 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
330     size_t bufferSize;
331 #else /* AFS_SGI61_ENV */
332     u_int bufferSize;
333 #endif /* AFS_SGI61_ENV */
334
335     AFS_STATCNT(afs_syscall_call);
336 #ifdef  AFS_SUN5_ENV
337     if (!afs_suser(CRED()) && (parm != AFSOP_GETMTU)
338         && (parm != AFSOP_GETMASK)) {
339         /* only root can run this code */
340         return (EACCES);
341 #else
342     if (!afs_suser() && (parm != AFSOP_GETMTU)
343         && (parm != AFSOP_GETMASK)) {
344         /* only root can run this code */
345 #if defined(KERNEL_HAVE_UERROR)
346         setuerror(EACCES);
347         return (EACCES);
348 #else
349 #if defined(AFS_OSF_ENV)
350         return EACCES;
351 #else /* AFS_OSF_ENV */
352         return EPERM;
353 #endif /* AFS_OSF_ENV */
354 #endif
355 #endif
356     }
357     AFS_GLOCK();
358 #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS) && !defined(UKERNEL)
359     if (parm < AFSOP_ADDCELL || parm == AFSOP_RXEVENT_DAEMON
360         || parm == AFSOP_RXLISTENER_DAEMON) {
361         afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
362     }
363 #else /* !(AFS_LINUX24_ENV && !UKERNEL) */
364     if (parm == AFSOP_START_RXCALLBACK) {
365         if (afs_CB_Running)
366             goto out;
367         afs_CB_Running = 1;
368 #ifndef RXK_LISTENER_ENV
369         code = afs_InitSetup(parm2);
370         if (!code)
371 #endif /* !RXK_LISTENER_ENV */
372         {
373 #ifdef RXK_LISTENER_ENV
374             while (afs_RX_Running != 2)
375                 afs_osi_Sleep(&afs_RX_Running);
376 #else /* !RXK_LISTENER_ENV */
377             afs_initState = AFSOP_START_AFS;
378             afs_osi_Wakeup(&afs_initState);
379 #endif /* RXK_LISTENER_ENV */
380             afs_osi_Invisible();
381             afs_RXCallBackServer();
382         }
383 #ifdef AFS_SGI_ENV
384         AFS_GUNLOCK();
385         exit(CLD_EXITED, code);
386 #endif /* AFS_SGI_ENV */
387     }
388 #ifdef RXK_LISTENER_ENV
389     else if (parm == AFSOP_RXLISTENER_DAEMON) {
390         if (afs_RX_Running)
391             goto out;
392         afs_RX_Running = 1;
393         code = afs_InitSetup(parm2);
394         if (parm3) {
395             rx_enablePeerRPCStats();
396         }
397         if (parm4) {
398             rx_enableProcessRPCStats();
399         }
400         if (!code) {
401             afs_initState = AFSOP_START_AFS;
402             afs_osi_Wakeup(&afs_initState);
403             afs_osi_Invisible();
404             afs_RX_Running = 2;
405             afs_osi_Wakeup(&afs_RX_Running);
406 #ifndef UKERNEL
407             afs_osi_RxkRegister();
408 #endif /* !UKERNEL */
409             rxk_Listener();
410         }
411 #ifdef  AFS_SGI_ENV
412         AFS_GUNLOCK();
413         exit(CLD_EXITED, code);
414 #endif /* AFS_SGI_ENV */
415     }
416 #endif /* RXK_LISTENER_ENV */
417     else if (parm == AFSOP_START_AFS) {
418         /* afs daemon */
419         if (AFS_Running)
420             goto out;
421         AFS_Running = 1;
422         while (afs_initState < AFSOP_START_AFS)
423             afs_osi_Sleep(&afs_initState);
424
425         afs_initState = AFSOP_START_BKG;
426         afs_osi_Wakeup(&afs_initState);
427         afs_osi_Invisible();
428         afs_Daemon();
429 #ifdef AFS_SGI_ENV
430         AFS_GUNLOCK();
431         exit(CLD_EXITED, 0);
432 #endif /* AFS_SGI_ENV */
433     } else if (parm == AFSOP_START_CS) {
434         afs_osi_Invisible();
435         afs_CheckServerDaemon();
436 #ifdef AFS_SGI_ENV
437         AFS_GUNLOCK();
438         exit(CLD_EXITED, 0);
439 #endif /* AFS_SGI_ENV */
440     } else if (parm == AFSOP_START_BKG) {
441         while (afs_initState < AFSOP_START_BKG)
442             afs_osi_Sleep(&afs_initState);
443         if (afs_initState < AFSOP_GO) {
444             afs_initState = AFSOP_GO;
445             afs_osi_Wakeup(&afs_initState);
446         }
447         /* start the bkg daemon */
448         afs_osi_Invisible();
449 #ifdef AFS_AIX32_ENV
450         if (parm2)
451             afs_BioDaemon(parm2);
452         else
453 #endif /* AFS_AIX32_ENV */
454             afs_BackgroundDaemon();
455 #ifdef AFS_SGI_ENV
456         AFS_GUNLOCK();
457         exit(CLD_EXITED, 0);
458 #endif /* AFS_SGI_ENV */
459     } else if (parm == AFSOP_START_TRUNCDAEMON) {
460         while (afs_initState < AFSOP_GO)
461             afs_osi_Sleep(&afs_initState);
462         /* start the bkg daemon */
463         afs_osi_Invisible();
464         afs_CacheTruncateDaemon();
465 #ifdef  AFS_SGI_ENV
466         AFS_GUNLOCK();
467         exit(CLD_EXITED, 0);
468 #endif /* AFS_SGI_ENV */
469     }
470 #if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
471     else if (parm == AFSOP_RXEVENT_DAEMON) {
472         while (afs_initState < AFSOP_START_BKG)
473             afs_osi_Sleep(&afs_initState);
474         afs_osi_Invisible();
475         afs_rxevent_daemon();
476 #ifdef AFS_SGI_ENV
477         AFS_GUNLOCK();
478         exit(CLD_EXITED, 0);
479 #endif /* AFS_SGI_ENV */
480     }
481 #endif /* AFS_SUN5_ENV || RXK_LISTENER_ENV */
482 #endif /* AFS_LINUX24_ENV && !UKERNEL */
483     else if (parm == AFSOP_BASIC_INIT) {
484         afs_int32 temp;
485
486         while (!afs_InitSetup_done)
487             afs_osi_Sleep(&afs_InitSetup_done);
488
489 #if defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
490         temp = AFS_MINBUFFERS;  /* Should fix this soon */
491 #else
492         /* number of 2k buffers we could get from all of the buffer space */
493         temp = ((afs_bufferpages * NBPG) >> 11);
494         temp = temp >> 2;       /* don't take more than 25% (our magic parameter) */
495         if (temp < AFS_MINBUFFERS)
496             temp = AFS_MINBUFFERS;      /* though we really should have this many */
497 #endif
498         DInit(temp);
499         afs_rootFid.Fid.Volume = 0;
500         code = 0;
501     } else if (parm == AFSOP_ADDCELL) {
502         /* add a cell.  Parameter 2 is 8 hosts (in net order),  parm 3 is the null-terminated
503          * name.  Parameter 4 is the length of the name, including the null.  Parm 5 is the
504          * home cell flag (0x1 bit) and the nosuid flag (0x2 bit) */
505         struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
506
507         AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
508                    code);
509         if (!code) {
510             if (parm4 > sizeof(tcell->cellName))
511                 code = EFAULT;
512             else {
513                 AFS_COPYIN((char *)parm3, tcell->cellName, parm4, code);
514                 if (!code)
515                     afs_NewCell(tcell->cellName, tcell->hosts, parm5, NULL, 0,
516                                 0, 0);
517             }
518         }
519         afs_osi_Free(tcell, sizeof(struct afsop_cell));
520     } else if (parm == AFSOP_ADDCELL2) {
521         struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
522         char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ), *lcnamep = 0;
523         char *tbuffer1 = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
524         int cflags = parm4;
525
526 #if 0
527         /* wait for basic init - XXX can't find any reason we need this? */
528         while (afs_initState < AFSOP_START_BKG)
529             afs_osi_Sleep(&afs_initState);
530 #endif
531
532         AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
533                    code);
534         if (!code) {
535             AFS_COPYINSTR((char *)parm3, tbuffer1, AFS_SMALLOCSIZ,
536                           &bufferSize, code);
537             if (!code) {
538                 if (parm4 & 4) {
539                     AFS_COPYINSTR((char *)parm5, tbuffer, AFS_SMALLOCSIZ,
540                                   &bufferSize, code);
541                     if (!code) {
542                         lcnamep = tbuffer;
543                         cflags |= CLinkedCell;
544                     }
545                 }
546                 if (!code)
547                     code =
548                         afs_NewCell(tbuffer1, tcell->hosts, cflags, lcnamep,
549                                     0, 0, 0);
550             }
551         }
552         afs_osi_Free(tcell, sizeof(struct afsop_cell));
553         osi_FreeSmallSpace(tbuffer);
554         osi_FreeSmallSpace(tbuffer1);
555     } else if (parm == AFSOP_ADDCELLALIAS) {
556         /*
557          * Call arguments:
558          * parm2 is the alias name
559          * parm3 is the real cell name
560          */
561         char *aliasName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
562         char *cellName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
563
564         AFS_COPYINSTR((char *)parm2, aliasName, AFS_SMALLOCSIZ, &bufferSize,
565                       code);
566         if (!code)
567             AFS_COPYINSTR((char *)parm3, cellName, AFS_SMALLOCSIZ,
568                           &bufferSize, code);
569         if (!code)
570             afs_NewCellAlias(aliasName, cellName);
571         osi_FreeSmallSpace(aliasName);
572         osi_FreeSmallSpace(cellName);
573     } else if (parm == AFSOP_SET_THISCELL) {
574         /*
575          * Call arguments:
576          * parm2 is the primary cell name
577          */
578         char *cell = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
579
580         AFS_COPYINSTR((char *)parm2, cell, AFS_SMALLOCSIZ, &bufferSize, code);
581         if (!code)
582             afs_SetPrimaryCell(cell);
583         osi_FreeSmallSpace(cell);
584     } else if (parm == AFSOP_CACHEINIT) {
585         struct afs_cacheParams cparms;
586
587         if (afs_CacheInit_Done)
588             goto out;
589
590         AFS_COPYIN((char *)parm2, (caddr_t) & cparms, sizeof(cparms), code);
591         if (code) {
592 #if defined(KERNEL_HAVE_UERROR)
593             setuerror(code);
594             code = -1;
595 #endif
596             goto out;
597         }
598         afs_CacheInit_Done = 1;
599         {
600             struct afs_icl_log *logp;
601             /* initialize the ICL system */
602             code = afs_icl_CreateLog("cmfx", 60 * 1024, &logp);
603             if (code == 0)
604                 code =
605                     afs_icl_CreateSetWithFlags("cm", logp, NULL,
606                                                ICL_CRSET_FLAG_DEFAULT_OFF,
607                                                &afs_iclSetp);
608             code =
609                 afs_icl_CreateSet("cmlongterm", logp, NULL,
610                                   &afs_iclLongTermSetp);
611         }
612         afs_setTime = cparms.setTimeFlag;
613
614         code =
615             afs_CacheInit(cparms.cacheScaches, cparms.cacheFiles,
616                           cparms.cacheBlocks, cparms.cacheDcaches,
617                           cparms.cacheVolumes, cparms.chunkSize,
618                           cparms.memCacheFlag, cparms.inodes, cparms.users);
619
620     } else if (parm == AFSOP_CACHEINODE) {
621         ino_t ainode = parm2;
622         /* wait for basic init */
623         while (afs_initState < AFSOP_START_BKG)
624             afs_osi_Sleep(&afs_initState);
625
626         /* do it by inode */
627 #ifdef AFS_SGI62_ENV
628         ainode = (ainode << 32) | (parm3 & 0xffffffff);
629 #endif
630         code = afs_InitCacheFile(NULL, ainode);
631     } else if (parm == AFSOP_ROOTVOLUME) {
632         /* wait for basic init */
633         while (afs_initState < AFSOP_START_BKG)
634             afs_osi_Sleep(&afs_initState);
635
636         if (parm2) {
637             AFS_COPYINSTR((char *)parm2, afs_rootVolumeName,
638                           sizeof(afs_rootVolumeName), &bufferSize, code);
639             afs_rootVolumeName[sizeof(afs_rootVolumeName) - 1] = 0;
640         } else
641             code = 0;
642     } else if (parm == AFSOP_CACHEFILE || parm == AFSOP_CACHEINFO
643                || parm == AFSOP_VOLUMEINFO || parm == AFSOP_AFSLOG
644                || parm == AFSOP_CELLINFO) {
645         char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
646
647         code = 0;
648         AFS_COPYINSTR((char *)parm2, tbuffer, AFS_SMALLOCSIZ, &bufferSize,
649                       code);
650         if (code) {
651             osi_FreeSmallSpace(tbuffer);
652             goto out;
653         }
654         if (!code) {
655             tbuffer[AFS_SMALLOCSIZ - 1] = '\0'; /* null-terminate the name */
656             /* We have the cache dir copied in.  Call the cache init routine */
657             if (parm == AFSOP_CACHEFILE)
658                 code = afs_InitCacheFile(tbuffer, 0);
659             else if (parm == AFSOP_CACHEINFO)
660                 code = afs_InitCacheInfo(tbuffer);
661             else if (parm == AFSOP_VOLUMEINFO)
662                 code = afs_InitVolumeInfo(tbuffer);
663             else if (parm == AFSOP_CELLINFO)
664                 code = afs_InitCellInfo(tbuffer);
665         }
666         osi_FreeSmallSpace(tbuffer);
667     } else if (parm == AFSOP_GO) {
668         /* the generic initialization calls come here.  One parameter: should we do the
669          * set-time operation on this workstation */
670         if (afs_Go_Done)
671             goto out;
672         afs_Go_Done = 1;
673         while (afs_initState < AFSOP_GO)
674             afs_osi_Sleep(&afs_initState);
675         afs_initState = 101;
676         afs_setTime = parm2;
677         afs_osi_Wakeup(&afs_initState);
678 #if     (!defined(AFS_NONFSTRANS) && !defined(AFS_DEC_ENV)) || defined(AFS_AIX_IAUTH_ENV)
679         afs_nfsclient_init();
680 #endif
681         printf("found %d non-empty cache files (%d%%).\n",
682                afs_stats_cmperf.cacheFilesReused,
683                (100 * afs_stats_cmperf.cacheFilesReused) /
684                (afs_stats_cmperf.cacheNumEntries ? afs_stats_cmperf.
685                 cacheNumEntries : 1));
686     } else if (parm == AFSOP_ADVISEADDR) {
687         /* pass in the host address to the rx package */
688         afs_int32 count = parm2;
689         afs_int32 *buffer =
690             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
691         afs_int32 *maskbuffer =
692             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
693         afs_int32 *mtubuffer =
694             afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
695         int i;
696         int code;
697
698         if (count > AFS_MAX_INTERFACE_ADDR) {
699             code = ENOMEM;
700             count = AFS_MAX_INTERFACE_ADDR;
701         }
702
703         AFS_COPYIN((char *)parm3, (char *)buffer, count * sizeof(afs_int32),
704                    code);
705         if (parm4)
706             AFS_COPYIN((char *)parm4, (char *)maskbuffer,
707                        count * sizeof(afs_int32), code);
708         if (parm5)
709             AFS_COPYIN((char *)parm5, (char *)mtubuffer,
710                        count * sizeof(afs_int32), code);
711
712         afs_cb_interface.numberOfInterfaces = count;
713         for (i = 0; i < count; i++) {
714             afs_cb_interface.addr_in[i] = buffer[i];
715 #ifdef AFS_USERSPACE_IP_ADDR
716             /* AFS_USERSPACE_IP_ADDR means we have no way of finding the
717              * machines IP addresses when in the kernel (the in_ifaddr
718              * struct is not available), so we pass the info in at
719              * startup. We also pass in the subnetmask and mtu size. The
720              * subnetmask is used when setting the rank:
721              * afsi_SetServerIPRank(); and the mtu size is used when
722              * finding the best mtu size. rxi_FindIfnet() is replaced
723              * with rxi_Findcbi().
724              */
725             afs_cb_interface.subnetmask[i] =
726                 (parm4 ? maskbuffer[i] : 0xffffffff);
727             afs_cb_interface.mtu[i] = (parm5 ? mtubuffer[i] : htonl(1500));
728 #endif
729         }
730         afs_uuid_create(&afs_cb_interface.uuid);
731         rxi_setaddr(buffer[0]);
732         afs_osi_Free(buffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
733         afs_osi_Free(maskbuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
734         afs_osi_Free(mtubuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
735     }
736 #ifdef  AFS_SGI53_ENV
737     else if (parm == AFSOP_NFSSTATICADDR) {
738         extern int (*nfs_rfsdisptab_v2) ();
739         nfs_rfsdisptab_v2 = (int (*)())parm2;
740     } else if (parm == AFSOP_NFSSTATICADDR2) {
741         extern int (*nfs_rfsdisptab_v2) ();
742 #ifdef _K64U64
743         nfs_rfsdisptab_v2 = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
744 #else /* _K64U64 */
745         nfs_rfsdisptab_v2 = (int (*)())(parm3 & 0xffffffff);
746 #endif /* _K64U64 */
747     }
748 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
749     else if (parm == AFSOP_SBLOCKSTATICADDR2) {
750         extern int (*afs_sblockp) ();
751         extern void (*afs_sbunlockp) ();
752 #ifdef _K64U64
753         afs_sblockp = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
754         afs_sbunlockp = (void (*)())((parm4 << 32) | (parm5 & 0xffffffff));
755 #else
756         afs_sblockp = (int (*)())(parm3 & 0xffffffff);
757         afs_sbunlockp = (void (*)())(parm5 & 0xffffffff);
758 #endif /* _K64U64 */
759     }
760 #endif /* AFS_SGI62_ENV && !AFS_SGI65_ENV */
761 #endif /* AFS_SGI53_ENV */
762     else if (parm == AFSOP_SHUTDOWN) {
763         afs_cold_shutdown = 0;
764         if (parm == 1)
765             afs_cold_shutdown = 1;
766 #ifndef AFS_DARWIN_ENV
767         if (afs_globalVFS != 0) {
768             afs_warn("AFS isn't unmounted yet! Call aborted\n");
769             code = EACCES;
770         } else
771 #endif
772             afs_shutdown();
773     } else if (parm == AFSOP_AFS_VFSMOUNT) {
774 #ifdef  AFS_HPUX_ENV
775         vfsmount(parm2, parm3, parm4, parm5);
776 #else /* defined(AFS_HPUX_ENV) */
777 #if defined(KERNEL_HAVE_UERROR)
778         setuerror(EINVAL);
779 #else
780         code = EINVAL;
781 #endif
782 #endif /* defined(AFS_HPUX_ENV) */
783     } else if (parm == AFSOP_CLOSEWAIT) {
784         afs_SynchronousCloses = 'S';
785     } else if (parm == AFSOP_GETMTU) {
786         afs_uint32 mtu = 0;
787 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
788 #ifdef AFS_USERSPACE_IP_ADDR
789         afs_int32 i;
790         i = rxi_Findcbi(parm2);
791         mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
792 #else /* AFS_USERSPACE_IP_ADDR */
793         struct ifnet *tifnp;
794
795         tifnp = rxi_FindIfnet(parm2, NULL);     /*  make iterative */
796         mtu = (tifnp ? tifnp->if_mtu : htonl(1500));
797 #endif /* else AFS_USERSPACE_IP_ADDR */
798 #endif /* !AFS_SUN5_ENV */
799         if (!code)
800             AFS_COPYOUT((caddr_t) & mtu, (caddr_t) parm3, sizeof(afs_int32),
801                         code);
802 #ifdef AFS_AIX32_ENV
803 /* this is disabled for now because I can't figure out how to get access
804  * to these kernel variables.  It's only for supporting user-mode rx
805  * programs -- it makes a huge difference on the 220's in my testbed,
806  * though I don't know why. The bosserver does this with /etc/no, so it's
807  * being handled a different way for the servers right now.  */
808 /*      {
809         static adjusted = 0;
810         extern u_long sb_max_dflt;
811         if (!adjusted) {
812           adjusted = 1;
813           if (sb_max_dflt < 131072) sb_max_dflt = 131072; 
814           if (sb_max < 131072) sb_max = 131072; 
815         }
816       } */
817 #endif /* AFS_AIX32_ENV */
818     } else if (parm == AFSOP_GETMASK) { /* parm2 == addr in net order */
819         afs_uint32 mask = 0;
820 #if     !defined(AFS_SUN5_ENV)
821 #ifdef AFS_USERSPACE_IP_ADDR
822         afs_int32 i;
823         i = rxi_Findcbi(parm2);
824         if (i != -1) {
825             mask = afs_cb_interface.subnetmask[i];
826         } else {
827             code = -1;
828         }
829 #else /* AFS_USERSPACE_IP_ADDR */
830         struct ifnet *tifnp;
831
832         tifnp = rxi_FindIfnet(parm2, &mask);    /* make iterative */
833         if (!tifnp)
834             code = -1;
835 #endif /* else AFS_USERSPACE_IP_ADDR */
836 #endif /* !AFS_SUN5_ENV */
837         if (!code)
838             AFS_COPYOUT((caddr_t) & mask, (caddr_t) parm3, sizeof(afs_int32),
839                         code);
840     }
841 #ifdef AFS_AFSDB_ENV
842     else if (parm == AFSOP_AFSDB_HANDLER) {
843         int sizeArg = (int)parm4;
844         int kmsgLen = sizeArg & 0xffff;
845         int cellLen = (sizeArg & 0xffff0000) >> 16;
846         afs_int32 *kmsg = afs_osi_Alloc(kmsgLen);
847         char *cellname = afs_osi_Alloc(cellLen);
848
849 #ifndef UKERNEL
850         afs_osi_MaskSignals();
851 #endif
852         AFS_COPYIN((afs_int32 *) parm2, cellname, cellLen, code);
853         AFS_COPYIN((afs_int32 *) parm3, kmsg, kmsgLen, code);
854         if (!code) {
855             code = afs_AFSDBHandler(cellname, cellLen, kmsg);
856             if (*cellname == 1)
857                 *cellname = 0;
858             if (code == -2) {   /* Shutting down? */
859                 *cellname = 1;
860                 code = 0;
861             }
862         }
863         if (!code)
864             AFS_COPYOUT(cellname, (char *)parm2, cellLen, code);
865         afs_osi_Free(kmsg, kmsgLen);
866         afs_osi_Free(cellname, cellLen);
867     }
868 #endif
869     else if (parm == AFSOP_SET_DYNROOT) {
870         code = afs_SetDynrootEnable(parm2);
871     } else if (parm == AFSOP_SET_FAKESTAT) {
872         afs_fakestat_enable = parm2;
873         code = 0;
874     } else if (parm == AFSOP_SET_BACKUPTREE) {
875         afs_bkvolpref = parm2;
876     } else
877         code = EINVAL;
878
879   out:
880     AFS_GUNLOCK();
881 #ifdef AFS_LINUX20_ENV
882     return -code;
883 #else
884     return code;
885 #endif
886 }
887
888 #ifdef AFS_AIX32_ENV
889
890 #include "sys/lockl.h"
891
892 /*
893  * syscall -    this is the VRMIX system call entry point.
894  *
895  * NOTE:
896  *      THIS SHOULD BE CHANGED TO afs_syscall(), but requires
897  *      all the user-level calls to `syscall' to change.
898  */
899 syscall(syscall, p1, p2, p3, p4, p5, p6)
900 {
901     register rval1 = 0, code;
902     register monster;
903     int retval = 0;
904 #ifndef AFS_AIX41_ENV
905     extern lock_t kernel_lock;
906     monster = lockl(&kernel_lock, LOCK_SHORT);
907 #endif /* !AFS_AIX41_ENV */
908
909     AFS_STATCNT(syscall);
910     setuerror(0);
911     switch (syscall) {
912     case AFSCALL_CALL:
913         rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
914         break;
915
916     case AFSCALL_SETPAG:
917         AFS_GLOCK();
918         rval1 = afs_setpag();
919         AFS_GUNLOCK();
920         break;
921
922     case AFSCALL_PIOCTL:
923         AFS_GLOCK();
924         rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
925         AFS_GUNLOCK();
926         break;
927
928     case AFSCALL_ICREATE:
929         rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
930         break;
931
932     case AFSCALL_IOPEN:
933         rval1 = afs_syscall_iopen(p1, p2, p3);
934         break;
935
936     case AFSCALL_IDEC:
937         rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
938         break;
939
940     case AFSCALL_IINC:
941         rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
942         break;
943
944     case AFSCALL_ICL:
945         AFS_GLOCK();
946         code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
947         AFS_GUNLOCK();
948         if (!code)
949             rval1 = retval;
950         if (!rval1)
951             rval1 = code;
952         break;
953
954     default:
955         rval1 = EINVAL;
956         setuerror(EINVAL);
957         break;
958     }
959
960   out:
961 #ifndef AFS_AIX41_ENV
962     if (monster != LOCK_NEST)
963         unlockl(&kernel_lock);
964 #endif /* !AFS_AIX41_ENV */
965     return getuerror()? -1 : rval1;
966 }
967
968 /*
969  * lsetpag -    interface to afs_setpag().
970  */
971 lsetpag()
972 {
973
974     AFS_STATCNT(lsetpag);
975     return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
976 }
977
978 /*
979  * lpioctl -    interface to pioctl()
980  */
981 lpioctl(path, cmd, cmarg, follow)
982      char *path, *cmarg;
983 {
984
985     AFS_STATCNT(lpioctl);
986     return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
987 }
988
989 #else /* !AFS_AIX32_ENV       */
990
991 #if defined(AFS_SGI_ENV)
992 struct afsargs {
993     sysarg_t syscall;
994     sysarg_t parm1;
995     sysarg_t parm2;
996     sysarg_t parm3;
997     sysarg_t parm4;
998     sysarg_t parm5;
999 };
1000
1001
1002 int
1003 Afs_syscall(struct afsargs *uap, rval_t * rvp)
1004 {
1005     int error;
1006     long retval;
1007
1008     AFS_STATCNT(afs_syscall);
1009     switch (uap->syscall) {
1010     case AFSCALL_ICL:
1011         retval = 0;
1012         AFS_GLOCK();
1013         error =
1014             Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1015                         uap->parm5, &retval);
1016         AFS_GUNLOCK();
1017         rvp->r_val1 = retval;
1018         break;
1019 #ifdef AFS_SGI_XFS_IOPS_ENV
1020     case AFSCALL_IDEC64:
1021         error =
1022             afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1023                                uap->parm5);
1024         break;
1025     case AFSCALL_IINC64:
1026         error =
1027             afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1028                                uap->parm5);
1029         break;
1030     case AFSCALL_ILISTINODE64:
1031         error =
1032             afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
1033                                      uap->parm4, uap->parm5);
1034         break;
1035     case AFSCALL_ICREATENAME64:
1036         error =
1037             afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
1038                                       uap->parm4, uap->parm5);
1039         break;
1040 #endif
1041 #ifdef AFS_SGI_VNODE_GLUE
1042     case AFSCALL_INIT_KERNEL_CONFIG:
1043         error = afs_init_kernel_config(uap->parm1);
1044         break;
1045 #endif
1046     default:
1047         error =
1048             afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
1049                              uap->parm4, uap->parm5);
1050     }
1051     return error;
1052 }
1053
1054 #else /* AFS_SGI_ENV */
1055
1056 struct iparam {
1057     long param1;
1058     long param2;
1059     long param3;
1060     long param4;
1061 };
1062
1063 struct iparam32 {
1064     int param1;
1065     int param2;
1066     int param3;
1067     int param4;
1068 };
1069
1070
1071 static void
1072 iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
1073 {
1074     dst->param1 = src->param1;
1075     dst->param2 = src->param2;
1076     dst->param3 = src->param3;
1077     dst->param4 = src->param4;
1078 }
1079
1080 /*
1081  * If you need to change copyin_iparam(), you may also need to change
1082  * copyin_afs_ioctl().
1083  */
1084
1085 static int
1086 copyin_iparam(caddr_t cmarg, struct iparam *dst)
1087 {
1088     int code;
1089
1090 #if defined(AFS_HPUX_64BIT_ENV)
1091     struct iparam32 dst32;
1092
1093     if (is_32bit(u.u_procp)) {  /* is_32bit() in proc_iface.h */
1094         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
1095         if (!code)
1096             iparam32_to_iparam(&dst32, dst);
1097         return code;
1098     }
1099 #endif /* AFS_HPUX_64BIT_ENV */
1100
1101 #if defined(AFS_SUN57_64BIT_ENV)
1102     struct iparam32 dst32;
1103
1104     if (get_udatamodel() == DATAMODEL_ILP32) {
1105         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
1106         if (!code)
1107             iparam32_to_iparam(&dst32, dst);
1108         return code;
1109     }
1110 #endif /* AFS_SUN57_64BIT_ENV */
1111
1112 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) && !defined(AFS_AMD64_LINUX20_ENV)
1113     struct iparam32 dst32;
1114
1115 #ifdef AFS_SPARC64_LINUX24_ENV
1116     if (current->thread.flags & SPARC_FLAG_32BIT)
1117 #elif defined(AFS_SPARC64_LINUX20_ENV)
1118     if (current->tss.flags & SPARC_FLAG_32BIT)
1119 #elif defined(AFS_AMD64_LINUX20_ENV)
1120     if (current->thread.flags & THREAD_IA32)
1121 #else
1122 #error Not done for this linux version
1123 #endif
1124     {
1125         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
1126         if (!code)
1127             iparam32_to_iparam(&dst32, dst);
1128         return code;
1129     }
1130 #endif /* AFS_LINUX_64BIT_KERNEL */
1131
1132     AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
1133     return code;
1134 }
1135
1136 /* Main entry of all afs system calls */
1137 #ifdef  AFS_SUN5_ENV
1138 extern int afs_sinited;
1139
1140 /** The 32 bit OS expects the members of this structure to be 32 bit
1141  * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
1142  * to accomodate both, *long* is used instead of afs_int32
1143  */
1144
1145 #ifdef AFS_SUN57_ENV
1146 struct afssysa {
1147     long syscall;
1148     long parm1;
1149     long parm2;
1150     long parm3;
1151     long parm4;
1152     long parm5;
1153     long parm6;
1154 };
1155 #else
1156 struct afssysa {
1157     afs_int32 syscall;
1158     afs_int32 parm1;
1159     afs_int32 parm2;
1160     afs_int32 parm3;
1161     afs_int32 parm4;
1162     afs_int32 parm5;
1163     afs_int32 parm6;
1164 };
1165 #endif
1166
1167 Afs_syscall(register struct afssysa *uap, rval_t * rvp)
1168 {
1169     int *retval = &rvp->r_val1;
1170 #else /* AFS_SUN5_ENV */
1171 #if     defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1172 int
1173 afs3_syscall(p, args, retval)
1174 #ifdef AFS_FBSD50_ENV
1175      struct thread *p;
1176 #else
1177      struct proc *p;
1178 #endif
1179      void *args;
1180      int *retval;
1181 {
1182     register struct a {
1183         long syscall;
1184         long parm1;
1185         long parm2;
1186         long parm3;
1187         long parm4;
1188         long parm5;
1189         long parm6;
1190     } *uap = (struct a *)args;
1191 #else /* AFS_OSF_ENV */
1192 #ifdef AFS_LINUX20_ENV
1193 struct afssysargs {
1194     long syscall;
1195     long parm1;
1196     long parm2;
1197     long parm3;
1198     long parm4;
1199     long parm5;
1200     long parm6;                 /* not actually used - should be removed */
1201 };
1202 /* Linux system calls only set up for 5 arguments. */
1203 asmlinkage long
1204 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
1205 {
1206     struct afssysargs args, *uap = &args;
1207     long linux_ret = 0;
1208     long *retval = &linux_ret;
1209     long eparm[4];              /* matches AFSCALL_ICL in fstrace.c */
1210 #ifdef AFS_SPARC64_LINUX24_ENV
1211     afs_int32 eparm32[4];
1212 #endif
1213     /* eparm is also used by AFSCALL_CALL in afsd.c */
1214 #else
1215 #if defined(UKERNEL)
1216 Afs_syscall()
1217 {
1218     register struct a {
1219         long syscall;
1220         long parm1;
1221         long parm2;
1222         long parm3;
1223         long parm4;
1224         long parm5;
1225         long parm6;
1226     } *uap = (struct a *)u.u_ap;
1227 #else /* UKERNEL */
1228 int
1229 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
1230 afs_syscall()
1231 #else
1232 Afs_syscall()
1233 #endif                          /* SUN && !SUN5 */
1234 {
1235     register struct a {
1236         long syscall;
1237         long parm1;
1238         long parm2;
1239         long parm3;
1240         long parm4;
1241         long parm5;
1242         long parm6;
1243     } *uap = (struct a *)u.u_ap;
1244 #endif /* UKERNEL */
1245 #if  defined(AFS_DEC_ENV)
1246     int *retval = &u.u_r.r_val1;
1247 #elif defined(AFS_HPUX_ENV)
1248     long *retval = &u.u_rval1;
1249 #else
1250     int *retval = &u.u_rval1;
1251 #endif
1252 #endif /* AFS_LINUX20_ENV */
1253 #endif /* AFS_OSF_ENV */
1254 #endif /* AFS_SUN5_ENV */
1255     register int code = 0;
1256
1257     AFS_STATCNT(afs_syscall);
1258 #ifdef        AFS_SUN5_ENV
1259     rvp->r_vals = 0;
1260     if (!afs_sinited) {
1261         return (ENODEV);
1262     }
1263 #endif
1264 #ifdef AFS_LINUX20_ENV
1265     lock_kernel();
1266     /* setup uap for use below - pull out the magic decoder ring to know
1267      * which syscalls have folded argument lists.
1268      */
1269     uap->syscall = syscall;
1270     uap->parm1 = parm1;
1271     uap->parm2 = parm2;
1272     uap->parm3 = parm3;
1273     if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
1274 #ifdef AFS_SPARC64_LINUX24_ENV
1275 /* from arch/sparc64/kernel/sys_sparc32.c */
1276 #define AA(__x)                                \
1277 ({     unsigned long __ret;            \
1278        __asm__ ("srl   %0, 0, %0"      \
1279                 : "=r" (__ret)         \
1280                 : "0" (__x));          \
1281        __ret;                          \
1282 })
1283
1284
1285         if (current->thread.flags & SPARC_FLAG_32BIT) {
1286             AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
1287             eparm[0] = AA(eparm32[0]);
1288             eparm[1] = AA(eparm32[1]);
1289             eparm[2] = AA(eparm32[2]);
1290 #undef AA
1291         } else
1292 #endif
1293             AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
1294         uap->parm4 = eparm[0];
1295         uap->parm5 = eparm[1];
1296         uap->parm6 = eparm[2];
1297     } else {
1298         uap->parm4 = parm4;
1299         uap->parm5 = 0;
1300         uap->parm6 = 0;
1301     }
1302 #endif
1303
1304 #if defined(AFS_HPUX_ENV)
1305     /*
1306      * There used to be code here (duplicated from osi_Init()) for
1307      * initializing the semaphore used by AFS_GLOCK().  Was the
1308      * duplication to handle the case of a dynamically loaded kernel
1309      * module?
1310      */
1311     osi_InitGlock();
1312 #endif
1313     if (uap->syscall == AFSCALL_CALL) {
1314 #ifdef  AFS_SUN5_ENV
1315         code =
1316             afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1317                              uap->parm5, uap->parm6, rvp, CRED());
1318 #else
1319         code =
1320             afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1321                              uap->parm5, uap->parm6);
1322 #endif
1323     } else if (uap->syscall == AFSCALL_SETPAG) {
1324 #ifdef  AFS_SUN5_ENV
1325         register proc_t *procp;
1326
1327         procp = ttoproc(curthread);
1328         AFS_GLOCK();
1329         code = afs_setpag(&procp->p_cred);
1330         AFS_GUNLOCK();
1331 #else
1332         AFS_GLOCK();
1333 #if     defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1334         code = afs_setpag(p, args, retval);
1335 #else /* AFS_OSF_ENV */
1336         code = afs_setpag();
1337 #endif
1338         AFS_GUNLOCK();
1339 #endif
1340     } else if (uap->syscall == AFSCALL_PIOCTL) {
1341         AFS_GLOCK();
1342 #if defined(AFS_SUN5_ENV)
1343         code =
1344             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1345                                rvp, CRED());
1346 #elif defined(AFS_FBSD50_ENV)
1347         code =
1348             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1349                                p->td_ucred);
1350 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1351         code =
1352             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1353                                p->p_cred->pc_ucred);
1354 #else
1355         code =
1356             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
1357                                uap->parm4);
1358 #endif
1359         AFS_GUNLOCK();
1360     } else if (uap->syscall == AFSCALL_ICREATE) {
1361         struct iparam iparams;
1362
1363         code = copyin_iparam((char *)uap->parm3, &iparams);
1364         if (code) {
1365 #if defined(KERNEL_HAVE_UERROR)
1366             setuerror(code);
1367 #endif
1368         } else
1369 #ifdef  AFS_SUN5_ENV
1370             code =
1371                 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
1372                                     iparams.param2, iparams.param3,
1373                                     iparams.param4, rvp, CRED());
1374 #else
1375             code =
1376                 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
1377                                     iparams.param2,
1378 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1379                                     iparams.param3, iparams.param4, retval);
1380 #else
1381                                     iparams.param3, iparams.param4);
1382 #endif
1383 #endif /* AFS_SUN5_ENV */
1384     } else if (uap->syscall == AFSCALL_IOPEN) {
1385 #ifdef  AFS_SUN5_ENV
1386         code =
1387             afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
1388                               CRED());
1389 #else
1390 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1391         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, retval);
1392 #else
1393         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3);
1394 #endif
1395 #endif /* AFS_SUN5_ENV */
1396     } else if (uap->syscall == AFSCALL_IDEC) {
1397 #ifdef  AFS_SUN5_ENV
1398         code =
1399             afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1, rvp,
1400                                 CRED());
1401 #else
1402         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1);
1403 #endif /* AFS_SUN5_ENV */
1404     } else if (uap->syscall == AFSCALL_IINC) {
1405 #ifdef  AFS_SUN5_ENV
1406         code =
1407             afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1, rvp,
1408                                 CRED());
1409 #else
1410         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1);
1411 #endif /* AFS_SUN5_ENV */
1412     } else if (uap->syscall == AFSCALL_ICL) {
1413         AFS_GLOCK();
1414         code =
1415             Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
1416                         uap->parm5, retval);
1417         AFS_GUNLOCK();
1418 #ifdef AFS_LINUX20_ENV
1419         if (!code) {
1420             /* ICL commands can return values. */
1421             code = -linux_ret;  /* Gets negated again at exit below */
1422         }
1423 #else
1424         if (code) {
1425 #if defined(KERNEL_HAVE_UERROR)
1426             setuerror(code);
1427 #endif
1428         }
1429 #endif /* !AFS_LINUX20_ENV */
1430     } else {
1431 #if defined(KERNEL_HAVE_UERROR)
1432         setuerror(EINVAL);
1433 #else
1434         code = EINVAL;
1435 #endif
1436     }
1437
1438 #ifdef AFS_LINUX20_ENV
1439     code = -code;
1440     unlock_kernel();
1441 #endif
1442     return code;
1443 }
1444 #endif /* AFS_SGI_ENV */
1445 #endif /* !AFS_AIX32_ENV       */
1446
1447 /*
1448  * Initstate in the range 0 < x < 100 are early initialization states.
1449  * Initstate of 100 means a AFSOP_START operation has been done.  After this,
1450  *  the cache may be initialized.
1451  * Initstate of 101 means a AFSOP_GO operation has been done.  This operation
1452  *  is done after all the cache initialization has been done.
1453  * Initstate of 200 means that the volume has been looked up once, possibly
1454  *  incorrectly.
1455  * Initstate of 300 means that the volume has been *successfully* looked up.
1456  */
1457 int
1458 afs_CheckInit(void)
1459 {
1460     register int code = 0;
1461
1462     AFS_STATCNT(afs_CheckInit);
1463     if (afs_initState <= 100)
1464         code = ENXIO;           /* never finished init phase */
1465     else if (afs_initState == 101) {    /* init done, wait for afs_daemon */
1466         while (afs_initState < 200)
1467             afs_osi_Sleep(&afs_initState);
1468     } else if (afs_initState == 200)
1469         code = ETIMEDOUT;       /* didn't find root volume */
1470     return code;
1471 }
1472
1473 int afs_shuttingdown = 0;
1474 void
1475 afs_shutdown(void)
1476 {
1477     extern short afs_brsDaemons;
1478     extern afs_int32 afs_CheckServerDaemonStarted;
1479     extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
1480     extern struct osi_file *afs_cacheInodep;
1481
1482     AFS_STATCNT(afs_shutdown);
1483     if (afs_shuttingdown)
1484         return;
1485     afs_shuttingdown = 1;
1486     if (afs_cold_shutdown)
1487         afs_warn("COLD ");
1488     else
1489         afs_warn("WARM ");
1490     afs_warn("shutting down of: CB... ");
1491
1492     afs_termState = AFSOP_STOP_RXCALLBACK;
1493     rx_WakeupServerProcs();
1494     /* shutdown_rxkernel(); */
1495     while (afs_termState == AFSOP_STOP_RXCALLBACK)
1496         afs_osi_Sleep(&afs_termState);
1497
1498     afs_warn("afs... ");
1499     while (afs_termState == AFSOP_STOP_AFS) {
1500         afs_osi_CancelWait(&AFS_WaitHandler);
1501         afs_osi_Sleep(&afs_termState);
1502     }
1503     if (afs_CheckServerDaemonStarted) {
1504         while (afs_termState == AFSOP_STOP_CS) {
1505             afs_osi_CancelWait(&AFS_CSWaitHandler);
1506             afs_osi_Sleep(&afs_termState);
1507         }
1508     }
1509     afs_warn("BkG... ");
1510     /* Wake-up afs_brsDaemons so that we don't have to wait for a bkg job! */
1511     while (afs_termState == AFSOP_STOP_BKG) {
1512         afs_osi_Wakeup(&afs_brsDaemons);
1513         afs_osi_Sleep(&afs_termState);
1514     }
1515     afs_warn("CTrunc... ");
1516     /* Cancel cache truncate daemon. */
1517     while (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
1518         afs_osi_Wakeup((char *)&afs_CacheTruncateDaemon);
1519         afs_osi_Sleep(&afs_termState);
1520     }
1521 #ifdef AFS_AFSDB_ENV
1522     afs_warn("AFSDB... ");
1523     afs_StopAFSDB();
1524     while (afs_termState == AFSOP_STOP_AFSDB)
1525         afs_osi_Sleep(&afs_termState);
1526 #endif
1527 #if     defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
1528     afs_warn("RxEvent... ");
1529     /* cancel rx event daemon */
1530     while (afs_termState == AFSOP_STOP_RXEVENT)
1531         afs_osi_Sleep(&afs_termState);
1532 #if defined(RXK_LISTENER_ENV)
1533 #ifndef UKERNEL
1534     afs_warn("UnmaskRxkSignals... ");
1535     afs_osi_UnmaskRxkSignals();
1536 #endif
1537     /* cancel rx listener */
1538     afs_warn("RxListener... ");
1539     osi_StopListener();         /* This closes rx_socket. */
1540     while (afs_termState == AFSOP_STOP_RXK_LISTENER) {
1541         afs_warn("Sleep... ");
1542         afs_osi_Sleep(&afs_termState);
1543     }
1544 #endif
1545 #else
1546     afs_termState = AFSOP_STOP_COMPLETE;
1547 #endif
1548     afs_warn("\n");
1549
1550     /* Close file only after daemons which can write to it are stopped. */
1551     if (afs_cacheInodep) {      /* memcache won't set this */
1552         osi_UFSClose(afs_cacheInodep);  /* Since we always leave it open */
1553         afs_cacheInodep = 0;
1554     }
1555     return;                     /* Just kill daemons for now */
1556 #ifdef notdef
1557     shutdown_CB();
1558     shutdown_AFS();
1559     shutdown_rxkernel();
1560     shutdown_rxevent();
1561     shutdown_rx();
1562     afs_shutdown_BKG();
1563     shutdown_bufferpackage();
1564     shutdown_daemons();
1565     shutdown_cache();
1566     shutdown_osi();
1567     shutdown_osinet();
1568     shutdown_osifile();
1569     shutdown_vnodeops();
1570     shutdown_vfsops();
1571     shutdown_exporter();
1572     shutdown_memcache();
1573 #if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
1574 #if !defined(AFS_DEC_ENV) && !defined(AFS_OSF_ENV)
1575     /* this routine does not exist in Ultrix systems... 93.01.19 */
1576     shutdown_nfsclnt();
1577 #endif /* AFS_DEC_ENV */
1578 #endif
1579     shutdown_afstest();
1580     /* The following hold the cm stats */
1581 /*
1582     memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));
1583     memset(&afs_stats_cmperf, 0, sizeof(struct afs_stats_CMPerf));
1584     memset(&afs_stats_cmfullperf, 0, sizeof(struct afs_stats_CMFullPerf));
1585 */
1586     afs_warn(" ALL allocated tables\n");
1587     afs_shuttingdown = 0;
1588 #endif
1589 }
1590
1591 void
1592 shutdown_afstest(void)
1593 {
1594     AFS_STATCNT(shutdown_afstest);
1595     afs_initState = afs_termState = afs_setTime = 0;
1596     AFS_Running = afs_CB_Running = 0;
1597     afs_CacheInit_Done = afs_Go_Done = 0;
1598     if (afs_cold_shutdown) {
1599         *afs_rootVolumeName = 0;
1600     }
1601 }
1602
1603
1604 /* In case there is a bunch of dynamically build bkg daemons to free */
1605 void
1606 afs_shutdown_BKG(void)
1607 {
1608     AFS_STATCNT(shutdown_BKG);
1609 }
1610
1611
1612 #if defined(AFS_ALPHA_ENV) || defined(AFS_SGI61_ENV)
1613 /* For SGI 6.2, this can is changed to 1 if it's a 32 bit kernel. */
1614 #if defined(AFS_SGI62_ENV) && defined(KERNEL) && !defined(_K64U64)
1615 int afs_icl_sizeofLong = 1;
1616 #else
1617 int afs_icl_sizeofLong = 2;
1618 #endif /* SGI62 */
1619 #else
1620 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
1621 int afs_icl_sizeofLong = 2;
1622 #else
1623 int afs_icl_sizeofLong = 1;
1624 #endif
1625 #endif
1626
1627 int afs_icl_inited = 0;
1628
1629 /* init function, called once, under afs_icl_lock */
1630 int
1631 afs_icl_Init(void)
1632 {
1633     afs_icl_inited = 1;
1634     return 0;
1635 }
1636
1637 extern struct afs_icl_log *afs_icl_FindLog();
1638 extern struct afs_icl_set *afs_icl_FindSet();
1639
1640
1641 static int
1642 Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval)
1643 {
1644     afs_int32 *lp, elts, flags;
1645     register afs_int32 code;
1646     struct afs_icl_log *logp;
1647     struct afs_icl_set *setp;
1648 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1649     size_t temp;
1650 #else /* AFS_SGI61_ENV */
1651 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
1652     afs_uint64 temp;
1653 #else
1654     afs_uint32 temp;
1655 #endif
1656 #endif /* AFS_SGI61_ENV */
1657     char tname[65];
1658     afs_int32 startCookie;
1659     afs_int32 allocated;
1660     struct afs_icl_log *tlp;
1661
1662 #ifdef  AFS_SUN5_ENV
1663     if (!afs_suser(CRED())) {   /* only root can run this code */
1664         return (EACCES);
1665     }
1666 #else
1667     if (!afs_suser()) {         /* only root can run this code */
1668 #if defined(KERNEL_HAVE_UERROR)
1669         setuerror(EACCES);
1670         return EACCES;
1671 #else
1672         return EPERM;
1673 #endif
1674     }
1675 #endif
1676     switch (opcode) {
1677     case ICL_OP_COPYOUTCLR:     /* copy out data then clear */
1678     case ICL_OP_COPYOUT:        /* copy ouy data */
1679         /* copyout: p1=logname, p2=&buffer, p3=size(words), p4=&cookie
1680          * return flags<<24 + nwords.
1681          * updates cookie to updated start (not end) if we had to
1682          * skip some records.
1683          */
1684         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1685         if (code)
1686             return code;
1687         AFS_COPYIN((char *)p4, (char *)&startCookie, sizeof(afs_int32), code);
1688         if (code)
1689             return code;
1690         logp = afs_icl_FindLog(tname);
1691         if (!logp)
1692             return ENOENT;
1693 #define BUFFERSIZE      AFS_LRALLOCSIZ
1694         lp = (afs_int32 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1695         elts = BUFFERSIZE / sizeof(afs_int32);
1696         if (p3 < elts)
1697             elts = p3;
1698         flags = (opcode == ICL_OP_COPYOUT) ? 0 : ICL_COPYOUTF_CLRAFTERREAD;
1699         code =
1700             afs_icl_CopyOut(logp, lp, &elts, (afs_uint32 *) & startCookie,
1701                             &flags);
1702         if (code) {
1703             osi_FreeLargeSpace((struct osi_buffer *)lp);
1704             break;
1705         }
1706         AFS_COPYOUT((char *)lp, (char *)p2, elts * sizeof(afs_int32), code);
1707         if (code)
1708             goto done;
1709         AFS_COPYOUT((char *)&startCookie, (char *)p4, sizeof(afs_int32),
1710                     code);
1711         if (code)
1712             goto done;
1713 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
1714         if (!(IS64U))
1715             *retval = ((long)((flags << 24) | (elts & 0xffffff))) << 32;
1716         else
1717 #endif
1718             *retval = (flags << 24) | (elts & 0xffffff);
1719       done:
1720         afs_icl_LogRele(logp);
1721         osi_FreeLargeSpace((struct osi_buffer *)lp);
1722         break;
1723
1724     case ICL_OP_ENUMLOGS:       /* enumerate logs */
1725         /* enumerate logs: p1=index, p2=&name, p3=sizeof(name), p4=&size.
1726          * return 0 for success, otherwise error.
1727          */
1728         for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
1729             if (p1-- == 0)
1730                 break;
1731         }
1732         if (!tlp)
1733             return ENOENT;      /* past the end of file */
1734         temp = strlen(tlp->name) + 1;
1735         if (temp > p3)
1736             return EINVAL;
1737         AFS_COPYOUT(tlp->name, (char *)p2, temp, code);
1738         if (!code)              /* copy out size of log */
1739             AFS_COPYOUT((char *)&tlp->logSize, (char *)p4, sizeof(afs_int32),
1740                         code);
1741         break;
1742
1743     case ICL_OP_ENUMLOGSBYSET:  /* enumerate logs by set name */
1744         /* enumerate logs: p1=setname, p2=index, p3=&name, p4=sizeof(name).
1745          * return 0 for success, otherwise error.
1746          */
1747         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1748         if (code)
1749             return code;
1750         setp = afs_icl_FindSet(tname);
1751         if (!setp)
1752             return ENOENT;
1753         if (p2 > ICL_LOGSPERSET)
1754             return EINVAL;
1755         if (!(tlp = setp->logs[p2]))
1756             return EBADF;
1757         temp = strlen(tlp->name) + 1;
1758         if (temp > p4)
1759             return EINVAL;
1760         AFS_COPYOUT(tlp->name, (char *)p3, temp, code);
1761         break;
1762
1763     case ICL_OP_CLRLOG: /* clear specified log */
1764         /* zero out the specified log: p1=logname */
1765         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1766         if (code)
1767             return code;
1768         logp = afs_icl_FindLog(tname);
1769         if (!logp)
1770             return ENOENT;
1771         code = afs_icl_ZeroLog(logp);
1772         afs_icl_LogRele(logp);
1773         break;
1774
1775     case ICL_OP_CLRSET: /* clear specified set */
1776         /* zero out the specified set: p1=setname */
1777         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1778         if (code)
1779             return code;
1780         setp = afs_icl_FindSet(tname);
1781         if (!setp)
1782             return ENOENT;
1783         code = afs_icl_ZeroSet(setp);
1784         afs_icl_SetRele(setp);
1785         break;
1786
1787     case ICL_OP_CLRALL: /* clear all logs */
1788         /* zero out all logs -- no args */
1789         code = 0;
1790         ObtainWriteLock(&afs_icl_lock, 178);
1791         for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
1792             tlp->refCount++;    /* hold this guy */
1793             ReleaseWriteLock(&afs_icl_lock);
1794             /* don't clear persistent logs */
1795             if ((tlp->states & ICL_LOGF_PERSISTENT) == 0)
1796                 code = afs_icl_ZeroLog(tlp);
1797             ObtainWriteLock(&afs_icl_lock, 179);
1798             if (--tlp->refCount == 0)
1799                 afs_icl_ZapLog(tlp);
1800             if (code)
1801                 break;
1802         }
1803         ReleaseWriteLock(&afs_icl_lock);
1804         break;
1805
1806     case ICL_OP_ENUMSETS:       /* enumerate all sets */
1807         /* enumerate sets: p1=index, p2=&name, p3=sizeof(name), p4=&states.
1808          * return 0 for success, otherwise error.
1809          */
1810         for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
1811             if (p1-- == 0)
1812                 break;
1813         }
1814         if (!setp)
1815             return ENOENT;      /* past the end of file */
1816         temp = strlen(setp->name) + 1;
1817         if (temp > p3)
1818             return EINVAL;
1819         AFS_COPYOUT(setp->name, (char *)p2, temp, code);
1820         if (!code)              /* copy out size of log */
1821             AFS_COPYOUT((char *)&setp->states, (char *)p4, sizeof(afs_int32),
1822                         code);
1823         break;
1824
1825     case ICL_OP_SETSTAT:        /* set status on a set */
1826         /* activate the specified set: p1=setname, p2=op */
1827         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1828         if (code)
1829             return code;
1830         setp = afs_icl_FindSet(tname);
1831         if (!setp)
1832             return ENOENT;
1833         code = afs_icl_SetSetStat(setp, p2);
1834         afs_icl_SetRele(setp);
1835         break;
1836
1837     case ICL_OP_SETSTATALL:     /* set status on all sets */
1838         /* activate the specified set: p1=op */
1839         code = 0;
1840         ObtainWriteLock(&afs_icl_lock, 180);
1841         for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
1842             setp->refCount++;   /* hold this guy */
1843             ReleaseWriteLock(&afs_icl_lock);
1844             /* don't set states on persistent sets */
1845             if ((setp->states & ICL_SETF_PERSISTENT) == 0)
1846                 code = afs_icl_SetSetStat(setp, p1);
1847             ObtainWriteLock(&afs_icl_lock, 181);
1848             if (--setp->refCount == 0)
1849                 afs_icl_ZapSet(setp);
1850             if (code)
1851                 break;
1852         }
1853         ReleaseWriteLock(&afs_icl_lock);
1854         break;
1855
1856     case ICL_OP_SETLOGSIZE:     /* set size of log */
1857         /* set the size of the specified log: p1=logname, p2=size (in words) */
1858         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1859         if (code)
1860             return code;
1861         logp = afs_icl_FindLog(tname);
1862         if (!logp)
1863             return ENOENT;
1864         code = afs_icl_LogSetSize(logp, p2);
1865         afs_icl_LogRele(logp);
1866         break;
1867
1868     case ICL_OP_GETLOGINFO:     /* get size of log */
1869         /* zero out the specified log: p1=logname, p2=&logSize, p3=&allocated */
1870         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1871         if (code)
1872             return code;
1873         logp = afs_icl_FindLog(tname);
1874         if (!logp)
1875             return ENOENT;
1876         allocated = !!logp->datap;
1877         AFS_COPYOUT((char *)&logp->logSize, (char *)p2, sizeof(afs_int32),
1878                     code);
1879         if (!code)
1880             AFS_COPYOUT((char *)&allocated, (char *)p3, sizeof(afs_int32),
1881                         code);
1882         afs_icl_LogRele(logp);
1883         break;
1884
1885     case ICL_OP_GETSETINFO:     /* get state of set */
1886         /* zero out the specified set: p1=setname, p2=&state */
1887         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1888         if (code)
1889             return code;
1890         setp = afs_icl_FindSet(tname);
1891         if (!setp)
1892             return ENOENT;
1893         AFS_COPYOUT((char *)&setp->states, (char *)p2, sizeof(afs_int32),
1894                     code);
1895         afs_icl_SetRele(setp);
1896         break;
1897
1898     default:
1899         code = EINVAL;
1900     }
1901
1902     return code;
1903 }
1904
1905
1906 afs_lock_t afs_icl_lock;
1907
1908 /* exported routine: a 4 parameter event */
1909 int
1910 afs_icl_Event4(register struct afs_icl_set *setp, afs_int32 eventID,
1911                afs_int32 lAndT, long p1, long p2, long p3, long p4)
1912 {
1913     afs_int32 mask;
1914     register int i;
1915     register afs_int32 tmask;
1916     int ix;
1917
1918     /* If things aren't init'ed yet (or the set is inactive), don't panic */
1919     if (!ICL_SETACTIVE(setp))
1920         return 0;
1921
1922     AFS_ASSERT_GLOCK();
1923     mask = lAndT >> 24 & 0xff;  /* mask of which logs to log to */
1924     ix = ICL_EVENTBYTE(eventID);
1925     ObtainReadLock(&setp->lock);
1926     if (setp->eventFlags[ix] & ICL_EVENTMASK(eventID)) {
1927         for (i = 0, tmask = 1; i < ICL_LOGSPERSET; i++, tmask <<= 1) {
1928             if (mask & tmask) {
1929                 afs_icl_AppendRecord(setp->logs[i], eventID, lAndT & 0xffffff,
1930                                      p1, p2, p3, p4);
1931             }
1932             mask &= ~tmask;
1933             if (mask == 0)
1934                 break;          /* break early */
1935         }
1936     }
1937     ReleaseReadLock(&setp->lock);
1938     return 0;
1939 }
1940
1941 /* Next 4 routines should be implemented via var-args or something.
1942  * Whole purpose is to avoid compiler warnings about parameter # mismatches.
1943  * Otherwise, could call afs_icl_Event4 directly.
1944  */
1945 int
1946 afs_icl_Event3(register struct afs_icl_set *setp, afs_int32 eventID,
1947                afs_int32 lAndT, long p1, long p2, long p3)
1948 {
1949     return afs_icl_Event4(setp, eventID, lAndT, p1, p2, p3, (long)0);
1950 }
1951
1952 int
1953 afs_icl_Event2(register struct afs_icl_set *setp, afs_int32 eventID,
1954                afs_int32 lAndT, long p1, long p2)
1955 {
1956     return afs_icl_Event4(setp, eventID, lAndT, p1, p2, (long)0, (long)0);
1957 }
1958
1959 int
1960 afs_icl_Event1(register struct afs_icl_set *setp, afs_int32 eventID,
1961                afs_int32 lAndT, long p1)
1962 {
1963     return afs_icl_Event4(setp, eventID, lAndT, p1, (long)0, (long)0,
1964                           (long)0);
1965 }
1966
1967 int
1968 afs_icl_Event0(register struct afs_icl_set *setp, afs_int32 eventID,
1969                afs_int32 lAndT)
1970 {
1971     return afs_icl_Event4(setp, eventID, lAndT, (long)0, (long)0, (long)0,
1972                           (long)0);
1973 }
1974
1975 struct afs_icl_log *afs_icl_allLogs = 0;
1976
1977 /* function to purge records from the start of the log, until there
1978  * is at least minSpace long's worth of space available without
1979  * making the head and the tail point to the same word.
1980  *
1981  * Log must be write-locked.
1982  */
1983 static void
1984 afs_icl_GetLogSpace(register struct afs_icl_log *logp, afs_int32 minSpace)
1985 {
1986     register unsigned int tsize;
1987
1988     while (logp->logSize - logp->logElements <= minSpace) {
1989         /* eat a record */
1990         tsize = ((logp->datap[logp->firstUsed]) >> 24) & 0xff;
1991         logp->logElements -= tsize;
1992         logp->firstUsed += tsize;
1993         if (logp->firstUsed >= logp->logSize)
1994             logp->firstUsed -= logp->logSize;
1995         logp->baseCookie += tsize;
1996     }
1997 }
1998
1999 /* append string astr to buffer, including terminating null char.
2000  *
2001  * log must be write-locked.
2002  */
2003 #define ICL_CHARSPERLONG        4
2004 static void
2005 afs_icl_AppendString(struct afs_icl_log *logp, char *astr)
2006 {
2007     char *op;                   /* ptr to char to write */
2008     int tc;
2009     register int bib;           /* bytes in buffer */
2010
2011     bib = 0;
2012     op = (char *)&(logp->datap[logp->firstFree]);
2013     while (1) {
2014         tc = *astr++;
2015         *op++ = tc;
2016         if (++bib >= ICL_CHARSPERLONG) {
2017             /* new word */
2018             bib = 0;
2019             if (++(logp->firstFree) >= logp->logSize) {
2020                 logp->firstFree = 0;
2021                 op = (char *)&(logp->datap[0]);
2022             }
2023             logp->logElements++;
2024         }
2025         if (tc == 0)
2026             break;
2027     }
2028     if (bib > 0) {
2029         /* if we've used this word at all, allocate it */
2030         if (++(logp->firstFree) >= logp->logSize) {
2031             logp->firstFree = 0;
2032         }
2033         logp->logElements++;
2034     }
2035 }
2036
2037 /* add a long to the log, ignoring overflow (checked already) */
2038 #define ICL_APPENDINT32(lp, x) \
2039     MACRO_BEGIN \
2040         (lp)->datap[(lp)->firstFree] = (x); \
2041         if (++((lp)->firstFree) >= (lp)->logSize) { \
2042                 (lp)->firstFree = 0; \
2043         } \
2044         (lp)->logElements++; \
2045     MACRO_END
2046
2047 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
2048 #define ICL_APPENDLONG(lp, x) \
2049     MACRO_BEGIN \
2050         ICL_APPENDINT32((lp), ((x) >> 32) & 0xffffffffL); \
2051         ICL_APPENDINT32((lp), (x) & 0xffffffffL); \
2052     MACRO_END
2053
2054 #else /* AFS_ALPHA_ENV */
2055 #define ICL_APPENDLONG(lp, x) ICL_APPENDINT32((lp), (x))
2056 #endif /* AFS_ALPHA_ENV */
2057
2058 /* routine to tell whether we're dealing with the address or the
2059  * object itself
2060  */
2061 int
2062 afs_icl_UseAddr(int type)
2063 {
2064     if (type == ICL_TYPE_HYPER || type == ICL_TYPE_STRING
2065         || type == ICL_TYPE_FID || type == ICL_TYPE_INT64)
2066         return 1;
2067     else
2068         return 0;
2069 }
2070
2071 /* Function to append a record to the log.  Written for speed
2072  * since we know that we're going to have to make this work fast
2073  * pretty soon, anyway.  The log must be unlocked.
2074  */
2075
2076 void
2077 afs_icl_AppendRecord(register struct afs_icl_log *logp, afs_int32 op,
2078                      afs_int32 types, long p1, long p2, long p3, long p4)
2079 {
2080     int rsize;                  /* record size in longs */
2081     register int tsize;         /* temp size */
2082     osi_timeval_t tv;
2083     int t1, t2, t3, t4;
2084
2085     t4 = types & 0x3f;          /* decode types */
2086     types >>= 6;
2087     t3 = types & 0x3f;
2088     types >>= 6;
2089     t2 = types & 0x3f;
2090     types >>= 6;
2091     t1 = types & 0x3f;
2092
2093     osi_GetTime(&tv);           /* It panics for solaris if inside */
2094     ObtainWriteLock(&logp->lock, 182);
2095     if (!logp->datap) {
2096         ReleaseWriteLock(&logp->lock);
2097         return;
2098     }
2099
2100     /* get timestamp as # of microseconds since some time that doesn't
2101      * change that often.  This algorithm ticks over every 20 minutes
2102      * or so (1000 seconds).  Write a timestamp record if it has.
2103      */
2104     if (tv.tv_sec - logp->lastTS > 1024) {
2105         /* the timer has wrapped -- write a timestamp record */
2106         if (logp->logSize - logp->logElements <= 5)
2107             afs_icl_GetLogSpace(logp, 5);
2108
2109         ICL_APPENDINT32(logp,
2110                         (afs_int32) (5 << 24) + (ICL_TYPE_UNIXDATE << 18));
2111         ICL_APPENDINT32(logp, (afs_int32) ICL_INFO_TIMESTAMP);
2112         ICL_APPENDINT32(logp, (afs_int32) 0);   /* use thread ID zero for clocks */
2113         ICL_APPENDINT32(logp,
2114                         (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 +
2115                         tv.tv_usec);
2116         ICL_APPENDINT32(logp, (afs_int32) tv.tv_sec);
2117
2118         logp->lastTS = tv.tv_sec;
2119     }
2120
2121     rsize = 4;                  /* base case */
2122     if (t1) {
2123         /* compute size of parameter p1.  Only tricky case is string.
2124          * In that case, we have to call strlen to get the string length.
2125          */
2126         ICL_SIZEHACK(t1, p1);
2127     }
2128     if (t2) {
2129         /* compute size of parameter p2.  Only tricky case is string.
2130          * In that case, we have to call strlen to get the string length.
2131          */
2132         ICL_SIZEHACK(t2, p2);
2133     }
2134     if (t3) {
2135         /* compute size of parameter p3.  Only tricky case is string.
2136          * In that case, we have to call strlen to get the string length.
2137          */
2138         ICL_SIZEHACK(t3, p3);
2139     }
2140     if (t4) {
2141         /* compute size of parameter p4.  Only tricky case is string.
2142          * In that case, we have to call strlen to get the string length.
2143          */
2144         ICL_SIZEHACK(t4, p4);
2145     }
2146
2147     /* At this point, we've computed all of the parameter sizes, and
2148      * have in rsize the size of the entire record we want to append.
2149      * Next, we check that we actually have room in the log to do this
2150      * work, and then we do the append.
2151      */
2152     if (rsize > 255) {
2153         ReleaseWriteLock(&logp->lock);
2154         return;                 /* log record too big to express */
2155     }
2156
2157     if (logp->logSize - logp->logElements <= rsize)
2158         afs_icl_GetLogSpace(logp, rsize);
2159
2160     ICL_APPENDINT32(logp,
2161                     (afs_int32) (rsize << 24) + (t1 << 18) + (t2 << 12) +
2162                     (t3 << 6) + t4);
2163     ICL_APPENDINT32(logp, (afs_int32) op);
2164     ICL_APPENDINT32(logp, (afs_int32) osi_ThreadUnique());
2165     ICL_APPENDINT32(logp,
2166                     (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 + tv.tv_usec);
2167
2168     if (t1) {
2169         /* marshall parameter 1 now */
2170         if (t1 == ICL_TYPE_STRING) {
2171             afs_icl_AppendString(logp, (char *)p1);
2172         } else if (t1 == ICL_TYPE_HYPER) {
2173             ICL_APPENDINT32(logp,
2174                             (afs_int32) ((struct afs_hyper_t *)p1)->high);
2175             ICL_APPENDINT32(logp,
2176                             (afs_int32) ((struct afs_hyper_t *)p1)->low);
2177         } else if (t1 == ICL_TYPE_INT64) {
2178 #ifdef AFSLITTLE_ENDIAN
2179 #ifdef AFS_64BIT_CLIENT
2180             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
2181             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
2182 #else /* AFS_64BIT_CLIENT */
2183             ICL_APPENDINT32(logp, (afs_int32) p1);
2184             ICL_APPENDINT32(logp, (afs_int32) 0);
2185 #endif /* AFS_64BIT_CLIENT */
2186 #else /* AFSLITTLE_ENDIAN */
2187 #ifdef AFS_64BIT_CLIENT
2188             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
2189             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
2190 #else /* AFS_64BIT_CLIENT */
2191             ICL_APPENDINT32(logp, (afs_int32) 0);
2192             ICL_APPENDINT32(logp, (afs_int32) p1);
2193 #endif /* AFS_64BIT_CLIENT */
2194 #endif /* AFSLITTLE_ENDIAN */
2195         } else if (t1 == ICL_TYPE_FID) {
2196             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
2197             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
2198             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[2]);
2199             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[3]);
2200         }
2201 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
2202         else if (t1 == ICL_TYPE_INT32)
2203             ICL_APPENDINT32(logp, (afs_int32) p1);
2204 #endif /* AFS_ALPHA_ENV */
2205         else
2206             ICL_APPENDLONG(logp, p1);
2207     }
2208     if (t2) {
2209         /* marshall parameter 2 now */
2210         if (t2 == ICL_TYPE_STRING)
2211             afs_icl_AppendString(logp, (char *)p2);
2212         else if (t2 == ICL_TYPE_HYPER) {
2213             ICL_APPENDINT32(logp,
2214                             (afs_int32) ((struct afs_hyper_t *)p2)->high);
2215             ICL_APPENDINT32(logp,
2216                             (afs_int32) ((struct afs_hyper_t *)p2)->low);
2217         } else if (t2 == ICL_TYPE_INT64) {
2218 #ifdef AFSLITTLE_ENDIAN
2219 #ifdef AFS_64BIT_CLIENT
2220             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
2221             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
2222 #else /* AFS_64BIT_CLIENT */
2223             ICL_APPENDINT32(logp, (afs_int32) p2);
2224             ICL_APPENDINT32(logp, (afs_int32) 0);
2225 #endif /* AFS_64BIT_CLIENT */
2226 #else /* AFSLITTLE_ENDIAN */
2227 #ifdef AFS_64BIT_CLIENT
2228             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
2229             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
2230 #else /* AFS_64BIT_CLIENT */
2231             ICL_APPENDINT32(logp, (afs_int32) 0);
2232             ICL_APPENDINT32(logp, (afs_int32) p2);
2233 #endif /* AFS_64BIT_CLIENT */
2234 #endif /* AFSLITTLE_ENDIAN */
2235         } else if (t2 == ICL_TYPE_FID) {
2236             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
2237             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
2238             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[2]);
2239             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[3]);
2240         }
2241 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
2242         else if (t2 == ICL_TYPE_INT32)
2243             ICL_APPENDINT32(logp, (afs_int32) p2);
2244 #endif /* AFS_ALPHA_ENV */
2245         else
2246             ICL_APPENDLONG(logp, p2);
2247     }
2248     if (t3) {
2249         /* marshall parameter 3 now */
2250         if (t3 == ICL_TYPE_STRING)
2251             afs_icl_AppendString(logp, (char *)p3);
2252         else if (t3 == ICL_TYPE_HYPER) {
2253             ICL_APPENDINT32(logp,
2254                             (afs_int32) ((struct afs_hyper_t *)p3)->high);
2255             ICL_APPENDINT32(logp,
2256                             (afs_int32) ((struct afs_hyper_t *)p3)->low);
2257         } else if (t3 == ICL_TYPE_INT64) {
2258 #ifdef AFSLITTLE_ENDIAN
2259 #ifdef AFS_64BIT_CLIENT
2260             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
2261             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
2262 #else /* AFS_64BIT_CLIENT */
2263             ICL_APPENDINT32(logp, (afs_int32) p3);
2264             ICL_APPENDINT32(logp, (afs_int32) 0);
2265 #endif /* AFS_64BIT_CLIENT */
2266 #else /* AFSLITTLE_ENDIAN */
2267 #ifdef AFS_64BIT_CLIENT
2268             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
2269             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
2270 #else /* AFS_64BIT_CLIENT */
2271             ICL_APPENDINT32(logp, (afs_int32) 0);
2272             ICL_APPENDINT32(logp, (afs_int32) p3);
2273 #endif /* AFS_64BIT_CLIENT */
2274 #endif /* AFSLITTLE_ENDIAN */
2275         } else if (t3 == ICL_TYPE_FID) {
2276             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
2277             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
2278             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[2]);
2279             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[3]);
2280         }
2281 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
2282         else if (t3 == ICL_TYPE_INT32)
2283             ICL_APPENDINT32(logp, (afs_int32) p3);
2284 #endif /* AFS_ALPHA_ENV */
2285         else
2286             ICL_APPENDLONG(logp, p3);
2287     }
2288     if (t4) {
2289         /* marshall parameter 4 now */
2290         if (t4 == ICL_TYPE_STRING)
2291             afs_icl_AppendString(logp, (char *)p4);
2292         else if (t4 == ICL_TYPE_HYPER) {
2293             ICL_APPENDINT32(logp,
2294                             (afs_int32) ((struct afs_hyper_t *)p4)->high);
2295             ICL_APPENDINT32(logp,
2296                             (afs_int32) ((struct afs_hyper_t *)p4)->low);
2297         } else if (t4 == ICL_TYPE_INT64) {
2298 #ifdef AFSLITTLE_ENDIAN
2299 #ifdef AFS_64BIT_CLIENT
2300             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
2301             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
2302 #else /* AFS_64BIT_CLIENT */
2303             ICL_APPENDINT32(logp, (afs_int32) p4);
2304             ICL_APPENDINT32(logp, (afs_int32) 0);
2305 #endif /* AFS_64BIT_CLIENT */
2306 #else /* AFSLITTLE_ENDIAN */
2307 #ifdef AFS_64BIT_CLIENT
2308             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
2309             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
2310 #else /* AFS_64BIT_CLIENT */
2311             ICL_APPENDINT32(logp, (afs_int32) 0);
2312             ICL_APPENDINT32(logp, (afs_int32) p4);
2313 #endif /* AFS_64BIT_CLIENT */
2314 #endif /* AFSLITTLE_ENDIAN */
2315         } else if (t4 == ICL_TYPE_FID) {
2316             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
2317             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
2318             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[2]);
2319             ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[3]);
2320         }
2321 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
2322         else if (t4 == ICL_TYPE_INT32)
2323             ICL_APPENDINT32(logp, (afs_int32) p4);
2324 #endif /* AFS_ALPHA_ENV */
2325         else
2326             ICL_APPENDLONG(logp, p4);
2327     }
2328     ReleaseWriteLock(&logp->lock);
2329 }
2330
2331 /* create a log with size logSize; return it in *outLogpp and tag
2332  * it with name "name."
2333  */
2334 int
2335 afs_icl_CreateLog(char *name, afs_int32 logSize,
2336                   struct afs_icl_log **outLogpp)
2337 {
2338     return afs_icl_CreateLogWithFlags(name, logSize, /*flags */ 0, outLogpp);
2339 }
2340
2341 /* create a log with size logSize; return it in *outLogpp and tag
2342  * it with name "name."  'flags' can be set to make the log unclearable.
2343  */
2344 int
2345 afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize, afs_uint32 flags,
2346                            struct afs_icl_log **outLogpp)
2347 {
2348     register struct afs_icl_log *logp;
2349
2350     /* add into global list under lock */
2351     ObtainWriteLock(&afs_icl_lock, 183);
2352     if (!afs_icl_inited)
2353         afs_icl_Init();
2354
2355     for (logp = afs_icl_allLogs; logp; logp = logp->nextp) {
2356         if (strcmp(logp->name, name) == 0) {
2357             /* found it already created, just return it */
2358             logp->refCount++;
2359             *outLogpp = logp;
2360             if (flags & ICL_CRLOG_FLAG_PERSISTENT) {
2361                 ObtainWriteLock(&logp->lock, 184);
2362                 logp->states |= ICL_LOGF_PERSISTENT;
2363                 ReleaseWriteLock(&logp->lock);
2364             }
2365             ReleaseWriteLock(&afs_icl_lock);
2366             return 0;
2367         }
2368     }
2369
2370     logp = (struct afs_icl_log *)
2371         osi_AllocSmallSpace(sizeof(struct afs_icl_log));
2372     memset((caddr_t) logp, 0, sizeof(*logp));
2373
2374     logp->refCount = 1;
2375     logp->name = osi_AllocSmallSpace(strlen(name) + 1);
2376     strcpy(logp->name, name);
2377     LOCK_INIT(&logp->lock, "logp lock");
2378     logp->logSize = logSize;
2379     logp->datap = NULL;         /* don't allocate it until we need it */
2380
2381     if (flags & ICL_CRLOG_FLAG_PERSISTENT)
2382         logp->states |= ICL_LOGF_PERSISTENT;
2383
2384     logp->nextp = afs_icl_allLogs;
2385     afs_icl_allLogs = logp;
2386     ReleaseWriteLock(&afs_icl_lock);
2387
2388     *outLogpp = logp;
2389     return 0;
2390 }
2391
2392 /* called with a log, a pointer to a buffer, the size of the buffer
2393  * (in *bufSizep), the starting cookie (in *cookiep, use 0 at the start)
2394  * and returns data in the provided buffer, and returns output flags
2395  * in *flagsp.  The flag ICL_COPYOUTF_MISSEDSOME is set if we can't
2396  * find the record with cookie value cookie.
2397  */
2398 int
2399 afs_icl_CopyOut(register struct afs_icl_log *logp, afs_int32 * bufferp,
2400                 afs_int32 * bufSizep, afs_uint32 * cookiep,
2401                 afs_int32 * flagsp)
2402 {
2403     afs_int32 nwords;           /* number of words to copy out */
2404     afs_uint32 startCookie;     /* first cookie to use */
2405     afs_int32 outWords;         /* words we've copied out */
2406     afs_int32 inWords;          /* max words to copy out */
2407     afs_int32 code;             /* return code */
2408     afs_int32 ix;               /* index we're copying from */
2409     afs_int32 outFlags;         /* return flags */
2410     afs_int32 inFlags;          /* flags passed in */
2411     afs_int32 end;
2412
2413     inWords = *bufSizep;        /* max to copy out */
2414     outWords = 0;               /* amount copied out */
2415     startCookie = *cookiep;
2416     outFlags = 0;
2417     inFlags = *flagsp;
2418     code = 0;
2419
2420     ObtainWriteLock(&logp->lock, 185);
2421     if (!logp->datap) {
2422         ReleaseWriteLock(&logp->lock);
2423         goto done;
2424     }
2425
2426     /* first, compute the index of the start cookie we've been passed */
2427     while (1) {
2428         /* (re-)compute where we should start */
2429         if (startCookie < logp->baseCookie) {
2430             if (startCookie)    /* missed some output */
2431                 outFlags |= ICL_COPYOUTF_MISSEDSOME;
2432             /* skip to the first available record */
2433             startCookie = logp->baseCookie;
2434             *cookiep = startCookie;
2435         }
2436
2437         /* compute where we find the first element to copy out */
2438         ix = logp->firstUsed + startCookie - logp->baseCookie;
2439         if (ix >= logp->logSize)
2440             ix -= logp->logSize;
2441
2442         /* if have some data now, break out and process it */
2443         if (startCookie - logp->baseCookie < logp->logElements)
2444             break;
2445
2446         /* At end of log, so clear it if we need to */
2447         if (inFlags & ICL_COPYOUTF_CLRAFTERREAD) {
2448             logp->firstUsed = logp->firstFree = 0;
2449             logp->logElements = 0;
2450         }
2451         /* otherwise, either wait for the data to arrive, or return */
2452         if (!(inFlags & ICL_COPYOUTF_WAITIO)) {
2453             ReleaseWriteLock(&logp->lock);
2454             code = 0;
2455             goto done;
2456         }
2457         logp->states |= ICL_LOGF_WAITING;
2458         ReleaseWriteLock(&logp->lock);
2459         afs_osi_Sleep(&logp->lock);
2460         ObtainWriteLock(&logp->lock, 186);
2461     }
2462     /* copy out data from ix to logSize or firstFree, depending
2463      * upon whether firstUsed <= firstFree (no wrap) or otherwise.
2464      * be careful not to copy out more than nwords.
2465      */
2466     if (ix >= logp->firstUsed) {
2467         if (logp->firstUsed <= logp->firstFree)
2468             /* no wrapping */
2469             end = logp->firstFree;      /* first element not to copy */
2470         else
2471             end = logp->logSize;
2472         nwords = inWords;       /* don't copy more than this */
2473         if (end - ix < nwords)
2474             nwords = end - ix;
2475         if (nwords > 0) {
2476             memcpy((char *)bufferp, (char *)&logp->datap[ix],
2477                    sizeof(afs_int32) * nwords);
2478             outWords += nwords;
2479             inWords -= nwords;
2480             bufferp += nwords;
2481         }
2482         /* if we're going to copy more out below, we'll start here */
2483         ix = 0;
2484     }
2485     /* now, if active part of the log has wrapped, there's more stuff
2486      * starting at the head of the log.  Copy out more from there.
2487      */
2488     if (logp->firstUsed > logp->firstFree && ix < logp->firstFree
2489         && inWords > 0) {
2490         /* (more to) copy out from the wrapped section at the
2491          * start of the log.  May get here even if didn't copy any
2492          * above, if the cookie points directly into the wrapped section.
2493          */
2494         nwords = inWords;
2495         if (logp->firstFree - ix < nwords)
2496             nwords = logp->firstFree - ix;
2497         memcpy((char *)bufferp, (char *)&logp->datap[ix],
2498                sizeof(afs_int32) * nwords);
2499         outWords += nwords;
2500         inWords -= nwords;
2501         bufferp += nwords;
2502     }
2503
2504     ReleaseWriteLock(&logp->lock);
2505
2506   done:
2507     if (code == 0) {
2508         *bufSizep = outWords;
2509         *flagsp = outFlags;
2510     }
2511     return code;
2512 }
2513
2514 /* return basic parameter information about a log */
2515 int
2516 afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
2517                     afs_int32 * curSizep)
2518 {
2519     ObtainReadLock(&logp->lock);
2520     *maxSizep = logp->logSize;
2521     *curSizep = logp->logElements;
2522     ReleaseReadLock(&logp->lock);
2523     return 0;
2524 }
2525
2526
2527 /* hold and release logs */
2528 int
2529 afs_icl_LogHold(register struct afs_icl_log *logp)
2530 {
2531     ObtainWriteLock(&afs_icl_lock, 187);
2532     logp->refCount++;
2533     ReleaseWriteLock(&afs_icl_lock);
2534     return 0;
2535 }
2536
2537 /* hold and release logs, called with lock already held */
2538 int
2539 afs_icl_LogHoldNL(register struct afs_icl_log *logp)
2540 {
2541     logp->refCount++;
2542     return 0;
2543 }
2544
2545 /* keep track of how many sets believe the log itself is allocated */
2546 int
2547 afs_icl_LogUse(register struct afs_icl_log *logp)
2548 {
2549     ObtainWriteLock(&logp->lock, 188);
2550     if (logp->setCount == 0) {
2551         /* this is the first set actually using the log -- allocate it */
2552         if (logp->logSize == 0) {
2553             /* we weren't passed in a hint and it wasn't set */
2554             logp->logSize = ICL_DEFAULT_LOGSIZE;
2555         }
2556         logp->datap =
2557             (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logp->logSize);
2558 #ifdef  KERNEL_HAVE_PIN
2559         pin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2560 #endif
2561     }
2562     logp->setCount++;
2563     ReleaseWriteLock(&logp->lock);
2564     return 0;
2565 }
2566
2567 /* decrement the number of real users of the log, free if possible */
2568 int
2569 afs_icl_LogFreeUse(register struct afs_icl_log *logp)
2570 {
2571     ObtainWriteLock(&logp->lock, 189);
2572     if (--logp->setCount == 0) {
2573         /* no more users -- free it (but keep log structure around) */
2574         afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
2575 #ifdef  KERNEL_HAVE_PIN
2576         unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2577 #endif
2578         logp->firstUsed = logp->firstFree = 0;
2579         logp->logElements = 0;
2580         logp->datap = NULL;
2581     }
2582     ReleaseWriteLock(&logp->lock);
2583     return 0;
2584 }
2585
2586 /* set the size of the log to 'logSize' */
2587 int
2588 afs_icl_LogSetSize(register struct afs_icl_log *logp, afs_int32 logSize)
2589 {
2590     ObtainWriteLock(&logp->lock, 190);
2591     if (!logp->datap) {
2592         /* nothing to worry about since it's not allocated */
2593         logp->logSize = logSize;
2594     } else {
2595         /* reset log */
2596         logp->firstUsed = logp->firstFree = 0;
2597         logp->logElements = 0;
2598
2599         /* free and allocate a new one */
2600         afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
2601 #ifdef  KERNEL_HAVE_PIN
2602         unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2603 #endif
2604         logp->datap =
2605             (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logSize);
2606 #ifdef  KERNEL_HAVE_PIN
2607         pin((char *)logp->datap, sizeof(afs_int32) * logSize);
2608 #endif
2609         logp->logSize = logSize;
2610     }
2611     ReleaseWriteLock(&logp->lock);
2612
2613     return 0;
2614 }
2615
2616 /* free a log.  Called with afs_icl_lock locked. */
2617 int
2618 afs_icl_ZapLog(register struct afs_icl_log *logp)
2619 {
2620     register struct afs_icl_log **lpp, *tp;
2621
2622     for (lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
2623         if (tp == logp) {
2624             /* found the dude we want to remove */
2625             *lpp = logp->nextp;
2626             osi_FreeSmallSpace(logp->name);
2627             osi_FreeSmallSpace(logp->datap);
2628             osi_FreeSmallSpace(logp);
2629             break;              /* won't find it twice */
2630         }
2631     }
2632     return 0;
2633 }
2634
2635 /* do the release, watching for deleted entries */
2636 int
2637 afs_icl_LogRele(register struct afs_icl_log *logp)
2638 {
2639     ObtainWriteLock(&afs_icl_lock, 191);
2640     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
2641         afs_icl_ZapLog(logp);   /* destroys logp's lock! */
2642     }
2643     ReleaseWriteLock(&afs_icl_lock);
2644     return 0;
2645 }
2646
2647 /* do the release, watching for deleted entries, log already held */
2648 int
2649 afs_icl_LogReleNL(register struct afs_icl_log *logp)
2650 {
2651     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
2652         afs_icl_ZapLog(logp);   /* destroys logp's lock! */
2653     }
2654     return 0;
2655 }
2656
2657 /* zero out the log */
2658 int
2659 afs_icl_ZeroLog(register struct afs_icl_log *logp)
2660 {
2661     ObtainWriteLock(&logp->lock, 192);
2662     logp->firstUsed = logp->firstFree = 0;
2663     logp->logElements = 0;
2664     logp->baseCookie = 0;
2665     ReleaseWriteLock(&logp->lock);
2666     return 0;
2667 }
2668
2669 /* free a log entry, and drop its reference count */
2670 int
2671 afs_icl_LogFree(register struct afs_icl_log *logp)
2672 {
2673     ObtainWriteLock(&logp->lock, 193);
2674     logp->states |= ICL_LOGF_DELETED;
2675     ReleaseWriteLock(&logp->lock);
2676     afs_icl_LogRele(logp);
2677     return 0;
2678 }
2679
2680 /* find a log by name, returning it held */
2681 struct afs_icl_log *
2682 afs_icl_FindLog(char *name)
2683 {
2684     register struct afs_icl_log *tp;
2685     ObtainWriteLock(&afs_icl_lock, 194);
2686     for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
2687         if (strcmp(tp->name, name) == 0) {
2688             /* this is the dude we want */
2689             tp->refCount++;
2690             break;
2691         }
2692     }
2693     ReleaseWriteLock(&afs_icl_lock);
2694     return tp;
2695 }
2696
2697 int
2698 afs_icl_EnumerateLogs(int (*aproc)
2699                         (char *name, char *arock, struct afs_icl_log * tp),
2700                       char *arock)
2701 {
2702     register struct afs_icl_log *tp;
2703     register afs_int32 code;
2704
2705     code = 0;
2706     ObtainWriteLock(&afs_icl_lock, 195);
2707     for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
2708         tp->refCount++;         /* hold this guy */
2709         ReleaseWriteLock(&afs_icl_lock);
2710         ObtainReadLock(&tp->lock);
2711         code = (*aproc) (tp->name, arock, tp);
2712         ReleaseReadLock(&tp->lock);
2713         ObtainWriteLock(&afs_icl_lock, 196);
2714         if (--tp->refCount == 0)
2715             afs_icl_ZapLog(tp);
2716         if (code)
2717             break;
2718     }
2719     ReleaseWriteLock(&afs_icl_lock);
2720     return code;
2721 }
2722
2723 struct afs_icl_set *afs_icl_allSets = 0;
2724
2725 int
2726 afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
2727                   struct afs_icl_log *fatalLogp,
2728                   struct afs_icl_set **outSetpp)
2729 {
2730     return afs_icl_CreateSetWithFlags(name, baseLogp, fatalLogp,
2731                                       /*flags */ 0, outSetpp);
2732 }
2733
2734 /* create a set, given pointers to base and fatal logs, if any.
2735  * Logs are unlocked, but referenced, and *outSetpp is returned
2736  * referenced.  Function bumps reference count on logs, since it
2737  * addds references from the new afs_icl_set.  When the set is destroyed,
2738  * those references will be released.
2739  */
2740 int
2741 afs_icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
2742                            struct afs_icl_log *fatalLogp, afs_uint32 flags,
2743                            struct afs_icl_set **outSetpp)
2744 {
2745     register struct afs_icl_set *setp;
2746     register int i;
2747     afs_int32 states = ICL_DEFAULT_SET_STATES;
2748
2749     ObtainWriteLock(&afs_icl_lock, 197);
2750     if (!afs_icl_inited)
2751         afs_icl_Init();
2752
2753     for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
2754         if (strcmp(setp->name, name) == 0) {
2755             setp->refCount++;
2756             *outSetpp = setp;
2757             if (flags & ICL_CRSET_FLAG_PERSISTENT) {
2758                 ObtainWriteLock(&setp->lock, 198);
2759                 setp->states |= ICL_SETF_PERSISTENT;
2760                 ReleaseWriteLock(&setp->lock);
2761             }
2762             ReleaseWriteLock(&afs_icl_lock);
2763             return 0;
2764         }
2765     }
2766
2767     /* determine initial state */
2768     if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
2769         states = ICL_SETF_ACTIVE;
2770     else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
2771         states = ICL_SETF_FREED;
2772     if (flags & ICL_CRSET_FLAG_PERSISTENT)
2773         states |= ICL_SETF_PERSISTENT;
2774
2775     setp = (struct afs_icl_set *)afs_osi_Alloc(sizeof(struct afs_icl_set));
2776     memset((caddr_t) setp, 0, sizeof(*setp));
2777     setp->refCount = 1;
2778     if (states & ICL_SETF_FREED)
2779         states &= ~ICL_SETF_ACTIVE;     /* if freed, can't be active */
2780     setp->states = states;
2781
2782     LOCK_INIT(&setp->lock, "setp lock");
2783     /* next lock is obtained in wrong order, hierarchy-wise, but
2784      * it doesn't matter, since no one can find this lock yet, since
2785      * the afs_icl_lock is still held, and thus the obtain can't block.
2786      */
2787     ObtainWriteLock(&setp->lock, 199);
2788     setp->name = osi_AllocSmallSpace(strlen(name) + 1);
2789     strcpy(setp->name, name);
2790     setp->nevents = ICL_DEFAULTEVENTS;
2791     setp->eventFlags = afs_osi_Alloc(ICL_DEFAULTEVENTS);
2792 #ifdef  KERNEL_HAVE_PIN
2793     pin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
2794 #endif
2795     for (i = 0; i < ICL_DEFAULTEVENTS; i++)
2796         setp->eventFlags[i] = 0xff;     /* default to enabled */
2797
2798     /* update this global info under the afs_icl_lock */
2799     setp->nextp = afs_icl_allSets;
2800     afs_icl_allSets = setp;
2801     ReleaseWriteLock(&afs_icl_lock);
2802
2803     /* set's basic lock is still held, so we can finish init */
2804     if (baseLogp) {
2805         setp->logs[0] = baseLogp;
2806         afs_icl_LogHold(baseLogp);
2807         if (!(setp->states & ICL_SETF_FREED))
2808             afs_icl_LogUse(baseLogp);   /* log is actually being used */
2809     }
2810     if (fatalLogp) {
2811         setp->logs[1] = fatalLogp;
2812         afs_icl_LogHold(fatalLogp);
2813         if (!(setp->states & ICL_SETF_FREED))
2814             afs_icl_LogUse(fatalLogp);  /* log is actually being used */
2815     }
2816     ReleaseWriteLock(&setp->lock);
2817
2818     *outSetpp = setp;
2819     return 0;
2820 }
2821
2822 /* function to change event enabling information for a particular set */
2823 int
2824 afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
2825 {
2826     char *tp;
2827
2828     ObtainWriteLock(&setp->lock, 200);
2829     if (!ICL_EVENTOK(setp, eventID)) {
2830         ReleaseWriteLock(&setp->lock);
2831         return -1;
2832     }
2833     tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
2834     if (setValue)
2835         *tp |= ICL_EVENTMASK(eventID);
2836     else
2837         *tp &= ~(ICL_EVENTMASK(eventID));
2838     ReleaseWriteLock(&setp->lock);
2839     return 0;
2840 }
2841
2842 /* return indication of whether a particular event ID is enabled
2843  * for tracing.  If *getValuep is set to 0, the event is disabled,
2844  * otherwise it is enabled.  All events start out enabled by default.
2845  */
2846 int
2847 afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
2848 {
2849     ObtainReadLock(&setp->lock);
2850     if (!ICL_EVENTOK(setp, eventID)) {
2851         ReleaseWriteLock(&setp->lock);
2852         return -1;
2853     }
2854     if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
2855         *getValuep = 1;
2856     else
2857         *getValuep = 0;
2858     ReleaseReadLock(&setp->lock);
2859     return 0;
2860 }
2861
2862 /* hold and release event sets */
2863 int
2864 afs_icl_SetHold(register struct afs_icl_set *setp)
2865 {
2866     ObtainWriteLock(&afs_icl_lock, 201);
2867     setp->refCount++;
2868     ReleaseWriteLock(&afs_icl_lock);
2869     return 0;
2870 }
2871
2872 /* free a set.  Called with afs_icl_lock locked */
2873 int
2874 afs_icl_ZapSet(register struct afs_icl_set *setp)
2875 {
2876     register struct afs_icl_set **lpp, *tp;
2877     int i;
2878     register struct afs_icl_log *tlp;
2879
2880     for (lpp = &afs_icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
2881         if (tp == setp) {
2882             /* found the dude we want to remove */
2883             *lpp = setp->nextp;
2884             osi_FreeSmallSpace(setp->name);
2885             afs_osi_Free(setp->eventFlags, ICL_DEFAULTEVENTS);
2886 #ifdef  KERNEL_HAVE_PIN
2887             unpin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
2888 #endif
2889             for (i = 0; i < ICL_LOGSPERSET; i++) {
2890                 if ((tlp = setp->logs[i]))
2891                     afs_icl_LogReleNL(tlp);
2892             }
2893             osi_FreeSmallSpace(setp);
2894             break;              /* won't find it twice */
2895         }
2896     }
2897     return 0;
2898 }
2899
2900 /* do the release, watching for deleted entries */
2901 int
2902 afs_icl_SetRele(register struct afs_icl_set *setp)
2903 {
2904     ObtainWriteLock(&afs_icl_lock, 202);
2905     if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
2906         afs_icl_ZapSet(setp);   /* destroys setp's lock! */
2907     }
2908     ReleaseWriteLock(&afs_icl_lock);
2909     return 0;
2910 }
2911
2912 /* free a set entry, dropping its reference count */
2913 int
2914 afs_icl_SetFree(register struct afs_icl_set *setp)
2915 {
2916     ObtainWriteLock(&setp->lock, 203);
2917     setp->states |= ICL_SETF_DELETED;
2918     ReleaseWriteLock(&setp->lock);
2919     afs_icl_SetRele(setp);
2920     return 0;
2921 }
2922
2923 /* find a set by name, returning it held */
2924 struct afs_icl_set *
2925 afs_icl_FindSet(char *name)
2926 {
2927     register struct afs_icl_set *tp;
2928     ObtainWriteLock(&afs_icl_lock, 204);
2929     for (tp = afs_icl_allSets; tp; tp = tp->nextp) {
2930         if (strcmp(tp->name, name) == 0) {
2931             /* this is the dude we want */
2932             tp->refCount++;
2933             break;
2934         }
2935     }
2936     ReleaseWriteLock(&afs_icl_lock);
2937     return tp;
2938 }
2939
2940 /* zero out all the logs in the set */
2941 int
2942 afs_icl_ZeroSet(struct afs_icl_set *setp)
2943 {
2944     register int i;
2945     int code = 0;
2946     int tcode;
2947     struct afs_icl_log *logp;
2948
2949     ObtainReadLock(&setp->lock);
2950     for (i = 0; i < ICL_LOGSPERSET; i++) {
2951         logp = setp->logs[i];
2952         if (logp) {
2953             afs_icl_LogHold(logp);
2954             tcode = afs_icl_ZeroLog(logp);
2955             if (tcode != 0)
2956                 code = tcode;   /* save the last bad one */
2957             afs_icl_LogRele(logp);
2958         }
2959     }
2960     ReleaseReadLock(&setp->lock);
2961     return code;
2962 }
2963
2964 int
2965 afs_icl_EnumerateSets(int (*aproc)
2966                         (char *name, char *arock, struct afs_icl_log * tp),
2967                       char *arock)
2968 {
2969     register struct afs_icl_set *tp, *np;
2970     register afs_int32 code;
2971
2972     code = 0;
2973     ObtainWriteLock(&afs_icl_lock, 205);
2974     for (tp = afs_icl_allSets; tp; tp = np) {
2975         tp->refCount++;         /* hold this guy */
2976         ReleaseWriteLock(&afs_icl_lock);
2977         code = (*aproc) (tp->name, arock, tp);
2978         ObtainWriteLock(&afs_icl_lock, 206);
2979         np = tp->nextp;         /* tp may disappear next, but not np */
2980         if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
2981             afs_icl_ZapSet(tp);
2982         if (code)
2983             break;
2984     }
2985     ReleaseWriteLock(&afs_icl_lock);
2986     return code;
2987 }
2988
2989 int
2990 afs_icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
2991 {
2992     register int i;
2993     int code = -1;
2994
2995     ObtainWriteLock(&setp->lock, 207);
2996     for (i = 0; i < ICL_LOGSPERSET; i++) {
2997         if (!setp->logs[i]) {
2998             setp->logs[i] = newlogp;
2999             code = i;
3000             afs_icl_LogHold(newlogp);
3001             if (!(setp->states & ICL_SETF_FREED)) {
3002                 /* bump up the number of sets using the log */
3003                 afs_icl_LogUse(newlogp);
3004             }
3005             break;
3006         }
3007     }
3008     ReleaseWriteLock(&setp->lock);
3009     return code;
3010 }
3011
3012 int
3013 afs_icl_SetSetStat(struct afs_icl_set *setp, int op)
3014 {
3015     int i;
3016     afs_int32 code;
3017     struct afs_icl_log *logp;
3018
3019     ObtainWriteLock(&setp->lock, 208);
3020     switch (op) {
3021     case ICL_OP_SS_ACTIVATE:    /* activate a log */
3022         /*
3023          * If we are not already active, see if we have released
3024          * our demand that the log be allocated (FREED set).  If
3025          * we have, reassert our desire.
3026          */
3027         if (!(setp->states & ICL_SETF_ACTIVE)) {
3028             if (setp->states & ICL_SETF_FREED) {
3029                 /* have to reassert desire for logs */
3030                 for (i = 0; i < ICL_LOGSPERSET; i++) {
3031                     logp = setp->logs[i];
3032                     if (logp) {
3033                         afs_icl_LogHold(logp);
3034                         afs_icl_LogUse(logp);
3035                         afs_icl_LogRele(logp);
3036                     }
3037                 }
3038                 setp->states &= ~ICL_SETF_FREED;
3039             }
3040             setp->states |= ICL_SETF_ACTIVE;
3041         }
3042         code = 0;
3043         break;
3044
3045     case ICL_OP_SS_DEACTIVATE:  /* deactivate a log */
3046         /* this doesn't require anything beyond clearing the ACTIVE flag */
3047         setp->states &= ~ICL_SETF_ACTIVE;
3048         code = 0;
3049         break;
3050
3051     case ICL_OP_SS_FREE:        /* deassert design for log */
3052         /* 
3053          * if we are already in this state, do nothing; otherwise
3054          * deassert desire for log
3055          */
3056         if (setp->states & ICL_SETF_ACTIVE)
3057             code = EINVAL;
3058         else {
3059             if (!(setp->states & ICL_SETF_FREED)) {
3060                 for (i = 0; i < ICL_LOGSPERSET; i++) {
3061                     logp = setp->logs[i];
3062                     if (logp) {
3063                         afs_icl_LogHold(logp);
3064                         afs_icl_LogFreeUse(logp);
3065                         afs_icl_LogRele(logp);
3066                     }
3067                 }
3068                 setp->states |= ICL_SETF_FREED;
3069             }
3070             code = 0;
3071         }
3072         break;
3073
3074     default:
3075         code = EINVAL;
3076     }
3077     ReleaseWriteLock(&setp->lock);
3078     return code;
3079 }