LCOV - code coverage report
Current view: top level - raid - check.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 60 60 100.0 %
Date: 2026-04-29 15:04:44 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : // Copyright (C) 2015 Andrea Mazzoleni
       3             : 
       4             : #include "internal.h"
       5             : #include "combo.h"
       6             : #include "gf.h"
       7             : 
       8             : /**
       9             :  * Validate the provided failed blocks.
      10             :  *
      11             :  * This function checks if the specified failed blocks satisfy the redundancy
      12             :  * information using the data from the known valid parity blocks.
      13             :  *
      14             :  * It's similar to raid_check(), just with a different format for arguments.
      15             :  *
      16             :  * The number of failed blocks @nr must be strictly less than the number of
      17             :  * parities @nv, because you need one more parity to validate the recovering.
      18             :  *
      19             :  * No data or parity blocks are modified.
      20             :  *
      21             :  * @nr Number of failed data blocks.
      22             :  * @id[] Vector of @nr indexes of the failed data blocks.
      23             :  *   The indexes start from 0. They must be in order.
      24             :  * @nv Number of valid parity blocks.
      25             :  * @ip[] Vector of @nv indexes of the valid parity blocks.
      26             :  *   The indexes start from 0. They must be in order.
      27             :  * @nd Number of data blocks.
      28             :  * @size Size of the blocks pointed by @v. It must be a multiple of 64.
      29             :  * @v Vector of pointers to the blocks of data and parity.
      30             :  *   It has (@nd + @ip[@nv - 1] + 1) elements. The starting elements are the
      31             :  *   blocks for data, following with the parity blocks.
      32             :  *   Each block has @size bytes. 
      33             :  * @return 0 if the check is satisfied. -1 otherwise.
      34             :  */
      35       11255 : static int raid_validate(int nr, int *id, int nv, int *ip, int nd, size_t size, void **vv)
      36             : {
      37       11255 :         uint8_t **v = (uint8_t **)vv;
      38             :         const uint8_t *T[RAID_PARITY_MAX][RAID_PARITY_MAX];
      39             :         uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX];
      40             :         uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX];
      41             :         size_t i;
      42             :         int j, k, l;
      43             : 
      44       11255 :         BUG_ON(nr >= nv);
      45             : 
      46             :         /* setup the coefficients matrix */
      47       41316 :         for (j = 0; j < nr; ++j)
      48      119934 :                 for (k = 0; k < nr; ++k)
      49      179746 :                         G[j * nr + k] = A(ip[j], id[k]);
      50             : 
      51             :         /* invert it to solve the system of linear equations */
      52       11255 :         raid_invert(G, V, nr);
      53             : 
      54             :         /* get multiplication tables */
      55       41316 :         for (j = 0; j < nr; ++j)
      56      119934 :                 for (k = 0; k < nr; ++k)
      57      179746 :                         T[j][k] = table(V[j * nr + k]);
      58             : 
      59             :         /* check all positions */
      60       35831 :         for (i = 0; i < size; ++i) {
      61             :                 uint8_t p[RAID_PARITY_MAX];
      62             : 
      63             :                 /* get parity */
      64      151819 :                 for (j = 0; j < nv; ++j)
      65      115994 :                         p[j] = v[nd + ip[j]][i];
      66             : 
      67             :                 /* compute delta parity, skipping broken disks */
      68      609025 :                 for (j = 0, k = 0; j < nd; ++j) {
      69             :                         uint8_t b;
      70             : 
      71             :                         /* skip broken disks */
      72      573200 :                         if (k < nr && id[k] == j) {
      73       66916 :                                 ++k;
      74       66916 :                                 continue;
      75             :                         }
      76             : 
      77      506284 :                         b = v[j][i];
      78     2094442 :                         for (l = 0; l < nv; ++l)
      79     1588158 :                                 p[l] ^= gfmul[b][gfgen[ip[l]][j]];
      80             :                 }
      81             : 
      82             :                 /* reconstruct data */
      83      102741 :                 for (j = 0; j < nr; ++j) {
      84       66916 :                         uint8_t b = 0;
      85       66916 :                         int idj = id[j];
      86             : 
      87             :                         /* recompute the data */
      88      234594 :                         for (k = 0; k < nr; ++k)
      89      167678 :                                 b ^= T[j][k][p[k]];
      90             : 
      91             :                         /* add the parity contribution of the reconstructed data */
      92      166984 :                         for (l = nr; l < nv; ++l)
      93      100068 :                                 p[l] ^= gfmul[b][gfgen[ip[l]][idj]];
      94             :                 }
      95             : 
      96             :                 /* check that the final parity is 0 */
      97       60482 :                 for (l = nr; l < nv; ++l)
      98       35906 :                         if (p[l] != 0)
      99       11249 :                                 return -1;
     100             :         }
     101             : 
     102           6 :         return 0;
     103             : }
     104             : 
     105       11255 : int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v)
     106             : {
     107             :         /* valid parity index */
     108             :         int ip[RAID_PARITY_MAX];
     109             :         int vp;
     110             :         int rd;
     111             :         int i, j;
     112             : 
     113             :         /* enforce limit on size */
     114       11255 :         BUG_ON(size % 64 != 0);
     115             : 
     116             :         /* enforce limit on number of failures */
     117       11255 :         BUG_ON(nr >= np); /* >= because we check with extra parity */
     118       11255 :         BUG_ON(np > RAID_PARITY_MAX);
     119             : 
     120             :         /* enforce order in index vector */
     121       11255 :         BUG_ON(nr >= 2 && ir[0] >= ir[1]);
     122       11255 :         BUG_ON(nr >= 3 && ir[1] >= ir[2]);
     123       11255 :         BUG_ON(nr >= 4 && ir[2] >= ir[3]);
     124       11255 :         BUG_ON(nr >= 5 && ir[3] >= ir[4]);
     125       11255 :         BUG_ON(nr >= 6 && ir[4] >= ir[5]);
     126             : 
     127             :         /* enforce limit on index vector */
     128       11255 :         BUG_ON(nr > 0 && ir[nr-1] >= nd + np);
     129             : 
     130             :         /* count failed data disk */
     131       11255 :         rd = 0;
     132       41316 :         while (rd < nr && ir[rd] < nd)
     133       30061 :                 ++rd;
     134             : 
     135             :         /* put valid parities into ip[] */
     136       11255 :         vp = 0;
     137       76488 :         for (i = rd, j = 0; j < np; ++j) {
     138             :                 /* if parity is failed */
     139       65233 :                 if (i < nr && ir[i] == nd + j) {
     140             :                         /* skip broken parity */
     141       10664 :                         ++i;
     142             :                 } else {
     143             :                         /* store valid parity */
     144       54569 :                         ip[vp] = j;
     145       54569 :                         ++vp;
     146             :                 }
     147             :         }
     148             : 
     149       11255 :         return raid_validate(rd, ir, vp, ip, nd, size, v);
     150             : }
     151             : 
     152           7 : int raid_scan(int *ir, int nd, int np, size_t size, void **v)
     153             : {
     154             :         int r;
     155             : 
     156             :         /* check the special case of no failure */
     157           7 :         if (np != 0 && raid_check(0, 0, nd, np, size, v) == 0)
     158           1 :                 return 0;
     159             : 
     160             :         /* for each number of possible failures */
     161          16 :         for (r = 1; r < np; ++r) {
     162             :                 /* try all combinations of r failures on n disks */
     163          15 :                 combination_first(r, nd + np, ir);
     164             :                 do {
     165             :                         /* verify if the combination is a valid one */
     166       11249 :                         if (raid_check(r, ir, nd, np, size, v) == 0)
     167           5 :                                 return r;
     168       22488 :                 } while (combination_next(r, nd + np, ir));
     169             :         }
     170             : 
     171             :         /* no solution found */
     172           1 :         return -1;
     173             : }
     174             : 

Generated by: LCOV version 1.0