Prints list of files outside the parity if growing is not possible.

This commit is contained in:
Andrea Mazzoleni 2012-10-06 13:17:21 +02:00
parent 3a8f21a839
commit 8373233f25
6 changed files with 114 additions and 26 deletions

View file

@ -7,11 +7,14 @@ SnapRAID HISTORY
This allows to restore the exact modification time in 'fix'.
The new 'content' files written with this version are not backward compatible,
but it's still possible to read the old 'content' format.
* Fixed hard-links automatic exclusion. All the hardlinks after the first one
are now correctly ignored.
* If it isn't possible to grow a parity file, prints the list of files outside
the maximum size allocated.
* Autosave isn't triggered if we are near the end of the 'sync' process.
* Before starting a 'sync', we wait for two seconds, to workaround the FAT
limitation of having two seconds modification time precision.
This a safe measure to be 100% sure to always detect file changes.
* Autosave isn't triggered if we are near the end of the 'sync' process.
* Fixed hard-links automatic exclusion after the first one.
* Always fill the memory after allocating it to avoid the OOM (Out Of Memory)
killer in Linux.

28
TODO
View file

@ -5,19 +5,7 @@ This is the list of TODO items for SnapRAID.
- v1.13
* In the repair() function the euristic to detect if we recovered after the sync, can be extended
to all the subsequent blocks, because we always proceeed in block order during a sync.
So, if for a block we can detect that we recovered after a sync, also for all the subsequent blocks
this is true.
* To list all the hardlink in Windows Vista it's possible to use FindFirstFileNameW/FindNextFileNameW
See: http://blogs.msdn.com/b/oldnewthing/archive/2011/07/20/10188033.aspx
* Support Symlinks also in Windows.
See: http://www.codeproject.com/Articles/21202/Reparse-Points-in-Vista
* In Windows to use FILE_FLAG_BACKUP_SEMANTICS we should also get privileges.
See http://www.codeproject.com/Articles/21202/Reparse-Points-in-Vista.
* In error growing, print the last file in the bigger data disk.
* Allow to filter the files to check/fix based on the drive where they reside.
@ -32,6 +20,20 @@ on the error message. See: https://sourceforge.net/projects/snapraid/forums/foru
* Support interrupted operations with EINTR. For remote filesystems it could be relevant.
* In the repair() function the euristic to detect if we recovered after the sync, can be extended
to all the subsequent blocks, because we always proceeed in block order during a sync.
So, if for a block we can detect that we recovered after a sync, also for all the subsequent blocks
this is true.
* In Windows to use FILE_FLAG_BACKUP_SEMANTICS we should also get privileges.
See http://www.codeproject.com/Articles/21202/Reparse-Points-in-Vista.
* Support Symlinks also in Windows.
See: http://www.codeproject.com/Articles/21202/Reparse-Points-in-Vista
* To list all the hardlink in Windows Vista it's possible to use FindFirstFileNameW/FindNextFileNameW
See: http://blogs.msdn.com/b/oldnewthing/archive/2011/07/20/10188033.aspx
* In Windows we must be case insensitive, at least for ASCII<128 comparison. For other UTF-8 chars
is too complex.

View file

@ -1190,7 +1190,7 @@ void state_check(struct snapraid_state* state, int fix, block_off_t blockstart,
/* 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);
ret = parity_create(parity_ptr, state->parity, size, 0);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to fix any error.\n");
exit(EXIT_FAILURE);
@ -1198,7 +1198,7 @@ void state_check(struct snapraid_state* state, int fix, block_off_t blockstart,
if (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_create(qarity_ptr, state->qarity, size);
ret = parity_create(qarity_ptr, state->qarity, size, 0);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to fix any error.\n");
exit(EXIT_FAILURE);

View file

@ -51,12 +51,54 @@ block_off_t parity_resize(struct snapraid_state* state)
return parity_block;
}
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size)
void parity_overflow(struct snapraid_state* state, data_off_t size)
{
tommy_node* i;
block_off_t blockalloc;
int first = 1;
/* don't report if everything is outside or if the file is not accessible */
if (size == 0) {
return;
}
blockalloc = size / state->block_size;
/* for all disks */
for(i=state->disklist;i!=0;i=i->next) {
struct snapraid_disk* disk = i->data;
tommy_node* j;
/* for all files */
for(j=disk->filelist;j!=0;j=j->next) {
struct snapraid_file* file = j->data;
if (file->blockmax > 0) {
if (file->blockvec[0].parity_pos > blockalloc) {
if (state->gui) {
fprintf(stderr, "outofparity:%s:%s\n", disk->name, file->sub);
fflush(stderr);
}
if (first) {
first = 0;
printf("Files outside the parity:\n");
}
printf("OutOfParity '%s%s'\n", disk->dir, file->sub);
}
}
}
}
}
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size, 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) {
@ -71,10 +113,14 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
goto bail;
}
/* get the size of the exising data */
/* get the size of the existing data */
parity->valid_size = parity->st.st_size;
if (out_size)
*out_size = parity->st.st_size;
if (parity->st.st_size < size) {
int f_ret;
int f_errno;
#if HAVE_FALLOCATE
/* allocate real space using the specific Linux fallocate() operation. */
/* If the underline filesystem doesn't support it, this operation fails, */
@ -100,11 +146,27 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
/* allocate using a sparse file */
ret = ftruncate(parity->f, size);
#endif
/* save the state of the grow operation */
f_ret = ret;
f_errno = errno;
/* reget the stat info */
ret = fstat(parity->f, &parity->st);
if (ret != 0) {
if (errno == ENOSPC) {
fprintf(stderr, "Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
goto bail;
}
/* return the new size */
if (out_size)
*out_size = parity->st.st_size;
/* now check the error */
if (f_ret != 0) {
if (f_errno == ENOSPC) {
fprintf(stderr, "Failed to grow parity file '%s' to size %"PRIu64" due lack of space.\n", parity->path, size);
} else {
fprintf(stderr, "Error growing parity file '%s' to size %"PRIu64". Do you have enough space? %s.\n", parity->path, size, strerror(errno));
fprintf(stderr, "Error growing parity file '%s' to size %"PRIu64". Do you have enough space? %s.\n", parity->path, size, strerror(f_errno));
}
goto bail;
}
@ -115,7 +177,18 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s
goto bail;
}
/* adjust the size to the truncated size */
/* reget the stat info */
ret = fstat(parity->f, &parity->st);
if (ret != 0) {
fprintf(stderr, "Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
goto bail;
}
/* return the new real size */
if (out_size)
*out_size = parity->st.st_size;
/* adjust the valid to the new size */
parity->valid_size = size;
}
@ -310,3 +383,4 @@ int parity_read(struct snapraid_parity* parity, block_off_t pos, unsigned char*
return block_size;
}

View file

@ -34,9 +34,15 @@ struct snapraid_parity {
block_off_t parity_resize(struct snapraid_state* state);
/**
* Creates the parity file.
* Reports all the files outside the specified parity size.
*/
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size);
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.
*/
int parity_create(struct snapraid_parity* parity, const char* path, data_off_t size, data_off_t* out_size);
/**
* Opens an already existing parity file.

7
sync.c
View file

@ -353,6 +353,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
{
block_off_t blockmax;
data_off_t size;
data_off_t size_after;
tommy_node* i;
int ret;
struct snapraid_parity parity;
@ -394,16 +395,18 @@ 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);
ret = parity_create(parity_ptr, state->parity, size, &size_after);
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 (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_create(qarity_ptr, state->qarity, size);
ret = parity_create(qarity_ptr, state->qarity, size, &size_after);
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);
}