#include <sys/types.h>
#include <sys/tree.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
struct rbmap_tree;
struct rbmap;
static void parseBlockMap(FILE *fp);
static void parseBTree(FILE *fp);
static void dumpResults(void);
static int rbmap_cmp(struct rbmap *, struct rbmap *);
typedef u_int64_t hammer_off_t;
typedef struct rbmap *rbmap_t;
RB_HEAD(rbmap_tree, rbmap);
RB_PROTOTYPE2(rbmap_tree, rbmap, rbentry, rbmap_cmp, hammer_off_t);
struct rbmap {
RB_ENTRY(rbmap) rbentry;
hammer_off_t base;
long app;
long free;
long bytes;
int zone;
};
RB_GENERATE2(rbmap_tree, rbmap, rbentry, rbmap_cmp, hammer_off_t, base);
struct rbmap_tree rbroot;
static
int
rbmap_cmp(struct rbmap *rb1, struct rbmap *rb2)
{
if (rb1->base < rb2->base)
return(-1);
if (rb1->base > rb2->base)
return(1);
return(0);
}
int
main(int ac, char **av)
{
FILE *fp;
if (ac != 3) {
fprintf(stderr, "checkhammer blockmapdump btreedump\n");
exit(1);
}
if ((fp = fopen(av[1], "r")) == NULL) {
fprintf(stderr, "Unable to open %s\n", av[1]);
exit(1);
}
RB_INIT(&rbroot);
parseBlockMap(fp);
fclose(fp);
if ((fp = fopen(av[2], "r")) == NULL) {
fprintf(stderr, "Unable to open %s\n", av[1]);
exit(1);
}
parseBTree(fp);
fclose(fp);
dumpResults();
return(0);
}
static void
parseBlockMap(FILE *fp)
{
char buf[1024];
rbmap_t map;
int zone;
long long base;
long long app;
long long free;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (sscanf(buf, " 4%llx zone=%d app=%lld free=%lld",
&base, &zone, &app, &free) != 4)
continue;
if (RB_LOOKUP(rbmap_tree, &rbroot, (hammer_off_t)base))
continue;
map = malloc(sizeof(*map));
map->base = (hammer_off_t)base;
map->app = (long)app;
map->free = (long)free;
map->zone = zone;
map->bytes = 0;
RB_INSERT(rbmap_tree, &rbroot, map);
}
}
static void
parseBTree(FILE *fp)
{
char buf[1024];
rbmap_t map;
long long base;
long long bytes;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (sscanf(buf, " NODE 8%llx", &base) == 1) {
base &= 0x0FFFFFFFFF800000LLU;
map = RB_LOOKUP(rbmap_tree, &rbroot, base);
if (map == NULL) {
printf("(not in blockmap): %s", buf);
continue;
}
map->bytes += 4096;
}
if (sscanf(buf, " dataoff=%llx/%lld",
&base, &bytes) == 2) {
base &= 0x0FFFFFFFFF800000LLU;
map = RB_LOOKUP(rbmap_tree, &rbroot, base);
if (map == NULL) {
printf("(not in blockmap): %s", buf);
continue;
}
map->bytes += (bytes + 15) & ~15;
}
}
}
static void
dumpResults(void)
{
rbmap_t map;
hammer_off_t bfree;
printf("mismatches: (blockmap, actual)\n");
RB_FOREACH(map, rbmap_tree, &rbroot) {
bfree = 8192 * 1024 - (int64_t)map->bytes;
if (map->free == bfree)
continue;
if (map->free == 0 && bfree == 8192 * 1024) {
if (map->zone == 3 || map->zone == 4 ||
map->zone == 15)
continue;
}
printf(" bmap %016jx %jd %jd\n",
map->base,
(intmax_t)(int64_t)map->free,
(intmax_t)(int64_t)bfree);
}
}