mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Adds the --find-by-name option to find files by path instead than by inode.
This commit is contained in:
parent
1dbd801dcb
commit
191dcdf3d4
14 changed files with 356 additions and 32 deletions
3
HISTORY
3
HISTORY
|
|
@ -21,6 +21,9 @@ SnapRAID HISTORY
|
|||
recreated from scratch.
|
||||
* When getting unrecoverable errors, the printed log line now starts with
|
||||
'unrecoverable:' instead of 'error:' to allow an easier identification.
|
||||
* Added a new option '--find-by-name' to allow to sync using only the
|
||||
file path and not the inode. This is useful to avoid long sync
|
||||
when you replace one disk with another copying manually the files.
|
||||
|
||||
1.6 2011/9 - THIS UPDATE IS HIGHLY RECOMMENDED!
|
||||
===============================================
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ check-local:
|
|||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check 2>> test.log
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix 2>> test.log
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check
|
||||
echo --- Sync after all the fixes with an empty drive to test --force-empty
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v --force-empty -c $(srcdir)/test-raid6.conf sync
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check
|
||||
echo --- Delete two disks, fix and check with raid6
|
||||
rm -r test/disk1
|
||||
mkdir test/disk1
|
||||
|
|
@ -159,8 +162,9 @@ check-local:
|
|||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix 2>> test.log
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check
|
||||
echo --- Sync after all the fixes with an empty drive to test -E
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -E -c $(srcdir)/test-raid6.conf sync
|
||||
echo --- Sync after all the fixes with an empty drive to test --find-by-name
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v --find-by-name -c $(srcdir)/test-raid6.conf sync
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check
|
||||
echo --- Delete some files and create some new, sync and check in multiple steps
|
||||
rm test/disk1/4*
|
||||
rm test/disk2/5*
|
||||
|
|
|
|||
4
TODO
4
TODO
|
|
@ -7,6 +7,10 @@ This is the list of TODO items for SnapRAID.
|
|||
|
||||
* When scanning, ensure that each file is in the expected disk.
|
||||
|
||||
* If fix fails for unrecoverable parts, rename such files adding ".unrecoverable".
|
||||
|
||||
* Check and fix also empty file.
|
||||
|
||||
* When fixing, before overwriting the present file, make a copy of it just in
|
||||
case that the original file cannot be completely recovered.
|
||||
We can always open files in read-only mode, if a write is required, we close it,
|
||||
|
|
|
|||
9
elem.c
9
elem.c
|
|
@ -297,6 +297,13 @@ int file_inode_compare(const void* void_arg, const void* void_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int file_path_compare(const void* void_arg, const void* void_data)
|
||||
{
|
||||
const char* arg = void_arg;
|
||||
const struct snapraid_file* file = void_data;
|
||||
return strcmp(arg, file->sub);
|
||||
}
|
||||
|
||||
struct snapraid_link* link_alloc(const char* sub, const char* linkto)
|
||||
{
|
||||
struct snapraid_link* link;
|
||||
|
|
@ -336,6 +343,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev
|
|||
disk->first_free_block = 0;
|
||||
tommy_list_init(&disk->filelist);
|
||||
tommy_hashdyn_init(&disk->inodeset);
|
||||
tommy_hashdyn_init(&disk->pathset);
|
||||
tommy_list_init(&disk->linklist);
|
||||
tommy_hashdyn_init(&disk->linkset);
|
||||
tommy_array_init(&disk->blockarr);
|
||||
|
|
@ -352,6 +360,7 @@ void disk_free(struct snapraid_disk* disk)
|
|||
file_free(file);
|
||||
}
|
||||
tommy_hashdyn_done(&disk->inodeset);
|
||||
tommy_hashdyn_done(&disk->pathset);
|
||||
node = disk->linklist;
|
||||
while (node) {
|
||||
struct snapraid_link* link = node->data;
|
||||
|
|
|
|||
15
elem.h
15
elem.h
|
|
@ -100,6 +100,7 @@ struct snapraid_file {
|
|||
/* nodes for data structures */
|
||||
tommy_node nodelist;
|
||||
tommy_hashdyn_node nodeset;
|
||||
tommy_hashdyn_node pathset;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -125,6 +126,7 @@ struct snapraid_disk {
|
|||
block_off_t first_free_block; /**< First free searching block. */
|
||||
tommy_list filelist; /**< List of all the files. */
|
||||
tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */
|
||||
tommy_hashdyn pathset; /**< Hashtable by path of all the files. */
|
||||
tommy_list linklist; /**< List of all the links. */
|
||||
tommy_hashdyn linkset; /**< Hashtable by name of all the links. */
|
||||
tommy_array blockarr; /**< Block array of the disk. */
|
||||
|
|
@ -274,6 +276,19 @@ static inline tommy_uint32_t file_inode_hash(uint64_t inode)
|
|||
return (tommy_uint32_t)tommy_inthash_u64(inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a file with a path.
|
||||
*/
|
||||
int file_path_compare(const void* void_arg, const void* void_data);
|
||||
|
||||
/**
|
||||
* Computes the hash of a file path.
|
||||
*/
|
||||
static inline tommy_uint32_t file_path_hash(const char* sub)
|
||||
{
|
||||
return tommy_hash_u32(0, sub, strlen(sub));
|
||||
}
|
||||
|
||||
static inline int link_flag_has(struct snapraid_link* link, unsigned mask)
|
||||
{
|
||||
return (link->flag & mask) == mask;
|
||||
|
|
|
|||
57
scan.c
57
scan.c
|
|
@ -73,6 +73,7 @@ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk*
|
|||
|
||||
/* remove the file from the file containers */
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
|
||||
tommy_list_remove_existing(&disk->filelist, &file->nodelist);
|
||||
|
||||
/* deallocate */
|
||||
|
|
@ -116,6 +117,7 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk*
|
|||
|
||||
/* insert the file in the file containers */
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
|
||||
}
|
||||
|
||||
|
|
@ -125,11 +127,16 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk*
|
|||
static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, int output, struct snapraid_disk* disk, const char* sub, const struct stat* st)
|
||||
{
|
||||
struct snapraid_file* file;
|
||||
uint64_t inode;
|
||||
|
||||
/* check if the file already exists */
|
||||
inode = st->st_ino;
|
||||
file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare, &inode, file_inode_hash(inode));
|
||||
if (state->find_by_name) {
|
||||
/* check if the file path already exists */
|
||||
file = tommy_hashdyn_search(&disk->pathset, file_path_compare, sub, file_path_hash(sub));
|
||||
} else {
|
||||
/* check if the file inode already exists */
|
||||
uint64_t inode = st->st_ino;
|
||||
file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare, &inode, file_inode_hash(inode));
|
||||
}
|
||||
|
||||
if (file) {
|
||||
/* check if multiple files have the same inode */
|
||||
if (file_flag_has(file, FILE_IS_PRESENT)) {
|
||||
|
|
@ -137,7 +144,7 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
printf("warning: Ignored hardlink '%s%s'\n", disk->dir, sub);
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for file '%s%s'\n", inode, disk->dir, sub);
|
||||
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for file '%s%s'\n", st->st_ino, disk->dir, sub);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
@ -147,8 +154,36 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
/* mark as present */
|
||||
file_flag_set(file, FILE_IS_PRESENT);
|
||||
|
||||
/* if the path is different, it means a moved file */
|
||||
if (strcmp(file->sub, sub) != 0) {
|
||||
/* if the path is different, it means a moved file with the same inode */
|
||||
++scan->count_moved;
|
||||
|
||||
if (file->inode != st->st_ino) {
|
||||
fprintf(stderr, "Internal inode inconsistency for file '%s%s'\n", disk->dir, sub);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (state->gui) {
|
||||
fprintf(stderr, "scan:move:%s:%s:%s\n", disk->name, file->sub, sub);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (output) {
|
||||
printf("Move '%s%s' '%s%s'\n", disk->dir, file->sub, disk->dir, sub);
|
||||
}
|
||||
|
||||
/* remove from the set */
|
||||
tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
|
||||
|
||||
/* save the new name */
|
||||
pathcpy(file->sub, sizeof(file->sub), sub);
|
||||
|
||||
/* reinsert in the set */
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
|
||||
/* we have to save the new name */
|
||||
state->need_write = 1;
|
||||
} else if (file->inode != st->st_ino) {
|
||||
/* if the inode is different, it means a rewritten file with the same path */
|
||||
++scan->count_moved;
|
||||
|
||||
if (state->gui) {
|
||||
|
|
@ -159,8 +194,14 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
printf("Move '%s%s' '%s%s'\n", disk->dir, file->sub, disk->dir, sub);
|
||||
}
|
||||
|
||||
/* save the new name */
|
||||
pathcpy(file->sub, sizeof(file->sub), sub);
|
||||
/* remove from the set */
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
|
||||
/* save the new inode */
|
||||
file->inode = st->st_ino;
|
||||
|
||||
/* reinsert in the set */
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
|
||||
/* we have to save the new name */
|
||||
state->need_write = 1;
|
||||
|
|
|
|||
86
snapraid.1
86
snapraid.1
|
|
@ -5,6 +5,10 @@ snapraid \(hy SnapRAID Backup For Disk Arrays
|
|||
snapraid [\(hyc, \(hy\(hyconf CONFIG] [\(hyf, \(hy\(hyfilter PATTERN]
|
||||
.PD 0
|
||||
.PP
|
||||
.PD
|
||||
[\(hyN, \(hy\(hyfind\(hyby\(hyname]
|
||||
.PD 0
|
||||
.PP
|
||||
.PD
|
||||
[\(hyZ, \(hy\(hyforce\(hyzero] [\(hyE, \(hy\(hyforce\(hyempty]
|
||||
.PD 0
|
||||
|
|
@ -333,6 +337,17 @@ pattern specifications.
|
|||
This option can be used many times.
|
||||
In Unix, ensure to quote globbing chars if used.
|
||||
.TP
|
||||
.B \(hyN, \(hy\(hyfind\(hyby\(hyname
|
||||
When syncing finds the files by name instead than by inode.
|
||||
This option allows a fast sync command after having replaced
|
||||
one physical disk with another copying manually the files.
|
||||
Without this option the \(cqsync\(cq command would recognize that
|
||||
the files were copied to a different disk, and will resync
|
||||
them all. Instead, with this option a file with the correct
|
||||
name, size and time will be assumed identical at the previous
|
||||
one.
|
||||
This option has effect only on the \(cqsync\(cq and \(cqdiff\(cq commands.
|
||||
.TP
|
||||
.B \(hyZ, \(hy\(hyforce\(hyzero
|
||||
Forces the insecure operation of syncing a file with zero
|
||||
size that before was not.
|
||||
|
|
@ -698,6 +713,77 @@ snapraid \(hyf \(a"*.mp3\(a" check
|
|||
.PP
|
||||
In Unix, when using globbing chars in the command line, you have to quote them.
|
||||
Otherwise the shell will try to expand them.
|
||||
.SH RECOVERING
|
||||
The worst happened, and you lost a disk!
|
||||
.PP
|
||||
DO NOT PANIC! You will be able to recover it!
|
||||
.PP
|
||||
The first thing you have to do is to avoid futher changes at you disk array.
|
||||
Disable any remote connections to it, any scheduled processes, including any
|
||||
scheduled SnapRAID nightly sync.
|
||||
.PP
|
||||
Then proceed with the following steps.
|
||||
.SS STEP 1 \(hy> Reconfigure
|
||||
You need some space to recover, even better if you have already an additional
|
||||
disk, but in case also an external USB or remote one is enough.
|
||||
.PP
|
||||
Change the SnapRAID configuration and change the \(cqdisk\(cq directory
|
||||
of the failed disk to point to the new empty space.
|
||||
.SS STEP 2 \(hy> Fix
|
||||
Run the fix command, storing the log in an external file with:
|
||||
.PP
|
||||
.RS 4
|
||||
snapraid fix 2>fix.log
|
||||
.PD 0
|
||||
.PP
|
||||
.PD
|
||||
.RE
|
||||
.PP
|
||||
This command will take a long time.
|
||||
.PP
|
||||
Take care that you need also few GB free to store the fix.log file, so run it
|
||||
from a disk with some free space.
|
||||
.PP
|
||||
Now you have recovered all the recoverable. If some file is partly or totally
|
||||
unrecoverable, it will be renamed adding the \(a".unrecoverable\(a" extension.
|
||||
.PP
|
||||
You can get a detailed list of all the unrecoverable blocks in the fix.log file
|
||||
checking all the lines starting with \(a"unrecoverable:\(a"
|
||||
.PP
|
||||
If you are not satified of the recovering, you can retry it as many time you wish.
|
||||
For example, if you have moved away some files from other disks after the last \(cqsync\(cq,
|
||||
you can retry to put them inplace, and retry the \(cqfix\(cq.
|
||||
.PP
|
||||
If you are satisfied of the recovering, you can now proceed synching the array,
|
||||
but take care that after synching you will no more able to retry the
|
||||
\(cqfix\(cq command!
|
||||
.SS STEP 3 \(hy> Sync
|
||||
Run the \(cqsync\(cq command to resyncronize the array with the new disk.
|
||||
.PP
|
||||
To avoid a long time sync you have to use the \(cq\(hy\(hyfind\(hyby\(hyname\(cq option to
|
||||
tell SnapRAID to ignore the fact that all the recovered files are now in
|
||||
a different physical disk, and they don\(cqt need to be synched.
|
||||
.PP
|
||||
.RS 4
|
||||
snapraid \(hy\(hyfind\(hyby\(hyname sync
|
||||
.PD 0
|
||||
.PP
|
||||
.PD
|
||||
.RE
|
||||
.PP
|
||||
If everything was recovered, this command is immediate.
|
||||
.SS STEP 4 \(hy> Check
|
||||
As paranoid check, you can now run a whole \(cqcheck\(cq command to ensure that
|
||||
everything is OK.
|
||||
.PP
|
||||
.RS 4
|
||||
snapraid check
|
||||
.PD 0
|
||||
.PP
|
||||
.PD
|
||||
.RE
|
||||
.PP
|
||||
This command will take a long time.
|
||||
.SH CONTENT
|
||||
SnapRAID stores the list and checksums of your files in the content file.
|
||||
.PP
|
||||
|
|
|
|||
11
snapraid.c
11
snapraid.c
|
|
@ -55,6 +55,7 @@ void usage(void)
|
|||
printf("Options:\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-c, --conf FILE ", "-c") " Configuration file (default " CONF ")\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-f, --filter PATTERN", "-f") " Filter the files to processs\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-N, --find-by-name ", "-N") " Find the file by name instead than by inode\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force synching of files that get zero size\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force synching of disks that get empty\n");
|
||||
printf(" " SWITCH_GETOPT_LONG("-s, --start BLKSTART", "-s") " Start from the specified block number\n");
|
||||
|
|
@ -78,6 +79,7 @@ struct option long_options[] = {
|
|||
{ "count", 1, 0, 't' },
|
||||
{ "force-zero", 0, 0, 'Z' },
|
||||
{ "force-empty", 0, 0, 'E' },
|
||||
{ "find-by-name", 0, 0, 'N' },
|
||||
{ "speed-test", 0, 0, 'T' },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "gui", 0, 0, 'G' }, /* undocumented GUI interface command */
|
||||
|
|
@ -93,7 +95,7 @@ struct option long_options[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#define OPTIONS "c:f:s:t:ZETvhVG"
|
||||
#define OPTIONS "c:f:s:t:ZENTvhVG"
|
||||
|
||||
volatile int global_interrupt = 0;
|
||||
|
||||
|
|
@ -119,6 +121,7 @@ int main(int argc, char* argv[])
|
|||
int gui;
|
||||
int force_zero;
|
||||
int force_empty;
|
||||
int find_by_name;
|
||||
int test_expect_unrecoverable;
|
||||
int test_expect_recoverable;
|
||||
int test_kill_after_sync;
|
||||
|
|
@ -139,6 +142,7 @@ int main(int argc, char* argv[])
|
|||
gui = 0;
|
||||
force_zero = 0;
|
||||
force_empty = 0;
|
||||
find_by_name = 0;
|
||||
test_expect_unrecoverable = 0;
|
||||
test_expect_recoverable = 0;
|
||||
test_kill_after_sync = 0;
|
||||
|
|
@ -188,6 +192,9 @@ int main(int argc, char* argv[])
|
|||
case 'E' :
|
||||
force_empty = 1;
|
||||
break;
|
||||
case 'N' :
|
||||
find_by_name = 1;
|
||||
break;
|
||||
case 'v' :
|
||||
verbose = 1;
|
||||
break;
|
||||
|
|
@ -251,7 +258,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
state_init(&state);
|
||||
|
||||
state_config(&state, conf, verbose, gui, force_zero, force_empty, test_expect_unrecoverable, test_expect_recoverable, test_skip_device);
|
||||
state_config(&state, conf, verbose, gui, force_zero, force_empty, find_by_name, test_expect_unrecoverable, test_expect_recoverable, test_skip_device);
|
||||
|
||||
if (operation == OPERATION_DIFF) {
|
||||
state_read(&state);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ disk d3 /mnt/disk3/
|
|||
# Format: "exclude /PATH/FILE"
|
||||
# Format: "exclude /PATH/DIR/"
|
||||
exclude *.bak
|
||||
exclude *.unrecoverable
|
||||
exclude /tmp/
|
||||
exclude /lost+found/
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ disk d3 I:\array\
|
|||
# Format: "exclude \PATH\FILE"
|
||||
# Format: "exclude \PATH\DIR\"
|
||||
exclude *.bak
|
||||
exclude *.unrecoverable
|
||||
exclude Thumbs.db
|
||||
exclude \$RECYCLE.BIN
|
||||
exclude \System Volume Information
|
||||
|
|
|
|||
73
snapraid.d
73
snapraid.d
|
|
@ -3,6 +3,7 @@ Name{number}
|
|||
|
||||
Synopsis
|
||||
:snapraid [-c, --conf CONFIG] [-f, --filter PATTERN]
|
||||
: [-N, --find-by-name]
|
||||
: [-Z, --force-zero] [-E, --force-empty]
|
||||
: [-s, --start BLKSTART] [-t, --count BLKCOUNT]
|
||||
: [-v, --verbose]
|
||||
|
|
@ -226,6 +227,17 @@ Options
|
|||
This option can be used many times.
|
||||
In Unix, ensure to quote globbing chars if used.
|
||||
|
||||
-N, --find-by-name
|
||||
When syncing finds the files by name instead than by inode.
|
||||
This option allows a fast sync command after having replaced
|
||||
one physical disk with another copying manually the files.
|
||||
Without this option the 'sync' command would recognize that
|
||||
the files were copied to a different disk, and will resync
|
||||
them all. Instead, with this option a file with the correct
|
||||
name, size and time will be assumed identical at the previous
|
||||
one.
|
||||
This option has effect only on the 'sync' and 'diff' commands.
|
||||
|
||||
-Z, --force-zero
|
||||
Forces the insecure operation of syncing a file with zero
|
||||
size that before was not.
|
||||
|
|
@ -466,6 +478,67 @@ Pattern
|
|||
In Unix, when using globbing chars in the command line, you have to quote them.
|
||||
Otherwise the shell will try to expand them.
|
||||
|
||||
Recovering
|
||||
The worst happened, and you lost a disk!
|
||||
|
||||
DO NOT PANIC! You will be able to recover it!
|
||||
|
||||
The first thing you have to do is to avoid futher changes at you disk array.
|
||||
Disable any remote connections to it, any scheduled processes, including any
|
||||
scheduled SnapRAID nightly sync.
|
||||
|
||||
Then proceed with the following steps.
|
||||
|
||||
STEP 1 -> Reconfigure
|
||||
You need some space to recover, even better if you have already an additional
|
||||
disk, but in case also an external USB or remote one is enough.
|
||||
|
||||
Change the SnapRAID configuration and change the 'disk' directory
|
||||
of the failed disk to point to the new empty space.
|
||||
|
||||
STEP 2 -> Fix
|
||||
Run the fix command, storing the log in an external file with:
|
||||
|
||||
:snapraid fix 2>fix.log
|
||||
|
||||
This command will take a long time.
|
||||
|
||||
Take care that you need also few GB free to store the fix.log file, so run it
|
||||
from a disk with some free space.
|
||||
|
||||
Now you have recovered all the recoverable. If some file is partly or totally
|
||||
unrecoverable, it will be renamed adding the ".unrecoverable" extension.
|
||||
|
||||
You can get a detailed list of all the unrecoverable blocks in the fix.log file
|
||||
checking all the lines starting with "unrecoverable:"
|
||||
|
||||
If you are not satified of the recovering, you can retry it as many time you wish.
|
||||
For example, if you have moved away some files from other disks after the last 'sync',
|
||||
you can retry to put them inplace, and retry the 'fix'.
|
||||
|
||||
If you are satisfied of the recovering, you can now proceed synching the array,
|
||||
but take care that after synching you will no more able to retry the
|
||||
'fix' command!
|
||||
|
||||
STEP 3 -> Sync
|
||||
Run the 'sync' command to resyncronize the array with the new disk.
|
||||
|
||||
To avoid a long time sync you have to use the '--find-by-name' option to
|
||||
tell SnapRAID to ignore the fact that all the recovered files are now in
|
||||
a different physical disk, and they don't need to be synched.
|
||||
|
||||
:snapraid --find-by-name sync
|
||||
|
||||
If everything was recovered, this command is immediate.
|
||||
|
||||
STEP 4 -> Check
|
||||
As paranoid check, you can now run a whole 'check' command to ensure that
|
||||
everything is OK.
|
||||
|
||||
:snapraid check
|
||||
|
||||
This command will take a long time.
|
||||
|
||||
Content
|
||||
SnapRAID stores the list and checksums of your files in the content file.
|
||||
|
||||
|
|
|
|||
112
snapraid.txt
112
snapraid.txt
|
|
@ -7,6 +7,7 @@
|
|||
==========
|
||||
|
||||
snapraid [-c, --conf CONFIG] [-f, --filter PATTERN]
|
||||
[-N, --find-by-name]
|
||||
[-Z, --force-zero] [-E, --force-empty]
|
||||
[-s, --start BLKSTART] [-t, --count BLKCOUNT]
|
||||
[-v, --verbose]
|
||||
|
|
@ -253,6 +254,17 @@ SnapRAID provides the following options:
|
|||
This option can be used many times.
|
||||
In Unix, ensure to quote globbing chars if used.
|
||||
|
||||
-N, --find-by-name
|
||||
When syncing finds the files by name instead than by inode.
|
||||
This option allows a fast sync command after having replaced
|
||||
one physical disk with another copying manually the files.
|
||||
Without this option the 'sync' command would recognize that
|
||||
the files were copied to a different disk, and will resync
|
||||
them all. Instead, with this option a file with the correct
|
||||
name, size and time will be assumed identical at the previous
|
||||
one.
|
||||
This option has effect only on the 'sync' and 'diff' commands.
|
||||
|
||||
-Z, --force-zero
|
||||
Forces the insecure operation of syncing a file with zero
|
||||
size that before was not.
|
||||
|
|
@ -514,8 +526,72 @@ In Unix, when using globbing chars in the command line, you have to quote them.
|
|||
Otherwise the shell will try to expand them.
|
||||
|
||||
|
||||
9 CONTENT
|
||||
=========
|
||||
9 RECOVERING
|
||||
============
|
||||
|
||||
The worst happened, and you lost a disk!
|
||||
|
||||
DO NOT PANIC! You will be able to recover it!
|
||||
|
||||
The first thing you have to do is to avoid futher changes at you disk array.
|
||||
Disable any remote connections to it, any scheduled processes, including any
|
||||
scheduled SnapRAID nightly sync.
|
||||
|
||||
Then proceed with the following steps.
|
||||
|
||||
---- 9.0.1 STEP 1 -> Reconfigure ----
|
||||
You need some space to recover, even better if you have already an additional
|
||||
disk, but in case also an external USB or remote one is enough.
|
||||
|
||||
Change the SnapRAID configuration and change the 'disk' directory
|
||||
of the failed disk to point to the new empty space.
|
||||
|
||||
---- 9.0.2 STEP 2 -> Fix ----
|
||||
Run the fix command, storing the log in an external file with:
|
||||
|
||||
snapraid fix 2>fix.log
|
||||
|
||||
This command will take a long time.
|
||||
|
||||
Take care that you need also few GB free to store the fix.log file, so run it
|
||||
from a disk with some free space.
|
||||
|
||||
Now you have recovered all the recoverable. If some file is partly or totally
|
||||
unrecoverable, it will be renamed adding the ".unrecoverable" extension.
|
||||
|
||||
You can get a detailed list of all the unrecoverable blocks in the fix.log file
|
||||
checking all the lines starting with "unrecoverable:"
|
||||
|
||||
If you are not satified of the recovering, you can retry it as many time you wish.
|
||||
For example, if you have moved away some files from other disks after the last 'sync',
|
||||
you can retry to put them inplace, and retry the 'fix'.
|
||||
|
||||
If you are satisfied of the recovering, you can now proceed synching the array,
|
||||
but take care that after synching you will no more able to retry the
|
||||
'fix' command!
|
||||
|
||||
---- 9.0.3 STEP 3 -> Sync ----
|
||||
Run the 'sync' command to resyncronize the array with the new disk.
|
||||
|
||||
To avoid a long time sync you have to use the '--find-by-name' option to
|
||||
tell SnapRAID to ignore the fact that all the recovered files are now in
|
||||
a different physical disk, and they don't need to be synched.
|
||||
|
||||
snapraid --find-by-name sync
|
||||
|
||||
If everything was recovered, this command is immediate.
|
||||
|
||||
---- 9.0.4 STEP 4 -> Check ----
|
||||
As paranoid check, you can now run a whole 'check' command to ensure that
|
||||
everything is OK.
|
||||
|
||||
snapraid check
|
||||
|
||||
This command will take a long time.
|
||||
|
||||
|
||||
10 CONTENT
|
||||
==========
|
||||
|
||||
SnapRAID stores the list and checksums of your files in the content file.
|
||||
|
||||
|
|
@ -528,24 +604,24 @@ for documentation.
|
|||
This file is read and written by the "sync" command, and only read by
|
||||
"fix" and "check".
|
||||
|
||||
9.1 blk_size SIZE
|
||||
-----------------
|
||||
10.1 blk_size SIZE
|
||||
------------------
|
||||
|
||||
Defines the size of the block in bytes. It must match the size
|
||||
defined in the configuration file.
|
||||
|
||||
9.2 checksum CHECKSUM
|
||||
---------------------
|
||||
10.2 checksum CHECKSUM
|
||||
----------------------
|
||||
|
||||
Defines the checksum kind used. It can be "md5" or "murmur3".
|
||||
|
||||
9.3 map NAME INDEX
|
||||
------------------
|
||||
10.3 map NAME INDEX
|
||||
-------------------
|
||||
|
||||
Defines the position INDEX of the disk NAME in the parity computation.
|
||||
|
||||
9.4 file DISK SIZE TIME INODE PATH
|
||||
----------------------------------
|
||||
10.4 file DISK SIZE TIME INODE PATH
|
||||
-----------------------------------
|
||||
|
||||
Defines a file in the specified DISK.
|
||||
|
||||
|
|
@ -560,8 +636,8 @@ to recompute the parity.
|
|||
The PATH information is used in the "check" and "fix" commands
|
||||
to identify the file.
|
||||
|
||||
9.5 blk BLOCK HASH
|
||||
------------------
|
||||
10.5 blk BLOCK HASH
|
||||
-------------------
|
||||
|
||||
Defines the ordered parity block list used by the last defined file.
|
||||
|
||||
|
|
@ -571,8 +647,8 @@ BLOCK is the block position in the "parity" file.
|
|||
HASH is the hash of the block. In the last block of the file,
|
||||
the HASH is the hash of only the used part of the block.
|
||||
|
||||
9.6 inv BLOCK [HASH]
|
||||
--------------------
|
||||
10.6 inv BLOCK [HASH]
|
||||
---------------------
|
||||
|
||||
Like "blk", but inform that the parity of this block is invalid.
|
||||
|
||||
|
|
@ -582,7 +658,7 @@ This field is used only when you interrupt manually the "sync"
|
|||
command.
|
||||
|
||||
|
||||
10 PARITY
|
||||
11 PARITY
|
||||
=========
|
||||
|
||||
SnapRAID stores the redundancy information of your array in the parity
|
||||
|
|
@ -607,7 +683,7 @@ because it's the last block of a file, it's assumed as filled with 0
|
|||
at the end.
|
||||
|
||||
|
||||
11 ENCODING
|
||||
12 ENCODING
|
||||
===========
|
||||
|
||||
SnapRAID in Unix ignores any encoding. It simply read and stores the
|
||||
|
|
@ -624,13 +700,13 @@ redirect the console output to a file, the resulting file is always
|
|||
in the UTF-8 format.
|
||||
|
||||
|
||||
12 COPYRIGHT
|
||||
13 COPYRIGHT
|
||||
============
|
||||
|
||||
This file is Copyright (C) 2011 Andrea Mazzoleni
|
||||
|
||||
|
||||
13 SEE ALSO
|
||||
14 SEE ALSO
|
||||
===========
|
||||
|
||||
rsync(1)
|
||||
|
|
|
|||
5
state.c
5
state.c
|
|
@ -27,6 +27,7 @@ void state_init(struct snapraid_state* state)
|
|||
state->gui = 0;
|
||||
state->force_zero = 0;
|
||||
state->force_empty = 0;
|
||||
state->find_by_name = 0;
|
||||
state->expect_unrecoverable = 0;
|
||||
state->expect_recoverable = 0;
|
||||
state->need_write = 0;
|
||||
|
|
@ -129,7 +130,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, i
|
|||
}
|
||||
}
|
||||
|
||||
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable, int skip_device)
|
||||
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_device)
|
||||
{
|
||||
STREAM* f;
|
||||
unsigned line;
|
||||
|
|
@ -138,6 +139,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
state->gui = gui;
|
||||
state->force_zero = force_zero;
|
||||
state->force_empty = force_empty;
|
||||
state->find_by_name = find_by_name;
|
||||
state->expect_unrecoverable = expect_unrecoverable;
|
||||
state->expect_recoverable = expect_recoverable;
|
||||
|
||||
|
|
@ -757,6 +759,7 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* insert the file in the file containers */
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
|
||||
|
||||
/* start the block allocation of the file */
|
||||
|
|
|
|||
3
state.h
3
state.h
|
|
@ -34,6 +34,7 @@ struct snapraid_state {
|
|||
int gui; /**< Gui output. */
|
||||
int force_zero; /**< Forced dangerous operations of synching file now with zero size. */
|
||||
int force_empty; /**< Forced dangerous operations of synching disk now empty. */
|
||||
int find_by_name; /**< Forced dangerous operations of synching a rewritten disk. */
|
||||
int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */
|
||||
int expect_recoverable; /**< Expect presence of recoverable error in checking. */
|
||||
int need_write; /**< If the state is changed. */
|
||||
|
|
@ -65,7 +66,7 @@ void state_done(struct snapraid_state* state);
|
|||
/**
|
||||
* Read the configuration file.
|
||||
*/
|
||||
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable, int skip_device);
|
||||
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_device);
|
||||
|
||||
/**
|
||||
* Read the state.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue