recov.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* -*- linux-c -*- ------------------------------------------------------- *
  3. *
  4. * Copyright 2002 H. Peter Anvin - All Rights Reserved
  5. *
  6. * ----------------------------------------------------------------------- */
  7. /*
  8. * raid6/recov.c
  9. *
  10. * RAID-6 data recovery in dual failure mode. In single failure mode,
  11. * use the RAID-5 algorithm (or, in the case of Q failure, just reconstruct
  12. * the syndrome.)
  13. */
  14. #include <linux/raid/pq.h>
  15. /* Recover two failed data blocks. */
  16. static void raid6_2data_recov_intx1(int disks, size_t bytes, int faila,
  17. int failb, void **ptrs)
  18. {
  19. u8 *p, *q, *dp, *dq;
  20. u8 px, qx, db;
  21. const u8 *pbmul; /* P multiplier table for B data */
  22. const u8 *qmul; /* Q multiplier table (for both) */
  23. p = (u8 *)ptrs[disks-2];
  24. q = (u8 *)ptrs[disks-1];
  25. /* Compute syndrome with zero for the missing data pages
  26. Use the dead data pages as temporary storage for
  27. delta p and delta q */
  28. dp = (u8 *)ptrs[faila];
  29. ptrs[faila] = raid6_get_zero_page();
  30. ptrs[disks-2] = dp;
  31. dq = (u8 *)ptrs[failb];
  32. ptrs[failb] = raid6_get_zero_page();
  33. ptrs[disks-1] = dq;
  34. raid6_call.gen_syndrome(disks, bytes, ptrs);
  35. /* Restore pointer table */
  36. ptrs[faila] = dp;
  37. ptrs[failb] = dq;
  38. ptrs[disks-2] = p;
  39. ptrs[disks-1] = q;
  40. /* Now, pick the proper data tables */
  41. pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
  42. qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
  43. /* Now do it... */
  44. while ( bytes-- ) {
  45. px = *p ^ *dp;
  46. qx = qmul[*q ^ *dq];
  47. *dq++ = db = pbmul[px] ^ qx; /* Reconstructed B */
  48. *dp++ = db ^ px; /* Reconstructed A */
  49. p++; q++;
  50. }
  51. }
  52. /* Recover failure of one data block plus the P block */
  53. static void raid6_datap_recov_intx1(int disks, size_t bytes, int faila,
  54. void **ptrs)
  55. {
  56. u8 *p, *q, *dq;
  57. const u8 *qmul; /* Q multiplier table */
  58. p = (u8 *)ptrs[disks-2];
  59. q = (u8 *)ptrs[disks-1];
  60. /* Compute syndrome with zero for the missing data page
  61. Use the dead data page as temporary storage for delta q */
  62. dq = (u8 *)ptrs[faila];
  63. ptrs[faila] = raid6_get_zero_page();
  64. ptrs[disks-1] = dq;
  65. raid6_call.gen_syndrome(disks, bytes, ptrs);
  66. /* Restore pointer table */
  67. ptrs[faila] = dq;
  68. ptrs[disks-1] = q;
  69. /* Now, pick the proper data tables */
  70. qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
  71. /* Now do it... */
  72. while ( bytes-- ) {
  73. *p++ ^= *dq = qmul[*q ^ *dq];
  74. q++; dq++;
  75. }
  76. }
  77. const struct raid6_recov_calls raid6_recov_intx1 = {
  78. .data2 = raid6_2data_recov_intx1,
  79. .datap = raid6_datap_recov_intx1,
  80. .valid = NULL,
  81. .name = "intx1",
  82. .priority = 0,
  83. };
  84. #ifndef __KERNEL__
  85. /* Testing only */
  86. /* Recover two failed blocks. */
  87. void raid6_dual_recov(int disks, size_t bytes, int faila, int failb, void **ptrs)
  88. {
  89. if ( faila > failb ) {
  90. int tmp = faila;
  91. faila = failb;
  92. failb = tmp;
  93. }
  94. if ( failb == disks-1 ) {
  95. if ( faila == disks-2 ) {
  96. /* P+Q failure. Just rebuild the syndrome. */
  97. raid6_call.gen_syndrome(disks, bytes, ptrs);
  98. } else {
  99. /* data+Q failure. Reconstruct data from P,
  100. then rebuild syndrome. */
  101. /* NOT IMPLEMENTED - equivalent to RAID-5 */
  102. }
  103. } else {
  104. if ( failb == disks-2 ) {
  105. /* data+P failure. */
  106. raid6_datap_recov(disks, bytes, faila, ptrs);
  107. } else {
  108. /* data+data failure. */
  109. raid6_2data_recov(disks, bytes, faila, failb, ptrs);
  110. }
  111. }
  112. }
  113. #endif