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