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