openbsd-20021016
[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_FBSD_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_FBSD_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_FBSD_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_FBSD_ENV)
1136 afs3_syscall(p, args, retval)
1137         struct proc *p;
1138         void *args;
1139         int *retval;
1140 {
1141     register struct a {
1142             long syscall;
1143             long parm1;
1144             long parm2;
1145             long parm3;
1146             long parm4;
1147             long parm5;
1148             long parm6;
1149         } *uap = (struct a *)args;
1150 #else   /* AFS_OSF_ENV */
1151 #ifdef AFS_LINUX20_ENV
1152 struct afssysargs {
1153     long syscall;
1154     long parm1;
1155     long parm2;
1156     long parm3;
1157     long parm4;
1158     long parm5;
1159     long parm6; /* not actually used - should be removed */
1160 };
1161 /* Linux system calls only set up for 5 arguments. */
1162 asmlinkage int afs_syscall(long syscall, long parm1, long parm2, long parm3,
1163                            long parm4)
1164 {
1165     struct afssysargs args, *uap = &args;
1166     long linux_ret=0;
1167     long *retval = &linux_ret;
1168     long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */
1169 #ifdef AFS_SPARC64_LINUX24_ENV
1170     afs_int32 eparm32[4];
1171 #endif
1172     /* eparm is also used by AFSCALL_CALL in afsd.c */
1173 #else
1174 #if defined(UKERNEL)
1175 Afs_syscall ()
1176 {
1177     register struct a {
1178             long syscall;
1179             long parm1;
1180             long parm2;
1181             long parm3;
1182             long parm4;
1183             long parm5;
1184             long parm6;
1185         } *uap = (struct a *)u.u_ap;
1186 #else /* UKERNEL */
1187 int
1188 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
1189 afs_syscall ()
1190 #else
1191 Afs_syscall ()
1192 #endif /* SUN && !SUN5 */
1193 {
1194     register struct a {
1195             long syscall;
1196             long parm1;
1197             long parm2;
1198             long parm3;
1199             long parm4;
1200             long parm5;
1201             long parm6;
1202         } *uap = (struct a *)u.u_ap;
1203 #endif /* UKERNEL */
1204 #if  defined(AFS_DEC_ENV)
1205     int *retval = &u.u_r.r_val1;
1206 #else
1207 #if defined(AFS_HPUX_ENV)
1208     long *retval = &u.u_rval1;
1209 #else
1210     int *retval = &u.u_rval1;
1211 #endif
1212 #endif
1213 #endif /* AFS_LINUX20_ENV */
1214 #endif /* AFS_OSF_ENV */
1215 #endif /* AFS_SUN5_ENV */
1216     register int code = 0;
1217
1218     AFS_STATCNT(afs_syscall);
1219 #ifdef        AFS_SUN5_ENV
1220     rvp->r_vals = 0;
1221     if (!afs_sinited) {
1222         return (ENODEV);
1223     }
1224 #endif
1225 #ifdef AFS_LINUX20_ENV
1226     lock_kernel();
1227     /* setup uap for use below - pull out the magic decoder ring to know
1228      * which syscalls have folded argument lists.
1229      */
1230     uap->syscall = syscall;
1231     uap->parm1 = parm1;
1232     uap->parm2 = parm2;
1233     uap->parm3 = parm3;
1234     if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
1235 #ifdef AFS_SPARC64_LINUX24_ENV
1236 /* from arch/sparc64/kernel/sys_sparc32.c */
1237 #define AA(__x)                                \
1238 ({     unsigned long __ret;            \
1239        __asm__ ("srl   %0, 0, %0"      \
1240                 : "=r" (__ret)         \
1241                 : "0" (__x));          \
1242        __ret;                          \
1243 })
1244
1245
1246         if (current->thread.flags & SPARC_FLAG_32BIT) {
1247         AFS_COPYIN((char*)parm4, (char*)eparm32, sizeof(eparm32), code);
1248         eparm[0]=AA(eparm32[0]);
1249         eparm[1]=AA(eparm32[1]);
1250         eparm[2]=AA(eparm32[2]);
1251 #undef AA
1252 } else
1253 #endif
1254         AFS_COPYIN((char*)parm4, (char*)eparm, sizeof(eparm), code);
1255         uap->parm4 = eparm[0];
1256         uap->parm5 = eparm[1];
1257         uap->parm6 = eparm[2];
1258     }
1259     else {
1260         uap->parm4 = parm4;
1261         uap->parm5 = 0;
1262         uap->parm6 = 0;
1263     }
1264 #endif
1265
1266 #if defined(AFS_HPUX_ENV)
1267     /*
1268      * There used to be code here (duplicated from osi_Init()) for
1269      * initializing the semaphore used by AFS_GLOCK().  Was the
1270      * duplication to handle the case of a dynamically loaded kernel
1271      * module?
1272      */
1273     osi_InitGlock();
1274 #endif
1275     if (uap->syscall == AFSCALL_CALL) {
1276 #ifdef  AFS_SUN5_ENV
1277         code =  afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, 
1278                                 uap->parm4, uap->parm5, uap->parm6, rvp, CRED());
1279 #else
1280         code = afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4, uap->parm5, uap->parm6);
1281 #endif
1282     } else if (uap->syscall == AFSCALL_SETPAG) {
1283 #ifdef  AFS_SUN5_ENV
1284         register proc_t *procp;
1285
1286         procp = ttoproc(curthread);
1287         AFS_GLOCK();
1288         code =  afs_setpag(&procp->p_cred);
1289         AFS_GUNLOCK();
1290 #else
1291         AFS_GLOCK();
1292 #if     defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1293         code = afs_setpag(p, args, retval);
1294 #else   /* AFS_OSF_ENV */
1295         code = afs_setpag();
1296 #endif
1297         AFS_GUNLOCK();
1298 #endif
1299     } else if (uap->syscall == AFSCALL_PIOCTL) {
1300         AFS_GLOCK();
1301 #ifdef  AFS_SUN5_ENV
1302         code = afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4, rvp, CRED());
1303 #else
1304 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1305         code = afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4, p->p_cred->pc_ucred);
1306 #else
1307         code = afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4);
1308 #endif
1309 #endif
1310         AFS_GUNLOCK();
1311     } else if (uap->syscall == AFSCALL_ICREATE) {
1312         struct iparam iparams;
1313
1314         code = copyin_iparam((char *)uap->parm3, &iparams);
1315         if (code) {
1316 #if defined(KERNEL_HAVE_UERROR)
1317             setuerror(code);
1318 #endif
1319         } else
1320 #ifdef  AFS_SUN5_ENV
1321         code =  afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1, iparams.param2, 
1322                                    iparams.param3, iparams.param4, rvp, CRED());
1323 #else
1324         code =  afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1, iparams.param2,
1325 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1326                                    iparams.param3, iparams.param4, retval);
1327 #else
1328                                    iparams.param3, iparams.param4);
1329 #endif
1330 #endif  /* AFS_SUN5_ENV */
1331     } else if (uap->syscall == AFSCALL_IOPEN) {
1332 #ifdef  AFS_SUN5_ENV
1333         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp, CRED());
1334 #else
1335 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1336         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, retval);
1337 #else
1338         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3);
1339 #endif
1340 #endif  /* AFS_SUN5_ENV */
1341     } else if (uap->syscall == AFSCALL_IDEC) {
1342 #ifdef  AFS_SUN5_ENV
1343         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1, rvp, CRED());
1344 #else
1345         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1);
1346 #endif  /* AFS_SUN5_ENV */
1347     } else if (uap->syscall == AFSCALL_IINC) {
1348 #ifdef  AFS_SUN5_ENV
1349         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1, rvp, CRED());
1350 #else
1351         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1);
1352 #endif  /* AFS_SUN5_ENV */
1353     } else if (uap->syscall == AFSCALL_ICL) {
1354         AFS_GLOCK();
1355         code = Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4, uap->parm5, retval);
1356         AFS_GUNLOCK();
1357 #ifdef AFS_LINUX20_ENV
1358         if (!code) {
1359             /* ICL commands can return values. */
1360             code = -linux_ret; /* Gets negated again at exit below */
1361         }
1362 #else
1363         if (code) {
1364 #if defined(KERNEL_HAVE_UERROR)
1365             setuerror(code);
1366 #endif
1367         }
1368 #endif /* !AFS_LINUX20_ENV */
1369     } else {
1370 #if defined(KERNEL_HAVE_UERROR)
1371         setuerror(EINVAL);
1372 #else
1373         code = EINVAL;
1374 #endif
1375     }
1376
1377 #ifdef AFS_LINUX20_ENV
1378     code = -code;
1379     unlock_kernel();
1380 #endif
1381     return code;
1382 }
1383 #endif /* AFS_SGI_ENV */
1384 #endif  /* !AFS_AIX32_ENV       */
1385
1386 /*
1387  * Initstate in the range 0 < x < 100 are early initialization states.
1388  * Initstate of 100 means a AFSOP_START operation has been done.  After this,
1389  *  the cache may be initialized.
1390  * Initstate of 101 means a AFSOP_GO operation has been done.  This operation
1391  *  is done after all the cache initialization has been done.
1392  * Initstate of 200 means that the volume has been looked up once, possibly
1393  *  incorrectly.
1394  * Initstate of 300 means that the volume has been *successfully* looked up.
1395  */
1396 int afs_CheckInit(void)
1397 {
1398     register int code = 0;
1399
1400     AFS_STATCNT(afs_CheckInit);
1401     if (afs_initState <= 100)
1402         code =  ENXIO;   /* never finished init phase */
1403     else if (afs_initState == 101) {    /* init done, wait for afs_daemon */
1404         while (afs_initState < 200) afs_osi_Sleep(&afs_initState);
1405     } else  if (afs_initState == 200) 
1406         code =  ETIMEDOUT; /* didn't find root volume */
1407     return code;
1408 }
1409
1410 int afs_shuttingdown = 0; 
1411 void afs_shutdown(void)
1412 {
1413     extern short afs_brsDaemons;
1414     extern afs_int32 afs_CheckServerDaemonStarted;
1415     extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
1416     extern struct osi_file *afs_cacheInodep;
1417
1418     AFS_STATCNT(afs_shutdown);
1419     if (afs_shuttingdown) return;
1420     afs_shuttingdown = 1;
1421     if (afs_cold_shutdown) afs_warn("COLD ");
1422     else afs_warn("WARM ");
1423     afs_warn("shutting down of: CB... "); 
1424
1425     afs_termState = AFSOP_STOP_RXCALLBACK;
1426     rx_WakeupServerProcs();
1427     /* shutdown_rxkernel(); */
1428     while (afs_termState == AFSOP_STOP_RXCALLBACK)
1429         afs_osi_Sleep(&afs_termState);
1430
1431     afs_warn("afs... ");
1432     while (afs_termState == AFSOP_STOP_AFS) {
1433         afs_osi_CancelWait(&AFS_WaitHandler);
1434         afs_osi_Sleep(&afs_termState);
1435     }
1436     if (afs_CheckServerDaemonStarted) {
1437         while (afs_termState == AFSOP_STOP_CS) {
1438             afs_osi_CancelWait(&AFS_CSWaitHandler);
1439             afs_osi_Sleep(&afs_termState);
1440         }
1441     }
1442     afs_warn("BkG... ");
1443     /* Wake-up afs_brsDaemons so that we don't have to wait for a bkg job! */
1444     while (afs_termState == AFSOP_STOP_BKG) {
1445         afs_osi_Wakeup(&afs_brsDaemons);
1446         afs_osi_Sleep(&afs_termState);
1447     }
1448     afs_warn("CTrunc... ");
1449     /* Cancel cache truncate daemon. */
1450     while (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
1451         afs_osi_Wakeup((char*)&afs_CacheTruncateDaemon);
1452         afs_osi_Sleep(&afs_termState);
1453     }
1454 #ifdef AFS_AFSDB_ENV
1455     afs_warn("AFSDB... ");
1456     afs_StopAFSDB();
1457     while (afs_termState == AFSOP_STOP_AFSDB)
1458         afs_osi_Sleep(&afs_termState);
1459 #endif
1460 #if     defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
1461     afs_warn("RxEvent... ");
1462     /* cancel rx event deamon */
1463     while (afs_termState == AFSOP_STOP_RXEVENT) 
1464         afs_osi_Sleep(&afs_termState);
1465 #if defined(RXK_LISTENER_ENV)
1466 #ifndef UKERNEL
1467     afs_warn("UnmaskRxkSignals... ");
1468     afs_osi_UnmaskRxkSignals();
1469 #endif
1470     /* cancel rx listener */
1471     afs_warn("RxListener... ");
1472     osi_StopListener(); /* This closes rx_socket. */
1473     while (afs_termState == AFSOP_STOP_RXK_LISTENER) {
1474         afs_warn("Sleep... ");
1475         afs_osi_Sleep(&afs_termState);
1476     }
1477 #endif
1478 #else
1479     afs_termState =  AFSOP_STOP_COMPLETE;
1480 #endif
1481     afs_warn("\n");
1482
1483     /* Close file only after daemons which can write to it are stopped. */
1484     if (afs_cacheInodep)        /* memcache won't set this */
1485     {
1486         osi_UFSClose(afs_cacheInodep);    /* Since we always leave it open */
1487         afs_cacheInodep = 0;
1488     }
1489     return;     /* Just kill daemons for now */
1490 #ifdef notdef
1491     shutdown_CB();  
1492     shutdown_AFS();
1493     shutdown_rxkernel();
1494     shutdown_rxevent(); 
1495     shutdown_rx();
1496     afs_shutdown_BKG(); 
1497     shutdown_bufferpackage();
1498     shutdown_daemons();
1499     shutdown_cache();
1500     shutdown_osi();
1501     shutdown_osinet();
1502     shutdown_osifile();
1503     shutdown_vnodeops();
1504     shutdown_vfsops();
1505     shutdown_exporter();
1506     shutdown_memcache();
1507 #if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
1508 #if !defined(AFS_DEC_ENV) && !defined(AFS_OSF_ENV)
1509     /* this routine does not exist in Ultrix systems... 93.01.19 */
1510     shutdown_nfsclnt();
1511 #endif /* AFS_DEC_ENV */
1512 #endif
1513     shutdown_afstest();
1514     /* The following hold the cm stats */
1515 /*
1516     memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));
1517     memset(&afs_stats_cmperf, 0, sizeof(struct afs_stats_CMPerf));
1518     memset(&afs_stats_cmfullperf, 0, sizeof(struct afs_stats_CMFullPerf));
1519 */
1520     afs_warn(" ALL allocated tables\n");
1521     afs_shuttingdown = 0;
1522 #endif
1523 }
1524
1525 void shutdown_afstest(void)
1526 {
1527     AFS_STATCNT(shutdown_afstest);
1528     afs_initState = afs_termState = afs_setTime = 0;
1529     AFS_Running = afs_CB_Running = 0;
1530     afs_CacheInit_Done = afs_Go_Done = 0;
1531     if (afs_cold_shutdown) {
1532       *afs_rootVolumeName = 0;
1533     }
1534 }
1535
1536
1537 /* In case there is a bunch of dynamically build bkg daemons to free */
1538 void afs_shutdown_BKG(void)
1539 {
1540   AFS_STATCNT(shutdown_BKG);
1541 }
1542
1543
1544 #if defined(AFS_ALPHA_ENV) || defined(AFS_SGI61_ENV)
1545 /* For SGI 6.2, this can is changed to 1 if it's a 32 bit kernel. */
1546 #if defined(AFS_SGI62_ENV) && defined(KERNEL) && !defined(_K64U64)
1547 int afs_icl_sizeofLong = 1;
1548 #else
1549 int afs_icl_sizeofLong = 2;
1550 #endif /* SGI62 */
1551 #else
1552 int afs_icl_sizeofLong = 1;
1553 #endif
1554
1555 int afs_icl_inited = 0;
1556
1557 /* init function, called once, under afs_icl_lock */
1558 int afs_icl_Init(void)
1559 {
1560     afs_icl_inited = 1;
1561     return 0;
1562 }
1563
1564 extern struct afs_icl_log *afs_icl_FindLog();
1565 extern struct afs_icl_set *afs_icl_FindSet();
1566
1567
1568 static int
1569 Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval)
1570 {
1571     afs_int32 *lp, elts, flags;
1572     register afs_int32 code;
1573     struct afs_icl_log *logp;
1574     struct afs_icl_set *setp;
1575 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1576     size_t temp;
1577 #else /* AFS_SGI61_ENV */
1578     afs_uint32 temp;
1579 #endif /* AFS_SGI61_ENV */
1580     char tname[65];
1581     afs_int32 startCookie;
1582     afs_int32 allocated;
1583     struct afs_icl_log *tlp;
1584
1585 #ifdef  AFS_SUN5_ENV
1586     if (!afs_suser(CRED())) {   /* only root can run this code */
1587         return (EACCES);
1588     }
1589 #else
1590     if (!afs_suser()) { /* only root can run this code */
1591 #if defined(KERNEL_HAVE_UERROR)
1592         setuerror(EACCES);
1593         return EACCES;
1594 #else
1595         return EPERM;
1596 #endif
1597     }
1598 #endif
1599     switch (opcode) {
1600     case ICL_OP_COPYOUTCLR:     /* copy out data then clear */
1601     case ICL_OP_COPYOUT:        /* copy ouy data */
1602         /* copyout: p1=logname, p2=&buffer, p3=size(words), p4=&cookie
1603          * return flags<<24 + nwords.
1604          * updates cookie to updated start (not end) if we had to
1605          * skip some records.
1606          */
1607         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1608         if (code) return code;
1609         AFS_COPYIN((char *)p4, (char *)&startCookie, sizeof(afs_int32), code);
1610         if (code) return code;
1611         logp = afs_icl_FindLog(tname);
1612         if (!logp) return ENOENT;
1613 #define BUFFERSIZE      AFS_LRALLOCSIZ
1614         lp = (afs_int32 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1615         elts = BUFFERSIZE / sizeof(afs_int32);
1616         if (p3 < elts) elts = p3;
1617         flags = (opcode == ICL_OP_COPYOUT) ? 0 : ICL_COPYOUTF_CLRAFTERREAD;
1618         code = afs_icl_CopyOut(logp, lp, &elts, (afs_uint32 *) &startCookie,
1619                            &flags);
1620         if (code) {
1621             osi_FreeLargeSpace((struct osi_buffer *) lp);
1622             break;
1623         }
1624         AFS_COPYOUT((char *)lp, (char *)p2, elts * sizeof(afs_int32), code);
1625         if (code) goto done;
1626         AFS_COPYOUT((char *) &startCookie, (char *)p4, sizeof(afs_int32), code);
1627         if (code) goto done;
1628         *retval = (flags<<24) | (elts & 0xffffff);
1629       done:
1630         afs_icl_LogRele(logp);
1631         osi_FreeLargeSpace((struct osi_buffer *) lp);
1632         break;
1633
1634     case ICL_OP_ENUMLOGS:       /* enumerate logs */
1635         /* enumerate logs: p1=index, p2=&name, p3=sizeof(name), p4=&size.
1636          * return 0 for success, otherwise error.
1637          */
1638         for(tlp = afs_icl_allLogs; tlp; tlp=tlp->nextp) {
1639             if (p1-- == 0) break;
1640         }
1641         if (!tlp) return ENOENT;     /* past the end of file */
1642         temp = strlen(tlp->name)+1;
1643         if (temp > p3) return EINVAL;
1644         AFS_COPYOUT(tlp->name, (char *) p2, temp, code);
1645         if (!code)      /* copy out size of log */
1646             AFS_COPYOUT((char *)&tlp->logSize, (char *)p4, sizeof (afs_int32), code);
1647         break;
1648
1649     case ICL_OP_ENUMLOGSBYSET:  /* enumerate logs by set name */
1650         /* enumerate logs: p1=setname, p2=index, p3=&name, p4=sizeof(name).
1651          * return 0 for success, otherwise error.
1652          */
1653         AFS_COPYINSTR((char *)p1, tname, sizeof (tname), &temp, code);
1654         if (code) return code;
1655         setp = afs_icl_FindSet(tname);
1656         if (!setp) return ENOENT;
1657         if (p2 > ICL_LOGSPERSET)
1658             return EINVAL;
1659         if (!(tlp = setp->logs[p2]))
1660             return EBADF;
1661         temp = strlen(tlp->name)+1;
1662         if (temp > p4) return EINVAL;
1663         AFS_COPYOUT(tlp->name, (char *)p3, temp, code);
1664         break;
1665
1666     case ICL_OP_CLRLOG:         /* clear specified log */
1667         /* zero out the specified log: p1=logname */
1668         AFS_COPYINSTR((char *)p1, tname, sizeof (tname), &temp, code);
1669         if (code) return code;
1670         logp = afs_icl_FindLog(tname);
1671         if (!logp) return ENOENT;
1672         code = afs_icl_ZeroLog(logp);
1673         afs_icl_LogRele(logp);
1674         break;
1675
1676     case ICL_OP_CLRSET:         /* clear specified set */
1677         /* zero out the specified set: p1=setname */
1678         AFS_COPYINSTR((char *)p1, tname, sizeof (tname), &temp, code);
1679         if (code) return code;
1680         setp = afs_icl_FindSet(tname);
1681         if (!setp) return ENOENT;
1682         code = afs_icl_ZeroSet(setp);
1683         afs_icl_SetRele(setp);
1684         break;
1685
1686     case ICL_OP_CLRALL:         /* clear all logs */
1687         /* zero out all logs -- no args */
1688         code = 0;
1689         ObtainWriteLock(&afs_icl_lock,178);
1690         for(tlp = afs_icl_allLogs; tlp; tlp=tlp->nextp) {
1691             tlp->refCount++;    /* hold this guy */
1692             ReleaseWriteLock(&afs_icl_lock);
1693             /* don't clear persistent logs */
1694             if ((tlp->states & ICL_LOGF_PERSISTENT) == 0)
1695                 code = afs_icl_ZeroLog(tlp);
1696             ObtainWriteLock(&afs_icl_lock,179);
1697             if (--tlp->refCount == 0)
1698                 afs_icl_ZapLog(tlp);
1699             if (code) break;
1700         }
1701         ReleaseWriteLock(&afs_icl_lock);
1702         break;
1703
1704     case ICL_OP_ENUMSETS:       /* enumerate all sets */
1705         /* enumerate sets: p1=index, p2=&name, p3=sizeof(name), p4=&states.
1706          * return 0 for success, otherwise error.
1707          */
1708         for(setp = afs_icl_allSets; setp; setp = setp->nextp) {
1709             if (p1-- == 0) break;
1710         }
1711         if (!setp) return ENOENT;       /* past the end of file */
1712         temp = strlen(setp->name)+1;
1713         if (temp > p3) return EINVAL;
1714         AFS_COPYOUT(setp->name, (char *)p2, temp, code);
1715         if (!code)      /* copy out size of log */
1716             AFS_COPYOUT((char *)&setp->states,(char *)p4, sizeof (afs_int32), code);
1717         break;
1718
1719     case ICL_OP_SETSTAT:        /* set status on a set */
1720         /* activate the specified set: p1=setname, p2=op */
1721         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1722         if (code) return code;
1723         setp = afs_icl_FindSet(tname);
1724         if (!setp) return ENOENT;
1725         code = afs_icl_SetSetStat(setp, p2);
1726         afs_icl_SetRele(setp);
1727         break;
1728
1729     case ICL_OP_SETSTATALL:     /* set status on all sets */
1730         /* activate the specified set: p1=op */
1731         code = 0;
1732         ObtainWriteLock(&afs_icl_lock,180);
1733         for(setp = afs_icl_allSets; setp; setp=setp->nextp) {
1734             setp->refCount++;   /* hold this guy */
1735             ReleaseWriteLock(&afs_icl_lock);
1736             /* don't set states on persistent sets */
1737             if ((setp->states & ICL_SETF_PERSISTENT) == 0)
1738                 code = afs_icl_SetSetStat(setp, p1);
1739             ObtainWriteLock(&afs_icl_lock,181);
1740             if (--setp->refCount == 0)
1741                 afs_icl_ZapSet(setp);
1742             if (code) break;
1743         }
1744         ReleaseWriteLock(&afs_icl_lock);
1745         break;
1746
1747     case ICL_OP_SETLOGSIZE:             /* set size of log */
1748         /* set the size of the specified log: p1=logname, p2=size (in words) */
1749         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1750         if (code) return code;
1751         logp = afs_icl_FindLog(tname);
1752         if (!logp) return ENOENT;
1753         code = afs_icl_LogSetSize(logp, p2);
1754         afs_icl_LogRele(logp);
1755         break;
1756
1757     case ICL_OP_GETLOGINFO:             /* get size of log */
1758         /* zero out the specified log: p1=logname, p2=&logSize, p3=&allocated */
1759         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1760         if (code) return code;
1761         logp = afs_icl_FindLog(tname);
1762         if (!logp) return ENOENT;
1763         allocated = !!logp->datap;
1764         AFS_COPYOUT((char *)&logp->logSize, (char *) p2, sizeof(afs_int32), code);
1765         if (!code)
1766             AFS_COPYOUT((char *)&allocated, (char *) p3, sizeof(afs_int32), code);
1767         afs_icl_LogRele(logp);
1768         break;
1769
1770     case ICL_OP_GETSETINFO:             /* get state of set */
1771         /* zero out the specified set: p1=setname, p2=&state */
1772         AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
1773         if (code) return code;
1774         setp = afs_icl_FindSet(tname);
1775         if (!setp) return ENOENT;
1776         AFS_COPYOUT((char *)&setp->states, (char *) p2, sizeof(afs_int32), code);
1777         afs_icl_SetRele(setp);
1778         break;
1779
1780     default:
1781         code = EINVAL;
1782     }
1783
1784     return code;
1785 }
1786
1787
1788 afs_lock_t afs_icl_lock;
1789
1790 /* exported routine: a 4 parameter event */
1791 int afs_icl_Event4(register struct afs_icl_set *setp, afs_int32 eventID, 
1792         afs_int32 lAndT, long p1, long p2, long p3, long p4)
1793 {
1794     afs_int32 mask;
1795     register int i;
1796     register afs_int32 tmask;
1797     int ix;
1798
1799     /* If things aren't init'ed yet (or the set is inactive), don't panic */
1800     if (!ICL_SETACTIVE(setp))
1801         return 0;
1802
1803     AFS_ASSERT_GLOCK();
1804     mask = lAndT>>24 & 0xff;    /* mask of which logs to log to */
1805     ix = ICL_EVENTBYTE(eventID);
1806     ObtainReadLock(&setp->lock);
1807     if (setp->eventFlags[ix] & ICL_EVENTMASK(eventID)) {
1808         for(i=0, tmask = 1; i<ICL_LOGSPERSET; i++, tmask <<= 1) {
1809             if (mask & tmask) {
1810                 afs_icl_AppendRecord(setp->logs[i], eventID, lAndT & 0xffffff,
1811                               p1, p2, p3, p4);
1812             }
1813             mask &= ~tmask;
1814             if (mask == 0) break;       /* break early */
1815         }
1816     }
1817     ReleaseReadLock(&setp->lock);
1818     return 0;
1819 }
1820
1821 /* Next 4 routines should be implemented via var-args or something.
1822  * Whole purpose is to avoid compiler warnings about parameter # mismatches.
1823  * Otherwise, could call afs_icl_Event4 directly.
1824  */
1825 int afs_icl_Event3(register struct afs_icl_set *setp, afs_int32 eventID, 
1826         afs_int32 lAndT, long p1, long p2, long p3)
1827 {
1828     return afs_icl_Event4(setp, eventID, lAndT, p1, p2, p3, (long)0);
1829 }
1830
1831 int afs_icl_Event2(register struct afs_icl_set *setp, afs_int32 eventID, 
1832         afs_int32 lAndT, long p1, long p2)
1833 {
1834     return afs_icl_Event4(setp, eventID, lAndT, p1, p2, (long)0, (long)0);
1835 }
1836
1837 int afs_icl_Event1(register struct afs_icl_set *setp, afs_int32 eventID, 
1838         afs_int32 lAndT, long p1)
1839 {
1840     return afs_icl_Event4(setp, eventID, lAndT, p1, (long)0, (long)0, (long)0);
1841 }
1842
1843 int afs_icl_Event0(register struct afs_icl_set *setp, afs_int32 eventID, 
1844         afs_int32 lAndT)
1845 {
1846     return afs_icl_Event4(setp, eventID, lAndT, (long)0, (long)0, (long)0, (long)0);
1847 }
1848
1849 struct afs_icl_log *afs_icl_allLogs = 0;
1850
1851 /* function to purge records from the start of the log, until there
1852  * is at least minSpace long's worth of space available without
1853  * making the head and the tail point to the same word.
1854  *
1855  * Log must be write-locked.
1856  */
1857 static void afs_icl_GetLogSpace(register struct afs_icl_log *logp, afs_int32 minSpace)
1858 {
1859     register unsigned int tsize;
1860
1861     while (logp->logSize - logp->logElements <= minSpace) {
1862         /* eat a record */
1863         tsize = ((logp->datap[logp->firstUsed]) >> 24) & 0xff;
1864         logp->logElements -= tsize;
1865         logp->firstUsed += tsize;
1866         if (logp->firstUsed >= logp->logSize)
1867             logp->firstUsed -= logp->logSize;
1868         logp->baseCookie += tsize;
1869     }
1870 }
1871
1872 /* append string astr to buffer, including terminating null char.
1873  *
1874  * log must be write-locked.
1875  */
1876 #define ICL_CHARSPERLONG        4
1877 static void afs_icl_AppendString(struct afs_icl_log *logp, char *astr)
1878 {
1879     char *op;           /* ptr to char to write */
1880     int tc;
1881     register int bib;   /* bytes in buffer */
1882
1883     bib = 0;
1884     op = (char *) &(logp->datap[logp->firstFree]);
1885     while (1) {
1886         tc = *astr++;
1887         *op++ = tc;
1888         if (++bib >= ICL_CHARSPERLONG) {
1889             /* new word */
1890             bib = 0;
1891             if (++(logp->firstFree) >= logp->logSize) {
1892                 logp->firstFree = 0;
1893                 op = (char *) &(logp->datap[0]);
1894             }
1895             logp->logElements++;
1896         }
1897         if (tc == 0) break;
1898     }
1899     if (bib > 0) {
1900         /* if we've used this word at all, allocate it */
1901         if (++(logp->firstFree) >= logp->logSize) {
1902             logp->firstFree = 0;
1903         }
1904         logp->logElements++;
1905     }
1906 }
1907
1908 /* add a long to the log, ignoring overflow (checked already) */
1909 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64))
1910 #define ICL_APPENDINT32(lp, x) \
1911     MACRO_BEGIN \
1912         (lp)->datap[(lp)->firstFree] = (x); \
1913         if (++((lp)->firstFree) >= (lp)->logSize) { \
1914                 (lp)->firstFree = 0; \
1915         } \
1916         (lp)->logElements++; \
1917     MACRO_END
1918
1919 #define ICL_APPENDLONG(lp, x) \
1920     MACRO_BEGIN \
1921         ICL_APPENDINT32((lp), ((x) >> 32) & 0xffffffffL); \
1922         ICL_APPENDINT32((lp), (x) & 0xffffffffL); \
1923     MACRO_END
1924
1925 #else /* AFS_ALPHA_ENV */
1926 #define ICL_APPENDLONG(lp, x) \
1927     MACRO_BEGIN \
1928         (lp)->datap[(lp)->firstFree] = (x); \
1929         if (++((lp)->firstFree) >= (lp)->logSize) { \
1930                 (lp)->firstFree = 0; \
1931         } \
1932         (lp)->logElements++; \
1933     MACRO_END
1934 #define ICL_APPENDINT32(lp, x) ICL_APPENDLONG((lp), (x))
1935 #endif /* AFS_ALPHA_ENV */
1936
1937 /* routine to tell whether we're dealing with the address or the
1938  * object itself
1939  */
1940 int afs_icl_UseAddr(int type)
1941 {
1942     if (type == ICL_TYPE_HYPER || type == ICL_TYPE_STRING
1943         || type == ICL_TYPE_FID || type == ICL_TYPE_INT64)
1944         return 1;
1945     else
1946         return 0;
1947 }
1948
1949 /* Function to append a record to the log.  Written for speed
1950  * since we know that we're going to have to make this work fast
1951  * pretty soon, anyway.  The log must be unlocked.
1952  */
1953
1954 void afs_icl_AppendRecord(register struct afs_icl_log *logp, afs_int32 op, 
1955         afs_int32 types, long p1, long p2, long p3, long p4)
1956 {
1957     int rsize;                  /* record size in longs */
1958     register int tsize;         /* temp size */
1959     osi_timeval_t tv;
1960     int t1, t2, t3, t4;
1961
1962     t4 = types & 0x3f;          /* decode types */
1963     types >>= 6;
1964     t3 = types & 0x3f;
1965     types >>= 6;
1966     t2 = types & 0x3f;
1967     types >>= 6;
1968     t1 = types & 0x3f;
1969
1970     osi_GetTime(&tv);           /* It panics for solaris if inside */
1971     ObtainWriteLock(&logp->lock,182);
1972     if (!logp->datap) {
1973         ReleaseWriteLock(&logp->lock);
1974         return;
1975     }
1976
1977     /* get timestamp as # of microseconds since some time that doesn't
1978      * change that often.  This algorithm ticks over every 20 minutes
1979      * or so (1000 seconds).  Write a timestamp record if it has.
1980      */
1981     if (tv.tv_sec - logp->lastTS > 1024)
1982     {
1983         /* the timer has wrapped -- write a timestamp record */
1984         if (logp->logSize - logp->logElements <= 5)
1985             afs_icl_GetLogSpace(logp, 5);
1986
1987         ICL_APPENDINT32(logp, (afs_int32)(5<<24) + (ICL_TYPE_UNIXDATE<<18));
1988         ICL_APPENDINT32(logp, (afs_int32)ICL_INFO_TIMESTAMP);
1989         ICL_APPENDINT32(logp, (afs_int32)0); /* use thread ID zero for clocks */
1990         ICL_APPENDINT32(logp,
1991                         (afs_int32)(tv.tv_sec & 0x3ff) * 1000000 + tv.tv_usec);
1992         ICL_APPENDINT32(logp, (afs_int32)tv.tv_sec);
1993
1994         logp->lastTS = tv.tv_sec;
1995     }
1996
1997     rsize = 4;                          /* base case */
1998     if (t1) {
1999         /* compute size of parameter p1.  Only tricky case is string.
2000          * In that case, we have to call strlen to get the string length.
2001          */
2002         ICL_SIZEHACK(t1, p1);
2003     }
2004     if (t2) {
2005         /* compute size of parameter p2.  Only tricky case is string.
2006          * In that case, we have to call strlen to get the string length.
2007          */
2008         ICL_SIZEHACK(t2, p2);
2009     }
2010     if (t3) {
2011         /* compute size of parameter p3.  Only tricky case is string.
2012          * In that case, we have to call strlen to get the string length.
2013          */
2014         ICL_SIZEHACK(t3, p3);
2015     }
2016     if (t4) {
2017         /* compute size of parameter p4.  Only tricky case is string.
2018          * In that case, we have to call strlen to get the string length.
2019          */
2020         ICL_SIZEHACK(t4, p4);
2021     }
2022
2023     /* At this point, we've computed all of the parameter sizes, and
2024      * have in rsize the size of the entire record we want to append.
2025      * Next, we check that we actually have room in the log to do this
2026      * work, and then we do the append.
2027      */
2028     if (rsize > 255) {
2029         ReleaseWriteLock(&logp->lock);
2030         return;         /* log record too big to express */
2031     }
2032
2033     if (logp->logSize - logp->logElements <= rsize)
2034         afs_icl_GetLogSpace(logp, rsize);
2035
2036     ICL_APPENDINT32(logp,
2037                     (afs_int32)(rsize<<24) + (t1<<18) + (t2<<12) + (t3<<6) + t4);
2038     ICL_APPENDINT32(logp, (afs_int32)op);
2039     ICL_APPENDINT32(logp, (afs_int32)osi_ThreadUnique());
2040     ICL_APPENDINT32(logp, (afs_int32)(tv.tv_sec & 0x3ff) * 1000000 + tv.tv_usec);
2041
2042     if (t1) {
2043         /* marshall parameter 1 now */
2044         if (t1 == ICL_TYPE_STRING) {
2045             afs_icl_AppendString(logp, (char *) p1);
2046         }
2047         else if (t1 == ICL_TYPE_HYPER) {
2048             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p1)->high);
2049             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p1)->low);
2050         }
2051         else if (t1 == ICL_TYPE_INT64) {
2052 #ifdef AFSLITTLE_ENDIAN
2053 #ifdef AFS_64BIT_CLIENT
2054             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[1]);
2055             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[0]);
2056 #else /* AFS_64BIT_CLIENT */
2057             ICL_APPENDINT32(logp, (afs_int32) p1);
2058             ICL_APPENDINT32(logp, (afs_int32) 0);
2059 #endif /* AFS_64BIT_CLIENT */
2060 #else /* AFSLITTLE_ENDIAN */
2061 #ifdef AFS_64BIT_CLIENT
2062             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[0]);
2063             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[1]);
2064 #else /* AFS_64BIT_CLIENT */
2065             ICL_APPENDINT32(logp, (afs_int32) 0);
2066             ICL_APPENDINT32(logp, (afs_int32) p1);
2067 #endif /* AFS_64BIT_CLIENT */
2068 #endif /* AFSLITTLE_ENDIAN */
2069         }
2070         else if (t1 == ICL_TYPE_FID) {
2071             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[0]);
2072             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[1]);
2073             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[2]);
2074             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p1)[3]);
2075         }
2076 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64))
2077         else if (t1 == ICL_TYPE_INT32)
2078             ICL_APPENDINT32(logp, (afs_int32)p1);
2079 #endif /* AFS_ALPHA_ENV */
2080         else ICL_APPENDLONG(logp, p1); 
2081     }
2082     if (t2) {
2083         /* marshall parameter 2 now */
2084         if (t2 == ICL_TYPE_STRING) afs_icl_AppendString(logp, (char *) p2);
2085         else if (t2 == ICL_TYPE_HYPER) {
2086             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p2)->high);
2087             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p2)->low);
2088         }
2089         else if (t2 == ICL_TYPE_INT64) {
2090 #ifdef AFSLITTLE_ENDIAN
2091 #ifdef AFS_64BIT_CLIENT
2092             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[1]);
2093             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[0]);
2094 #else /* AFS_64BIT_CLIENT */
2095             ICL_APPENDINT32(logp, (afs_int32) p2);
2096             ICL_APPENDINT32(logp, (afs_int32) 0);
2097 #endif /* AFS_64BIT_CLIENT */
2098 #else /* AFSLITTLE_ENDIAN */
2099 #ifdef AFS_64BIT_CLIENT
2100             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[0]);
2101             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[1]);
2102 #else /* AFS_64BIT_CLIENT */
2103             ICL_APPENDINT32(logp, (afs_int32) 0);
2104             ICL_APPENDINT32(logp, (afs_int32) p2);
2105 #endif /* AFS_64BIT_CLIENT */
2106 #endif /* AFSLITTLE_ENDIAN */
2107         }
2108         else if (t2 == ICL_TYPE_FID) {
2109             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[0]);
2110             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[1]);
2111             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[2]);
2112             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p2)[3]);
2113         }
2114 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64))
2115         else if (t2 == ICL_TYPE_INT32)
2116             ICL_APPENDINT32(logp, (afs_int32)p2);
2117 #endif /* AFS_ALPHA_ENV */
2118         else ICL_APPENDLONG(logp, p2);
2119     }
2120     if (t3) {
2121         /* marshall parameter 3 now */
2122         if (t3 == ICL_TYPE_STRING) afs_icl_AppendString(logp, (char *) p3);
2123         else if (t3 == ICL_TYPE_HYPER) {
2124             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p3)->high);
2125             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p3)->low);
2126         }
2127         else if (t3 == ICL_TYPE_INT64) {
2128 #ifdef AFSLITTLE_ENDIAN
2129 #ifdef AFS_64BIT_CLIENT
2130             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[1]);
2131             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[0]);
2132 #else /* AFS_64BIT_CLIENT */
2133             ICL_APPENDINT32(logp, (afs_int32) p3);
2134             ICL_APPENDINT32(logp, (afs_int32) 0);
2135 #endif /* AFS_64BIT_CLIENT */
2136 #else /* AFSLITTLE_ENDIAN */
2137 #ifdef AFS_64BIT_CLIENT
2138             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[0]);
2139             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[1]);
2140 #else /* AFS_64BIT_CLIENT */
2141             ICL_APPENDINT32(logp, (afs_int32) 0);
2142             ICL_APPENDINT32(logp, (afs_int32) p3);
2143 #endif /* AFS_64BIT_CLIENT */
2144 #endif /* AFSLITTLE_ENDIAN */
2145         }
2146         else if (t3 == ICL_TYPE_FID) {
2147             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[0]);
2148             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[1]);
2149             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[2]);
2150             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p3)[3]);
2151         }
2152 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64))
2153         else if (t3 == ICL_TYPE_INT32)
2154             ICL_APPENDINT32(logp, (afs_int32)p3);
2155 #endif /* AFS_ALPHA_ENV */
2156         else ICL_APPENDLONG(logp, p3);
2157     }
2158     if (t4) {
2159         /* marshall parameter 4 now */
2160         if (t4 == ICL_TYPE_STRING) afs_icl_AppendString(logp, (char *) p4);
2161         else if (t4 == ICL_TYPE_HYPER) {
2162             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p4)->high);
2163             ICL_APPENDINT32(logp, (afs_int32)((struct afs_hyper_t *)p4)->low);
2164         }
2165         else if (t4 == ICL_TYPE_INT64) {
2166 #ifdef AFSLITTLE_ENDIAN
2167 #ifdef AFS_64BIT_CLIENT
2168             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[1]);
2169             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[0]);
2170 #else /* AFS_64BIT_CLIENT */
2171             ICL_APPENDINT32(logp, (afs_int32) p4);
2172             ICL_APPENDINT32(logp, (afs_int32) 0);
2173 #endif /* AFS_64BIT_CLIENT */
2174 #else /* AFSLITTLE_ENDIAN */
2175 #ifdef AFS_64BIT_CLIENT
2176             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[0]);
2177             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[1]);
2178 #else /* AFS_64BIT_CLIENT */
2179             ICL_APPENDINT32(logp, (afs_int32) 0);
2180             ICL_APPENDINT32(logp, (afs_int32) p4);
2181 #endif /* AFS_64BIT_CLIENT */
2182 #endif /* AFSLITTLE_ENDIAN */
2183         }
2184         else if (t4 == ICL_TYPE_FID) {
2185             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[0]);
2186             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[1]);
2187             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[2]);
2188             ICL_APPENDINT32(logp, (afs_int32)((afs_int32 *)p4)[3]);
2189         }
2190 #if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64))
2191         else if (t4 == ICL_TYPE_INT32)
2192             ICL_APPENDINT32(logp, (afs_int32)p4);
2193 #endif /* AFS_ALPHA_ENV */
2194         else ICL_APPENDLONG(logp, p4);
2195     }
2196     ReleaseWriteLock(&logp->lock);
2197 }
2198
2199 /* create a log with size logSize; return it in *outLogpp and tag
2200  * it with name "name."
2201  */
2202 int afs_icl_CreateLog(char *name, afs_int32 logSize, struct afs_icl_log **outLogpp)
2203 {
2204     return afs_icl_CreateLogWithFlags(name, logSize, /*flags*/0, outLogpp);
2205 }
2206
2207 /* create a log with size logSize; return it in *outLogpp and tag
2208  * it with name "name."  'flags' can be set to make the log unclearable.
2209  */
2210 int afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize, afs_uint32 flags, 
2211         struct afs_icl_log **outLogpp)
2212 {
2213     register struct afs_icl_log *logp;
2214
2215     /* add into global list under lock */
2216     ObtainWriteLock(&afs_icl_lock,183);
2217     if (!afs_icl_inited) afs_icl_Init();
2218
2219     for (logp = afs_icl_allLogs; logp; logp=logp->nextp) {
2220         if (strcmp(logp->name, name) == 0) {
2221             /* found it already created, just return it */
2222             logp->refCount++;
2223             *outLogpp = logp;
2224             if (flags & ICL_CRLOG_FLAG_PERSISTENT)
2225             {
2226                 ObtainWriteLock(&logp->lock,184);
2227                 logp->states |= ICL_LOGF_PERSISTENT;
2228                 ReleaseWriteLock(&logp->lock);
2229             }
2230             ReleaseWriteLock(&afs_icl_lock);
2231             return 0;
2232         }
2233     }
2234     
2235     logp = (struct afs_icl_log *)
2236         osi_AllocSmallSpace(sizeof(struct afs_icl_log));
2237     memset((caddr_t)logp, 0, sizeof(*logp));
2238
2239     logp->refCount = 1;
2240     logp->name = osi_AllocSmallSpace(strlen(name)+1);
2241     strcpy(logp->name, name);
2242     LOCK_INIT(&logp->lock, "logp lock");
2243     logp->logSize = logSize;
2244     logp->datap = NULL; /* don't allocate it until we need it */
2245
2246     if (flags & ICL_CRLOG_FLAG_PERSISTENT)
2247         logp->states |= ICL_LOGF_PERSISTENT;
2248
2249     logp->nextp = afs_icl_allLogs;
2250     afs_icl_allLogs = logp;
2251     ReleaseWriteLock(&afs_icl_lock);
2252
2253     *outLogpp = logp;
2254     return 0;
2255 }
2256
2257 /* called with a log, a pointer to a buffer, the size of the buffer
2258  * (in *bufSizep), the starting cookie (in *cookiep, use 0 at the start)
2259  * and returns data in the provided buffer, and returns output flags
2260  * in *flagsp.  The flag ICL_COPYOUTF_MISSEDSOME is set if we can't
2261  * find the record with cookie value cookie.
2262  */
2263 int afs_icl_CopyOut(register struct afs_icl_log *logp, afs_int32 *bufferp, 
2264         afs_int32 *bufSizep, afs_uint32 *cookiep, afs_int32 *flagsp)
2265 {
2266     afs_int32 nwords;           /* number of words to copy out */
2267     afs_uint32 startCookie;     /* first cookie to use */
2268     afs_int32 outWords;         /* words we've copied out */
2269     afs_int32 inWords;          /* max words to copy out */
2270     afs_int32 code;                     /* return code */
2271     afs_int32 ix;                       /* index we're copying from */
2272     afs_int32 outFlags;         /* return flags */
2273     afs_int32 inFlags;          /* flags passed in */
2274     afs_int32 end;
2275
2276     inWords = *bufSizep;        /* max to copy out */
2277     outWords = 0;               /* amount copied out */
2278     startCookie = *cookiep;
2279     outFlags = 0;
2280     inFlags = *flagsp;
2281     code = 0;
2282
2283     ObtainWriteLock(&logp->lock,185);
2284     if (!logp->datap) {
2285         ReleaseWriteLock(&logp->lock);
2286         goto done;
2287     }
2288
2289     /* first, compute the index of the start cookie we've been passed */
2290     while (1) {
2291         /* (re-)compute where we should start */
2292         if (startCookie < logp->baseCookie) {
2293             if (startCookie)  /* missed some output */
2294                 outFlags |= ICL_COPYOUTF_MISSEDSOME;
2295             /* skip to the first available record */
2296             startCookie = logp->baseCookie;
2297             *cookiep = startCookie;
2298         }
2299
2300         /* compute where we find the first element to copy out */
2301         ix = logp->firstUsed + startCookie - logp->baseCookie;
2302         if (ix >= logp->logSize) ix -= logp->logSize;
2303
2304         /* if have some data now, break out and process it */
2305         if (startCookie - logp->baseCookie < logp->logElements) break;
2306
2307         /* At end of log, so clear it if we need to */
2308         if (inFlags & ICL_COPYOUTF_CLRAFTERREAD)
2309         {
2310             logp->firstUsed = logp->firstFree = 0;
2311             logp->logElements = 0;
2312         }
2313         /* otherwise, either wait for the data to arrive, or return */
2314         if (!(inFlags & ICL_COPYOUTF_WAITIO)) {
2315             ReleaseWriteLock(&logp->lock);
2316             code = 0;
2317             goto done;
2318         }
2319         logp->states |= ICL_LOGF_WAITING;
2320         ReleaseWriteLock(&logp->lock);
2321         afs_osi_Sleep(&logp->lock);
2322         ObtainWriteLock(&logp->lock,186);
2323     }
2324     /* copy out data from ix to logSize or firstFree, depending
2325      * upon whether firstUsed <= firstFree (no wrap) or otherwise.
2326      * be careful not to copy out more than nwords.
2327      */
2328     if (ix >= logp->firstUsed) {
2329         if (logp->firstUsed <= logp->firstFree)
2330             /* no wrapping */
2331             end = logp->firstFree;      /* first element not to copy */
2332         else
2333             end = logp->logSize;
2334         nwords = inWords;       /* don't copy more than this */
2335         if (end - ix < nwords)
2336             nwords = end - ix;
2337         if (nwords > 0) {
2338             memcpy((char *) bufferp, (char *) &logp->datap[ix], sizeof(afs_int32) * nwords);
2339             outWords += nwords;
2340             inWords -= nwords;
2341             bufferp += nwords;
2342         }
2343         /* if we're going to copy more out below, we'll start here */
2344         ix = 0;
2345     }
2346     /* now, if active part of the log has wrapped, there's more stuff
2347      * starting at the head of the log.  Copy out more from there.
2348      */
2349     if (logp->firstUsed > logp->firstFree
2350         && ix < logp->firstFree && inWords > 0) {
2351         /* (more to) copy out from the wrapped section at the
2352          * start of the log.  May get here even if didn't copy any
2353          * above, if the cookie points directly into the wrapped section.
2354          */
2355         nwords = inWords;
2356         if (logp->firstFree - ix < nwords)
2357             nwords = logp->firstFree - ix;
2358         memcpy((char *) bufferp, (char *) &logp->datap[ix], sizeof(afs_int32) * nwords);
2359         outWords += nwords;
2360         inWords -= nwords;
2361         bufferp += nwords;
2362     }
2363
2364     ReleaseWriteLock(&logp->lock);
2365
2366   done:
2367     if (code == 0) {
2368         *bufSizep = outWords;
2369         *flagsp = outFlags;
2370     }
2371     return code;
2372 }
2373
2374 /* return basic parameter information about a log */
2375 int afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 *maxSizep, 
2376         afs_int32 *curSizep)
2377 {
2378     ObtainReadLock(&logp->lock);
2379     *maxSizep = logp->logSize;
2380     *curSizep = logp->logElements;
2381     ReleaseReadLock(&logp->lock);
2382     return 0;
2383 }
2384
2385
2386 /* hold and release logs */
2387 int afs_icl_LogHold(register struct afs_icl_log *logp)
2388 {
2389     ObtainWriteLock(&afs_icl_lock,187);
2390     logp->refCount++;
2391     ReleaseWriteLock(&afs_icl_lock);
2392     return 0;
2393 }
2394
2395 /* hold and release logs, called with lock already held */
2396 int afs_icl_LogHoldNL(register struct afs_icl_log *logp)
2397 {
2398     logp->refCount++;
2399     return 0;
2400 }
2401
2402 /* keep track of how many sets believe the log itself is allocated */
2403 int afs_icl_LogUse(register struct afs_icl_log *logp)
2404 {
2405     ObtainWriteLock(&logp->lock,188);
2406     if (logp->setCount == 0) {
2407         /* this is the first set actually using the log -- allocate it */
2408         if (logp->logSize == 0) {
2409             /* we weren't passed in a hint and it wasn't set */
2410             logp->logSize = ICL_DEFAULT_LOGSIZE;
2411         }
2412         logp->datap = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logp->logSize);
2413 #ifdef  KERNEL_HAVE_PIN
2414         pin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2415 #endif
2416     }
2417     logp->setCount++;
2418     ReleaseWriteLock(&logp->lock);
2419     return 0;
2420 }
2421
2422 /* decrement the number of real users of the log, free if possible */
2423 int afs_icl_LogFreeUse(register struct afs_icl_log *logp)
2424 {
2425     ObtainWriteLock(&logp->lock,189);
2426     if (--logp->setCount == 0) {
2427         /* no more users -- free it (but keep log structure around)*/
2428         afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
2429 #ifdef  KERNEL_HAVE_PIN
2430         unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2431 #endif
2432         logp->firstUsed = logp->firstFree = 0;
2433         logp->logElements = 0;
2434         logp->datap = NULL;
2435     }
2436     ReleaseWriteLock(&logp->lock);
2437     return 0;
2438 }
2439
2440 /* set the size of the log to 'logSize' */
2441 int afs_icl_LogSetSize(register struct afs_icl_log *logp, afs_int32 logSize)
2442 {  
2443     ObtainWriteLock(&logp->lock,190);
2444     if (!logp->datap) {
2445         /* nothing to worry about since it's not allocated */
2446         logp->logSize = logSize;
2447     }
2448     else {
2449         /* reset log */
2450         logp->firstUsed = logp->firstFree = 0;
2451         logp->logElements = 0;
2452
2453         /* free and allocate a new one */
2454         afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
2455 #ifdef  KERNEL_HAVE_PIN
2456         unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
2457 #endif
2458         logp->datap = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logSize);
2459 #ifdef  KERNEL_HAVE_PIN
2460         pin((char *)logp->datap, sizeof(afs_int32) * logSize);
2461 #endif
2462         logp->logSize = logSize;
2463     }
2464     ReleaseWriteLock(&logp->lock);
2465
2466     return 0;
2467 }
2468
2469 /* free a log.  Called with afs_icl_lock locked. */
2470 int afs_icl_ZapLog(register struct afs_icl_log *logp)
2471 {
2472     register struct afs_icl_log **lpp, *tp;
2473
2474     for(lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
2475         if (tp == logp) {
2476             /* found the dude we want to remove */
2477             *lpp = logp->nextp;
2478             osi_FreeSmallSpace(logp->name);
2479             osi_FreeSmallSpace(logp->datap);
2480             osi_FreeSmallSpace(logp);
2481             break;      /* won't find it twice */
2482         }
2483     }
2484     return 0;
2485 }
2486
2487 /* do the release, watching for deleted entries */
2488 int afs_icl_LogRele(register struct afs_icl_log *logp)
2489 {
2490     ObtainWriteLock(&afs_icl_lock,191);
2491     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
2492         afs_icl_ZapLog(logp);   /* destroys logp's lock! */
2493     }
2494     ReleaseWriteLock(&afs_icl_lock);
2495     return 0;
2496 }
2497
2498 /* do the release, watching for deleted entries, log already held */
2499 int afs_icl_LogReleNL(register struct afs_icl_log *logp)
2500 {
2501     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
2502         afs_icl_ZapLog(logp);   /* destroys logp's lock! */
2503     }
2504     return 0;
2505 }
2506
2507 /* zero out the log */
2508 int afs_icl_ZeroLog(register struct afs_icl_log *logp)
2509 {
2510     ObtainWriteLock(&logp->lock,192);
2511     logp->firstUsed = logp->firstFree = 0;
2512     logp->logElements = 0;
2513     logp->baseCookie = 0;
2514     ReleaseWriteLock(&logp->lock);
2515     return 0;
2516 }
2517
2518 /* free a log entry, and drop its reference count */
2519 int afs_icl_LogFree(register struct afs_icl_log *logp)
2520 {
2521     ObtainWriteLock(&logp->lock,193);
2522     logp->states |= ICL_LOGF_DELETED;
2523     ReleaseWriteLock(&logp->lock);
2524     afs_icl_LogRele(logp);
2525     return 0;
2526 }
2527
2528 /* find a log by name, returning it held */
2529 struct afs_icl_log *afs_icl_FindLog(char *name)
2530 {
2531     register struct afs_icl_log *tp;
2532     ObtainWriteLock(&afs_icl_lock,194);
2533     for(tp = afs_icl_allLogs; tp; tp=tp->nextp) {
2534         if (strcmp(tp->name, name) == 0) {
2535             /* this is the dude we want */
2536             tp->refCount++;
2537             break;
2538         }
2539     }
2540     ReleaseWriteLock(&afs_icl_lock);
2541     return tp;
2542 }
2543
2544 int afs_icl_EnumerateLogs(int (*aproc)(), char *arock)
2545 {
2546     register struct afs_icl_log *tp;
2547     register afs_int32 code;
2548
2549     code = 0;
2550     ObtainWriteLock(&afs_icl_lock,195);
2551     for(tp = afs_icl_allLogs; tp; tp=tp->nextp) {
2552         tp->refCount++; /* hold this guy */
2553         ReleaseWriteLock(&afs_icl_lock);
2554         ObtainReadLock(&tp->lock);
2555         code = (*aproc)(tp->name, arock, tp);
2556         ReleaseReadLock(&tp->lock);
2557         ObtainWriteLock(&afs_icl_lock,196);
2558         if (--tp->refCount == 0)
2559             afs_icl_ZapLog(tp);
2560         if (code) break;
2561     }
2562     ReleaseWriteLock(&afs_icl_lock);
2563     return code;
2564 }
2565
2566 struct afs_icl_set *afs_icl_allSets = 0;
2567
2568 int afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp, 
2569         struct afs_icl_log *fatalLogp, struct afs_icl_set **outSetpp)
2570 {
2571     return afs_icl_CreateSetWithFlags(name, baseLogp, fatalLogp,
2572                                       /*flags*/0, outSetpp);
2573 }
2574
2575 /* create a set, given pointers to base and fatal logs, if any.
2576  * Logs are unlocked, but referenced, and *outSetpp is returned
2577  * referenced.  Function bumps reference count on logs, since it
2578  * addds references from the new afs_icl_set.  When the set is destroyed,
2579  * those references will be released.
2580  */
2581 int afs_icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp, 
2582         struct afs_icl_log *fatalLogp, afs_uint32 flags, struct afs_icl_set **outSetpp)
2583 {
2584     register struct afs_icl_set *setp;
2585     register int i;
2586     afs_int32 states = ICL_DEFAULT_SET_STATES;
2587
2588     ObtainWriteLock(&afs_icl_lock,197);
2589     if (!afs_icl_inited) afs_icl_Init();
2590
2591     for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
2592         if (strcmp(setp->name, name) == 0) {
2593             setp->refCount++;
2594             *outSetpp = setp;
2595             if (flags & ICL_CRSET_FLAG_PERSISTENT)
2596             {
2597                 ObtainWriteLock(&setp->lock,198);
2598                 setp->states |= ICL_SETF_PERSISTENT;
2599                 ReleaseWriteLock(&setp->lock);
2600             }
2601             ReleaseWriteLock(&afs_icl_lock);
2602             return 0;
2603         }
2604     }
2605     
2606     /* determine initial state */
2607     if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
2608         states = ICL_SETF_ACTIVE;
2609     else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
2610         states = ICL_SETF_FREED;
2611     if (flags & ICL_CRSET_FLAG_PERSISTENT)
2612         states |= ICL_SETF_PERSISTENT;
2613
2614     setp = (struct afs_icl_set *) afs_osi_Alloc(sizeof(struct afs_icl_set));
2615     memset((caddr_t)setp, 0, sizeof(*setp));
2616     setp->refCount = 1;
2617     if (states & ICL_SETF_FREED)
2618         states &= ~ICL_SETF_ACTIVE;     /* if freed, can't be active */
2619     setp->states = states;
2620
2621     LOCK_INIT(&setp->lock, "setp lock");
2622     /* next lock is obtained in wrong order, hierarchy-wise, but
2623      * it doesn't matter, since no one can find this lock yet, since
2624      * the afs_icl_lock is still held, and thus the obtain can't block.
2625      */
2626     ObtainWriteLock(&setp->lock,199);
2627     setp->name = osi_AllocSmallSpace(strlen(name)+1);
2628     strcpy(setp->name, name);
2629     setp->nevents = ICL_DEFAULTEVENTS;
2630     setp->eventFlags = afs_osi_Alloc(ICL_DEFAULTEVENTS);
2631 #ifdef  KERNEL_HAVE_PIN
2632     pin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
2633 #endif
2634     for(i=0; i<ICL_DEFAULTEVENTS; i++)
2635         setp->eventFlags[i] = 0xff;     /* default to enabled */
2636
2637     /* update this global info under the afs_icl_lock */
2638     setp->nextp = afs_icl_allSets;
2639     afs_icl_allSets = setp;
2640     ReleaseWriteLock(&afs_icl_lock);
2641
2642     /* set's basic lock is still held, so we can finish init */
2643     if (baseLogp) {
2644         setp->logs[0] = baseLogp;
2645         afs_icl_LogHold(baseLogp);
2646         if (!(setp->states & ICL_SETF_FREED))
2647             afs_icl_LogUse(baseLogp);   /* log is actually being used */
2648     }
2649     if (fatalLogp) {
2650         setp->logs[1] = fatalLogp;
2651         afs_icl_LogHold(fatalLogp);
2652         if (!(setp->states & ICL_SETF_FREED))
2653             afs_icl_LogUse(fatalLogp);  /* log is actually being used */
2654     }
2655     ReleaseWriteLock(&setp->lock);
2656
2657     *outSetpp = setp;
2658     return 0;
2659 }
2660
2661 /* function to change event enabling information for a particular set */
2662 int afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
2663 {
2664     char *tp;
2665
2666     ObtainWriteLock(&setp->lock,200);
2667     if (!ICL_EVENTOK(setp, eventID)) {
2668         ReleaseWriteLock(&setp->lock);
2669         return -1;
2670     }
2671     tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
2672     if (setValue)
2673         *tp |= ICL_EVENTMASK(eventID);
2674     else
2675         *tp &= ~(ICL_EVENTMASK(eventID));
2676     ReleaseWriteLock(&setp->lock);
2677     return 0;
2678 }
2679
2680 /* return indication of whether a particular event ID is enabled
2681  * for tracing.  If *getValuep is set to 0, the event is disabled,
2682  * otherwise it is enabled.  All events start out enabled by default.
2683  */
2684 int afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, 
2685         int *getValuep)
2686 {
2687     ObtainReadLock(&setp->lock);
2688     if (!ICL_EVENTOK(setp, eventID)) {
2689         ReleaseWriteLock(&setp->lock);
2690         return -1;
2691     }
2692     if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
2693         *getValuep = 1;
2694     else
2695         *getValuep = 0;
2696     ReleaseReadLock(&setp->lock);
2697     return 0;
2698 }
2699
2700 /* hold and release event sets */
2701 int afs_icl_SetHold(register struct afs_icl_set *setp)
2702 {
2703     ObtainWriteLock(&afs_icl_lock,201);
2704     setp->refCount++;
2705     ReleaseWriteLock(&afs_icl_lock);
2706     return 0;
2707 }
2708
2709 /* free a set.  Called with afs_icl_lock locked */
2710 int afs_icl_ZapSet(register struct afs_icl_set *setp)
2711 {
2712     register struct afs_icl_set **lpp, *tp;
2713     int i;
2714     register struct afs_icl_log *tlp;
2715
2716     for(lpp = &afs_icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
2717         if (tp == setp) {
2718             /* found the dude we want to remove */
2719             *lpp = setp->nextp;
2720             osi_FreeSmallSpace(setp->name);
2721             afs_osi_Free(setp->eventFlags, ICL_DEFAULTEVENTS);
2722 #ifdef  KERNEL_HAVE_PIN
2723             unpin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
2724 #endif
2725             for(i=0; i < ICL_LOGSPERSET; i++) {
2726                 if ((tlp = setp->logs[i]))
2727                     afs_icl_LogReleNL(tlp);
2728             }
2729             osi_FreeSmallSpace(setp);
2730             break;      /* won't find it twice */
2731         }
2732     }
2733     return 0;
2734 }
2735
2736 /* do the release, watching for deleted entries */
2737 int afs_icl_SetRele(register struct afs_icl_set *setp)
2738 {
2739     ObtainWriteLock(&afs_icl_lock,202);
2740     if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
2741         afs_icl_ZapSet(setp);   /* destroys setp's lock! */
2742     }
2743     ReleaseWriteLock(&afs_icl_lock);
2744     return 0;
2745 }
2746
2747 /* free a set entry, dropping its reference count */
2748 int afs_icl_SetFree(register struct afs_icl_set *setp)
2749 {
2750     ObtainWriteLock(&setp->lock,203);
2751     setp->states |= ICL_SETF_DELETED;
2752     ReleaseWriteLock(&setp->lock);
2753     afs_icl_SetRele(setp);
2754     return 0;
2755 }
2756
2757 /* find a set by name, returning it held */
2758 struct afs_icl_set *afs_icl_FindSet(char *name)
2759 {
2760     register struct afs_icl_set *tp;
2761     ObtainWriteLock(&afs_icl_lock,204);
2762     for(tp = afs_icl_allSets; tp; tp=tp->nextp) {
2763         if (strcmp(tp->name, name) == 0) {
2764             /* this is the dude we want */
2765             tp->refCount++;
2766             break;
2767         }
2768     }
2769     ReleaseWriteLock(&afs_icl_lock);
2770     return tp;
2771 }
2772
2773 /* zero out all the logs in the set */
2774 int afs_icl_ZeroSet(struct afs_icl_set *setp)
2775 {
2776     register int i;
2777     int code = 0;
2778     int tcode;
2779     struct afs_icl_log *logp;
2780     
2781     ObtainReadLock(&setp->lock);
2782     for(i = 0; i < ICL_LOGSPERSET; i++) {
2783         logp = setp->logs[i];
2784         if (logp) {
2785             afs_icl_LogHold(logp);
2786             tcode = afs_icl_ZeroLog(logp);
2787             if (tcode != 0) code = tcode;       /* save the last bad one */
2788             afs_icl_LogRele(logp);
2789         }
2790     }
2791     ReleaseReadLock(&setp->lock);
2792     return code;
2793 }
2794
2795 int afs_icl_EnumerateSets(int (*aproc)(), char *arock)
2796 {
2797     register struct afs_icl_set *tp, *np;
2798     register afs_int32 code;
2799
2800     code = 0;
2801     ObtainWriteLock(&afs_icl_lock,205);
2802     for(tp = afs_icl_allSets; tp; tp=np) {
2803         tp->refCount++; /* hold this guy */
2804         ReleaseWriteLock(&afs_icl_lock);
2805         code = (*aproc)(tp->name, arock, tp);
2806         ObtainWriteLock(&afs_icl_lock,206);
2807         np = tp->nextp; /* tp may disappear next, but not np */
2808         if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
2809             afs_icl_ZapSet(tp);
2810         if (code) break;
2811     }
2812     ReleaseWriteLock(&afs_icl_lock);
2813     return code;
2814 }
2815
2816 int afs_icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
2817 {
2818     register int i;
2819     int code = -1;
2820     
2821     ObtainWriteLock(&setp->lock,207);
2822     for(i = 0; i < ICL_LOGSPERSET; i++) {
2823         if (!setp->logs[i]) {
2824             setp->logs[i] = newlogp;
2825             code = i;
2826             afs_icl_LogHold(newlogp);
2827             if (!(setp->states & ICL_SETF_FREED)) {
2828                 /* bump up the number of sets using the log */
2829                 afs_icl_LogUse(newlogp);
2830             }
2831             break;
2832         }
2833     }
2834     ReleaseWriteLock(&setp->lock);
2835     return code;
2836 }
2837
2838 int afs_icl_SetSetStat(struct afs_icl_set *setp, int op)
2839 {
2840     int i;
2841     afs_int32 code;
2842     struct afs_icl_log *logp;
2843
2844     ObtainWriteLock(&setp->lock,208);
2845     switch(op) {
2846     case ICL_OP_SS_ACTIVATE:    /* activate a log */
2847         /*
2848          * If we are not already active, see if we have released
2849          * our demand that the log be allocated (FREED set).  If
2850          * we have, reassert our desire.
2851          */
2852         if (!(setp->states & ICL_SETF_ACTIVE)) {
2853             if (setp->states & ICL_SETF_FREED) {
2854                 /* have to reassert desire for logs */
2855                 for(i = 0; i < ICL_LOGSPERSET; i++) {
2856                     logp = setp->logs[i];
2857                     if (logp) {
2858                         afs_icl_LogHold(logp);
2859                         afs_icl_LogUse(logp);
2860                         afs_icl_LogRele(logp);
2861                     }
2862                 }
2863                 setp->states &= ~ICL_SETF_FREED;
2864             }
2865             setp->states |= ICL_SETF_ACTIVE;
2866         }
2867         code = 0;
2868         break;
2869
2870     case ICL_OP_SS_DEACTIVATE:  /* deactivate a log */
2871         /* this doesn't require anything beyond clearing the ACTIVE flag */
2872         setp->states &= ~ICL_SETF_ACTIVE;
2873         code = 0;
2874         break;
2875
2876     case ICL_OP_SS_FREE:        /* deassert design for log */
2877         /* 
2878          * if we are already in this state, do nothing; otherwise
2879          * deassert desire for log
2880          */
2881         if (setp->states & ICL_SETF_ACTIVE)
2882             code = EINVAL;
2883         else {
2884             if (!(setp->states & ICL_SETF_FREED)) {
2885                 for(i = 0; i < ICL_LOGSPERSET; i++) {
2886                     logp = setp->logs[i];
2887                     if (logp) {
2888                         afs_icl_LogHold(logp);
2889                         afs_icl_LogFreeUse(logp);
2890                         afs_icl_LogRele(logp);
2891                     }
2892                 }
2893                 setp->states |= ICL_SETF_FREED;
2894             }
2895             code = 0;
2896         }
2897         break;
2898
2899     default:
2900         code = EINVAL;
2901     }
2902     ReleaseWriteLock(&setp->lock);
2903     return code;
2904 }
2905