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