1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* -*- linux-c -*- ------------------------------------------------------- * 3 * 4 * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved 5 * 6 * ----------------------------------------------------------------------- */ 7 8 /* 9 * raid6test.c 10 * 11 * Test RAID-6 recovery with various algorithms 12 */ 13 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <linux/raid/pq.h> 18 19 #define NDISKS 16 /* Including P and Q */ 20 21 const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 22 23 char *dataptrs[NDISKS]; 24 char data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 25 char recovi[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 26 char recovj[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 27 28 static void makedata(int start, int stop) 29 { 30 int i, j; 31 32 for (i = start; i <= stop; i++) { 33 for (j = 0; j < PAGE_SIZE; j++) 34 data[i][j] = rand(); 35 36 dataptrs[i] = data[i]; 37 } 38 } 39 40 static char disk_type(int d) 41 { 42 switch (d) { 43 case NDISKS-2: 44 return 'P'; 45 case NDISKS-1: 46 return 'Q'; 47 default: 48 return 'D'; 49 } 50 } 51 52 static int test_disks(int i, int j) 53 { 54 int erra, errb; 55 56 memset(recovi, 0xf0, PAGE_SIZE); 57 memset(recovj, 0xba, PAGE_SIZE); 58 59 dataptrs[i] = recovi; 60 dataptrs[j] = recovj; 61 62 raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); 63 64 erra = memcmp(data[i], recovi, PAGE_SIZE); 65 errb = memcmp(data[j], recovj, PAGE_SIZE); 66 67 if (i < NDISKS-2 && j == NDISKS-1) { 68 /* We don't implement the DQ failure scenario, since it's 69 equivalent to a RAID-5 failure (XOR, then recompute Q) */ 70 erra = errb = 0; 71 } else { 72 printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", 73 raid6_call.name, 74 i, disk_type(i), 75 j, disk_type(j), 76 (!erra && !errb) ? "OK" : 77 !erra ? "ERRB" : 78 !errb ? "ERRA" : "ERRAB"); 79 } 80 81 dataptrs[i] = data[i]; 82 dataptrs[j] = data[j]; 83 84 return erra || errb; 85 } 86 87 int main(int argc, char *argv[]) 88 { 89 const struct raid6_calls *const *algo; 90 const struct raid6_recov_calls *const *ra; 91 int i, j, p1, p2; 92 int err = 0; 93 94 makedata(0, NDISKS-1); 95 96 for (ra = raid6_recov_algos; *ra; ra++) { 97 if ((*ra)->valid && !(*ra)->valid()) 98 continue; 99 100 raid6_2data_recov = (*ra)->data2; 101 raid6_datap_recov = (*ra)->datap; 102 103 printf("using recovery %s\n", (*ra)->name); 104 105 for (algo = raid6_algos; *algo; algo++) { 106 if ((*algo)->valid && !(*algo)->valid()) 107 continue; 108 109 raid6_call = **algo; 110 111 /* Nuke syndromes */ 112 memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); 113 114 /* Generate assumed good syndrome */ 115 raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, 116 (void **)&dataptrs); 117 118 for (i = 0; i < NDISKS-1; i++) 119 for (j = i+1; j < NDISKS; j++) 120 err += test_disks(i, j); 121 122 if (!raid6_call.xor_syndrome) 123 continue; 124 125 for (p1 = 0; p1 < NDISKS-2; p1++) 126 for (p2 = p1; p2 < NDISKS-2; p2++) { 127 128 /* Simulate rmw run */ 129 raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE, 130 (void **)&dataptrs); 131 makedata(p1, p2); 132 raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE, 133 (void **)&dataptrs); 134 135 for (i = 0; i < NDISKS-1; i++) 136 for (j = i+1; j < NDISKS; j++) 137 err += test_disks(i, j); 138 } 139 140 } 141 printf("\n"); 142 } 143 144 printf("\n"); 145 /* Pick the best algorithm test */ 146 raid6_select_algo(); 147 148 if (err) 149 printf("\n*** ERRORS FOUND ***\n"); 150 151 return err; 152 } 153