diff options
Diffstat (limited to 'lib/raid6/test/test.c')
| -rw-r--r-- | lib/raid6/test/test.c | 124 | 
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/raid6/test/test.c b/lib/raid6/test/test.c new file mode 100644 index 00000000000..7a930318b17 --- /dev/null +++ b/lib/raid6/test/test.c @@ -0,0 +1,124 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + *   Copyright 2002-2007 H. Peter Anvin - All Rights Reserved + * + *   This file is part of the Linux kernel, and is made available under + *   the terms of the GNU General Public License version 2 or (at your + *   option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * 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(256))); +struct raid6_calls raid6_call; + +char *dataptrs[NDISKS]; +char data[NDISKS][PAGE_SIZE]; +char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; + +static void makedata(void) +{ +	int i, j; + +	for (i = 0; i < NDISKS; 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; +	int i, j; +	int err = 0; + +	makedata(); + +	for (algo = raid6_algos; *algo; algo++) { +		if (!(*algo)->valid || (*algo)->valid()) { +			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); +		} +		printf("\n"); +	} + +	printf("\n"); +	/* Pick the best algorithm test */ +	raid6_select_algo(); + +	if (err) +		printf("\n*** ERRORS FOUND ***\n"); + +	return err; +}  |