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