Checks the parity size in sync.

This commit is contained in:
Andrea Mazzoleni 2012-10-09 23:02:46 +02:00
parent c5575d2095
commit 91e74e91b8
8 changed files with 89 additions and 27 deletions

View file

@ -20,6 +20,8 @@ SnapRAID HISTORY
* Always fill the memory after allocating it to avoid the OOM (Out Of Memory)
killer in Linux.
* Fixed compilation in Solaris for lacking both futimes() and futimens().
* Now 'sync' ensures that the parity file are not too small to contains the
loaded data.
1.12 2012/9
=============

19
check.c
View file

@ -1187,6 +1187,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
{
block_off_t blockmax;
data_off_t size;
data_off_t out_size;
int ret;
struct snapraid_parity parity;
struct snapraid_parity qarity;
@ -1201,7 +1202,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
exit(EXIT_FAILURE);
}
blockmax = parity_resize(state);
blockmax = parity_size(state);
size = blockmax * (data_off_t)state->block_size;
if (blockstart > blockmax) {
@ -1218,19 +1219,31 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
/* 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, size, 0);
ret = parity_create(parity_ptr, state->parity, &out_size);
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);
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, size, 0);
ret = parity_create(qarity_ptr, state->qarity, &out_size);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to fix any error.\n");
exit(EXIT_FAILURE);
}
ret = parity_chsize(qarity_ptr, size, &out_size);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n");
exit(EXIT_FAILURE);
}
} else {
qarity_ptr = 0;
}

2
dry.c
View file

@ -156,7 +156,7 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
printf("Drying...\n");
blockmax = parity_resize(state);
blockmax = parity_size(state);
if (blockstart > blockmax) {
fprintf(stderr, "Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);

View file

@ -24,7 +24,7 @@
/****************************************************************************/
/* parity */
block_off_t parity_resize(struct snapraid_state* state)
block_off_t parity_size(struct snapraid_state* state)
{
block_off_t parity_block;
tommy_node* i;
@ -90,15 +90,12 @@ void parity_overflow(struct snapraid_state* state, data_off_t size)
}
}
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size, data_off_t* out_size)
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size)
{
int ret;
pathcpy(parity->path, sizeof(parity->path), path);
if (out_size)
*out_size = 0;
/* opening in sequential mode in Windows */
parity->f = open(parity->path, O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL, 0600);
if (parity->f == -1) {
@ -115,8 +112,20 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
/* get the size of the existing data */
parity->valid_size = parity->st.st_size;
if (out_size)
*out_size = parity->st.st_size;
*out_size = parity->st.st_size;
return 0;
bail:
close(parity->f);
parity->f = -1;
parity->valid_size = 0;
return -1;
}
int parity_chsize(struct snapraid_parity* parity, data_off_t size, data_off_t* out_size)
{
int ret;
if (parity->st.st_size < size) {
int f_ret;
@ -158,8 +167,7 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
}
/* return the new size */
if (out_size)
*out_size = parity->st.st_size;
*out_size = parity->st.st_size;
/* now check the error */
if (f_ret != 0) {
@ -185,8 +193,7 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
}
/* return the new real size */
if (out_size)
*out_size = parity->st.st_size;
*out_size = parity->st.st_size;
/* adjust the valid to the new size */
parity->valid_size = size;
@ -204,8 +211,6 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
return 0;
bail:
close(parity->f);
parity->f = -1;
parity->valid_size = 0;
return -1;
}

View file

@ -31,7 +31,7 @@ struct snapraid_parity {
/**
* Computes the size of the parity data in number of blocks.
*/
block_off_t parity_resize(struct snapraid_state* state);
block_off_t parity_size(struct snapraid_state* state);
/**
* Reports all the files outside the specified parity size.
@ -40,9 +40,15 @@ void parity_overflow(struct snapraid_state* state, data_off_t size);
/**
* Creates the parity file.
* \param out_size Return the final size of the parity file. Returned also in error cases.
* \param out_size Return the size of the parity file.
*/
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size, data_off_t* out_size);
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size);
/**
* Changes the parity size.
* \param out_size Return the size of the parity file. The out_size is set also on error to reflect a partial resize.
*/
int parity_chsize(struct snapraid_parity* parity, data_off_t size, data_off_t* out_size);
/**
* Opens an already existing parity file.

View file

@ -44,6 +44,7 @@ void state_init(struct snapraid_state* state)
tommy_list_init(&state->maplist);
tommy_list_init(&state->contentlist);
tommy_list_init(&state->filterlist);
state->loaded_blockmax = 0;
}
void state_done(struct snapraid_state* state)
@ -645,6 +646,7 @@ void state_read(struct snapraid_state* state)
struct snapraid_disk* disk;
struct snapraid_file* file;
block_off_t blockidx;
block_off_t blockmax;
unsigned line;
unsigned count_file;
unsigned count_block;
@ -707,6 +709,7 @@ void state_read(struct snapraid_state* state)
file = 0;
line = 1;
blockidx = 0;
blockmax = 0;
while (1) {
char buffer[PATH_MAX];
@ -748,6 +751,10 @@ void state_read(struct snapraid_state* state)
exit(EXIT_FAILURE);
}
/* keep track of the max block number */
if (blockidx > blockmax)
blockmax = blockidx;
block = &file->blockvec[blockidx];
if (block->parity_pos != POS_INVALID) {
@ -1191,6 +1198,8 @@ void state_read(struct snapraid_state* state)
sclose(f);
state->loaded_blockmax = blockmax;
/* update the mapping */
state_map(state);

View file

@ -51,6 +51,7 @@ struct snapraid_state {
tommy_list disklist; /**< List of all the disks. */
tommy_list maplist; /**< List of all the disk mappings. */
tommy_list filterlist; /**< List of inclusion/exclusion. */
block_off_t loaded_blockmax; /**< Previous size of the parity file, computed from the loaded state. */
time_t progress_start; /**< Start of processing for progress visualization. */
time_t progress_last; /**< Last update of progress visualization. */
time_t progress_interruption; /**< Start of the measure interruption. */

40
sync.c
View file

@ -352,8 +352,9 @@ bail:
int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount)
{
block_off_t blockmax;
data_off_t loaded_size;
data_off_t size;
data_off_t size_after;
data_off_t out_size;
tommy_node* i;
int ret;
struct snapraid_parity parity;
@ -364,10 +365,11 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
printf("Initializing...\n");
blockmax = parity_resize(state);
blockmax = parity_size(state);
size = blockmax * (data_off_t)state->block_size;
loaded_size = state->loaded_blockmax * (data_off_t)state->block_size;
/* remove all the deleted blocks over the upper limit */
/* remove all the deleted blocks over the new parity size */
for(i=state->disklist;i!=0;i=i->next) {
struct snapraid_disk* disk = i->data;
block_off_t diskblockmax = tommy_array_size(&disk->blockarr);
@ -395,18 +397,42 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
/* create the file and open for writing */
parity_ptr = &parity;
ret = parity_create(parity_ptr, state->parity, size, &size_after);
ret = parity_create(parity_ptr, state->parity, &out_size);
if (ret == -1) {
parity_overflow(state, size_after);
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 %lld.\n", state->parity, loaded_size);
exit(EXIT_FAILURE);
}
ret = parity_chsize(parity_ptr, size, &out_size);
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, size, &size_after);
ret = parity_create(qarity_ptr, state->qarity, &out_size);
if (ret == -1) {
parity_overflow(state, size_after);
fprintf(stderr, "WARNING! Without an accessible Q-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 Q-Parity file %s is smaller than the expected %lld.\n", state->qarity, loaded_size);
exit(EXIT_FAILURE);
}
ret = parity_chsize(qarity_ptr, size, &out_size);
if (ret == -1) {
parity_overflow(state, out_size);
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n");
exit(EXIT_FAILURE);
}