Demand attach warning fixes
[openafs.git] / src / tviced / state_analyzer.c
1 /*
2  * Copyright 2006, Sine Nomine Associates 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 /*
11  * demand attach fs
12  * fileserver state serialization
13  *
14  * state analyzer
15  */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20
21 #include <stdio.h>
22 #include <errno.h>
23 #include <sys/file.h>
24 #include <netdb.h>
25 #include <netinet/in.h>
26 #include <time.h>
27 #include <string.h>
28
29 #include <afs/stds.h>
30 #include <rx/xdr.h>
31 #include <afs/assert.h>
32 #include <lwp.h>
33 #include <lock.h>
34 #include <afs/afsint.h>
35 #include <afs/rxgen_consts.h>
36 #include <afs/nfs.h>
37 #include <afs/errors.h>
38 #include <afs/ihandle.h>
39 #include <afs/vnode.h>
40 #include <afs/volume.h>
41 #ifdef AFS_ATHENA_STDENV
42 #include <krb.h>
43 #endif
44 #include <afs/acl.h>
45 #include <afs/ptclient.h>
46 #include <afs/prs_fs.h>
47 #include <afs/afsutil.h>
48 #include <rx/rx.h>
49 #include <afs/cellconfig.h>
50 #include <stdlib.h>
51 #include "../util/afsutil_prototypes.h"
52 #include "../viced/viced.h"
53 #include "../viced/host.h"
54 #include "../viced/callback.h"
55 #include "serialize_state.h"
56 #include <fcntl.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <sys/mman.h>
60 #include <unistd.h>
61
62 /*@+fcnmacros +macrofcndecl@*/
63 #ifdef O_LARGEFILE
64 #ifdef S_SPLINT_S
65 extern off64_t afs_lseek(int FD, off64_t O, int F);
66 #endif /*S_SPLINT_S */
67 #define afs_lseek(FD, O, F)     lseek64(FD, (off64_t)(O), F)
68 #define afs_stat                stat64
69 #define afs_fstat               fstat64
70 #define afs_open                open64
71 #define afs_fopen               fopen64
72 #define afs_mmap                mmap64
73 #ifdef AFS_AIX_ENV
74 extern void * mmap64();  /* ugly hack since aix build env appears to be somewhat broken */
75 #endif
76 #else /* !O_LARGEFILE */
77 #ifdef S_SPLINT_S
78 extern off_t afs_lseek(int FD, off_t O, int F);
79 #endif /*S_SPLINT_S */
80 #define afs_lseek(FD, O, F)     lseek(FD, (off_t)(O), F)
81 #define afs_stat                stat
82 #define afs_fstat               fstat
83 #define afs_open                open
84 #define afs_fopen               fopen
85 #define afs_mmap                mmap
86 #endif /* !O_LARGEFILE */
87 /*@=fcnmacros =macrofcndecl@*/
88
89
90 #ifndef AFS_DEMAND_ATTACH_FS
91 int
92 main (int argc, char ** argv)
93 {
94     fprintf(stderr, "%s is only supported for demand attach fileservers\n",
95             argv[0] ? argv[0] : "state analyzer");
96     return 1;
97 }
98 #else /* AFS_DEMAND_ATTACH_FS */
99
100 static void usage(char * prog);
101 static int openFile(char * path);
102 static void initState(void);
103
104 static void banner(void);
105 static void prompt(void);
106
107 static void print_help(void);
108 static void print_global_help(void);
109 static void print_h_help(void);
110 static void print_fe_help(void);
111 static void print_cb_help(void);
112
113 static void dump_hdr(void);
114 static void dump_h_hdr(void);
115 static void dump_cb_hdr(void);
116
117 static void dump_cb_timeout(void);
118 static void dump_cb_fehash(void);
119
120 static void dump_all_hes(void);
121 static void dump_all_fes(void);
122 static void dump_all_cbs(void);
123
124 static void dump_he(afs_uint32 idx);
125 static void dump_fe(afs_uint32 idx);
126 static void dump_cb(afs_uint32 idx);
127 static void dump_this_he(void);
128 static void dump_this_fe(void);
129 static void dump_this_cb(void);
130 static void dump_next_he(void);
131 static void dump_next_fe(void);
132 static void dump_next_cb(void);
133 static void dump_prev_he(void);
134 static void dump_prev_fe(void);
135 static void dump_prev_cb(void);
136 static void dump_first_he(void);
137 static void dump_first_fe(void);
138 static void dump_first_cb(void);
139 static void dump_last_he(void);
140 static void dump_last_fe(void);
141 static void dump_last_cb(void);
142 static void dump_he_hdr(void);
143 static void dump_he_entry(void);
144 static void dump_he_interfaces(void);
145 static void dump_he_hcps(void);
146 static void dump_fe_hdr(void);
147 static void dump_fe_entry(void);
148 static void dump_cb_entry(void);
149
150 static void hexdump_map(afs_uint32 offset, afs_uint32 len);
151
152 static int get_hdr(void);
153 static int get_h_hdr(void);
154 static int get_cb_hdr(void);
155 static int get_cb_timeout_hdr(void);
156 static int get_cb_timeout(void);
157 static int get_cb_fehash_hdr(void);
158 static int get_cb_fehash(void);
159 static int get_he(afs_uint32 idx);
160 static int get_he_hdr(void);
161 static int get_he_entry(void);
162 static int get_fe(afs_uint32 idx);
163 static int get_fe_hdr(void);
164 static int get_fe_entry(void);
165 static int get_cb(afs_uint32 idx);
166 static int get_cb_entry(void);
167
168 static int find_fe_by_index(afs_uint32 idx);
169 static int find_cb_by_index(afs_uint32 idx);
170 static int find_fe_by_fid(afs_uint32 vol, afs_uint32 vn, afs_uint32 uniq);
171
172
173 static int dump_fd = -1;
174 static void * map = NULL;
175 static size_t map_len;
176
177 static struct {
178     struct fs_state_header hdr;
179     struct host_state_header h_hdr;
180     struct callback_state_header cb_hdr;
181     struct callback_state_timeout_header timeout_hdr;
182     struct callback_state_fehash_header fehash_hdr;
183     afs_uint32 * timeout;
184     afs_uint32 * fehash;
185
186     /* pointers into the memory map */
187     void * hdr_p;
188     void * h_hdr_p;
189     void * cb_hdr_p;
190     void * timeout_hdr_p;
191     void * timeout_p;
192     void * fehash_hdr_p;
193     void * fehash_p;
194
195     byte hdr_valid;
196     byte h_hdr_valid;
197     byte cb_hdr_valid;
198     byte timeout_hdr_valid;
199     byte fehash_hdr_valid;
200 } hdrs;
201
202 static struct {
203     void * fh;
204     void * cursor;
205     void * ifp;
206     void * hcps;
207     struct host_state_entry_header hdr;
208     struct hostDiskEntry he;
209     afs_uint32 idx;
210     byte hdr_valid;
211     byte he_valid;
212 } he_cursor;
213
214 static struct {
215     void ** cursor;
216 } he_cache;
217
218 static struct {
219     void * ffe;
220     void * cursor;
221     void * fcb;
222     struct callback_state_entry_header hdr;
223     struct FEDiskEntry fe;
224     afs_uint32 idx;
225     byte hdr_valid;
226     byte fe_valid;
227 } fe_cursor;
228
229 static struct {
230     void ** cursor;
231 } fe_cache;
232
233 static struct {
234     void * cursor;
235     struct CBDiskEntry cb;
236     afs_uint32 idx;
237     byte cb_valid;
238 } cb_cursor;
239
240 static void
241 usage(char * prog)
242 {
243     fprintf(stderr, "usage: %s [<state dump file>]\n", prog);
244 }
245
246 int
247 main(int argc, char ** argv)
248 {
249     banner();
250     if (argc > 2 || (argc == 2 && !strcmp(argv[1], "-h"))) {
251         usage(argv[0]);
252         return 1;
253     }
254
255     initState();
256
257     if (argc > 1) {
258         if (openFile(argv[1]))
259             return 1;
260     } else {
261         if (openFile((char *)AFSDIR_SERVER_FSSTATE_FILEPATH))
262             return 1;
263     }
264
265     prompt();
266     return 0;
267 }
268
269
270 static int
271 openFile(char * path)
272 {
273     int ret = 0;
274     struct afs_stat status;
275     
276     dump_fd = afs_open(path, O_RDWR);
277     if (dump_fd == -1) {
278         fprintf(stderr, "dump file '%s' failed to open\n", path);
279         ret = 1;
280         goto done;
281     }
282
283     printf("opened dump file '%s'\n", path);
284
285     if (afs_fstat(dump_fd, &status) == -1) {
286         fprintf(stderr, "failed to stat file\n");
287         ret = 1;
288         goto done;
289     }
290
291     map_len = status.st_size;
292
293     map = afs_mmap(NULL, map_len, PROT_READ, MAP_SHARED, dump_fd, 0);
294     if (map == MAP_FAILED) {
295         fprintf(stderr, "failed to mmap file\n");
296         ret = 1;
297         goto done;
298     }
299
300     printf("mapped %lu bytes at %"AFS_PTR_FMT"\n", (unsigned long)map_len, map);
301
302  done:
303     if (ret) {
304         if (map) {
305             munmap(map, map_len);
306             map = NULL;
307         }
308         if (dump_fd != -1) {
309             close(dump_fd);
310             dump_fd = -1;
311         }
312     }
313     return ret;
314 }
315
316 static void
317 initState(void)
318 {
319     hdrs.hdr_valid = hdrs.h_hdr_valid = hdrs.cb_hdr_valid = 0;
320     he_cursor.cursor = fe_cursor.cursor = cb_cursor.cursor = NULL;
321     he_cursor.fh = fe_cursor.ffe = fe_cursor.fcb = NULL;
322     he_cache.cursor = fe_cache.cursor = NULL;
323 }
324
325 static void
326 banner(void)
327 {
328     fprintf(stderr, "demand attach fs\n");
329     fprintf(stderr, "fileserver state analyzer\n");
330     fprintf(stderr, "version 0.1\n");
331 }
332
333 #define PROGNAME "fs state analyzer"
334
335 static void
336 prompt(void)
337 {
338     char input[256];
339     char prev_input[256];
340     char * tok = NULL;
341     afs_uint32 x, y, z;
342     enum {
343         PR_GLOBAL_MODE,
344         PR_H_MODE,
345         PR_FE_MODE,
346         PR_CB_MODE
347     } mode = PR_GLOBAL_MODE, next_mode;
348
349     next_mode = mode;
350     input[0] = prev_input[0] = '\0';
351
352     while (1) {
353         if (!tok) {
354             switch(mode) {
355             case PR_GLOBAL_MODE:
356                 printf(PROGNAME "> ");
357                 break;
358             case PR_H_MODE:
359                 printf(PROGNAME ": h(%d)> ", he_cursor.idx);
360                 break;
361             case PR_FE_MODE:
362                 printf(PROGNAME ": fe(%d)> ", fe_cursor.idx);
363                 break;
364             case PR_CB_MODE:
365                 printf(PROGNAME ": fe(%d):cb(%d)> ", fe_cursor.idx, cb_cursor.idx);
366                 break;
367             default:
368                 fprintf(stderr, "prompt state broken; aborting\n");
369                 return;
370             }
371             gets(input);
372
373             if (!strcmp(input, "")) {
374                 /* repeat last command */
375                 if (!strcmp(prev_input, "")) {
376                     continue;
377                 }
378                 strlcpy(input, prev_input, sizeof(input));
379             } else {
380                 /* save command for repetition */
381                 strlcpy(prev_input, input, sizeof(prev_input));
382             }
383
384             tok = strtok(input, " \t");
385         }
386         while (tok && !strcmp(tok, ";")) {
387             tok = strtok(NULL, "; \t");
388         }
389
390         if (!tok) {
391             continue;
392         }
393
394         if (!strcasecmp(tok, "exit")) {
395             return;
396         } else if (!strcasecmp(tok, "quit")) {
397             switch(mode) {
398             case PR_CB_MODE:
399                 next_mode = PR_FE_MODE;
400                 break;
401             case PR_FE_MODE:
402             case PR_H_MODE:
403                 next_mode = PR_GLOBAL_MODE;
404                 break;
405             default:
406                 return;
407             }
408         } else if (!strcasecmp(tok, "h")) {
409             tok = strtok(NULL, " \t");
410             mode = PR_H_MODE;
411             if (!tok) {
412                 next_mode = mode;
413             }
414             continue;
415         } else if (!strcasecmp(tok, "fe")) {
416             tok = strtok(NULL, " \t");
417             mode = PR_FE_MODE;
418             if (!tok) {
419                 next_mode = mode;
420             }
421             continue;
422         } else if (!strcasecmp(tok, "fs")) {
423             tok = strtok(NULL, " \t");
424             mode = PR_GLOBAL_MODE;
425             if (!tok) {
426                 next_mode = mode;
427             }
428             continue;
429         } else if (!strcasecmp(tok, "cb")) {
430             tok = strtok(NULL, " \t");
431             mode = PR_CB_MODE;
432             if (!tok) {
433                 next_mode = mode;
434             }
435             continue;
436         } else if (!strcasecmp(tok, "help")) {
437             switch(mode) {
438             case PR_H_MODE:
439                 print_h_help();
440                 break;
441             case PR_FE_MODE:
442                 print_fe_help();
443                 break;
444             case PR_CB_MODE:
445                 print_cb_help();
446                 break;
447             default:
448                 print_global_help();
449             }
450             print_help();
451         } else if (!strcasecmp(tok, "hexdump")) {
452             tok = strtok(NULL, " \t");
453             if (!tok) {
454                 hexdump_map(0, map_len);
455                 continue;
456             }
457             if (sscanf(tok, "%u", &x) != 1) {
458                 fprintf(stderr, "hexdump parse error 1\n");
459                 tok = NULL;
460                 continue;
461             }
462             tok = strtok(NULL, " \t");
463             if (!tok) {
464                 hexdump_map(x, map_len - x);
465                 continue;
466             }
467             if (sscanf(tok, "%u", &y) != 1) {
468                 fprintf(stderr, "hexdump parse error 2\n");
469                 continue;
470             }
471             hexdump_map(x,y);
472         } else if (!strcasecmp(tok, "hdr")) {
473             switch(mode) {
474             case PR_H_MODE:
475                 dump_h_hdr();
476                 break;
477             case PR_FE_MODE:
478                 dump_cb_hdr();
479                 break;
480             case PR_CB_MODE:
481                 dump_this_fe();
482                 break;
483             default:
484                 dump_hdr();
485             }
486         } else if (!strcasecmp(tok, "this")) {
487             switch(mode) {
488             case PR_H_MODE:
489                 dump_this_he();
490                 break;
491             case PR_FE_MODE:
492                 dump_this_fe();
493                 break;
494             case PR_CB_MODE:
495                 dump_this_cb();
496                 break;
497             default:
498                 fprintf(stderr, "command not valid for this mode\n");
499             }
500         } else if (!strcasecmp(tok, "next")) {
501             switch(mode) {
502             case PR_H_MODE:
503                 dump_next_he();
504                 break;
505             case PR_FE_MODE:
506                 dump_next_fe();
507                 break;
508             case PR_CB_MODE:
509                 dump_next_cb();
510                 break;
511             default:
512                 fprintf(stderr, "command not valid for this mode\n");
513             }
514         } else if (!strcasecmp(tok, "prev")) {
515             switch(mode) {
516             case PR_H_MODE:
517                 dump_prev_he();
518                 break;
519             case PR_FE_MODE:
520                 dump_prev_fe();
521                 break;
522             case PR_CB_MODE:
523                 dump_prev_cb();
524                 break;
525             default:
526                 fprintf(stderr, "command not valid for this mode\n");
527             }
528         } else if (!strcasecmp(tok, "first")) {
529             switch(mode) {
530             case PR_H_MODE:
531                 dump_first_he();
532                 break;
533             case PR_FE_MODE:
534                 dump_first_fe();
535                 break;
536             case PR_CB_MODE:
537                 dump_first_cb();
538                 break;
539             default:
540                 fprintf(stderr, "command not valid for this mode\n");
541             }
542         } else if (!strcasecmp(tok, "last")) {
543             switch(mode) {
544             case PR_H_MODE:
545                 dump_last_he();
546                 break;
547             case PR_FE_MODE:
548                 dump_last_fe();
549                 break;
550             case PR_CB_MODE:
551                 dump_last_cb();
552                 break;
553             default:
554                 fprintf(stderr, "command not valid for this mode\n");
555             }
556         } else if (!strcasecmp(tok, "dump")) {
557             switch(mode) {
558             case PR_H_MODE:
559                 dump_all_hes();
560                 break;
561             case PR_FE_MODE:
562                 dump_all_fes();
563                 break;
564             case PR_CB_MODE:
565                 dump_all_cbs();
566                 break;
567             default:
568                 fprintf(stderr, "command not valid for this mode\n");
569             }
570         } else if (!strcasecmp(tok, "find")) {
571             tok = strtok(NULL, " \t");
572             if (!tok || strcasecmp(tok, "by")) {
573                 tok = NULL;
574                 fprintf(stderr, "find syntax error 1 (%s)\n", 
575                         (tok) ? tok : "nil");
576                 continue;
577             }
578             tok = strtok(NULL, " \t");
579             if (!tok) {
580                 fprintf(stderr, "find syntax error 2\n");
581                 continue;
582             }
583             switch(mode) {
584             case PR_H_MODE:
585                 fprintf(stderr, "not implemented yet\n");
586                 break;
587             case PR_FE_MODE:
588                 if (!strcasecmp(tok, "index")) {
589                     tok = strtok(NULL, " \t");
590                     if (!tok || sscanf(tok, "%u", &x) != 1) {
591                         tok = NULL;
592                         fprintf(stderr, "find syntax error 3\n");
593                         continue;
594                     }
595                     if (find_fe_by_index(x)) {
596                         fprintf(stderr, "find returned no results\n");
597                     }
598                 } else if (!strcasecmp(tok, "fid")) {
599                     tok = strtok(NULL, "(), \t");
600                     if (!tok || sscanf(tok, "%u", &x) != 1) {
601                         tok = NULL;
602                         fprintf(stderr, "find syntax error 4\n");
603                         continue;
604                     }
605                     tok = strtok(NULL, "(), \t");
606                     if (!tok || sscanf(tok, "%u", &y) != 1) {
607                         tok = NULL;
608                         fprintf(stderr, "find syntax error 5\n");
609                         continue;
610                     }
611                     tok = strtok(NULL, "(), \t");
612                     if (!tok || sscanf(tok, "%u", &z) != 1) {
613                         tok = NULL;
614                         fprintf(stderr, "find syntax error 6\n");
615                         continue;
616                     }
617                     if (find_fe_by_fid(x,y,z)) {
618                         fprintf(stderr, "find returned no results\n");
619                     }
620                 } else {
621                     fprintf(stderr, "unsupported filter type\n");
622                 }
623                 break;
624             case PR_CB_MODE:
625                 if (!strcasecmp(tok, "index")) {
626                     tok = strtok(NULL, " \t");
627                     if (!tok || sscanf(tok, "%u", &x) != 1) {
628                         tok = NULL;
629                         fprintf(stderr, "find syntax error 3\n");
630                         continue;
631                     }
632                     if (find_cb_by_index(x)) {
633                         fprintf(stderr, "find returned no results\n");
634                     }
635                 } else {
636                     fprintf(stderr, "unsupported filter type\n");
637                 }
638                 break;
639             default:
640                 fprintf(stderr, "find not supported for this menu\n");
641             }
642         } else if (!strcspn(tok, "0123456789")) {
643             if (sscanf(tok, "%u", &x) == 1) {
644                 switch(mode) {
645                 case PR_H_MODE:
646                     dump_he(x);
647                     break;
648                 case PR_FE_MODE:
649                     dump_fe(x);
650                     break;
651                 case PR_CB_MODE:
652                     dump_cb(x);
653                     break;
654                 default:
655                     fprintf(stderr, "command not available from this menu\n");
656                 }
657             } else {
658                 fprintf(stderr, "input parse error ('%s')\n", tok);
659             }
660         } else if (mode == PR_FE_MODE) {
661             if (!strcmp(tok, "timeout")) {
662                 dump_cb_timeout();
663             } else if (!strcmp(tok, "hash")) {
664                 dump_cb_fehash();
665             }
666         } else {
667             fprintf(stderr, "unknown command\n");
668         }
669         tok = strtok(NULL, " \t");
670         mode = next_mode;
671     }
672 }
673
674 static void
675 print_help(void)
676 {
677     printf("\th <...>  -- host menu commands\n");
678     printf("\tfe <...> -- FileEntry menu commands\n");
679     printf("\tcb <...> -- CallBack menu commands\n");
680     printf("\thexdump [<offset> [<len>]]\n\t\t -- hex dump the raw data\n");
681     printf("\tquit     -- quit this menu\n");
682     printf("\texit     -- exit the debugger\n");
683     printf("\thelp     -- this help message\n");
684 }
685
686 static void
687 print_global_help(void)
688 {
689     printf("\thdr      -- display the fs_state_header struct\n");
690 }
691
692 static void
693 print_h_help(void)
694 {
695     printf("\thdr      -- display the host_state_header struct\n");
696     printf("\tfirst    -- display the first host\n");
697     printf("\tprev     -- display the previous host\n");
698     printf("\tthis     -- display this host\n");
699     printf("\tnext     -- display the next host\n");
700     printf("\tlast     -- display the last host\n");
701     printf("\tdump     -- display all hosts\n");
702 }
703
704 static void
705 print_fe_help(void)
706 {
707     printf("\thdr      -- display the callback_state_header struct\n");
708     printf("\tfirst    -- display the first FE\n");
709     printf("\tprev     -- display the previous FE\n");
710     printf("\tthis     -- display this FE\n");
711     printf("\tnext     -- display the next FE\n");
712     printf("\tlast     -- display the last FE\n");
713     printf("\tdump     -- display all FEs\n");
714     printf("\ttimeout  -- display the timeout queue heads\n");
715     printf("\thash   -- display the file entry hash buckets\n");
716     printf("\tfind by index <id>\n\t\t -- find an fe by its array index\n");
717     printf("\tfind by fid <(vol,vnode,unique)>\n\t\t -- find an fe by its AFSFid\n");
718 }
719
720 static void
721 print_cb_help(void)
722 {
723     printf("\thdr      -- display the callback_state_entry_header struct\n");
724     printf("\tfirst    -- display the first CB\n");
725     printf("\tprev     -- display the previous CB\n");
726     printf("\tthis     -- display this CB\n");
727     printf("\tnext     -- display the next CB\n");
728     printf("\tlast     -- display the last CB\n");
729     printf("\tdump     -- display all CBs\n");
730 }
731
732 #define DPFTB0 "\t"
733 #define DPFTB1 "\t\t"
734 #define DPFTB2 "\t\t\t"
735
736 #define DPFOFF(addr) \
737     do { \
738         char * _p = (char *)addr; \
739         char * _m = (char *)map; \
740         printf("loading structure from address %"AFS_PTR_FMT" (offset %u)\n", \
741                addr, _p-_m); \
742     } while (0)
743
744 /* structs */
745 #define DPFSO(T, name) printf(T "%s = {\n", name)
746 #define DPFSO0(name) DPFSO(DPFTB0, name)
747 #define DPFSO1(name) DPFSO(DPFTB1, name)
748 #define DPFSC(T) printf(T "}\n")
749 #define DPFSC0 DPFSC(DPFTB0)
750 #define DPFSC1 DPFSC(DPFTB1)
751
752 /* arrays */
753 #define DPFAO(T1, T2, name) printf(T1 "%s =\n" T2 "{ ", name)
754 #define DPFAO0(name) DPFAO(DPFTB0, DPFTB1, name)
755 #define DPFAO1(name) DPFAO(DPFTB1, DPFTB2, name)
756 #define DPFAC0 printf(" }\n")
757 #define DPFAC1 DPFAC0
758 #define DPFA1 printf(DPFTB1 "  ")
759 #define DPFA2 printf(DPFTB2 "  ")
760 #define DPFAN printf("\n")
761 #define DPFALE(type, var) printf("%" type, var)
762 #define DPFAE(type, var) printf("%" type ",\t", var)
763
764 /* normal vars */
765 #define DPFV(T, name, type, var) printf(T "%s = %" type "\n", name, var)
766 #define DPFV1(name, type, var) DPFV(DPFTB1, name, type, var)
767 #define DPFV2(name, type, var) DPFV(DPFTB2, name, type, var)
768
769 /* hex */
770 #define DPFX(T, name, var) printf(T "%s = 0x%x\n", name, var)
771 #define DPFX1(name, var) DPFX(DPFTB1, name, var)
772 #define DPFX2(name, var) DPFX(DPFTB2, name, var)
773
774 /* strings */
775 #define DPFS(T, name, var) printf(T "%s = \"%s\"\n", name, var)
776 #define DPFS1(name, var) DPFS(DPFTB1, name, var)
777 #define DPFS2(name, var) DPFS(DPFTB2, name, var)
778
779 /* time */
780 #define DPFT(T, name, var) \
781     do { \
782         time_t t = var; \
783         printf(T "%s = \"%.24s\"\n", name, ctime(&t)); \
784     } while(0)
785 #define DPFT1(name, var) DPFT(DPFTB1, name, var)
786 #define DPFT2(name, var) DPFT(DPFTB2, name, var)
787
788 static void
789 dump_hdr(void)
790 {
791     char uuid_str[40];
792     afs_uint32 hi, lo;
793
794     if (get_hdr())
795         return;
796
797     DPFOFF(map);
798     DPFSO0("fs_state_header");
799     DPFSO1("stamp");
800     DPFX2("magic", hdrs.hdr.stamp.magic);
801     DPFV2("version", "u", hdrs.hdr.stamp.version);
802     DPFSC1;
803     DPFT1("timestamp", hdrs.hdr.timestamp);
804     DPFV1("sys_name", "u", hdrs.hdr.sys_name);
805
806     afsUUID_to_string(&hdrs.hdr.server_uuid, uuid_str, sizeof(uuid_str));
807     DPFS1("server_uuid", uuid_str);
808     DPFV1("valid", "d", hdrs.hdr.valid);
809     DPFV1("endianness", "d", hdrs.hdr.endianness);
810     DPFV1("stats_detailed", "d", hdrs.hdr.stats_detailed);
811
812     SplitInt64(hdrs.hdr.h_offset, hi, lo);
813     DPFSO1("h_offset");
814     DPFV2("hi", "u", hi);
815     DPFV2("lo", "u", lo);
816     DPFSC1;
817
818     SplitInt64(hdrs.hdr.cb_offset, hi, lo);
819     DPFSO1("cb_offset");
820     DPFV2("hi", "u", hi);
821     DPFV2("lo", "u", lo);
822     DPFSC1;
823
824     DPFS1("server_version_string", hdrs.hdr.server_version_string);
825     DPFSC0;
826
827     if (hdrs.hdr.stamp.magic != FS_STATE_MAGIC) {
828         fprintf(stderr, "* magic check failed\n");
829     }
830     if (hdrs.hdr.stamp.version != FS_STATE_VERSION) {
831         fprintf(stderr, "* version check failed\n");
832     }
833 }
834
835 static void
836 dump_h_hdr(void)
837 {
838     if (get_h_hdr())
839         return;
840
841     DPFOFF(hdrs.h_hdr_p);
842     DPFSO0("host_state_header");
843     DPFSO1("stamp");
844     DPFX2("magic", hdrs.h_hdr.stamp.magic);
845     DPFV2("version", "u", hdrs.h_hdr.stamp.version);
846     DPFSC1;
847     DPFV1("records", "u", hdrs.h_hdr.records);
848     DPFV1("index_max", "u", hdrs.h_hdr.index_max);
849     DPFSC0;
850
851     if (hdrs.h_hdr.stamp.magic != HOST_STATE_MAGIC) {
852         fprintf(stderr, "* magic check failed\n");
853     }
854     if (hdrs.h_hdr.stamp.version != HOST_STATE_VERSION) {
855         fprintf(stderr, "* version check failed\n");
856     }
857 }
858
859 static void
860 dump_cb_hdr(void)
861 {
862     afs_uint32 hi, lo;
863
864     if (get_cb_hdr())
865         return;
866
867     DPFOFF(hdrs.cb_hdr_p);
868     DPFSO0("callback_state_header");
869     DPFSO1("stamp");
870     DPFX2("magic", hdrs.cb_hdr.stamp.magic);
871     DPFV2("version", "u", hdrs.cb_hdr.stamp.version);
872     DPFSC1;
873     DPFV1("nFEs", "u", hdrs.cb_hdr.nFEs);
874     DPFV1("nCBs", "u", hdrs.cb_hdr.nCBs);
875     DPFV1("fe_max", "u", hdrs.cb_hdr.fe_max);
876     DPFV1("cb_max", "u", hdrs.cb_hdr.cb_max);
877     DPFV1("tfirst", "d", hdrs.cb_hdr.tfirst);
878
879     SplitInt64(hdrs.cb_hdr.timeout_offset, hi, lo);
880     DPFSO1("timeout_offset");
881     DPFV2("hi", "u", hi);
882     DPFV2("lo", "u", lo);
883     DPFSC1;
884
885     SplitInt64(hdrs.cb_hdr.fehash_offset, hi, lo);
886     DPFSO1("fehash_offset");
887     DPFV2("hi", "u", hi);
888     DPFV2("lo", "u", lo);
889     DPFSC1;
890
891     SplitInt64(hdrs.cb_hdr.fe_offset, hi, lo);
892     DPFSO1("fe_offset");
893     DPFV2("hi", "u", hi);
894     DPFV2("lo", "u", lo);
895     DPFSC1;
896
897     DPFSC0;
898
899     if (hdrs.cb_hdr.stamp.magic != CALLBACK_STATE_MAGIC) {
900         fprintf(stderr, "* magic check failed\n");
901     }
902     if (hdrs.cb_hdr.stamp.version != CALLBACK_STATE_VERSION) {
903         fprintf(stderr, "* version check failed\n");
904     }
905 }
906
907 static void
908 dump_cb_timeout(void)
909 {
910     int i;
911
912     if (get_cb_hdr())
913         return;
914
915     if (get_cb_timeout_hdr())
916         return;
917
918     if (get_cb_timeout())
919         return;
920
921     DPFOFF(hdrs.timeout_hdr_p);
922     DPFSO0("callback_state_timeout_header");
923     DPFX1("magic", hdrs.timeout_hdr.magic);
924     DPFV1("len", "u", hdrs.timeout_hdr.len);
925     DPFV1("records", "u", hdrs.timeout_hdr.records);
926     DPFSC0;
927
928     if (hdrs.timeout_hdr.magic != CALLBACK_STATE_TIMEOUT_MAGIC) {
929         fprintf(stderr, "* magic check failed\n");
930     }
931
932     DPFOFF(hdrs.timeout_p);
933     DPFAO0("timeout");
934     for (i = 0; i < 127; i++) {
935         DPFAE("u", hdrs.timeout[i]);
936         if ((i % 8) == 7) {
937             DPFAN;
938             DPFA1;
939         }
940     }
941     DPFALE("u", hdrs.timeout[127]);
942     DPFAC0;
943 }
944
945 static void
946 dump_cb_fehash(void)
947 {
948     int i;
949
950     if (get_cb_hdr())
951         return;
952
953     if (get_cb_fehash_hdr())
954         return;
955
956     if (get_cb_fehash())
957         return;
958
959     DPFOFF(hdrs.fehash_hdr_p);
960     DPFSO0("callback_state_fehash_header");
961     DPFX1("magic", hdrs.fehash_hdr.magic);
962     DPFV1("len", "u", hdrs.fehash_hdr.len);
963     DPFV1("records", "u", hdrs.fehash_hdr.records);
964     DPFSC0;
965
966     if (hdrs.fehash_hdr.magic != CALLBACK_STATE_FEHASH_MAGIC) {
967         fprintf(stderr, "* magic check failed\n");
968     }
969
970     DPFOFF(hdrs.fehash_p);
971     DPFAO0("fehash");
972     for (i = 0; i < hdrs.fehash_hdr.records - 1; i++) {
973         DPFAE("u", hdrs.fehash[i]);
974         if ((i % 8) == 7) {
975             DPFAN;
976             DPFA1;
977         }
978     }
979     DPFALE("u", hdrs.fehash[hdrs.fehash_hdr.records-1]);
980     DPFAC0;
981 }
982
983 static void
984 dump_all_hes(void)
985 {
986     int i;
987
988     if (get_h_hdr()) {
989         fprintf(stderr, "error getting host_state_header\n");
990         return;
991     }
992
993     for (i = 0; i < hdrs.h_hdr.records; i++) {
994         dump_he(i);
995     }
996 }
997
998 static void
999 dump_all_fes(void)
1000 {
1001     int i;
1002
1003     if (get_cb_hdr()) {
1004         fprintf(stderr, "error getting callback_state_header\n");
1005         return;
1006     }
1007
1008     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1009         dump_fe(i);
1010     }
1011 }
1012
1013 static void
1014 dump_all_cbs(void)
1015 {
1016     int i;
1017
1018     if (get_fe_hdr()) {
1019         fprintf(stderr, "error getting callback_state_entry_header\n");
1020         return;
1021     }
1022
1023     for (i = 0; i < fe_cursor.hdr.nCBs; i++) {
1024         dump_cb(i);
1025     }
1026 }
1027
1028 static void
1029 dump_he(afs_uint32 idx)
1030 {
1031     if (get_he(idx)) {
1032         fprintf(stderr, "error getting he %d\n", idx);
1033         return;
1034     }
1035
1036     DPFOFF(he_cursor.cursor);
1037     dump_he_hdr();
1038     dump_he_entry();
1039     dump_he_interfaces();
1040     dump_he_hcps();
1041 }
1042
1043 static void
1044 dump_fe(afs_uint32 idx)
1045 {
1046     if (get_fe(idx)) {
1047         fprintf(stderr, "error getting fe %d\n", idx);
1048         return;
1049     }
1050
1051     DPFOFF(fe_cursor.cursor);
1052     dump_fe_hdr();
1053     dump_fe_entry();
1054 }
1055
1056 static void
1057 dump_cb(afs_uint32 idx)
1058 {
1059     if (get_cb(idx)) {
1060         fprintf(stderr, "error getting cb %d\n", idx);
1061         return;
1062     }
1063
1064     DPFOFF(cb_cursor.cursor);
1065     dump_cb_entry();
1066 }
1067
1068 static void
1069 dump_this_he(void)
1070 {
1071     dump_he(he_cursor.idx);
1072 }
1073
1074 static void
1075 dump_this_fe(void)
1076 {
1077     dump_fe(fe_cursor.idx);
1078 }
1079
1080 static void
1081 dump_this_cb(void)
1082 {
1083     dump_cb(cb_cursor.idx);
1084 }
1085
1086 static void
1087 dump_next_he(void)
1088 {
1089     if (get_h_hdr()) {
1090         fprintf(stderr, "error getting host_state_header\n");
1091         return;
1092     }
1093
1094     if ((he_cursor.idx + 1) >= hdrs.h_hdr.records) {
1095         fprintf(stderr, "no more HEs\n");
1096         return;
1097     }
1098     
1099     dump_he(he_cursor.idx+1);
1100 }
1101
1102 static void
1103 dump_next_fe(void)
1104 {
1105     if (get_cb_hdr()) {
1106         fprintf(stderr, "error getting callback_state_header\n");
1107         return;
1108     }
1109
1110     if ((fe_cursor.idx + 1) >= hdrs.cb_hdr.nFEs) {
1111         fprintf(stderr, "no more FEs\n");
1112         return;
1113     }
1114     
1115     dump_fe(fe_cursor.idx+1);
1116 }
1117
1118 static void
1119 dump_next_cb(void)
1120 {
1121     if (get_fe_hdr()) {
1122         fprintf(stderr, "error getting callback_state_entry_header\n");
1123         return;
1124     }
1125
1126     if ((cb_cursor.idx + 1) >= fe_cursor.hdr.nCBs) {
1127         fprintf(stderr, "no more CBs\n");
1128         return;
1129     }
1130     
1131     dump_cb(cb_cursor.idx+1);
1132 }
1133
1134 static void
1135 dump_prev_he(void)
1136 {
1137     if (!he_cursor.idx) {
1138         fprintf(stderr, "no more HEs\n");
1139         return;
1140     }
1141     
1142     dump_he(he_cursor.idx-1);
1143 }
1144
1145 static void
1146 dump_prev_fe(void)
1147 {
1148     if (!fe_cursor.idx) {
1149         fprintf(stderr, "no more FEs\n");
1150         return;
1151     }
1152     
1153     dump_fe(fe_cursor.idx-1);
1154 }
1155
1156 static void
1157 dump_prev_cb(void)
1158 {
1159     if (!cb_cursor.idx) {
1160         fprintf(stderr, "no more CBs\n");
1161         return;
1162     }
1163     
1164     dump_cb(cb_cursor.idx-1);
1165 }
1166
1167 static void
1168 dump_first_fe(void)
1169 {
1170     if (get_cb_hdr()) {
1171         fprintf(stderr, "error getting callback_state_header\n");
1172         return;
1173     }
1174
1175     if (!hdrs.cb_hdr.nFEs) {
1176         fprintf(stderr, "no FEs present\n");
1177         return;
1178     }
1179     
1180     dump_fe(0);
1181 }
1182
1183 static void
1184 dump_first_he(void)
1185 {
1186     if (get_h_hdr()) {
1187         fprintf(stderr, "error getting host_state_header\n");
1188         return;
1189     }
1190
1191     if (!hdrs.h_hdr.records) {
1192         fprintf(stderr, "no HEs present\n");
1193         return;
1194     }
1195     
1196     dump_he(0);
1197 }
1198
1199 static void
1200 dump_first_cb(void)
1201 {
1202     if (get_fe_hdr()) {
1203         fprintf(stderr, "error getting callback_state_entry_header\n");
1204         return;
1205     }
1206
1207     if (!fe_cursor.hdr.nCBs) {
1208         fprintf(stderr, "no CBs present\n");
1209         return;
1210     }
1211     
1212     dump_cb(0);
1213 }
1214
1215 static void
1216 dump_last_he(void)
1217 {
1218     if (get_h_hdr()) {
1219         fprintf(stderr, "error getting host_state_header\n");
1220         return;
1221     }
1222
1223     if (!hdrs.h_hdr.records) {
1224         fprintf(stderr, "no HEs present\n");
1225         return;
1226     }
1227     
1228     dump_he(hdrs.h_hdr.records-1);
1229 }
1230
1231 static void
1232 dump_last_fe(void)
1233 {
1234     if (get_cb_hdr()) {
1235         fprintf(stderr, "error getting callback_state_header\n");
1236         return;
1237     }
1238
1239     if (!hdrs.cb_hdr.nFEs) {
1240         fprintf(stderr, "no FEs present\n");
1241         return;
1242     }
1243     
1244     dump_fe(hdrs.cb_hdr.nFEs-1);
1245 }
1246
1247 static void
1248 dump_last_cb(void)
1249 {
1250     if (get_fe_hdr()) {
1251         fprintf(stderr, "error getting callback_state_entry_header\n");
1252         return;
1253     }
1254
1255     if (!fe_cursor.hdr.nCBs) {
1256         fprintf(stderr, "no CBs present\n");
1257         return;
1258     }
1259
1260     dump_cb(fe_cursor.hdr.nCBs-1);
1261 }
1262
1263 static void
1264 dump_he_hdr(void)
1265 {
1266     DPFSO0("host_state_entry_header");
1267     DPFX1("magic", he_cursor.hdr.magic);
1268     DPFV1("len", "u", he_cursor.hdr.len);
1269     DPFV1("interfaces", "u", he_cursor.hdr.interfaces);
1270     DPFV1("hcps", "u", he_cursor.hdr.hcps);
1271     DPFSC0;
1272
1273     if (he_cursor.hdr.magic != HOST_STATE_ENTRY_MAGIC) {
1274         fprintf(stderr, "* magic check failed\n");
1275     }
1276 }
1277
1278 static void
1279 dump_he_entry(void)
1280 {
1281     DPFSO0("hostDiskEntry");
1282     DPFS1("host", afs_inet_ntoa(he_cursor.he.host));
1283     DPFV1("port", "u", he_cursor.he.port);
1284     DPFX1("hostFlags", he_cursor.he.hostFlags);
1285     DPFV1("Console", "u", he_cursor.he.Console);
1286     DPFV1("hcpsfailed", "u", he_cursor.he.hcpsfailed);
1287     DPFV1("hcps_valid", "u", he_cursor.he.hcps_valid);
1288     if (hdrs.hdr.stats_detailed) {
1289 #ifdef FS_STATS_DETAILED
1290         DPFV1("InSameNetwork", "u", he_cursor.he.InSameNetwork);
1291 #else
1292         DPFV1("InSameNetwork", "u", he_cursor.he.padding1[0]);
1293 #endif
1294     }
1295     DPFV1("hcps_len", "u", he_cursor.he.hcps_len);
1296     DPFT1("LastCall", he_cursor.he.LastCall);
1297     DPFT1("ActiveCall", he_cursor.he.ActiveCall);
1298     DPFT1("cpsCall", he_cursor.he.cpsCall);
1299     DPFV1("cblist", "u", he_cursor.he.cblist);
1300     DPFV1("index", "u", he_cursor.he.index);
1301     DPFSC0;
1302 }
1303
1304 static void
1305 dump_he_interfaces(void)
1306 {
1307     char temp_str[40];
1308     struct Interface * ifp;
1309     int len, i;
1310
1311     if (!he_cursor.hdr.interfaces)
1312         return;
1313
1314     len = sizeof(struct Interface) + ((he_cursor.hdr.interfaces-1)*sizeof(struct AddrPort));
1315     ifp = (struct Interface *) malloc(len);
1316     assert(ifp != NULL);
1317
1318     memcpy(ifp, he_cursor.ifp, len);
1319
1320     DPFSO0("Interface");
1321     DPFV1("numberOfInterfaces", "u", ifp->numberOfInterfaces);
1322
1323     afsUUID_to_string(&ifp->uuid, temp_str, sizeof(temp_str));
1324     DPFS1("uuid", temp_str);
1325     for (i = 0; i < he_cursor.hdr.interfaces; i++) {
1326         snprintf(temp_str, sizeof(temp_str), "interface[%d]", i);
1327         DPFSO1(temp_str);
1328         DPFS2("addr", afs_inet_ntoa(ifp->interface[i].addr));
1329         DPFV2("port", "u", ifp->interface[i].port);
1330         DPFSC1;
1331     }
1332
1333     DPFSC0;
1334
1335     if (he_cursor.hdr.interfaces != ifp->numberOfInterfaces) {
1336         fprintf(stderr, "* interface count mismatch between header and Interface struct\n");
1337     }
1338     free(ifp);
1339 }
1340
1341 static void
1342 dump_he_hcps(void)
1343 {
1344     afs_int32 * hcps;
1345     int len, i;
1346
1347     if (!he_cursor.hdr.hcps)
1348         return;
1349
1350     len = (he_cursor.hdr.hcps)*sizeof(afs_uint32);
1351     hcps = (afs_int32 *) malloc(len);
1352     assert(hcps != NULL);
1353     memcpy(hcps, he_cursor.hcps, len);
1354
1355     DPFSO0("hcps");
1356     DPFAO1("prlist_val");
1357     for (i = 0; i < he_cursor.hdr.hcps - 1; i++) {
1358         DPFAE("d", hcps[i]);
1359         if ((i % 8) == 7) {
1360             DPFAN;
1361             DPFA2;
1362         }
1363     }
1364     DPFALE("d", hcps[he_cursor.hdr.hcps-1]);
1365     DPFAC1;
1366     DPFSC0;
1367     free(hcps);
1368 }
1369
1370 static void
1371 dump_fe_hdr(void)
1372 {
1373     DPFSO0("callback_state_entry_header");
1374     DPFX1("magic", fe_cursor.hdr.magic);
1375     DPFV1("len", "u", fe_cursor.hdr.len);
1376     DPFV1("nCBs", "u", fe_cursor.hdr.nCBs);
1377     DPFSC0;
1378
1379     if (fe_cursor.hdr.magic != CALLBACK_STATE_ENTRY_MAGIC) {
1380         fprintf(stderr, "* magic check failed\n");
1381     }
1382 }
1383
1384 static void
1385 dump_fe_entry(void)
1386 {
1387     DPFSO0("FEDiskEntry");
1388     DPFSO1("fe");
1389     DPFV2("vnode", "u", fe_cursor.fe.fe.vnode);
1390     DPFV2("unique", "u", fe_cursor.fe.fe.unique);
1391     DPFV2("volid", "u", fe_cursor.fe.fe.volid);
1392     DPFV2("fnext", "u", fe_cursor.fe.fe.fnext);
1393     DPFV2("ncbs", "u", fe_cursor.fe.fe.ncbs);
1394     DPFV2("firstcb", "u", fe_cursor.fe.fe.firstcb);
1395     DPFV2("status", "u", fe_cursor.fe.fe.status);
1396     DPFSC1;
1397     DPFV1("index", "u", fe_cursor.fe.index);
1398     DPFSC0;
1399 }
1400
1401 static void
1402 dump_cb_entry(void)
1403 {
1404     DPFSO0("CBDiskEntry");
1405     DPFSO1("cb");
1406     DPFV2("cnext", "u", cb_cursor.cb.cb.cnext);
1407     DPFV2("fhead", "u", cb_cursor.cb.cb.fhead);
1408     DPFV2("thead", "u", (afs_uint32)cb_cursor.cb.cb.thead);
1409     DPFV2("status", "u", (afs_uint32)cb_cursor.cb.cb.status);
1410     DPFV2("hhead", "u", cb_cursor.cb.cb.hhead);
1411     DPFV2("tprev", "u", cb_cursor.cb.cb.tprev);
1412     DPFV2("tnext", "u", cb_cursor.cb.cb.tnext);
1413     DPFV2("hprev", "u", cb_cursor.cb.cb.hprev);
1414     DPFV2("hnext", "u", cb_cursor.cb.cb.hnext);
1415     DPFSC1;
1416     DPFV1("index", "u", cb_cursor.cb.index);
1417     DPFSC0;
1418 }
1419
1420 #define DPFHMS printf("  ")
1421 #define DPFHS printf("    ")
1422 #define DPFHN(offset) printf("\n%u\t", offset)
1423 #define DPFHD(x) printf("%02X  ", x)
1424 #define DPFHE printf("\n")
1425
1426 static void
1427 hexdump_map(afs_uint32 offset, afs_uint32 len)
1428 {
1429     int i;
1430     unsigned char * p = (unsigned char *)map;
1431
1432     if (!len)
1433         return;
1434
1435     if ((offset + len) > map_len) {
1436         fprintf(stderr, "offset + length exceeds memory map size (%u > %lu)\n",
1437                 offset+len, (unsigned long)map_len);
1438         return;
1439     }
1440
1441     p += offset;
1442     DPFOFF(p);
1443     DPFHN(offset);
1444
1445     for (i = offset % 16; i > 0; i--) {
1446         DPFHS;
1447     }
1448
1449     for (i=0; i < len; i++, p++, offset++) {
1450         if (!(offset % 16)) {
1451             DPFHN(offset);
1452         } else if (!(offset % 8)) {
1453             DPFHMS;
1454         }
1455         DPFHD(*p);
1456     }
1457     DPFHE;
1458 }
1459
1460 static int
1461 get_hdr(void)
1462 {
1463     if (!hdrs.hdr_valid) {
1464         if (map_len < sizeof(struct fs_state_header)) {
1465             fprintf(stderr, "corrupt state dump: fs_state_header larger than memory map\n");
1466             return 1;
1467         }
1468         memcpy(&hdrs.hdr, map, sizeof(hdrs.hdr));
1469         hdrs.hdr_p = map;
1470         hdrs.hdr_valid = 1;
1471     }
1472     return 0;
1473 }
1474
1475 static int
1476 get_h_hdr(void)
1477 {
1478     char * buf;
1479     afs_uint32 hi, lo;
1480
1481     if (hdrs.h_hdr_valid)
1482         return 0;
1483
1484     if (get_hdr())
1485         return 1;
1486
1487     SplitInt64(hdrs.hdr.h_offset, hi, lo);
1488
1489     if (hi) {
1490         fprintf(stderr, "hi offset bits set in h_offset; can't get host_state_header\n");
1491         return 1;
1492     }
1493     if ((lo >= map_len) || 
1494         ((lo + sizeof(struct host_state_header)) > map_len) ||
1495         (lo + sizeof(struct host_state_header) < lo)) {
1496         fprintf(stderr, "h_offset puts host_state_header beyond end of memory map\n");
1497         return 1;
1498     }
1499
1500     buf = (char *) map;
1501     buf += lo;
1502     memcpy(&hdrs.h_hdr, buf, sizeof(struct host_state_header));
1503     hdrs.h_hdr_p = buf;
1504     buf += sizeof(struct host_state_header);
1505     he_cursor.fh = (void *)buf;
1506     return 0;
1507 }
1508
1509 static int
1510 get_cb_hdr(void)
1511 {
1512     char * buf;
1513     afs_uint32 hi, lo;
1514
1515     if (hdrs.cb_hdr_valid)
1516         return 0;
1517
1518     if (get_hdr())
1519         return 1;
1520
1521     SplitInt64(hdrs.hdr.cb_offset, hi, lo);
1522
1523     if (hi) {
1524         fprintf(stderr, "hi offset bits set in cb_offset; can't get callback_state_header\n");
1525         return 1;
1526     }
1527     if ((lo >= map_len) || 
1528         ((lo + sizeof(struct callback_state_header)) > map_len) ||
1529         (lo + sizeof(struct callback_state_header) < lo)) {
1530         fprintf(stderr, "cb_offset puts callback_state_header beyond end of memory map\n");
1531         return 1;
1532     }
1533
1534     buf = (char *) map;
1535     buf += lo;
1536     memcpy(&hdrs.cb_hdr, buf, sizeof(struct callback_state_header));
1537     hdrs.cb_hdr_p = buf;
1538     hdrs.cb_hdr_valid = 1;
1539
1540     SplitInt64(hdrs.cb_hdr.fe_offset, hi, lo);
1541
1542     if (hi) {
1543         fprintf(stderr, "hi offset bits set in fe_offset; can't get callback_state_entry_header\n");
1544         return 1;
1545     }
1546     hi = lo + (hdrs.cb_hdr.nFEs * (sizeof(struct callback_state_entry_header) +
1547                                   sizeof(struct FEDiskEntry)) +
1548                hdrs.cb_hdr.nCBs * sizeof(struct CBDiskEntry));
1549     if ((hi > map_len) ||
1550         (lo > hi)) {
1551         fprintf(stderr, "fe_offset puts callback_state_entry_header beyond end of memory map\n");
1552         return 1;
1553     }
1554
1555     buf = (char *) map;
1556     buf += lo;
1557     fe_cursor.ffe = (void *)buf;
1558
1559     return 0;
1560 }
1561
1562 static int
1563 get_cb_timeout_hdr(void)
1564 {
1565     char * buf;
1566     afs_uint32 hi, lo;
1567
1568     if (hdrs.timeout_hdr_valid)
1569         return 0;
1570
1571     if (get_cb_hdr())
1572         return 1;
1573
1574     SplitInt64(hdrs.cb_hdr.timeout_offset, hi, lo);
1575
1576     if (hi) {
1577         fprintf(stderr, "hi offset bits set in timeout_offset; can't get callback_state_timeout_header\n");
1578         return 1;
1579     }
1580     if ((lo >= map_len) || 
1581         ((lo + sizeof(struct callback_state_timeout_header)) > map_len) ||
1582         (lo + sizeof(struct callback_state_timeout_header) < lo)) {
1583         fprintf(stderr, "timeout_offset puts callback_state_timeout_header beyond end of memory map\n");
1584         return 1;
1585     }
1586
1587     buf = (char *) map;
1588     buf += lo;
1589     memcpy(&hdrs.timeout_hdr, buf, sizeof(struct callback_state_timeout_header));
1590     hdrs.timeout_hdr_p = buf;
1591     hdrs.timeout_hdr_valid = 1;
1592     buf += sizeof(struct callback_state_timeout_header);
1593     hdrs.timeout_p = buf;
1594
1595     return 0;
1596 }
1597
1598 static int
1599 get_cb_timeout(void)
1600 {
1601     if (hdrs.timeout)
1602         return 0;
1603
1604     if (get_cb_timeout_hdr())
1605         return 1;
1606
1607     hdrs.timeout = (afs_uint32 *) calloc(hdrs.timeout_hdr.records, sizeof(afs_uint32));
1608     assert(hdrs.timeout != NULL);
1609     memcpy(hdrs.timeout, hdrs.timeout_p, hdrs.timeout_hdr.records * sizeof(afs_uint32));
1610     return 0;
1611 }
1612
1613 static int
1614 get_cb_fehash_hdr(void)
1615 {
1616     char * buf;
1617     afs_uint32 hi, lo;
1618
1619     if (hdrs.fehash_hdr_valid)
1620         return 0;
1621
1622     if (get_cb_hdr())
1623         return 1;
1624
1625     SplitInt64(hdrs.cb_hdr.fehash_offset, hi, lo);
1626
1627     if (hi) {
1628         fprintf(stderr, "hi offset bits set in fehash_offset; can't get callback_state_fehash_header\n");
1629         return 1;
1630     }
1631     if ((lo >= map_len) || 
1632         ((lo + sizeof(struct callback_state_fehash_header)) > map_len) ||
1633         (lo + sizeof(struct callback_state_fehash_header) < lo)) {
1634         fprintf(stderr, "timeout_offset puts callback_state_fehash_header beyond end of memory map\n");
1635         return 1;
1636     }
1637
1638     buf = (char *) map;
1639     buf += lo;
1640     memcpy(&hdrs.fehash_hdr, buf, sizeof(struct callback_state_fehash_header));
1641     hdrs.fehash_hdr_p = buf;
1642     hdrs.fehash_hdr_valid = 1;
1643     buf += sizeof(struct callback_state_fehash_header);
1644     hdrs.fehash_p = buf;
1645
1646     return 0;
1647 }
1648
1649 static int
1650 get_cb_fehash(void)
1651 {
1652     if (hdrs.fehash)
1653         return 0;
1654
1655     if (get_cb_fehash_hdr())
1656         return 1;
1657
1658     hdrs.fehash = (afs_uint32 *) calloc(hdrs.fehash_hdr.records, sizeof(afs_uint32));
1659     assert(hdrs.fehash != NULL);
1660     memcpy(hdrs.fehash, hdrs.fehash_p, hdrs.fehash_hdr.records * sizeof(afs_uint32));
1661     return 0;
1662 }
1663
1664 static int
1665 get_he(afs_uint32 idx)
1666 {
1667     int i;
1668     char * p;
1669
1670     if (get_h_hdr())
1671         return 1;
1672
1673     if (idx >= hdrs.h_hdr.records)
1674         return 1;
1675
1676     if (he_cursor.idx == idx && he_cursor.hdr_valid && he_cursor.he_valid)
1677         return 0;
1678
1679     he_cursor.hdr_valid = he_cursor.he_valid = 0;
1680
1681     if (he_cache.cursor == NULL) {
1682         he_cache.cursor = (void **) calloc(hdrs.h_hdr.records, sizeof(void *));
1683         assert(he_cache.cursor != NULL);
1684     }
1685
1686     if (idx && he_cache.cursor[idx-1] == NULL) {
1687         for (i = 0; i < idx; i++) {
1688             if (he_cache.cursor[i] == NULL) {
1689                 get_he(i);
1690             }
1691         }
1692     }
1693
1694     if (!idx) {
1695         he_cursor.cursor = he_cursor.fh;
1696     } else if (he_cursor.cursor == he_cache.cursor[idx-1]) {
1697         p = (char *)he_cursor.cursor;
1698         p += he_cursor.hdr.len;
1699         he_cursor.cursor = (void *)p;
1700     } else {
1701         he_cursor.cursor = he_cache.cursor[idx-1];
1702         if (get_he_hdr())
1703             return 1;
1704         p = (char *)he_cursor.cursor;
1705         p += he_cursor.hdr.len;
1706         he_cursor.cursor = (void *)p;
1707     }
1708
1709     he_cursor.idx = idx;
1710     he_cache.cursor[idx] = he_cursor.cursor;
1711
1712     if (get_he_hdr())
1713         return 1;
1714     if (get_he_entry())
1715         return 1;
1716
1717     return 0;
1718 }
1719
1720 static int
1721 get_he_hdr(void)
1722 {
1723     memcpy(&he_cursor.hdr, he_cursor.cursor, sizeof(struct host_state_entry_header));
1724     he_cursor.hdr_valid = 1;
1725     return 0;
1726 }
1727
1728 static int
1729 get_he_entry(void)
1730 {
1731     char * p;
1732
1733     if (!he_cursor.hdr_valid) {
1734         if (get_he_hdr()) {
1735             return 1;
1736         }
1737     }
1738
1739     p = (char *) he_cursor.cursor;
1740     p += sizeof(struct host_state_entry_header);
1741
1742     memcpy(&he_cursor.he, p, sizeof(struct hostDiskEntry));
1743
1744     he_cursor.he_valid = 1;
1745     p += sizeof(struct hostDiskEntry);
1746     he_cursor.ifp = (void *)p;
1747     if (he_cursor.hdr.interfaces) {
1748         p += sizeof(struct Interface) + ((he_cursor.hdr.interfaces-1)*sizeof(struct AddrPort));
1749         he_cursor.hcps = (void *)p;
1750     } else {
1751         he_cursor.hcps = he_cursor.ifp;
1752     }
1753     return 0;
1754 }
1755
1756 static int
1757 get_fe(afs_uint32 idx)
1758 {
1759     int i;
1760     char * p;
1761
1762     cb_cursor.cb_valid = 0;
1763
1764     if (get_cb_hdr())
1765         return 1;
1766
1767     if (idx >= hdrs.cb_hdr.nFEs)
1768         return 1;
1769
1770     if (fe_cursor.idx == idx && fe_cursor.hdr_valid && fe_cursor.fe_valid)
1771         return 0;
1772
1773     fe_cursor.hdr_valid = fe_cursor.fe_valid = 0;
1774
1775     if (fe_cache.cursor == NULL) {
1776         fe_cache.cursor = (void **) calloc(hdrs.cb_hdr.nFEs, sizeof(void *));
1777         assert(fe_cache.cursor != NULL);
1778     }
1779
1780     if (idx && fe_cache.cursor[idx-1] == NULL) {
1781         for (i = 0; i < idx; i++) {
1782             if (fe_cache.cursor[i] == NULL) {
1783                 get_fe(i);
1784             }
1785         }
1786     }
1787
1788     if (!idx) {
1789         fe_cursor.cursor = fe_cursor.ffe;
1790     } else if (fe_cursor.cursor == fe_cache.cursor[idx-1]) {
1791         p = (char *)fe_cursor.cursor;
1792         p += fe_cursor.hdr.len;
1793         fe_cursor.cursor = (void *)p;
1794     } else {
1795         fe_cursor.cursor = fe_cache.cursor[idx-1];
1796         if (get_fe_hdr())
1797             return 1;
1798         p = (char *)fe_cursor.cursor;
1799         p += fe_cursor.hdr.len;
1800         fe_cursor.cursor = (void *)p;
1801     }
1802
1803     fe_cursor.idx = idx;
1804     fe_cache.cursor[idx] = fe_cursor.cursor;
1805
1806     if (get_fe_hdr())
1807         return 1;
1808     if (get_fe_entry())
1809         return 1;
1810
1811     return 0;
1812 }
1813
1814 static int
1815 get_fe_hdr(void)
1816 {
1817     if (!fe_cursor.cursor) {
1818         if(get_fe(fe_cursor.idx)) {
1819             return 1;
1820         }
1821     }
1822     
1823     memcpy(&fe_cursor.hdr, fe_cursor.cursor, sizeof(struct callback_state_entry_header));
1824     fe_cursor.hdr_valid = 1;
1825     return 0;
1826 }
1827
1828 static int
1829 get_fe_entry(void)
1830 {
1831     char * p;
1832
1833     if (!fe_cursor.hdr_valid) {
1834         if (get_fe_hdr()) {
1835             return 1;
1836         }
1837     }
1838
1839     p = (char *) fe_cursor.cursor;
1840     p += sizeof(struct callback_state_entry_header);
1841
1842     memcpy(&fe_cursor.fe, p, sizeof(struct FEDiskEntry));
1843
1844     fe_cursor.fe_valid = 1;
1845     p += sizeof(struct FEDiskEntry);
1846     fe_cursor.fcb = (void *)p;
1847     return 0;
1848 }
1849
1850 static int
1851 get_cb(afs_uint32 idx)
1852 {
1853     char * p;
1854
1855     if (get_fe(fe_cursor.idx))
1856         return 1;
1857
1858     if (idx >= fe_cursor.hdr.nCBs)
1859         return 1;
1860
1861     if (idx == cb_cursor.idx && cb_cursor.cb_valid)
1862         return 0;
1863
1864     cb_cursor.cb_valid = 0;
1865
1866     p = (char *)fe_cursor.fcb;
1867     p += idx * sizeof(struct CBDiskEntry);
1868     cb_cursor.cursor = (void *)p;
1869
1870     cb_cursor.idx = idx;
1871
1872     if (get_cb_entry())
1873         return 1;
1874
1875     return 0;
1876 }
1877
1878 static int
1879 get_cb_entry(void)
1880 {
1881     memcpy(&cb_cursor.cb, cb_cursor.cursor, sizeof(struct CBDiskEntry));
1882     cb_cursor.cb_valid = 1;
1883     return 0;
1884 }
1885
1886 #if 0
1887 static int
1888 find_he_by_index(afs_uint32 idx)
1889 {
1890     int i;
1891
1892     if (get_h_hdr()) {
1893         return 1;
1894     }
1895
1896     for (i = 0; i < hdrs.h_hdr.records; i++) {
1897         if (get_he(i)) {
1898             fprintf(stderr, "error getting he %d\n", i);
1899             return 1;
1900         }
1901         if (he_cursor.he.index == idx)
1902             break;
1903     }
1904
1905     if (i < hdrs.h_hdr.records) {
1906         dump_this_he();
1907         return 0;
1908     }
1909     return 1;
1910 }
1911 #endif
1912
1913 static int
1914 find_fe_by_index(afs_uint32 idx)
1915 {
1916     int i;
1917
1918     if (get_cb_hdr()) {
1919         return 1;
1920     }
1921
1922     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1923         if (get_fe(i)) {
1924             fprintf(stderr, "error getting fe %d\n", i);
1925             return 1;
1926         }
1927         if (fe_cursor.fe.index == idx)
1928             break;
1929     }
1930
1931     if (i < hdrs.cb_hdr.nFEs) {
1932         dump_this_fe();
1933         return 0;
1934     }
1935     return 1;
1936 }
1937
1938 static int
1939 find_fe_by_fid(afs_uint32 volid, afs_uint32 vnode, afs_uint32 unique)
1940 {
1941     int i;
1942
1943     if (get_cb_hdr()) {
1944         return 1;
1945     }
1946
1947     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1948         if (get_fe(i)) {
1949             fprintf(stderr, "error getting fe %d\n", i);
1950             return 1;
1951         }
1952         if ((fe_cursor.fe.fe.unique == unique) &&
1953             (fe_cursor.fe.fe.volid == volid) &&
1954             (fe_cursor.fe.fe.vnode == vnode))
1955             break;
1956     }
1957
1958     if (i < hdrs.cb_hdr.nFEs) {
1959         dump_this_fe();
1960         return 0;
1961     }
1962     return 1;
1963 }
1964
1965 static int
1966 find_cb_by_index(afs_uint32 idx)
1967 {
1968     int i;
1969
1970     if (get_fe_hdr()) {
1971         return 1;
1972     }
1973
1974     for (i = 0; i < fe_cursor.hdr.nCBs; i++) {
1975         if (get_cb(i)) {
1976             fprintf(stderr, "error getting cb %d\n", i);
1977             return 1;
1978         }
1979         if (cb_cursor.cb.index == idx)
1980             break;
1981     }
1982
1983     if (i < fe_cursor.hdr.nCBs) {
1984         dump_this_cb();
1985         return 0;
1986     }
1987     return 1;
1988 }
1989
1990 #endif /* AFS_DEMAND_ATTACH_FS */