153 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* -*- linux-c -*- ------------------------------------------------------- *3 *4 * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved5 *6 * ----------------------------------------------------------------------- */7 8/*9 * raid6test.c10 *11 * Test RAID-6 recovery with various algorithms12 */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 21const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));22 23char *dataptrs[NDISKS];24char data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));25char recovi[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));26char recovj[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));27 28static 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 40static 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 52static 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's69 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 87int 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