Quoting H. Peter Anvin who came up with the RAID6 P/Q algorithm, and who wrote the initial implementation, then still part of the md driver:
The RAID-6 code has *never* supported only 3 units, and if it ever worked for *any* of the implementations it was purely by accident. Speaking as the original author I should know; this was deliberate as in some cases the degenerate case (3) would have required extra trays in the code to no user benefit. While md never allowed less than 4 devices, btrfs does. This new warning will trigger for such file systems, but given how it already causes havoc that is a good thing. If btrfs wants to fix third, it should switch to transparently use three-way mirroring underneath, which will work as P and Q are copies of the single data device by the definition of the Linux RAID 6 P/Q algorithm. Signed-off-by: Christoph Hellwig <[email protected]> Acked-by: Ard Biesheuvel <[email protected]> Tested-by: Ard Biesheuvel <[email protected]> # kunit only on arm64 --- include/linux/raid/pq.h | 2 ++ lib/raid/raid6/algos.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h index 425a227591c0..87e3cb55bf07 100644 --- a/include/linux/raid/pq.h +++ b/include/linux/raid/pq.h @@ -11,6 +11,8 @@ #include <linux/blkdev.h> #include <linux/mm.h> +#define RAID6_MIN_DISKS 4 + void raid6_gen_syndrome(int disks, size_t bytes, void **ptrs); void raid6_xor_syndrome(int disks, int start, int stop, size_t bytes, void **ptrs); diff --git a/lib/raid/raid6/algos.c b/lib/raid/raid6/algos.c index b0ba31f6d48e..63d1945ba63c 100644 --- a/lib/raid/raid6/algos.c +++ b/lib/raid/raid6/algos.c @@ -42,6 +42,7 @@ void raid6_gen_syndrome(int disks, size_t bytes, void **ptrs) { WARN_ON_ONCE(!in_task() || irqs_disabled() || softirq_count()); WARN_ON_ONCE(bytes & 511); + WARN_ON_ONCE(disks < RAID6_MIN_DISKS); raid6_call.gen_syndrome(disks, bytes, ptrs); } @@ -77,6 +78,7 @@ void raid6_xor_syndrome(int disks, int start, int stop, size_t bytes, { WARN_ON_ONCE(!in_task() || irqs_disabled() || softirq_count()); WARN_ON_ONCE(bytes & 511); + WARN_ON_ONCE(disks < RAID6_MIN_DISKS); WARN_ON_ONCE(stop < start); raid6_call.xor_syndrome(disks, start, stop, bytes, ptrs); -- 2.53.0
