/****************************************************************************\
* *
* raidrec v0.6 - Manually try to put a RAID5 array back together. *
* *
* I wrote this program when, after a few disk failures, md refused to put *
* my damaged RAID array back together itself, or tried to resync it incor- *
* rectly, further damaging my partitions. *
* *
* Instead of figuring out how to do this, I decided to just write a small *
* program that does all the required XOR-ing. *
* *
* Note that I wrote this tool to scratch *my* specific itch, it's possible *
* that your RAID5 array was built differently. Mine had a stripe size of *
* 64K. If yours is different, try changing the #define down here. Also, my *
* array is left-symmetric so if yours isn't, this tool is going to expect *
* the checksum at the wrong place. I haven't made this configurable. But *
* since AFAIK left-symmetric is the default setup, you may be lucky. It *
* may also work with some hardware RAID disks, depending on the setup. *
* *
* Usage is very simple: Run the tool, pass it the partitions/images you're *
* trying to recover, and the reconstructed image will be written to std- *
* out. If one of the images is missing or corrupted, pass an empty string *
* instead. Its data will then be reconstructed. *
* *
* Example: *
* root@txt:/mnt/toscadisks# /root/raidrec sda2 '' sdc2 > md2 *
* *
* If you're impatient and want some kind of progress indicator, you can *
* pipe stuff through pv: http://www.ivarch.com/programs/pv.shtml *
* *
* Use this tool at your own risk. I can't guarantee that it will work, but *
* definitely did for me. Obviously, don't use it on your partitions direc- *
* tly, but on block-by-block copies of them. If you have any questions, *
* feel free to e-mail me, but I can't guarantee a quick response, sorry. *
* If the program actually helped you, I'd also love to hear about it! *
* *
* But please, no questions like "how do I compile this" or anything like *
* that. If you have to ask that, you'll be better off sending your disks *
* to a professional recovery company as soon as possible. Doing something *
* wrong here could only get you in more trouble. *
* *
* Good luck! *
* *
* Copyright 2009 Wilmer van der Gaast. <wilmer@gaast.net> *
* Licensed under the GPLv2. *
* *
\****************************************************************************/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOLS 5
#define STRIPESIZE 0x10000
char *getblocks( int ncols, char **istr, int xor_col );
int main( int argc, char *argv[] )
{
int ifd[MAXCOLS];
char **istr;
int i, n, ncols;
ncols = argc - 1;
if( ncols > MAXCOLS || ncols < 3 )
{
fprintf( stderr, "Invalid number of columns.\n" );
return 1;
}
n = 0;
istr = malloc( sizeof( char* ) * ncols );
for( i = 0; i < ncols; i ++ )
{
if( strcmp( argv[i+1], "" ) != 0 )
{
ifd[i] = open( argv[i+1], O_RDONLY );
if( ifd[i] == -1 )
{
perror( "open" );
return 1;
}
istr[i] = malloc( STRIPESIZE );
}
else
{
if( ( n ++ ) > 0 )
{
fprintf( stderr, "More than one missing image.\n" );
return 1;
}
ifd[i] = -1;
istr[i] = NULL;
}
}
while( 1 )
{
static int xor_col = 0;
xor_col = ( xor_col + ncols - 1 ) % ncols;
for( i = 0; i < ncols; i ++ )
{
if( istr[i] == NULL )
continue;
if( ( n = read( ifd[i], istr[i], STRIPESIZE ) ) != STRIPESIZE )
{
if( n == 0 )
{
return 0;
}
else
{
perror( "read" );
return 1;
}
}
}
write( 1, getblocks( ncols, istr, xor_col ), ( ncols - 1 ) * STRIPESIZE );
}
}
char *getblocks( int ncols, char **istr, int xor_col )
{
static char ret[(MAXCOLS-1)*STRIPESIZE], *s;
int cur_col;
int i;
cur_col = ( xor_col + 1 ) % ncols;
s = ret;
for( i = 0; i < ( ncols - 1 ); i ++ )
{
if( istr[cur_col] )
{
memcpy( s, istr[cur_col], STRIPESIZE );
}
else
{
int j;
memset( s, 0, STRIPESIZE );
for( j = 0; j < ( ncols - 1 ); j ++ )
{
long *ip, *op;
cur_col = ( cur_col + 1 ) % ncols;
ip = (long*) istr[cur_col];
op = (long*) s;
while( op < (long*) ( s + STRIPESIZE ) )
{
*op ^= *ip;
ip ++;
op ++;
}
}
cur_col = ( cur_col + 1 ) % ncols;
}
s += STRIPESIZE;
cur_col = ( cur_col + 1 ) % ncols;
}
return ret;
}
* *
* raidrec v0.6 - Manually try to put a RAID5 array back together. *
* *
* I wrote this program when, after a few disk failures, md refused to put *
* my damaged RAID array back together itself, or tried to resync it incor- *
* rectly, further damaging my partitions. *
* *
* Instead of figuring out how to do this, I decided to just write a small *
* program that does all the required XOR-ing. *
* *
* Note that I wrote this tool to scratch *my* specific itch, it's possible *
* that your RAID5 array was built differently. Mine had a stripe size of *
* 64K. If yours is different, try changing the #define down here. Also, my *
* array is left-symmetric so if yours isn't, this tool is going to expect *
* the checksum at the wrong place. I haven't made this configurable. But *
* since AFAIK left-symmetric is the default setup, you may be lucky. It *
* may also work with some hardware RAID disks, depending on the setup. *
* *
* Usage is very simple: Run the tool, pass it the partitions/images you're *
* trying to recover, and the reconstructed image will be written to std- *
* out. If one of the images is missing or corrupted, pass an empty string *
* instead. Its data will then be reconstructed. *
* *
* Example: *
* root@txt:/mnt/toscadisks# /root/raidrec sda2 '' sdc2 > md2 *
* *
* If you're impatient and want some kind of progress indicator, you can *
* pipe stuff through pv: http://www.ivarch.com/programs/pv.shtml *
* *
* Use this tool at your own risk. I can't guarantee that it will work, but *
* definitely did for me. Obviously, don't use it on your partitions direc- *
* tly, but on block-by-block copies of them. If you have any questions, *
* feel free to e-mail me, but I can't guarantee a quick response, sorry. *
* If the program actually helped you, I'd also love to hear about it! *
* *
* But please, no questions like "how do I compile this" or anything like *
* that. If you have to ask that, you'll be better off sending your disks *
* to a professional recovery company as soon as possible. Doing something *
* wrong here could only get you in more trouble. *
* *
* Good luck! *
* *
* Copyright 2009 Wilmer van der Gaast. <wilmer@gaast.net> *
* Licensed under the GPLv2. *
* *
\****************************************************************************/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOLS 5
#define STRIPESIZE 0x10000
char *getblocks( int ncols, char **istr, int xor_col );
int main( int argc, char *argv[] )
{
int ifd[MAXCOLS];
char **istr;
int i, n, ncols;
ncols = argc - 1;
if( ncols > MAXCOLS || ncols < 3 )
{
fprintf( stderr, "Invalid number of columns.\n" );
return 1;
}
n = 0;
istr = malloc( sizeof( char* ) * ncols );
for( i = 0; i < ncols; i ++ )
{
if( strcmp( argv[i+1], "" ) != 0 )
{
ifd[i] = open( argv[i+1], O_RDONLY );
if( ifd[i] == -1 )
{
perror( "open" );
return 1;
}
istr[i] = malloc( STRIPESIZE );
}
else
{
if( ( n ++ ) > 0 )
{
fprintf( stderr, "More than one missing image.\n" );
return 1;
}
ifd[i] = -1;
istr[i] = NULL;
}
}
while( 1 )
{
static int xor_col = 0;
xor_col = ( xor_col + ncols - 1 ) % ncols;
for( i = 0; i < ncols; i ++ )
{
if( istr[i] == NULL )
continue;
if( ( n = read( ifd[i], istr[i], STRIPESIZE ) ) != STRIPESIZE )
{
if( n == 0 )
{
return 0;
}
else
{
perror( "read" );
return 1;
}
}
}
write( 1, getblocks( ncols, istr, xor_col ), ( ncols - 1 ) * STRIPESIZE );
}
}
char *getblocks( int ncols, char **istr, int xor_col )
{
static char ret[(MAXCOLS-1)*STRIPESIZE], *s;
int cur_col;
int i;
cur_col = ( xor_col + 1 ) % ncols;
s = ret;
for( i = 0; i < ( ncols - 1 ); i ++ )
{
if( istr[cur_col] )
{
memcpy( s, istr[cur_col], STRIPESIZE );
}
else
{
int j;
memset( s, 0, STRIPESIZE );
for( j = 0; j < ( ncols - 1 ); j ++ )
{
long *ip, *op;
cur_col = ( cur_col + 1 ) % ncols;
ip = (long*) istr[cur_col];
op = (long*) s;
while( op < (long*) ( s + STRIPESIZE ) )
{
*op ^= *ip;
ip ++;
op ++;
}
}
cur_col = ( cur_col + 1 ) % ncols;
}
s += STRIPESIZE;
cur_col = ( cur_col + 1 ) % ncols;
}
return ret;
}