xref: /dragonfly/test/debug/checkhammer.c (revision 0db87cb7)
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 }
170