mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Implement G23 Extended Cauchy construction for AES RAID mode
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
This commit is contained in:
parent
a831853092
commit
48bed76dd1
20 changed files with 5716 additions and 5639 deletions
|
|
@ -1237,6 +1237,12 @@ void selftest(void)
|
|||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (raid_test_rec2_g23(256) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "Failed G23 P/Q recovery test\n");
|
||||
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");
|
||||
|
|
@ -1244,23 +1250,52 @@ void selftest(void)
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* verify raid_mode get/set behavior */
|
||||
int cur = raid_mode(RAID_MODE_GET);
|
||||
int prev = raid_mode(RAID_MODE_CAUCHY_AES);
|
||||
if (prev != cur) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "raid_mode set did not return previous mode\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (raid_mode(RAID_MODE_GET) != RAID_MODE_CAUCHY_AES) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "raid_mode GET did not return active mode\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* restore default mode */
|
||||
/* verify RAID -> AES -> RAID switches every active table */
|
||||
raid_mode(RAID_MODE_CAUCHY_RAID);
|
||||
if (raid_gfmul != raid_gfmul_raid || raid_gfinv != raid_gfinv_raid
|
||||
|| raid_gfcauchy != raid_gfcauchy_raid || raid_gfgen != raid_gfcauchy_raid) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "raid_mode did not select RAID tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)
|
||||
if (raid_gfcauchypshufb != raid_gfcauchypshufb_raid
|
||||
|| raid_gfmulpshufb != raid_gfmulpshufb_raid) {
|
||||
log_fatal(EINTERNAL, "raid_mode did not select RAID SIMD tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
if (raid_mode(RAID_MODE_CAUCHY_AES) != RAID_MODE_CAUCHY_RAID
|
||||
|| raid_mode(RAID_MODE_GET) != RAID_MODE_CAUCHY_AES
|
||||
|| raid_gfmul != raid_gfmul_aes || raid_gfinv != raid_gfinv_aes
|
||||
|| raid_gfcauchy != raid_gfcauchy_aes || raid_gfgen != raid_gfcauchy_aes) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "raid_mode did not select AES tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)
|
||||
if (raid_gfcauchypshufb != raid_gfcauchypshufb_aes
|
||||
|| raid_gfmulpshufb != raid_gfmulpshufb_aes) {
|
||||
log_fatal(EINTERNAL, "raid_mode did not select AES SIMD tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
if (raid_mode(RAID_MODE_CAUCHY_RAID) != RAID_MODE_CAUCHY_AES
|
||||
|| raid_gfmul != raid_gfmul_raid || raid_gfinv != raid_gfinv_raid
|
||||
|| raid_gfcauchy != raid_gfcauchy_raid || raid_gfgen != raid_gfcauchy_raid) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "raid_mode did not restore RAID tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)
|
||||
if (raid_gfcauchypshufb != raid_gfcauchypshufb_raid
|
||||
|| raid_gfmulpshufb != raid_gfmulpshufb_raid) {
|
||||
log_fatal(EINTERNAL, "raid_mode did not restore RAID SIMD tables\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
21
raid/README
21
raid/README
|
|
@ -120,17 +120,20 @@ Operating Modes and Polynomials
|
|||
(Z parity). Optimized for low-end CPUs without vector instructions.
|
||||
|
||||
RAID_MODE_CAUCHY_AES (Mode = 2)
|
||||
Uses Cauchy matrix with AES polynomial 0x1b (x^8 + x^4 + x^3 + x + 1,
|
||||
0x11b) and primitive generator g = 3. On CPUs supporting Intel GFNI,
|
||||
generation and recovery are accelerated directly using VGF2P8MULB.
|
||||
Uses a 6x251 Extended Cauchy matrix with AES polynomial 0x1b
|
||||
(x^8 + x^4 + x^3 + x + 1, 0x11b). Its Q row uses the G23 sequence,
|
||||
with multiplication by 2 for almost every coefficient transition and
|
||||
multiplication by 3 only between its five cosets. On CPUs supporting
|
||||
Intel GFNI, generation and recovery are accelerated directly using VGF2P8MULB.
|
||||
This native GFNI multiplication is typically faster than the affine GFNI
|
||||
implementation required by the standard RAID polynomial. Parity data is
|
||||
incompatible with standard 0x11d polynomial arrays.
|
||||
incompatible with standard 0x11d polynomial arrays and with the previous
|
||||
RAID_MODE_CAUCHY_AES parity layout.
|
||||
|
||||
Both Cauchy modes use the same Extended Cauchy construction with coefficients
|
||||
based on powers of their respective primitive generator. GFNI acceleration
|
||||
is available for both fields: the RAID field uses affine transformations,
|
||||
while the AES field uses the native GFNI multiplication instruction.
|
||||
Both Cauchy modes support RAID_DATA_MAX = 251 data disks and
|
||||
RAID_PARITY_MAX = 6 parity levels. GFNI acceleration is available for both
|
||||
fields: the RAID field uses affine transformations, while the AES field uses
|
||||
the native GFNI multiplication instruction.
|
||||
|
||||
|
||||
Implementation Structure
|
||||
|
|
@ -140,7 +143,7 @@ Implementation Structure
|
|||
raid.c Cauchy matrix solver, Gauss-Jordan inversion, delta generation.
|
||||
module.c Algorithm registration, CPU detection, and dynamic dispatch.
|
||||
int.c Portable C fallback implementation (8/32/64-bit word loops).
|
||||
tables.c Precomputed GF(2^8) log/exp, multiplication, Cauchy tables.
|
||||
tables.c Precomputed GF(2^8) multiplication and Cauchy tables.
|
||||
mktables.c Generator for GF(2^8), Cauchy, and GFNI affine tables.
|
||||
internal.h Private header, assertion macros (BUG_ON), alignment helpers.
|
||||
|
||||
|
|
|
|||
167
raid/avx2.c
167
raid/avx2.c
|
|
@ -39,9 +39,9 @@ void raid_gen1_avx2(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* GEN2 Cauchy AVX2 implementation using the active generator
|
||||
* GEN2 Cauchy AVX2 implementation using the active Q transition
|
||||
*/
|
||||
static __always_inline void raid_gen2_avx2_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_avx2_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -65,7 +65,7 @@ static __always_inline void raid_gen2_avx2_gen(int nd, size_t size, void **vv, i
|
|||
asm volatile ("vmovdqa %ymm1,%ymm3");
|
||||
|
||||
for (d = l - 1; d >= 0; --d) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("vmovdqa %ymm2,%ymm4");
|
||||
asm volatile ("vmovdqa %ymm3,%ymm5");
|
||||
asm volatile ("vpaddb %ymm2,%ymm2,%ymm2");
|
||||
|
|
@ -108,12 +108,12 @@ static __always_inline void raid_gen2_avx2_gen(int nd, size_t size, void **vv, i
|
|||
|
||||
void raid_gen2_avx2_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_avx2_gen(nd, size, vv, 2);
|
||||
raid_gen2_avx2_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_avx2_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_avx2_gen(nd, size, vv, 3);
|
||||
raid_gen2_avx2_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
|
@ -126,7 +126,7 @@ void raid_gen2_avx2_aes(int nd, size_t size, void **vv)
|
|||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen2_avx2ext_gen(int nd, size_t size,
|
||||
void **vv, int generator)
|
||||
void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -156,41 +156,48 @@ static __always_inline void raid_gen2_avx2ext_gen(int nd, size_t size,
|
|||
asm volatile ("vmovdqa %0,%%ymm6" : : "m" (v[d - 1][i]));
|
||||
asm volatile ("vmovdqa %0,%%ymm7" : : "m" (v[d - 1][i + 32]));
|
||||
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("vmovdqa %ymm2,%ymm12");
|
||||
asm volatile ("vmovdqa %ymm3,%ymm13");
|
||||
}
|
||||
asm volatile ("vpcmpgtb %ymm2,%ymm14,%ymm10");
|
||||
asm volatile ("vpaddb %ymm2,%ymm2,%ymm8");
|
||||
asm volatile ("vpxor %ymm6,%ymm4,%ymm12");
|
||||
asm volatile ("vpand %ymm15,%ymm10,%ymm10");
|
||||
asm volatile ("vpxor %ymm10,%ymm8,%ymm8");
|
||||
asm volatile ("vpxor %ymm4,%ymm8,%ymm8");
|
||||
asm volatile ("vpcmpgtb %ymm8,%ymm14,%ymm10");
|
||||
asm volatile ("vpaddb %ymm8,%ymm8,%ymm8");
|
||||
asm volatile ("vpxor %ymm12,%ymm0,%ymm0");
|
||||
if (generator == 3)
|
||||
asm volatile ("vpxor %ymm2,%ymm12,%ymm12");
|
||||
asm volatile ("vpand %ymm15,%ymm10,%ymm10");
|
||||
asm volatile ("vpxor %ymm10,%ymm8,%ymm8");
|
||||
if (generator == 3)
|
||||
asm volatile ("vpxor %ymm12,%ymm8,%ymm2");
|
||||
else
|
||||
asm volatile ("vpxor %ymm6,%ymm8,%ymm2");
|
||||
|
||||
asm volatile ("vpcmpgtb %ymm3,%ymm14,%ymm11");
|
||||
asm volatile ("vpaddb %ymm3,%ymm3,%ymm9");
|
||||
asm volatile ("vpxor %ymm7,%ymm5,%ymm13");
|
||||
asm volatile ("vpaddb %ymm2,%ymm2,%ymm2");
|
||||
asm volatile ("vpaddb %ymm3,%ymm3,%ymm3");
|
||||
asm volatile ("vpand %ymm15,%ymm10,%ymm10");
|
||||
asm volatile ("vpand %ymm15,%ymm11,%ymm11");
|
||||
asm volatile ("vpxor %ymm11,%ymm9,%ymm9");
|
||||
asm volatile ("vpxor %ymm5,%ymm9,%ymm9");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm14,%ymm11");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpxor %ymm13,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
asm volatile ("vpxor %ymm3,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm10,%ymm2,%ymm2");
|
||||
asm volatile ("vpxor %ymm11,%ymm3,%ymm3");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm2,%ymm2");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm13,%ymm3,%ymm3");
|
||||
asm volatile ("vpxor %ymm4,%ymm2,%ymm2");
|
||||
asm volatile ("vpxor %ymm5,%ymm3,%ymm3");
|
||||
|
||||
if (g23 && raid_g23_x3(d - 1)) {
|
||||
asm volatile ("vmovdqa %ymm2,%ymm12");
|
||||
asm volatile ("vmovdqa %ymm3,%ymm13");
|
||||
}
|
||||
asm volatile ("vpcmpgtb %ymm2,%ymm14,%ymm10");
|
||||
asm volatile ("vpcmpgtb %ymm3,%ymm14,%ymm11");
|
||||
asm volatile ("vpaddb %ymm2,%ymm2,%ymm2");
|
||||
asm volatile ("vpaddb %ymm3,%ymm3,%ymm3");
|
||||
asm volatile ("vpand %ymm15,%ymm10,%ymm10");
|
||||
asm volatile ("vpand %ymm15,%ymm11,%ymm11");
|
||||
asm volatile ("vpxor %ymm11,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm3");
|
||||
else
|
||||
asm volatile ("vpxor %ymm7,%ymm9,%ymm3");
|
||||
asm volatile ("vpxor %ymm10,%ymm2,%ymm2");
|
||||
asm volatile ("vpxor %ymm11,%ymm3,%ymm3");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vpxor %ymm12,%ymm2,%ymm2");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vpxor %ymm13,%ymm3,%ymm3");
|
||||
asm volatile ("vpxor %ymm6,%ymm2,%ymm2");
|
||||
asm volatile ("vpxor %ymm7,%ymm3,%ymm3");
|
||||
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
asm volatile ("vpxor %ymm6,%ymm0,%ymm0");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
asm volatile ("vpxor %ymm7,%ymm1,%ymm1");
|
||||
}
|
||||
|
||||
/* single remaining disk */
|
||||
|
|
@ -201,11 +208,11 @@ static __always_inline void raid_gen2_avx2ext_gen(int nd, size_t size,
|
|||
asm volatile ("vpcmpgtb %ymm2,%ymm14,%ymm10");
|
||||
asm volatile ("vpaddb %ymm2,%ymm2,%ymm8");
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm4,%ymm2,%ymm12");
|
||||
asm volatile ("vpand %ymm15,%ymm10,%ymm10");
|
||||
asm volatile ("vpxor %ymm10,%ymm8,%ymm8");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm8,%ymm2");
|
||||
else
|
||||
asm volatile ("vpxor %ymm4,%ymm8,%ymm2");
|
||||
|
|
@ -213,11 +220,11 @@ static __always_inline void raid_gen2_avx2ext_gen(int nd, size_t size,
|
|||
asm volatile ("vpcmpgtb %ymm3,%ymm14,%ymm11");
|
||||
asm volatile ("vpaddb %ymm3,%ymm3,%ymm9");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm5,%ymm3,%ymm13");
|
||||
asm volatile ("vpand %ymm15,%ymm11,%ymm11");
|
||||
asm volatile ("vpxor %ymm11,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm3");
|
||||
else
|
||||
asm volatile ("vpxor %ymm5,%ymm9,%ymm3");
|
||||
|
|
@ -234,12 +241,12 @@ static __always_inline void raid_gen2_avx2ext_gen(int nd, size_t size,
|
|||
|
||||
void raid_gen2_avx2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_avx2ext_gen(nd, size, vv, 2);
|
||||
raid_gen2_avx2ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_avx2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_avx2ext_gen(nd, size, vv, 3);
|
||||
raid_gen2_avx2ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -324,7 +331,7 @@ void raid_genz_avx2ext_raid(int nd, size_t size, void **vv)
|
|||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -385,14 +392,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (raid_gfcauchypshufb[d][1][0][0]));
|
||||
asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (raid_gfcauchypshufb[d][1][1][0]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm6");
|
||||
asm volatile ("vpxor %ymm5,%ymm5,%ymm5");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm3,%ymm5,%ymm5");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm6,%ymm1,%ymm1");
|
||||
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
|
|
@ -407,14 +414,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vpxor %ymm7,%ymm6,%ymm6");
|
||||
asm volatile ("vpxor %ymm6,%ymm2,%ymm2");
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm9,%ymm6");
|
||||
asm volatile ("vpxor %ymm13,%ymm13,%ymm13");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpand %ymm3,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm6,%ymm9,%ymm9");
|
||||
|
||||
asm volatile ("vpxor %ymm12,%ymm8,%ymm8");
|
||||
|
|
@ -435,14 +442,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (raid_gfcauchypshufb[d - 1][1][0][0]));
|
||||
asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (raid_gfcauchypshufb[d - 1][1][1][0]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm6");
|
||||
asm volatile ("vpxor %ymm5,%ymm5,%ymm5");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm3,%ymm5,%ymm5");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vpxor %ymm6,%ymm1,%ymm1");
|
||||
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
|
|
@ -457,14 +464,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vpxor %ymm7,%ymm6,%ymm6");
|
||||
asm volatile ("vpxor %ymm6,%ymm2,%ymm2");
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vmovdqa %ymm9,%ymm6");
|
||||
asm volatile ("vpxor %ymm13,%ymm13,%ymm13");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpand %ymm3,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("vpxor %ymm6,%ymm9,%ymm9");
|
||||
|
||||
asm volatile ("vpxor %ymm12,%ymm8,%ymm8");
|
||||
|
|
@ -485,14 +492,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[1][i]));
|
||||
asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[1][i + 32]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm6");
|
||||
asm volatile ("vpxor %ymm5,%ymm5,%ymm5");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm3,%ymm5,%ymm5");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm6,%ymm1,%ymm1");
|
||||
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
|
|
@ -510,14 +517,14 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vpxor %ymm7,%ymm6,%ymm6");
|
||||
asm volatile ("vpxor %ymm6,%ymm2,%ymm2");
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm9,%ymm6");
|
||||
asm volatile ("vpxor %ymm13,%ymm13,%ymm13");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpand %ymm3,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm6,%ymm9,%ymm9");
|
||||
|
||||
asm volatile ("vpxor %ymm12,%ymm8,%ymm8");
|
||||
|
|
@ -537,7 +544,7 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[0][i]));
|
||||
asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[0][i + 32]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("vmovdqa %ymm1,%ymm6");
|
||||
asm volatile ("vmovdqa %ymm9,%ymm14");
|
||||
}
|
||||
|
|
@ -551,7 +558,7 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vpand %ymm3,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("vpxor %ymm6,%ymm1,%ymm1");
|
||||
asm volatile ("vpxor %ymm14,%ymm9,%ymm9");
|
||||
}
|
||||
|
|
@ -576,12 +583,12 @@ static __always_inline void raid_gen3_avx2ext_gen(int nd, size_t size, void **vv
|
|||
|
||||
void raid_gen3_avx2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_avx2ext_gen(nd, size, vv, 2);
|
||||
raid_gen3_avx2ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen3_avx2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_avx2ext_gen(nd, size, vv, 3);
|
||||
raid_gen3_avx2ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -591,7 +598,7 @@ void raid_gen3_avx2ext_aes(int nd, size_t size, void **vv)
|
|||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -658,14 +665,14 @@ static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv
|
|||
|
||||
/* intermediate disks */
|
||||
for (d = l - 1; d > 0; --d) {
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm4");
|
||||
asm volatile ("vpxor %ymm5,%ymm5,%ymm5");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm6,%ymm5,%ymm5");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm4,%ymm1,%ymm1");
|
||||
asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i]));
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
|
|
@ -673,14 +680,14 @@ static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("vpsrlw $4,%ymm4,%ymm5");
|
||||
asm volatile ("vpand %ymm7,%ymm4,%ymm4");
|
||||
asm volatile ("vpand %ymm7,%ymm5,%ymm5");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm9,%ymm12");
|
||||
asm volatile ("vpxor %ymm13,%ymm13,%ymm13");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpand %ymm6,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm9,%ymm9");
|
||||
|
||||
asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[d][i + 32]));
|
||||
|
|
@ -715,28 +722,28 @@ static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv
|
|||
}
|
||||
|
||||
/* first disk with all coefficients at 1 */
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm4");
|
||||
asm volatile ("vpxor %ymm5,%ymm5,%ymm5");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm6,%ymm5,%ymm5");
|
||||
asm volatile ("vpxor %ymm5,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm4,%ymm1,%ymm1");
|
||||
asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[0][i]));
|
||||
asm volatile ("vpxor %ymm4,%ymm0,%ymm0");
|
||||
asm volatile ("vpxor %ymm4,%ymm1,%ymm1");
|
||||
asm volatile ("vpxor %ymm4,%ymm2,%ymm2");
|
||||
asm volatile ("vpxor %ymm4,%ymm3,%ymm3");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm9,%ymm12");
|
||||
asm volatile ("vpxor %ymm13,%ymm13,%ymm13");
|
||||
asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13");
|
||||
asm volatile ("vpaddb %ymm9,%ymm9,%ymm9");
|
||||
asm volatile ("vpand %ymm6,%ymm13,%ymm13");
|
||||
asm volatile ("vpxor %ymm13,%ymm9,%ymm9");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm9,%ymm9");
|
||||
|
||||
asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[0][i + 32]));
|
||||
|
|
@ -760,12 +767,12 @@ static __always_inline void raid_gen4_avx2ext_gen(int nd, size_t size, void **vv
|
|||
|
||||
void raid_gen4_avx2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_avx2ext_gen(nd, size, vv, 2);
|
||||
raid_gen4_avx2ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen4_avx2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_avx2ext_gen(nd, size, vv, 3);
|
||||
raid_gen4_avx2ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -773,7 +780,7 @@ void raid_gen4_avx2ext_aes(int nd, size_t size, void **vv)
|
|||
/*
|
||||
* GENX AVX2EXT implementation
|
||||
*/
|
||||
static __always_inline void raid_genX_avx2ext(int nd, size_t size, void **vv, int np, int generator)
|
||||
static __always_inline void raid_genX_avx2ext(int nd, size_t size, void **vv, int np, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
size_t i;
|
||||
|
|
@ -838,13 +845,13 @@ static __always_inline void raid_genX_avx2ext(int nd, size_t size, void **vv, in
|
|||
for (d = l - 1; d > 0; --d) {
|
||||
asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[d][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm12");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm6,%ymm11");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm14,%ymm11,%ymm11");
|
||||
asm volatile ("vpxor %ymm11,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm1,%ymm1");
|
||||
|
||||
asm volatile ("vpxor %ymm10,%ymm0,%ymm0");
|
||||
|
|
@ -890,13 +897,13 @@ static __always_inline void raid_genX_avx2ext(int nd, size_t size, void **vv, in
|
|||
/* first disk with all coefficients at 1 */
|
||||
asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[0][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vmovdqa %ymm1,%ymm12");
|
||||
asm volatile ("vpcmpgtb %ymm1,%ymm6,%ymm11");
|
||||
asm volatile ("vpaddb %ymm1,%ymm1,%ymm1");
|
||||
asm volatile ("vpand %ymm14,%ymm11,%ymm11");
|
||||
asm volatile ("vpxor %ymm11,%ymm1,%ymm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("vpxor %ymm12,%ymm1,%ymm1");
|
||||
|
||||
asm volatile ("vpxor %ymm10,%ymm0,%ymm0");
|
||||
|
|
@ -934,12 +941,12 @@ static __always_inline void raid_genX_avx2ext(int nd, size_t size, void **vv, in
|
|||
*/
|
||||
void raid_gen5_avx2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_avx2ext(nd, size, vv, 5, 2);
|
||||
raid_genX_avx2ext(nd, size, vv, 5, 0);
|
||||
}
|
||||
|
||||
void raid_gen5_avx2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_avx2ext(nd, size, vv, 5, 3);
|
||||
raid_genX_avx2ext(nd, size, vv, 5, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -951,12 +958,12 @@ void raid_gen5_avx2ext_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen6_avx2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_avx2ext(nd, size, vv, 6, 2);
|
||||
raid_genX_avx2ext(nd, size, vv, 6, 0);
|
||||
}
|
||||
|
||||
void raid_gen6_avx2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_avx2ext(nd, size, vv, 6, 3);
|
||||
raid_genX_avx2ext(nd, size, vv, 6, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
10
raid/gf.h
10
raid/gf.h
|
|
@ -29,16 +29,6 @@ static __always_inline uint8_t inv(uint8_t v)
|
|||
return raid_gfinv[v];
|
||||
}
|
||||
|
||||
/*
|
||||
* GF generator^a for the active Cauchy matrix.
|
||||
*/
|
||||
static __always_inline uint8_t powgen(int v)
|
||||
{
|
||||
BUG_ON(v < 0 || v > 254); /* invalid exponent */
|
||||
|
||||
return raid_gfexp[v];
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the multiplication table for a specified value.
|
||||
*/
|
||||
|
|
|
|||
20
raid/int.c
20
raid/int.c
|
|
@ -63,7 +63,7 @@ void raid_gen1_int64(int nd, size_t size, void **vv)
|
|||
/*
|
||||
* GEN2 (double parity) 32bit C implementation
|
||||
*/
|
||||
static __always_inline void raid_gen2_int32_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_int32_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -92,12 +92,12 @@ static __always_inline void raid_gen2_int32_gen(int nd, size_t size, void **vv,
|
|||
|
||||
qold = q0;
|
||||
q0 = x2_32(q0, poly_32);
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
q0 ^= qold;
|
||||
|
||||
qold = q1;
|
||||
q1 = x2_32(q1, poly_32);
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
q1 ^= qold;
|
||||
|
||||
q0 ^= d0;
|
||||
|
|
@ -112,18 +112,18 @@ static __always_inline void raid_gen2_int32_gen(int nd, size_t size, void **vv,
|
|||
|
||||
void raid_gen2_int32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_int32_gen(nd, size, vv, 2);
|
||||
raid_gen2_int32_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_int32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_int32_gen(nd, size, vv, 3);
|
||||
raid_gen2_int32_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* GEN2 (double parity) 64bit C implementation
|
||||
*/
|
||||
static __always_inline void raid_gen2_int64_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_int64_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -152,12 +152,12 @@ static __always_inline void raid_gen2_int64_gen(int nd, size_t size, void **vv,
|
|||
|
||||
qold = q0;
|
||||
q0 = x2_64(q0, poly_64);
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
q0 ^= qold;
|
||||
|
||||
qold = q1;
|
||||
q1 = x2_64(q1, poly_64);
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
q1 ^= qold;
|
||||
|
||||
q0 ^= d0;
|
||||
|
|
@ -172,12 +172,12 @@ static __always_inline void raid_gen2_int64_gen(int nd, size_t size, void **vv,
|
|||
|
||||
void raid_gen2_int64_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_int64_gen(nd, size, vv, 2);
|
||||
raid_gen2_int64_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_int64_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_int64_gen(nd, size, vv, 3);
|
||||
raid_gen2_int64_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
void raid_gen2_int8(int nd, size_t size, void **vv)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,15 @@ static __always_inline void * __align_ptr(void *ptr, uintptr_t size)
|
|||
return (void *)offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true at the four transitions between the five G23 cosets.
|
||||
* In descending Horner loops, d identifies the q[d] -> q[d + 1] step.
|
||||
*/
|
||||
static __always_inline int raid_g23_x3(int d)
|
||||
{
|
||||
return d == 50 || d == 101 || d == 152 || d == 203;
|
||||
}
|
||||
|
||||
/*
|
||||
* Includes the main interface headers.
|
||||
*/
|
||||
|
|
@ -357,7 +366,6 @@ extern struct gfconst16 gfconst16 __aligned(16);
|
|||
* Tables.
|
||||
*/
|
||||
extern const uint8_t raid_gfmul_raid[256][256] __aligned(256);
|
||||
extern const uint8_t raid_gfexp_raid[256] __aligned(256);
|
||||
extern const uint8_t raid_gfinv_raid[256] __aligned(256);
|
||||
extern const uint8_t raid_gfvandermonde_raid[3][256] __aligned(256);
|
||||
extern const uint8_t raid_gfcauchy_raid[6][256] __aligned(256);
|
||||
|
|
@ -368,7 +376,6 @@ extern const uint8_t raid_gfmulpshufb_raid[256][2][16] __aligned(256);
|
|||
#endif
|
||||
|
||||
extern const uint8_t raid_gfmul_aes[256][256] __aligned(256);
|
||||
extern const uint8_t raid_gfexp_aes[256] __aligned(256);
|
||||
extern const uint8_t raid_gfinv_aes[256] __aligned(256);
|
||||
extern const uint8_t raid_gfcauchy_aes[6][256] __aligned(256);
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)
|
||||
|
|
@ -377,7 +384,6 @@ extern const uint8_t raid_gfmulpshufb_aes[256][2][16] __aligned(256);
|
|||
#endif
|
||||
|
||||
extern const uint8_t(*raid_gfmul)[256];
|
||||
extern const uint8_t *raid_gfexp;
|
||||
extern const uint8_t *raid_gfinv;
|
||||
extern const uint8_t(*raid_gfvandermonde)[256];
|
||||
extern const uint8_t(*raid_gfcauchy)[256];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Galois field reduction polynomials.
|
||||
|
|
@ -84,9 +85,9 @@ uint8_t raid_gfinv[256];
|
|||
#define DISK (257 - PARITY)
|
||||
|
||||
/**
|
||||
* Setup the Cauchy matrix used to generate the parity.
|
||||
* Setup the RAID/g=2 Cauchy matrix used to generate parity.
|
||||
*/
|
||||
static void set_cauchy(uint8_t poly, uint8_t generator, uint8_t *matrix)
|
||||
static void set_cauchy_raid(uint8_t poly, uint8_t generator, uint8_t *matrix)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t inv_x, y;
|
||||
|
|
@ -206,6 +207,60 @@ static void set_cauchy(uint8_t poly, uint8_t generator, uint8_t *matrix)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the AES Extended Cauchy matrix using the G23 sequence.
|
||||
*/
|
||||
static void set_cauchy_aes(uint8_t *matrix)
|
||||
{
|
||||
uint8_t q[255];
|
||||
uint8_t y[PARITY - 1];
|
||||
int i, j, k;
|
||||
|
||||
q[0] = 1;
|
||||
for (i = 0; i < 254; ++i) {
|
||||
uint8_t generator = i == 50 || i == 101 || i == 152 || i == 203 ? 3 : 2;
|
||||
|
||||
q[i + 1] = raid_gfmul(RAID_POLY_AES, generator, q[i]);
|
||||
}
|
||||
|
||||
/* The five cosets must enumerate GF(256)* exactly once. */
|
||||
for (i = 0; i < 255; ++i) {
|
||||
if (q[i] == 0) {
|
||||
fprintf(stderr, "Invalid zero in AES G23 sequence at %d\n", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (k = i + 1; k < 255; ++k) {
|
||||
if (q[i] == q[k]) {
|
||||
fprintf(stderr, "Duplicate in AES G23 sequence at %d and %d\n", i, k);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < DISK; ++i)
|
||||
matrix[i] = 1;
|
||||
|
||||
y[0] = 0;
|
||||
for (j = 1; j < PARITY - 1; ++j)
|
||||
y[j] = raid_gfinv[q[DISK + j - 1]];
|
||||
|
||||
for (j = 0; j < PARITY - 1; ++j) {
|
||||
for (i = 0; i < DISK; ++i) {
|
||||
uint8_t x = raid_gfinv[q[i]];
|
||||
|
||||
matrix[(j + 1) * DISK + i] = raid_gfinv[x ^ y[j]];
|
||||
}
|
||||
}
|
||||
|
||||
/* Normalize R..U so every coefficient in the first column is 1. */
|
||||
for (j = 1; j < PARITY - 1; ++j) {
|
||||
uint8_t f = raid_gfinv[matrix[(j + 1) * DISK]];
|
||||
|
||||
for (i = 0; i < DISK; ++i)
|
||||
matrix[(j + 1) * DISK + i] = raid_gfmul(RAID_POLY_AES, matrix[(j + 1) * DISK + i], f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the Power matrix used to generate the parity.
|
||||
*/
|
||||
|
|
@ -284,22 +339,6 @@ void tables(uint8_t poly, uint8_t generator, const char *tag)
|
|||
printf("};\n\n");
|
||||
}
|
||||
|
||||
/* generator^a */
|
||||
printf("const uint8_t __aligned(256) raid_gfexp_%s[256] =\n", tag);
|
||||
printf("{\n");
|
||||
v = 1;
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (i % 8 == 0)
|
||||
printf("\t");
|
||||
printf("0x%02x,", v);
|
||||
v = raid_gfmul(poly, v, generator);
|
||||
if (i % 8 == 7)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* 1/a */
|
||||
printf("const uint8_t __aligned(256) raid_gfinv_%s[256] =\n", tag);
|
||||
printf("{\n");
|
||||
|
|
@ -320,7 +359,10 @@ void tables(uint8_t poly, uint8_t generator, const char *tag)
|
|||
printf("};\n\n");
|
||||
|
||||
/* cauchy matrix */
|
||||
set_cauchy(poly, generator, matrix);
|
||||
if (poly == RAID_POLY_AES)
|
||||
set_cauchy_aes(matrix);
|
||||
else
|
||||
set_cauchy_raid(poly, generator, matrix);
|
||||
|
||||
printf("/**\n");
|
||||
printf(" * Cauchy matrix used to generate parity.\n");
|
||||
|
|
@ -410,10 +452,11 @@ void tables(uint8_t poly, uint8_t generator, const char *tag)
|
|||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n");
|
||||
printf("#endif\n\n");
|
||||
printf("#endif\n");
|
||||
|
||||
if (poly == RAID_POLY_AES)
|
||||
return;
|
||||
printf("\n");
|
||||
|
||||
/* power matrix */
|
||||
set_power(poly, matrix);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ static struct raid_rec_algo *raid_rec_algo;
|
|||
int raid_mode_active = RAID_MODE_GET;
|
||||
|
||||
const uint8_t(*raid_gfmul)[256];
|
||||
const uint8_t *raid_gfexp;
|
||||
const uint8_t *raid_gfinv;
|
||||
const uint8_t(*raid_gfvandermonde)[256];
|
||||
const uint8_t(*raid_gfcauchy)[256];
|
||||
|
|
@ -225,7 +224,6 @@ int raid_mode(int mode)
|
|||
|
||||
if (mode == RAID_MODE_CAUCHY_AES) {
|
||||
raid_gfmul = raid_gfmul_aes;
|
||||
raid_gfexp = raid_gfexp_aes;
|
||||
raid_gfinv = raid_gfinv_aes;
|
||||
raid_gfvandermonde = 0;
|
||||
raid_gfcauchy = raid_gfcauchy_aes;
|
||||
|
|
@ -245,7 +243,6 @@ int raid_mode(int mode)
|
|||
raid_rec_algo = raid_rec_algo_aes;
|
||||
} else {
|
||||
raid_gfmul = raid_gfmul_raid;
|
||||
raid_gfexp = raid_gfexp_raid;
|
||||
raid_gfinv = raid_gfinv_raid;
|
||||
raid_gfvandermonde = raid_gfvandermonde_raid;
|
||||
raid_gfcauchy = raid_gfcauchy_raid;
|
||||
|
|
|
|||
38
raid/neon.c
38
raid/neon.c
|
|
@ -60,9 +60,9 @@ void raid_gen1_neon(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* GEN2 Cauchy NEON implementation using the active generator
|
||||
* GEN2 Cauchy NEON implementation using the active Q transition
|
||||
*/
|
||||
static __always_inline void raid_gen2_neon_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_neon_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -93,7 +93,7 @@ static __always_inline void raid_gen2_neon_gen(int nd, size_t size, void **vv, i
|
|||
);
|
||||
|
||||
for (d = l - 1; d >= 0; --d) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
/* v14-v15 are otherwise unused and preserve Q across the AES xtime. */
|
||||
asm volatile (
|
||||
"mov v14.16b, v2.16b\n"
|
||||
|
|
@ -122,7 +122,7 @@ static __always_inline void raid_gen2_neon_gen(int nd, size_t size, void **vv, i
|
|||
:
|
||||
: "m" (v[d][i]), "m" (v[d][i + 16])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"eor v2.16b, v2.16b, v14.16b\n"
|
||||
"eor v3.16b, v3.16b, v15.16b\n"
|
||||
|
|
@ -145,12 +145,12 @@ static __always_inline void raid_gen2_neon_gen(int nd, size_t size, void **vv, i
|
|||
|
||||
void raid_gen2_neon_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_neon_gen(nd, size, vv, 2);
|
||||
raid_gen2_neon_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_neon_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_neon_gen(nd, size, vv, 3);
|
||||
raid_gen2_neon_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -250,7 +250,7 @@ void raid_genz_neon_raid(int nd, size_t size, void **vv)
|
|||
/*
|
||||
* GENX NEON implementation
|
||||
*/
|
||||
static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int np, int generator)
|
||||
static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int np, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
size_t i;
|
||||
|
|
@ -359,7 +359,7 @@ static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int n
|
|||
|
||||
/* intermediate disks */
|
||||
for (d = l - 1; d > 0; --d) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"mov v14.16b, v2.16b\n"
|
||||
"mov v15.16b, v3.16b\n"
|
||||
|
|
@ -387,7 +387,7 @@ static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int n
|
|||
:
|
||||
: "m" (v[d][i]), "m" (v[d][i + 16])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"eor v2.16b, v2.16b, v14.16b\n"
|
||||
"eor v3.16b, v3.16b, v15.16b\n"
|
||||
|
|
@ -475,7 +475,7 @@ static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int n
|
|||
}
|
||||
|
||||
/* first disk with all coefficients at 1 */
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"mov v14.16b, v2.16b\n"
|
||||
"mov v15.16b, v3.16b\n"
|
||||
|
|
@ -503,7 +503,7 @@ static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int n
|
|||
:
|
||||
: "m" (v[0][i]), "m" (v[0][i + 16])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"eor v2.16b, v2.16b, v14.16b\n"
|
||||
"eor v3.16b, v3.16b, v15.16b\n"
|
||||
|
|
@ -582,12 +582,12 @@ static __always_inline void raid_genX_neon(int nd, size_t size, void **vv, int n
|
|||
*/
|
||||
void raid_gen3_neon_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 3, 2);
|
||||
raid_genX_neon(nd, size, vv, 3, 0);
|
||||
}
|
||||
|
||||
void raid_gen3_neon_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 3, 3);
|
||||
raid_genX_neon(nd, size, vv, 3, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -595,12 +595,12 @@ void raid_gen3_neon_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen4_neon_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 4, 2);
|
||||
raid_genX_neon(nd, size, vv, 4, 0);
|
||||
}
|
||||
|
||||
void raid_gen4_neon_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 4, 3);
|
||||
raid_genX_neon(nd, size, vv, 4, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -608,12 +608,12 @@ void raid_gen4_neon_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen5_neon_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 5, 2);
|
||||
raid_genX_neon(nd, size, vv, 5, 0);
|
||||
}
|
||||
|
||||
void raid_gen5_neon_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 5, 3);
|
||||
raid_genX_neon(nd, size, vv, 5, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -621,12 +621,12 @@ void raid_gen5_neon_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen6_neon_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 6, 2);
|
||||
raid_genX_neon(nd, size, vv, 6, 0);
|
||||
}
|
||||
|
||||
void raid_gen6_neon_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon(nd, size, vv, 6, 3);
|
||||
raid_genX_neon(nd, size, vv, 6, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -63,10 +63,10 @@ void raid_gen1_neon32(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* GEN2 Cauchy AArch32 NEON implementation using the active generator.
|
||||
* GEN2 Cauchy AArch32 NEON implementation using the active Q transition.
|
||||
*/
|
||||
static __always_inline void raid_gen2_neon32_gen(int nd, size_t size,
|
||||
void **vv, int generator)
|
||||
void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -98,7 +98,7 @@ static __always_inline void raid_gen2_neon32_gen(int nd, size_t size,
|
|||
);
|
||||
|
||||
for (d = l - 1; d >= 0; --d) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"vmov q10, q2\n"
|
||||
"vmov q11, q3\n"
|
||||
|
|
@ -122,7 +122,7 @@ static __always_inline void raid_gen2_neon32_gen(int nd, size_t size,
|
|||
:
|
||||
: "Q" (v[d][i]), "Q" (v[d][i + 16])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"veor q2, q2, q10\n"
|
||||
"veor q3, q3, q11\n"
|
||||
|
|
@ -145,12 +145,12 @@ static __always_inline void raid_gen2_neon32_gen(int nd, size_t size,
|
|||
|
||||
void raid_gen2_neon32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_neon32_gen(nd, size, vv, 2);
|
||||
raid_gen2_neon32_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_neon32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_neon32_gen(nd, size, vv, 3);
|
||||
raid_gen2_neon32_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -244,7 +244,7 @@ void raid_genz_neon32_raid(int nd, size_t size, void **vv)
|
|||
* GENX AArch32 NEON implementation.
|
||||
*/
|
||||
static __always_inline void raid_genX_neon32(int nd, size_t size,
|
||||
void **vv, int np, int generator)
|
||||
void **vv, int np, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
size_t i;
|
||||
|
|
@ -353,7 +353,7 @@ static __always_inline void raid_genX_neon32(int nd, size_t size,
|
|||
|
||||
/* intermediate disks */
|
||||
for (d = l - 1; d > 0; --d) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"vmov q13, q1\n"
|
||||
);
|
||||
|
|
@ -369,7 +369,7 @@ static __always_inline void raid_genX_neon32(int nd, size_t size,
|
|||
:
|
||||
: "Q" (v[d][i])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"veor q1, q1, q13\n"
|
||||
);
|
||||
|
|
@ -448,7 +448,7 @@ static __always_inline void raid_genX_neon32(int nd, size_t size,
|
|||
}
|
||||
|
||||
/* first disk with all coefficients at 1 */
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"vmov q13, q1\n"
|
||||
);
|
||||
|
|
@ -464,7 +464,7 @@ static __always_inline void raid_genX_neon32(int nd, size_t size,
|
|||
:
|
||||
: "Q" (v[0][i])
|
||||
);
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile (
|
||||
"veor q1, q1, q13\n"
|
||||
);
|
||||
|
|
@ -533,12 +533,12 @@ static __always_inline void raid_genX_neon32(int nd, size_t size,
|
|||
*/
|
||||
void raid_gen3_neon32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 3, 2);
|
||||
raid_genX_neon32(nd, size, vv, 3, 0);
|
||||
}
|
||||
|
||||
void raid_gen3_neon32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 3, 3);
|
||||
raid_genX_neon32(nd, size, vv, 3, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -546,12 +546,12 @@ void raid_gen3_neon32_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen4_neon32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 4, 2);
|
||||
raid_genX_neon32(nd, size, vv, 4, 0);
|
||||
}
|
||||
|
||||
void raid_gen4_neon32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 4, 3);
|
||||
raid_genX_neon32(nd, size, vv, 4, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -559,12 +559,12 @@ void raid_gen4_neon32_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen5_neon32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 5, 2);
|
||||
raid_genX_neon32(nd, size, vv, 5, 0);
|
||||
}
|
||||
|
||||
void raid_gen5_neon32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 5, 3);
|
||||
raid_genX_neon32(nd, size, vv, 5, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -572,12 +572,12 @@ void raid_gen5_neon32_aes(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen6_neon32_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 6, 2);
|
||||
raid_genX_neon32(nd, size, vv, 6, 0);
|
||||
}
|
||||
|
||||
void raid_gen6_neon32_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_neon32(nd, size, vv, 6, 3);
|
||||
raid_genX_neon32(nd, size, vv, 6, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
60
raid/raid.c
60
raid/raid.c
|
|
@ -38,20 +38,30 @@
|
|||
* nonsingular, so the linear system is always solvable for any combination
|
||||
* of missing disks. This guarantees an MDS code.
|
||||
*
|
||||
* The Cauchy construction below uses a primitive generator g.
|
||||
* RAID_MODE_CAUCHY_RAID uses polynomial 0x11d and the existing primitive
|
||||
* generator g=2 construction described below.
|
||||
*
|
||||
* RAID_MODE_CAUCHY_RAID uses:
|
||||
* polynomial 0x11d
|
||||
* generator g = 2
|
||||
* RAID_MODE_CAUCHY_AES instead uses polynomial 0x11b and a G23 Extended
|
||||
* Cauchy construction. In the AES field, element 2 has multiplicative order
|
||||
* 51 while element 3 is primitive. Therefore H=<2> has five cosets in
|
||||
* GF(256)*. The Q coefficients q[0..254] enumerate those cosets, starting
|
||||
* with q[0]=1. Within a coset q advances by multiplication by 2. The four
|
||||
* transitions between cosets advance by multiplication by 3, after the
|
||||
* coefficients indexed 50, 101, 152, and 203.
|
||||
*
|
||||
* RAID_MODE_CAUCHY_AES uses:
|
||||
* polynomial 0x11b
|
||||
* generator g = 3
|
||||
* The AES data columns use q[0..250]. Their inverses form the X set. The
|
||||
* inverses of the four unused values q[251..254], together with zero, form
|
||||
* the five-element Y set. X and Y are disjoint and together contain all 256
|
||||
* field elements, so C[j,i]=1/(X[i]+Y[j]) defines five valid Cauchy rows.
|
||||
* Adding P as an all-ones row forms an Extended Cauchy matrix. Q is the row
|
||||
* for Y[0]=0 and therefore Q=sum(q[i]*Di). Rows R through U are
|
||||
* scaled so their first coefficient is 1. This nonzero row scaling preserves
|
||||
* the MDS property, and the resulting 6x251 matrix is MDS.
|
||||
*
|
||||
* The numerical examples below refer to RAID_MODE_CAUCHY_RAID,
|
||||
* using polynomial 0x11d and generator g = 2.
|
||||
*
|
||||
* How the matrix is obtained:
|
||||
* How the RAID/g=2 matrix is obtained:
|
||||
*
|
||||
* The matrix is constructed to match Linux RAID coefficients for the
|
||||
* first two rows, while ensuring that all square submatrices are nonsingular.
|
||||
|
|
@ -121,7 +131,7 @@
|
|||
* data disks, one for each column. All the 377,342,351,231 square submatrices
|
||||
* are nonsingular, verified also by brute-force testing.
|
||||
*
|
||||
* This matrix can be extended to support any number of parities by simply
|
||||
* The RAID/g=2 matrix can be extended to support any number of parities by simply
|
||||
* adding additional rows and removing one column for each new row to maintain
|
||||
* the condition i + j < 255.
|
||||
* (See mktables.c for more details on how the matrix is generated.)
|
||||
|
|
@ -132,27 +142,27 @@
|
|||
* or AVX2 instructions [1][5] make this approach competitive with the triple
|
||||
* parity computation using power coefficients.
|
||||
*
|
||||
* Another advantage of the Cauchy matrix is that the first two rows can
|
||||
* Another advantage of the RAID/g=2 Cauchy matrix is that the first two rows can
|
||||
* replicate the RAID5 and RAID6 approach, resulting in a compatible extension.
|
||||
* SSSE3 or AVX2 instructions are only needed for triple parity or beyond.
|
||||
*
|
||||
* Parity computation is as follows:
|
||||
*
|
||||
* P = sum(Di)
|
||||
* Q = sum(g^i * Di)
|
||||
* Q = sum(A[1,i] * Di)
|
||||
* R = sum(A[2,i] * Di)
|
||||
* S = sum(A[3,i] * Di)
|
||||
* T = sum(A[4,i] * Di)
|
||||
* U = sum(A[5,i] * Di) for 0 <= i < N
|
||||
*
|
||||
* where g=2 for RAID_MODE_CAUCHY_RAID and
|
||||
* g=3 for RAID_MODE_CAUCHY_AES.
|
||||
* For RAID_MODE_CAUCHY_RAID, A[1,i]=2^i. For RAID_MODE_CAUCHY_AES,
|
||||
* A[1,i]=q[i] from the G23 sequence.
|
||||
*
|
||||
* Recovery from six disk failures at indices x, y, z, h, v, w (0 <= x < y < z < h < v < w < N)
|
||||
* involves computing parity of the remaining N-6 disks:
|
||||
*
|
||||
* Pa = sum(Di)
|
||||
* Qa = sum(g^i * Di)
|
||||
* Qa = sum(A[1,i] * Di)
|
||||
* Ra = sum(A[2,i] * Di)
|
||||
* Sa = sum(A[3,i] * Di)
|
||||
* Ta = sum(A[4,i] * Di)
|
||||
|
|
@ -170,15 +180,12 @@
|
|||
* yields:
|
||||
*
|
||||
* Pd = Dx + Dy + Dz + Dh + Dv + Dw
|
||||
* Qd = g^x * Dx + g^y * Dy + g^z * Dz + g^h * Dh + g^v * Dv + g^w * Dw
|
||||
* Qd = A[1,x] * Dx + A[1,y] * Dy + A[1,z] * Dz + A[1,h] * Dh + A[1,v] * Dv + A[1,w] * Dw
|
||||
* Rd = A[2,x] * Dx + A[2,y] * Dy + A[2,z] * Dz + A[2,h] * Dh + A[2,v] * Dv + A[2,w] * Dw
|
||||
* Sd = A[3,x] * Dx + A[3,y] * Dy + A[3,z] * Dz + A[3,h] * Dh + A[3,v] * Dv + A[3,w] * Dw
|
||||
* Td = A[4,x] * Dx + A[4,y] * Dy + A[4,z] * Dz + A[4,h] * Dh + A[4,v] * Dv + A[4,w] * Dw
|
||||
* Ud = A[5,x] * Dx + A[5,y] * Dy + A[5,z] * Dz + A[5,h] * Dh + A[5,v] * Dv + A[5,w] * Dw
|
||||
*
|
||||
* with g=2 for RAID_MODE_CAUCHY_RAID and
|
||||
* g=3 for RAID_MODE_CAUCHY_AES.
|
||||
*
|
||||
* This linear system is always solvable since the coefficient matrix is
|
||||
* nonsingular due to the properties of A[].
|
||||
*
|
||||
|
|
@ -422,20 +429,19 @@ void raid_rec1of1(int *id, int nd, size_t size, void **v)
|
|||
* Starting from the equations:
|
||||
*
|
||||
* Pd = Dx + Dy
|
||||
* Qd = g^id[0] * Dx + g^id[1] * Dy
|
||||
* Qd = A[1,id[0]] * Dx + A[1,id[1]] * Dy
|
||||
*
|
||||
* and solving we get:
|
||||
*
|
||||
* 1 g^(-id[0])
|
||||
* Dy = ------------------- * Pd + ------------------- * Qd
|
||||
* g^(id[1]-id[0]) + 1 g^(id[1]-id[0]) + 1
|
||||
* Qd + A[1,id[0]] * Pd
|
||||
* Dy = ------------------------
|
||||
* A[1,id[0]] + A[1,id[1]]
|
||||
*
|
||||
* Dx = Dy + Pd
|
||||
*
|
||||
* with conditions:
|
||||
*
|
||||
* g^id[0] != 0
|
||||
* g^(id[1]-id[0]) + 1 != 0
|
||||
* A[1,id[0]] + A[1,id[1]] != 0
|
||||
*
|
||||
* That are always satisfied for any 0<=id[0]<id[1]<255.
|
||||
*/
|
||||
|
|
@ -449,9 +455,9 @@ void raid_rec2of2_int8(int *id, int *ip, int nd, size_t size, void **vv)
|
|||
uint8_t *qa;
|
||||
const uint8_t *T[2];
|
||||
|
||||
/* get multiplication tables */
|
||||
T[0] = table(inv(powgen(id[1] - id[0]) ^ 1));
|
||||
T[1] = table(inv(powgen(id[0]) ^ powgen(id[1])));
|
||||
/* get multiplication tables from the actual active Q coefficients */
|
||||
T[0] = table(mul(A(1, id[0]), inv(A(1, id[0]) ^ A(1, id[1]))));
|
||||
T[1] = table(inv(A(1, id[0]) ^ A(1, id[1])));
|
||||
|
||||
/* compute delta parity */
|
||||
raid_delta_gen(2, id, ip, nd, size, vv);
|
||||
|
|
|
|||
17
raid/raid.h
17
raid/raid.h
|
|
@ -11,7 +11,7 @@
|
|||
* arithmetic is performed modulo an irreducible polynomial of degree 8.
|
||||
* The choice of operating mode affects both correctness and performance:
|
||||
* all tables, coefficients, and parity data are tied to the selected
|
||||
* polynomial and primitive generator and cannot be mixed between
|
||||
* polynomial and generator matrix and cannot be mixed between
|
||||
* incompatible operating modes.
|
||||
*
|
||||
* Two polynomials are supported:
|
||||
|
|
@ -31,7 +31,8 @@
|
|||
* 0x1b (x^8 + x^4 + x^3 + x + 1) -- AES polynomial
|
||||
*
|
||||
* The polynomial used by the AES encryption standard (0x11b including
|
||||
* the x^8 term), used with primitive generator g=3.
|
||||
* the x^8 term). Parity uses a 6x251 Extended Cauchy matrix whose Q row
|
||||
* follows the G23 sequence.
|
||||
*
|
||||
* On CPUs supporting Intel GFNI, generation and recovery can use the
|
||||
* vgf2p8mulb instruction, which performs GF(2^8) multiplication directly
|
||||
|
|
@ -76,14 +77,14 @@
|
|||
#define RAID_MODE_VANDERMONDE_RAID 1
|
||||
|
||||
/**
|
||||
* RAID mode supporting up to 6 parities using AES polynomial 0x1b (0x11b) and primitive generator g=3.
|
||||
* RAID mode supporting up to 6 parities and 251 data disks using AES polynomial 0x1b (0x11b).
|
||||
*
|
||||
* It has slightly lower performance than RAID_MODE_CAUCHY_RAID on CPUs without GFNI due
|
||||
* to the additional cost of generator g=3. On CPUs supporting GFNI, it uses native
|
||||
* VGF2P8MULB multiplication and is typically faster than the affine GFNI implementation
|
||||
* required by RAID_MODE_CAUCHY_RAID.
|
||||
* It uses an Extended Cauchy matrix with a G23 Q sequence, allowing optimized
|
||||
* generators to use multiplication by 2 for almost every disk transition.
|
||||
* On CPUs supporting GFNI, it uses native VGF2P8MULB multiplication.
|
||||
*
|
||||
* Parity data is incompatible with RAID_MODE_CAUCHY_RAID.
|
||||
* This parity layout is incompatible with RAID_MODE_CAUCHY_RAID and with the
|
||||
* previous RAID_MODE_CAUCHY_AES layout.
|
||||
*/
|
||||
#define RAID_MODE_CAUCHY_AES 2
|
||||
|
||||
|
|
|
|||
120
raid/sse2.c
120
raid/sse2.c
|
|
@ -52,11 +52,11 @@
|
|||
* ================================================================
|
||||
*
|
||||
* This file implements different strategies for computing the Q parity.
|
||||
* Q parity requires scaling each data disk by a descending power of the
|
||||
* primitive generator g (g=2 for RAID_MODE_CAUCHY_RAID, g=3 for
|
||||
* RAID_MODE_CAUCHY_AES) in the Galois Field:
|
||||
* Q parity uses coefficients connected by cheap GF transitions. RAID mode
|
||||
* always uses multiplication by 2. AES mode also uses multiplication by 2,
|
||||
* except for the four G23 coset transitions that use multiplication by 3.
|
||||
*
|
||||
* Q = (D_l * g^l) + (D_{l-1} * g^{l-1}) + ... + (D_1 * g^1) + (D_0 * 1)
|
||||
* Q = (D_l * q[l]) + ... + (D_1 * q[1]) + (D_0 * q[0])
|
||||
*
|
||||
* To efficiently calculate this sequentially using SIMD instructions, we
|
||||
* use Horner's method. Depending on hardware architecture and whether we
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
* CASE 1: Multiplication BEFORE XOR, handling all disks inside the loop
|
||||
* -------------------------------------------------------------------------
|
||||
* Used in GEN2 where all disks can be processed uniformly.
|
||||
* The accumulator is scaled by the active generator BEFORE adding the current disk.
|
||||
* The accumulator is scaled by the active Q transition BEFORE adding the current disk.
|
||||
* Because the loop runs all the way down to D0 (d >= 0), the final disk is XORed
|
||||
* into the accumulator and the loop terminates. This naturally leaves D0 with
|
||||
* a coefficient of 1, as it escapes the scaling step.
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
* Simplified Code:
|
||||
* Q = D_l;
|
||||
* for (d = l - 1; d >= 0; --d) {
|
||||
* Q = Q * g; // Scale accumulator by active generator
|
||||
* Q = Q * step[d]; // Scale by 2, or by 3 at a G23 transition
|
||||
* Q = Q ^ D_d; // Add current disk
|
||||
* }
|
||||
*
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
* Simplified Code:
|
||||
* Q = D_l;
|
||||
* for (d = l - 1; d > 0; --d) {
|
||||
* Q = Q * g; // Scale accumulator by active generator
|
||||
* Q = Q * step[d]; // Scale by 2, or by 3 at a G23 transition
|
||||
* Q = Q ^ D_d; // Add current disk
|
||||
* }
|
||||
*
|
||||
|
|
@ -137,9 +137,9 @@ void raid_gen1_sse2(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* GEN2 Cauchy SSE2 implementation using the active generator
|
||||
* GEN2 Cauchy SSE2 implementation using the active Q transition
|
||||
*/
|
||||
static __always_inline void raid_gen2_sse2_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_sse2_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -162,8 +162,8 @@ static __always_inline void raid_gen2_sse2_gen(int nd, size_t size, void **vv, i
|
|||
asm volatile ("movdqa %xmm1,%xmm3");
|
||||
|
||||
for (d = l - 1; d >= 0; --d) {
|
||||
/* scale Q by the active generator before adding the current disk */
|
||||
if (generator == 3) {
|
||||
/* scale Q before adding the current disk */
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm2,%xmm4");
|
||||
asm volatile ("movdqa %xmm3,%xmm5");
|
||||
asm volatile ("pxor %xmm6,%xmm6");
|
||||
|
|
@ -210,21 +210,21 @@ static __always_inline void raid_gen2_sse2_gen(int nd, size_t size, void **vv, i
|
|||
|
||||
void raid_gen2_sse2_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_sse2_gen(nd, size, vv, 2);
|
||||
raid_gen2_sse2_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_sse2_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_sse2_gen(nd, size, vv, 3);
|
||||
raid_gen2_sse2_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* GEN2 Cauchy SSE2 implementation using the active generator
|
||||
* GEN2 Cauchy SSE2 implementation using the active Q transition
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen2_sse2ext_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen2_sse2ext_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -256,118 +256,122 @@ static __always_inline void raid_gen2_sse2ext_gen(int nd, size_t size, void **vv
|
|||
asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i]));
|
||||
asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d - 1][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm4,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm4,%xmm11");
|
||||
asm volatile ("paddb %xmm4,%xmm4");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm4");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm10,%xmm4");
|
||||
asm volatile ("pxor %xmm8,%xmm4");
|
||||
|
||||
asm volatile ("pxor %xmm9,%xmm8");
|
||||
asm volatile ("pxor %xmm8,%xmm0");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm10,%xmm8");
|
||||
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("movdqa %xmm4,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm4,%xmm11");
|
||||
asm volatile ("paddb %xmm4,%xmm4");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm4");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm8,%xmm4");
|
||||
else
|
||||
asm volatile ("pxor %xmm9,%xmm4");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("pxor %xmm10,%xmm4");
|
||||
asm volatile ("pxor %xmm9,%xmm4");
|
||||
|
||||
asm volatile ("pxor %xmm8,%xmm0");
|
||||
asm volatile ("pxor %xmm9,%xmm0");
|
||||
|
||||
/* lane 1 */
|
||||
asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i + 16]));
|
||||
asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d - 1][i + 16]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm5,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm5,%xmm11");
|
||||
asm volatile ("paddb %xmm5,%xmm5");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm5");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm10,%xmm5");
|
||||
asm volatile ("pxor %xmm8,%xmm5");
|
||||
|
||||
asm volatile ("pxor %xmm9,%xmm8");
|
||||
asm volatile ("pxor %xmm8,%xmm1");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm10,%xmm8");
|
||||
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("movdqa %xmm5,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm5,%xmm11");
|
||||
asm volatile ("paddb %xmm5,%xmm5");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm5");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm8,%xmm5");
|
||||
else
|
||||
asm volatile ("pxor %xmm9,%xmm5");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("pxor %xmm10,%xmm5");
|
||||
asm volatile ("pxor %xmm9,%xmm5");
|
||||
|
||||
asm volatile ("pxor %xmm8,%xmm1");
|
||||
asm volatile ("pxor %xmm9,%xmm1");
|
||||
|
||||
/* lane 2 */
|
||||
asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i + 32]));
|
||||
asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d - 1][i + 32]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm6,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm6,%xmm11");
|
||||
asm volatile ("paddb %xmm6,%xmm6");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm6");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm10,%xmm6");
|
||||
asm volatile ("pxor %xmm8,%xmm6");
|
||||
|
||||
asm volatile ("pxor %xmm9,%xmm8");
|
||||
asm volatile ("pxor %xmm8,%xmm2");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm10,%xmm8");
|
||||
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("movdqa %xmm6,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm6,%xmm11");
|
||||
asm volatile ("paddb %xmm6,%xmm6");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm6");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm8,%xmm6");
|
||||
else
|
||||
asm volatile ("pxor %xmm9,%xmm6");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("pxor %xmm10,%xmm6");
|
||||
asm volatile ("pxor %xmm9,%xmm6");
|
||||
|
||||
asm volatile ("pxor %xmm8,%xmm2");
|
||||
asm volatile ("pxor %xmm9,%xmm2");
|
||||
|
||||
/* lane 3 */
|
||||
asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i + 48]));
|
||||
asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d - 1][i + 48]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm7,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm7,%xmm11");
|
||||
asm volatile ("paddb %xmm7,%xmm7");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm7");
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm10,%xmm7");
|
||||
asm volatile ("pxor %xmm8,%xmm7");
|
||||
|
||||
asm volatile ("pxor %xmm9,%xmm8");
|
||||
asm volatile ("pxor %xmm8,%xmm3");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm10,%xmm8");
|
||||
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("movdqa %xmm7,%xmm10");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm7,%xmm11");
|
||||
asm volatile ("paddb %xmm7,%xmm7");
|
||||
asm volatile ("pand %xmm15,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm7");
|
||||
if (generator == 3)
|
||||
asm volatile ("pxor %xmm8,%xmm7");
|
||||
else
|
||||
asm volatile ("pxor %xmm9,%xmm7");
|
||||
if (g23 && raid_g23_x3(d - 1))
|
||||
asm volatile ("pxor %xmm10,%xmm7");
|
||||
asm volatile ("pxor %xmm9,%xmm7");
|
||||
|
||||
asm volatile ("pxor %xmm8,%xmm3");
|
||||
asm volatile ("pxor %xmm9,%xmm3");
|
||||
}
|
||||
|
||||
/* single remaining disk */
|
||||
if (d == 0) {
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm4,%xmm8");
|
||||
asm volatile ("movdqa %xmm5,%xmm9");
|
||||
asm volatile ("movdqa %xmm6,%xmm10");
|
||||
|
|
@ -448,12 +452,12 @@ static __always_inline void raid_gen2_sse2ext_gen(int nd, size_t size, void **vv
|
|||
|
||||
void raid_gen2_sse2ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_sse2ext_gen(nd, size, vv, 2);
|
||||
raid_gen2_sse2ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen2_sse2ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen2_sse2ext_gen(nd, size, vv, 3);
|
||||
raid_gen2_sse2ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
82
raid/ssse3.c
82
raid/ssse3.c
|
|
@ -9,7 +9,7 @@
|
|||
/*
|
||||
* GEN3 (triple parity with Cauchy matrix) SSSE3 implementation
|
||||
*/
|
||||
static __always_inline void raid_gen3_ssse3_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen3_ssse3_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -58,14 +58,14 @@ static __always_inline void raid_gen3_ssse3_gen(int nd, size_t size, void **vv,
|
|||
for (d = l - 1; d > 0; --d) {
|
||||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("pxor %xmm5,%xmm5");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm5");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm3,%xmm5");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
|
||||
asm volatile ("pxor %xmm4,%xmm0");
|
||||
|
|
@ -87,14 +87,14 @@ static __always_inline void raid_gen3_ssse3_gen(int nd, size_t size, void **vv,
|
|||
/* first disk with all coefficients at 1 */
|
||||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("pxor %xmm5,%xmm5");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm5");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm3,%xmm5");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
|
||||
asm volatile ("pxor %xmm4,%xmm0");
|
||||
|
|
@ -111,12 +111,12 @@ static __always_inline void raid_gen3_ssse3_gen(int nd, size_t size, void **vv,
|
|||
|
||||
void raid_gen3_ssse3_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_ssse3_gen(nd, size, vv, 2);
|
||||
raid_gen3_ssse3_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen3_ssse3_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_ssse3_gen(nd, size, vv, 3);
|
||||
raid_gen3_ssse3_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
|
@ -125,7 +125,7 @@ void raid_gen3_ssse3_aes(int nd, size_t size, void **vv)
|
|||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -191,7 +191,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm7" : : "m" (raid_gfcauchypshufb[d][1][0][0]));
|
||||
asm volatile ("movdqa %0,%%xmm15" : : "m" (raid_gfcauchypshufb[d][1][1][0]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm3,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -241,7 +241,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm7" : : "m" (raid_gfcauchypshufb[d - 1][1][0][0]));
|
||||
asm volatile ("movdqa %0,%%xmm15" : : "m" (raid_gfcauchypshufb[d - 1][1][1][0]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d - 1)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm3,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d - 1)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -290,7 +290,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[1][i]));
|
||||
asm volatile ("movdqa %0,%%xmm12" : : "m" (v[1][i + 16]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -304,7 +304,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm3,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -341,7 +341,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
|
||||
asm volatile ("movdqa %0,%%xmm12" : : "m" (v[0][i + 16]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -355,7 +355,7 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm3,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -380,19 +380,19 @@ static __always_inline void raid_gen3_ssse3ext_gen(int nd, size_t size, void **v
|
|||
|
||||
void raid_gen3_ssse3ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_ssse3ext_gen(nd, size, vv, 2);
|
||||
raid_gen3_ssse3ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen3_ssse3ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen3_ssse3ext_gen(nd, size, vv, 3);
|
||||
raid_gen3_ssse3ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GEN4 (quad parity with Cauchy matrix) SSSE3 implementation
|
||||
*/
|
||||
static __always_inline void raid_gen4_ssse3_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen4_ssse3_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -448,14 +448,14 @@ static __always_inline void raid_gen4_ssse3_gen(int nd, size_t size, void **vv,
|
|||
asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("pxor %xmm5,%xmm5");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm5");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm7,%xmm5");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
|
||||
asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
|
||||
|
|
@ -487,14 +487,14 @@ static __always_inline void raid_gen4_ssse3_gen(int nd, size_t size, void **vv,
|
|||
asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("pxor %xmm5,%xmm5");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm5");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm7,%xmm5");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
|
||||
asm volatile ("pxor %xmm4,%xmm0");
|
||||
|
|
@ -513,12 +513,12 @@ static __always_inline void raid_gen4_ssse3_gen(int nd, size_t size, void **vv,
|
|||
|
||||
void raid_gen4_ssse3_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_ssse3_gen(nd, size, vv, 2);
|
||||
raid_gen4_ssse3_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen4_ssse3_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_ssse3_gen(nd, size, vv, 3);
|
||||
raid_gen4_ssse3_gen(nd, size, vv, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
|
@ -527,7 +527,7 @@ void raid_gen4_ssse3_aes(int nd, size_t size, void **vv)
|
|||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **vv, int generator)
|
||||
static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **vv, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -602,7 +602,7 @@ static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
|
||||
asm volatile ("movdqa %0,%%xmm12" : : "m" (v[d][i + 16]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -616,7 +616,7 @@ static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm7,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -668,7 +668,7 @@ static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
|
||||
asm volatile ("movdqa %0,%%xmm12" : : "m" (v[0][i + 16]));
|
||||
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("movdqa %xmm1,%xmm6");
|
||||
asm volatile ("movdqa %xmm9,%xmm14");
|
||||
}
|
||||
|
|
@ -682,7 +682,7 @@ static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **v
|
|||
asm volatile ("pand %xmm7,%xmm13");
|
||||
asm volatile ("pxor %xmm5,%xmm1");
|
||||
asm volatile ("pxor %xmm13,%xmm9");
|
||||
if (generator == 3) {
|
||||
if (g23 && raid_g23_x3(d)) {
|
||||
asm volatile ("pxor %xmm6,%xmm1");
|
||||
asm volatile ("pxor %xmm14,%xmm9");
|
||||
}
|
||||
|
|
@ -711,12 +711,12 @@ static __always_inline void raid_gen4_ssse3ext_gen(int nd, size_t size, void **v
|
|||
|
||||
void raid_gen4_ssse3ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_ssse3ext_gen(nd, size, vv, 2);
|
||||
raid_gen4_ssse3ext_gen(nd, size, vv, 0);
|
||||
}
|
||||
|
||||
void raid_gen4_ssse3ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_gen4_ssse3ext_gen(nd, size, vv, 3);
|
||||
raid_gen4_ssse3ext_gen(nd, size, vv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -859,7 +859,7 @@ void raid_gen5_ssse3_raid(int nd, size_t size, void **vv)
|
|||
/*
|
||||
* GENX SSSE3ext implementation
|
||||
*/
|
||||
static __always_inline void raid_genX_ssse3ext(int nd, size_t size, void **vv, int np, int generator)
|
||||
static __always_inline void raid_genX_ssse3ext(int nd, size_t size, void **vv, int np, int g23)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -941,14 +941,14 @@ static __always_inline void raid_genX_ssse3ext(int nd, size_t size, void **vv, i
|
|||
for (d = l - 1; d > 0; --d) {
|
||||
asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm12");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm11");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm14,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm12,%xmm1");
|
||||
|
||||
asm volatile ("pxor %xmm10,%xmm0");
|
||||
|
|
@ -999,14 +999,14 @@ static __always_inline void raid_genX_ssse3ext(int nd, size_t size, void **vv, i
|
|||
/* first disk with all coefficients at 1 */
|
||||
asm volatile ("movdqa %0,%%xmm10" : : "m" (v[0][i]));
|
||||
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("movdqa %xmm1,%xmm12");
|
||||
asm volatile ("pxor %xmm11,%xmm11");
|
||||
asm volatile ("pcmpgtb %xmm1,%xmm11");
|
||||
asm volatile ("paddb %xmm1,%xmm1");
|
||||
asm volatile ("pand %xmm14,%xmm11");
|
||||
asm volatile ("pxor %xmm11,%xmm1");
|
||||
if (generator == 3)
|
||||
if (g23 && raid_g23_x3(d))
|
||||
asm volatile ("pxor %xmm12,%xmm1");
|
||||
|
||||
asm volatile ("pxor %xmm10,%xmm0");
|
||||
|
|
@ -1042,12 +1042,12 @@ static __always_inline void raid_genX_ssse3ext(int nd, size_t size, void **vv, i
|
|||
*/
|
||||
void raid_gen5_ssse3ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_ssse3ext(nd, size, vv, 5, 2);
|
||||
raid_genX_ssse3ext(nd, size, vv, 5, 0);
|
||||
}
|
||||
|
||||
void raid_gen5_ssse3ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_ssse3ext(nd, size, vv, 5, 3);
|
||||
raid_genX_ssse3ext(nd, size, vv, 5, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1215,12 +1215,12 @@ void raid_gen6_ssse3_raid(int nd, size_t size, void **vv)
|
|||
*/
|
||||
void raid_gen6_ssse3ext_raid(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_ssse3ext(nd, size, vv, 6, 2);
|
||||
raid_genX_ssse3ext(nd, size, vv, 6, 0);
|
||||
}
|
||||
|
||||
void raid_gen6_ssse3ext_aes(int nd, size_t size, void **vv)
|
||||
{
|
||||
raid_genX_ssse3ext(nd, size, vv, 6, 3);
|
||||
raid_genX_ssse3ext(nd, size, vv, 6, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
10400
raid/tables.c
10400
raid/tables.c
File diff suppressed because it is too large
Load diff
195
raid/test.c
195
raid/test.c
|
|
@ -189,17 +189,19 @@ int raid_test_sort(void)
|
|||
*
|
||||
* RAID_MODE_CAUCHY_AES:
|
||||
* polynomial 0x11b
|
||||
* primitive generator g=3
|
||||
* G23 Extended Cauchy construction
|
||||
*
|
||||
* The parity generation tests compare optimized implementations against
|
||||
* raid_gen_ref(), but both use the same active generator matrix. Therefore
|
||||
* they can agree even if the matrix itself is mathematically unsuitable.
|
||||
*
|
||||
* This test instead checks a few fundamental properties of the field
|
||||
* generator and of the generated Cauchy matrix.
|
||||
* This test instead constructs the expected Q sequence independently and
|
||||
* checks the generated matrix coefficients.
|
||||
*/
|
||||
int raid_test_poly(unsigned mode)
|
||||
{
|
||||
uint8_t q[255];
|
||||
uint8_t v;
|
||||
int i, j;
|
||||
int p, d;
|
||||
|
||||
|
|
@ -216,7 +218,6 @@ int raid_test_poly(unsigned mode)
|
|||
/*
|
||||
* Select the mode first so that:
|
||||
*
|
||||
* raid_gfexp
|
||||
* raid_gfcauchy
|
||||
* raid_gfmul
|
||||
* raid_gfinv
|
||||
|
|
@ -229,89 +230,80 @@ int raid_test_poly(unsigned mode)
|
|||
raid_mode(mode);
|
||||
|
||||
/*
|
||||
* Primitive order alone is not enough to protect parity format
|
||||
* compatibility. Each Cauchy mode has a fixed reducing polynomial
|
||||
* and primitive generator, which determine the actual matrix coefficients.
|
||||
* Each Cauchy mode has a fixed reducing polynomial and matrix
|
||||
* construction, which together determine the parity format.
|
||||
*/
|
||||
if (mode == RAID_MODE_CAUCHY_RAID) {
|
||||
if (raid_poly_byte != RAID_POLY_RAID)
|
||||
return -1;
|
||||
if (raid_gfexp[1] != 2)
|
||||
return -1;
|
||||
} else if (mode == RAID_MODE_CAUCHY_AES) {
|
||||
} else {
|
||||
if (raid_poly_byte != RAID_POLY_AES)
|
||||
return -1;
|
||||
if (raid_gfexp[1] != 3)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* raid_gfexp[a] contains g^a for the primitive generator associated
|
||||
* with the active Cauchy mode.
|
||||
*
|
||||
* The multiplicative group GF(2^8)* contains 255 elements:
|
||||
*
|
||||
* 255 = 3 * 5 * 17
|
||||
*
|
||||
* The order of every nonzero field element divides 255.
|
||||
*
|
||||
* To prove that g has order exactly 255, it is therefore sufficient
|
||||
* to verify:
|
||||
*
|
||||
* g^255 == 1
|
||||
*
|
||||
* and to exclude the three maximal proper divisors:
|
||||
*
|
||||
* 255 / 3 = 85
|
||||
* 255 / 5 = 51
|
||||
* 255 / 17 = 15
|
||||
*
|
||||
* Hence a primitive generator must satisfy:
|
||||
*
|
||||
* g^85 != 1
|
||||
* g^51 != 1
|
||||
* g^15 != 1
|
||||
*/
|
||||
if (raid_gfexp[0] != 1)
|
||||
return -1;
|
||||
if (raid_gfexp[255] != 1)
|
||||
return -1;
|
||||
if (raid_gfexp[85] == 1)
|
||||
return -1;
|
||||
if (raid_gfexp[51] == 1)
|
||||
return -1;
|
||||
if (raid_gfexp[15] == 1)
|
||||
return -1;
|
||||
q[0] = 1;
|
||||
for (i = 0; i < 254; ++i) {
|
||||
uint8_t f = 2;
|
||||
|
||||
/*
|
||||
* The Q row of the Extended Cauchy matrix contains:
|
||||
*
|
||||
* 1, g, g^2, g^3, ...
|
||||
*
|
||||
* SnapRAID supports RAID_DATA_MAX data disks, so all generator powers
|
||||
* corresponding to those columns must be distinct.
|
||||
*
|
||||
* A primitive generator of order 255 guarantees this, but checking it
|
||||
* explicitly is inexpensive and also verifies the generated
|
||||
* raid_gfexp[] table itself.
|
||||
*/
|
||||
for (i = 0; i < RAID_DATA_MAX; ++i)
|
||||
for (j = i + 1; j < RAID_DATA_MAX; ++j)
|
||||
if (raid_gfexp[i] == raid_gfexp[j])
|
||||
return -1;
|
||||
if (mode == RAID_MODE_CAUCHY_AES && raid_g23_x3(i))
|
||||
f = 3;
|
||||
q[i + 1] = mul(f, q[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The second row of the Extended Cauchy matrix is exactly g^d.
|
||||
*
|
||||
* Verify that the exponent table and the actual matrix used for
|
||||
* parity generation agree for every supported data column.
|
||||
*
|
||||
* This makes sure that the primitive generator checked above is the
|
||||
* same generator actually used by the Q row.
|
||||
*/
|
||||
for (d = 0; d < RAID_DATA_MAX; ++d)
|
||||
if (raid_gfcauchy[1][d] != raid_gfexp[d])
|
||||
/* Both constructions enumerate distinct nonzero Q coefficients. */
|
||||
for (i = 0; i < 255; ++i) {
|
||||
if (q[i] == 0)
|
||||
return -1;
|
||||
for (j = i + 1; j < 255; ++j)
|
||||
if (q[i] == q[j])
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (d = 0; d < RAID_DATA_MAX; ++d)
|
||||
if (raid_gfcauchy[1][d] != q[d])
|
||||
return -1;
|
||||
|
||||
if (mode == RAID_MODE_CAUCHY_AES) {
|
||||
/* In AES, 2 has order 51 and 3 has order 255. */
|
||||
v = 1;
|
||||
for (i = 1; i <= 51; ++i) {
|
||||
v = mul(2, v);
|
||||
if ((i == 3 || i == 17) && v == 1)
|
||||
return -1;
|
||||
}
|
||||
if (v != 1)
|
||||
return -1;
|
||||
|
||||
v = 1;
|
||||
for (i = 1; i <= 255; ++i) {
|
||||
v = mul(3, v);
|
||||
if ((i == 15 || i == 51 || i == 85) && v == 1)
|
||||
return -1;
|
||||
}
|
||||
if (v != 1)
|
||||
return -1;
|
||||
|
||||
if (q[251] != 0xb8 || q[252] != 0x6b
|
||||
|| q[253] != 0xd6 || q[254] != 0xb7)
|
||||
return -1;
|
||||
if (inv(q[251]) != 0xa5 || inv(q[252]) != 0xdf
|
||||
|| inv(q[253]) != 0xe2 || inv(q[254]) != 0x71)
|
||||
return -1;
|
||||
|
||||
/* Independently reconstruct and normalize the four Cauchy rows. */
|
||||
for (p = 2; p < RAID_PARITY_MAX; ++p) {
|
||||
uint8_t y = inv(q[RAID_DATA_MAX + p - 2]);
|
||||
uint8_t f = inv(inv(q[0]) ^ y);
|
||||
uint8_t scale = inv(f);
|
||||
|
||||
for (d = 0; d < RAID_DATA_MAX; ++d) {
|
||||
uint8_t c = inv(inv(q[d]) ^ y);
|
||||
|
||||
if (raid_gfcauchy[p][d] != mul(c, scale))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Every coefficient of the active 6x251 Cauchy generator matrix must
|
||||
|
|
@ -550,6 +542,57 @@ bail:
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
int raid_test_rec2_g23(size_t size)
|
||||
{
|
||||
static const int missing[][2] = {
|
||||
{ 1, 20 },
|
||||
{ 50, 51 },
|
||||
{ 10, 204 }
|
||||
};
|
||||
void *v_alloc;
|
||||
void **v;
|
||||
void *save[2];
|
||||
int ip[2] = { 0, 1 };
|
||||
int nv = RAID_DATA_MAX + RAID_PARITY_MAX + 3;
|
||||
int i, j;
|
||||
|
||||
raid_mode(RAID_MODE_CAUCHY_AES);
|
||||
v = raid_malloc_vector(nv, size, &v_alloc);
|
||||
if (!v)
|
||||
return -1;
|
||||
|
||||
memset(v[nv - 1], 0, size);
|
||||
raid_zero(v[nv - 1]);
|
||||
raid_mrand_vector(3, RAID_DATA_MAX, size, v);
|
||||
raid_gen_ref(RAID_DATA_MAX, RAID_PARITY_MAX, size, v);
|
||||
|
||||
for (j = 0; j < (int)(sizeof(missing) / sizeof(missing[0])); ++j) {
|
||||
int id[2] = { missing[j][0], missing[j][1] };
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
save[i] = v[id[i]];
|
||||
v[id[i]] = v[RAID_DATA_MAX + RAID_PARITY_MAX + i];
|
||||
}
|
||||
|
||||
raid_rec2_int8(2, id, ip, RAID_DATA_MAX, size, v);
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (memcmp(v[id[i]], save[i], size) != 0)
|
||||
goto bail;
|
||||
v[id[i]] = save[i];
|
||||
}
|
||||
}
|
||||
|
||||
free(v_alloc);
|
||||
free(v);
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
free(v_alloc);
|
||||
free(v);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ int raid_test_gfaffine(void);
|
|||
/**
|
||||
* Tests the Galois field and Cauchy matrix properties.
|
||||
*
|
||||
* Verifies the expected polynomial and primitive generator and basic
|
||||
* Verifies the expected polynomial and matrix construction and basic
|
||||
* properties of the Extended Cauchy matrix for the specified RAID mode.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
|
|
@ -60,6 +60,13 @@ int raid_test_poly(unsigned mode);
|
|||
*/
|
||||
int raid_test_rec(unsigned mode, int nd, size_t size);
|
||||
|
||||
/**
|
||||
* Tests P/Q double-disk recovery at selected G23 positions.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int raid_test_rec2_g23(size_t size);
|
||||
|
||||
/**
|
||||
* Tests recovering functions on the tail data disks.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -151,6 +151,13 @@ int main(void)
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
printf("Test Cauchy AES P/Q recovery within and across G23 cosets...\n");
|
||||
if (raid_test_rec2_g23(TEST_SIZE) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
goto bail;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* nonsingular (invertible) for both operating modes:
|
||||
*
|
||||
* RAID: GF polynomial 0x11d, primitive generator g=2
|
||||
* AES: GF polynomial 0x11b, primitive generator g=3
|
||||
* AES: GF polynomial 0x11b, G23 Extended Cauchy construction
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* nonsingular (invertible) for both operating modes:
|
||||
*
|
||||
* RAID: GF polynomial 0x11d, primitive generator g=2
|
||||
* AES: GF polynomial 0x11b, primitive generator g=3
|
||||
* AES: GF polynomial 0x11b, G23 Extended Cauchy construction
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue