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