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