scoutfs: add radix block metadata checker

Add a quick runtime check of the consistency of the radix block and
reference metadata fields.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-02-28 11:34:02 -08:00
committed by Zach Brown
parent c10c7d9748
commit 6eac823bd3
+58
View File
@@ -456,6 +456,61 @@ static struct radix_path *walk_paths(struct rb_root *rbroot,
return NULL;
}
/*
* Make sure radix metadata is consistent.
*/
static void check_first_total(struct radix_path *path)
{
struct scoutfs_radix_block *rdx;
struct scoutfs_radix_ref *ref;
int level;
u64 st;
u64 lt;
u32 sf;
u32 lf;
int i;
for (level = 0; level < path->height; level++) {
rdx = path->bls[level]->data;
ref = path_ref(path, level);
if (level == 0) {
st = bitmap_weight((long *)rdx->bits,
SCOUTFS_RADIX_BITS);
lt = count_lg_bits(rdx->bits, 0, SCOUTFS_RADIX_BITS);
sf = find_next_bit_le(rdx->bits, SCOUTFS_RADIX_BITS, 0);
lf = find_next_lg(rdx->bits, 0);
} else {
st = 0;
lt = 0;
sf = SCOUTFS_RADIX_REFS;
lf = SCOUTFS_RADIX_REFS;
for (i = 0; i < SCOUTFS_RADIX_REFS; i++) {
st += le64_to_cpu(rdx->refs[i].sm_total);
lt += le64_to_cpu(rdx->refs[i].lg_total);
if (rdx->refs[i].sm_total != 0 && i < sf)
sf = i;
if (rdx->refs[i].lg_total != 0 && i < lf)
lf = i;
}
}
if (le64_to_cpu(ref->sm_total) != st ||
le64_to_cpu(ref->lg_total) != lt ||
le32_to_cpu(rdx->sm_first) > sf ||
le32_to_cpu(rdx->lg_first) > lf) {
printk("radix inconsistency: level %u calced sf %u st %llu lf %u lt %llu, stored sf %u st %llu lf %u lt %llu\n",
level, sf, st, lf, lt,
le32_to_cpu(rdx->sm_first),
le64_to_cpu(ref->sm_total),
le32_to_cpu(rdx->lg_first),
le64_to_cpu(ref->lg_total));
BUG();
}
}
}
/*
* Update the first tracking in a block after the caller has modified
* the block at the given index. If the modification at the index is
@@ -528,6 +583,9 @@ static void fixup_first_total(struct super_block *sb, struct radix_path *path,
ref->lg_total == 0);
}
}
if (0) /* expensive, would be nice to make conditional */
check_first_total(path);
}
static void store_next_find_bit(struct super_block *sb, bool meta,