Reuses previous .unrecoverable files to help multistep recovering.

This commit is contained in:
Andrea Mazzoleni 2014-01-26 10:17:13 +01:00
parent f005009f4b
commit d43bd8e928
3 changed files with 45 additions and 32 deletions

View file

@ -10,6 +10,9 @@ SnapRAID HISTORY
But any new data added will be protected if you are using
enough parity to fix both the silent error and at least
another potential error.
* In "fix", if a previous attempt was made, resulting in a
.unrecoverable file, uses this file as starting point for the
new attempt.
* New source code organization. The RAID engine is now
an external component usable also in other projects.

17
TODO
View file

@ -5,15 +5,6 @@ This is the list of TODO items for SnapRAID.
- Next
* When renaming to .unrecoverable at now we always overwrite
a previous copy losing partial, but potentially better, file recovery.
Is it possible a better strategy ?
Maybe we can rename the unrecoverable as the real file, if the real file
is missing at the first open. This should ensure to always
get better results if the file is hashed.
Something like an incremental recovery, in case multiple fix commands
are attempted.
* Don't disable default 10d/12% if -p or -o is specified.
But check that -p0 still work.
@ -25,6 +16,14 @@ parity, but we can reuse the hash to check that the file was moved
correctly.
We can assume a file moved to another disk if it has the same name, size,
and timestamp. Directory and inode can be different.
This can be implemented with NEW blocks with HASH.
In synch, we can do the hash check of such blocks before any other operation,
before invalidating the parity of the moved files now converted in DELETED
blocks.
If an error is found, or we stop the sync, or we can use the parity of
DELETED blocks to recover the missing ones.
Missing blocks can be find by hash, using all the DELETED blocks with hash
as search base.
* Avoid to do optimized move operation if more files with
same timestamp/size are present.

View file

@ -45,32 +45,41 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
handle->truncated = 0;
handle->created = 0;
/* open for read write */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
/* flags for opening */
/* O_BINARY: open as binary file (Windows only) */
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
flags = O_RDWR | O_BINARY | O_NOFOLLOW;
/* O_SEQUENTIAL: improve performance for sequential access (Windows only) */
flags = O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open(handle->path, flags);
/* if failed for missing permission */
if (handle->f == -1 && errno == EACCES) {
/* retry without requesting write permission */
flags = O_RDONLY | O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open(handle->path, flags);
/* open for read write */
handle->f = open(handle->path, flags | O_RDWR);
/* if failed for missing write permission */
if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
/* open for real-only */
handle->f = open(handle->path, flags | O_RDONLY);
}
/* if failed for missing file */
if (handle->f == -1 && errno == ENOENT) {
/* retry creating it */
flags = O_RDWR | O_CREAT | O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
/* mark it as created */
handle->created = 1;
handle->f = open(handle->path, flags, 0600);
char path_from[PATH_MAX];
/* check if exists a .unrecoverable copy, and rename to the real one */
pathprint(path_from , sizeof(path_from), "%s.unrecoverable", handle->path);
if (rename(path_from, handle->path) == 0) {
/* open for read write */
handle->f = open(handle->path, flags | O_RDWR);
} else {
/* create it */
handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600);
if (handle->f != -1) {
/* mark it as created if really done */
handle->created = 1;
}
}
}
if (handle->f == -1) {
@ -147,14 +156,16 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int
handle->truncated = 0;
handle->created = 0;
/* open for read */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
/* flags for opening */
/* O_BINARY: open as binary file (Windows only) */
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
/* O_NOATIME: do not change access time */
flags = O_RDONLY | O_BINARY | O_NOFOLLOW;
/* O_SEQUENTIAL: improve performance for sequential access (Windows only) */
flags = O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open_noatime(handle->path, flags);
/* open for read */
handle->f = open_noatime(handle->path, flags | O_RDONLY);
if (handle->f == -1) {
/* invalidate for error */
handle->file = 0;