1 /* -*- linux-c -*- ------------------------------------------------------- * 2 * 3 * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved 4 * 5 * This file is part of the Linux kernel, and is made available under 6 * the terms of the GNU General Public License version 2 or (at your 7 * option) any later version; incorporated herein by reference. 8 * 9 * ----------------------------------------------------------------------- */ 10 11 /* 12 * raid6test.c 13 * 14 * Test RAID-6 recovery with various algorithms 15 */ 16 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <linux/raid/pq.h> 21 22 #define NDISKS 16 /* Including P and Q */ 23 24 const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); 25 struct raid6_calls raid6_call; 26 27 char *dataptrs[NDISKS]; 28 char data[NDISKS][PAGE_SIZE]; 29 char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; 30 31 static void makedata(void) 32 { 33 int i, j; 34 35 for (i = 0; i < NDISKS; i++) { 36 for (j = 0; j < PAGE_SIZE; j++) 37 data[i][j] = rand(); 38 39 dataptrs[i] = data[i]; 40 } 41 } 42 43 static char disk_type(int d) 44 { 45 switch (d) { 46 case NDISKS-2: 47 return 'P'; 48 case NDISKS-1: 49 return 'Q'; 50 default: 51 return 'D'; 52 } 53 } 54 55 static int test_disks(int i, int j) 56 { 57 int erra, errb; 58 59 memset(recovi, 0xf0, PAGE_SIZE); 60 memset(recovj, 0xba, PAGE_SIZE); 61 62 dataptrs[i] = recovi; 63 dataptrs[j] = recovj; 64 65 raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); 66 67 erra = memcmp(data[i], recovi, PAGE_SIZE); 68 errb = memcmp(data[j], recovj, PAGE_SIZE); 69 70 if (i < NDISKS-2 && j == NDISKS-1) { 71 /* We don't implement the DQ failure scenario, since it's 72 equivalent to a RAID-5 failure (XOR, then recompute Q) */ 73 erra = errb = 0; 74 } else { 75 printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", 76 raid6_call.name, 77 i, disk_type(i), 78 j, disk_type(j), 79 (!erra && !errb) ? "OK" : 80 !erra ? "ERRB" : 81 !errb ? "ERRA" : "ERRAB"); 82 } 83 84 dataptrs[i] = data[i]; 85 dataptrs[j] = data[j]; 86 87 return erra || errb; 88 } 89 90 int main(int argc, char *argv[]) 91 { 92 const struct raid6_calls *const *algo; 93 const struct raid6_recov_calls *const *ra; 94 int i, j; 95 int err = 0; 96 97 makedata(); 98 99 for (ra = raid6_recov_algos; *ra; ra++) { 100 if ((*ra)->valid && !(*ra)->valid()) 101 continue; 102 raid6_2data_recov = (*ra)->data2; 103 raid6_datap_recov = (*ra)->datap; 104 105 printf("using recovery %s\n", (*ra)->name); 106 107 for (algo = raid6_algos; *algo; algo++) { 108 if (!(*algo)->valid || (*algo)->valid()) { 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 } 123 printf("\n"); 124 } 125 126 printf("\n"); 127 /* Pick the best algorithm test */ 128 raid6_select_algo(); 129 130 if (err) 131 printf("\n*** ERRORS FOUND ***\n"); 132 133 return err; 134 } 135