1 /* SB - Copyright 1982 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author. In all cases
5 * the source code and any modifications thereto must remain
6 * available to any user.
8 * This is part of the SB library package.
9 * Any software using the SB library must likewise be made
10 * quasi-public, with freely available sources.
13 #define PRINT /* Include printout stuff */
18 extern struct smblk
*sbm_nfl
;
19 extern struct smblk
*sbm_list
;
20 extern struct sdblk
*sbx_nfl
;
23 #define PRF(stmt) {if(p) stmt;}
24 #define PRFBUG(str,stmt) {if(p) stmt;else return(str);}
25 #define PRFBAD(str,stmt) {if(p) stmt; return(str);}
28 #define PRFBUG(str,stmt) return(str);
29 #define PRFBAD(str,stmt) return(str);
33 #define NPTRS (1000) /* Catch loops of period less than this. */
36 int sbe_dec
= 0; /* Set nonzero to use decimal printout */
39 int pt_pflag
; /* Printflag value */
40 char *pt_err
; /* Error string return */
41 int pt_xerr
; /* Error index return */
42 int pt_hidx
; /* Highest freelist entry */
43 int pt_nsto
; /* # entries stored in table */
44 int pt_cnt
; /* # of entry store attempts */
45 struct smblk
*pt_tab
[NPTRS
];
48 _PROTOTYPE( char *sbe_sdtab
, (struct ptab
*pt
, int p
, int phys
) );
49 _PROTOTYPE( char *sbe_schk
, (struct sdblk
*sd
, struct ptab
*pt
) );
50 _PROTOTYPE( int sbe_tbent
, (struct ptab
*pt
, struct smblk
*sm
) );
52 #define PTF_PRF 01 /* Do printout stuff */
53 #define PTF_OVFERR 02 /* Complain if table overflows */
54 #define PTF_SDPHYS 04 /* Follow SD phys links (else logical links) */
61 _PROTOTYPE( char *sbe_fstr
, (int flags
, struct flgt
*fp
) );
63 char *sbe_mvfy(), *sbe_mfl(), *sbe_mlst(); /* SBM */
64 char *sbe_sbvfy(), *sbe_sbs(); /* SBBUF */
65 char *sbe_svfy(), *sbe_sdlist(), *sbe_sdtab(), *sbe_schk(); /* SD */
66 char *sbe_fstr(); /* Misc utility */
69 /* SBE_MEM() - Print out memory usage list
73 printf("\nMemory Usage:\n");
74 printf("\tsbm_nfl : %6o\n",sbm_nfl
);
75 printf("\tsbm_list: %6o\n",sbm_list
);
76 printf("\tsmblk nodes are %o bytes long.\n",sizeof (struct smblk
));
78 sbe_mlst(1); /* Scan mem list, printing stuff. */
81 /* SBE_MVFY() - Verify memory allocation structures
82 * Returns error message (0 if no errors found).
89 || (res
= sbe_mlst(0)))
94 /* SBM Debugging Routines */
96 struct flgt smflgtab
[] = {
105 static char smfhelp
[] = "U-Used, N-NXM, E-External, M-SMnodes, D-SDnodes";
106 static char smhdline
[] = "\
107 SM: back smaddr smlen smuse smflags";
109 /* SBE_MFL(printflag) - Verify/Print memory freelist
110 * Returns error message (0 if no errors found).
115 { register struct smblk
*sm
;
117 struct ptab smtab
; /* For loop detection */
119 PRF(printf("Tracing SM node freelist --\n"))
120 PRF(printf(" Maximum loop detection size is %d.", NPTRS
))
121 if((sm
= sbm_nfl
) == 0)
122 { PRF(printf("\n\tNo list.\n"))
123 return(0); /* Null freelist is ok */
125 smtab
.pt_pflag
= p
? PTF_PRF
: 0;
126 smtab
.pt_nsto
= smtab
.pt_cnt
= 0;
127 i
= 0; /* Print 8 addrs/line */
128 for(; sm
; sm
= sm
->smforw
)
130 PRF(printf("%s%7o->", (i
==0 ? "\n " : ""), sm
))
132 if(sbe_tbent(&smtab
, sm
) < 0) /* If hit loop, stop */
133 PRFBAD("SM freelist loop",
134 printf("\nLOOP - %o seen as node %d!!\n",
137 { PRF((i
= 0, printf("\nFreelist node has flags:\n")))
138 PRFBUG("Free SM flagged", sbe_smp(sm
, 0))
141 PRF(printf("\nEnd - %d nodes on SM freelist.\n", smtab
.pt_cnt
))
145 /* SBE_MLST(printflag) - Verify/Print allocated memory list.
146 * Returns error message (0 if no errors found).
151 { register struct smblk
*sm
, *smf
, *smb
;
152 char *nextaddr
= NULL
;
154 struct ptab smtab
; /* For loop detection */
156 PRF(printf("Tracing mem list -- \n"))
157 if((sm
= sbm_list
) == 0)
158 { PRF(printf("\tNo list?!\n"))
159 if(sbm_nfl
) /* Ensure rest are 0 too */
160 return("No mem list?!!");
165 smtab
.pt_cnt
= smtab
.pt_nsto
= 0;
167 PRF(printf(" Flags: %s\n%s\n", smfhelp
, smhdline
))
169 { PRF(printf(" %6o: ",sm
))
170 if(sbe_tbent(&smtab
, sm
) < 0)
171 PRFBAD("Loop in mem list!!",
172 printf("LOOP - seen as node %d!!\n", smtab
.pt_xerr
))
174 if(sm
->smback
== smb
)
175 PRF(printf("^ ")) /* Back ptr OK */
177 else PRFBUG("Bad back ptr!",
178 printf("%6o BAD Backptr!!\n\t ",sm
->smback
))
180 if((sm
->smflags
&0377)!= SM_NID
)
181 PRFBUG("SM: bad node ID",
182 printf("BAD - no node ID!\n\t "))
183 PRF(printf((sm
->smflags
&SM_USE
) ? " " : "FREE "))
186 printf("Zero-length area!"))
187 if((sm
->smflags
&SM_USE
)==0
188 && rndrem(sm
->smaddr
- sbm_lowaddr
))
189 PRFBUG("Bad free-mem block",
190 printf("Bad free-mem block"))
191 PRF(sbe_smp(sm
, 1)) /* Print out rest of info */
193 if(nextaddr
!= sm
->smaddr
194 && smtab
.pt_cnt
!= 1) /* 1st time needs init */
195 { PRFBUG("Alignment error!",
196 printf("\t BAD!! %6o expected; ",nextaddr
))
198 PRF((i
= sm
->smaddr
- nextaddr
) > 0
199 ? printf("%d skipped.\n",i
)
200 : printf("%d overlapped.\n",-i
))
203 nextaddr
= sm
->smaddr
+ sm
->smlen
;
205 smb
= sm
; /* Save ptr to back */
207 PRF(printf("End = %6o\n",nextaddr
))
213 register struct smblk
*sm
;
217 printf(" %6o: %s ", sm
,
218 ((sm
->smflags
&SM_USE
) ? " " : "FREE"));
219 printf("%6o: ", sm
->smaddr
);
220 printf((sbe_dec
? "%5d. %5d." : "%6o %6o"), sm
->smlen
, sm
->smuse
);
221 printf(" %7o = %s\n", sm
->smflags
, sbe_fstr(sm
->smflags
, smflgtab
));
225 /* SD (SBSTR) debugging routines */
227 struct flgt sdflgtab
[] = {
234 static char sdfhelp
[] = "\
235 <f> flags: *-MOD (disk outofdate), L-LOCK, T-LCK2 (temp)";
236 static char sdhdline
[] = "\
237 <f> SD: slforw slback sdflgs sdforw sdback sdmem sdfile sdaddr sdlen";
240 /* SBE_SFL(printflag) - Verify/Print SD freelist
241 * Returns error message (0 if no errors found).
246 { register struct sdblk
*sd
;
248 struct ptab sdtab
; /* For loop detection */
250 PRF(printf("Tracing SDBLK node freelist --\n"))
251 PRF(printf(" Maximum loop detection size is %d.", NPTRS
))
252 if((sd
= sbx_nfl
) == 0)
253 { PRF(printf("\n\tNo list.\n"))
254 return(0); /* Null freelist is ok */
256 sdtab
.pt_pflag
= p
? PTF_PRF
: 0;
257 sdtab
.pt_nsto
= sdtab
.pt_cnt
= 0;
258 i
= 0; /* Print 8 addrs/line */
259 for(; sd
; sd
= sd
->slforw
)
261 PRF(printf("%s%7o->", (i
==0 ? "\n " : ""), sd
))
263 if(sbe_tbent(&sdtab
, sd
) < 0) /* If hit loop, stop */
264 PRFBAD("SD freelist loop",
265 printf("\nLOOP - %o seen as node %d!!",
268 { PRF((i
= 0, printf("\nFreelist node has flags:\n")))
269 PRFBUG("Free SD flagged", sbe_psd(sd
))
272 PRF(printf("\nEnd - %d nodes on SD freelist.\n", sdtab
.pt_cnt
))
278 /* SBE_SDS() - Print out all sdblk data stuff
283 printf("Printout of all in-use SDBLKs:\n");
284 printf(" %s\n", sdfhelp
);
285 printf("%s\n", sdhdline
);
286 sbm_nfor(SM_DNODS
,sizeof(struct sdblk
),sbe_psd
,0);
290 /* SBE_PSD - Auxiliary for invocation by SBE_SDS above. */
292 register struct sdblk
*sd
;
293 { register int flags
;
297 ((flags
&SD_MOD
) ? '*' : ' '),
298 ((flags
&SD_LOCK
) ? 'L' : ' '),
299 ((flags
&SD_LCK2
) ? 'T' : ' '));
301 printf(" %7o: %6o %6o %6o %6o %6o %6o %6o %7lo %5ld.\n", sd
,
302 sd
->slforw
, sd
->slback
, sd
->sdflags
,
303 sd
->sdforw
, sd
->sdback
, sd
->sdmem
,
304 sd
->sdfile
, sd
->sdaddr
, sd
->sdlen
);
308 /* SBE_SVFY() - Verify all SD blocks
309 * Returns error message (0 if no errors found).
313 { register char *res
;
314 return((res
= sbe_sdlist(0,0)) ? res
: sbe_sdlist(0,1));
317 /* SBE_SDLIST(printflag, physflag) - Verify/Print all SD blocks.
318 * Show logical lists if physflag 0
319 * Show physical lists otherwise
320 * Returns error message (0 if no errors found).
325 { register char *res
;
326 struct ptab sdtab
; /* The SDLIST table to use */
328 /* First put freelist in table, then scan for all
329 * SD nodes. Each active node (not in table) gets
330 * its entire list traced forward/backward and added to table.
332 if(res
= sbe_sdtab(&sdtab
, p
, phys
)) /* Set up freelist table */
335 /* Freelist entered in table, now scan all SD's */
336 res
= (char *)sbm_nfor(SM_DNODS
,sizeof(struct sdblk
),
343 /* SBE_SDTAB(tableptr, printflag, physflag) - Auxiliary for SBE_SDLIST.
344 * Stuffs all freelist SDBLK addresses in table for dup detection.
345 * Returns error message (0 if no errors found).
348 sbe_sdtab(pt
, p
, phys
)
349 register struct ptab
*pt
;
351 { register struct sdblk
*sd
;
353 pt
->pt_pflag
= (p
? PTF_PRF
: 0) | (phys
? PTF_SDPHYS
: 0)
355 pt
->pt_cnt
= pt
->pt_nsto
= 0; /* Initialize */
357 /* Stick freelist in table */
358 for(sd
= sbx_nfl
; sd
; sd
= sd
->slforw
)
359 { if(sbe_tbent(pt
, sd
) < 0)
360 { if(pt
->pt_xerr
< 0)
361 PRFBAD("SD freelist too long",
362 printf("SD freelist too long (%d)\n",
364 PRFBAD("SD freelist loop",
365 printf("SD freelist loop at %o\n", pt
->pt_xerr
))
370 PRF(printf("Bad free SD, non-zero flag:\n"))
371 PRFBUG("Free SD flagged", sbe_psd(sd
))
374 pt
->pt_hidx
= pt
->pt_nsto
; /* Set idx of 1st non-FL entry */
378 /* SBE_SCHK(SDptr, tableptr) - Auxiliary for SBE_SDLIST.
379 * If SD not already in table, verifies or prints
380 * the complete physical or logical list it's on, and enters all
381 * of its SDs into table (to prevent doing it again).
382 * Returns 0 if no errors, else error string.
383 ** There is a problem when the table overflows. The tbent routine
384 ** wants to add it (wrapping around at bottom) in that case, because
385 ** that still helps detect loops. But this routine wants to reset
386 ** the table back (after scanning to head of list) and once it starts
387 ** scanning forward again it will fail, because some of the SDs are
388 ** still in the table due to the wraparound! Thus PTF_OVFERR is always
389 ** set, in order to at least give the right error message.
393 register struct sdblk
*sd
;
395 { register struct sdblk
*sdx
;
396 register struct smblk
*sm
;
397 struct sbfile
*savfile
;
401 phys
= pt
->pt_pflag
&PTF_SDPHYS
; /* Set up physflag */
402 if(phys
&& (sd
->sdfile
== 0)) /* Ignore non-phys stuff if phys */
404 p
= pt
->pt_pflag
&PTF_PRF
; /* Set up printflag */
405 savidx
= pt
->pt_nsto
; /* Remember initial extent of table */
407 if(sbe_tbent(pt
, sd
) < 0)
408 { if(pt
->pt_xerr
>= 0) /* OK if already in table */
410 PRFBAD("Too many SDs",
411 printf("Too many SDs for table (%d)\n", NPTRS
))
414 /* Now search backward for start of list */
415 while(sdx
= (phys
? sd
->sdback
: sd
->slback
))
416 if(sbe_tbent(pt
,sdx
) >= 0)
420 { if(pt
->pt_xerr
< 0) /* Table error? */
421 PRFBAD("Too many SDs",
422 printf("Too many SDs for table (%d)\n",NPTRS
))
423 PRF(printf("Backlist loop!! Dup'd node:%s\n",
424 (pt
->pt_xerr
< pt
->pt_hidx
) ?
425 "(on freelist!)" : "" ))
426 PRFBUG((phys
? "Phys SD loop" : "SD loop"), sbe_psd(sdx
))
428 /* Reset table to flush nodes backed over */
429 pt
->pt_cnt
= pt
->pt_nsto
= savidx
;
431 /* SD now points to start of list. Begin stepping thru list... */
432 PRF(printf("---- %sList started: ", (phys
? "Phys " : "")))
434 { savfile
= sd
->sdfile
;
435 PRF(printf(" SF: %o, fd= %d, ln= %ld\n",
436 savfile
,savfile
->sffd
,savfile
->sflen
))
437 if(savfile
->sfptr1
!= sd
)
439 printf(" BAD!! Sfptr1 %o doesn't match SD %o!!\n",
440 savfile
->sfptr1
, sd
))
443 else PRF(printf("\n"))
445 PRF(printf("%s\n", sdhdline
))
446 for(sdx
= 0; sd
; (sdx
= sd
, sd
= (phys
? sd
->sdforw
: sd
->slforw
)))
448 PRF(sbe_psd(sd
)) /* Print it out */
449 if(sdx
!= (phys
? sd
->sdback
: sd
->slback
))
451 PRFBUG("PSD bad sdback",printf("\tBad phys backptr\n"))
453 PRFBUG("SD bad slback",printf("\tBad backptr\n"))
456 if((sd
->sdflags
&0377) != SD_NID
)
457 PRFBUG("Bad SD node ID", printf("\tBad node ID!\n"))
460 if(sd
->sdfile
&& (sd
->sdlen
< 0 || sd
->sdaddr
< 0))
461 PRFBUG("SD: neg len/addr",
462 printf("\tNeg disk len/addr\n"))
463 if(phys
) goto dophys
;
465 /* Do special stuff for logical list */
467 { if((sm
->smflags
&0377) != SM_NID
)
469 printf("\nBad SMBLK ptr\n"))
470 if((sd
->sdflags
&SD_MOD
)==0
471 && sd
->sdlen
!= sm
->smuse
)
473 printf("\tBad SMBLK? Len conflict\n"))
474 if(sm
->smlen
< sm
->smuse
)
475 PRFBUG("SD: SM len < use",
476 printf("\tBad SMBLK, len < use\n"))
478 goto doboth
; /* Skip phys stuff */
480 /* Do special stuff for phys list */
481 dophys
: if(sd
->sdfile
!= savfile
)
482 PRFBUG("SD: bad sdfile",
483 printf("\tBad sdfile ptr! Shd be %o\n",
485 if(sd
->sdaddr
< lastaddr
)
486 PRFBUG("SD addr out of order",
487 printf("\tBad disk addr, not in order!\n"))
488 lastaddr
= sd
->sdaddr
;
489 /* Done with special phys stuff */
491 doboth
: if(sbe_tbent(pt
, sd
) < 0)
492 { if(pt
->pt_xerr
< 0)
493 PRFBAD("Too many SDs",
494 printf("Too many SDs for table (%d)\n",NPTRS
))
497 printf("\tLOOP!! This SD already seen%s.\n",
498 (pt
->pt_xerr
< pt
->pt_hidx
) ?
499 " (on freelist!)" : "" ))
503 PRF(printf("-----------\n"))
507 /* SBE_DSK(SFptr) - Print out disk usage list for specific file
513 printf("SBFILE printout not coded: %o\n",sfp
);
516 /* SBBUF structure debugging routines */
518 struct flgt sbflgtab
[] = {
523 static char sbfhelp
[] = "O-Overwrite, W-Write";
525 /* SBE_SBVFY(SBptr) - Verify a SB-string.
526 * Returns error message (0 if no errors found).
531 { return(sbe_sbs(sbp
,0));
534 /* SBE_SBS(SBptr, printflag) - Verify/Print SBSTR data stuff
535 * Returns error message (0 if no errors found).
541 { register SBBUF
*sb
;
542 register struct smblk
*sm
;
543 register struct sdblk
*sd
;
546 PRF(printf("SBSTR %o: ",sb
))
548 PRFBUG(0,printf("Zero pointer???\n"))
550 /* First print out cryptic summary in case pointers bomb
552 PRF(printf(" (io,cur,r,w,f,.,+ = %o,%o,%d,%d,%o,%lo,%lo)\n",
553 sb
->sbiop
, sb
->sbcur
, sb
->sbrleft
, sb
->sbwleft
,
554 sb
->sbflags
, sb
->sbdot
, sb
->sboff
))
556 PRF(printf(" sbflags %5o = %s (%s)\n",
557 sb
->sbflags
, sbe_fstr(sb
->sbflags
,sbflgtab
),
560 if(sd
= sb
->sbcur
) /* Okay, now try getting pointers */
564 PRF(printf(" sbcur %6o",sd
))
567 PRF(printf("\n %s\n ", sdhdline
))
570 if((sd
->sdflags
&0377) != SD_NID
)
571 PRFBUG("SBCUR not SD?",printf(" BAD SDBLK ID!! \n"))
574 PRF(printf(" %s\n ", smhdline
))
576 if((sm
->smflags
&0377) != SM_NID
)
577 PRFBUG("SBCUR has bad SM",
578 printf(" BAD SMBLK ID!!\n"))
583 PRF(printf(" sbiop %6o",sb
->sbiop
))
585 { if(!sm
|| sb
->sbiop
< sm
->smaddr
586 || sb
->sbiop
> (sm
->smaddr
+ sm
->smlen
))
587 PRFBUG("Bad SBIOP", printf(" BAD"))
589 else if(sb
->sbrleft
> 0 || sb
->sbwleft
> 0)
590 PRFBUG("Bad SBIOP/cnts", printf(" BAD"))
593 PRF(printf(" sbrleft %5o = %5d.",sb
->sbrleft
, sb
->sbrleft
))
597 || (sb
->sbflags
&SB_WRIT
)
598 || (sb
->sbrleft
!= (sm
->smuse
- (sb
->sbiop
- sm
->smaddr
)))
600 PRFBUG("Bad sbrleft", printf(" BAD"))
603 PRF(printf(" sbwleft %5o = %5d.", sb
->sbwleft
, sb
->sbwleft
))
606 || (sb
->sbflags
&SB_WRIT
) == 0
607 || (sb
->sbwleft
> (sm
->smlen
- (sb
->sbiop
- sm
->smaddr
)))
609 PRFBUG("Bad sbwleft", printf(" BAD"))
612 PRF(printf(" sbdot %7lo = %7ld.", sb
->sbdot
, sb
->sbdot
))
614 PRFBUG("Bad sbdot", printf(" BAD"))
616 PRF(printf("\n sboff %7lo = %7ld.\n", sb
->sboff
, sb
->sboff
))
617 PRF(printf(" I/O ptr loc: %ld.\n\n", sb_tell(sb
)))
622 /* SBE_TBENT() - Auxiliary to add and check entries to a pointer table.
623 * Note we assume here that smblk ptrs are used, although sdblks
624 * can also be hacked. This wins as long as the two kinds of ptrs
625 * are basically identical (saves horrible casting problems).
626 * Returns index # if successful (between 0 and NPTRS-1 inclusive).
627 * Otherwise an error (-1), with relevant info in pt_xerr:
628 * -1 if out of room and flag set making it an error
629 * 0-n if entry already existed.
632 register struct ptab
*pt
;
634 { register struct smblk
**smt
;
638 p
= pt
->pt_pflag
&PTF_PRF
; /* Set up print flag */
639 smt
= &(pt
->pt_tab
[0]);
643 { pt
->pt_xerr
= pt
->pt_nsto
- i
;
651 if(++(pt
->pt_nsto
) > NPTRS
)
652 { if(pt
->pt_pflag
&PTF_OVFERR
)
653 { pt
->pt_err
= "Ptrtab overflow";
664 /* SBE_FSTR(flags, flagtab) - Auxiliary to convert flag word to a string
665 * and return pointer to it. Handy for printfs.
670 register struct flgt
*fp
;
671 { static char retstr
[17]; /* Max of 16 flags */
674 for(; fp
->flg_bit
; ++fp
)
675 *cp
++ = (fp
->flg_bit
&flags
) ? fp
->flg_chr
: ' ';