commit e2a7f03a6b43cf093fc814dd8610e2b73c1345a3
parent 6d9bfc25ce2ba1ddc768c68522d05195d783472b
Author: sin <sin@2f30.org>
Date: Mon, 4 Mar 2019 14:45:41 +0000
Check cache for consistency
Diffstat:
M | dedup.c | | | 67 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
1 file changed, 61 insertions(+), 6 deletions(-)
diff --git a/dedup.c b/dedup.c
@@ -25,6 +25,10 @@ enum {
WALK_STOP
};
+struct check_cache_args {
+ int ret;
+};
+
struct extract_args {
uint8_t *md;
int fd;
@@ -346,8 +350,12 @@ extract(struct snapshot *snap, void *arg)
return WALK_STOP;
}
+/*
+ * For each snapshot, hash every block and check if the hash
+ * matches the one in the corresponding block descriptor.
+ */
static int
-check(struct snapshot *snap, void *arg)
+check_snap(struct snapshot *snap, void *arg)
{
uint8_t md[MDSIZE];
uint8_t *buf;
@@ -355,10 +363,6 @@ check(struct snapshot *snap, void *arg)
uint64_t i;
buf = alloc_buf(compr_size(BLKSIZE_MAX));
- /*
- * Calculate hash for each block and compare
- * against snapshot entry block descriptor
- */
for (i = 0; i < snap->nr_blk_descs; i++) {
struct blk_desc *blk_desc;
@@ -388,6 +392,35 @@ check(struct snapshot *snap, void *arg)
return WALK_CONTINUE;
}
+/*
+ * For each block descriptor within each snapshot, do a lookup
+ * of the block descriptor hash in the cache. If the lookup fails
+ * the cache is corrupted. The caller will rebuild the cache in
+ * that case.
+ */
+static int
+check_cache(struct snapshot *snap, void *arg)
+{
+ struct check_cache_args *args = arg;
+ uint64_t i;
+
+ for (i = 0; i < snap->nr_blk_descs; i++) {
+ struct blk_desc *blk_desc;
+ struct cache_entry cache_entry;
+
+ blk_desc = &snap->blk_desc[i];
+ memcpy(&cache_entry.md, blk_desc->md, sizeof(cache_entry.md));
+ if (lookup_cache_entry(cache, &cache_entry) < 0) {
+ if (verbose)
+ fprintf(stderr, "Cache is corrupted\n");
+ args->ret = -1;
+ return WALK_STOP;
+ }
+ }
+ args->ret = 0;
+ return WALK_CONTINUE;
+}
+
static int
list(struct snapshot *snap, void *arg)
{
@@ -703,8 +736,30 @@ main(int argc, char *argv[])
}
if (cflag) {
+ struct check_cache_args args;
+
+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET);
+ walk_snap(check_snap, NULL);
+
xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET);
- walk_snap(check, NULL);
+ args.ret = -1;
+ walk_snap(check_cache, &args);
+ if (args.ret != 0) {
+ free_cache(cache);
+ cache = alloc_cache();
+
+ if (ftruncate(cfd, 0) < 0)
+ err(1, "ftruncate");
+
+ if (verbose > 0)
+ fprintf(stderr, "Rebuilding cache...");
+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET);
+ xlseek(cfd, 0, SEEK_SET);
+ walk_snap(rebuild_cache, NULL);
+ if (verbose > 0)
+ fprintf(stderr, "done\n");
+ }
+
term();
return 0;
}