diff --git a/scan.c b/scan.c index 2c550134..aa5ee5c5 100644 --- a/scan.c +++ b/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); } } diff --git a/snapraid.conf.example b/snapraid.conf.example index ed6c8e7c..29abdb8b 100644 --- a/snapraid.conf.example +++ b/snapraid.conf.example @@ -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 diff --git a/snapraid.d b/snapraid.d index b41a03ba..f1f93dc2 100644 --- a/snapraid.d +++ b/snapraid.d @@ -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: diff --git a/snapraid.html b/snapraid.html index ac625d2d..452145eb 100644 --- a/snapraid.html +++ b/snapraid.html @@ -232,7 +232,7 @@ This option can be used many times. block_size SIZE_IN_KILOBYTES
| -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 |
diff --git a/snapraid.txt b/snapraid.txt
index fb70cd74..ed867f5f 100644
--- a/snapraid.txt
+++ b/snapraid.txt
@@ -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:
diff --git a/state.c b/state.c
index fd0a3259..5559a94f 100644
--- a/state.c
+++ b/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