Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* -*- linux-c -*- ------------------------------------------------------- *
0003  *
0004  *   Copyright 2002-2007 H. Peter Anvin - All Rights Reserved
0005  *
0006  * ----------------------------------------------------------------------- */
0007 
0008 /*
0009  * raid6test.c
0010  *
0011  * Test RAID-6 recovery with various algorithms
0012  */
0013 
0014 #include <stdlib.h>
0015 #include <stdio.h>
0016 #include <string.h>
0017 #include <linux/raid/pq.h>
0018 
0019 #define NDISKS      16  /* Including P and Q */
0020 
0021 const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
0022 
0023 char *dataptrs[NDISKS];
0024 char data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
0025 char recovi[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
0026 char recovj[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
0027 
0028 static void makedata(int start, int stop)
0029 {
0030     int i, j;
0031 
0032     for (i = start; i <= stop; i++) {
0033         for (j = 0; j < PAGE_SIZE; j++)
0034             data[i][j] = rand();
0035 
0036         dataptrs[i] = data[i];
0037     }
0038 }
0039 
0040 static char disk_type(int d)
0041 {
0042     switch (d) {
0043     case NDISKS-2:
0044         return 'P';
0045     case NDISKS-1:
0046         return 'Q';
0047     default:
0048         return 'D';
0049     }
0050 }
0051 
0052 static int test_disks(int i, int j)
0053 {
0054     int erra, errb;
0055 
0056     memset(recovi, 0xf0, PAGE_SIZE);
0057     memset(recovj, 0xba, PAGE_SIZE);
0058 
0059     dataptrs[i] = recovi;
0060     dataptrs[j] = recovj;
0061 
0062     raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs);
0063 
0064     erra = memcmp(data[i], recovi, PAGE_SIZE);
0065     errb = memcmp(data[j], recovj, PAGE_SIZE);
0066 
0067     if (i < NDISKS-2 && j == NDISKS-1) {
0068         /* We don't implement the DQ failure scenario, since it's
0069            equivalent to a RAID-5 failure (XOR, then recompute Q) */
0070         erra = errb = 0;
0071     } else {
0072         printf("algo=%-8s  faila=%3d(%c)  failb=%3d(%c)  %s\n",
0073                raid6_call.name,
0074                i, disk_type(i),
0075                j, disk_type(j),
0076                (!erra && !errb) ? "OK" :
0077                !erra ? "ERRB" :
0078                !errb ? "ERRA" : "ERRAB");
0079     }
0080 
0081     dataptrs[i] = data[i];
0082     dataptrs[j] = data[j];
0083 
0084     return erra || errb;
0085 }
0086 
0087 int main(int argc, char *argv[])
0088 {
0089     const struct raid6_calls *const *algo;
0090     const struct raid6_recov_calls *const *ra;
0091     int i, j, p1, p2;
0092     int err = 0;
0093 
0094     makedata(0, NDISKS-1);
0095 
0096     for (ra = raid6_recov_algos; *ra; ra++) {
0097         if ((*ra)->valid  && !(*ra)->valid())
0098             continue;
0099 
0100         raid6_2data_recov = (*ra)->data2;
0101         raid6_datap_recov = (*ra)->datap;
0102 
0103         printf("using recovery %s\n", (*ra)->name);
0104 
0105         for (algo = raid6_algos; *algo; algo++) {
0106             if ((*algo)->valid && !(*algo)->valid())
0107                 continue;
0108 
0109             raid6_call = **algo;
0110 
0111             /* Nuke syndromes */
0112             memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
0113 
0114             /* Generate assumed good syndrome */
0115             raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
0116                         (void **)&dataptrs);
0117 
0118             for (i = 0; i < NDISKS-1; i++)
0119                 for (j = i+1; j < NDISKS; j++)
0120                     err += test_disks(i, j);
0121 
0122             if (!raid6_call.xor_syndrome)
0123                 continue;
0124 
0125             for (p1 = 0; p1 < NDISKS-2; p1++)
0126                 for (p2 = p1; p2 < NDISKS-2; p2++) {
0127 
0128                     /* Simulate rmw run */
0129                     raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
0130                                 (void **)&dataptrs);
0131                     makedata(p1, p2);
0132                     raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
0133                                                                 (void **)&dataptrs);
0134 
0135                     for (i = 0; i < NDISKS-1; i++)
0136                         for (j = i+1; j < NDISKS; j++)
0137                             err += test_disks(i, j);
0138                 }
0139 
0140         }
0141         printf("\n");
0142     }
0143 
0144     printf("\n");
0145     /* Pick the best algorithm test */
0146     raid6_select_algo();
0147 
0148     if (err)
0149         printf("\n*** ERRORS FOUND ***\n");
0150 
0151     return err;
0152 }