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