mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Prints list of files outside the parity if growing is not possible.
This commit is contained in:
parent
3a8f21a839
commit
8373233f25
6 changed files with 114 additions and 26 deletions
7
HISTORY
7
HISTORY
|
|
@ -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
28
TODO
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
4
check.c
4
check.c
|
|
@ -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);
|
||||
|
|
|
|||
84
parity.c
84
parity.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
10
parity.h
10
parity.h
|
|
@ -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
7
sync.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue