2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h"
17 #include "rx/rx_globals.h"
18 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
21 #include "h/hashing.h"
23 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
24 #include "netinet/in_var.h"
26 #endif /* !defined(UKERNEL) */
27 #ifdef AFS_LINUX22_ENV
28 #include "h/smp_lock.h"
32 struct afs_icl_set *afs_iclSetp = (struct afs_icl_set *)0;
33 struct afs_icl_set *afs_iclLongTermSetp = (struct afs_icl_set *)0;
35 #if defined(AFS_SGI61_ENV)
36 /* For SGI 6.2, this can is changed to 1 if it's a 32 bit kernel. */
37 #if defined(AFS_SGI62_ENV) && !defined(_K64U64)
38 int afs_icl_sizeofLong = 1;
40 int afs_icl_sizeofLong = 2;
43 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
44 int afs_icl_sizeofLong = 2;
46 int afs_icl_sizeofLong = 1;
50 int afs_icl_inited = 0;
52 /* init function, called once, under afs_icl_lock */
60 /* Function called at shutdown - zap everything */
64 struct afs_icl_log *logp;
65 struct afs_icl_set *setp;
67 setp = afs_icl_FindSet("cm");
69 /* Release the reference from Find, and the initial one */
70 afs_icl_SetFree(setp);
71 afs_icl_SetFree(setp);
73 setp = afs_icl_FindSet("cmlongterm");
75 /* Release the reference from Find, and the initial one */
76 afs_icl_SetFree(setp);
77 afs_icl_SetFree(setp);
79 logp = afs_icl_FindLog("cmfx");
81 /* Release the reference from Find, and the initial one */
82 afs_icl_LogFree(logp);
83 afs_icl_LogFree(logp);
88 afs_icl_InitLogs(void)
90 struct afs_icl_log *logp;
93 /* initialize the ICL system */
94 code = afs_icl_CreateLog("cmfx", 60 * 1024, &logp);
97 afs_icl_CreateSetWithFlags("cm", logp, NULL,
98 ICL_CRSET_FLAG_DEFAULT_OFF,
101 afs_icl_CreateSet("cmlongterm", logp, NULL,
102 &afs_iclLongTermSetp);
107 struct afs_icl_log *afs_icl_FindLog(char *);
108 struct afs_icl_set *afs_icl_FindSet(char *);
111 #ifdef AFS_DARWIN100_ENV
112 #define AFSKPTR(X) k ## X
114 Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval)
116 return Afscall64_icl(opcode,
117 CAST_USER_ADDR_T((p1)),
118 CAST_USER_ADDR_T((p2)),
119 CAST_USER_ADDR_T((p3)),
120 CAST_USER_ADDR_T((p4)),
124 #define AFSKPTR(X) ((caddr_t)X)
128 #ifdef AFS_DARWIN100_ENV
129 Afscall64_icl(int opcode, user_addr_t kp1, user_addr_t kp2, user_addr_t kp3, user_addr_t kp4, int *retval)
131 Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval)
134 afs_int32 *lp, elts, flags;
135 register afs_int32 code;
136 struct afs_icl_log *logp;
137 struct afs_icl_set *setp;
138 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
140 #else /* AFS_SGI61_ENV */
141 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
146 #endif /* AFS_SGI61_ENV */
148 afs_int32 startCookie;
150 struct afs_icl_log *tlp;
151 #ifdef AFS_DARWIN100_ENV
152 afs_uint32 p1 = (afs_uint32)kp1;
153 afs_uint32 p2 = (afs_uint32)kp2;
154 afs_uint32 p3 = (afs_uint32)kp3;
155 afs_uint32 p4 = (afs_uint32)kp4;
159 if (!afs_suser(CRED())) { /* only root can run this code */
163 if (!afs_suser(NULL)) { /* only root can run this code */
164 #if defined(KERNEL_HAVE_UERROR)
173 case ICL_OP_COPYOUTCLR: /* copy out data then clear */
174 case ICL_OP_COPYOUT: /* copy ouy data */
175 /* copyout: p1=logname, p2=&buffer, p3=size(words), p4=&cookie
176 * return flags<<24 + nwords.
177 * updates cookie to updated start (not end) if we had to
180 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
183 AFS_COPYIN(AFSKPTR(p4), (char *)&startCookie, sizeof(afs_int32), code);
186 logp = afs_icl_FindLog(tname);
189 #define BUFFERSIZE AFS_LRALLOCSIZ
190 lp = (afs_int32 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
191 elts = BUFFERSIZE / sizeof(afs_int32);
194 flags = (opcode == ICL_OP_COPYOUT) ? 0 : ICL_COPYOUTF_CLRAFTERREAD;
196 afs_icl_CopyOut(logp, lp, &elts, (afs_uint32 *) & startCookie,
199 osi_FreeLargeSpace((struct osi_buffer *)lp);
202 AFS_COPYOUT((char *)lp, AFSKPTR(p2), elts * sizeof(afs_int32), code);
205 AFS_COPYOUT((char *)&startCookie, AFSKPTR(p4), sizeof(afs_int32),
209 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
211 *retval = ((long)((flags << 24) | (elts & 0xffffff))) << 32;
214 *retval = (flags << 24) | (elts & 0xffffff);
216 afs_icl_LogRele(logp);
217 osi_FreeLargeSpace((struct osi_buffer *)lp);
220 case ICL_OP_ENUMLOGS: /* enumerate logs */
221 /* enumerate logs: p1=index, p2=&name, p3=sizeof(name), p4=&size.
222 * return 0 for success, otherwise error.
224 for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
229 return ENOENT; /* past the end of file */
230 temp = strlen(tlp->name) + 1;
233 AFS_COPYOUT(tlp->name, AFSKPTR(p2), temp, code);
234 if (!code) /* copy out size of log */
235 AFS_COPYOUT((char *)&tlp->logSize, AFSKPTR(p4), sizeof(afs_int32),
239 case ICL_OP_ENUMLOGSBYSET: /* enumerate logs by set name */
240 /* enumerate logs: p1=setname, p2=index, p3=&name, p4=sizeof(name).
241 * return 0 for success, otherwise error.
243 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
246 setp = afs_icl_FindSet(tname);
249 if (p2 > ICL_LOGSPERSET)
251 if (!(tlp = setp->logs[p2]))
253 temp = strlen(tlp->name) + 1;
256 AFS_COPYOUT(tlp->name, AFSKPTR(p3), temp, code);
259 case ICL_OP_CLRLOG: /* clear specified log */
260 /* zero out the specified log: p1=logname */
261 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
264 logp = afs_icl_FindLog(tname);
267 code = afs_icl_ZeroLog(logp);
268 afs_icl_LogRele(logp);
271 case ICL_OP_CLRSET: /* clear specified set */
272 /* zero out the specified set: p1=setname */
273 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
276 setp = afs_icl_FindSet(tname);
279 code = afs_icl_ZeroSet(setp);
280 afs_icl_SetRele(setp);
283 case ICL_OP_CLRALL: /* clear all logs */
284 /* zero out all logs -- no args */
286 ObtainWriteLock(&afs_icl_lock, 178);
287 for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
288 tlp->refCount++; /* hold this guy */
289 ReleaseWriteLock(&afs_icl_lock);
290 /* don't clear persistent logs */
291 if ((tlp->states & ICL_LOGF_PERSISTENT) == 0)
292 code = afs_icl_ZeroLog(tlp);
293 ObtainWriteLock(&afs_icl_lock, 179);
294 if (--tlp->refCount == 0)
299 ReleaseWriteLock(&afs_icl_lock);
302 case ICL_OP_ENUMSETS: /* enumerate all sets */
303 /* enumerate sets: p1=index, p2=&name, p3=sizeof(name), p4=&states.
304 * return 0 for success, otherwise error.
306 for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
311 return ENOENT; /* past the end of file */
312 temp = strlen(setp->name) + 1;
315 AFS_COPYOUT(setp->name, AFSKPTR(p2), temp, code);
316 if (!code) /* copy out size of log */
317 AFS_COPYOUT((char *)&setp->states, AFSKPTR(p4), sizeof(afs_int32),
321 case ICL_OP_SETSTAT: /* set status on a set */
322 /* activate the specified set: p1=setname, p2=op */
323 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
326 setp = afs_icl_FindSet(tname);
329 code = afs_icl_SetSetStat(setp, p2);
330 afs_icl_SetRele(setp);
333 case ICL_OP_SETSTATALL: /* set status on all sets */
334 /* activate the specified set: p1=op */
336 ObtainWriteLock(&afs_icl_lock, 180);
337 for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
338 setp->refCount++; /* hold this guy */
339 ReleaseWriteLock(&afs_icl_lock);
340 /* don't set states on persistent sets */
341 if ((setp->states & ICL_SETF_PERSISTENT) == 0)
342 code = afs_icl_SetSetStat(setp, p1);
343 ObtainWriteLock(&afs_icl_lock, 181);
344 if (--setp->refCount == 0)
345 afs_icl_ZapSet(setp);
349 ReleaseWriteLock(&afs_icl_lock);
352 case ICL_OP_SETLOGSIZE: /* set size of log */
353 /* set the size of the specified log: p1=logname, p2=size (in words) */
354 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
357 logp = afs_icl_FindLog(tname);
360 code = afs_icl_LogSetSize(logp, p2);
361 afs_icl_LogRele(logp);
364 case ICL_OP_GETLOGINFO: /* get size of log */
365 /* zero out the specified log: p1=logname, p2=&logSize, p3=&allocated */
366 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
369 logp = afs_icl_FindLog(tname);
372 allocated = !!logp->datap;
373 AFS_COPYOUT((char *)&logp->logSize, AFSKPTR(p2), sizeof(afs_int32),
376 AFS_COPYOUT((char *)&allocated, AFSKPTR(p3), sizeof(afs_int32),
378 afs_icl_LogRele(logp);
381 case ICL_OP_GETSETINFO: /* get state of set */
382 /* zero out the specified set: p1=setname, p2=&state */
383 AFS_COPYINSTR(AFSKPTR(p1), tname, sizeof(tname), &temp, code);
386 setp = afs_icl_FindSet(tname);
389 AFS_COPYOUT((char *)&setp->states, AFSKPTR(p2), sizeof(afs_int32),
391 afs_icl_SetRele(setp);
402 afs_lock_t afs_icl_lock;
404 /* exported routine: a 4 parameter event */
406 afs_icl_Event4(register struct afs_icl_set *setp, afs_int32 eventID,
407 afs_int32 lAndT, long p1, long p2, long p3, long p4)
411 register afs_int32 tmask;
414 /* If things aren't init'ed yet (or the set is inactive), don't panic */
415 if (!ICL_SETACTIVE(setp))
419 mask = lAndT >> 24 & 0xff; /* mask of which logs to log to */
420 ix = ICL_EVENTBYTE(eventID);
421 ObtainReadLock(&setp->lock);
422 if (setp->eventFlags[ix] & ICL_EVENTMASK(eventID)) {
423 for (i = 0, tmask = 1; i < ICL_LOGSPERSET; i++, tmask <<= 1) {
425 afs_icl_AppendRecord(setp->logs[i], eventID, lAndT & 0xffffff,
430 break; /* break early */
433 ReleaseReadLock(&setp->lock);
437 /* Next 4 routines should be implemented via var-args or something.
438 * Whole purpose is to avoid compiler warnings about parameter # mismatches.
439 * Otherwise, could call afs_icl_Event4 directly.
442 afs_icl_Event3(register struct afs_icl_set *setp, afs_int32 eventID,
443 afs_int32 lAndT, long p1, long p2, long p3)
445 return afs_icl_Event4(setp, eventID, lAndT, p1, p2, p3, (long)0);
449 afs_icl_Event2(register struct afs_icl_set *setp, afs_int32 eventID,
450 afs_int32 lAndT, long p1, long p2)
452 return afs_icl_Event4(setp, eventID, lAndT, p1, p2, (long)0, (long)0);
456 afs_icl_Event1(register struct afs_icl_set *setp, afs_int32 eventID,
457 afs_int32 lAndT, long p1)
459 return afs_icl_Event4(setp, eventID, lAndT, p1, (long)0, (long)0,
464 afs_icl_Event0(register struct afs_icl_set *setp, afs_int32 eventID,
467 return afs_icl_Event4(setp, eventID, lAndT, (long)0, (long)0, (long)0,
471 struct afs_icl_log *afs_icl_allLogs = 0;
473 /* function to purge records from the start of the log, until there
474 * is at least minSpace long's worth of space available without
475 * making the head and the tail point to the same word.
477 * Log must be write-locked.
480 afs_icl_GetLogSpace(register struct afs_icl_log *logp, afs_int32 minSpace)
482 register unsigned int tsize;
484 while (logp->logSize - logp->logElements <= minSpace) {
486 tsize = ((logp->datap[logp->firstUsed]) >> 24) & 0xff;
487 logp->logElements -= tsize;
488 logp->firstUsed += tsize;
489 if (logp->firstUsed >= logp->logSize)
490 logp->firstUsed -= logp->logSize;
491 logp->baseCookie += tsize;
495 /* append string astr to buffer, including terminating null char.
497 * log must be write-locked.
499 #define ICL_CHARSPERLONG 4
501 afs_icl_AppendString(struct afs_icl_log *logp, char *astr)
503 char *op; /* ptr to char to write */
505 register int bib; /* bytes in buffer */
508 op = (char *)&(logp->datap[logp->firstFree]);
512 if (++bib >= ICL_CHARSPERLONG) {
515 if (++(logp->firstFree) >= logp->logSize) {
517 op = (char *)&(logp->datap[0]);
525 /* if we've used this word at all, allocate it */
526 if (++(logp->firstFree) >= logp->logSize) {
533 /* add a long to the log, ignoring overflow (checked already) */
534 #define ICL_APPENDINT32(lp, x) \
536 (lp)->datap[(lp)->firstFree] = (x); \
537 if (++((lp)->firstFree) >= (lp)->logSize) { \
538 (lp)->firstFree = 0; \
540 (lp)->logElements++; \
543 #if (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)) || defined(AFS_DARWIN_ENV) && defined(__amd64__)
544 #define ICL_APPENDLONG(lp, x) \
546 ICL_APPENDINT32((lp), ((x) >> 32) & 0xffffffffL); \
547 ICL_APPENDINT32((lp), (x) & 0xffffffffL); \
551 #define ICL_APPENDLONG(lp, x) ICL_APPENDINT32((lp), (x))
554 /* routine to tell whether we're dealing with the address or the
558 afs_icl_UseAddr(int type)
560 if (type == ICL_TYPE_HYPER || type == ICL_TYPE_STRING
561 || type == ICL_TYPE_FID || type == ICL_TYPE_INT64)
568 afs_icl_AppendOne(struct afs_icl_log *logp, int type, long parm)
571 /* marshall parameter 3 now */
572 if (type == ICL_TYPE_STRING)
573 afs_icl_AppendString(logp, (char *)parm);
574 else if (type == ICL_TYPE_HYPER) {
575 ICL_APPENDINT32(logp,
576 (afs_int32) ((struct afs_hyper_t *)parm)->high);
577 ICL_APPENDINT32(logp,
578 (afs_int32) ((struct afs_hyper_t *)parm)->low);
579 } else if (type == ICL_TYPE_INT64) {
580 #ifndef WORDS_BIGENDIAN
581 #ifdef AFS_64BIT_CLIENT
582 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[1]);
583 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[0]);
584 #else /* AFS_64BIT_CLIENT */
585 ICL_APPENDINT32(logp, (afs_int32) parm);
586 ICL_APPENDINT32(logp, (afs_int32) 0);
587 #endif /* AFS_64BIT_CLIENT */
588 #else /* AFSLITTLE_ENDIAN */
589 #ifdef AFS_64BIT_CLIENT
590 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[0]);
591 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[1]);
592 #else /* AFS_64BIT_CLIENT */
593 ICL_APPENDINT32(logp, (afs_int32) 0);
594 ICL_APPENDINT32(logp, (afs_int32) parm);
595 #endif /* AFS_64BIT_CLIENT */
596 #endif /* AFSLITTLE_ENDIAN */
597 } else if (type == ICL_TYPE_FID) {
598 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[0]);
599 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[1]);
600 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[2]);
601 ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) parm)[3]);
603 #if (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
604 else if (type == ICL_TYPE_INT32)
605 ICL_APPENDINT32(logp, (afs_int32) parm);
608 ICL_APPENDLONG(logp, parm);
612 /* Function to append a record to the log. Written for speed
613 * since we know that we're going to have to make this work fast
614 * pretty soon, anyway. The log must be unlocked.
618 afs_icl_AppendRecord(register struct afs_icl_log *logp, afs_int32 op,
619 afs_int32 types, long p1, long p2, long p3, long p4)
621 int rsize; /* record size in longs */
622 register int tsize; /* temp size */
626 t4 = types & 0x3f; /* decode types */
634 osi_GetTime(&tv); /* It panics for solaris if inside */
635 ObtainWriteLock(&logp->lock, 182);
637 ReleaseWriteLock(&logp->lock);
641 /* get timestamp as # of microseconds since some time that doesn't
642 * change that often. This algorithm ticks over every 20 minutes
643 * or so (1000 seconds). Write a timestamp record if it has.
645 if (tv.tv_sec - logp->lastTS > 1024) {
646 /* the timer has wrapped -- write a timestamp record */
647 if (logp->logSize - logp->logElements <= 5)
648 afs_icl_GetLogSpace(logp, 5);
650 ICL_APPENDINT32(logp,
651 (afs_int32) (5 << 24) + (ICL_TYPE_UNIXDATE << 18));
652 ICL_APPENDINT32(logp, (afs_int32) ICL_INFO_TIMESTAMP);
653 ICL_APPENDINT32(logp, (afs_int32) 0); /* use thread ID zero for clocks */
654 ICL_APPENDINT32(logp,
655 (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 +
657 ICL_APPENDINT32(logp, (afs_int32) tv.tv_sec);
659 logp->lastTS = tv.tv_sec;
662 rsize = 4; /* base case: see 4 items below */
664 /* compute size of parameter p1. Only tricky case is string.
665 * In that case, we have to call strlen to get the string length.
667 ICL_SIZEHACK(t1, p1, tsize, rsize);
670 /* compute size of parameter p2. Only tricky case is string.
671 * In that case, we have to call strlen to get the string length.
673 ICL_SIZEHACK(t2, p2, tsize, rsize);
676 /* compute size of parameter p3. Only tricky case is string.
677 * In that case, we have to call strlen to get the string length.
679 ICL_SIZEHACK(t3, p3, tsize, rsize);
682 /* compute size of parameter p4. Only tricky case is string.
683 * In that case, we have to call strlen to get the string length.
685 ICL_SIZEHACK(t4, p4, tsize, rsize);
688 /* At this point, we've computed all of the parameter sizes, and
689 * have in rsize the size of the entire record we want to append.
690 * Next, we check that we actually have room in the log to do this
691 * work, and then we do the append.
694 ReleaseWriteLock(&logp->lock);
695 return; /* log record too big to express */
698 if (logp->logSize - logp->logElements <= rsize)
699 afs_icl_GetLogSpace(logp, rsize);
701 ICL_APPENDINT32(logp,
702 (afs_int32) (rsize << 24) + (t1 << 18) + (t2 << 12) +
704 ICL_APPENDINT32(logp, (afs_int32) op);
705 ICL_APPENDINT32(logp, (afs_int32) osi_ThreadUnique());
706 ICL_APPENDINT32(logp,
707 (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 + tv.tv_usec);
709 afs_icl_AppendOne(logp, t1, p1);
710 afs_icl_AppendOne(logp, t2, p2);
711 afs_icl_AppendOne(logp, t3, p3);
712 afs_icl_AppendOne(logp, t4, p4);
713 ReleaseWriteLock(&logp->lock);
716 /* create a log with size logSize; return it in *outLogpp and tag
717 * it with name "name."
720 afs_icl_CreateLog(char *name, afs_int32 logSize,
721 struct afs_icl_log **outLogpp)
723 return afs_icl_CreateLogWithFlags(name, logSize, /*flags */ 0, outLogpp);
726 /* create a log with size logSize; return it in *outLogpp and tag
727 * it with name "name." 'flags' can be set to make the log unclearable.
730 afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize, afs_uint32 flags,
731 struct afs_icl_log **outLogpp)
733 register struct afs_icl_log *logp;
735 /* add into global list under lock */
736 ObtainWriteLock(&afs_icl_lock, 183);
740 for (logp = afs_icl_allLogs; logp; logp = logp->nextp) {
741 if (strcmp(logp->name, name) == 0) {
742 /* found it already created, just return it */
745 if (flags & ICL_CRLOG_FLAG_PERSISTENT) {
746 ObtainWriteLock(&logp->lock, 184);
747 logp->states |= ICL_LOGF_PERSISTENT;
748 ReleaseWriteLock(&logp->lock);
750 ReleaseWriteLock(&afs_icl_lock);
755 logp = (struct afs_icl_log *)
756 osi_AllocSmallSpace(sizeof(struct afs_icl_log));
757 memset((caddr_t) logp, 0, sizeof(*logp));
760 logp->name = osi_AllocSmallSpace(strlen(name) + 1);
761 strcpy(logp->name, name);
762 LOCK_INIT(&logp->lock, "logp lock");
763 logp->logSize = logSize;
764 logp->datap = NULL; /* don't allocate it until we need it */
766 if (flags & ICL_CRLOG_FLAG_PERSISTENT)
767 logp->states |= ICL_LOGF_PERSISTENT;
769 logp->nextp = afs_icl_allLogs;
770 afs_icl_allLogs = logp;
771 ReleaseWriteLock(&afs_icl_lock);
777 /* called with a log, a pointer to a buffer, the size of the buffer
778 * (in *bufSizep), the starting cookie (in *cookiep, use 0 at the start)
779 * and returns data in the provided buffer, and returns output flags
780 * in *flagsp. The flag ICL_COPYOUTF_MISSEDSOME is set if we can't
781 * find the record with cookie value cookie.
784 afs_icl_CopyOut(register struct afs_icl_log *logp, afs_int32 * bufferp,
785 afs_int32 * bufSizep, afs_uint32 * cookiep,
788 afs_int32 nwords; /* number of words to copy out */
789 afs_uint32 startCookie; /* first cookie to use */
790 afs_int32 outWords; /* words we've copied out */
791 afs_int32 inWords; /* max words to copy out */
792 afs_int32 code; /* return code */
793 afs_int32 ix; /* index we're copying from */
794 afs_int32 outFlags; /* return flags */
795 afs_int32 inFlags; /* flags passed in */
798 inWords = *bufSizep; /* max to copy out */
799 outWords = 0; /* amount copied out */
800 startCookie = *cookiep;
805 ObtainWriteLock(&logp->lock, 185);
807 ReleaseWriteLock(&logp->lock);
811 /* first, compute the index of the start cookie we've been passed */
813 /* (re-)compute where we should start */
814 if (startCookie < logp->baseCookie) {
815 if (startCookie) /* missed some output */
816 outFlags |= ICL_COPYOUTF_MISSEDSOME;
817 /* skip to the first available record */
818 startCookie = logp->baseCookie;
819 *cookiep = startCookie;
822 /* compute where we find the first element to copy out */
823 ix = logp->firstUsed + startCookie - logp->baseCookie;
824 if (ix >= logp->logSize)
827 /* if have some data now, break out and process it */
828 if (startCookie - logp->baseCookie < logp->logElements)
831 /* At end of log, so clear it if we need to */
832 if (inFlags & ICL_COPYOUTF_CLRAFTERREAD) {
833 logp->firstUsed = logp->firstFree = 0;
834 logp->logElements = 0;
836 /* otherwise, either wait for the data to arrive, or return */
837 if (!(inFlags & ICL_COPYOUTF_WAITIO)) {
838 ReleaseWriteLock(&logp->lock);
842 logp->states |= ICL_LOGF_WAITING;
843 ReleaseWriteLock(&logp->lock);
844 afs_osi_Sleep(&logp->lock);
845 ObtainWriteLock(&logp->lock, 186);
847 /* copy out data from ix to logSize or firstFree, depending
848 * upon whether firstUsed <= firstFree (no wrap) or otherwise.
849 * be careful not to copy out more than nwords.
851 if (ix >= logp->firstUsed) {
852 if (logp->firstUsed <= logp->firstFree)
854 end = logp->firstFree; /* first element not to copy */
857 nwords = inWords; /* don't copy more than this */
858 if (end - ix < nwords)
861 memcpy((char *)bufferp, (char *)&logp->datap[ix],
862 sizeof(afs_int32) * nwords);
867 /* if we're going to copy more out below, we'll start here */
870 /* now, if active part of the log has wrapped, there's more stuff
871 * starting at the head of the log. Copy out more from there.
873 if (logp->firstUsed > logp->firstFree && ix < logp->firstFree
875 /* (more to) copy out from the wrapped section at the
876 * start of the log. May get here even if didn't copy any
877 * above, if the cookie points directly into the wrapped section.
880 if (logp->firstFree - ix < nwords)
881 nwords = logp->firstFree - ix;
882 memcpy((char *)bufferp, (char *)&logp->datap[ix],
883 sizeof(afs_int32) * nwords);
889 ReleaseWriteLock(&logp->lock);
893 *bufSizep = outWords;
899 /* return basic parameter information about a log */
901 afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
902 afs_int32 * curSizep)
904 ObtainReadLock(&logp->lock);
905 *maxSizep = logp->logSize;
906 *curSizep = logp->logElements;
907 ReleaseReadLock(&logp->lock);
912 /* hold and release logs */
914 afs_icl_LogHold(register struct afs_icl_log *logp)
916 ObtainWriteLock(&afs_icl_lock, 187);
918 ReleaseWriteLock(&afs_icl_lock);
922 /* hold and release logs, called with lock already held */
924 afs_icl_LogHoldNL(register struct afs_icl_log *logp)
930 /* keep track of how many sets believe the log itself is allocated */
932 afs_icl_LogUse(register struct afs_icl_log *logp)
934 ObtainWriteLock(&logp->lock, 188);
935 if (logp->setCount == 0) {
936 /* this is the first set actually using the log -- allocate it */
937 if (logp->logSize == 0) {
938 /* we weren't passed in a hint and it wasn't set */
939 logp->logSize = ICL_DEFAULT_LOGSIZE;
942 (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logp->logSize);
943 #ifdef KERNEL_HAVE_PIN
944 pin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
948 ReleaseWriteLock(&logp->lock);
952 /* decrement the number of real users of the log, free if possible */
954 afs_icl_LogFreeUse(register struct afs_icl_log *logp)
956 ObtainWriteLock(&logp->lock, 189);
957 if (--logp->setCount == 0) {
958 /* no more users -- free it (but keep log structure around) */
959 afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
960 #ifdef KERNEL_HAVE_PIN
961 unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
963 logp->firstUsed = logp->firstFree = 0;
964 logp->logElements = 0;
967 ReleaseWriteLock(&logp->lock);
971 /* set the size of the log to 'logSize' */
973 afs_icl_LogSetSize(register struct afs_icl_log *logp, afs_int32 logSize)
975 ObtainWriteLock(&logp->lock, 190);
977 /* nothing to worry about since it's not allocated */
978 logp->logSize = logSize;
981 logp->firstUsed = logp->firstFree = 0;
982 logp->logElements = 0;
984 /* free and allocate a new one */
985 afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
986 #ifdef KERNEL_HAVE_PIN
987 unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
990 (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logSize);
991 #ifdef KERNEL_HAVE_PIN
992 pin((char *)logp->datap, sizeof(afs_int32) * logSize);
994 logp->logSize = logSize;
996 ReleaseWriteLock(&logp->lock);
1001 /* free a log. Called with afs_icl_lock locked. */
1003 afs_icl_ZapLog(register struct afs_icl_log *logp)
1005 register struct afs_icl_log **lpp, *tp;
1007 for (lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1009 /* found the dude we want to remove */
1011 osi_FreeSmallSpace(logp->name);
1012 afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
1013 #ifdef KERNEL_HAVE_PIN
1014 unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
1016 osi_FreeSmallSpace(logp);
1017 break; /* won't find it twice */
1023 /* do the release, watching for deleted entries */
1025 afs_icl_LogRele(register struct afs_icl_log *logp)
1027 ObtainWriteLock(&afs_icl_lock, 191);
1028 if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1029 afs_icl_ZapLog(logp); /* destroys logp's lock! */
1031 ReleaseWriteLock(&afs_icl_lock);
1035 /* do the release, watching for deleted entries, log already held */
1037 afs_icl_LogReleNL(register struct afs_icl_log *logp)
1039 if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1040 afs_icl_ZapLog(logp); /* destroys logp's lock! */
1045 /* zero out the log */
1047 afs_icl_ZeroLog(register struct afs_icl_log *logp)
1049 ObtainWriteLock(&logp->lock, 192);
1050 logp->firstUsed = logp->firstFree = 0;
1051 logp->logElements = 0;
1052 logp->baseCookie = 0;
1053 ReleaseWriteLock(&logp->lock);
1057 /* free a log entry, and drop its reference count */
1059 afs_icl_LogFree(register struct afs_icl_log *logp)
1061 ObtainWriteLock(&logp->lock, 193);
1062 logp->states |= ICL_LOGF_DELETED;
1063 ReleaseWriteLock(&logp->lock);
1064 afs_icl_LogRele(logp);
1068 /* find a log by name, returning it held */
1069 struct afs_icl_log *
1070 afs_icl_FindLog(char *name)
1072 register struct afs_icl_log *tp;
1073 ObtainWriteLock(&afs_icl_lock, 194);
1074 for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
1075 if (strcmp(tp->name, name) == 0) {
1076 /* this is the dude we want */
1081 ReleaseWriteLock(&afs_icl_lock);
1086 afs_icl_EnumerateLogs(int (*aproc)
1087 (char *name, char *arock, struct afs_icl_log * tp),
1090 register struct afs_icl_log *tp;
1091 register afs_int32 code;
1094 ObtainWriteLock(&afs_icl_lock, 195);
1095 for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
1096 tp->refCount++; /* hold this guy */
1097 ReleaseWriteLock(&afs_icl_lock);
1098 ObtainReadLock(&tp->lock);
1099 code = (*aproc) (tp->name, arock, tp);
1100 ReleaseReadLock(&tp->lock);
1101 ObtainWriteLock(&afs_icl_lock, 196);
1102 if (--tp->refCount == 0)
1107 ReleaseWriteLock(&afs_icl_lock);
1111 struct afs_icl_set *afs_icl_allSets = 0;
1114 afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
1115 struct afs_icl_log *fatalLogp,
1116 struct afs_icl_set **outSetpp)
1118 return afs_icl_CreateSetWithFlags(name, baseLogp, fatalLogp,
1119 /*flags */ 0, outSetpp);
1122 /* create a set, given pointers to base and fatal logs, if any.
1123 * Logs are unlocked, but referenced, and *outSetpp is returned
1124 * referenced. Function bumps reference count on logs, since it
1125 * addds references from the new afs_icl_set. When the set is destroyed,
1126 * those references will be released.
1129 afs_icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
1130 struct afs_icl_log *fatalLogp, afs_uint32 flags,
1131 struct afs_icl_set **outSetpp)
1133 register struct afs_icl_set *setp;
1135 afs_int32 states = ICL_DEFAULT_SET_STATES;
1137 ObtainWriteLock(&afs_icl_lock, 197);
1138 if (!afs_icl_inited)
1141 for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
1142 if (strcmp(setp->name, name) == 0) {
1145 if (flags & ICL_CRSET_FLAG_PERSISTENT) {
1146 ObtainWriteLock(&setp->lock, 198);
1147 setp->states |= ICL_SETF_PERSISTENT;
1148 ReleaseWriteLock(&setp->lock);
1150 ReleaseWriteLock(&afs_icl_lock);
1155 /* determine initial state */
1156 if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
1157 states = ICL_SETF_ACTIVE;
1158 else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
1159 states = ICL_SETF_FREED;
1160 if (flags & ICL_CRSET_FLAG_PERSISTENT)
1161 states |= ICL_SETF_PERSISTENT;
1163 setp = (struct afs_icl_set *)osi_AllocSmallSpace(sizeof(struct afs_icl_set));
1164 memset((caddr_t) setp, 0, sizeof(*setp));
1166 if (states & ICL_SETF_FREED)
1167 states &= ~ICL_SETF_ACTIVE; /* if freed, can't be active */
1168 setp->states = states;
1170 LOCK_INIT(&setp->lock, "setp lock");
1171 /* next lock is obtained in wrong order, hierarchy-wise, but
1172 * it doesn't matter, since no one can find this lock yet, since
1173 * the afs_icl_lock is still held, and thus the obtain can't block.
1175 ObtainWriteLock(&setp->lock, 199);
1176 setp->name = osi_AllocSmallSpace(strlen(name) + 1);
1177 strcpy(setp->name, name);
1178 setp->nevents = ICL_DEFAULTEVENTS;
1179 setp->eventFlags = afs_osi_Alloc(ICL_DEFAULTEVENTS);
1180 #ifdef KERNEL_HAVE_PIN
1181 pin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
1183 for (i = 0; i < ICL_DEFAULTEVENTS; i++)
1184 setp->eventFlags[i] = 0xff; /* default to enabled */
1186 /* update this global info under the afs_icl_lock */
1187 setp->nextp = afs_icl_allSets;
1188 afs_icl_allSets = setp;
1189 ReleaseWriteLock(&afs_icl_lock);
1191 /* set's basic lock is still held, so we can finish init */
1193 setp->logs[0] = baseLogp;
1194 afs_icl_LogHold(baseLogp);
1195 if (!(setp->states & ICL_SETF_FREED))
1196 afs_icl_LogUse(baseLogp); /* log is actually being used */
1199 setp->logs[1] = fatalLogp;
1200 afs_icl_LogHold(fatalLogp);
1201 if (!(setp->states & ICL_SETF_FREED))
1202 afs_icl_LogUse(fatalLogp); /* log is actually being used */
1204 ReleaseWriteLock(&setp->lock);
1210 /* function to change event enabling information for a particular set */
1212 afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
1216 ObtainWriteLock(&setp->lock, 200);
1217 if (!ICL_EVENTOK(setp, eventID)) {
1218 ReleaseWriteLock(&setp->lock);
1221 tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
1223 *tp |= ICL_EVENTMASK(eventID);
1225 *tp &= ~(ICL_EVENTMASK(eventID));
1226 ReleaseWriteLock(&setp->lock);
1230 /* return indication of whether a particular event ID is enabled
1231 * for tracing. If *getValuep is set to 0, the event is disabled,
1232 * otherwise it is enabled. All events start out enabled by default.
1235 afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
1237 ObtainReadLock(&setp->lock);
1238 if (!ICL_EVENTOK(setp, eventID)) {
1239 ReleaseWriteLock(&setp->lock);
1242 if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
1246 ReleaseReadLock(&setp->lock);
1250 /* hold and release event sets */
1252 afs_icl_SetHold(register struct afs_icl_set *setp)
1254 ObtainWriteLock(&afs_icl_lock, 201);
1256 ReleaseWriteLock(&afs_icl_lock);
1260 /* free a set. Called with afs_icl_lock locked */
1262 afs_icl_ZapSet(register struct afs_icl_set *setp)
1264 register struct afs_icl_set **lpp, *tp;
1266 register struct afs_icl_log *tlp;
1268 for (lpp = &afs_icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1270 /* found the dude we want to remove */
1272 osi_FreeSmallSpace(setp->name);
1273 afs_osi_Free(setp->eventFlags, ICL_DEFAULTEVENTS);
1274 #ifdef KERNEL_HAVE_PIN
1275 unpin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
1277 for (i = 0; i < ICL_LOGSPERSET; i++) {
1278 if ((tlp = setp->logs[i]))
1279 afs_icl_LogReleNL(tlp);
1281 osi_FreeSmallSpace(setp);
1282 break; /* won't find it twice */
1288 /* do the release, watching for deleted entries */
1290 afs_icl_SetRele(register struct afs_icl_set *setp)
1292 ObtainWriteLock(&afs_icl_lock, 202);
1293 if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
1294 afs_icl_ZapSet(setp); /* destroys setp's lock! */
1296 ReleaseWriteLock(&afs_icl_lock);
1300 /* free a set entry, dropping its reference count */
1302 afs_icl_SetFree(register struct afs_icl_set *setp)
1304 ObtainWriteLock(&setp->lock, 203);
1305 setp->states |= ICL_SETF_DELETED;
1306 ReleaseWriteLock(&setp->lock);
1307 afs_icl_SetRele(setp);
1311 /* find a set by name, returning it held */
1312 struct afs_icl_set *
1313 afs_icl_FindSet(char *name)
1315 register struct afs_icl_set *tp;
1316 ObtainWriteLock(&afs_icl_lock, 204);
1317 for (tp = afs_icl_allSets; tp; tp = tp->nextp) {
1318 if (strcmp(tp->name, name) == 0) {
1319 /* this is the dude we want */
1324 ReleaseWriteLock(&afs_icl_lock);
1328 /* zero out all the logs in the set */
1330 afs_icl_ZeroSet(struct afs_icl_set *setp)
1335 struct afs_icl_log *logp;
1337 ObtainReadLock(&setp->lock);
1338 for (i = 0; i < ICL_LOGSPERSET; i++) {
1339 logp = setp->logs[i];
1341 afs_icl_LogHold(logp);
1342 tcode = afs_icl_ZeroLog(logp);
1344 code = tcode; /* save the last bad one */
1345 afs_icl_LogRele(logp);
1348 ReleaseReadLock(&setp->lock);
1353 afs_icl_EnumerateSets(int (*aproc)
1354 (char *name, char *arock, struct afs_icl_log * tp),
1357 register struct afs_icl_set *tp, *np;
1358 register afs_int32 code;
1361 ObtainWriteLock(&afs_icl_lock, 205);
1362 for (tp = afs_icl_allSets; tp; tp = np) {
1363 tp->refCount++; /* hold this guy */
1364 ReleaseWriteLock(&afs_icl_lock);
1365 code = (*aproc) (tp->name, arock, (struct afs_icl_log *)tp);
1366 ObtainWriteLock(&afs_icl_lock, 206);
1367 np = tp->nextp; /* tp may disappear next, but not np */
1368 if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
1373 ReleaseWriteLock(&afs_icl_lock);
1378 afs_icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
1383 ObtainWriteLock(&setp->lock, 207);
1384 for (i = 0; i < ICL_LOGSPERSET; i++) {
1385 if (!setp->logs[i]) {
1386 setp->logs[i] = newlogp;
1388 afs_icl_LogHold(newlogp);
1389 if (!(setp->states & ICL_SETF_FREED)) {
1390 /* bump up the number of sets using the log */
1391 afs_icl_LogUse(newlogp);
1396 ReleaseWriteLock(&setp->lock);
1401 afs_icl_SetSetStat(struct afs_icl_set *setp, int op)
1405 struct afs_icl_log *logp;
1407 ObtainWriteLock(&setp->lock, 208);
1409 case ICL_OP_SS_ACTIVATE: /* activate a log */
1411 * If we are not already active, see if we have released
1412 * our demand that the log be allocated (FREED set). If
1413 * we have, reassert our desire.
1415 if (!(setp->states & ICL_SETF_ACTIVE)) {
1416 if (setp->states & ICL_SETF_FREED) {
1417 /* have to reassert desire for logs */
1418 for (i = 0; i < ICL_LOGSPERSET; i++) {
1419 logp = setp->logs[i];
1421 afs_icl_LogHold(logp);
1422 afs_icl_LogUse(logp);
1423 afs_icl_LogRele(logp);
1426 setp->states &= ~ICL_SETF_FREED;
1428 setp->states |= ICL_SETF_ACTIVE;
1433 case ICL_OP_SS_DEACTIVATE: /* deactivate a log */
1434 /* this doesn't require anything beyond clearing the ACTIVE flag */
1435 setp->states &= ~ICL_SETF_ACTIVE;
1439 case ICL_OP_SS_FREE: /* deassert design for log */
1441 * if we are already in this state, do nothing; otherwise
1442 * deassert desire for log
1444 if (setp->states & ICL_SETF_ACTIVE)
1447 if (!(setp->states & ICL_SETF_FREED)) {
1448 for (i = 0; i < ICL_LOGSPERSET; i++) {
1449 logp = setp->logs[i];
1451 afs_icl_LogHold(logp);
1452 afs_icl_LogFreeUse(logp);
1453 afs_icl_LogRele(logp);
1456 setp->states |= ICL_SETF_FREED;
1465 ReleaseWriteLock(&setp->lock);