LCOV - code coverage report
Current view: top level - raid - test.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 167 169 98.8 %
Date: 2026-04-29 15:04:44 Functions: 7 7 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 "cpu.h"
       6             : #include "combo.h"
       7             : #include "memory.h"
       8             : 
       9             : /**
      10             :  * Binomial coefficient of n over r.
      11             :  */
      12         120 : static int ibc(int n, int r)
      13             : {
      14         120 :         if (r == 0 || n == r)
      15          63 :                 return 1;
      16             :         else
      17          57 :                 return ibc(n - 1, r - 1) + ibc(n - 1, r);
      18             : }
      19             : 
      20             : /**
      21             :  * Power n ^ r;
      22             :  */
      23           6 : static int ipow(int n, int r)
      24             : {
      25           6 :         int v = 1;
      26             : 
      27          27 :         while (r) {
      28          21 :                 v *= n;
      29          21 :                 --r;
      30             :         }
      31           6 :         return v;
      32             : }
      33             : 
      34           1 : int raid_test_combo(void)
      35             : {
      36             :         int r;
      37             :         int count;
      38             :         int p[RAID_PARITY_MAX];
      39             : 
      40           7 :         for (r = 1; r <= RAID_PARITY_MAX; ++r) {
      41             :                 /* count combination (r of RAID_PARITY_MAX) elements */
      42           6 :                 count = 0;
      43             :                 combination_first(r, RAID_PARITY_MAX, p);
      44             : 
      45             :                 do {
      46          63 :                         ++count;
      47          63 :                 } while (combination_next(r, RAID_PARITY_MAX, p));
      48             : 
      49           6 :                 if (count != ibc(RAID_PARITY_MAX, r)) {
      50             :                         /* LCOV_EXCL_START */
      51             :                         return -1;
      52             :                         /* LCOV_EXCL_STOP */
      53             :                 }
      54             :         }
      55             : 
      56           7 :         for (r = 1; r <= RAID_PARITY_MAX; ++r) {
      57             :                 /* count permutation (r of RAID_PARITY_MAX) elements */
      58           6 :                 count = 0;
      59             :                 permutation_first(r, RAID_PARITY_MAX, p);
      60             : 
      61             :                 do {
      62       55986 :                         ++count;
      63       55986 :                 } while (permutation_next(r, RAID_PARITY_MAX, p));
      64             : 
      65           6 :                 if (count != ipow(RAID_PARITY_MAX, r)) {
      66             :                         /* LCOV_EXCL_START */
      67             :                         return -1;
      68             :                         /* LCOV_EXCL_STOP */
      69             :                 }
      70             :         }
      71             : 
      72           1 :         return 0;
      73             : }
      74             : 
      75           1 : int raid_test_insert(void)
      76             : {
      77             :         int p[RAID_PARITY_MAX];
      78             :         int r;
      79             : 
      80           7 :         for (r = 1; r <= RAID_PARITY_MAX; ++r) {
      81             :                 permutation_first(r, RAID_PARITY_MAX, p);
      82             :                 do {
      83             :                         int i[RAID_PARITY_MAX];
      84             :                         int j;
      85             : 
      86             :                         /* insert in order */
      87      380712 :                         for (j = 0; j < r; ++j)
      88      324726 :                                 raid_insert(j, i, p[j]);
      89             : 
      90             :                         /* check order */
      91      324726 :                         for (j = 1; j < r; ++j) {
      92      268740 :                                 if (i[j - 1] > i[j]) {
      93             :                                         /* LCOV_EXCL_START */
      94             :                                         return -1;
      95             :                                         /* LCOV_EXCL_STOP */
      96             :                                 }
      97             :                         }
      98       55986 :                 } while (permutation_next(r, RAID_PARITY_MAX, p));
      99             :         }
     100             : 
     101           1 :         return 0;
     102             : }
     103             : 
     104           1 : int raid_test_sort(void)
     105             : {
     106             :         int p[RAID_PARITY_MAX];
     107             :         int r;
     108             : 
     109           7 :         for (r = 1; r <= RAID_PARITY_MAX; ++r) {
     110             :                 permutation_first(r, RAID_PARITY_MAX, p);
     111             :                 do {
     112             :                         int i[RAID_PARITY_MAX];
     113             :                         int j;
     114             : 
     115             :                         /* make a copy */
     116      380712 :                         for (j = 0; j < r; ++j)
     117      324726 :                                 i[j] = p[j];
     118             : 
     119       55986 :                         raid_sort(r, i);
     120             : 
     121             :                         /* check order */
     122      324726 :                         for (j = 1; j < r; ++j) {
     123      268740 :                                 if (i[j - 1] > i[j]) {
     124             :                                         /* LCOV_EXCL_START */
     125             :                                         return -1;
     126             :                                         /* LCOV_EXCL_STOP */
     127             :                                 }
     128             :                         }
     129       55986 :                 } while (permutation_next(r, RAID_PARITY_MAX, p));
     130             :         }
     131             : 
     132           1 :         return 0;
     133             : }
     134             : 
     135           2 : int raid_test_rec(int mode, int nd, size_t size)
     136             : {
     137             :         void (*f[RAID_PARITY_MAX][4])(
     138             :                 int nr, int *id, int *ip, int nd, size_t size, void **vbuf);
     139             :         void *v_alloc;
     140             :         void **v;
     141             :         void **data;
     142             :         void **parity;
     143             :         void **test;
     144             :         void *data_save[RAID_PARITY_MAX];
     145             :         void *parity_save[RAID_PARITY_MAX];
     146             :         void *waste;
     147             :         int nv;
     148             :         int id[RAID_PARITY_MAX];
     149             :         int ip[RAID_PARITY_MAX];
     150             :         int i;
     151             :         int j;
     152             :         int nr;
     153             :         int nf[RAID_PARITY_MAX];
     154             :         int np;
     155             : 
     156           2 :         raid_mode(mode);
     157           2 :         if (mode == RAID_MODE_CAUCHY)
     158           1 :                 np = RAID_PARITY_MAX;
     159             :         else
     160           1 :                 np = 3;
     161             : 
     162           2 :         nv = nd + np * 2 + 2;
     163             : 
     164           2 :         v = raid_malloc_vector(nd, nv, size, &v_alloc);
     165           2 :         if (!v) {
     166             :                 /* LCOV_EXCL_START */
     167             :                 return -1;
     168             :                 /* LCOV_EXCL_STOP */
     169             :         }
     170             : 
     171           2 :         data = v;
     172           2 :         parity = v + nd;
     173           2 :         test = v + nd + np;
     174             : 
     175          11 :         for (i = 0; i < np; ++i)
     176           9 :                 parity_save[i] = parity[i];
     177             : 
     178           2 :         memset(v[nv - 2], 0, size);
     179           2 :         raid_zero(v[nv - 2]);
     180             : 
     181           2 :         waste = v[nv - 1];
     182             : 
     183             :         /* fill with pseudo-random data with the arbitrary seed "1" */
     184           2 :         raid_mrand_vector(1, nd, size, v);
     185             : 
     186             :         /* setup recov functions */
     187          11 :         for (i = 0; i < np; ++i) {
     188           9 :                 nf[i] = 0;
     189           9 :                 if (i == 0) {
     190           2 :                         f[i][nf[i]++] = raid_rec1_int8;
     191             : #ifdef CONFIG_X86
     192             : #ifdef CONFIG_SSSE3
     193           2 :                         if (raid_cpu_has_ssse3())
     194           2 :                                 f[i][nf[i]++] = raid_rec1_ssse3;
     195             : #endif
     196             : #ifdef CONFIG_AVX2
     197           2 :                         if (raid_cpu_has_avx2())
     198           2 :                                 f[i][nf[i]++] = raid_rec1_avx2;
     199             : #endif
     200             : #endif
     201             : #ifdef CONFIG_X86_64
     202             : #ifdef CONFIG_AVX512BW
     203           2 :                         if (raid_cpu_has_avx512bw())
     204           2 :                                 f[i][nf[i]++] = raid_rec1_avx512bw;
     205             : #endif
     206             : #endif
     207           7 :                 } else if (i == 1) {
     208           2 :                         f[i][nf[i]++] = raid_rec2_int8;
     209             : #ifdef CONFIG_X86
     210             : #ifdef CONFIG_SSSE3
     211           2 :                         if (raid_cpu_has_ssse3())
     212           2 :                                 f[i][nf[i]++] = raid_rec2_ssse3;
     213             : #endif
     214             : #ifdef CONFIG_AVX2
     215           2 :                         if (raid_cpu_has_avx2())
     216           2 :                                 f[i][nf[i]++] = raid_rec2_avx2;
     217             : #endif
     218             : #endif
     219             : #ifdef CONFIG_X86_64
     220             : #ifdef CONFIG_AVX512BW
     221           2 :                         if (raid_cpu_has_avx512bw())
     222           2 :                                 f[i][nf[i]++] = raid_rec2_avx512bw;
     223             : #endif
     224             : #endif
     225             :                 } else {
     226           5 :                         f[i][nf[i]++] = raid_recX_int8;
     227             : #ifdef CONFIG_X86
     228             : #ifdef CONFIG_SSSE3
     229           5 :                         if (raid_cpu_has_ssse3())
     230           5 :                                 f[i][nf[i]++] = raid_recX_ssse3;
     231             : #endif
     232             : #ifdef CONFIG_AVX2
     233           5 :                         if (raid_cpu_has_avx2())
     234           5 :                                 f[i][nf[i]++] = raid_recX_avx2;
     235             : #endif
     236             : #endif
     237             : #ifdef CONFIG_X86_64
     238             : #ifdef CONFIG_AVX512BW
     239           5 :                         if (raid_cpu_has_avx512bw())
     240           5 :                                 f[i][nf[i]++] = raid_recX_avx512bw;
     241             : #endif
     242             : #endif
     243             :                 }
     244             :         }
     245             : 
     246             :         /* compute the parity */
     247           2 :         raid_gen_ref(nd, np, size, v);
     248             : 
     249             :         /* set all the parity to the waste v */
     250          11 :         for (i = 0; i < np; ++i)
     251           9 :                 parity[i] = waste;
     252             : 
     253             :         /* all parity levels */
     254          11 :         for (nr = 1; nr <= np; ++nr) {
     255             :                 /* all combinations (nr of nd) disks */
     256             :                 combination_first(nr, nd, id);
     257             :                 do {
     258             :                         /* all combinations (nr of np) parities */
     259             :                         combination_first(nr, np, ip);
     260             :                         do {
     261             :                                 /* for each recover function */
     262       95085 :                                 for (j = 0; j < nf[nr - 1]; ++j) {
     263             :                                         /* set */
     264      377460 :                                         for (i = 0; i < nr; ++i) {
     265             :                                                 /* remove the missing data */
     266      301392 :                                                 data_save[i] = data[id[i]];
     267      301392 :                                                 data[id[i]] = test[i];
     268             :                                                 /* set the parity to use */
     269      301392 :                                                 parity[ip[i]] = parity_save[ip[i]];
     270             :                                         }
     271             : 
     272             :                                         /* recover */
     273       76068 :                                         f[nr - 1][j](nr, id, ip, nd, size, v);
     274             : 
     275             :                                         /* check */
     276      377460 :                                         for (i = 0; i < nr; ++i) {
     277      301392 :                                                 if (memcmp(test[i], data_save[i], size) != 0) {
     278             :                                                         /* LCOV_EXCL_START */
     279             :                                                         goto bail;
     280             :                                                         /* LCOV_EXCL_STOP */
     281             :                                                 }
     282             :                                         }
     283             : 
     284             :                                         /* restore */
     285      377460 :                                         for (i = 0; i < nr; ++i) {
     286             :                                                 /* restore the data */
     287      301392 :                                                 data[id[i]] = data_save[i];
     288             :                                                 /* restore the parity */
     289      301392 :                                                 parity[ip[i]] = waste;
     290             :                                         }
     291             :                                 }
     292       19017 :                         } while (combination_next(nr, np, ip));
     293        2807 :                 } while (combination_next(nr, nd, id));
     294             :         }
     295             : 
     296           2 :         free(v_alloc);
     297           2 :         free(v);
     298           2 :         return 0;
     299             : 
     300           0 : bail:
     301             :         /* LCOV_EXCL_START */
     302             :         free(v_alloc);
     303             :         free(v);
     304             :         return -1;
     305             :         /* LCOV_EXCL_STOP */
     306             : }
     307             : 
     308           3 : int raid_test_par(int mode, int nd, size_t size)
     309             : {
     310             :         void (*f[64])(int nd, size_t size, void **vbuf);
     311             :         void *v_alloc;
     312             :         void **v;
     313             :         int nv;
     314             :         int i, j;
     315             :         int nf;
     316             :         int np;
     317             : 
     318           3 :         raid_mode(mode);
     319           3 :         if (mode == RAID_MODE_CAUCHY)
     320           2 :                 np = RAID_PARITY_MAX;
     321             :         else
     322           1 :                 np = 3;
     323             : 
     324           3 :         nv = nd + np * 2;
     325             : 
     326           3 :         v = raid_malloc_vector(nd, nv, size, &v_alloc);
     327           3 :         if (!v) {
     328             :                 /* LCOV_EXCL_START */
     329             :                 return -1;
     330             :                 /* LCOV_EXCL_STOP */
     331             :         }
     332             : 
     333             :         /* check memory */
     334           3 :         if (raid_mtest_vector(nv, size, v) != 0) {
     335             :                 /* LCOV_EXCL_START */
     336             :                 goto bail;
     337             :                 /* LCOV_EXCL_STOP */
     338             :         }
     339             : 
     340             :         /* fill with pseudo-random data with the arbitrary seed "2" */
     341           3 :         raid_mrand_vector(2, nv, size, v);
     342             : 
     343             :         /* compute the parity */
     344           3 :         raid_gen_ref(nd, np, size, v);
     345             : 
     346             :         /* copy in back buffers */
     347          18 :         for (i = 0; i < np; ++i)
     348          15 :                 memcpy(v[nd + np + i], v[nd + i], size);
     349             : 
     350             :         /* load all the available functions */
     351           3 :         nf = 0;
     352             : 
     353           3 :         f[nf++] = raid_gen1_int32;
     354           3 :         f[nf++] = raid_gen1_int64;
     355           3 :         f[nf++] = raid_gen2_int32;
     356           3 :         f[nf++] = raid_gen2_int64;
     357             : 
     358             : #ifdef CONFIG_X86
     359             : #ifdef CONFIG_SSE2
     360           3 :         if (raid_cpu_has_sse2()) {
     361           3 :                 f[nf++] = raid_gen1_sse2;
     362           3 :                 f[nf++] = raid_gen2_sse2;
     363             : #ifdef CONFIG_X86_64
     364           3 :                 f[nf++] = raid_gen2_sse2ext;
     365             : #endif
     366             :         }
     367             : #endif
     368             : 
     369             : #ifdef CONFIG_AVX2
     370           3 :         if (raid_cpu_has_avx2()) {
     371           3 :                 f[nf++] = raid_gen1_avx2;
     372           3 :                 f[nf++] = raid_gen2_avx2;
     373             :         }
     374             : #endif
     375             : 
     376             : #ifdef CONFIG_AVX512BW
     377             : #ifdef CONFIG_X86_64
     378           3 :         if (raid_cpu_has_avx512bw()) {
     379           3 :                 f[nf++] = raid_gen1_avx512bw;
     380           3 :                 f[nf++] = raid_gen2_avx512bw;
     381             :         }
     382             : #endif
     383             : #endif
     384             : #endif /* CONFIG_X86 */
     385             : 
     386           3 :         if (mode == RAID_MODE_CAUCHY) {
     387           2 :                 f[nf++] = raid_gen3_int8;
     388           2 :                 f[nf++] = raid_gen4_int8;
     389           2 :                 f[nf++] = raid_gen5_int8;
     390           2 :                 f[nf++] = raid_gen6_int8;
     391             : 
     392             : #ifdef CONFIG_X86
     393             : #ifdef CONFIG_SSSE3
     394           2 :                 if (raid_cpu_has_ssse3()) {
     395           2 :                         f[nf++] = raid_gen3_ssse3;
     396           2 :                         f[nf++] = raid_gen4_ssse3;
     397           2 :                         f[nf++] = raid_gen5_ssse3;
     398           2 :                         f[nf++] = raid_gen6_ssse3;
     399             : #ifdef CONFIG_X86_64
     400           2 :                         f[nf++] = raid_gen3_ssse3ext;
     401           2 :                         f[nf++] = raid_gen4_ssse3ext;
     402           2 :                         f[nf++] = raid_gen5_ssse3ext;
     403           2 :                         f[nf++] = raid_gen6_ssse3ext;
     404             : #endif
     405             :                 }
     406             : #endif
     407             : 
     408             : #ifdef CONFIG_AVX2
     409             : #ifdef CONFIG_X86_64
     410           2 :                 if (raid_cpu_has_avx2()) {
     411           2 :                         f[nf++] = raid_gen3_avx2ext;
     412           2 :                         f[nf++] = raid_gen4_avx2ext;
     413           2 :                         f[nf++] = raid_gen5_avx2ext;
     414           2 :                         f[nf++] = raid_gen6_avx2ext;
     415             :                 }
     416             : #endif
     417             : #endif
     418             : 
     419             : #ifdef CONFIG_AVX512BW
     420             : #ifdef CONFIG_X86_64
     421           2 :                 if (raid_cpu_has_avx512bw()) {
     422           2 :                         f[nf++] = raid_gen3_avx512bw;
     423           2 :                         f[nf++] = raid_gen4_avx512bw;
     424           2 :                         f[nf++] = raid_gen5_avx512bw;
     425           2 :                         f[nf++] = raid_gen6_avx512bw;
     426             :                 }
     427             : #endif
     428             : #endif
     429             : 
     430             : #endif /* CONFIG_X86 */
     431             :         } else {
     432           1 :                 f[nf++] = raid_genz_int32;
     433           1 :                 f[nf++] = raid_genz_int64;
     434             : 
     435             : #ifdef CONFIG_X86
     436             : #ifdef CONFIG_SSE2
     437           1 :                 if (raid_cpu_has_sse2()) {
     438           1 :                         f[nf++] = raid_genz_sse2;
     439             : #ifdef CONFIG_X86_64
     440           1 :                         f[nf++] = raid_genz_sse2ext;
     441             : #endif
     442             :                 }
     443             : #endif
     444             : 
     445             : #ifdef CONFIG_AVX2
     446             : #ifdef CONFIG_X86_64
     447           1 :                 if (raid_cpu_has_avx2())
     448           1 :                         f[nf++] = raid_genz_avx2ext;
     449             : #endif
     450             : #endif
     451             : #endif /* CONFIG_X86 */
     452             :         }
     453             : 
     454             :         /* check all the functions */
     455          81 :         for (j = 0; j < nf; ++j) {
     456             :                 /* compute parity */
     457          78 :                 f[j](nd, size, v);
     458             : 
     459             :                 /* check it */
     460         498 :                 for (i = 0; i < np; ++i) {
     461         420 :                         if (memcmp(v[nd + np + i], v[nd + i], size) != 0) {
     462             :                                 /* LCOV_EXCL_START */
     463             :                                 goto bail;
     464             :                                 /* LCOV_EXCL_STOP */
     465             :                         }
     466             :                 }
     467             :         }
     468             : 
     469           3 :         free(v_alloc);
     470           3 :         free(v);
     471           3 :         return 0;
     472             : 
     473           0 : bail:
     474             :         /* LCOV_EXCL_START */
     475             :         free(v_alloc);
     476             :         free(v);
     477             :         return -1;
     478             :         /* LCOV_EXCL_STOP */
     479             : }
     480             : 

Generated by: LCOV version 1.0