diff --git a/elem.c b/elem.c index 96ed27af..7d25364e 100644 --- a/elem.c +++ b/elem.c @@ -248,7 +248,32 @@ int filter_existence(int filter_missing, const char* dir, const char* sub) exit(EXIT_FAILURE); } - /* the file is presen, so we filter it out */ + /* the file is present, so we filter it out */ + return 1; +} + +int filter_correctness(int filter_error, tommy_arrayof* infoarr, struct snapraid_file* file) +{ + unsigned i; + + if (!filter_error) + return 0; + + /* check each block of the file */ + for(i=0;iblockmax;++i) { + struct snapraid_block* block; + snapraid_info info; + + block = &file->blockvec[i]; + + info = info_get(infoarr, block->parity_pos); + + /* if the file has a bad block, don't exclude it */ + if (info_get_bad(info)) + return 0; + } + + /* the file is correct, so we filter it out */ return 1; } diff --git a/elem.h b/elem.h index 9b949029..e490bcbf 100644 --- a/elem.h +++ b/elem.h @@ -363,6 +363,12 @@ int filter_path(tommy_list* filterlist, const char* disk, const char* sub); */ int filter_existence(int filter_missing, const char* dir, const char* sub); +/** + * Filter a file if bad. + * Return !=0 if the file is correct and it should be excluded. + */ +int filter_correctness(int filter_error, tommy_arrayof* infoarr, struct snapraid_file* file); + /** * Filters a dir using a list of filters. * For each element of the path all the filters are applied, until the first one that matches. diff --git a/snapraid.c b/snapraid.c index 90c063f2..568d9bee 100644 --- a/snapraid.c +++ b/snapraid.c @@ -61,7 +61,8 @@ void usage(void) printf(" " SWITCH_GETOPT_LONG("-c, --conf FILE ", "-c") " Configuration file (default " CONF ")\n"); printf(" " SWITCH_GETOPT_LONG("-f, --filter PATTERN ", "-f") " Process only files matching the pattern\n"); printf(" " SWITCH_GETOPT_LONG("-d, --filter-dist NAME", "-f") " Process only files in the disk\n"); - printf(" " SWITCH_GETOPT_LONG("-m, --filter-missing ", "-m") " Process only missing/delete files\n"); + printf(" " SWITCH_GETOPT_LONG("-m, --filter-missing ", "-m") " Process only missing/deleted files\n"); + printf(" " SWITCH_GETOPT_LONG("-e, --filter-error ", "-e") " Process only blocks with silent errors\n"); printf(" " SWITCH_GETOPT_LONG("-i, --import DIR ", "-i") " Import deleted files\n"); printf(" " SWITCH_GETOPT_LONG("-l, --log FILE ", "-l") " Log file. Default none\n"); printf(" " SWITCH_GETOPT_LONG("-a, --audit-only ", "-A") " Check only file data and not parity\n"); @@ -103,6 +104,7 @@ struct option long_options[] = { { "filter", 1, 0, 'f' }, { "filter-disk", 1, 0, 'd' }, { "filter-missing", 0, 0, 'm' }, + { "filter-error", 0, 0, 'e' }, { "start", 1, 0, 's' }, { "count", 1, 0, 't' }, { "import", 1, 0, 'i' }, @@ -176,7 +178,7 @@ struct option long_options[] = { }; #endif -#define OPTIONS "c:f:d:ms:t:i:l:ZEUDNaTvhVG" +#define OPTIONS "c:f:d:mes:t:i:l:ZEUDNaTvhVG" volatile int global_interrupt = 0; @@ -215,6 +217,7 @@ int main(int argc, char* argv[]) tommy_list filterlist_file; tommy_list filterlist_disk; int filter_missing; + int filter_error; char* e; const char* command; const char* import; @@ -232,6 +235,7 @@ int main(int argc, char* argv[]) tommy_list_init(&filterlist_file); tommy_list_init(&filterlist_disk); filter_missing = 0; + filter_error = 0; import = 0; log = 0; lock = 0; @@ -267,6 +271,9 @@ int main(int argc, char* argv[]) case 'm' : filter_missing = 1; break; + case 'e' : + filter_error = 1; + break; case 's' : blockstart = strtoul(optarg, &e, 0); if (!e || *e) { @@ -452,8 +459,27 @@ int main(int argc, char* argv[]) case OPERATION_DRY : break; default: - if (!tommy_list_empty(&filterlist_file) || !tommy_list_empty(&filterlist_disk) || filter_missing) { - fprintf(stderr, "You cannot filter with the '%s' command\n", command); + if (!tommy_list_empty(&filterlist_file)) { + fprintf(stderr, "You cannot use -f, --filter with the '%s' command\n", command); + exit(EXIT_FAILURE); + } + if (!tommy_list_empty(&filterlist_disk)) { + fprintf(stderr, "You cannot use -d, --filter-disk with the '%s' command\n", command); + exit(EXIT_FAILURE); + } + if (filter_missing != 0) { + fprintf(stderr, "You cannot use -m, --filter-missing with the '%s' command\n", command); + exit(EXIT_FAILURE); + } + } + + switch (operation) { + case OPERATION_CHECK : + case OPERATION_FIX : + break; + default: + if (filter_error != 0) { + fprintf(stderr, "You cannot use -e, --filter-error with the '%s' command\n", command); exit(EXIT_FAILURE); } } @@ -565,7 +591,7 @@ int main(int argc, char* argv[]) state_read(&state); /* apply the command line filter */ - state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing); + state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); /* intercept Ctrl+C */ signal(SIGINT, &signal_handler); @@ -620,7 +646,7 @@ int main(int argc, char* argv[]) state_import(&state, import); /* apply the command line filter */ - state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing); + state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); /* intercept Ctrl+C */ signal(SIGINT, &signal_handler); diff --git a/state.c b/state.c index 926e7218..627103af 100644 --- a/state.c +++ b/state.c @@ -3318,12 +3318,12 @@ void state_write(struct snapraid_state* state) state->need_write = 0; /* no write needed anymore */ } -void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing) +void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) { tommy_node* i; /* if no filter, include all */ - if (!filter_missing && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) + if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) return; printf("Filtering...\n"); @@ -3346,6 +3346,8 @@ void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tom } if (filter_missing) printf("\t\n"); + if (filter_error) + printf("\t\n"); } /* for each disk */ @@ -3364,6 +3366,7 @@ void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tom if (filter_path(filterlist_disk, disk->name, file->sub) != 0 || filter_path(filterlist_file, disk->name, file->sub) != 0 || filter_existence(filter_missing, disk->dir, file->sub) != 0 + || filter_correctness(filter_error, &state->infoarr, file) != 0 ) { file_flag_set(file, FILE_IS_EXCLUDED); } diff --git a/state.h b/state.h index ad9095bc..b3246dab 100644 --- a/state.h +++ b/state.h @@ -172,7 +172,7 @@ void state_pool(struct snapraid_state* state); * Filter files, symlinks and dirs. * Apply an additional filter to the list currently loaded. */ -void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing); +void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error); /** * Begins the progress visualization. diff --git a/status.c b/status.c index 55808145..0a5ca5be 100644 --- a/status.c +++ b/status.c @@ -222,7 +222,7 @@ int state_status(struct snapraid_state* state) printf("\n"); if (bad) { - printf("DANGER! In the array there are %u failing blocks!\n", bad); + printf("DANGER! In the array there are %u failing blocks!\n\n", bad); printf("They are:"); @@ -238,7 +238,10 @@ int state_status(struct snapraid_state* state) printf(" %u", i); } - printf("\n"); + printf("\n\n"); + + printf("To fix them use the command 'snapraid --filter-error fix'.\n"); + printf("The errors will disapper from the 'status' at the next 'scrub' command.\n"); } else { printf("No silent error detected!\n"); }