diff --git a/check.c b/check.c index cea1be3e..9ec644aa 100644 --- a/check.c +++ b/check.c @@ -488,7 +488,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); if (!state->opt.skip_self) - mtest_vector(buffer, buffermax, state->block_size); + mtest_vector(buffermax, state->block_size, buffer); /* fill up the zero buffer */ memset(buffer[buffermax-1], 0, state->block_size); diff --git a/raid/memory.c b/raid/memory.c index 0cfceee5..bb49ee1e 100644 --- a/raid/memory.c +++ b/raid/memory.c @@ -34,41 +34,53 @@ void *raid_malloc_align(size_t size, void **freeptr) return ptr; } -void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr) +void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr) { void **v; unsigned char *va; - size_t i; + int i; - assert(reverse <= count); - - v = malloc(count * sizeof(void *)); + v = malloc(n * sizeof(void *)); if (!v) return 0; - va = raid_malloc_align(count * (size + RAID_MALLOC_DISPLACEMENT), freeptr); + va = raid_malloc_align(n * (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); + for (i = 0; i < n; ++i) { + v[i] = va; + va += size + RAID_MALLOC_DISPLACEMENT; + } - /* reverse order for the initial ones */ - for (i = 0; i < reverse/2; ++i) { + /* reverse order of the data blocks */ + /* because they are usually accessed from the last one */ + for (i = 0; i < nd/2; ++i) { void *ptr = v[i]; - v[i] = v[reverse - 1 - i]; - v[reverse - 1 - i] = ptr; + v[i] = v[nd - 1 - i]; + v[nd - 1 - i] = ptr; } return v; } -int raid_mtest_vector(void **vv, size_t count, size_t size) +void raid_mrand_vector(int n, size_t size, void **vv) { unsigned char **v = (unsigned char **)vv; - size_t i; + int i; + size_t j; + + for (i = 0; i < n; ++i) + for (j = 0; j < size; ++j) + v[i][j] = rand(); +} + +int raid_mtest_vector(int n, size_t size, void **vv) +{ + unsigned char **v = (unsigned char **)vv; + int i; size_t j; unsigned k; unsigned char d; @@ -76,7 +88,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size) /* fill with 0 */ d = 0; - for (i = 0; i < count; ++i) + for (i = 0; i < n; ++i) for (j = 0; j < size; ++j) v[i][j] = d; @@ -86,7 +98,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size) d = k; /* forward fill */ - for (i = 0; i < count; ++i) { + for (i = 0; i < n; ++i) { for (j = 0; j < size; ++j) { if (v[i][j] != p) return -1; @@ -97,7 +109,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size) p = d; d = ~p; /* backward fill with complement */ - for (i = 0; i < count; ++i) { + for (i = 0; i < n; ++i) { for (j = size; j > 0; --j) { if (v[i][j-1] != p) return -1; @@ -109,14 +121,3 @@ int raid_mtest_vector(void **vv, size_t count, size_t size) 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 index 3a679709..bea3cc33 100644 --- a/raid/memory.h +++ b/raid/memory.h @@ -28,26 +28,27 @@ * * 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. + * cache line or prefetching prediction, resulting in 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 of 256 KB. * - * With displacement: - * (8 buffers of 256 KB, icore5, 32 bits): + * These are the results with no displacement: * - * sse2 - * par1 21936 [MB/s] - * par2 11902 [MB/s] - * parz 5838 [MB/s] + * sse2 + * par1 15368 [MB/s] + * par2 6814 [MB/s] + * parz 3033 [MB/s] * - * Without displacement: + * These are the results with displacement resulting in improvments + * in the order of 20% or more: + * + * sse2 + * par1 21936 [MB/s] + * par2 11902 [MB/s] + * parz 5838 [MB/s] * - * sse2 - * par1 15368 [MB/s] - * par2 6814 [MB/s] - * parz 3033 [MB/s] */ #define RAID_MALLOC_DISPLACEMENT (7*256) @@ -58,22 +59,22 @@ 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. + * Returns a vector of ::n pointers, each one pointing to a block of + * the specified ::size. + * The first ::nd elements are reversed in order. */ -void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr); +void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr); + +/** + * Fills the memory vector with random data. + */ +void raid_mrand_vector(int n, size_t size, void **vv); /** * 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); +int raid_mtest_vector(int n, size_t size, void **vv); #endif diff --git a/raid/module.c b/raid/module.c index 9b5f9843..ba185b0d 100644 --- a/raid/module.c +++ b/raid/module.c @@ -228,7 +228,7 @@ int raid_selftest(void) /* test parity generation */ ret = raid_test_par(nd, np, size, v, ref); if (ret != 0) - return ret; + goto bail; /* test recovering with full broken data disks */ for (i = 0; i < np; ++i) diff --git a/raid/test.c b/raid/test.c index 3eb0143f..6a3217cb 100644 --- a/raid/test.c +++ b/raid/test.c @@ -148,7 +148,7 @@ int raid_test_rec(int mode, int nd, size_t size) waste = v[nv-1]; /* fill data disk with random */ - raid_mrand_vector(v, nd, size); + raid_mrand_vector(nd, size, v); /* setup recov functions */ for (i = 0; i < np; ++i) { @@ -253,7 +253,7 @@ int raid_test_par(int mode, int nd, size_t size) return -1; /* fill with random */ - raid_mrand_vector(v, nv, size); + raid_mrand_vector(nv, size, v); /* compute the parity */ raid_par_ref(nd, np, size, v); diff --git a/scrub.c b/scrub.c index 175fe6d9..cbf0bcbb 100644 --- a/scrub.c +++ b/scrub.c @@ -69,7 +69,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); if (!state->opt.skip_self) - mtest_vector(buffer, buffermax, state->block_size); + mtest_vector(buffermax, state->block_size, buffer); error = 0; silent_error = 0; diff --git a/speed.c b/speed.c index d63bb60d..2d2b0c42 100644 --- a/speed.c +++ b/speed.c @@ -81,7 +81,6 @@ void speed(void) void *v_alloc; void **v; - /* we need disk + 1 for each parity buffers + 1 zero v */ nv = nd + RAID_PARITY_MAX + 1; v = malloc_nofail_vector_align(nd, nv, size, &v_alloc); diff --git a/sync.c b/sync.c index 376bfe46..f229af25 100644 --- a/sync.c +++ b/sync.c @@ -76,7 +76,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); if (!state->opt.skip_self) - mtest_vector(buffer, buffermax, state->block_size); + mtest_vector(buffermax, state->block_size, buffer); error = 0; silent_error = 0; diff --git a/util.c b/util.c index 25e5787f..67040174 100644 --- a/util.c +++ b/util.c @@ -1384,11 +1384,11 @@ void* malloc_nofail_align(size_t size, void** freeptr) return ptr; } -void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr) +void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr) { void* ptr; - ptr = raid_malloc_vector(reverse, count, size, freeptr); + ptr = raid_malloc_vector(nd, n, size, freeptr); if (!ptr) { /* don't use printf to avoid any possible extra allocation */ @@ -1401,20 +1401,20 @@ void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, voi return ptr; } -void mtest_vector(void** vv, size_t count, size_t size) +void mrand_vector(int n , size_t size, void** vv) { - if (raid_mtest_vector(vv, count, size) != 0) { + raid_mrand_vector(n, size, vv); +} + +void mtest_vector(int n , size_t size, void** vv) +{ + if (raid_mtest_vector(n, size, vv) != 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 */ diff --git a/util.h b/util.h index aa10fcaf..e528ec63 100644 --- a/util.h +++ b/util.h @@ -466,22 +466,20 @@ void* malloc_nofail_align(size_t size, void** freeptr); /** * Safe 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. * If no memory is available, it aborts. */ -void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr); +void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr); + +/** + * Fills the memory vector with random data. + */ +void mrand_vector(int n, size_t size, void** vv); /** * Tests the memory vector for RAM problems. * If a problem is found, it crashes. */ -void mtest_vector(void** vv, size_t count, size_t size); - -/** - * Fills the memory vector with random data. - */ -void mrand_vector(void** vv, size_t count, size_t size); +void mtest_vector(int n, size_t size, void** vv); /** * Safe strdup.