diff --git a/check.c b/check.c index bc1f4370..32809db0 100644 --- a/check.c +++ b/check.c @@ -94,12 +94,15 @@ static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_bl * Returns <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. * If success, the parity and qarity are computed in the buffer variable. */ -static int repair_step(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_parity, unsigned char* buffer_qarity, unsigned char* buffer_rarity, unsigned char* buffer_zero) +static int repair_step(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) { unsigned j; int error = 0; int has_hash; int hash_checked; + unsigned char* buffer_parity = buffer_recov[0]; + unsigned char* buffer_qarity = buffer_recov[1]; + unsigned char* buffer_rarity = buffer_recov[2]; /* no fix required */ if (failed_count == 0) { @@ -407,7 +410,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u 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_parity, unsigned char* buffer_qarity, unsigned char* buffer_rarity, unsigned char* buffer_zero) +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) { int ret; int error; @@ -471,7 +474,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign return 0; } - ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); + ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); if (ret == 0) { /* reprocess the blocks for NEW and CHG ones, for which we don't have a hash to check */ /* if they were BAD we have to use some euristics to ensure that we have recovered */ @@ -588,7 +591,7 @@ 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) { - ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); + 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 */ return 0; @@ -604,7 +607,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign return -1; } -static int state_check_process(struct snapraid_state* state, int check, int fix, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) +static int state_check_process(struct snapraid_state* state, int check, int fix, struct snapraid_parity** parity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax; @@ -622,6 +625,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, unsigned recovered_error; struct failed_struct* failed; unsigned* failed_map; + unsigned l; handle = handle_map(state, &diskmax); @@ -906,72 +910,42 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, /* now read and check the parity if requested */ if (check) { - unsigned char* buffer_parity; - unsigned char* buffer_qarity; - unsigned char* buffer_rarity; + unsigned char* buffer_recov[LEV_MAX]; unsigned char* buffer_zero; /* buffers for parity read and not computed */ if (state->level == 1) { - buffer_parity = buffer[diskmax + 1]; - buffer_qarity = 0; - buffer_rarity = 0; + buffer_recov[0] = buffer[diskmax + 1]; + buffer_recov[1] = 0; + buffer_recov[2] = 0; } else if (state->level == 2) { - buffer_parity = buffer[diskmax + 2]; - buffer_qarity = buffer[diskmax + 3]; - buffer_rarity = 0; + buffer_recov[0] = buffer[diskmax + 2]; + buffer_recov[1] = buffer[diskmax + 3]; + buffer_recov[2] = 0; } else { - buffer_parity = buffer[diskmax + 3]; - buffer_qarity = buffer[diskmax + 4]; - buffer_rarity = buffer[diskmax + 5]; + buffer_recov[0] = buffer[diskmax + 3]; + buffer_recov[1] = buffer[diskmax + 4]; + buffer_recov[2] = buffer[diskmax + 5]; } buffer_zero = buffer[buffermax-1]; /* read the parity */ - if (parity) { - ret = parity_read(parity, i, buffer_parity, state->block_size, stdlog); - if (ret == -1) { - buffer_parity = 0; /* no parity to use */ - - fprintf(stdlog, "error:%u:parity: Read error\n", i); - ++error; - } - } else { - buffer_parity = 0; - } - - /* read the qarity */ - if (state->level >= 2) { - if (qarity) { - ret = parity_read(qarity, i, buffer_qarity, state->block_size, stdlog); + for(l=0;llevel;++l) { + if (parity[l]) { + ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, stdlog); if (ret == -1) { - buffer_qarity = 0; /* no qarity to use */ + buffer_recov[l] = 0; /* no parity to use */ - fprintf(stdlog, "error:%u:qarity: Read error\n", i); + fprintf(stdlog, "error:%u:%s: Read error\n", i, lev_config_name(l)); ++error; } } else { - buffer_qarity = 0; - } - } - - /* read the rarity */ - if (state->level >= 3) { - if (rarity) { - ret = parity_read(rarity, i, buffer_rarity, state->block_size, stdlog); - if (ret == -1) { - buffer_rarity = 0; /* no rarity to use */ - - fprintf(stdlog, "error:%u:rarity: Read error\n", i); - ++error; - } - } else { - buffer_rarity = 0; + buffer_recov[l] = 0; } } /* try all the recovering strategies */ - ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); + ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); if (ret != 0) { /* increment the number of errors */ if (ret > 0) @@ -1012,29 +986,11 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, /* and doesn't make sense to try to fix it */ if (valid_parity) { /* check the parity */ - if (buffer_parity != 0 && memcmp(buffer_parity, buffer[diskmax], state->block_size) != 0) { - buffer_parity = 0; + for(l=0;llevel;++l) { + if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { + buffer_recov[l] = 0; - fprintf(stdlog, "error:%u:parity: Data error\n", i); - ++error; - } - - /* check the qarity */ - if (state->level >= 2) { - if (buffer_qarity != 0 && memcmp(buffer_qarity, buffer[diskmax + 1], state->block_size) != 0) { - buffer_qarity = 0; - - fprintf(stdlog, "error:%u:qarity: Data error\n", i); - ++error; - } - } - - /* check the rarity */ - if (state->level >= 3) { - if (buffer_rarity != 0 && memcmp(buffer_rarity, buffer[diskmax + 2], state->block_size) != 0) { - buffer_rarity = 0; - - fprintf(stdlog, "error:%u:rarity: Data error\n", i); + fprintf(stdlog, "error:%u:%s: Data error\n", i, lev_config_name(l)); ++error; } } @@ -1082,55 +1038,23 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, ++recovered_error; } - /* update parity and q-parity only if all the blocks have it computed */ + /* update parity only if all the blocks have it computed */ /* if you check/fix after a partial sync, you do not want to fix parity */ /* for blocks that are going to have it computed in the sync completion */ if (valid_parity) { /* update the parity */ - if (buffer_parity == 0 && parity) { - ret = parity_write(parity, i, buffer[diskmax], state->block_size); - if (ret == -1) { - /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - fprintf(stderr, "WARNING! Without a working Parity disk, it isn't possible to fix errors on it.\n"); - printf("Stopping at block %u\n", i); - ++unrecoverable_error; - goto bail; - } - - fprintf(stdlog, "fixed:%u:parity: Fixed data error\n", i); - ++recovered_error; - } - - /* update the qarity */ - if (state->level >= 2) { - if (buffer_qarity == 0 && qarity) { - ret = parity_write(qarity, i, buffer[diskmax + 1], state->block_size); + for(l=0;llevel;++l) { + if (buffer_recov[l] == 0 && parity[l] != 0) { + ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); if (ret == -1) { /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - fprintf(stderr, "WARNING! Without a working Q-Parity disk, it isn't possible to fix errors on it.\n"); + fprintf(stderr, "WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l)); printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } - fprintf(stdlog, "fixed:%u:qarity: Fixed data error\n", i); - ++recovered_error; - } - } - - /* update the rarity */ - if (state->level >= 3) { - if (buffer_rarity == 0 && rarity) { - ret = parity_write(rarity, i, buffer[diskmax + 2], state->block_size); - if (ret == -1) { - /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - fprintf(stderr, "WARNING! Without a working R-Parity disk, it isn't possible to fix errors on it.\n"); - printf("Stopping at block %u\n", i); - ++unrecoverable_error; - goto bail; - } - - fprintf(stdlog, "fixed:%u:rarity: Fixed data error\n", i); + fprintf(stdlog, "fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); ++recovered_error; } } @@ -1800,13 +1724,10 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl data_off_t size; data_off_t out_size; int ret; - struct snapraid_parity parity; - struct snapraid_parity qarity; - struct snapraid_parity rarity; - struct snapraid_parity* parity_ptr; - struct snapraid_parity* qarity_ptr; - struct snapraid_parity* rarity_ptr; + struct snapraid_parity parity[LEV_MAX]; + struct snapraid_parity* parity_ptr[LEV_MAX]; unsigned error; + unsigned l; printf("Initializing...\n"); @@ -1831,91 +1752,36 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl if (fix) { /* if fixing, create the file and open for writing */ /* if it fails, we cannot continue */ - parity_ptr = &parity; - ret = parity_create(parity_ptr, state->parity, &out_size, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to fix any error.\n"); - exit(EXIT_FAILURE); - } - - ret = parity_chsize(parity_ptr, size, &out_size, state->opt.skip_fallocate); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - - if (state->level >= 2) { - qarity_ptr = &qarity; - ret = parity_create(qarity_ptr, state->qarity, &out_size, state->opt.skip_sequential); + for(l=0;llevel;++l) { + parity_ptr[l] = &parity[l]; + ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->opt.skip_sequential); if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to fix any error.\n"); + fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l)); exit(EXIT_FAILURE); } - ret = parity_chsize(qarity_ptr, size, &out_size, state->opt.skip_fallocate); + ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate); if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n"); + fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); exit(EXIT_FAILURE); } - } else { - qarity_ptr = 0; - } - - if (state->level >= 3) { - rarity_ptr = &rarity; - ret = parity_create(rarity_ptr, state->rarity, &out_size, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to fix any error.\n"); - exit(EXIT_FAILURE); - } - - ret = parity_chsize(rarity_ptr, size, &out_size, state->opt.skip_fallocate); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - } else { - rarity_ptr = 0; } } else if (check) { /* if checking, open the file for reading */ /* it may fail if the file doesn't exist, in this case we continue to check the files */ - parity_ptr = &parity; - ret = parity_open(parity_ptr, state->parity, state->opt.skip_sequential); - if (ret == -1) { - printf("No accessible Parity file, only files will be checked.\n"); - /* continue anyway */ - parity_ptr = 0; - } - - if (state->level >= 2) { - qarity_ptr = &qarity; - ret = parity_open(qarity_ptr, state->qarity, state->opt.skip_sequential); + for(l=0;llevel;++l) { + parity_ptr[l] = &parity[l]; + ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential); if (ret == -1) { - printf("No accessible Q-Parity file, only files will be checked.\n"); + printf("No accessible %s file, only files will be checked.\n", lev_name(l)); /* continue anyway */ - qarity_ptr = 0; + parity_ptr[l] = 0; } - } else { - qarity_ptr = 0; - } - - if (state->level >= 3) { - rarity_ptr = &rarity; - ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); - if (ret == -1) { - printf("No accessible R-Parity file, only files will be checked.\n"); - /* continue anyway */ - rarity_ptr = 0; - } - } else { - rarity_ptr = 0; } } else { /* otherwise don't use any parity */ - parity_ptr = 0; - qarity_ptr = 0; - rarity_ptr = 0; + for(l=0;llevel;++l) + parity_ptr[l] = 0; } if (fix) @@ -1929,7 +1795,7 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_check_process(state, check, fix, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); + ret = state_check_process(state, check, fix, parity_ptr, blockstart, blockmax); if (ret == -1) { ++error; /* continue, as we are already exiting */ @@ -1937,31 +1803,11 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl } /* try to close only if opened */ - if (parity_ptr) { - ret = parity_close(parity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Parity disk.\n"); - ++error; - /* continue, as we are already exiting */ - } - } - - if (state->level >= 2) { - if (qarity_ptr) { - ret = parity_close(qarity_ptr); + for(l=0;llevel;++l) { + if (parity_ptr[l]) { + ret = parity_close(parity_ptr[l]); if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Q-Parity disk.\n"); - ++error; - /* continue, as we are already exiting */ - } - } - } - - if (state->level >= 3) { - if (rarity_ptr) { - ret = parity_close(rarity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l)); ++error; /* continue, as we are already exiting */ } diff --git a/dry.c b/dry.c index 9bca85ea..4a74f27b 100644 --- a/dry.c +++ b/dry.c @@ -26,7 +26,7 @@ /****************************************************************************/ /* dry */ -static int state_dry_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) +static int state_dry_process(struct snapraid_state* state, struct snapraid_parity** parity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax; @@ -39,6 +39,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit block_off_t countpos; block_off_t countmax; unsigned error; + unsigned l; handle = handle_map(state, &diskmax); @@ -98,31 +99,11 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit } /* read the parity */ - if (parity) { - ret = parity_read(parity, i, buffer_aligned, state->block_size, stdlog); - if (ret == -1) { - fprintf(stdlog, "error:%u:parity: Read error\n", i); - ++error; - } - } - - /* read the qarity */ - if (state->level >= 2) { - if (qarity) { - ret = parity_read(qarity, i, buffer_aligned, state->block_size, stdlog); + for(l=0;llevel;++l) { + if (parity[l]) { + ret = parity_read(parity[l], i, buffer_aligned, state->block_size, stdlog); if (ret == -1) { - fprintf(stdlog, "error:%u:qarity: Read error\n", i); - ++error; - } - } - } - - /* read the rarity */ - if (state->level >= 3) { - if (rarity) { - ret = parity_read(rarity, i, buffer_aligned, state->block_size, stdlog); - if (ret == -1) { - fprintf(stdlog, "error:%u:rarity: Read error\n", i); + fprintf(stdlog, "error:%u:%s: Read error\n", i, lev_config_name(l)); ++error; } } @@ -168,13 +149,10 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t { block_off_t blockmax; int ret; - struct snapraid_parity parity; - struct snapraid_parity qarity; - struct snapraid_parity rarity; - struct snapraid_parity* parity_ptr; - struct snapraid_parity* qarity_ptr; - struct snapraid_parity* rarity_ptr; + struct snapraid_parity parity[LEV_MAX]; + struct snapraid_parity* parity_ptr[LEV_MAX]; unsigned error; + unsigned l; printf("Drying...\n"); @@ -192,43 +170,21 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t /* open the file for reading */ /* it may fail if the file doesn't exist, in this case we continue to dry the files */ - parity_ptr = &parity; - ret = parity_open(parity_ptr, state->parity, state->opt.skip_sequential); - if (ret == -1) { - printf("No accessible Parity file.\n"); - /* continue anyway */ - parity_ptr = 0; - } - - if (state->level >= 2) { - qarity_ptr = &qarity; - ret = parity_open(qarity_ptr, state->qarity, state->opt.skip_sequential); + for(l=0;llevel;++l) { + parity_ptr[l] = &parity[l]; + ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential); if (ret == -1) { - printf("No accessible Q-Parity file.\n"); + printf("No accessible %s file.\n", lev_name(l)); /* continue anyway */ - qarity_ptr = 0; + parity_ptr[l] = 0; } - } else { - qarity_ptr = 0; - } - - if (state->level >= 3) { - rarity_ptr = &rarity; - ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); - if (ret == -1) { - printf("No accessible R-Parity file.\n"); - /* continue anyway */ - rarity_ptr = 0; - } - } else { - rarity_ptr = 0; } error = 0; /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_dry_process(state, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); + ret = state_dry_process(state, parity_ptr, blockstart, blockmax); if (ret == -1) { ++error; /* continue, as we are already exiting */ @@ -236,27 +192,9 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t } /* try to close only if opened */ - if (parity_ptr) { - ret = parity_close(parity_ptr); - if (ret == -1) { - ++error; - /* continue, as we are already exiting */ - } - } - - if (state->level >= 2) { - if (qarity_ptr) { - ret = parity_close(qarity_ptr); - if (ret == -1) { - ++error; - /* continue, as we are already exiting */ - } - } - } - - if (state->level >= 3) { - if (rarity_ptr) { - ret = parity_close(rarity_ptr); + for(l=0;llevel;++l) { + if (parity_ptr[l]) { + ret = parity_close(parity_ptr[l]); if (ret == -1) { ++error; /* continue, as we are already exiting */ diff --git a/scrub.c b/scrub.c index bb405de9..a58b0c2a 100644 --- a/scrub.c +++ b/scrub.c @@ -35,7 +35,7 @@ struct snapraid_rehash { struct snapraid_block* block; }; -static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax, time_t timelimit, block_off_t countlimit, time_t now) +static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity** parity, block_off_t blockstart, block_off_t blockmax, time_t timelimit, block_off_t countlimit, time_t now) { struct snapraid_handle* handle; void* rehandle_alloc; @@ -56,6 +56,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par int ret; unsigned error; unsigned silent_error; + unsigned l; /* maps the disks to handles */ handle = handle_map(state, &diskmax); @@ -281,51 +282,29 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* if we have read all the data required and it's correct, proceed with the parity check */ if (!error_on_this_block && !silent_error_on_this_block) { - unsigned char* buffer_parity; - unsigned char* buffer_qarity; - unsigned char* buffer_rarity; + unsigned char* buffer_recov[LEV_MAX]; /* buffers for parity read and not computed */ if (state->level == 1) { - buffer_parity = buffer[diskmax + 1]; - buffer_qarity = 0; - buffer_rarity = 0; + buffer_recov[0] = buffer[diskmax + 1]; + buffer_recov[1] = 0; + buffer_recov[2] = 0; } else if (state->level == 2) { - buffer_parity = buffer[diskmax + 2]; - buffer_qarity = buffer[diskmax + 3]; - buffer_rarity = 0; + buffer_recov[0] = buffer[diskmax + 2]; + buffer_recov[1] = buffer[diskmax + 3]; + buffer_recov[2] = 0; } else { - buffer_parity = buffer[diskmax + 3]; - buffer_qarity = buffer[diskmax + 4]; - buffer_rarity = buffer[diskmax + 5]; + buffer_recov[0] = buffer[diskmax + 3]; + buffer_recov[1] = buffer[diskmax + 4]; + buffer_recov[2] = buffer[diskmax + 5]; } /* read the parity */ - ret = parity_read(parity, i, buffer_parity, state->block_size, stdlog); - if (ret == -1) { - buffer_parity = 0; - fprintf(stdlog, "error:%u:parity: Read error\n", i); - ++error; - error_on_this_block = 1; - } - - /* read the qarity */ - if (state->level >= 2) { - ret = parity_read(qarity, i, buffer_qarity, state->block_size, stdlog); + for(l=0;llevel;++l) { + ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, stdlog); if (ret == -1) { - buffer_qarity = 0; - fprintf(stdlog, "error:%u:qarity: Read error\n", i); - ++error; - error_on_this_block = 1; - } - } - - /* read the rarity */ - if (state->level >= 3) { - ret = parity_read(rarity, i, buffer_rarity, state->block_size, stdlog); - if (ret == -1) { - buffer_rarity = 0; - fprintf(stdlog, "error:%u:rarity: Read error\n", i); + buffer_recov[l] = 0; + fprintf(stdlog, "error:%u:%s: Read error\n", i, lev_config_name(l)); ++error; error_on_this_block = 1; } @@ -335,39 +314,12 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par raid_gen(state->level, buffer, diskmax, state->block_size); /* compare the parity */ - if (buffer_parity && memcmp(buffer[diskmax], buffer_parity, state->block_size) != 0) { - fprintf(stdlog, "error:%u:parity: Data error\n", i); - ++error; + for(l=0;llevel;++l) { + + if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { + fprintf(stdlog, "error:%u:%s: Data error\n", i, lev_config_name(l)); + ++error; - /* it's a silent error only if we are dealing with synched blocks */ - if (block_is_unsynched) { - error_on_this_block = 1; - } else { - ++silent_error; - silent_error_on_this_block = 1; - } - } - - if (state->level >= 2) { - if (buffer_qarity && memcmp(buffer[diskmax + 1], buffer_qarity, state->block_size) != 0) { - fprintf(stdlog, "error:%u:qarity: Data error\n", i); - ++error; - - /* it's a silent error only if we are dealing with synched blocks */ - if (block_is_unsynched) { - error_on_this_block = 1; - } else { - ++silent_error; - silent_error_on_this_block = 1; - } - } - } - - if (state->level >= 3) { - if (buffer_rarity && memcmp(buffer[diskmax + 2], buffer_rarity, state->block_size) != 0) { - fprintf(stdlog, "error:%u:rarity: Data error\n", i); - ++error; - /* it's a silent error only if we are dealing with synched blocks */ if (block_is_unsynched) { error_on_this_block = 1; @@ -472,15 +424,12 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) time_t recentlimit; unsigned count; int ret; - struct snapraid_parity parity; - struct snapraid_parity qarity; - struct snapraid_parity rarity; - struct snapraid_parity* parity_ptr; - struct snapraid_parity* qarity_ptr; - struct snapraid_parity* rarity_ptr; + struct snapraid_parity parity[LEV_MAX]; + struct snapraid_parity* parity_ptr[LEV_MAX]; snapraid_info* infomap; unsigned error; time_t now; + unsigned l; /* get the present time */ now = time(0); @@ -559,65 +508,29 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) free(infomap); /* open the file for reading */ - parity_ptr = &parity; - ret = parity_open(parity_ptr, state->parity, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to scrub.\n"); - exit(EXIT_FAILURE); - } - - if (state->level >= 2) { - qarity_ptr = &qarity; - ret = parity_open(qarity_ptr, state->qarity, state->opt.skip_sequential); + for(l=0;llevel;++l) { + parity_ptr[l] = &parity[l]; + ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential); if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to scrub.\n"); + fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to scrub.\n", lev_name(l)); exit(EXIT_FAILURE); } - } else { - qarity_ptr = 0; - } - - if (state->level >= 3) { - rarity_ptr = &rarity; - ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to scrub.\n"); - exit(EXIT_FAILURE); - } - } else { - rarity_ptr = 0; } printf("Scrubbing...\n"); error = 0; - ret = state_scrub_process(state, parity_ptr, qarity_ptr, rarity_ptr, 0, blockmax, timelimit, countlimit, now); + ret = state_scrub_process(state, parity_ptr, 0, blockmax, timelimit, countlimit, now); if (ret == -1) { ++error; /* continue, as we are already exiting */ } - ret = parity_close(parity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Parity disk.\n"); - ++error; - /* continue, as we are already exiting */ - } - - if (state->level >= 2) { - ret = parity_close(qarity_ptr); + for(l=0;llevel;++l) { + ret = parity_close(parity_ptr[l]); if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Q-Parity disk.\n"); - ++error; - /* continue, as we are already exiting */ - } - } - - if (state->level >= 3) { - ret = parity_close(rarity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l)); ++error; /* continue, as we are already exiting */ } diff --git a/state.c b/state.c index b6df158e..494de621 100644 --- a/state.c +++ b/state.c @@ -24,18 +24,40 @@ #include "parity.h" #include "cpu.h" +const char* lev_name(unsigned l) +{ + switch (l) { + case 0 : return "Parity"; + case 1 : return "Q-Parity"; + case 2 : return "R-Parity"; + } + + return 0; +} + +const char* lev_config_name(unsigned l) +{ + switch (l) { + case 0 : return "parity"; + case 1 : return "q-parity"; + case 2 : return "r-parity"; + } + + return 0; +} + void state_init(struct snapraid_state* state) { + unsigned l; + state->filter_hidden = 0; state->autosave = 0; state->need_write = 0; state->block_size = 256 * 1024; /* default 256 KiB */ - state->parity[0] = 0; - state->parity_device = 0; - state->qarity[0] = 0; - state->qarity_device = 0; - state->rarity[0] = 0; - state->rarity_device = 0; + for(l=0;lparity_path[l][0] = 0; + state->parity_device[l] = 0; + } state->pool[0] = 0; state->pool_device = 0; state->lockfile[0] = 0; @@ -70,20 +92,13 @@ void state_done(struct snapraid_state* state) static void state_config_check(struct snapraid_state* state, const char* path) { tommy_node* i; + unsigned l; - if (state->level >= 1 && state->parity[0] == 0) { - fprintf(stderr, "No 'parity' specification in '%s'\n", path); - exit(EXIT_FAILURE); - } - - if (state->level >= 2 && state->qarity[0] == 0) { - fprintf(stderr, "No 'q-parity' specification in '%s'\n", path); - exit(EXIT_FAILURE); - } - - if (state->level >= 3 && state->rarity[0] == 0) { - fprintf(stderr, "No 'r-parity' specification in '%s'\n", path); - exit(EXIT_FAILURE); + for(l=0;llevel;++l) { + if (state->parity_path[l][0] == 0) { + fprintf(stderr, "No '%s' specification in '%s'\n", lev_config_name(l), path); + exit(EXIT_FAILURE); + } } if (tommy_list_empty(&state->contentlist)) { @@ -95,19 +110,11 @@ static void state_config_check(struct snapraid_state* state, const char* path) for(i=state->contentlist;i!=0;i=i->next) { struct snapraid_content* content = i->data; - if (pathcmp(state->parity, content->content) == 0) { - fprintf(stderr, "Same path used for 'parity' and 'content' as '%s'\n", content->content); - exit(EXIT_FAILURE); - } - - if (state->qarity[0] != 0 && pathcmp(state->qarity, content->content) == 0) { - fprintf(stderr, "Same path used for 'q-parity' and 'content' as '%s'\n", content->content); - exit(EXIT_FAILURE); - } - - if (state->rarity[0] != 0 && pathcmp(state->rarity, content->content) == 0) { - fprintf(stderr, "Same path used for 'r-parity' and 'content' as '%s'\n", content->content); - exit(EXIT_FAILURE); + for(l=0;llevel;++l) { + if (pathcmp(state->parity_path[l], content->content) == 0) { + fprintf(stderr, "Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content); + exit(EXIT_FAILURE); + } } } @@ -146,28 +153,14 @@ static void state_config_check(struct snapraid_state* state, const char* path) } } - if (disk->device == state->parity_device) { - fprintf(stderr, "Disk '%s' and parity '%s' are on the same device.\n", disk->dir, state->parity); + for(l=0;llevel;++l) { + if (disk->device == state->parity_device[l]) { + fprintf(stderr, "Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity_path[l]); #ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); #endif - exit(EXIT_FAILURE); - } - - if (state->qarity[0] != 0 && disk->device == state->qarity_device) { - fprintf(stderr, "Disk '%s' and q-parity '%s' are on the same device.\n", disk->dir, state->qarity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); -#endif - exit(EXIT_FAILURE); - } - - if (state->rarity[0] != 0 && disk->device == state->rarity_device) { - fprintf(stderr, "Disk '%s' and r-parity '%s' are on the same device.\n", disk->dir, state->rarity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); -#endif - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } } if (state->pool[0] != 0 && disk->device == state->pool_device) { @@ -188,28 +181,14 @@ static void state_config_check(struct snapraid_state* state, const char* path) } #ifdef _WIN32 - if (state->parity_device == 0) { - fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->parity); - fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); - fprintf(stderr, "it's better to change the serial number of the disk.\n"); - fprintf(stderr, "Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - exit(EXIT_FAILURE); - } - - if (state->qarity[0] != 0 && state->qarity_device == 0) { - fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->qarity); - fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); - fprintf(stderr, "it's better to change the serial number of the disk.\n"); - fprintf(stderr, "Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - exit(EXIT_FAILURE); - } - - if (state->rarity[0] != 0 && state->rarity_device == 0) { - fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->rarity); - fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); - fprintf(stderr, "it's better to change the serial number of the disk.\n"); - fprintf(stderr, "Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - exit(EXIT_FAILURE); + for(l=0;llevel;++l) { + if (state->parity_device[l] == 0) { + fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->parity_path[l]); + fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); + fprintf(stderr, "it's better to change the serial number of the disk.\n"); + fprintf(stderr, "Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + exit(EXIT_FAILURE); + } } if (state->pool[0] != 0 && state->pool_device == 0) { @@ -221,52 +200,27 @@ static void state_config_check(struct snapraid_state* state, const char* path) } #endif - if (state->qarity[0] != 0 && state->parity_device == state->qarity_device) { - fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->parity, state->qarity); + for(l=0;llevel;++l) { + unsigned j; + for(j=l+1;jlevel;++j) { + if (state->parity_device[l] == state->parity_device[j]) { + fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->parity_path[l], state->parity_path[j]); #ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->parity_device); + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->parity_device[l]); #endif - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } + } } - if (state->rarity[0] != 0 && state->parity_device == state->rarity_device) { - fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->parity, state->rarity); + for(l=0;llevel;++l) { + if (state->pool[0] != 0 && state->pool_device == state->parity_device[l]) { + fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity_path[l]); #ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->parity_device); -#endif - exit(EXIT_FAILURE); - } - - if (state->qarity[0] != 0 && state->rarity[0] != 0 && state->qarity_device == state->rarity_device) { - fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->qarity, state->rarity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->qarity_device); -#endif - exit(EXIT_FAILURE); - } - - if (state->pool[0] != 0 && state->pool_device == state->parity_device) { - fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); #endif - exit(EXIT_FAILURE); - } - - if (state->pool[0] != 0 && state->qarity[0] != 0 && state->pool_device == state->qarity_device) { - fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->qarity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); -#endif - exit(EXIT_FAILURE); - } - - if (state->pool[0] != 0 && state->rarity[0] != 0 && state->pool_device == state->rarity_device) { - fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->rarity); -#ifdef _WIN32 - fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); -#endif - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } } } @@ -374,28 +328,38 @@ void state_config(struct snapraid_state* state, const char* path, const char* co exit(EXIT_FAILURE); } state->block_size *= 1024; - } else if (strcmp(tag, "parity") == 0) { + } else if (strcmp(tag, "parity") == 0 || strcmp(tag, "q-parity") == 0 || strcmp(tag, "r-parity") == 0) { char device[PATH_MAX]; char* slash; struct stat st; + unsigned l; - if (*state->parity) { - fprintf(stderr, "Multiple 'parity' specification in '%s' at line %u\n", path, line); + switch (tag[0]) { + case 'p' : l = 0; break; + case 'q' : l = 1; break; + case 'r' : l = 2; break; + default: + fprintf(stderr, "Invalid '%s' specification in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + } + + if (*state->parity_path[l]) { + fprintf(stderr, "Multiple '%s' specification in '%s' at line %u\n", tag, path, line); exit(EXIT_FAILURE); } ret = sgetlasttok(f, buffer, sizeof(buffer)); if (ret < 0) { - fprintf(stderr, "Invalid 'parity' specification in '%s' at line %u\n", path, line); + fprintf(stderr, "Invalid '%s' specification in '%s' at line %u\n", tag, path, line); exit(EXIT_FAILURE); } if (!*buffer) { - fprintf(stderr, "Empty 'parity' specification in '%s' at line %u\n", path, line); + fprintf(stderr, "Empty '%s' specification in '%s' at line %u\n", tag, path, line); exit(EXIT_FAILURE); } - pathimport(state->parity, sizeof(state->parity), buffer); + pathimport(state->parity_path[l], sizeof(state->parity_path[l]), buffer); /* get the device of the directory containing the parity file */ pathimport(device, sizeof(device), buffer); @@ -409,94 +373,17 @@ void state_config(struct snapraid_state* state, const char* path, const char* co exit(EXIT_FAILURE); } - state->parity_device = st.st_dev; + state->parity_device[l] = st.st_dev; - /* set lock file */ - pathcpy(state->lockfile, sizeof(state->lockfile), state->parity); - pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); - - if (state->level < 1) - state->level = 1; - } else if (strcmp(tag, "q-parity") == 0) { - char device[PATH_MAX]; - char* slash; - struct stat st; - - if (*state->qarity) { - fprintf(stderr, "Multiple 'q-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); + /* set lock file if first parity */ + if (l == 0) { + pathcpy(state->lockfile, sizeof(state->lockfile), state->parity_path[l]); + pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); } - ret = sgetlasttok(f, buffer, sizeof(buffer)); - if (ret < 0) { - fprintf(stderr, "Invalid 'q-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - } - - if (!*buffer) { - fprintf(stderr, "Empty 'q-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - } - - pathimport(state->qarity, sizeof(state->qarity), buffer); - - /* get the device of the directory containing the qparity file */ - pathimport(device, sizeof(device), buffer); - slash = strrchr(device, '/'); - if (slash) - *slash = 0; - else - pathcpy(device, sizeof(device), "."); - if (stat(device, &st) != 0) { - fprintf(stderr, "Error accessing 'qarity' dir '%s' specification in '%s' at line %u\n", device, path, line); - exit(EXIT_FAILURE); - } - - state->qarity_device = st.st_dev; - - /* we have two level of parity */ - if (state->level < 2) - state->level = 2; - } else if (strcmp(tag, "r-parity") == 0) { - char device[PATH_MAX]; - char* slash; - struct stat st; - - if (*state->rarity) { - fprintf(stderr, "Multiple 'r-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - } - - ret = sgetlasttok(f, buffer, sizeof(buffer)); - if (ret < 0) { - fprintf(stderr, "Invalid 'r-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - } - - if (!*buffer) { - fprintf(stderr, "Empty 'r-parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - } - - pathimport(state->rarity, sizeof(state->rarity), buffer); - - /* get the device of the directory containing the qparity file */ - pathimport(device, sizeof(device), buffer); - slash = strrchr(device, '/'); - if (slash) - *slash = 0; - else - pathcpy(device, sizeof(device), "."); - if (stat(device, &st) != 0) { - fprintf(stderr, "Error accessing 'rarity' dir '%s' specification in '%s' at line %u\n", device, path, line); - exit(EXIT_FAILURE); - } - - state->rarity_device = st.st_dev; - - /* we have three level of parity */ - if (state->level < 3) - state->level = 3; + /* adjust the level */ + if (state->level < l + 1) + state->level = l + 1; } else if (strcmp(tag, "pool") == 0) { struct stat st; @@ -747,22 +634,23 @@ void state_config(struct snapraid_state* state, const char* path, const char* co if (state->opt.gui) { tommy_node* i; + unsigned l; + fprintf(stdlog, "blocksize:%u\n", state->block_size); for(i=state->disklist;i!=0;i=i->next) { struct snapraid_disk* disk = i->data; fprintf(stdlog, "disk:%s:%s\n", disk->name, disk->dir); } - if (state->rarity[0] != 0) - fprintf(stdlog, "mode:raidTP\n"); - else if (state->qarity[0] != 0) - fprintf(stdlog, "mode:raid6\n"); - else - fprintf(stdlog, "mode:raid5\n"); - fprintf(stdlog, "parity:%s\n", state->parity); - if (state->qarity[0] != 0) - fprintf(stdlog, "qarity:%s\n", state->qarity); - if (state->rarity[0] != 0) - fprintf(stdlog, "rarity:%s\n", state->rarity); + + switch (state->level) { + case 1 : fprintf(stdlog, "mode:raid5\n"); break; + case 2 : fprintf(stdlog, "mode:raid6\n"); break; + case 3 : fprintf(stdlog, "mode:raidTP\n"); break; + } + + for(l=0;llevel;++l) { + fprintf(stdlog, "%s:%s\n", lev_config_name(l), state->parity_path[l]); + } if (state->pool[0] != 0) fprintf(stdlog, "pool:%s\n", state->pool); fflush(stdlog); diff --git a/state.h b/state.h index 61bc5b85..6a0bd5e4 100644 --- a/state.h +++ b/state.h @@ -18,6 +18,24 @@ #ifndef __STATE_H #define __STATE_H +/****************************************************************************/ +/* parity level */ + +/** + * Max level of parity supported. + */ +#define LEV_MAX 3 + +/** + * Returns the parity name: Parity, Q-Parity, R-Parity. + */ +const char* lev_name(unsigned level); + +/** + * Returns the parity name used in the config file: parity, q-parity, r-parity. + */ +const char* lev_config_name(unsigned level); + /****************************************************************************/ /* state */ @@ -66,12 +84,8 @@ struct snapraid_state { uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */ int need_write; /**< If the state is changed. */ uint32_t block_size; /**< Block size in bytes. */ - char parity[PATH_MAX]; /**< Path of the parity file. */ - uint64_t parity_device; /**< Device identifier of the parity. */ - char qarity[PATH_MAX]; /**< Path of the qarity file. */ - uint64_t qarity_device; /**< Device identifier of the qarity. */ - char rarity[PATH_MAX]; /**< Path of the qarity file. */ - uint64_t rarity_device; /**< Device identifier of the rarity. */ + char parity_path[LEV_MAX][PATH_MAX]; /**< Path of the parity file. One for each parity. */ + uint64_t parity_device[LEV_MAX]; /**< Device identifier of the parity. One for each parity. */ char pool[PATH_MAX]; /**< Path of the pool tree. */ uint64_t pool_device; /**< Device identifier of the pool. */ unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */ diff --git a/sync.c b/sync.c index 1c59ef0a..f3c63fc8 100644 --- a/sync.c +++ b/sync.c @@ -35,7 +35,7 @@ struct snapraid_rehash { struct snapraid_block* block; }; -static int state_sync_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) +static int state_sync_process(struct snapraid_state* state, struct snapraid_parity** parity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; void* rehandle_alloc; @@ -55,6 +55,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari int ret; unsigned unrecoverable_error; time_t now; + unsigned l; /* get the present time */ now = time(0); @@ -301,30 +302,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari raid_gen(state->level, buffer, diskmax, state->block_size); /* write the parity */ - ret = parity_write(parity, i, buffer[diskmax], state->block_size); - if (ret == -1) { - fprintf(stderr, "DANGER! Write error in the Parity disk, it isn't possible to sync.\n"); - printf("Stopping at block %u\n", i); - ++unrecoverable_error; - goto bail; - } - - /* write the qarity */ - if (state->level >= 2) { - ret = parity_write(qarity, i, buffer[diskmax+1], state->block_size); + for(l=0;llevel;++l) { + ret = parity_write(parity[l], i, buffer[diskmax+l], state->block_size); if (ret == -1) { - fprintf(stderr, "DANGER! Write error in the Q-Parity disk, it isn't possible to sync.\n"); - printf("Stopping at block %u\n", i); - ++unrecoverable_error; - goto bail; - } - } - - /* write the rarity */ - if (state->level >= 3) { - ret = parity_write(rarity, i, buffer[diskmax+2], state->block_size); - if (ret == -1) { - fprintf(stderr, "DANGER! Write error in the R-Parity disk, it isn't possible to sync.\n"); + fprintf(stderr, "DANGER! Write error in the %s disk, it isn't possible to sync.\n", lev_name(l)); printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; @@ -423,13 +404,10 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t data_off_t size; data_off_t out_size; int ret; - struct snapraid_parity parity; - struct snapraid_parity qarity; - struct snapraid_parity rarity; - struct snapraid_parity* parity_ptr; - struct snapraid_parity* qarity_ptr; - struct snapraid_parity* rarity_ptr; + struct snapraid_parity parity[LEV_MAX]; + struct snapraid_parity* parity_ptr[LEV_MAX]; unsigned unrecoverable_error; + unsigned l; printf("Initializing...\n"); @@ -447,76 +425,30 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax = blockstart + blockcount; } - /* create the file and open for writing */ - parity_ptr = &parity; - ret = parity_create(parity_ptr, state->parity, &out_size, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - - /* if the file is too small */ - if (out_size < loaded_size) { - fprintf(stderr, "DANGER! The Parity file %s is smaller than the expected %" PRId64 ".\n", state->parity, loaded_size); - exit(EXIT_FAILURE); - } - - /* change the size of the parity file, truncating or extending it */ - /* from this point all the DELETED blocks after the end of the parity are invalid */ - /* and they are automatically removed when we save the new content file */ - ret = parity_chsize(parity_ptr, size, &out_size, state->opt.skip_fallocate); - if (ret == -1) { - parity_overflow(state, out_size); - fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - - if (state->level >= 2) { - qarity_ptr = &qarity; - ret = parity_create(qarity_ptr, state->qarity, &out_size, state->opt.skip_sequential); + for(l=0;llevel;++l) { + /* create the file and open for writing */ + parity_ptr[l] = &parity[l]; + ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->opt.skip_sequential); if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n"); + fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); exit(EXIT_FAILURE); } /* if the file is too small */ if (out_size < loaded_size) { - fprintf(stderr, "DANGER! The Q-Parity file %s is smaller than the expected %" PRId64 ".\n", state->qarity, loaded_size); + fprintf(stderr, "DANGER! The %s file %s is smaller than the expected %" PRId64 ".\n", lev_name(l), state->parity_path[l], loaded_size); exit(EXIT_FAILURE); } - ret = parity_chsize(qarity_ptr, size, &out_size, state->opt.skip_fallocate); + /* change the size of the parity file, truncating or extending it */ + /* from this point all the DELETED blocks after the end of the parity are invalid */ + /* and they are automatically removed when we save the new content file */ + ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate); if (ret == -1) { parity_overflow(state, out_size); - fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n"); + fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); exit(EXIT_FAILURE); } - } else { - qarity_ptr = 0; - } - - if (state->level >= 3) { - rarity_ptr = &rarity; - ret = parity_create(rarity_ptr, state->rarity, &out_size, state->opt.skip_sequential); - if (ret == -1) { - fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - - /* if the file is too small */ - if (out_size < loaded_size) { - fprintf(stderr, "DANGER! The R-Parity file %s is smaller than the expected %" PRId64 ".\n", state->rarity, loaded_size); - exit(EXIT_FAILURE); - } - - ret = parity_chsize(rarity_ptr, size, &out_size, state->opt.skip_fallocate); - if (ret == -1) { - parity_overflow(state, out_size); - fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); - exit(EXIT_FAILURE); - } - } else { - rarity_ptr = 0; } printf("Syncing...\n"); @@ -525,7 +457,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_sync_process(state, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); + ret = state_sync_process(state, parity_ptr, blockstart, blockmax); if (ret == -1) { ++unrecoverable_error; /* continue, as we are already exiting */ @@ -534,47 +466,17 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t printf("Nothing to do\n"); } - ret = parity_sync(parity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected sync error in Parity disk.\n"); - ++unrecoverable_error; - /* continue, as we are already exiting */ - } - - ret = parity_close(parity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Parity disk.\n"); - ++unrecoverable_error; - /* continue, as we are already exiting */ - } - - if (state->level >= 2) { - ret = parity_sync(qarity_ptr); + for(l=0;llevel;++l) { + ret = parity_sync(parity_ptr[l]); if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected sync error in Q-Parity disk.\n"); + fprintf(stderr, "DANGER! Unexpected sync error in %s disk.\n", lev_name(l)); ++unrecoverable_error; /* continue, as we are already exiting */ } - ret = parity_close(qarity_ptr); + ret = parity_close(parity_ptr[l]); if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in Q-Parity disk.\n"); - ++unrecoverable_error; - /* continue, as we are already exiting */ - } - } - - if (state->level >= 3) { - ret = parity_sync(rarity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected sync error in R-Parity disk.\n"); - ++unrecoverable_error; - /* continue, as we are already exiting */ - } - - ret = parity_close(rarity_ptr); - if (ret == -1) { - fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l)); ++unrecoverable_error; /* continue, as we are already exiting */ }