When renaming incomplete files, scans the full file list to take into account for fragmented files.

This commit is contained in:
Andrea Mazzoleni 2013-05-31 23:34:59 +02:00
parent f8420e1dff
commit 5fef489a25
3 changed files with 71 additions and 30 deletions

4
TODO
View file

@ -3,12 +3,10 @@ SnapRAID TODO
This is the list of TODO items for SnapRAID.
- v3.1
- v3.2
* Allow to specify the shared path to use to access remote symlink.
- v3.2
* In the import list, uses also all the blocks in the array.
But we must cover the case of bad blocks. Likely we can just check the
hash after reading, and in case, skip it, and retry with another copy.

66
check.c
View file

@ -963,6 +963,9 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* finish the fix process if it's the last block of the files */
if (fix) {
/* mark that we finished with this file */
file_flag_set(file, FILE_IS_FINISHED);
/* if the file is damaged, meaning that a fix failed */
if (file_flag_has(file, FILE_IS_DAMAGED)) {
/* rename it to .unrecoverable */
@ -1420,30 +1423,57 @@ close_and_continue:
state_progress_end(state, countpos, countmax, countsize);
bail:
/* close all the files left open */
for(j=0;j<diskmax;++j) {
/* if the file is open */
if (handle->file != 0) {
struct snapraid_file* file = handle[j].file;
ret = handle_close(&handle[j]);
if (ret == -1) {
fprintf(stderr, "DANGER! Unexpected close error in a data disk.\n");
++unrecoverable_error;
/* continue, as we are already exiting */
}
}
/* now close it */
ret = handle_close(&handle[j]);
if (ret == -1) {
fprintf(stderr, "DANGER! Unexpected close error in a data disk.\n");
++unrecoverable_error;
/* continue, as we are already exiting */
}
/* rename all the files created from scratch that have not finished the processing */
/* it happens only when aborting */
if (fix) {
/* for each disk */
for(i=0;i<diskmax;++i) {
tommy_node* node;
struct snapraid_disk* disk;
/* if we closed the file now, it means that we are aborting the execution */
/* and if the file was originally missing, we have to throw it away */
/* to ensure that at the next run we will retry to fix it */
/* in case we select to undelete missing files */
if (fix && file_flag_has(file, FILE_IS_CREATED)) {
/* rename it to .unrecoverable */
if (!handle[i].disk)
continue;
/* for each file in the disk */
disk = handle[i].disk;
node = disk->filelist;
while (node) {
char path[PATH_MAX];
char path_to[PATH_MAX];
struct snapraid_file* file;
pathprint(path, sizeof(path), "%s%s", handle[j].disk->dir, file->sub);
pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", handle[j].disk->dir, file->sub);
file = node->data;
node = node->next; /* next node */
/* if the file was not created, meaning that it was already existing */
if (!file_flag_has(file, FILE_IS_CREATED)) {
/* nothing to do */
continue;
}
/* if processing was finished */
if (file_flag_has(file, FILE_IS_FINISHED)) {
/* nothing to do */
continue;
}
/* if the file was originally missing, and processing not yet finished */
/* we have to throw it away to ensure that at the next run we will retry */
/* to fix it, in case we select to undelete missing files */
/* rename it to .unrecoverable */
pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
ret = rename(path, path_to);
if (ret != 0) {

31
elem.h
View file

@ -136,41 +136,54 @@ struct snapraid_block {
#define BLOCK_EMPTY 0
/**
* If it's seen as present.
* It's used only in sync.
* If a file is present in the disk.
* It's used only in scan to detect present and missing files.
*/
#define FILE_IS_PRESENT 0x01
/**
* If it's an excluded file from the processing.
* It's used in sync/check/fix.
* It's used in both check and fix to mark files to exclude from the processing.
*/
#define FILE_IS_EXCLUDED 0x02
/**
* If the file was originally larger, and then truncated to the expected suze.
* It's used in check/fix to avoid to report this condition more than one time.
* If the file was originally larger, and then truncated to the expected size.
* It's used only in check to avoid to report this condition more than one time,
* in case the file is opened multiple times.
* In fix it's not used, because the size is fixed just after the first opening.
*/
#define FILE_IS_LARGER 0x04
/**
* If a fix was attempted but it failed.
* It's used only in fix.
* It's used only in fix to mark that some data is unrecoverable.
*/
#define FILE_IS_DAMAGED 0x08
/**
* If a fix was done.
* It's used only in fix.
* It's used only in fix to mark that some data was recovered.
*/
#define FILE_IS_FIXED 0x10
/**
* If the file was originally missing, and it's created in the fix process.
* It's used only in fix.
* If the file was originally missing, and it was created in the fix process.
* It's used only in fix to mark files recovered from scratch,
* meaning that they don't have any previous content.
* This is important because it means that deleting them, you are not going
* to lose something that cannot be recovered.
* Note that excluded files won't ever get this flag.
*/
#define FILE_IS_CREATED 0x20
/**
* If the file has completed its processing, meaning that it won't be opened anymore.
* It's used only in fix to mark when we finish processing one file.
* Note that excluded files won't ever get this flag.
*/
#define FILE_IS_FINISHED 0x40
#define FILE_IS_HARDLINK 0x100 /**< If it's an hardlink. */
#define FILE_IS_SYMLINK 0x200 /**< If it's a file symlink. */
#define FILE_IS_SYMDIR 0x400 /**< If it's a dir symlink for Windows. Not yet supported. */