mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Moves RAID tests in the raid/ dir.
This commit is contained in:
parent
eb08995834
commit
03482b84a6
16 changed files with 943 additions and 612 deletions
|
|
@ -11,6 +11,8 @@ snapraid_SOURCES = \
|
|||
raid/intz.c \
|
||||
raid/x86z.c \
|
||||
raid/sort.c \
|
||||
raid/memory.c \
|
||||
raid/test.c \
|
||||
snapraid.c \
|
||||
tommy.c \
|
||||
util.c \
|
||||
|
|
@ -43,6 +45,9 @@ noinst_HEADERS = \
|
|||
raid/internal.h \
|
||||
raid/cpu.h \
|
||||
raid/gf.h \
|
||||
raid/combo.h \
|
||||
raid/memory.h \
|
||||
raid/test.h \
|
||||
portable.h \
|
||||
snapraid.h \
|
||||
util.h \
|
||||
|
|
@ -69,7 +74,6 @@ noinst_HEADERS = \
|
|||
tommyhashdyn.c \
|
||||
tommylist.c \
|
||||
fnmatch.h \
|
||||
combo.h \
|
||||
import.h \
|
||||
mingw.h \
|
||||
unix.h
|
||||
|
|
|
|||
2
check.c
2
check.c
|
|
@ -24,7 +24,7 @@
|
|||
#include "parity.h"
|
||||
#include "handle.h"
|
||||
#include "raid/raid.h"
|
||||
#include "combo.h"
|
||||
#include "raid/combo.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* check */
|
||||
|
|
|
|||
90
combo.h
90
combo.h
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __COMBO_H
|
||||
#define __COMBO_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* Get the first combination of r of n elements.
|
||||
*
|
||||
* Typical use is with combination_next() in the form :
|
||||
*
|
||||
* int i[R];
|
||||
* combination_first(R, N, i);
|
||||
* do {
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
* } while (combination_next(R, N, i));
|
||||
*
|
||||
* It's equivalent at the code :
|
||||
*
|
||||
* for(i[0]=0;i[0]<N-(R-1);++i[0])
|
||||
* for(i[1]=i[0]+1;i[1]<N-(R-2);++i[1])
|
||||
* ...
|
||||
* for(i[R-2]=i[R-3]+1;i[R-2]<N-1;++i[R-2])
|
||||
* for(i[R-1]=i[R-2]+1;i[R-1]<N;++i[R-1])
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
*/
|
||||
static inline void combination_first(unsigned r, unsigned n, int* c)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
(void)n; /* unused, but kept for clarity */
|
||||
assert(0 < r && r <= n);
|
||||
|
||||
for(i=0;i<r;++i)
|
||||
c[i] = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next combination of r of n elements.
|
||||
* Return ==0 when finished.
|
||||
*/
|
||||
static inline int combination_next(unsigned r, unsigned n, int* c)
|
||||
{
|
||||
unsigned i = r - 1; /* present position */
|
||||
int h = n; /* high limit for this position */
|
||||
|
||||
recurse:
|
||||
/* next element at position i */
|
||||
++c[i];
|
||||
|
||||
/* if the position has reached the max */
|
||||
if (c[i] >= h) {
|
||||
|
||||
/* if we are at the first level, we have finished */
|
||||
if (i == 0)
|
||||
return 0;
|
||||
|
||||
/* increase the previous position */
|
||||
--i;
|
||||
--h;
|
||||
goto recurse;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
/* initialize all the next positions, if any */
|
||||
while (i < r) {
|
||||
c[i] = c[i-1] + 1; /* each position start at the next value of the previous one */
|
||||
++i;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
158
raid/combo.h
Normal file
158
raid/combo.h
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __COMBO_H
|
||||
#define __COMBO_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* Get the first permutation with repetition of r of n elements.
|
||||
*
|
||||
* Typical use is with permutation_next() in the form :
|
||||
*
|
||||
* int i[R];
|
||||
* permutation_first(R, N, i);
|
||||
* do {
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
* } while (permutation_next(R, N, i));
|
||||
*
|
||||
* It's equivalent at the code :
|
||||
*
|
||||
* for(i[0]=0;i[0]<N;++i[0])
|
||||
* for(i[1]=0;i[1]<N;++i[1])
|
||||
* ...
|
||||
* for(i[R-2]=0;i[R-2]<N;++i[R-2])
|
||||
* for(i[R-1]=0;i[R-1]<N;++i[R-1])
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
*/
|
||||
static inline void permutation_first(int r, int n, int *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)n; /* unused, but kept for clarity */
|
||||
assert(0 < r && r <= n);
|
||||
|
||||
for (i = 0; i < r; ++i)
|
||||
c[i] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next permutation with repetition of r of n elements.
|
||||
* Return ==0 when finished.
|
||||
*/
|
||||
static inline int permutation_next(int r, int n, int *c)
|
||||
{
|
||||
int i = r - 1; /* present position */
|
||||
|
||||
recurse:
|
||||
/* next element at position i */
|
||||
++c[i];
|
||||
|
||||
/* if the position has reached the max */
|
||||
if (c[i] >= n) {
|
||||
|
||||
/* if we are at the first level, we have finished */
|
||||
if (i == 0)
|
||||
return 0;
|
||||
|
||||
/* increase the previous position */
|
||||
--i;
|
||||
goto recurse;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
/* initialize all the next positions, if any */
|
||||
while (i < r) {
|
||||
c[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first combination without repetition of r of n elements.
|
||||
*
|
||||
* Typical use is with combination_next() in the form :
|
||||
*
|
||||
* int i[R];
|
||||
* combination_first(R, N, i);
|
||||
* do {
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
* } while (combination_next(R, N, i));
|
||||
*
|
||||
* It's equivalent at the code :
|
||||
*
|
||||
* for(i[0]=0;i[0]<N-(R-1);++i[0])
|
||||
* for(i[1]=i[0]+1;i[1]<N-(R-2);++i[1])
|
||||
* ...
|
||||
* for(i[R-2]=i[R-3]+1;i[R-2]<N-1;++i[R-2])
|
||||
* for(i[R-1]=i[R-2]+1;i[R-1]<N;++i[R-1])
|
||||
* code using i[0], i[1], ..., i[R-1]
|
||||
*/
|
||||
static inline void combination_first(int r, int n, int *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)n; /* unused, but kept for clarity */
|
||||
assert(0 < r && r <= n);
|
||||
|
||||
for (i = 0; i < r; ++i)
|
||||
c[i] = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next combination without repetition of r of n elements.
|
||||
* Return ==0 when finished.
|
||||
*/
|
||||
static inline int combination_next(int r, int n, int *c)
|
||||
{
|
||||
int i = r - 1; /* present position */
|
||||
int h = n; /* high limit for this position */
|
||||
|
||||
recurse:
|
||||
/* next element at position i */
|
||||
++c[i];
|
||||
|
||||
/* if the position has reached the max */
|
||||
if (c[i] >= h) {
|
||||
|
||||
/* if we are at the first level, we have finished */
|
||||
if (i == 0)
|
||||
return 0;
|
||||
|
||||
/* increase the previous position */
|
||||
--i;
|
||||
--h;
|
||||
goto recurse;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
/* initialize all the next positions, if any */
|
||||
while (i < r) {
|
||||
/* each position start at the next value of the previous one */
|
||||
c[i] = c[i-1] + 1;
|
||||
++i;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -24,12 +24,6 @@
|
|||
* Basic range checks are implemented using BUG_ON().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic assert() with inverted meaning.
|
||||
*/
|
||||
#define BUG_ON(a) assert(!(a))
|
||||
|
||||
|
||||
/*
|
||||
* GF a*b.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ void raid_rec1_int8(int nr, const int *id, const int *ip, int nd, size_t size, v
|
|||
|
||||
(void)nr; /* unused, it's always 1 */
|
||||
|
||||
/* if it's RAID5 uses the dedicated and faster function */
|
||||
/* if it's RAID5 uses the faster function */
|
||||
if (ip[0] == 0) {
|
||||
raid_rec1_par1(id, nd, size, vv);
|
||||
return;
|
||||
|
|
@ -459,7 +459,7 @@ void raid_rec2_int8(int nr, const int *id, const int *ip, int nd, size_t size, v
|
|||
|
||||
(void)nr; /* unused, it's always 2 */
|
||||
|
||||
/* if it's RAID6 recovering with P and Q uses the dedicated and faster function */
|
||||
/* if it's RAID6 recovering with P and Q uses the faster function */
|
||||
if (ip[0] == 0 && ip[1] == 1) {
|
||||
raid_rec2_par2(id, ip, nd, size, vv);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,15 @@
|
|||
#ifndef __RAID_INTERNAL_H
|
||||
#define __RAID_INTERNAL_H
|
||||
|
||||
/*
|
||||
* Includes anything required for compatibility.
|
||||
*/
|
||||
#include "../portable.h"
|
||||
#define BUG_ON(a) assert(!(a))
|
||||
|
||||
/*
|
||||
* Include the main header.
|
||||
*/
|
||||
#include "raid.h"
|
||||
|
||||
/*
|
||||
|
|
|
|||
125
raid/memory.c
Normal file
125
raid/memory.c
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "memory.h"
|
||||
|
||||
void *raid_malloc_align(size_t size, void **freeptr)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
uintptr_t offset;
|
||||
|
||||
ptr = malloc(size + RAID_MALLOC_ALIGN);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
*freeptr = ptr;
|
||||
|
||||
offset = ((uintptr_t)ptr) % RAID_MALLOC_ALIGN;
|
||||
|
||||
if (offset != 0)
|
||||
ptr += RAID_MALLOC_ALIGN - offset;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr)
|
||||
{
|
||||
void **v;
|
||||
unsigned char *va;
|
||||
size_t i;
|
||||
|
||||
assert(reverse <= count);
|
||||
|
||||
v = malloc(count * sizeof(void *));
|
||||
if (!v)
|
||||
return 0;
|
||||
|
||||
va = raid_malloc_align(count * (size + RAID_MALLOC_DISPLACEMENT), freeptr);
|
||||
if (!va) {
|
||||
free(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
v[i] = va + i * (size + RAID_MALLOC_DISPLACEMENT);
|
||||
|
||||
/* reverse order for the initial ones */
|
||||
for (i = 0; i < reverse/2; ++i) {
|
||||
void *ptr = v[i];
|
||||
v[i] = v[reverse - 1 - i];
|
||||
v[reverse - 1 - i] = ptr;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int raid_mtest_vector(void **vv, size_t count, size_t size)
|
||||
{
|
||||
unsigned char **v = (unsigned char **)vv;
|
||||
size_t i;
|
||||
size_t j;
|
||||
unsigned k;
|
||||
unsigned char d;
|
||||
unsigned char p;
|
||||
|
||||
/* fill with 0 */
|
||||
d = 0;
|
||||
for (i = 0; i < count; ++i)
|
||||
for (j = 0; j < size; ++j)
|
||||
v[i][j] = d;
|
||||
|
||||
/* test with all the byte patterns */
|
||||
for (k = 1; k < 256; ++k) {
|
||||
p = d;
|
||||
d = k;
|
||||
|
||||
/* forward fill */
|
||||
for (i = 0; i < count; ++i) {
|
||||
for (j = 0; j < size; ++j) {
|
||||
if (v[i][j] != p)
|
||||
return -1;
|
||||
v[i][j] = d;
|
||||
}
|
||||
}
|
||||
|
||||
p = d;
|
||||
d = ~p;
|
||||
/* backward fill with complement */
|
||||
for (i = 0; i < count; ++i) {
|
||||
for (j = size; j > 0; --j) {
|
||||
if (v[i][j-1] != p)
|
||||
return -1;
|
||||
v[i][j-1] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void raid_mrand_vector(void **vv, size_t count, size_t size)
|
||||
{
|
||||
unsigned char **v = (unsigned char **)vv;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
for (j = 0; j < size; ++j)
|
||||
v[i][j] = rand();
|
||||
}
|
||||
|
||||
80
raid/memory.h
Normal file
80
raid/memory.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RAID_MEMORY_H
|
||||
#define __RAID_MEMORY_H
|
||||
|
||||
/**
|
||||
* Memory alignment provided by raid_malloc_align().
|
||||
*
|
||||
* It should guarantee good cache performance everywhere.
|
||||
*/
|
||||
#define RAID_MALLOC_ALIGN 256
|
||||
|
||||
/**
|
||||
* Memory displacement to avoid cache collisions on contiguous blocks,
|
||||
* ued by raid_malloc_vector().
|
||||
*
|
||||
* When allocating a sequence of blocks with a size of power of 2,
|
||||
* there is the risk that the start of each block is mapped into the same
|
||||
* cache line, resulting in cache collisions if you access all the blocks
|
||||
* in parallel, from the start to the end.
|
||||
*
|
||||
* The selected value was choosen empirically with some speed tests
|
||||
* with 8/12/16/20/24 data buffers and 3 parity buffers
|
||||
* for RAID-5/6/TP computation.
|
||||
*
|
||||
* With displacement (8 buffers, icore5, 32 bit):
|
||||
*
|
||||
* PAR1 sse2x4 21936 [MB/s]
|
||||
* PAR2 sse2x2 11902 [MB/s]
|
||||
* PARz sse2x1 5838 [MB/s]
|
||||
*
|
||||
* Without displacement:
|
||||
*
|
||||
* PAR1 sse2x4 15368 [MB/s]
|
||||
* PAR2 sse2x2 6814 [MB/s]
|
||||
* PARz sse2x1 3033 [MB/s]
|
||||
*/
|
||||
#define RAID_MALLOC_DISPLACEMENT (7*256)
|
||||
|
||||
/**
|
||||
* Aligned malloc.
|
||||
*/
|
||||
void *raid_malloc_align(size_t size, void **freeptr);
|
||||
|
||||
/**
|
||||
* Aligned vector allocation.
|
||||
* Returns a vector of "count" pointers, each one pointing to a block of the
|
||||
* specified "size".
|
||||
* The first "reverse" pointers are put in reverse memory offset order.
|
||||
*/
|
||||
void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr);
|
||||
|
||||
/**
|
||||
* Tests the memory vector for RAM problems.
|
||||
* If a problem is found, it crashes.
|
||||
*/
|
||||
int raid_mtest_vector(void **vv, size_t count, size_t size);
|
||||
|
||||
/**
|
||||
* Fills the memory vector with random data.
|
||||
*/
|
||||
void raid_mrand_vector(void **vv, size_t count, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
/**
|
||||
* Maximum number of data disks.
|
||||
* Limit of the parity generator matrix used.
|
||||
*/
|
||||
#define RAID_DATA_MAX 251
|
||||
|
||||
|
|
|
|||
331
raid/test.c
Normal file
331
raid/test.c
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "cpu.h"
|
||||
#include "combo.h"
|
||||
#include "memory.h"
|
||||
|
||||
/**
|
||||
* Binomial coefficient of n over r.
|
||||
*/
|
||||
static int ibc(int n, int r)
|
||||
{
|
||||
if (r == 0 || n == r)
|
||||
return 1;
|
||||
else
|
||||
return ibc(n - 1, r - 1) + ibc(n - 1, r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Power n ^ r;
|
||||
*/
|
||||
static int ipow(int n, int r)
|
||||
{
|
||||
int v = 1;
|
||||
while (r) {
|
||||
v *= n;
|
||||
--r;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int raid_test_combo(void)
|
||||
{
|
||||
int r;
|
||||
int count;
|
||||
int p[RAID_PARITY_MAX];
|
||||
|
||||
for (r = 1; r <= RAID_PARITY_MAX; ++r) {
|
||||
/* count combination (r of RAID_PARITY_MAX) elements */
|
||||
count = 0;
|
||||
combination_first(r, RAID_PARITY_MAX, p);
|
||||
|
||||
do {
|
||||
++count;
|
||||
} while (combination_next(r, RAID_PARITY_MAX, p));
|
||||
|
||||
if (count != ibc(RAID_PARITY_MAX, r))
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (r = 1; r <= RAID_PARITY_MAX; ++r) {
|
||||
/* count permutation (r of RAID_PARITY_MAX) elements */
|
||||
count = 0;
|
||||
permutation_first(r, RAID_PARITY_MAX, p);
|
||||
|
||||
do {
|
||||
++count;
|
||||
} while (permutation_next(r, RAID_PARITY_MAX, p));
|
||||
|
||||
if (count != ipow(RAID_PARITY_MAX, r))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int raid_test_sort(void)
|
||||
{
|
||||
int p[RAID_PARITY_MAX];
|
||||
int r;
|
||||
|
||||
for (r = 1; r <= RAID_PARITY_MAX; ++r) {
|
||||
permutation_first(r, RAID_PARITY_MAX, p);
|
||||
do {
|
||||
int i[RAID_PARITY_MAX];
|
||||
int j;
|
||||
|
||||
/* make a copy */
|
||||
for (j = 0; j < r; ++j)
|
||||
i[j] = p[j];
|
||||
|
||||
raid_sort(r, i);
|
||||
|
||||
/* check order */
|
||||
for (j = 1; j < r; ++j)
|
||||
if (i[j-1] > i[j])
|
||||
return -1;
|
||||
} while (permutation_next(r, RAID_PARITY_MAX, p));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int raid_test_rec(int mode, int nd, size_t size)
|
||||
{
|
||||
void *buffer_alloc;
|
||||
void **buffer;
|
||||
void **data;
|
||||
void **parity;
|
||||
void **test;
|
||||
void *data_save[RAID_PARITY_MAX];
|
||||
void *parity_save[RAID_PARITY_MAX];
|
||||
void *zero;
|
||||
void *waste;
|
||||
int buffermax;
|
||||
int id[RAID_PARITY_MAX];
|
||||
int ip[RAID_PARITY_MAX];
|
||||
int i;
|
||||
int j;
|
||||
int nr;
|
||||
void (*map[RAID_PARITY_MAX][4])(int nr, const int *id, const int *ip, int nd, size_t size, void **vbuf);
|
||||
int mac[RAID_PARITY_MAX];
|
||||
int np;
|
||||
|
||||
raid_mode(mode);
|
||||
if (mode == RAID_MODE_CAUCHY)
|
||||
np = RAID_PARITY_MAX;
|
||||
else
|
||||
np = 3;
|
||||
|
||||
buffermax = nd + np * 2 + 2;
|
||||
|
||||
buffer = raid_malloc_vector(nd, buffermax, size, &buffer_alloc);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
data = buffer;
|
||||
parity = buffer + nd;
|
||||
test = buffer + nd + np;
|
||||
|
||||
for (i = 0; i < np; ++i)
|
||||
parity_save[i] = parity[i];
|
||||
|
||||
zero = buffer[buffermax-2];
|
||||
memset(zero, 0, size);
|
||||
raid_zero(zero);
|
||||
|
||||
waste = buffer[buffermax-1];
|
||||
|
||||
/* fill data disk with random */
|
||||
raid_mrand_vector(buffer, nd, size);
|
||||
|
||||
/* setup recov functions */
|
||||
for (i = 0; i < np; ++i) {
|
||||
mac[i] = 0;
|
||||
if (i == 0) {
|
||||
map[i][mac[i]++] = raid_rec1_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3())
|
||||
map[i][mac[i]++] = raid_rec1_ssse3;
|
||||
#endif
|
||||
} else if (i == 1) {
|
||||
map[i][mac[i]++] = raid_rec2_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3())
|
||||
map[i][mac[i]++] = raid_rec2_ssse3;
|
||||
#endif
|
||||
} else {
|
||||
map[i][mac[i]++] = raid_recX_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3())
|
||||
map[i][mac[i]++] = raid_recX_ssse3;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_par(nd, np, size, buffer);
|
||||
|
||||
/* set all the parity to the waste buffer */
|
||||
for (i = 0; i < np; ++i)
|
||||
parity[i] = waste;
|
||||
|
||||
/* all parity levels */
|
||||
for (nr = 1; nr <= np; ++nr) {
|
||||
/* all combinations (nr of nd) disks */
|
||||
combination_first(nr, nd, id);
|
||||
do {
|
||||
/* all combinations (nr of np) parities */
|
||||
combination_first(nr, np, ip);
|
||||
do {
|
||||
/* for each recover function */
|
||||
for (j = 0; j < mac[nr-1]; ++j) {
|
||||
/* set */
|
||||
for (i = 0; i < nr; ++i) {
|
||||
/* remove the missing data */
|
||||
data_save[i] = data[id[i]];
|
||||
data[id[i]] = test[i];
|
||||
/* set the parity to use */
|
||||
parity[ip[i]] = parity_save[ip[i]];
|
||||
}
|
||||
|
||||
/* recover */
|
||||
map[nr-1][j](nr, id, ip, nd, size, buffer);
|
||||
|
||||
/* check */
|
||||
for (i = 0; i < nr; ++i)
|
||||
if (memcmp(test[i], data_save[i], size) != 0)
|
||||
return -1;
|
||||
|
||||
/* restore */
|
||||
for (i = 0; i < nr; ++i) {
|
||||
/* restore the data */
|
||||
data[id[i]] = data_save[i];
|
||||
/* restore the parity */
|
||||
parity[ip[i]] = waste;
|
||||
}
|
||||
}
|
||||
} while (combination_next(nr, np, ip));
|
||||
} while (combination_next(nr, nd, id));
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int raid_test_par(int mode, int nd, size_t size)
|
||||
{
|
||||
void *buffer_alloc;
|
||||
void **buffer;
|
||||
int buffermax;
|
||||
int i, j;
|
||||
void (*map[64])(int nd, size_t size, void **vbuf);
|
||||
int mac;
|
||||
int np;
|
||||
|
||||
raid_mode(mode);
|
||||
if (mode == RAID_MODE_CAUCHY)
|
||||
np = RAID_PARITY_MAX;
|
||||
else
|
||||
np = 3;
|
||||
|
||||
buffermax = nd + np * 2;
|
||||
|
||||
buffer = raid_malloc_vector(nd, buffermax, size, &buffer_alloc);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
/* fill with random */
|
||||
raid_mrand_vector(buffer, buffermax, size);
|
||||
|
||||
/* compute the parity */
|
||||
raid_par(nd, np, size, buffer);
|
||||
|
||||
/* copy in back buffers */
|
||||
for (i = 0; i < np; ++i)
|
||||
memcpy(buffer[nd + np + i], buffer[nd + i], size);
|
||||
|
||||
/* load all the available functions */
|
||||
mac = 0;
|
||||
|
||||
map[mac++] = raid_par1_int32;
|
||||
map[mac++] = raid_par1_int64;
|
||||
map[mac++] = raid_par2_int32;
|
||||
map[mac++] = raid_par2_int64;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_sse2()) {
|
||||
map[mac++] = raid_par1_sse2;
|
||||
map[mac++] = raid_par2_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_par2_sse2ext;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mode == RAID_MODE_CAUCHY) {
|
||||
map[mac++] = raid_par3_int8;
|
||||
map[mac++] = raid_par4_int8;
|
||||
map[mac++] = raid_par5_int8;
|
||||
map[mac++] = raid_par6_int8;
|
||||
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
map[mac++] = raid_par3_ssse3;
|
||||
map[mac++] = raid_par4_ssse3;
|
||||
map[mac++] = raid_par5_ssse3;
|
||||
map[mac++] = raid_par6_ssse3;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_par3_ssse3ext;
|
||||
map[mac++] = raid_par4_ssse3ext;
|
||||
map[mac++] = raid_par5_ssse3ext;
|
||||
map[mac++] = raid_par6_ssse3ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
map[mac++] = raid_parz_int32;
|
||||
map[mac++] = raid_parz_int64;
|
||||
if (raid_cpu_has_sse2()) {
|
||||
map[mac++] = raid_parz_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_parz_sse2ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check all the functions */
|
||||
for (j = 0; j < mac; ++j) {
|
||||
/* compute parity */
|
||||
map[j](nd, size, buffer);
|
||||
|
||||
/* check it */
|
||||
for (i = 0; i < np; ++i)
|
||||
if (memcmp(buffer[nd + np + i], buffer[nd + i], size) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
62
raid/test.h
Normal file
62
raid/test.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RAID_TEST_H
|
||||
#define __RAID_TEST_H
|
||||
|
||||
/**
|
||||
* Tests sorting functions.
|
||||
*
|
||||
* Test raid_sort() with all the possible combinations of elements to sort.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int raid_test_sort(void);
|
||||
|
||||
/**
|
||||
* Tests combinations functions.
|
||||
*
|
||||
* Tests combination_first() and combination_next() for all the parity levels.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int raid_test_combo(void);
|
||||
|
||||
/**
|
||||
* Tests recovering functions.
|
||||
*
|
||||
* All the recovering functions are tested with all the combinations
|
||||
* of failing disks and recovering parities.
|
||||
*
|
||||
* Take care that the test time grows exponentially with the number of disks.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int raid_test_rec(unsigned mode, int nd, size_t size);
|
||||
|
||||
/**
|
||||
* Tests parity generation functions.
|
||||
*
|
||||
* All the parity generation functions are tested with the specified
|
||||
* number of disks.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int raid_test_par(unsigned mode, int nd, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1338,7 +1338,7 @@ void raid_rec1_ssse3(int nr, const int *id, const int *ip, int nd, size_t size,
|
|||
|
||||
(void)nr; /* unused, it's always 1 */
|
||||
|
||||
/* if it's RAID5 uses the dedicated and faster function */
|
||||
/* if it's RAID5 uses the faster function */
|
||||
if (ip[0] == 0) {
|
||||
raid_rec1_par1(id, nd, size, vv);
|
||||
return;
|
||||
|
|
|
|||
306
selftest.c
306
selftest.c
|
|
@ -21,10 +21,11 @@
|
|||
#include "util.h"
|
||||
#include "raid/raid.h"
|
||||
#include "raid/cpu.h"
|
||||
#include "raid/combo.h"
|
||||
#include "raid/internal.h"
|
||||
#include "raid/test.h"
|
||||
#include "elem.h"
|
||||
#include "state.h"
|
||||
#include "combo.h"
|
||||
|
||||
struct hash_test_vector {
|
||||
const char* data;
|
||||
|
|
@ -48,268 +49,9 @@ static struct hash_test_vector TEST_SPOOKY2[] = {
|
|||
{ 0, 0, { 0 } }
|
||||
};
|
||||
|
||||
/**
|
||||
* Binomial coefficient of n over r.
|
||||
*/
|
||||
static unsigned bc(unsigned n, unsigned r)
|
||||
{
|
||||
if (r == 0 || n == r)
|
||||
return 1;
|
||||
else
|
||||
return bc(n - 1, r - 1) + bc(n - 1, r);
|
||||
}
|
||||
|
||||
static void combotest(void)
|
||||
{
|
||||
unsigned r;
|
||||
unsigned count;
|
||||
int p[LEV_MAX];
|
||||
|
||||
/* all parities */
|
||||
for(r=1;r<=LEV_MAX;++r) {
|
||||
/* count combination (r of LEV_MAX) parities */
|
||||
count = 0;
|
||||
combination_first(r, LEV_MAX, p);
|
||||
do {
|
||||
++count;
|
||||
} while (combination_next(r, LEV_MAX, p));
|
||||
|
||||
if (count != bc(LEV_MAX, r)) {
|
||||
fprintf(stderr, "Failed COMBO test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void recovtest(unsigned mode, unsigned nd, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
void** buffer;
|
||||
void** data;
|
||||
void** parity;
|
||||
void** test;
|
||||
void* data_save[LEV_MAX];
|
||||
void* parity_save[LEV_MAX];
|
||||
void* zero;
|
||||
void* waste;
|
||||
unsigned buffermax;
|
||||
int id[LEV_MAX];
|
||||
int ip[LEV_MAX];
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
unsigned nr;
|
||||
void (*map[LEV_MAX][4])(int nr, const int* id, const int* ip, int nd, size_t size, void** vbuf);
|
||||
unsigned mac[LEV_MAX];
|
||||
unsigned np;
|
||||
|
||||
raid_mode(mode);
|
||||
if (mode == RAID_MODE_CAUCHY)
|
||||
np = RAID_PARITY_MAX;
|
||||
else
|
||||
np = 3;
|
||||
|
||||
buffermax = nd + np * 2 + 2;
|
||||
|
||||
buffer = malloc_nofail_vector_align(nd, buffermax, block_size, &buffer_alloc);
|
||||
mtest_vector(buffer, buffermax, block_size);
|
||||
|
||||
data = buffer;
|
||||
parity = buffer + nd;
|
||||
test = buffer + nd + np;
|
||||
|
||||
for(i=0;i<np;++i)
|
||||
parity_save[i] = parity[i];
|
||||
|
||||
zero = buffer[buffermax-2];
|
||||
memset(zero, 0, block_size);
|
||||
raid_zero(zero);
|
||||
|
||||
waste = buffer[buffermax-1];
|
||||
|
||||
/* fill data disk with random */
|
||||
mrand_vector(buffer, nd, block_size);
|
||||
|
||||
/* setup recov functions */
|
||||
for(i=0;i<np;++i) {
|
||||
mac[i] = 0;
|
||||
if (i == 0) {
|
||||
map[i][mac[i]++] = raid_rec1_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_rec1_ssse3;
|
||||
}
|
||||
#endif
|
||||
} else if (i == 1) {
|
||||
map[i][mac[i]++] = raid_rec2_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_rec2_ssse3;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
map[i][mac[i]++] = raid_recX_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_recX_ssse3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_par(nd, np, block_size, buffer);
|
||||
|
||||
/* set all the parity to the waste buffer */
|
||||
for(i=0;i<np;++i)
|
||||
parity[i] = waste;
|
||||
|
||||
/* all parity levels */
|
||||
for(nr=1;nr<=np;++nr) {
|
||||
/* all combinations (nr of nd) disks */
|
||||
combination_first(nr, nd, id);
|
||||
do {
|
||||
/* all combinations (nr of np) parities */
|
||||
combination_first(nr, np, ip);
|
||||
do {
|
||||
/* for each recover function */
|
||||
for(j=0;j<mac[nr-1];++j) {
|
||||
/* set */
|
||||
for(i=0;i<nr;++i) {
|
||||
/* remove the missing data */
|
||||
data_save[i] = data[id[i]];
|
||||
data[id[i]] = test[i];
|
||||
/* set the parity to use */
|
||||
parity[ip[i]] = parity_save[ip[i]];
|
||||
}
|
||||
|
||||
/* recover */
|
||||
map[nr-1][j](nr, id, ip, nd, block_size, buffer);
|
||||
|
||||
/* check */
|
||||
for(i=0;i<nr;++i) {
|
||||
if (memcmp(test[i], data_save[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RECOV test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* restore */
|
||||
for(i=0;i<nr;++i) {
|
||||
/* restore the data */
|
||||
data[id[i]] = data_save[i];
|
||||
/* restore the parity */
|
||||
parity[ip[i]] = waste;
|
||||
}
|
||||
}
|
||||
} while (combination_next(nr, np, ip));
|
||||
} while (combination_next(nr, nd, id));
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void gentest(unsigned mode, unsigned nd, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
void** buffer;
|
||||
unsigned buffermax;
|
||||
unsigned i, j;
|
||||
void (*map[64])(int nd, size_t size, void** vbuf);
|
||||
unsigned mac;
|
||||
unsigned np;
|
||||
|
||||
raid_mode(mode);
|
||||
if (mode == RAID_MODE_CAUCHY)
|
||||
np = RAID_PARITY_MAX;
|
||||
else
|
||||
np = 3;
|
||||
|
||||
buffermax = nd + np * 2;
|
||||
|
||||
buffer = malloc_nofail_vector_align(nd, buffermax, block_size, &buffer_alloc);
|
||||
mtest_vector(buffer, buffermax, block_size);
|
||||
|
||||
/* fill with random */
|
||||
mrand_vector(buffer, buffermax, block_size);
|
||||
|
||||
/* compute the parity */
|
||||
raid_par(nd, np, block_size, buffer);
|
||||
|
||||
/* copy in back buffers */
|
||||
for(i=0;i<np;++i)
|
||||
memcpy(buffer[nd + np + i], buffer[nd + i], block_size);
|
||||
|
||||
/* load all the available functions */
|
||||
mac = 0;
|
||||
|
||||
map[mac++] = raid_par1_int32;
|
||||
map[mac++] = raid_par1_int64;
|
||||
map[mac++] = raid_par2_int32;
|
||||
map[mac++] = raid_par2_int64;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_sse2()) {
|
||||
map[mac++] = raid_par1_sse2;
|
||||
map[mac++] = raid_par2_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_par2_sse2ext;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mode == RAID_MODE_CAUCHY) {
|
||||
map[mac++] = raid_par3_int8;
|
||||
map[mac++] = raid_par4_int8;
|
||||
map[mac++] = raid_par5_int8;
|
||||
map[mac++] = raid_par6_int8;
|
||||
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
map[mac++] = raid_par3_ssse3;
|
||||
map[mac++] = raid_par4_ssse3;
|
||||
map[mac++] = raid_par5_ssse3;
|
||||
map[mac++] = raid_par6_ssse3;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_par3_ssse3ext;
|
||||
map[mac++] = raid_par4_ssse3ext;
|
||||
map[mac++] = raid_par5_ssse3ext;
|
||||
map[mac++] = raid_par6_ssse3ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
map[mac++] = raid_parz_int32;
|
||||
map[mac++] = raid_parz_int64;
|
||||
if (raid_cpu_has_sse2()) {
|
||||
map[mac++] = raid_parz_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid_parz_sse2ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check all the functions */
|
||||
for(j=0;j<mac;++j) {
|
||||
/* compute parity */
|
||||
map[j](nd, block_size, buffer);
|
||||
|
||||
/* check it */
|
||||
for(i=0;i<np;++i) {
|
||||
if (memcmp(buffer[nd + np + i], buffer[nd + i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed GEN test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
#define HASH_TEST_MAX 512 /* tests are never longer than 512 bytes */
|
||||
|
||||
static void hashtest(void)
|
||||
static void test_hash(void)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned char* seed_aligned;
|
||||
|
|
@ -391,7 +133,7 @@ static struct crc_test_vector TEST_CRC32C[] = {
|
|||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void crc32ctest(void)
|
||||
static void test_crc32c(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
|
@ -405,7 +147,7 @@ static void crc32ctest(void)
|
|||
}
|
||||
}
|
||||
|
||||
void selftest()
|
||||
void selftest(void)
|
||||
{
|
||||
fprintf(stdlog, "selftest:\n");
|
||||
fflush(stdlog);
|
||||
|
|
@ -418,13 +160,35 @@ void selftest()
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
hashtest();
|
||||
crc32ctest();
|
||||
combotest();
|
||||
gentest(RAID_MODE_VANDERMONDE, 32, 256);
|
||||
recovtest(RAID_MODE_VANDERMONDE, 12, 256);
|
||||
gentest(RAID_MODE_CAUCHY, 32, 256);
|
||||
recovtest(RAID_MODE_CAUCHY, 12, 256);
|
||||
gentest(RAID_MODE_CAUCHY, 1, 256);
|
||||
test_hash();
|
||||
test_crc32c();
|
||||
if (raid_test_sort() != 0) {
|
||||
fprintf(stderr, "Failed SORT test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_combo() != 0) {
|
||||
fprintf(stderr, "Failed COMBO test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) {
|
||||
fprintf(stderr, "Failed PAR Vandermonde test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) {
|
||||
fprintf(stderr, "Failed REC Vandermonde test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) {
|
||||
fprintf(stderr, "Failed PAR Cauchy test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) {
|
||||
fprintf(stderr, "Failed REC Cauchy test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) {
|
||||
fprintf(stderr, "Failed PAR Cauchy test sigle data disk\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
189
speed.c
189
speed.c
|
|
@ -27,9 +27,14 @@
|
|||
/**
|
||||
* Differential us of two timeval.
|
||||
*/
|
||||
static int64_t diffgettimeofday(struct timeval* start, struct timeval* stop)
|
||||
static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop)
|
||||
{
|
||||
return 1000000LL * (stop->tv_sec - start->tv_sec) + stop->tv_usec - start->tv_usec;
|
||||
int64_t d;
|
||||
|
||||
d = 1000000LL * (stop->tv_sec - start->tv_sec);
|
||||
d += stop->tv_usec - start->tv_usec;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,7 +53,7 @@ static int64_t diffgettimeofday(struct timeval* start, struct timeval* stop)
|
|||
count += delta; \
|
||||
gettimeofday(&stop, 0); \
|
||||
} while (diffgettimeofday(&start, &stop) < 1000000LL); \
|
||||
ds = block_size * (int64_t)count * nd; \
|
||||
ds = size * (int64_t)count * nd; \
|
||||
dt = diffgettimeofday(&start, &stop);
|
||||
|
||||
void speed(void)
|
||||
|
|
@ -57,40 +62,37 @@ void speed(void)
|
|||
struct timeval stop;
|
||||
int64_t ds;
|
||||
int64_t dt;
|
||||
unsigned i, j;
|
||||
int i, j;
|
||||
unsigned char digest[HASH_SIZE];
|
||||
unsigned char seed[HASH_SIZE];
|
||||
int id[LEV_MAX];
|
||||
int ip[LEV_MAX];
|
||||
unsigned count;
|
||||
unsigned delta = 10;
|
||||
unsigned block_size = 256 * 1024;
|
||||
unsigned nd = 8;
|
||||
unsigned buffermax;
|
||||
void* buffer_alloc;
|
||||
void** buffer;
|
||||
int count;
|
||||
int delta = 10;
|
||||
int size = 256 * 1024;
|
||||
int nd = 8;
|
||||
int buffermax;
|
||||
void* v_alloc;
|
||||
void** v;
|
||||
void* zero;
|
||||
|
||||
/* we need disk + 1 for each parity buffers + 1 zero buffer */
|
||||
/* we need disk + 1 for each parity buffers + 1 zero v */
|
||||
buffermax = nd + LEV_MAX + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(nd, buffermax, block_size, &buffer_alloc);
|
||||
mtest_vector(buffer, buffermax, block_size);
|
||||
v = malloc_nofail_vector_align(nd, buffermax, size, &v_alloc);
|
||||
|
||||
/* initialize disks with fixed data */
|
||||
for(i=0;i<nd;++i) {
|
||||
memset(buffer[i], i, block_size);
|
||||
}
|
||||
for(i=0;i<nd;++i)
|
||||
memset(v[i], i, size);
|
||||
|
||||
/* zero buffer */
|
||||
zero = buffer[nd+LEV_MAX];
|
||||
memset(zero, 0, block_size);
|
||||
/* zero v */
|
||||
zero = v[nd+LEV_MAX];
|
||||
memset(zero, 0, size);
|
||||
raid_zero(zero);
|
||||
|
||||
/* hash seed */
|
||||
for(i=0;i<HASH_SIZE;++i) {
|
||||
for(i=0;i<HASH_SIZE;++i)
|
||||
seed[i] = i;
|
||||
}
|
||||
|
||||
/* basic disks and parity mapping */
|
||||
for(i=0;i<LEV_MAX;++i) {
|
||||
|
|
@ -127,9 +129,9 @@ void speed(void)
|
|||
printf("CPU is not a x86/x64\n");
|
||||
#endif
|
||||
#if WORDS_BIGENDIAN
|
||||
printf("Memory is big-endian %u-bit\n", (unsigned)sizeof(void*) * 8);
|
||||
printf("Memory is big-endian %d-bit\n", (int)sizeof(void*) * 8);
|
||||
#else
|
||||
printf("Memory is little-endian %u-bit\n", (unsigned)sizeof(void*) * 8);
|
||||
printf("Memory is little-endian %d-bit\n", (int)sizeof(void*) * 8);
|
||||
#endif
|
||||
|
||||
#if HAVE_FUTIMENS
|
||||
|
|
@ -144,8 +146,8 @@ void speed(void)
|
|||
|
||||
printf("\n");
|
||||
|
||||
printf("Speed test using %u buffers of %u bytes, for a total of %u KiB.\n", nd, block_size, nd * block_size / 1024);
|
||||
printf("The reported value is the sustainable aggregate bandwidth of all data disks in MiB/s (not counting parity disks).\n");
|
||||
printf("Speed test using %u data buffers of %u bytes, for a total of %u KiB.\n", nd, size, nd * size / 1024);
|
||||
printf("The reported value is the aggregate bandwidth of all data disks in MiB/s (not counting parity disks).\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Memory write speed using the C memset() function:\n");
|
||||
|
|
@ -153,9 +155,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
memset(buffer[j], j, block_size);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
memset(v[j], j, size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -169,9 +170,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
crc32c_gen(0, buffer[j], block_size);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
crc32c_gen(0, v[j], size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -183,9 +183,8 @@ void speed(void)
|
|||
#if HAVE_CRC32B
|
||||
if (raid_cpu_has_sse42()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
crc32c_x86(0, buffer[j], block_size);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
crc32c_x86(0, v[j], size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -218,18 +217,16 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
memhash(HASH_MURMUR3, seed, digest, buffer[j], block_size);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
memhash(HASH_MURMUR3, seed, digest, v[j], size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
memhash(HASH_SPOOKY2, seed, digest, buffer[j], block_size);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
memhash(HASH_SPOOKY2, seed, digest, v[j], size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -263,14 +260,14 @@ void speed(void)
|
|||
printf("%8s", "");
|
||||
|
||||
SPEED_START {
|
||||
raid_par1_int32(nd, block_size, buffer);
|
||||
raid_par1_int32(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par1_int64(nd, block_size, buffer);
|
||||
raid_par1_int64(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -279,7 +276,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_sse2()) {
|
||||
SPEED_START {
|
||||
raid_par1_sse2(nd, block_size, buffer);
|
||||
raid_par1_sse2(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -296,14 +293,14 @@ void speed(void)
|
|||
printf("%8s", "");
|
||||
|
||||
SPEED_START {
|
||||
raid_par2_int32(nd, block_size, buffer);
|
||||
raid_par2_int32(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par2_int64(nd, block_size, buffer);
|
||||
raid_par2_int64(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -312,7 +309,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_sse2()) {
|
||||
SPEED_START {
|
||||
raid_par2_sse2(nd, block_size, buffer);
|
||||
raid_par2_sse2(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -320,7 +317,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_par2_sse2ext(nd, block_size, buffer);
|
||||
raid_par2_sse2ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -338,14 +335,14 @@ void speed(void)
|
|||
printf("%8s", "");
|
||||
|
||||
SPEED_START {
|
||||
raid_parz_int32(nd, block_size, buffer);
|
||||
raid_parz_int32(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_parz_int64(nd, block_size, buffer);
|
||||
raid_parz_int64(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -354,7 +351,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_sse2()) {
|
||||
SPEED_START {
|
||||
raid_parz_sse2(nd, block_size, buffer);
|
||||
raid_parz_sse2(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -362,7 +359,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_parz_sse2ext(nd, block_size, buffer);
|
||||
raid_parz_sse2ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -378,7 +375,7 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par3_int8(nd, block_size, buffer);
|
||||
raid_par3_int8(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -398,7 +395,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raid_par3_ssse3(nd, block_size, buffer);
|
||||
raid_par3_ssse3(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -406,7 +403,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_par3_ssse3ext(nd, block_size, buffer);
|
||||
raid_par3_ssse3ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -422,7 +419,7 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par4_int8(nd, block_size, buffer);
|
||||
raid_par4_int8(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -442,7 +439,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raid_par4_ssse3(nd, block_size, buffer);
|
||||
raid_par4_ssse3(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -450,7 +447,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_par4_ssse3ext(nd, block_size, buffer);
|
||||
raid_par4_ssse3ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -466,7 +463,7 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par5_int8(nd, block_size, buffer);
|
||||
raid_par5_int8(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -486,7 +483,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raid_par5_ssse3(nd, block_size, buffer);
|
||||
raid_par5_ssse3(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -494,7 +491,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_par5_ssse3ext(nd, block_size, buffer);
|
||||
raid_par5_ssse3ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -510,7 +507,7 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raid_par6_int8(nd, block_size, buffer);
|
||||
raid_par6_int8(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -530,7 +527,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raid_par6_ssse3(nd, block_size, buffer);
|
||||
raid_par6_ssse3(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -538,7 +535,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raid_par6_ssse3ext(nd, block_size, buffer);
|
||||
raid_par6_ssse3ext(nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -562,10 +559,9 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
for(j=0;j<nd;++j)
|
||||
/* +1 to avoid PAR1 optimized case */
|
||||
raid_rec1_int8(1, id, ip + 1, nd, block_size, buffer);
|
||||
}
|
||||
raid_rec1_int8(1, id, ip + 1, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -574,10 +570,9 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
for(j=0;j<nd;++j)
|
||||
/* +1 to avoid PAR1 optimized case */
|
||||
raid_rec1_ssse3(1, id, ip + 1, nd, block_size, buffer);
|
||||
}
|
||||
raid_rec1_ssse3(1, id, ip + 1, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -590,10 +585,9 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
for(j=0;j<nd;++j)
|
||||
/* +1 to avoid PAR2 optimized case */
|
||||
raid_rec2_int8(2, id, ip + 1, nd, block_size, buffer);
|
||||
}
|
||||
raid_rec2_int8(2, id, ip + 1, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -602,10 +596,9 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
for(j=0;j<nd;++j)
|
||||
/* +1 to avoid PAR2 optimized case */
|
||||
raid_rec2_ssse3(2, id, ip + 1, nd, block_size, buffer);
|
||||
}
|
||||
raid_rec2_ssse3(2, id, ip + 1, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -618,9 +611,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_int8(3, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_int8(3, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -629,9 +621,8 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_ssse3(3, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_ssse3(3, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -644,9 +635,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_int8(4, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_int8(4, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -655,9 +645,8 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_ssse3(4, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_ssse3(4, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -670,9 +659,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_int8(5, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_int8(5, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -681,9 +669,8 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_ssse3(5, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_ssse3(5, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -696,9 +683,8 @@ void speed(void)
|
|||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_int8(6, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_int8(6, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -707,9 +693,8 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<nd;++j) {
|
||||
raid_recX_ssse3(6, id, ip, nd, block_size, buffer);
|
||||
}
|
||||
for(j=0;j<nd;++j)
|
||||
raid_recX_ssse3(6, id, ip, nd, size, v);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -720,7 +705,7 @@ void speed(void)
|
|||
|
||||
printf("If the 'best' expectations are wrong, please report it in the SnapRAID forum\n\n");
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
free(v_alloc);
|
||||
free(v);
|
||||
}
|
||||
|
||||
|
|
|
|||
186
util.c
186
util.c
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "raid/cpu.h"
|
||||
#include "raid/memory.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* hex conversion table */
|
||||
|
|
@ -1342,143 +1343,6 @@ void* malloc_nofail(size_t size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory alignment provided by malloc_nofail_align().
|
||||
*
|
||||
* It should guarantee good cache performance everywhere.
|
||||
*/
|
||||
#define MALLOC_ALIGN 256
|
||||
|
||||
void* malloc_nofail_align(size_t size, void** freeptr)
|
||||
{
|
||||
unsigned char* ptr = malloc_nofail(size + MALLOC_ALIGN);
|
||||
uintptr_t offset;
|
||||
|
||||
*freeptr = ptr;
|
||||
|
||||
offset = ((uintptr_t)ptr) % MALLOC_ALIGN;
|
||||
|
||||
if (offset != 0) {
|
||||
ptr += MALLOC_ALIGN - offset;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory displacement to avoid cache collisions on contiguous blocks.
|
||||
*
|
||||
* When allocating a sequence of blocks with a size of power of 2,
|
||||
* there is the risk that the start of each block is mapped into the same cache line,
|
||||
* resulting in cache collisions if you access all the blocks in parallel,
|
||||
* from the start to the end.
|
||||
*
|
||||
* The selected value was choosen empirically with some speed tests
|
||||
* with 8/12/16/20/24 data buffers and 3 parity buffers
|
||||
* for RAID-5/6/TP computation.
|
||||
*
|
||||
* With displacement (8 buffers, icore5, 32 bit):
|
||||
*
|
||||
* PAR1 sse2x4 21936 [MB/s]
|
||||
* PAR2 sse2x2 11902 [MB/s]
|
||||
* PARz sse2x1 5838 [MB/s]
|
||||
*
|
||||
* Without displacement:
|
||||
*
|
||||
* PAR1 sse2x4 15368 [MB/s]
|
||||
* PAR2 sse2x2 6814 [MB/s]
|
||||
* PARz sse2x1 3033 [MB/s]
|
||||
*/
|
||||
#define MALLOC_DISPLACEMENT (7*256)
|
||||
|
||||
void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr)
|
||||
{
|
||||
void** buffer;
|
||||
unsigned char* buffer_aligned;
|
||||
size_t i;
|
||||
|
||||
assert(reverse <= count);
|
||||
|
||||
buffer = malloc_nofail(count * sizeof(void*));
|
||||
|
||||
buffer_aligned = malloc_nofail_align(count * (size + MALLOC_DISPLACEMENT), freeptr);
|
||||
|
||||
for(i=0;i<count;++i)
|
||||
buffer[i] = buffer_aligned + i * (size + MALLOC_DISPLACEMENT);
|
||||
|
||||
/* reverse order for the initial ones */
|
||||
for(i=0;i<reverse/2;++i) {
|
||||
void* ptr = buffer[i];
|
||||
buffer[i] = buffer[reverse - 1 - i];
|
||||
buffer[reverse - 1 - i] = ptr;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void mtest_vector(void** vv, size_t count, size_t size)
|
||||
{
|
||||
unsigned char** v = (unsigned char**)vv;
|
||||
size_t i;
|
||||
size_t j;
|
||||
unsigned k;
|
||||
unsigned char d;
|
||||
unsigned char p;
|
||||
|
||||
/* fill with 0 */
|
||||
d = 0;
|
||||
for(i=0;i<count;++i) {
|
||||
for(j=0;j<size;++j) {
|
||||
v[i][j] = d;
|
||||
}
|
||||
}
|
||||
|
||||
/* test with all the byte patterns */
|
||||
for(k=1;k<256;++k) {
|
||||
p = d;
|
||||
d = k;
|
||||
|
||||
/* forward fill */
|
||||
for(i=0;i<count;++i) {
|
||||
for(j=0;j<size;++j) {
|
||||
if (v[i][j] != p)
|
||||
goto fail;
|
||||
v[i][j] = d;
|
||||
}
|
||||
}
|
||||
|
||||
p = d;
|
||||
d = ~p;
|
||||
/* backward fill with complement */
|
||||
for(i=0;i<count;++i) {
|
||||
for(j=size;j>0;--j) {
|
||||
if (v[i][j-1] != p)
|
||||
goto fail;
|
||||
v[i][j-1] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
fprintf(stderr, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
|
||||
fprintf(stderr, "Try running some memory test like http://www.memtest86.com/\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void mrand_vector(void** vv, size_t count, size_t size)
|
||||
{
|
||||
unsigned char** v = (unsigned char**)vv;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
for(i=0;i<count;++i) {
|
||||
for(j=0;j<size;++j)
|
||||
v[i][j] = rand();
|
||||
}
|
||||
}
|
||||
|
||||
char* strdup_nofail(const char* str)
|
||||
{
|
||||
size_t size;
|
||||
|
|
@ -1503,6 +1367,54 @@ char* strdup_nofail(const char* str)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
void* malloc_nofail_align(size_t size, void** freeptr)
|
||||
{
|
||||
void* ptr;
|
||||
|
||||
ptr = raid_malloc_align(size, freeptr);
|
||||
|
||||
if (!ptr) {
|
||||
/* don't use printf to avoid any possible extra allocation */
|
||||
if (write(2, "Low Memory\n", 11) != 11) {
|
||||
/* ignore error */
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr)
|
||||
{
|
||||
void* ptr;
|
||||
|
||||
ptr = raid_malloc_vector(reverse, count, size, freeptr);
|
||||
|
||||
if (!ptr) {
|
||||
/* don't use printf to avoid any possible extra allocation */
|
||||
if (write(2, "Low Memory\n", 11) != 11) {
|
||||
/* ignore error */
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void mtest_vector(void** vv, size_t count, size_t size)
|
||||
{
|
||||
if (raid_mtest_vector(vv, count, size) != 0) {
|
||||
fprintf(stderr, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
|
||||
fprintf(stderr, "Try running some memory test like http://www.memtest86.com/\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void mrand_vector(void** vv, size_t count, size_t size)
|
||||
{
|
||||
raid_mrand_vector(vv, count, size);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* byte operations */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue