mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Reuses previous .unrecoverable files to help multistep recovering.
This commit is contained in:
parent
f005009f4b
commit
d43bd8e928
3 changed files with 45 additions and 32 deletions
3
HISTORY
3
HISTORY
|
|
@ -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
17
TODO
|
|
@ -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.
|
||||
|
|
|
|||
57
handle.c
57
handle.c
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue