Add raid_test_tail to test recovery of tail disks across all array sizes up to 251

This commit is contained in:
Andrea Mazzoleni 2026-08-21 11:42:14 +02:00
parent c410b11162
commit a745a05d4e
4 changed files with 296 additions and 19 deletions

View file

@ -1183,6 +1183,12 @@ void selftest(void)
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_tail(RAID_MODE_VANDERMONDE_RAID, RAID_DATA_MAX, 256) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed TAIL Vandermonde RAID test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_poly(RAID_MODE_CAUCHY_RAID) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed POLY Cauchy RAID test\n");
@ -1201,6 +1207,12 @@ void selftest(void)
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_tail(RAID_MODE_CAUCHY_RAID, RAID_DATA_MAX, 256) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed TAIL Cauchy RAID test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_par(RAID_MODE_CAUCHY_RAID, 1, 256) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed GEN Cauchy RAID test single data disk\n");
@ -1225,6 +1237,12 @@ void selftest(void)
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_tail(RAID_MODE_CAUCHY_AES, RAID_DATA_MAX, 256) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed TAIL Cauchy AES test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* verify raid_mode get/set behavior */
int cur = raid_mode(RAID_MODE_GET);
@ -1241,7 +1259,7 @@ void selftest(void)
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* restore default mode */
raid_mode(RAID_MODE_CAUCHY_RAID);
}

View file

