mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
193 lines
9.7 KiB
Text
193 lines
9.7 KiB
Text
RAID Library
|
|
============
|
|
|
|
This directory contains the Galois Field GF(2^8) erasure coding engine used by
|
|
SnapRAID. It provides multi-parity generation, missing data and parity block
|
|
recovery, error candidate validation, and brute-force block failure scanning.
|
|
|
|
The library supports up to 251 data blocks and up to 6 parity blocks using an
|
|
Extended Cauchy Matrix construction that guarantees MDS (Maximum Distance
|
|
Separable) properties for all supported combinations of disk failures.
|
|
|
|
|
|
Public API
|
|
----------
|
|
|
|
Header: #include "raid.h"
|
|
|
|
Before invoking any generation or recovery functions, call raid_init() once to
|
|
detect CPU capabilities and initialize mode dispatch. Then select the RAID mode
|
|
to use, if different from the default, and call raid_selftest(). raid_selftest()
|
|
verifies only the currently selected mode and is intended to be run at every
|
|
library startup before normal RAID operations.
|
|
|
|
void raid_init(void)
|
|
Initializes algorithm tables and detects hardware SIMD instruction sets
|
|
(SSE2, SSSE3, AVX2, AVX-512, GFNI, NEON). Sets default operating mode to
|
|
RAID_MODE_CAUCHY_RAID. Must be called before any other API function.
|
|
|
|
int raid_mode(int mode)
|
|
Sets or queries the active operating mode.
|
|
- Pass RAID_MODE_GET (-1) to query current active mode.
|
|
- Pass RAID_MODE_CAUCHY_RAID, RAID_MODE_VANDERMONDE_RAID, or
|
|
RAID_MODE_CAUCHY_AES to set mode.
|
|
Returns the mode active prior to this call.
|
|
|
|
void raid_gen(int nd, int np, size_t size, void **v, int streaming)
|
|
Computes 'np' parity blocks from 'nd' data blocks. Vector 'v' contains
|
|
'nd + np' block pointers (data blocks v[0..nd-1], parity blocks
|
|
v[nd..nd+np-1]). Each block must be aligned to a 64-byte boundary.
|
|
Data entries are used only for reading and may reference read-only memory.
|
|
Parity entries are outputs and must reference writable memory.
|
|
'streaming' must be either 0 or 1. If it is 1, non-temporal streaming stores
|
|
are used where supported to avoid polluting the CPU cache when parity is
|
|
written directly to disk. If it is 0, normal cached stores are used.
|
|
|
|
void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v)
|
|
Recovers 'nr' failed blocks (data or parity) listed in sorted index array
|
|
'ir'. Indexes start at 0 (data 0..nd-1, parity nd..nd+np-1). Each block
|
|
pointed to by 'v' must be aligned to a 64-byte boundary. Pointers in 'v'
|
|
for good blocks are read; pointers for bad blocks are target destinations.
|
|
Requires nr <= np. If nr is 0, 'ir' may be null; 'v' must be non-null but
|
|
no block pointers are accessed.
|
|
|
|
void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
|
|
Recovers 'nr' failed data blocks listed in sorted array 'id', using
|
|
parities listed in sorted array 'ip'. Each block pointed to by 'v' must
|
|
be aligned to a 64-byte boundary. Parity blocks in 'v' are unmodified.
|
|
Requires nr <= nd and nr <= RAID_PARITY_MAX. If nr is 0, 'id' and 'ip'
|
|
may be null; 'v' must be non-null but no block pointers are accessed.
|
|
|
|
int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v)
|
|
Validates whether candidate failed block set 'ir' matches available parity
|
|
redundancy. Each block pointed to by 'v' must be aligned to a 64-byte
|
|
boundary. Returns 0 if candidate set matches, or -1 if invalid. Requires
|
|
nr < np. If nr is 0, 'ir' may be null. Does not modify data or parity
|
|
blocks. Returns -1 if size is 0.
|
|
|
|
int raid_scan(int *ir, int nd, int np, size_t size, void **v)
|
|
Searches for up to 'np - 1' failed blocks using available redundancy.
|
|
Candidates are tested with an increasing number of failures, and the
|
|
first combination matching the redundancy is returned. If multiple
|
|
combinations match, the first one encountered is returned without
|
|
checking uniqueness. Each block pointed to by 'v' must be aligned to a
|
|
64-byte boundary. Fills 'ir' with the matching block indexes and returns
|
|
their number (0 if no error), or -1 if no compatible combination is found.
|
|
Returns -1 if size is 0.
|
|
|
|
int raid_selftest(void)
|
|
Runs startup verification tests for parity generation, recovery, and
|
|
scanning across parity levels supported by the currently selected mode.
|
|
It is intended to be called at every library startup after the RAID mode
|
|
has been selected, to verify the selected implementation on the current
|
|
CPU, compiler, and ABI. If the mode is changed later, the self test should
|
|
be run again before using the new mode. Returns 0 on success, < 0 on
|
|
failure.
|
|
|
|
|
|
Memory, Alignment and Aliasing Requirements
|
|
-------------------------------------------
|
|
|
|
- Vector Layout: In vector 'v', data blocks MUST precede parity blocks:
|
|
v[0 ... nd-1] -> Data blocks
|
|
v[nd ... nd+np-1] -> Parity blocks (PAR1, PAR2, ..., PAR6)
|
|
|
|
- Block Size: Parameter 'size' MUST be a multiple of 64 bytes
|
|
(size % 64 == 0). A zero size makes generation and recovery empty
|
|
operations; validation and scanning return -1 because no redundancy data
|
|
is available.
|
|
|
|
- Memory Alignment: All data and parity blocks pointed to by 'v[]'
|
|
MUST be aligned to a 64-byte boundary. This requirement applies to each
|
|
individual block buffer, not to the pointer array 'v' itself.
|
|
|
|
- Buffer Aliasing: In raid_gen(), entries in 'v[]' MAY point to the same
|
|
block buffer. Blocks are processed from lower to higher offsets. For each
|
|
processed byte or vector chunk, all required inputs are read before outputs
|
|
are written. Parity outputs are written in increasing parity order. When
|
|
multiple parity outputs point to the same block, later parity outputs
|
|
overwrite earlier ones.
|
|
|
|
In raid_rec() and raid_data(), each block being recovered MUST have a
|
|
distinct destination buffer that does not alias any other block in 'v[]'.
|
|
|
|
This guarantee applies to block aliasing (identical block pointers);
|
|
arbitrary partial overlap between distinct block ranges is not supported.
|
|
|
|
- Sorted Index Arrays: Index arrays ('ir', 'id', 'ip') MUST be strictly
|
|
sorted in ascending order (e.g. ir[0] < ir[1] < ... < ir[nr-1]).
|
|
|
|
|
|
Operating Modes and Polynomials
|
|
-------------------------------
|
|
|
|
RAID_MODE_CAUCHY_RAID (Default mode = 0)
|
|
Uses Cauchy matrix generator with standard RAID polynomial 0x1d
|
|
(x^8 + x^4 + x^3 + x^2 + 1, decimal 285, 0x11d) and primitive generator
|
|
g = 2. Supports parities 1 to 6. Matches standard Linux RAID-6 (Anvin
|
|
method) for 2-parity arrays and ensures on-disk compatibility. On CPUs
|
|
supporting Intel GFNI, generation and recovery are accelerated using
|
|
VGF2P8AFFINEQB with precomputed affine matrices for the RAID field.
|
|
|
|
RAID_MODE_VANDERMONDE_RAID (Mode = 1)
|
|
Legacy mode supporting up to 3 parities using standard polynomial 0x1d.
|
|
Uses Cauchy for PAR1/PAR2 and Vandermonde matrix coefficients for PAR3
|
|
(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 can use VGF2P8MULB directly for multiplication
|
|
in the AES field. This mode also provides a useful benchmark and
|
|
reference implementation for comparison with RAID_MODE_CAUCHY_RAID,
|
|
where fixed-coefficient multiplication in the 0x11d field is implemented
|
|
with VGF2P8AFFINEQB and precomputed affine matrices. Relative performance
|
|
depends on the CPU, backend, parity count, and workload. Parity data is
|
|
incompatible with standard 0x11d polynomial arrays.
|
|
|
|
Both Cauchy modes use the same Extended Cauchy construction with
|
|
coefficients based on powers of their respective primitive generators.
|
|
GFNI acceleration is available for both fields: the RAID field uses
|
|
VGF2P8AFFINEQB for fixed-coefficient multiplication, while the AES field
|
|
can use native VGF2P8MULB. Neither instruction should be assumed to be
|
|
faster in general; relative performance is hardware and workload
|
|
dependent.
|
|
|
|
|
|
Implementation Structure
|
|
------------------------
|
|
|
|
raid.h Public API declarations, macros, and mode constants.
|
|
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.
|
|
mktables.c Generator for GF(2^8), Cauchy, and GFNI affine tables.
|
|
internal.h Private header, assertion macros (BUG_ON), alignment helpers.
|
|
|
|
Platform-Specific Acceleration:
|
|
sse2.c x86 SSE2 (128-bit SIMD vectorization)
|
|
ssse3.c x86 SSSE3 (128-bit pshufb nibble-split multiplication)
|
|
avx2.c x86 AVX2 (256-bit vectorization)
|
|
avx512.c x86 AVX-512BW (512-bit vectorization)
|
|
gfni.c x86 GFNI generation/recovery (RAID affine and AES multiply)
|
|
neon.c AArch64 ARM NEON (128-bit SIMD vectorization)
|
|
neon32.c AArch32 ARM NEON (128-bit SIMD vectorization)
|
|
|
|
|
|
Testing and Benchmarks
|
|
----------------------
|
|
|
|
Standalone test applications located in raid/test/ provide verification and
|
|
performance evaluation:
|
|
|
|
raid/test/selftest Quick startup self-test exercising raid_selftest().
|
|
raid/test/fulltest Comprehensive test suite verifying parity generation and
|
|
tail recovery for 1..251 data disks, and all multi-disk
|
|
failure recovery combinations for up to TEST_COUNT disks
|
|
(default 24/32).
|
|
raid/test/invtest Matrix inversion test verifying non-singularity for all
|
|
square submatrices of the Cauchy matrix.
|
|
raid/test/speedtest Benchmark measuring single-thread throughput (MiB/s)
|
|
for parity generation and recovery across all SIMD
|
|
implementations.
|