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