diff --git a/cmdline/selftest.c b/cmdline/selftest.c index 76c0d323..0291d86d 100644 --- a/cmdline/selftest.c +++ b/cmdline/selftest.c @@ -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); } diff --git a/raid/test.c b/raid/test.c index c6c33276..89f2919f 100644 --- a/raid/test.c +++ b/raid/test.c @@ -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; diff --git a/raid/test.h b/raid/test.h index 04a2f66e..bda0b456 100644 --- a/raid/test.h +++ b/raid/test.h @@ -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. * diff --git a/raid/test/fulltest.c b/raid/test/fulltest.c index 5c898486..c1611359 100644 --- a/raid/test/fulltest.c +++ b/raid/test/fulltest.c @@ -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;