diff --git a/Makefile.am b/Makefile.am index 336ec460..4cb80bd2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/check.c b/check.c index 245a8dc5..cea1be3e 100644 --- a/check.c +++ b/check.c @@ -24,7 +24,7 @@ #include "parity.h" #include "handle.h" #include "raid/raid.h" -#include "combo.h" +#include "raid/combo.h" /****************************************************************************/ /* check */ diff --git a/combo.h b/combo.h deleted file mode 100644 index 847daab6..00000000 --- a/combo.h +++ /dev/null @@ -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 . - */ - -#ifndef __COMBO_H -#define __COMBO_H - -#include - -/** - * 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]= 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 diff --git a/raid/combo.h b/raid/combo.h new file mode 100644 index 00000000..566e191b --- /dev/null +++ b/raid/combo.h @@ -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 . + */ + +#ifndef __COMBO_H +#define __COMBO_H + +#include + +/** + * 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) { + + /* 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]= 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 + diff --git a/raid/gf.h b/raid/gf.h index 7d165ad1..818b9d13 100644 --- a/raid/gf.h +++ b/raid/gf.h @@ -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. */ diff --git a/raid/int.c b/raid/int.c index d15622a5..ab0aa904 100644 --- a/raid/int.c +++ b/raid/int.c @@ -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; diff --git a/raid/internal.h b/raid/internal.h index b86e5064..864f6e95 100644 --- a/raid/internal.h +++ b/raid/internal.h @@ -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" /* diff --git a/raid/memory.c b/raid/memory.c new file mode 100644 index 00000000..e65add7b --- /dev/null +++ b/raid/memory.c @@ -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 . + */ + +#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(); +} + diff --git a/raid/memory.h b/raid/memory.h new file mode 100644 index 00000000..8f44548e --- /dev/null +++ b/raid/memory.h @@ -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 . + */ + +#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 + diff --git a/raid/raid.h b/raid/raid.h index 406f20be..1600fb26 100644 --- a/raid/raid.h +++ b/raid/raid.h @@ -44,7 +44,6 @@ /** * Maximum number of data disks. - * Limit of the parity generator matrix used. */ #define RAID_DATA_MAX 251 diff --git a/raid/test.c b/raid/test.c new file mode 100644 index 00000000..4eb65207 --- /dev/null +++ b/raid/test.c @@ -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 . + */ + +#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; +} + diff --git a/raid/test.h b/raid/test.h new file mode 100644 index 00000000..721c7e5a --- /dev/null +++ b/raid/test.h @@ -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 . + */ + +#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 + diff --git a/raid/x86.c b/raid/x86.c index c0f6ad4e..471ece6d 100644 --- a/raid/x86.c +++ b/raid/x86.c @@ -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; diff --git a/selftest.c b/selftest.c index 34f6d81f..3cf86986 100644 --- a/selftest.c +++ b/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;itv_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;i0;--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