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