diff --git a/HISTORY b/HISTORY index 2b809888..8455472a 100644 --- a/HISTORY +++ b/HISTORY @@ -1,8 +1,15 @@ SnapRAID HISTORY ================ -5.2 2013/12 (BETA) -================== +5.3 2014/3 +================= + * Don't warn about UUID changed if it's for an empty disk. + * Fixed the number of blocks that scrub has to process when + selecting a high percentage of the array. + * Removed duplicate recovery attempts in synched state. + +5.2 2013/12 +=========== * If a disk changes UUID, automatically disable the inode recognition, because this is likely a new filesystem with all the inodes reassigned, and we don't want to risk a false @@ -15,7 +22,8 @@ SnapRAID HISTORY * Doesn't count empty dirs as files in the diff counters. * Added a new "share" configuration option to allow to share in the network the pool directory also in Windows. - * Fixed build problem in OpenBSD due the old assembler. + * Fixed build problems in OpenBSD due the old assembler. + * Fixed build problems in platforms different than x86. 5.1 2013/12 =========== diff --git a/check.c b/check.c index e795238c..bd111096 100644 --- a/check.c +++ b/check.c @@ -160,6 +160,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u /* if too many error, we don't have any strategy */ n = state->level; if (failed_count > n) { + fprintf(stdlog, "strategy_error:%u: No strategy to recover from %u failures with %u parity\n", pos, failed_count, n); return -1; } @@ -260,8 +261,10 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u /* return the number of failed attempts, or -1 if no strategy */ if (error) return error; - else - return -1; + + fprintf(stdlog, "strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", + pos, failed_count, n, has_hash ? "with" : "without"); + return -1; } static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, unsigned char** buffer, unsigned char** buffer_recov, unsigned char* buffer_zero) @@ -271,6 +274,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign unsigned j; int n; int something_to_recover; + int something_unsynched; error = 0; @@ -386,6 +390,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign /* and we are not interested to recover DELETED ones. */ n = 0; something_to_recover = 0; /* keep track if there is at least one block to fix */ + something_unsynched = 0; /* keep track if we have some unsynched info to process */ for(j=0;jhash, buffer[failed[j].index]) == 0) { @@ -444,7 +450,8 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign } /* if nothing to fix, we just don't try */ - if (something_to_recover) { + /* if nothing unsynched we also don't retry, because it's the same try as before */ + if (something_to_recover && something_unsynched) { ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); if (ret == 0) { /* we alreay marked as outdated NEW and CHG blocks, we don't need to do it again */ @@ -622,6 +629,8 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, failed[failed_count].block = block; failed[failed_count].handle = 0; ++failed_count; + + fprintf(stdlog, "block_delete:%u:%s: Delete block\n", i, handle[j].disk->name); continue; } @@ -737,6 +746,8 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, failed[failed_count].block = block; failed[failed_count].handle = &handle[j]; ++failed_count; + + fprintf(stdlog, "block_change:%u:%s:%s: Change block at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block)); continue; } @@ -806,7 +817,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, /* print a list of all the errors in files */ for(j=0;jdisk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block)); + fprintf(stdlog, "unrecoverable:%u:%s:%s: Unrecoverable synched error at position %u\n", i, failed[j].handle->disk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block)); } /* keep track of damaged files */ @@ -824,7 +835,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, for(j=0;jdisk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block)); + fprintf(stdlog, "unrecoverable:%u:%s:%s: Unrecoverable unsynched error at position %u\n", i, failed[j].handle->disk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block)); } } if (partial_recover_error != 0) { diff --git a/configure.ac b/configure.ac index da308c15..e3f8af88 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([snapraid], [5.2], [], [], [http://snapraid.sourceforge.net]) +AC_INIT([snapraid], [5.3], [], [], [http://snapraid.sourceforge.net]) AM_INIT_AUTOMAKE([foreign no-dependencies -Wall]) AC_CONFIG_SRCDIR([snapraid.c]) AC_CONFIG_HEADER([config.h]) diff --git a/elem.c b/elem.c index 52f9fb52..5843f4d4 100644 --- a/elem.c +++ b/elem.c @@ -533,6 +533,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev disk->has_volatile_inodes = 0; disk->has_unreliable_physical = 0; disk->has_different_uuid = 0; + disk->had_empty_uuid = 0; disk->mapping = -1; tommy_list_init(&disk->filelist); tommy_list_init(&disk->deletedlist); diff --git a/elem.h b/elem.h index 1648442d..3f944e9a 100644 --- a/elem.h +++ b/elem.h @@ -284,6 +284,7 @@ struct snapraid_disk { int has_volatile_inodes; /**< If the underline filesystem has not persistent inodes. */ int has_unreliable_physical; /**< If the physical offset of files has duplicates. */ int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same filesystem. */ + int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */ int mapping; /**< Index in the mapping vector. Used only as buffer when writing the content file. */ /**< diff --git a/fnmatch.c b/fnmatch.c index ea916c04..060db8e5 100644 --- a/fnmatch.c +++ b/fnmatch.c @@ -9,12 +9,7 @@ This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Library General Public License for more details. */ #if HAVE_CONFIG_H # include diff --git a/fnmatch.h b/fnmatch.h index cc3ec379..efeba70d 100644 --- a/fnmatch.h +++ b/fnmatch.h @@ -9,12 +9,7 @@ The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Library General Public License for more details. */ #ifndef _FNMATCH_H #define _FNMATCH_H 1 diff --git a/scan.c b/scan.c index 3189b784..d0fcdad5 100644 --- a/scan.c +++ b/scan.c @@ -1297,7 +1297,11 @@ void state_scan(struct snapraid_state* state, int output) for(i=state->disklist;i!=0;i=i->next) { struct snapraid_disk* disk = i->data; - if (disk->has_different_uuid) { + /* don't print the message if the UUID changed because before */ + /* if was no set. */ + /* this is the normal condition for an empty disk because it */ + /* isn't stored */ + if (disk->has_different_uuid && !disk->had_empty_uuid) { if (!done) { done = 1; fprintf(stderr, "WARNING! UUID is changed for disks: '%s'", disk->name); diff --git a/scrub.c b/scrub.c index 28b19006..c97d48cc 100644 --- a/scrub.c +++ b/scrub.c @@ -471,7 +471,7 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) recentlimit = now; } else if (percentage != -1 || olderthan != -1) { if (percentage != -1) - countlimit = (blockmax * percentage + 99) / 100; + countlimit = (blockmax * (uint64_t)percentage + 99) / 100; else countlimit = blockmax; if (olderthan != -1) diff --git a/selftest.c b/selftest.c index 9505f1b3..6345765c 100644 --- a/selftest.c +++ b/selftest.c @@ -184,7 +184,7 @@ static void recovtest(unsigned mode, unsigned diskmax, unsigned block_size) } /* recover */ - map[r-1][0](r, d, p, buffer, diskmax, zero, block_size); + map[r-1][j](r, d, p, buffer, diskmax, zero, block_size); /* check */ for(i=0;iname, map->uuid, uuid); + } else { + disk->had_empty_uuid = 1; } /* update the uuid in the mapping, */ @@ -2155,7 +2157,7 @@ static void decoding_error(const char* path, STREAM* f) fprintf(stderr, "This content file is damaged! Use an alternate copy.\n"); exit(EXIT_FAILURE); } else { - fprintf(stderr, "The file CRC is correct! This seems a SnapRAID bug!\n"); + fprintf(stderr, "The file CRC is correct!\n"); } } @@ -2226,6 +2228,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST ret = sgetb32(f, &mapping); if (ret < 0 || mapping >= mapping_max) { decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in mapping index!\n"); exit(EXIT_FAILURE); } disk = tommy_array_get(&disk_mapping, mapping); @@ -2239,7 +2242,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST /* check for impossible file size to avoid to crash for a too big allocation */ if (v_size / state->block_size > blockmax) { decoding_error(path, f); - fprintf(stderr, "Internal inconsistency in file size!\n"); + fprintf(stderr, "Internal inconsistency in file size too big!\n"); exit(EXIT_FAILURE); } @@ -2313,9 +2316,15 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST } if (v_pos + v_count > blockmax) { - decoding_error(path, f); - fprintf(stderr, "Internal inconsistency in block size!\n"); - exit(EXIT_FAILURE); + if (state->opt.skip_content_check) { + fprintf(stderr, "Internal inconsistency in block size!\n"); + fprintf(stderr, "Overriding from %u to %u...\n", blockmax, v_pos + v_count); + blockmax = v_pos + v_count; + } else { + fprintf(stderr, "Internal inconsistency in block size!\n"); + decoding_error(path, f); + exit(EXIT_FAILURE); + } } /* grow the array */ @@ -2416,9 +2425,15 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST } if (v_pos + v_count > blockmax) { - decoding_error(path, f); - fprintf(stderr, "Internal inconsistency in info size!\n"); - exit(EXIT_FAILURE); + if (state->opt.skip_content_check) { + fprintf(stderr, "Internal inconsistency in info size!\n"); + fprintf(stderr, "Overriding from %u to %u...\n", blockmax, v_pos + v_count); + blockmax = v_pos + v_count; + } else { + decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in info size!\n"); + exit(EXIT_FAILURE); + } } ret = sgetb32(f, &flag); @@ -2488,6 +2503,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST ret = sgetb32(f, &mapping); if (ret < 0 || mapping >= mapping_max) { decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in mapping index!\n"); exit(EXIT_FAILURE); } disk = tommy_array_get(&disk_mapping, mapping); @@ -2503,9 +2519,15 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST } if (v_pos + v_count > blockmax) { - decoding_error(path, f); - fprintf(stderr, "Internal inconsistency in hole size!\n"); - exit(EXIT_FAILURE); + if (state->opt.skip_content_check) { + fprintf(stderr, "Internal inconsistency in hole size!\n"); + fprintf(stderr, "Overriding from %u to %u...\n", blockmax, v_pos + v_count); + blockmax = v_pos + v_count; + } else { + decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in hole size!\n"); + exit(EXIT_FAILURE); + } } /* get the subcommand */ @@ -2577,6 +2599,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST ret = sgetb32(f, &mapping); if (ret < 0 || mapping >= mapping_max) { decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in mapping index!\n"); exit(EXIT_FAILURE); } disk = tommy_array_get(&disk_mapping, mapping); @@ -2618,6 +2641,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST ret = sgetb32(f, &mapping); if (ret < 0 || mapping >= mapping_max) { decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in mapping index!\n"); exit(EXIT_FAILURE); } disk = tommy_array_get(&disk_mapping, mapping); @@ -2658,6 +2682,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST ret = sgetb32(f, &mapping); if (ret < 0 || mapping >= mapping_max) { decoding_error(path, f); + fprintf(stderr, "Internal inconsistency in mapping index!\n"); exit(EXIT_FAILURE); } disk = tommy_array_get(&disk_mapping, mapping); @@ -2788,6 +2813,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST if (!disk) { decoding_error(path, f); fprintf(stderr, "Disk named '%s' not present in the configuration file!\n", buffer); + fprintf(stderr, "If you have removed it from the configuration file, please restore it\n"); exit(EXIT_FAILURE); } @@ -2841,7 +2867,12 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST /* check that the stored parity size matches the loaded state */ if (blockmax != parity_size(state)) { fprintf(stderr, "Internal inconsistency in parity size in '%s' at offset %"PRIi64"\n", path, stell(f)); - exit(EXIT_FAILURE); + if (state->opt.skip_content_check) { + fprintf(stderr, "Overriding from %u to %u...\n", blockmax, parity_size(state)); + blockmax = parity_size(state); + } else { + exit(EXIT_FAILURE); + } } /* set the required parity size */ diff --git a/state.h b/state.h index d68e201e..35930624 100644 --- a/state.h +++ b/state.h @@ -71,6 +71,7 @@ struct snapraid_option { int skip_sequential; /**< Skip sequential hint. */ int skip_lock; /**< Skip the lock file protection. */ int skip_self; /**< Skip the self-test. */ + int skip_content_check; /**< Relax some content file checks. */ int kill_after_sync; /**< Kill the process after sync without saving the final state. */ int force_murmur3; /**< Force Murmur3 choice. */ int force_spooky2; /**< Force Spooky2 choice. */