mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Finalizes alternate triple parity support.
This commit is contained in:
parent
a762c30a46
commit
bb0cd0e7ac
8 changed files with 177 additions and 63 deletions
9
HISTORY
9
HISTORY
|
|
@ -3,10 +3,11 @@ SnapRAID HISTORY
|
|||
|
||||
5.0 2013/11 (BETA)
|
||||
==================
|
||||
* Added support for up to six level of parity. Take care that to get
|
||||
good performance for triple parity and beyond you need a CPU with
|
||||
SSSE3 support.
|
||||
* Faster RAID5 and RAID6 computation for ARM 64 bit CPUs.
|
||||
* Added support for up to six level of parity.
|
||||
* Added a specific and faster triple parity format for CPUs that
|
||||
don't support SSSE3 instructions like ARM and AMD Phenom, Athlon
|
||||
and Opteron.
|
||||
* Faster RAID5 and RAID6 implementation for ARM 64 bit CPUs.
|
||||
* In sync, if a silent error is found, directly mark the block as bad
|
||||
like in scrub, and continue with the sync process.
|
||||
* Sort files by inode when listing the directory. This improves
|
||||
|
|
|
|||
2
raid.c
2
raid.c
|
|
@ -739,7 +739,7 @@ void raidZ3_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
for(i=0;i<size;i+=32) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ static void recovtest(unsigned mode, unsigned diskmax, unsigned block_size)
|
|||
|
||||
raid_set(mode);
|
||||
if (mode == RAID_MODE_S)
|
||||
level = LEV_MAX;
|
||||
level = RAID_PARITY_S_MAX;
|
||||
else
|
||||
level = 3;
|
||||
level = RAID_PARITY_Z_MAX;
|
||||
|
||||
buffermax = diskmax + level * 2 + 2;
|
||||
|
||||
|
|
@ -222,9 +222,9 @@ static void gentest(unsigned mode, unsigned diskmax, unsigned block_size)
|
|||
|
||||
raid_set(mode);
|
||||
if (mode == RAID_MODE_S)
|
||||
level = LEV_MAX;
|
||||
level = RAID_PARITY_S_MAX;
|
||||
else
|
||||
level = 3;
|
||||
level = RAID_PARITY_Z_MAX;
|
||||
|
||||
buffermax = diskmax + level * 2;
|
||||
|
||||
|
|
|
|||
20
snapraid.1
20
snapraid.1
|
|
@ -809,6 +809,26 @@ Leaving the parity disks reserved for only these files ensures that
|
|||
they doesn\(cqt get fragmented, improving the performance.
|
||||
.PP
|
||||
These options are optional and they can be used only one time.
|
||||
.SS z\(hyparity FILE
|
||||
Defines an alternate file and format to store the triple parity,
|
||||
instead of the other \(cqr\(hyparity\(cq one.
|
||||
.PP
|
||||
It\(cqs mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
|
||||
and Opteron that don\(cqt support the SSSE3 instructions set, and in
|
||||
such case it may provide better performance.
|
||||
.PP
|
||||
This is also the parity format used by ZFS, but it doesn\(cqt work
|
||||
for beyond triple parity.
|
||||
.PP
|
||||
If you are using the \(cqr\(hyparity\(cq you will be warned if it\(cqs
|
||||
recommended to use the \(cqz\(hyparity\(cq format for a performance
|
||||
increase.
|
||||
.PP
|
||||
It\(cqs possible to convert from one format to another, adjusting
|
||||
the configuraton file with the wanted z\(hyparity or r\(hyparity file,
|
||||
and using \(cqfix\(cq to recreate it.
|
||||
.PP
|
||||
This option is alternative to \(cqr\(hyparity\(cq.
|
||||
.SS content FILE
|
||||
Defines the file to use to store the list and checksums of all the
|
||||
files present in your disk array.
|
||||
|
|
|
|||
21
snapraid.d
21
snapraid.d
|
|
@ -602,6 +602,27 @@ Configuration
|
|||
|
||||
These options are optional and they can be used only one time.
|
||||
|
||||
z-parity FILE
|
||||
Defines an alternate file and format to store the triple parity,
|
||||
instead of the other 'r-parity' one.
|
||||
|
||||
It's mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
|
||||
and Opteron that don't support the SSSE3 instructions set, and in
|
||||
such case it may provide better performance.
|
||||
|
||||
This is also the parity format used by ZFS, but it doesn't work
|
||||
for beyond triple parity.
|
||||
|
||||
If you are using the 'r-parity' you will be warned if it's
|
||||
recommended to use the 'z-parity' format for a performance
|
||||
increase.
|
||||
|
||||
It's possible to convert from one format to another, adjusting
|
||||
the configuraton file with the wanted z-parity or r-parity file,
|
||||
and using 'fix' to recreate it.
|
||||
|
||||
This option is alternative to 'r-parity'.
|
||||
|
||||
content FILE
|
||||
Defines the file to use to store the list and checksums of all the
|
||||
files present in your disk array.
|
||||
|
|
|
|||
39
snapraid.txt
39
snapraid.txt
|
|
@ -656,7 +656,30 @@ they doesn't get fragmented, improving the performance.
|
|||
|
||||
These options are optional and they can be used only one time.
|
||||
|
||||
7.3 content FILE
|
||||
7.3 z-parity FILE
|
||||
-----------------
|
||||
|
||||
Defines an alternate file and format to store the triple parity,
|
||||
instead of the other 'r-parity' one.
|
||||
|
||||
It's mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
|
||||
and Opteron that don't support the SSSE3 instructions set, and in
|
||||
such case it may provide better performance.
|
||||
|
||||
This is also the parity format used by ZFS, but it doesn't work
|
||||
for beyond triple parity.
|
||||
|
||||
If you are using the 'r-parity' you will be warned if it's
|
||||
recommended to use the 'z-parity' format for a performance
|
||||
increase.
|
||||
|
||||
It's possible to convert from one format to another, adjusting
|
||||
the configuraton file with the wanted z-parity or r-parity file,
|
||||
and using 'fix' to recreate it.
|
||||
|
||||
This option is alternative to 'r-parity'.
|
||||
|
||||
7.4 content FILE
|
||||
----------------
|
||||
|
||||
Defines the file to use to store the list and checksums of all the
|
||||
|
|
@ -673,7 +696,7 @@ more copies of the same files.
|
|||
You have to store at least one copy for each parity disk used
|
||||
plus one. Using some more don't hurt.
|
||||
|
||||
7.4 disk NAME DIR
|
||||
7.5 disk NAME DIR
|
||||
-----------------
|
||||
|
||||
Defines the name and the mount point of the disks of the array.
|
||||
|
|
@ -685,14 +708,14 @@ keep the NAME fixed.
|
|||
|
||||
You should use one option for each disk of the array.
|
||||
|
||||
7.5 nohidden
|
||||
7.6 nohidden
|
||||
------------
|
||||
|
||||
Excludes all the hidden files and directory.
|
||||
In Unix hidden files are the ones starting with ".".
|
||||
In Windows they are the ones with the hidden attribute.
|
||||
|
||||
7.6 exclude/include PATTERN
|
||||
7.7 exclude/include PATTERN
|
||||
---------------------------
|
||||
|
||||
Defines the file or directory patterns to exclude and include
|
||||
|
|
@ -710,7 +733,7 @@ specifications.
|
|||
|
||||
This option can be used many times.
|
||||
|
||||
7.7 block_size SIZE_IN_KIBIBYTES
|
||||
7.8 block_size SIZE_IN_KIBIBYTES
|
||||
--------------------------------
|
||||
|
||||
Defines the basic block size in kibi bytes of the redundancy
|
||||
|
|
@ -741,7 +764,7 @@ wasted for each file.
|
|||
For example, with 10000 files and a 256 KiB block size, you are
|
||||
going to waste 1.2 GiB.
|
||||
|
||||
---- 7.7.1 autosave SIZE_IN_GIBIBYTES ----
|
||||
---- 7.8.1 autosave SIZE_IN_GIBIBYTES ----
|
||||
Automatically save the state when synching after the specied amount
|
||||
of GiB processed.
|
||||
This option is useful to avoid to restart from scratch long "sync"
|
||||
|
|
@ -750,12 +773,12 @@ may interrupt SnapRAID.
|
|||
The SIZE argument is specified in gibibytes. Where one gibi bytes
|
||||
is 1073741824 bytes.
|
||||
|
||||
---- 7.7.2 pool DIR ----
|
||||
---- 7.8.2 pool DIR ----
|
||||
Defines the pooling directory where the virtual view of the disk
|
||||
array is created using the "pool" command.
|
||||
The directory must already exist.
|
||||
|
||||
7.8 Examples
|
||||
7.9 Examples
|
||||
------------
|
||||
|
||||
An example of a typical configuration for Unix is:
|
||||
|
|
|
|||
107
speed.c
107
speed.c
|
|
@ -110,15 +110,16 @@ void speed(void)
|
|||
|
||||
cpu_info(vendor, &family, &model);
|
||||
|
||||
printf("CPU %s, family %u, model %u, flags%s%s%s%s%s%s%s\n", vendor, family, model,
|
||||
printf("CPU %s, family %u, model %u, flags%s%s%s%s%s%s%s%s\n", vendor, family, model,
|
||||
cpu_has_mmx() ? " mmx" : "",
|
||||
cpu_has_sse2() ? " sse2" : "",
|
||||
cpu_has_ssse3() ? " ssse3" : "",
|
||||
cpu_has_sse42() ? " sse42" : "",
|
||||
cpu_has_avx() ? " avx" : "",
|
||||
cpu_has_avx2() ? "avx2" : "",
|
||||
cpu_has_slowmult() ? " slowmult" : "",
|
||||
cpu_has_slowpshufb() ? " slowpshufb" : ""
|
||||
);
|
||||
);
|
||||
}
|
||||
#else
|
||||
printf("CPU is not a x86/x64\n");
|
||||
|
|
@ -568,14 +569,18 @@ void speed(void)
|
|||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID5 optimized case */
|
||||
raid_recov1_ssse3(1, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID5 optimized case */
|
||||
raid_recov1_ssse3(1, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "recov2");
|
||||
|
|
@ -592,14 +597,18 @@ void speed(void)
|
|||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID6 optimized case */
|
||||
raid_recov2_ssse3(2, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID6 optimized case */
|
||||
raid_recov2_ssse3(2, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "recov3");
|
||||
|
|
@ -615,13 +624,17 @@ void speed(void)
|
|||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(3, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(3, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "recov4");
|
||||
|
|
@ -637,13 +650,17 @@ void speed(void)
|
|||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(4, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(4, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "recov5");
|
||||
|
|
@ -658,14 +675,18 @@ void speed(void)
|
|||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(5, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(5, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "recov6");
|
||||
|
|
@ -681,13 +702,17 @@ void speed(void)
|
|||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(6, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(6, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
|
||||
|
|
|
|||
34
state.c
34
state.c
|
|
@ -53,12 +53,15 @@ const char* lev_config_name(unsigned l)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* lev_raid_name(unsigned n)
|
||||
const char* lev_raid_name(unsigned mode, unsigned n)
|
||||
{
|
||||
switch (n) {
|
||||
case 1 : return "raid5";
|
||||
case 2 : return "raid6";
|
||||
case 3 : return "raidS3";
|
||||
case 3 : if (mode == RAID_MODE_S)
|
||||
return "raidS3";
|
||||
else
|
||||
return "raidZ3";
|
||||
case 4 : return "raidS4";
|
||||
case 5 : return "raidS5";
|
||||
case 6 : return "raidS6";
|
||||
|
|
@ -118,6 +121,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
|
|||
tommy_node* i;
|
||||
unsigned l;
|
||||
|
||||
/* check for parity level */
|
||||
if (state->raid_mode == RAID_MODE_Z) {
|
||||
if (state->level > RAID_PARITY_Z_MAX) {
|
||||
fprintf(stderr, "If you use the z-parity you cannot have more than %u parities.\n", RAID_PARITY_Z_MAX);
|
||||
|
|
@ -275,11 +279,18 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
|
|||
}
|
||||
}
|
||||
|
||||
/* check for speed */
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (!cpu_has_ssse3())
|
||||
#endif
|
||||
if (state->level > 2) {
|
||||
fprintf(stderr, "WARNING! Your CPU doesn't have a fast implementation beyond RAID6.\n");
|
||||
if (state->raid_mode == RAID_MODE_S) {
|
||||
if (state->level == 3) {
|
||||
fprintf(stderr, "WARNING! Your CPU doesn't have a fast implementation for triple parity.\n");
|
||||
fprintf(stderr, "WARNING! It's recommended to switch to 'z-parity' instead than 'r-parity'.\n");
|
||||
} else if (state->level > 3) {
|
||||
fprintf(stderr, "WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n");
|
||||
fprintf(stderr, "WARNING! It's recommended to reduce the parity levels to triple parity.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ensure that specified filter disks are valid ones */
|
||||
|
|
@ -696,7 +707,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
fprintf(stdlog, "disk:%s:%s\n", disk->name, disk->dir);
|
||||
}
|
||||
|
||||
fprintf(stdlog, "mode:%s\n", lev_raid_name(state->level));
|
||||
fprintf(stdlog, "mode:%s\n", lev_raid_name(state->raid_mode, state->level));
|
||||
for(l=0;l<state->level;++l)
|
||||
fprintf(stdlog, "%s:%s\n", lev_config_name(l), state->parity_path[l]);
|
||||
if (state->pool[0] != 0)
|
||||
|
|
@ -861,6 +872,19 @@ static void state_map(struct snapraid_state* state)
|
|||
fprintf(stderr, "Too few data disks. You must define at least %u.\n", RAID_DATA_MIN);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* recommend number of parities */
|
||||
if (diskcount >= 34 && state->level < 6) {
|
||||
fprintf(stderr, "WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
|
||||
} else if (diskcount >= 27 && state->level < 5) {
|
||||
fprintf(stderr, "WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
|
||||
} else if (diskcount >= 20 && state->level < 4) {
|
||||
fprintf(stderr, "WARNING! With %u disks it's recommended to use four parity leveles.\n", diskcount);
|
||||
} else if (diskcount >= 13 && state->level < 3) {
|
||||
fprintf(stderr, "WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
|
||||
} else if (diskcount >= 6 && state->level < 2) {
|
||||
fprintf(stderr, "WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue