Merge branch 'vendor/OPENRESOLV' with the following changes:
[dragonfly.git] / test / debug / checkhammer.c
1 /*
2  * checkhammer.c
3  *
4  * checkhammer blockmapdump btreedump
5  */
6
7 #include <sys/types.h>
8 #include <sys/tree.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13
14 struct rbmap_tree;
15 struct rbmap;
16
17 static void parseBlockMap(FILE *fp);
18 static void parseBTree(FILE *fp);
19 static void dumpResults(void);
20 static int rbmap_cmp(struct rbmap *, struct rbmap *);
21
22 typedef u_int64_t hammer_off_t;
23 typedef struct rbmap *rbmap_t;
24
25 RB_HEAD(rbmap_tree, rbmap);
26 RB_PROTOTYPE2(rbmap_tree, rbmap, rbentry, rbmap_cmp, hammer_off_t);
27
28 struct rbmap {
29         RB_ENTRY(rbmap) rbentry;
30         hammer_off_t    base;
31         long            app;
32         long            free;
33         long            bytes;
34         int             zone;
35 };
36
37 RB_GENERATE2(rbmap_tree, rbmap, rbentry, rbmap_cmp, hammer_off_t, base);
38
39 struct rbmap_tree rbroot;
40
41 static
42 int
43 rbmap_cmp(struct rbmap *rb1, struct rbmap *rb2)
44 {
45         if (rb1->base < rb2->base)
46                 return(-1);
47         if (rb1->base > rb2->base)
48                 return(1);
49         return(0);
50 }
51
52 int
53 main(int ac, char **av)
54 {
55         FILE *fp;
56
57         if (ac != 3) {
58                 fprintf(stderr, "checkhammer blockmapdump btreedump\n");
59                 exit(1);
60         }
61         if ((fp = fopen(av[1], "r")) == NULL) {
62                 fprintf(stderr, "Unable to open %s\n", av[1]);
63                 exit(1);
64         }
65
66         RB_INIT(&rbroot);
67         parseBlockMap(fp);
68         fclose(fp);
69         if ((fp = fopen(av[2], "r")) == NULL) {
70                 fprintf(stderr, "Unable to open %s\n", av[1]);
71                 exit(1);
72         }
73         parseBTree(fp);
74         fclose(fp);
75
76         dumpResults();
77         return(0);
78 }
79
80 static void
81 parseBlockMap(FILE *fp)
82 {
83         char buf[1024];
84         rbmap_t map;
85         int zone;
86         long long base;
87         long long app;
88         long long free;
89
90         while (fgets(buf, sizeof(buf), fp) != NULL) {
91                 if (sscanf(buf, "        4%llx zone=%d app=%lld free=%lld",
92                            &base, &zone, &app, &free) != 4)
93                         continue;
94                 if (RB_LOOKUP(rbmap_tree, &rbroot, (hammer_off_t)base))
95                         continue;
96                 map = malloc(sizeof(*map));
97                 map->base = (hammer_off_t)base;
98                 map->app = (long)app;
99                 map->free = (long)free;
100                 map->zone = zone;
101                 map->bytes = 0;
102                 RB_INSERT(rbmap_tree, &rbroot, map);
103         }
104 }
105
106 static void
107 parseBTree(FILE *fp)
108 {
109         char buf[1024];
110         rbmap_t map;
111         long long base;
112         long long bytes;
113
114         while (fgets(buf, sizeof(buf), fp) != NULL) {
115                 if (sscanf(buf, "     NODE 8%llx", &base) == 1) {
116                         base &= 0x0FFFFFFFFF800000LLU;
117                         map = RB_LOOKUP(rbmap_tree, &rbroot, base);
118                         if (map == NULL) {
119                                 printf("(not in blockmap): %s", buf);
120                                 continue;
121                         }
122                         map->bytes += 4096;
123                 }
124                 if (sscanf(buf, "                 dataoff=%llx/%lld",
125                            &base, &bytes) == 2) {
126                         base &= 0x0FFFFFFFFF800000LLU;
127                         map = RB_LOOKUP(rbmap_tree, &rbroot, base);
128                         if (map == NULL) {
129                                 printf("(not in blockmap): %s", buf);
130                                 continue;
131                         }
132                         map->bytes += (bytes + 15) & ~15;
133                 }
134         }
135 }
136
137 static void
138 dumpResults(void)
139 {
140         rbmap_t map;
141         hammer_off_t bfree;
142
143         printf("mismatches: (blockmap, actual)\n");
144         RB_FOREACH(map, rbmap_tree, &rbroot) {
145                 bfree = 8192 * 1024 - (int64_t)map->bytes;
146
147                 /*
148                  * Ignore matches
149                  */
150                 if (map->free == bfree)
151                         continue;
152
153                 /*
154                  * If the block is completely allocated but our calculations
155                  * show nobody is referencing it it is probably an undo,
156                  * blockmap, or unavailable reserved area.
157                  */
158                 if (map->free == 0 && bfree == 8192 * 1024) {
159                         if (map->zone == 3 || map->zone == 4 ||
160                             map->zone == 15)
161                                 continue;
162                 }
163
164                 printf(" bmap %016jx %jd %jd\n",
165                         map->base,
166                         (intmax_t)(int64_t)map->free,
167                         (intmax_t)(int64_t)bfree);
168         }
169 }