2005-04-16 15:20:36 -07:00
/* -*- linux-c -*- ------------------------------------------------------- *
*
2008-02-06 01:39:48 -08:00
* Copyright 2002 - 2007 H . Peter Anvin - All Rights Reserved
2005-04-16 15:20:36 -07:00
*
2008-02-06 01:39:48 -08:00
* 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 .
2005-04-16 15:20:36 -07:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* raid6test . c
*
* Test RAID - 6 recovery with various algorithms
*/
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
2009-03-31 15:09:39 +11:00
# include <linux/raid/pq.h>
2005-04-16 15:20:36 -07:00
# define NDISKS 16 /* Including P and Q */
2016-09-26 14:37:38 -07:00
const char raid6_empty_zero_page [ PAGE_SIZE ] __attribute__ ( ( aligned ( PAGE_SIZE ) ) ) ;
2005-04-16 15:20:36 -07:00
struct raid6_calls raid6_call ;
char * dataptrs [ NDISKS ] ;
2016-09-26 14:37:38 -07:00
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 ) ) ) ;
2005-04-16 15:20:36 -07:00
2014-12-15 12:57:04 +11:00
static void makedata ( int start , int stop )
2005-04-16 15:20:36 -07:00
{
int i , j ;
2014-12-15 12:57:04 +11:00
for ( i = start ; i < = stop ; i + + ) {
2008-02-06 01:39:48 -08:00
for ( j = 0 ; j < PAGE_SIZE ; j + + )
2005-04-16 15:20:36 -07:00
data [ i ] [ j ] = rand ( ) ;
2008-02-06 01:39:48 -08:00
2005-04-16 15:20:36 -07:00
dataptrs [ i ] = data [ i ] ;
}
}
2008-02-06 01:39:48 -08:00
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 ;
}
2005-04-16 15:20:36 -07:00
int main ( int argc , char * argv [ ] )
{
2008-02-06 01:39:48 -08:00
const struct raid6_calls * const * algo ;
2012-05-22 13:54:23 +10:00
const struct raid6_recov_calls * const * ra ;
2014-12-15 12:57:04 +11:00
int i , j , p1 , p2 ;
2008-02-06 01:39:48 -08:00
int err = 0 ;
2005-04-16 15:20:36 -07:00
2014-12-15 12:57:04 +11:00
makedata ( 0 , NDISKS - 1 ) ;
2005-04-16 15:20:36 -07:00
2012-05-22 13:54:23 +10:00
for ( ra = raid6_recov_algos ; * ra ; ra + + ) {
if ( ( * ra ) - > valid & & ! ( * ra ) - > valid ( ) )
continue ;
2014-12-15 12:57:04 +11:00
2012-05-22 13:54:23 +10:00
raid6_2data_recov = ( * ra ) - > data2 ;
raid6_datap_recov = ( * ra ) - > datap ;
2005-04-16 15:20:36 -07:00
2012-05-22 13:54:23 +10:00
printf ( " using recovery %s \n " , ( * ra ) - > name ) ;
2005-04-16 15:20:36 -07:00
2012-05-22 13:54:23 +10:00
for ( algo = raid6_algos ; * algo ; algo + + ) {
2014-12-15 12:57:04 +11:00
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 + + ) {
2008-02-06 01:39:48 -08:00
2014-12-15 12:57:04 +11:00
/* 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 ) ;
2012-05-22 13:54:23 +10:00
2014-12-15 12:57:04 +11:00
for ( i = 0 ; i < NDISKS - 1 ; i + + )
for ( j = i + 1 ; j < NDISKS ; j + + )
err + = test_disks ( i , j ) ;
}
2012-05-22 13:54:23 +10:00
2005-04-16 15:20:36 -07:00
}
printf ( " \n " ) ;
}
printf ( " \n " ) ;
/* Pick the best algorithm test */
raid6_select_algo ( ) ;
2008-02-06 01:39:48 -08:00
if ( err )
printf ( " \n *** ERRORS FOUND *** \n " ) ;
return err ;
2005-04-16 15:20:36 -07:00
}