162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * ----------------------------------------------------------------------- */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * raid6test.c 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Test RAID-6 recovery with various algorithms 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <stdlib.h> 1562306a36Sopenharmony_ci#include <stdio.h> 1662306a36Sopenharmony_ci#include <string.h> 1762306a36Sopenharmony_ci#include <linux/raid/pq.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define NDISKS 16 /* Including P and Q */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciconst char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cichar *dataptrs[NDISKS]; 2462306a36Sopenharmony_cichar data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 2562306a36Sopenharmony_cichar recovi[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 2662306a36Sopenharmony_cichar recovj[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void makedata(int start, int stop) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci int i, j; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci for (i = start; i <= stop; i++) { 3362306a36Sopenharmony_ci for (j = 0; j < PAGE_SIZE; j++) 3462306a36Sopenharmony_ci data[i][j] = rand(); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci dataptrs[i] = data[i]; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic char disk_type(int d) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci switch (d) { 4362306a36Sopenharmony_ci case NDISKS-2: 4462306a36Sopenharmony_ci return 'P'; 4562306a36Sopenharmony_ci case NDISKS-1: 4662306a36Sopenharmony_ci return 'Q'; 4762306a36Sopenharmony_ci default: 4862306a36Sopenharmony_ci return 'D'; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic int test_disks(int i, int j) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci int erra, errb; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci memset(recovi, 0xf0, PAGE_SIZE); 5762306a36Sopenharmony_ci memset(recovj, 0xba, PAGE_SIZE); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dataptrs[i] = recovi; 6062306a36Sopenharmony_ci dataptrs[j] = recovj; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci erra = memcmp(data[i], recovi, PAGE_SIZE); 6562306a36Sopenharmony_ci errb = memcmp(data[j], recovj, PAGE_SIZE); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (i < NDISKS-2 && j == NDISKS-1) { 6862306a36Sopenharmony_ci /* We don't implement the DQ failure scenario, since it's 6962306a36Sopenharmony_ci equivalent to a RAID-5 failure (XOR, then recompute Q) */ 7062306a36Sopenharmony_ci erra = errb = 0; 7162306a36Sopenharmony_ci } else { 7262306a36Sopenharmony_ci printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", 7362306a36Sopenharmony_ci raid6_call.name, 7462306a36Sopenharmony_ci i, disk_type(i), 7562306a36Sopenharmony_ci j, disk_type(j), 7662306a36Sopenharmony_ci (!erra && !errb) ? "OK" : 7762306a36Sopenharmony_ci !erra ? "ERRB" : 7862306a36Sopenharmony_ci !errb ? "ERRA" : "ERRAB"); 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci dataptrs[i] = data[i]; 8262306a36Sopenharmony_ci dataptrs[j] = data[j]; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return erra || errb; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciint main(int argc, char *argv[]) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci const struct raid6_calls *const *algo; 9062306a36Sopenharmony_ci const struct raid6_recov_calls *const *ra; 9162306a36Sopenharmony_ci int i, j, p1, p2; 9262306a36Sopenharmony_ci int err = 0; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci makedata(0, NDISKS-1); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci for (ra = raid6_recov_algos; *ra; ra++) { 9762306a36Sopenharmony_ci if ((*ra)->valid && !(*ra)->valid()) 9862306a36Sopenharmony_ci continue; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci raid6_2data_recov = (*ra)->data2; 10162306a36Sopenharmony_ci raid6_datap_recov = (*ra)->datap; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci printf("using recovery %s\n", (*ra)->name); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci for (algo = raid6_algos; *algo; algo++) { 10662306a36Sopenharmony_ci if ((*algo)->valid && !(*algo)->valid()) 10762306a36Sopenharmony_ci continue; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci raid6_call = **algo; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* Nuke syndromes */ 11262306a36Sopenharmony_ci memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Generate assumed good syndrome */ 11562306a36Sopenharmony_ci raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, 11662306a36Sopenharmony_ci (void **)&dataptrs); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci for (i = 0; i < NDISKS-1; i++) 11962306a36Sopenharmony_ci for (j = i+1; j < NDISKS; j++) 12062306a36Sopenharmony_ci err += test_disks(i, j); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci if (!raid6_call.xor_syndrome) 12362306a36Sopenharmony_ci continue; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci for (p1 = 0; p1 < NDISKS-2; p1++) 12662306a36Sopenharmony_ci for (p2 = p1; p2 < NDISKS-2; p2++) { 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Simulate rmw run */ 12962306a36Sopenharmony_ci raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE, 13062306a36Sopenharmony_ci (void **)&dataptrs); 13162306a36Sopenharmony_ci makedata(p1, p2); 13262306a36Sopenharmony_ci raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE, 13362306a36Sopenharmony_ci (void **)&dataptrs); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci for (i = 0; i < NDISKS-1; i++) 13662306a36Sopenharmony_ci for (j = i+1; j < NDISKS; j++) 13762306a36Sopenharmony_ci err += test_disks(i, j); 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci printf("\n"); 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci printf("\n"); 14562306a36Sopenharmony_ci /* Pick the best algorithm test */ 14662306a36Sopenharmony_ci raid6_select_algo(); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (err) 14962306a36Sopenharmony_ci printf("\n*** ERRORS FOUND ***\n"); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return err; 15262306a36Sopenharmony_ci} 153