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