| 1 | |
| 2 | |
| 3 | * Copyright 2002 H. Peter Anvin - All Rights Reserved
|
| 4 | *
|
| 5 | * RAID-6 data recovery in dual failure mode. In single failure mode, use the
|
| 6 | * RAID-5 algorithm (or, in the case of Q failure, just reconstruct the
|
| 7 | * syndrome.)
|
| 8 |
|
| 9 |
|
| 10 | #include <linux/mm.h>
|
| 11 | #include <linux/raid/pq.h>
|
| 12 | #include "algos.h"
|
| 13 |
|
| 14 |
|
| 15 | static void raid6_2data_recov_intx1(int disks, size_t bytes, int faila,
|
| 16 | int failb, void **ptrs)
|
| 17 | {
|
| 18 | u8 *p, *q, *dp, *dq;
|
| 19 | u8 px, qx, db;
|
| 20 | const u8 *pbmul;
|
| 21 | const u8 *qmul;
|
| 22 |
|
| 23 | p = (u8 *)ptrs[disks-2];
|
| 24 | q = (u8 *)ptrs[disks-1];
|
| 25 |
|
| 26 | |
| 27 | Use the dead data pages as temporary storage for
|
| 28 | delta p and delta q
|
| 29 | dp = (u8 *)ptrs[faila];
|
| 30 | ptrs[faila] = page_address(ZERO_PAGE(0));
|
| 31 | ptrs[disks-2] = dp;
|
| 32 | dq = (u8 *)ptrs[failb];
|
| 33 | ptrs[failb] = page_address(ZERO_PAGE(0));
|
| 34 | ptrs[disks-1] = dq;
|
| 35 |
|
| 36 | raid6_gen_syndrome(disks, bytes, ptrs);
|
| 37 |
|
| 38 |
|
| 39 | ptrs[faila] = dp;
|
| 40 | ptrs[failb] = dq;
|
| 41 | ptrs[disks-2] = p;
|
| 42 | ptrs[disks-1] = q;
|
| 43 |
|
| 44 |
|
| 45 | pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
|
| 46 | qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
|
| 47 |
|
| 48 |
|
| 49 | while ( bytes-- ) {
|
| 50 | px = *p ^ *dp;
|
| 51 | qx = qmul[*q ^ *dq];
|
| 52 | *dq++ = db = pbmul[px] ^ qx;
|
| 53 | *dp++ = db ^ px;
|
| 54 | p++; q++;
|
| 55 | }
|
| 56 | }
|
| 57 |
|
| 58 |
|
| 59 | static void raid6_datap_recov_intx1(int disks, size_t bytes, int faila,
|
| 60 | void **ptrs)
|
| 61 | {
|
| 62 | u8 *p, *q, *dq;
|
| 63 | const u8 *qmul;
|
| 64 |
|
| 65 | p = (u8 *)ptrs[disks-2];
|
| 66 | q = (u8 *)ptrs[disks-1];
|
| 67 |
|
| 68 | |
| 69 | Use the dead data page as temporary storage for delta q
|
| 70 | dq = (u8 *)ptrs[faila];
|
| 71 | ptrs[faila] = page_address(ZERO_PAGE(0));
|
| 72 | ptrs[disks-1] = dq;
|
| 73 |
|
| 74 | raid6_gen_syndrome(disks, bytes, ptrs);
|
| 75 |
|
| 76 |
|
| 77 | ptrs[faila] = dq;
|
| 78 | ptrs[disks-1] = q;
|
| 79 |
|
| 80 |
|
| 81 | qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
|
| 82 |
|
| 83 |
|
| 84 | while ( bytes-- ) {
|
| 85 | *p++ ^= *dq = qmul[*q ^ *dq];
|
| 86 | q++; dq++;
|
| 87 | }
|
| 88 | }
|
| 89 |
|
| 90 |
|
| 91 | const struct raid6_recov_calls raid6_recov_intx1 = {
|
| 92 | .data2 = raid6_2data_recov_intx1,
|
| 93 | .datap = raid6_datap_recov_intx1,
|
| 94 | .name = "intx1",
|
| 95 | };
|