@ -356,10 +356,10 @@ int raid_test_rec(int mode, int nd, size_t size)
int np;
raid_mode(mode);
if (mode == RAID_MODE_CAUCHY_RAID || mode == RAID_MODE_CAUCHY_AES)
np = RAID_PARITY_MAX;
else
if (mode == RAID_MODE_VANDERMONDE_RAID)
np = 3;
else
np = RAID_PARITY_MAX;
nv = nd + np * 2 + 2;
@ -550,6 +550,233 @@ bail:
/* LCOV_EXCL_STOP */
}
int raid_test_tail(int mode, int nd_max, size_t size)
{
void (*f[RAID_PARITY_MAX][32])(int nr, int *id, int *ip, int nd, size_t size, void **vbuf);
void *v_alloc;
void **v;
void **data;
void **parity;
void **test;
void *data_save[RAID_PARITY_MAX];
void *parity_save[RAID_PARITY_MAX];
void *waste;
int nv;
int id[RAID_PARITY_MAX];
int ip[RAID_PARITY_MAX];
int i;
int j;
int nr;
int nf[RAID_PARITY_MAX];
int np;
int nd;
raid_mode(mode);
if (mode == RAID_MODE_VANDERMONDE_RAID)
np = 3;
else
np = RAID_PARITY_MAX;
nv = nd_max + np * 2 + 2;
v = raid_malloc_vector(nv, size, &v_alloc);
if (!v) {
/* LCOV_EXCL_START */
return -1;
/* LCOV_EXCL_STOP */
}
data = v;
parity = v + nd_max;
test = v + nd_max + np;
for (i = 0; i < np; ++i)
parity_save[i] = parity[i];
memset(v[nv - 2], 0, size);
raid_zero(v[nv - 2]);
waste = v[nv - 1];
/* fill with pseudo-random data with the arbitrary seed "1" */
raid_mrand_vector(1, nd_max, size, v);
/* counters of functions for each parity level */
for (i = 0; i < np; ++i)
nf[i] = 0;
/* setup recov functions */
for (i = 1; i <= np; ++i) {
if (i == 1) {
test_setup(i) = raid_rec1_int8;
#ifdef CONFIG_X86
if (raid_cpu_has_ssse3())
test_setup(i) = raid_rec1_ssse3;
if (raid_cpu_has_avx2())
test_setup(i) = raid_rec1_avx2;
#ifdef CONFIG_X86_64
if (mode == RAID_MODE_CAUCHY_RAID || mode == RAID_MODE_CAUCHY_AES) {
if (raid_cpu_has_avx2gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_rec1_avx2gfni_aes;
else
test_setup(i) = raid_rec1_avx2gfni_raid;
}
if (raid_cpu_has_avx512gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_rec1_avx512gfni_aes;
else
test_setup(i) = raid_rec1_avx512gfni_raid;
}
}
#endif
#endif
#ifdef CONFIG_NEON
test_setup(i) = raid_rec1_neon;
#endif
#ifdef CONFIG_NEON32
test_setup(i) = raid_rec1_neon32;
#endif
} else if (i == 2) {
test_setup(i) = raid_rec2_int8;
#ifdef CONFIG_X86
if (raid_cpu_has_ssse3())
test_setup(i) = raid_rec2_ssse3;
if (raid_cpu_has_avx2())
test_setup(i) = raid_rec2_avx2;
#ifdef CONFIG_X86_64
if (raid_cpu_has_avx512bw())
test_setup(i) = raid_rec2_avx512bw;
if (mode == RAID_MODE_CAUCHY_RAID || mode == RAID_MODE_CAUCHY_AES) {
if (raid_cpu_has_avx2gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_rec2_avx2gfni_aes;
else
test_setup(i) = raid_rec2_avx2gfni_raid;
}
if (raid_cpu_has_avx512gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_rec2_avx512gfni_aes;
else
test_setup(i) = raid_rec2_avx512gfni_raid;
}
}
#endif
#endif
#ifdef CONFIG_NEON
test_setup(i) = raid_rec2_neon;
#endif
#ifdef CONFIG_NEON32
test_setup(i) = raid_rec2_neon32;
#endif
} else {
test_setup(i) = raid_recX_int8;
#ifdef CONFIG_X86
if (raid_cpu_has_ssse3())
test_setup(i) = raid_recX_ssse3;
if (raid_cpu_has_avx2())
test_setup(i) = raid_recX_avx2;
#ifdef CONFIG_X86_64
if (raid_cpu_has_avx512bw())
test_setup(i) = raid_recX_avx512bw;
if (mode == RAID_MODE_CAUCHY_RAID || mode == RAID_MODE_CAUCHY_AES) {
if (raid_cpu_has_avx2gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_recX_avx2gfni_aes;
else
test_setup(i) = raid_recX_avx2gfni_raid;
}
if (raid_cpu_has_avx512gfni()) {
if (mode == RAID_MODE_CAUCHY_AES)
test_setup(i) = raid_recX_avx512gfni_aes;
else
test_setup(i) = raid_recX_avx512gfni_raid;
}
}
#endif
#endif
#ifdef CONFIG_NEON
test_setup(i) = raid_recX_neon;
#endif
#ifdef CONFIG_NEON32
test_setup(i) = raid_recX_neon32;
#endif
}
}
/* test all disk counts from 1 to nd_max */
for (nd = 1; nd <= nd_max; ++nd) {
/* set data pointers */
for (i = 0; i < nd; ++i)
v[i] = data[i];
/* set parity pointers */
for (i = 0; i < np; ++i)
v[nd + i] = parity_save[i];
/* compute the parity for this disk count */
raid_gen_ref(nd, np, size, v);
/* set all the parity in v to the waste v */
for (i = 0; i < np; ++i)
v[nd + i] = waste;
/* all parity levels up to min(nd, np) */
for (nr = 1; nr <= np && nr <= nd; ++nr) {
/* only test the tail: the last nr data disks */
for (i = 0; i < nr; ++i)
id[i] = nd - nr + i;
/* all combinations (nr of np) parities */
combination_first(nr, np, ip);
do {
/* for each recover function */
for (j = 0; j < nf[nr - 1]; ++j) {
/* set */
for (i = 0; i < nr; ++i) {
/* remove the missing data */
data_save[i] = data[id[i]];
v[id[i]] = test[i];
/* set the parity to use */
v[nd + ip[i]] = parity_save[ip[i]];
}
/* recover */
f[nr - 1][j](nr, id, ip, nd, size, v);
/* check */
for (i = 0; i < nr; ++i) {
if (memcmp(test[i], data_save[i], size) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
}
/* restore */
for (i = 0; i < nr; ++i) {
/* restore the data */
v[id[i]] = data_save[i];
/* restore the parity to waste */
v[nd + ip[i]] = waste;
}
}
} while (combination_next(nr, np, ip));
}
}
free(v_alloc);
free(v);
return 0;
bail:
/* LCOV_EXCL_START */
free(v_alloc);
free(v);
return -1;
/* LCOV_EXCL_STOP */
}
int raid_test_par(int mode, int nd, size_t size)
{
void (*f[RAID_PARITY_MAX][32])(int nd, size_t size, void **vbuf);
@ -561,10 +788,10 @@ int raid_test_par(int mode, int nd, size_t size)
int np;
raid_mode(mode);
if (mode == RAID_MODE_CAUCHY_RAID || mode == RAID_MODE_CAUCHY_AES)
np = RAID_PARITY_MAX;
else
if (mode == RAID_MODE_VANDERMONDE_RAID)
np = 3;
else
np = RAID_PARITY_MAX;
nv = nd + np * 2;

View file

@ -60,6 +60,16 @@ int raid_test_poly(unsigned mode);
*/
int raid_test_rec(unsigned mode, int nd, size_t size);
/**
* Tests recovering functions on the tail data disks.
*
* All the recovering functions are tested by recovering the last 1, 2, ..., np
* data disks for each disk count from 1 to nd.
*
* Returns 0 on success.
*/
int raid_test_tail(unsigned mode, int nd, size_t size);
/**
* Tests parity generation functions.
*

View file

@ -83,6 +83,13 @@ int main(void)
/* LCOV_EXCL_STOP */
}
printf("Test Vandermonde RAID parity generation with %u data disks...\n", RAID_DATA_MAX);
if (raid_test_par(RAID_MODE_VANDERMONDE_RAID, RAID_DATA_MAX, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("Test Cauchy RAID parity generation with 1-%u data disks...\n", RAID_DATA_MAX);
for (int i = 1; i <= RAID_DATA_MAX; ++i) {
if (raid_test_par(RAID_MODE_CAUCHY_RAID, i, TEST_SIZE) != 0) {
@ -91,14 +98,6 @@ int main(void)
/* LCOV_EXCL_STOP */
}
}
printf("Test Cauchy RAID recovering with all combinations of %u data and 6 parity blocks...\n", TEST_COUNT);
if (raid_test_rec(RAID_MODE_CAUCHY_RAID, TEST_COUNT, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("Test Cauchy AES parity generation with 1-%u data disks...\n", RAID_DATA_MAX);
for (int i = 1; i <= RAID_DATA_MAX; ++i) {
if (raid_test_par(RAID_MODE_CAUCHY_AES, i, TEST_SIZE) != 0) {
@ -108,15 +107,22 @@ int main(void)
}
}
printf("Test Cauchy AES recovering with all combinations of %u data and 6 parity blocks...\n", TEST_COUNT);
if (raid_test_rec(RAID_MODE_CAUCHY_AES, TEST_COUNT, TEST_SIZE) != 0) {
printf("Test Vandermonde RAID tail recovering with 1-%u data disks...\n", RAID_DATA_MAX);
if (raid_test_tail(RAID_MODE_VANDERMONDE_RAID, RAID_DATA_MAX, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("Test Vandermonde RAID parity generation with %u data disks...\n", RAID_DATA_MAX);
if (raid_test_par(RAID_MODE_VANDERMONDE_RAID, RAID_DATA_MAX, TEST_SIZE) != 0) {
printf("Test Cauchy RAID tail recovering with 1-%u data disks...\n", RAID_DATA_MAX);
if (raid_test_tail(RAID_MODE_CAUCHY_RAID, RAID_DATA_MAX, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("Test Cauchy AES tail recovering with 1-%u data disks...\n", RAID_DATA_MAX);
if (raid_test_tail(RAID_MODE_CAUCHY_AES, RAID_DATA_MAX, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
@ -129,6 +135,22 @@ int main(void)
/* LCOV_EXCL_STOP */
}
printf("Test Cauchy RAID recovering with all combinations of %u data and 6 parity blocks...\n", TEST_COUNT);
if (raid_test_rec(RAID_MODE_CAUCHY_RAID, TEST_COUNT, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("Test Cauchy AES recovering with all combinations of %u data and 6 parity blocks...\n", TEST_COUNT);
if (raid_test_rec(RAID_MODE_CAUCHY_AES, TEST_COUNT, TEST_SIZE) != 0) {
/* LCOV_EXCL_START */
goto bail;
/* LCOV_EXCL_STOP */
}
printf("OK\n");
return 0;