RAID Reconstructor does not directly support RAID-6 arrays, so it will not automatically retrieve a RAID-6 configuration. However, with some knowledge about your RAID-6, you can build a Virtual Image (VIM file) that allows you to rebuild the RAID-6 after the failure of up to two drives. Our entire lineup of data recovery software supports Virtual Images. Once you've made a VIM file, you can use it to mount, clone, image, or recover data from your reconstructed RAID-6. At this time, the following software versions support VIM files for RAID-6: DiskExplorer X V2.01, GetDataBack Pro V5.63, RAID Reconstructor V5.13, DriveMap V0.11 BETA, DriveDoppel V0.91 BETA.
Runtime's Virtual Images support two distinct RAID-6 schemes. The first one is a pure XOR-based scheme, where drives are XOR-ed in multiple ways to make the array resilient against the failure of up to two drives. We will look at a real-world example of a RAID-6 consisting of 4 drives on an Adaptec AIC-9405W controller.
The second scheme is a Reed-Solomon implementation using one drive for RAID-5 style XOR-parity and a second for the Reed-Solomon parity. We will look at an example of a 6-drive RAID-6 on a RocketRaid 4520SGL controller.
For both RAID-6 schemes, we will show you how to build the VIM file to reconstruct the array after the failure of 0, 1, or 2 drives.
This scheme uses XOR only and is, therefore, easy to analyze. The RAID controller chooses data and parity blocks so that they are all scattered across the drives, horizontally and vertically, ensuring you can recover from a 2-drive failure.
Multiple XOR-Based | ||||||||||||
Example: RAID-6, 4 drives, block size 128 on Adaptec AIC-9405W | ||||||||||||
Local drive sector*)\ |
Drive 1 | Drive 2 | Drive 3 | Drive 4 | Cycle | Stripe | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
0-127 | B1 **) | B2 | B3 | B4 | 0 | 0 | ||||||
128-255 | P1***) | P2 | P3 | P4 | 1 | |||||||
256-383 | B5 | B6 | B7 | B8 | 1 | 0 | ||||||
384-511 | P5 | P6 | P7 | P8 | 1 | |||||||
: | : | : | : | : | : | : | ||||||
|
Stripes alternate between pure data blocks and parity blocks:
B3 xor B4 => P1
B1 xor B4 => P2
B1 xor B2 => P3
B2 xor B3 => P4
These parities ensure that even the loss of any two drives can be mitigated. If, for example, drive 1 and drive 2 fail, you can rebuild B2
from B3 xor P4
, and then B1
from B2 xor P3
.
VIM for extracting the data using all drives:
<virtualimage>
<loop>
<drive>...ada_1.img: </drive>
<drive>...ada_2.img: </drive>
<drive>...ada_3.img: </drive>
<drive>...ada_4.img: </drive>
<cycle blocksize="128">
<stripe>1,2,3,4</stripe>
<stripe></stripe>
</cycle>
</loop>
</virtualimage>
If no drive is missing, we can simply get the data from the data blocks of each stripe.
The first stripe retrieves 128 sectors from each drive in the order drives 1, 2, 3, and 4. The next stripe is empty, containing only the parities we do not need. The empty stripe increases the sector counter by 128 to 256, so the first stripe in the next cycle iteration returns data from drives 1, 2, 3, and 4 again.
VIM for extracting the data after failure of one drive:
<virtualimage>
<loop>
<drive>...ada_1.img: </drive>
<drive>...ada_2.img: </drive>
<drive>...ada_3.img: </drive>
<drive>...ada_4.img: </drive>
<cycle blocksize="128">
<stripe>2x3(1),2,3,4</stripe>
<stripe></stripe>
</cycle>
</loop>
</virtualimage>
Assuming drive 1 is missing, we can recreate the drive by replacing the occurrence of drive 1 with B2 xor P3
.
As P3
is in the next stripe, we must peek ahead in our stripe expression. This is realized with 3(1)
, which indicates "drive 3 one stripe ahead". Our stripe expression 2x3(1),2,3,4
retrieves 128 sectors from drive 2, xors this with the content of drive 3 at 128 sectors ahead, and then collects the remaining drives 2, 3, and 4. The next stripe is empty again, as we already collected what we need with the peek-ahead. The empty stripe increases the sector counter by 128 to 256, so the first stripe in the next cycle iteration returns data from 2x3(1),2,3,4
again.
VIM for extracting the data after the failure of two drives:
<virtualimage>
<loop>
<drive>...ada_1.img: </drive>
<drive>...ada_2.img: </drive>
<drive>...ada_3.img: </drive>
<drive>...ada_4.img: </drive>
<cycle blocksize="128">
<stripe>3x4(1)x3(1),3x4(1),3,4
</stripe>
<stripe></stripe>
</cycle>
</loop>
</virtualimage>
Assuming drives 1 and 2 are missing, we can recreate the drives by replacing the occurrences of drive 2 with B3 xor P4
, and drive 1 with B2 xor P3
.
As P3
and P4
are in the next stripe, we must again peek ahead in our stripe expression. This is realized with 3(1)
and 4(1)
, which indicate "drive 3 one stripe ahead" and "drive 4 one stripe ahead", respectively. Our stripe expression 3x4(1)x3(1),3x4(1),3,4
retrieves drive 2 using 3x4(1)
, and drive 1 using the just retrieved drive 2 xor-ed with 3x4(1)
.
The next stripe is empty again, as we already collected what we need with the peek-ahead. The empty stripe increases the sector counter by 128 to 256, so the first stripe in the next cycle iteration returns data from 3x4(1)x3(1),3x4(1),3,4
again.
This scheme employs two distinct parity algorithms for data blocks, XOR and Reed-Solomon error correction, allowing for a 2-drive redundancy. RS is elegant, allowing both parity blocks, P and R, to rotate across the drives without storing the parity blocks in special stripes. On the other hand, RS is more complicated to calculate than XOR. RS is not commutative, while XOR is.
Reed-Solomon and XOR-Based | ||||||||||||
Example: RAID-6, 6 drives, block size 128 on a RocketRaid 4520SGL controller | ||||||||||||
Local drive sector*)\ |
Drive 1 | Drive 2 | Drive 3 | Drive 4 | Drive 5 | Drive 6 | Cycle | Stripe | ||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
0-127 | B1 **) | B2 | B3 | B4 | P | R | 0 | 0 | ||||
128-255 | B5 | B6 | B7 | P | R | B8 | 1 | |||||
256-383 | B9 | B10 | P | R | B11 | B12 | 2 | |||||
384-511 | B13 | P | R | B14 | B15 | B16 | 3 | |||||
512-639 | P | R | B17 | B18 | B19 | B20 | 4 | |||||
640-767 | R | B21 | B22 | B23 | B24 | P | 5 | |||||
768-895 | B25 | B26 | B27 | B28 | P | R | 1 | 0 | ||||
896-1023 | B29 | B30 | B31 | P | R | B32 | 1 | |||||
: | : | : | : | : | : | : | : | : | ||||
|
All relations between data and parity blocks are expressed within the same stripe. There is no peek-ahead as in the previous scheme. Here are the relationships:
Stripe 0: B1 xor B2 xor B3 xor B4 => P
B1 rs B2 rs B3 rs B4 => R
Stripe 1: B5 xor B6 xor B7 xor B8 => P
B5 rs B6 rs B7 rs B8 => R
Stripe 2: B9 xor B10 xor B11 xor B12 => P
B9 rs B10 rs B11 rs B12 => R
etc.
As you can see, single-drive failures can easily be resolved using P. If you need to recover from a two-drive loss, you will need R as well. We will later show how to incorporate both operations, XOR and RS, into a VIM file.
VIM for extracting the data using all drives:
<virtualimage>
<loop>
<drive>...high_1.img: </drive>
<drive>...high_2.img: </drive>
<drive>...high_3.img: </drive>
<drive>...high_4.img: </drive>
<drive>...high_5.img: </drive>
<drive>...high_6.img: </drive>
<cycle blocksize="128">
<stripe>1,2,3,4</stripe>
<stripe>1,2,3,6</stripe>
<stripe>1,2,5,6</stripe>
<stripe>1,4,5,6</stripe>
<stripe>3,4,5,6</stripe>
<stripe>2,3,4,5</stripe>
</cycle>
</loop>
</virtualimage>
If no drive is missing, we can simply get the data from the data blocks of each stripe. Refer to the Reed-Solomon rotation table to determine the data drives for each stripe: they are 1,2,3,4
for stripe 0, 1,2,3,6
for stripe 1, 1,2,5,6
for stripe 2, 1,4,5,6
for stripe 3, 3,4,5,6
for stripe 4, and 2,3,4,5
for stripe 5.
These 6 vectors are exactly, what you see in this VIM file.
VIM for extracting the data after failure of one drive using parity:
<virtualimage>
<loop>
<drive>...high_1.img: </drive>
<drive>...high_2.img: </drive>
<drive>...high_3.img: </drive>
<drive>...high_4.img: </drive>
<drive>...high_5.img: </drive>
<drive>...high_6.img: </drive>
<cycle blocksize="128">
<stripe>2x3x4x5,2,3,4</stripe>
<stripe>2x3x4x6,2,3,6</stripe>
<stripe>2x3x5x6,2,5,6</stripe>
<stripe>2x4x5x6,4,5,6</stripe>
<stripe>3,4,5,6</stripe>
<stripe>2,3,4,5</stripe>
</cycle>
</loop>
</virtualimage>
If one drive is missing, we can recreate it by simply applying the parity P. In practice, we xor P with the surviving data drives.
Assuming drive 1 is missing, let's write up the 6 vectors for our stripes. Look at the rotation table, stripe 0: from drive 1 to drive 6, the data and parity drives are ordered DDDDPR. We can replace the missing drive 1 with 2x3x4x5. Drives 2, 3, and 4 are the remaining data drives and P is the XOR-parity drive of this stripe.
Stripe 0:
D,D,D,D,P,R -> 1,2,3,4,5,6 --(replace 1 with 2x3x4x5)-> 2x3x4x5,2,3,4
Stripe 1:
D,D,D,P,R,D -> 1,2,3,4,5,6 --(replace 1 with 2x3x4x6)-> 2x3x4x6,2,3,6
Stripe 2:
D,D,P,R,D,D -> 1,2,3,4,5,6 --(replace 1 with 2x3x5x6)-> 2x3x5x6,2,5,6
Stripe 3:
D,P,R,D,D,D -> 1,2,3,4,5,6 --(replace 1 with 2x4x5x6)-> 2x4x5x6,4,5,6
Stripe 4:
P,R,D,D,D,D -> 1,2,3,4,5,6 --(no replacement)-> 3,4,5,6
Stripe 5:
R,D,D,D,D,P -> 1,2,3,4,5,6 --(no replacement)-> 2,3,4,5
The 6 vectors on the right-hand side are our stripe descriptions in the VIM file.
VIM for extracting the data after failure of one drive using Reed-Solomon:
<virtualimage>
<loop>
<drive>...high_1.img: </drive>
<drive>...high_2.img: </drive>
<drive>...high_3.img: </drive>
<drive>...high_4.img: </drive>
<drive>...high_5.img: </drive>
<drive>...high_6.img: </drive>
<cycle blocksize="128">
<stripe>?r2r3r4r5r6,2,3,4</stripe>
<stripe>?r2r3r6r4r5,2,3,6</stripe>
<stripe>?r2r5r6r3r4,2,5,6</stripe>
<stripe>?r4r5r6r2r3,4,5,6</stripe>
<stripe>3,4,5,6</stripe>
<stripe>2,3,4,5</stripe>
</cycle>
</loop>
</virtualimage>
We can also recover from a single-drive failure using the Reed-Solomon algorithm RS. We define RS as a function on all drives, available or not, in the correct order:
RS(D,D,D,D,P,R). For use in the VIM file, we write this as DrDrDrDrPrR. Look at the rotation table to replace the parameters with the correct drive number:
Stripe 0: RS(1,2,3,4,5,6) -> 1r2r3r4r5r6
Stripe 1: RS(1,2,3,6,4,5) -> 1r2r3r6r4r5
Stripe 2: RS(1,2,5,6,3,4) -> 1r2r5r6r3r4
Stripe 3: RS(1,4,5,6,2,3) -> 1r4r5r6r2r3
Stripe 4: RS(3,4,5,6,1,2) -> 3r4r5r6r1r2
Stripe 5: RS(2,3,4,5,6,1) -> 2r3r4r5r6r1
Assuming drive 1 is missing, we replace the leftmost drive descriptor with the RS descriptor for the first 4 stripes. The last 2 stripes, again, do not require us to reconstruct anything. Before inserting the RS descriptor, replace the missing drive with a ?. This indicates which output we need. For stripe 0, 1r2r3r4r5r6 becomes ?r2r3r4r5r6.
VIM for extracting the data after the failure of two drives:
<virtualimage>
<loop>
<drive>...high_1.img: </drive>
<drive>...high_2.img: </drive>
<drive>...high_3.img: </drive>
<drive>...high_4.img: </drive>
<drive>...high_5.img: </drive>
<drive>...high_6.img: </drive>
<cycle blocksize="128">
<stripe>!r?r3r4r5r6,?r!r3r4r5r6,3,4 </stripe>
<stripe>!r?r3r6r4r5,?r!r3r6r4r5,3,6 </stripe>
<stripe>!r?r5r6r3r4,?r!r5r6r3r4,5,6 </stripe>
<stripe>!r4r5r6r?r3,4,5,6 </stripe>
<stripe>3,4,5,6 </stripe>
<stripe>3x4x5x6,3,4,5 </stripe>
</cycle>
</loop>
</virtualimage>
In this paragraph, we will put it all together: XOR and RS to recover after a two-drive failure.
Assuming drives 1 and 2 are missing, we will need to replace drive descriptors 1 and 2 in stripe 0. According to the previous paragraph, the RS function for stripe 0 is 1r2r3r4r5r6. Use ? and ! for the missing drives, ! being the drive you want to calculate. For stripe 1 the RS function is 1r2r3r6r4r5 and the descriptors for drives 1 and 2 are
Stripe 0: 1r2r3r4r5r6 => 1,2,3,4 => !r?r3r4r5r6,?r!r3r4r5r6,3,4
Stripe 1: 1r2r3r6r4r5 => 1,2,3,6 => !r?r3r6r4r5,?r!r3r6r4r5,3,6
Stripe 2: 1r2r5r6r3r4 => 1,2,5,6 => !r?r5r6r3r4,?r!r5r6r3r4,5,6
Stripe 3: 1r4r5r6r2r3 => 1,4,5,6 => !r4r5r6r?r3,4,5,6
Stripe 4: 3r4r5r6r1r2 => 3,4,5,6 => 3,4,5,6
Stripe 5: 2r3r4r5r6r1 => 2,3,4,5 => 3x4x5x6,3,4,5 (or !r3r4r5r6r?,3,4,5)