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