152 lines · 3.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* -*- linux-c -*- ------------------------------------------------------- * * *   Copyright 2002-2007 H. Peter Anvin - All Rights Reserved * * ----------------------------------------------------------------------- */ /* * raid6test.c * * Test RAID-6 recovery with various algorithms */ #include <stdlib.h>#include <stdio.h>#include <string.h>#include <linux/raid/pq.h> #define NDISKS		16	/* Including P and Q */ const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); char *dataptrs[NDISKS];char data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));char recovi[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));char recovj[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); static void makedata(int start, int stop){	int i, j; 	for (i = start; i <= stop; i++) {		for (j = 0; j < PAGE_SIZE; j++)			data[i][j] = rand(); 		dataptrs[i] = data[i];	}} static char disk_type(int d){	switch (d) {	case NDISKS-2:		return 'P';	case NDISKS-1:		return 'Q';	default:		return 'D';	}} static int test_disks(int i, int j){	int erra, errb; 	memset(recovi, 0xf0, PAGE_SIZE);	memset(recovj, 0xba, PAGE_SIZE); 	dataptrs[i] = recovi;	dataptrs[j] = recovj; 	raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); 	erra = memcmp(data[i], recovi, PAGE_SIZE);	errb = memcmp(data[j], recovj, PAGE_SIZE); 	if (i < NDISKS-2 && j == NDISKS-1) {		/* We don't implement the DQ failure scenario, since it's		   equivalent to a RAID-5 failure (XOR, then recompute Q) */		erra = errb = 0;	} else {		printf("algo=%-8s  faila=%3d(%c)  failb=%3d(%c)  %s\n",		       raid6_call.name,		       i, disk_type(i),		       j, disk_type(j),		       (!erra && !errb) ? "OK" :		       !erra ? "ERRB" :		       !errb ? "ERRA" : "ERRAB");	} 	dataptrs[i] = data[i];	dataptrs[j] = data[j]; 	return erra || errb;} int main(int argc, char *argv[]){	const struct raid6_calls *const *algo;	const struct raid6_recov_calls *const *ra;	int i, j, p1, p2;	int err = 0; 	makedata(0, NDISKS-1); 	for (ra = raid6_recov_algos; *ra; ra++) {		if ((*ra)->valid  && !(*ra)->valid())			continue; 		raid6_2data_recov = (*ra)->data2;		raid6_datap_recov = (*ra)->datap; 		printf("using recovery %s\n", (*ra)->name); 		for (algo = raid6_algos; *algo; algo++) {			if ((*algo)->valid && !(*algo)->valid())				continue; 			raid6_call = **algo; 			/* Nuke syndromes */			memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); 			/* Generate assumed good syndrome */			raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,						(void **)&dataptrs); 			for (i = 0; i < NDISKS-1; i++)				for (j = i+1; j < NDISKS; j++)					err += test_disks(i, j); 			if (!raid6_call.xor_syndrome)				continue; 			for (p1 = 0; p1 < NDISKS-2; p1++)				for (p2 = p1; p2 < NDISKS-2; p2++) { 					/* Simulate rmw run */					raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,								(void **)&dataptrs);					makedata(p1, p2);					raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,                                                                (void **)&dataptrs); 					for (i = 0; i < NDISKS-1; i++)						for (j = i+1; j < NDISKS; j++)							err += test_disks(i, j);				} 		}		printf("\n");	} 	printf("\n");	/* Pick the best algorithm test */	raid6_select_algo(); 	if (err)		printf("\n*** ERRORS FOUND ***\n"); 	return err;}