/dev/raid
is a simple software RAID1 driver, hardcoded for a specific use
case where four devices are to be used in a voting setup.
General Description
The simple RAID1 driver is a software RAID1 solution for applications where four SPI NOR devices are to contain identical, mirrored data. SPI NOR devices are typically not able to self-report many types of errors. In order to detect errors, the requested data is read from every device and checksummed. If all checksums match, no error is assumed to have occured.
Error Handling
If the checksum of the data returned from the devices does not match, the driver will assume an error has occured. A voting system is employed to decide which data set to trust. The decision rules are as follows:
- When the driver initializes, the JEDEC ID of each device is requested. Each device is assigned an initial score based on this ID being retrievable or not.
- The devices are sorted based on their checksum. If an error was made during reading, such as an SPI bus error, the checksum is forced to zero so that they are grouped.
- The sorting will naturally group the devices, and each group is given a score based on their size. Devices that indicated a read error earlier on are not scored.
The scores calculated using the checksums and the scores calculated at
initialization is then combined, and data from the highest scoring device is
used by attempting to re-read it. A final checksum is calculated as a safety
measure, if this does not match what was previously read the driver will
return EIO
.
Error Reporting
Errors are reported by entries in /kfs/raid/
. There are multiple entries:
- jedec[0,1,2,3]: One for each device.
- rderr: Four unsigned bytes packed into an integer. Incremented on read errors.
- wrerr: Four unsigned bytes packed into an integer. Incremented on write errors.
- votes[0,1]: One for each pair of devices, containing two unsigned shorts packed into integers. Incremented whenever a device lost during voting.
union {
unsigned char read_errors[4];
int read_error;
};
union {
unsigned char write_errors[4];
int write_error;
};
union {
unsigned short voted_out[4];
int votes[2];
};