mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Adds a check to prevent to zeroing a file as typical ext4 behaviour after a crash.
Changes the default block size from 128 to 256 kB. Write the block size in the state file to prevent a mismatch value from the configuration.
This commit is contained in:
parent
b9b8fd0bb8
commit
1720854353
6 changed files with 99 additions and 71 deletions
10
scan.c
10
scan.c
|
|
@ -108,6 +108,14 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
file->is_present = 1;
|
||||
return;
|
||||
} else {
|
||||
/* do a safety check to ensure that the common ext4 case of zeroing */
|
||||
/* the size of a file after a crash doesn't propagate to the backup */
|
||||
if (file->size != 0 && st->st_size == 0) {
|
||||
fprintf(stderr, "The file '%s' in disk '%s' at dir '%s' has zero size!\n", sub, disk->name, disk->dir);
|
||||
fprintf(stderr, "If it's really what you want to do, use 'snapraid --force sync\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* remove and reinsert it */
|
||||
++scan->count_change;
|
||||
--scan->count_insert;
|
||||
|
|
@ -241,7 +249,7 @@ void state_scan(struct snapraid_state* state)
|
|||
if (scan[i].count_equal == 0 && scan[i].count_remove != 0) {
|
||||
if (!state->force) {
|
||||
fprintf(stderr, "All the file in disk '%s' at dir '%s' are missing!\n", disk->name, disk->dir);
|
||||
fprintf(stderr, "If it's really what you want to do, use 'snapraid -f sync\n");
|
||||
fprintf(stderr, "If it's really what you want to do, use 'snapraid --force sync\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ exclude /lost+found/
|
|||
|
||||
# Define the block size in kilo bytes (1024 bytes).
|
||||
# Format: "block_size SIZE_IN_KB"
|
||||
# Default value is 128 -> 128 kilo bytes
|
||||
block_size 128
|
||||
# Default value is 256 -> 256 kilo bytes
|
||||
block_size 256
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ Configuration
|
|||
|
||||
=block_size SIZE_IN_KILOBYTES
|
||||
Defines the basic block size in kilo bytes of
|
||||
the redundancy blocks. The default is 128 and it should
|
||||
the redundancy blocks. The default is 256 and it should
|
||||
work for most conditions.
|
||||
You should use this option only if you do not have enough
|
||||
memory to run SnapRAID.
|
||||
|
|
@ -162,10 +162,10 @@ Configuration
|
|||
size in bytes of your disk array, and BS is the block size
|
||||
in bytes.
|
||||
|
||||
For example with 6 disk of 2 TB and a block size of 128 kB you
|
||||
For example with 6 disk of 2 TB and a block size of 256 kB you
|
||||
have:
|
||||
|
||||
:memory = (6 * 2 * 2^40) * 24 / (128 * 2^10) = 2.3 GB
|
||||
:memory = (6 * 2 * 2^40) * 24 / (256 * 2^10) = 1.1 GB
|
||||
|
||||
An example of a typical configuration is:
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ This option can be used many times.
|
|||
block_size SIZE_IN_KILOBYTES
|
||||
</strong></td></tr><tr><td>
|
||||
Defines the basic block size in kilo bytes of
|
||||
the redundancy blocks. The default is 128 and it should
|
||||
the redundancy blocks. The default is 256 and it should
|
||||
work for most conditions.
|
||||
You should use this option only if you do not have enough
|
||||
memory to run SnapRAID.
|
||||
|
|
@ -243,13 +243,13 @@ in bytes.
|
|||
</table>
|
||||
<p>
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="5%"></td><td width="95%">
|
||||
For example with 6 disk of 2 TB and a block size of 128 kB you
|
||||
For example with 6 disk of 2 TB and a block size of 256 kB you
|
||||
have:
|
||||
</td></tr></table>
|
||||
<p>
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="5%"></td><td width="95%">
|
||||
<pre>
|
||||
memory = (6 * 2 * 2^40) * 24 / (128 * 2^10) = 2.3 GB
|
||||
memory = (6 * 2 * 2^40) * 24 / (256 * 2^10) = 1.1 GB
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ it should contains the following options:
|
|||
|
||||
block_size SIZE_IN_KILOBYTES
|
||||
Defines the basic block size in kilo bytes of
|
||||
the redundancy blocks. The default is 128 and it should
|
||||
the redundancy blocks. The default is 256 and it should
|
||||
work for most conditions.
|
||||
You should use this option only if you do not have enough
|
||||
memory to run SnapRAID.
|
||||
|
|
@ -178,10 +178,10 @@ it should contains the following options:
|
|||
size in bytes of your disk array, and BS is the block size
|
||||
in bytes.
|
||||
|
||||
For example with 6 disk of 2 TB and a block size of 128 kB you
|
||||
For example with 6 disk of 2 TB and a block size of 256 kB you
|
||||
have:
|
||||
|
||||
memory = (6 * 2 * 2^40) * 24 / (128 * 2^10) = 2.3 GB
|
||||
memory = (6 * 2 * 2^40) * 24 / (256 * 2^10) = 1.1 GB
|
||||
|
||||
An example of a typical configuration is:
|
||||
|
||||
|
|
|
|||
138
state.c
138
state.c
|
|
@ -29,7 +29,7 @@
|
|||
void state_init(struct snapraid_state* state)
|
||||
{
|
||||
state->verbose = 0;
|
||||
state->block_size = 128*1024; /* default 128 kB */
|
||||
state->block_size = 256 * 1024; /* default 256 kB */
|
||||
state->content[0] = 0;
|
||||
state->parity[0] = 0;
|
||||
tommy_array_init(&state->diskarr);
|
||||
|
|
@ -166,7 +166,7 @@ void state_read(struct snapraid_state* state)
|
|||
char path[PATH_MAX];
|
||||
struct snapraid_disk* disk;
|
||||
struct snapraid_file* file;
|
||||
unsigned block_index;
|
||||
block_off_t blockidx;
|
||||
unsigned line;
|
||||
unsigned count_file;
|
||||
unsigned count_block;
|
||||
|
|
@ -190,7 +190,7 @@ void state_read(struct snapraid_state* state)
|
|||
disk = 0;
|
||||
file = 0;
|
||||
line = 0;
|
||||
block_index = 0;
|
||||
blockidx = 0;
|
||||
while (1) {
|
||||
char buffer[TEXT_LINE_MAX];
|
||||
char* tag;
|
||||
|
|
@ -218,7 +218,66 @@ void state_read(struct snapraid_state* state)
|
|||
tag = s;
|
||||
s = strtoken(s);
|
||||
|
||||
if (strcmp(tag, "file") == 0) {
|
||||
if (strcmp(tag, "blk") == 0) {
|
||||
char* pos;
|
||||
char* hash;
|
||||
block_off_t v_pos;
|
||||
struct snapraid_block* block;
|
||||
char* e;
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "Unexpected 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pos = s;
|
||||
s = strtoken(s);
|
||||
hash = s;
|
||||
|
||||
ret = stru32(pos, &v_pos);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (blockidx >= file->blockmax) {
|
||||
fprintf(stderr, "Internal inconsistency in 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
block = &file->blockvec[blockidx];
|
||||
|
||||
if (block->parity_pos != POS_INVALID) {
|
||||
fprintf(stderr, "Internal inconsistency in 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
block->parity_pos = v_pos;
|
||||
|
||||
/* set the hash only if present */
|
||||
if (*hash != 0) {
|
||||
e = strdechex(block->hash, HASH_MAX, hash);
|
||||
if (e) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
block->is_hashed = 1;
|
||||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_grow(&disk->blockarr, block->parity_pos + 1);
|
||||
tommy_array_set(&disk->blockarr, block->parity_pos, block);
|
||||
|
||||
/* check for termination of the block list */
|
||||
++blockidx;
|
||||
if (blockidx == file->blockmax) {
|
||||
file = 0;
|
||||
disk = 0;
|
||||
}
|
||||
|
||||
/* stat */
|
||||
++count_block;
|
||||
} else if (strcmp(tag, "file") == 0) {
|
||||
char* name;
|
||||
char* size;
|
||||
char* mtime;
|
||||
|
|
@ -276,75 +335,30 @@ void state_read(struct snapraid_state* state)
|
|||
tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
|
||||
|
||||
/* start the block allocation of the file */
|
||||
block_index = 0;
|
||||
blockidx = 0;
|
||||
|
||||
/* check for empty file */
|
||||
if (block_index == file->blockmax) {
|
||||
if (blockidx == file->blockmax) {
|
||||
file = 0;
|
||||
disk = 0;
|
||||
}
|
||||
|
||||
/* stat */
|
||||
++count_file;
|
||||
} else if (strcmp(tag, "blk") == 0) {
|
||||
char* pos;
|
||||
char* hash;
|
||||
block_off_t v_pos;
|
||||
struct snapraid_block* block;
|
||||
char* e;
|
||||
} else if (strcmp(tag, "blksize") == 0) {
|
||||
block_off_t blksize;
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "Unexpected 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pos = s;
|
||||
s = strtoken(s);
|
||||
hash = s;
|
||||
|
||||
ret = stru32(pos, &v_pos);
|
||||
ret = stru32(s, &blksize);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
fprintf(stderr, "Invalid 'blksize' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (block_index >= file->blockmax) {
|
||||
fprintf(stderr, "Internal inconsistency in 'blk' specification in '%s' at line %u\n", path, line);
|
||||
if (blksize != state->block_size) {
|
||||
fprintf(stderr, "Mismatching 'blksize' and 'block_size' specification in '%s' at line %u\n", path, line);
|
||||
fprintf(stderr, "Please restore the 'block_size' value in the configuration file to '%u'\n", blksize / 1024);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
block = &file->blockvec[block_index];
|
||||
|
||||
if (block->parity_pos != POS_INVALID) {
|
||||
fprintf(stderr, "Internal inconsistency in 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
block->parity_pos = v_pos;
|
||||
|
||||
/* set the hash only if present */
|
||||
if (*hash != 0) {
|
||||
e = strdechex(block->hash, HASH_MAX, hash);
|
||||
if (e) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
block->is_hashed = 1;
|
||||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_grow(&disk->blockarr, block->parity_pos + 1);
|
||||
tommy_array_set(&disk->blockarr, block->parity_pos, block);
|
||||
|
||||
/* check for termination of the block list */
|
||||
++block_index;
|
||||
if (block_index == file->blockmax) {
|
||||
file = 0;
|
||||
disk = 0;
|
||||
}
|
||||
|
||||
/* stat */
|
||||
++count_block;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown tag '%s' in '%s' at line%u\n", tag, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -371,6 +385,7 @@ void state_write(struct snapraid_state* state)
|
|||
unsigned i;
|
||||
unsigned count_file;
|
||||
unsigned count_block;
|
||||
int ret;
|
||||
|
||||
count_file = 0;
|
||||
count_block = 0;
|
||||
|
|
@ -384,6 +399,12 @@ void state_write(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = fprintf(f, "blksize %u\n", state->block_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing the state file '%s' in fprintf(). %s.\n", path, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* for each disk */
|
||||
for(i=0;i<tommy_array_size(&state->diskarr);++i) {
|
||||
tommy_node* j;
|
||||
|
|
@ -393,7 +414,6 @@ void state_write(struct snapraid_state* state)
|
|||
for(j=disk->filelist;j!=0;j=j->next) {
|
||||
block_off_t k;
|
||||
struct snapraid_file* file = j->data;
|
||||
int ret;
|
||||
|
||||
ret = fprintf(f,"file %s %lld %ld %s\n", disk->name, file->size, file->mtime, file->sub);
|
||||
if (ret < 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue