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

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : // Copyright (C) 2013 Andrea Mazzoleni
       3             : 
       4             : #include "internal.h"
       5             : #include "memory.h"
       6             : #include "cpu.h"
       7             : 
       8             : /**
       9             :  * Forwarders for parity generation.
      10             :  *
      11             :  * Set by the raid_mode() call.
      12             :  * 
      13             :  * Index 0 is for one parity, 1 for the two parities, and so on.
      14             :  */
      15             : static raid_gen_fn* raid_gen_ptr[RAID_PARITY_MAX];
      16             : 
      17             : struct raid_gen_algo {
      18             :         raid_gen_fn *gen;
      19             :         const char *tag; /**< Hardware descriptive tag. */
      20             : };
      21             : 
      22             : /**
      23             :  * Registered algorithms for parity generation.
      24             :  *
      25             :  * Set by the raid_gen_register() calls.
      26             :  * 
      27             :  * Indexes are the RAID_ALGO_* constants
      28             :  */
      29             : static struct raid_gen_algo raid_gen_algo[RAID_ALGO_MAX];
      30             : 
      31     1327991 : void raid_gen(int nd, int np, size_t size, void **v)
      32             : {
      33             :         /* enforce limit on size */
      34     1327991 :         BUG_ON(size % 64 != 0);
      35             : 
      36             :         /* enforce limit on number of failures */
      37     1327991 :         BUG_ON(np < 1);
      38     1327991 :         BUG_ON(np > RAID_PARITY_MAX);
      39             : 
      40     1327991 :         raid_gen_ptr[np - 1](nd, size, v);
      41     1327991 : }
      42             : 
      43             : /**
      44             :  * Forwarders for data recovery.
      45             :  *
      46             :  * Set by the raid_mode() call.
      47             :  * 
      48             :  * Index 0 is for one parity, 1 for the two parities, and so on.
      49             :  */
      50             : static raid_rec_fn* raid_rec_ptr[RAID_PARITY_MAX]; 
      51             : 
      52             : struct raid_rec_algo {
      53             :         raid_rec_fn *rec;
      54             :         const char *tag;  /**< Hardware descriptive tag. */
      55             : };
      56             : 
      57             : /**
      58             :  * Registered algorithms for data recovery.
      59             :  *
      60             :  * Set by the raid_rec_register() calls.
      61             :  * 
      62             :  * Indexes are the RAID_ALGO_* constants
      63             :  */
      64             : static struct raid_rec_algo raid_rec_algo[RAID_PARITY_MAX];
      65             : 
      66         870 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v)
      67             : {
      68             :         int nrd; /* number of data blocks to recover */
      69             :         int nrp; /* number of parity blocks to recover */
      70             : 
      71             :         /* enforce limit on size */
      72         870 :         BUG_ON(size % 64 != 0);
      73             : 
      74             :         /* enforce limit on number of failures */
      75         870 :         BUG_ON(nr > np);
      76         870 :         BUG_ON(np > RAID_PARITY_MAX);
      77             : 
      78             :         /* enforce order in index vector */
      79         870 :         BUG_ON(nr >= 2 && ir[0] >= ir[1]);
      80         870 :         BUG_ON(nr >= 3 && ir[1] >= ir[2]);
      81         870 :         BUG_ON(nr >= 4 && ir[2] >= ir[3]);
      82         870 :         BUG_ON(nr >= 5 && ir[3] >= ir[4]);
      83         870 :         BUG_ON(nr >= 6 && ir[4] >= ir[5]);
      84             : 
      85             :         /* enforce limit on index vector */
      86         870 :         BUG_ON(nr > 0 && ir[nr-1] >= nd + np);
      87             : 
      88             :         /* count the number of data blocks to recover */
      89         870 :         nrd = 0;
      90        2613 :         while (nrd < nr && ir[nrd] < nd)
      91        1743 :                 ++nrd;
      92             : 
      93             :         /* all the remaining are parity */
      94         870 :         nrp = nr - nrd;
      95             : 
      96             :         /* enforce limit on number of failures */
      97         870 :         BUG_ON(nrd > nd);
      98         870 :         BUG_ON(nrp > np);
      99             : 
     100             :         /* if failed data is present */
     101         870 :         if (nrd != 0) {
     102             :                 int ip[RAID_PARITY_MAX];
     103             :                 int i, j, k;
     104             : 
     105             :                 /* setup the vector of parities to use */
     106        6041 :                 for (i = 0, j = 0, k = 0; i < np; ++i) {
     107        5173 :                         if (j < nrp && ir[nrd + j] == nd + i) {
     108             :                                 /* this parity has to be recovered */
     109          22 :                                 ++j;
     110             :                         } else {
     111             :                                 /* this parity is used for recovering */
     112        5151 :                                 ip[k] = i;
     113        5151 :                                 ++k;
     114             :                         }
     115             :                 }
     116             : 
     117             :                 /*
     118             :                  * Recover the nrd data blocks specified in ir[],
     119             :                  * using the first nrd parity in ip[] for recovering
     120             :                  */
     121         868 :                 raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v);
     122             :         }
     123             : 
     124             :         /* recompute all the parities up to the last bad one */
     125         870 :         if (nrp != 0)
     126          12 :                 raid_gen(nd, ir[nr - 1] - nd + 1, size, v);
     127         870 : }
     128             : 
     129      227485 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
     130             : {
     131             :         /* enforce limit on size */
     132      227485 :         BUG_ON(size % 64 != 0);
     133             : 
     134             :         /* enforce limit on number of failures */
     135      227485 :         BUG_ON(nr > nd);
     136      227485 :         BUG_ON(nr > RAID_PARITY_MAX);
     137             : 
     138             :         /* enforce order in index vector for data */
     139      227485 :         BUG_ON(nr >= 2 && id[0] >= id[1]);
     140      227485 :         BUG_ON(nr >= 3 && id[1] >= id[2]);
     141      227485 :         BUG_ON(nr >= 4 && id[2] >= id[3]);
     142      227485 :         BUG_ON(nr >= 5 && id[3] >= id[4]);
     143      227485 :         BUG_ON(nr >= 6 && id[4] >= id[5]);
     144             : 
     145             :         /* enforce limit on index vector for data */
     146      227485 :         BUG_ON(nr > 0 && id[nr-1] >= nd);
     147             : 
     148             :         /* enforce order in index vector for parity */
     149      227485 :         BUG_ON(nr >= 2 && ip[0] >= ip[1]);
     150      227485 :         BUG_ON(nr >= 3 && ip[1] >= ip[2]);
     151      227485 :         BUG_ON(nr >= 4 && ip[2] >= ip[3]);
     152      227485 :         BUG_ON(nr >= 5 && ip[3] >= ip[4]);
     153      227485 :         BUG_ON(nr >= 6 && ip[4] >= ip[5]);
     154             : 
     155             :         /* if failed data is present */
     156      227485 :         if (nr != 0)
     157      227483 :                 raid_rec_algo[nr - 1].rec(nr, id, ip, nd, size, v);
     158      227485 : }
     159             : 
     160          35 : const char *raid_gen_tag(int na)
     161             : {
     162          35 :         BUG_ON(na < 0 || na >= RAID_ALGO_MAX);
     163             : 
     164          35 :         return raid_gen_algo[na].tag;
     165             : }
     166             : 
     167          30 : const char *raid_rec_tag(int na)
     168             : {
     169             :         /* there is no custom recover for vandermonde */
     170          30 :         if (na == RAID_ALGO_VANDERMONDE_PAR3)
     171           0 :                 na = RAID_ALGO_CAUCHY_PAR3;
     172             : 
     173          30 :         BUG_ON(na < 0 || na >= RAID_PARITY_MAX);
     174             : 
     175          30 :         return raid_rec_algo[na].tag;
     176             : }
     177             : 
     178             : /**
     179             :  * Generator matrix currently used.
     180             :  */
     181             : const uint8_t (*raid_gfgen)[256];
     182             : 
     183         642 : void raid_mode(int mode)
     184             : {
     185         642 :         BUG_ON(mode != RAID_MODE_VANDERMONDE && mode != RAID_MODE_CAUCHY);
     186             :         
     187         642 :         if (mode == RAID_MODE_VANDERMONDE) {
     188           5 :                 raid_gen_ptr[0] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR1].gen;
     189           5 :                 raid_gen_ptr[1] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR2].gen;
     190           5 :                 raid_gen_ptr[2] = raid_gen_algo[RAID_ALGO_VANDERMONDE_PAR3].gen;
     191           5 :                 raid_gen_ptr[3] = 0;
     192           5 :                 raid_gen_ptr[4] = 0;
     193           5 :                 raid_gen_ptr[5] = 0;
     194           5 :                 raid_rec_ptr[0] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR1].rec;
     195           5 :                 raid_rec_ptr[1] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR2].rec;
     196           5 :                 raid_rec_ptr[2] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR3].rec;
     197           5 :                 raid_rec_ptr[3] = 0;
     198           5 :                 raid_rec_ptr[4] = 0;
     199           5 :                 raid_rec_ptr[5] = 0;
     200           5 :                 raid_gfgen = gfvandermonde;
     201             :         } else {
     202         637 :                 raid_gen_ptr[0] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR1].gen;
     203         637 :                 raid_gen_ptr[1] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR2].gen;
     204         637 :                 raid_gen_ptr[2] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR3].gen;
     205         637 :                 raid_gen_ptr[3] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR4].gen;
     206         637 :                 raid_gen_ptr[4] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR5].gen;
     207         637 :                 raid_gen_ptr[5] = raid_gen_algo[RAID_ALGO_CAUCHY_PAR6].gen;
     208         637 :                 raid_rec_ptr[0] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR1].rec;
     209         637 :                 raid_rec_ptr[1] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR2].rec;
     210         637 :                 raid_rec_ptr[2] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR3].rec;
     211         637 :                 raid_rec_ptr[3] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR4].rec;
     212         637 :                 raid_rec_ptr[4] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR5].rec;
     213         637 :                 raid_rec_ptr[5] = raid_rec_algo[RAID_ALGO_CAUCHY_PAR6].rec;
     214         637 :                 raid_gfgen = gfcauchy;
     215             :         }
     216         642 : }
     217             : 
     218         119 : void raid_gen_force(int np, raid_gen_fn *fn)
     219             : {
     220         119 :         BUG_ON(np < 1 || np > RAID_PARITY_MAX);
     221             : 
     222         119 :         raid_gen_ptr[np - 1] = fn;
     223         119 : }
     224             : 
     225        6143 : void raid_gen_register(int na, const char *tag, raid_gen_fn *gen)
     226             : {
     227        6143 :         BUG_ON(na < 0 || na >= RAID_ALGO_MAX);
     228             : 
     229        6143 :         raid_gen_algo[na].tag = tag;
     230        6143 :         raid_gen_algo[na].gen = gen;
     231        6143 : }
     232             : 
     233        3888 : void raid_rec_register(int na, const char *tag, raid_rec_fn *rec)
     234             : {
     235        3888 :         BUG_ON(na < 0 || na >= RAID_PARITY_MAX);
     236             : 
     237        3888 :         raid_rec_algo[na].tag = tag;
     238        3888 :         raid_rec_algo[na].rec = rec;
     239        3888 : }
     240             : 
     241             : /*
     242             :  * Initializes and selects the best algorithm.
     243             :  */
     244         322 : void raid_init(void)
     245             : {
     246         322 :         raid_register_int();
     247             : #if defined(CONFIG_X86) && defined(CONFIG_SSE2)
     248         322 :         raid_register_x86();
     249             : #endif
     250             : 
     251             :         /* set the default mode */
     252         322 :         raid_mode(RAID_MODE_CAUCHY);
     253         322 : }
     254             : 
     255             : /*
     256             :  * Reference parity computation.
     257             :  */
     258           6 : void raid_gen_ref(int nd, int np, size_t size, void **vv)
     259             : {
     260           6 :         uint8_t **v = (uint8_t **)vv;
     261             :         size_t i;
     262             : 
     263        5382 :         for (i = 0; i < size; ++i) {
     264             :                 uint8_t p[RAID_PARITY_MAX];
     265             :                 int j, d;
     266             : 
     267       36096 :                 for (j = 0; j < np; ++j)
     268       30720 :                         p[j] = 0;
     269             : 
     270       93696 :                 for (d = 0; d < nd; ++d) {
     271       88320 :                         uint8_t b = v[d][i];
     272             : 
     273      584448 :                         for (j = 0; j < np; ++j)
     274      496128 :                                 p[j] ^= gfmul[b][gfgen[j][d]];
     275             :                 }
     276             : 
     277       36096 :                 for (j = 0; j < np; ++j)
     278       30720 :                         v[nd + j][i] = p[j];
     279             :         }
     280           6 : }
     281             : 
     282             : /*
     283             :  * Size of the blocks to test.
     284             :  */
     285             : #define TEST_SIZE 4096
     286             : 
     287             : /*
     288             :  * Number of data blocks to test.
     289             :  */
     290             : #define TEST_COUNT (65536 / TEST_SIZE)
     291             : 
     292             : /*
     293             :  * Parity generation test.
     294             :  */
     295           6 : static int raid_test_par(int nd, int np, size_t size, void **v, void **ref)
     296             : {
     297             :         int i;
     298             :         void *t[TEST_COUNT + RAID_PARITY_MAX];
     299             : 
     300             :         /* setup data */
     301         102 :         for (i = 0; i < nd; ++i)
     302          96 :                 t[i] = ref[i];
     303             : 
     304             :         /* setup parity */
     305          27 :         for (i = 0; i < np; ++i)
     306          21 :                 t[nd + i] = v[nd + i];
     307             : 
     308           6 :         raid_gen(nd, np, size, t);
     309             : 
     310             :         /* compare parity */
     311          27 :         for (i = 0; i < np; ++i) {
     312          21 :                 if (memcmp(t[nd + i], ref[nd + i], size) != 0) {
     313             :                         /* LCOV_EXCL_START */
     314             :                         return -1;
     315             :                         /* LCOV_EXCL_STOP */
     316             :                 }
     317             :         }
     318             : 
     319           6 :         return 0;
     320             : }
     321             : 
     322             : /*
     323             :  * Recovering test.
     324             :  */
     325          18 : static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
     326             : {
     327             :         int i, j;
     328             :         void *t[TEST_COUNT + RAID_PARITY_MAX];
     329             : 
     330             :         /* setup data and parity vector */
     331         369 :         for (i = 0, j = 0; i < nd + np; ++i) {
     332         351 :                 if (j < nr && ir[j] == i) {
     333             :                         /* this block has to be recovered */
     334          63 :                         t[i] = v[i];
     335          63 :                         ++j;
     336             :                 } else {
     337             :                         /* this block is used for recovering */
     338         288 :                         t[i] = ref[i];
     339             :                 }
     340             :         }
     341             : 
     342          18 :         raid_rec(nr, ir, nd, np, size, t);
     343             : 
     344             :         /* compare all data and parity */
     345         369 :         for (i = 0; i < nd + np; ++i) {
     346         351 :                 if (t[i] != ref[i]
     347          63 :                         && memcmp(t[i], ref[i], size) != 0) {
     348             :                         /* LCOV_EXCL_START */
     349             :                         return -1;
     350             :                         /* LCOV_EXCL_STOP */
     351             :                 }
     352             :         }
     353             : 
     354          18 :         return 0;
     355             : }
     356             : 
     357             : /*
     358             :  * Recovering test for data.
     359             :  */
     360          18 : static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref)
     361             : {
     362             :         int i, j;
     363             :         void *t[TEST_COUNT + RAID_PARITY_MAX];
     364             : 
     365             :         /* setup data vector */
     366         306 :         for (i = 0, j = 0; i < nd; ++i) {
     367         288 :                 if (j < nr && id[j] == i) {
     368             :                         /* this block has to be recovered */
     369          39 :                         t[i] = v[i];
     370          39 :                         ++j;
     371             :                 } else {
     372             :                         /* this block is left unchanged */
     373         249 :                         t[i] = ref[i];
     374             :                 }
     375             :         }
     376             : 
     377             :         /* setup parity vector */
     378          81 :         for (i = 0, j = 0; i < np; ++i) {
     379          63 :                 if (j < nr && ip[j] == i) {
     380             :                         /* this block is used for recovering */
     381          39 :                         t[nd + i] = ref[nd + i];
     382          39 :                         ++j;
     383             :                 } else {
     384             :                         /* this block should not be read or written */
     385          24 :                         t[nd + i] = 0;
     386             :                 }
     387             :         }
     388             : 
     389          18 :         raid_data(nr, id, ip, nd, size, t);
     390             : 
     391             :         /* compare all data and parity */
     392         306 :         for (i = 0; i < nd; ++i) {
     393         288 :                 if (t[i] != ref[i]
     394          39 :                         && t[i] != 0
     395          39 :                         && memcmp(t[i], ref[i], size) != 0) {
     396             :                         /* LCOV_EXCL_START */
     397             :                         return -1;
     398             :                         /* LCOV_EXCL_STOP */
     399             :                 }
     400             :         }
     401             : 
     402          18 :         return 0;
     403             : }
     404             : 
     405             : /*
     406             :  * Scan test.
     407             :  */
     408           7 : static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
     409             : {
     410             :         int i, j, ret;
     411             :         void *t[TEST_COUNT + RAID_PARITY_MAX];
     412             :         int is[RAID_PARITY_MAX];
     413             : 
     414             :         /* setup data and parity vector */
     415         140 :         for (i = 0, j = 0; i < nd + np; ++i) {
     416         133 :                 if (j < nr && ir[j] == i) {
     417             :                         /* this block is bad */
     418          15 :                         t[i] = v[i];
     419          15 :                         ++j;
     420             :                 } else {
     421             :                         /* this block is used for recovering */
     422         118 :                         t[i] = ref[i];
     423             :                 }
     424             :         }
     425             : 
     426           7 :         ret = raid_scan(is, nd, np, size, t);
     427             : 
     428             :         /* compare identified bad blocks */
     429           7 :         if (ret != nr)
     430           1 :                 return -1;
     431          21 :         for (i = 0; i < nr; ++i) {
     432          15 :                 if (ir[i] != is[i]) {
     433             :                         /* LCOV_EXCL_START */
     434             :                         return -1;
     435             :                         /* LCOV_EXCL_STOP */
     436             :                 }
     437             :         }
     438             : 
     439           6 :         return 0;
     440             : }
     441             : 
     442           1 : int raid_selftest(void)
     443           1 : {
     444           1 :         const int nd = TEST_COUNT;
     445           1 :         const size_t size = TEST_SIZE;
     446           1 :         const int nv = nd + RAID_PARITY_MAX * 2 + 1;
     447             :         void *v_alloc;
     448             :         void **v;
     449           1 :         void *ref[nd + RAID_PARITY_MAX];
     450             :         int ir[RAID_PARITY_MAX];
     451             :         int ip[RAID_PARITY_MAX];
     452             :         int i, np;
     453           1 :         int ret = 0;
     454             : 
     455             :         /* ensure to have enough space for data */
     456           1 :         BUG_ON(nd * size > 65536);
     457             : 
     458           1 :         v = raid_malloc_vector(nd, nv, size, &v_alloc);
     459           1 :         if (!v) {
     460             :                 /* LCOV_EXCL_START */
     461             :                 return -1;
     462             :                 /* LCOV_EXCL_STOP */
     463             :         }
     464             : 
     465           1 :         memset(v[nv - 1], 0, size);
     466           1 :         raid_zero(v[nv - 1]);
     467             : 
     468             :         /* use the multiplication table as data */
     469          17 :         for (i = 0; i < nd; ++i)
     470          16 :                 ref[i] = ((uint8_t *)gfmul) + size * i;
     471             : 
     472             :         /* setup reference parity */
     473           7 :         for (i = 0; i < RAID_PARITY_MAX; ++i)
     474           6 :                 ref[nd + i] = v[nd + RAID_PARITY_MAX + i];
     475             : 
     476             :         /* compute reference parity */
     477           1 :         raid_gen_ref(nd, RAID_PARITY_MAX, size, ref);
     478             : 
     479             :         /* test for each parity level */
     480           7 :         for (np = 1; np <= RAID_PARITY_MAX; ++np) {
     481             :                 /* test parity generation */
     482           6 :                 ret = raid_test_par(nd, np, size, v, ref);
     483           6 :                 if (ret != 0) {
     484             :                         /* LCOV_EXCL_START */
     485             :                         goto bail;
     486             :                         /* LCOV_EXCL_STOP */
     487             :                 }
     488             : 
     489             :                 /* test recovering with broken ending data disks */
     490          27 :                 for (i = 0; i < np; ++i) {
     491             :                         /* bad data */
     492          21 :                         ir[i] = nd - np + i;
     493             : 
     494             :                         /* good parity */
     495          21 :                         ip[i] = i;
     496             :                 }
     497             : 
     498           6 :                 ret = raid_test_rec(np, ir, nd, np, size, v, ref);
     499           6 :                 if (ret != 0) {
     500             :                         /* LCOV_EXCL_START */
     501             :                         goto bail;
     502             :                         /* LCOV_EXCL_STOP */
     503             :                 }
     504             : 
     505           6 :                 ret = raid_test_data(np, ir, ip, nd, np, size, v, ref);
     506           6 :                 if (ret != 0) {
     507             :                         /* LCOV_EXCL_START */
     508             :                         goto bail;
     509             :                         /* LCOV_EXCL_STOP */
     510             :                 }
     511             : 
     512             :                 /* test recovering with broken leading data and broken leading parity */
     513          15 :                 for (i = 0; i < np / 2; ++i) {
     514             :                         /* bad data */
     515           9 :                         ir[i] = i;
     516             : 
     517             :                         /* good parity */
     518           9 :                         ip[i] = (np + 1) / 2 + i;
     519             :                 }
     520             : 
     521             :                 /* bad parity */
     522          18 :                 for (i = 0; i < (np + 1) / 2; ++i)
     523          12 :                         ir[np / 2 + i] = nd + i;
     524             : 
     525           6 :                 ret = raid_test_rec(np, ir, nd, np, size, v, ref);
     526           6 :                 if (ret != 0) {
     527             :                         /* LCOV_EXCL_START */
     528             :                         goto bail;
     529             :                         /* LCOV_EXCL_STOP */
     530             :                 }
     531             : 
     532           6 :                 ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
     533           6 :                 if (ret != 0) {
     534             :                         /* LCOV_EXCL_START */
     535             :                         goto bail;
     536             :                         /* LCOV_EXCL_STOP */
     537             :                 }
     538             : 
     539             :                 /* test recovering with broken leading data and broken ending parity */
     540          15 :                 for (i = 0; i < np / 2; ++i) {
     541             :                         /* bad data */
     542           9 :                         ir[i] = i;
     543             : 
     544             :                         /* good parity */
     545           9 :                         ip[i] = i;
     546             :                 }
     547             : 
     548             :                 /* bad parity */
     549          18 :                 for (i = 0; i < (np + 1) / 2; ++i)
     550          12 :                         ir[np / 2 + i] = nd + np - (np + 1) / 2 + i;
     551             : 
     552           6 :                 ret = raid_test_rec(np, ir, nd, np, size, v, ref);
     553           6 :                 if (ret != 0) {
     554             :                         /* LCOV_EXCL_START */
     555             :                         goto bail;
     556             :                         /* LCOV_EXCL_STOP */
     557             :                 }
     558             : 
     559           6 :                 ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
     560           6 :                 if (ret != 0) {
     561             :                         /* LCOV_EXCL_START */
     562             :                         goto bail;
     563             :                         /* LCOV_EXCL_STOP */
     564             :                 }
     565             : 
     566             :                 /* scan test with broken data and parity */
     567          15 :                 for (i = 0; i < np / 2; ++i) {
     568             :                         /* bad data */
     569           9 :                         ir[i] = i;
     570             :                 }
     571          12 :                 for (i = 0; i < (np - 1) / 2; ++i) {
     572             :                         /* bad parity */
     573           6 :                         ir[np / 2 + i] = nd + i;
     574             :                 }
     575          21 :                 for (i = 0; i < np - 1; ++i) {
     576             :                         /*
     577             :                          * Make blocks bad
     578             :                          * we cannot fill them with 0, because the original
     579             :                          * data may be already filled with 0
     580             :                          */
     581          15 :                         memset(v[ir[i]], 0x55, size);
     582             :                 }
     583             : 
     584           6 :                 ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref);
     585           6 :                 if (ret != 0) {
     586             :                         /* LCOV_EXCL_START */
     587             :                         goto bail;
     588             :                         /* LCOV_EXCL_STOP */
     589             :                 }
     590             :         }
     591             : 
     592             :         /* scan test with no parity */
     593           1 :         ret = raid_test_scan(0, 0, nd, 0, size, v, ref);
     594           1 :         if (ret != -1) {
     595             :                 /* LCOV_EXCL_START */
     596             :                 goto bail;
     597             :                 /* LCOV_EXCL_STOP */
     598             :         }
     599             : 
     600           1 :         ret = 0;
     601             : 
     602           1 : bail:
     603           1 :         free(v);
     604           1 :         free(v_alloc);
     605             : 
     606           1 :         return ret;
     607             : }
     608             : 
     609             : #ifdef __KERNEL__ /* to build the user mode test */
     610             : static int speedtest = 1;
     611             : 
     612             : static int __init raid_cauchy_init(void)
     613             : {
     614             :         int ret;
     615             : 
     616             :         raid_init();
     617             : 
     618             :         pr_info("raid: Using xor_blocks\n");
     619             : #ifdef RAID_USE_RAID6_PQ
     620             :         pr_info("raid: Using raid6\n");
     621             : #endif
     622             : 
     623             :         ret = raid_selftest();
     624             :         if (ret != 0)
     625             :                 return ret;
     626             : 
     627             :         pr_info("raid: Self test passed\n");
     628             : 
     629             :         if (speedtest) {
     630             :                 pr_info("raid: Speed test\n");
     631             :                 raid_speedtest(0);
     632             :                 pr_info("raid: Speed test with optimized memory layout\n");
     633             :                 raid_speedtest(64); /* 64 is the typical cache line size */
     634             :         }
     635             : 
     636             :         return 0;
     637             : }
     638             : 
     639             : static void raid_cauchy_exit(void)
     640             : {
     641             : }
     642             : 
     643             : subsys_initcall(raid_cauchy_init);
     644             : module_exit(raid_cauchy_exit);
     645             : module_param(speedtest, int, 0);
     646             : MODULE_PARM_DESC(speedtest, "Runs a startup speed test");
     647             : MODULE_AUTHOR("Andrea Mazzoleni <amadvance@gmail.com>");
     648             : MODULE_LICENSE("GPL");
     649             : MODULE_DESCRIPTION("RAID Cauchy functions");
     650             : #endif
     651             : 

Generated by: LCOV version 1.0