diff --git a/cov/cmdline/check.c.func-sort-c.html b/cov/cmdline/check.c.func-sort-c.html
index 9d707518..2de16b5f 100644
--- a/cov/cmdline/check.c.func-sort-c.html
+++ b/cov/cmdline/check.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -61,31 +61,27 @@
| block_is_enabled |
- 1866664 |
+ 1869102 |
| file_post |
- 933332 |
+ 934551 |
| repair |
- 869089 |
+ 870166 |
| blockcmp |
- 468172 |
+ 469276 |
| repair_step |
- 260805 |
+ 254143 |
| is_hash_matching |
- 209449 |
-
-
- | is_parity_matching |
- 8386 |
+ 211335 |
| state_check |
@@ -95,6 +91,10 @@
state_check_process |
118 |
+
+ | is_parity_matching |
+ 8 |
+
diff --git a/cov/cmdline/check.c.func.html b/cov/cmdline/check.c.func.html
index 9544066b..b46f8731 100644
--- a/cov/cmdline/check.c.func.html
+++ b/cov/cmdline/check.c.func.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -61,31 +61,31 @@
| block_is_enabled |
- 1866664 |
+ 1869102 |
| blockcmp |
- 468172 |
+ 469276 |
| file_post |
- 933332 |
+ 934551 |
| is_hash_matching |
- 209449 |
+ 211335 |
| is_parity_matching |
- 8386 |
+ 8 |
| repair |
- 869089 |
+ 870166 |
| repair_step |
- 260805 |
+ 254143 |
| state_check |
diff --git a/cov/cmdline/check.c.gcov.html b/cov/cmdline/check.c.gcov.html
index d2e357c6..2e56b65e 100644
--- a/cov/cmdline/check.c.gcov.html
+++ b/cov/cmdline/check.c.gcov.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -129,64 +129,64 @@
67 : * Check if a block hash matches the specified buffer.
68 : * Return ==0 if equal
69 : */
- 70 468172 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero)
+ 70 469276 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero)
71 : {
72 : unsigned char hash[HASH_SIZE];
73 :
74 : /* now compute the hash of the valid part */
- 75 468172 : if (rehash) {
- 76 22270 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size);
+ 75 469276 : if (rehash) {
+ 76 0 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size);
77 : } else {
- 78 445902 : memhash(state->hash, state->hashseed, hash, buffer, pos_size);
+ 78 469276 : memhash(state->hash, state->hashseed, hash, buffer, pos_size);
79 : }
80 :
81 : /* compare the hash */
- 82 468172 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
- 83 13872 : return -1;
+ 82 469276 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 83 13920 : return -1;
84 : }
85 :
86 : /* compare to the end of the block */
- 87 454300 : if (pos_size < state->block_size) {
- 88 187749 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) {
- 89 24 : return -1;
+ 87 455356 : if (pos_size < state->block_size) {
+ 88 188035 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) {
+ 89 18 : return -1;
90 : }
91 : }
92 :
- 93 454276 : return 0;
+ 93 455338 : return 0;
94 : }
95 :
96 : /**
97 : * Check if the hash of all the failed block we are expecting to recover are now matching.
98 : */
- 99 209449 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero)
+ 99 211335 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero)
100 : {
101 : unsigned j;
102 : int hash_checked;
103 :
- 104 209449 : hash_checked = 0; /* keep track if we check at least one block */
+ 104 211335 : hash_checked = 0; /* keep track if we check at least one block */
105 :
106 : /* check if the recovered blocks are OK */
- 107 668247 : for (j = 0; j < failed_count; ++j) {
+ 107 671195 : for (j = 0; j < failed_count; ++j) {
108 : /* if we are expected to recover this block */
- 109 472694 : if (!failed[failed_map[j]].is_outofdate
+ 109 473798 : if (!failed[failed_map[j]].is_outofdate
110 : /* if the block has a hash to check */
- 111 468172 : && block_has_updated_hash(failed[failed_map[j]].block)
+ 111 469276 : && block_has_updated_hash(failed[failed_map[j]].block)
112 : ) {
113 : /* if a hash doesn't match, fail the check */
- 114 468172 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size);
- 115 468172 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) {
- 116 13896 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]);
- 117 13896 : return 0;
+ 114 469276 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size);
+ 115 469276 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) {
+ 116 13938 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]);
+ 117 13938 : return 0;
118 : }
119 :
- 120 454276 : hash_checked = 1;
+ 120 455338 : hash_checked = 1;
121 : }
122 : }
123 :
124 : /* if nothing checked, we reject it */
125 : /* note that we are excluding this case at upper level */
126 : /* but checking again doesn't hurt */
- 127 195553 : if (!hash_checked) {
+ 127 197397 : if (!hash_checked) {
128 : /* LCOV_EXCL_START */
129 : return 0;
130 : /* LCOV_EXCL_STOP */
@@ -194,23 +194,23 @@
132 :
133 : /* if we checked something, and no block failed the check */
134 : /* recompute all the redundancy information */
- 135 195553 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 136 195553 : return 1;
+ 135 197397 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 136 197397 : return 1;
137 : }
138 :
139 : /**
140 : * Check if specified parity is now matching with a recomputed one.
141 : */
- 142 8386 : static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, void** buffer, void** buffer_recov)
+ 142 8 : static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, void** buffer, void** buffer_recov)
143 : {
144 : /* recompute parity, note that we don't need parity over i */
- 145 8386 : raid_gen(diskmax, i + 1, state->block_size, buffer);
+ 145 8 : raid_gen(diskmax, i + 1, state->block_size, buffer);
146 :
147 : /* if the recovered parity block matches */
- 148 8386 : if (memcmp(buffer[diskmax + i], buffer_recov[i], state->block_size) == 0) {
+ 148 8 : if (memcmp(buffer[diskmax + i], buffer_recov[i], state->block_size) == 0) {
149 : /* recompute all the redundancy information */
- 150 8386 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 151 8386 : return 1;
+ 150 8 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 151 8 : return 1;
152 : }
153 :
154 0 : return 0;
@@ -221,7 +221,7 @@
159 : * Return <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success.
160 : * If success, the parity are computed in the buffer variable.
161 : */
- 162 260805 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
+ 162 254143 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
163 : {
164 : unsigned i, n;
165 : int error;
@@ -230,7 +230,7 @@
168 : int ip[LEV_MAX];
169 :
170 : /* no fix required, already checked at higher level, but just to be sure */
- 171 260805 : if (failed_count == 0) {
+ 171 254143 : if (failed_count == 0) {
172 : /* LCOV_EXCL_START */
173 : /* recompute only the parity */
174 : raid_gen(diskmax, state->level, state->block_size, buffer);
@@ -238,52 +238,52 @@
176 : /* LCOV_EXCL_STOP */
177 : }
178 :
- 179 260805 : n = state->level;
- 180 260805 : error = 0;
+ 179 254143 : n = state->level;
+ 180 254143 : error = 0;
181 :
182 : /* setup vector of failed disk indexes */
- 183 908349 : for (i = 0; i < failed_count; ++i)
- 184 647544 : id[i] = failed[failed_map[i]].index;
+ 183 894073 : for (i = 0; i < failed_count; ++i)
+ 184 639930 : id[i] = failed[failed_map[i]].index;
185 :
186 : /* check if there is at least a failed block that can be checked for correctness using the hash */
187 : /* if there isn't, we have to sacrifice a parity block to check that the result is correct */
- 188 260805 : has_hash = 0;
- 189 908349 : for (i = 0; i < failed_count; ++i) {
+ 188 254143 : has_hash = 0;
+ 189 894073 : for (i = 0; i < failed_count; ++i) {
190 : /* if we are expected to recover this block */
- 191 647544 : if (!failed[failed_map[i]].is_outofdate
+ 191 639930 : if (!failed[failed_map[i]].is_outofdate
192 : /* if the block has a hash to check */
- 193 638500 : && block_has_updated_hash(failed[failed_map[i]].block)
+ 193 630886 : && block_has_updated_hash(failed[failed_map[i]].block)
194 : )
- 195 630114 : has_hash = 1;
+ 195 630878 : has_hash = 1;
196 : }
197 :
198 : /* if we don't have a hash, but we have an extra parity */
199 : /* (strictly-less failures than number of parities) */
- 200 260805 : if (!has_hash && failed_count < n) {
+ 200 254143 : if (!has_hash && failed_count < n) {
201 : /* number of parity to use, one more to check the recovering */
- 202 8386 : unsigned r = failed_count + 1;
+ 202 8 : unsigned r = failed_count + 1;
203 :
204 : /* all combinations (r of n) parities */
- 205 8386 : combination_first(r, n, ip);
+ 205 8 : combination_first(r, n, ip);
206 : do {
207 : /* if a parity is missing, do nothing */
- 208 25158 : for (i = 0; i < r; ++i) {
- 209 16772 : if (buffer_recov[ip[i]] == 0)
+ 208 24 : for (i = 0; i < r; ++i) {
+ 209 16 : if (buffer_recov[ip[i]] == 0)
210 0 : break;
211 : }
- 212 8386 : if (i != r)
+ 212 8 : if (i != r)
213 0 : continue;
214 :
215 : /* copy the parities to use, one less because the last is used for checking */
- 216 16772 : for (i = 0; i < r - 1; ++i)
- 217 8386 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
+ 216 16 : for (i = 0; i < r - 1; ++i)
+ 217 8 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
218 :
219 : /* recover using one less parity, the ip[r-1] one */
- 220 8386 : raid_data(r - 1, id, ip, diskmax, state->block_size, buffer);
+ 220 8 : raid_data(r - 1, id, ip, diskmax, state->block_size, buffer);
221 :
222 : /* use the remaining ip[r-1] parity to check the result */
- 223 8386 : if (is_parity_matching(state, diskmax, ip[r - 1], buffer, buffer_recov))
- 224 8386 : return 0;
+ 223 8 : if (is_parity_matching(state, diskmax, ip[r - 1], buffer, buffer_recov))
+ 224 8 : return 0;
225 :
226 : /* log */
227 0 : log_tag("parity_error:%u:", pos);
@@ -299,54 +299,54 @@
237 :
238 : /* if we have a hash, and enough parities */
239 : /* (less-or-equal failures than number of parities) */
- 240 252419 : if (has_hash && failed_count <= n) {
+ 240 254135 : if (has_hash && failed_count <= n) {
241 : /* number of parities to use equal at the number of failures */
- 242 204707 : unsigned r = failed_count;
+ 242 206565 : unsigned r = failed_count;
243 :
244 : /* all combinations (r of n) parities */
- 245 204707 : combination_first(r, n, ip);
+ 245 206565 : combination_first(r, n, ip);
246 : do {
247 : /* if a parity is missing, do nothing */
- 248 686792 : for (i = 0; i < r; ++i) {
- 249 477343 : if (buffer_recov[ip[i]] == 0)
+ 248 689782 : for (i = 0; i < r; ++i) {
+ 249 478447 : if (buffer_recov[ip[i]] == 0)
250 4649 : break;
251 : }
- 252 214098 : if (i != r)
+ 252 215984 : if (i != r)
253 4649 : continue;
254 :
255 : /* copy the parities to use */
- 256 682143 : for (i = 0; i < r; ++i)
- 257 472694 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
+ 256 685133 : for (i = 0; i < r; ++i)
+ 257 473798 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
258 :
259 : /* recover */
- 260 209449 : raid_data(r, id, ip, diskmax, state->block_size, buffer);
+ 260 211335 : raid_data(r, id, ip, diskmax, state->block_size, buffer);
261 :
262 : /* use the hash to check the result */
- 263 209449 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
- 264 195553 : return 0;
+ 263 211335 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
+ 264 197397 : return 0;
265 :
266 : /* log */
- 267 13896 : log_tag("parity_error:%u:", pos);
- 268 27792 : for (i = 0; i < r; ++i) {
- 269 13896 : if (i != 0)
+ 267 13938 : log_tag("parity_error:%u:", pos);
+ 268 27876 : for (i = 0; i < r; ++i) {
+ 269 13938 : if (i != 0)
270 0 : log_tag("/");
- 271 13896 : log_tag("%s", lev_config_name(ip[i]));
+ 271 13938 : log_tag("%s", lev_config_name(ip[i]));
272 : }
- 273 13896 : log_tag(":hash: Hash mismatch\n");
- 274 13896 : ++error;
- 275 37090 : } while (combination_next(r, n, ip));
+ 273 13938 : log_tag(":hash: Hash mismatch\n");
+ 274 13938 : ++error;
+ 275 37174 : } while (combination_next(r, n, ip));
276 : }
277 :
278 : /* return the number of failed attempts, or -1 if no strategy */
- 279 56866 : if (error)
- 280 9154 : return error;
+ 279 56738 : if (error)
+ 280 9168 : return error;
281 :
- 282 47712 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n",
+ 282 47570 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n",
283 : pos, failed_count, n, has_hash ? "with" : "without");
- 284 47712 : return -1;
+ 284 47570 : return -1;
285 : }
286 :
- 287 869089 : static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
+ 287 870166 : static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
288 : {
289 : int ret;
290 : int error;
@@ -355,51 +355,51 @@
293 : int something_to_recover;
294 : int something_unsynced;
295 :
- 296 869089 : error = 0;
+ 296 870166 : error = 0;
297 :
298 : /* if nothing failed, just recompute the parity */
- 299 869089 : if (failed_count == 0) {
- 300 581432 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 301 581432 : return 0;
+ 299 870166 : if (failed_count == 0) {
+ 300 580935 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 301 580935 : return 0;
302 : }
303 :
304 : /* logs the status */
- 305 1016720 : for (j = 0; j < failed_count; ++j) {
+ 305 1019108 : for (j = 0; j < failed_count; ++j) {
306 : const char* desc;
307 : const char* hash;
308 : const char* data;
- 309 729063 : struct snapraid_block* block = failed[j].block;
- 310 729063 : unsigned block_state = block_state_get(block);
+ 309 729877 : struct snapraid_block* block = failed[j].block;
+ 310 729877 : unsigned block_state = block_state_get(block);
311 :
- 312 729063 : switch (block_state) {
+ 312 729877 : switch (block_state) {
313 18454 : case BLOCK_STATE_DELETED : desc = "delete"; break;
- 314 52081 : case BLOCK_STATE_CHG : desc = "change"; break;
- 315 24042 : case BLOCK_STATE_REP : desc = "replace"; break;
- 316 634486 : case BLOCK_STATE_BLK : desc = "block"; break;
+ 314 13851 : case BLOCK_STATE_CHG : desc = "change"; break;
+ 315 62282 : case BLOCK_STATE_REP : desc = "replace"; break;
+ 316 635290 : case BLOCK_STATE_BLK : desc = "block"; break;
317 : /* LCOV_EXCL_START */
318 : default : desc = "unknown"; break;
319 : /* LCOV_EXCL_STOP */
320 : }
321 :
- 322 729063 : if (hash_is_invalid(block->hash)) {
- 323 13841 : hash = "lost";
- 324 715222 : } else if (hash_is_zero(block->hash)) {
- 325 29602 : hash = "zero";
+ 322 729877 : if (hash_is_invalid(block->hash)) {
+ 323 13843 : hash = "lost";
+ 324 716034 : } else if (hash_is_zero(block->hash)) {
+ 325 8 : hash = "zero";
326 : } else {
- 327 685620 : hash = "known";
+ 327 716026 : hash = "known";
328 : }
329 :
- 330 729063 : if (failed[j].is_bad)
- 331 643340 : data = "bad";
+ 330 729877 : if (failed[j].is_bad)
+ 331 644152 : data = "bad";
332 : else
- 333 85723 : data = "good";
+ 333 85725 : data = "good";
334 :
- 335 729063 : if (failed[j].file) {
- 336 710609 : struct snapraid_disk* disk = failed[j].disk;
- 337 710609 : struct snapraid_file* file = failed[j].file;
- 338 710609 : block_off_t file_pos = failed[j].file_pos;
+ 335 729877 : if (failed[j].file) {
+ 336 711423 : struct snapraid_disk* disk = failed[j].disk;
+ 337 711423 : struct snapraid_file* file = failed[j].file;
+ 338 711423 : block_off_t file_pos = failed[j].file_pos;
339 :
- 340 710609 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc(file->sub), file_pos);
+ 340 711423 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc(file->sub), file_pos);
341 : } else {
342 18454 : log_tag("entry:%u:%s:%s:%s:\n", j, desc, hash, data);
343 : }
@@ -421,58 +421,58 @@
359 : /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */
360 : /* but we are not interested in DELETED ones. */
361 :
- 362 287657 : n = 0;
- 363 287657 : something_to_recover = 0; /* keep track if there is at least one block to fix */
- 364 1016720 : for (j = 0; j < failed_count; ++j) {
- 365 729063 : if (failed[j].is_bad) {
- 366 643340 : unsigned block_state = block_state_get(failed[j].block);
+ 362 289231 : n = 0;
+ 363 289231 : something_to_recover = 0; /* keep track if there is at least one block to fix */
+ 364 1019108 : for (j = 0; j < failed_count; ++j) {
+ 365 729877 : if (failed[j].is_bad) {
+ 366 644152 : unsigned block_state = block_state_get(failed[j].block);
367 :
- 368 643340 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */
+ 368 644152 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */
369 :
370 : /* if we have the hash for it */
- 371 643340 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP)
+ 371 644152 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP)
372 : /* try to fetch the block using the known hash */
- 373 634954 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0
- 374 630482 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0)
+ 373 644144 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0
+ 374 639672 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0)
375 : ) {
376 : /* we already have corrected it! */
- 377 13884 : log_tag("hash_import: Fixed entry %u\n", j);
+ 377 22310 : log_tag("hash_import: Fixed entry %u\n", j);
378 : } else {
379 : /* otherwise try to recover it */
- 380 629456 : failed_map[n] = j;
- 381 629456 : ++n;
+ 380 621842 : failed_map[n] = j;
+ 381 621842 : ++n;
382 :
383 : /* we have something to try to recover */
- 384 629456 : something_to_recover = 1;
+ 384 621842 : something_to_recover = 1;
385 : }
386 : }
387 : }
388 :
389 : /* if nothing to fix */
- 390 287657 : if (!something_to_recover) {
- 391 35896 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n);
+ 390 289231 : if (!something_to_recover) {
+ 391 44132 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n);
392 :
393 : /* recompute only the parity */
- 394 35896 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 395 35896 : return 0;
+ 394 44132 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 395 44132 : return 0;
396 : }
397 :
- 398 251761 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
- 399 251761 : if (ret == 0) {
+ 398 245099 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
+ 399 245099 : if (ret == 0) {
400 : /* reprocess the CHG blocks, for which we don't have a hash to check */
- 401 : /* if they were BAD we have to use some euristics to ensure that we have recovered */
+ 401 : /* if they were BAD we have to use some heuristics to ensure that we have recovered */
402 : /* the state after the sync. If unsure, we assume the worst case */
403 :
- 404 683858 : for (j = 0; j < failed_count; ++j) {
+ 404 670084 : for (j = 0; j < failed_count; ++j) {
405 : /* we take care only of BAD blocks we have to write back */
- 406 484441 : if (failed[j].is_bad) {
- 407 470929 : unsigned block_state = block_state_get(failed[j].block);
+ 406 477201 : if (failed[j].is_bad) {
+ 407 463729 : unsigned block_state = block_state_get(failed[j].block);
408 :
409 : /* BLK and REP blocks are always OK, because at this point */
410 : /* we have already checked their hash */
- 411 470929 : if (block_state != BLOCK_STATE_CHG) {
- 412 462543 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
- 413 462543 : continue;
+ 411 463729 : if (block_state != BLOCK_STATE_CHG) {
+ 412 463721 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
+ 413 463721 : continue;
414 : }
415 :
416 : /* for CHG blocks we have to 'guess' if they are correct or not */
@@ -480,22 +480,22 @@
418 : /* if the hash is invalid we cannot check the result */
419 : /* this could happen if we have lost this information */
420 : /* after an aborted sync */
- 421 8386 : if (hash_is_invalid(failed[j].block->hash)) {
+ 421 8 : if (hash_is_invalid(failed[j].block->hash)) {
422 : /* it may contain garbage */
423 0 : failed[j].is_outofdate = 1;
424 :
425 0 : log_tag("hash_unknown: Unknown hash on entry %u\n", j);
- 426 8386 : } else if (hash_is_zero(failed[j].block->hash)) {
+ 426 8 : } else if (hash_is_zero(failed[j].block->hash)) {
427 : /* if the block is not filled with 0, we are sure to have */
428 : /* restored it to the state after the 'sync' */
429 : /* instead, if the block is filled with 0, it could be either that the */
430 : /* block after the sync is really filled by 0, or that */
431 : /* we restored the block before the 'sync'. */
- 432 8386 : if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) == 0) {
+ 432 8 : if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) == 0) {
433 : /* it may contain garbage */
- 434 4192 : failed[j].is_outofdate = 1;
+ 434 8 : failed[j].is_outofdate = 1;
435 :
- 436 4192 : log_tag("hash_unknown: Maybe old zero on entry %u\n", j);
+ 436 8 : log_tag("hash_unknown: Maybe old zero on entry %u\n", j);
437 : }
438 : } else {
439 : /* if the hash is different than the previous one, we are sure to have */
@@ -514,15 +514,15 @@
452 : }
453 : }
454 :
- 455 199417 : return 0;
+ 455 192883 : return 0;
456 : }
- 457 52344 : if (ret > 0)
- 458 9154 : error += ret;
+ 457 52216 : if (ret > 0)
+ 458 9168 : error += ret;
459 :
- 460 52344 : if (ret < 0)
- 461 43190 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n);
+ 460 52216 : if (ret < 0)
+ 461 43048 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n);
462 : else
- 463 9154 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret);
+ 463 9168 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret);
464 :
465 : /* Now assume that the parity IS NOT updated at the current state, */
466 : /* but still represent the state before the last 'sync' process. */
@@ -532,15 +532,15 @@
470 : /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */
471 : /* even if marked as bad, because we don't have parity for them and it's just impossible, */
472 : /* and we are not interested to recover DELETED ones. */
- 473 52344 : n = 0;
- 474 52344 : something_to_recover = 0; /* keep track if there is at least one block to fix */
- 475 52344 : something_unsynced = 0; /* keep track if we have some unsynced info to process */
- 476 232704 : for (j = 0; j < failed_count; ++j) {
- 477 180360 : unsigned block_state = block_state_get(failed[j].block);
+ 473 52216 : n = 0;
+ 474 52216 : something_to_recover = 0; /* keep track if there is at least one block to fix */
+ 475 52216 : something_unsynced = 0; /* keep track if we have some unsynced info to process */
+ 476 232278 : for (j = 0; j < failed_count; ++j) {
+ 477 180062 : unsigned block_state = block_state_get(failed[j].block);
478 :
- 479 180360 : if (block_state == BLOCK_STATE_DELETED
- 480 171316 : || block_state == BLOCK_STATE_CHG
- 481 171316 : || block_state == BLOCK_STATE_REP
+ 479 180062 : if (block_state == BLOCK_STATE_DELETED
+ 480 171018 : || block_state == BLOCK_STATE_CHG
+ 481 171018 : || block_state == BLOCK_STATE_REP
482 : ) {
483 : /* If the block is CHG, REP or DELETED, we don't have the original content of block, */
484 : /* and we must try to recover it. */
@@ -580,26 +580,26 @@
518 : /* this applies to REP blocks because we are going to recover the old state */
519 : /* and the REP hash represent the new one */
520 : /* it also applies to CHG and DELETE blocks because we want to have */
- 521 : /* a succesful recovering only if a BLK one is matching */
+ 521 : /* a successful recovering only if a BLK one is matching */
522 9044 : failed[j].is_outofdate = 1;
- 523 171316 : } else if (failed[j].is_bad) {
+ 523 171018 : } else if (failed[j].is_bad) {
524 : /* If the block is bad we don't know its content, and we try to recover it */
525 : /* At this point, we can have only BLK ones */
526 :
- 527 171316 : assert(block_state == BLOCK_STATE_BLK);
+ 527 171018 : assert(block_state == BLOCK_STATE_BLK);
528 :
529 : /* we have something we are interested to recover */
- 530 171316 : something_to_recover = 1;
+ 530 171018 : something_to_recover = 1;
531 :
532 : /* we try to recover it */
- 533 171316 : failed_map[n] = j;
- 534 171316 : ++n;
+ 533 171018 : failed_map[n] = j;
+ 534 171018 : ++n;
535 : }
536 : }
537 :
538 : /* if nothing to fix, we just don't try */
539 : /* if nothing unsynced we also don't retry, because it's the same try as before */
- 540 52344 : if (something_to_recover && something_unsynced) {
+ 540 52216 : if (something_to_recover && something_unsynced) {
541 9044 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
542 9044 : if (ret == 0) {
543 : /* reprocess the REP and CHG blocks, for which we have recovered and old state */
@@ -633,17 +633,17 @@
571 : else
572 0 : log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret);
573 : } else {
- 574 43300 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n,
+ 574 43172 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n,
575 : !something_to_recover ? " nothing to recover" : "",
576 : !something_unsynced ? " nothing unsynched" : ""
577 : );
578 : }
579 :
580 : /* return the number of failed attempts, or -1 if no strategy */
- 581 47822 : if (error)
- 582 4632 : return error;
+ 581 47694 : if (error)
+ 582 4646 : return error;
583 : else
- 584 43190 : return -1;
+ 584 43048 : return -1;
585 : }
586 :
587 : /**
@@ -655,19 +655,19 @@
593 : * fix. This assumption is not always correct, and in such case we have to
594 : * skip the whole postprocessing. And example, is when fixing only bad blocks.
595 : */
- 596 933332 : static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax)
+ 596 934551 : static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax)
597 : {
598 : unsigned j;
599 : int ret;
600 :
- 601 : /* if we are processing only bad blocks, we don't have to do any postprocessing */
+ 601 : /* if we are processing only bad blocks, we don't have to do any post-processing */
602 : /* as we don't have any guarantee to process the last block of the fixed files */
- 603 933332 : if (state->opt.badonly)
- 604 9342 : return 0;
+ 603 934551 : if (state->opt.badonly)
+ 604 9358 : return 0;
605 :
606 : /* for all the files print the final status, and does the final time fix */
607 : /* we also ensure to close files after processing the last block */
- 608 6467930 : for (j = 0; j < diskmax; ++j) {
+ 608 6476351 : for (j = 0; j < diskmax; ++j) {
609 : struct snapraid_block* block;
610 : struct snapraid_disk* disk;
611 : struct snapraid_file* collide_file;
@@ -676,51 +676,51 @@
614 : char path[PATH_MAX];
615 : uint64_t inode;
616 :
- 617 5543940 : disk = handle[j].disk;
- 618 5543940 : if (!disk) {
+ 617 5551158 : disk = handle[j].disk;
+ 618 5551158 : if (!disk) {
619 : /* if no disk, nothing to do */
- 620 3396852 : continue;
+ 620 3403281 : continue;
621 : }
622 :
- 623 5529927 : block = fs_par2block_get(disk, i);
- 624 5529927 : if (!block_has_file(block)) {
+ 623 5537121 : block = fs_par2block_get(disk, i);
+ 624 5537121 : if (!block_has_file(block)) {
625 : /* if no file, nothing to do */
- 626 210017 : continue;
+ 626 210707 : continue;
627 : }
628 :
- 629 5319910 : file = fs_par2file_get(disk, i, &file_pos);
- 630 5319910 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
+ 629 5326414 : file = fs_par2file_get(disk, i, &file_pos);
+ 630 5326414 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
631 :
632 : /* if it isn't the last block in the file */
- 633 5319910 : if (!file_block_is_last(file, file_pos)) {
+ 633 5326414 : if (!file_block_is_last(file, file_pos)) {
634 : /* nothing to do */
- 635 3158809 : continue;
+ 635 3164500 : continue;
636 : }
637 :
638 : /* if the file is excluded, we have nothing to adjust as the file is never written */
- 639 2161101 : if (file_flag_has(file, FILE_IS_EXCLUDED)
- 640 2064360 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) {
+ 639 2161914 : if (file_flag_has(file, FILE_IS_EXCLUDED)
+ 640 2065035 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) {
641 : /* nothing to do, but close the file */
642 : goto close_and_continue;
643 : }
644 :
645 : /* finish the fix process if it's the last block of the files */
- 646 2064360 : if (fix) {
+ 646 2065035 : if (fix) {
647 : /* mark that we finished with this file */
648 : /* to identify later any NOT finished ones */
- 649 757042 : file_flag_set(file, FILE_IS_FINISHED);
+ 649 757215 : file_flag_set(file, FILE_IS_FINISHED);
650 :
651 : /* if the file is damaged, meaning that a fix failed */
- 652 757042 : if (file_flag_has(file, FILE_IS_DAMAGED)) {
+ 652 757215 : if (file_flag_has(file, FILE_IS_DAMAGED)) {
653 : /* rename it to .unrecoverable */
654 : char path_to[PATH_MAX];
655 :
- 656 64972 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
+ 656 63364 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
657 :
658 : /* ensure to close the file before renaming */
- 659 64972 : if (handle[j].file == file) {
- 660 64972 : ret = handle_close(&handle[j]);
- 661 64972 : if (ret != 0) {
+ 659 63364 : if (handle[j].file == file) {
+ 660 63364 : ret = handle_close(&handle[j]);
+ 661 63364 : if (ret != 0) {
662 : /* LCOV_EXCL_START */
663 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
664 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -729,8 +729,8 @@
667 : }
668 : }
669 :
- 670 64972 : ret = rename(path, path_to);
- 671 64972 : if (ret != 0) {
+ 670 63364 : ret = rename(path, path_to);
+ 671 63364 : if (ret != 0) {
672 : /* LCOV_EXCL_START */
673 : log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno));
674 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
@@ -738,22 +738,22 @@
676 : /* LCOV_EXCL_STOP */
677 : }
678 :
- 679 64972 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub));
- 680 64972 : msg_info("unrecoverable %s\n", path);
+ 679 63364 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub));
+ 680 63364 : msg_info("unrecoverable %s\n", path);
681 :
682 : /* and do not set the time if damaged */
- 683 64972 : goto close_and_continue;
+ 683 63364 : goto close_and_continue;
684 : }
685 :
686 : /* if the file is not fixed, meaning that it is untouched */
- 687 692070 : if (!file_flag_has(file, FILE_IS_FIXED)) {
+ 687 693851 : if (!file_flag_has(file, FILE_IS_FIXED)) {
688 : /* nothing to do, but close the file */
- 689 574306 : goto close_and_continue;
+ 689 574395 : goto close_and_continue;
690 : }
691 :
692 : /* if the file is closed or different than the one expected, reopen it */
693 : /* a different open file could happen when filtering for bad blocks */
- 694 117764 : if (handle[j].file != file) {
+ 694 119456 : if (handle[j].file != file) {
695 : /* close a potential different file */
696 0 : ret = handle_close(&handle[j]);
697 0 : if (ret != 0) {
@@ -776,13 +776,13 @@
714 : }
715 : }
716 :
- 717 117764 : log_tag("status:recovered:%s:%s\n", disk->name, esc(file->sub));
- 718 117764 : msg_info("recovered %s\n", path);
+ 717 119456 : log_tag("status:recovered:%s:%s\n", disk->name, esc(file->sub));
+ 718 119456 : msg_info("recovered %s\n", path);
719 :
- 720 117764 : inode = handle[j].st.st_ino;
+ 720 119456 : inode = handle[j].st.st_ino;
721 :
722 : /* search for the corresponding inode */
- 723 117764 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
+ 723 119456 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
724 :
725 : /* if the inode is already in the database and it refers at a different file name, */
726 : /* we can fix the file time ONLY if the time and size allow to differentiate */
@@ -792,15 +792,15 @@
730 : /* when recreating them the inodes may be reused in a different order, */
731 : /* and at the next sync some files may have matching inode/size/time even if different name */
732 : /* not allowing sync to detect that the file is changed and not renamed */
- 733 117764 : if (!collide_file /* if not in the database, there is no collision */
- 734 29250 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */
- 735 27741 : || collide_file->size != file->size /* if the size is different, the collision is identified */
- 736 5 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */
- 737 3 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */
+ 733 119456 : if (!collide_file /* if not in the database, there is no collision */
+ 734 37496 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */
+ 735 35757 : || collide_file->size != file->size /* if the size is different, the collision is identified */
+ 736 10 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */
+ 737 5 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */
738 : ) {
739 : /* set the original modification time */
- 740 117763 : ret = handle_utime(&handle[j]);
- 741 235526 : if (ret == -1) {
+ 740 119455 : ret = handle_utime(&handle[j]);
+ 741 238910 : if (ret == -1) {
742 : /* LCOV_EXCL_START */
743 : /* mark the file as damaged */
744 : file_flag_set(file, FILE_IS_DAMAGED);
@@ -814,22 +814,22 @@
752 : } else {
753 : /* we are not fixing, but only checking */
754 : /* print just the final status */
- 755 1307318 : if (file_flag_has(file, FILE_IS_DAMAGED)) {
- 756 9389 : if (state->opt.auditonly) {
- 757 2806 : log_tag("status:damaged:%s:%s\n", disk->name, esc(file->sub));
- 758 2806 : msg_info("damaged %s\n", path);
+ 755 1307820 : if (file_flag_has(file, FILE_IS_DAMAGED)) {
+ 756 9087 : if (state->opt.auditonly) {
+ 757 2758 : log_tag("status:damaged:%s:%s\n", disk->name, esc(file->sub));
+ 758 2758 : msg_info("damaged %s\n", path);
759 : } else {
- 760 6583 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub));
- 761 6583 : msg_info("unrecoverable %s\n", path);
+ 760 6329 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub));
+ 761 6329 : msg_info("unrecoverable %s\n", path);
762 : }
- 763 1297929 : } else if (file_flag_has(file, FILE_IS_FIXED)) {
- 764 76370 : log_tag("status:recoverable:%s:%s\n", disk->name, esc(file->sub));
- 765 76370 : msg_info("recoverable %s\n", path);
+ 763 1298733 : } else if (file_flag_has(file, FILE_IS_FIXED)) {
+ 764 76728 : log_tag("status:recoverable:%s:%s\n", disk->name, esc(file->sub));
+ 765 76728 : msg_info("recoverable %s\n", path);
766 : } else {
- 767 1221559 : log_tag("status:correct:%s:%s\n", disk->name, esc(file->sub));
+ 767 1222005 : log_tag("status:correct:%s:%s\n", disk->name, esc(file->sub));
768 : /* we don't use msg_verbose() because it also goes into the log */
- 769 1221559 : if (msg_level >= MSG_VERBOSE)
- 770 23233 : msg_info("correct %s\n", path);
+ 769 1222005 : if (msg_level >= MSG_VERBOSE)
+ 770 23203 : msg_info("correct %s\n", path);
771 : }
772 : }
773 :
@@ -837,11 +837,11 @@
775 : /* if the opened file is the correct one, close it */
776 : /* in case of excluded and fragmented files it's possible */
777 : /* that the opened file is not the current one */
- 778 2161101 : if (handle[j].file == file) {
+ 778 2161914 : if (handle[j].file == file) {
779 : /* ensure to close the file just after finishing with it */
780 : /* to avoid to keep it open without any possible use */
- 781 1975748 : ret = handle_close(&handle[j]);
- 782 1975748 : if (ret != 0) {
+ 781 1978155 : ret = handle_close(&handle[j]);
+ 782 1978155 : if (ret != 0) {
783 : /* LCOV_EXCL_START */
784 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
785 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -851,56 +851,56 @@
789 : }
790 : }
791 :
- 792 923990 : return 0;
+ 792 925193 : return 0;
793 : }
794 :
795 : /**
796 : * Check if we have to process the specified block index ::i.
797 : */
- 798 1866664 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax)
+ 798 1869102 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax)
799 : {
800 : snapraid_info info;
801 : unsigned j;
802 : unsigned l;
803 :
804 : /* get block specific info */
- 805 1866664 : info = info_get(&state->infoarr, i);
+ 805 1869102 : info = info_get(&state->infoarr, i);
806 :
807 : /* if we filter for only bad blocks */
- 808 1866664 : if (state->opt.badonly) {
+ 808 1869102 : if (state->opt.badonly) {
809 : /* skip if this is not bad */
- 810 18684 : if (!info_get_bad(info))
- 811 15080 : return 0;
+ 810 18716 : if (!info_get_bad(info))
+ 811 15174 : return 0;
812 : }
813 :
814 : /* for each parity */
- 815 2120448 : for (l = 0; l < state->level; ++l) {
- 816 2037332 : if (!state->parity[l].is_excluded) {
- 817 1768468 : return 1;
+ 815 2123608 : for (l = 0; l < state->level; ++l) {
+ 816 2040324 : if (!state->parity[l].is_excluded) {
+ 817 1770644 : return 1;
818 : }
819 : }
820 :
821 : /* for each disk */
- 822 384812 : for (j = 0; j < diskmax; ++j) {
+ 822 385562 : for (j = 0; j < diskmax; ++j) {
823 : struct snapraid_block* block;
824 :
825 : /* if no disk, nothing to check */
- 826 349760 : if (!handle[j].disk)
+ 826 350436 : if (!handle[j].disk)
827 0 : continue;
828 :
- 829 349760 : block = fs_par2block_get(handle[j].disk, i);
+ 829 350436 : block = fs_par2block_get(handle[j].disk, i);
830 :
831 : /* try to recover all files, even the ones without hash */
832 : /* because in some cases we can recover also them */
- 833 349760 : if (block_has_file(block)) {
- 834 343338 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0);
- 835 343338 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */
- 836 48064 : return 1;
+ 833 350436 : if (block_has_file(block)) {
+ 834 343994 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0);
+ 835 343994 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */
+ 836 48158 : return 1;
837 : }
838 : }
839 : }
840 :
- 841 35052 : return 0;
+ 841 35126 : return 0;
842 : }
843 :
844 118 : static int state_check_process(struct snapraid_state* state, int fix, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax)
@@ -945,33 +945,33 @@
883 :
884 : /* first count the number of blocks to process */
885 118 : countmax = 0;
- 886 933450 : for (i = blockstart; i < blockmax; ++i) {
- 887 933332 : if (!block_is_enabled(state, i, handle, diskmax))
- 888 25066 : continue;
- 889 908266 : ++countmax;
+ 886 934669 : for (i = blockstart; i < blockmax; ++i) {
+ 887 934551 : if (!block_is_enabled(state, i, handle, diskmax))
+ 888 25150 : continue;
+ 889 909401 : ++countmax;
890 : }
891 :
892 : /* check all the blocks in files */
893 118 : countsize = 0;
894 118 : countpos = 0;
895 118 : state_progress_begin(state, blockstart, blockmax, countmax);
- 896 933450 : for (i = blockstart; i < blockmax; ++i) {
+ 896 934669 : for (i = blockstart; i < blockmax; ++i) {
897 : unsigned failed_count;
898 : int valid_parity;
899 : snapraid_info info;
900 : int rehash;
901 :
- 902 933332 : if (!block_is_enabled(state, i, handle, diskmax)) {
+ 902 934551 : if (!block_is_enabled(state, i, handle, diskmax)) {
903 : /* post process the files */
- 904 25066 : ret = file_post(state, fix, i, handle, diskmax);
- 905 25066 : if (ret == -1) {
+ 904 25150 : ret = file_post(state, fix, i, handle, diskmax);
+ 905 25150 : if (ret == -1) {
906 0 : log_fatal("Stopping at block %u\n", i);
907 0 : ++unrecoverable_error;
908 0 : goto bail;
909 : }
910 :
911 : /* and now continue with the next block */
- 912 25066 : continue;
+ 912 25150 : continue;
913 : }
914 :
915 : /* If we have valid parity, and it makes sense to check its content. */
@@ -979,19 +979,19 @@
917 : /* but we don't report parity errors */
918 : /* Note that with auditonly, we anyway skip the full parity check, */
919 : /* because we also don't read it at all */
- 920 908266 : valid_parity = 1;
+ 920 909401 : valid_parity = 1;
921 :
922 : /* keep track of the number of failed blocks */
- 923 908266 : failed_count = 0;
+ 923 909401 : failed_count = 0;
924 :
925 : /* get block specific info */
- 926 908266 : info = info_get(&state->infoarr, i);
+ 926 909401 : info = info_get(&state->infoarr, i);
927 :
928 : /* if we have to use the old hash */
- 929 908266 : rehash = info_get_rehash(info);
+ 929 909401 : rehash = info_get_rehash(info);
930 :
931 : /* for each disk, process the block */
- 932 6357862 : for (j = 0; j < diskmax; ++j) {
+ 932 6365807 : for (j = 0; j < diskmax; ++j) {
933 : int read_size;
934 : unsigned char hash[HASH_SIZE];
935 : struct snapraid_disk* disk;
@@ -1001,34 +1001,34 @@
939 : unsigned block_state;
940 :
941 : /* if the disk position is not used */
- 942 5449596 : disk = handle[j].disk;
- 943 5449596 : if (!disk) {
+ 942 5456406 : disk = handle[j].disk;
+ 943 5456406 : if (!disk) {
944 : /* use an empty block */
- 945 14013 : memset(buffer[j], 0, state->block_size);
- 946 951802 : continue;
+ 945 14037 : memset(buffer[j], 0, state->block_size);
+ 946 953296 : continue;
947 : }
948 :
949 : /* if the disk block is not used */
- 950 5435583 : block = fs_par2block_get(disk, i);
- 951 5435583 : if (block == BLOCK_EMPTY) {
+ 950 5442369 : block = fs_par2block_get(disk, i);
+ 951 5442369 : if (block == BLOCK_EMPTY) {
952 : /* use an empty block */
- 953 188862 : memset(buffer[j], 0, state->block_size);
- 954 188862 : continue;
+ 953 189495 : memset(buffer[j], 0, state->block_size);
+ 954 189495 : continue;
955 : }
956 :
957 : /* get the state of the block */
- 958 5246721 : block_state = block_state_get(block);
+ 958 5252874 : block_state = block_state_get(block);
959 :
960 : /* if the parity is not valid */
- 961 5246721 : if (block_has_invalid_parity(block)) {
+ 961 5252874 : if (block_has_invalid_parity(block)) {
962 : /* mark the parity as invalid, and don't try to check/fix it */
963 : /* because it will be recomputed at the next sync */
- 964 94577 : valid_parity = 0;
+ 964 94587 : valid_parity = 0;
965 : /* follow */
966 : }
967 :
968 : /* if the block is DELETED */
- 969 5246721 : if (block_state == BLOCK_STATE_DELETED) {
+ 969 5252874 : if (block_state == BLOCK_STATE_DELETED) {
970 : /* use an empty block */
971 18454 : memset(buffer[j], 0, state->block_size);
972 :
@@ -1047,22 +1047,22 @@
985 : }
986 :
987 : /* get the file of this block */
- 988 5228267 : file = fs_par2file_get(disk, i, &file_pos);
+ 988 5234420 : file = fs_par2file_get(disk, i, &file_pos);
989 :
990 : /* if we are only hashing, we can skip excluded files and don't even read them */
- 991 5228267 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 991 5234420 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) {
992 : /* use an empty block */
- 993 : /* in true, this is unnecessary, becase we are not checking any parity */
+ 993 : /* in true, this is unnecessary, because we are not checking any parity */
994 : /* but we keep it for completeness */
995 0 : memset(buffer[j], 0, state->block_size);
996 0 : continue;
997 : }
998 :
999 : /* if the file is closed or different than the current one */
- 1000 5228267 : if (handle[j].file == 0 || handle[j].file != file) {
+ 1000 5234420 : if (handle[j].file == 0 || handle[j].file != file) {
1001 : /* close the old one, if any */
- 1002 2258931 : ret = handle_close(&handle[j]);
- 1003 2258931 : if (ret == -1) {
+ 1002 2259919 : ret = handle_close(&handle[j]);
+ 1003 2259919 : if (ret == -1) {
1004 : /* LCOV_EXCL_START */
1005 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(handle[j].file->sub), strerror(errno));
1006 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -1073,10 +1073,10 @@
1011 : }
1012 :
1013 : /* if fixing, and the file is not excluded, we must open for writing */
- 1014 2258931 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1014 2259919 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) {
1015 : /* if fixing, create the file, open for writing and resize if required */
- 1016 771210 : ret = handle_create(&handle[j], file, state->file_mode);
- 1017 771210 : if (ret == -1) {
+ 1016 771290 : ret = handle_create(&handle[j], file, state->file_mode);
+ 1017 771290 : if (ret == -1) {
1018 : /* LCOV_EXCL_START */
1019 : if (errno == EACCES) {
1020 : log_fatal("WARNING! Please give write permission to the file.\n");
@@ -1090,69 +1090,69 @@
1028 : }
1029 :
1030 : /* check if the file was just created */
- 1031 1542420 : if (handle[j].created != 0) {
+ 1031 1542580 : if (handle[j].created != 0) {
1032 : /* if fragmented, it may be reopened, so remember that the file */
1033 : /* was originally missing */
- 1034 113024 : file_flag_set(file, FILE_IS_CREATED);
+ 1034 113107 : file_flag_set(file, FILE_IS_CREATED);
1035 : }
1036 : } else {
1037 : /* open the file only for reading */
- 1038 1487721 : if (!file_flag_has(file, FILE_IS_MISSING))
- 1039 1372062 : ret = handle_open(&handle[j], file, state->file_mode,
- 1040 1372062 : log_error, state->opt.expected_missing ? log_expected : 0);
+ 1038 1488629 : if (!file_flag_has(file, FILE_IS_MISSING))
+ 1039 1372724 : ret = handle_open(&handle[j], file, state->file_mode,
+ 1040 1372724 : log_error, state->opt.expected_missing ? log_expected : 0);
1041 : else
- 1042 115659 : ret = -1; /* if the file is missing, we cannot open it */
- 1043 1487721 : if (ret == -1) {
+ 1042 115905 : ret = -1; /* if the file is missing, we cannot open it */
+ 1043 1488629 : if (ret == -1) {
1044 : /* save the failed block for the check/fix */
- 1045 194418 : failed[failed_count].is_bad = 1;
- 1046 194418 : failed[failed_count].is_outofdate = 0;
- 1047 194418 : failed[failed_count].index = j;
- 1048 194418 : failed[failed_count].block = block;
- 1049 194418 : failed[failed_count].disk = disk;
- 1050 194418 : failed[failed_count].file = file;
- 1051 194418 : failed[failed_count].file_pos = file_pos;
- 1052 194418 : failed[failed_count].handle = &handle[j];
- 1053 194418 : ++failed_count;
+ 1045 194668 : failed[failed_count].is_bad = 1;
+ 1046 194668 : failed[failed_count].is_outofdate = 0;
+ 1047 194668 : failed[failed_count].index = j;
+ 1048 194668 : failed[failed_count].block = block;
+ 1049 194668 : failed[failed_count].disk = disk;
+ 1050 194668 : failed[failed_count].file = file;
+ 1051 194668 : failed[failed_count].file_pos = file_pos;
+ 1052 194668 : failed[failed_count].handle = &handle[j];
+ 1053 194668 : ++failed_count;
1054 :
- 1055 194418 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc(file->sub), file_pos);
- 1056 194418 : ++error;
+ 1055 194668 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc(file->sub), file_pos);
+ 1056 194668 : ++error;
1057 :
1058 : /* mark the file as missing, to avoid to retry to open it again */
1059 : /* note that this can be done only if we are not fixing it */
1060 : /* otherwise, it could be recreated */
- 1061 194418 : file_flag_set(file, FILE_IS_MISSING);
- 1062 194418 : continue;
+ 1061 194668 : file_flag_set(file, FILE_IS_MISSING);
+ 1062 194668 : continue;
1063 : }
1064 : }
1065 :
1066 : /* if it's the first open, and not excluded */
- 1067 2064513 : if (!file_flag_has(file, FILE_IS_OPENED)
- 1068 2049148 : && !file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1067 2065251 : if (!file_flag_has(file, FILE_IS_OPENED)
+ 1068 2049859 : && !file_flag_has(file, FILE_IS_EXCLUDED)) {
1069 :
1070 : /* check if the file is changed */
- 1071 1997793 : if (handle[j].st.st_size != file->size
- 1072 1804861 : || handle[j].st.st_mtime != file->mtime_sec
- 1073 1780308 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
- 1074 : /* don't check the inode to support filesystem without persistent inodes */
+ 1071 1998374 : if (handle[j].st.st_size != file->size
+ 1072 1805527 : || handle[j].st.st_mtime != file->mtime_sec
+ 1073 1781193 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
+ 1074 : /* don't check the inode to support file-system without persistent inodes */
1075 : ) {
1076 : /* report that the file is not synced */
- 1077 217485 : file_flag_set(file, FILE_IS_UNSYNCED);
+ 1077 217181 : file_flag_set(file, FILE_IS_UNSYNCED);
1078 : }
1079 : }
1080 :
1081 : /* if it's the first open, and not excluded and larger */
- 1082 2064513 : if (!file_flag_has(file, FILE_IS_OPENED)
- 1083 2049148 : && !file_flag_has(file, FILE_IS_EXCLUDED)
- 1084 1997793 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))
- 1085 1997793 : && handle[j].st.st_size > file->size
+ 1082 2065251 : if (!file_flag_has(file, FILE_IS_OPENED)
+ 1083 2049859 : && !file_flag_has(file, FILE_IS_EXCLUDED)
+ 1084 1998374 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))
+ 1085 1998374 : && handle[j].st.st_size > file->size
1086 : ) {
- 1087 8781 : log_error("File '%s' is larger than expected.\n", handle[j].path);
- 1088 8781 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc(file->sub));
- 1089 8781 : ++error;
+ 1087 8640 : log_error("File '%s' is larger than expected.\n", handle[j].path);
+ 1088 8640 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc(file->sub));
+ 1089 8640 : ++error;
1090 :
- 1091 8781 : if (fix) {
- 1092 3249 : ret = handle_truncate(&handle[j], file);
- 1093 3249 : if (ret == -1) {
+ 1091 8640 : if (fix) {
+ 1092 3187 : ret = handle_truncate(&handle[j], file);
+ 1093 3187 : if (ret == -1) {
1094 : /* LCOV_EXCL_START */
1095 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n");
1096 : log_fatal("Stopping at block %u\n", i);
@@ -1161,202 +1161,202 @@
1099 : /* LCOV_EXCL_STOP */
1100 : }
1101 :
- 1102 3249 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc(file->sub));
- 1103 3249 : ++recovered_error;
+ 1102 3187 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc(file->sub));
+ 1103 3187 : ++recovered_error;
1104 : }
1105 : }
1106 :
1107 : /* mark the file as opened at least one time */
1108 : /* this is used to avoid to check the unsynced and size */
1109 : /* more than one time, in case the file is reopened later */
- 1110 2064513 : file_flag_set(file, FILE_IS_OPENED);
+ 1110 2065251 : file_flag_set(file, FILE_IS_OPENED);
1111 : }
1112 :
1113 : /* read from the file */
- 1114 5033849 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size,
- 1115 5033849 : log_error, state->opt.expected_missing ? log_expected : 0);
- 1116 5033849 : if (read_size == -1) {
+ 1114 5039752 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size,
+ 1115 5039752 : log_error, state->opt.expected_missing ? log_expected : 0);
+ 1116 5039752 : if (read_size == -1) {
1117 : /* save the failed block for the check/fix */
- 1118 442025 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */
- 1119 442025 : failed[failed_count].is_outofdate = 0;
- 1120 442025 : failed[failed_count].index = j;
- 1121 442025 : failed[failed_count].block = block;
- 1122 442025 : failed[failed_count].disk = disk;
- 1123 442025 : failed[failed_count].file = file;
- 1124 442025 : failed[failed_count].file_pos = file_pos;
- 1125 442025 : failed[failed_count].handle = &handle[j];
- 1126 442025 : ++failed_count;
+ 1118 442526 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */
+ 1119 442526 : failed[failed_count].is_outofdate = 0;
+ 1120 442526 : failed[failed_count].index = j;
+ 1121 442526 : failed[failed_count].block = block;
+ 1122 442526 : failed[failed_count].disk = disk;
+ 1123 442526 : failed[failed_count].file = file;
+ 1124 442526 : failed[failed_count].file_pos = file_pos;
+ 1125 442526 : failed[failed_count].handle = &handle[j];
+ 1126 442526 : ++failed_count;
1127 :
- 1128 442025 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos);
- 1129 442025 : ++error;
- 1130 442025 : continue;
+ 1128 442526 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos);
+ 1129 442526 : ++error;
+ 1130 442526 : continue;
1131 : }
1132 :
- 1133 4591824 : countsize += read_size;
+ 1133 4597226 : countsize += read_size;
1134 :
1135 : /* always insert CHG blocks, the repair functions needs all of them */
1136 : /* because the parity may be still referring at the old state */
1137 : /* and the repair must be aware of it */
- 1138 4591824 : if (block_state == BLOCK_STATE_CHG) {
+ 1138 4597226 : if (block_state == BLOCK_STATE_CHG) {
1139 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */
1140 : /* if we don't have a hash, we always assume the first read of the block correct. */
- 1141 43695 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */
- 1142 43695 : failed[failed_count].is_outofdate = 0;
- 1143 43695 : failed[failed_count].index = j;
- 1144 43695 : failed[failed_count].block = block;
- 1145 43695 : failed[failed_count].disk = disk;
- 1146 43695 : failed[failed_count].file = file;
- 1147 43695 : failed[failed_count].file_pos = file_pos;
- 1148 43695 : failed[failed_count].handle = &handle[j];
- 1149 43695 : ++failed_count;
- 1150 43695 : continue;
+ 1141 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */
+ 1142 13843 : failed[failed_count].is_outofdate = 0;
+ 1143 13843 : failed[failed_count].index = j;
+ 1144 13843 : failed[failed_count].block = block;
+ 1145 13843 : failed[failed_count].disk = disk;
+ 1146 13843 : failed[failed_count].file = file;
+ 1147 13843 : failed[failed_count].file_pos = file_pos;
+ 1148 13843 : failed[failed_count].handle = &handle[j];
+ 1149 13843 : ++failed_count;
+ 1150 13843 : continue;
1151 : }
1152 :
- 1153 4548129 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
+ 1153 4583383 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
1154 :
1155 : /* compute the hash of the block just read */
- 1156 4548129 : if (rehash) {
- 1157 286660 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
+ 1156 4583383 : if (rehash) {
+ 1157 27231 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
1158 : } else {
- 1159 4261469 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
+ 1159 4556152 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
1160 : }
1161 :
1162 : /* compare the hash */
- 1163 4548129 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
- 1164 12748 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE);
+ 1163 4583383 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 1164 12808 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE);
1165 :
1166 : /* save the failed block for the check/fix */
- 1167 12748 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */
- 1168 12748 : failed[failed_count].is_outofdate = 0;
- 1169 12748 : failed[failed_count].index = j;
- 1170 12748 : failed[failed_count].block = block;
- 1171 12748 : failed[failed_count].disk = disk;
- 1172 12748 : failed[failed_count].file = file;
- 1173 12748 : failed[failed_count].file_pos = file_pos;
- 1174 12748 : failed[failed_count].handle = &handle[j];
- 1175 12748 : ++failed_count;
+ 1167 12808 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */
+ 1168 12808 : failed[failed_count].is_outofdate = 0;
+ 1169 12808 : failed[failed_count].index = j;
+ 1170 12808 : failed[failed_count].block = block;
+ 1171 12808 : failed[failed_count].disk = disk;
+ 1172 12808 : failed[failed_count].file = file;
+ 1173 12808 : failed[failed_count].file_pos = file_pos;
+ 1174 12808 : failed[failed_count].handle = &handle[j];
+ 1175 12808 : ++failed_count;
1176 :
- 1177 12748 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff);
- 1178 12748 : ++error;
- 1179 12748 : continue;
+ 1177 12808 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff);
+ 1178 12808 : ++error;
+ 1179 12808 : continue;
1180 : }
1181 :
1182 : /* always insert REP blocks, the repair functions needs all of them */
1183 : /* because the parity may be still referring at the old state */
1184 : /* and the repair must be aware of it */
- 1185 4535381 : if (block_state == BLOCK_STATE_REP) {
- 1186 23574 : failed[failed_count].is_bad = 0; /* it's not bad */
- 1187 23574 : failed[failed_count].is_outofdate = 0;
- 1188 23574 : failed[failed_count].index = j;
- 1189 23574 : failed[failed_count].block = block;
- 1190 23574 : failed[failed_count].disk = disk;
- 1191 23574 : failed[failed_count].file = file;
- 1192 23574 : failed[failed_count].file_pos = file_pos;
- 1193 23574 : failed[failed_count].handle = &handle[j];
- 1194 23574 : ++failed_count;
- 1195 23574 : continue;
+ 1185 4570575 : if (block_state == BLOCK_STATE_REP) {
+ 1186 53428 : failed[failed_count].is_bad = 0; /* it's not bad */
+ 1187 53428 : failed[failed_count].is_outofdate = 0;
+ 1188 53428 : failed[failed_count].index = j;
+ 1189 53428 : failed[failed_count].block = block;
+ 1190 53428 : failed[failed_count].disk = disk;
+ 1191 53428 : failed[failed_count].file = file;
+ 1192 53428 : failed[failed_count].file_pos = file_pos;
+ 1193 53428 : failed[failed_count].handle = &handle[j];
+ 1194 53428 : ++failed_count;
+ 1195 53428 : continue;
1196 : }
1197 : }
1198 :
1199 : /* now read and check the parity if requested */
- 1200 908266 : if (!state->opt.auditonly) {
+ 1200 909401 : if (!state->opt.auditonly) {
1201 : void* buffer_recov[LEV_MAX];
1202 : void* buffer_zero;
1203 :
1204 : /* buffers for parity read and not computed */
- 1205 4161698 : for (l = 0; l < state->level; ++l)
- 1206 3292609 : buffer_recov[l] = buffer[diskmax + state->level + l];
- 1207 2791014 : for (; l < LEV_MAX; ++l)
- 1208 1921925 : buffer_recov[l] = 0;
+ 1205 4166971 : for (l = 0; l < state->level; ++l)
+ 1206 3296805 : buffer_recov[l] = buffer[diskmax + state->level + l];
+ 1207 2794357 : for (; l < LEV_MAX; ++l)
+ 1208 1924191 : buffer_recov[l] = 0;
1209 :
1210 : /* the zero buffer is the last one */
- 1211 869089 : buffer_zero = buffer[buffermax - 1];
+ 1211 870166 : buffer_zero = buffer[buffermax - 1];
1212 :
1213 : /* read the parity */
- 1214 4161698 : for (l = 0; l < state->level; ++l) {
- 1215 3292609 : if (parity[l]) {
- 1216 3278739 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
- 1217 3278739 : if (ret == -1) {
- 1218 90275 : buffer_recov[l] = 0; /* no parity to use */
+ 1214 4166971 : for (l = 0; l < state->level; ++l) {
+ 1215 3296805 : if (parity[l]) {
+ 1216 3282919 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
+ 1217 3282919 : if (ret == -1) {
+ 1218 90295 : buffer_recov[l] = 0; /* no parity to use */
1219 :
- 1220 90275 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
- 1221 90275 : ++error;
+ 1220 90295 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
+ 1221 90295 : ++error;
1222 : }
1223 : } else {
- 1224 13870 : buffer_recov[l] = 0;
+ 1224 13886 : buffer_recov[l] = 0;
1225 : }
1226 : }
1227 :
1228 : /* try all the recovering strategies */
- 1229 869089 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero);
- 1230 869089 : if (ret != 0) {
+ 1229 870166 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero);
+ 1230 870166 : if (ret != 0) {
1231 : /* increment the number of errors */
- 1232 47822 : if (ret > 0)
- 1233 4632 : error += ret;
- 1234 47822 : ++unrecoverable_error;
+ 1232 47694 : if (ret > 0)
+ 1233 4646 : error += ret;
+ 1234 47694 : ++unrecoverable_error;
1235 :
1236 : /* print a list of all the errors in files */
- 1237 219138 : for (j = 0; j < failed_count; ++j) {
- 1238 171316 : if (failed[j].is_bad)
- 1239 166794 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
+ 1237 218712 : for (j = 0; j < failed_count; ++j) {
+ 1238 171018 : if (failed[j].is_bad)
+ 1239 166496 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
1240 : }
1241 :
1242 : /* keep track of damaged files */
- 1243 219138 : for (j = 0; j < failed_count; ++j) {
- 1244 171316 : if (failed[j].is_bad)
- 1245 166794 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1243 218712 : for (j = 0; j < failed_count; ++j) {
+ 1244 171018 : if (failed[j].is_bad)
+ 1245 166496 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
1246 : }
1247 : } else {
1248 : /* now counts partial recovers */
1249 : /* note that this could happen only when we have an incomplete 'sync' */
1250 : /* and that we have recovered is the state before the 'sync' */
- 1251 821267 : int partial_recover_error = 0;
+ 1251 822472 : int partial_recover_error = 0;
1252 :
1253 : /* print a list of all the errors in files */
- 1254 1379014 : for (j = 0; j < failed_count; ++j) {
- 1255 557747 : if (failed[j].is_bad && failed[j].is_outofdate) {
- 1256 4192 : ++partial_recover_error;
- 1257 4192 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
+ 1254 1381331 : for (j = 0; j < failed_count; ++j) {
+ 1255 558859 : if (failed[j].is_bad && failed[j].is_outofdate) {
+ 1256 8 : ++partial_recover_error;
+ 1257 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
1258 : }
1259 : }
- 1260 821267 : if (partial_recover_error != 0) {
- 1261 4192 : error += partial_recover_error;
- 1262 4192 : ++unrecoverable_error;
+ 1260 822472 : if (partial_recover_error != 0) {
+ 1261 8 : error += partial_recover_error;
+ 1262 8 : ++unrecoverable_error;
1263 : }
1264 :
1265 : /* now check parities, but only if all the blocks have it computed */
1266 : /* if you check/fix after a partial sync, it's OK to have parity errors on the blocks with invalid parity */
1267 : /* and doesn't make sense to try to fix it */
- 1268 821267 : if (valid_parity) {
+ 1268 822472 : if (valid_parity) {
1269 : /* check the parity */
- 1270 3719151 : for (l = 0; l < state->level; ++l) {
- 1271 2959573 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) {
- 1272 10640 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size);
+ 1270 3725482 : for (l = 0; l < state->level; ++l) {
+ 1271 2964593 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) {
+ 1272 10750 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size);
1273 :
1274 : /* mark that the read parity is wrong, setting ptr to 0 */
- 1275 10640 : buffer_recov[l] = 0;
+ 1275 10750 : buffer_recov[l] = 0;
1276 :
- 1277 10640 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff);
- 1278 10640 : ++error;
+ 1277 10750 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff);
+ 1278 10750 : ++error;
1279 : }
1280 : }
1281 : }
1282 :
1283 : /* now write recovered files */
- 1284 821267 : if (fix) {
+ 1284 822472 : if (fix) {
1285 : /* update the fixed files */
- 1286 651810 : for (j = 0; j < failed_count; ++j) {
+ 1286 652441 : for (j = 0; j < failed_count; ++j) {
1287 : /* nothing to do if it doesn't need recovering */
- 1288 337787 : if (!failed[j].is_bad)
+ 1288 338114 : if (!failed[j].is_bad)
1289 40318 : continue;
1290 :
1291 : /* do not fix if the file is excluded */
- 1292 297469 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED)
- 1293 288205 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED)))
+ 1292 297796 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED)
+ 1293 288532 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED)))
1294 9264 : continue;
1295 :
- 1296 288205 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size);
- 1297 288205 : if (ret == -1) {
+ 1296 288532 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size);
+ 1297 288532 : if (ret == -1) {
1298 : /* LCOV_EXCL_START */
1299 : /* mark the file as damaged */
1300 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
@@ -1374,35 +1374,35 @@
1312 : }
1313 :
1314 : /* if we are not sure that the recovered content is uptodate */
- 1315 288205 : if (failed[j].is_outofdate) {
+ 1315 288532 : if (failed[j].is_outofdate) {
1316 : /* mark the file as damaged */
- 1317 4192 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
- 1318 4192 : continue;
+ 1317 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1318 8 : continue;
1319 : }
1320 :
1321 : /* mark the file as containing some fixes */
1322 : /* note that it could be also marked as damaged in other iterations */
- 1323 284013 : file_flag_set(failed[j].file, FILE_IS_FIXED);
+ 1323 288524 : file_flag_set(failed[j].file, FILE_IS_FIXED);
1324 :
- 1325 284013 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
- 1326 284013 : ++recovered_error;
+ 1325 288524 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos);
+ 1326 288524 : ++recovered_error;
1327 : }
1328 :
1329 : /* update parity only if all the blocks have it computed */
1330 : /* if you check/fix after a partial sync, you do not want to fix parity */
1331 : /* for blocks that are going to have it computed in the sync completion */
- 1332 314023 : if (valid_parity) {
+ 1332 314327 : if (valid_parity) {
1333 : /* update the parity */
- 1334 961782 : for (l = 0; l < state->level; ++l) {
+ 1334 962923 : for (l = 0; l < state->level; ++l) {
1335 : /* if the parity on disk is wrong */
- 1336 696931 : if (buffer_recov[l] == 0
+ 1336 697776 : if (buffer_recov[l] == 0
1337 : /* and we have access at the parity */
- 1338 67199 : && parity[l] != 0
+ 1338 67218 : && parity[l] != 0
1339 : /* and the parity is not excluded */
- 1340 62528 : && !state->parity[l].is_excluded
+ 1340 62539 : && !state->parity[l].is_excluded
1341 : ) {
- 1342 62528 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
- 1343 62528 : if (ret == -1) {
+ 1342 62539 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
+ 1343 62539 : if (ret == -1) {
1344 : /* LCOV_EXCL_START */
1345 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
1346 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l));
@@ -1412,17 +1412,17 @@
1350 : /* LCOV_EXCL_STOP */
1351 : }
1352 :
- 1353 62528 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l));
- 1354 62528 : ++recovered_error;
+ 1353 62539 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l));
+ 1354 62539 : ++recovered_error;
1355 : }
1356 : }
1357 : }
1358 : } else {
1359 : /* if we are not fixing, we just set the FIXED flag */
1360 : /* meaning that we could fix this file if we try */
- 1361 727204 : for (j = 0; j < failed_count; ++j) {
- 1362 219960 : if (failed[j].is_bad) {
- 1363 179077 : file_flag_set(failed[j].file, FILE_IS_FIXED);
+ 1361 728890 : for (j = 0; j < failed_count; ++j) {
+ 1362 220745 : if (failed[j].is_bad) {
+ 1363 179860 : file_flag_set(failed[j].file, FILE_IS_FIXED);
1364 : }
1365 : }
1366 : }
@@ -1430,26 +1430,26 @@
1368 : } else {
1369 : /* if we are not checking, we just set the DAMAGED flag */
1370 : /* to report that the file is damaged, and we don't know if we can fix it */
- 1371 45028 : for (j = 0; j < failed_count; ++j) {
- 1372 5851 : if (failed[j].is_bad) {
- 1373 5851 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1371 45085 : for (j = 0; j < failed_count; ++j) {
+ 1372 5850 : if (failed[j].is_bad) {
+ 1373 5850 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
1374 : }
1375 : }
1376 : }
1377 :
1378 : /* post process the files */
- 1379 908266 : ret = file_post(state, fix, i, handle, diskmax);
- 1380 908266 : if (ret == -1) {
+ 1379 909401 : ret = file_post(state, fix, i, handle, diskmax);
+ 1380 909401 : if (ret == -1) {
1381 0 : log_fatal("Stopping at block %u\n", i);
1382 0 : ++unrecoverable_error;
1383 0 : goto bail;
1384 : }
1385 :
1386 : /* count the number of processed block */
- 1387 908266 : ++countpos;
+ 1387 909401 : ++countpos;
1388 :
1389 : /* progress */
- 1390 908266 : if (state_progress(state, i, countpos, countmax, countsize)) {
+ 1390 909401 : if (state_progress(state, i, countpos, countmax, countsize)) {
1391 : /* LCOV_EXCL_START */
1392 : break;
1393 : /* LCOV_EXCL_STOP */
@@ -1467,18 +1467,18 @@
1405 : /* for each empty file in the disk */
1406 705 : disk = handle[i].disk;
1407 705 : node = disk->filelist;
- 1408 2187957 : while (node) {
+ 1408 2188784 : while (node) {
1409 : char path[PATH_MAX];
1410 : struct stat st;
1411 : struct snapraid_file* file;
- 1412 2186547 : int unsuccesful = 0;
+ 1412 2187374 : int unsuccesful = 0;
1413 :
- 1414 2186547 : file = node->data;
- 1415 2186547 : node = node->next; /* next node */
+ 1414 2187374 : file = node->data;
+ 1415 2187374 : node = node->next; /* next node */
1416 :
1417 : /* if not empty, it's already checked and continue to the next one */
- 1418 2186547 : if (file->size != 0) {
- 1419 4367359 : continue;
+ 1418 2187374 : if (file->size != 0) {
+ 1419 4369013 : continue;
1420 : }
1421 :
1422 : /* if excluded continue to the next one */
@@ -1490,21 +1490,21 @@
1428 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
1429 2783 : ret = stat(path, &st);
1430 2783 : if (ret == -1) {
- 1431 173 : unsuccesful = 1;
+ 1431 169 : unsuccesful = 1;
1432 :
- 1433 173 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno));
- 1434 173 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc(file->sub));
- 1435 173 : ++error;
- 1436 2610 : } else if (!S_ISREG(st.st_mode)) {
+ 1433 169 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno));
+ 1434 169 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc(file->sub));
+ 1435 169 : ++error;
+ 1436 2614 : } else if (!S_ISREG(st.st_mode)) {
1437 0 : unsuccesful = 1;
1438 :
1439 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc(file->sub));
1440 0 : ++error;
- 1441 2610 : } else if (st.st_size != 0) {
- 1442 8 : unsuccesful = 1;
+ 1441 2614 : } else if (st.st_size != 0) {
+ 1442 14 : unsuccesful = 1;
1443 :
- 1444 8 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc(file->sub), st.st_size);
- 1445 8 : ++error;
+ 1444 14 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc(file->sub), st.st_size);
+ 1445 14 : ++error;
1446 : }
1447 :
1448 2783 : if (fix && unsuccesful) {
@@ -1650,33 +1650,33 @@
1588 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub);
1589 66532 : ret = readlink(path, linkto, sizeof(linkto));
1590 66532 : if (ret < 0) {
- 1591 4337 : unsuccesful = 1;
+ 1591 4273 : unsuccesful = 1;
1592 :
- 1593 4337 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno));
- 1594 4337 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub));
- 1595 4337 : ++error;
- 1596 62195 : } else if (ret >= PATH_MAX) {
+ 1593 4273 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno));
+ 1594 4273 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub));
+ 1595 4273 : ++error;
+ 1596 62259 : } else if (ret >= PATH_MAX) {
1597 0 : unsuccesful = 1;
1598 :
1599 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path);
1600 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub));
1601 0 : ++error;
1602 : } else {
- 1603 62195 : linkto[ret] = 0;
+ 1603 62259 : linkto[ret] = 0;
1604 :
- 1605 62195 : if (strcmp(linkto, slink->linkto) != 0) {
- 1606 493 : unsuccesful = 1;
+ 1605 62259 : if (strcmp(linkto, slink->linkto) != 0) {
+ 1606 561 : unsuccesful = 1;
1607 :
- 1608 493 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc(slink->sub), linkto, slink->linkto);
- 1609 493 : ++error;
+ 1608 561 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc(slink->sub), linkto, slink->linkto);
+ 1609 561 : ++error;
1610 : }
1611 : }
1612 : }
1613 :
1614 66850 : if (fix && unsuccesful && !unrecoverable) {
1615 : /* create the ancestor directories */
- 1616 3940 : ret = mkancestor(path);
- 1617 3940 : if (ret != 0) {
+ 1616 3941 : ret = mkancestor(path);
+ 1617 3941 : if (ret != 0) {
1618 : /* LCOV_EXCL_START */
1619 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
1620 : log_fatal("Stopping\n");
@@ -1686,8 +1686,8 @@
1624 : }
1625 :
1626 : /* if it exists, it must be deleted before recreating */
- 1627 3940 : ret = remove(path);
- 1628 3940 : if (ret != 0 && errno != ENOENT) {
+ 1627 3941 : ret = remove(path);
+ 1628 3941 : if (ret != 0 && errno != ENOENT) {
1629 : /* LCOV_EXCL_START */
1630 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
1631 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
@@ -1698,7 +1698,7 @@
1636 : }
1637 :
1638 : /* create it */
- 1639 3940 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
+ 1639 3941 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
1640 12 : ret = hardlink(pathto, path);
1641 12 : if (ret != 0) {
1642 : /* LCOV_EXCL_START */
@@ -1718,8 +1718,8 @@
1656 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc(slink->sub));
1657 12 : ++recovered_error;
1658 : } else {
- 1659 3928 : ret = symlink(slink->linkto, path);
- 1660 3928 : if (ret != 0) {
+ 1659 3929 : ret = symlink(slink->linkto, path);
+ 1660 3929 : if (ret != 0) {
1661 : /* LCOV_EXCL_START */
1662 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno));
1663 : if (errno == EACCES) {
@@ -1734,12 +1734,12 @@
1672 : /* LCOV_EXCL_STOP */
1673 : }
1674 :
- 1675 3928 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc(slink->sub));
- 1676 3928 : ++recovered_error;
+ 1675 3929 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc(slink->sub));
+ 1676 3929 : ++recovered_error;
1677 : }
1678 :
- 1679 3940 : log_tag("status:recovered:%s:%s\n", disk->name, esc(slink->sub));
- 1680 3940 : msg_info("recovered %s%s\n", disk->dir, slink->sub);
+ 1679 3941 : log_tag("status:recovered:%s:%s\n", disk->name, esc(slink->sub));
+ 1680 3941 : msg_info("recovered %s%s\n", disk->dir, slink->sub);
1681 : }
1682 : }
1683 :
@@ -1846,23 +1846,23 @@
1784 : /* for each file in the disk */
1785 269 : disk = handle[i].disk;
1786 269 : node = disk->filelist;
- 1787 870399 : while (node) {
+ 1787 870715 : while (node) {
1788 : char path[PATH_MAX];
1789 : struct snapraid_file* file;
1790 :
- 1791 869861 : file = node->data;
- 1792 869861 : node = node->next; /* next node */
+ 1791 870177 : file = node->data;
+ 1792 870177 : node = node->next; /* next node */
1793 :
1794 : /* if the file was not created, meaning that it was already existing */
- 1795 869861 : if (!file_flag_has(file, FILE_IS_CREATED)) {
+ 1795 870177 : if (!file_flag_has(file, FILE_IS_CREATED)) {
1796 : /* nothing to do */
- 1797 1626698 : continue;
+ 1797 1627247 : continue;
1798 : }
1799 :
1800 : /* if processing was finished */
- 1801 113024 : if (file_flag_has(file, FILE_IS_FINISHED)) {
+ 1801 113107 : if (file_flag_has(file, FILE_IS_FINISHED)) {
1802 : /* nothing to do */
- 1803 113024 : continue;
+ 1803 113107 : continue;
1804 : }
1805 :
1806 : /* if the file was originally missing, and processing not yet finished */
diff --git a/cov/cmdline/device.c.func-sort-c.html b/cov/cmdline/device.c.func-sort-c.html
index 566e5929..df63bf7b 100644
--- a/cov/cmdline/device.c.func-sort-c.html
+++ b/cov/cmdline/device.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -64,7 +64,7 @@
72 |
- | printl |
+ printl |
52 |
@@ -84,7 +84,7 @@
| 18 |
- | printp |
+ printp |
18 |
@@ -92,15 +92,15 @@
| 13 |
- | state_device |
+ state_device |
5 |
- | state_smart |
+ state_smart |
1 |
- | devtest |
+ devtest |
1 |
diff --git a/cov/cmdline/device.c.func.html b/cov/cmdline/device.c.func.html
index b0da8a8b..9ffc7cc5 100644
--- a/cov/cmdline/device.c.func.html
+++ b/cov/cmdline/device.c.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -60,7 +60,7 @@
Hit count  |
- | devtest |
+ devtest |
1 |
@@ -76,11 +76,11 @@
| 31 |
- | printl |
+ printl |
52 |
- | printp |
+ printp |
18 |
@@ -96,11 +96,11 @@
| 72 |
- | state_device |
+ state_device |
5 |
- | state_smart |
+ state_smart |
1 |
diff --git a/cov/cmdline/device.c.gcov.html b/cov/cmdline/device.c.gcov.html
index 1014045d..8b590e26 100644
--- a/cov/cmdline/device.c.gcov.html
+++ b/cov/cmdline/device.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -100,7 +100,7 @@
38 : * they really fail, not counting as a failure.
39 : *
40 : * The following tables are computed using the data from 2014-02-14 to 2014-12-31
- 41 : * becasue it's the period when more SMART attributes were gathered.
+ 41 : * because it's the period when more SMART attributes were gathered.
42 : *
43 : * In this period there are 47322 disk seen, with 1988 removed because failed,
44 : * and with 4121 removed because predicted to fail.
@@ -632,451 +632,455 @@
570 : * Garth Alan Gibson, "Redundant Disk Arrays: Reliable, Parallel Secondary Storage", 1990
571 : */
572 :
- 573 : /* get the Mean Time Between Failure of a single disk */
- 574 : /* from the array failure rate */
- 575 18 : MTBF = n / array_failure_rate;
+ 573 : /* avoid division by zero */
+ 574 18 : if (array_failure_rate == 0)
+ 575 0 : return 0;
576 :
- 577 : /* get the Mean Time Between Repair (the time that a failed disk is replaced) */
- 578 : /* from the repair rate */
- 579 18 : MTTR = 1.0 / replace_rate;
+ 577 : /* get the Mean Time Between Failure of a single disk */
+ 578 : /* from the array failure rate */
+ 579 18 : MTBF = n / array_failure_rate;
580 :
- 581 : /* use the approximated MTTDL equation */
- 582 18 : MTTDL = pow(MTBF, redundancy + 1) / pow(MTTR, redundancy);
- 583 99 : for (i = 0; i < redundancy + 1; ++i)
- 584 81 : MTTDL /= n - i;
- 585 :
- 586 : /* the raid failure rate is just the inverse of the MTTDL */
- 587 18 : raid_failure_rate = 1.0 / MTTDL;
- 588 :
- 589 : /* probability of at least one RAID failure */
- 590 : /* note that is almost equal at the probabilty of */
- 591 : /* the first failure. */
- 592 18 : return poisson_prob_n_or_more_failures(raid_failure_rate, 1);
- 593 : }
- 594 :
- 595 : /**
- 596 : * Print a string with space padding.
- 597 : */
- 598 52 : static void printl(const char* str, size_t pad)
- 599 : {
- 600 : size_t len;
- 601 :
- 602 52 : printf("%s", str);
- 603 :
- 604 52 : len = strlen(str);
+ 581 : /* get the Mean Time Between Repair (the time that a failed disk is replaced) */
+ 582 : /* from the repair rate */
+ 583 18 : MTTR = 1.0 / replace_rate;
+ 584 :
+ 585 : /* use the approximated MTTDL equation */
+ 586 18 : MTTDL = pow(MTBF, redundancy + 1) / pow(MTTR, redundancy);
+ 587 99 : for (i = 0; i < redundancy + 1; ++i)
+ 588 81 : MTTDL /= n - i;
+ 589 :
+ 590 : /* the raid failure rate is just the inverse of the MTTDL */
+ 591 18 : raid_failure_rate = 1.0 / MTTDL;
+ 592 :
+ 593 : /* probability of at least one RAID failure */
+ 594 : /* note that is almost equal at the probability of */
+ 595 : /* the first failure. */
+ 596 18 : return poisson_prob_n_or_more_failures(raid_failure_rate, 1);
+ 597 : }
+ 598 :
+ 599 : /**
+ 600 : * Print a string with space padding.
+ 601 : */
+ 602 52 : static void printl(const char* str, size_t pad)
+ 603 : {
+ 604 : size_t len;
605 :
- 606 245 : while (len < pad) {
- 607 141 : printf(" ");
- 608 141 : ++len;
- 609 : }
- 610 52 : }
- 611 :
- 612 : /**
- 613 : * Print a probability with space padding.
- 614 : */
- 615 18 : static void printp(double v, size_t pad)
- 616 : {
- 617 : char buf[64];
- 618 18 : const char* s = "%";
- 619 :
- 620 18 : if (v > 0.1)
- 621 4 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s);
- 622 14 : else if (v > 0.01)
- 623 2 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s);
- 624 12 : else if (v > 0.001)
- 625 3 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s);
- 626 9 : else if (v > 0.0001)
- 627 2 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s);
- 628 7 : else if (v > 0.00001)
- 629 2 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s);
- 630 5 : else if (v > 0.000001)
- 631 1 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s);
- 632 4 : else if (v > 0.0000001)
- 633 1 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s);
- 634 3 : else if (v > 0.00000001)
- 635 1 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s);
- 636 2 : else if (v > 0.000000001)
- 637 1 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s);
- 638 1 : else if (v > 0.0000000001)
- 639 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s);
- 640 1 : else if (v > 0.00000000001)
- 641 1 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s);
- 642 0 : else if (v > 0.000000000001)
- 643 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s);
- 644 : else
- 645 0 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s);
- 646 18 : printl(buf, pad);
- 647 18 : }
- 648 :
- 649 1 : static void state_smart(unsigned n, tommy_list* low)
- 650 : {
- 651 : tommy_node* i;
- 652 : unsigned j;
- 653 : size_t device_pad;
- 654 : size_t serial_pad;
- 655 : int have_parent;
- 656 : double array_failure_rate;
- 657 : double p_at_least_one_failure;
- 658 1 : int make_it_fail = 0;
- 659 1 : uint64_t mask32 = 0xffffffffU;
- 660 1 : uint64_t mask16 = 0xffffU;
- 661 :
- 662 : /* compute lengths for padding */
- 663 1 : device_pad = 0;
- 664 1 : serial_pad = 0;
- 665 1 : have_parent = 0;
- 666 17 : for (i = tommy_list_head(low); i != 0; i = i->next) {
- 667 : size_t len;
- 668 16 : devinfo_t* devinfo = i->data;
- 669 :
- 670 16 : len = strlen(devinfo->file);
- 671 16 : if (len > device_pad)
- 672 1 : device_pad = len;
+ 606 52 : printf("%s", str);
+ 607 :
+ 608 52 : len = strlen(str);
+ 609 :
+ 610 245 : while (len < pad) {
+ 611 141 : printf(" ");
+ 612 141 : ++len;
+ 613 : }
+ 614 52 : }
+ 615 :
+ 616 : /**
+ 617 : * Print a probability with space padding.
+ 618 : */
+ 619 18 : static void printp(double v, size_t pad)
+ 620 : {
+ 621 : char buf[64];
+ 622 18 : const char* s = "%";
+ 623 :
+ 624 18 : if (v > 0.1)
+ 625 4 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s);
+ 626 14 : else if (v > 0.01)
+ 627 2 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s);
+ 628 12 : else if (v > 0.001)
+ 629 3 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s);
+ 630 9 : else if (v > 0.0001)
+ 631 2 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s);
+ 632 7 : else if (v > 0.00001)
+ 633 2 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s);
+ 634 5 : else if (v > 0.000001)
+ 635 1 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s);
+ 636 4 : else if (v > 0.0000001)
+ 637 1 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s);
+ 638 3 : else if (v > 0.00000001)
+ 639 1 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s);
+ 640 2 : else if (v > 0.000000001)
+ 641 1 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s);
+ 642 1 : else if (v > 0.0000000001)
+ 643 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s);
+ 644 1 : else if (v > 0.00000000001)
+ 645 1 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s);
+ 646 0 : else if (v > 0.000000000001)
+ 647 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s);
+ 648 : else
+ 649 0 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s);
+ 650 18 : printl(buf, pad);
+ 651 18 : }
+ 652 :
+ 653 1 : static void state_smart(unsigned n, tommy_list* low)
+ 654 : {
+ 655 : tommy_node* i;
+ 656 : unsigned j;
+ 657 : size_t device_pad;
+ 658 : size_t serial_pad;
+ 659 : int have_parent;
+ 660 : double array_failure_rate;
+ 661 : double p_at_least_one_failure;
+ 662 1 : int make_it_fail = 0;
+ 663 1 : uint64_t mask32 = 0xffffffffU;
+ 664 1 : uint64_t mask16 = 0xffffU;
+ 665 :
+ 666 : /* compute lengths for padding */
+ 667 1 : device_pad = 0;
+ 668 1 : serial_pad = 0;
+ 669 1 : have_parent = 0;
+ 670 17 : for (i = tommy_list_head(low); i != 0; i = i->next) {
+ 671 : size_t len;
+ 672 16 : devinfo_t* devinfo = i->data;
673 :
- 674 16 : len = strlen(devinfo->smart_serial);
- 675 16 : if (len > serial_pad)
- 676 2 : serial_pad = len;
+ 674 16 : len = strlen(devinfo->file);
+ 675 16 : if (len > device_pad)
+ 676 1 : device_pad = len;
677 :
- 678 16 : if (devinfo->parent != 0)
- 679 0 : have_parent = 1;
- 680 : }
+ 678 16 : len = strlen(devinfo->smart_serial);
+ 679 16 : if (len > serial_pad)
+ 680 2 : serial_pad = len;
681 :
- 682 1 : printf("SnapRAID SMART report:\n");
- 683 1 : printf("\n");
- 684 1 : printf(" Temp");
- 685 1 : printf(" Power");
- 686 1 : printf(" Error");
- 687 1 : printf(" FP");
- 688 1 : printf(" Size");
- 689 1 : printf("\n");
- 690 1 : printf(" C");
- 691 1 : printf(" OnDays");
- 692 1 : printf(" Count");
- 693 1 : printf(" ");
- 694 1 : printf(" TB");
- 695 1 : printf(" "); printl("Serial", serial_pad);
- 696 1 : printf(" "); printl("Device", device_pad);
- 697 1 : printf(" Disk");
- 698 1 : printf("\n");
- 699 : /* |<##################################################################72>|####80>| */
- 700 1 : printf(" -----------------------------------------------------------------------\n");
- 701 :
- 702 1 : array_failure_rate = 0;
- 703 17 : for (i = tommy_list_head(low); i != 0; i = i->next) {
- 704 16 : devinfo_t* devinfo = i->data;
- 705 : double afr;
- 706 : uint64_t flag;
- 707 :
- 708 16 : if (devinfo->smart[194] != SMART_UNASSIGNED)
- 709 15 : printf("%7" PRIu64, devinfo->smart[194] & mask16);
- 710 1 : else if (devinfo->smart[190] != SMART_UNASSIGNED)
- 711 0 : printf("%7" PRIu64, devinfo->smart[190] & mask16);
- 712 : else
- 713 1 : printf(" -");
- 714 :
- 715 16 : if (devinfo->smart[9] != SMART_UNASSIGNED)
- 716 15 : printf("%7" PRIu64, (devinfo->smart[9] & mask32) / 24);
- 717 : else
- 718 1 : printf(" -");
- 719 :
- 720 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
- 721 8 : flag = devinfo->smart[SMART_FLAGS];
- 722 : else
- 723 8 : flag = 0;
- 724 16 : if (flag & SMARTCTL_FLAG_FAIL)
- 725 1 : printf(" FAIL");
- 726 15 : else if (flag & SMARTCTL_FLAG_PREFAIL)
- 727 1 : printf(" PREFAIL");
- 728 14 : else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED)
- 729 1 : printf(" logfail");
- 730 13 : else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED
- 731 13 : && devinfo->smart[SMART_ERROR] != 0)
- 732 1 : printf("%8" PRIu64, devinfo->smart[SMART_ERROR]);
- 733 12 : else if (flag & SMARTCTL_FLAG_ERROR)
- 734 1 : printf(" logerr");
- 735 11 : else if (flag & SMARTCTL_FLAG_ERROR_LOGGED)
- 736 1 : printf(" selferr");
- 737 10 : else if (devinfo->smart[SMART_ERROR] == 0)
- 738 10 : printf(" 0");
- 739 : else
- 740 0 : printf(" -");
- 741 :
- 742 : /* if some fail/prefail attribute, make the command to fail */
- 743 16 : if (flag & (SMARTCTL_FLAG_FAIL | SMARTCTL_FLAG_PREFAIL))
- 744 2 : make_it_fail = 1;
+ 682 16 : if (devinfo->parent != 0)
+ 683 0 : have_parent = 1;
+ 684 : }
+ 685 :
+ 686 1 : printf("SnapRAID SMART report:\n");
+ 687 1 : printf("\n");
+ 688 1 : printf(" Temp");
+ 689 1 : printf(" Power");
+ 690 1 : printf(" Error");
+ 691 1 : printf(" FP");
+ 692 1 : printf(" Size");
+ 693 1 : printf("\n");
+ 694 1 : printf(" C");
+ 695 1 : printf(" OnDays");
+ 696 1 : printf(" Count");
+ 697 1 : printf(" ");
+ 698 1 : printf(" TB");
+ 699 1 : printf(" "); printl("Serial", serial_pad);
+ 700 1 : printf(" "); printl("Device", device_pad);
+ 701 1 : printf(" Disk");
+ 702 1 : printf("\n");
+ 703 : /* |<##################################################################72>|####80>| */
+ 704 1 : printf(" -----------------------------------------------------------------------\n");
+ 705 :
+ 706 1 : array_failure_rate = 0;
+ 707 17 : for (i = tommy_list_head(low); i != 0; i = i->next) {
+ 708 16 : devinfo_t* devinfo = i->data;
+ 709 : double afr;
+ 710 : uint64_t flag;
+ 711 :
+ 712 16 : if (devinfo->smart[194] != SMART_UNASSIGNED)
+ 713 15 : printf("%7" PRIu64, devinfo->smart[194] & mask16);
+ 714 1 : else if (devinfo->smart[190] != SMART_UNASSIGNED)
+ 715 0 : printf("%7" PRIu64, devinfo->smart[190] & mask16);
+ 716 : else
+ 717 1 : printf(" -");
+ 718 :
+ 719 16 : if (devinfo->smart[9] != SMART_UNASSIGNED)
+ 720 15 : printf("%7" PRIu64, (devinfo->smart[9] & mask32) / 24);
+ 721 : else
+ 722 1 : printf(" -");
+ 723 :
+ 724 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
+ 725 8 : flag = devinfo->smart[SMART_FLAGS];
+ 726 : else
+ 727 8 : flag = 0;
+ 728 16 : if (flag & SMARTCTL_FLAG_FAIL)
+ 729 1 : printf(" FAIL");
+ 730 15 : else if (flag & SMARTCTL_FLAG_PREFAIL)
+ 731 1 : printf(" PREFAIL");
+ 732 14 : else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED)
+ 733 1 : printf(" logfail");
+ 734 13 : else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED
+ 735 13 : && devinfo->smart[SMART_ERROR] != 0)
+ 736 1 : printf("%8" PRIu64, devinfo->smart[SMART_ERROR]);
+ 737 12 : else if (flag & SMARTCTL_FLAG_ERROR)
+ 738 1 : printf(" logerr");
+ 739 11 : else if (flag & SMARTCTL_FLAG_ERROR_LOGGED)
+ 740 1 : printf(" selferr");
+ 741 10 : else if (devinfo->smart[SMART_ERROR] == 0)
+ 742 10 : printf(" 0");
+ 743 : else
+ 744 0 : printf(" -");
745 :
- 746 : /* note that in older smartmontools, like 5.x, rotation rate is not present */
- 747 : /* and then it could remain unassigned */
- 748 :
- 749 16 : if (flag & (SMARTCTL_FLAG_UNSUPPORTED | SMARTCTL_FLAG_OPEN)) {
- 750 : /* if error running smartctl, skip AFR estimation */
- 751 2 : afr = 0;
- 752 2 : printf(" n/a");
- 753 14 : } else if (devinfo->smart[SMART_ROTATION_RATE] == 0) {
- 754 : /* if SSD, skip AFR estimation as data is from not SSD disks */
- 755 1 : afr = 0;
- 756 1 : printf(" SSD");
- 757 : } else {
- 758 13 : afr = smart_afr(devinfo->smart);
- 759 :
- 760 13 : if (afr == 0) {
- 761 : /* this happens only if no data */
- 762 1 : printf(" -");
- 763 : } else {
- 764 : /* use only the disks in the array */
- 765 12 : if (devinfo->parent != 0 || !have_parent)
- 766 12 : array_failure_rate += afr;
- 767 :
- 768 12 : printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100);
- 769 : }
- 770 : }
+ 746 : /* if some fail/prefail attribute, make the command to fail */
+ 747 16 : if (flag & (SMARTCTL_FLAG_FAIL | SMARTCTL_FLAG_PREFAIL))
+ 748 2 : make_it_fail = 1;
+ 749 :
+ 750 : /* note that in older smartmontools, like 5.x, rotation rate is not present */
+ 751 : /* and then it could remain unassigned */
+ 752 :
+ 753 16 : if (flag & (SMARTCTL_FLAG_UNSUPPORTED | SMARTCTL_FLAG_OPEN)) {
+ 754 : /* if error running smartctl, skip AFR estimation */
+ 755 2 : afr = 0;
+ 756 2 : printf(" n/a");
+ 757 14 : } else if (devinfo->smart[SMART_ROTATION_RATE] == 0) {
+ 758 : /* if SSD, skip AFR estimation as data is from not SSD disks */
+ 759 1 : afr = 0;
+ 760 1 : printf(" SSD");
+ 761 : } else {
+ 762 13 : afr = smart_afr(devinfo->smart);
+ 763 :
+ 764 13 : if (afr == 0) {
+ 765 : /* this happens only if no data */
+ 766 1 : printf(" -");
+ 767 : } else {
+ 768 : /* use only the disks in the array */
+ 769 12 : if (devinfo->parent != 0 || !have_parent)
+ 770 12 : array_failure_rate += afr;
771 :
- 772 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
- 773 15 : printf(" %4.1f", devinfo->smart[SMART_SIZE] / 1E12);
- 774 : else
- 775 1 : printf(" -");
- 776 :
- 777 16 : printf(" ");
- 778 16 : if (*devinfo->smart_serial)
- 779 15 : printl(devinfo->smart_serial, serial_pad);
- 780 : else
- 781 1 : printl("-", serial_pad);
- 782 :
- 783 16 : printf(" ");
- 784 16 : if (*devinfo->file)
- 785 15 : printl(devinfo->file, device_pad);
- 786 : else
- 787 1 : printl("-", device_pad);
- 788 :
- 789 16 : printf(" ");
- 790 16 : if (*devinfo->name)
- 791 15 : printf("%s", devinfo->name);
- 792 : else
- 793 1 : printf("-");
- 794 :
- 795 16 : printf("\n");
- 796 :
- 797 16 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name);
- 798 16 : if (devinfo->smart_serial[0])
- 799 15 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc(devinfo->smart_serial));
- 800 16 : if (afr != 0)
- 801 12 : log_tag("attr:%s:%s:afr:%g\n", devinfo->file, devinfo->name, afr);
- 802 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
- 803 15 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_SIZE]);
- 804 16 : if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED)
- 805 16 : log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]);
- 806 16 : if (devinfo->smart[SMART_ROTATION_RATE] != SMART_UNASSIGNED)
- 807 16 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ROTATION_RATE]);
- 808 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
- 809 8 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]);
- 810 4112 : for (j = 0; j < 256; ++j)
- 811 4096 : if (devinfo->smart[j] != SMART_UNASSIGNED)
- 812 3840 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]);
- 813 : }
- 814 :
- 815 1 : printf("\n");
- 816 :
- 817 : /* |<##################################################################72>|####80>| */
- 818 1 : printf("The FP column is the estimated probability (in percentage) that the disk\n");
- 819 1 : printf("is going to fail in the next year.\n");
- 820 1 : printf("\n");
- 821 :
- 822 : /*
- 823 : * The probability of one and of at least one failure is computed assuming
- 824 : * a Poisson distribution with the estimated array failure rate.
- 825 : */
- 826 1 : p_at_least_one_failure = poisson_prob_n_or_more_failures(array_failure_rate, 1);
- 827 :
- 828 1 : printf("Probability that at least one disk is going to fail in the next year is %.0f%%.\n", p_at_least_one_failure * 100);
- 829 1 : log_tag("summary:array_failure:%g:%g\n", array_failure_rate, p_at_least_one_failure);
- 830 :
- 831 : /* print extra stats only in verbose mode */
- 832 1 : if (msg_level < MSG_VERBOSE)
- 833 0 : goto bail;
+ 772 12 : printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100);
+ 773 : }
+ 774 : }
+ 775 :
+ 776 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
+ 777 15 : printf(" %4.1f", devinfo->smart[SMART_SIZE] / 1E12);
+ 778 : else
+ 779 1 : printf(" -");
+ 780 :
+ 781 16 : printf(" ");
+ 782 16 : if (*devinfo->smart_serial)
+ 783 15 : printl(devinfo->smart_serial, serial_pad);
+ 784 : else
+ 785 1 : printl("-", serial_pad);
+ 786 :
+ 787 16 : printf(" ");
+ 788 16 : if (*devinfo->file)
+ 789 15 : printl(devinfo->file, device_pad);
+ 790 : else
+ 791 1 : printl("-", device_pad);
+ 792 :
+ 793 16 : printf(" ");
+ 794 16 : if (*devinfo->name)
+ 795 15 : printf("%s", devinfo->name);
+ 796 : else
+ 797 1 : printf("-");
+ 798 :
+ 799 16 : printf("\n");
+ 800 :
+ 801 16 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name);
+ 802 16 : if (devinfo->smart_serial[0])
+ 803 15 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc(devinfo->smart_serial));
+ 804 16 : if (afr != 0)
+ 805 12 : log_tag("attr:%s:%s:afr:%g\n", devinfo->file, devinfo->name, afr);
+ 806 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
+ 807 15 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_SIZE]);
+ 808 16 : if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED)
+ 809 16 : log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]);
+ 810 16 : if (devinfo->smart[SMART_ROTATION_RATE] != SMART_UNASSIGNED)
+ 811 16 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ROTATION_RATE]);
+ 812 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
+ 813 8 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]);
+ 814 4112 : for (j = 0; j < 256; ++j)
+ 815 4096 : if (devinfo->smart[j] != SMART_UNASSIGNED)
+ 816 3840 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]);
+ 817 : }
+ 818 :
+ 819 1 : printf("\n");
+ 820 :
+ 821 : /* |<##################################################################72>|####80>| */
+ 822 1 : printf("The FP column is the estimated probability (in percentage) that the disk\n");
+ 823 1 : printf("is going to fail in the next year.\n");
+ 824 1 : printf("\n");
+ 825 :
+ 826 : /*
+ 827 : * The probability of one and of at least one failure is computed assuming
+ 828 : * a Poisson distribution with the estimated array failure rate.
+ 829 : */
+ 830 1 : p_at_least_one_failure = poisson_prob_n_or_more_failures(array_failure_rate, 1);
+ 831 :
+ 832 1 : printf("Probability that at least one disk is going to fail in the next year is %.0f%%.\n", p_at_least_one_failure * 100);
+ 833 1 : log_tag("summary:array_failure:%g:%g\n", array_failure_rate, p_at_least_one_failure);
834 :
- 835 : /* |<##################################################################72>|####80>| */
- 836 1 : printf("\n");
- 837 1 : printf("Probability of data loss in the next year for different parity and\n");
- 838 1 : printf("combined scrub and repair time:\n");
- 839 1 : printf("\n");
- 840 1 : printf(" Parity 1 Week 1 Month 3 Months\n");
- 841 1 : printf(" -----------------------------------------------------------------------\n");
- 842 7 : for (j = 0; j < RAID_PARITY_MAX; ++j) {
- 843 6 : printf("%6u", j + 1);
- 844 6 : printf(" ");
- 845 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 7, n, j + 1) * 100, 19);
- 846 6 : printf(" ");
- 847 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 30, n, j + 1) * 100, 17);
+ 835 : /* print extra stats only in verbose mode */
+ 836 1 : if (msg_level < MSG_VERBOSE)
+ 837 0 : goto bail;
+ 838 :
+ 839 : /* |<##################################################################72>|####80>| */
+ 840 1 : printf("\n");
+ 841 1 : printf("Probability of data loss in the next year for different parity and\n");
+ 842 1 : printf("combined scrub and repair time:\n");
+ 843 1 : printf("\n");
+ 844 1 : printf(" Parity 1 Week 1 Month 3 Months\n");
+ 845 1 : printf(" -----------------------------------------------------------------------\n");
+ 846 7 : for (j = 0; j < RAID_PARITY_MAX; ++j) {
+ 847 6 : printf("%6u", j + 1);
848 6 : printf(" ");
- 849 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 90, n, j + 1) * 100, 13);
- 850 6 : printf("\n");
- 851 : }
- 852 :
- 853 1 : printf("\n");
- 854 :
- 855 : /* |<##################################################################72>|####80>| */
- 856 1 : printf("These values are the probabilities that in the next year you'll have a\n");
- 857 1 : printf("sequence of failures that the parity WONT be able to recover, assuming\n");
- 858 1 : printf("that you regularly scrub, and in case repair, the array in the specified\n");
- 859 1 : printf("time.\n");
- 860 :
- 861 : bail:
- 862 1 : if (make_it_fail) {
- 863 1 : printf("\n");
- 864 1 : printf("DANGER! SMART is reporting that one or more disks are FAILING!\n");
- 865 1 : printf("Please take immediate action!\n");
- 866 1 : exit(EXIT_FAILURE);
- 867 : }
- 868 0 : }
- 869 :
- 870 : /**
- 871 : * Fill with fake data the device list.
- 872 : */
- 873 1 : static int devtest(tommy_list* low, int operation)
- 874 : {
- 875 : unsigned c;
- 876 :
- 877 1 : if (operation != DEVICE_SMART)
- 878 0 : return -1;
- 879 :
- 880 : /* add some fake data */
- 881 17 : for (c = 0; c < 16; ++c) {
- 882 : devinfo_t* entry;
- 883 : int j;
- 884 :
- 885 16 : entry = calloc_nofail(1, sizeof(devinfo_t));
- 886 :
- 887 16 : entry->device = c;
+ 849 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 7, n, j + 1) * 100, 19);
+ 850 6 : printf(" ");
+ 851 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 30, n, j + 1) * 100, 17);
+ 852 6 : printf(" ");
+ 853 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 90, n, j + 1) * 100, 13);
+ 854 6 : printf("\n");
+ 855 : }
+ 856 :
+ 857 1 : printf("\n");
+ 858 :
+ 859 : /* |<##################################################################72>|####80>| */
+ 860 1 : printf("These values are the probabilities that in the next year you'll have a\n");
+ 861 1 : printf("sequence of failures that the parity WONT be able to recover, assuming\n");
+ 862 1 : printf("that you regularly scrub, and in case repair, the array in the specified\n");
+ 863 1 : printf("time.\n");
+ 864 :
+ 865 : bail:
+ 866 1 : if (make_it_fail) {
+ 867 1 : printf("\n");
+ 868 1 : printf("DANGER! SMART is reporting that one or more disks are FAILING!\n");
+ 869 1 : printf("Please take immediate action!\n");
+ 870 1 : exit(EXIT_FAILURE);
+ 871 : }
+ 872 0 : }
+ 873 :
+ 874 : /**
+ 875 : * Fill with fake data the device list.
+ 876 : */
+ 877 1 : static int devtest(tommy_list* low, int operation)
+ 878 : {
+ 879 : unsigned c;
+ 880 :
+ 881 1 : if (operation != DEVICE_SMART)
+ 882 0 : return -1;
+ 883 :
+ 884 : /* add some fake data */
+ 885 17 : for (c = 0; c < 16; ++c) {
+ 886 : devinfo_t* entry;
+ 887 : int j;
888 :
- 889 16 : tommy_list_insert_tail(low, &entry->node, entry);
+ 889 16 : entry = calloc_nofail(1, sizeof(devinfo_t));
890 :
- 891 4112 : for (j = 0; j < 256; ++j) {
- 892 4096 : switch (c) {
- 893 256 : case 0 : entry->smart[j] = 0; break;
- 894 256 : case 1 : entry->smart[j] = SMART_UNASSIGNED; break;
- 895 : default:
- 896 3584 : if (j == 193)
- 897 14 : entry->smart[j] = c - 2;
- 898 : else
- 899 3570 : entry->smart[j] = 0;
- 900 3584 : break;
- 901 : }
- 902 : }
- 903 :
- 904 16 : if (c == 0) {
- 905 1 : entry->smart_serial[0] = 0;
- 906 1 : entry->file[0] = 0;
- 907 1 : entry->name[0] = 0;
- 908 1 : entry->smart[SMART_SIZE] = SMART_UNASSIGNED;
- 909 1 : entry->smart[SMART_ROTATION_RATE] = 0;
- 910 : } else {
- 911 15 : snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c);
- 912 15 : pathcpy(entry->file, sizeof(entry->name), "file");
- 913 15 : pathcpy(entry->name, sizeof(entry->name), "name");
- 914 15 : entry->smart[SMART_SIZE] = c * TERA;
- 915 15 : entry->smart[SMART_ROTATION_RATE] = 7200;
- 916 : }
- 917 :
- 918 16 : entry->smart[SMART_ERROR] = 0;
- 919 16 : entry->smart[SMART_FLAGS] = SMART_UNASSIGNED;
- 920 :
- 921 16 : switch (c) {
- 922 1 : case 3 : entry->smart[SMART_ERROR] = 1; break;
- 923 1 : case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break;
- 924 1 : case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break;
- 925 1 : case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break;
- 926 1 : case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break;
- 927 1 : case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break;
- 928 1 : case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break;
- 929 1 : case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break;
- 930 1 : case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break;
- 931 : }
- 932 : }
- 933 :
- 934 1 : return 0;
- 935 : }
- 936 :
- 937 5 : void state_device(struct snapraid_state* state, int operation)
- 938 : {
- 939 : tommy_node* i;
- 940 : unsigned j;
- 941 : tommy_list high;
- 942 : tommy_list low;
- 943 : int ret;
- 944 :
- 945 5 : switch (operation) {
- 946 1 : case DEVICE_UP : msg_progress("Spinup...\n"); break;
- 947 1 : case DEVICE_DOWN : msg_progress("Spindown...\n"); break;
- 948 : }
- 949 :
- 950 5 : tommy_list_init(&high);
- 951 5 : tommy_list_init(&low);
- 952 :
- 953 : /* for all disks */
- 954 35 : for (i = state->disklist; i != 0; i = i->next) {
- 955 30 : struct snapraid_disk* disk = i->data;
- 956 : devinfo_t* entry;
- 957 :
- 958 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
- 959 :
- 960 30 : entry->device = disk->device;
- 961 30 : pathcpy(entry->name, sizeof(entry->name), disk->name);
- 962 30 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir);
- 963 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl);
- 964 :
- 965 30 : tommy_list_insert_tail(&high, &entry->node, entry);
- 966 : }
- 967 :
- 968 : /* for all parities */
- 969 35 : for (j = 0; j < state->level; ++j) {
- 970 : devinfo_t* entry;
+ 891 16 : entry->device = c;
+ 892 :
+ 893 16 : tommy_list_insert_tail(low, &entry->node, entry);
+ 894 :
+ 895 4112 : for (j = 0; j < 256; ++j) {
+ 896 4096 : switch (c) {
+ 897 256 : case 0 : entry->smart[j] = 0; break;
+ 898 256 : case 1 : entry->smart[j] = SMART_UNASSIGNED; break;
+ 899 : default:
+ 900 3584 : if (j == 193)
+ 901 14 : entry->smart[j] = c - 2;
+ 902 : else
+ 903 3570 : entry->smart[j] = 0;
+ 904 3584 : break;
+ 905 : }
+ 906 : }
+ 907 :
+ 908 16 : if (c == 0) {
+ 909 1 : entry->smart_serial[0] = 0;
+ 910 1 : entry->file[0] = 0;
+ 911 1 : entry->name[0] = 0;
+ 912 1 : entry->smart[SMART_SIZE] = SMART_UNASSIGNED;
+ 913 1 : entry->smart[SMART_ROTATION_RATE] = 0;
+ 914 : } else {
+ 915 15 : snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c);
+ 916 15 : pathcpy(entry->file, sizeof(entry->name), "file");
+ 917 15 : pathcpy(entry->name, sizeof(entry->name), "name");
+ 918 15 : entry->smart[SMART_SIZE] = c * TERA;
+ 919 15 : entry->smart[SMART_ROTATION_RATE] = 7200;
+ 920 : }
+ 921 :
+ 922 16 : entry->smart[SMART_ERROR] = 0;
+ 923 16 : entry->smart[SMART_FLAGS] = SMART_UNASSIGNED;
+ 924 :
+ 925 16 : switch (c) {
+ 926 1 : case 3 : entry->smart[SMART_ERROR] = 1; break;
+ 927 1 : case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break;
+ 928 1 : case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break;
+ 929 1 : case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break;
+ 930 1 : case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break;
+ 931 1 : case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break;
+ 932 1 : case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break;
+ 933 1 : case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break;
+ 934 1 : case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break;
+ 935 : }
+ 936 : }
+ 937 :
+ 938 1 : return 0;
+ 939 : }
+ 940 :
+ 941 5 : void state_device(struct snapraid_state* state, int operation)
+ 942 : {
+ 943 : tommy_node* i;
+ 944 : unsigned j;
+ 945 : tommy_list high;
+ 946 : tommy_list low;
+ 947 : int ret;
+ 948 :
+ 949 5 : switch (operation) {
+ 950 1 : case DEVICE_UP : msg_progress("Spinup...\n"); break;
+ 951 1 : case DEVICE_DOWN : msg_progress("Spindown...\n"); break;
+ 952 : }
+ 953 :
+ 954 5 : tommy_list_init(&high);
+ 955 5 : tommy_list_init(&low);
+ 956 :
+ 957 : /* for all disks */
+ 958 35 : for (i = state->disklist; i != 0; i = i->next) {
+ 959 30 : struct snapraid_disk* disk = i->data;
+ 960 : devinfo_t* entry;
+ 961 :
+ 962 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
+ 963 :
+ 964 30 : entry->device = disk->device;
+ 965 30 : pathcpy(entry->name, sizeof(entry->name), disk->name);
+ 966 30 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir);
+ 967 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl);
+ 968 :
+ 969 30 : tommy_list_insert_tail(&high, &entry->node, entry);
+ 970 : }
971 :
- 972 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
- 973 :
- 974 30 : entry->device = state->parity[j].device;
- 975 30 : pathcpy(entry->name, sizeof(entry->name), lev_config_name(j));
- 976 30 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path);
- 977 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl);
- 978 30 : pathcut(entry->mount); /* remove the parity file */
- 979 :
- 980 30 : tommy_list_insert_tail(&high, &entry->node, entry);
- 981 : }
- 982 :
- 983 5 : if (state->opt.fake_device)
- 984 1 : ret = devtest(&low, operation);
- 985 : else
- 986 4 : ret = devquery(&high, &low, operation);
- 987 :
- 988 5 : if (ret != 0) {
- 989 2 : const char* ope = 0;
- 990 2 : switch (operation) {
- 991 0 : case DEVICE_UP : ope = "Spinup"; break;
- 992 1 : case DEVICE_DOWN : ope = "Spindown"; break;
- 993 0 : case DEVICE_LIST : ope = "List"; break;
- 994 1 : case DEVICE_SMART : ope = "SMART"; break;
- 995 : }
- 996 2 : log_fatal("%s unsupported in this platform.\n", ope);
- 997 : } else {
- 998 3 : if (operation == DEVICE_LIST) {
- 999 13 : for (i = tommy_list_head(&low); i != 0; i = i->next) {
- 1000 12 : devinfo_t* devinfo = i->data;
- 1001 12 : devinfo_t* parent = devinfo->parent;
- 1002 : #ifdef _WIN32
- 1003 : printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name);
- 1004 : #else
- 1005 12 : printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name);
- 1006 : #endif
- 1007 : }
- 1008 : }
- 1009 :
- 1010 3 : if (operation == DEVICE_SMART)
- 1011 1 : state_smart(state->level + tommy_list_count(&state->disklist), &low);
- 1012 : }
+ 972 : /* for all parities */
+ 973 35 : for (j = 0; j < state->level; ++j) {
+ 974 : devinfo_t* entry;
+ 975 :
+ 976 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
+ 977 :
+ 978 30 : entry->device = state->parity[j].device;
+ 979 30 : pathcpy(entry->name, sizeof(entry->name), lev_config_name(j));
+ 980 30 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path);
+ 981 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl);
+ 982 30 : pathcut(entry->mount); /* remove the parity file */
+ 983 :
+ 984 30 : tommy_list_insert_tail(&high, &entry->node, entry);
+ 985 : }
+ 986 :
+ 987 5 : if (state->opt.fake_device)
+ 988 1 : ret = devtest(&low, operation);
+ 989 : else
+ 990 4 : ret = devquery(&high, &low, operation);
+ 991 :
+ 992 5 : if (ret != 0) {
+ 993 2 : const char* ope = 0;
+ 994 2 : switch (operation) {
+ 995 0 : case DEVICE_UP : ope = "Spinup"; break;
+ 996 1 : case DEVICE_DOWN : ope = "Spindown"; break;
+ 997 0 : case DEVICE_LIST : ope = "List"; break;
+ 998 1 : case DEVICE_SMART : ope = "SMART"; break;
+ 999 : }
+ 1000 2 : log_fatal("%s unsupported in this platform.\n", ope);
+ 1001 : } else {
+ 1002 3 : if (operation == DEVICE_LIST) {
+ 1003 13 : for (i = tommy_list_head(&low); i != 0; i = i->next) {
+ 1004 12 : devinfo_t* devinfo = i->data;
+ 1005 12 : devinfo_t* parent = devinfo->parent;
+ 1006 : #ifdef _WIN32
+ 1007 : printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name);
+ 1008 : #else
+ 1009 12 : printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name);
+ 1010 : #endif
+ 1011 : }
+ 1012 : }
1013 :
- 1014 4 : tommy_list_foreach(&high, free);
- 1015 4 : tommy_list_foreach(&low, free);
- 1016 4 : }
+ 1014 3 : if (operation == DEVICE_SMART)
+ 1015 1 : state_smart(state->level + tommy_list_count(&state->disklist), &low);
+ 1016 : }
1017 :
+ 1018 4 : tommy_list_foreach(&high, free);
+ 1019 4 : tommy_list_foreach(&low, free);
+ 1020 4 : }
+ 1021 :
diff --git a/cov/cmdline/dry.c.func-sort-c.html b/cov/cmdline/dry.c.func-sort-c.html
index ac636230..fd89714e 100644
--- a/cov/cmdline/dry.c.func-sort-c.html
+++ b/cov/cmdline/dry.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/dry.c.func.html b/cov/cmdline/dry.c.func.html
index 05c93ac8..318ac87c 100644
--- a/cov/cmdline/dry.c.func.html
+++ b/cov/cmdline/dry.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/dry.c.gcov.html b/cov/cmdline/dry.c.gcov.html
index 52891e1b..6886148c 100644
--- a/cov/cmdline/dry.c.gcov.html
+++ b/cov/cmdline/dry.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -116,38 +116,38 @@
54 2 : countsize = 0;
55 2 : countpos = 0;
56 2 : state_progress_begin(state, blockstart, blockmax, countmax);
- 57 7054 : for (i = blockstart; i < blockmax; ++i) {
+ 57 7088 : for (i = blockstart; i < blockmax; ++i) {
58 : /* for each disk, process the block */
- 59 49364 : for (j = 0; j < diskmax; ++j) {
+ 59 49602 : for (j = 0; j < diskmax; ++j) {
60 : int read_size;
61 : struct snapraid_block* block;
- 62 42312 : struct snapraid_disk* disk = handle[j].disk;
+ 62 42516 : struct snapraid_disk* disk = handle[j].disk;
63 : struct snapraid_file* file;
64 : block_off_t file_pos;
65 :
- 66 42312 : if (!disk) {
+ 66 42516 : if (!disk) {
67 : /* if no disk, nothing to do */
- 68 9755 : continue;
+ 68 9855 : continue;
69 : }
70 :
- 71 37641 : block = fs_par2block_get(disk, i);
+ 71 37837 : block = fs_par2block_get(disk, i);
72 :
- 73 37641 : if (!block_has_file(block)) {
+ 73 37837 : if (!block_has_file(block)) {
74 : /* if no file, nothing to do */
- 75 413 : continue;
+ 75 497 : continue;
76 : }
77 :
78 : /* get the file of this block */
- 79 37228 : file = fs_par2file_get(disk, i, &file_pos);
+ 79 37340 : file = fs_par2file_get(disk, i, &file_pos);
80 :
81 : /* until now is CPU */
- 82 37228 : state_usage_cpu(state);
+ 82 37340 : state_usage_cpu(state);
83 :
84 : /* if the file is closed or different than the current one */
- 85 37228 : if (handle[j].file == 0 || handle[j].file != file) {
+ 85 37340 : if (handle[j].file == 0 || handle[j].file != file) {
86 : /* close the old one, if any */
- 87 15082 : ret = handle_close(&handle[j]);
- 88 15082 : if (ret == -1) {
+ 87 15096 : ret = handle_close(&handle[j]);
+ 88 15096 : if (ret == -1) {
89 : /* LCOV_EXCL_START */
90 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(handle[j].file->sub), strerror(errno));
91 : log_fatal("DANGER! Unexpected close error in a data disk, it isn't possible to dry.\n");
@@ -158,8 +158,8 @@
96 : }
97 :
98 : /* open the file only for reading */
- 99 15082 : ret = handle_open(&handle[j], file, state->file_mode, log_fatal, 0);
- 100 15082 : if (ret == -1) {
+ 99 15096 : ret = handle_open(&handle[j], file, state->file_mode, log_fatal, 0);
+ 100 15096 : if (ret == -1) {
101 : /* LCOV_EXCL_START */
102 : log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
103 : log_fatal("DANGER! Unexpected open error in a data disk, it isn't possible to dry.\n");
@@ -171,41 +171,41 @@
109 : }
110 :
111 : /* read from the file */
- 112 37228 : read_size = handle_read(&handle[j], file_pos, buffer_aligned, state->block_size, log_error, 0);
- 113 37228 : if (read_size == -1) {
+ 112 37340 : read_size = handle_read(&handle[j], file_pos, buffer_aligned, state->block_size, log_error, 0);
+ 113 37340 : if (read_size == -1) {
114 0 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos);
115 0 : ++error;
116 0 : continue;
117 : }
118 :
119 : /* until now is disk */
- 120 37228 : state_usage_disk(state, disk);
+ 120 37340 : state_usage_disk(state, disk);
121 :
- 122 37228 : countsize += read_size;
+ 122 37340 : countsize += read_size;
123 : }
124 :
125 : /* read the parity */
- 126 49364 : for (l = 0; l < state->level; ++l) {
- 127 42312 : if (parity[l]) {
+ 126 49602 : for (l = 0; l < state->level; ++l) {
+ 127 42516 : if (parity[l]) {
128 : /* until now is CPU */
- 129 42312 : state_usage_cpu(state);
+ 129 42516 : state_usage_cpu(state);
130 :
- 131 42312 : ret = parity_read(parity[l], i, buffer_aligned, state->block_size, log_error);
- 132 42312 : if (ret == -1) {
+ 131 42516 : ret = parity_read(parity[l], i, buffer_aligned, state->block_size, log_error);
+ 132 42516 : if (ret == -1) {
133 0 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
134 0 : ++error;
135 : }
136 :
137 : /* until now is parity */
- 138 42312 : state_usage_parity(state, l);
+ 138 42516 : state_usage_parity(state, l);
139 : }
140 : }
141 :
142 : /* count the number of processed block */
- 143 7052 : ++countpos;
+ 143 7086 : ++countpos;
144 :
145 : /* progress */
- 146 7052 : if (state_progress(state, i, countpos, countmax, countsize)) {
+ 146 7086 : if (state_progress(state, i, countpos, countmax, countsize)) {
147 : /* LCOV_EXCL_START */
148 : break;
149 : /* LCOV_EXCL_STOP */
diff --git a/cov/cmdline/dup.c.func-sort-c.html b/cov/cmdline/dup.c.func-sort-c.html
index 0817fb38..bf95ff92 100644
--- a/cov/cmdline/dup.c.func-sort-c.html
+++ b/cov/cmdline/dup.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,24 +61,24 @@
| hash_alloc |
- 16956 |
+ 16970 |
| hash_free |
- 16956 |
+ 16970 |
| hash_hash |
- 16956 |
+ 16970 |
+
+
+ | hash_compare |
+ 14 |
| state_dup |
3 |
-
- | hash_compare |
- 2 |
-
diff --git a/cov/cmdline/dup.c.func.html b/cov/cmdline/dup.c.func.html
index 90e3eb0b..3dd795c3 100644
--- a/cov/cmdline/dup.c.func.html
+++ b/cov/cmdline/dup.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| hash_alloc |
- 16956 |
+ 16970 |
| hash_compare |
- 2 |
+ 14 |
| hash_free |
- 16956 |
+ 16970 |
| hash_hash |
- 16956 |
+ 16970 |
| state_dup |
diff --git a/cov/cmdline/dup.c.gcov.html b/cov/cmdline/dup.c.gcov.html
index 628d41b2..2be2ce52 100644
--- a/cov/cmdline/dup.c.gcov.html
+++ b/cov/cmdline/dup.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -98,54 +98,54 @@
36 : tommy_hashdyn_node node;
37 : };
38 :
- 39 16956 : struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
+ 39 16970 : struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
40 : {
41 : struct snapraid_hash* hash;
42 : block_off_t i;
43 : unsigned char* buf;
44 :
- 45 16956 : hash = malloc_nofail(sizeof(struct snapraid_hash));
- 46 16956 : hash->disk = disk;
- 47 16956 : hash->file = file;
+ 45 16970 : hash = malloc_nofail(sizeof(struct snapraid_hash));
+ 46 16970 : hash->disk = disk;
+ 47 16970 : hash->file = file;
48 :
- 49 16956 : buf = malloc_nofail(file->blockmax * HASH_SIZE);
+ 49 16970 : buf = malloc_nofail(file->blockmax * HASH_SIZE);
50 :
51 : /* set the back pointer */
- 52 58816 : for (i = 0; i < file->blockmax; ++i) {
- 53 41860 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 52 58942 : for (i = 0; i < file->blockmax; ++i) {
+ 53 41972 : struct snapraid_block* block = fs_file2block_get(file, i);
54 :
- 55 41860 : memcpy(buf + i * HASH_SIZE, block->hash, HASH_SIZE);
+ 55 41972 : memcpy(buf + i * HASH_SIZE, block->hash, HASH_SIZE);
56 :
- 57 41860 : if (!block_has_updated_hash(block)) {
+ 57 41972 : if (!block_has_updated_hash(block)) {
58 0 : free(buf);
59 0 : free(hash);
60 0 : return 0;
61 : }
62 : }
63 :
- 64 16956 : memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * HASH_SIZE);
+ 64 16970 : memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * HASH_SIZE);
65 :
- 66 16956 : free(buf);
+ 66 16970 : free(buf);
67 :
- 68 16956 : return hash;
+ 68 16970 : return hash;
69 : }
70 :
- 71 16956 : static inline tommy_uint32_t hash_hash(struct snapraid_hash* hash)
+ 71 16970 : static inline tommy_uint32_t hash_hash(struct snapraid_hash* hash)
72 : {
- 73 16956 : return tommy_hash_u32(0, hash->hash, HASH_SIZE);
+ 73 16970 : return tommy_hash_u32(0, hash->hash, HASH_SIZE);
74 : }
75 :
- 76 16956 : void hash_free(struct snapraid_hash* hash)
+ 76 16970 : void hash_free(struct snapraid_hash* hash)
77 : {
- 78 16956 : free(hash);
- 79 16956 : }
+ 78 16970 : free(hash);
+ 79 16970 : }
80 :
- 81 2 : int hash_compare(const void* void_arg, const void* void_data)
+ 81 14 : int hash_compare(const void* void_arg, const void* void_data)
82 : {
- 83 2 : const char* arg = void_arg;
- 84 2 : const struct snapraid_hash* hash = void_data;
+ 83 14 : const char* arg = void_arg;
+ 84 14 : const struct snapraid_hash* hash = void_data;
85 :
- 86 2 : return memcmp(arg, hash->hash, HASH_SIZE);
+ 86 14 : return memcmp(arg, hash->hash, HASH_SIZE);
87 : }
88 :
89 3 : void state_dup(struct snapraid_state* state)
@@ -168,32 +168,32 @@
106 18 : struct snapraid_disk* disk = i->data;
107 :
108 : /* for each file */
- 109 16998 : for (j = disk->filelist; j != 0; j = j->next) {
- 110 16980 : struct snapraid_file* file = j->data;
+ 109 17012 : for (j = disk->filelist; j != 0; j = j->next) {
+ 110 16994 : struct snapraid_file* file = j->data;
111 : struct snapraid_hash* hash;
112 : tommy_hash_t hash32;
113 :
114 : /* if empty, skip it */
- 115 16980 : if (file->size == 0)
+ 115 16994 : if (file->size == 0)
116 24 : continue;
117 :
- 118 16956 : hash = hash_alloc(state, disk, file);
+ 118 16970 : hash = hash_alloc(state, disk, file);
119 :
120 : /* if no hash, skip it */
- 121 16956 : if (!hash)
+ 121 16970 : if (!hash)
122 0 : continue;
123 :
- 124 16956 : hash32 = hash_hash(hash);
+ 124 16970 : hash32 = hash_hash(hash);
125 :
- 126 16956 : struct snapraid_hash* found = tommy_hashdyn_search(&hashset, hash_compare, hash->hash, hash32);
- 127 16956 : if (found) {
- 128 2 : ++count;
- 129 2 : size += found->file->size;
- 130 2 : log_tag("dup:%s:%s:%s:%s:%" PRIu64 ": dup\n", disk->name, esc(file->sub), found->disk->name, esc(found->file->sub), found->file->size);
- 131 2 : printf("%12" PRIu64 " %s%s = %s%s\n", file->size, disk->dir, file->sub, found->disk->dir, found->file->sub);
- 132 2 : hash_free(hash);
+ 126 16970 : struct snapraid_hash* found = tommy_hashdyn_search(&hashset, hash_compare, hash->hash, hash32);
+ 127 16970 : if (found) {
+ 128 14 : ++count;
+ 129 14 : size += found->file->size;
+ 130 14 : log_tag("dup:%s:%s:%s:%s:%" PRIu64 ": dup\n", disk->name, esc(file->sub), found->disk->name, esc(found->file->sub), found->file->size);
+ 131 14 : printf("%12" PRIu64 " %s%s = %s%s\n", file->size, disk->dir, file->sub, found->disk->dir, found->file->sub);
+ 132 14 : hash_free(hash);
133 : } else {
- 134 16954 : tommy_hashdyn_insert(&hashset, &hash->node, hash, hash32);
+ 134 16956 : tommy_hashdyn_insert(&hashset, &hash->node, hash, hash32);
135 : }
136 : }
137 : }
diff --git a/cov/cmdline/elem.c.func-sort-c.html b/cov/cmdline/elem.c.func-sort-c.html
index ad72c590..fdcb8ada 100644
--- a/cov/cmdline/elem.c.func-sort-c.html
+++ b/cov/cmdline/elem.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -60,248 +60,248 @@
Hit count  |
- | chunk_parity_inside_compare |
- 211700412 |
-
-
- | chunk_file_inside_compare |
- 123424429 |
-
-
- | fs_file2block_get |
- 112904165 |
-
-
- | fs_par2file_get_ts |
- 62671366 |
-
-
- | fs_par2chunk_get_ts |
- 62562730 |
-
-
- | fs_par2block_get_ts |
- 51148943 |
+ chunk_parity_inside_compare |
+ 102351431 |
| chunk_file_compare |
- 43527418 |
+ 44153325 |
+
+
+ | fs_file2block_get |
+ 44106216 |
| chunk_parity_compare |
- 43029600 |
+ 43351652 |
- | fs_file2chunk_get_ts |
- 34157182 |
+ fs_par2chunk_get_ts |
+ 38418652 |
- | fs_file2par_get_ts |
- 28740730 |
+ fs_par2file_get_ts |
+ 38311850 |
+
+
+ | fs_par2block_get_ts |
+ 26733115 |
+
+
+ | chunk_file_inside_compare |
+ 21495373 |
| filter_apply |
- 12035450 |
+ 12222233 |
- | fs_allocate |
- 8849850 |
+ fs_file2chunk_get_ts |
+ 10223247 |
+
+
+ | fs_allocate |
+ 8975787 |
| file_block_size |
- 6610122 |
+ 6677441 |
- | chunk_file_check_foreach |
- 6291380 |
+ chunk_file_check_foreach |
+ 6441048 |
- | chunk_parity_check_foreach |
- 6291380 |
+ chunk_parity_check_foreach |
+ 6441048 |
| filter_recurse |
- 6023667 |
+ 6118464 |
| file_block_is_last |
- 5319910 |
+ 5326414 |
+
+
+ | fs_file2par_get_ts |
+ 4878725 |
| chunk_alloc |
- 3607761 |
+ 3657427 |
| file_alloc |
- 3565141 |
+ 3611495 |
| chunk_free |
- 3437520 |
+ 3486903 |
| file_free |
- 3417248 |
+ 3466242 |
| filter_element |
- 3226232 |
+ 3273724 |
| filter_path |
- 3223260 |
+ 3270701 |
| filter_content |
- 3066852 |
+ 3114300 |
| file_inode_compare_to_arg |
- 866983 |
+ 927047 |
- | time_compare |
- 743492 |
+ time_compare |
+ 707506 |
| file_path_compare |
- 126356 |
+ 129121 |
| filter_type |
- 125437 |
+ 125387 |
| link_alloc |
- 115419 |
+ 116876 |
| link_free |
- 109621 |
+ 111078 |
+
+
+ | fs_deallocate |
+ 106802 |
| file_path_compare_to_arg |
- 105104 |
-
-
- | fs_deallocate |
- 104155 |
+ 104908 |
| filter_existence |
- 80654 |
-
-
- | file_name |
- 47908 |
-
-
- | chunk_disk_size_compare |
- 47779 |
-
-
- | filter_correctness |
- 38806 |
+ 80688 |
| file_physical_compare |
- 34618 |
+ 49676 |
+
+
+ | chunk_disk_size_compare |
+ 48702 |
+
+
+ | file_name |
+ 47994 |
+
+
+ | filter_correctness |
+ 38732 |
| link_name_compare_to_arg |
- 30380 |
-
-
- | file_namestamp_compare |
- 23954 |
-
-
- | file_name_compare |
- 23954 |
-
-
- | file_stamp_compare |
- 23659 |
+ 31837 |
| file_dup |
- 21785 |
+ 24707 |
+
+
+ | file_namestamp_compare |
+ 23997 |
+
+
+ | file_name_compare |
+ 23997 |
+
+
+ | file_stamp_compare |
+ 23661 |
| file_copy |
- 6209 |
+ 23633 |
- | disk_size |
- 3955 |
+ disk_size |
+ 4165 |
| filter_dir |
- 2972 |
+ 3023 |
- | fs_check |
- 2676 |
+ fs_check |
+ 2838 |
| disk_alloc |
- 1477 |
+ 1525 |
- | map_alloc |
- 1447 |
+ map_alloc |
+ 1495 |
| content_alloc |
- 1434 |
+ 1490 |
- | disk_free |
- 1351 |
+ disk_free |
+ 1399 |
- | map_free |
- 1327 |
+ map_free |
+ 1375 |
| content_free |
- 1297 |
+ 1353 |
| link_alpha_compare |
1249 |
- | disk_is_empty |
- 804 |
+ disk_is_empty |
+ 870 |
| dir_alloc |
- 760 |
+ 772 |
| dir_free |
- 712 |
+ 724 |
| filter_alloc_file |
- 498 |
+ 514 |
| filter_free |
- 461 |
+ 477 |
| dir_name_compare |
- 217 |
+ 229 |
| file_rename |
155 |
- | chunk_disk_empty_compare |
- 10 |
+ chunk_disk_empty_compare |
+ 13 |
| filter_alloc_disk |
diff --git a/cov/cmdline/elem.c.func.html b/cov/cmdline/elem.c.func.html
index a43507ef..b00e3681 100644
--- a/cov/cmdline/elem.c.func.html
+++ b/cov/cmdline/elem.c.func.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -61,103 +61,103 @@
| chunk_alloc |
- 3607761 |
+ 3657427 |
- | chunk_disk_empty_compare |
- 10 |
+ chunk_disk_empty_compare |
+ 13 |
- | chunk_disk_size_compare |
- 47779 |
+ chunk_disk_size_compare |
+ 48702 |
- | chunk_file_check_foreach |
- 6291380 |
+ chunk_file_check_foreach |
+ 6441048 |
| chunk_file_compare |
- 43527418 |
+ 44153325 |
- | chunk_file_inside_compare |
- 123424429 |
+ chunk_file_inside_compare |
+ 21495373 |
| chunk_free |
- 3437520 |
+ 3486903 |
- | chunk_parity_check_foreach |
- 6291380 |
+ chunk_parity_check_foreach |
+ 6441048 |
| chunk_parity_compare |
- 43029600 |
+ 43351652 |
- | chunk_parity_inside_compare |
- 211700412 |
+ chunk_parity_inside_compare |
+ 102351431 |
| content_alloc |
- 1434 |
+ 1490 |
| content_free |
- 1297 |
+ 1353 |
| dir_alloc |
- 760 |
+ 772 |
| dir_free |
- 712 |
+ 724 |
| dir_name_compare |
- 217 |
+ 229 |
| disk_alloc |
- 1477 |
+ 1525 |
- | disk_free |
- 1351 |
+ disk_free |
+ 1399 |
- | disk_is_empty |
- 804 |
+ disk_is_empty |
+ 870 |
- | disk_size |
- 3955 |
+ disk_size |
+ 4165 |
| file_alloc |
- 3565141 |
+ 3611495 |
| file_block_is_last |
- 5319910 |
+ 5326414 |
| file_block_size |
- 6610122 |
+ 6677441 |
| file_copy |
- 6209 |
+ 23633 |
| file_dup |
- 21785 |
+ 24707 |
| file_free |
- 3417248 |
+ 3466242 |
| file_inode_compare |
@@ -165,27 +165,27 @@
| file_inode_compare_to_arg |
- 866983 |
+ 927047 |
| file_name |
- 47908 |
+ 47994 |
| file_name_compare |
- 23954 |
+ 23997 |
| file_namestamp_compare |
- 23954 |
+ 23997 |
| file_path_compare |
- 126356 |
+ 129121 |
| file_path_compare_to_arg |
- 105104 |
+ 104908 |
| file_pathstamp_compare |
@@ -193,7 +193,7 @@
| file_physical_compare |
- 34618 |
+ 49676 |
| file_rename |
@@ -201,7 +201,7 @@
| file_stamp_compare |
- 23659 |
+ 23661 |
| filter_alloc_disk |
@@ -209,87 +209,87 @@
| filter_alloc_file |
- 498 |
+ 514 |
| filter_apply |
- 12035450 |
+ 12222233 |
| filter_content |
- 3066852 |
+ 3114300 |
| filter_correctness |
- 38806 |
+ 38732 |
| filter_dir |
- 2972 |
+ 3023 |
| filter_element |
- 3226232 |
+ 3273724 |
| filter_existence |
- 80654 |
+ 80688 |
| filter_free |
- 461 |
+ 477 |
| filter_path |
- 3223260 |
+ 3270701 |
| filter_recurse |
- 6023667 |
+ 6118464 |
| filter_type |
- 125437 |
+ 125387 |
- | fs_allocate |
- 8849850 |
+ fs_allocate |
+ 8975787 |
- | fs_check |
- 2676 |
+ fs_check |
+ 2838 |
- | fs_deallocate |
- 104155 |
+ fs_deallocate |
+ 106802 |
- | fs_file2block_get |
- 112904165 |
+ fs_file2block_get |
+ 44106216 |
- | fs_file2chunk_get_ts |
- 34157182 |
+ fs_file2chunk_get_ts |
+ 10223247 |
- | fs_file2par_get_ts |
- 28740730 |
+ fs_file2par_get_ts |
+ 4878725 |
- | fs_par2block_get_ts |
- 51148943 |
+ fs_par2block_get_ts |
+ 26733115 |
- | fs_par2chunk_get_ts |
- 62562730 |
+ fs_par2chunk_get_ts |
+ 38418652 |
- | fs_par2file_get_ts |
- 62671366 |
+ fs_par2file_get_ts |
+ 38311850 |
| link_alloc |
- 115419 |
+ 116876 |
| link_alpha_compare |
@@ -297,23 +297,23 @@
| link_free |
- 109621 |
+ 111078 |
| link_name_compare_to_arg |
- 30380 |
+ 31837 |
- | map_alloc |
- 1447 |
+ map_alloc |
+ 1495 |
- | map_free |
- 1327 |
+ map_free |
+ 1375 |
- | time_compare |
- 743492 |
+ time_compare |
+ 707506 |
diff --git a/cov/cmdline/elem.c.gcov.html b/cov/cmdline/elem.c.gcov.html
index 0121811d..647e3a16 100644
--- a/cov/cmdline/elem.c.gcov.html
+++ b/cov/cmdline/elem.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -86,23 +86,23 @@
24 : /****************************************************************************/
25 : /* snapraid */
26 :
- 27 1434 : struct snapraid_content* content_alloc(const char* path, uint64_t dev)
+ 27 1490 : struct snapraid_content* content_alloc(const char* path, uint64_t dev)
28 : {
29 : struct snapraid_content* content;
30 :
- 31 1434 : content = malloc_nofail(sizeof(struct snapraid_content));
- 32 1434 : pathimport(content->content, sizeof(content->content), path);
- 33 1434 : content->device = dev;
+ 31 1490 : content = malloc_nofail(sizeof(struct snapraid_content));
+ 32 1490 : pathimport(content->content, sizeof(content->content), path);
+ 33 1490 : content->device = dev;
34 :
- 35 1434 : return content;
+ 35 1490 : return content;
36 : }
37 :
- 38 1297 : void content_free(struct snapraid_content* content)
+ 38 1353 : void content_free(struct snapraid_content* content)
39 : {
- 40 1297 : free(content);
- 41 1297 : }
+ 40 1353 : free(content);
+ 41 1353 : }
42 :
- 43 498 : struct snapraid_filter* filter_alloc_file(int direction, const char* pattern)
+ 43 514 : struct snapraid_filter* filter_alloc_file(int direction, const char* pattern)
44 : {
45 : struct snapraid_filter* filter;
46 : char* i;
@@ -111,18 +111,18 @@
49 : int token_is_valid;
50 : int token_is_filled;
51 :
- 52 498 : filter = malloc_nofail(sizeof(struct snapraid_filter));
- 53 498 : pathimport(filter->pattern, sizeof(filter->pattern), pattern);
- 54 498 : filter->direction = direction;
+ 52 514 : filter = malloc_nofail(sizeof(struct snapraid_filter));
+ 53 514 : pathimport(filter->pattern, sizeof(filter->pattern), pattern);
+ 54 514 : filter->direction = direction;
55 :
56 : /* find first and last slash */
- 57 498 : first = 0;
- 58 498 : last = 0;
+ 57 514 : first = 0;
+ 58 514 : last = 0;
59 : /* reject invalid tokens, like "<empty>", ".", ".." and more dots */
- 60 498 : token_is_valid = 0;
- 61 498 : token_is_filled = 0;
- 62 6172 : for (i = filter->pattern; *i; ++i) {
- 63 5675 : if (*i == '/') {
+ 60 514 : token_is_valid = 0;
+ 61 514 : token_is_filled = 0;
+ 62 6372 : for (i = filter->pattern; *i; ++i) {
+ 63 5859 : if (*i == '/') {
64 : /* reject invalid tokens, but accept an empty one as first */
65 5 : if (!token_is_valid && (first != 0 || token_is_filled)) {
66 1 : free(filter);
@@ -135,27 +135,27 @@
73 4 : if (!first)
74 3 : first = i;
75 4 : last = i;
- 76 5670 : } else if (*i != '.') {
- 77 5176 : token_is_valid = 1;
- 78 5176 : token_is_filled = 1;
+ 76 5854 : } else if (*i != '.') {
+ 77 5344 : token_is_valid = 1;
+ 78 5344 : token_is_filled = 1;
79 : } else {
- 80 494 : token_is_filled = 1;
+ 80 510 : token_is_filled = 1;
81 : }
82 : }
83 :
84 : /* reject invalid tokens, but accept an empty one as last, but not if it's the only one */
- 85 497 : if (!token_is_valid && (first == 0 || token_is_filled)) {
+ 85 513 : if (!token_is_valid && (first == 0 || token_is_filled)) {
86 1 : free(filter);
87 1 : return 0;
88 : }
89 :
90 : /* it's a file filter */
- 91 496 : filter->is_disk = 0;
+ 91 512 : filter->is_disk = 0;
92 :
- 93 496 : if (first == 0) {
+ 93 512 : if (first == 0) {
94 : /* no slash */
- 95 493 : filter->is_path = 0;
- 96 493 : filter->is_dir = 0;
+ 95 509 : filter->is_path = 0;
+ 96 509 : filter->is_dir = 0;
97 3 : } else if (first == last && last[1] == 0) {
98 : /* one slash at the end */
99 1 : filter->is_path = 0;
@@ -178,7 +178,7 @@
116 : }
117 : }
118 :
- 119 495 : return filter;
+ 119 511 : return filter;
120 : }
121 :
122 8 : struct snapraid_filter* filter_alloc_disk(int direction, const char* pattern)
@@ -205,162 +205,162 @@
143 8 : return filter;
144 : }
145 :
- 146 461 : void filter_free(struct snapraid_filter* filter)
+ 146 477 : void filter_free(struct snapraid_filter* filter)
147 : {
- 148 461 : free(filter);
- 149 461 : }
+ 148 477 : free(filter);
+ 149 477 : }
150 :
- 151 125437 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size)
+ 151 125387 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size)
152 : {
153 : const char* direction;
- 154 125437 : if (filter->direction < 0)
- 155 125191 : direction = "exclude";
+ 154 125387 : if (filter->direction < 0)
+ 155 125133 : direction = "exclude";
156 : else
- 157 246 : direction = "include";
+ 157 254 : direction = "include";
158 :
- 159 125437 : if (filter->is_disk)
+ 159 125387 : if (filter->is_disk)
160 0 : pathprint(out, out_size, "%s %s:", direction, filter->pattern);
- 161 125437 : else if (filter->is_dir)
+ 161 125387 : else if (filter->is_dir)
162 0 : pathprint(out, out_size, "%s %s/", direction, filter->pattern);
163 : else
- 164 125437 : pathprint(out, out_size, "%s %s", direction, filter->pattern);
+ 164 125387 : pathprint(out, out_size, "%s %s", direction, filter->pattern);
165 :
- 166 125437 : return out;
+ 166 125387 : return out;
167 : }
168 :
- 169 12035450 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir)
+ 169 12222233 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir)
170 : {
- 171 12035450 : int ret = 0;
+ 171 12222233 : int ret = 0;
172 :
173 : /* match dirs with dirs and files with files */
- 174 12035450 : if (filter->is_dir && !is_dir)
- 175 2939 : return 0;
- 176 12032511 : if (!filter->is_dir && is_dir)
- 177 6014680 : return 0;
+ 174 12222233 : if (filter->is_dir && !is_dir)
+ 175 2946 : return 0;
+ 176 12219287 : if (!filter->is_dir && is_dir)
+ 177 6106768 : return 0;
178 :
- 179 6017831 : if (filter->is_path) {
+ 179 6112519 : if (filter->is_path) {
180 : /* skip initial slash, as always missing from the path */
- 181 2939 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 181 2946 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0)
182 0 : ret = filter->direction;
183 : } else {
- 184 6014892 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
- 185 127935 : ret = filter->direction;
+ 184 6109573 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 185 127869 : ret = filter->direction;
186 : }
187 :
- 188 6017831 : if (reason != 0 && ret < 0)
- 189 124945 : *reason = filter;
+ 188 6112519 : if (reason != 0 && ret < 0)
+ 189 124879 : *reason = filter;
190 :
- 191 6017831 : return ret;
+ 191 6112519 : return ret;
192 : }
193 :
- 194 6023667 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir)
+ 194 6118464 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir)
195 : {
196 : char path[PATH_MAX];
197 : char* name;
198 : unsigned i;
199 :
- 200 6023667 : pathcpy(path, sizeof(path), const_path);
+ 200 6118464 : pathcpy(path, sizeof(path), const_path);
201 :
202 : /* filter for all the directories */
- 203 6023667 : name = path;
- 204 86942366 : for (i = 0; path[i] != 0; ++i) {
- 205 80921689 : if (path[i] == '/') {
+ 203 6118464 : name = path;
+ 204 88222216 : for (i = 0; path[i] != 0; ++i) {
+ 205 82106742 : if (path[i] == '/') {
206 : /* set a terminator */
- 207 6014773 : path[i] = 0;
+ 207 6106759 : path[i] = 0;
208 :
209 : /* filter the directory */
- 210 6014773 : if (filter_apply(filter, reason, path, name, 1) != 0)
+ 210 6106759 : if (filter_apply(filter, reason, path, name, 1) != 0)
211 2990 : return filter->direction;
212 :
213 : /* restore the slash */
- 214 6011783 : path[i] = '/';
+ 214 6103769 : path[i] = '/';
215 :
216 : /* next name */
- 217 6011783 : name = path + i + 1;
+ 217 6103769 : name = path + i + 1;
218 : }
219 : }
220 :
221 : /* filter the final file */
- 222 6020677 : if (filter_apply(filter, reason, path, name, is_dir) != 0)
- 223 124945 : return filter->direction;
+ 222 6115474 : if (filter_apply(filter, reason, path, name, is_dir) != 0)
+ 223 124879 : return filter->direction;
224 :
- 225 5895732 : return 0;
+ 225 5990595 : return 0;
226 : }
227 :
- 228 3226232 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir)
+ 228 3273724 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir)
229 : {
230 : tommy_node* i;
231 :
- 232 3226232 : int direction = 1; /* by default include all */
+ 232 3273724 : int direction = 1; /* by default include all */
233 :
234 : /* for each filter */
- 235 9223179 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) {
+ 235 9365584 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) {
236 : int ret;
- 237 6133552 : struct snapraid_filter* filter = i->data;
+ 237 6228405 : struct snapraid_filter* filter = i->data;
238 :
- 239 6133552 : if (filter->is_disk) {
- 240 109885 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
- 241 8670 : ret = filter->direction;
+ 239 6228405 : if (filter->is_disk) {
+ 240 109941 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 241 8676 : ret = filter->direction;
242 : else
- 243 101215 : ret = 0;
- 244 109885 : if (reason != 0 && ret < 0)
+ 243 101265 : ret = 0;
+ 244 109941 : if (reason != 0 && ret < 0)
245 0 : *reason = filter;
246 : } else {
- 247 6023667 : ret = filter_recurse(filter, reason, sub, is_dir);
+ 247 6118464 : ret = filter_recurse(filter, reason, sub, is_dir);
248 : }
249 :
- 250 6133552 : if (ret > 0) {
+ 250 6228405 : if (ret > 0) {
251 : /* include the file */
- 252 11660 : return 0;
- 253 6121892 : } else if (ret < 0) {
+ 252 11666 : return 0;
+ 253 6216739 : } else if (ret < 0) {
254 : /* exclude the file */
- 255 124945 : return -1;
+ 255 124879 : return -1;
256 : } else {
257 : /* default is opposite of the last filter */
- 258 5996947 : direction = -filter->direction;
- 259 5996947 : if (reason != 0 && direction < 0)
- 260 3004435 : *reason = filter;
+ 258 6091860 : direction = -filter->direction;
+ 259 6091860 : if (reason != 0 && direction < 0)
+ 260 3051823 : *reason = filter;
261 : /* continue with the next one */
262 : }
263 : }
264 :
265 : /* directories are always included by default, otherwise we cannot apply rules */
266 : /* to the contained files */
- 267 3089627 : if (is_dir)
- 268 2971 : return 0;
+ 267 3137179 : if (is_dir)
+ 268 3022 : return 0;
269 :
270 : /* files are excluded/included depending of the last rule processed */
- 271 3086656 : if (direction < 0)
- 272 57545 : return -1;
+ 271 3134157 : if (direction < 0)
+ 272 57574 : return -1;
273 :
- 274 3029111 : return 0;
+ 274 3076583 : return 0;
275 : }
276 :
- 277 3223260 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
+ 277 3270701 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
278 : {
- 279 3223260 : return filter_element(filterlist, reason, disk, sub, 0);
+ 279 3270701 : return filter_element(filterlist, reason, disk, sub, 0);
280 : }
281 :
- 282 2972 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
+ 282 3023 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
283 : {
- 284 2972 : return filter_element(filterlist, reason, disk, sub, 1);
+ 284 3023 : return filter_element(filterlist, reason, disk, sub, 1);
285 : }
286 :
- 287 80654 : int filter_existence(int filter_missing, const char* dir, const char* sub)
+ 287 80688 : int filter_existence(int filter_missing, const char* dir, const char* sub)
288 : {
289 : char path[PATH_MAX];
290 : struct stat st;
291 :
- 292 80654 : if (!filter_missing)
- 293 34958 : return 0;
+ 292 80688 : if (!filter_missing)
+ 293 34978 : return 0;
294 :
295 : /* we directly check if in the disk the file is present or not */
- 296 45696 : pathprint(path, sizeof(path), "%s%s", dir, sub);
+ 296 45710 : pathprint(path, sizeof(path), "%s%s", dir, sub);
297 :
- 298 45696 : if (lstat(path, &st) != 0) {
+ 298 45710 : if (lstat(path, &st) != 0) {
299 : /* if the file doesn't exist, we don't filter it out */
- 300 5007 : if (errno == ENOENT)
- 301 5007 : return 0;
+ 300 4913 : if (errno == ENOENT)
+ 301 4913 : return 0;
302 : /* LCOV_EXCL_START */
303 : log_fatal("Error in stat file '%s'. %s.\n", path, strerror(errno));
304 : exit(EXIT_FAILURE);
@@ -368,111 +368,111 @@
306 : }
307 :
308 : /* the file is present, so we filter it out */
- 309 40689 : return 1;
+ 309 40797 : return 1;
310 : }
311 :
- 312 38806 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file)
+ 312 38732 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file)
313 : {
314 : unsigned i;
315 :
- 316 38806 : if (!filter_error)
- 317 16278 : return 0;
+ 316 38732 : if (!filter_error)
+ 317 16190 : return 0;
318 :
319 : /* check each block of the file */
- 320 60231 : for (i = 0; i < file->blockmax; ++i) {
- 321 46123 : block_off_t parity_pos = fs_file2par_get(disk, file, i);
- 322 46123 : snapraid_info info = info_get(infoarr, parity_pos);
+ 320 60567 : for (i = 0; i < file->blockmax; ++i) {
+ 321 46357 : block_off_t parity_pos = fs_file2par_get(disk, file, i);
+ 322 46357 : snapraid_info info = info_get(infoarr, parity_pos);
323 :
324 : /* if the file has a bad block, don't exclude it */
- 325 46123 : if (info_get_bad(info))
- 326 8420 : return 0;
+ 325 46357 : if (info_get_bad(info))
+ 326 8332 : return 0;
327 : }
328 :
329 : /* the file is correct, so we filter it out */
- 330 14108 : return 1;
+ 330 14210 : return 1;
331 : }
332 :
- 333 3066852 : int filter_content(tommy_list* contentlist, const char* path)
+ 333 3114300 : int filter_content(tommy_list* contentlist, const char* path)
334 : {
335 : tommy_node* i;
336 :
- 337 39681406 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) {
- 338 16773851 : struct snapraid_content* content = i->data;
+ 337 40437716 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) {
+ 338 17104558 : struct snapraid_content* content = i->data;
339 : char tmp[PATH_MAX];
340 :
- 341 16773851 : if (pathcmp(content->content, path) == 0)
+ 341 17104558 : if (pathcmp(content->content, path) == 0)
342 0 : return -1;
343 :
344 : /* exclude also the ".tmp" copy used to save it */
- 345 16773851 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 346 16773851 : if (pathcmp(tmp, path) == 0)
+ 345 17104558 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 346 17104558 : if (pathcmp(tmp, path) == 0)
347 0 : return -1;
348 :
349 : /* exclude also the ".lock" file */
- 350 16773851 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content);
- 351 16773851 : if (pathcmp(tmp, path) == 0)
+ 350 17104558 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content);
+ 351 17104558 : if (pathcmp(tmp, path) == 0)
352 0 : return -1;
353 : }
354 :
- 355 3066852 : return 0;
+ 355 3114300 : return 0;
356 : }
357 :
- 358 3565141 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical)
+ 358 3611495 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical)
359 : {
360 : struct snapraid_file* file;
361 : block_off_t i;
362 :
- 363 3565141 : file = malloc_nofail(sizeof(struct snapraid_file));
- 364 3565141 : file->sub = strdup_nofail(sub);
- 365 3565141 : file->size = size;
- 366 3565141 : file->blockmax = (size + block_size - 1) / block_size;
- 367 3565141 : file->mtime_sec = mtime_sec;
- 368 3565141 : file->mtime_nsec = mtime_nsec;
- 369 3565141 : file->inode = inode;
- 370 3565141 : file->physical = physical;
- 371 3565141 : file->flag = 0;
- 372 3565141 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block));
+ 363 3611495 : file = malloc_nofail(sizeof(struct snapraid_file));
+ 364 3611495 : file->sub = strdup_nofail(sub);
+ 365 3611495 : file->size = size;
+ 366 3611495 : file->blockmax = (size + block_size - 1) / block_size;
+ 367 3611495 : file->mtime_sec = mtime_sec;
+ 368 3611495 : file->mtime_nsec = mtime_nsec;
+ 369 3611495 : file->inode = inode;
+ 370 3611495 : file->physical = physical;
+ 371 3611495 : file->flag = 0;
+ 372 3611495 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block));
373 :
- 374 12361356 : for (i = 0; i < file->blockmax; ++i) {
- 375 8796215 : block_state_set(&file->blockvec[i], BLOCK_STATE_CHG);
- 376 8796215 : hash_invalid_set(file->blockvec[i].hash);
+ 374 12530604 : for (i = 0; i < file->blockmax; ++i) {
+ 375 8919109 : block_state_set(&file->blockvec[i], BLOCK_STATE_CHG);
+ 376 8919109 : hash_invalid_set(file->blockvec[i].hash);
377 : }
378 :
- 379 3565141 : return file;
+ 379 3611495 : return file;
380 : }
381 :
- 382 21785 : struct snapraid_file* file_dup(struct snapraid_file* copy)
+ 382 24707 : struct snapraid_file* file_dup(struct snapraid_file* copy)
383 : {
384 : struct snapraid_file* file;
385 : block_off_t i;
386 :
- 387 21785 : file = malloc_nofail(sizeof(struct snapraid_file));
- 388 21785 : file->sub = strdup_nofail(copy->sub);
- 389 21785 : file->size = copy->size;
- 390 21785 : file->blockmax = copy->blockmax;
- 391 21785 : file->mtime_sec = copy->mtime_sec;
- 392 21785 : file->mtime_nsec = copy->mtime_nsec;
- 393 21785 : file->inode = copy->inode;
- 394 21785 : file->physical = copy->physical;
- 395 21785 : file->flag = copy->flag;
- 396 21785 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block));
+ 387 24707 : file = malloc_nofail(sizeof(struct snapraid_file));
+ 388 24707 : file->sub = strdup_nofail(copy->sub);
+ 389 24707 : file->size = copy->size;
+ 390 24707 : file->blockmax = copy->blockmax;
+ 391 24707 : file->mtime_sec = copy->mtime_sec;
+ 392 24707 : file->mtime_nsec = copy->mtime_nsec;
+ 393 24707 : file->inode = copy->inode;
+ 394 24707 : file->physical = copy->physical;
+ 395 24707 : file->flag = copy->flag;
+ 396 24707 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block));
397 :
- 398 75420 : for (i = 0; i < file->blockmax; ++i) {
- 399 53635 : file->blockvec[i].state = copy->blockvec[i].state;
- 400 53635 : memcpy(file->blockvec[i].hash, copy->blockvec[i].hash, HASH_SIZE);
+ 398 81385 : for (i = 0; i < file->blockmax; ++i) {
+ 399 56678 : file->blockvec[i].state = copy->blockvec[i].state;
+ 400 56678 : memcpy(file->blockvec[i].hash, copy->blockvec[i].hash, HASH_SIZE);
401 : }
402 :
- 403 21785 : return file;
+ 403 24707 : return file;
404 : }
405 :
- 406 3417248 : void file_free(struct snapraid_file* file)
+ 406 3466242 : void file_free(struct snapraid_file* file)
407 : {
- 408 3417248 : free(file->sub);
- 409 3417248 : file->sub = 0;
- 410 3417248 : free(file->blockvec);
- 411 3417248 : file->blockvec = 0;
- 412 3417248 : free(file);
- 413 3417248 : }
+ 408 3466242 : free(file->sub);
+ 409 3466242 : file->sub = 0;
+ 410 3466242 : free(file->blockvec);
+ 411 3466242 : file->blockvec = 0;
+ 412 3466242 : free(file);
+ 413 3466242 : }
414 :
415 155 : void file_rename(struct snapraid_file* file, const char* sub)
416 : {
@@ -480,94 +480,94 @@
418 155 : file->sub = strdup_nofail(sub);
419 155 : }
420 :
- 421 6209 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file)
+ 421 23633 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file)
422 : {
423 : block_off_t i;
424 :
- 425 6209 : if (src_file->size != dst_file->size) {
+ 425 23633 : if (src_file->size != dst_file->size) {
426 : /* LCOV_EXCL_START */
427 : log_fatal("Internal inconsistency in copy file with different size\n");
- 428 : exit(EXIT_FAILURE);
+ 428 : os_abort();
429 : /* LCOV_EXCL_STOP */
430 : }
431 :
- 432 6209 : if (src_file->mtime_sec != dst_file->mtime_sec) {
+ 432 23633 : if (src_file->mtime_sec != dst_file->mtime_sec) {
433 : /* LCOV_EXCL_START */
434 : log_fatal("Internal inconsistency in copy file with different mtime_sec\n");
- 435 : exit(EXIT_FAILURE);
+ 435 : os_abort();
436 : /* LCOV_EXCL_STOP */
437 : }
438 :
- 439 6209 : if (src_file->mtime_nsec != dst_file->mtime_nsec) {
+ 439 23633 : if (src_file->mtime_nsec != dst_file->mtime_nsec) {
440 : /* LCOV_EXCL_START */
441 : log_fatal("Internal inconsistency in copy file with different mtime_nsec\n");
- 442 : exit(EXIT_FAILURE);
+ 442 : os_abort();
443 : /* LCOV_EXCL_STOP */
444 : }
445 :
- 446 17910 : for (i = 0; i < dst_file->blockmax; ++i) {
+ 446 81852 : for (i = 0; i < dst_file->blockmax; ++i) {
447 : /* set a block with hash computed but without parity */
- 448 11701 : block_state_set(&dst_file->blockvec[i], BLOCK_STATE_REP);
+ 448 58219 : block_state_set(&dst_file->blockvec[i], BLOCK_STATE_REP);
449 :
450 : /* copy the hash */
- 451 11701 : memcpy(dst_file->blockvec[i].hash, src_file->blockvec[i].hash, HASH_SIZE);
+ 451 58219 : memcpy(dst_file->blockvec[i].hash, src_file->blockvec[i].hash, HASH_SIZE);
452 : }
453 :
- 454 6209 : file_flag_set(dst_file, FILE_IS_COPY);
- 455 6209 : }
+ 454 23633 : file_flag_set(dst_file, FILE_IS_COPY);
+ 455 23633 : }
456 :
- 457 47908 : const char* file_name(const struct snapraid_file* file)
+ 457 47994 : const char* file_name(const struct snapraid_file* file)
458 : {
- 459 47908 : const char* r = strrchr(file->sub, '/');
+ 459 47994 : const char* r = strrchr(file->sub, '/');
460 :
- 461 47908 : if (!r)
- 462 8 : r = file->sub;
+ 461 47994 : if (!r)
+ 462 60 : r = file->sub;
463 : else
- 464 47900 : ++r;
- 465 47908 : return r;
+ 464 47934 : ++r;
+ 465 47994 : return r;
466 : }
467 :
- 468 6610122 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size)
+ 468 6677441 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size)
469 : {
470 : /* if it's the last block */
- 471 6610122 : if (file_pos + 1 == file->blockmax) {
+ 471 6677441 : if (file_pos + 1 == file->blockmax) {
472 : unsigned block_remainder;
- 473 2692717 : if (file->size == 0)
+ 473 2717238 : if (file->size == 0)
474 0 : return 0;
- 475 2692717 : block_remainder = file->size % block_size;
- 476 2692717 : if (block_remainder == 0)
- 477 1544 : block_remainder = block_size;
- 478 2692717 : return block_remainder;
+ 475 2717238 : block_remainder = file->size % block_size;
+ 476 2717238 : if (block_remainder == 0)
+ 477 2543 : block_remainder = block_size;
+ 478 2717238 : return block_remainder;
479 : }
480 :
- 481 3917405 : return block_size;
+ 481 3960203 : return block_size;
482 : }
483 :
- 484 5319910 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos)
+ 484 5326414 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos)
485 : {
- 486 5319910 : if (file_pos == 0 && file->blockmax == 0)
+ 486 5326414 : if (file_pos == 0 && file->blockmax == 0)
487 0 : return 1;
488 :
- 489 5319910 : if (file_pos >= file->blockmax) {
+ 489 5326414 : if (file_pos >= file->blockmax) {
490 : /* LCOV_EXCL_START */
491 : log_fatal("Internal inconsistency in file block position\n");
- 492 : exit(EXIT_FAILURE);
+ 492 : os_abort();
493 : /* LCOV_EXCL_STOP */
494 : }
495 :
- 496 5319910 : return file_pos == file->blockmax - 1;
+ 496 5326414 : return file_pos == file->blockmax - 1;
497 : }
498 :
- 499 866983 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data)
+ 499 927047 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data)
500 : {
- 501 866983 : const uint64_t* arg = void_arg;
- 502 866983 : const struct snapraid_file* file = void_data;
+ 501 927047 : const uint64_t* arg = void_arg;
+ 502 927047 : const struct snapraid_file* file = void_data;
503 :
- 504 866983 : if (*arg < file->inode)
+ 504 927047 : if (*arg < file->inode)
505 0 : return -1;
- 506 866983 : if (*arg > file->inode)
+ 506 927047 : if (*arg > file->inode)
507 0 : return 1;
- 508 866983 : return 0;
+ 508 927047 : return 0;
509 : }
510 :
511 0 : int file_inode_compare(const void* void_a, const void* void_b)
@@ -582,76 +582,76 @@
520 0 : return 0;
521 : }
522 :
- 523 126356 : int file_path_compare(const void* void_a, const void* void_b)
+ 523 129121 : int file_path_compare(const void* void_a, const void* void_b)
524 : {
- 525 126356 : const struct snapraid_file* file_a = void_a;
- 526 126356 : const struct snapraid_file* file_b = void_b;
+ 525 129121 : const struct snapraid_file* file_a = void_a;
+ 526 129121 : const struct snapraid_file* file_b = void_b;
527 :
- 528 126356 : return strcmp(file_a->sub, file_b->sub);
+ 528 129121 : return strcmp(file_a->sub, file_b->sub);
529 : }
530 :
- 531 34618 : int file_physical_compare(const void* void_a, const void* void_b)
+ 531 49676 : int file_physical_compare(const void* void_a, const void* void_b)
532 : {
- 533 34618 : const struct snapraid_file* file_a = void_a;
- 534 34618 : const struct snapraid_file* file_b = void_b;
+ 533 49676 : const struct snapraid_file* file_a = void_a;
+ 534 49676 : const struct snapraid_file* file_b = void_b;
535 :
- 536 34618 : if (file_a->physical < file_b->physical)
- 537 26412 : return -1;
- 538 8206 : if (file_a->physical > file_b->physical)
- 539 8204 : return 1;
+ 536 49676 : if (file_a->physical < file_b->physical)
+ 537 34678 : return -1;
+ 538 14998 : if (file_a->physical > file_b->physical)
+ 539 14996 : return 1;
540 2 : return 0;
541 : }
542 :
- 543 105104 : int file_path_compare_to_arg(const void* void_arg, const void* void_data)
+ 543 104908 : int file_path_compare_to_arg(const void* void_arg, const void* void_data)
544 : {
- 545 105104 : const char* arg = void_arg;
- 546 105104 : const struct snapraid_file* file = void_data;
+ 545 104908 : const char* arg = void_arg;
+ 546 104908 : const struct snapraid_file* file = void_data;
547 :
- 548 105104 : return strcmp(arg, file->sub);
+ 548 104908 : return strcmp(arg, file->sub);
549 : }
550 :
- 551 23954 : int file_name_compare(const void* void_a, const void* void_b)
+ 551 23997 : int file_name_compare(const void* void_a, const void* void_b)
552 : {
- 553 23954 : const struct snapraid_file* file_a = void_a;
- 554 23954 : const struct snapraid_file* file_b = void_b;
- 555 23954 : const char* name_a = file_name(file_a);
- 556 23954 : const char* name_b = file_name(file_b);
+ 553 23997 : const struct snapraid_file* file_a = void_a;
+ 554 23997 : const struct snapraid_file* file_b = void_b;
+ 555 23997 : const char* name_a = file_name(file_a);
+ 556 23997 : const char* name_b = file_name(file_b);
557 :
- 558 23954 : return strcmp(name_a, name_b);
+ 558 23997 : return strcmp(name_a, name_b);
559 : }
560 :
- 561 23659 : int file_stamp_compare(const void* void_a, const void* void_b)
+ 561 23661 : int file_stamp_compare(const void* void_a, const void* void_b)
562 : {
- 563 23659 : const struct snapraid_file* file_a = void_a;
- 564 23659 : const struct snapraid_file* file_b = void_b;
+ 563 23661 : const struct snapraid_file* file_a = void_a;
+ 564 23661 : const struct snapraid_file* file_b = void_b;
565 :
- 566 23659 : if (file_a->size < file_b->size)
+ 566 23661 : if (file_a->size < file_b->size)
567 0 : return -1;
- 568 23659 : if (file_a->size > file_b->size)
+ 568 23661 : if (file_a->size > file_b->size)
569 0 : return 1;
570 :
- 571 23659 : if (file_a->mtime_sec < file_b->mtime_sec)
+ 571 23661 : if (file_a->mtime_sec < file_b->mtime_sec)
572 0 : return -1;
- 573 23659 : if (file_a->mtime_sec > file_b->mtime_sec)
+ 573 23661 : if (file_a->mtime_sec > file_b->mtime_sec)
574 0 : return 1;
575 :
- 576 23659 : if (file_a->mtime_nsec < file_b->mtime_nsec)
+ 576 23661 : if (file_a->mtime_nsec < file_b->mtime_nsec)
577 0 : return -1;
- 578 23659 : if (file_a->mtime_nsec > file_b->mtime_nsec)
+ 578 23661 : if (file_a->mtime_nsec > file_b->mtime_nsec)
579 0 : return 1;
580 :
- 581 23659 : return 0;
+ 581 23661 : return 0;
582 : }
583 :
- 584 23954 : int file_namestamp_compare(const void* void_a, const void* void_b)
+ 584 23997 : int file_namestamp_compare(const void* void_a, const void* void_b)
585 : {
586 : int ret;
587 :
- 588 23954 : ret = file_name_compare(void_a, void_b);
- 589 23954 : if (ret != 0)
- 590 295 : return ret;
+ 588 23997 : ret = file_name_compare(void_a, void_b);
+ 589 23997 : if (ret != 0)
+ 590 336 : return ret;
591 :
- 592 23659 : return file_stamp_compare(void_a, void_b);
+ 592 23661 : return file_stamp_compare(void_a, void_b);
593 : }
594 :
595 0 : int file_pathstamp_compare(const void* void_a, const void* void_b)
@@ -665,93 +665,93 @@
603 0 : return file_stamp_compare(void_a, void_b);
604 : }
605 :
- 606 3607761 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count)
+ 606 3657427 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count)
607 : {
608 : struct snapraid_chunk* chunk;
609 :
- 610 3607761 : if (count == 0) {
+ 610 3657427 : if (count == 0) {
611 : /* LCOV_EXCL_START */
612 : log_fatal("Internal inconsistency when allocating empty chunk for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
- 613 : exit(EXIT_FAILURE);
+ 613 : os_abort();
614 : /* LCOV_EXCL_STOP */
615 : }
- 616 3607761 : if (file_pos + count > file->blockmax) {
+ 616 3657427 : if (file_pos + count > file->blockmax) {
617 : /* LCOV_EXCL_START */
618 : log_fatal("Internal inconsistency when allocating overflowing chunk for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax);
- 619 : exit(EXIT_FAILURE);
+ 619 : os_abort();
620 : /* LCOV_EXCL_STOP */
621 : }
622 :
- 623 3607761 : chunk = malloc_nofail(sizeof(struct snapraid_chunk));
- 624 3607761 : chunk->parity_pos = parity_pos;
- 625 3607761 : chunk->file = file;
- 626 3607761 : chunk->file_pos = file_pos;
- 627 3607761 : chunk->count = count;
+ 623 3657427 : chunk = malloc_nofail(sizeof(struct snapraid_chunk));
+ 624 3657427 : chunk->parity_pos = parity_pos;
+ 625 3657427 : chunk->file = file;
+ 626 3657427 : chunk->file_pos = file_pos;
+ 627 3657427 : chunk->count = count;
628 :
- 629 3607761 : return chunk;
+ 629 3657427 : return chunk;
630 : }
631 :
- 632 3437520 : void chunk_free(struct snapraid_chunk* chunk)
+ 632 3486903 : void chunk_free(struct snapraid_chunk* chunk)
633 : {
- 634 3437520 : free(chunk);
- 635 3437520 : }
+ 634 3486903 : free(chunk);
+ 635 3486903 : }
636 :
- 637 43029600 : int chunk_parity_compare(const void* void_a, const void* void_b)
+ 637 43351652 : int chunk_parity_compare(const void* void_a, const void* void_b)
638 : {
- 639 43029600 : const struct snapraid_chunk* arg_a = void_a;
- 640 43029600 : const struct snapraid_chunk* arg_b = void_b;
+ 639 43351652 : const struct snapraid_chunk* arg_a = void_a;
+ 640 43351652 : const struct snapraid_chunk* arg_b = void_b;
641 :
- 642 43029600 : if (arg_a->parity_pos < arg_b->parity_pos)
- 643 932908 : return -1;
- 644 42096692 : if (arg_a->parity_pos > arg_b->parity_pos)
- 645 42057855 : return 1;
+ 642 43351652 : if (arg_a->parity_pos < arg_b->parity_pos)
+ 643 2220745 : return -1;
+ 644 41130907 : if (arg_a->parity_pos > arg_b->parity_pos)
+ 645 41089282 : return 1;
646 :
- 647 38837 : return 0;
+ 647 41625 : return 0;
648 : }
649 :
- 650 43527418 : int chunk_file_compare(const void* void_a, const void* void_b)
+ 650 44153325 : int chunk_file_compare(const void* void_a, const void* void_b)
651 : {
- 652 43527418 : const struct snapraid_chunk* arg_a = void_a;
- 653 43527418 : const struct snapraid_chunk* arg_b = void_b;
+ 652 44153325 : const struct snapraid_chunk* arg_a = void_a;
+ 653 44153325 : const struct snapraid_chunk* arg_b = void_b;
654 :
- 655 43527418 : if (arg_a->file < arg_b->file)
- 656 856585 : return -1;
- 657 42670833 : if (arg_a->file > arg_b->file)
- 658 42601978 : return 1;
+ 655 44153325 : if (arg_a->file < arg_b->file)
+ 656 875219 : return -1;
+ 657 43278106 : if (arg_a->file > arg_b->file)
+ 658 43205895 : return 1;
659 :
- 660 68855 : if (arg_a->file_pos < arg_b->file_pos)
- 661 192 : return -1;
- 662 68663 : if (arg_a->file_pos > arg_b->file_pos)
- 663 29826 : return 1;
+ 660 72211 : if (arg_a->file_pos < arg_b->file_pos)
+ 661 194 : return -1;
+ 662 72017 : if (arg_a->file_pos > arg_b->file_pos)
+ 663 30392 : return 1;
664 :
- 665 38837 : return 0;
+ 665 41625 : return 0;
666 : }
667 :
- 668 115419 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag)
+ 668 116876 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag)
669 : {
670 : struct snapraid_link* slink;
671 :
- 672 115419 : slink = malloc_nofail(sizeof(struct snapraid_link));
- 673 115419 : slink->sub = strdup_nofail(sub);
- 674 115419 : slink->linkto = strdup_nofail(linkto);
- 675 115419 : slink->flag = link_flag;
+ 672 116876 : slink = malloc_nofail(sizeof(struct snapraid_link));
+ 673 116876 : slink->sub = strdup_nofail(sub);
+ 674 116876 : slink->linkto = strdup_nofail(linkto);
+ 675 116876 : slink->flag = link_flag;
676 :
- 677 115419 : return slink;
+ 677 116876 : return slink;
678 : }
679 :
- 680 109621 : void link_free(struct snapraid_link* slink)
+ 680 111078 : void link_free(struct snapraid_link* slink)
681 : {
- 682 109621 : free(slink->sub);
- 683 109621 : free(slink->linkto);
- 684 109621 : free(slink);
- 685 109621 : }
+ 682 111078 : free(slink->sub);
+ 683 111078 : free(slink->linkto);
+ 684 111078 : free(slink);
+ 685 111078 : }
686 :
- 687 30380 : int link_name_compare_to_arg(const void* void_arg, const void* void_data)
+ 687 31837 : int link_name_compare_to_arg(const void* void_arg, const void* void_data)
688 : {
- 689 30380 : const char* arg = void_arg;
- 690 30380 : const struct snapraid_link* slink = void_data;
+ 689 31837 : const char* arg = void_arg;
+ 690 31837 : const struct snapraid_link* slink = void_data;
691 :
- 692 30380 : return strcmp(arg, slink->sub);
+ 692 31837 : return strcmp(arg, slink->sub);
693 : }
694 :
695 1249 : int link_alpha_compare(const void* void_a, const void* void_b)
@@ -762,643 +762,644 @@
700 1249 : return strcmp(slink_a->sub, slink_b->sub);
701 : }
702 :
- 703 760 : struct snapraid_dir* dir_alloc(const char* sub)
+ 703 772 : struct snapraid_dir* dir_alloc(const char* sub)
704 : {
705 : struct snapraid_dir* dir;
706 :
- 707 760 : dir = malloc_nofail(sizeof(struct snapraid_dir));
- 708 760 : dir->sub = strdup_nofail(sub);
- 709 760 : dir->flag = 0;
+ 707 772 : dir = malloc_nofail(sizeof(struct snapraid_dir));
+ 708 772 : dir->sub = strdup_nofail(sub);
+ 709 772 : dir->flag = 0;
710 :
- 711 760 : return dir;
+ 711 772 : return dir;
712 : }
713 :
- 714 712 : void dir_free(struct snapraid_dir* dir)
+ 714 724 : void dir_free(struct snapraid_dir* dir)
715 : {
- 716 712 : free(dir->sub);
- 717 712 : free(dir);
- 718 712 : }
+ 716 724 : free(dir->sub);
+ 717 724 : free(dir);
+ 718 724 : }
719 :
- 720 217 : int dir_name_compare(const void* void_arg, const void* void_data)
+ 720 229 : int dir_name_compare(const void* void_arg, const void* void_data)
721 : {
- 722 217 : const char* arg = void_arg;
- 723 217 : const struct snapraid_dir* dir = void_data;
+ 722 229 : const char* arg = void_arg;
+ 723 229 : const struct snapraid_dir* dir = void_data;
724 :
- 725 217 : return strcmp(arg, dir->sub);
+ 725 229 : return strcmp(arg, dir->sub);
726 : }
727 :
- 728 1477 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip)
+ 728 1525 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip)
729 : {
730 : struct snapraid_disk* disk;
731 :
- 732 1477 : disk = malloc_nofail(sizeof(struct snapraid_disk));
- 733 1477 : pathcpy(disk->name, sizeof(disk->name), name);
- 734 1477 : pathimport(disk->dir, sizeof(disk->dir), dir);
- 735 :
- 736 : /* ensure that the dir terminate with "/" if it isn't empty */
- 737 1477 : pathslash(disk->dir, sizeof(disk->dir));
- 738 :
- 739 1477 : disk->smartctl[0] = 0;
- 740 1477 : disk->device = dev;
- 741 1477 : disk->tick = 0;
- 742 1477 : disk->total_blocks = 0;
- 743 1477 : disk->free_blocks = 0;
- 744 1477 : disk->first_free_block = 0;
- 745 1477 : disk->has_volatile_inodes = 0;
- 746 1477 : disk->has_unreliable_physical = 0;
- 747 1477 : disk->has_different_uuid = 0;
- 748 1477 : disk->has_unsupported_uuid = 0;
- 749 1477 : disk->had_empty_uuid = 0;
- 750 1477 : disk->mapping_idx = -1;
- 751 1477 : disk->skip_access = skip;
- 752 1477 : tommy_list_init(&disk->filelist);
- 753 1477 : tommy_list_init(&disk->deletedlist);
- 754 1477 : tommy_hashdyn_init(&disk->inodeset);
- 755 1477 : tommy_hashdyn_init(&disk->pathset);
- 756 1477 : tommy_hashdyn_init(&disk->stampset);
- 757 1477 : tommy_list_init(&disk->linklist);
- 758 1477 : tommy_hashdyn_init(&disk->linkset);
- 759 1477 : tommy_list_init(&disk->dirlist);
- 760 1477 : tommy_hashdyn_init(&disk->dirset);
- 761 1477 : tommy_tree_init(&disk->fs_parity, chunk_parity_compare);
- 762 1477 : tommy_tree_init(&disk->fs_file, chunk_file_compare);
- 763 1477 : disk->fs_last = 0;
- 764 :
- 765 1477 : return disk;
- 766 : }
- 767 :
- 768 1351 : void disk_free(struct snapraid_disk* disk)
- 769 : {
- 770 1351 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free);
- 771 1351 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free);
- 772 1351 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)chunk_free);
- 773 1351 : tommy_hashdyn_done(&disk->inodeset);
- 774 1351 : tommy_hashdyn_done(&disk->pathset);
- 775 1351 : tommy_hashdyn_done(&disk->stampset);
- 776 1351 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free);
- 777 1351 : tommy_hashdyn_done(&disk->linkset);
- 778 1351 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free);
- 779 1351 : tommy_hashdyn_done(&disk->dirset);
- 780 1351 : free(disk);
- 781 1351 : }
- 782 :
- 783 : struct chunk_disk_empty {
- 784 : block_off_t blockmax;
- 785 : };
- 786 :
- 787 : /**
- 788 : * Compare the chunk if inside the specified blockmax.
- 789 : */
- 790 10 : static int chunk_disk_empty_compare(const void* void_a, const void* void_b)
- 791 : {
- 792 10 : const struct chunk_disk_empty* arg_a = void_a;
- 793 10 : const struct snapraid_chunk* arg_b = void_b;
- 794 :
- 795 : /* if the block is inside the specified blockmax, it's found */
- 796 10 : if (arg_a->blockmax > arg_b->parity_pos)
- 797 5 : return 0;
- 798 :
- 799 : /* otherwise search for a smaller one */
- 800 5 : return -1;
- 801 : }
- 802 :
- 803 804 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax)
- 804 : {
- 805 804 : struct chunk_disk_empty arg = { blockmax };
- 806 :
- 807 : /* if there is an element, it's not empty */
- 808 : /* even if links and dirs have no block allocation */
- 809 804 : if (!tommy_list_empty(&disk->filelist))
- 810 736 : return 0;
- 811 68 : if (!tommy_list_empty(&disk->linklist))
- 812 0 : return 0;
- 813 68 : if (!tommy_list_empty(&disk->dirlist))
- 814 0 : return 0;
- 815 :
- 816 : /* search for any chunk inside blockmax */
- 817 68 : if (tommy_tree_search_compare(&disk->fs_parity, chunk_disk_empty_compare, &arg) != 0)
- 818 5 : return 0;
- 819 :
- 820 : /* finally, it's empty */
- 821 63 : return 1;
- 822 : }
- 823 :
- 824 : struct chunk_disk_size {
- 825 : block_off_t size;
- 826 : };
- 827 :
- 828 : /**
- 829 : * Compare the chunk by highest parity position.
- 830 : *
- 831 : * The maximum parity position is stored as size.
- 832 : */
- 833 47779 : static int chunk_disk_size_compare(const void* void_a, const void* void_b)
- 834 : {
- 835 47779 : struct chunk_disk_size* arg_a = (void*)void_a;
- 836 47779 : const struct snapraid_chunk* arg_b = void_b;
- 837 :
- 838 : /* get the maximum size */
- 839 47779 : if (arg_a->size < arg_b->parity_pos + arg_b->count)
- 840 47779 : arg_a->size = arg_b->parity_pos + arg_b->count;
- 841 :
- 842 : /* search always for a bigger one */
- 843 47779 : return 1;
- 844 : }
- 845 :
- 846 3955 : block_off_t disk_size(struct snapraid_disk* disk)
- 847 : {
- 848 3955 : struct chunk_disk_size arg = { 0 };
- 849 3955 : tommy_tree_search_compare(&disk->fs_parity, chunk_disk_size_compare, &arg);
- 850 3955 : return arg.size;
- 851 : }
- 852 :
- 853 : struct chunk_check {
- 854 : const struct snapraid_chunk* prev;
- 855 : int result;
- 856 : };
- 857 :
- 858 6291380 : void chunk_parity_check_foreach(void* void_arg, void* void_obj)
- 859 : {
- 860 6291380 : struct chunk_check* arg = void_arg;
- 861 6291380 : const struct snapraid_chunk* obj = void_obj;
- 862 6291380 : const struct snapraid_chunk* prev = arg->prev;
- 863 :
- 864 : /* set the next previous block */
- 865 6291380 : arg->prev = obj;
- 866 :
- 867 : /* stop reporting if too many errors */
- 868 6291380 : if (arg->result > 100) {
- 869 : /* LCOV_EXCL_START */
- 870 : return;
- 871 : /* LCOV_EXCL_STOP */
- 872 : }
- 873 :
- 874 6291380 : if (obj->count == 0) {
- 875 : /* LCOV_EXCL_START */
- 876 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n",
- 877 : obj->file->sub, obj->parity_pos);
- 878 : ++arg->result;
- 879 : return;
- 880 : /* LCOV_EXCL_STOP */
- 881 : }
- 882 :
- 883 : /* check only if there is a previous block */
- 884 6291380 : if (!prev)
- 885 2473 : return;
- 886 :
- 887 : /* check the order */
- 888 6288907 : if (prev->parity_pos >= obj->parity_pos) {
- 889 : /* LCOV_EXCL_START */
- 890 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
- 891 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
- 892 : ++arg->result;
- 893 : return;
- 894 : /* LCOV_EXCL_STOP */
- 895 : }
- 896 :
- 897 : /* check that the chunks don't overlap */
- 898 6288907 : if (prev->parity_pos + prev->count > obj->parity_pos) {
- 899 : /* LCOV_EXCL_START */
- 900 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
- 901 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
- 902 : ++arg->result;
- 903 : return;
- 904 : /* LCOV_EXCL_STOP */
- 905 : }
- 906 : }
- 907 :
- 908 6291380 : void chunk_file_check_foreach(void* void_arg, void* void_obj)
- 909 : {
- 910 6291380 : struct chunk_check* arg = void_arg;
- 911 6291380 : const struct snapraid_chunk* obj = void_obj;
- 912 6291380 : const struct snapraid_chunk* prev = arg->prev;
- 913 :
- 914 : /* set the next previous block */
- 915 6291380 : arg->prev = obj;
- 916 :
- 917 : /* stop reporting if too many errors */
- 918 6291380 : if (arg->result > 100) {
- 919 : /* LCOV_EXCL_START */
- 920 : return;
- 921 : /* LCOV_EXCL_STOP */
- 922 : }
- 923 :
- 924 6291380 : if (obj->count == 0) {
- 925 : /* LCOV_EXCL_START */
- 926 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n",
- 927 : obj->file->sub, obj->file_pos);
- 928 : ++arg->result;
- 929 : return;
- 930 : /* LCOV_EXCL_STOP */
- 931 : }
- 932 :
- 933 : /* note that for deleted files, some chunks may be missing */
- 934 :
- 935 : /* if the files are different */
- 936 6291380 : if (!prev || prev->file != obj->file) {
- 937 6247390 : if (prev != 0) {
- 938 6244917 : if (file_flag_has(prev->file, FILE_IS_DELETED)) {
- 939 : /* check that the chunk doesn't overflow the file */
- 940 59701 : if (prev->file_pos + prev->count > prev->file->blockmax) {
- 941 : /* LCOV_EXCL_START */
- 942 : log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n",
- 943 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
- 944 : ++arg->result;
- 945 : return;
- 946 : /* LCOV_EXCL_STOP */
- 947 : }
- 948 : } else {
- 949 : /* check that the chunk ends the file */
- 950 6185216 : if (prev->file_pos + prev->count != prev->file->blockmax) {
- 951 : /* LCOV_EXCL_START */
- 952 : log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n",
- 953 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
- 954 : ++arg->result;
- 955 : return;
- 956 : /* LCOV_EXCL_STOP */
- 957 : }
- 958 : }
- 959 : }
- 960 :
- 961 12494780 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
- 962 : /* check that the chunk doesn't overflow the file */
- 963 59776 : if (obj->file_pos + obj->count > obj->file->blockmax) {
- 964 : /* LCOV_EXCL_START */
- 965 : log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n",
- 966 : obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax);
- 967 : ++arg->result;
- 968 : return;
- 969 : /* LCOV_EXCL_STOP */
- 970 : }
- 971 : } else {
- 972 : /* check that the chunk starts the file */
- 973 6187614 : if (obj->file_pos != 0) {
- 974 : /* LCOV_EXCL_START */
- 975 : log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n",
- 976 : obj->file->sub, obj->file_pos, obj->count);
- 977 : ++arg->result;
- 978 : return;
- 979 : /* LCOV_EXCL_STOP */
- 980 : }
- 981 : }
- 982 : } else {
- 983 : /* check the order */
- 984 43990 : if (prev->file_pos >= obj->file_pos) {
- 985 : /* LCOV_EXCL_START */
- 986 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n",
- 987 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
- 988 : ++arg->result;
- 989 : return;
- 990 : /* LCOV_EXCL_STOP */
- 991 : }
- 992 :
- 993 43990 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
- 994 : /* check that the chunks don't overlap */
- 995 27 : if (prev->file_pos + prev->count > obj->file_pos) {
- 996 : /* LCOV_EXCL_START */
- 997 : log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
- 998 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
- 999 : ++arg->result;
- 1000 : return;
- 1001 : /* LCOV_EXCL_STOP */
- 1002 : }
- 1003 : } else {
- 1004 : /* check that the chunks are sequential */
- 1005 43963 : if (prev->file_pos + prev->count != obj->file_pos) {
- 1006 : /* LCOV_EXCL_START */
- 1007 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
- 1008 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
- 1009 : ++arg->result;
- 1010 : return;
- 1011 : /* LCOV_EXCL_STOP */
- 1012 : }
- 1013 : }
- 1014 : }
- 1015 : }
- 1016 :
- 1017 2676 : int fs_check(struct snapraid_disk* disk)
- 1018 : {
- 1019 : struct chunk_check arg;
- 1020 :
- 1021 : /* error count starts from 0 */
- 1022 2676 : arg.result = 0;
- 1023 :
- 1024 : /* check parity sequence */
- 1025 2676 : arg.prev = 0;
- 1026 2676 : tommy_tree_foreach_arg(&disk->fs_parity, chunk_parity_check_foreach, &arg);
- 1027 :
- 1028 : /* check file sequence */
- 1029 2676 : arg.prev = 0;
- 1030 2676 : tommy_tree_foreach_arg(&disk->fs_file, chunk_file_check_foreach, &arg);
- 1031 :
- 1032 2676 : if (arg.result != 0)
- 1033 0 : return -1;
- 1034 :
- 1035 2676 : return 0;
- 1036 : }
- 1037 :
- 1038 : struct chunk_parity_inside {
- 1039 : block_off_t parity_pos;
- 1040 : };
- 1041 :
- 1042 : /**
- 1043 : * Compare the chunk if containing the specified parity position.
- 1044 : */
- 1045 211700412 : static int chunk_parity_inside_compare(const void* void_a, const void* void_b)
- 1046 : {
- 1047 211700412 : const struct chunk_parity_inside* arg_a = void_a;
- 1048 211700412 : const struct snapraid_chunk* arg_b = void_b;
- 1049 :
- 1050 211700412 : if (arg_a->parity_pos < arg_b->parity_pos)
- 1051 78963776 : return -1;
- 1052 132736636 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count)
- 1053 115362811 : return 1;
- 1054 :
- 1055 17373825 : return 0;
- 1056 : }
- 1057 :
- 1058 : /**
- 1059 : * Seach the chunk at the specified parity position.
- 1060 : * The search is optimized for sequential accesses.
- 1061 : * \return If not found return 0
- 1062 : */
- 1063 62562730 : static struct snapraid_chunk* fs_par2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos)
- 1064 : {
- 1065 : struct snapraid_chunk* chunk;
- 1066 :
- 1067 : /* check if the last accessed chunk matches */
- 1068 62562730 : if (*fs_last
- 1069 62828537 : && parity_pos >= (*fs_last)->parity_pos
- 1070 62678201 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count
- 1071 : ) {
- 1072 43113171 : chunk = *fs_last;
- 1073 : } else {
- 1074 19449559 : struct chunk_parity_inside arg = { parity_pos };
- 1075 19449559 : chunk = tommy_tree_search_compare(&disk->fs_parity, chunk_parity_inside_compare, &arg);
- 1076 : }
- 1077 :
- 1078 62800800 : if (!chunk)
- 1079 2351363 : return 0;
- 1080 :
- 1081 : /* store the last accessed chunk */
- 1082 60449437 : *fs_last = chunk;
- 1083 :
- 1084 60449437 : return chunk;
- 1085 : }
- 1086 :
- 1087 : struct chunk_file_inside {
- 1088 : struct snapraid_file* file;
- 1089 : block_off_t file_pos;
- 1090 : };
- 1091 :
- 1092 : /**
- 1093 : * Compare the chunk if containing the specified file position.
- 1094 : */
- 1095 123424429 : static int chunk_file_inside_compare(const void* void_a, const void* void_b)
- 1096 : {
- 1097 123424429 : const struct chunk_file_inside* arg_a = void_a;
- 1098 123424429 : const struct snapraid_chunk* arg_b = void_b;
- 1099 :
- 1100 123424429 : if (arg_a->file < arg_b->file)
- 1101 52876931 : return -1;
- 1102 70547498 : if (arg_a->file > arg_b->file)
- 1103 58630297 : return 1;
- 1104 :
- 1105 11917201 : if (arg_a->file_pos < arg_b->file_pos)
- 1106 49120 : return -1;
- 1107 11868081 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count)
- 1108 44006 : return 1;
- 1109 :
- 1110 11824075 : return 0;
- 1111 : }
- 1112 :
- 1113 : /**
- 1114 : * Seach the chunk at the specified file position.
- 1115 : * The search is optimized for sequential accesses.
- 1116 : * \return If not found return 0
- 1117 : */
- 1118 34157182 : static struct snapraid_chunk* fs_file2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos)
- 1119 : {
- 1120 : struct snapraid_chunk* chunk;
- 1121 :
- 1122 : /* check if the last accessed chunk matches */
- 1123 34157182 : if (*fs_last
- 1124 34107260 : && file == (*fs_last)->file
- 1125 22496891 : && file_pos >= (*fs_last)->file_pos
- 1126 22481340 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count
- 1127 : ) {
- 1128 22376150 : chunk = *fs_last;
- 1129 : } else {
- 1130 11781032 : struct chunk_file_inside arg = { file, file_pos };
- 1131 11781032 : chunk = tommy_tree_search_compare(&disk->fs_file, chunk_file_inside_compare, &arg);
- 1132 : }
- 1133 :
- 1134 34132437 : if (!chunk)
- 1135 0 : return 0;
- 1136 :
- 1137 : /* store the last accessed chunk */
- 1138 34132437 : *fs_last = chunk;
- 1139 :
- 1140 34132437 : return chunk;
- 1141 : }
- 1142 :
- 1143 62671366 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos)
- 1144 : {
- 1145 : struct snapraid_chunk* chunk;
- 1146 :
- 1147 62671366 : chunk = fs_par2chunk_get_ts(disk, fs_last, parity_pos);
- 1148 62750330 : if (!chunk)
- 1149 2351221 : return 0;
- 1150 :
- 1151 60399109 : if (file_pos)
- 1152 59839728 : *file_pos = chunk->file_pos + (parity_pos - chunk->parity_pos);
- 1153 :
- 1154 60399109 : return chunk->file;
- 1155 : }
- 1156 :
- 1157 28740730 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos)
- 1158 : {
- 1159 : struct snapraid_chunk* chunk;
- 1160 :
- 1161 28740730 : chunk = fs_file2chunk_get_ts(disk, fs_last, file, file_pos);
- 1162 28850478 : if (!chunk) {
- 1163 : /* LCOV_EXCL_START */
- 1164 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
- 1165 : exit(EXIT_FAILURE);
- 1166 : /* LCOV_EXCL_STOP */
- 1167 : }
- 1168 :
- 1169 28850478 : return chunk->parity_pos + (file_pos - chunk->file_pos);
- 1170 : }
- 1171 :
- 1172 8849850 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos)
- 1173 : {
- 1174 : struct snapraid_chunk* chunk;
- 1175 : struct snapraid_chunk* parity_chunk;
- 1176 : struct snapraid_chunk* file_chunk;
- 1177 :
- 1178 8849850 : if (file_pos > 0) {
- 1179 : /* search an existing chunk for the previous file_pos */
- 1180 5267799 : chunk = fs_file2chunk_get_ts(disk, &disk->fs_last, file, file_pos - 1);
- 1181 :
- 1182 5267799 : if (chunk != 0 && parity_pos == chunk->parity_pos + chunk->count) {
- 1183 : /* ensure that we are extending the chunk at the end */
- 1184 5242090 : if (file_pos != chunk->file_pos + chunk->count) {
- 1185 : /* LCOV_EXCL_START */
- 1186 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name);
- 1187 : exit(EXIT_FAILURE);
- 1188 : /* LCOV_EXCL_STOP */
- 1189 : }
- 1190 :
- 1191 : /* extend the existing chunk */
- 1192 5242090 : ++chunk->count;
- 1193 :
- 1194 14091940 : return;
- 1195 : }
- 1196 : }
- 1197 :
- 1198 : /* a chunk doesn't exist, and we have to create a new one */
- 1199 3607760 : chunk = chunk_alloc(parity_pos, file, file_pos, 1);
- 1200 :
- 1201 : /* insert the chunk in the trees */
- 1202 3607760 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &chunk->parity_node, chunk);
- 1203 3607760 : file_chunk = tommy_tree_insert(&disk->fs_file, &chunk->file_node, chunk);
- 1204 :
- 1205 3607760 : if (parity_chunk != chunk || file_chunk != chunk) {
- 1206 : /* LCOV_EXCL_START */
- 1207 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name);
- 1208 : exit(EXIT_FAILURE);
- 1209 : /* LCOV_EXCL_STOP */
- 1210 : }
- 1211 :
- 1212 : /* store the last accessed chunk */
- 1213 3607760 : disk->fs_last = chunk;
- 1214 : }
- 1215 :
- 1216 104155 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
- 1217 : {
- 1218 : struct snapraid_chunk* chunk;
- 1219 : struct snapraid_chunk* second_chunk;
- 1220 : struct snapraid_chunk* parity_chunk;
- 1221 : struct snapraid_chunk* file_chunk;
- 1222 : block_off_t first_count, second_count;
- 1223 :
- 1224 104155 : chunk = fs_par2chunk_get_ts(disk, &disk->fs_last, parity_pos);
- 1225 104155 : if (!chunk) {
- 1226 : /* LCOV_EXCL_START */
- 1227 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name);
- 1228 : exit(EXIT_FAILURE);
- 1229 : /* LCOV_EXCL_STOP */
- 1230 : }
- 1231 :
- 1232 : /* if it's the only block of the chunk, delete it */
- 1233 104155 : if (chunk->count == 1) {
- 1234 : /* remove from the trees */
- 1235 38837 : tommy_tree_remove(&disk->fs_parity, chunk);
- 1236 38837 : tommy_tree_remove(&disk->fs_file, chunk);
- 1237 :
- 1238 : /* deallocate */
- 1239 38837 : chunk_free(chunk);
- 1240 :
- 1241 : /* clear the last accessed chunk */
- 1242 38837 : disk->fs_last = 0;
- 1243 38837 : return;
- 1244 : }
- 1245 :
- 1246 : /* if it's at the start of the chunk, shrink the chunk */
- 1247 65318 : if (parity_pos == chunk->parity_pos) {
- 1248 65316 : ++chunk->parity_pos;
- 1249 65316 : ++chunk->file_pos;
- 1250 65316 : --chunk->count;
- 1251 65316 : return;
- 1252 : }
- 1253 :
- 1254 : /* if it's at the end of the chunk, shrink the chunk */
- 1255 2 : if (parity_pos == chunk->parity_pos + chunk->count - 1) {
- 1256 1 : --chunk->count;
- 1257 1 : return;
- 1258 : }
- 1259 :
- 1260 : /* otherwise it's in the middle */
- 1261 1 : first_count = parity_pos - chunk->parity_pos;
- 1262 1 : second_count = chunk->count - first_count - 1;
- 1263 :
- 1264 : /* adjust the first chunk */
- 1265 1 : chunk->count = first_count;
- 1266 :
- 1267 : /* allocate the second chunk */
- 1268 1 : second_chunk = chunk_alloc(chunk->parity_pos + first_count + 1, chunk->file, chunk->file_pos + first_count + 1, second_count);
- 1269 :
- 1270 : /* insert the chunk in the trees */
- 1271 1 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &second_chunk->parity_node, second_chunk);
- 1272 1 : file_chunk = tommy_tree_insert(&disk->fs_file, &second_chunk->file_node, second_chunk);
- 1273 :
- 1274 1 : if (parity_chunk != second_chunk || file_chunk != second_chunk) {
- 1275 : /* LCOV_EXCL_START */
- 1276 : log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name);
- 1277 : exit(EXIT_FAILURE);
- 1278 : /* LCOV_EXCL_STOP */
- 1279 : }
- 1280 :
- 1281 : /* store the last accessed chunk */
- 1282 1 : disk->fs_last = second_chunk;
- 1283 : }
- 1284 :
- 1285 112904165 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos)
- 1286 : {
- 1287 112904165 : if (file_pos >= file->blockmax) {
- 1288 : /* LCOV_EXCL_START */
- 1289 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
- 1290 : exit(EXIT_FAILURE);
- 1291 : /* LCOV_EXCL_STOP */
- 1292 : }
- 1293 :
- 1294 112904165 : return &file->blockvec[file_pos];
- 1295 : }
- 1296 :
- 1297 51148943 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos)
- 1298 : {
- 1299 : struct snapraid_file* file;
- 1300 : block_off_t file_pos;
- 1301 :
- 1302 51148943 : file = fs_par2file_get_ts(disk, fs_last, parity_pos, &file_pos);
- 1303 :
- 1304 51044271 : if (!file)
- 1305 2337947 : return BLOCK_EMPTY;
- 1306 :
- 1307 48706324 : return fs_file2block_get(file, file_pos);
- 1308 : }
- 1309 :
- 1310 1447 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid)
- 1311 : {
- 1312 : struct snapraid_map* map;
- 1313 :
- 1314 1447 : map = malloc_nofail(sizeof(struct snapraid_map));
- 1315 1447 : pathcpy(map->name, sizeof(map->name), name);
- 1316 1447 : map->position = position;
- 1317 1447 : map->total_blocks = total_blocks;
- 1318 1447 : map->free_blocks = free_blocks;
- 1319 1447 : pathcpy(map->uuid, sizeof(map->uuid), uuid);
- 1320 :
- 1321 1447 : return map;
- 1322 : }
- 1323 :
- 1324 1327 : void map_free(struct snapraid_map* map)
- 1325 : {
- 1326 1327 : free(map);
- 1327 1327 : }
- 1328 :
- 1329 743492 : int time_compare(const void* void_a, const void* void_b)
- 1330 : {
- 1331 743492 : const time_t* time_a = void_a;
- 1332 743492 : const time_t* time_b = void_b;
- 1333 :
- 1334 743492 : if (*time_a < *time_b)
- 1335 28996 : return -1;
- 1336 714496 : if (*time_a > *time_b)
- 1337 185655 : return 1;
- 1338 528841 : return 0;
- 1339 : }
+ 732 1525 : disk = malloc_nofail(sizeof(struct snapraid_disk));
+ 733 1525 : pathcpy(disk->name, sizeof(disk->name), name);
+ 734 1525 : pathimport(disk->dir, sizeof(disk->dir), dir);
+ 735 1525 : pathcpy(disk->uuid, sizeof(disk->uuid), uuid);
+ 736 :
+ 737 : /* ensure that the dir terminate with "/" if it isn't empty */
+ 738 1525 : pathslash(disk->dir, sizeof(disk->dir));
+ 739 :
+ 740 1525 : disk->smartctl[0] = 0;
+ 741 1525 : disk->device = dev;
+ 742 1525 : disk->tick = 0;
+ 743 1525 : disk->total_blocks = 0;
+ 744 1525 : disk->free_blocks = 0;
+ 745 1525 : disk->first_free_block = 0;
+ 746 1525 : disk->has_volatile_inodes = 0;
+ 747 1525 : disk->has_unreliable_physical = 0;
+ 748 1525 : disk->has_different_uuid = 0;
+ 749 1525 : disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */
+ 750 1525 : disk->had_empty_uuid = 0;
+ 751 1525 : disk->mapping_idx = -1;
+ 752 1525 : disk->skip_access = skip;
+ 753 1525 : tommy_list_init(&disk->filelist);
+ 754 1525 : tommy_list_init(&disk->deletedlist);
+ 755 1525 : tommy_hashdyn_init(&disk->inodeset);
+ 756 1525 : tommy_hashdyn_init(&disk->pathset);
+ 757 1525 : tommy_hashdyn_init(&disk->stampset);
+ 758 1525 : tommy_list_init(&disk->linklist);
+ 759 1525 : tommy_hashdyn_init(&disk->linkset);
+ 760 1525 : tommy_list_init(&disk->dirlist);
+ 761 1525 : tommy_hashdyn_init(&disk->dirset);
+ 762 1525 : tommy_tree_init(&disk->fs_parity, chunk_parity_compare);
+ 763 1525 : tommy_tree_init(&disk->fs_file, chunk_file_compare);
+ 764 1525 : disk->fs_last = 0;
+ 765 :
+ 766 1525 : return disk;
+ 767 : }
+ 768 :
+ 769 1399 : void disk_free(struct snapraid_disk* disk)
+ 770 : {
+ 771 1399 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free);
+ 772 1399 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free);
+ 773 1399 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)chunk_free);
+ 774 1399 : tommy_hashdyn_done(&disk->inodeset);
+ 775 1399 : tommy_hashdyn_done(&disk->pathset);
+ 776 1399 : tommy_hashdyn_done(&disk->stampset);
+ 777 1399 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free);
+ 778 1399 : tommy_hashdyn_done(&disk->linkset);
+ 779 1399 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free);
+ 780 1399 : tommy_hashdyn_done(&disk->dirset);
+ 781 1399 : free(disk);
+ 782 1399 : }
+ 783 :
+ 784 : struct chunk_disk_empty {
+ 785 : block_off_t blockmax;
+ 786 : };
+ 787 :
+ 788 : /**
+ 789 : * Compare the chunk if inside the specified blockmax.
+ 790 : */
+ 791 13 : static int chunk_disk_empty_compare(const void* void_a, const void* void_b)
+ 792 : {
+ 793 13 : const struct chunk_disk_empty* arg_a = void_a;
+ 794 13 : const struct snapraid_chunk* arg_b = void_b;
+ 795 :
+ 796 : /* if the block is inside the specified blockmax, it's found */
+ 797 13 : if (arg_a->blockmax > arg_b->parity_pos)
+ 798 8 : return 0;
+ 799 :
+ 800 : /* otherwise search for a smaller one */
+ 801 5 : return -1;
+ 802 : }
+ 803 :
+ 804 870 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax)
+ 805 : {
+ 806 870 : struct chunk_disk_empty arg = { blockmax };
+ 807 :
+ 808 : /* if there is an element, it's not empty */
+ 809 : /* even if links and dirs have no block allocation */
+ 810 870 : if (!tommy_list_empty(&disk->filelist))
+ 811 778 : return 0;
+ 812 92 : if (!tommy_list_empty(&disk->linklist))
+ 813 0 : return 0;
+ 814 92 : if (!tommy_list_empty(&disk->dirlist))
+ 815 0 : return 0;
+ 816 :
+ 817 : /* search for any chunk inside blockmax */
+ 818 92 : if (tommy_tree_search_compare(&disk->fs_parity, chunk_disk_empty_compare, &arg) != 0)
+ 819 8 : return 0;
+ 820 :
+ 821 : /* finally, it's empty */
+ 822 84 : return 1;
+ 823 : }
+ 824 :
+ 825 : struct chunk_disk_size {
+ 826 : block_off_t size;
+ 827 : };
+ 828 :
+ 829 : /**
+ 830 : * Compare the chunk by highest parity position.
+ 831 : *
+ 832 : * The maximum parity position is stored as size.
+ 833 : */
+ 834 48702 : static int chunk_disk_size_compare(const void* void_a, const void* void_b)
+ 835 : {
+ 836 48702 : struct chunk_disk_size* arg_a = (void*)void_a;
+ 837 48702 : const struct snapraid_chunk* arg_b = void_b;
+ 838 :
+ 839 : /* get the maximum size */
+ 840 48702 : if (arg_a->size < arg_b->parity_pos + arg_b->count)
+ 841 48702 : arg_a->size = arg_b->parity_pos + arg_b->count;
+ 842 :
+ 843 : /* search always for a bigger one */
+ 844 48702 : return 1;
+ 845 : }
+ 846 :
+ 847 4165 : block_off_t disk_size(struct snapraid_disk* disk)
+ 848 : {
+ 849 4165 : struct chunk_disk_size arg = { 0 };
+ 850 4165 : tommy_tree_search_compare(&disk->fs_parity, chunk_disk_size_compare, &arg);
+ 851 4165 : return arg.size;
+ 852 : }
+ 853 :
+ 854 : struct chunk_check {
+ 855 : const struct snapraid_chunk* prev;
+ 856 : int result;
+ 857 : };
+ 858 :
+ 859 6441048 : void chunk_parity_check_foreach(void* void_arg, void* void_obj)
+ 860 : {
+ 861 6441048 : struct chunk_check* arg = void_arg;
+ 862 6441048 : const struct snapraid_chunk* obj = void_obj;
+ 863 6441048 : const struct snapraid_chunk* prev = arg->prev;
+ 864 :
+ 865 : /* set the next previous block */
+ 866 6441048 : arg->prev = obj;
+ 867 :
+ 868 : /* stop reporting if too many errors */
+ 869 6441048 : if (arg->result > 100) {
+ 870 : /* LCOV_EXCL_START */
+ 871 : return;
+ 872 : /* LCOV_EXCL_STOP */
+ 873 : }
+ 874 :
+ 875 6441048 : if (obj->count == 0) {
+ 876 : /* LCOV_EXCL_START */
+ 877 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n",
+ 878 : obj->file->sub, obj->parity_pos);
+ 879 : ++arg->result;
+ 880 : return;
+ 881 : /* LCOV_EXCL_STOP */
+ 882 : }
+ 883 :
+ 884 : /* check only if there is a previous block */
+ 885 6441048 : if (!prev)
+ 886 2588 : return;
+ 887 :
+ 888 : /* check the order */
+ 889 6438460 : if (prev->parity_pos >= obj->parity_pos) {
+ 890 : /* LCOV_EXCL_START */
+ 891 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
+ 892 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
+ 893 : ++arg->result;
+ 894 : return;
+ 895 : /* LCOV_EXCL_STOP */
+ 896 : }
+ 897 :
+ 898 : /* check that the chunks don't overlap */
+ 899 6438460 : if (prev->parity_pos + prev->count > obj->parity_pos) {
+ 900 : /* LCOV_EXCL_START */
+ 901 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
+ 902 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
+ 903 : ++arg->result;
+ 904 : return;
+ 905 : /* LCOV_EXCL_STOP */
+ 906 : }
+ 907 : }
+ 908 :
+ 909 6441048 : void chunk_file_check_foreach(void* void_arg, void* void_obj)
+ 910 : {
+ 911 6441048 : struct chunk_check* arg = void_arg;
+ 912 6441048 : const struct snapraid_chunk* obj = void_obj;
+ 913 6441048 : const struct snapraid_chunk* prev = arg->prev;
+ 914 :
+ 915 : /* set the next previous block */
+ 916 6441048 : arg->prev = obj;
+ 917 :
+ 918 : /* stop reporting if too many errors */
+ 919 6441048 : if (arg->result > 100) {
+ 920 : /* LCOV_EXCL_START */
+ 921 : return;
+ 922 : /* LCOV_EXCL_STOP */
+ 923 : }
+ 924 :
+ 925 6441048 : if (obj->count == 0) {
+ 926 : /* LCOV_EXCL_START */
+ 927 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n",
+ 928 : obj->file->sub, obj->file_pos);
+ 929 : ++arg->result;
+ 930 : return;
+ 931 : /* LCOV_EXCL_STOP */
+ 932 : }
+ 933 :
+ 934 : /* note that for deleted files, some chunks may be missing */
+ 935 :
+ 936 : /* if the files are different */
+ 937 6441048 : if (!prev || prev->file != obj->file) {
+ 938 6395699 : if (prev != 0) {
+ 939 6393111 : if (file_flag_has(prev->file, FILE_IS_DELETED)) {
+ 940 : /* check that the chunk doesn't overflow the file */
+ 941 59771 : if (prev->file_pos + prev->count > prev->file->blockmax) {
+ 942 : /* LCOV_EXCL_START */
+ 943 : log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n",
+ 944 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
+ 945 : ++arg->result;
+ 946 : return;
+ 947 : /* LCOV_EXCL_STOP */
+ 948 : }
+ 949 : } else {
+ 950 : /* check that the chunk ends the file */
+ 951 6333340 : if (prev->file_pos + prev->count != prev->file->blockmax) {
+ 952 : /* LCOV_EXCL_START */
+ 953 : log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n",
+ 954 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
+ 955 : ++arg->result;
+ 956 : return;
+ 957 : /* LCOV_EXCL_STOP */
+ 958 : }
+ 959 : }
+ 960 : }
+ 961 :
+ 962 12791398 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
+ 963 : /* check that the chunk doesn't overflow the file */
+ 964 59854 : if (obj->file_pos + obj->count > obj->file->blockmax) {
+ 965 : /* LCOV_EXCL_START */
+ 966 : log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n",
+ 967 : obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax);
+ 968 : ++arg->result;
+ 969 : return;
+ 970 : /* LCOV_EXCL_STOP */
+ 971 : }
+ 972 : } else {
+ 973 : /* check that the chunk starts the file */
+ 974 6335845 : if (obj->file_pos != 0) {
+ 975 : /* LCOV_EXCL_START */
+ 976 : log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n",
+ 977 : obj->file->sub, obj->file_pos, obj->count);
+ 978 : ++arg->result;
+ 979 : return;
+ 980 : /* LCOV_EXCL_STOP */
+ 981 : }
+ 982 : }
+ 983 : } else {
+ 984 : /* check the order */
+ 985 45349 : if (prev->file_pos >= obj->file_pos) {
+ 986 : /* LCOV_EXCL_START */
+ 987 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n",
+ 988 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
+ 989 : ++arg->result;
+ 990 : return;
+ 991 : /* LCOV_EXCL_STOP */
+ 992 : }
+ 993 :
+ 994 45349 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
+ 995 : /* check that the chunks don't overlap */
+ 996 27 : if (prev->file_pos + prev->count > obj->file_pos) {
+ 997 : /* LCOV_EXCL_START */
+ 998 : log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
+ 999 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
+ 1000 : ++arg->result;
+ 1001 : return;
+ 1002 : /* LCOV_EXCL_STOP */
+ 1003 : }
+ 1004 : } else {
+ 1005 : /* check that the chunks are sequential */
+ 1006 45322 : if (prev->file_pos + prev->count != obj->file_pos) {
+ 1007 : /* LCOV_EXCL_START */
+ 1008 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
+ 1009 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
+ 1010 : ++arg->result;
+ 1011 : return;
+ 1012 : /* LCOV_EXCL_STOP */
+ 1013 : }
+ 1014 : }
+ 1015 : }
+ 1016 : }
+ 1017 :
+ 1018 2838 : int fs_check(struct snapraid_disk* disk)
+ 1019 : {
+ 1020 : struct chunk_check arg;
+ 1021 :
+ 1022 : /* error count starts from 0 */
+ 1023 2838 : arg.result = 0;
+ 1024 :
+ 1025 : /* check parity sequence */
+ 1026 2838 : arg.prev = 0;
+ 1027 2838 : tommy_tree_foreach_arg(&disk->fs_parity, chunk_parity_check_foreach, &arg);
+ 1028 :
+ 1029 : /* check file sequence */
+ 1030 2838 : arg.prev = 0;
+ 1031 2838 : tommy_tree_foreach_arg(&disk->fs_file, chunk_file_check_foreach, &arg);
+ 1032 :
+ 1033 2838 : if (arg.result != 0)
+ 1034 0 : return -1;
+ 1035 :
+ 1036 2838 : return 0;
+ 1037 : }
+ 1038 :
+ 1039 : struct chunk_parity_inside {
+ 1040 : block_off_t parity_pos;
+ 1041 : };
+ 1042 :
+ 1043 : /**
+ 1044 : * Compare the chunk if containing the specified parity position.
+ 1045 : */
+ 1046 102351431 : static int chunk_parity_inside_compare(const void* void_a, const void* void_b)
+ 1047 : {
+ 1048 102351431 : const struct chunk_parity_inside* arg_a = void_a;
+ 1049 102351431 : const struct snapraid_chunk* arg_b = void_b;
+ 1050 :
+ 1051 102351431 : if (arg_a->parity_pos < arg_b->parity_pos)
+ 1052 35386523 : return -1;
+ 1053 66964908 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count)
+ 1054 59326333 : return 1;
+ 1055 :
+ 1056 7638575 : return 0;
+ 1057 : }
+ 1058 :
+ 1059 : /**
+ 1060 : * Seach the chunk at the specified parity position.
+ 1061 : * The search is optimized for sequential accesses.
+ 1062 : * \return If not found return 0
+ 1063 : */
+ 1064 38418652 : static struct snapraid_chunk* fs_par2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos)
+ 1065 : {
+ 1066 : struct snapraid_chunk* chunk;
+ 1067 :
+ 1068 : /* check if the last accessed chunk matches */
+ 1069 38418652 : if (*fs_last
+ 1070 38399475 : && parity_pos >= (*fs_last)->parity_pos
+ 1071 38241144 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count
+ 1072 : ) {
+ 1073 29222600 : chunk = *fs_last;
+ 1074 : } else {
+ 1075 9196052 : struct chunk_parity_inside arg = { parity_pos };
+ 1076 9196052 : chunk = tommy_tree_search_compare(&disk->fs_parity, chunk_parity_inside_compare, &arg);
+ 1077 : }
+ 1078 :
+ 1079 38418652 : if (!chunk)
+ 1080 1557477 : return 0;
+ 1081 :
+ 1082 : /* store the last accessed chunk */
+ 1083 36861175 : *fs_last = chunk;
+ 1084 :
+ 1085 36861175 : return chunk;
+ 1086 : }
+ 1087 :
+ 1088 : struct chunk_file_inside {
+ 1089 : struct snapraid_file* file;
+ 1090 : block_off_t file_pos;
+ 1091 : };
+ 1092 :
+ 1093 : /**
+ 1094 : * Compare the chunk if containing the specified file position.
+ 1095 : */
+ 1096 21495373 : static int chunk_file_inside_compare(const void* void_a, const void* void_b)
+ 1097 : {
+ 1098 21495373 : const struct chunk_file_inside* arg_a = void_a;
+ 1099 21495373 : const struct snapraid_chunk* arg_b = void_b;
+ 1100 :
+ 1101 21495373 : if (arg_a->file < arg_b->file)
+ 1102 8992026 : return -1;
+ 1103 12503347 : if (arg_a->file > arg_b->file)
+ 1104 10470075 : return 1;
+ 1105 :
+ 1106 2033272 : if (arg_a->file_pos < arg_b->file_pos)
+ 1107 7395 : return -1;
+ 1108 2025877 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count)
+ 1109 9044 : return 1;
+ 1110 :
+ 1111 2016833 : return 0;
+ 1112 : }
+ 1113 :
+ 1114 : /**
+ 1115 : * Search the chunk at the specified file position.
+ 1116 : * The search is optimized for sequential accesses.
+ 1117 : * \return If not found return 0
+ 1118 : */
+ 1119 10223247 : static struct snapraid_chunk* fs_file2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos)
+ 1120 : {
+ 1121 : struct snapraid_chunk* chunk;
+ 1122 :
+ 1123 : /* check if the last accessed chunk matches */
+ 1124 10223247 : if (*fs_last
+ 1125 10199301 : && file == (*fs_last)->file
+ 1126 8220750 : && file_pos >= (*fs_last)->file_pos
+ 1127 8220750 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count
+ 1128 : ) {
+ 1129 8206414 : chunk = *fs_last;
+ 1130 : } else {
+ 1131 2016833 : struct chunk_file_inside arg = { file, file_pos };
+ 1132 2016833 : chunk = tommy_tree_search_compare(&disk->fs_file, chunk_file_inside_compare, &arg);
+ 1133 : }
+ 1134 :
+ 1135 10223247 : if (!chunk)
+ 1136 0 : return 0;
+ 1137 :
+ 1138 : /* store the last accessed chunk */
+ 1139 10223247 : *fs_last = chunk;
+ 1140 :
+ 1141 10223247 : return chunk;
+ 1142 : }
+ 1143 :
+ 1144 38311850 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos)
+ 1145 : {
+ 1146 : struct snapraid_chunk* chunk;
+ 1147 :
+ 1148 38311850 : chunk = fs_par2chunk_get_ts(disk, fs_last, parity_pos);
+ 1149 38311850 : if (!chunk)
+ 1150 1557477 : return 0;
+ 1151 :
+ 1152 36754373 : if (file_pos)
+ 1153 36410379 : *file_pos = chunk->file_pos + (parity_pos - chunk->parity_pos);
+ 1154 :
+ 1155 36754373 : return chunk->file;
+ 1156 : }
+ 1157 :
+ 1158 4878725 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos)
+ 1159 : {
+ 1160 : struct snapraid_chunk* chunk;
+ 1161 :
+ 1162 4878725 : chunk = fs_file2chunk_get_ts(disk, fs_last, file, file_pos);
+ 1163 4878725 : if (!chunk) {
+ 1164 : /* LCOV_EXCL_START */
+ 1165 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
+ 1166 : os_abort();
+ 1167 : /* LCOV_EXCL_STOP */
+ 1168 : }
+ 1169 :
+ 1170 4878725 : return chunk->parity_pos + (file_pos - chunk->file_pos);
+ 1171 : }
+ 1172 :
+ 1173 8975787 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos)
+ 1174 : {
+ 1175 : struct snapraid_chunk* chunk;
+ 1176 : struct snapraid_chunk* parity_chunk;
+ 1177 : struct snapraid_chunk* file_chunk;
+ 1178 :
+ 1179 8975787 : if (file_pos > 0) {
+ 1180 : /* search an existing chunk for the previous file_pos */
+ 1181 5344522 : chunk = fs_file2chunk_get_ts(disk, &disk->fs_last, file, file_pos - 1);
+ 1182 :
+ 1183 5344522 : if (chunk != 0 && parity_pos == chunk->parity_pos + chunk->count) {
+ 1184 : /* ensure that we are extending the chunk at the end */
+ 1185 5318361 : if (file_pos != chunk->file_pos + chunk->count) {
+ 1186 : /* LCOV_EXCL_START */
+ 1187 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name);
+ 1188 : os_abort();
+ 1189 : /* LCOV_EXCL_STOP */
+ 1190 : }
+ 1191 :
+ 1192 : /* extend the existing chunk */
+ 1193 5318361 : ++chunk->count;
+ 1194 :
+ 1195 14294148 : return;
+ 1196 : }
+ 1197 : }
+ 1198 :
+ 1199 : /* a chunk doesn't exist, and we have to create a new one */
+ 1200 3657426 : chunk = chunk_alloc(parity_pos, file, file_pos, 1);
+ 1201 :
+ 1202 : /* insert the chunk in the trees */
+ 1203 3657426 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &chunk->parity_node, chunk);
+ 1204 3657426 : file_chunk = tommy_tree_insert(&disk->fs_file, &chunk->file_node, chunk);
+ 1205 :
+ 1206 3657426 : if (parity_chunk != chunk || file_chunk != chunk) {
+ 1207 : /* LCOV_EXCL_START */
+ 1208 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name);
+ 1209 : os_abort();
+ 1210 : /* LCOV_EXCL_STOP */
+ 1211 : }
+ 1212 :
+ 1213 : /* store the last accessed chunk */
+ 1214 3657426 : disk->fs_last = chunk;
+ 1215 : }
+ 1216 :
+ 1217 106802 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
+ 1218 : {
+ 1219 : struct snapraid_chunk* chunk;
+ 1220 : struct snapraid_chunk* second_chunk;
+ 1221 : struct snapraid_chunk* parity_chunk;
+ 1222 : struct snapraid_chunk* file_chunk;
+ 1223 : block_off_t first_count, second_count;
+ 1224 :
+ 1225 106802 : chunk = fs_par2chunk_get_ts(disk, &disk->fs_last, parity_pos);
+ 1226 106802 : if (!chunk) {
+ 1227 : /* LCOV_EXCL_START */
+ 1228 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name);
+ 1229 : os_abort();
+ 1230 : /* LCOV_EXCL_STOP */
+ 1231 : }
+ 1232 :
+ 1233 : /* if it's the only block of the chunk, delete it */
+ 1234 106802 : if (chunk->count == 1) {
+ 1235 : /* remove from the trees */
+ 1236 41625 : tommy_tree_remove(&disk->fs_parity, chunk);
+ 1237 41625 : tommy_tree_remove(&disk->fs_file, chunk);
+ 1238 :
+ 1239 : /* deallocate */
+ 1240 41625 : chunk_free(chunk);
+ 1241 :
+ 1242 : /* clear the last accessed chunk */
+ 1243 41625 : disk->fs_last = 0;
+ 1244 41625 : return;
+ 1245 : }
+ 1246 :
+ 1247 : /* if it's at the start of the chunk, shrink the chunk */
+ 1248 65177 : if (parity_pos == chunk->parity_pos) {
+ 1249 65175 : ++chunk->parity_pos;
+ 1250 65175 : ++chunk->file_pos;
+ 1251 65175 : --chunk->count;
+ 1252 65175 : return;
+ 1253 : }
+ 1254 :
+ 1255 : /* if it's at the end of the chunk, shrink the chunk */
+ 1256 2 : if (parity_pos == chunk->parity_pos + chunk->count - 1) {
+ 1257 1 : --chunk->count;
+ 1258 1 : return;
+ 1259 : }
+ 1260 :
+ 1261 : /* otherwise it's in the middle */
+ 1262 1 : first_count = parity_pos - chunk->parity_pos;
+ 1263 1 : second_count = chunk->count - first_count - 1;
+ 1264 :
+ 1265 : /* adjust the first chunk */
+ 1266 1 : chunk->count = first_count;
+ 1267 :
+ 1268 : /* allocate the second chunk */
+ 1269 1 : second_chunk = chunk_alloc(chunk->parity_pos + first_count + 1, chunk->file, chunk->file_pos + first_count + 1, second_count);
+ 1270 :
+ 1271 : /* insert the chunk in the trees */
+ 1272 1 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &second_chunk->parity_node, second_chunk);
+ 1273 1 : file_chunk = tommy_tree_insert(&disk->fs_file, &second_chunk->file_node, second_chunk);
+ 1274 :
+ 1275 1 : if (parity_chunk != second_chunk || file_chunk != second_chunk) {
+ 1276 : /* LCOV_EXCL_START */
+ 1277 : log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name);
+ 1278 : os_abort();
+ 1279 : /* LCOV_EXCL_STOP */
+ 1280 : }
+ 1281 :
+ 1282 : /* store the last accessed chunk */
+ 1283 1 : disk->fs_last = second_chunk;
+ 1284 : }
+ 1285 :
+ 1286 44106216 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos)
+ 1287 : {
+ 1288 44106216 : if (file_pos >= file->blockmax) {
+ 1289 : /* LCOV_EXCL_START */
+ 1290 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
+ 1291 : os_abort();
+ 1292 : /* LCOV_EXCL_STOP */
+ 1293 : }
+ 1294 :
+ 1295 44106216 : return &file->blockvec[file_pos];
+ 1296 : }
+ 1297 :
+ 1298 26733115 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos)
+ 1299 : {
+ 1300 : struct snapraid_file* file;
+ 1301 : block_off_t file_pos;
+ 1302 :
+ 1303 26733115 : file = fs_par2file_get_ts(disk, fs_last, parity_pos, &file_pos);
+ 1304 :
+ 1305 26733115 : if (!file)
+ 1306 1557477 : return BLOCK_EMPTY;
+ 1307 :
+ 1308 25175638 : return fs_file2block_get(file, file_pos);
+ 1309 : }
+ 1310 :
+ 1311 1495 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid)
+ 1312 : {
+ 1313 : struct snapraid_map* map;
+ 1314 :
+ 1315 1495 : map = malloc_nofail(sizeof(struct snapraid_map));
+ 1316 1495 : pathcpy(map->name, sizeof(map->name), name);
+ 1317 1495 : map->position = position;
+ 1318 1495 : map->total_blocks = total_blocks;
+ 1319 1495 : map->free_blocks = free_blocks;
+ 1320 1495 : pathcpy(map->uuid, sizeof(map->uuid), uuid);
+ 1321 :
+ 1322 1495 : return map;
+ 1323 : }
+ 1324 :
+ 1325 1375 : void map_free(struct snapraid_map* map)
+ 1326 : {
+ 1327 1375 : free(map);
+ 1328 1375 : }
+ 1329 :
+ 1330 707506 : int time_compare(const void* void_a, const void* void_b)
+ 1331 : {
+ 1332 707506 : const time_t* time_a = void_a;
+ 1333 707506 : const time_t* time_b = void_b;
+ 1334 :
+ 1335 707506 : if (*time_a < *time_b)
+ 1336 26871 : return -1;
+ 1337 680635 : if (*time_a > *time_b)
+ 1338 146878 : return 1;
+ 1339 533757 : return 0;
+ 1340 : }
diff --git a/cov/cmdline/elem.h.func-sort-c.html b/cov/cmdline/elem.h.func-sort-c.html
index 2a9ac818..8bc953ab 100644
--- a/cov/cmdline/elem.h.func-sort-c.html
+++ b/cov/cmdline/elem.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,159 +60,159 @@
Hit count  |
- | block_state_get |
- 96735410 |
+ block_state_get |
+ 49967196 |
- | file_flag_has |
- 33299459 |
+ file_flag_has |
+ 33706389 |
- | fs_par2block_get |
- 21727310 |
+ fs_par2block_get |
+ 22209416 |
- | block_state_set |
- 18242161 |
+ block_state_set |
+ 18633161 |
- | block_has_file |
- 12929086 |
+ block_has_file |
+ 13243669 |
- | fs_par2file_get |
- 11514087 |
+ block_has_invalid_parity |
+ 11837218 |
- | block_has_invalid_parity |
- 11489174 |
+ fs_par2file_get |
+ 11578735 |
- | info_get |
- 10573034 |
+ hash_invalid_set |
+ 9036734 |
- | hash_invalid_set |
- 8910831 |
+ file_stamp_hash |
+ 6198269 |
- | file_stamp_hash |
- 6139138 |
+ file_flag_set |
+ 5250833 |
- | file_flag_set |
- 5176917 |
+ info_get |
+ 5104110 |
- | file_inode_hash |
- 4822298 |
+ file_inode_hash |
+ 4924816 |
- | file_path_hash |
- 3766623 |
+ file_path_hash |
+ 3815727 |
- | info_get_rehash |
- 3312725 |
+ filter_hidden |
+ 3114300 |
- | filter_hidden |
- 3066852 |
+ block_has_past_hash |
+ 2401624 |
- | block_has_past_hash |
- 2287366 |
+ block_has_updated_hash |
+ 2075259 |
- | info_get_time |
- 2258078 |
+ info_get_rehash |
+ 2058338 |
- | block_has_updated_hash |
- 2005171 |
+ info_set |
+ 1639782 |
- | info_get_bad |
- 1725704 |
+ info_get_time |
+ 890086 |
- | info_set |
- 1609485 |
+ hash_is_zero |
+ 761026 |
- | info_get_justsynced |
- 1474627 |
+ hash_is_invalid |
+ 759605 |
- | hash_is_zero |
- 790275 |
+ fs_file2par_get |
+ 519510 |
- | hash_is_invalid |
- 776042 |
+ info_get_bad |
+ 338860 |
- | fs_file2par_get |
- 464306 |
+ block_has_file_and_valid_parity |
+ 257893 |
- | link_flag_get |
- 410820 |
+ link_flag_has |
+ 205548 |
- | info_make |
- 394996 |
+ info_make |
+ 174394 |
- | block_has_file_and_valid_parity |
- 221100 |
+ link_name_hash |
+ 151170 |
- | link_flag_has |
- 202633 |
+ hash_zero_set |
+ 115487 |
- | hash_zero_set |
- 153288 |
+ link_flag_get |
+ 89637 |
- | link_name_hash |
- 148256 |
+ info_get_justsynced |
+ 79285 |
- | hash_is_real |
- 65785 |
+ hash_is_real |
+ 44133 |
- | link_flag_set |
- 36114 |
+ link_flag_set |
+ 37571 |
- | file_flag_clear |
- 14174 |
+ file_flag_clear |
+ 20621 |
- | info_set_rehash |
- 9199 |
+ info_set_rehash |
+ 9207 |
- | info_set_bad |
- 1802 |
+ info_set_bad |
+ 1771 |
- | dir_name_hash |
- 987 |
+ dir_name_hash |
+ 1011 |
- | dir_flag_has |
- 876 |
+ dir_flag_has |
+ 900 |
- | dir_flag_set |
- 235 |
+ dir_flag_set |
+ 247 |
- | link_flag_let |
+ link_flag_let |
6 |
diff --git a/cov/cmdline/elem.h.func.html b/cov/cmdline/elem.h.func.html
index 8e76d216..d9c2ba6e 100644
--- a/cov/cmdline/elem.h.func.html
+++ b/cov/cmdline/elem.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,160 +60,160 @@
Hit count  |
- | block_has_file |
- 12929086 |
+ block_has_file |
+ 13243669 |
- | block_has_file_and_valid_parity |
- 221100 |
+ block_has_file_and_valid_parity |
+ 257893 |
- | block_has_invalid_parity |
- 11489174 |
+ block_has_invalid_parity |
+ 11837218 |
- | block_has_past_hash |
- 2287366 |
+ block_has_past_hash |
+ 2401624 |
- | block_has_updated_hash |
- 2005171 |
+ block_has_updated_hash |
+ 2075259 |
- | block_state_get |
- 96735410 |
+ block_state_get |
+ 49967196 |
- | block_state_set |
- 18242161 |
+ block_state_set |
+ 18633161 |
- | dir_flag_has |
- 876 |
+ dir_flag_has |
+ 900 |
- | dir_flag_set |
- 235 |
+ dir_flag_set |
+ 247 |
- | dir_name_hash |
- 987 |
+ dir_name_hash |
+ 1011 |
- | file_flag_clear |
- 14174 |
+ file_flag_clear |
+ 20621 |
- | file_flag_has |
- 33299459 |
+ file_flag_has |
+ 33706389 |
- | file_flag_set |
- 5176917 |
+ file_flag_set |
+ 5250833 |
- | file_inode_hash |
- 4822298 |
+ file_inode_hash |
+ 4924816 |
- | file_path_hash |
- 3766623 |
+ file_path_hash |
+ 3815727 |
- | file_stamp_hash |
- 6139138 |
+ file_stamp_hash |
+ 6198269 |
- | filter_hidden |
- 3066852 |
+ filter_hidden |
+ 3114300 |
- | fs_file2par_get |
- 464306 |
+ fs_file2par_get |
+ 519510 |
- | fs_par2block_get |
- 21727310 |
+ fs_par2block_get |
+ 22209416 |
- | fs_par2file_get |
- 11514087 |
+ fs_par2file_get |
+ 11578735 |
- | hash_invalid_set |
- 8910831 |
+ hash_invalid_set |
+ 9036734 |
- | hash_is_invalid |
- 776042 |
+ hash_is_invalid |
+ 759605 |
- | hash_is_real |
- 65785 |
+ hash_is_real |
+ 44133 |
- | hash_is_zero |
- 790275 |
+ hash_is_zero |
+ 761026 |
- | hash_zero_set |
- 153288 |
+ hash_zero_set |
+ 115487 |
- | info_get |
- 10573034 |
+ info_get |
+ 5104110 |
- | info_get_bad |
- 1725704 |
+ info_get_bad |
+ 338860 |
- | info_get_justsynced |
- 1474627 |
+ info_get_justsynced |
+ 79285 |
- | info_get_rehash |
- 3312725 |
+ info_get_rehash |
+ 2058338 |
- | info_get_time |
- 2258078 |
+ info_get_time |
+ 890086 |
- | info_make |
- 394996 |
+ info_make |
+ 174394 |
- | info_set |
- 1609485 |
+ info_set |
+ 1639782 |
- | info_set_bad |
- 1802 |
+ info_set_bad |
+ 1771 |
- | info_set_rehash |
- 9199 |
+ info_set_rehash |
+ 9207 |
- | link_flag_get |
- 410820 |
+ link_flag_get |
+ 89637 |
- | link_flag_has |
- 202633 |
+ link_flag_has |
+ 205548 |
- | link_flag_let |
+ link_flag_let |
6 |
- | link_flag_set |
- 36114 |
+ link_flag_set |
+ 37571 |
- | link_name_hash |
- 148256 |
+ link_name_hash |
+ 151170 |
diff --git a/cov/cmdline/elem.h.gcov.html b/cov/cmdline/elem.h.gcov.html
index c8f25c02..e99f6062 100644
--- a/cov/cmdline/elem.h.gcov.html
+++ b/cov/cmdline/elem.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,1057 +94,1059 @@
32 : /* snapraid */
33 :
34 : /**
- 35 : * Invalid position.
+ 35 : * Max UUID length.
36 : */
- 37 : #define POS_INVALID ((block_off_t)-1)
+ 37 : #define UUID_MAX 128
38 :
39 : /**
- 40 : * Basic block position type.
- 41 : * With 32 bits and 128k blocks you can address 256 TB.
- 42 : */
- 43 : typedef uint32_t block_off_t;
- 44 :
- 45 : /**
- 46 : * Basic data position type.
- 47 : * It's signed as file size and offset are usually signed.
- 48 : */
- 49 : typedef int64_t data_off_t;
- 50 :
- 51 : /**
- 52 : * Content file specification.
+ 40 : * Invalid position.
+ 41 : */
+ 42 : #define POS_INVALID ((block_off_t)-1)
+ 43 :
+ 44 : /**
+ 45 : * Basic block position type.
+ 46 : * With 32 bits and 128k blocks you can address 256 TB.
+ 47 : */
+ 48 : typedef uint32_t block_off_t;
+ 49 :
+ 50 : /**
+ 51 : * Basic data position type.
+ 52 : * It's signed as file size and offset are usually signed.
53 : */
- 54 : struct snapraid_content {
- 55 : char content[PATH_MAX]; /**< Path of the content file. */
- 56 : uint64_t device; /**< Device identifier. */
- 57 : void* context; /**< Context used for multithread operations. */
- 58 : tommy_node node; /**< Next node in the list. */
- 59 : };
- 60 :
- 61 : /**
- 62 : * Filter for paths.
- 63 : */
- 64 : struct snapraid_filter {
- 65 : char pattern[PATH_MAX]; /**< Filter pattern. */
- 66 : int is_disk; /**< If the pattern is a disk one. */
- 67 : int is_path; /**< If the pattern is only for the complete path. */
- 68 : int is_dir; /**< If the pattern is only for dir. */
- 69 : int direction; /**< If it's an inclusion (=1) or an exclusion (=-1). */
- 70 : tommy_node node; /**< Next node in the list. */
- 71 : };
- 72 :
- 73 : /**
- 74 : * Block pointer used to represent unused blocks.
- 75 : */
- 76 : #define BLOCK_EMPTY 0
+ 54 : typedef int64_t data_off_t;
+ 55 :
+ 56 : /**
+ 57 : * Content file specification.
+ 58 : */
+ 59 : struct snapraid_content {
+ 60 : char content[PATH_MAX]; /**< Path of the content file. */
+ 61 : uint64_t device; /**< Device identifier. */
+ 62 : void* context; /**< Context used for multithread operations. */
+ 63 : tommy_node node; /**< Next node in the list. */
+ 64 : };
+ 65 :
+ 66 : /**
+ 67 : * Filter for paths.
+ 68 : */
+ 69 : struct snapraid_filter {
+ 70 : char pattern[PATH_MAX]; /**< Filter pattern. */
+ 71 : int is_disk; /**< If the pattern is a disk one. */
+ 72 : int is_path; /**< If the pattern is only for the complete path. */
+ 73 : int is_dir; /**< If the pattern is only for dir. */
+ 74 : int direction; /**< If it's an inclusion (=1) or an exclusion (=-1). */
+ 75 : tommy_node node; /**< Next node in the list. */
+ 76 : };
77 :
78 : /**
- 79 : * This block is an empty one.
- 80 : * Note that an empty block is represent with ::BLOCK_EMPTY.
- 81 : */
- 82 : #define BLOCK_STATE_EMPTY 0
- 83 :
- 84 : /**
- 85 : * The block has both the hash and the parity computed.
- 86 : * This is the normal state of a saved block.
- 87 : *
- 88 : * The block hash field IS set.
- 89 : * The parity for this disk is updated.
- 90 : */
- 91 : #define BLOCK_STATE_BLK 1
- 92 :
- 93 : /**
- 94 : * The block is new and not yet hashed.
- 95 : * This happens when a new block overwrite a just removed block, or an empty space.
- 96 : *
- 97 : * The block hash field MAY be set and it represents the hash of the OLD data.
- 98 : * The hash may be also INVALID or ZERO.
- 99 : *
- 100 : * If the OLD block was empty, the hash is set to the special ZERO value.
- 101 : * If the OLD block was lost, the hash is set to the special INVALID value.
- 102 : *
- 103 : * The parity for this disk is not updated, but it contains the old data referenced by the hash.
+ 79 : * Block pointer used to represent unused blocks.
+ 80 : */
+ 81 : #define BLOCK_EMPTY 0
+ 82 :
+ 83 : /**
+ 84 : * This block is an empty one.
+ 85 : * Note that an empty block is represent with ::BLOCK_EMPTY.
+ 86 : */
+ 87 : #define BLOCK_STATE_EMPTY 0
+ 88 :
+ 89 : /**
+ 90 : * The block has both the hash and the parity computed.
+ 91 : * This is the normal state of a saved block.
+ 92 : *
+ 93 : * The block hash field IS set.
+ 94 : * The parity for this disk is updated.
+ 95 : */
+ 96 : #define BLOCK_STATE_BLK 1
+ 97 :
+ 98 : /**
+ 99 : * The block is new and not yet hashed.
+ 100 : * This happens when a new block overwrite a just removed block, or an empty space.
+ 101 : *
+ 102 : * The block hash field MAY be set and it represents the hash of the OLD data.
+ 103 : * The hash may be also INVALID or ZERO.
104 : *
- 105 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the
- 106 : * data used to compute the parity, because the sync process was interrupted at an unknown point,
- 107 : * and the parity may or may not be updated.
- 108 : *
- 109 : * For this reson we clear all such hashes when reading the state from an incomplete sync before
- 110 : * starting a new sync, because sync is affected by such hashes, as sync updates the parity, only
- 111 : * if the new data read for CHG blocks has a mismatching hash.
- 112 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
- 113 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced
- 114 : * hashes, and scrub ignores CHG/DELETED blocks.
- 115 : */
- 116 : #define BLOCK_STATE_CHG 2
- 117 :
- 118 : /**
- 119 : * The block is new and hashed.
- 120 : * This happens when a new block overwrite a just removed block, or an empty space.
- 121 : *
- 122 : * Note that when the file copy heuristic is enabled, the REP blocks may be set
- 123 : * using this euristic, meaning that the hash may be wrong.
- 124 : *
- 125 : * For this reason, when the ::force_nocopy flag is enabled in sync, we convert all the REP blocks
- 126 : * to CHG, invalidating the stored hash.
- 127 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
- 128 : * No clearing is done in other commands, as they don't stop the process like in sync
- 129 : * when there is a false silent error.
- 130 : *
- 131 : * The block hash field IS set, and it represents the hash of the new data.
- 132 : * The parity for this disk is not updated.
- 133 : */
- 134 : #define BLOCK_STATE_REP 3
- 135 :
- 136 : /**
- 137 : * This block is a deleted one.
- 138 : * This happens when a file is deleted.
- 139 : *
- 140 : * The block hash field IS set, and it represents the hash of the previous data,
- 141 : * but only if it's different by all 0.
- 142 : * The parity for this disk is not updated, but it contains the old data referenced by the hash.
- 143 : *
- 144 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the
- 145 : * data used to compute the parity, because the sync process was interrupted at an unknown point,
- 146 : * and the parity may or may not be updated.
- 147 : *
- 148 : * A now the sync process is not affected by DELETED hash, so clearing won't be really needed,
- 149 : * but considering that we have to do it for CHG blocks, we do it also for DELETED ones,
- 150 : * clearing all the past hashes.
- 151 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
- 152 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced
- 153 : * hashes, and scrub ignores CHG/DELETED blocks.
- 154 : */
- 155 : #define BLOCK_STATE_DELETED 4
- 156 :
- 157 : /**
- 158 : * Block of a file.
+ 105 : * If the OLD block was empty, the hash is set to the special ZERO value.
+ 106 : * If the OLD block was lost, the hash is set to the special INVALID value.
+ 107 : *
+ 108 : * The parity for this disk is not updated, but it contains the old data referenced by the hash.
+ 109 : *
+ 110 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the
+ 111 : * data used to compute the parity, because the sync process was interrupted at an unknown point,
+ 112 : * and the parity may or may not be updated.
+ 113 : *
+ 114 : * For this reason we clear all such hashes when reading the state from an incomplete sync before
+ 115 : * starting a new sync, because sync is affected by such hashes, as sync updates the parity, only
+ 116 : * if the new data read for CHG blocks has a mismatching hash.
+ 117 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
+ 118 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced
+ 119 : * hashes, and scrub ignores CHG/DELETED blocks.
+ 120 : */
+ 121 : #define BLOCK_STATE_CHG 2
+ 122 :
+ 123 : /**
+ 124 : * The block is new and hashed.
+ 125 : * This happens when a new block overwrite a just removed block, or an empty space.
+ 126 : *
+ 127 : * Note that when the file copy heuristic is enabled, the REP blocks may be set
+ 128 : * using this heuristic, meaning that the hash may be wrong.
+ 129 : *
+ 130 : * For this reason, when the ::force_nocopy flag is enabled in sync, we convert all the REP blocks
+ 131 : * to CHG, invalidating the stored hash.
+ 132 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
+ 133 : * No clearing is done in other commands, as they don't stop the process like in sync
+ 134 : * when there is a false silent error.
+ 135 : *
+ 136 : * The block hash field IS set, and it represents the hash of the new data.
+ 137 : * The parity for this disk is not updated.
+ 138 : */
+ 139 : #define BLOCK_STATE_REP 3
+ 140 :
+ 141 : /**
+ 142 : * This block is a deleted one.
+ 143 : * This happens when a file is deleted.
+ 144 : *
+ 145 : * The block hash field IS set, and it represents the hash of the previous data,
+ 146 : * but only if it's different by all 0.
+ 147 : * The parity for this disk is not updated, but it contains the old data referenced by the hash.
+ 148 : *
+ 149 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the
+ 150 : * data used to compute the parity, because the sync process was interrupted at an unknown point,
+ 151 : * and the parity may or may not be updated.
+ 152 : *
+ 153 : * A now the sync process is not affected by DELETED hash, so clearing won't be really needed,
+ 154 : * but considering that we have to do it for CHG blocks, we do it also for DELETED ones,
+ 155 : * clearing all the past hashes.
+ 156 : * Clearing is done setting the ::clear_past_hash flag before reading the state.
+ 157 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced
+ 158 : * hashes, and scrub ignores CHG/DELETED blocks.
159 : */
- 160 : struct snapraid_block {
- 161 : unsigned char hash[HASH_SIZE]; /**< Hash of the block. */
- 162 : unsigned char state; /**< State of the block. */
- 163 : };
- 164 :
- 165 : /**
- 166 : * If a file is present in the disk.
- 167 : * It's used only in scan to detect present and missing files.
- 168 : */
- 169 : #define FILE_IS_PRESENT 0x01
- 170 :
- 171 : /**
- 172 : * If it's an excluded file from the processing.
- 173 : * It's used in both check and fix to mark files to exclude from the processing.
- 174 : */
- 175 : #define FILE_IS_EXCLUDED 0x02
- 176 :
- 177 : /**
- 178 : * If a fix was attempted but it failed.
- 179 : * It's used only in fix to mark that some data is unrecoverable.
- 180 : */
- 181 : #define FILE_IS_DAMAGED 0x04
- 182 :
- 183 : /**
- 184 : * If a fix was done.
- 185 : * It's used only in fix to mark that some data was recovered.
- 186 : */
- 187 : #define FILE_IS_FIXED 0x08
- 188 :
- 189 : /**
- 190 : * If the file was originally missing, and it was created in the fix process.
- 191 : * It's used only in fix to mark files recovered from scratch,
- 192 : * meaning that they don't have any previous content.
- 193 : * This is important because it means that deleting them, you are not going
- 194 : * to lose something that cannot be recovered.
- 195 : * Note that excluded files won't ever get this flag.
- 196 : */
- 197 : #define FILE_IS_CREATED 0x10
- 198 :
- 199 : /**
- 200 : * If the file has completed its processing, meaning that it won't be opened anymore.
- 201 : * It's used only in fix to mark when we finish processing one file.
- 202 : * Note that excluded files won't ever get this flag.
- 203 : */
- 204 : #define FILE_IS_FINISHED 0x20
- 205 :
- 206 : /**
- 207 : * If the file hash was obtained from a file copy
- 208 : * identified by the same name, size and stamp.
- 209 : */
- 210 : #define FILE_IS_COPY 0x40
- 211 :
- 212 : /**
- 213 : * If the file was opened.
- 214 : * It's used in fix to detect if it's the first time a file is opened.
- 215 : */
- 216 : #define FILE_IS_OPENED 0x80
- 217 :
- 218 : /**
- 219 : * If the file is modified from the latest sync.
- 220 : * It's used in fix to store if the state of the file before being modified.
- 221 : */
- 222 : #define FILE_IS_UNSYNCED 0x100
- 223 :
- 224 : /**
- 225 : * If the file is without inode.
- 226 : * It could happen in filesystem where inodes are not persistent,
- 227 : * or when restoring a full disk with "fix".
- 228 : * In such cases we have to clear any stored duplicate inode.
- 229 : * After the scan process completes, no file should have this flag set.
- 230 : */
- 231 : #define FILE_IS_WITHOUT_INODE 0x200
- 232 :
- 233 : /**
- 234 : * The file is deleted.
- 235 : * This happens when a file is deleted from the array,
- 236 : * but it's keep inside the parity until the next sync.
- 237 : *
- 238 : * During the filesystem check we needs this information,
- 239 : * because deleted files may be present only partially.
- 240 : */
- 241 : #define FILE_IS_DELETED 0x400
- 242 :
- 243 : /**
- 244 : * The file is missing.
- 245 : * This happens in fix/check when a file is cannot be opened,
- 246 : * and marking it as such prevents to retry to open it again.
- 247 : */
- 248 : #define FILE_IS_MISSING 0x800
- 249 :
- 250 : #define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */
- 251 : #define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */
- 252 : #define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */
- 253 : #define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */
- 254 : #define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */
- 255 :
- 256 : /**
- 257 : * File.
- 258 : */
- 259 : struct snapraid_file {
- 260 : int64_t mtime_sec; /**< Modification time. */
- 261 : uint64_t inode; /**< Inode. */
- 262 : uint64_t physical; /**< Physical offset of the file. */
- 263 : data_off_t size; /**< Size of the file. */
- 264 : struct snapraid_block* blockvec; /**< All the blocks of the file. */
- 265 : int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */
- 266 : block_off_t blockmax; /**< Number of blocks. */
- 267 : unsigned flag; /**< FILE_IS_* flags. */
- 268 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
- 269 :
- 270 : /* nodes for data structures */
- 271 : tommy_node nodelist;
- 272 : tommy_hashdyn_node nodeset;
- 273 : tommy_hashdyn_node pathset;
- 274 : tommy_hashdyn_node stampset;
- 275 : };
- 276 :
- 277 : /**
- 278 : * Symbolic Link.
- 279 : */
- 280 : struct snapraid_link {
- 281 : unsigned flag; /**< FILE_IS_* flags. */
- 282 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
- 283 : char* linkto; /**< Link to. */
- 284 :
- 285 : /* nodes for data structures */
- 286 : tommy_node nodelist;
- 287 : tommy_hashdyn_node nodeset;
- 288 : };
+ 160 : #define BLOCK_STATE_DELETED 4
+ 161 :
+ 162 : /**
+ 163 : * Block of a file.
+ 164 : */
+ 165 : struct snapraid_block {
+ 166 : unsigned char hash[HASH_SIZE]; /**< Hash of the block. */
+ 167 : unsigned char state; /**< State of the block. */
+ 168 : };
+ 169 :
+ 170 : /**
+ 171 : * If a file is present in the disk.
+ 172 : * It's used only in scan to detect present and missing files.
+ 173 : */
+ 174 : #define FILE_IS_PRESENT 0x01
+ 175 :
+ 176 : /**
+ 177 : * If it's an excluded file from the processing.
+ 178 : * It's used in both check and fix to mark files to exclude from the processing.
+ 179 : */
+ 180 : #define FILE_IS_EXCLUDED 0x02
+ 181 :
+ 182 : /**
+ 183 : * If a fix was attempted but it failed.
+ 184 : * It's used only in fix to mark that some data is unrecoverable.
+ 185 : */
+ 186 : #define FILE_IS_DAMAGED 0x04
+ 187 :
+ 188 : /**
+ 189 : * If a fix was done.
+ 190 : * It's used only in fix to mark that some data was recovered.
+ 191 : */
+ 192 : #define FILE_IS_FIXED 0x08
+ 193 :
+ 194 : /**
+ 195 : * If the file was originally missing, and it was created in the fix process.
+ 196 : * It's used only in fix to mark files recovered from scratch,
+ 197 : * meaning that they don't have any previous content.
+ 198 : * This is important because it means that deleting them, you are not going
+ 199 : * to lose something that cannot be recovered.
+ 200 : * Note that excluded files won't ever get this flag.
+ 201 : */
+ 202 : #define FILE_IS_CREATED 0x10
+ 203 :
+ 204 : /**
+ 205 : * If the file has completed its processing, meaning that it won't be opened anymore.
+ 206 : * It's used only in fix to mark when we finish processing one file.
+ 207 : * Note that excluded files won't ever get this flag.
+ 208 : */
+ 209 : #define FILE_IS_FINISHED 0x20
+ 210 :
+ 211 : /**
+ 212 : * If the file hash was obtained from a file copy
+ 213 : * identified by the same name, size and stamp.
+ 214 : */
+ 215 : #define FILE_IS_COPY 0x40
+ 216 :
+ 217 : /**
+ 218 : * If the file was opened.
+ 219 : * It's used in fix to detect if it's the first time a file is opened.
+ 220 : */
+ 221 : #define FILE_IS_OPENED 0x80
+ 222 :
+ 223 : /**
+ 224 : * If the file is modified from the latest sync.
+ 225 : * It's used in fix to store if the state of the file before being modified.
+ 226 : */
+ 227 : #define FILE_IS_UNSYNCED 0x100
+ 228 :
+ 229 : /**
+ 230 : * If the file is without inode.
+ 231 : * It could happen in file-system where inodes are not persistent,
+ 232 : * or when restoring a full disk with "fix".
+ 233 : * In such cases we have to clear any stored duplicate inode.
+ 234 : * After the scan process completes, no file should have this flag set.
+ 235 : */
+ 236 : #define FILE_IS_WITHOUT_INODE 0x200
+ 237 :
+ 238 : /**
+ 239 : * The file is deleted.
+ 240 : * This happens when a file is deleted from the array,
+ 241 : * but it's keep inside the parity until the next sync.
+ 242 : *
+ 243 : * During the file-system check we needs this information,
+ 244 : * because deleted files may be present only partially.
+ 245 : */
+ 246 : #define FILE_IS_DELETED 0x400
+ 247 :
+ 248 : /**
+ 249 : * The file is missing.
+ 250 : * This happens in fix/check when a file is cannot be opened,
+ 251 : * and marking it as such prevents to retry to open it again.
+ 252 : */
+ 253 : #define FILE_IS_MISSING 0x800
+ 254 :
+ 255 : #define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */
+ 256 : #define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */
+ 257 : #define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */
+ 258 : #define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */
+ 259 : #define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */
+ 260 :
+ 261 : /**
+ 262 : * File.
+ 263 : */
+ 264 : struct snapraid_file {
+ 265 : int64_t mtime_sec; /**< Modification time. */
+ 266 : uint64_t inode; /**< Inode. */
+ 267 : uint64_t physical; /**< Physical offset of the file. */
+ 268 : data_off_t size; /**< Size of the file. */
+ 269 : struct snapraid_block* blockvec; /**< All the blocks of the file. */
+ 270 : int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */
+ 271 : block_off_t blockmax; /**< Number of blocks. */
+ 272 : unsigned flag; /**< FILE_IS_* flags. */
+ 273 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
+ 274 :
+ 275 : /* nodes for data structures */
+ 276 : tommy_node nodelist;
+ 277 : tommy_hashdyn_node nodeset;
+ 278 : tommy_hashdyn_node pathset;
+ 279 : tommy_hashdyn_node stampset;
+ 280 : };
+ 281 :
+ 282 : /**
+ 283 : * Symbolic Link.
+ 284 : */
+ 285 : struct snapraid_link {
+ 286 : unsigned flag; /**< FILE_IS_* flags. */
+ 287 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
+ 288 : char* linkto; /**< Link to. */
289 :
- 290 : /**
- 291 : * Dir.
- 292 : */
- 293 : struct snapraid_dir {
- 294 : unsigned flag; /**< FILE_IS_* flags. */
- 295 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
- 296 :
- 297 : /* nodes for data structures */
- 298 : tommy_node nodelist;
- 299 : tommy_hashdyn_node nodeset;
- 300 : };
+ 290 : /* nodes for data structures */
+ 291 : tommy_node nodelist;
+ 292 : tommy_hashdyn_node nodeset;
+ 293 : };
+ 294 :
+ 295 : /**
+ 296 : * Dir.
+ 297 : */
+ 298 : struct snapraid_dir {
+ 299 : unsigned flag; /**< FILE_IS_* flags. */
+ 300 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */
301 :
- 302 : /**
- 303 : * Chunk.
- 304 : *
- 305 : * A chunk represents a fragment of a file mapped into the parity.
- 306 : */
- 307 : struct snapraid_chunk {
- 308 : struct snapraid_file* file; /* File containing this chunk. */
- 309 : block_off_t parity_pos; /**< Parity position. */
- 310 : block_off_t file_pos; /**< Position in the file. */
- 311 : block_off_t count; /**< Number of sequential blocks in the file and parity. */
- 312 : tommy_tree_node parity_node; /**< Tree sorted by <parity_pos>. */
- 313 : tommy_tree_node file_node; /**< Tree sorter by <file,file_pos>. */
- 314 : };
- 315 :
- 316 : /**
- 317 : * Disk.
- 318 : */
- 319 : struct snapraid_disk {
- 320 : char name[PATH_MAX]; /**< Name of the disk. */
- 321 : char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */
- 322 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
- 323 : uint64_t device; /**< Device identifier. */
- 324 : uint64_t tick; /**< Usage time of the disk. */
- 325 : block_off_t total_blocks; /**< Number of total blocks. */
- 326 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */
- 327 :
- 328 : /**
- 329 : * First free searching block.
- 330 : * Note that it doesn't necessarely point at the first free block,
- 331 : * but it just tell you that no free block is present before this position.
- 332 : */
- 333 : block_off_t first_free_block;
+ 302 : /* nodes for data structures */
+ 303 : tommy_node nodelist;
+ 304 : tommy_hashdyn_node nodeset;
+ 305 : };
+ 306 :
+ 307 : /**
+ 308 : * Chunk.
+ 309 : *
+ 310 : * A chunk represents a fragment of a file mapped into the parity.
+ 311 : */
+ 312 : struct snapraid_chunk {
+ 313 : struct snapraid_file* file; /**< File containing this chunk. */
+ 314 : block_off_t parity_pos; /**< Parity position. */
+ 315 : block_off_t file_pos; /**< Position in the file. */
+ 316 : block_off_t count; /**< Number of sequential blocks in the file and parity. */
+ 317 : tommy_tree_node parity_node; /**< Tree sorted by <parity_pos>. */
+ 318 : tommy_tree_node file_node; /**< Tree sorter by <file,file_pos>. */
+ 319 : };
+ 320 :
+ 321 : /**
+ 322 : * Disk.
+ 323 : */
+ 324 : struct snapraid_disk {
+ 325 : char name[PATH_MAX]; /**< Name of the disk. */
+ 326 : char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */
+ 327 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
+ 328 : char uuid[UUID_MAX]; /**< UUID of the disk. */
+ 329 :
+ 330 : uint64_t device; /**< Device identifier. */
+ 331 : uint64_t tick; /**< Usage time of the disk. */
+ 332 : block_off_t total_blocks; /**< Number of total blocks. */
+ 333 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */
334 :
- 335 : int has_volatile_inodes; /**< If the underline filesystem has not persistent inodes. */
- 336 : int has_unreliable_physical; /**< If the physical offset of files has duplicates. */
- 337 : int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same filesystem. */
- 338 : int has_unsupported_uuid; /**< If the disk doesn't report UUID, meaning it's not supported. */
- 339 : int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */
- 340 : int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */
- 341 : int skip_access; /**< If the disk is unaccessible and it should be skipped. */
- 342 :
- 343 : /**
- 344 : * Mapping of chunks in the parity.
- 345 : * Sorted by <parity_pos> and by <file,file_pos>
- 346 : */
- 347 : tommy_tree fs_parity;
- 348 : tommy_tree fs_file;
+ 335 : /**
+ 336 : * First free searching block.
+ 337 : * Note that it doesn't necessarily point at the first free block,
+ 338 : * but it just tell you that no free block is present before this position.
+ 339 : */
+ 340 : block_off_t first_free_block;
+ 341 :
+ 342 : int has_volatile_inodes; /**< If the underline file-system has not persistent inodes. */
+ 343 : int has_unreliable_physical; /**< If the physical offset of files has duplicates. */
+ 344 : int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same file-system. */
+ 345 : int has_unsupported_uuid; /**< If the disk doesn't report UUID, meaning it's not supported. */
+ 346 : int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */
+ 347 : int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */
+ 348 : int skip_access; /**< If the disk is inaccessible and it should be skipped. */
349 :
350 : /**
- 351 : * Last chunk we accessed.
- 352 : * It's used to optimize access of sequential blocks.
+ 351 : * Mapping of chunks in the parity.
+ 352 : * Sorted by <parity_pos> and by <file,file_pos>
353 : */
- 354 : struct snapraid_chunk* fs_last;
- 355 :
- 356 : /**
- 357 : * List of all the snapraid_file for the disk.
- 358 : */
- 359 : tommy_list filelist;
- 360 :
- 361 : /**
- 362 : * List of all the deleted file for the disk.
- 363 : *
- 364 : * These files are kept allocated, because the blocks are still referenced in
- 365 : * the ::blockarr.
- 366 : */
- 367 : tommy_list deletedlist;
- 368 :
- 369 : tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */
- 370 : tommy_hashdyn pathset; /**< Hashtable by path of all the files. */
- 371 : tommy_hashdyn stampset; /**< Hashtable by stamp (size and time) of all the files. */
- 372 : tommy_list linklist; /**< List of all the links. */
- 373 : tommy_hashdyn linkset; /**< Hashtable by name of all the links. */
- 374 : tommy_list dirlist; /**< List of all the dirs. */
- 375 : tommy_hashdyn dirset; /**< Hashtable by name of all the dirs. */
- 376 :
- 377 : /* nodes for data structures */
- 378 : tommy_node node;
- 379 : };
- 380 :
- 381 : /**
- 382 : * Max UUID length.
- 383 : */
- 384 : #define UUID_MAX 128
- 385 :
- 386 : /**
- 387 : * Disk mapping.
- 388 : */
- 389 : struct snapraid_map {
- 390 : char name[PATH_MAX]; /**< Name of the disk. */
- 391 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */
- 392 : block_off_t total_blocks; /**< Number of total blocks. */
- 393 : block_off_t free_blocks; /**< Number of free blocks at last 'sync'. */
- 394 : unsigned position; /**< Position of the disk in the parity. */
- 395 :
- 396 : /* nodes for data structures */
- 397 : tommy_node node;
- 398 : };
- 399 :
- 400 : /**
- 401 : * Parity.
- 402 : */
- 403 : struct snapraid_parity {
- 404 : char path[PATH_MAX]; /**< Path of the parity file. */
- 405 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */
- 406 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
- 407 : uint64_t device; /**< Device identifier of the parity. */
- 408 : block_off_t total_blocks; /**< Number of total blocks. */
- 409 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */
- 410 : int skip_access; /**< If the disk is unaccessible and it should be skipped. */
- 411 : int is_excluded; /**< If the parity is excluded by disk filter. */
- 412 :
- 413 : /**
- 414 : * Cumulative time used for parity disks.
- 415 : */
- 416 : uint64_t tick;
- 417 : };
- 418 :
- 419 : /**
- 420 : * Info.
- 421 : */
- 422 : typedef uint32_t snapraid_info;
- 423 :
- 424 : /**
- 425 : * Allocate a content.
- 426 : */
- 427 : struct snapraid_content* content_alloc(const char* path, uint64_t dev);
- 428 :
- 429 : /**
- 430 : * Deallocate a content.
- 431 : */
- 432 : void content_free(struct snapraid_content* content);
- 433 :
- 434 : /**
- 435 : * Allocate a filter pattern for files and directories.
- 436 : */
- 437 : struct snapraid_filter* filter_alloc_file(int is_include, const char* pattern);
- 438 :
- 439 : /**
- 440 : * Allocate a filter pattern for disks.
- 441 : */
- 442 : struct snapraid_filter* filter_alloc_disk(int is_include, const char* pattern);
- 443 :
- 444 : /**
- 445 : * Deallocate an exclusion.
- 446 : */
- 447 : void filter_free(struct snapraid_filter* filter);
- 448 :
- 449 : /**
- 450 : * Filter type description.
- 451 : */
- 452 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size);
- 453 :
- 454 : /**
- 455 : * Filter hidden files.
- 456 : * Return !=0 if it matches and it should be excluded.
- 457 : */
- 458 3066852 : static inline int filter_hidden(int enable, struct dirent* dd)
- 459 : {
- 460 3066852 : if (enable && dirent_hidden(dd)) {
- 461 0 : return 1; /* filter out */
- 462 : }
- 463 :
- 464 3066852 : return 0;
- 465 : }
- 466 :
- 467 : /**
- 468 : * Filter a path using a list of filters.
- 469 : * For each element of the path all the filters are applied, until the first one that matches.
- 470 : * Return !=0 if it should be excluded.
- 471 : */
- 472 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub);
- 473 :
- 474 : /**
- 475 : * Filter a file/link/dir if missing.
- 476 : * This call imply a disk check for the file presence.
- 477 : * Return !=0 if the file is present and it should be excluded.
- 478 : */
- 479 : int filter_existence(int filter_missing, const char* dir, const char* sub);
- 480 :
- 481 : /**
- 482 : * Filter a file if bad.
- 483 : * Return !=0 if the file is correct and it should be excluded.
- 484 : */
- 485 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file);
- 486 :
- 487 : /**
- 488 : * Filter a dir using a list of filters.
- 489 : * For each element of the path all the filters are applied, until the first one that matches.
- 490 : * Return !=0 if should be excluded.
- 491 : */
- 492 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub);
- 493 :
- 494 : /**
- 495 : * Filter a path if it's a content file.
- 496 : * Return !=0 if should be excluded.
- 497 : */
- 498 : int filter_content(tommy_list* contentlist, const char* path);
- 499 :
- 500 : /**
- 501 : * Check if the specified hash is invalid.
- 502 : *
- 503 : * An invalid hash is represented with all bytes at 0x00.
- 504 : */
- 505 776042 : static inline int hash_is_invalid(const unsigned char* hash)
- 506 : {
- 507 : unsigned i;
- 508 :
- 509 1264688 : for (i = 0; i < HASH_SIZE; ++i)
- 510 1234312 : if (hash[i] != 0x00)
- 511 745666 : return 0;
- 512 :
- 513 30376 : return 1;
- 514 : }
- 515 :
- 516 : /**
- 517 : * Check if the specified hash represent the zero block.
- 518 : *
- 519 : * A zero hash is represented with all bytes at 0xFF.
- 520 : */
- 521 790275 : static inline int hash_is_zero(const unsigned char* hash)
- 522 : {
- 523 : unsigned i;
- 524 :
- 525 1835799 : for (i = 0; i < HASH_SIZE; ++i)
- 526 1770619 : if (hash[i] != 0xFF)
- 527 725095 : return 0;
- 528 :
- 529 65180 : return 1;
- 530 : }
- 531 :
- 532 : /**
- 533 : * Check if the specified hash is a real hash.
- 534 : */
- 535 65785 : static inline int hash_is_real(const unsigned char* hash)
- 536 : {
- 537 65785 : return !hash_is_zero(hash) && !hash_is_invalid(hash);
- 538 : }
- 539 :
- 540 : /**
- 541 : * Set the hash to the special INVALID value.
- 542 : */
- 543 8910831 : static inline void hash_invalid_set(unsigned char* hash)
- 544 : {
- 545 8910831 : memset(hash, 0x00, HASH_SIZE);
- 546 8910831 : }
- 547 :
- 548 : /**
- 549 : * Set the hash to the special ZERO value.
- 550 : */
- 551 153288 : static inline void hash_zero_set(unsigned char* hash)
- 552 : {
- 553 153288 : memset(hash, 0xFF, HASH_SIZE);
- 554 153288 : }
- 555 :
- 556 : /**
- 557 : * Get the state of the block.
- 558 : *
- 559 : * For this function, it's allowed to pass a NULL block
- 560 : * pointer than results in the BLOCK_STATE_EMPTY state.
- 561 : */
- 562 96735410 : static inline unsigned block_state_get(const struct snapraid_block* block)
- 563 : {
- 564 96735410 : if (block == BLOCK_EMPTY)
- 565 2427201 : return BLOCK_STATE_EMPTY;
- 566 :
- 567 94308209 : return block->state;
- 568 : }
- 569 :
- 570 : /**
- 571 : * Set the state of the block.
- 572 : */
- 573 18242161 : static inline void block_state_set(struct snapraid_block* block, unsigned state)
- 574 : {
- 575 18242161 : block->state = state;
- 576 18242161 : }
- 577 :
- 578 : /**
- 579 : * Check if the specified block has an updated hash.
- 580 : *
- 581 : * Note that EMPTY / CHG / DELETED return 0.
- 582 : */
- 583 2005171 : static inline int block_has_updated_hash(const struct snapraid_block* block)
- 584 : {
- 585 2005171 : unsigned state = block_state_get(block);
- 586 :
- 587 2005171 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP;
- 588 : }
- 589 :
- 590 : /**
- 591 : * Check if the specified block has a past hash,
- 592 : * i.e. the hash of the data that it's now overwritten or lost.
- 593 : *
- 594 : * Note that EMPTY / BLK / REP return 0.
- 595 : */
- 596 2287366 : static inline int block_has_past_hash(const struct snapraid_block* block)
- 597 : {
- 598 2287366 : unsigned state = block_state_get(block);
- 599 :
- 600 2287366 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED;
- 601 : }
- 602 :
- 603 : /**
- 604 : * Check if the specified block is part of a file.
- 605 : *
- 606 : * Note that EMPTY / DELETED return 0.
- 607 : */
- 608 12929086 : static inline int block_has_file(const struct snapraid_block* block)
- 609 : {
- 610 12929086 : unsigned state = block_state_get(block);
- 611 :
- 612 12929086 : return state == BLOCK_STATE_BLK
- 613 12929086 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
- 614 : }
- 615 :
- 616 : /**
- 617 : * Check if the block has an invalid parity than needs to be updated.
- 618 : *
- 619 : * Note that EMPTY / BLK return 0.
- 620 : */
- 621 11489174 : static inline int block_has_invalid_parity(const struct snapraid_block* block)
- 622 : {
- 623 11489174 : unsigned state = block_state_get(block);
- 624 :
- 625 11489174 : return state == BLOCK_STATE_DELETED
- 626 11489174 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
- 627 : }
- 628 :
- 629 : /**
- 630 : * Check if the block is part of a file with valid parity.
- 631 : *
- 632 : * Note that anything different than BLK return 0.
- 633 : */
- 634 221100 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block)
- 635 : {
- 636 221100 : unsigned state = block_state_get(block);
- 637 :
- 638 221100 : return state == BLOCK_STATE_BLK;
- 639 : }
- 640 :
- 641 33299459 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask)
- 642 : {
- 643 33299459 : return (file->flag & mask) == mask;
- 644 : }
- 645 :
- 646 5176917 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask)
- 647 : {
- 648 5176917 : file->flag |= mask;
- 649 5176917 : }
- 650 :
- 651 14174 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask)
- 652 : {
- 653 14174 : file->flag &= ~mask;
- 654 14174 : }
- 655 :
- 656 : /**
- 657 : * Allocate a file.
- 658 : */
- 659 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical);
- 660 :
- 661 : /**
- 662 : * Duplicate a file.
- 663 : */
- 664 : struct snapraid_file* file_dup(struct snapraid_file* copy);
- 665 :
- 666 : /**
- 667 : * Deallocate a file.
- 668 : */
- 669 : void file_free(struct snapraid_file* file);
- 670 :
- 671 : /**
- 672 : * Rename a file.
- 673 : */
- 674 : void file_rename(struct snapraid_file* file, const char* sub);
- 675 :
- 676 : /**
- 677 : * Copy a file.
- 678 : */
- 679 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file);
- 680 :
- 681 : /**
- 682 : * Return the name of the file, without the dir.
- 683 : */
- 684 : const char* file_name(const struct snapraid_file* file);
- 685 :
- 686 : /**
- 687 : * Check if the block is the last in the file.
- 688 : */
- 689 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos);
- 690 :
- 691 : /**
- 692 : * Get the size in bytes of the block.
- 693 : * If it's the last block of a file it could be less than block_size.
- 694 : */
- 695 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size);
- 696 :
- 697 : /**
- 698 : * Compare a file with an inode.
- 699 : */
- 700 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data);
- 701 :
- 702 : /**
- 703 : * Compare files by inode.
- 704 : */
- 705 : int file_inode_compare(const void* void_a, const void* void_b);
- 706 :
- 707 : /**
- 708 : * Compare files by path.
- 709 : */
- 710 : int file_path_compare(const void* void_a, const void* void_b);
- 711 :
- 712 : /**
- 713 : * Compare files by physical address.
- 714 : */
- 715 : int file_physical_compare(const void* void_a, const void* void_b);
- 716 :
- 717 : /**
- 718 : * Compute the hash of a file inode.
- 719 : */
- 720 4822298 : static inline tommy_uint32_t file_inode_hash(uint64_t inode)
- 721 : {
- 722 4822298 : return (tommy_uint32_t)tommy_inthash_u64(inode);
- 723 : }
- 724 :
- 725 : /**
- 726 : * Compare a file with a path.
- 727 : */
- 728 : int file_path_compare_to_arg(const void* void_arg, const void* void_data);
- 729 :
- 730 : /**
- 731 : * Compare a file with another file for name, stamp, and both.
- 732 : */
- 733 : int file_name_compare(const void* void_a, const void* void_b);
- 734 : int file_stamp_compare(const void* void_a, const void* void_b);
- 735 : int file_namestamp_compare(const void* void_a, const void* void_b);
- 736 : int file_pathstamp_compare(const void* void_a, const void* void_b);
- 737 :
- 738 : /**
- 739 : * Compute the hash of a file path.
- 740 : */
- 741 3766623 : static inline tommy_uint32_t file_path_hash(const char* sub)
- 742 : {
- 743 3766623 : return tommy_hash_u32(0, sub, strlen(sub));
- 744 : }
- 745 :
- 746 : /**
- 747 : * Compute the hash of a file stamp.
- 748 : */
- 749 6139138 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec)
- 750 : {
- 751 6139138 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec)));
- 752 : }
- 753 :
- 754 : /**
- 755 : * Allocate a chunk.
- 756 : */
- 757 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count);
- 758 :
- 759 : /**
- 760 : * Deallocate a chunk.
- 761 : */
- 762 : void chunk_free(struct snapraid_chunk* chunk);
- 763 :
- 764 : /**
- 765 : * Compare chunk by parity position.
- 766 : */
- 767 : int chunk_parity_compare(const void* void_a, const void* void_b);
- 768 :
- 769 : /**
- 770 : * Compare chunk by file and file position.
- 771 : */
- 772 : int chunk_file_compare(const void* void_a, const void* void_b);
- 773 :
- 774 202633 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask)
- 775 : {
- 776 202633 : return (slink->flag & mask) == mask;
- 777 : }
- 778 :
- 779 36114 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask)
- 780 : {
- 781 36114 : slink->flag |= mask;
- 782 36114 : }
- 783 :
- 784 : static inline void link_flag_clear(struct snapraid_link* slink, unsigned mask)
- 785 : {
- 786 : slink->flag &= ~mask;
- 787 : }
- 788 :
- 789 6 : static inline void link_flag_let(struct snapraid_link* slink, unsigned flag, unsigned mask)
- 790 : {
- 791 6 : slink->flag &= ~mask;
- 792 6 : slink->flag |= flag & mask;
- 793 6 : }
- 794 :
- 795 410820 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask)
- 796 : {
- 797 410820 : return slink->flag & mask;
- 798 : }
- 799 :
- 800 : /**
- 801 : * Allocate a link.
- 802 : */
- 803 : struct snapraid_link* link_alloc(const char* name, const char* slink, unsigned link_flag);
- 804 :
- 805 : /**
- 806 : * Deallocate a link.
- 807 : */
- 808 : void link_free(struct snapraid_link* slink);
- 809 :
- 810 : /**
- 811 : * Compare a link with a name.
- 812 : */
- 813 : int link_name_compare_to_arg(const void* void_arg, const void* void_data);
- 814 :
- 815 : /**
- 816 : * Compare links by path.
- 817 : */
- 818 : int link_alpha_compare(const void* void_a, const void* void_b);
- 819 :
- 820 : /**
- 821 : * Compute the hash of a link name.
- 822 : */
- 823 148256 : static inline tommy_uint32_t link_name_hash(const char* name)
- 824 : {
- 825 148256 : return tommy_hash_u32(0, name, strlen(name));
- 826 : }
- 827 :
- 828 876 : static inline int dir_flag_has(const struct snapraid_dir* dir, unsigned mask)
- 829 : {
- 830 876 : return (dir->flag & mask) == mask;
- 831 : }
- 832 :
- 833 235 : static inline void dir_flag_set(struct snapraid_dir* dir, unsigned mask)
- 834 : {
- 835 235 : dir->flag |= mask;
- 836 235 : }
- 837 :
- 838 : static inline void dir_flag_clear(struct snapraid_dir* dir, unsigned mask)
- 839 : {
- 840 : dir->flag &= ~mask;
- 841 : }
- 842 :
- 843 : /**
- 844 : * Allocate a dir.
- 845 : */
- 846 : struct snapraid_dir* dir_alloc(const char* name);
- 847 :
- 848 : /**
- 849 : * Deallocate a dir.
- 850 : */
- 851 : void dir_free(struct snapraid_dir* dir);
- 852 :
- 853 : /**
- 854 : * Compare a dir with a name.
- 855 : */
- 856 : int dir_name_compare(const void* void_arg, const void* void_data);
- 857 :
- 858 : /**
- 859 : * Compute the hash of a dir name.
- 860 : */
- 861 987 : static inline tommy_uint32_t dir_name_hash(const char* name)
- 862 : {
- 863 987 : return tommy_hash_u32(0, name, strlen(name));
- 864 : }
- 865 :
- 866 : /**
- 867 : * Allocate a disk.
- 868 : */
- 869 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip);
- 870 :
- 871 : /**
- 872 : * Deallocate a disk.
- 873 : */
- 874 : void disk_free(struct snapraid_disk* disk);
- 875 :
- 876 : /**
- 877 : * Get the size of the disk in blocks.
- 878 : */
- 879 : block_off_t disk_size(struct snapraid_disk* disk);
- 880 :
- 881 : /**
- 882 : * Check if a disk is totally empty and can be discarded from the content file.
- 883 : * A disk is empty if it doesn't contain any file, symlink, hardlink or dir
- 884 : * and without any DELETED block.
- 885 : * The blockmax is used to limit the search of DELETED block up to blockmax.
- 886 : */
- 887 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax);
- 888 :
- 889 : /**
- 890 : * Check the filesystem for errors.
- 891 : * Return 0 if it's OK.
- 892 : */
- 893 : int fs_check(struct snapraid_disk* disk);
- 894 :
- 895 : /**
- 896 : * Allocate a parity position for the specified file position.
- 897 : *
- 898 : * After this call you can use the par2file/par2block operations
- 899 : * to query the relation.
- 900 : *
- 901 : * \note This function is NOT thread-safe as it uses the the disk cache. +
- 902 : */
- 903 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos);
- 904 :
- 905 : /**
- 906 : * Deallocate the parity position.
- 907 : *
- 908 : * After this call the par2file/par2block operations
- 909 : * won't find anymore the parity association.
- 910 : *
- 911 : * \note This function is NOT thread-safe as it uses the the disk cache.
- 912 : */
- 913 : void fs_deallocate(struct snapraid_disk* disk, block_off_t pos);
- 914 :
- 915 : /**
- 916 : * Get the block from the file position.
- 917 : */
- 918 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos);
- 919 :
- 920 : /**
- 921 : * Like fs_file2par_get() but thread-safe.
- 922 : */
- 923 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos);
- 924 :
- 925 : /**
- 926 : * Get the file position from the parity position.
- 927 : * Return 0 if no file is using it.
- 928 : * \note This function is NOT thread-safe as it uses the the disk cache.
- 929 : */
- 930 11514087 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
- 931 : {
- 932 11514087 : return fs_par2file_get_ts(disk, &disk->fs_last, parity_pos, file_pos);
- 933 : }
- 934 :
- 935 : /**
- 936 : * Like fs_file2par_get() but thread-safe.
- 937 : */
- 938 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos);
- 939 :
- 940 : /**
- 941 : * Get the parity position from the file position.
- 942 : * \note This function is NOT thread-safe as it uses the the disk cache.
- 943 : */
- 944 464306 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
- 945 : {
- 946 464306 : return fs_file2par_get_ts(disk, &disk->fs_last, file, file_pos);
- 947 : }
- 948 :
- 949 : /**
- 950 : * Like fs_par2block_get() but thread-safe.
- 951 : */
- 952 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos);
- 953 :
- 954 : /**
- 955 : * Get the block from the parity position.
- 956 : * Return BLOCK_EMPTY==0 if the block is over the end of the disk or not used.
- 957 : * \note This function is NOT thread-safe as it uses the the disk cache.
- 958 : */
- 959 21727310 : static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk, block_off_t parity_pos)
- 960 : {
- 961 21727310 : return fs_par2block_get_ts(disk, &disk->fs_last, parity_pos);
- 962 : }
- 963 :
- 964 : /**
- 965 : * Allocate a disk mapping.
- 966 : * Uses uuid="" if not available.
- 967 : */
- 968 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid);
- 969 :
- 970 : /**
- 971 : * Deallocate a disk mapping.
- 972 : */
- 973 : void map_free(struct snapraid_map* map);
- 974 :
- 975 : /**
- 976 : * Mask used to store additional information in the info bits.
- 977 : *
- 978 : * These bits reduce the granurality of the time in the memory representation.
- 979 : */
- 980 : #define INFO_MASK 0x7
- 981 :
- 982 : /**
- 983 : * Make an info.
- 984 : */
- 985 394996 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced)
- 986 : {
- 987 : /* clear the lowest bits as reserved for other information */
- 988 394996 : snapraid_info info = last_access & ~INFO_MASK;
- 989 :
- 990 394996 : if (error != 0)
- 991 5460 : info |= 0x1;
- 992 394996 : if (rehash != 0)
- 993 127410 : info |= 0x2;
- 994 394996 : if (justsynced != 0)
- 995 226412 : info |= 0x4;
- 996 394996 : return info;
- 997 : }
- 998 :
- 999 : /**
- 1000 : * Extract the time information.
- 1001 : * This is the last time when the block was know to be correct.
- 1002 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub.
- 1003 : */
- 1004 2258078 : static inline time_t info_get_time(snapraid_info info)
- 1005 : {
- 1006 2258078 : return info & ~INFO_MASK;
- 1007 : }
- 1008 :
- 1009 : /**
- 1010 : * Extract the error information.
- 1011 : * Report if the block address had some problem.
- 1012 : */
- 1013 1725704 : static inline int info_get_bad(snapraid_info info)
- 1014 : {
- 1015 1725704 : return (info & 0x1) != 0;
- 1016 : }
- 1017 :
- 1018 : /**
- 1019 : * Extract the rehash information.
- 1020 : * Report if the block address is using the old hash and needs to be rehashed.
- 1021 : */
- 1022 3312725 : static inline int info_get_rehash(snapraid_info info)
- 1023 : {
- 1024 3312725 : return (info & 0x2) != 0;
- 1025 : }
- 1026 :
- 1027 : /**
- 1028 : * Extract the scrubbed information.
- 1029 : * Report if the block address was never scrubbed.
- 1030 : */
- 1031 1474627 : static inline int info_get_justsynced(snapraid_info info)
- 1032 : {
- 1033 1474627 : return (info & 0x4) != 0;
- 1034 : }
- 1035 :
- 1036 : /**
- 1037 : * Mark the block address as with error.
- 1038 : */
- 1039 1802 : static inline snapraid_info info_set_bad(snapraid_info info)
- 1040 : {
- 1041 1802 : return info | 0x1;
- 1042 : }
- 1043 :
- 1044 : /**
- 1045 : * Mark the block address as with rehash.
- 1046 : */
- 1047 9199 : static inline snapraid_info info_set_rehash(snapraid_info info)
- 1048 : {
- 1049 9199 : return info | 0x2;
- 1050 : }
- 1051 :
- 1052 : /**
- 1053 : * Set the info at the specified position.
- 1054 : * The position is allocated if not yet done.
- 1055 : */
- 1056 1609485 : static inline void info_set(tommy_arrayblkof* array, unsigned pos, snapraid_info info)
- 1057 : {
- 1058 1609485 : tommy_arrayblkof_grow(array, pos + 1);
- 1059 :
- 1060 1609485 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info));
- 1061 1609485 : }
- 1062 :
- 1063 : /**
- 1064 : * Get the info at the specified position.
- 1065 : * For not allocated position, 0 is returned.
- 1066 : */
- 1067 10573034 : static inline snapraid_info info_get(tommy_arrayblkof* array, unsigned pos)
- 1068 : {
- 1069 : snapraid_info info;
- 1070 :
- 1071 10573034 : if (pos >= tommy_arrayblkof_size(array))
- 1072 474047 : return 0;
- 1073 :
- 1074 10073489 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info));
+ 354 : tommy_tree fs_parity;
+ 355 : tommy_tree fs_file;
+ 356 :
+ 357 : /**
+ 358 : * Last chunk we accessed.
+ 359 : * It's used to optimize access of sequential blocks.
+ 360 : */
+ 361 : struct snapraid_chunk* fs_last;
+ 362 :
+ 363 : /**
+ 364 : * List of all the snapraid_file for the disk.
+ 365 : */
+ 366 : tommy_list filelist;
+ 367 :
+ 368 : /**
+ 369 : * List of all the deleted file for the disk.
+ 370 : *
+ 371 : * These files are kept allocated, because the blocks are still referenced in
+ 372 : * the ::blockarr.
+ 373 : */
+ 374 : tommy_list deletedlist;
+ 375 :
+ 376 : tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */
+ 377 : tommy_hashdyn pathset; /**< Hashtable by path of all the files. */
+ 378 : tommy_hashdyn stampset; /**< Hashtable by stamp (size and time) of all the files. */
+ 379 : tommy_list linklist; /**< List of all the links. */
+ 380 : tommy_hashdyn linkset; /**< Hashtable by name of all the links. */
+ 381 : tommy_list dirlist; /**< List of all the dirs. */
+ 382 : tommy_hashdyn dirset; /**< Hashtable by name of all the dirs. */
+ 383 :
+ 384 : /* nodes for data structures */
+ 385 : tommy_node node;
+ 386 : };
+ 387 :
+ 388 : /**
+ 389 : * Disk mapping.
+ 390 : */
+ 391 : struct snapraid_map {
+ 392 : char name[PATH_MAX]; /**< Name of the disk. */
+ 393 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */
+ 394 : block_off_t total_blocks; /**< Number of total blocks. */
+ 395 : block_off_t free_blocks; /**< Number of free blocks at last 'sync'. */
+ 396 : unsigned position; /**< Position of the disk in the parity. */
+ 397 :
+ 398 : /* nodes for data structures */
+ 399 : tommy_node node;
+ 400 : };
+ 401 :
+ 402 : /**
+ 403 : * Parity.
+ 404 : */
+ 405 : struct snapraid_parity {
+ 406 : char path[PATH_MAX]; /**< Path of the parity file. */
+ 407 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */
+ 408 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
+ 409 : uint64_t device; /**< Device identifier of the parity. */
+ 410 : block_off_t total_blocks; /**< Number of total blocks. */
+ 411 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */
+ 412 : int skip_access; /**< If the disk is inaccessible and it should be skipped. */
+ 413 : int is_excluded; /**< If the parity is excluded by disk filter. */
+ 414 :
+ 415 : /**
+ 416 : * Cumulative time used for parity disks.
+ 417 : */
+ 418 : uint64_t tick;
+ 419 : };
+ 420 :
+ 421 : /**
+ 422 : * Info.
+ 423 : */
+ 424 : typedef uint32_t snapraid_info;
+ 425 :
+ 426 : /**
+ 427 : * Allocate a content.
+ 428 : */
+ 429 : struct snapraid_content* content_alloc(const char* path, uint64_t dev);
+ 430 :
+ 431 : /**
+ 432 : * Deallocate a content.
+ 433 : */
+ 434 : void content_free(struct snapraid_content* content);
+ 435 :
+ 436 : /**
+ 437 : * Allocate a filter pattern for files and directories.
+ 438 : */
+ 439 : struct snapraid_filter* filter_alloc_file(int is_include, const char* pattern);
+ 440 :
+ 441 : /**
+ 442 : * Allocate a filter pattern for disks.
+ 443 : */
+ 444 : struct snapraid_filter* filter_alloc_disk(int is_include, const char* pattern);
+ 445 :
+ 446 : /**
+ 447 : * Deallocate an exclusion.
+ 448 : */
+ 449 : void filter_free(struct snapraid_filter* filter);
+ 450 :
+ 451 : /**
+ 452 : * Filter type description.
+ 453 : */
+ 454 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size);
+ 455 :
+ 456 : /**
+ 457 : * Filter hidden files.
+ 458 : * Return !=0 if it matches and it should be excluded.
+ 459 : */
+ 460 3114300 : static inline int filter_hidden(int enable, struct dirent* dd)
+ 461 : {
+ 462 3114300 : if (enable && dirent_hidden(dd)) {
+ 463 0 : return 1; /* filter out */
+ 464 : }
+ 465 :
+ 466 3114300 : return 0;
+ 467 : }
+ 468 :
+ 469 : /**
+ 470 : * Filter a path using a list of filters.
+ 471 : * For each element of the path all the filters are applied, until the first one that matches.
+ 472 : * Return !=0 if it should be excluded.
+ 473 : */
+ 474 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub);
+ 475 :
+ 476 : /**
+ 477 : * Filter a file/link/dir if missing.
+ 478 : * This call imply a disk check for the file presence.
+ 479 : * Return !=0 if the file is present and it should be excluded.
+ 480 : */
+ 481 : int filter_existence(int filter_missing, const char* dir, const char* sub);
+ 482 :
+ 483 : /**
+ 484 : * Filter a file if bad.
+ 485 : * Return !=0 if the file is correct and it should be excluded.
+ 486 : */
+ 487 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file);
+ 488 :
+ 489 : /**
+ 490 : * Filter a dir using a list of filters.
+ 491 : * For each element of the path all the filters are applied, until the first one that matches.
+ 492 : * Return !=0 if should be excluded.
+ 493 : */
+ 494 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub);
+ 495 :
+ 496 : /**
+ 497 : * Filter a path if it's a content file.
+ 498 : * Return !=0 if should be excluded.
+ 499 : */
+ 500 : int filter_content(tommy_list* contentlist, const char* path);
+ 501 :
+ 502 : /**
+ 503 : * Check if the specified hash is invalid.
+ 504 : *
+ 505 : * An invalid hash is represented with all bytes at 0x00.
+ 506 : */
+ 507 759605 : static inline int hash_is_invalid(const unsigned char* hash)
+ 508 : {
+ 509 : unsigned i;
+ 510 :
+ 511 1179159 : for (i = 0; i < HASH_SIZE; ++i)
+ 512 1153105 : if (hash[i] != 0x00)
+ 513 733551 : return 0;
+ 514 :
+ 515 26054 : return 1;
+ 516 : }
+ 517 :
+ 518 : /**
+ 519 : * Check if the specified hash represent the zero block.
+ 520 : *
+ 521 : * A zero hash is represented with all bytes at 0xFF.
+ 522 : */
+ 523 761026 : static inline int hash_is_zero(const unsigned char* hash)
+ 524 : {
+ 525 : unsigned i;
+ 526 :
+ 527 994627 : for (i = 0; i < HASH_SIZE; ++i)
+ 528 980198 : if (hash[i] != 0xFF)
+ 529 746597 : return 0;
+ 530 :
+ 531 14429 : return 1;
+ 532 : }
+ 533 :
+ 534 : /**
+ 535 : * Check if the specified hash is a real hash.
+ 536 : */
+ 537 44133 : static inline int hash_is_real(const unsigned char* hash)
+ 538 : {
+ 539 44133 : return !hash_is_zero(hash) && !hash_is_invalid(hash);
+ 540 : }
+ 541 :
+ 542 : /**
+ 543 : * Set the hash to the special INVALID value.
+ 544 : */
+ 545 9036734 : static inline void hash_invalid_set(unsigned char* hash)
+ 546 : {
+ 547 9036734 : memset(hash, 0x00, HASH_SIZE);
+ 548 9036734 : }
+ 549 :
+ 550 : /**
+ 551 : * Set the hash to the special ZERO value.
+ 552 : */
+ 553 115487 : static inline void hash_zero_set(unsigned char* hash)
+ 554 : {
+ 555 115487 : memset(hash, 0xFF, HASH_SIZE);
+ 556 115487 : }
+ 557 :
+ 558 : /**
+ 559 : * Get the state of the block.
+ 560 : *
+ 561 : * For this function, it's allowed to pass a NULL block
+ 562 : * pointer than results in the BLOCK_STATE_EMPTY state.
+ 563 : */
+ 564 49967196 : static inline unsigned block_state_get(const struct snapraid_block* block)
+ 565 : {
+ 566 49967196 : if (block == BLOCK_EMPTY)
+ 567 1604566 : return BLOCK_STATE_EMPTY;
+ 568 :
+ 569 48362630 : return block->state;
+ 570 : }
+ 571 :
+ 572 : /**
+ 573 : * Set the state of the block.
+ 574 : */
+ 575 18633161 : static inline void block_state_set(struct snapraid_block* block, unsigned state)
+ 576 : {
+ 577 18633161 : block->state = state;
+ 578 18633161 : }
+ 579 :
+ 580 : /**
+ 581 : * Check if the specified block has an updated hash.
+ 582 : *
+ 583 : * Note that EMPTY / CHG / DELETED return 0.
+ 584 : */
+ 585 2075259 : static inline int block_has_updated_hash(const struct snapraid_block* block)
+ 586 : {
+ 587 2075259 : unsigned state = block_state_get(block);
+ 588 :
+ 589 2075259 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP;
+ 590 : }
+ 591 :
+ 592 : /**
+ 593 : * Check if the specified block has a past hash,
+ 594 : * i.e. the hash of the data that it's now overwritten or lost.
+ 595 : *
+ 596 : * Note that EMPTY / BLK / REP return 0.
+ 597 : */
+ 598 2401624 : static inline int block_has_past_hash(const struct snapraid_block* block)
+ 599 : {
+ 600 2401624 : unsigned state = block_state_get(block);
+ 601 :
+ 602 2401624 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED;
+ 603 : }
+ 604 :
+ 605 : /**
+ 606 : * Check if the specified block is part of a file.
+ 607 : *
+ 608 : * Note that EMPTY / DELETED return 0.
+ 609 : */
+ 610 13243669 : static inline int block_has_file(const struct snapraid_block* block)
+ 611 : {
+ 612 13243669 : unsigned state = block_state_get(block);
+ 613 :
+ 614 13243669 : return state == BLOCK_STATE_BLK
+ 615 13243669 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
+ 616 : }
+ 617 :
+ 618 : /**
+ 619 : * Check if the block has an invalid parity than needs to be updated.
+ 620 : *
+ 621 : * Note that EMPTY / BLK return 0.
+ 622 : */
+ 623 11837218 : static inline int block_has_invalid_parity(const struct snapraid_block* block)
+ 624 : {
+ 625 11837218 : unsigned state = block_state_get(block);
+ 626 :
+ 627 11837218 : return state == BLOCK_STATE_DELETED
+ 628 11837218 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
+ 629 : }
+ 630 :
+ 631 : /**
+ 632 : * Check if the block is part of a file with valid parity.
+ 633 : *
+ 634 : * Note that anything different than BLK return 0.
+ 635 : */
+ 636 257893 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block)
+ 637 : {
+ 638 257893 : unsigned state = block_state_get(block);
+ 639 :
+ 640 257893 : return state == BLOCK_STATE_BLK;
+ 641 : }
+ 642 :
+ 643 33706389 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask)
+ 644 : {
+ 645 33706389 : return (file->flag & mask) == mask;
+ 646 : }
+ 647 :
+ 648 5250833 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask)
+ 649 : {
+ 650 5250833 : file->flag |= mask;
+ 651 5250833 : }
+ 652 :
+ 653 20621 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask)
+ 654 : {
+ 655 20621 : file->flag &= ~mask;
+ 656 20621 : }
+ 657 :
+ 658 : /**
+ 659 : * Allocate a file.
+ 660 : */
+ 661 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical);
+ 662 :
+ 663 : /**
+ 664 : * Duplicate a file.
+ 665 : */
+ 666 : struct snapraid_file* file_dup(struct snapraid_file* copy);
+ 667 :
+ 668 : /**
+ 669 : * Deallocate a file.
+ 670 : */
+ 671 : void file_free(struct snapraid_file* file);
+ 672 :
+ 673 : /**
+ 674 : * Rename a file.
+ 675 : */
+ 676 : void file_rename(struct snapraid_file* file, const char* sub);
+ 677 :
+ 678 : /**
+ 679 : * Copy a file.
+ 680 : */
+ 681 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file);
+ 682 :
+ 683 : /**
+ 684 : * Return the name of the file, without the dir.
+ 685 : */
+ 686 : const char* file_name(const struct snapraid_file* file);
+ 687 :
+ 688 : /**
+ 689 : * Check if the block is the last in the file.
+ 690 : */
+ 691 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos);
+ 692 :
+ 693 : /**
+ 694 : * Get the size in bytes of the block.
+ 695 : * If it's the last block of a file it could be less than block_size.
+ 696 : */
+ 697 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size);
+ 698 :
+ 699 : /**
+ 700 : * Compare a file with an inode.
+ 701 : */
+ 702 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data);
+ 703 :
+ 704 : /**
+ 705 : * Compare files by inode.
+ 706 : */
+ 707 : int file_inode_compare(const void* void_a, const void* void_b);
+ 708 :
+ 709 : /**
+ 710 : * Compare files by path.
+ 711 : */
+ 712 : int file_path_compare(const void* void_a, const void* void_b);
+ 713 :
+ 714 : /**
+ 715 : * Compare files by physical address.
+ 716 : */
+ 717 : int file_physical_compare(const void* void_a, const void* void_b);
+ 718 :
+ 719 : /**
+ 720 : * Compute the hash of a file inode.
+ 721 : */
+ 722 4924816 : static inline tommy_uint32_t file_inode_hash(uint64_t inode)
+ 723 : {
+ 724 4924816 : return (tommy_uint32_t)tommy_inthash_u64(inode);
+ 725 : }
+ 726 :
+ 727 : /**
+ 728 : * Compare a file with a path.
+ 729 : */
+ 730 : int file_path_compare_to_arg(const void* void_arg, const void* void_data);
+ 731 :
+ 732 : /**
+ 733 : * Compare a file with another file for name, stamp, and both.
+ 734 : */
+ 735 : int file_name_compare(const void* void_a, const void* void_b);
+ 736 : int file_stamp_compare(const void* void_a, const void* void_b);
+ 737 : int file_namestamp_compare(const void* void_a, const void* void_b);
+ 738 : int file_pathstamp_compare(const void* void_a, const void* void_b);
+ 739 :
+ 740 : /**
+ 741 : * Compute the hash of a file path.
+ 742 : */
+ 743 3815727 : static inline tommy_uint32_t file_path_hash(const char* sub)
+ 744 : {
+ 745 3815727 : return tommy_hash_u32(0, sub, strlen(sub));
+ 746 : }
+ 747 :
+ 748 : /**
+ 749 : * Compute the hash of a file stamp.
+ 750 : */
+ 751 6198269 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec)
+ 752 : {
+ 753 6198269 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec)));
+ 754 : }
+ 755 :
+ 756 : /**
+ 757 : * Allocate a chunk.
+ 758 : */
+ 759 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count);
+ 760 :
+ 761 : /**
+ 762 : * Deallocate a chunk.
+ 763 : */
+ 764 : void chunk_free(struct snapraid_chunk* chunk);
+ 765 :
+ 766 : /**
+ 767 : * Compare chunk by parity position.
+ 768 : */
+ 769 : int chunk_parity_compare(const void* void_a, const void* void_b);
+ 770 :
+ 771 : /**
+ 772 : * Compare chunk by file and file position.
+ 773 : */
+ 774 : int chunk_file_compare(const void* void_a, const void* void_b);
+ 775 :
+ 776 205548 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask)
+ 777 : {
+ 778 205548 : return (slink->flag & mask) == mask;
+ 779 : }
+ 780 :
+ 781 37571 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask)
+ 782 : {
+ 783 37571 : slink->flag |= mask;
+ 784 37571 : }
+ 785 :
+ 786 : static inline void link_flag_clear(struct snapraid_link* slink, unsigned mask)
+ 787 : {
+ 788 : slink->flag &= ~mask;
+ 789 : }
+ 790 :
+ 791 6 : static inline void link_flag_let(struct snapraid_link* slink, unsigned flag, unsigned mask)
+ 792 : {
+ 793 6 : slink->flag &= ~mask;
+ 794 6 : slink->flag |= flag & mask;
+ 795 6 : }
+ 796 :
+ 797 89637 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask)
+ 798 : {
+ 799 89637 : return slink->flag & mask;
+ 800 : }
+ 801 :
+ 802 : /**
+ 803 : * Allocate a link.
+ 804 : */
+ 805 : struct snapraid_link* link_alloc(const char* name, const char* slink, unsigned link_flag);
+ 806 :
+ 807 : /**
+ 808 : * Deallocate a link.
+ 809 : */
+ 810 : void link_free(struct snapraid_link* slink);
+ 811 :
+ 812 : /**
+ 813 : * Compare a link with a name.
+ 814 : */
+ 815 : int link_name_compare_to_arg(const void* void_arg, const void* void_data);
+ 816 :
+ 817 : /**
+ 818 : * Compare links by path.
+ 819 : */
+ 820 : int link_alpha_compare(const void* void_a, const void* void_b);
+ 821 :
+ 822 : /**
+ 823 : * Compute the hash of a link name.
+ 824 : */
+ 825 151170 : static inline tommy_uint32_t link_name_hash(const char* name)
+ 826 : {
+ 827 151170 : return tommy_hash_u32(0, name, strlen(name));
+ 828 : }
+ 829 :
+ 830 900 : static inline int dir_flag_has(const struct snapraid_dir* dir, unsigned mask)
+ 831 : {
+ 832 900 : return (dir->flag & mask) == mask;
+ 833 : }
+ 834 :
+ 835 247 : static inline void dir_flag_set(struct snapraid_dir* dir, unsigned mask)
+ 836 : {
+ 837 247 : dir->flag |= mask;
+ 838 247 : }
+ 839 :
+ 840 : static inline void dir_flag_clear(struct snapraid_dir* dir, unsigned mask)
+ 841 : {
+ 842 : dir->flag &= ~mask;
+ 843 : }
+ 844 :
+ 845 : /**
+ 846 : * Allocate a dir.
+ 847 : */
+ 848 : struct snapraid_dir* dir_alloc(const char* name);
+ 849 :
+ 850 : /**
+ 851 : * Deallocate a dir.
+ 852 : */
+ 853 : void dir_free(struct snapraid_dir* dir);
+ 854 :
+ 855 : /**
+ 856 : * Compare a dir with a name.
+ 857 : */
+ 858 : int dir_name_compare(const void* void_arg, const void* void_data);
+ 859 :
+ 860 : /**
+ 861 : * Compute the hash of a dir name.
+ 862 : */
+ 863 1011 : static inline tommy_uint32_t dir_name_hash(const char* name)
+ 864 : {
+ 865 1011 : return tommy_hash_u32(0, name, strlen(name));
+ 866 : }
+ 867 :
+ 868 : /**
+ 869 : * Allocate a disk.
+ 870 : */
+ 871 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip);
+ 872 :
+ 873 : /**
+ 874 : * Deallocate a disk.
+ 875 : */
+ 876 : void disk_free(struct snapraid_disk* disk);
+ 877 :
+ 878 : /**
+ 879 : * Get the size of the disk in blocks.
+ 880 : */
+ 881 : block_off_t disk_size(struct snapraid_disk* disk);
+ 882 :
+ 883 : /**
+ 884 : * Check if a disk is totally empty and can be discarded from the content file.
+ 885 : * A disk is empty if it doesn't contain any file, symlink, hardlink or dir
+ 886 : * and without any DELETED block.
+ 887 : * The blockmax is used to limit the search of DELETED block up to blockmax.
+ 888 : */
+ 889 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax);
+ 890 :
+ 891 : /**
+ 892 : * Check the file-system for errors.
+ 893 : * Return 0 if it's OK.
+ 894 : */
+ 895 : int fs_check(struct snapraid_disk* disk);
+ 896 :
+ 897 : /**
+ 898 : * Allocate a parity position for the specified file position.
+ 899 : *
+ 900 : * After this call you can use the par2file/par2block operations
+ 901 : * to query the relation.
+ 902 : *
+ 903 : * \note This function is NOT thread-safe as it uses the the disk cache. +
+ 904 : */
+ 905 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos);
+ 906 :
+ 907 : /**
+ 908 : * Deallocate the parity position.
+ 909 : *
+ 910 : * After this call the par2file/par2block operations
+ 911 : * won't find anymore the parity association.
+ 912 : *
+ 913 : * \note This function is NOT thread-safe as it uses the the disk cache.
+ 914 : */
+ 915 : void fs_deallocate(struct snapraid_disk* disk, block_off_t pos);
+ 916 :
+ 917 : /**
+ 918 : * Get the block from the file position.
+ 919 : */
+ 920 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos);
+ 921 :
+ 922 : /**
+ 923 : * Like fs_file2par_get() but thread-safe.
+ 924 : */
+ 925 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos);
+ 926 :
+ 927 : /**
+ 928 : * Get the file position from the parity position.
+ 929 : * Return 0 if no file is using it.
+ 930 : * \note This function is NOT thread-safe as it uses the the disk cache.
+ 931 : */
+ 932 11578735 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
+ 933 : {
+ 934 11578735 : return fs_par2file_get_ts(disk, &disk->fs_last, parity_pos, file_pos);
+ 935 : }
+ 936 :
+ 937 : /**
+ 938 : * Like fs_file2par_get() but thread-safe.
+ 939 : */
+ 940 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos);
+ 941 :
+ 942 : /**
+ 943 : * Get the parity position from the file position.
+ 944 : * \note This function is NOT thread-safe as it uses the the disk cache.
+ 945 : */
+ 946 519510 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
+ 947 : {
+ 948 519510 : return fs_file2par_get_ts(disk, &disk->fs_last, file, file_pos);
+ 949 : }
+ 950 :
+ 951 : /**
+ 952 : * Like fs_par2block_get() but thread-safe.
+ 953 : */
+ 954 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos);
+ 955 :
+ 956 : /**
+ 957 : * Get the block from the parity position.
+ 958 : * Return BLOCK_EMPTY==0 if the block is over the end of the disk or not used.
+ 959 : * \note This function is NOT thread-safe as it uses the the disk cache.
+ 960 : */
+ 961 22209416 : static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk, block_off_t parity_pos)
+ 962 : {
+ 963 22209416 : return fs_par2block_get_ts(disk, &disk->fs_last, parity_pos);
+ 964 : }
+ 965 :
+ 966 : /**
+ 967 : * Allocate a disk mapping.
+ 968 : * Uses uuid="" if not available.
+ 969 : */
+ 970 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid);
+ 971 :
+ 972 : /**
+ 973 : * Deallocate a disk mapping.
+ 974 : */
+ 975 : void map_free(struct snapraid_map* map);
+ 976 :
+ 977 : /**
+ 978 : * Mask used to store additional information in the info bits.
+ 979 : *
+ 980 : * These bits reduce the granularity of the time in the memory representation.
+ 981 : */
+ 982 : #define INFO_MASK 0x7
+ 983 :
+ 984 : /**
+ 985 : * Make an info.
+ 986 : */
+ 987 174394 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced)
+ 988 : {
+ 989 : /* clear the lowest bits as reserved for other information */
+ 990 174394 : snapraid_info info = last_access & ~INFO_MASK;
+ 991 :
+ 992 174394 : if (error != 0)
+ 993 5365 : info |= 0x1;
+ 994 174394 : if (rehash != 0)
+ 995 14409 : info |= 0x2;
+ 996 174394 : if (justsynced != 0)
+ 997 122709 : info |= 0x4;
+ 998 174394 : return info;
+ 999 : }
+ 1000 :
+ 1001 : /**
+ 1002 : * Extract the time information.
+ 1003 : * This is the last time when the block was know to be correct.
+ 1004 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub.
+ 1005 : */
+ 1006 890086 : static inline time_t info_get_time(snapraid_info info)
+ 1007 : {
+ 1008 890086 : return info & ~INFO_MASK;
+ 1009 : }
+ 1010 :
+ 1011 : /**
+ 1012 : * Extract the error information.
+ 1013 : * Report if the block address had some problem.
+ 1014 : */
+ 1015 338860 : static inline int info_get_bad(snapraid_info info)
+ 1016 : {
+ 1017 338860 : return (info & 0x1) != 0;
+ 1018 : }
+ 1019 :
+ 1020 : /**
+ 1021 : * Extract the rehash information.
+ 1022 : * Report if the block address is using the old hash and needs to be rehashed.
+ 1023 : */
+ 1024 2058338 : static inline int info_get_rehash(snapraid_info info)
+ 1025 : {
+ 1026 2058338 : return (info & 0x2) != 0;
+ 1027 : }
+ 1028 :
+ 1029 : /**
+ 1030 : * Extract the scrubbed information.
+ 1031 : * Report if the block address was never scrubbed.
+ 1032 : */
+ 1033 79285 : static inline int info_get_justsynced(snapraid_info info)
+ 1034 : {
+ 1035 79285 : return (info & 0x4) != 0;
+ 1036 : }
+ 1037 :
+ 1038 : /**
+ 1039 : * Mark the block address as with error.
+ 1040 : */
+ 1041 1771 : static inline snapraid_info info_set_bad(snapraid_info info)
+ 1042 : {
+ 1043 1771 : return info | 0x1;
+ 1044 : }
+ 1045 :
+ 1046 : /**
+ 1047 : * Mark the block address as with rehash.
+ 1048 : */
+ 1049 9207 : static inline snapraid_info info_set_rehash(snapraid_info info)
+ 1050 : {
+ 1051 9207 : return info | 0x2;
+ 1052 : }
+ 1053 :
+ 1054 : /**
+ 1055 : * Set the info at the specified position.
+ 1056 : * The position is allocated if not yet done.
+ 1057 : */
+ 1058 1639782 : static inline void info_set(tommy_arrayblkof* array, unsigned pos, snapraid_info info)
+ 1059 : {
+ 1060 1639782 : tommy_arrayblkof_grow(array, pos + 1);
+ 1061 :
+ 1062 1639782 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info));
+ 1063 1639782 : }
+ 1064 :
+ 1065 : /**
+ 1066 : * Get the info at the specified position.
+ 1067 : * For not allocated position, 0 is returned.
+ 1068 : */
+ 1069 5104110 : static inline snapraid_info info_get(tommy_arrayblkof* array, unsigned pos)
+ 1070 : {
+ 1071 : snapraid_info info;
+ 1072 :
+ 1073 5104110 : if (pos >= tommy_arrayblkof_size(array))
+ 1074 262738 : return 0;
1075 :
- 1076 10085303 : return info;
- 1077 : }
- 1078 :
- 1079 : /**
- 1080 : * Compare times
- 1081 : */
- 1082 : int time_compare(const void* void_a, const void* void_b);
- 1083 :
- 1084 : #endif
+ 1076 4841372 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info));
+ 1077 :
+ 1078 4841372 : return info;
+ 1079 : }
+ 1080 :
+ 1081 : /**
+ 1082 : * Compare times
+ 1083 : */
+ 1084 : int time_compare(const void* void_a, const void* void_b);
1085 :
+ 1086 : #endif
+ 1087 :
diff --git a/cov/cmdline/handle.c.func-sort-c.html b/cov/cmdline/handle.c.func-sort-c.html
index 364aeee3..2444eacb 100644
--- a/cov/cmdline/handle.c.func-sort-c.html
+++ b/cov/cmdline/handle.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -61,35 +61,35 @@
| handle_read |
- 5656394 |
+ 5713632 |
| handle_close |
- 4568631 |
+ 4590919 |
| handle_open |
- 1972488 |
+ 2024387 |
| handle_create |
- 771210 |
+ 771290 |
| handle_write |
- 288205 |
+ 288532 |
| handle_utime |
- 117763 |
+ 119455 |
| handle_truncate |
- 3249 |
+ 3187 |
| handle_map |
- 206 |
+ 214 |
diff --git a/cov/cmdline/handle.c.func.html b/cov/cmdline/handle.c.func.html
index f0a579bc..cb35a7e7 100644
--- a/cov/cmdline/handle.c.func.html
+++ b/cov/cmdline/handle.c.func.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -61,35 +61,35 @@
| handle_close |
- 4568631 |
+ 4590919 |
| handle_create |
- 771210 |
+ 771290 |
| handle_map |
- 206 |
+ 214 |
| handle_open |
- 1972488 |
+ 2024387 |
| handle_read |
- 5656394 |
+ 5713632 |
| handle_truncate |
- 3249 |
+ 3187 |
| handle_utime |
- 117763 |
+ 119455 |
| handle_write |
- 288205 |
+ 288532 |
diff --git a/cov/cmdline/handle.c.gcov.html b/cov/cmdline/handle.c.gcov.html
index 72e13a47..84f0dbae 100644
--- a/cov/cmdline/handle.c.gcov.html
+++ b/cov/cmdline/handle.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -86,66 +86,66 @@
24 : /****************************************************************************/
25 : /* handle */
26 :
- 27 771210 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode)
+ 27 771290 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode)
28 : {
29 : int ret;
30 : int flags;
31 :
32 : /* if it's the same file, and already opened, nothing to do */
- 33 771210 : if (handle->file == file && handle->f != -1) {
+ 33 771290 : if (handle->file == file && handle->f != -1) {
34 0 : return 0;
35 : }
36 :
- 37 771210 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
+ 37 771290 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
38 :
- 39 771210 : ret = mkancestor(handle->path);
- 40 771210 : if (ret != 0) {
+ 39 771290 : ret = mkancestor(handle->path);
+ 40 771290 : if (ret != 0) {
41 : /* LCOV_EXCL_START */
42 : return -1;
43 : /* LCOV_EXCL_STOP */
44 : }
45 :
46 : /* initial values, changed later if required */
- 47 771210 : handle->created = 0;
+ 47 771290 : handle->created = 0;
48 :
49 : /* flags for opening */
50 : /* O_BINARY: open as binary file (Windows only) */
51 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
52 : /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */
- 53 771210 : flags = O_BINARY | O_NOFOLLOW;
- 54 771210 : if ((mode & MODE_SEQUENTIAL) != 0)
- 55 771210 : flags |= O_SEQUENTIAL;
+ 53 771290 : flags = O_BINARY | O_NOFOLLOW;
+ 54 771290 : if ((mode & MODE_SEQUENTIAL) != 0)
+ 55 771290 : flags |= O_SEQUENTIAL;
56 :
57 : /* open for read write */
- 58 771210 : handle->f = open(handle->path, flags | O_RDWR);
+ 58 771290 : handle->f = open(handle->path, flags | O_RDWR);
59 :
60 : /* if failed for missing write permission */
- 61 771210 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
+ 61 771290 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
62 : /* open for real-only */
63 0 : handle->f = open(handle->path, flags | O_RDONLY);
64 : }
65 :
66 : /* if failed for missing file */
- 67 771210 : if (handle->f == -1 && errno == ENOENT) {
+ 67 771290 : if (handle->f == -1 && errno == ENOENT) {
68 : char path_from[PATH_MAX];
69 :
70 : /* check if exists a .unrecoverable copy, and rename to the real one */
- 71 176420 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path);
+ 71 176470 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path);
72 :
- 73 176420 : if (rename(path_from, handle->path) == 0) {
+ 73 176470 : if (rename(path_from, handle->path) == 0) {
74 : /* open for read write */
- 75 63396 : handle->f = open(handle->path, flags | O_RDWR);
+ 75 63363 : handle->f = open(handle->path, flags | O_RDWR);
76 : } else {
77 : /* create it */
- 78 113024 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600);
- 79 113024 : if (handle->f != -1) {
+ 78 113107 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600);
+ 79 113107 : if (handle->f != -1) {
80 : /* mark it as created if really done */
- 81 113024 : handle->created = 1;
+ 81 113107 : handle->created = 1;
82 : }
83 : }
84 : }
85 :
- 86 771210 : if (handle->f == -1) {
+ 86 771290 : if (handle->f == -1) {
87 : /* LCOV_EXCL_START */
88 : /* invalidate for error */
89 : handle->file = 0;
@@ -158,11 +158,11 @@
96 : }
97 :
98 : /* just opened */
- 99 771210 : handle->file = file;
+ 99 771290 : handle->file = file;
100 :
101 : /* get the stat info */
- 102 771210 : ret = fstat(handle->f, &handle->st);
- 103 771210 : if (ret != 0) {
+ 102 771290 : ret = fstat(handle->f, &handle->st);
+ 103 771290 : if (ret != 0) {
104 : /* LCOV_EXCL_START */
105 : log_fatal("Error accessing file '%s'. %s.\n", handle->path, strerror(errno));
106 : return -1;
@@ -170,13 +170,13 @@
108 : }
109 :
110 : /* get the size of the existing data */
- 111 771210 : handle->valid_size = handle->st.st_size;
+ 111 771290 : handle->valid_size = handle->st.st_size;
112 :
113 : #if HAVE_POSIX_FADVISE
- 114 771210 : if ((mode & MODE_SEQUENTIAL) != 0) {
+ 114 771290 : if ((mode & MODE_SEQUENTIAL) != 0) {
115 : /* advise sequential access */
- 116 771210 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 117 771210 : if (ret != 0) {
+ 116 771290 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 117 771290 : if (ret != 0) {
118 : /* LCOV_EXCL_START */
119 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(ret));
120 : return -1;
@@ -185,15 +185,15 @@
123 : }
124 : #endif
125 :
- 126 771210 : return 0;
+ 126 771290 : return 0;
127 : }
128 :
- 129 3249 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
+ 129 3187 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
130 : {
131 : int ret;
132 :
- 133 3249 : ret = ftruncate(handle->f, file->size);
- 134 3249 : if (ret != 0) {
+ 133 3187 : ret = ftruncate(handle->f, file->size);
+ 134 3187 : if (ret != 0) {
135 : /* LCOV_EXCL_START */
136 : if (errno == EACCES) {
137 : log_fatal("Failed to truncate file '%s' for missing write permission.\n", handle->path);
@@ -205,58 +205,58 @@
143 : }
144 :
145 : /* adjust the size to the truncated size */
- 146 3249 : handle->valid_size = file->size;
+ 146 3187 : handle->valid_size = file->size;
147 :
- 148 3249 : return 0;
+ 148 3187 : return 0;
149 : }
150 :
- 151 1972488 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing)
+ 151 2024387 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing)
152 : {
153 : int ret;
154 : int flags;
155 :
- 156 1972488 : if (!out_missing)
- 157 1971972 : out_missing = out;
+ 156 2024387 : if (!out_missing)
+ 157 2023815 : out_missing = out;
158 :
159 : /* if already opened, nothing to do */
- 160 1972488 : if (handle->file == file && handle->f != -1) {
- 161 332290 : return 0;
+ 160 2024387 : if (handle->file == file && handle->f != -1) {
+ 161 363056 : return 0;
162 : }
163 :
- 164 1640198 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
+ 164 1661331 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
165 :
166 : /* for sure not created */
- 167 1640198 : handle->created = 0;
+ 167 1661331 : handle->created = 0;
168 :
169 : /* flags for opening */
170 : /* O_BINARY: open as binary file (Windows only) */
171 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
172 : /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */
- 173 1640198 : flags = O_BINARY | O_NOFOLLOW;
- 174 1640198 : if ((mode & MODE_SEQUENTIAL) != 0)
- 175 1628870 : flags |= O_SEQUENTIAL;
+ 173 1661331 : flags = O_BINARY | O_NOFOLLOW;
+ 174 1661331 : if ((mode & MODE_SEQUENTIAL) != 0)
+ 175 1649996 : flags |= O_SEQUENTIAL;
176 :
177 : /* open for read */
- 178 1640198 : handle->f = open_noatime(handle->path, flags | O_RDONLY);
- 179 1640198 : if (handle->f == -1) {
+ 178 1661331 : handle->f = open_noatime(handle->path, flags | O_RDONLY);
+ 179 1661331 : if (handle->f == -1) {
180 : /* invalidate for error */
- 181 78777 : handle->file = 0;
- 182 78777 : handle->f = -1;
- 183 78777 : handle->valid_size = 0;
+ 181 78781 : handle->file = 0;
+ 182 78781 : handle->f = -1;
+ 183 78781 : handle->valid_size = 0;
184 :
- 185 78777 : if (errno == ENOENT)
- 186 78765 : out_missing("Missing file '%s'.\n", handle->path);
+ 185 78781 : if (errno == ENOENT)
+ 186 78769 : out_missing("Missing file '%s'.\n", handle->path);
187 : else
188 12 : out("Error opening file '%s'. %s.\n", handle->path, strerror(errno));
- 189 78777 : return -1;
+ 189 78781 : return -1;
190 : }
191 :
192 : /* just opened */
- 193 1561421 : handle->file = file;
+ 193 1582550 : handle->file = file;
194 :
195 : /* get the stat info */
- 196 1561421 : ret = fstat(handle->f, &handle->st);
- 197 1561421 : if (ret != 0) {
+ 196 1582550 : ret = fstat(handle->f, &handle->st);
+ 197 1582550 : if (ret != 0) {
198 : /* LCOV_EXCL_START */
199 : out("Error accessing file '%s'. %s.\n", handle->path, strerror(errno));
200 : return -1;
@@ -264,13 +264,13 @@
202 : }
203 :
204 : /* get the size of the existing data */
- 205 1561421 : handle->valid_size = handle->st.st_size;
+ 205 1582550 : handle->valid_size = handle->st.st_size;
206 :
207 : #if HAVE_POSIX_FADVISE
- 208 1561421 : if ((mode & MODE_SEQUENTIAL) != 0) {
+ 208 1582550 : if ((mode & MODE_SEQUENTIAL) != 0) {
209 : /* advise sequential access */
- 210 1550093 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 211 1550093 : if (ret != 0) {
+ 210 1571215 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 211 1571215 : if (ret != 0) {
212 : /* LCOV_EXCL_START */
213 : out("Error advising file '%s'. %s.\n", handle->path, strerror(ret));
214 : return -1;
@@ -279,17 +279,17 @@
217 : }
218 : #endif
219 :
- 220 1561421 : return 0;
+ 220 1582550 : return 0;
221 : }
222 :
- 223 4568631 : int handle_close(struct snapraid_handle* handle)
+ 223 4590919 : int handle_close(struct snapraid_handle* handle)
224 : {
225 : int ret;
226 :
227 : /* close if open */
- 228 4568631 : if (handle->f != -1) {
- 229 2332631 : ret = close(handle->f);
- 230 2332631 : if (ret != 0) {
+ 228 4590919 : if (handle->f != -1) {
+ 229 2353840 : ret = close(handle->f);
+ 230 2353840 : if (ret != 0) {
231 : /* LCOV_EXCL_START */
232 : log_fatal("Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno));
233 :
@@ -303,36 +303,36 @@
241 : }
242 :
243 : /* reset the descriptor */
- 244 4568631 : handle->file = 0;
- 245 4568631 : handle->f = -1;
- 246 4568631 : handle->valid_size = 0;
+ 244 4590919 : handle->file = 0;
+ 245 4590919 : handle->f = -1;
+ 246 4590919 : handle->valid_size = 0;
247 :
- 248 4568631 : return 0;
+ 248 4590919 : return 0;
249 : }
250 :
- 251 5656394 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing)
+ 251 5713632 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing)
252 : {
253 : ssize_t read_ret;
254 : data_off_t offset;
255 : unsigned read_size;
256 : unsigned count;
257 :
- 258 5656394 : offset = file_pos * (data_off_t)block_size;
+ 258 5713632 : offset = file_pos * (data_off_t)block_size;
259 :
- 260 5656394 : if (!out_missing)
- 261 5642993 : out_missing = out;
+ 260 5713632 : if (!out_missing)
+ 261 5700398 : out_missing = out;
262 :
263 : /* check if we are going to read only not initialized data */
- 264 5656394 : if (offset >= handle->valid_size) {
+ 264 5713632 : if (offset >= handle->valid_size) {
265 : /* if the file is missing, it's at 0 size, or it's rebuilt while reading */
- 266 433131 : if (offset == handle->valid_size || handle->valid_size == 0)
- 267 431906 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
+ 266 433671 : if (offset == handle->valid_size || handle->valid_size == 0)
+ 267 432378 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
268 : else
- 269 1225 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
- 270 433131 : return -1;
+ 269 1293 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
+ 270 433671 : return -1;
271 : }
272 :
- 273 5223263 : read_size = file_block_size(handle->file, file_pos, block_size);
+ 273 5279961 : read_size = file_block_size(handle->file, file_pos, block_size);
274 :
275 : #if !HAVE_PREAD
276 : if (lseek(handle->f, offset, SEEK_SET) != offset) {
@@ -343,32 +343,32 @@
281 : }
282 : #endif
283 :
- 284 5223263 : count = 0;
+ 284 5279961 : count = 0;
285 : do {
286 :
287 : #if HAVE_PREAD
- 288 5232157 : read_ret = pread(handle->f, block_buffer + count, read_size - count, offset + count);
+ 288 5288816 : read_ret = pread(handle->f, block_buffer + count, read_size - count, offset + count);
289 : #else
290 : read_ret = read(handle->f, block_buffer + count, read_size - count);
291 : #endif
292 :
- 293 5232157 : if (read_ret < 0) {
+ 293 5288816 : if (read_ret < 0) {
294 : /* LCOV_EXCL_START */
295 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, read_size - count, strerror(errno));
296 : return -1;
297 : /* LCOV_EXCL_STOP */
298 : }
- 299 5232157 : if (read_ret == 0) {
- 300 8894 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
- 301 8894 : return -1;
+ 299 5288816 : if (read_ret == 0) {
+ 300 8855 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
+ 301 8855 : return -1;
302 : }
303 :
- 304 5223263 : count += read_ret;
- 305 5223263 : } while (count < read_size);
+ 304 5279961 : count += read_ret;
+ 305 5279961 : } while (count < read_size);
306 :
307 : /* pad with 0 */
- 308 5214369 : if (read_size < block_size) {
- 309 2112031 : memset(block_buffer + read_size, 0, block_size - read_size);
+ 308 5271106 : if (read_size < block_size) {
+ 309 2132322 : memset(block_buffer + read_size, 0, block_size - read_size);
310 : }
311 :
312 : /* Here isn't needed to call posix_fadvise(..., POSIX_FADV_DONTNEED) */
@@ -382,21 +382,21 @@
320 : /* at: https://lkml.org/lkml/2010/12/6/122 */
321 : /* We relay only on the automatic readahead triggered by POSIX_FADV_SEQUENTIAL. */
322 :
- 323 5214369 : return read_size;
+ 323 5271106 : return read_size;
324 : }
325 :
- 326 288205 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size)
+ 326 288532 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size)
327 : {
328 : ssize_t write_ret;
329 : data_off_t offset;
330 : unsigned write_size;
331 :
- 332 288205 : offset = file_pos * (data_off_t)block_size;
+ 332 288532 : offset = file_pos * (data_off_t)block_size;
333 :
- 334 288205 : write_size = file_block_size(handle->file, file_pos, block_size);
+ 334 288532 : write_size = file_block_size(handle->file, file_pos, block_size);
335 :
336 : #if HAVE_PWRITE
- 337 288205 : write_ret = pwrite(handle->f, block_buffer, write_size, offset);
+ 337 288532 : write_ret = pwrite(handle->f, block_buffer, write_size, offset);
338 : #else
339 : if (lseek(handle->f, offset, SEEK_SET) != offset) {
340 : /* LCOV_EXCL_START */
@@ -407,7 +407,7 @@
345 :
346 : write_ret = write(handle->f, block_buffer, write_size);
347 : #endif
- 348 288205 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */
+ 348 288532 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */
349 : /* LCOV_EXCL_START */
350 : log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno));
351 : return -1;
@@ -415,88 +415,89 @@
353 : }
354 :
355 : /* adjust the size of the valid data */
- 356 288205 : if (handle->valid_size < offset + write_size) {
- 357 282174 : handle->valid_size = offset + write_size;
+ 356 288532 : if (handle->valid_size < offset + write_size) {
+ 357 282422 : handle->valid_size = offset + write_size;
358 : }
359 :
360 : /* Here doesn't make sense to call posix_fadvise(..., POSIX_FADV_DONTNEED) because */
361 : /* at this time the data is still not yet written and it cannot be discharged. */
362 :
- 363 288205 : return 0;
+ 363 288532 : return 0;
364 : }
365 :
- 366 117763 : int handle_utime(struct snapraid_handle* handle)
+ 366 119455 : int handle_utime(struct snapraid_handle* handle)
367 : {
368 : int ret;
369 :
370 : /* do nothing if not opened */
- 371 117763 : if (handle->f == -1)
+ 371 119455 : if (handle->f == -1)
372 0 : return 0;
373 :
- 374 117763 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec);
+ 374 119455 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec);
375 :
- 376 117763 : if (ret != 0) {
+ 376 119455 : if (ret != 0) {
377 : /* LCOV_EXCL_START */
378 : log_fatal("Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno));
379 : return -1;
380 : /* LCOV_EXCL_STOP */
381 : }
382 :
- 383 117763 : return 0;
+ 383 119455 : return 0;
384 : }
385 :
- 386 206 : struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax)
+ 386 214 : struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax)
387 : {
388 : tommy_node* i;
389 : unsigned j;
- 390 206 : unsigned size = 0;
+ 390 214 : unsigned size = 0;
391 : struct snapraid_handle* handle;
392 :
393 : /* get the size of the mapping */
- 394 206 : size = 0;
- 395 1437 : for (i = state->maplist; i != 0; i = i->next) {
- 396 1231 : struct snapraid_map* map = i->data;
- 397 1231 : if (map->position > size)
- 398 895 : size = map->position;
+ 394 214 : size = 0;
+ 395 1493 : for (i = state->maplist; i != 0; i = i->next) {
+ 396 1279 : struct snapraid_map* map = i->data;
+ 397 1279 : if (map->position > size)
+ 398 925 : size = map->position;
399 : }
- 400 206 : ++size; /* size is one more than the max */
+ 400 214 : ++size; /* size is one more than the max */
401 :
- 402 206 : handle = malloc_nofail(size * sizeof(struct snapraid_handle));
+ 402 214 : handle = malloc_nofail(size * sizeof(struct snapraid_handle));
403 :
- 404 1442 : for (j = 0; j < size; ++j) {
+ 404 1498 : for (j = 0; j < size; ++j) {
405 : /* default for empty position */
- 406 1236 : handle[j].disk = 0;
- 407 1236 : handle[j].file = 0;
- 408 1236 : handle[j].f = -1;
- 409 1236 : handle[j].valid_size = 0;
+ 406 1284 : handle[j].disk = 0;
+ 407 1284 : handle[j].file = 0;
+ 408 1284 : handle[j].f = -1;
+ 409 1284 : handle[j].valid_size = 0;
410 : }
411 :
412 : /* set the vector */
- 413 1437 : for (i = state->disklist; i != 0; i = i->next) {
+ 413 1493 : for (i = state->disklist; i != 0; i = i->next) {
414 : struct snapraid_map* map;
- 415 1231 : struct snapraid_disk* disk = i->data;
+ 415 1279 : struct snapraid_disk* disk = i->data;
416 : tommy_node* k;
417 :
418 : /* search the mapping for this disk */
- 419 4296 : for (k = state->maplist; k != 0; k = k->next) {
- 420 4296 : map = k->data;
- 421 4296 : if (strcmp(disk->name, map->name) == 0)
- 422 1231 : break;
- 423 : }
- 424 1231 : if (k == 0) {
- 425 : /* LCOV_EXCL_START */
- 426 : log_fatal("Internal error for inconsistent disk mapping.\n");
- 427 : exit(EXIT_FAILURE);
- 428 : /* LCOV_EXCL_STOP */
- 429 : }
- 430 :
- 431 1231 : handle[map->position].disk = disk;
- 432 : }
- 433 :
- 434 206 : *handlemax = size;
- 435 206 : return handle;
- 436 : }
- 437 :
+ 419 1279 : map = 0;
+ 420 4464 : for (k = state->maplist; k != 0; k = k->next) {
+ 421 4464 : map = k->data;
+ 422 4464 : if (strcmp(disk->name, map->name) == 0)
+ 423 1279 : break;
+ 424 : }
+ 425 1279 : if (!map) {
+ 426 : /* LCOV_EXCL_START */
+ 427 : log_fatal("Internal error for inconsistent disk mapping.\n");
+ 428 : os_abort();
+ 429 : /* LCOV_EXCL_STOP */
+ 430 : }
+ 431 :
+ 432 1279 : handle[map->position].disk = disk;
+ 433 : }
+ 434 :
+ 435 214 : *handlemax = size;
+ 436 214 : return handle;
+ 437 : }
+ 438 :
diff --git a/cov/cmdline/import.c.func-sort-c.html b/cov/cmdline/import.c.func-sort-c.html
index 4ed3e003..fc384422 100644
--- a/cov/cmdline/import.c.func-sort-c.html
+++ b/cov/cmdline/import.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -61,36 +61,36 @@
| import_block_hash |
- 652942 |
+ 657660 |
- | state_import_fetch |
- 643998 |
-
-
- | import_block_prevhash_compare |
- 2238 |
+ state_import_fetch |
+ 653188 |
| import_block_hash_compare |
- 2234 |
+ 4472 |
- | import_file |
+ import_file |
1750 |
- | import_file_free |
+ import_file_free |
1750 |
- | state_import |
+ state_import |
1 |
- | import_dir |
+ import_dir |
1 |
+
+ | import_block_prevhash_compare |
+ 0 |
+
diff --git a/cov/cmdline/import.c.func.html b/cov/cmdline/import.c.func.html
index 00f16958..c081b511 100644
--- a/cov/cmdline/import.c.func.html
+++ b/cov/cmdline/import.c.func.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -61,35 +61,35 @@
| import_block_hash |
- 652942 |
+ 657660 |
| import_block_hash_compare |
- 2234 |
+ 4472 |
| import_block_prevhash_compare |
- 2238 |
+ 0 |
- | import_dir |
+ import_dir |
1 |
- | import_file |
+ import_file |
1750 |
- | import_file_free |
+ import_file_free |
1750 |
- | state_import |
+ state_import |
1 |
- | state_import_fetch |
- 643998 |
+ state_import_fetch |
+ 653188 |
diff --git a/cov/cmdline/import.c.gcov.html b/cov/cmdline/import.c.gcov.html
index 0cec9c66..a3d12909 100644
--- a/cov/cmdline/import.c.gcov.html
+++ b/cov/cmdline/import.c.gcov.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -88,303 +88,304 @@
26 : /**
27 : * Compare the hash of two import blocks.
28 : */
- 29 2234 : int import_block_hash_compare(const void* void_arg, const void* void_data)
+ 29 4472 : int import_block_hash_compare(const void* void_arg, const void* void_data)
30 : {
- 31 2234 : const unsigned char* arg = void_arg;
- 32 2234 : const struct snapraid_import_block* block = void_data;
+ 31 4472 : const unsigned char* arg = void_arg;
+ 32 4472 : const struct snapraid_import_block* block = void_data;
33 :
- 34 2234 : return memcmp(arg, block->hash, HASH_SIZE);
+ 34 4472 : return memcmp(arg, block->hash, HASH_SIZE);
35 : }
36 :
- 37 2238 : int import_block_prevhash_compare(const void* void_arg, const void* void_data)
+ 37 0 : int import_block_prevhash_compare(const void* void_arg, const void* void_data)
38 : {
- 39 2238 : const unsigned char* arg = void_arg;
- 40 2238 : const struct snapraid_import_block* block = void_data;
+ 39 0 : const unsigned char* arg = void_arg;
+ 40 0 : const struct snapraid_import_block* block = void_data;
41 :
- 42 2238 : return memcmp(arg, block->prevhash, HASH_SIZE);
+ 42 0 : return memcmp(arg, block->prevhash, HASH_SIZE);
43 : }
44 :
45 : /**
46 : * Compute the hash of the hash for an import block.
47 : * We just use the first 32 bit of the hash itself.
48 : */
- 49 652942 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash)
+ 49 657660 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash)
50 : {
- 51 652942 : return *(const tommy_uint32_t*)hash;
- 52 : }
- 53 :
- 54 1750 : static void import_file(struct snapraid_state* state, const char* path, uint64_t size)
- 55 : {
- 56 : struct snapraid_import_file* file;
- 57 : block_off_t i;
- 58 : data_off_t offset;
- 59 : void* buffer;
- 60 : int ret;
- 61 : int f;
- 62 : int flags;
- 63 1750 : unsigned block_size = state->block_size;
- 64 :
- 65 1750 : file = malloc_nofail(sizeof(struct snapraid_import_file));
- 66 1750 : file->path = strdup_nofail(path);
- 67 1750 : file->size = size;
- 68 1750 : file->blockmax = (size + block_size - 1) / block_size;
- 69 1750 : file->blockimp = malloc_nofail(file->blockmax * sizeof(struct snapraid_import_block));
- 70 :
- 71 1750 : buffer = malloc_nofail(block_size);
- 72 :
- 73 : /* open for read */
- 74 : /* O_SEQUENTIAL: opening in sequential mode in Windows */
- 75 1750 : flags = O_RDONLY | O_BINARY;
- 76 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0)
- 77 1750 : flags |= O_SEQUENTIAL;
- 78 1750 : f = open(path, flags);
- 79 1750 : if (f == -1) {
- 80 : /* LCOV_EXCL_START */
- 81 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno));
- 82 : exit(EXIT_FAILURE);
- 83 : /* LCOV_EXCL_STOP */
- 84 : }
- 85 :
- 86 : #if HAVE_POSIX_FADVISE
- 87 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) {
- 88 : /* advise sequential access */
- 89 1750 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 90 1750 : if (ret != 0) {
- 91 : /* LCOV_EXCL_START */
- 92 : log_fatal("Error advising file '%s'. %s.\n", path, strerror(ret));
- 93 : exit(EXIT_FAILURE);
- 94 : /* LCOV_EXCL_STOP */
- 95 : }
- 96 : }
- 97 : #endif
- 98 :
- 99 1750 : offset = 0;
- 100 6222 : for (i = 0; i < file->blockmax; ++i) {
- 101 4472 : struct snapraid_import_block* block = &file->blockimp[i];
- 102 4472 : unsigned read_size = block_size;
- 103 4472 : if (read_size > size)
- 104 1745 : read_size = size;
- 105 :
- 106 4472 : ret = read(f, buffer, read_size);
- 107 4472 : if (ret < 0 || (unsigned)ret != read_size) {
- 108 : /* LCOV_EXCL_START */
- 109 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
- 110 : exit(EXIT_FAILURE);
- 111 : /* LCOV_EXCL_STOP */
- 112 : }
- 113 :
- 114 4472 : block->file = file;
- 115 4472 : block->offset = offset;
- 116 4472 : block->size = read_size;
- 117 :
- 118 4472 : memhash(state->hash, state->hashseed, block->hash, buffer, read_size);
- 119 4472 : tommy_hashdyn_insert(&state->importset, &block->nodeset, block, import_block_hash(block->hash));
- 120 :
- 121 : /* if we are in a rehash state */
- 122 4472 : if (state->prevhash != HASH_UNDEFINED) {
- 123 : /* compute also the previous hash */
- 124 4472 : memhash(state->prevhash, state->prevhashseed, block->prevhash, buffer, read_size);
- 125 4472 : tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash));
- 126 : }
- 127 :
- 128 4472 : offset += read_size;
- 129 4472 : size -= read_size;
- 130 : }
- 131 :
- 132 1750 : ret = close(f);
- 133 1750 : if (ret != 0) {
- 134 : /* LCOV_EXCL_START */
- 135 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
- 136 : exit(EXIT_FAILURE);
- 137 : /* LCOV_EXCL_STOP */
- 138 : }
- 139 :
- 140 1750 : tommy_list_insert_tail(&state->importlist, &file->nodelist, file);
- 141 :
- 142 1750 : free(buffer);
- 143 1750 : }
- 144 :
- 145 1750 : void import_file_free(struct snapraid_import_file* file)
- 146 : {
- 147 1750 : free(file->path);
- 148 1750 : free(file->blockimp);
- 149 1750 : free(file);
- 150 1750 : }
- 151 :
- 152 643998 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer)
- 153 : {
- 154 : struct snapraid_import_block* block;
- 155 : int ret;
- 156 : int f;
- 157 643998 : const unsigned char* hash = missing_block->hash;
- 158 643998 : unsigned block_size = state->block_size;
- 159 : unsigned read_size;
- 160 : unsigned char buffer_hash[HASH_SIZE];
- 161 : const char* path;
- 162 :
- 163 643998 : if (rehash) {
- 164 28986 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash));
- 165 : } else {
- 166 615012 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash));
- 167 : }
- 168 643998 : if (!block)
- 169 639526 : return -1;
- 170 :
- 171 4472 : path = block->file->path;
- 172 4472 : read_size = block->size;
- 173 :
- 174 4472 : f = open(path, O_RDONLY | O_BINARY);
- 175 4472 : if (f == -1) {
- 176 : /* LCOV_EXCL_START */
- 177 : if (errno == ENOENT) {
- 178 : log_fatal("DANGER! file '%s' disappeared.\n", path);
- 179 : log_fatal("If you moved it, please rerun the same command.\n");
- 180 : } else {
- 181 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno));
- 182 : }
- 183 : exit(EXIT_FAILURE);
- 184 : /* LCOV_EXCL_STOP */
- 185 : }
- 186 :
- 187 4472 : if (lseek(f, block->offset, SEEK_SET) != block->offset) {
- 188 : /* LCOV_EXCL_START */
- 189 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno));
- 190 : exit(EXIT_FAILURE);
- 191 : /* LCOV_EXCL_STOP */
- 192 : }
- 193 :
- 194 4472 : ret = read(f, buffer, read_size);
- 195 4472 : if (ret < 0 || (unsigned)ret != read_size) {
- 196 : /* LCOV_EXCL_START */
- 197 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
- 198 : exit(EXIT_FAILURE);
- 199 : /* LCOV_EXCL_STOP */
- 200 : }
- 201 :
- 202 4472 : ret = close(f);
- 203 4472 : if (ret != 0) {
- 204 : /* LCOV_EXCL_START */
- 205 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
- 206 : exit(EXIT_FAILURE);
- 207 : /* LCOV_EXCL_STOP */
- 208 : }
- 209 :
- 210 4472 : if (read_size != block_size) {
- 211 : /* fill the remaining with 0 */
- 212 1745 : memset(buffer + read_size, 0, block_size - read_size);
- 213 : }
- 214 :
- 215 : /* recheck the hash */
- 216 4472 : if (rehash)
- 217 2238 : memhash(state->prevhash, state->prevhashseed, buffer_hash, buffer, read_size);
- 218 : else
- 219 2234 : memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size);
- 220 :
- 221 4472 : if (memcmp(buffer_hash, hash, HASH_SIZE) != 0) {
- 222 : /* LCOV_EXCL_START */
- 223 : log_fatal("Error in data reading file '%s'.\n", path);
- 224 : log_fatal("Please don't change imported files while running.\n");
- 225 : exit(EXIT_FAILURE);
- 226 : /* LCOV_EXCL_STOP */
- 227 : }
- 228 :
- 229 4472 : return 0;
- 230 : }
- 231 :
- 232 1 : static void import_dir(struct snapraid_state* state, const char* dir)
- 233 : {
- 234 : DIR* d;
- 235 :
- 236 1 : d = opendir(dir);
- 237 1 : if (!d) {
- 238 : /* LCOV_EXCL_START */
- 239 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
- 240 : exit(EXIT_FAILURE);
- 241 : /* LCOV_EXCL_STOP */
- 242 : }
- 243 :
- 244 : while (1) {
- 245 : char path_next[PATH_MAX];
- 246 : struct stat st;
- 247 : const char* name;
- 248 : struct dirent* dd;
- 249 :
- 250 : /* clear errno to detect erroneous conditions */
- 251 1812 : errno = 0;
- 252 1812 : dd = readdir(d);
- 253 1812 : if (dd == 0 && errno != 0) {
- 254 : /* LCOV_EXCL_START */
- 255 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
- 256 : exit(EXIT_FAILURE);
- 257 : /* LCOV_EXCL_STOP */
- 258 : }
- 259 1812 : if (dd == 0) {
- 260 1 : break; /* finished */
- 261 : }
- 262 :
- 263 : /* skip "." and ".." files */
- 264 1811 : name = dd->d_name;
- 265 1811 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
- 266 2 : continue;
- 267 :
- 268 1809 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
- 269 :
- 270 : #if HAVE_STRUCT_DIRENT_D_STAT
- 271 : /* convert dirent to lstat result */
- 272 : dirent_lstat(dd, &st);
- 273 :
- 274 : /* if the st_mode field is missing, takes care to fill it using normal lstat() */
- 275 : /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */
- 276 : /* because we use a directory reading method that doesn't read info about ReparsePoint. */
- 277 : /* Note that here we cannot call here lstat_sync(), because we don't know what kind */
- 278 : /* of file is it, and lstat_sync() doesn't always work */
- 279 : if (st.st_mode == 0) {
- 280 : if (lstat(path_next, &st) != 0) {
- 281 : /* LCOV_EXCL_START */
- 282 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
- 283 : exit(EXIT_FAILURE);
- 284 : /* LCOV_EXCL_STOP */
- 285 : }
- 286 : }
- 287 : #else
- 288 : /* get lstat info about the file */
- 289 1809 : if (lstat(path_next, &st) != 0) {
- 290 : /* LCOV_EXCL_START */
- 291 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
- 292 : exit(EXIT_FAILURE);
- 293 : /* LCOV_EXCL_STOP */
- 294 : }
- 295 : #endif
- 296 :
- 297 1809 : if (S_ISREG(st.st_mode)) {
- 298 1750 : import_file(state, path_next, st.st_size);
- 299 59 : } else if (S_ISDIR(st.st_mode)) {
- 300 0 : pathslash(path_next, sizeof(path_next));
- 301 0 : import_dir(state, path_next);
- 302 : }
- 303 1811 : }
- 304 :
- 305 1 : if (closedir(d) != 0) {
- 306 : /* LCOV_EXCL_START */
- 307 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
- 308 : exit(EXIT_FAILURE);
- 309 : /* LCOV_EXCL_STOP */
- 310 : }
- 311 1 : }
- 312 :
- 313 1 : void state_import(struct snapraid_state* state, const char* dir)
- 314 : {
- 315 : char path[PATH_MAX];
- 316 :
- 317 1 : msg_progress("Importing...\n");
- 318 :
- 319 : /* add the final slash */
- 320 1 : pathimport(path, sizeof(path), dir);
- 321 1 : pathslash(path, sizeof(path));
- 322 :
- 323 1 : import_dir(state, path);
- 324 1 : }
- 325 :
+ 51 : /* the hash data is not aligned, and we cannot access it with a direct cast */
+ 52 657660 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24);
+ 53 : }
+ 54 :
+ 55 1750 : static void import_file(struct snapraid_state* state, const char* path, uint64_t size)
+ 56 : {
+ 57 : struct snapraid_import_file* file;
+ 58 : block_off_t i;
+ 59 : data_off_t offset;
+ 60 : void* buffer;
+ 61 : int ret;
+ 62 : int f;
+ 63 : int flags;
+ 64 1750 : unsigned block_size = state->block_size;
+ 65 :
+ 66 1750 : file = malloc_nofail(sizeof(struct snapraid_import_file));
+ 67 1750 : file->path = strdup_nofail(path);
+ 68 1750 : file->size = size;
+ 69 1750 : file->blockmax = (size + block_size - 1) / block_size;
+ 70 1750 : file->blockimp = malloc_nofail(file->blockmax * sizeof(struct snapraid_import_block));
+ 71 :
+ 72 1750 : buffer = malloc_nofail(block_size);
+ 73 :
+ 74 : /* open for read */
+ 75 : /* O_SEQUENTIAL: opening in sequential mode in Windows */
+ 76 1750 : flags = O_RDONLY | O_BINARY;
+ 77 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0)
+ 78 1750 : flags |= O_SEQUENTIAL;
+ 79 1750 : f = open(path, flags);
+ 80 1750 : if (f == -1) {
+ 81 : /* LCOV_EXCL_START */
+ 82 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno));
+ 83 : exit(EXIT_FAILURE);
+ 84 : /* LCOV_EXCL_STOP */
+ 85 : }
+ 86 :
+ 87 : #if HAVE_POSIX_FADVISE
+ 88 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) {
+ 89 : /* advise sequential access */
+ 90 1750 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 91 1750 : if (ret != 0) {
+ 92 : /* LCOV_EXCL_START */
+ 93 : log_fatal("Error advising file '%s'. %s.\n", path, strerror(ret));
+ 94 : exit(EXIT_FAILURE);
+ 95 : /* LCOV_EXCL_STOP */
+ 96 : }
+ 97 : }
+ 98 : #endif
+ 99 :
+ 100 1750 : offset = 0;
+ 101 6222 : for (i = 0; i < file->blockmax; ++i) {
+ 102 4472 : struct snapraid_import_block* block = &file->blockimp[i];
+ 103 4472 : unsigned read_size = block_size;
+ 104 4472 : if (read_size > size)
+ 105 1745 : read_size = size;
+ 106 :
+ 107 4472 : ret = read(f, buffer, read_size);
+ 108 4472 : if (ret < 0 || (unsigned)ret != read_size) {
+ 109 : /* LCOV_EXCL_START */
+ 110 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
+ 111 : exit(EXIT_FAILURE);
+ 112 : /* LCOV_EXCL_STOP */
+ 113 : }
+ 114 :
+ 115 4472 : block->file = file;
+ 116 4472 : block->offset = offset;
+ 117 4472 : block->size = read_size;
+ 118 :
+ 119 4472 : memhash(state->hash, state->hashseed, block->hash, buffer, read_size);
+ 120 4472 : tommy_hashdyn_insert(&state->importset, &block->nodeset, block, import_block_hash(block->hash));
+ 121 :
+ 122 : /* if we are in a rehash state */
+ 123 4472 : if (state->prevhash != HASH_UNDEFINED) {
+ 124 : /* compute also the previous hash */
+ 125 0 : memhash(state->prevhash, state->prevhashseed, block->prevhash, buffer, read_size);
+ 126 0 : tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash));
+ 127 : }
+ 128 :
+ 129 4472 : offset += read_size;
+ 130 4472 : size -= read_size;
+ 131 : }
+ 132 :
+ 133 1750 : ret = close(f);
+ 134 1750 : if (ret != 0) {
+ 135 : /* LCOV_EXCL_START */
+ 136 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
+ 137 : exit(EXIT_FAILURE);
+ 138 : /* LCOV_EXCL_STOP */
+ 139 : }
+ 140 :
+ 141 1750 : tommy_list_insert_tail(&state->importlist, &file->nodelist, file);
+ 142 :
+ 143 1750 : free(buffer);
+ 144 1750 : }
+ 145 :
+ 146 1750 : void import_file_free(struct snapraid_import_file* file)
+ 147 : {
+ 148 1750 : free(file->path);
+ 149 1750 : free(file->blockimp);
+ 150 1750 : free(file);
+ 151 1750 : }
+ 152 :
+ 153 653188 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer)
+ 154 : {
+ 155 : struct snapraid_import_block* block;
+ 156 : int ret;
+ 157 : int f;
+ 158 653188 : const unsigned char* hash = missing_block->hash;
+ 159 653188 : unsigned block_size = state->block_size;
+ 160 : unsigned read_size;
+ 161 : unsigned char buffer_hash[HASH_SIZE];
+ 162 : const char* path;
+ 163 :
+ 164 653188 : if (rehash) {
+ 165 0 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash));
+ 166 : } else {
+ 167 653188 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash));
+ 168 : }
+ 169 653188 : if (!block)
+ 170 648716 : return -1;
+ 171 :
+ 172 4472 : path = block->file->path;
+ 173 4472 : read_size = block->size;
+ 174 :
+ 175 4472 : f = open(path, O_RDONLY | O_BINARY);
+ 176 4472 : if (f == -1) {
+ 177 : /* LCOV_EXCL_START */
+ 178 : if (errno == ENOENT) {
+ 179 : log_fatal("DANGER! file '%s' disappeared.\n", path);
+ 180 : log_fatal("If you moved it, please rerun the same command.\n");
+ 181 : } else {
+ 182 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno));
+ 183 : }
+ 184 : exit(EXIT_FAILURE);
+ 185 : /* LCOV_EXCL_STOP */
+ 186 : }
+ 187 :
+ 188 4472 : if (lseek(f, block->offset, SEEK_SET) != block->offset) {
+ 189 : /* LCOV_EXCL_START */
+ 190 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno));
+ 191 : exit(EXIT_FAILURE);
+ 192 : /* LCOV_EXCL_STOP */
+ 193 : }
+ 194 :
+ 195 4472 : ret = read(f, buffer, read_size);
+ 196 4472 : if (ret < 0 || (unsigned)ret != read_size) {
+ 197 : /* LCOV_EXCL_START */
+ 198 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
+ 199 : exit(EXIT_FAILURE);
+ 200 : /* LCOV_EXCL_STOP */
+ 201 : }
+ 202 :
+ 203 4472 : ret = close(f);
+ 204 4472 : if (ret != 0) {
+ 205 : /* LCOV_EXCL_START */
+ 206 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
+ 207 : exit(EXIT_FAILURE);
+ 208 : /* LCOV_EXCL_STOP */
+ 209 : }
+ 210 :
+ 211 4472 : if (read_size != block_size) {
+ 212 : /* fill the remaining with 0 */
+ 213 1745 : memset(buffer + read_size, 0, block_size - read_size);
+ 214 : }
+ 215 :
+ 216 : /* recheck the hash */
+ 217 4472 : if (rehash)
+ 218 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, buffer, read_size);
+ 219 : else
+ 220 4472 : memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size);
+ 221 :
+ 222 4472 : if (memcmp(buffer_hash, hash, HASH_SIZE) != 0) {
+ 223 : /* LCOV_EXCL_START */
+ 224 : log_fatal("Error in data reading file '%s'.\n", path);
+ 225 : log_fatal("Please don't change imported files while running.\n");
+ 226 : exit(EXIT_FAILURE);
+ 227 : /* LCOV_EXCL_STOP */
+ 228 : }
+ 229 :
+ 230 4472 : return 0;
+ 231 : }
+ 232 :
+ 233 1 : static void import_dir(struct snapraid_state* state, const char* dir)
+ 234 : {
+ 235 : DIR* d;
+ 236 :
+ 237 1 : d = opendir(dir);
+ 238 1 : if (!d) {
+ 239 : /* LCOV_EXCL_START */
+ 240 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
+ 241 : exit(EXIT_FAILURE);
+ 242 : /* LCOV_EXCL_STOP */
+ 243 : }
+ 244 :
+ 245 : while (1) {
+ 246 : char path_next[PATH_MAX];
+ 247 : struct stat st;
+ 248 : const char* name;
+ 249 : struct dirent* dd;
+ 250 :
+ 251 : /* clear errno to detect erroneous conditions */
+ 252 1812 : errno = 0;
+ 253 1812 : dd = readdir(d);
+ 254 1812 : if (dd == 0 && errno != 0) {
+ 255 : /* LCOV_EXCL_START */
+ 256 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
+ 257 : exit(EXIT_FAILURE);
+ 258 : /* LCOV_EXCL_STOP */
+ 259 : }
+ 260 1812 : if (dd == 0) {
+ 261 1 : break; /* finished */
+ 262 : }
+ 263 :
+ 264 : /* skip "." and ".." files */
+ 265 1811 : name = dd->d_name;
+ 266 1811 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+ 267 2 : continue;
+ 268 :
+ 269 1809 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 270 :
+ 271 : #if HAVE_STRUCT_DIRENT_D_STAT
+ 272 : /* convert dirent to lstat result */
+ 273 : dirent_lstat(dd, &st);
+ 274 :
+ 275 : /* if the st_mode field is missing, takes care to fill it using normal lstat() */
+ 276 : /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */
+ 277 : /* because we use a directory reading method that doesn't read info about ReparsePoint. */
+ 278 : /* Note that here we cannot call here lstat_sync(), because we don't know what kind */
+ 279 : /* of file is it, and lstat_sync() doesn't always work */
+ 280 : if (st.st_mode == 0) {
+ 281 : if (lstat(path_next, &st) != 0) {
+ 282 : /* LCOV_EXCL_START */
+ 283 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
+ 284 : exit(EXIT_FAILURE);
+ 285 : /* LCOV_EXCL_STOP */
+ 286 : }
+ 287 : }
+ 288 : #else
+ 289 : /* get lstat info about the file */
+ 290 1809 : if (lstat(path_next, &st) != 0) {
+ 291 : /* LCOV_EXCL_START */
+ 292 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
+ 293 : exit(EXIT_FAILURE);
+ 294 : /* LCOV_EXCL_STOP */
+ 295 : }
+ 296 : #endif
+ 297 :
+ 298 1809 : if (S_ISREG(st.st_mode)) {
+ 299 1750 : import_file(state, path_next, st.st_size);
+ 300 59 : } else if (S_ISDIR(st.st_mode)) {
+ 301 0 : pathslash(path_next, sizeof(path_next));
+ 302 0 : import_dir(state, path_next);
+ 303 : }
+ 304 1811 : }
+ 305 :
+ 306 1 : if (closedir(d) != 0) {
+ 307 : /* LCOV_EXCL_START */
+ 308 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
+ 309 : exit(EXIT_FAILURE);
+ 310 : /* LCOV_EXCL_STOP */
+ 311 : }
+ 312 1 : }
+ 313 :
+ 314 1 : void state_import(struct snapraid_state* state, const char* dir)
+ 315 : {
+ 316 : char path[PATH_MAX];
+ 317 :
+ 318 1 : msg_progress("Importing...\n");
+ 319 :
+ 320 : /* add the final slash */
+ 321 1 : pathimport(path, sizeof(path), dir);
+ 322 1 : pathslash(path, sizeof(path));
+ 323 :
+ 324 1 : import_dir(state, path);
+ 325 1 : }
+ 326 :
diff --git a/cov/cmdline/index-sort-f.html b/cov/cmdline/index-sort-f.html
index 7e050b55..4610da17 100644
--- a/cov/cmdline/index-sort-f.html
+++ b/cov/cmdline/index-sort-f.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -69,6 +69,16 @@
Line Coverage  |
Functions  |
+
+ | import.c |
+
+
+ |
+ 90.5 % |
+ 95 / 105 |
+ 87.5 % |
+ 7 / 8 |
+
| parity.c |
@@ -92,22 +102,32 @@
|
| unix.c |
-
+
|
- 79.2 % |
- 229 / 289 |
- 91.3 % |
- 21 / 23 |
+ 76.8 % |
+ 255 / 332 |
+ 92.0 % |
+ 23 / 25 |
| support.c |
-
+
|
- 79.2 % |
- 232 / 293 |
- 93.5 % |
- 29 / 31 |
+ 79.7 % |
+ 240 / 301 |
+ 93.8 % |
+ 30 / 32 |
+
+
+ | stream.c |
+
+
+ |
+ 91.8 % |
+ 257 / 280 |
+ 96.4 % |
+ 27 / 28 |
| elem.c |
@@ -115,19 +135,19 @@
93.8 % |
- 545 / 581 |
+ 546 / 582 |
96.9 % |
62 / 64 |
| state.c |
-
+
|
- 92.4 % |
- 1248 / 1351 |
- 97.2 % |
- 35 / 36 |
+ 92.6 % |
+ 1262 / 1363 |
+ 97.3 % |
+ 36 / 37 |
| nano.c |
@@ -292,70 +312,60 @@
| search.c |
-
+
|
- 92.0 % |
- 92 / 100 |
+ 91.0 % |
+ 91 / 100 |
100.0 % |
7 / 7 |
-
- | import.c |
-
-
- |
- 98.1 % |
- 103 / 105 |
- 100.0 % |
- 8 / 8 |
-
| handle.c |
|
97.7 % |
- 125 / 128 |
+ 126 / 129 |
100.0 % |
8 / 8 |
| selftest.c |
-
+
|
- 83.7 % |
- 144 / 172 |
+ 100.0 % |
+ 144 / 144 |
100.0 % |
8 / 8 |
| snapraid.c |
-
+
|
- 94.1 % |
- 446 / 474 |
+ 93.8 % |
+ 454 / 484 |
100.0 % |
8 / 8 |
| check.c |
-
+
|
- 91.3 % |
- 713 / 781 |
+ 91.2 % |
+ 712 / 781 |
100.0 % |
9 / 9 |
| device.c |
-
+
|
- 94.3 % |
- 300 / 318 |
+ 94.1 % |
+ 301 / 320 |
100.0 % |
11 / 11 |
@@ -382,23 +392,13 @@
| scan.c |
-
+
|
- 87.4 % |
- 542 / 620 |
+ 89.1 % |
+ 554 / 622 |
100.0 % |
23 / 23 |
-
- | stream.c |
-
-
- |
- 93.2 % |
- 261 / 280 |
- 100.0 % |
- 28 / 28 |
-
| elem.h |
diff --git a/cov/cmdline/index-sort-l.html b/cov/cmdline/index-sort-l.html
index 8aa34497..e8ea2475 100644
--- a/cov/cmdline/index-sort-l.html
+++ b/cov/cmdline/index-sort-l.html
@@ -31,18 +31,18 @@
|
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -70,14 +70,14 @@
Functions  |
- | support.c |
+ unix.c |
-
+
|
- 79.2 % |
- 232 / 293 |
- 93.5 % |
- 29 / 31 |
+ 76.8 % |
+ 255 / 332 |
+ 92.0 % |
+ 23 / 25 |
| parity.c |
@@ -89,16 +89,6 @@
90.9 % |
10 / 11 |
-
- | unix.c |
-
-
- |
- 79.2 % |
- 229 / 289 |
- 91.3 % |
- 21 / 23 |
-
| scrub.c |
@@ -110,14 +100,14 @@
| 4 / 4 |
- | selftest.c |
+ support.c |
-
+
|
- 83.7 % |
- 144 / 172 |
- 100.0 % |
- 8 / 8 |
+ 79.7 % |
+ 240 / 301 |
+ 93.8 % |
+ 30 / 32 |
| dry.c |
@@ -132,10 +122,10 @@
| scan.c |
-
+
|
- 87.4 % |
- 542 / 620 |
+ 89.1 % |
+ 554 / 622 |
100.0 % |
23 / 23 |
@@ -150,34 +140,54 @@
10 / 11 |
- | check.c |
+ import.c |
-
+
|
- 91.3 % |
- 713 / 781 |
- 100.0 % |
- 9 / 9 |
+ 90.5 % |
+ 95 / 105 |
+ 87.5 % |
+ 7 / 8 |
| search.c |
-
+
|
- 92.0 % |
- 92 / 100 |
+ 91.0 % |
+ 91 / 100 |
100.0 % |
7 / 7 |
+
+ | check.c |
+
+
+ |
+ 91.2 % |
+ 712 / 781 |
+ 100.0 % |
+ 9 / 9 |
+
+
+ | stream.c |
+
+
+ |
+ 91.8 % |
+ 257 / 280 |
+ 96.4 % |
+ 27 / 28 |
+
| state.c |
-
+
|
- 92.4 % |
- 1248 / 1351 |
- 97.2 % |
- 35 / 36 |
+ 92.6 % |
+ 1262 / 1363 |
+ 97.3 % |
+ 36 / 37 |
| sync.c |
@@ -199,16 +209,6 @@
100.0 % |
18 / 18 |
-
- | stream.c |
-
-
- |
- 93.2 % |
- 261 / 280 |
- 100.0 % |
- 28 / 28 |
-
| util.h |
@@ -229,25 +229,35 @@
| 100.0 % |
5 / 5 |
+
+ | snapraid.c |
+
+
+ |
+ 93.8 % |
+ 454 / 484 |
+ 100.0 % |
+ 8 / 8 |
+
| elem.c |
|
93.8 % |
- 545 / 581 |
+ 546 / 582 |
96.9 % |
62 / 64 |
- | snapraid.c |
+ device.c |
|
94.1 % |
- 446 / 474 |
+ 301 / 320 |
100.0 % |
- 8 / 8 |
+ 11 / 11 |
| pool.c |
@@ -259,16 +269,6 @@
100.0 % |
3 / 3 |
-
- | device.c |
-
-
- |
- 94.3 % |
- 300 / 318 |
- 100.0 % |
- 11 / 11 |
-
| rehash.c |
@@ -305,17 +305,7 @@
|
97.7 % |
- 125 / 128 |
- 100.0 % |
- 8 / 8 |
-
-
- | import.c |
-
-
- |
- 98.1 % |
- 103 / 105 |
+ 126 / 129 |
100.0 % |
8 / 8 |
@@ -409,6 +399,16 @@
100.0 % |
2 / 2 |
+
+ | selftest.c |
+
+
+ |
+ 100.0 % |
+ 144 / 144 |
+ 100.0 % |
+ 8 / 8 |
+
diff --git a/cov/cmdline/index.html b/cov/cmdline/index.html
index 8449d375..852332c6 100644
--- a/cov/cmdline/index.html
+++ b/cov/cmdline/index.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,20 +72,20 @@
| check.c |
-
+
|
- 91.3 % |
- 713 / 781 |
+ 91.2 % |
+ 712 / 781 |
100.0 % |
9 / 9 |
| device.c |
-
+
|
- 94.3 % |
- 300 / 318 |
+ 94.1 % |
+ 301 / 320 |
100.0 % |
11 / 11 |
@@ -115,7 +115,7 @@
93.8 % |
- 545 / 581 |
+ 546 / 582 |
96.9 % |
62 / 64 |
@@ -135,19 +135,19 @@
97.7 % |
- 125 / 128 |
+ 126 / 129 |
100.0 % |
8 / 8 |
| import.c |
-
+
|
- 98.1 % |
- 103 / 105 |
- 100.0 % |
- 8 / 8 |
+ 90.5 % |
+ 95 / 105 |
+ 87.5 % |
+ 7 / 8 |
| list.c |
@@ -242,10 +242,10 @@
| scan.c |
-
+
|
- 87.4 % |
- 542 / 620 |
+ 89.1 % |
+ 554 / 622 |
100.0 % |
23 / 23 |
@@ -262,30 +262,30 @@
| search.c |
-
+
|
- 92.0 % |
- 92 / 100 |
+ 91.0 % |
+ 91 / 100 |
100.0 % |
7 / 7 |
| selftest.c |
-
+
|
- 83.7 % |
- 144 / 172 |
+ 100.0 % |
+ 144 / 144 |
100.0 % |
8 / 8 |
| snapraid.c |
-
+
|
- 94.1 % |
- 446 / 474 |
+ 93.8 % |
+ 454 / 484 |
100.0 % |
8 / 8 |
@@ -312,12 +312,12 @@
| state.c |
-
+
|
- 92.4 % |
- 1248 / 1351 |
- 97.2 % |
- 35 / 36 |
+ 92.6 % |
+ 1262 / 1363 |
+ 97.3 % |
+ 36 / 37 |
| state.h |
@@ -342,12 +342,12 @@
| stream.c |
-
+
|
- 93.2 % |
- 261 / 280 |
- 100.0 % |
- 28 / 28 |
+ 91.8 % |
+ 257 / 280 |
+ 96.4 % |
+ 27 / 28 |
| stream.h |
@@ -362,12 +362,12 @@
| support.c |
-
+
|
- 79.2 % |
- 232 / 293 |
- 93.5 % |
- 29 / 31 |
+ 79.7 % |
+ 240 / 301 |
+ 93.8 % |
+ 30 / 32 |
| sync.c |
@@ -382,12 +382,12 @@
| unix.c |
-
+
|
- 79.2 % |
- 229 / 289 |
- 91.3 % |
- 21 / 23 |
+ 76.8 % |
+ 255 / 332 |
+ 92.0 % |
+ 23 / 25 |
| util.c |
diff --git a/cov/cmdline/list.c.func-sort-c.html b/cov/cmdline/list.c.func-sort-c.html
index 8a842797..a1d33ff3 100644
--- a/cov/cmdline/list.c.func-sort-c.html
+++ b/cov/cmdline/list.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/list.c.func.html b/cov/cmdline/list.c.func.html
index 6de816a4..77720432 100644
--- a/cov/cmdline/list.c.func.html
+++ b/cov/cmdline/list.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/list.c.gcov.html b/cov/cmdline/list.c.gcov.html
index 6d26e742..41e63009 100644
--- a/cov/cmdline/list.c.gcov.html
+++ b/cov/cmdline/list.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -110,34 +110,34 @@
48 18 : tommy_list_sort(&disk->filelist, file_path_compare);
49 :
50 : /* for each file */
- 51 16998 : for (j = disk->filelist; j != 0; j = j->next) {
- 52 16980 : struct snapraid_file* file = j->data;
+ 51 17012 : for (j = disk->filelist; j != 0; j = j->next) {
+ 52 16994 : struct snapraid_file* file = j->data;
53 : #if HAVE_LOCALTIME_R
54 : struct tm tm_res;
55 : #endif
56 : struct tm* tm;
57 : time_t t;
58 :
- 59 16980 : ++file_count;
- 60 16980 : file_size += file->size;
+ 59 16994 : ++file_count;
+ 60 16994 : file_size += file->size;
61 :
- 62 16980 : log_tag("file:%s:%s:%" PRIu64 ":%" PRIi64 ":%u:%" PRIi64 "\n", disk->name, esc(file->sub), file->size, file->mtime_sec, file->mtime_nsec, file->inode);
+ 62 16994 : log_tag("file:%s:%s:%" PRIu64 ":%" PRIi64 ":%u:%" PRIi64 "\n", disk->name, esc(file->sub), file->size, file->mtime_sec, file->mtime_nsec, file->inode);
63 :
- 64 16980 : t = file->mtime_sec;
+ 64 16994 : t = file->mtime_sec;
65 : #if HAVE_LOCALTIME_R
- 66 16980 : tm = localtime_r(&t, &tm_res);
+ 66 16994 : tm = localtime_r(&t, &tm_res);
67 : #else
68 : tm = localtime(&t);
69 : #endif
70 :
- 71 16980 : printf("%12" PRIu64 " ", file->size);
- 72 16980 : if (tm) {
- 73 16980 : printf("%04u/%02u/%02u %02u:%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
- 74 16980 : if (msg_level >= MSG_VERBOSE)
- 75 16980 : printf(":%02u.%03u", tm->tm_sec, file->mtime_nsec / 1000000);
- 76 16980 : printf(" ");
+ 71 16994 : printf("%12" PRIu64 " ", file->size);
+ 72 16994 : if (tm) {
+ 73 16994 : printf("%04u/%02u/%02u %02u:%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+ 74 16994 : if (msg_level >= MSG_VERBOSE)
+ 75 16994 : printf(":%02u.%03u", tm->tm_sec, file->mtime_nsec / 1000000);
+ 76 16994 : printf(" ");
77 : }
- 78 16980 : printf("%s%s\n", disk->dir, file->sub);
+ 78 16994 : printf("%s%s\n", disk->dir, file->sub);
79 : }
80 :
81 : /* sort by name */
diff --git a/cov/cmdline/mkstream.c.func-sort-c.html b/cov/cmdline/mkstream.c.func-sort-c.html
index 0ef05fdf..e22bee50 100644
--- a/cov/cmdline/mkstream.c.func-sort-c.html
+++ b/cov/cmdline/mkstream.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/mkstream.c.func.html b/cov/cmdline/mkstream.c.func.html
index bd99773d..5b87fdd6 100644
--- a/cov/cmdline/mkstream.c.func.html
+++ b/cov/cmdline/mkstream.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/mkstream.c.gcov.html b/cov/cmdline/mkstream.c.gcov.html
index f02e9bf5..7c9b10f2 100644
--- a/cov/cmdline/mkstream.c.gcov.html
+++ b/cov/cmdline/mkstream.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/mktest.c.func-sort-c.html b/cov/cmdline/mktest.c.func-sort-c.html
index 60c06d2d..2268a650 100644
--- a/cov/cmdline/mktest.c.func-sort-c.html
+++ b/cov/cmdline/mktest.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| rnd |
- 50988385 |
+ 50969532 |
| rndnz |
- 50578180 |
+ 50559223 |
| file_cmp |
- 146608 |
+ 146593 |
| rndnz_range |
- 31195 |
+ 31151 |
| rnd_name |
- 26824 |
+ 26849 |
| cmd_generate |
@@ -93,19 +93,19 @@
| cmd_write |
- 4703 |
-
-
- | cmd_append |
- 3252 |
+ 4719 |
| cmd_delete |
- 3155 |
+ 3209 |
+
+
+ | cmd_append |
+ 3192 |
| cmd_truncate |
- 3151 |
+ 3139 |
| cmd_damage |
@@ -121,7 +121,7 @@
| cmd_generate_symlink |
- 915 |
+ 940 |
| main |
diff --git a/cov/cmdline/mktest.c.func.html b/cov/cmdline/mktest.c.func.html
index 96c88f25..3b8f65ae 100644
--- a/cov/cmdline/mktest.c.func.html
+++ b/cov/cmdline/mktest.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| cmd_append |
- 3252 |
+ 3192 |
| cmd_change |
@@ -73,7 +73,7 @@
| cmd_delete |
- 3155 |
+ 3209 |
| cmd_generate |
@@ -85,15 +85,15 @@
| cmd_generate_symlink |
- 915 |
+ 940 |
| cmd_truncate |
- 3151 |
+ 3139 |
| cmd_write |
- 4703 |
+ 4719 |
| fallback |
@@ -101,7 +101,7 @@
| file_cmp |
- 146608 |
+ 146593 |
| help |
@@ -113,15 +113,15 @@
| rnd |
- 50988385 |
+ 50969532 |
| rnd_name |
- 26824 |
+ 26849 |
| rndnz |
- 50578180 |
+ 50559223 |
| rndnz_damage |
@@ -129,7 +129,7 @@
| rndnz_range |
- 31195 |
+ 31151 |
diff --git a/cov/cmdline/mktest.c.gcov.html b/cov/cmdline/mktest.c.gcov.html
index 501823e9..2f63044d 100644
--- a/cov/cmdline/mktest.c.gcov.html
+++ b/cov/cmdline/mktest.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -89,28 +89,28 @@
27 : */
28 : unsigned long long seed = 0;
29 :
- 30 50988385 : unsigned rnd(unsigned max)
+ 30 50969532 : unsigned rnd(unsigned max)
31 : {
- 32 50988385 : seed = seed * 6364136223846793005LL + 1442695040888963407LL;
+ 32 50969532 : seed = seed * 6364136223846793005LL + 1442695040888963407LL;
33 :
- 34 50988385 : return (seed >> 32) % max;
+ 34 50969532 : return (seed >> 32) % max;
35 : }
36 :
- 37 50578180 : unsigned rndnz(unsigned max)
+ 37 50559223 : unsigned rndnz(unsigned max)
38 : {
- 39 50578180 : if (max <= 1)
+ 39 50559223 : if (max <= 1)
40 2831 : return 1;
41 : else
- 42 50575349 : return rnd(max - 1) + 1;
+ 42 50556392 : return rnd(max - 1) + 1;
43 : }
44 :
- 45 31195 : void rndnz_range(unsigned char* data, int size)
+ 45 31151 : void rndnz_range(unsigned char* data, int size)
46 : {
47 : int i;
48 :
- 49 50604116 : for (i = 0; i < size; ++i)
- 50 50572921 : data[i] = rndnz(256);
- 51 31195 : }
+ 49 50585115 : for (i = 0; i < size; ++i)
+ 50 50553964 : data[i] = rndnz(256);
+ 51 31151 : }
52 :
53 1821 : void rndnz_damage(unsigned char* data, int size)
54 : {
@@ -131,23 +131,23 @@
69 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+";
70 : #define CHARSET_LEN (sizeof(CHARSET) - 1)
71 :
- 72 26824 : void rnd_name(char* file)
+ 72 26849 : void rnd_name(char* file)
73 : {
- 74 26824 : int l = 1 + rnd(20);
+ 74 26849 : int l = 1 + rnd(20);
75 :
- 76 335360 : while (l) {
- 77 281712 : *file++ = CHARSET[rnd(CHARSET_LEN)];
- 78 281712 : --l;
+ 76 335469 : while (l) {
+ 77 281771 : *file++ = CHARSET[rnd(CHARSET_LEN)];
+ 78 281771 : --l;
79 : }
- 80 26824 : *file = 0;
- 81 26824 : }
+ 80 26849 : *file = 0;
+ 81 26849 : }
82 :
83 : /****************************************************************************/
84 : /* file */
85 :
- 86 146608 : int file_cmp(const void* a, const void* b)
+ 86 146593 : int file_cmp(const void* a, const void* b)
87 : {
- 88 146608 : return strcmp(a, b);
+ 88 146593 : return strcmp(a, b);
89 : }
90 :
91 1821 : int fallback(int f, struct stat* st)
@@ -259,11 +259,11 @@
197 : * Create a symlink.
198 : * - If the file already exists, it's removed.
199 : */
- 200 915 : void cmd_generate_symlink(const char* path, const char* linkto)
+ 200 940 : void cmd_generate_symlink(const char* path, const char* linkto)
201 : {
202 : /* remove the existing file/symlink if any */
- 203 915 : if (remove(path) != 0) {
- 204 894 : if (errno != ENOENT) {
+ 203 940 : if (remove(path) != 0) {
+ 204 919 : if (errno != ENOENT) {
205 : /* LCOV_EXCL_START */
206 : log_fatal("Error removing file %s\n", path);
207 : exit(EXIT_FAILURE);
@@ -271,13 +271,13 @@
209 : }
210 : }
211 :
- 212 915 : if (symlink(linkto, path) != 0) {
+ 212 940 : if (symlink(linkto, path) != 0) {
213 : /* LCOV_EXCL_START */
214 : log_fatal("Error writing symlink %s\n", path);
215 : exit(EXIT_FAILURE);
216 : /* LCOV_EXCL_STOP */
217 : }
- 218 915 : }
+ 218 940 : }
219 :
220 : /**
221 : * Create a file or a symlink with a random name.
@@ -350,68 +350,68 @@
288 : * - The written data may be equal or not at the already existing one.
289 : * - If it's a symlink nothing is done.
290 : */
- 291 4703 : void cmd_write(const char* path, int size)
+ 291 4719 : void cmd_write(const char* path, int size)
292 : {
293 : struct stat st;
294 :
- 295 4703 : if (lstat(path, &st) != 0) {
+ 295 4719 : if (lstat(path, &st) != 0) {
296 : /* LCOV_EXCL_START */
297 : log_fatal("Error accessing %s\n", path);
298 : exit(EXIT_FAILURE);
299 : /* LCOV_EXCL_STOP */
300 : }
301 :
- 302 4703 : if (S_ISREG(st.st_mode)) {
+ 302 4719 : if (S_ISREG(st.st_mode)) {
303 : unsigned char* data;
304 : off_t off;
305 : int f;
306 :
307 : /* not over the end */
- 308 4676 : if (size > st.st_size)
- 309 179 : size = st.st_size;
+ 308 4692 : if (size > st.st_size)
+ 309 175 : size = st.st_size;
310 :
311 : /* start at random position inside the file */
- 312 4676 : if (size < st.st_size)
- 313 4496 : off = rnd(st.st_size - size);
+ 312 4692 : if (size < st.st_size)
+ 313 4517 : off = rnd(st.st_size - size);
314 : else
- 315 180 : off = 0;
+ 315 175 : off = 0;
316 :
- 317 4676 : data = malloc(size);
+ 317 4692 : data = malloc(size);
318 :
- 319 4676 : rndnz_range(data, size);
+ 319 4692 : rndnz_range(data, size);
320 :
- 321 4676 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
- 322 4676 : if (f < 0) {
+ 321 4692 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
+ 322 4692 : if (f < 0) {
323 : /* LCOV_EXCL_START */
324 : log_fatal("Error creating file %s\n", path);
325 : exit(EXIT_FAILURE);
326 : /* LCOV_EXCL_STOP */
327 : }
328 :
- 329 4676 : if (lseek(f, off, SEEK_SET) != off) {
+ 329 4692 : if (lseek(f, off, SEEK_SET) != off) {
330 : /* LCOV_EXCL_START */
331 : log_fatal("Error seeking file %s\n", path);
332 : exit(EXIT_FAILURE);
333 : /* LCOV_EXCL_STOP */
334 : }
335 :
- 336 4676 : if (write(f, data, size) != size) {
+ 336 4692 : if (write(f, data, size) != size) {
337 : /* LCOV_EXCL_START */
338 : log_fatal("Error writing file %s\n", path);
339 : exit(EXIT_FAILURE);
340 : /* LCOV_EXCL_STOP */
341 : }
342 :
- 343 4676 : if (close(f) != 0) {
+ 343 4692 : if (close(f) != 0) {
344 : /* LCOV_EXCL_START */
345 : log_fatal("Error closing file %s\n", path);
346 : exit(EXIT_FAILURE);
347 : /* LCOV_EXCL_STOP */
348 : }
349 :
- 350 4676 : free(data);
+ 350 4692 : free(data);
351 : }
- 352 4703 : }
+ 352 4719 : }
353 :
354 : /**
355 : * Damage a file.
@@ -518,50 +518,50 @@
456 : * - The file must exist.
457 : * - If it's a symlink nothing is done.
458 : */
- 459 3252 : void cmd_append(const char* path, int size)
+ 459 3192 : void cmd_append(const char* path, int size)
460 : {
461 : struct stat st;
462 :
- 463 3252 : if (lstat(path, &st) != 0) {
+ 463 3192 : if (lstat(path, &st) != 0) {
464 : /* LCOV_EXCL_START */
465 : log_fatal("Error accessing %s\n", path);
466 : exit(EXIT_FAILURE);
467 : /* LCOV_EXCL_STOP */
468 : }
469 :
- 470 3252 : if (S_ISREG(st.st_mode)) {
+ 470 3192 : if (S_ISREG(st.st_mode)) {
471 : unsigned char* data;
472 : int f;
473 :
- 474 3252 : data = malloc(size);
+ 474 3192 : data = malloc(size);
475 :
- 476 3252 : rndnz_range(data, size);
+ 476 3192 : rndnz_range(data, size);
477 :
- 478 3252 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW);
- 479 3252 : if (f < 0) {
+ 478 3192 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW);
+ 479 3192 : if (f < 0) {
480 : /* LCOV_EXCL_START */
481 : log_fatal("Error opening file %s\n", path);
482 : exit(EXIT_FAILURE);
483 : /* LCOV_EXCL_STOP */
484 : }
485 :
- 486 3252 : if (write(f, data, size) != size) {
+ 486 3192 : if (write(f, data, size) != size) {
487 : /* LCOV_EXCL_START */
488 : log_fatal("Error writing file %s\n", path);
489 : exit(EXIT_FAILURE);
490 : /* LCOV_EXCL_STOP */
491 : }
492 :
- 493 3252 : if (close(f) != 0) {
+ 493 3192 : if (close(f) != 0) {
494 : /* LCOV_EXCL_START */
495 : log_fatal("Error closing file %s\n", path);
496 : exit(EXIT_FAILURE);
497 : /* LCOV_EXCL_STOP */
498 : }
499 :
- 500 3252 : free(data);
+ 500 3192 : free(data);
501 : }
- 502 3252 : }
+ 502 3192 : }
503 :
504 : /**
505 : * Truncate a file.
@@ -569,69 +569,69 @@
507 : * - The file is NEVER truncated to 0.
508 : * - If it's a symlink nothing is done.
509 : */
- 510 3151 : void cmd_truncate(const char* path, int size)
+ 510 3139 : void cmd_truncate(const char* path, int size)
511 : {
512 : struct stat st;
513 :
- 514 3151 : if (lstat(path, &st) != 0) {
+ 514 3139 : if (lstat(path, &st) != 0) {
515 : /* LCOV_EXCL_START */
516 : log_fatal("Error accessing %s\n", path);
517 : exit(EXIT_FAILURE);
518 : /* LCOV_EXCL_STOP */
519 : }
520 :
- 521 3151 : if (S_ISREG(st.st_mode)) {
+ 521 3139 : if (S_ISREG(st.st_mode)) {
522 : off_t off;
523 : int f;
524 :
525 : /* if file is empty, just rewrite it */
- 526 3151 : if (st.st_size == 0) {
- 527 3 : size = 0;
+ 526 3139 : if (st.st_size == 0) {
+ 527 4 : size = 0;
528 : } else {
529 : /* don't truncate files to 0 size to avoid ZERO file size protection */
- 530 3148 : if (size >= st.st_size)
- 531 193 : size = st.st_size - 1;
+ 530 3135 : if (size >= st.st_size)
+ 531 211 : size = st.st_size - 1;
532 : }
533 :
- 534 3151 : off = st.st_size - size;
+ 534 3139 : off = st.st_size - size;
535 :
- 536 3151 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
- 537 3151 : if (f < 0) {
+ 536 3139 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
+ 537 3139 : if (f < 0) {
538 : /* LCOV_EXCL_START */
539 : log_fatal("Error opening file %s\n", path);
540 : exit(EXIT_FAILURE);
541 : /* LCOV_EXCL_STOP */
542 : }
543 :
- 544 3151 : if (ftruncate(f, off) != 0) {
+ 544 3139 : if (ftruncate(f, off) != 0) {
545 : /* LCOV_EXCL_START */
546 : log_fatal("Error truncating file %s\n", path);
547 : exit(EXIT_FAILURE);
548 : /* LCOV_EXCL_STOP */
549 : }
550 :
- 551 3151 : if (close(f) != 0) {
+ 551 3139 : if (close(f) != 0) {
552 : /* LCOV_EXCL_START */
553 : log_fatal("Error closing file %s\n", path);
554 : exit(EXIT_FAILURE);
555 : /* LCOV_EXCL_STOP */
556 : }
557 : }
- 558 3151 : }
+ 558 3139 : }
559 :
560 : /**
561 : * Delete a file.
562 : * - The file must exist.
563 : */
- 564 3155 : void cmd_delete(const char* path)
+ 564 3209 : void cmd_delete(const char* path)
565 : {
- 566 3155 : if (remove(path) != 0) {
+ 566 3209 : if (remove(path) != 0) {
567 : /* LCOV_EXCL_START */
568 : log_fatal("Error removing %s\n", path);
569 : exit(EXIT_FAILURE);
570 : /* LCOV_EXCL_STOP */
571 : }
- 572 3155 : }
+ 572 3209 : }
573 :
574 : /**
575 : * Change a file. Or deleted/truncated/append/created.
@@ -642,20 +642,20 @@
580 : struct stat st;
581 :
582 13128 : if (!size)
- 583 13152 : return;
+ 583 13153 : return;
584 :
- 585 13104 : if (lstat(path, &st) != 0) {
+ 585 13103 : if (lstat(path, &st) != 0) {
586 : /* LCOV_EXCL_START */
587 : log_fatal("Error accessing %s\n", path);
588 : exit(EXIT_FAILURE);
589 : /* LCOV_EXCL_STOP */
590 : }
591 :
- 592 13104 : if (S_ISLNK(st.st_mode)) {
+ 592 13103 : if (S_ISLNK(st.st_mode)) {
593 : /* symlink */
- 594 392 : if (rnd(2) == 0) {
+ 594 393 : if (rnd(2) == 0) {
595 : /* delete */
- 596 210 : if (remove(path) != 0) {
+ 596 186 : if (remove(path) != 0) {
597 : /* LCOV_EXCL_START */
598 : log_fatal("Error removing %s\n", path);
599 : exit(EXIT_FAILURE);
@@ -665,30 +665,30 @@
603 : /* recreate */
604 : char linkto[PATH_MAX];
605 :
- 606 182 : if (remove(path) != 0) {
+ 606 207 : if (remove(path) != 0) {
607 : /* LCOV_EXCL_START */
608 : log_fatal("Error removing %s\n", path);
609 : exit(EXIT_FAILURE);
610 : /* LCOV_EXCL_STOP */
611 : }
612 :
- 613 182 : rnd_name(linkto);
+ 613 207 : rnd_name(linkto);
614 :
- 615 182 : cmd_generate_symlink(path, linkto);
+ 615 207 : cmd_generate_symlink(path, linkto);
616 : }
- 617 12712 : } else if (S_ISREG(st.st_mode)) {
+ 617 12710 : } else if (S_ISREG(st.st_mode)) {
618 : int r;
619 :
- 620 12712 : r = rnd(4);
+ 620 12710 : r = rnd(4);
621 :
- 622 12712 : if (r == 0) {
- 623 3154 : cmd_write(path, size);
- 624 9558 : } else if (r == 1) {
- 625 3252 : cmd_append(path, size);
- 626 6306 : } else if (r == 2) {
- 627 3151 : cmd_truncate(path, size);
+ 622 12710 : if (r == 0) {
+ 623 3170 : cmd_write(path, size);
+ 624 9540 : } else if (r == 1) {
+ 625 3192 : cmd_append(path, size);
+ 626 6348 : } else if (r == 2) {
+ 627 3139 : cmd_truncate(path, size);
628 : } else {
- 629 3155 : cmd_delete(path);
+ 629 3209 : cmd_delete(path);
630 : }
631 : }
632 : }
diff --git a/cov/cmdline/murmur3.c.func-sort-c.html b/cov/cmdline/murmur3.c.func-sort-c.html
index 890c3fb1..1f49f399 100644
--- a/cov/cmdline/murmur3.c.func-sort-c.html
+++ b/cov/cmdline/murmur3.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| fmix32 |
- 9010328 |
+ 7745044 |
| MurmurHash3_x86_128 |
- 2252582 |
+ 1936261 |
diff --git a/cov/cmdline/murmur3.c.func.html b/cov/cmdline/murmur3.c.func.html
index 749722b4..aec58569 100644
--- a/cov/cmdline/murmur3.c.func.html
+++ b/cov/cmdline/murmur3.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| MurmurHash3_x86_128 |
- 2252582 |
+ 1936261 |
| fmix32 |
- 9010328 |
+ 7745044 |
diff --git a/cov/cmdline/murmur3.c.gcov.html b/cov/cmdline/murmur3.c.gcov.html
index b92c0ea0..75a6add6 100644
--- a/cov/cmdline/murmur3.c.gcov.html
+++ b/cov/cmdline/murmur3.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -91,14 +91,14 @@
29 : // domain. The author hereby disclaims copyright to this source code.
30 :
31 : /* Finalization mix - force all bits of a hash block to avalanche */
- 32 9010328 : static inline uint32_t fmix32(uint32_t h)
+ 32 7745044 : static inline uint32_t fmix32(uint32_t h)
33 : {
- 34 9010328 : h ^= h >> 16;
- 35 9010328 : h *= 0x85ebca6b;
- 36 9010328 : h ^= h >> 13;
- 37 9010328 : h *= 0xc2b2ae35;
- 38 9010328 : h ^= h >> 16;
- 39 9010328 : return h;
+ 34 7745044 : h ^= h >> 16;
+ 35 7745044 : h *= 0x85ebca6b;
+ 36 7745044 : h ^= h >> 13;
+ 37 7745044 : h *= 0xc2b2ae35;
+ 38 7745044 : h ^= h >> 16;
+ 39 7745044 : return h;
40 : }
41 :
42 : /*
@@ -137,17 +137,17 @@
75 : uint32_t c3 = 0x38b34ae5;
76 : uint32_t c4 = 0xa1e38b93;
77 :
- 78 2252582 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest)
+ 78 1936261 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest)
79 : {
80 : size_t nblocks;
81 : const uint32_t* blocks;
82 : const uint32_t* end;
83 : size_t size_remainder;
84 :
- 85 2252582 : uint32_t h1 = ((const uint32_t*)seed)[0];
- 86 2252582 : uint32_t h2 = ((const uint32_t*)seed)[1];
- 87 2252582 : uint32_t h3 = ((const uint32_t*)seed)[2];
- 88 2252582 : uint32_t h4 = ((const uint32_t*)seed)[3];
+ 85 1936261 : uint32_t h1 = ((const uint32_t*)seed)[0];
+ 86 1936261 : uint32_t h2 = ((const uint32_t*)seed)[1];
+ 87 1936261 : uint32_t h3 = ((const uint32_t*)seed)[2];
+ 88 1936261 : uint32_t h4 = ((const uint32_t*)seed)[3];
89 :
90 : #if WORDS_BIGENDIAN
91 : h1 = util_swap32(h1);
@@ -156,16 +156,16 @@
94 : h4 = util_swap32(h4);
95 : #endif
96 :
- 97 2252582 : nblocks = size / 16;
- 98 2252582 : blocks = data;
- 99 2252582 : end = blocks + nblocks * 4;
+ 97 1936261 : nblocks = size / 16;
+ 98 1936261 : blocks = data;
+ 99 1936261 : end = blocks + nblocks * 4;
100 :
101 : /* body */
- 102 119857435 : while (blocks < end) {
- 103 115352271 : uint32_t k1 = blocks[0];
- 104 115352271 : uint32_t k2 = blocks[1];
- 105 115352271 : uint32_t k3 = blocks[2];
- 106 115352271 : uint32_t k4 = blocks[3];
+ 102 103248950 : while (blocks < end) {
+ 103 99376428 : uint32_t k1 = blocks[0];
+ 104 99376428 : uint32_t k2 = blocks[1];
+ 105 99376428 : uint32_t k3 = blocks[2];
+ 106 99376428 : uint32_t k4 = blocks[3];
107 :
108 : #if WORDS_BIGENDIAN
109 : k1 = util_swap32(k1);
@@ -174,71 +174,71 @@
112 : k4 = util_swap32(k4);
113 : #endif
114 :
- 115 115352271 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
+ 115 99376428 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
116 :
- 117 115352271 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b;
+ 117 99376428 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b;
118 :
- 119 115352271 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
+ 119 99376428 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
120 :
- 121 115352271 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747;
+ 121 99376428 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747;
122 :
- 123 115352271 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
+ 123 99376428 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
124 :
- 125 115352271 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35;
+ 125 99376428 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35;
126 :
- 127 115352271 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
+ 127 99376428 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
128 :
- 129 115352271 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17;
+ 129 99376428 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17;
130 :
- 131 115352271 : blocks += 4;
+ 131 99376428 : blocks += 4;
132 : }
133 :
134 : /* tail */
- 135 2252582 : size_remainder = size & 15;
- 136 2252582 : if (size_remainder != 0) {
- 137 848153 : const uint8_t* tail = (const uint8_t*)blocks;
+ 135 1936261 : size_remainder = size & 15;
+ 136 1936261 : if (size_remainder != 0) {
+ 137 726747 : const uint8_t* tail = (const uint8_t*)blocks;
138 :
- 139 848153 : uint32_t k1 = 0;
- 140 848153 : uint32_t k2 = 0;
- 141 848153 : uint32_t k3 = 0;
- 142 848153 : uint32_t k4 = 0;
+ 139 726747 : uint32_t k1 = 0;
+ 140 726747 : uint32_t k2 = 0;
+ 141 726747 : uint32_t k3 = 0;
+ 142 726747 : uint32_t k4 = 0;
143 :
- 144 848153 : switch (size_remainder) {
- 145 55834 : case 15 : k4 ^= tail[14] << 16;
- 146 112972 : case 14 : k4 ^= tail[13] << 8;
- 147 170132 : case 13 : k4 ^= tail[12] << 0;
- 148 170132 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
- 149 227529 : case 12 : k3 ^= tail[11] << 24;
- 150 284808 : case 11 : k3 ^= tail[10] << 16;
- 151 341803 : case 10 : k3 ^= tail[ 9] << 8;
- 152 400242 : case 9 : k3 ^= tail[ 8] << 0;
- 153 400242 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
- 154 458531 : case 8 : k2 ^= tail[ 7] << 24;
- 155 512645 : case 7 : k2 ^= tail[ 6] << 16;
- 156 569544 : case 6 : k2 ^= tail[ 5] << 8;
- 157 624516 : case 5 : k2 ^= tail[ 4] << 0;
- 158 624516 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
- 159 680502 : case 4 : k1 ^= tail[ 3] << 24;
- 160 735518 : case 3 : k1 ^= tail[ 2] << 16;
- 161 791435 : case 2 : k1 ^= tail[ 1] << 8;
- 162 848153 : case 1 : k1 ^= tail[ 0] << 0;
- 163 848153 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
+ 144 726747 : switch (size_remainder) {
+ 145 47814 : case 15 : k4 ^= (uint32_t)tail[14] << 16;
+ 146 97089 : case 14 : k4 ^= (uint32_t)tail[13] << 8;
+ 147 145774 : case 13 : k4 ^= (uint32_t)tail[12] << 0;
+ 148 145774 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
+ 149 194991 : case 12 : k3 ^= (uint32_t)tail[11] << 24;
+ 150 244008 : case 11 : k3 ^= (uint32_t)tail[10] << 16;
+ 151 292626 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8;
+ 152 342276 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0;
+ 153 342276 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
+ 154 392525 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24;
+ 155 438669 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16;
+ 156 487770 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8;
+ 157 534928 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0;
+ 158 534928 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
+ 159 583310 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24;
+ 160 630301 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16;
+ 161 678080 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8;
+ 162 726747 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0;
+ 163 726747 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
164 : }
165 : }
166 :
167 : /* finalization */
- 168 2252582 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size;
+ 168 1936261 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size;
169 :
- 170 2252582 : h1 += h2; h1 += h3; h1 += h4;
- 171 2252582 : h2 += h1; h3 += h1; h4 += h1;
+ 170 1936261 : h1 += h2; h1 += h3; h1 += h4;
+ 171 1936261 : h2 += h1; h3 += h1; h4 += h1;
172 :
- 173 2252582 : h1 = fmix32(h1);
- 174 2252582 : h2 = fmix32(h2);
- 175 2252582 : h3 = fmix32(h3);
- 176 2252582 : h4 = fmix32(h4);
+ 173 1936261 : h1 = fmix32(h1);
+ 174 1936261 : h2 = fmix32(h2);
+ 175 1936261 : h3 = fmix32(h3);
+ 176 1936261 : h4 = fmix32(h4);
177 :
- 178 2252582 : h1 += h2; h1 += h3; h1 += h4;
- 179 2252582 : h2 += h1; h3 += h1; h4 += h1;
+ 178 1936261 : h1 += h2; h1 += h3; h1 += h4;
+ 179 1936261 : h2 += h1; h3 += h1; h4 += h1;
180 :
181 : #if WORDS_BIGENDIAN
182 : h1 = util_swap32(h1);
@@ -247,11 +247,11 @@
185 : h4 = util_swap32(h4);
186 : #endif
187 :
- 188 2252582 : ((uint32_t*)digest)[0] = h1;
- 189 2252582 : ((uint32_t*)digest)[1] = h2;
- 190 2252582 : ((uint32_t*)digest)[2] = h3;
- 191 2252582 : ((uint32_t*)digest)[3] = h4;
- 192 2252582 : }
+ 188 1936261 : ((uint32_t*)digest)[0] = h1;
+ 189 1936261 : ((uint32_t*)digest)[1] = h2;
+ 190 1936261 : ((uint32_t*)digest)[2] = h3;
+ 191 1936261 : ((uint32_t*)digest)[3] = h4;
+ 192 1936261 : }
193 :
diff --git a/cov/cmdline/nano.c.func-sort-c.html b/cov/cmdline/nano.c.func-sort-c.html
index 86954774..9a6e5795 100644
--- a/cov/cmdline/nano.c.func-sort-c.html
+++ b/cov/cmdline/nano.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/nano.c.func.html b/cov/cmdline/nano.c.func.html
index 0a3357e1..40cd8921 100644
--- a/cov/cmdline/nano.c.func.html
+++ b/cov/cmdline/nano.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/nano.c.gcov.html b/cov/cmdline/nano.c.gcov.html
index 931ad05d..6c81a29b 100644
--- a/cov/cmdline/nano.c.gcov.html
+++ b/cov/cmdline/nano.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -96,13 +96,13 @@
34 : tommy_node* j;
35 :
36 : /* for all files */
- 37 5724 : for (j = disk->filelist; j != 0; j = j->next) {
- 38 5718 : struct snapraid_file* file = j->data;
+ 37 5731 : for (j = disk->filelist; j != 0; j = j->next) {
+ 38 5725 : struct snapraid_file* file = j->data;
39 :
40 : /* if the file has a zero nanosecond timestamp */
41 : /* note that symbolic links are not in the file list */
42 : /* and then are not processed */
- 43 5718 : if (file->mtime_nsec == 0) {
+ 43 5725 : if (file->mtime_nsec == 0) {
44 : char path[PATH_MAX];
45 : struct stat st;
46 : int f;
@@ -180,7 +180,7 @@
118 :
119 : /* set the same nanosecond value in the content file */
120 : /* note that if the seconds value is already matching */
- 121 : /* the file won't be synched because the content file will */
+ 121 : /* the file won't be synced because the content file will */
122 : /* contain the new updated timestamp */
123 16 : file->mtime_nsec = STAT_NSEC(&st);
124 :
diff --git a/cov/cmdline/parity.c.func-sort-c.html b/cov/cmdline/parity.c.func-sort-c.html
index 862a0682..9234472e 100644
--- a/cov/cmdline/parity.c.func-sort-c.html
+++ b/cov/cmdline/parity.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,39 +61,39 @@
| parity_read |
- 3488577 |
+ 3492991 |
| parity_write |
- 506040 |
+ 559380 |
| parity_close |
- 952 |
+ 1000 |
| parity_allocated_size |
- 589 |
+ 616 |
| parity_create |
- 551 |
+ 599 |
| parity_chsize |
- 551 |
+ 599 |
+
+
+ | parity_sync |
+ 447 |
| parity_open |
402 |
-
- | parity_sync |
- 399 |
-
| parity_used_size |
- 72 |
+ 80 |
| parity_is_invalid |
diff --git a/cov/cmdline/parity.c.func.html b/cov/cmdline/parity.c.func.html
index 700c0fe6..72656e05 100644
--- a/cov/cmdline/parity.c.func.html
+++ b/cov/cmdline/parity.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| parity_allocated_size |
- 589 |
+ 616 |
| parity_chsize |
- 551 |
+ 599 |
| parity_close |
- 952 |
+ 1000 |
| parity_create |
- 551 |
+ 599 |
| parity_is_invalid |
@@ -89,19 +89,19 @@
| parity_read |
- 3488577 |
+ 3492991 |
| parity_sync |
- 399 |
+ 447 |
| parity_used_size |
- 72 |
+ 80 |
| parity_write |
- 506040 |
+ 559380 |
diff --git a/cov/cmdline/parity.c.gcov.html b/cov/cmdline/parity.c.gcov.html
index 6ebacc6b..ac06a6d2 100644
--- a/cov/cmdline/parity.c.gcov.html
+++ b/cov/cmdline/parity.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -88,56 +88,56 @@
26 : /****************************************************************************/
27 : /* parity */
28 :
- 29 589 : block_off_t parity_allocated_size(struct snapraid_state* state)
+ 29 616 : block_off_t parity_allocated_size(struct snapraid_state* state)
30 : {
31 : block_off_t parity_block;
32 : tommy_node* i;
33 :
34 : /* compute the size of the parity file */
- 35 589 : parity_block = 0;
- 36 4113 : for (i = state->disklist; i != 0; i = i->next) {
- 37 3524 : struct snapraid_disk* disk = i->data;
+ 35 616 : parity_block = 0;
+ 36 4302 : for (i = state->disklist; i != 0; i = i->next) {
+ 37 3686 : struct snapraid_disk* disk = i->data;
38 :
39 : /* start from the declared size */
- 40 3524 : block_off_t block = disk_size(disk);
+ 40 3686 : block_off_t block = disk_size(disk);
41 :
42 : /* decrease the block until an allocated one, but part of a file */
43 : /* we don't stop at deleted blocks, because we want to have them cleared */
44 : /* if they are at the end of the parity */
- 45 189514 : while (block > parity_block && !block_has_file(fs_par2block_get(disk, block - 1)))
- 46 182466 : --block;
+ 45 128726 : while (block > parity_block && !block_has_file(fs_par2block_get(disk, block - 1)))
+ 46 121354 : --block;
47 :
48 : /* get the highest value */
- 49 3524 : if (block > parity_block)
- 50 2273 : parity_block = block;
+ 49 3686 : if (block > parity_block)
+ 50 2201 : parity_block = block;
51 : }
52 :
- 53 589 : return parity_block;
+ 53 616 : return parity_block;
54 : }
55 :
- 56 72 : block_off_t parity_used_size(struct snapraid_state* state)
+ 56 80 : block_off_t parity_used_size(struct snapraid_state* state)
57 : {
58 : block_off_t parity_block;
59 : tommy_node* i;
60 :
61 : /* compute the size of the parity file */
- 62 72 : parity_block = 0;
- 63 503 : for (i = state->disklist; i != 0; i = i->next) {
- 64 431 : struct snapraid_disk* disk = i->data;
+ 62 80 : parity_block = 0;
+ 63 559 : for (i = state->disklist; i != 0; i = i->next) {
+ 64 479 : struct snapraid_disk* disk = i->data;
65 :
66 : /* start from the declared size */
- 67 431 : block_off_t block = disk_size(disk);
+ 67 479 : block_off_t block = disk_size(disk);
68 :
69 : /* decrease the block until an used one */
- 70 221700 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_get(disk, block - 1)))
- 71 220838 : --block;
+ 70 258592 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_get(disk, block - 1)))
+ 71 257634 : --block;
72 :
73 : /* get the highest value */
- 74 431 : if (block > parity_block)
- 75 262 : parity_block = block;
+ 74 479 : if (block > parity_block)
+ 75 259 : parity_block = block;
76 : }
77 :
- 78 72 : return parity_block;
+ 78 80 : return parity_block;
79 : }
80 :
81 1 : int parity_is_invalid(struct snapraid_state* state)
@@ -211,20 +211,20 @@
149 : }
150 : }
151 :
- 152 551 : int parity_create(struct snapraid_parity_handle* parity, const char* path, data_off_t* out_size, int mode)
+ 152 599 : int parity_create(struct snapraid_parity_handle* parity, const char* path, data_off_t* out_size, int mode)
153 : {
154 : int ret;
155 : int flags;
156 :
- 157 551 : pathcpy(parity->path, sizeof(parity->path), path);
+ 157 599 : pathcpy(parity->path, sizeof(parity->path), path);
158 :
159 : /* opening in sequential mode in Windows */
160 : /* O_SEQUENTIAL: opening in sequential mode in Windows */
- 161 551 : flags = O_RDWR | O_CREAT | O_BINARY;
- 162 551 : if ((mode & MODE_SEQUENTIAL) != 0)
- 163 551 : flags |= O_SEQUENTIAL;
- 164 551 : parity->f = open(parity->path, flags, 0600);
- 165 551 : if (parity->f == -1) {
+ 161 599 : flags = O_RDWR | O_CREAT | O_BINARY;
+ 162 599 : if ((mode & MODE_SEQUENTIAL) != 0)
+ 163 599 : flags |= O_SEQUENTIAL;
+ 164 599 : parity->f = open(parity->path, flags, 0600);
+ 165 599 : if (parity->f == -1) {
166 : /* LCOV_EXCL_START */
167 : log_fatal("Error opening parity file '%s'. %s.\n", parity->path, strerror(errno));
168 : return -1;
@@ -232,8 +232,8 @@
170 : }
171 :
172 : /* get the stat info */
- 173 551 : ret = fstat(parity->f, &parity->st);
- 174 551 : if (ret != 0) {
+ 173 599 : ret = fstat(parity->f, &parity->st);
+ 174 599 : if (ret != 0) {
175 : /* LCOV_EXCL_START */
176 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
177 : goto bail;
@@ -241,10 +241,10 @@
179 : }
180 :
181 : #if HAVE_POSIX_FADVISE
- 182 551 : if ((mode & MODE_SEQUENTIAL) != 0) {
+ 182 599 : if ((mode & MODE_SEQUENTIAL) != 0) {
183 : /* advise sequential access */
- 184 551 : ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 185 551 : if (ret != 0) {
+ 184 599 : ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 185 599 : if (ret != 0) {
186 : /* LCOV_EXCL_START */
187 : log_fatal("Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
188 : goto bail;
@@ -254,10 +254,10 @@
192 : #endif
193 :
194 : /* get the size of the existing data */
- 195 551 : parity->valid_size = parity->st.st_size;
- 196 551 : *out_size = parity->st.st_size;
+ 195 599 : parity->valid_size = parity->st.st_size;
+ 196 599 : *out_size = parity->st.st_size;
197 :
- 198 551 : return 0;
+ 198 599 : return 0;
199 :
200 : bail:
201 : /* LCOV_EXCL_START */
@@ -268,28 +268,28 @@
206 : /* LCOV_EXCL_STOP */
207 : }
208 :
- 209 551 : int parity_chsize(struct snapraid_parity_handle* parity, data_off_t size, data_off_t* out_size, int skip_fallocate)
+ 209 599 : int parity_chsize(struct snapraid_parity_handle* parity, data_off_t size, data_off_t* out_size, int skip_fallocate)
210 : {
211 : int ret;
212 :
- 213 551 : if (parity->st.st_size < size) {
+ 213 599 : if (parity->st.st_size < size) {
214 : int f_ret;
215 : int f_errno;
216 : const char* call;
217 :
218 : #if HAVE_FALLOCATE
- 219 83 : call = "fallocate";
- 220 83 : if (!skip_fallocate) {
+ 219 95 : call = "fallocate";
+ 220 95 : if (!skip_fallocate) {
221 : /* allocate real space using the specific Linux fallocate() operation. */
- 222 : /* If the underline filesystem doesn't support it, this operation fails, */
+ 222 : /* If the underline file-system doesn't support it, this operation fails, */
223 : /* instead posix_fallocate() fallbacks to write the whole file. */
- 224 82 : ret = fallocate(parity->f, 0, 0, size);
+ 224 94 : ret = fallocate(parity->f, 0, 0, size);
225 :
226 : /* fallocate() returns the error number as positive integer, */
227 : /* and in this case it doesn't set errno, just like posix_fallocate() */
228 : /* Checking the glibc code (2.11.1 and 2.14.1) it seems that ENOSYS */
229 : /* may be returned in errno, so we support both the return way */
- 230 82 : if (ret > 0) { /* if a positive error is returned, convert it to errno */
+ 230 94 : if (ret > 0) { /* if a positive error is returned, convert it to errno */
231 : /* LCOV_EXCL_START */
232 : errno = ret;
233 : ret = -1;
@@ -302,7 +302,7 @@
240 :
241 : /* we get EOPNOTSUPP if the operation is not supported, like in ext3/ext2 */
242 : /* or ENOSYS with kernel before 2.6.23 */
- 243 83 : if (errno == EOPNOTSUPP || errno == ENOSYS) {
+ 243 95 : if (errno == EOPNOTSUPP || errno == ENOSYS) {
244 : /* fallback using ftruncate() */
245 1 : call = "ftruncate";
246 1 : ret = ftruncate(parity->f, size);
@@ -315,12 +315,12 @@
253 : ret = ftruncate(parity->f, size);
254 : #endif
255 : /* save the state of the grow operation */
- 256 83 : f_ret = ret;
- 257 83 : f_errno = errno;
+ 256 95 : f_ret = ret;
+ 257 95 : f_errno = errno;
258 :
259 : /* get the stat info */
- 260 83 : ret = fstat(parity->f, &parity->st);
- 261 83 : if (ret != 0) {
+ 260 95 : ret = fstat(parity->f, &parity->st);
+ 261 95 : if (ret != 0) {
262 : /* LCOV_EXCL_START */
263 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
264 : goto bail;
@@ -328,10 +328,10 @@
266 : }
267 :
268 : /* return the new size */
- 269 83 : *out_size = parity->st.st_size;
+ 269 95 : *out_size = parity->st.st_size;
270 :
271 : /* now check the error */
- 272 83 : if (f_ret != 0) {
+ 272 95 : if (f_ret != 0) {
273 : /* LCOV_EXCL_START */
274 : if (f_errno == ENOSPC) {
275 : log_fatal("Failed to grow parity file '%s' to size %" PRIu64 " using %s due lack of space.\n", parity->path, size, call);
@@ -341,20 +341,20 @@
279 : goto bail;
280 : /* LCOV_EXCL_STOP */
281 : }
- 282 468 : } else if (parity->st.st_size > size) {
+ 282 504 : } else if (parity->st.st_size > size) {
283 : int f_ret;
284 : int f_errno;
285 :
286 : /* truncate the parity file */
- 287 48 : ret = ftruncate(parity->f, size);
+ 287 72 : ret = ftruncate(parity->f, size);
288 :
289 : /* save the state of the shrink operation */
- 290 48 : f_ret = ret;
- 291 48 : f_errno = errno;
+ 290 72 : f_ret = ret;
+ 291 72 : f_errno = errno;
292 :
293 : /* get the stat info */
- 294 48 : ret = fstat(parity->f, &parity->st);
- 295 48 : if (ret != 0) {
+ 294 72 : ret = fstat(parity->f, &parity->st);
+ 295 72 : if (ret != 0) {
296 : /* LCOV_EXCL_START */
297 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
298 : goto bail;
@@ -362,10 +362,10 @@
300 : }
301 :
302 : /* return the new size */
- 303 48 : *out_size = parity->st.st_size;
+ 303 72 : *out_size = parity->st.st_size;
304 :
305 : /* now check the error */
- 306 48 : if (f_ret != 0) {
+ 306 72 : if (f_ret != 0) {
307 : /* LCOV_EXCL_START */
308 : log_fatal("Error truncating parity file '%s' to size %" PRIu64 ". %s.\n", parity->path, size, strerror(f_errno));
309 : goto bail;
@@ -373,10 +373,10 @@
311 : }
312 :
313 : /* adjust the valid to the new size */
- 314 48 : parity->valid_size = size;
+ 314 72 : parity->valid_size = size;
315 : }
316 :
- 317 551 : return 0;
+ 317 599 : return 0;
318 :
319 : bail:
320 : /* LCOV_EXCL_START */
@@ -413,7 +413,7 @@
351 : /* LCOV_EXCL_STOP */
352 : }
353 :
- 354 : /* get the size of the exising data */
+ 354 : /* get the size of the existing data */
355 401 : parity->valid_size = parity->st.st_size;
356 :
357 : #if HAVE_POSIX_FADVISE
@@ -440,7 +440,7 @@
378 : /* LCOV_EXCL_STOP */
379 : }
380 :
- 381 399 : int parity_sync(struct snapraid_parity_handle* parity)
+ 381 447 : int parity_sync(struct snapraid_parity_handle* parity)
382 : {
383 : #if HAVE_FSYNC
384 : int ret;
@@ -448,8 +448,8 @@
386 : /* Ensure that data changes are written to disk. */
387 : /* This is required to ensure that parity is more updated than content */
388 : /* in case of a system crash. */
- 389 399 : ret = fsync(parity->f);
- 390 399 : if (ret != 0) {
+ 389 447 : ret = fsync(parity->f);
+ 390 447 : if (ret != 0) {
391 : /* LCOV_EXCL_START */
392 : log_fatal("Error synching parity file '%s'. %s.\n", parity->path, strerror(errno));
393 : return -1;
@@ -457,15 +457,15 @@
395 : }
396 : #endif
397 :
- 398 399 : return 0;
+ 398 447 : return 0;
399 : }
400 :
- 401 952 : int parity_close(struct snapraid_parity_handle* parity)
+ 401 1000 : int parity_close(struct snapraid_parity_handle* parity)
402 : {
403 : int ret;
404 :
- 405 952 : ret = close(parity->f);
- 406 952 : if (ret != 0) {
+ 405 1000 : ret = close(parity->f);
+ 406 1000 : if (ret != 0) {
407 : /* LCOV_EXCL_START */
408 : /* invalidate for error */
409 : parity->f = -1;
@@ -473,28 +473,28 @@
411 :
412 : /* This is a serious error, as it may be the result of a failed write */
413 : /* identified at later time. */
- 414 : /* In a normal filesystem (not NFS) it should never happen */
+ 414 : /* In a normal file-system (not NFS) it should never happen */
415 : log_fatal("Error closing parity file '%s'. %s.\n", parity->path, strerror(errno));
416 : return -1;
417 : /* LCOV_EXCL_STOP */
418 : }
419 :
420 : /* reset the descriptor */
- 421 952 : parity->f = -1;
- 422 952 : parity->valid_size = 0;
+ 421 1000 : parity->f = -1;
+ 422 1000 : parity->valid_size = 0;
423 :
- 424 952 : return 0;
+ 424 1000 : return 0;
425 : }
426 :
- 427 506040 : int parity_write(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size)
+ 427 559380 : int parity_write(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size)
428 : {
429 : ssize_t write_ret;
430 : data_off_t offset;
431 :
- 432 506040 : offset = pos * (data_off_t)block_size;
+ 432 559380 : offset = pos * (data_off_t)block_size;
433 :
434 : #if HAVE_PWRITE
- 435 506040 : write_ret = pwrite(parity->f, block_buffer, block_size, offset);
+ 435 559380 : write_ret = pwrite(parity->f, block_buffer, block_size, offset);
436 : #else
437 : if (lseek(parity->f, offset, SEEK_SET) != offset) {
438 : /* LCOV_EXCL_START */
@@ -509,7 +509,7 @@
447 :
448 : write_ret = write(parity->f, block_buffer, block_size);
449 : #endif
- 450 506040 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */
+ 450 559380 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */
451 : /* LCOV_EXCL_START */
452 : if (errno == ENOSPC) {
453 : log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", parity->path);
@@ -521,28 +521,28 @@
459 : }
460 :
461 : /* adjust the size of the valid data */
- 462 506040 : if (parity->valid_size < offset + block_size) {
- 463 170559 : parity->valid_size = offset + block_size;
+ 462 559380 : if (parity->valid_size < offset + block_size) {
+ 463 171021 : parity->valid_size = offset + block_size;
464 : }
465 :
466 : /* Here doesn't make sense to call posix_fadvise(..., POSIX_FADV_DONTNEED) because */
467 : /* at this time the data is still in not yet written and it cannot be discharged. */
468 :
- 469 506040 : return 0;
+ 469 559380 : return 0;
470 : }
471 :
- 472 3488577 : int parity_read(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out)
+ 472 3492991 : int parity_read(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out)
473 : {
474 : ssize_t read_ret;
475 : data_off_t offset;
476 : unsigned count;
477 :
- 478 3488577 : offset = pos * (data_off_t)block_size;
+ 478 3492991 : offset = pos * (data_off_t)block_size;
479 :
480 : /* check if we are going to read only not initialized data */
- 481 3488577 : if (offset >= parity->valid_size) {
- 482 90275 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", parity->path, offset);
- 483 90275 : return -1;
+ 481 3492991 : if (offset >= parity->valid_size) {
+ 482 90295 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", parity->path, offset);
+ 483 90295 : return -1;
484 : }
485 :
486 : #if !HAVE_PREAD
@@ -554,36 +554,36 @@
492 : }
493 : #endif
494 :
- 495 3398302 : count = 0;
+ 495 3402696 : count = 0;
496 : do {
497 :
498 : #if HAVE_PREAD
- 499 3398302 : read_ret = pread(parity->f, block_buffer + count, block_size - count, offset + count);
+ 499 3402696 : read_ret = pread(parity->f, block_buffer + count, block_size - count, offset + count);
500 : #else
501 : read_ret = read(parity->f, block_buffer + count, block_size - count);
502 : #endif
- 503 3398302 : if (read_ret < 0) {
+ 503 3402696 : if (read_ret < 0) {
504 : /* LCOV_EXCL_START */
505 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", parity->path, offset + count, block_size - count, strerror(errno));
506 : return -1;
507 : /* LCOV_EXCL_STOP */
508 : }
- 509 3398302 : if (read_ret == 0) {
+ 509 3402696 : if (read_ret == 0) {
510 : /* LCOV_EXCL_START */
511 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", parity->path, offset, strerror(errno));
512 : return -1;
513 : /* LCOV_EXCL_STOP */
514 : }
515 :
- 516 3398302 : count += read_ret;
- 517 3398302 : } while (count < block_size);
+ 516 3402696 : count += read_ret;
+ 517 3402696 : } while (count < block_size);
518 :
519 : /* Here isn't needed to call posix_fadvise(..., POSIX_FADV_DONTNEED) */
520 : /* because we already advised sequential access with POSIX_FADV_SEQUENTIAL. */
521 : /* In Linux 2.6.33 it's enough to ensure that data is not kept in the cache. */
522 : /* Better to do nothing and save a syscall for each block. */
523 :
- 524 3398302 : return block_size;
+ 524 3402696 : return block_size;
525 : }
526 :
diff --git a/cov/cmdline/pool.c.func-sort-c.html b/cov/cmdline/pool.c.func-sort-c.html
index 745f72a1..227f106b 100644
--- a/cov/cmdline/pool.c.func-sort-c.html
+++ b/cov/cmdline/pool.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| make_link |
- 17569 |
+ 17583 |
| clean_dir |
diff --git a/cov/cmdline/pool.c.func.html b/cov/cmdline/pool.c.func.html
index 6a1d2ec3..a874cb8a 100644
--- a/cov/cmdline/pool.c.func.html
+++ b/cov/cmdline/pool.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,7 +65,7 @@
| make_link |
- 17569 |
+ 17583 |
| state_pool |
diff --git a/cov/cmdline/pool.c.gcov.html b/cov/cmdline/pool.c.gcov.html
index 233bc037..3172ab70 100644
--- a/cov/cmdline/pool.c.gcov.html
+++ b/cov/cmdline/pool.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -107,24 +107,24 @@
45 : struct dirent* dd;
46 :
47 : /* clear errno to detect erroneous conditions */
- 48 5760 : errno = 0;
- 49 5760 : dd = readdir(d);
- 50 5760 : if (dd == 0 && errno != 0) {
+ 48 5767 : errno = 0;
+ 49 5767 : dd = readdir(d);
+ 50 5767 : if (dd == 0 && errno != 0) {
51 : /* LCOV_EXCL_START */
52 : log_fatal("Error reading pool directory '%s'. %s.\n", dir, strerror(errno));
53 : exit(EXIT_FAILURE);
54 : /* LCOV_EXCL_STOP */
55 : }
- 56 5760 : if (dd == 0 && errno == 0) {
+ 56 5767 : if (dd == 0 && errno == 0) {
57 5 : break; /* finished */
58 : }
59 :
60 : /* skip "." and ".." files */
- 61 5755 : name = dd->d_name;
- 62 5755 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+ 61 5762 : name = dd->d_name;
+ 62 5762 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
63 10 : continue;
64 :
- 65 5745 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 65 5752 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
66 :
67 : #if HAVE_STRUCT_DIRENT_D_STAT
68 : /* convert dirent to lstat result */
@@ -142,7 +142,7 @@
80 : }
81 : #else
82 : /* get lstat info about the file */
- 83 5745 : if (lstat(path_next, &st) != 0) {
+ 83 5752 : if (lstat(path_next, &st) != 0) {
84 : /* LCOV_EXCL_START */
85 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
86 : exit(EXIT_FAILURE);
@@ -150,12 +150,12 @@
88 : }
89 : #endif
90 :
- 91 5745 : if (S_ISLNK(st.st_mode)) {
+ 91 5752 : if (S_ISLNK(st.st_mode)) {
92 : int ret;
93 :
94 : /* delete the link */
- 95 5743 : ret = remove(path_next);
- 96 5743 : if (ret < 0) {
+ 95 5750 : ret = remove(path_next);
+ 96 5750 : if (ret < 0) {
97 : /* LCOV_EXCL_START */
98 : log_fatal("Error removing symlink '%s'. %s.\n", path_next, strerror(errno));
99 : exit(EXIT_FAILURE);
@@ -194,7 +194,7 @@
132 0 : ignored = 1;
133 0 : msg_verbose("Ignoring pool file '%s'\n", path_next);
134 : }
- 135 5755 : }
+ 135 5762 : }
136 :
137 5 : if (closedir(d) != 0) {
138 : /* LCOV_EXCL_START */
@@ -209,7 +209,7 @@
147 : /**
148 : * Create a link to the specified disk entry.
149 : */
- 150 17569 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub)
+ 150 17583 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub)
151 : {
152 : char path[PATH_MAX];
153 : char linkto[PATH_MAX];
@@ -217,31 +217,31 @@
155 : int ret;
156 :
157 : /* make the source path */
- 158 17569 : pathprint(path, sizeof(path), "%s%s", pool_dir, sub);
+ 158 17583 : pathprint(path, sizeof(path), "%s%s", pool_dir, sub);
159 :
160 : /* make the linkto path */
- 161 17569 : if (share_dir[0] != 0) {
+ 161 17583 : if (share_dir[0] != 0) {
162 : /* with a shared directory, use it */
- 163 17569 : pathprint(linkto, sizeof(linkto), "%s%s/%s", share_dir, disk->name, sub);
+ 163 17583 : pathprint(linkto, sizeof(linkto), "%s%s/%s", share_dir, disk->name, sub);
164 : } else {
165 : /* without a share directory, use the local disk paths */
166 0 : pathprint(linkto, sizeof(linkto), "%s%s", disk->dir, sub);
167 : }
168 :
169 : /* create the ancestor directories */
- 170 17569 : ret = mkancestor(path);
- 171 17569 : if (ret != 0) {
+ 170 17583 : ret = mkancestor(path);
+ 171 17583 : if (ret != 0) {
172 : /* LCOV_EXCL_START */
173 : exit(EXIT_FAILURE);
174 : /* LCOV_EXCL_STOP */
175 : }
176 :
177 : /* convert back slashes */
- 178 17569 : pathexport(linkto_exported, sizeof(linkto_exported), linkto);
+ 178 17583 : pathexport(linkto_exported, sizeof(linkto_exported), linkto);
179 :
180 : /* create the symlink */
- 181 17569 : ret = symlink(linkto_exported, path);
- 182 17569 : if (ret != 0) {
+ 181 17583 : ret = symlink(linkto_exported, path);
+ 182 17583 : if (ret != 0) {
183 517 : if (errno == EEXIST) {
184 517 : log_fatal("WARNING! Duplicate pooling for '%s'\n", path);
185 : #ifdef _WIN32
@@ -258,7 +258,7 @@
196 : /* LCOV_EXCL_STOP */
197 : }
198 : }
- 199 17569 : }
+ 199 17583 : }
200 :
201 3 : void state_pool(struct snapraid_state* state)
202 : {
@@ -296,10 +296,10 @@
234 18 : struct snapraid_disk* disk = i->data;
235 :
236 : /* for each file */
- 237 16998 : for (j = disk->filelist; j != 0; j = j->next) {
- 238 16980 : struct snapraid_file* file = j->data;
- 239 16980 : make_link(pool_dir, share_dir, disk, file->sub);
- 240 16980 : ++count;
+ 237 17012 : for (j = disk->filelist; j != 0; j = j->next) {
+ 238 16994 : struct snapraid_file* file = j->data;
+ 239 16994 : make_link(pool_dir, share_dir, disk, file->sub);
+ 240 16994 : ++count;
241 : }
242 :
243 : /* for each link */
diff --git a/cov/cmdline/portable.h.func-sort-c.html b/cov/cmdline/portable.h.func-sort-c.html
index 4b66bf09..5265a465 100644
--- a/cov/cmdline/portable.h.func-sort-c.html
+++ b/cov/cmdline/portable.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,7 +60,7 @@
Hit count  |
- | hardlink |
+ hardlink |
12 |
diff --git a/cov/cmdline/portable.h.func.html b/cov/cmdline/portable.h.func.html
index ee3455ec..c83d5fe3 100644
--- a/cov/cmdline/portable.h.func.html
+++ b/cov/cmdline/portable.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,7 +60,7 @@
Hit count  |
- | hardlink |
+ hardlink |
12 |
diff --git a/cov/cmdline/portable.h.gcov.html b/cov/cmdline/portable.h.gcov.html
index 5cb42125..c75de15a 100644
--- a/cov/cmdline/portable.h.gcov.html
+++ b/cov/cmdline/portable.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -131,357 +131,385 @@
69 : #define __always_inline inline __attribute__((always_inline))
70 : #endif
71 :
- 72 : /**
- 73 : * Architecture.
- 74 : */
- 75 : #if defined(__i386__)
- 76 : #define CONFIG_X86 1
- 77 : #define CONFIG_X86_32 1
- 78 : #endif
- 79 :
- 80 : #if defined(__x86_64__)
+ 72 : #ifndef __noreturn
+ 73 : #define __noreturn __attribute__((noreturn))
+ 74 : #endif
+ 75 :
+ 76 :
+ 77 : /**
+ 78 : * Architecture.
+ 79 : */
+ 80 : #if defined(__i386__)
81 : #define CONFIG_X86 1
- 82 : #define CONFIG_X86_64 1
+ 82 : #define CONFIG_X86_32 1
83 : #endif
84 :
- 85 : /**
- 86 : * Includes some platform specific headers.
- 87 : */
- 88 : #if HAVE_SYS_PARAM_H
- 89 : #include <sys/param.h>
- 90 : #endif
- 91 :
- 92 : #if HAVE_SYS_MOUNT_H
- 93 : #include <sys/mount.h>
- 94 : #endif
- 95 :
- 96 : #if HAVE_SYS_VFS_H
- 97 : #include <sys/vfs.h>
- 98 : #endif
- 99 :
- 100 : #if HAVE_SYS_STATFS_H
- 101 : #include <sys/statfs.h>
- 102 : #endif
- 103 :
- 104 : #if HAVE_SYS_FILE_H
- 105 : #include <sys/file.h>
- 106 : #endif
- 107 :
- 108 : #if HAVE_SYS_IOCTL_H
- 109 : #include <sys/ioctl.h>
- 110 : #endif
- 111 :
- 112 : #if HAVE_LINUX_FS_H
- 113 : #include <linux/fs.h>
- 114 : #endif
- 115 :
- 116 : #if HAVE_LINUX_FIEMAP_H
- 117 : #include <linux/fiemap.h>
- 118 : #endif
- 119 :
- 120 : /**
- 121 : * Includes some standard headers.
- 122 : */
- 123 : #include <stdio.h>
- 124 : #include <stdlib.h> /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */
- 125 : #include <stdarg.h>
- 126 : #include <string.h>
- 127 : #include <ctype.h>
- 128 : #include <fcntl.h>
- 129 : #include <assert.h>
- 130 : #include <errno.h>
- 131 : #include <signal.h>
- 132 : #include <limits.h>
- 133 :
- 134 : #if HAVE_STDINT_H
- 135 : #include <stdint.h>
- 136 : #endif
- 137 :
- 138 : #if HAVE_INTTYPES_H
- 139 : #include <inttypes.h>
- 140 : #endif
- 141 :
- 142 : #if HAVE_UNISTD_H
- 143 : #include <unistd.h>
- 144 : #endif
+ 85 : #if defined(__x86_64__)
+ 86 : #define CONFIG_X86 1
+ 87 : #define CONFIG_X86_64 1
+ 88 : #endif
+ 89 :
+ 90 : /**
+ 91 : * Includes some platform specific headers.
+ 92 : */
+ 93 : #if HAVE_SYS_PARAM_H
+ 94 : #include <sys/param.h>
+ 95 : #endif
+ 96 :
+ 97 : #if HAVE_SYS_MOUNT_H
+ 98 : #include <sys/mount.h>
+ 99 : #endif
+ 100 :
+ 101 : #if HAVE_SYS_VFS_H
+ 102 : #include <sys/vfs.h>
+ 103 : #endif
+ 104 :
+ 105 : #if HAVE_SYS_STATFS_H
+ 106 : #include <sys/statfs.h>
+ 107 : #endif
+ 108 :
+ 109 : #if HAVE_SYS_FILE_H
+ 110 : #include <sys/file.h>
+ 111 : #endif
+ 112 :
+ 113 : #if HAVE_SYS_IOCTL_H
+ 114 : #include <sys/ioctl.h>
+ 115 : #endif
+ 116 :
+ 117 : #if HAVE_LINUX_FS_H
+ 118 : #include <linux/fs.h>
+ 119 : #endif
+ 120 :
+ 121 : #if HAVE_LINUX_FIEMAP_H
+ 122 : #include <linux/fiemap.h>
+ 123 : #endif
+ 124 :
+ 125 : #if HAVE_BLKID_BLKID_H
+ 126 : #include <blkid/blkid.h>
+ 127 : #if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE
+ 128 : #define HAVE_BLKID 1
+ 129 : #endif
+ 130 : #endif
+ 131 :
+ 132 : /**
+ 133 : * Includes some standard headers.
+ 134 : */
+ 135 : #include <stdio.h>
+ 136 : #include <stdlib.h> /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */
+ 137 : #include <stdarg.h>
+ 138 : #include <string.h>
+ 139 : #include <ctype.h>
+ 140 : #include <fcntl.h>
+ 141 : #include <assert.h>
+ 142 : #include <errno.h>
+ 143 : #include <signal.h>
+ 144 : #include <limits.h>
145 :
- 146 : #if TIME_WITH_SYS_TIME
- 147 : #include <sys/time.h>
- 148 : #include <time.h>
- 149 : #else
- 150 : #if HAVE_SYS_TIME_H
- 151 : #include <sys/time.h>
- 152 : #else
- 153 : #include <time.h>
- 154 : #endif
- 155 : #endif
- 156 :
- 157 : #if HAVE_MACH_MACH_TIME_H
- 158 : #include <mach/mach_time.h>
- 159 : #endif
- 160 :
- 161 : #if HAVE_DIRENT_H
- 162 : #include <dirent.h>
- 163 : #define NAMLEN(dirent) strlen((dirent)->d_name)
+ 146 : #if HAVE_STDINT_H
+ 147 : #include <stdint.h>
+ 148 : #endif
+ 149 :
+ 150 : #if HAVE_INTTYPES_H
+ 151 : #include <inttypes.h>
+ 152 : #endif
+ 153 :
+ 154 : #if HAVE_UNISTD_H
+ 155 : #include <unistd.h>
+ 156 : #endif
+ 157 :
+ 158 : #if TIME_WITH_SYS_TIME
+ 159 : #include <sys/time.h>
+ 160 : #include <time.h>
+ 161 : #else
+ 162 : #if HAVE_SYS_TIME_H
+ 163 : #include <sys/time.h>
164 : #else
- 165 : #define dirent direct
- 166 : #define NAMLEN(dirent) (dirent)->d_namlen
- 167 : #if HAVE_SYS_NDIR_H
- 168 : #include <sys/ndir.h>
- 169 : #endif
- 170 : #if HAVE_SYS_DIR_H
- 171 : #include <sys/dir.h>
- 172 : #endif
- 173 : #if HAVE_NDIR_H
- 174 : #include <ndir.h>
- 175 : #endif
- 176 : #endif
- 177 :
- 178 : #if HAVE_SYS_TYPES_H
- 179 : #include <sys/types.h>
- 180 : #endif
- 181 :
- 182 : #if HAVE_SYS_STAT_H
- 183 : #include <sys/stat.h>
+ 165 : #include <time.h>
+ 166 : #endif
+ 167 : #endif
+ 168 :
+ 169 : #if HAVE_MACH_MACH_TIME_H
+ 170 : #include <mach/mach_time.h>
+ 171 : #endif
+ 172 :
+ 173 : #if HAVE_DIRENT_H
+ 174 : #include <dirent.h>
+ 175 : #define NAMLEN(dirent) strlen((dirent)->d_name)
+ 176 : #else
+ 177 : #define dirent direct
+ 178 : #define NAMLEN(dirent) (dirent)->d_namlen
+ 179 : #if HAVE_SYS_NDIR_H
+ 180 : #include <sys/ndir.h>
+ 181 : #endif
+ 182 : #if HAVE_SYS_DIR_H
+ 183 : #include <sys/dir.h>
184 : #endif
- 185 :
- 186 : #if HAVE_SYS_WAIT_H
- 187 : #include <sys/wait.h>
+ 185 : #if HAVE_NDIR_H
+ 186 : #include <ndir.h>
+ 187 : #endif
188 : #endif
- 189 : #ifndef WEXITSTATUS
- 190 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
- 191 : #endif
- 192 : #ifndef WIFEXITED
- 193 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
- 194 : #endif
- 195 :
- 196 : #if HAVE_GETOPT_H
- 197 : #include <getopt.h>
- 198 : #endif
- 199 :
- 200 : #if HAVE_FNMATCH_H
- 201 : #include <fnmatch.h>
- 202 : #else
- 203 : #include "fnmatch.h"
- 204 : #endif
- 205 :
- 206 : #if HAVE_PTHREAD_H
- 207 : #include <pthread.h>
- 208 : #endif
- 209 :
- 210 : #if HAVE_MATH_H
- 211 : #include <math.h>
- 212 : #endif
- 213 :
- 214 : /**
- 215 : * Disable case check in Windows.
- 216 : */
- 217 : #ifdef _WIN32
- 218 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD
- 219 : #else
- 220 : #define FNM_CASEINSENSITIVE_FOR_WIN 0
- 221 : #endif
- 222 :
- 223 : #if HAVE_IO_H
- 224 : #include <io.h>
- 225 : #endif
- 226 :
- 227 : #if HAVE_GETOPT_LONG
- 228 : #define SWITCH_GETOPT_LONG(a, b) a
- 229 : #else
- 230 : #define SWITCH_GETOPT_LONG(a, b) b
- 231 : #endif
- 232 :
- 233 : /**
- 234 : * Enables lock file support.
- 235 : */
- 236 : #if HAVE_FLOCK && HAVE_FTRUNCATE
- 237 : #define HAVE_LOCKFILE 1
- 238 : #endif
- 239 :
- 240 : /**
- 241 : * Includes specific support for Windows or Linux.
- 242 : */
- 243 : #ifdef __MINGW32__
- 244 : #include "mingw.h"
- 245 : #else
- 246 : #include "unix.h"
- 247 : #endif
- 248 :
- 249 : /**
- 250 : * Include list support to have tommy_node.
- 251 : */
- 252 : #include "tommyds/tommylist.h"
- 253 :
- 254 : /**
- 255 : * Another name for link() to avoid confusion with local variables called "link".
- 256 : */
- 257 12 : static inline int hardlink(const char* a, const char* b)
- 258 : {
- 259 12 : return link(a, b);
- 260 : }
- 261 :
- 262 : /**
- 263 : * Get the device UUID.
- 264 : * Return 0 on success.
+ 189 :
+ 190 : #if HAVE_SYS_TYPES_H
+ 191 : #include <sys/types.h>
+ 192 : #endif
+ 193 :
+ 194 : #if HAVE_SYS_STAT_H
+ 195 : #include <sys/stat.h>
+ 196 : #endif
+ 197 :
+ 198 : #if HAVE_SYS_WAIT_H
+ 199 : #include <sys/wait.h>
+ 200 : #endif
+ 201 : #ifndef WEXITSTATUS
+ 202 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+ 203 : #endif
+ 204 : #ifndef WIFEXITED
+ 205 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+ 206 : #endif
+ 207 :
+ 208 : #if HAVE_GETOPT_H
+ 209 : #include <getopt.h>
+ 210 : #endif
+ 211 :
+ 212 : #if HAVE_FNMATCH_H
+ 213 : #include <fnmatch.h>
+ 214 : #else
+ 215 : #include "fnmatch.h"
+ 216 : #endif
+ 217 :
+ 218 : #if HAVE_PTHREAD_H
+ 219 : #include <pthread.h>
+ 220 : #endif
+ 221 :
+ 222 : #if HAVE_MATH_H
+ 223 : #include <math.h>
+ 224 : #endif
+ 225 :
+ 226 : #if HAVE_EXECINFO_H
+ 227 : #include <execinfo.h>
+ 228 : #endif
+ 229 :
+ 230 : /**
+ 231 : * Enable thread use.
+ 232 : */
+ 233 : #if HAVE_PTHREAD_H && HAVE_PTHREAD_CREATE
+ 234 : #define HAVE_PTHREAD 1
+ 235 : #endif
+ 236 :
+ 237 : /**
+ 238 : * Disable case check in Windows.
+ 239 : */
+ 240 : #ifdef _WIN32
+ 241 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD
+ 242 : #else
+ 243 : #define FNM_CASEINSENSITIVE_FOR_WIN 0
+ 244 : #endif
+ 245 :
+ 246 : #if HAVE_IO_H
+ 247 : #include <io.h>
+ 248 : #endif
+ 249 :
+ 250 : #if HAVE_GETOPT_LONG
+ 251 : #define SWITCH_GETOPT_LONG(a, b) a
+ 252 : #else
+ 253 : #define SWITCH_GETOPT_LONG(a, b) b
+ 254 : #endif
+ 255 :
+ 256 : /**
+ 257 : * Enables lock file support.
+ 258 : */
+ 259 : #if HAVE_FLOCK && HAVE_FTRUNCATE
+ 260 : #define HAVE_LOCKFILE 1
+ 261 : #endif
+ 262 :
+ 263 : /**
+ 264 : * Includes specific support for Windows or Linux.
265 : */
- 266 : int devuuid(uint64_t device, char* uuid, size_t size);
- 267 :
- 268 : /**
- 269 : * Physical offset not yet read.
- 270 : */
- 271 : #define FILEPHY_UNREAD_OFFSET 0
- 272 :
- 273 : /**
- 274 : * Special value returned when the filesystem doesn't report any offset for unknown reason.
- 275 : */
- 276 : #define FILEPHY_UNREPORTED_OFFSET 1
- 277 :
- 278 : /**
- 279 : * Special value returned when the file doesn't have a real offset.
- 280 : * For example, because it's stored in the NTFS MFT.
- 281 : */
- 282 : #define FILEPHY_WITHOUT_OFFSET 2
- 283 :
- 284 : /**
- 285 : * Value indicating real offsets. All offsets greater or equal at this one are real.
- 286 : */
- 287 : #define FILEPHY_REAL_OFFSET 3
- 288 :
- 289 : /**
- 290 : * Get the physcal address of the specified file.
- 291 : * This is expected to be just a hint and not necessarely correct or unique.
- 292 : * Return 0 on success.
+ 266 : #ifdef __MINGW32__
+ 267 : #include "mingw.h"
+ 268 : #else
+ 269 : #include "unix.h"
+ 270 : #endif
+ 271 :
+ 272 : /**
+ 273 : * Include list support to have tommy_node.
+ 274 : */
+ 275 : #include "tommyds/tommylist.h"
+ 276 :
+ 277 : /**
+ 278 : * Another name for link() to avoid confusion with local variables called "link".
+ 279 : */
+ 280 12 : static inline int hardlink(const char* a, const char* b)
+ 281 : {
+ 282 12 : return link(a, b);
+ 283 : }
+ 284 :
+ 285 : /**
+ 286 : * Get the device UUID.
+ 287 : * Return 0 on success.
+ 288 : */
+ 289 : int devuuid(uint64_t device, char* uuid, size_t size);
+ 290 :
+ 291 : /**
+ 292 : * Physical offset not yet read.
293 : */
- 294 : int filephy(const char* path, uint64_t size, uint64_t* physical);
+ 294 : #define FILEPHY_UNREAD_OFFSET 0
295 :
296 : /**
- 297 : * Check if the underline filesystem support persistent inodes.
- 298 : * Return -1 on error, 0 on success.
- 299 : */
- 300 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space);
- 301 :
- 302 : /**
- 303 : * Get the tick counter value.
- 304 : *
- 305 : * Note that the frequency is unspecified, because the time measure
- 306 : * is meant to be used to compare the ratio between usage times.
- 307 : */
- 308 : uint64_t tick(void);
- 309 :
- 310 : /**
- 311 : * Get the tick counter value in millisecond.
- 312 : */
- 313 : uint64_t tick_ms(void);
- 314 :
- 315 : /**
- 316 : * Initializes the system.
- 317 : */
- 318 : void os_init(int opt);
- 319 :
- 320 : /**
- 321 : * Deintialize the system.
+ 297 : * Special value returned when the file-system doesn't report any offset for unknown reason.
+ 298 : */
+ 299 : #define FILEPHY_UNREPORTED_OFFSET 1
+ 300 :
+ 301 : /**
+ 302 : * Special value returned when the file doesn't have a real offset.
+ 303 : * For example, because it's stored in the NTFS MFT.
+ 304 : */
+ 305 : #define FILEPHY_WITHOUT_OFFSET 2
+ 306 :
+ 307 : /**
+ 308 : * Value indicating real offsets. All offsets greater or equal at this one are real.
+ 309 : */
+ 310 : #define FILEPHY_REAL_OFFSET 3
+ 311 :
+ 312 : /**
+ 313 : * Get the physcal address of the specified file.
+ 314 : * This is expected to be just a hint and not necessarily correct or unique.
+ 315 : * Return 0 on success.
+ 316 : */
+ 317 : int filephy(const char* path, uint64_t size, uint64_t* physical);
+ 318 :
+ 319 : /**
+ 320 : * Check if the underline file-system support persistent inodes.
+ 321 : * Return -1 on error, 0 on success.
322 : */
- 323 : void os_done(void);
+ 323 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space);
324 :
325 : /**
- 326 : * Log file.
+ 326 : * Get the tick counter value.
327 : *
- 328 : * This stream if fully buffered.
- 329 : *
- 330 : * If no log file is selected, it's 0.
- 331 : */
- 332 : FILE* stdlog;
- 333 :
- 334 : /**
- 335 : * Exit codes for testing.
- 336 : */
- 337 : int exit_success;
- 338 : int exit_failure;
- 339 : int exit_sync_needed;
- 340 : #undef EXIT_SUCCESS
- 341 : #undef EXIT_FAILURE
- 342 : #define EXIT_SUCCESS exit_success
- 343 : #define EXIT_FAILURE exit_failure
- 344 : #define EXIT_SYNC_NEEDED exit_sync_needed
- 345 :
- 346 : /**
- 347 : * Fill memory with psudeo-random values.
- 348 : */
- 349 : int randomize(void* ptr, size_t size);
- 350 :
- 351 : /**
- 352 : * Additional SMART attributes.
- 353 : */
- 354 : #define SMART_ERROR 256 /**< ATA Error count. */
- 355 : #define SMART_SIZE 257 /**< Size in bytes. */
- 356 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */
- 357 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */
- 358 :
- 359 : /**
- 360 : * SMART attributes count.
- 361 : */
- 362 : #define SMART_COUNT 260
- 363 :
- 364 : /**
- 365 : * Flags returned by smartctl.
- 366 : */
- 367 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */
- 368 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */
- 369 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */
- 370 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
- 371 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
- 372 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */
- 373 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */
- 374 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
- 375 :
- 376 : /**
- 377 : * SMART max attribute length.
- 378 : */
- 379 : #define SMART_MAX 64
- 380 :
- 381 : /**
- 382 : * Value for unassigned SMART attribute.
- 383 : */
- 384 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL
- 385 :
- 386 : /**
- 387 : * Device info entry.
- 388 : */
- 389 : struct devinfo_struct {
- 390 : uint64_t device; /**< Device ID. */
- 391 : char name[PATH_MAX]; /**< Name of the disk. */
- 392 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */
- 393 : char smartctl[PATH_MAX]; /**< Options for smartctl. */
- 394 : char file[PATH_MAX]; /**< File device. */
- 395 : #ifdef _WIN32
- 396 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
- 397 : #endif
- 398 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */
- 399 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */
- 400 : char smart_serial[SMART_MAX]; /**< SMART serial number. */
- 401 : #if HAVE_PTHREAD_CREATE
- 402 : pthread_t thread;
- 403 : #endif
- 404 : tommy_node node;
- 405 : };
- 406 : typedef struct devinfo_struct devinfo_t;
- 407 :
- 408 : #define DEVICE_LIST 0
- 409 : #define DEVICE_DOWN 1
- 410 : #define DEVICE_UP 2
- 411 : #define DEVICE_SMART 3
- 412 :
- 413 : /**
- 414 : * Query all the "high" level devices with the specified operation,
- 415 : * and produces a list of "low" level devices to operate on.
- 416 : *
- 417 : * The passed "low" device list must be already initialized.
- 418 : */
- 419 : int devquery(tommy_list* high, tommy_list* low, int operation);
- 420 :
- 421 : #endif
- 422 :
+ 328 : * Note that the frequency is unspecified, because the time measure
+ 329 : * is meant to be used to compare the ratio between usage times.
+ 330 : */
+ 331 : uint64_t tick(void);
+ 332 :
+ 333 : /**
+ 334 : * Get the tick counter value in millisecond.
+ 335 : */
+ 336 : uint64_t tick_ms(void);
+ 337 :
+ 338 : /**
+ 339 : * Initializes the system.
+ 340 : */
+ 341 : void os_init(int opt);
+ 342 :
+ 343 : /**
+ 344 : * Deinitialize the system.
+ 345 : */
+ 346 : void os_done(void);
+ 347 :
+ 348 : /**
+ 349 : * Abort the process with a stacktrace.
+ 350 : */
+ 351 : void os_abort(void) __noreturn;
+ 352 :
+ 353 : /**
+ 354 : * Log file.
+ 355 : *
+ 356 : * This stream if fully buffered.
+ 357 : *
+ 358 : * If no log file is selected, it's 0.
+ 359 : */
+ 360 : FILE* stdlog;
+ 361 :
+ 362 : /**
+ 363 : * Exit codes for testing.
+ 364 : */
+ 365 : int exit_success;
+ 366 : int exit_failure;
+ 367 : int exit_sync_needed;
+ 368 : #undef EXIT_SUCCESS
+ 369 : #undef EXIT_FAILURE
+ 370 : #define EXIT_SUCCESS exit_success
+ 371 : #define EXIT_FAILURE exit_failure
+ 372 : #define EXIT_SYNC_NEEDED exit_sync_needed
+ 373 :
+ 374 : /**
+ 375 : * Fill memory with psudeo-random values.
+ 376 : */
+ 377 : int randomize(void* ptr, size_t size);
+ 378 :
+ 379 : /**
+ 380 : * Additional SMART attributes.
+ 381 : */
+ 382 : #define SMART_ERROR 256 /**< ATA Error count. */
+ 383 : #define SMART_SIZE 257 /**< Size in bytes. */
+ 384 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */
+ 385 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */
+ 386 :
+ 387 : /**
+ 388 : * SMART attributes count.
+ 389 : */
+ 390 : #define SMART_COUNT 260
+ 391 :
+ 392 : /**
+ 393 : * Flags returned by smartctl.
+ 394 : */
+ 395 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */
+ 396 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */
+ 397 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */
+ 398 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
+ 399 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
+ 400 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */
+ 401 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */
+ 402 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
+ 403 :
+ 404 : /**
+ 405 : * SMART max attribute length.
+ 406 : */
+ 407 : #define SMART_MAX 64
+ 408 :
+ 409 : /**
+ 410 : * Value for unassigned SMART attribute.
+ 411 : */
+ 412 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL
+ 413 :
+ 414 : /**
+ 415 : * Device info entry.
+ 416 : */
+ 417 : struct devinfo_struct {
+ 418 : uint64_t device; /**< Device ID. */
+ 419 : char name[PATH_MAX]; /**< Name of the disk. */
+ 420 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */
+ 421 : char smartctl[PATH_MAX]; /**< Options for smartctl. */
+ 422 : char file[PATH_MAX]; /**< File device. */
+ 423 : #ifdef _WIN32
+ 424 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
+ 425 : #endif
+ 426 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */
+ 427 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */
+ 428 : char smart_serial[SMART_MAX]; /**< SMART serial number. */
+ 429 : #if HAVE_PTHREAD
+ 430 : pthread_t thread;
+ 431 : #endif
+ 432 : tommy_node node;
+ 433 : };
+ 434 : typedef struct devinfo_struct devinfo_t;
+ 435 :
+ 436 : #define DEVICE_LIST 0
+ 437 : #define DEVICE_DOWN 1
+ 438 : #define DEVICE_UP 2
+ 439 : #define DEVICE_SMART 3
+ 440 :
+ 441 : /**
+ 442 : * Query all the "high" level devices with the specified operation,
+ 443 : * and produces a list of "low" level devices to operate on.
+ 444 : *
+ 445 : * The passed "low" device list must be already initialized.
+ 446 : */
+ 447 : int devquery(tommy_list* high, tommy_list* low, int operation);
+ 448 :
+ 449 : #endif
+ 450 :
diff --git a/cov/cmdline/rehash.c.func-sort-c.html b/cov/cmdline/rehash.c.func-sort-c.html
index 7f91b7d7..4ebb089d 100644
--- a/cov/cmdline/rehash.c.func-sort-c.html
+++ b/cov/cmdline/rehash.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/rehash.c.func.html b/cov/cmdline/rehash.c.func.html
index 4f50c788..66f4b11d 100644
--- a/cov/cmdline/rehash.c.func.html
+++ b/cov/cmdline/rehash.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/rehash.c.gcov.html b/cov/cmdline/rehash.c.gcov.html
index 66b8ba99..a8adc540 100644
--- a/cov/cmdline/rehash.c.gcov.html
+++ b/cov/cmdline/rehash.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -126,28 +126,28 @@
64 : }
65 :
66 : /* mark all the block for rehashing */
- 67 9200 : for (i = 0; i < blockmax; ++i) {
+ 67 9208 : for (i = 0; i < blockmax; ++i) {
68 : snapraid_info info;
69 :
70 : /* if it's unused */
- 71 9199 : info = info_get(&state->infoarr, i);
- 72 9199 : if (info == 0) {
+ 71 9207 : info = info_get(&state->infoarr, i);
+ 72 9207 : if (info == 0) {
73 : /* skip it */
74 0 : continue;
75 : }
76 :
- 77 9199 : if (info_get_rehash(info)) {
+ 77 9207 : if (info_get_rehash(info)) {
78 : /* LCOV_EXCL_START */
79 : log_fatal("Internal inconsistency for a rehash already in progress\n");
- 80 : exit(EXIT_FAILURE);
+ 80 : os_abort();
81 : /* LCOV_EXCL_STOP */
82 : }
83 :
84 : /* enable the rehash */
- 85 9199 : info = info_set_rehash(info);
+ 85 9207 : info = info_set_rehash(info);
86 :
87 : /* save it */
- 88 9199 : info_set(&state->infoarr, i, info);
+ 88 9207 : info_set(&state->infoarr, i, info);
89 : }
90 :
91 : /* save the new content file */
diff --git a/cov/cmdline/scan.c.func-sort-c.html b/cov/cmdline/scan.c.func-sort-c.html
index c14fca19..c5b96cf3 100644
--- a/cov/cmdline/scan.c.func-sort-c.html
+++ b/cov/cmdline/scan.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -61,59 +61,59 @@
| dd_name_compare |
- 10485497 |
+ 10959090 |
| dstat |
- 1004217 |
+ 1049496 |
| scan_file |
- 1003082 |
+ 1048310 |
| scan_file_keep |
- 923721 |
+ 968997 |
| file_is_full_invalid_parity_and_stable |
- 923721 |
-
-
- | dd_ino_compare |
- 103314 |
+ 968997 |
| scan_file_delayed_allocate |
- 100975 |
+ 103840 |
| scan_file_insert |
- 100975 |
+ 103840 |
| scan_file_allocate |
- 100975 |
+ 103840 |
+
+
+ | dd_ino_compare |
+ 103366 |
| scan_file_refresh |
- 79190 |
+ 79133 |
| scan_file_remove |
- 56139 |
+ 58983 |
| scan_file_deallocate |
- 56139 |
+ 58983 |
| scan_link |
- 32837 |
+ 34294 |
| file_is_full_hashed_and_stable |
- 23659 |
+ 23661 |
| scan_link_insert |
@@ -121,7 +121,7 @@
| scan_dir |
- 1614 |
+ 1713 |
| scan_link_remove |
@@ -129,22 +129,22 @@
| scan_emptydir |
- 227 |
+ 239 |
- | state_diffscan |
- 80 |
+ state_diffscan |
+ 88 |
- | state_scan |
- 73 |
+ state_scan |
+ 81 |
| scan_emptydir_insert |
10 |
- | state_diff |
+ state_diff |
7 |
diff --git a/cov/cmdline/scan.c.func.html b/cov/cmdline/scan.c.func.html
index abe27914..93ca7fe6 100644
--- a/cov/cmdline/scan.c.func.html
+++ b/cov/cmdline/scan.c.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -61,31 +61,31 @@
| dd_ino_compare |
- 103314 |
+ 103366 |
| dd_name_compare |
- 10485497 |
+ 10959090 |
| dstat |
- 1004217 |
+ 1049496 |
| file_is_full_hashed_and_stable |
- 23659 |
+ 23661 |
| file_is_full_invalid_parity_and_stable |
- 923721 |
+ 968997 |
| scan_dir |
- 1614 |
+ 1713 |
| scan_emptydir |
- 227 |
+ 239 |
| scan_emptydir_insert |
@@ -97,39 +97,39 @@
| scan_file |
- 1003082 |
+ 1048310 |
| scan_file_allocate |
- 100975 |
+ 103840 |
| scan_file_deallocate |
- 56139 |
+ 58983 |
| scan_file_delayed_allocate |
- 100975 |
+ 103840 |
| scan_file_insert |
- 100975 |
+ 103840 |
| scan_file_keep |
- 923721 |
+ 968997 |
| scan_file_refresh |
- 79190 |
+ 79133 |
| scan_file_remove |
- 56139 |
+ 58983 |
| scan_link |
- 32837 |
+ 34294 |
| scan_link_insert |
@@ -140,16 +140,16 @@
956 |
- | state_diff |
+ state_diff |
7 |
- | state_diffscan |
- 80 |
+ state_diffscan |
+ 88 |
- | state_scan |
- 73 |
+ state_scan |
+ 81 |
diff --git a/cov/cmdline/scan.c.gcov.html b/cov/cmdline/scan.c.gcov.html
index 28c662b0..6fbcb4f0 100644
--- a/cov/cmdline/scan.c.gcov.html
+++ b/cov/cmdline/scan.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -145,32 +145,32 @@
83 : /**
84 : * Process a symbolic link.
85 : */
- 86 32837 : static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag)
+ 86 34294 : static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag)
87 : {
- 88 32837 : struct snapraid_state* state = scan->state;
- 89 32837 : struct snapraid_disk* disk = scan->disk;
+ 88 34294 : struct snapraid_state* state = scan->state;
+ 89 34294 : struct snapraid_disk* disk = scan->disk;
90 : struct snapraid_link* slink;
91 :
92 : /* check if the link already exists */
- 93 32837 : slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub));
- 94 32837 : if (slink) {
+ 93 34294 : slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub));
+ 94 34294 : if (slink) {
95 : /* check if multiple files have the same name */
- 96 30380 : if (link_flag_has(slink, FILE_IS_PRESENT)) {
+ 96 31837 : if (link_flag_has(slink, FILE_IS_PRESENT)) {
97 : /* LCOV_EXCL_START */
98 : log_fatal("Internal inconsistency for link '%s%s'\n", disk->dir, sub);
- 99 : exit(EXIT_FAILURE);
+ 99 : os_abort();
100 : /* LCOV_EXCL_STOP */
101 : }
102 :
103 : /* mark as present */
- 104 30380 : link_flag_set(slink, FILE_IS_PRESENT);
+ 104 31837 : link_flag_set(slink, FILE_IS_PRESENT);
105 :
106 : /* check if the link is not changed and it's of the same kind */
- 107 30380 : if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) {
+ 107 31837 : if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) {
108 : /* it's equal */
- 109 30374 : ++scan->count_equal;
+ 109 31831 : ++scan->count_equal;
110 :
- 111 60748 : if (state->opt.gui) {
+ 111 63662 : if (state->opt.gui) {
112 829 : log_tag("scan:equal:%s:%s\n", disk->name, esc(slink->sub));
113 : }
114 : } else {
@@ -193,7 +193,7 @@
131 : }
132 :
133 : /* nothing more to do */
- 134 63217 : return;
+ 134 66131 : return;
135 : } else {
136 : /* create the new link */
137 2457 : ++scan->count_insert;
@@ -219,72 +219,72 @@
157 : /**
158 : * Insert the specified file in the parity.
159 : */
- 160 100975 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 160 103840 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
161 : {
- 162 100975 : struct snapraid_state* state = scan->state;
- 163 100975 : struct snapraid_disk* disk = scan->disk;
+ 162 103840 : struct snapraid_state* state = scan->state;
+ 163 103840 : struct snapraid_disk* disk = scan->disk;
164 : block_off_t i;
165 : block_off_t parity_pos;
166 :
167 : /* state changed */
- 168 100975 : state->need_write = 1;
+ 168 103840 : state->need_write = 1;
169 :
170 : /* allocate the blocks of the file */
- 171 100975 : parity_pos = disk->first_free_block;
- 172 349689 : for (i = 0; i < file->blockmax; ++i) {
+ 171 103840 : parity_pos = disk->first_free_block;
+ 172 355546 : for (i = 0; i < file->blockmax; ++i) {
173 : struct snapraid_block* block;
174 : struct snapraid_block* over_block;
175 : snapraid_info info;
176 :
177 : /* increment the position until the first really free block */
- 178 1013456 : while (block_has_file(fs_par2block_get(disk, parity_pos)))
- 179 516028 : ++parity_pos;
+ 178 1072060 : while (block_has_file(fs_par2block_get(disk, parity_pos)))
+ 179 568648 : ++parity_pos;
180 :
181 : /* get block we are going to overwrite, if any */
- 182 248714 : over_block = fs_par2block_get(disk, parity_pos);
+ 182 251706 : over_block = fs_par2block_get(disk, parity_pos);
183 :
184 : /* deallocate it */
- 185 248714 : if (over_block != BLOCK_EMPTY)
- 186 93089 : fs_deallocate(disk, parity_pos);
+ 185 251706 : if (over_block != BLOCK_EMPTY)
+ 186 95873 : fs_deallocate(disk, parity_pos);
187 :
188 : /* get block specific info */
- 189 248714 : info = info_get(&state->infoarr, parity_pos);
+ 189 251706 : info = info_get(&state->infoarr, parity_pos);
190 :
191 : /* get the new block we are going to write */
- 192 248714 : block = fs_file2block_get(file, i);
+ 192 251706 : block = fs_file2block_get(file, i);
193 :
194 : /* if the file block already has an updated hash without rehash */
- 195 248714 : if (block_has_updated_hash(block) && !info_get_rehash(info)) {
+ 195 251706 : if (block_has_updated_hash(block) && !info_get_rehash(info)) {
196 : /* the only possible case is for REP blocks */
- 197 37269 : assert(block_state_get(block) == BLOCK_STATE_REP);
+ 197 86941 : assert(block_state_get(block) == BLOCK_STATE_REP);
198 :
199 : /* convert to a REP block */
- 200 37269 : block_state_set(block, BLOCK_STATE_REP);
+ 200 86941 : block_state_set(block, BLOCK_STATE_REP);
201 :
202 : /* and keep the hash as it's */
203 : } else {
204 : unsigned over_state;
205 :
206 : /* convert to a CHG block */
- 207 211445 : block_state_set(block, BLOCK_STATE_CHG);
+ 207 164765 : block_state_set(block, BLOCK_STATE_CHG);
208 :
209 : /* state of the block we are going to overwrite */
- 210 211445 : over_state = block_state_get(over_block);
+ 210 164765 : over_state = block_state_get(over_block);
211 :
212 : /* if the block is an empty one */
- 213 211445 : if (over_state == BLOCK_STATE_EMPTY) {
+ 213 164765 : if (over_state == BLOCK_STATE_EMPTY) {
214 : /* the block was empty and filled with zeros */
215 : /* set the hash to the special ZERO value */
- 216 153288 : hash_zero_set(block->hash);
+ 216 115487 : hash_zero_set(block->hash);
217 : } else {
218 : /* otherwise it's a DELETED one */
- 219 58157 : assert(over_state == BLOCK_STATE_DELETED);
+ 219 49278 : assert(over_state == BLOCK_STATE_DELETED);
220 :
221 : /* copy the past hash of the block */
- 222 58157 : memcpy(block->hash, over_block->hash, HASH_SIZE);
+ 222 49278 : memcpy(block->hash, over_block->hash, HASH_SIZE);
223 :
224 : /* if we have not already cleared the past hash */
- 225 58157 : if (!state->clear_past_hash) {
+ 225 49278 : if (!state->clear_past_hash) {
226 : /* in this case we don't know if the old state is still the one */
227 : /* stored inside the parity, because after an aborted sync, the parity */
228 : /* may be or may be not have been updated with the new data */
@@ -294,22 +294,22 @@
232 : /* - Sync aborted after, updating the parity to the new state, */
233 : /* but without saving the content file representing this new state. */
234 : /* - Another file is added again (exactly here) */
- 235 : /* with the hash of DELETED block not represeting the real parity state */
+ 235 : /* with the hash of DELETED block not representing the real parity state */
236 381 : hash_invalid_set(block->hash);
237 : }
238 : }
239 : }
240 :
241 : /* store in the disk map, after invalidating all the other blocks */
- 242 248714 : fs_allocate(disk, parity_pos, file, i);
+ 242 251706 : fs_allocate(disk, parity_pos, file, i);
243 :
244 : /* set the new free position */
- 245 248714 : disk->first_free_block = parity_pos + 1;
+ 245 251706 : disk->first_free_block = parity_pos + 1;
246 : }
247 :
248 : /* insert in the list of contained files */
- 249 100975 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
- 250 100975 : }
+ 249 103840 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
+ 250 103840 : }
251 :
252 : /**
253 : * Delete the specified file from the parity.
@@ -318,44 +318,44 @@
256 : * The file is then inserted in the deleted set, and it should not be deallocated,
257 : * as the parity still references it.
258 : */
- 259 56139 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 259 58983 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file)
260 : {
- 261 56139 : struct snapraid_state* state = scan->state;
- 262 56139 : struct snapraid_disk* disk = scan->disk;
+ 261 58983 : struct snapraid_state* state = scan->state;
+ 262 58983 : struct snapraid_disk* disk = scan->disk;
263 : block_off_t i;
264 :
265 : /* remove from the list of contained files */
- 266 56139 : tommy_list_remove_existing(&disk->filelist, &file->nodelist);
+ 266 58983 : tommy_list_remove_existing(&disk->filelist, &file->nodelist);
267 :
268 : /* state changed */
- 269 56139 : state->need_write = 1;
+ 269 58983 : state->need_write = 1;
270 :
271 : /* here we are supposed to adjust the ::first_free_block position */
272 : /* with the parity position we are deleting */
273 : /* but we also know that we do only delayed insert, after all the deletion, */
274 : /* so at this point ::first_free_block is always at 0, and we don't need to update it */
- 275 56139 : if (disk->first_free_block != 0) {
+ 275 58983 : if (disk->first_free_block != 0) {
276 : /* LCOV_EXCL_START */
277 : log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub);
- 278 : exit(EXIT_FAILURE);
+ 278 : os_abort();
279 : /* LCOV_EXCL_STOP */
280 : }
281 :
282 : /* free all the blocks of the file */
- 283 194478 : for (i = 0; i < file->blockmax; ++i) {
- 284 138339 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 283 200146 : for (i = 0; i < file->blockmax; ++i) {
+ 284 141163 : struct snapraid_block* block = fs_file2block_get(file, i);
285 : unsigned block_state;
286 :
287 : /* in case we scan after an aborted sync, */
288 : /* we could get also intermediate states */
- 289 138339 : block_state = block_state_get(block);
- 290 138339 : switch (block_state) {
+ 289 141163 : block_state = block_state_get(block);
+ 290 141163 : switch (block_state) {
291 : case BLOCK_STATE_BLK :
292 : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */
- 293 33544 : break;
+ 293 33358 : break;
294 : case BLOCK_STATE_CHG :
295 : /* if we have not already cleared the past hash */
- 296 57596 : if (!state->clear_past_hash) {
+ 296 28000 : if (!state->clear_past_hash) {
297 : /* in these cases we don't know if the old state is still the one */
298 : /* stored inside the parity, because after an aborted sync, the parity */
299 : /* may be or may be not have been updated with the data that it's now */
@@ -366,39 +366,39 @@
304 : /* but without saving the content file representing this new state. */
305 : /* - File is now deleted after the aborted sync */
306 : /* - Sync again, deleting the blocks (exactly here) */
- 307 : /* with the hash of CHG block not represeting the real parity state */
+ 307 : /* with the hash of CHG block not representing the real parity state */
308 0 : hash_invalid_set(block->hash);
309 : }
- 310 57596 : break;
+ 310 28000 : break;
311 : case BLOCK_STATE_REP :
312 : /* we just don't know the old hash, and then we set it to invalid */
- 313 47199 : hash_invalid_set(block->hash);
- 314 47199 : break;
+ 313 79805 : hash_invalid_set(block->hash);
+ 314 79805 : break;
315 : default :
316 : /* LCOV_EXCL_START */
317 : log_fatal("Internal inconsistency in file '%s' deallocating block '%u:%u' state %u\n", file->sub, i, file->blockmax, block_state);
- 318 : exit(EXIT_FAILURE);
+ 318 : os_abort();
319 : /* LCOV_EXCL_STOP */
320 : }
321 :
322 : /* set the block as deleted */
- 323 138339 : block_state_set(block, BLOCK_STATE_DELETED);
+ 323 141163 : block_state_set(block, BLOCK_STATE_DELETED);
324 : }
325 :
326 : /* mark the file as deleted */
- 327 56139 : file_flag_set(file, FILE_IS_DELETED);
+ 327 58983 : file_flag_set(file, FILE_IS_DELETED);
328 :
329 : /* insert it in the list of deleted blocks */
- 330 56139 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file);
- 331 56139 : }
+ 330 58983 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file);
+ 331 58983 : }
332 :
- 333 100975 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 333 103840 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
334 : {
- 335 100975 : struct snapraid_state* state = scan->state;
- 336 100975 : struct snapraid_disk* disk = scan->disk;
+ 335 103840 : struct snapraid_state* state = scan->state;
+ 336 103840 : struct snapraid_disk* disk = scan->disk;
337 :
338 : /* if we sort for physical offsets we have to read them for new files */
- 339 100975 : if (state->opt.force_order == SORT_PHYSICAL
+ 339 103840 : if (state->opt.force_order == SORT_PHYSICAL
340 11432 : && file->physical == FILEPHY_UNREAD_OFFSET
341 : ) {
342 : char path_next[PATH_MAX];
@@ -414,30 +414,30 @@
352 : }
353 :
354 : /* insert in the delayed list */
- 355 100975 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file);
- 356 100975 : }
+ 355 103840 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file);
+ 356 103840 : }
357 :
358 : /**
359 : * Check if a file is completely formed of blocks with invalid parity,
360 : * and no rehash is tagged, and if it has at least one block.
361 : */
- 362 923721 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
+ 362 968997 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
363 : {
364 : block_off_t i;
365 :
366 : /* with no block, it never has an invalid parity */
- 367 923721 : if (file->blockmax == 0)
- 368 1290 : return 0;
+ 367 968997 : if (file->blockmax == 0)
+ 368 1354 : return 0;
369 :
370 : /* check all blocks */
- 371 976066 : for (i = 0; i < file->blockmax; ++i) {
+ 371 1032530 : for (i = 0; i < file->blockmax; ++i) {
372 : snapraid_info info;
- 373 954281 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 373 1007823 : struct snapraid_block* block = fs_file2block_get(file, i);
374 : block_off_t parity_pos;
375 :
376 : /* exclude blocks with parity */
- 377 954281 : if (!block_has_invalid_parity(block))
- 378 900646 : return 0;
+ 377 1007823 : if (!block_has_invalid_parity(block))
+ 378 923696 : return 0;
379 :
380 : /*
381 : * Get the parity position, but only after checking
@@ -445,40 +445,40 @@
383 : * This is not really required, as we are sure
384 : * that 'kept" files are mapped into parity.
385 : */
- 386 53635 : parity_pos = fs_file2par_get(disk, file, i);
+ 386 84127 : parity_pos = fs_file2par_get(disk, file, i);
387 :
388 : /* get block specific info */
- 389 53635 : info = info_get(&state->infoarr, parity_pos);
+ 389 84127 : info = info_get(&state->infoarr, parity_pos);
390 :
391 : /* if rehash fails */
- 392 53635 : if (info_get_rehash(info))
- 393 0 : return 0;
+ 392 84127 : if (info_get_rehash(info))
+ 393 19240 : return 0;
394 : }
395 :
- 396 21785 : return 1;
+ 396 24707 : return 1;
397 : }
398 :
399 : /**
400 : * Check if a file is completely formed of blocks with an updated hash,
401 : * and no rehash is tagged, and if it has at least one block.
402 : */
- 403 23659 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
+ 403 23661 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
404 : {
405 : block_off_t i;
406 :
407 : /* with no block, it never has a hash */
- 408 23659 : if (file->blockmax == 0)
+ 408 23661 : if (file->blockmax == 0)
409 27 : return 0;
410 :
411 : /* check all blocks */
- 412 42158 : for (i = 0; i < file->blockmax; ++i) {
+ 412 81853 : for (i = 0; i < file->blockmax; ++i) {
413 : snapraid_info info;
- 414 35949 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 414 58220 : struct snapraid_block* block = fs_file2block_get(file, i);
415 : block_off_t parity_pos;
416 :
417 : /* exclude blocks without hash */
- 418 35949 : if (!block_has_updated_hash(block))
- 419 1704 : return 0;
+ 418 58220 : if (!block_has_updated_hash(block))
+ 419 1 : return 0;
420 :
421 : /*
422 : * Get the parity position, but only AFTER checking
@@ -492,17 +492,17 @@
430 : * As just allocated files have only CHG blocks, checking that
431 : * the hash is updated is enough to exclude such cases.
432 : */
- 433 34245 : parity_pos = fs_file2par_get(disk, file, i);
+ 433 58219 : parity_pos = fs_file2par_get(disk, file, i);
434 :
435 : /* get block specific info */
- 436 34245 : info = info_get(&state->infoarr, parity_pos);
+ 436 58219 : info = info_get(&state->infoarr, parity_pos);
437 :
438 : /* exclude blocks needing a rehash */
- 439 34245 : if (info_get_rehash(info))
- 440 15719 : return 0;
+ 439 58219 : if (info_get_rehash(info))
+ 440 0 : return 0;
441 : }
442 :
- 443 6209 : return 1;
+ 443 23633 : return 1;
444 : }
445 :
446 : /**
@@ -514,7 +514,7 @@
452 : *
453 : * If this happens, we read also the physical offset, to avoid to read it later.
454 : */
- 455 79190 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)
+ 455 79133 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)
456 : {
457 : #if HAVE_LSTAT_SYNC
458 : struct snapraid_state* state = scan->state;
@@ -586,43 +586,43 @@
524 : (void)st;
525 : (void)physical;
526 : #endif
- 527 79190 : }
+ 527 79133 : }
528 :
529 : /**
530 : * Insert the file in the data set.
531 : */
- 532 100975 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)
+ 532 103840 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)
533 : {
- 534 100975 : struct snapraid_disk* disk = scan->disk;
+ 534 103840 : struct snapraid_disk* disk = scan->disk;
535 :
536 : /* insert the file in the containers */
- 537 100975 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
- 538 100975 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
- 539 100975 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
- 540 100975 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
+ 537 103840 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
+ 538 103840 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 539 103840 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
+ 540 103840 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
541 :
542 : /* delayed allocation of the parity */
- 543 100975 : scan_file_delayed_allocate(scan, file);
- 544 100975 : }
+ 543 103840 : scan_file_delayed_allocate(scan, file);
+ 544 103840 : }
545 :
546 : /**
547 : * Remove the file from the data set.
548 : *
549 : * File is then deleted.
550 : */
- 551 56139 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file)
+ 551 58983 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file)
552 : {
- 553 56139 : struct snapraid_disk* disk = scan->disk;
+ 553 58983 : struct snapraid_disk* disk = scan->disk;
554 :
555 : /* remove the file from the containers */
- 556 56139 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
- 557 56084 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
- 558 56139 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
- 559 56139 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
+ 556 58983 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
+ 557 58942 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 558 58983 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
+ 559 58983 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
560 :
561 : /* deallocate the file from the parity */
- 562 56139 : scan_file_deallocate(scan, file);
- 563 56139 : }
+ 562 58983 : scan_file_deallocate(scan, file);
+ 563 58983 : }
564 :
565 : /**
566 : * Keep the file as it's (or with only a name/inode modification).
@@ -635,29 +635,29 @@
573 : * This could happen after a failed sync, when some other files are deleted,
574 : * and then new ones can be moved backward to fill the hole created.
575 : */
- 576 923721 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file)
+ 576 968997 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file)
577 : {
- 578 923721 : struct snapraid_disk* disk = scan->disk;
+ 578 968997 : struct snapraid_disk* disk = scan->disk;
579 :
580 : /* if the file is full invalid, schedule a reinsert at later stage */
- 581 923721 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {
- 582 21785 : struct snapraid_file* copy = file_dup(file);
+ 581 968997 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {
+ 582 24707 : struct snapraid_file* copy = file_dup(file);
583 :
584 : /* remove the file */
- 585 21785 : scan_file_remove(scan, file);
+ 585 24707 : scan_file_remove(scan, file);
586 :
587 : /* reinsert the copy in the delayed list */
- 588 21785 : scan_file_insert(scan, copy);
+ 588 24707 : scan_file_insert(scan, copy);
589 : }
- 590 923721 : }
+ 590 968997 : }
591 :
592 : /**
593 : * Process a file.
594 : */
- 595 1003082 : static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical)
+ 595 1048310 : static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical)
596 : {
- 597 1003082 : struct snapraid_state* state = scan->state;
- 598 1003082 : struct snapraid_disk* disk = scan->disk;
+ 597 1048310 : struct snapraid_state* state = scan->state;
+ 598 1048310 : struct snapraid_disk* disk = scan->disk;
599 : struct snapraid_file* file;
600 : tommy_node* i;
601 : int is_original_file_size_different_than_zero;
@@ -668,7 +668,7 @@
606 : * If the disk has persistent inodes and UUID, try a search on the past inodes,
607 : * to detect moved files.
608 : *
- 609 : * For persistent inodes we mean inodes that keep their values when the filesystem
+ 609 : * For persistent inodes we mean inodes that keep their values when the file-system
610 : * is unmounted and remounted. This don't always happen.
611 : *
612 : * Cases found are:
@@ -682,55 +682,55 @@
620 : * file recognition.
621 : *
622 : * For persistent UUID we mean that it has the same UUID as before.
- 623 : * Otherwise, if the UUID is changed, likely it's a new recreated filesystem,
+ 623 : * Otherwise, if the UUID is changed, likely it's a new recreated file-system,
624 : * and then the inode have no meaning.
625 : *
- 626 : * Note that to disable the search by past inode, we do this implicitely
+ 626 : * Note that to disable the search by past inode, we do this implicitly
627 : * removing all the past inode before searching for files.
628 : * This ensures that no file is found with a past inode, but at the same time,
629 : * it allows to find new files with the same inode, to identify them as hardlinks.
630 : */
- 631 1003082 : int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid;
+ 631 1048310 : int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid;
632 :
633 : /* always search with the new inode, in the all new inodes found until now, */
634 : /* with the eventual presence of also the past inodes */
- 635 1003082 : uint64_t inode = st->st_ino;
+ 635 1048310 : uint64_t inode = st->st_ino;
636 :
- 637 1003082 : file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
+ 637 1048310 : file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
638 :
639 : /* identify moved files with past inodes and hardlinks with the new inodes */
- 640 1003082 : if (file) {
+ 640 1048310 : if (file) {
641 : /* check if the file is not changed */
- 642 837733 : if (file->size == st->st_size
- 643 826569 : && file->mtime_sec == st->st_mtime
- 644 823506 : && (file->mtime_nsec == STAT_NSEC(st)
+ 642 889551 : if (file->size == st->st_size
+ 643 871917 : && file->mtime_sec == st->st_mtime
+ 644 868905 : && (file->mtime_nsec == STAT_NSEC(st)
645 : /* always accept the stored value if it's STAT_NSEC_INVALID */
646 : /* it happens when upgrading from an old version of SnapRAID */
647 : /* not yet supporting the nanosecond field */
- 648 2 : || file->mtime_nsec == STAT_NSEC_INVALID
+ 648 6 : || file->mtime_nsec == STAT_NSEC_INVALID
649 : )
650 : ) {
651 : /* check if multiple files have the same inode */
- 652 823504 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 652 868899 : if (file_flag_has(file, FILE_IS_PRESENT)) {
653 : #if HAVE_STRUCT_STAT_ST_NLINK
- 654 171 : if (st->st_nlink <= 1) {
+ 654 180 : if (st->st_nlink <= 1) {
655 : /* LCOV_EXCL_START */
656 : log_fatal("Internal inode '%" PRIu64 "' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub);
- 657 : exit(EXIT_FAILURE);
+ 657 : os_abort();
658 : /* LCOV_EXCL_STOP */
659 : }
660 : #endif
661 : /* it's a hardlink */
- 662 171 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK);
- 663 171 : return;
+ 662 180 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK);
+ 663 180 : return;
664 : }
665 :
666 : /* mark as present */
- 667 823333 : file_flag_set(file, FILE_IS_PRESENT);
+ 667 868719 : file_flag_set(file, FILE_IS_PRESENT);
668 :
669 : /* update the nanoseconds mtime only if different */
670 : /* to avoid unneeded updates */
- 671 823333 : if (file->mtime_nsec == STAT_NSEC_INVALID
+ 671 868719 : if (file->mtime_nsec == STAT_NSEC_INVALID
672 0 : && STAT_NSEC(st) != file->mtime_nsec
673 : ) {
674 0 : file->mtime_nsec = STAT_NSEC(st);
@@ -739,7 +739,7 @@
677 0 : state->need_write = 1;
678 : }
679 :
- 680 823333 : if (strcmp(file->sub, sub) != 0) {
+ 680 868719 : if (strcmp(file->sub, sub) != 0) {
681 : /* if the path is different, it means a moved file with the same inode */
682 155 : ++scan->count_move;
683 :
@@ -761,96 +761,96 @@
699 155 : state->need_write = 1;
700 : } else {
701 : /* otherwise it's equal */
- 702 823178 : ++scan->count_equal;
+ 702 868564 : ++scan->count_equal;
703 :
- 704 823178 : if (state->opt.gui) {
- 705 22559 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub));
+ 704 868564 : if (state->opt.gui) {
+ 705 22587 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub));
706 : }
707 : }
708 :
709 : /* mark the file as kept */
- 710 823333 : scan_file_keep(scan, file);
+ 710 868719 : scan_file_keep(scan, file);
711 :
712 : /* nothing more to do */
- 713 823333 : return;
+ 713 868719 : return;
714 : }
715 :
716 : /* here the file matches the inode, but not the other info */
717 : /* if could be a modified file with the same name, */
718 : /* or a restored/copied file that get assigned a previously used inode, */
- 719 : /* or a filesystem with not persistent inodes */
+ 719 : /* or a file-system with not persistent inodes */
720 :
721 : /* for sure it cannot be already present */
- 722 14229 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 722 20652 : if (file_flag_has(file, FILE_IS_PRESENT)) {
723 : /* LCOV_EXCL_START */
724 : log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub);
- 725 : exit(EXIT_FAILURE);
+ 725 : os_abort();
726 : /* LCOV_EXCL_STOP */
727 : }
728 :
729 : /* assume a previously used inode, it's the worst case */
730 : /* and we handle it removing the duplicate stored inode. */
- 731 : /* If the file is found by name (not necessarely in this function call), */
+ 731 : /* If the file is found by name (not necessarily in this function call), */
732 : /* it will have the inode restored, otherwise, it will get removed */
733 :
734 : /* remove from the inode set */
- 735 14229 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 735 20652 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
736 :
737 : /* clear the inode */
738 : /* this is not really needed for correct functionality */
739 : /* because we are going to set FILE_IS_WITHOUT_INODE */
740 : /* but it's easier for debugging to have invalid inodes set to 0 */
- 741 14229 : file->inode = 0;
+ 741 20652 : file->inode = 0;
742 :
743 : /* mark as missing inode */
- 744 14229 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
+ 744 20652 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
745 :
746 : /* go further to find it by name */
747 : }
748 :
749 : /* initialize for later overwrite */
- 750 179578 : is_file_reported = 0;
- 751 179578 : is_original_file_size_different_than_zero = 0;
+ 750 179411 : is_file_reported = 0;
+ 751 179411 : is_original_file_size_different_than_zero = 0;
752 :
753 : /* then try finding it by name */
- 754 179578 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub));
+ 754 179411 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub));
755 :
756 : /* keep track if the file already exists */
- 757 179578 : is_file_already_present = file != 0;
+ 757 179411 : is_file_already_present = file != 0;
758 :
- 759 179578 : if (is_file_already_present) {
+ 759 179411 : if (is_file_already_present) {
760 : /* if the file is without an inode */
- 761 105104 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) {
+ 761 104908 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) {
762 : /* set it now */
- 763 14174 : file->inode = st->st_ino;
+ 763 20621 : file->inode = st->st_ino;
764 :
765 : /* insert in the set */
- 766 14174 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 766 20621 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
767 :
768 : /* unmark as missing inode */
- 769 14174 : file_flag_clear(file, FILE_IS_WITHOUT_INODE);
+ 769 20621 : file_flag_clear(file, FILE_IS_WITHOUT_INODE);
770 : } else {
771 : /* here the inode has to be different, otherwise we would have found it before */
- 772 90930 : if (file->inode == st->st_ino) {
+ 772 84287 : if (file->inode == st->st_ino) {
773 : /* LCOV_EXCL_START */
774 : log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub);
- 775 : exit(EXIT_FAILURE);
+ 775 : os_abort();
776 : /* LCOV_EXCL_STOP */
777 : }
778 : }
779 :
780 : /* for sure it cannot be already present */
- 781 105104 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 781 104908 : if (file_flag_has(file, FILE_IS_PRESENT)) {
782 : /* LCOV_EXCL_START */
783 : log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub);
- 784 : exit(EXIT_FAILURE);
+ 784 : os_abort();
785 : /* LCOV_EXCL_STOP */
786 : }
787 :
788 : /* check if the file is not changed */
- 789 105104 : if (file->size == st->st_size
- 790 104510 : && file->mtime_sec == st->st_mtime
- 791 100388 : && (file->mtime_nsec == STAT_NSEC(st)
+ 789 104908 : if (file->size == st->st_size
+ 790 104314 : && file->mtime_sec == st->st_mtime
+ 791 100278 : && (file->mtime_nsec == STAT_NSEC(st)
792 : /* always accept the stored value if it's STAT_NSEC_INVALID */
793 : /* it happens when upgrading from an old version of SnapRAID */
794 : /* not yet supporting the nanosecond field */
@@ -858,11 +858,11 @@
796 : )
797 : ) {
798 : /* mark as present */
- 799 100388 : file_flag_set(file, FILE_IS_PRESENT);
+ 799 100278 : file_flag_set(file, FILE_IS_PRESENT);
800 :
801 : /* update the nano seconds mtime only if different */
802 : /* to avoid unneeded updates */
- 803 100388 : if (file->mtime_nsec == STAT_NSEC_INVALID
+ 803 100278 : if (file->mtime_nsec == STAT_NSEC_INVALID
804 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID
805 : ) {
806 0 : file->mtime_nsec = STAT_NSEC(st);
@@ -872,55 +872,55 @@
810 : }
811 :
812 : /* if when processing the disk we used the past inodes values */
- 813 100388 : if (has_past_inodes) {
+ 813 100278 : if (has_past_inodes) {
814 : /* if persistent inodes are supported, we are sure that the inode number */
815 : /* is now different, because otherwise the file would have been found */
816 : /* when searching by inode. */
817 : /* if the inode is different, it means a rewritten file with the same path */
818 : /* like when restoring a backup that restores also the timestamp */
- 819 100388 : ++scan->count_restore;
+ 819 100268 : ++scan->count_restore;
820 :
- 821 100388 : log_tag("scan:restore:%s:%s\n", disk->name, esc(sub));
- 822 100388 : if (is_diff) {
+ 821 100268 : log_tag("scan:restore:%s:%s\n", disk->name, esc(sub));
+ 822 100268 : if (is_diff) {
823 0 : printf("restore %s%s\n", disk->dir, sub);
824 : }
825 :
826 : /* remove from the inode set */
- 827 100388 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 827 100268 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
828 :
829 : /* save the new inode */
- 830 100388 : file->inode = st->st_ino;
+ 830 100268 : file->inode = st->st_ino;
831 :
832 : /* reinsert in the inode set */
- 833 100388 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 833 100268 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
834 :
835 : /* we have to save the new inode */
- 836 100388 : state->need_write = 1;
+ 836 100268 : state->need_write = 1;
837 : } else {
838 : /* otherwise it's the case of not persistent inode, where doesn't */
839 : /* matter if the inode is different or equal, because they have no */
840 : /* meaning, and then we don't even save them */
- 841 0 : ++scan->count_equal;
+ 841 10 : ++scan->count_equal;
842 :
- 843 0 : if (state->opt.gui) {
+ 843 10 : if (state->opt.gui) {
844 0 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub));
845 : }
846 : }
847 :
848 : /* mark the file as kept */
- 849 100388 : scan_file_keep(scan, file);
+ 849 100278 : scan_file_keep(scan, file);
850 :
851 : /* nothing more to do */
- 852 100388 : return;
+ 852 100278 : return;
853 : }
854 :
855 : /* here if the file is changed but with the correct name */
856 :
857 : /* keep track if the original file was not of zero size */
- 858 4716 : is_original_file_size_different_than_zero = file->size != 0;
+ 858 4630 : is_original_file_size_different_than_zero = file->size != 0;
859 :
860 : /* remove it, and continue to insert it again */
- 861 4716 : scan_file_remove(scan, file);
+ 861 4630 : scan_file_remove(scan, file);
862 :
863 : /* and continue to insert it again */
864 : }
@@ -928,13 +928,13 @@
866 : /* refresh the info, to ensure that they are synced, */
867 : /* note that we refresh only the info of the new or modified files */
868 : /* because this is slow operation */
- 869 79190 : scan_file_refresh(scan, sub, st, &physical);
+ 869 79133 : scan_file_refresh(scan, sub, st, &physical);
870 :
871 : #ifndef _WIN32
872 : /* do a safety check to ensure that the common ext4 case of zeroing */
873 : /* the size of a file after a crash doesn't propagate to the backup */
874 : /* this check is specific for Linux, so we disable it on Windows */
- 875 79190 : if (is_original_file_size_different_than_zero && st->st_size == 0) {
+ 875 79133 : if (is_original_file_size_different_than_zero && st->st_size == 0) {
876 0 : if (!state->opt.force_zero) {
877 : /* LCOV_EXCL_START */
878 : log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub);
@@ -953,74 +953,74 @@
891 : #endif
892 :
893 : /* insert it */
- 894 79190 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical);
+ 894 79133 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical);
895 :
896 : /* mark it as present */
- 897 79190 : file_flag_set(file, FILE_IS_PRESENT);
+ 897 79133 : file_flag_set(file, FILE_IS_PRESENT);
898 :
899 : /* if copy detection is enabled */
900 : /* note that the copy detection is tried also for updated files */
901 : /* this makes sense because it may happen to have two different copies */
902 : /* of the same file, and we move the right one over the wrong one */
903 : /* in such case we have a "copy" over an "update" */
- 904 79190 : if (!state->opt.force_nocopy) {
- 905 79190 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
+ 904 79133 : if (!state->opt.force_nocopy) {
+ 905 79133 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
906 :
907 : /* search for a file with the same name and stamp in all the disks */
- 908 518611 : for (i = state->disklist; i != 0; i = i->next) {
- 909 445630 : struct snapraid_disk* other_disk = i->data;
+ 908 422996 : for (i = state->disklist; i != 0; i = i->next) {
+ 909 367496 : struct snapraid_disk* other_disk = i->data;
910 : struct snapraid_file* other_file;
911 :
912 : /* if the nanosecond part of the time stamp is valid, search */
913 : /* for name and stamp, otherwise for path and stamp */
- 914 445630 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
- 915 445522 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
+ 914 367496 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
+ 915 367388 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
916 : else
917 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash);
918 :
919 : /* if found, and it's a fully hashed file */
- 920 445630 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
+ 920 367496 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
921 : /* assume that the file is a copy, and reuse the hash */
- 922 6209 : file_copy(other_file, file);
+ 922 23633 : file_copy(other_file, file);
923 :
924 : /* revert old counter and use the copy one */
- 925 6209 : ++scan->count_copy;
+ 925 23633 : ++scan->count_copy;
926 :
- 927 6209 : log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc(other_file->sub), disk->name, esc(file->sub));
- 928 6209 : if (is_diff) {
+ 927 23633 : log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc(other_file->sub), disk->name, esc(file->sub));
+ 928 23633 : if (is_diff) {
929 31 : printf("copy %s%s -> %s%s\n", other_disk->dir, other_file->sub, disk->dir, file->sub);
930 : }
931 :
932 : /* mark it as reported */
- 933 6209 : is_file_reported = 1;
+ 933 23633 : is_file_reported = 1;
934 :
935 : /* no need to continue the search */
- 936 6209 : break;
+ 936 23633 : break;
937 : }
938 : }
939 : }
940 :
941 : /* if not yet reported, do it now */
- 942 79190 : if (!is_file_reported) {
- 943 72981 : if (is_file_already_present) {
- 944 4716 : ++scan->count_change;
+ 942 79133 : if (!is_file_reported) {
+ 943 55500 : if (is_file_already_present) {
+ 944 4630 : ++scan->count_change;
945 :
- 946 4716 : log_tag("scan:update:%s:%s\n", disk->name, esc(sub));
- 947 4716 : if (is_diff) {
+ 946 4630 : log_tag("scan:update:%s:%s\n", disk->name, esc(sub));
+ 947 4630 : if (is_diff) {
948 118 : printf("update %s%s\n", disk->dir, sub);
949 : }
950 : } else {
- 951 68265 : ++scan->count_insert;
+ 951 50870 : ++scan->count_insert;
952 :
- 953 68265 : log_tag("scan:add:%s:%s\n", disk->name, esc(sub));
- 954 68265 : if (is_diff) {
- 955 17044 : printf("add %s%s\n", disk->dir, sub);
+ 953 50870 : log_tag("scan:add:%s:%s\n", disk->name, esc(sub));
+ 954 50870 : if (is_diff) {
+ 955 17051 : printf("add %s%s\n", disk->dir, sub);
956 : }
957 : }
958 : }
959 :
960 : /* insert the file in the delayed list */
- 961 79190 : scan_file_insert(scan, file);
+ 961 79133 : scan_file_insert(scan, file);
962 : }
963 :
964 : /**
@@ -1061,27 +1061,27 @@
999 : /**
1000 : * Process a dir.
1001 : */
- 1002 227 : static void scan_emptydir(struct snapraid_scan* scan, const char* sub)
+ 1002 239 : static void scan_emptydir(struct snapraid_scan* scan, const char* sub)
1003 : {
- 1004 227 : struct snapraid_disk* disk = scan->disk;
+ 1004 239 : struct snapraid_disk* disk = scan->disk;
1005 : struct snapraid_dir* dir;
1006 :
1007 : /* check if the dir already exists */
- 1008 227 : dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub));
- 1009 227 : if (dir) {
+ 1008 239 : dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub));
+ 1009 239 : if (dir) {
1010 : /* check if multiple files have the same name */
- 1011 217 : if (dir_flag_has(dir, FILE_IS_PRESENT)) {
+ 1011 229 : if (dir_flag_has(dir, FILE_IS_PRESENT)) {
1012 : /* LCOV_EXCL_START */
1013 : log_fatal("Internal inconsistency for dir '%s%s'\n", disk->dir, sub);
- 1014 : exit(EXIT_FAILURE);
+ 1014 : os_abort();
1015 : /* LCOV_EXCL_STOP */
1016 : }
1017 :
1018 : /* mark as present */
- 1019 217 : dir_flag_set(dir, FILE_IS_PRESENT);
+ 1019 229 : dir_flag_set(dir, FILE_IS_PRESENT);
1020 :
1021 : /* nothing more to do */
- 1022 444 : return;
+ 1022 468 : return;
1023 : } else {
1024 : /* and continue to insert it */
1025 : }
@@ -1113,26 +1113,26 @@
1051 : };
1052 :
1053 : #if HAVE_STRUCT_DIRENT_D_INO
- 1054 103314 : static int dd_ino_compare(const void* void_a, const void* void_b)
+ 1054 103366 : static int dd_ino_compare(const void* void_a, const void* void_b)
1055 : {
- 1056 103314 : const struct dirent_sorted* a = void_a;
- 1057 103314 : const struct dirent_sorted* b = void_b;
+ 1056 103366 : const struct dirent_sorted* a = void_a;
+ 1057 103366 : const struct dirent_sorted* b = void_b;
1058 :
- 1059 103314 : if (a->d_ino < b->d_ino)
- 1060 49400 : return -1;
- 1061 53914 : if (a->d_ino > b->d_ino)
- 1062 53914 : return 1;
+ 1059 103366 : if (a->d_ino < b->d_ino)
+ 1060 49430 : return -1;
+ 1061 53936 : if (a->d_ino > b->d_ino)
+ 1062 53936 : return 1;
1063 :
1064 0 : return 0;
1065 : }
1066 : #endif
1067 :
- 1068 10485497 : static int dd_name_compare(const void* void_a, const void* void_b)
+ 1068 10959090 : static int dd_name_compare(const void* void_a, const void* void_b)
1069 : {
- 1070 10485497 : const struct dirent_sorted* a = void_a;
- 1071 10485497 : const struct dirent_sorted* b = void_b;
+ 1070 10959090 : const struct dirent_sorted* a = void_a;
+ 1071 10959090 : const struct dirent_sorted* b = void_b;
1072 :
- 1073 10485497 : return strcmp(a->d_name, b->d_name);
+ 1073 10959090 : return strcmp(a->d_name, b->d_name);
1074 : }
1075 :
1076 : /**
@@ -1146,15 +1146,15 @@
1084 : }
1085 : #else
1086 : #define DSTAT(file, dd, buf) dstat(file, buf)
- 1087 1004217 : struct stat* dstat(const char* file, struct stat* st)
+ 1087 1049496 : struct stat* dstat(const char* file, struct stat* st)
1088 : {
- 1089 1004217 : if (lstat(file, st) != 0) {
+ 1089 1049496 : if (lstat(file, st) != 0) {
1090 : /* LCOV_EXCL_START */
1091 : log_fatal("Error in stat file/directory '%s'. %s.\n", file, strerror(errno));
1092 : exit(EXIT_FAILURE);
1093 : /* LCOV_EXCL_STOP */
1094 : }
- 1095 1004217 : return st;
+ 1095 1049496 : return st;
1096 : }
1097 : #endif
1098 :
@@ -1162,19 +1162,19 @@
1100 : * Process a directory.
1101 : * Return != 0 if at least one file or link is processed.
1102 : */
- 1103 1614 : static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
+ 1103 1713 : static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
1104 : {
- 1105 1614 : struct snapraid_state* state = scan->state;
- 1106 1614 : struct snapraid_disk* disk = scan->disk;
- 1107 1614 : int processed = 0;
+ 1105 1713 : struct snapraid_state* state = scan->state;
+ 1106 1713 : struct snapraid_disk* disk = scan->disk;
+ 1107 1713 : int processed = 0;
1108 : DIR* d;
1109 : tommy_list list;
1110 : tommy_node* node;
1111 :
- 1112 1614 : tommy_list_init(&list);
+ 1112 1713 : tommy_list_init(&list);
1113 :
- 1114 1614 : d = opendir(dir);
- 1115 1614 : if (!d) {
+ 1114 1713 : d = opendir(dir);
+ 1115 1713 : if (!d) {
1116 : /* LCOV_EXCL_START */
1117 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
1118 : if (level == 0)
@@ -1195,29 +1195,29 @@
1133 : size_t name_len;
1134 :
1135 : /* clear errno to detect erroneous conditions */
- 1136 1041725 : errno = 0;
- 1137 1041725 : dd = readdir(d);
- 1138 1041725 : if (dd == 0 && errno != 0) {
+ 1136 1088749 : errno = 0;
+ 1137 1088749 : dd = readdir(d);
+ 1138 1088749 : if (dd == 0 && errno != 0) {
1139 : /* LCOV_EXCL_START */
1140 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
1141 : log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub);
1142 : exit(EXIT_FAILURE);
1143 : /* LCOV_EXCL_STOP */
1144 : }
- 1145 1041725 : if (dd == 0) {
- 1146 1614 : break; /* finished */
+ 1145 1088749 : if (dd == 0) {
+ 1146 1713 : break; /* finished */
1147 : }
1148 :
1149 : /* skip "." and ".." files */
- 1150 1040111 : name = dd->d_name;
- 1151 1040111 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
- 1152 6456 : continue;
+ 1150 1087036 : name = dd->d_name;
+ 1151 1087036 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+ 1152 6852 : continue;
1153 :
- 1154 1036883 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
- 1155 1036883 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
+ 1154 1083610 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 1155 1083610 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
1156 :
1157 : /* check for not supported file names */
- 1158 1036883 : if (name[0] == 0) {
+ 1158 1083610 : if (name[0] == 0) {
1159 : /* LCOV_EXCL_START */
1160 : log_fatal("Unsupported name '%s' in file '%s'.\n", name, path_next);
1161 : exit(EXIT_FAILURE);
@@ -1225,26 +1225,26 @@
1163 : }
1164 :
1165 : /* exclude hidden files even before calling lstat() */
- 1166 1036883 : if (filter_hidden(state->filter_hidden, dd) != 0) {
+ 1166 1083610 : if (filter_hidden(state->filter_hidden, dd) != 0) {
1167 0 : msg_verbose("Excluding hidden '%s'\n", path_next);
1168 0 : continue;
1169 : }
1170 :
1171 : /* exclude content files even before calling lstat() */
- 1172 1036883 : if (filter_content(&state->contentlist, path_next) != 0) {
+ 1172 1083610 : if (filter_content(&state->contentlist, path_next) != 0) {
1173 0 : msg_verbose("Excluding content '%s'\n", path_next);
1174 0 : continue;
1175 : }
1176 :
- 1177 1036883 : name_len = strlen(dd->d_name);
- 1178 1036883 : entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1);
+ 1177 1083610 : name_len = strlen(dd->d_name);
+ 1178 1083610 : entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1);
1179 :
1180 : /* copy the dir entry */
1181 : #if HAVE_STRUCT_DIRENT_D_INO
- 1182 1036883 : entry->d_ino = dd->d_ino;
+ 1182 1083610 : entry->d_ino = dd->d_ino;
1183 : #endif
1184 : #if HAVE_STRUCT_DIRENT_D_TYPE
- 1185 1036883 : entry->d_type = dd->d_type;
+ 1185 1083610 : entry->d_type = dd->d_type;
1186 : #endif
1187 : #if HAVE_STRUCT_DIRENT_D_STAT
1188 : /* convert dirent to lstat result */
@@ -1252,24 +1252,24 @@
1190 :
1191 : /* note that at this point the st_mode may be 0 */
1192 : #endif
- 1193 1036883 : memcpy(entry->d_name, dd->d_name, name_len + 1);
+ 1193 1083610 : memcpy(entry->d_name, dd->d_name, name_len + 1);
1194 :
1195 : /* insert in the list */
- 1196 1036883 : tommy_list_insert_tail(&list, &entry->node, entry);
- 1197 1040111 : }
+ 1196 1083610 : tommy_list_insert_tail(&list, &entry->node, entry);
+ 1197 1087036 : }
1198 :
- 1199 1614 : if (closedir(d) != 0) {
+ 1199 1713 : if (closedir(d) != 0) {
1200 : /* LCOV_EXCL_START */
1201 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
1202 : exit(EXIT_FAILURE);
1203 : /* LCOV_EXCL_STOP */
1204 : }
1205 :
- 1206 1614 : if (state->opt.force_order == SORT_ALPHA) {
+ 1206 1713 : if (state->opt.force_order == SORT_ALPHA) {
1207 : /* if requested sort alphabetically */
1208 : /* this is mainly done for testing to ensure to always */
1209 : /* process in the same way in different platforms */
- 1210 1578 : tommy_list_sort(&list, dd_name_compare);
+ 1210 1677 : tommy_list_sort(&list, dd_name_compare);
1211 : }
1212 : #if HAVE_STRUCT_DIRENT_D_INO
1213 36 : else if (!disk->has_volatile_inodes) {
@@ -1281,40 +1281,40 @@
1219 : #endif
1220 :
1221 : /* process the sorted dir entries */
- 1222 1614 : node = list;
- 1223 1040111 : while (node != 0) {
+ 1222 1713 : node = list;
+ 1223 1087036 : while (node != 0) {
1224 : char path_next[PATH_MAX];
1225 : char sub_next[PATH_MAX];
1226 : char out[PATH_MAX];
- 1227 1036883 : struct snapraid_filter* reason = 0;
- 1228 1036883 : struct dirent_sorted* dd = node->data;
- 1229 1036883 : const char* name = dd->d_name;
+ 1227 1083610 : struct snapraid_filter* reason = 0;
+ 1228 1083610 : struct dirent_sorted* dd = node->data;
+ 1229 1083610 : const char* name = dd->d_name;
1230 : struct stat* st;
1231 : int type;
1232 : #if !HAVE_STRUCT_DIRENT_D_STAT
1233 : struct stat st_buf;
1234 : #endif
1235 :
- 1236 1036883 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
- 1237 1036883 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
+ 1236 1083610 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 1237 1083610 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
1238 :
1239 : /* start with an unknown type */
- 1240 1036883 : type = -1;
- 1241 1036883 : st = 0;
+ 1240 1083610 : type = -1;
+ 1241 1083610 : st = 0;
1242 :
1243 : /* if dirent has the type, use it */
1244 : #if HAVE_STRUCT_DIRENT_D_TYPE
- 1245 1036883 : switch (dd->d_type) {
+ 1245 1083610 : switch (dd->d_type) {
1246 0 : case DT_UNKNOWN : break;
- 1247 1003082 : case DT_REG : type = 0; break;
- 1248 32666 : case DT_LNK : type = 1; break;
- 1249 1135 : case DT_DIR : type = 2; break;
+ 1247 1048310 : case DT_REG : type = 0; break;
+ 1248 34114 : case DT_LNK : type = 1; break;
+ 1249 1186 : case DT_DIR : type = 2; break;
1250 0 : default : type = 3; break;
1251 : }
1252 : #endif
1253 :
1254 : /* if type is still unknown */
- 1255 1036883 : if (type < 0) {
+ 1255 1083610 : if (type < 0) {
1256 : /* get the type from stat */
1257 0 : st = DSTAT(path_next, dd, &st_buf);
1258 :
@@ -1344,12 +1344,12 @@
1282 0 : type = 3;
1283 : }
1284 :
- 1285 1036883 : if (type == 0) { /* REG */
- 1286 1003082 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 1285 1083610 : if (type == 0) { /* REG */
+ 1286 1048310 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
1287 :
1288 : /* late stat, if not yet called */
- 1289 1003082 : if (!st)
- 1290 1003082 : st = DSTAT(path_next, dd, &st_buf);
+ 1289 1048310 : if (!st)
+ 1290 1048310 : st = DSTAT(path_next, dd, &st_buf);
1291 :
1292 : #if HAVE_LSTAT_SYNC
1293 : /* if the st_ino field is missing, takes care to fill it using the extended lstat() */
@@ -1364,539 +1364,545 @@
1302 : }
1303 : #endif
1304 :
- 1305 1003082 : scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);
- 1306 1003082 : processed = 1;
+ 1305 1048310 : scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);
+ 1306 1048310 : processed = 1;
1307 : } else {
1308 0 : msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
1309 : }
- 1310 33801 : } else if (type == 1) { /* LNK */
- 1311 32666 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 1310 35300 : } else if (type == 1) { /* LNK */
+ 1311 34114 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
1312 : char subnew[PATH_MAX];
1313 : int ret;
1314 :
- 1315 32666 : ret = readlink(path_next, subnew, sizeof(subnew));
- 1316 32666 : if (ret >= PATH_MAX) {
+ 1315 34114 : ret = readlink(path_next, subnew, sizeof(subnew));
+ 1316 34114 : if (ret >= PATH_MAX) {
1317 : /* LCOV_EXCL_START */
1318 : log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next);
1319 : exit(EXIT_FAILURE);
1320 : /* LCOV_EXCL_STOP */
1321 : }
- 1322 32666 : if (ret < 0) {
+ 1322 34114 : if (ret < 0) {
1323 : /* LCOV_EXCL_START */
1324 : log_fatal("Error in readlink file '%s'. %s.\n", path_next, strerror(errno));
1325 : exit(EXIT_FAILURE);
1326 : /* LCOV_EXCL_STOP */
1327 : }
- 1328 :
- 1329 : /* readlink doesn't put the final 0 */
- 1330 32666 : subnew[ret] = 0;
- 1331 :
- 1332 : /* process as a symbolic link */
- 1333 32666 : scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK);
- 1334 32666 : processed = 1;
- 1335 : } else {
- 1336 0 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
- 1337 : }
- 1338 1135 : } else if (type == 2) { /* DIR */
- 1339 1135 : if (filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
- 1340 : #ifndef _WIN32
- 1341 : /* late stat, if not yet called */
- 1342 1135 : if (!st)
- 1343 1135 : st = DSTAT(path_next, dd, &st_buf);
- 1344 :
- 1345 : /* in Unix don't follow mount points in different devices */
- 1346 : /* in Windows we are already skipping them reporting them as special files */
- 1347 1135 : if ((uint64_t)st->st_dev != disk->device) {
- 1348 0 : log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next);
- 1349 : } else
- 1350 : #endif
- 1351 : {
- 1352 : char sub_dir[PATH_MAX];
- 1353 :
- 1354 : /* recurse */
- 1355 1135 : pathslash(path_next, sizeof(path_next));
- 1356 1135 : pathcpy(sub_dir, sizeof(sub_dir), sub_next);
- 1357 1135 : pathslash(sub_dir, sizeof(sub_dir));
- 1358 1135 : if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) {
- 1359 : /* scan the directory as empty dir */
- 1360 227 : scan_emptydir(scan, sub_next);
- 1361 : }
- 1362 : /* or we processed something internally, or we have added the empty dir */
- 1363 1135 : processed = 1;
- 1364 : }
- 1365 : } else {
- 1366 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
- 1367 : }
- 1368 : } else {
- 1369 0 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
- 1370 : /* late stat, if not yet called */
- 1371 0 : if (!st)
- 1372 0 : st = DSTAT(path_next, dd, &st_buf);
- 1373 :
- 1374 0 : log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
- 1375 : } else {
- 1376 0 : msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
- 1377 : }
- 1378 : }
- 1379 :
- 1380 : /* next entry */
- 1381 1036883 : node = node->next;
- 1382 :
- 1383 : /* free the present one */
- 1384 1036883 : free(dd);
- 1385 : }
- 1386 :
- 1387 1614 : return processed;
- 1388 : }
- 1389 :
- 1390 80 : static int state_diffscan(struct snapraid_state* state, int is_diff)
- 1391 : {
- 1392 : tommy_node* i;
- 1393 : tommy_node* j;
- 1394 : tommy_list scanlist;
- 1395 : int done;
- 1396 : fptr* msg;
- 1397 : struct snapraid_scan total;
- 1398 : int no_difference;
- 1399 :
- 1400 80 : tommy_list_init(&scanlist);
+ 1328 34114 : if (ret == 0)
+ 1329 0 : log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next);
+ 1330 :
+ 1331 : /* readlink doesn't put the final 0 */
+ 1332 34114 : subnew[ret] = 0;
+ 1333 :
+ 1334 : /* process as a symbolic link */
+ 1335 34114 : scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK);
+ 1336 34114 : processed = 1;
+ 1337 : } else {
+ 1338 0 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
+ 1339 : }
+ 1340 1186 : } else if (type == 2) { /* DIR */
+ 1341 1186 : if (filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 1342 : #ifndef _WIN32
+ 1343 : /* late stat, if not yet called */
+ 1344 1186 : if (!st)
+ 1345 1186 : st = DSTAT(path_next, dd, &st_buf);
+ 1346 :
+ 1347 : /* in Unix don't follow mount points in different devices */
+ 1348 : /* in Windows we are already skipping them reporting them as special files */
+ 1349 1186 : if ((uint64_t)st->st_dev != disk->device) {
+ 1350 0 : log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next);
+ 1351 : } else
+ 1352 : #endif
+ 1353 : {
+ 1354 : char sub_dir[PATH_MAX];
+ 1355 :
+ 1356 : /* recurse */
+ 1357 1186 : pathslash(path_next, sizeof(path_next));
+ 1358 1186 : pathcpy(sub_dir, sizeof(sub_dir), sub_next);
+ 1359 1186 : pathslash(sub_dir, sizeof(sub_dir));
+ 1360 1186 : if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) {
+ 1361 : /* scan the directory as empty dir */
+ 1362 239 : scan_emptydir(scan, sub_next);
+ 1363 : }
+ 1364 : /* or we processed something internally, or we have added the empty dir */
+ 1365 1186 : processed = 1;
+ 1366 : }
+ 1367 : } else {
+ 1368 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
+ 1369 : }
+ 1370 : } else {
+ 1371 0 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 1372 : /* late stat, if not yet called */
+ 1373 0 : if (!st)
+ 1374 0 : st = DSTAT(path_next, dd, &st_buf);
+ 1375 :
+ 1376 0 : log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
+ 1377 : } else {
+ 1378 0 : msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
+ 1379 : }
+ 1380 : }
+ 1381 :
+ 1382 : /* next entry */
+ 1383 1083610 : node = node->next;
+ 1384 :
+ 1385 : /* free the present one */
+ 1386 1083610 : free(dd);
+ 1387 : }
+ 1388 :
+ 1389 1713 : return processed;
+ 1390 : }
+ 1391 :
+ 1392 88 : static int state_diffscan(struct snapraid_state* state, int is_diff)
+ 1393 : {
+ 1394 : tommy_node* i;
+ 1395 : tommy_node* j;
+ 1396 : tommy_list scanlist;
+ 1397 : int done;
+ 1398 : fptr* msg;
+ 1399 : struct snapraid_scan total;
+ 1400 : int no_difference;
1401 :
- 1402 80 : if (is_diff)
- 1403 7 : msg_progress("Comparing...\n");
- 1404 :
- 1405 : /* first scan all the directory and find new and deleted files */
- 1406 559 : for (i = state->disklist; i != 0; i = i->next) {
- 1407 479 : struct snapraid_disk* disk = i->data;
- 1408 : struct snapraid_scan* scan;
- 1409 : tommy_node* node;
- 1410 : int ret;
- 1411 : int has_persistent_inode;
- 1412 :
- 1413 479 : scan = malloc_nofail(sizeof(struct snapraid_scan));
- 1414 479 : scan->state = state;
- 1415 479 : scan->disk = disk;
- 1416 479 : scan->count_equal = 0;
- 1417 479 : scan->count_move = 0;
- 1418 479 : scan->count_copy = 0;
- 1419 479 : scan->count_restore = 0;
- 1420 479 : scan->count_change = 0;
- 1421 479 : scan->count_remove = 0;
- 1422 479 : scan->count_insert = 0;
- 1423 479 : tommy_list_init(&scan->file_insert_list);
- 1424 479 : tommy_list_init(&scan->link_insert_list);
- 1425 479 : tommy_list_init(&scan->dir_insert_list);
- 1426 :
- 1427 479 : tommy_list_insert_tail(&scanlist, &scan->node, scan);
+ 1402 88 : tommy_list_init(&scanlist);
+ 1403 :
+ 1404 88 : if (is_diff)
+ 1405 7 : msg_progress("Comparing...\n");
+ 1406 :
+ 1407 : /* first scan all the directory and find new and deleted files */
+ 1408 615 : for (i = state->disklist; i != 0; i = i->next) {
+ 1409 527 : struct snapraid_disk* disk = i->data;
+ 1410 : struct snapraid_scan* scan;
+ 1411 : tommy_node* node;
+ 1412 : int ret;
+ 1413 : int has_persistent_inode;
+ 1414 :
+ 1415 527 : scan = malloc_nofail(sizeof(struct snapraid_scan));
+ 1416 527 : scan->state = state;
+ 1417 527 : scan->disk = disk;
+ 1418 527 : scan->count_equal = 0;
+ 1419 527 : scan->count_move = 0;
+ 1420 527 : scan->count_copy = 0;
+ 1421 527 : scan->count_restore = 0;
+ 1422 527 : scan->count_change = 0;
+ 1423 527 : scan->count_remove = 0;
+ 1424 527 : scan->count_insert = 0;
+ 1425 527 : tommy_list_init(&scan->file_insert_list);
+ 1426 527 : tommy_list_init(&scan->link_insert_list);
+ 1427 527 : tommy_list_init(&scan->dir_insert_list);
1428 :
- 1429 479 : if (!is_diff)
- 1430 437 : msg_progress("Scanning disk %s...\n", disk->name);
- 1431 :
- 1432 : /* check if the disk supports persistent inodes */
- 1433 479 : ret = fsinfo(disk->dir, &has_persistent_inode, 0, 0);
- 1434 479 : if (ret < 0) {
- 1435 : /* LCOV_EXCL_START */
- 1436 : log_fatal("Error accessing disk '%s' to get filesystem info. %s.\n", disk->dir, strerror(errno));
- 1437 : exit(EXIT_FAILURE);
- 1438 : /* LCOV_EXCL_STOP */
- 1439 : }
- 1440 479 : if (!has_persistent_inode) {
- 1441 0 : disk->has_volatile_inodes = 1;
- 1442 : }
- 1443 :
- 1444 : /* if inodes or UUID are not persistent/changed/unsupported */
- 1445 479 : if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
- 1446 : /* remove all the inodes from the inode collection */
- 1447 : /* if they are not persistent, all of them could be changed now */
- 1448 : /* and we don't want to find false matching ones */
- 1449 : /* see scan_file() for more details */
- 1450 75 : node = disk->filelist;
- 1451 150 : while (node) {
- 1452 0 : struct snapraid_file* file = node->data;
- 1453 :
- 1454 0 : node = node->next;
+ 1429 527 : tommy_list_insert_tail(&scanlist, &scan->node, scan);
+ 1430 :
+ 1431 527 : if (!is_diff)
+ 1432 485 : msg_progress("Scanning disk %s...\n", disk->name);
+ 1433 :
+ 1434 : /* check if the disk supports persistent inodes */
+ 1435 527 : ret = fsinfo(disk->dir, &has_persistent_inode, 0, 0);
+ 1436 527 : if (ret < 0) {
+ 1437 : /* LCOV_EXCL_START */
+ 1438 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
+ 1439 : exit(EXIT_FAILURE);
+ 1440 : /* LCOV_EXCL_STOP */
+ 1441 : }
+ 1442 527 : if (!has_persistent_inode) {
+ 1443 0 : disk->has_volatile_inodes = 1;
+ 1444 : }
+ 1445 :
+ 1446 : /* if inodes or UUID are not persistent/changed/unsupported */
+ 1447 527 : if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
+ 1448 : /* remove all the inodes from the inode collection */
+ 1449 : /* if they are not persistent, all of them could be changed now */
+ 1450 : /* and we don't want to find false matching ones */
+ 1451 : /* see scan_file() for more details */
+ 1452 90 : node = disk->filelist;
+ 1453 190 : while (node) {
+ 1454 10 : struct snapraid_file* file = node->data;
1455 :
- 1456 : /* remove from the inode set */
- 1457 0 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
- 1458 :
- 1459 : /* clear the inode */
- 1460 0 : file->inode = 0;
- 1461 :
- 1462 : /* mark as missing inode */
- 1463 0 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
- 1464 : }
- 1465 : }
- 1466 :
- 1467 479 : scan_dir(scan, 0, is_diff, disk->dir, "");
- 1468 : }
- 1469 :
- 1470 : /* we split the search in two phases because to detect files */
- 1471 : /* moved from one disk to another we have to start deletion */
- 1472 : /* only when all disks have all the new files found */
- 1473 :
- 1474 : /* now process all the new and deleted files */
- 1475 559 : for (i = scanlist; i != 0; i = i->next) {
- 1476 479 : struct snapraid_scan* scan = i->data;
- 1477 479 : struct snapraid_disk* disk = scan->disk;
- 1478 : tommy_node* node;
- 1479 : unsigned phy_count;
- 1480 : unsigned phy_dup;
- 1481 : uint64_t phy_last;
- 1482 : struct snapraid_file* phy_file_last;
- 1483 :
- 1484 : /* check for removed files */
- 1485 479 : node = disk->filelist;
- 1486 932532 : while (node) {
- 1487 931574 : struct snapraid_file* file = node->data;
- 1488 :
- 1489 : /* next node */
- 1490 931574 : node = node->next;
- 1491 :
- 1492 : /* remove if not present */
- 1493 931574 : if (!file_flag_has(file, FILE_IS_PRESENT)) {
- 1494 29638 : ++scan->count_remove;
- 1495 :
- 1496 29638 : log_tag("scan:remove:%s:%s\n", disk->name, esc(file->sub));
- 1497 29638 : if (is_diff) {
- 1498 97 : printf("remove %s%s\n", disk->dir, file->sub);
- 1499 : }
- 1500 :
- 1501 29638 : scan_file_remove(scan, file);
- 1502 : }
- 1503 : }
- 1504 :
- 1505 : /* check for removed links */
- 1506 479 : node = disk->linklist;
- 1507 32294 : while (node) {
- 1508 31336 : struct snapraid_link* slink = node->data;
- 1509 :
- 1510 : /* next node */
- 1511 31336 : node = node->next;
- 1512 :
- 1513 : /* remove if not present */
- 1514 31336 : if (!link_flag_has(slink, FILE_IS_PRESENT)) {
- 1515 956 : ++scan->count_remove;
- 1516 :
- 1517 956 : log_tag("scan:remove:%s:%s\n", disk->name, esc(slink->sub));
- 1518 956 : if (is_diff) {
- 1519 10 : printf("remove %s%s\n", disk->dir, slink->sub);
- 1520 : }
- 1521 :
- 1522 956 : scan_link_remove(scan, slink);
- 1523 : }
- 1524 : }
- 1525 :
- 1526 : /* check for removed dirs */
- 1527 479 : node = disk->dirlist;
- 1528 1177 : while (node) {
- 1529 219 : struct snapraid_dir* dir = node->data;
- 1530 :
- 1531 : /* next node */
- 1532 219 : node = node->next;
- 1533 :
- 1534 : /* remove if not present */
- 1535 219 : if (!dir_flag_has(dir, FILE_IS_PRESENT)) {
- 1536 2 : scan_emptydir_remove(scan, dir);
- 1537 : }
- 1538 : }
- 1539 :
- 1540 : /* sort the files before inserting them */
- 1541 : /* we use a stable sort to ensure that if the reported physical offset/inode */
- 1542 : /* are always 0, we keep at least the directory order */
- 1543 479 : switch (state->opt.force_order) {
- 1544 : case SORT_PHYSICAL :
- 1545 12 : tommy_list_sort(&scan->file_insert_list, file_physical_compare);
- 1546 12 : break;
- 1547 : case SORT_INODE :
- 1548 0 : tommy_list_sort(&scan->file_insert_list, file_inode_compare);
- 1549 0 : break;
- 1550 : case SORT_ALPHA :
- 1551 467 : tommy_list_sort(&scan->file_insert_list, file_path_compare);
- 1552 467 : break;
- 1553 : case SORT_DIR :
- 1554 : /* already in order */
- 1555 0 : break;
- 1556 : }
- 1557 :
- 1558 : /* insert all the new files, we insert them only after the deletion */
- 1559 : /* to reuse the just freed space */
- 1560 : /* also check if the physical offset reported are fakes or not */
- 1561 479 : node = scan->file_insert_list;
- 1562 479 : phy_count = 0;
- 1563 479 : phy_dup = 0;
- 1564 479 : phy_last = FILEPHY_UNREAD_OFFSET;
- 1565 479 : phy_file_last = 0;
- 1566 101933 : while (node) {
- 1567 100975 : struct snapraid_file* file = node->data;
- 1568 :
- 1569 : /* if the file is not empty, count duplicate physical offsets */
- 1570 100975 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {
- 1571 11418 : if (phy_file_last != 0 && file->physical == phy_last
- 1572 : /* files without offset are expected to have duplicates */
- 1573 0 : && phy_last != FILEPHY_WITHOUT_OFFSET
- 1574 : ) {
- 1575 : /* if verbose, print the list of duplicates real offsets */
- 1576 : /* other cases are for offsets not supported, so we don't need to report them file by file */
- 1577 0 : if (phy_last >= FILEPHY_REAL_OFFSET) {
- 1578 0 : log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last);
- 1579 : }
- 1580 0 : ++phy_dup;
- 1581 : }
- 1582 11418 : phy_file_last = file;
- 1583 11418 : phy_last = file->physical;
- 1584 11418 : ++phy_count;
- 1585 : }
- 1586 :
- 1587 : /* next node */
- 1588 100975 : node = node->next;
- 1589 :
- 1590 : /* insert in the parity */
- 1591 100975 : scan_file_allocate(scan, file);
- 1592 : }
- 1593 :
- 1594 : /* mark the disk without reliable physical offset if it has duplicates */
- 1595 : /* here it should never happen because we already sorted out hardlinks */
- 1596 479 : if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) {
- 1597 0 : disk->has_unreliable_physical = 1;
- 1598 : }
- 1599 :
- 1600 : /* insert all the new links */
- 1601 479 : node = scan->link_insert_list;
- 1602 3415 : while (node) {
- 1603 2457 : struct snapraid_link* slink = node->data;
- 1604 :
- 1605 : /* next node */
- 1606 2457 : node = node->next;
- 1607 :
- 1608 : /* insert it */
- 1609 2457 : scan_link_insert(scan, slink);
- 1610 : }
- 1611 :
- 1612 : /* insert all the new dirs */
- 1613 479 : node = scan->dir_insert_list;
- 1614 968 : while (node) {
- 1615 10 : struct snapraid_dir* dir = node->data;
- 1616 :
- 1617 : /* next node */
- 1618 10 : node = node->next;
- 1619 :
- 1620 : /* insert it */
- 1621 10 : scan_emptydir_insert(scan, dir);
- 1622 : }
- 1623 : }
- 1624 :
- 1625 : /* check for disks where all the previously existing files where removed */
- 1626 80 : if (!state->opt.force_empty) {
- 1627 75 : int all_missing = 0;
- 1628 75 : int all_rewritten = 0;
- 1629 75 : done = 0;
- 1630 524 : for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) {
- 1631 449 : struct snapraid_disk* disk = i->data;
- 1632 449 : struct snapraid_scan* scan = j->data;
- 1633 :
- 1634 449 : if (scan->count_equal == 0
- 1635 60 : && scan->count_move == 0
- 1636 60 : && scan->count_restore == 0
- 1637 60 : && (scan->count_remove != 0 || scan->count_change != 0)
- 1638 : ) {
- 1639 1 : if (!done) {
- 1640 1 : done = 1;
- 1641 1 : log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir);
- 1642 : } else {
- 1643 0 : log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir);
- 1644 : }
- 1645 :
- 1646 : /* detect the special condition of all files missing */
- 1647 1 : if (scan->count_change == 0)
- 1648 1 : all_missing = 1;
- 1649 :
- 1650 : /* detect the special condition of all files rewritten */
- 1651 1 : if (scan->count_remove == 0)
- 1652 0 : all_rewritten = 1;
- 1653 : }
- 1654 : }
- 1655 75 : if (done) {
- 1656 1 : log_fatal("\nare now missing or rewritten!\n");
- 1657 1 : if (all_rewritten) {
- 1658 0 : log_fatal("This could happen when restoring a disk with a backup\n");
- 1659 0 : log_fatal("program that is not setting correctly the timestamps.\n");
- 1660 : }
- 1661 1 : if (all_missing) {
- 1662 1 : log_fatal("This could happen when some disks are not mounted\n");
- 1663 1 : log_fatal("in the expected directory.\n");
- 1664 : }
- 1665 1 : if (!is_diff) {
- 1666 1 : log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.", state->command, state->command);
- 1667 1 : exit(EXIT_FAILURE);
- 1668 : }
- 1669 : }
- 1670 : }
- 1671 :
- 1672 : /* check for disks without the physical offset support */
- 1673 79 : if (state->opt.force_order == SORT_PHYSICAL) {
- 1674 2 : done = 0;
- 1675 14 : for (i = state->disklist; i != 0; i = i->next) {
- 1676 12 : struct snapraid_disk* disk = i->data;
- 1677 :
- 1678 12 : if (disk->has_unreliable_physical) {
- 1679 0 : if (!done) {
- 1680 0 : done = 1;
- 1681 0 : log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name);
- 1682 : } else {
- 1683 0 : log_fatal(", '%s'", disk->name);
- 1684 : }
- 1685 : }
- 1686 : }
- 1687 2 : if (done) {
- 1688 0 : log_fatal(". Files order won't be optimal.\n");
- 1689 : }
- 1690 : }
- 1691 :
- 1692 : /* check for disks without persistent inodes */
- 1693 79 : done = 0;
- 1694 552 : for (i = state->disklist; i != 0; i = i->next) {
- 1695 473 : struct snapraid_disk* disk = i->data;
- 1696 :
- 1697 473 : if (disk->has_volatile_inodes) {
- 1698 0 : if (!done) {
- 1699 0 : done = 1;
- 1700 0 : log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name);
- 1701 : } else {
- 1702 0 : log_fatal(", '%s'", disk->name);
- 1703 : }
- 1704 : }
- 1705 : }
- 1706 79 : if (done) {
- 1707 0 : log_fatal(". Move operations won't be optimal.\n");
- 1708 : }
- 1709 :
- 1710 : /* check for disks with changed UUID */
- 1711 79 : done = 0;
- 1712 552 : for (i = state->disklist; i != 0; i = i->next) {
- 1713 473 : struct snapraid_disk* disk = i->data;
- 1714 :
- 1715 : /* don't print the message if the UUID changed because before */
- 1716 : /* it was no set. */
- 1717 : /* this is the normal condition for an empty disk because it */
- 1718 : /* isn't stored */
- 1719 473 : if (disk->has_different_uuid && !disk->had_empty_uuid) {
- 1720 0 : if (!done) {
- 1721 0 : done = 1;
- 1722 0 : log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name);
- 1723 : } else {
- 1724 0 : log_fatal(", '%s'", disk->name);
- 1725 : }
- 1726 : }
- 1727 : }
- 1728 79 : if (done) {
- 1729 0 : log_fatal(". Move operations won't be optimal.\n");
- 1730 : }
- 1731 :
- 1732 : /* check for disks with unsupported UUID */
- 1733 79 : done = 0;
- 1734 552 : for (i = state->disklist; i != 0; i = i->next) {
- 1735 473 : struct snapraid_disk* disk = i->data;
- 1736 :
- 1737 473 : if (disk->has_unsupported_uuid) {
- 1738 0 : if (!done) {
- 1739 0 : done = 1;
- 1740 0 : log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name);
- 1741 : } else {
- 1742 0 : log_fatal(", '%s'", disk->name);
- 1743 : }
- 1744 : }
- 1745 : }
- 1746 79 : if (done) {
- 1747 0 : log_fatal(". Move operations won't be optimal.\n");
- 1748 : }
- 1749 :
- 1750 79 : total.count_equal = 0;
- 1751 79 : total.count_move = 0;
- 1752 79 : total.count_copy = 0;
- 1753 79 : total.count_restore = 0;
- 1754 79 : total.count_change = 0;
- 1755 79 : total.count_remove = 0;
- 1756 79 : total.count_insert = 0;
- 1757 :
- 1758 552 : for (i = scanlist; i != 0; i = i->next) {
- 1759 473 : struct snapraid_scan* scan = i->data;
- 1760 473 : total.count_equal += scan->count_equal;
- 1761 473 : total.count_move += scan->count_move;
- 1762 473 : total.count_copy += scan->count_copy;
- 1763 473 : total.count_restore += scan->count_restore;
- 1764 473 : total.count_change += scan->count_change;
- 1765 473 : total.count_remove += scan->count_remove;
- 1766 473 : total.count_insert += scan->count_insert;
- 1767 : }
- 1768 :
- 1769 79 : if (is_diff) {
- 1770 7 : msg_status("\n");
- 1771 7 : msg = msg_status;
- 1772 : } else {
- 1773 72 : msg = msg_verbose;
- 1774 : }
- 1775 :
- 1776 79 : msg("%8u equal\n", total.count_equal);
- 1777 79 : msg("%8u moved\n", total.count_move);
- 1778 79 : msg("%8u copied\n", total.count_copy);
- 1779 79 : msg("%8u restored\n", total.count_restore);
- 1780 79 : msg("%8u updated\n", total.count_change);
- 1781 79 : msg("%8u removed\n", total.count_remove);
- 1782 79 : msg("%8u added\n", total.count_insert);
- 1783 :
- 1784 79 : log_tag("summary:equal:%u\n", total.count_equal);
- 1785 79 : log_tag("summary:moved:%u\n", total.count_move);
- 1786 79 : log_tag("summary:copied:%u\n", total.count_copy);
- 1787 79 : log_tag("summary:restored:%u\n", total.count_restore);
- 1788 79 : log_tag("summary:updated:%u\n", total.count_change);
- 1789 79 : log_tag("summary:removed:%u\n", total.count_remove);
- 1790 79 : log_tag("summary:added:%u\n", total.count_insert);
- 1791 :
- 1792 236 : no_difference = !total.count_move && !total.count_copy && !total.count_restore
- 1793 129 : && !total.count_change && !total.count_remove && !total.count_insert;
- 1794 :
- 1795 79 : if (is_diff) {
- 1796 7 : if (no_difference) {
- 1797 1 : msg_status("No differences\n");
- 1798 : } else {
- 1799 6 : msg_status("There are differences!\n");
- 1800 : }
- 1801 : }
- 1802 :
- 1803 79 : if (no_difference) {
- 1804 9 : log_tag("summary:exit:equal\n");
- 1805 : } else {
- 1806 70 : log_tag("summary:exit:diff\n");
+ 1456 10 : node = node->next;
+ 1457 :
+ 1458 : /* remove from the inode set */
+ 1459 10 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 1460 :
+ 1461 : /* clear the inode */
+ 1462 10 : file->inode = 0;
+ 1463 :
+ 1464 : /* mark as missing inode */
+ 1465 10 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
+ 1466 : }
+ 1467 : }
+ 1468 :
+ 1469 527 : scan_dir(scan, 0, is_diff, disk->dir, "");
+ 1470 : }
+ 1471 :
+ 1472 : /* we split the search in two phases because to detect files */
+ 1473 : /* moved from one disk to another we have to start deletion */
+ 1474 : /* only when all disks have all the new files found */
+ 1475 :
+ 1476 : /* now process all the new and deleted files */
+ 1477 615 : for (i = scanlist; i != 0; i = i->next) {
+ 1478 527 : struct snapraid_scan* scan = i->data;
+ 1479 527 : struct snapraid_disk* disk = scan->disk;
+ 1480 : tommy_node* node;
+ 1481 : unsigned phy_count;
+ 1482 : unsigned phy_dup;
+ 1483 : uint64_t phy_last;
+ 1484 : struct snapraid_file* phy_file_last;
+ 1485 :
+ 1486 : /* check for removed files */
+ 1487 527 : node = disk->filelist;
+ 1488 974990 : while (node) {
+ 1489 973936 : struct snapraid_file* file = node->data;
+ 1490 :
+ 1491 : /* next node */
+ 1492 973936 : node = node->next;
+ 1493 :
+ 1494 : /* remove if not present */
+ 1495 973936 : if (!file_flag_has(file, FILE_IS_PRESENT)) {
+ 1496 29646 : ++scan->count_remove;
+ 1497 :
+ 1498 29646 : log_tag("scan:remove:%s:%s\n", disk->name, esc(file->sub));
+ 1499 29646 : if (is_diff) {
+ 1500 97 : printf("remove %s%s\n", disk->dir, file->sub);
+ 1501 : }
+ 1502 :
+ 1503 29646 : scan_file_remove(scan, file);
+ 1504 : }
+ 1505 : }
+ 1506 :
+ 1507 : /* check for removed links */
+ 1508 527 : node = disk->linklist;
+ 1509 33847 : while (node) {
+ 1510 32793 : struct snapraid_link* slink = node->data;
+ 1511 :
+ 1512 : /* next node */
+ 1513 32793 : node = node->next;
+ 1514 :
+ 1515 : /* remove if not present */
+ 1516 32793 : if (!link_flag_has(slink, FILE_IS_PRESENT)) {
+ 1517 956 : ++scan->count_remove;
+ 1518 :
+ 1519 956 : log_tag("scan:remove:%s:%s\n", disk->name, esc(slink->sub));
+ 1520 956 : if (is_diff) {
+ 1521 10 : printf("remove %s%s\n", disk->dir, slink->sub);
+ 1522 : }
+ 1523 :
+ 1524 956 : scan_link_remove(scan, slink);
+ 1525 : }
+ 1526 : }
+ 1527 :
+ 1528 : /* check for removed dirs */
+ 1529 527 : node = disk->dirlist;
+ 1530 1285 : while (node) {
+ 1531 231 : struct snapraid_dir* dir = node->data;
+ 1532 :
+ 1533 : /* next node */
+ 1534 231 : node = node->next;
+ 1535 :
+ 1536 : /* remove if not present */
+ 1537 231 : if (!dir_flag_has(dir, FILE_IS_PRESENT)) {
+ 1538 2 : scan_emptydir_remove(scan, dir);
+ 1539 : }
+ 1540 : }
+ 1541 :
+ 1542 : /* sort the files before inserting them */
+ 1543 : /* we use a stable sort to ensure that if the reported physical offset/inode */
+ 1544 : /* are always 0, we keep at least the directory order */
+ 1545 527 : switch (state->opt.force_order) {
+ 1546 : case SORT_PHYSICAL :
+ 1547 12 : tommy_list_sort(&scan->file_insert_list, file_physical_compare);
+ 1548 12 : break;
+ 1549 : case SORT_INODE :
+ 1550 0 : tommy_list_sort(&scan->file_insert_list, file_inode_compare);
+ 1551 0 : break;
+ 1552 : case SORT_ALPHA :
+ 1553 515 : tommy_list_sort(&scan->file_insert_list, file_path_compare);
+ 1554 515 : break;
+ 1555 : case SORT_DIR :
+ 1556 : /* already in order */
+ 1557 0 : break;
+ 1558 : }
+ 1559 :
+ 1560 : /* insert all the new files, we insert them only after the deletion */
+ 1561 : /* to reuse the just freed space */
+ 1562 : /* also check if the physical offset reported are fakes or not */
+ 1563 527 : node = scan->file_insert_list;
+ 1564 527 : phy_count = 0;
+ 1565 527 : phy_dup = 0;
+ 1566 527 : phy_last = FILEPHY_UNREAD_OFFSET;
+ 1567 527 : phy_file_last = 0;
+ 1568 104894 : while (node) {
+ 1569 103840 : struct snapraid_file* file = node->data;
+ 1570 :
+ 1571 : /* if the file is not empty, count duplicate physical offsets */
+ 1572 103840 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {
+ 1573 11418 : if (phy_file_last != 0 && file->physical == phy_last
+ 1574 : /* files without offset are expected to have duplicates */
+ 1575 0 : && phy_last != FILEPHY_WITHOUT_OFFSET
+ 1576 : ) {
+ 1577 : /* if verbose, print the list of duplicates real offsets */
+ 1578 : /* other cases are for offsets not supported, so we don't need to report them file by file */
+ 1579 0 : if (phy_last >= FILEPHY_REAL_OFFSET) {
+ 1580 0 : log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last);
+ 1581 : }
+ 1582 0 : ++phy_dup;
+ 1583 : }
+ 1584 11418 : phy_file_last = file;
+ 1585 11418 : phy_last = file->physical;
+ 1586 11418 : ++phy_count;
+ 1587 : }
+ 1588 :
+ 1589 : /* next node */
+ 1590 103840 : node = node->next;
+ 1591 :
+ 1592 : /* insert in the parity */
+ 1593 103840 : scan_file_allocate(scan, file);
+ 1594 : }
+ 1595 :
+ 1596 : /* mark the disk without reliable physical offset if it has duplicates */
+ 1597 : /* here it should never happen because we already sorted out hardlinks */
+ 1598 527 : if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) {
+ 1599 0 : disk->has_unreliable_physical = 1;
+ 1600 : }
+ 1601 :
+ 1602 : /* insert all the new links */
+ 1603 527 : node = scan->link_insert_list;
+ 1604 3511 : while (node) {
+ 1605 2457 : struct snapraid_link* slink = node->data;
+ 1606 :
+ 1607 : /* next node */
+ 1608 2457 : node = node->next;
+ 1609 :
+ 1610 : /* insert it */
+ 1611 2457 : scan_link_insert(scan, slink);
+ 1612 : }
+ 1613 :
+ 1614 : /* insert all the new dirs */
+ 1615 527 : node = scan->dir_insert_list;
+ 1616 1064 : while (node) {
+ 1617 10 : struct snapraid_dir* dir = node->data;
+ 1618 :
+ 1619 : /* next node */
+ 1620 10 : node = node->next;
+ 1621 :
+ 1622 : /* insert it */
+ 1623 10 : scan_emptydir_insert(scan, dir);
+ 1624 : }
+ 1625 : }
+ 1626 :
+ 1627 : /* check for disks where all the previously existing files where removed */
+ 1628 88 : if (!state->opt.force_empty) {
+ 1629 82 : int all_missing = 0;
+ 1630 82 : int all_rewritten = 0;
+ 1631 82 : done = 0;
+ 1632 573 : for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) {
+ 1633 491 : struct snapraid_disk* disk = i->data;
+ 1634 491 : struct snapraid_scan* scan = j->data;
+ 1635 :
+ 1636 491 : if (scan->count_equal == 0
+ 1637 71 : && scan->count_move == 0
+ 1638 71 : && scan->count_restore == 0
+ 1639 71 : && (scan->count_remove != 0 || scan->count_change != 0)
+ 1640 : ) {
+ 1641 1 : if (!done) {
+ 1642 1 : done = 1;
+ 1643 1 : log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir);
+ 1644 : } else {
+ 1645 0 : log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir);
+ 1646 : }
+ 1647 :
+ 1648 : /* detect the special condition of all files missing */
+ 1649 1 : if (scan->count_change == 0)
+ 1650 1 : all_missing = 1;
+ 1651 :
+ 1652 : /* detect the special condition of all files rewritten */
+ 1653 1 : if (scan->count_remove == 0)
+ 1654 0 : all_rewritten = 1;
+ 1655 : }
+ 1656 : }
+ 1657 82 : if (done) {
+ 1658 1 : log_fatal("\nare now missing or rewritten!\n");
+ 1659 1 : if (all_rewritten) {
+ 1660 0 : log_fatal("This could happen when restoring a disk with a backup\n");
+ 1661 0 : log_fatal("program that is not setting correctly the timestamps.\n");
+ 1662 : }
+ 1663 1 : if (all_missing) {
+ 1664 1 : log_fatal("This could happen when some disks are not mounted\n");
+ 1665 1 : log_fatal("in the expected directory.\n");
+ 1666 : }
+ 1667 1 : if (!is_diff) {
+ 1668 1 : log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.\n", state->command, state->command);
+ 1669 1 : exit(EXIT_FAILURE);
+ 1670 : }
+ 1671 : }
+ 1672 : }
+ 1673 :
+ 1674 : /* check for disks without the physical offset support */
+ 1675 87 : if (state->opt.force_order == SORT_PHYSICAL) {
+ 1676 2 : done = 0;
+ 1677 14 : for (i = state->disklist; i != 0; i = i->next) {
+ 1678 12 : struct snapraid_disk* disk = i->data;
+ 1679 :
+ 1680 12 : if (disk->has_unreliable_physical) {
+ 1681 0 : if (!done) {
+ 1682 0 : done = 1;
+ 1683 0 : log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name);
+ 1684 : } else {
+ 1685 0 : log_fatal(", '%s'", disk->name);
+ 1686 : }
+ 1687 : }
+ 1688 : }
+ 1689 2 : if (done) {
+ 1690 0 : log_fatal(". Files order won't be optimal.\n");
+ 1691 : }
+ 1692 : }
+ 1693 :
+ 1694 : /* check for disks without persistent inodes */
+ 1695 87 : done = 0;
+ 1696 608 : for (i = state->disklist; i != 0; i = i->next) {
+ 1697 521 : struct snapraid_disk* disk = i->data;
+ 1698 :
+ 1699 521 : if (disk->has_volatile_inodes) {
+ 1700 0 : if (!done) {
+ 1701 0 : done = 1;
+ 1702 0 : log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name);
+ 1703 : } else {
+ 1704 0 : log_fatal(", '%s'", disk->name);
+ 1705 : }
+ 1706 : }
+ 1707 : }
+ 1708 87 : if (done) {
+ 1709 0 : log_fatal(". Move operations won't be optimal.\n");
+ 1710 : }
+ 1711 :
+ 1712 : /* check for disks with changed UUID */
+ 1713 87 : done = 0;
+ 1714 608 : for (i = state->disklist; i != 0; i = i->next) {
+ 1715 521 : struct snapraid_disk* disk = i->data;
+ 1716 :
+ 1717 : /* don't print the message if the UUID changed because before */
+ 1718 : /* it was no set. */
+ 1719 : /* this is the normal condition for an empty disk because it */
+ 1720 : /* isn't stored */
+ 1721 521 : if (disk->has_different_uuid && !disk->had_empty_uuid) {
+ 1722 2 : if (!done) {
+ 1723 2 : done = 1;
+ 1724 2 : log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name);
+ 1725 : } else {
+ 1726 0 : log_fatal(", '%s'", disk->name);
+ 1727 : }
+ 1728 : }
+ 1729 : }
+ 1730 87 : if (done) {
+ 1731 2 : log_fatal(". Move operations won't be optimal.\n");
+ 1732 : }
+ 1733 :
+ 1734 : /* check for disks with unsupported UUID */
+ 1735 87 : done = 0;
+ 1736 608 : for (i = state->disklist; i != 0; i = i->next) {
+ 1737 521 : struct snapraid_disk* disk = i->data;
+ 1738 :
+ 1739 521 : if (disk->has_unsupported_uuid) {
+ 1740 0 : if (!done) {
+ 1741 0 : done = 1;
+ 1742 0 : log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name);
+ 1743 : } else {
+ 1744 0 : log_fatal(", '%s'", disk->name);
+ 1745 : }
+ 1746 : }
+ 1747 : }
+ 1748 87 : if (done) {
+ 1749 0 : log_fatal(". Move operations won't be optimal.\n");
+ 1750 : #if defined(_linux) && !HAVE_BLKID
+ 1751 : log_fatal("The 'blkid' library is not linked in SnapRAID!\n");
+ 1752 : log_fatal("Try rebuilding it after installing the libblkid-dev/devel package.\n");
+ 1753 : #endif
+ 1754 : }
+ 1755 :
+ 1756 87 : total.count_equal = 0;
+ 1757 87 : total.count_move = 0;
+ 1758 87 : total.count_copy = 0;
+ 1759 87 : total.count_restore = 0;
+ 1760 87 : total.count_change = 0;
+ 1761 87 : total.count_remove = 0;
+ 1762 87 : total.count_insert = 0;
+ 1763 :
+ 1764 608 : for (i = scanlist; i != 0; i = i->next) {
+ 1765 521 : struct snapraid_scan* scan = i->data;
+ 1766 521 : total.count_equal += scan->count_equal;
+ 1767 521 : total.count_move += scan->count_move;
+ 1768 521 : total.count_copy += scan->count_copy;
+ 1769 521 : total.count_restore += scan->count_restore;
+ 1770 521 : total.count_change += scan->count_change;
+ 1771 521 : total.count_remove += scan->count_remove;
+ 1772 521 : total.count_insert += scan->count_insert;
+ 1773 : }
+ 1774 :
+ 1775 87 : if (is_diff) {
+ 1776 7 : msg_status("\n");
+ 1777 7 : msg = msg_status;
+ 1778 : } else {
+ 1779 80 : msg = msg_verbose;
+ 1780 : }
+ 1781 :
+ 1782 87 : msg("%8u equal\n", total.count_equal);
+ 1783 87 : msg("%8u moved\n", total.count_move);
+ 1784 87 : msg("%8u copied\n", total.count_copy);
+ 1785 87 : msg("%8u restored\n", total.count_restore);
+ 1786 87 : msg("%8u updated\n", total.count_change);
+ 1787 87 : msg("%8u removed\n", total.count_remove);
+ 1788 87 : msg("%8u added\n", total.count_insert);
+ 1789 :
+ 1790 87 : log_tag("summary:equal:%u\n", total.count_equal);
+ 1791 87 : log_tag("summary:moved:%u\n", total.count_move);
+ 1792 87 : log_tag("summary:copied:%u\n", total.count_copy);
+ 1793 87 : log_tag("summary:restored:%u\n", total.count_restore);
+ 1794 87 : log_tag("summary:updated:%u\n", total.count_change);
+ 1795 87 : log_tag("summary:removed:%u\n", total.count_remove);
+ 1796 87 : log_tag("summary:added:%u\n", total.count_insert);
+ 1797 :
+ 1798 260 : no_difference = !total.count_move && !total.count_copy && !total.count_restore
+ 1799 144 : && !total.count_change && !total.count_remove && !total.count_insert;
+ 1800 :
+ 1801 87 : if (is_diff) {
+ 1802 7 : if (no_difference) {
+ 1803 1 : msg_status("No differences\n");
+ 1804 : } else {
+ 1805 6 : msg_status("There are differences!\n");
+ 1806 : }
1807 : }
- 1808 79 : log_flush();
- 1809 :
- 1810 79 : tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);
- 1811 :
- 1812 : /* check the filesystem on all disks */
- 1813 79 : state_fscheck(state, "after scan");
- 1814 :
- 1815 79 : if (is_diff) {
- 1816 : /* check for file difference */
- 1817 7 : if (!no_difference)
- 1818 6 : return 1;
- 1819 :
- 1820 : /* check also for incomplete "sync" */
- 1821 1 : if (parity_is_invalid(state))
- 1822 0 : return 1;
- 1823 : }
- 1824 :
- 1825 73 : return 0;
- 1826 : }
- 1827 :
- 1828 7 : int state_diff(struct snapraid_state* state)
- 1829 : {
- 1830 7 : return state_diffscan(state, 1);
- 1831 : }
- 1832 :
- 1833 73 : void state_scan(struct snapraid_state* state)
- 1834 : {
- 1835 73 : (void)state_diffscan(state, 0); /* ignore return value */
- 1836 72 : }
- 1837 :
+ 1808 :
+ 1809 87 : if (no_difference) {
+ 1810 14 : log_tag("summary:exit:equal\n");
+ 1811 : } else {
+ 1812 73 : log_tag("summary:exit:diff\n");
+ 1813 : }
+ 1814 87 : log_flush();
+ 1815 :
+ 1816 87 : tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);
+ 1817 :
+ 1818 : /* check the file-system on all disks */
+ 1819 87 : state_fscheck(state, "after scan");
+ 1820 :
+ 1821 87 : if (is_diff) {
+ 1822 : /* check for file difference */
+ 1823 7 : if (!no_difference)
+ 1824 6 : return 1;
+ 1825 :
+ 1826 : /* check also for incomplete "sync" */
+ 1827 1 : if (parity_is_invalid(state))
+ 1828 0 : return 1;
+ 1829 : }
+ 1830 :
+ 1831 81 : return 0;
+ 1832 : }
+ 1833 :
+ 1834 7 : int state_diff(struct snapraid_state* state)
+ 1835 : {
+ 1836 7 : return state_diffscan(state, 1);
+ 1837 : }
+ 1838 :
+ 1839 81 : void state_scan(struct snapraid_state* state)
+ 1840 : {
+ 1841 81 : (void)state_diffscan(state, 0); /* ignore return value */
+ 1842 80 : }
+ 1843 :
diff --git a/cov/cmdline/scrub.c.func-sort-c.html b/cov/cmdline/scrub.c.func-sort-c.html
index a40ea5f0..677e4c72 100644
--- a/cov/cmdline/scrub.c.func-sort-c.html
+++ b/cov/cmdline/scrub.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| block_is_enabled |
- 111818 |
+ 111994 |
| state_scrub_process |
diff --git a/cov/cmdline/scrub.c.func.html b/cov/cmdline/scrub.c.func.html
index 9815b4ce..0a104426 100644
--- a/cov/cmdline/scrub.c.func.html
+++ b/cov/cmdline/scrub.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| block_is_enabled |
- 111818 |
+ 111994 |
| md |
diff --git a/cov/cmdline/scrub.c.gcov.html b/cov/cmdline/scrub.c.gcov.html
index 751e79a9..d8624e9e 100644
--- a/cov/cmdline/scrub.c.gcov.html
+++ b/cov/cmdline/scrub.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -110,55 +110,55 @@
48 : /**
49 : * Check if we have to process the specified block index ::i.
50 : */
- 51 111818 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_plan* plan)
+ 51 111994 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_plan* plan)
52 : {
53 : time_t blocktime;
54 : snapraid_info info;
55 :
56 : /* don't scrub unused blocks in all plans */
- 57 111818 : info = info_get(&state->infoarr, i);
- 58 111818 : if (info == 0)
+ 57 111994 : info = info_get(&state->infoarr, i);
+ 58 111994 : if (info == 0)
59 0 : return 0;
60 :
61 : /* bad blocks are always scrubbed in all plans */
- 62 111818 : if (info_get_bad(info))
- 63 3604 : return 1;
+ 62 111994 : if (info_get_bad(info))
+ 63 3542 : return 1;
64 :
- 65 108214 : switch (plan->plan) {
+ 65 108452 : switch (plan->plan) {
66 : case SCRUB_FULL :
67 : /* in 'full' plan everything is scrubbed */
- 68 16920 : return 1;
+ 68 17014 : return 1;
69 : case SCRUB_EVEN :
70 : /* in 'even' plan, scrub only even blocks */
- 71 18398 : return i % 2 == 0;
+ 71 18414 : return i % 2 == 0;
72 : case SCRUB_NEW :
73 : /* in 'sync' plan, only blocks never scrubbed */
- 74 9342 : return info_get_justsynced(info);
+ 74 9358 : return info_get_justsynced(info);
75 : case SCRUB_BAD :
76 : /* in 'bad' plan, only bad blocks (already reported) */
- 77 7502 : return 0;
+ 77 7518 : return 0;
78 : }
79 :
80 : /* if it's too new */
- 81 56052 : blocktime = info_get_time(info);
- 82 56052 : if (blocktime > plan->timelimit) {
+ 81 56148 : blocktime = info_get_time(info);
+ 82 56148 : if (blocktime > plan->timelimit) {
83 : /* skip it */
- 84 22506 : return 0;
+ 84 20662 : return 0;
85 : }
86 :
87 : /* if the time is less than the limit, always include */
88 : /* otherwise, check if we reached the last limit count */
- 89 33546 : if (blocktime == plan->timelimit) {
+ 89 35486 : if (blocktime == plan->timelimit) {
90 : /* if we reached the count limit */
- 91 16872 : if (plan->countlast >= plan->lastlimit) {
+ 91 18980 : if (plan->countlast >= plan->lastlimit) {
92 : /* skip it */
- 93 11882 : return 0;
+ 93 13790 : return 0;
94 : }
95 :
- 96 4990 : ++plan->countlast;
+ 96 5190 : ++plan->countlast;
97 : }
98 :
- 99 21664 : return 1;
+ 99 21696 : return 1;
100 : }
101 :
102 11 : static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax, struct snapraid_plan* plan, time_t now)
@@ -204,11 +204,11 @@
142 : /* first count the number of blocks to process */
143 11 : countmax = 0;
144 11 : plan->countlast = 0;
- 145 55920 : for (i = blockstart; i < blockmax; ++i) {
- 146 55909 : if (!block_is_enabled(state, i, plan))
- 147 27950 : continue;
+ 145 56008 : for (i = blockstart; i < blockmax; ++i) {
+ 146 55997 : if (!block_is_enabled(state, i, plan))
+ 147 28002 : continue;
148 :
- 149 27959 : ++countmax;
+ 149 27995 : ++countmax;
150 : }
151 :
152 : /* compute the autosave size for all disk, even if not read */
@@ -225,7 +225,7 @@
163 11 : countpos = 0;
164 11 : plan->countlast = 0;
165 11 : state_progress_begin(state, blockstart, blockmax, countmax);
- 166 55920 : for (i = blockstart; i < blockmax; ++i) {
+ 166 56008 : for (i = blockstart; i < blockmax; ++i) {
167 : snapraid_info info;
168 : int error_on_this_block;
169 : int silent_error_on_this_block;
@@ -233,65 +233,65 @@
171 : int block_is_unsynced;
172 : int rehash;
173 :
- 174 55909 : if (!block_is_enabled(state, i, plan))
- 175 27950 : continue;
+ 174 55997 : if (!block_is_enabled(state, i, plan))
+ 175 28002 : continue;
176 :
177 : /* one more block processed for autosave */
- 178 27959 : ++autosavedone;
- 179 27959 : --autosavemissing;
+ 178 27995 : ++autosavedone;
+ 179 27995 : --autosavemissing;
180 :
181 : /* by default process the block, and skip it if something goes wrong */
- 182 27959 : error_on_this_block = 0;
- 183 27959 : silent_error_on_this_block = 0;
- 184 27959 : io_error_on_this_block = 0;
+ 182 27995 : error_on_this_block = 0;
+ 183 27995 : silent_error_on_this_block = 0;
+ 184 27995 : io_error_on_this_block = 0;
185 :
186 : /* if all the blocks at this address are synced */
187 : /* if not, parity is not even checked */
- 188 27959 : block_is_unsynced = 0;
+ 188 27995 : block_is_unsynced = 0;
189 :
190 : /* get block specific info */
- 191 27959 : info = info_get(&state->infoarr, i);
+ 191 27995 : info = info_get(&state->infoarr, i);
192 :
193 : /* if we have to use the old hash */
- 194 27959 : rehash = info_get_rehash(info);
+ 194 27995 : rehash = info_get_rehash(info);
195 :
196 : /* for each disk, process the block */
- 197 195713 : for (j = 0; j < diskmax; ++j) {
+ 197 195965 : for (j = 0; j < diskmax; ++j) {
198 : int read_size;
199 : unsigned char hash[HASH_SIZE];
200 : struct snapraid_block* block;
201 : int file_is_unsynced;
- 202 167754 : struct snapraid_disk* disk = handle[j].disk;
+ 202 167970 : struct snapraid_disk* disk = handle[j].disk;
203 : struct snapraid_file* file;
204 : block_off_t file_pos;
205 :
206 : /* if the file on this disk is synced */
207 : /* if not, silent errors are assumed as expected error */
- 208 167754 : file_is_unsynced = 0;
+ 208 167970 : file_is_unsynced = 0;
209 :
210 : /* by default no rehash in case of "continue" */
- 211 167754 : rehandle[j].block = 0;
+ 211 167970 : rehandle[j].block = 0;
212 :
213 : /* if the disk position is not used */
- 214 167754 : if (!disk) {
+ 214 167970 : if (!disk) {
215 : /* use an empty block */
216 0 : memset(buffer[j], 0, state->block_size);
- 217 2433 : continue;
+ 217 2397 : continue;
218 : }
219 :
220 : /* if the block is not used */
- 221 167754 : block = fs_par2block_get(disk, i);
- 222 167754 : if (!block_has_file(block)) {
+ 221 167970 : block = fs_par2block_get(disk, i);
+ 222 167970 : if (!block_has_file(block)) {
223 : /* use an empty block */
- 224 1513 : memset(buffer[j], 0, state->block_size);
- 225 1513 : continue;
+ 224 1477 : memset(buffer[j], 0, state->block_size);
+ 225 1477 : continue;
226 : }
227 :
228 : /* get the file of this block */
- 229 166241 : file = fs_par2file_get(disk, i, &file_pos);
+ 229 166493 : file = fs_par2file_get(disk, i, &file_pos);
230 :
231 : /* if the block is unsynced, errors are expected */
- 232 166241 : if (block_has_invalid_parity(block)) {
+ 232 166493 : if (block_has_invalid_parity(block)) {
233 : /* report that the block and the file are not synced */
234 0 : block_is_unsynced = 1;
235 0 : file_is_unsynced = 1;
@@ -299,14 +299,14 @@
237 : }
238 :
239 : /* until now is CPU */
- 240 166241 : state_usage_cpu(state);
+ 240 166493 : state_usage_cpu(state);
241 :
242 : /* if the file is different than the current one, close it */
- 243 166241 : if (handle[j].file != 0 && handle[j].file != file) {
+ 243 166493 : if (handle[j].file != 0 && handle[j].file != file) {
244 : /* keep a pointer at the file we are going to close for error reporting */
- 245 78552 : struct snapraid_file* report = handle[j].file;
- 246 78552 : ret = handle_close(&handle[j]);
- 247 78552 : if (ret == -1) {
+ 245 78228 : struct snapraid_file* report = handle[j].file;
+ 246 78228 : ret = handle_close(&handle[j]);
+ 247 78228 : if (ret == -1) {
248 : /* LCOV_EXCL_START */
249 : /* This one is really an unexpected error, because we are only reading */
250 : /* and closing a descriptor should never fail */
@@ -329,8 +329,8 @@
267 : }
268 : }
269 :
- 270 166241 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
- 271 166241 : if (ret == -1) {
+ 270 166493 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
+ 271 166493 : if (ret == -1) {
272 0 : if (errno == EIO) {
273 : /* LCOV_EXCL_START */
274 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
@@ -349,14 +349,14 @@
287 : }
288 :
289 : /* check if the file is changed */
- 290 166241 : if (handle[j].st.st_size != file->size
- 291 166241 : || handle[j].st.st_mtime != file->mtime_sec
- 292 160522 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
- 293 : /* don't check the inode to support filesystem without persistent inodes */
+ 290 166493 : if (handle[j].st.st_size != file->size
+ 291 166493 : || handle[j].st.st_mtime != file->mtime_sec
+ 292 160895 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
+ 293 : /* don't check the inode to support file-system without persistent inodes */
294 : ) {
295 : /* report that the block and the file are not synced */
- 296 5719 : block_is_unsynced = 1;
- 297 5719 : file_is_unsynced = 1;
+ 296 5598 : block_is_unsynced = 1;
+ 297 5598 : file_is_unsynced = 1;
298 : /* follow */
299 : }
300 :
@@ -364,8 +364,8 @@
302 : /* from the last sync, as we are expected to return errors if running */
303 : /* in an unsynced array. This is just like the check command. */
304 :
- 305 166241 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0);
- 306 166241 : if (read_size == -1) {
+ 305 166493 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0);
+ 306 166493 : if (read_size == -1) {
307 0 : if (errno == EIO) {
308 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc(file->sub), file_pos, strerror(errno));
309 0 : if (io_error >= state->opt.io_error_limit) {
@@ -391,24 +391,24 @@
329 : }
330 :
331 : /* until now is disk */
- 332 166241 : state_usage_disk(state, disk);
+ 332 166493 : state_usage_disk(state, disk);
333 :
- 334 166241 : countsize += read_size;
+ 334 166493 : countsize += read_size;
335 :
336 : /* now compute the hash */
- 337 166241 : if (rehash) {
- 338 27207 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
+ 337 166493 : if (rehash) {
+ 338 27235 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
339 :
340 : /* compute the new hash, and store it */
- 341 27207 : rehandle[j].block = block;
- 342 27207 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size);
+ 341 27235 : rehandle[j].block = block;
+ 342 27235 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size);
343 : } else {
- 344 139034 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
+ 344 139258 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
345 : }
346 :
- 347 166241 : if (block_has_updated_hash(block)) {
+ 347 166493 : if (block_has_updated_hash(block)) {
348 : /* compare the hash */
- 349 166241 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 349 166493 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
350 920 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE);
351 :
352 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff);
@@ -428,22 +428,22 @@
366 : }
367 :
368 : /* if we have read all the data required and it's correct, proceed with the parity check */
- 369 27959 : if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) {
+ 369 27995 : if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) {
370 : unsigned char* buffer_recov[LEV_MAX];
371 :
372 : /* until now is CPU */
- 373 27039 : state_usage_cpu(state);
+ 373 27075 : state_usage_cpu(state);
374 :
375 : /* buffers for parity read and not computed */
- 376 189273 : for (l = 0; l < state->level; ++l)
- 377 162234 : buffer_recov[l] = buffer[diskmax + state->level + l];
- 378 27039 : for (; l < LEV_MAX; ++l)
+ 376 189525 : for (l = 0; l < state->level; ++l)
+ 377 162450 : buffer_recov[l] = buffer[diskmax + state->level + l];
+ 378 27075 : for (; l < LEV_MAX; ++l)
379 0 : buffer_recov[l] = 0;
380 :
381 : /* read the parity */
- 382 189273 : for (l = 0; l < state->level; ++l) {
- 383 162234 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
- 384 162234 : if (ret == -1) {
+ 382 189525 : for (l = 0; l < state->level; ++l) {
+ 383 162450 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
+ 384 162450 : if (ret == -1) {
385 0 : buffer_recov[l] = 0;
386 :
387 0 : if (errno == EIO) {
@@ -471,15 +471,15 @@
409 : }
410 :
411 : /* until now is parity */
- 412 162234 : state_usage_parity(state, l);
+ 412 162450 : state_usage_parity(state, l);
413 : }
414 :
415 : /* compute the parity */
- 416 27039 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 416 27075 : raid_gen(diskmax, state->level, state->block_size, buffer);
417 :
418 : /* compare the parity */
- 419 189273 : for (l = 0; l < state->level; ++l) {
- 420 162234 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) {
+ 419 189525 : for (l = 0; l < state->level; ++l) {
+ 420 162450 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) {
421 0 : unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size);
422 :
423 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff);
@@ -497,42 +497,42 @@
435 : }
436 : }
437 :
- 438 27959 : if (silent_error_on_this_block || io_error_on_this_block) {
+ 438 27995 : if (silent_error_on_this_block || io_error_on_this_block) {
439 : /* set the error status keeping other info */
440 920 : info_set(&state->infoarr, i, info_set_bad(info));
- 441 27039 : } else if (error_on_this_block) {
+ 441 27075 : } else if (error_on_this_block) {
442 : /* do nothing, as this is a generic error */
443 : /* likely caused by a not synced array */
444 : } else {
445 : /* if rehash is needed */
- 446 27039 : if (rehash) {
+ 446 27075 : if (rehash) {
447 : /* store all the new hash already computed */
- 448 32200 : for (j = 0; j < diskmax; ++j) {
- 449 27600 : if (rehandle[j].block)
- 450 27207 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE);
+ 448 32228 : for (j = 0; j < diskmax; ++j) {
+ 449 27624 : if (rehandle[j].block)
+ 450 27235 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE);
451 : }
452 : }
453 :
454 : /* update the time info of the block */
455 : /* and clear any other flag */
- 456 27039 : info_set(&state->infoarr, i, info_make(now, 0, 0, 0));
+ 456 27075 : info_set(&state->infoarr, i, info_make(now, 0, 0, 0));
457 : }
458 :
459 : /* mark the state as needing write */
- 460 27959 : state->need_write = 1;
+ 460 27995 : state->need_write = 1;
461 :
462 : /* count the number of processed block */
- 463 27959 : ++countpos;
+ 463 27995 : ++countpos;
464 :
465 : /* progress */
- 466 27959 : if (state_progress(state, i, countpos, countmax, countsize)) {
+ 466 27995 : if (state_progress(state, i, countpos, countmax, countsize)) {
467 : /* LCOV_EXCL_START */
468 : break;
469 : /* LCOV_EXCL_STOP */
470 : }
471 :
472 : /* autosave */
- 473 27959 : if (state->autosave != 0
+ 473 27995 : if (state->autosave != 0
474 0 : && autosavedone >= autosavelimit /* if we have reached the limit */
475 0 : && autosavemissing >= autosavelimit /* if we have at least a full step to do */
476 : ) {
@@ -705,14 +705,14 @@
643 : /* copy the info in the temp vector */
644 11 : count = 0;
645 11 : log_tag("block_count:%u\n", blockmax);
- 646 55920 : for (i = 0; i < blockmax; ++i) {
- 647 55909 : snapraid_info info = info_get(&state->infoarr, i);
+ 646 56008 : for (i = 0; i < blockmax; ++i) {
+ 647 55997 : snapraid_info info = info_get(&state->infoarr, i);
648 :
649 : /* skip unused blocks */
- 650 55909 : if (info == 0)
+ 650 55997 : if (info == 0)
651 0 : continue;
652 :
- 653 55909 : timemap[count++] = info_get_time(info);
+ 653 55997 : timemap[count++] = info_get_time(info);
654 : }
655 :
656 11 : if (!count) {
@@ -728,12 +728,12 @@
666 : /* output the info map */
667 11 : i = 0;
668 11 : log_tag("info_count:%u\n", count);
- 669 54 : while (i < count) {
- 670 32 : unsigned j = i + 1;
- 671 55941 : while (j < count && timemap[i] == timemap[j])
- 672 55877 : ++j;
- 673 32 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i);
- 674 32 : i = j;
+ 669 49 : while (i < count) {
+ 670 27 : unsigned j = i + 1;
+ 671 56024 : while (j < count && timemap[i] == timemap[j])
+ 672 55970 : ++j;
+ 673 27 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i);
+ 674 27 : i = j;
675 : }
676 :
677 : /* compute the limits from count/recentlimit */
@@ -754,8 +754,8 @@
692 : /* count how many entries for this exact time we have to scrub */
693 : /* if the blocks have all the same time, we end with countlimit == lastlimit */
694 5 : ps.lastlimit = 1;
- 695 2500 : while (countlimit > ps.lastlimit && timemap[countlimit - ps.lastlimit - 1] == ps.timelimit)
- 696 2490 : ++ps.lastlimit;
+ 695 2600 : while (countlimit > ps.lastlimit && timemap[countlimit - ps.lastlimit - 1] == ps.timelimit)
+ 696 2590 : ++ps.lastlimit;
697 : } else {
698 : /* if nothing to scrub, disable also other limits */
699 1 : ps.timelimit = 0;
diff --git a/cov/cmdline/search.c.func-sort-c.html b/cov/cmdline/search.c.func-sort-c.html
index 29c53774..b4963364 100644
--- a/cov/cmdline/search.c.func-sort-c.html
+++ b/cov/cmdline/search.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -61,19 +61,19 @@
| search_file |
- 1842576 |
+ 1843303 |
| search_file_free |
- 1842576 |
+ 1843303 |
| state_search_fetch |
- 630482 |
+ 639672 |
| search_file_compare |
- 11531 |
+ 20073 |
| search_dir |
diff --git a/cov/cmdline/search.c.func.html b/cov/cmdline/search.c.func.html
index 7773723e..bc92b8ca 100644
--- a/cov/cmdline/search.c.func.html
+++ b/cov/cmdline/search.c.func.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -65,15 +65,15 @@
| search_file |
- 1842576 |
+ 1843303 |
| search_file_compare |
- 11531 |
+ 20073 |
| search_file_free |
- 1842576 |
+ 1843303 |
| state_search |
@@ -85,7 +85,7 @@
| state_search_fetch |
- 630482 |
+ 639672 |
diff --git a/cov/cmdline/search.c.gcov.html b/cov/cmdline/search.c.gcov.html
index ae597b03..06f79786 100644
--- a/cov/cmdline/search.c.gcov.html
+++ b/cov/cmdline/search.c.gcov.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -85,27 +85,27 @@
23 : /****************************************************************************/
24 : /* search */
25 :
- 26 1842576 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec)
+ 26 1843303 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec)
27 : {
28 : struct snapraid_search_file* file;
29 : tommy_uint32_t file_hash;
30 :
- 31 1842576 : file = malloc_nofail(sizeof(struct snapraid_search_file));
- 32 1842576 : file->path = strdup_nofail(path);
- 33 1842576 : file->size = size;
- 34 1842576 : file->mtime_sec = mtime_sec;
- 35 1842576 : file->mtime_nsec = mtime_nsec;
+ 31 1843303 : file = malloc_nofail(sizeof(struct snapraid_search_file));
+ 32 1843303 : file->path = strdup_nofail(path);
+ 33 1843303 : file->size = size;
+ 34 1843303 : file->mtime_sec = mtime_sec;
+ 35 1843303 : file->mtime_nsec = mtime_nsec;
36 :
- 37 1842576 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
+ 37 1843303 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
38 :
- 39 1842576 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash);
- 40 1842576 : }
+ 39 1843303 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash);
+ 40 1843303 : }
41 :
- 42 1842576 : void search_file_free(struct snapraid_search_file* file)
+ 42 1843303 : void search_file_free(struct snapraid_search_file* file)
43 : {
- 44 1842576 : free(file->path);
- 45 1842576 : free(file);
- 46 1842576 : }
+ 44 1843303 : free(file->path);
+ 45 1843303 : free(file);
+ 46 1843303 : }
47 :
48 : struct search_file_compare_arg {
49 : const struct snapraid_state* state;
@@ -117,29 +117,29 @@
55 : int prevhash;
56 : };
57 :
- 58 11531 : int search_file_compare(const void* void_arg, const void* void_data)
+ 58 20073 : int search_file_compare(const void* void_arg, const void* void_data)
59 : {
- 60 11531 : const struct search_file_compare_arg* arg = void_arg;
- 61 11531 : const struct snapraid_search_file* file = void_data;
- 62 11531 : const struct snapraid_state* state = arg->state;
+ 60 20073 : const struct search_file_compare_arg* arg = void_arg;
+ 61 20073 : const struct snapraid_search_file* file = void_data;
+ 62 20073 : const struct snapraid_state* state = arg->state;
63 : unsigned char buffer_hash[HASH_SIZE];
- 64 11531 : const char* path = file->path;
+ 64 20073 : const char* path = file->path;
65 : int f;
66 : ssize_t ret;
67 :
68 : /* compare file info */
- 69 11531 : if (arg->file->size != file->size)
+ 69 20073 : if (arg->file->size != file->size)
70 0 : return -1;
71 :
- 72 11531 : if (arg->file->mtime_sec != file->mtime_sec)
+ 72 20073 : if (arg->file->mtime_sec != file->mtime_sec)
73 0 : return -1;
74 :
- 75 11531 : if (arg->file->mtime_nsec != file->mtime_nsec)
+ 75 20073 : if (arg->file->mtime_nsec != file->mtime_nsec)
76 0 : return -1;
77 :
78 : /* read the block and compare the hash */
- 79 11531 : f = open(path, O_RDONLY | O_BINARY);
- 80 11531 : if (f == -1) {
+ 79 20073 : f = open(path, O_RDONLY | O_BINARY);
+ 80 20073 : if (f == -1) {
81 : /* LCOV_EXCL_START */
82 : if (errno == ENOENT) {
83 : log_fatal("DANGER! file '%s' disappeared.\n", path);
@@ -151,23 +151,23 @@
89 : /* LCOV_EXCL_STOP */
90 : }
91 :
- 92 11531 : if (lseek(f, arg->offset, SEEK_SET) != arg->offset) {
+ 92 20073 : if (lseek(f, arg->offset, SEEK_SET) != arg->offset) {
93 : /* LCOV_EXCL_START */
94 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno));
95 : exit(EXIT_FAILURE);
96 : /* LCOV_EXCL_STOP */
97 : }
98 :
- 99 11531 : ret = read(f, arg->buffer, arg->read_size);
- 100 11531 : if (ret < 0 || (unsigned)ret != arg->read_size) {
+ 99 20073 : ret = read(f, arg->buffer, arg->read_size);
+ 100 20073 : if (ret < 0 || (unsigned)ret != arg->read_size) {
101 : /* LCOV_EXCL_START */
102 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
103 : exit(EXIT_FAILURE);
104 : /* LCOV_EXCL_STOP */
105 : }
106 :
- 107 11531 : ret = close(f);
- 108 11531 : if (ret != 0) {
+ 107 20073 : ret = close(f);
+ 108 20073 : if (ret != 0) {
109 : /* LCOV_EXCL_START */
110 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
111 : exit(EXIT_FAILURE);
@@ -175,46 +175,46 @@
113 : }
114 :
115 : /* compute the hash */
- 116 11531 : if (arg->prevhash)
- 117 4492 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size);
+ 116 20073 : if (arg->prevhash)
+ 117 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size);
118 : else
- 119 7039 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size);
+ 119 20073 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size);
120 :
121 : /* check if the hash is matching */
- 122 11531 : if (memcmp(buffer_hash, arg->block->hash, HASH_SIZE) != 0)
- 123 2119 : return -1;
+ 122 20073 : if (memcmp(buffer_hash, arg->block->hash, HASH_SIZE) != 0)
+ 123 2235 : return -1;
124 :
- 125 9412 : if (arg->read_size != state->block_size) {
+ 125 17838 : if (arg->read_size != state->block_size) {
126 : /* fill the remaining with 0 */
- 127 3956 : memset(arg->buffer + arg->read_size, 0, state->block_size - arg->read_size);
+ 127 7108 : memset(arg->buffer + arg->read_size, 0, state->block_size - arg->read_size);
128 : }
129 :
- 130 9412 : return 0;
+ 130 17838 : return 0;
131 : }
132 :
- 133 630482 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer)
+ 133 639672 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer)
134 : {
135 : struct snapraid_search_file* file;
136 : tommy_uint32_t file_hash;
137 : struct search_file_compare_arg arg;
138 :
- 139 630482 : arg.state = state;
- 140 630482 : arg.block = missing_block;
- 141 630482 : arg.file = missing_file;
- 142 630482 : arg.buffer = buffer;
- 143 630482 : arg.offset = state->block_size * (data_off_t)missing_file_pos;
- 144 630482 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size);
- 145 630482 : arg.prevhash = prevhash;
+ 139 639672 : arg.state = state;
+ 140 639672 : arg.block = missing_block;
+ 141 639672 : arg.file = missing_file;
+ 142 639672 : arg.buffer = buffer;
+ 143 639672 : arg.offset = state->block_size * (data_off_t)missing_file_pos;
+ 144 639672 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size);
+ 145 639672 : arg.prevhash = prevhash;
146 :
- 147 630482 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec);
+ 147 639672 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec);
148 :
149 : /* search in the hashtable, and also check if the data matches the hash */
- 150 630482 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash);
- 151 630482 : if (!file)
- 152 621070 : return -1;
+ 150 639672 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash);
+ 151 639672 : if (!file)
+ 152 621834 : return -1;
153 :
154 : /* if found, buffer is already set with data */
- 155 9412 : return 0;
+ 155 17838 : return 0;
156 : }
157 :
158 2462 : static void search_dir(struct snapraid_state* state, struct snapraid_disk* disk, const char* dir, const char* sub)
@@ -233,40 +233,40 @@
171 : char path_next[PATH_MAX];
172 : char sub_next[PATH_MAX];
173 : char out[PATH_MAX];
- 174 2039164 : struct snapraid_filter* reason = 0;
+ 174 2039885 : struct snapraid_filter* reason = 0;
175 : struct stat st;
176 : const char* name;
177 : struct dirent* dd;
178 :
179 : /* clear errno to detect erroneous conditions */
- 180 2039164 : errno = 0;
- 181 2039164 : dd = readdir(d);
- 182 2039164 : if (dd == 0 && errno != 0) {
+ 180 2039885 : errno = 0;
+ 181 2039885 : dd = readdir(d);
+ 182 2039885 : if (dd == 0 && errno != 0) {
183 : /* LCOV_EXCL_START */
184 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
185 : exit(EXIT_FAILURE);
186 : /* LCOV_EXCL_STOP */
187 : }
- 188 2039164 : if (dd == 0) {
+ 188 2039885 : if (dd == 0) {
189 2462 : break; /* finished */
190 : }
191 :
192 : /* skip "." and ".." files */
- 193 2036702 : name = dd->d_name;
- 194 2036702 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+ 193 2037423 : name = dd->d_name;
+ 194 2037423 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
195 9848 : continue;
196 :
- 197 2031778 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
- 198 2031778 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
+ 197 2032499 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 198 2032499 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
199 :
200 : /* exclude hidden files even before calling lstat() */
- 201 2031778 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) {
+ 201 2032499 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) {
202 0 : msg_verbose("Excluding hidden '%s'\n", path_next);
203 0 : continue;
204 : }
205 :
206 : /* exclude content files even before calling lstat() */
- 207 2031778 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) {
+ 207 2032499 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) {
208 0 : msg_verbose("Excluding content '%s'\n", path_next);
209 0 : continue;
210 : }
@@ -290,7 +290,7 @@
228 : }
229 : #else
230 : /* get lstat info about the file */
- 231 2031778 : if (lstat(path_next, &st) != 0) {
+ 231 2032499 : if (lstat(path_next, &st) != 0) {
232 : /* LCOV_EXCL_START */
233 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
234 : exit(EXIT_FAILURE);
@@ -298,13 +298,13 @@
236 : }
237 : #endif
238 :
- 239 2031778 : if (S_ISREG(st.st_mode)) {
- 240 1967521 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
- 241 1842576 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st));
+ 239 2032499 : if (S_ISREG(st.st_mode)) {
+ 240 1968182 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 241 1843303 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st));
242 : } else {
- 243 124945 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
+ 243 124879 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
244 : }
- 245 64257 : } else if (S_ISDIR(st.st_mode)) {
+ 245 64317 : } else if (S_ISDIR(st.st_mode)) {
246 1781 : if (disk == 0 || filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
247 1781 : pathslash(path_next, sizeof(path_next));
248 1781 : pathslash(sub_next, sizeof(sub_next));
@@ -313,7 +313,7 @@
251 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
252 : }
253 : }
- 254 2036702 : }
+ 254 2037423 : }
255 :
256 2462 : if (closedir(d) != 0) {
257 : /* LCOV_EXCL_START */
diff --git a/cov/cmdline/selftest.c.func-sort-c.html b/cov/cmdline/selftest.c.func-sort-c.html
index cbbf9134..ef0b6b12 100644
--- a/cov/cmdline/selftest.c.func-sort-c.html
+++ b/cov/cmdline/selftest.c.func-sort-c.html
@@ -32,12 +32,12 @@
|
-
-
+
+
-
+
|
@@ -88,7 +88,7 @@
1 |
- | selftest |
+ selftest |
1 |
diff --git a/cov/cmdline/selftest.c.func.html b/cov/cmdline/selftest.c.func.html
index 7dd73f90..bb9ef14f 100644
--- a/cov/cmdline/selftest.c.func.html
+++ b/cov/cmdline/selftest.c.func.html
@@ -32,12 +32,12 @@
|
-
-
+
+
-
+
|
@@ -60,7 +60,7 @@
Hit count  |
- | selftest |
+ selftest |
1 |
diff --git a/cov/cmdline/selftest.c.gcov.html b/cov/cmdline/selftest.c.gcov.html
index c18817e6..31f5f6df 100644
--- a/cov/cmdline/selftest.c.gcov.html
+++ b/cov/cmdline/selftest.c.gcov.html
@@ -32,12 +32,12 @@
|
-
-
+
+
-
+
|
@@ -378,207 +378,288 @@
316 256 : *(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) = i;
317 : }
318 :
- 319 1 : if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*))
- 320 0 : goto bail;
- 321 1 : if (tommy_arrayblk_memory_usage(&arrayblk) < TOMMY_SIZE * sizeof(void*))
- 322 0 : goto bail;
- 323 1 : if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned))
- 324 0 : goto bail;
- 325 :
- 326 257 : for (i = 0; i < TOMMY_SIZE; ++i) {
- 327 256 : if (tommy_array_get(&array, i) != &node[i])
- 328 0 : goto bail;
- 329 256 : if (tommy_arrayblk_get(&arrayblk, i) != &node[i])
- 330 0 : goto bail;
- 331 256 : if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i)
- 332 0 : goto bail;
+ 319 1 : if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*)) {
+ 320 : /* LCOV_EXCL_START */
+ 321 : goto bail;
+ 322 : /* LCOV_EXCL_STOP */
+ 323 : }
+ 324 1 : if (tommy_arrayblk_memory_usage(&arrayblk) < TOMMY_SIZE * sizeof(void*)) {
+ 325 : /* LCOV_EXCL_START */
+ 326 : goto bail;
+ 327 : /* LCOV_EXCL_STOP */
+ 328 : }
+ 329 1 : if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned)) {
+ 330 : /* LCOV_EXCL_START */
+ 331 : goto bail;
+ 332 : /* LCOV_EXCL_STOP */
333 : }
334 :
- 335 1 : tommy_arrayblkof_done(&arrayblkof);
- 336 1 : tommy_arrayblk_done(&arrayblk);
- 337 1 : tommy_array_done(&array);
- 338 :
- 339 1 : tommy_list_init(&list);
- 340 :
- 341 1 : if (!tommy_list_empty(&list))
- 342 0 : goto bail;
- 343 :
- 344 1 : if (tommy_list_tail(&list))
- 345 0 : goto bail;
- 346 :
- 347 1 : if (tommy_list_head(&list))
- 348 0 : goto bail;
- 349 :
- 350 1 : tommy_hashdyn_init(&hashdyn);
- 351 :
- 352 257 : for (i = 0; i < TOMMY_SIZE; ++i)
- 353 256 : tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64);
- 354 :
- 355 1 : if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE)
- 356 0 : goto bail;
- 357 :
- 358 1 : if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node))
- 359 0 : goto bail;
- 360 :
- 361 1 : tommy_test_foreach_count = 0;
- 362 1 : tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach);
- 363 1 : if (tommy_test_foreach_count != TOMMY_SIZE)
- 364 0 : goto bail;
- 365 :
- 366 1 : tommy_test_foreach_count = 0;
- 367 1 : tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count);
- 368 1 : if (tommy_test_foreach_count != TOMMY_SIZE)
- 369 0 : goto bail;
+ 335 257 : for (i = 0; i < TOMMY_SIZE; ++i) {
+ 336 256 : if (tommy_array_get(&array, i) != &node[i]) {
+ 337 : /* LCOV_EXCL_START */
+ 338 : goto bail;
+ 339 : /* LCOV_EXCL_STOP */
+ 340 : }
+ 341 256 : if (tommy_arrayblk_get(&arrayblk, i) != &node[i]) {
+ 342 : /* LCOV_EXCL_START */
+ 343 : goto bail;
+ 344 : /* LCOV_EXCL_STOP */
+ 345 : }
+ 346 256 : if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i) {
+ 347 : /* LCOV_EXCL_START */
+ 348 : goto bail;
+ 349 : /* LCOV_EXCL_STOP */
+ 350 : }
+ 351 : }
+ 352 :
+ 353 1 : tommy_arrayblkof_done(&arrayblkof);
+ 354 1 : tommy_arrayblk_done(&arrayblk);
+ 355 1 : tommy_array_done(&array);
+ 356 :
+ 357 1 : tommy_list_init(&list);
+ 358 :
+ 359 1 : if (!tommy_list_empty(&list)) {
+ 360 : /* LCOV_EXCL_START */
+ 361 : goto bail;
+ 362 : /* LCOV_EXCL_STOP */
+ 363 : }
+ 364 :
+ 365 1 : if (tommy_list_tail(&list)) {
+ 366 : /* LCOV_EXCL_START */
+ 367 : goto bail;
+ 368 : /* LCOV_EXCL_STOP */
+ 369 : }
370 :
- 371 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
- 372 128 : tommy_hashdyn_remove_existing(&hashdyn, &node[i]);
- 373 :
- 374 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
- 375 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0)
- 376 0 : goto bail;
- 377 :
- 378 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i)
- 379 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0)
- 380 0 : goto bail;
+ 371 1 : if (tommy_list_head(&list)) {
+ 372 : /* LCOV_EXCL_START */
+ 373 : goto bail;
+ 374 : /* LCOV_EXCL_STOP */
+ 375 : }
+ 376 :
+ 377 1 : tommy_hashdyn_init(&hashdyn);
+ 378 :
+ 379 257 : for (i = 0; i < TOMMY_SIZE; ++i)
+ 380 256 : tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64);
381 :
- 382 1 : if (tommy_hashdyn_count(&hashdyn) != 0)
- 383 0 : goto bail;
- 384 :
- 385 1 : tommy_hashdyn_done(&hashdyn);
- 386 :
- 387 1 : tommy_tree_init(&tree, tommy_test_compare);
- 388 :
- 389 257 : for (i = 0; i < TOMMY_SIZE; ++i)
- 390 256 : tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i+1));
- 391 :
- 392 : /* try to insert a duplicate, count should not change */
- 393 1 : if (tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)1) != (void*)1)
- 394 0 : goto bail;
- 395 :
- 396 1 : if (tommy_tree_count(&tree) != TOMMY_SIZE)
- 397 0 : goto bail;
- 398 :
- 399 1 : if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node))
- 400 0 : goto bail;
+ 382 1 : if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE) {
+ 383 : /* LCOV_EXCL_START */
+ 384 : goto bail;
+ 385 : /* LCOV_EXCL_STOP */
+ 386 : }
+ 387 :
+ 388 1 : if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node)) {
+ 389 : /* LCOV_EXCL_START */
+ 390 : goto bail;
+ 391 : /* LCOV_EXCL_STOP */
+ 392 : }
+ 393 :
+ 394 1 : tommy_test_foreach_count = 0;
+ 395 1 : tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach);
+ 396 1 : if (tommy_test_foreach_count != TOMMY_SIZE) {
+ 397 : /* LCOV_EXCL_START */
+ 398 : goto bail;
+ 399 : /* LCOV_EXCL_STOP */
+ 400 : }
401 :
- 402 1 : if (tommy_tree_search(&tree, (void*)1) != (void*)1)
- 403 0 : goto bail;
- 404 :
- 405 1 : if (tommy_tree_search(&tree, (void*)-1) != 0)
- 406 0 : goto bail;
- 407 :
- 408 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1)
- 409 0 : goto bail;
- 410 :
- 411 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0)
- 412 0 : goto bail;
- 413 :
- 414 1 : tommy_test_foreach_count = 0;
- 415 1 : tommy_tree_foreach(&tree, tommy_test_foreach);
- 416 1 : if (tommy_test_foreach_count != TOMMY_SIZE)
- 417 0 : goto bail;
- 418 :
- 419 1 : tommy_test_foreach_count = 0;
- 420 1 : tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count);
- 421 1 : if (tommy_test_foreach_count != TOMMY_SIZE)
- 422 0 : goto bail;
- 423 :
- 424 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
- 425 128 : tommy_tree_remove_existing(&tree, &node[i]);
- 426 :
- 427 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
- 428 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) != 0)
- 429 0 : goto bail;
- 430 :
- 431 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i)
- 432 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) == 0)
- 433 0 : goto bail;
- 434 :
- 435 1 : if (tommy_tree_count(&tree) != 0)
- 436 0 : goto bail;
+ 402 1 : tommy_test_foreach_count = 0;
+ 403 1 : tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count);
+ 404 1 : if (tommy_test_foreach_count != TOMMY_SIZE) {
+ 405 : /* LCOV_EXCL_START */
+ 406 : goto bail;
+ 407 : /* LCOV_EXCL_STOP */
+ 408 : }
+ 409 :
+ 410 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
+ 411 128 : tommy_hashdyn_remove_existing(&hashdyn, &node[i]);
+ 412 :
+ 413 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) {
+ 414 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0) {
+ 415 : /* LCOV_EXCL_START */
+ 416 : goto bail;
+ 417 : /* LCOV_EXCL_STOP */
+ 418 : }
+ 419 : }
+ 420 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) {
+ 421 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0) {
+ 422 : /* LCOV_EXCL_START */
+ 423 : goto bail;
+ 424 : /* LCOV_EXCL_STOP */
+ 425 : }
+ 426 : }
+ 427 :
+ 428 1 : if (tommy_hashdyn_count(&hashdyn) != 0) {
+ 429 : /* LCOV_EXCL_START */
+ 430 : goto bail;
+ 431 : /* LCOV_EXCL_STOP */
+ 432 : }
+ 433 :
+ 434 1 : tommy_hashdyn_done(&hashdyn);
+ 435 :
+ 436 1 : tommy_tree_init(&tree, tommy_test_compare);
437 :
- 438 2 : return;
- 439 : bail:
- 440 : /* LCOV_EXCL_START */
- 441 : log_fatal("Failed tommy test\n");
- 442 : exit(EXIT_FAILURE);
- 443 : /* LCOV_EXCL_STOP */
- 444 : }
- 445 :
- 446 1 : void selftest(void)
- 447 : {
- 448 1 : log_tag("selftest:\n");
- 449 1 : log_flush();
- 450 :
- 451 1 : msg_progress("Self test...\n");
- 452 :
- 453 : /* large file check */
- 454 : if (sizeof(off_t) < sizeof(uint64_t)) {
- 455 : /* LCOV_EXCL_START */
- 456 : log_fatal("Missing support for large files\n");
- 457 : exit(EXIT_FAILURE);
- 458 : /* LCOV_EXCL_STOP */
- 459 : }
- 460 :
- 461 1 : test_hash();
- 462 1 : test_crc32c();
- 463 1 : test_tommy();
- 464 1 : if (raid_selftest() != 0) {
- 465 : /* LCOV_EXCL_START */
- 466 : log_fatal("Failed SELF test\n");
- 467 : exit(EXIT_FAILURE);
- 468 : /* LCOV_EXCL_STOP */
- 469 : }
- 470 1 : if (raid_test_sort() != 0) {
- 471 : /* LCOV_EXCL_START */
- 472 : log_fatal("Failed SORT test\n");
- 473 : exit(EXIT_FAILURE);
- 474 : /* LCOV_EXCL_STOP */
- 475 : }
- 476 1 : if (raid_test_insert() != 0) {
- 477 : /* LCOV_EXCL_START */
- 478 : log_fatal("Failed INSERT test\n");
- 479 : exit(EXIT_FAILURE);
- 480 : /* LCOV_EXCL_STOP */
- 481 : }
- 482 1 : if (raid_test_combo() != 0) {
- 483 : /* LCOV_EXCL_START */
- 484 : log_fatal("Failed COMBO test\n");
- 485 : exit(EXIT_FAILURE);
- 486 : /* LCOV_EXCL_STOP */
- 487 : }
- 488 1 : if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) {
+ 438 257 : for (i = 0; i < TOMMY_SIZE; ++i)
+ 439 256 : tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i+1));
+ 440 :
+ 441 : /* try to insert a duplicate, count should not change */
+ 442 1 : if (tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)1) != (void*)1) {
+ 443 : /* LCOV_EXCL_START */
+ 444 : goto bail;
+ 445 : /* LCOV_EXCL_STOP */
+ 446 : }
+ 447 1 : if (tommy_tree_count(&tree) != TOMMY_SIZE) {
+ 448 : /* LCOV_EXCL_START */
+ 449 : goto bail;
+ 450 : /* LCOV_EXCL_STOP */
+ 451 : }
+ 452 1 : if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node)) {
+ 453 : /* LCOV_EXCL_START */
+ 454 : goto bail;
+ 455 : /* LCOV_EXCL_STOP */
+ 456 : }
+ 457 1 : if (tommy_tree_search(&tree, (void*)1) != (void*)1) {
+ 458 : /* LCOV_EXCL_START */
+ 459 : goto bail;
+ 460 : /* LCOV_EXCL_STOP */
+ 461 : }
+ 462 1 : if (tommy_tree_search(&tree, (void*)-1) != 0) {
+ 463 : /* LCOV_EXCL_START */
+ 464 : goto bail;
+ 465 : /* LCOV_EXCL_STOP */
+ 466 : }
+ 467 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1) {
+ 468 : /* LCOV_EXCL_START */
+ 469 : goto bail;
+ 470 : /* LCOV_EXCL_STOP */
+ 471 : }
+ 472 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0) {
+ 473 : /* LCOV_EXCL_START */
+ 474 : goto bail;
+ 475 : /* LCOV_EXCL_STOP */
+ 476 : }
+ 477 :
+ 478 1 : tommy_test_foreach_count = 0;
+ 479 1 : tommy_tree_foreach(&tree, tommy_test_foreach);
+ 480 1 : if (tommy_test_foreach_count != TOMMY_SIZE) {
+ 481 : /* LCOV_EXCL_START */
+ 482 : goto bail;
+ 483 : /* LCOV_EXCL_STOP */
+ 484 : }
+ 485 :
+ 486 1 : tommy_test_foreach_count = 0;
+ 487 1 : tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count);
+ 488 1 : if (tommy_test_foreach_count != TOMMY_SIZE) {
489 : /* LCOV_EXCL_START */
- 490 : log_fatal("Failed GEN Vandermonde test\n");
- 491 : exit(EXIT_FAILURE);
- 492 : /* LCOV_EXCL_STOP */
- 493 : }
- 494 1 : if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) {
- 495 : /* LCOV_EXCL_START */
- 496 : log_fatal("Failed REC Vandermonde test\n");
- 497 : exit(EXIT_FAILURE);
- 498 : /* LCOV_EXCL_STOP */
- 499 : }
- 500 1 : if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) {
- 501 : /* LCOV_EXCL_START */
- 502 : log_fatal("Failed GEN Cauchy test\n");
- 503 : exit(EXIT_FAILURE);
- 504 : /* LCOV_EXCL_STOP */
- 505 : }
- 506 1 : if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) {
- 507 : /* LCOV_EXCL_START */
- 508 : log_fatal("Failed REC Cauchy test\n");
- 509 : exit(EXIT_FAILURE);
- 510 : /* LCOV_EXCL_STOP */
+ 490 : goto bail;
+ 491 : /* LCOV_EXCL_STOP */
+ 492 : }
+ 493 :
+ 494 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i)
+ 495 128 : tommy_tree_remove_existing(&tree, &node[i]);
+ 496 :
+ 497 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) {
+ 498 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) != 0) {
+ 499 : /* LCOV_EXCL_START */
+ 500 : goto bail;
+ 501 : /* LCOV_EXCL_STOP */
+ 502 : }
+ 503 : }
+ 504 :
+ 505 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) {
+ 506 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) == 0) {
+ 507 : /* LCOV_EXCL_START */
+ 508 : goto bail;
+ 509 : /* LCOV_EXCL_STOP */
+ 510 : }
511 : }
- 512 1 : if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) {
- 513 : /* LCOV_EXCL_START */
- 514 : log_fatal("Failed GEN Cauchy test sigle data disk\n");
- 515 : exit(EXIT_FAILURE);
+ 512 :
+ 513 1 : if (tommy_tree_count(&tree) != 0) {
+ 514 : /* LCOV_EXCL_START */
+ 515 : goto bail;
516 : /* LCOV_EXCL_STOP */
517 : }
- 518 1 : }
- 519 :
+ 518 :
+ 519 2 : return;
+ 520 : bail:
+ 521 : /* LCOV_EXCL_START */
+ 522 : log_fatal("Failed tommy test\n");
+ 523 : exit(EXIT_FAILURE);
+ 524 : /* LCOV_EXCL_STOP */
+ 525 : }
+ 526 :
+ 527 1 : void selftest(void)
+ 528 : {
+ 529 1 : log_tag("selftest:\n");
+ 530 1 : log_flush();
+ 531 :
+ 532 1 : msg_progress("Self test...\n");
+ 533 :
+ 534 : /* large file check */
+ 535 : if (sizeof(off_t) < sizeof(uint64_t)) {
+ 536 : /* LCOV_EXCL_START */
+ 537 : log_fatal("Missing support for large files\n");
+ 538 : exit(EXIT_FAILURE);
+ 539 : /* LCOV_EXCL_STOP */
+ 540 : }
+ 541 :
+ 542 1 : test_hash();
+ 543 1 : test_crc32c();
+ 544 1 : test_tommy();
+ 545 1 : if (raid_selftest() != 0) {
+ 546 : /* LCOV_EXCL_START */
+ 547 : log_fatal("Failed SELF test\n");
+ 548 : exit(EXIT_FAILURE);
+ 549 : /* LCOV_EXCL_STOP */
+ 550 : }
+ 551 1 : if (raid_test_sort() != 0) {
+ 552 : /* LCOV_EXCL_START */
+ 553 : log_fatal("Failed SORT test\n");
+ 554 : exit(EXIT_FAILURE);
+ 555 : /* LCOV_EXCL_STOP */
+ 556 : }
+ 557 1 : if (raid_test_insert() != 0) {
+ 558 : /* LCOV_EXCL_START */
+ 559 : log_fatal("Failed INSERT test\n");
+ 560 : exit(EXIT_FAILURE);
+ 561 : /* LCOV_EXCL_STOP */
+ 562 : }
+ 563 1 : if (raid_test_combo() != 0) {
+ 564 : /* LCOV_EXCL_START */
+ 565 : log_fatal("Failed COMBO test\n");
+ 566 : exit(EXIT_FAILURE);
+ 567 : /* LCOV_EXCL_STOP */
+ 568 : }
+ 569 1 : if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) {
+ 570 : /* LCOV_EXCL_START */
+ 571 : log_fatal("Failed GEN Vandermonde test\n");
+ 572 : exit(EXIT_FAILURE);
+ 573 : /* LCOV_EXCL_STOP */
+ 574 : }
+ 575 1 : if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) {
+ 576 : /* LCOV_EXCL_START */
+ 577 : log_fatal("Failed REC Vandermonde test\n");
+ 578 : exit(EXIT_FAILURE);
+ 579 : /* LCOV_EXCL_STOP */
+ 580 : }
+ 581 1 : if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) {
+ 582 : /* LCOV_EXCL_START */
+ 583 : log_fatal("Failed GEN Cauchy test\n");
+ 584 : exit(EXIT_FAILURE);
+ 585 : /* LCOV_EXCL_STOP */
+ 586 : }
+ 587 1 : if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) {
+ 588 : /* LCOV_EXCL_START */
+ 589 : log_fatal("Failed REC Cauchy test\n");
+ 590 : exit(EXIT_FAILURE);
+ 591 : /* LCOV_EXCL_STOP */
+ 592 : }
+ 593 1 : if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) {
+ 594 : /* LCOV_EXCL_START */
+ 595 : log_fatal("Failed GEN Cauchy test sigle data disk\n");
+ 596 : exit(EXIT_FAILURE);
+ 597 : /* LCOV_EXCL_STOP */
+ 598 : }
+ 599 1 : }
+ 600 :
diff --git a/cov/cmdline/snapraid.c.func-sort-c.html b/cov/cmdline/snapraid.c.func-sort-c.html
index 8601a790..1a663a69 100644
--- a/cov/cmdline/snapraid.c.func-sort-c.html
+++ b/cov/cmdline/snapraid.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -60,28 +60,28 @@
Hit count  |
- | main |
- 257 |
+ main |
+ 265 |
| config |
- 257 |
+ 265 |
| log_open |
- 247 |
+ 255 |
| log_close |
- 225 |
+ 233 |
| memory |
- 222 |
+ 230 |
- | signal_init |
- 208 |
+ signal_init |
+ 216 |
| version |
diff --git a/cov/cmdline/snapraid.c.func.html b/cov/cmdline/snapraid.c.func.html
index 5c3cd1ce..ccd27a1f 100644
--- a/cov/cmdline/snapraid.c.func.html
+++ b/cov/cmdline/snapraid.c.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -61,27 +61,27 @@
| config |
- 257 |
+ 265 |
| log_close |
- 225 |
+ 233 |
| log_open |
- 247 |
+ 255 |
- | main |
- 257 |
+ main |
+ 265 |
| memory |
- 222 |
+ 230 |
- | signal_init |
- 208 |
+ signal_init |
+ 216 |
| usage |
diff --git a/cov/cmdline/snapraid.c.gcov.html b/cov/cmdline/snapraid.c.gcov.html
index 9efa5568..7343ea06 100644
--- a/cov/cmdline/snapraid.c.gcov.html
+++ b/cov/cmdline/snapraid.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -103,13 +103,13 @@
41 1 : printf("\n");
42 1 : printf("Commands:\n");
43 1 : printf(" status Print the status of the array\n");
- 44 1 : printf(" diff Show the changes that needs to be syncronized\n");
- 45 1 : printf(" sync Syncronize the state of the array\n");
+ 44 1 : printf(" diff Show the changes that needs to be synchronized\n");
+ 45 1 : printf(" sync Synchronize the state of the array\n");
46 1 : printf(" scrub Scrub the array\n");
47 1 : printf(" list List the array content\n");
48 1 : printf(" dup Find duplicate files\n");
- 49 1 : printf(" up Spinup the array\n");
- 50 1 : printf(" down Spindown the array\n");
+ 49 1 : printf(" up Spin-up the array\n");
+ 50 1 : printf(" down Spin-down the array\n");
51 1 : printf(" smart SMART attributes of the array\n");
52 1 : printf(" pool Create or update the virtual view of the array\n");
53 1 : printf(" check Check the array\n");
@@ -126,34 +126,34 @@
64 1 : printf(" " SWITCH_GETOPT_LONG("-i, --import DIR ", "-i") " Import deleted files\n");
65 1 : printf(" " SWITCH_GETOPT_LONG("-l, --log FILE ", "-l") " Log file. Default none\n");
66 1 : printf(" " SWITCH_GETOPT_LONG("-a, --audit-only ", "-a") " Check only file data and not parity\n");
- 67 1 : printf(" " SWITCH_GETOPT_LONG("-h, --pre-hash ", "-h") " Pre hash all the new data\n");
- 68 1 : printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force synching of files that get zero size\n");
- 69 1 : printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force synching of disks that get empty\n");
+ 67 1 : printf(" " SWITCH_GETOPT_LONG("-h, --pre-hash ", "-h") " Pre-hash all the new data\n");
+ 68 1 : printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force syncing of files that get zero size\n");
+ 69 1 : printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force syncing of disks that get empty\n");
70 1 : printf(" " SWITCH_GETOPT_LONG("-U, --force-uuid ", "-U") " Force commands on disks with uuid changed\n");
- 71 1 : printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands with unaccessible/shared disks\n");
+ 71 1 : printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands with inaccessible/shared disks\n");
72 1 : printf(" " SWITCH_GETOPT_LONG("-N, --force-nocopy ", "-N") " Force commands disabling the copy detection\n");
73 1 : printf(" " SWITCH_GETOPT_LONG("-F, --force-full ", "-F") " Force commands requiring a full sync\n");
74 1 : printf(" " SWITCH_GETOPT_LONG("-v, --verbose ", "-v") " Verbose\n");
75 1 : }
76 :
- 77 222 : void memory(void)
+ 77 230 : void memory(void)
78 : {
- 79 222 : log_tag("memory:used:%" PRIu64 "\n", (uint64_t)malloc_counter());
+ 79 230 : log_tag("memory:used:%" PRIu64 "\n", (uint64_t)malloc_counter_get());
80 :
81 : /* size of the block */
- 82 222 : log_tag("memory:block:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_block)));
- 83 222 : log_tag("memory:chunk:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_chunk)));
- 84 222 : log_tag("memory:file:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_file)));
- 85 222 : log_tag("memory:link:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_link)));
- 86 222 : log_tag("memory:dir:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_dir)));
+ 82 230 : log_tag("memory:block:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_block)));
+ 83 230 : log_tag("memory:chunk:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_chunk)));
+ 84 230 : log_tag("memory:file:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_file)));
+ 85 230 : log_tag("memory:link:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_link)));
+ 86 230 : log_tag("memory:dir:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_dir)));
87 :
- 88 222 : msg_progress("Using %u MiB of memory.\n", (unsigned)(malloc_counter() / (1024 * 1024)));
- 89 222 : }
+ 88 230 : msg_progress("Using %u MiB of memory.\n", (unsigned)(malloc_counter_get() / (1024 * 1024)));
+ 89 230 : }
90 :
91 : /****************************************************************************/
92 : /* log */
93 :
- 94 247 : void log_open(const char* file)
+ 94 255 : void log_open(const char* file)
95 : {
96 : char path[PATH_MAX];
97 : const char* mode;
@@ -163,8 +163,8 @@
101 : struct tm* tm;
102 :
103 : /* leave stdlog at 0 if not specified */
- 104 247 : if (file == 0)
- 105 343 : return;
+ 104 255 : if (file == 0)
+ 105 359 : return;
106 :
107 77 : t = time(0);
108 77 : tm = localtime(&t);
@@ -237,9 +237,9 @@
175 : }
176 : }
177 :
- 178 225 : void log_close(const char* file)
+ 178 233 : void log_close(const char* file)
179 : {
- 180 225 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) {
+ 180 233 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) {
181 74 : if (fclose(stdlog) != 0) {
182 : /* LCOV_EXCL_START */
183 : log_fatal("Error closing the log file '%s'. %s.\n", file, strerror(errno));
@@ -248,13 +248,13 @@
186 : }
187 : }
188 :
- 189 225 : stdlog = 0;
- 190 225 : }
+ 189 233 : stdlog = 0;
+ 190 233 : }
191 :
192 : /****************************************************************************/
193 : /* config */
194 :
- 195 257 : void config(char* conf, size_t conf_size, const char* argv0)
+ 195 265 : void config(char* conf, size_t conf_size, const char* argv0)
196 : {
197 : #ifdef _WIN32
198 : char* slash;
@@ -271,9 +271,9 @@
209 : #else
210 : (void)argv0;
211 :
- 212 257 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf");
+ 212 265 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf");
213 : #endif
- 214 257 : }
+ 214 265 : }
215 :
216 : /****************************************************************************/
217 : /* main */
@@ -307,1052 +307,1084 @@
245 : #define OPT_TEST_FORCE_AUTOSAVE_AT 283
246 : #define OPT_TEST_FAKE_DEVICE 284
247 : #define OPT_TEST_EXPECT_NEED_SYNC 285
- 248 :
- 249 : #if HAVE_GETOPT_LONG
- 250 : struct option long_options[] = {
- 251 : { "conf", 1, 0, 'c' },
- 252 : { "filter", 1, 0, 'f' },
- 253 : { "filter-disk", 1, 0, 'd' },
- 254 : { "filter-missing", 0, 0, 'm' },
- 255 : { "filter-error", 0, 0, 'e' },
- 256 : { "percentage", 1, 0, 'p' }, /* legacy name for --plan */
- 257 : { "plan", 1, 0, 'p' },
- 258 : { "older-than", 1, 0, 'o' },
- 259 : { "start", 1, 0, 'S' },
- 260 : { "count", 1, 0, 'B' },
- 261 : { "error-limit", 1, 0, 'L' },
- 262 : { "import", 1, 0, 'i' },
- 263 : { "log", 1, 0, 'l' },
- 264 : { "force-zero", 0, 0, 'Z' },
- 265 : { "force-empty", 0, 0, 'E' },
- 266 : { "force-uuid", 0, 0, 'U' },
- 267 : { "force-device", 0, 0, 'D' },
- 268 : { "force-nocopy", 0, 0, 'N' },
- 269 : { "force-full", 0, 0, 'F' },
- 270 : { "audit-only", 0, 0, 'a' },
- 271 : { "pre-hash", 0, 0, 'h' },
- 272 : { "speed-test", 0, 0, 'T' }, /* undocumented speed test command */
- 273 : { "gen-conf", 1, 0, 'C' },
- 274 : { "verbose", 0, 0, 'v' },
- 275 : { "quiet", 0, 0, 'q' }, /* undocumented quiet option */
- 276 : { "gui", 0, 0, 'G' }, /* undocumented GUI interface option */
- 277 : { "help", 0, 0, 'H' },
- 278 : { "version", 0, 0, 'V' },
- 279 :
- 280 : /* The following are test specific options, DO NOT USE! */
- 281 :
- 282 : /* After syncing, do not write the new content file */
- 283 : { "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC },
- 284 :
- 285 : /* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */
- 286 : { "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE },
- 287 :
- 288 : /* Exit with failure if after check/fix there ARE NOT recoverable errors. */
- 289 : { "test-expect-recoverable", 0, 0, OPT_TEST_EXPECT_RECOVERABLE },
- 290 :
- 291 : /* Skip the initial self test */
- 292 : { "test-skip-self", 0, 0, OPT_TEST_SKIP_SELF },
- 293 :
- 294 : /* Skip the initial sign check when reading the content file */
- 295 : { "test-skip-sign", 0, 0, OPT_TEST_SKIP_SIGN },
- 296 :
- 297 : /* Skip the fallocate() when growing the parity files */
- 298 : { "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE },
- 299 :
- 300 : /* Skip the sequential hint when reading files */
- 301 : { "test-skip-sequential", 0, 0, OPT_TEST_SKIP_SEQUENTIAL },
- 302 :
- 303 : /* Skip the device check */
- 304 : { "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE },
- 305 :
- 306 : /* Force Murmur3 hash */
- 307 : { "test-force-murmur3", 0, 0, OPT_TEST_FORCE_MURMUR3 },
- 308 :
- 309 : /* Force Spooky2 hash */
- 310 : { "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 },
- 311 :
- 312 : /* Skip the use of lock file */
- 313 : { "test-skip-lock", 0, 0, OPT_TEST_SKIP_LOCK },
- 314 :
- 315 : /* Force a sort order for files */
- 316 : { "test-force-order-physical", 0, 0, OPT_TEST_FORCE_ORDER_PHYSICAL },
- 317 : { "test-force-order-inode", 0, 0, OPT_TEST_FORCE_ORDER_INODE },
- 318 : { "test-force-order-alpha", 0, 0, OPT_TEST_FORCE_ORDER_ALPHA },
- 319 : { "test-force-order-dir", 0, 0, OPT_TEST_FORCE_ORDER_DIR },
- 320 :
- 321 : /* Force scrub of the specified number of blocks */
- 322 : { "test-force-scrub-at", 1, 0, OPT_TEST_FORCE_SCRUB_AT },
- 323 :
- 324 : /* Force scrub of all the even blocks. This is really for testing, don't try it */
- 325 : { "test-force-scrub-even", 0, 0, OPT_TEST_FORCE_SCRUB_EVEN },
- 326 :
- 327 : /* Force write of the content file even if no modification is done */
- 328 : { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE },
- 329 :
- 330 : /* Relax the checks done at the content file */
- 331 : { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK },
- 332 :
- 333 : /* Skip the parity access */
- 334 : { "test-skip-parity-access", 0, 0, OPT_TEST_SKIP_PARITY_ACCESS },
- 335 :
- 336 : /* Exit generic failure */
- 337 : { "test-expect-failure", 0, 0, OPT_TEST_EXPECT_FAILURE },
- 338 :
- 339 : /* Exit generic need sync */
- 340 : { "test-expect-need-sync", 0, 0, OPT_TEST_EXPECT_NEED_SYNC },
- 341 :
- 342 : /* Run some command after loading the state and before the command */
- 343 : { "test-run", 1, 0, OPT_TEST_RUN },
- 344 :
- 345 : /* Use the FindFirst/Next approach in Windows to list files */
- 346 : { "test-force-scan-winfind", 0, 0, OPT_TEST_FORCE_SCAN_WINFIND },
- 347 :
- 348 : /* Alternative import working by data */
- 349 : { "test-import-content", 1, 0, OPT_TEST_IMPORT_CONTENT },
- 350 :
- 351 : /* Force immediate progress state update */
- 352 : { "test-force-progress", 0, 0, OPT_TEST_FORCE_PROGRESS },
- 353 :
- 354 : /* Skip the disk access */
- 355 : { "test-skip-disk-access", 0, 0, OPT_TEST_SKIP_DISK_ACCESS },
- 356 :
- 357 : /* Force autosave at the specified block */
- 358 : { "test-force-autosave-at", 1, 0, OPT_TEST_FORCE_AUTOSAVE_AT },
- 359 :
- 360 : /* Fake device data */
- 361 : { "test-fake-device", 0, 0, OPT_TEST_FAKE_DEVICE },
- 362 :
- 363 : { 0, 0, 0, 0 }
- 364 : };
- 365 : #endif
+ 248 : #define OPT_NO_WARNINGS 286
+ 249 : #define OPT_TEST_FAKE_UUID 287
+ 250 : #define OPT_TEST_MATCH_FIRST_UUID 288
+ 251 : #define OPT_TEST_FORCE_PARITY_UPDATE 289
+ 252 :
+ 253 : #if HAVE_GETOPT_LONG
+ 254 : struct option long_options[] = {
+ 255 : { "conf", 1, 0, 'c' },
+ 256 : { "filter", 1, 0, 'f' },
+ 257 : { "filter-disk", 1, 0, 'd' },
+ 258 : { "filter-missing", 0, 0, 'm' },
+ 259 : { "filter-error", 0, 0, 'e' },
+ 260 : { "percentage", 1, 0, 'p' }, /* legacy name for --plan */
+ 261 : { "plan", 1, 0, 'p' },
+ 262 : { "older-than", 1, 0, 'o' },
+ 263 : { "start", 1, 0, 'S' },
+ 264 : { "count", 1, 0, 'B' },
+ 265 : { "error-limit", 1, 0, 'L' },
+ 266 : { "import", 1, 0, 'i' },
+ 267 : { "log", 1, 0, 'l' },
+ 268 : { "force-zero", 0, 0, 'Z' },
+ 269 : { "force-empty", 0, 0, 'E' },
+ 270 : { "force-uuid", 0, 0, 'U' },
+ 271 : { "force-device", 0, 0, 'D' },
+ 272 : { "force-nocopy", 0, 0, 'N' },
+ 273 : { "force-full", 0, 0, 'F' },
+ 274 : { "audit-only", 0, 0, 'a' },
+ 275 : { "pre-hash", 0, 0, 'h' },
+ 276 : { "speed-test", 0, 0, 'T' }, /* undocumented speed test command */
+ 277 : { "gen-conf", 1, 0, 'C' },
+ 278 : { "verbose", 0, 0, 'v' },
+ 279 : { "quiet", 0, 0, 'q' }, /* undocumented quiet option */
+ 280 : { "gui", 0, 0, 'G' }, /* undocumented GUI interface option */
+ 281 : { "help", 0, 0, 'H' },
+ 282 : { "version", 0, 0, 'V' },
+ 283 :
+ 284 : /* The following are test specific options, DO NOT USE! */
+ 285 :
+ 286 : /* After syncing, do not write the new content file */
+ 287 : { "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC },
+ 288 :
+ 289 : /* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */
+ 290 : { "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE },
+ 291 :
+ 292 : /* Exit with failure if after check/fix there ARE NOT recoverable errors. */
+ 293 : { "test-expect-recoverable", 0, 0, OPT_TEST_EXPECT_RECOVERABLE },
+ 294 :
+ 295 : /* Skip the initial self test */
+ 296 : { "test-skip-self", 0, 0, OPT_TEST_SKIP_SELF },
+ 297 :
+ 298 : /* Skip the initial sign check when reading the content file */
+ 299 : { "test-skip-sign", 0, 0, OPT_TEST_SKIP_SIGN },
+ 300 :
+ 301 : /* Skip the fallocate() when growing the parity files */
+ 302 : { "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE },
+ 303 :
+ 304 : /* Skip the sequential hint when reading files */
+ 305 : { "test-skip-sequential", 0, 0, OPT_TEST_SKIP_SEQUENTIAL },
+ 306 :
+ 307 : /* Skip the device check */
+ 308 : { "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE },
+ 309 :
+ 310 : /* Force Murmur3 hash */
+ 311 : { "test-force-murmur3", 0, 0, OPT_TEST_FORCE_MURMUR3 },
+ 312 :
+ 313 : /* Force Spooky2 hash */
+ 314 : { "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 },
+ 315 :
+ 316 : /* Skip the use of lock file */
+ 317 : { "test-skip-lock", 0, 0, OPT_TEST_SKIP_LOCK },
+ 318 :
+ 319 : /* Force a sort order for files */
+ 320 : { "test-force-order-physical", 0, 0, OPT_TEST_FORCE_ORDER_PHYSICAL },
+ 321 : { "test-force-order-inode", 0, 0, OPT_TEST_FORCE_ORDER_INODE },
+ 322 : { "test-force-order-alpha", 0, 0, OPT_TEST_FORCE_ORDER_ALPHA },
+ 323 : { "test-force-order-dir", 0, 0, OPT_TEST_FORCE_ORDER_DIR },
+ 324 :
+ 325 : /* Force scrub of the specified number of blocks */
+ 326 : { "test-force-scrub-at", 1, 0, OPT_TEST_FORCE_SCRUB_AT },
+ 327 :
+ 328 : /* Force scrub of all the even blocks. This is really for testing, don't try it */
+ 329 : { "test-force-scrub-even", 0, 0, OPT_TEST_FORCE_SCRUB_EVEN },
+ 330 :
+ 331 : /* Force write of the content file even if no modification is done */
+ 332 : { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE },
+ 333 :
+ 334 : /* Relax the checks done at the content file */
+ 335 : { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK },
+ 336 :
+ 337 : /* Skip the parity access */
+ 338 : { "test-skip-parity-access", 0, 0, OPT_TEST_SKIP_PARITY_ACCESS },
+ 339 :
+ 340 : /* Exit generic failure */
+ 341 : { "test-expect-failure", 0, 0, OPT_TEST_EXPECT_FAILURE },
+ 342 :
+ 343 : /* Exit generic need sync */
+ 344 : { "test-expect-need-sync", 0, 0, OPT_TEST_EXPECT_NEED_SYNC },
+ 345 :
+ 346 : /* Run some command after loading the state and before the command */
+ 347 : { "test-run", 1, 0, OPT_TEST_RUN },
+ 348 :
+ 349 : /* Use the FindFirst/Next approach in Windows to list files */
+ 350 : { "test-force-scan-winfind", 0, 0, OPT_TEST_FORCE_SCAN_WINFIND },
+ 351 :
+ 352 : /* Alternative import working by data */
+ 353 : { "test-import-content", 1, 0, OPT_TEST_IMPORT_CONTENT },
+ 354 :
+ 355 : /* Force immediate progress state update */
+ 356 : { "test-force-progress", 0, 0, OPT_TEST_FORCE_PROGRESS },
+ 357 :
+ 358 : /* Skip the disk access */
+ 359 : { "test-skip-disk-access", 0, 0, OPT_TEST_SKIP_DISK_ACCESS },
+ 360 :
+ 361 : /* Force autosave at the specified block */
+ 362 : { "test-force-autosave-at", 1, 0, OPT_TEST_FORCE_AUTOSAVE_AT },
+ 363 :
+ 364 : /* Fake device data */
+ 365 : { "test-fake-device", 0, 0, OPT_TEST_FAKE_DEVICE },
366 :
- 367 : #define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFahTC:vqHVG"
- 368 :
- 369 : volatile int global_interrupt = 0;
- 370 :
- 371 : /* LCOV_EXCL_START */
- 372 : void signal_handler(int signum)
- 373 : {
- 374 : (void)signum;
+ 367 : /* Disable annoying warnings */
+ 368 : { "no-warnings", 0, 0, OPT_NO_WARNINGS },
+ 369 :
+ 370 : /* Fake UUID */
+ 371 : { "test-fake-uuid", 0, 0, OPT_TEST_FAKE_UUID },
+ 372 :
+ 373 : /* Match first UUID */
+ 374 : { "test-match-first-uuid", 0, 0, OPT_TEST_MATCH_FIRST_UUID },
375 :
- 376 : /* report the request of interruption */
- 377 : global_interrupt = 1;
- 378 : }
- 379 : /* LCOV_EXCL_STOP */
- 380 :
- 381 208 : void signal_init(void)
- 382 : {
- 383 : #if HAVE_SIGACTION
- 384 : struct sigaction sa;
- 385 :
- 386 208 : sa.sa_handler = signal_handler;
- 387 208 : sigemptyset(&sa.sa_mask);
- 388 :
- 389 : /* use the SA_RESTART to automatically restart interrupted system calls */
- 390 208 : sa.sa_flags = SA_RESTART;
+ 376 : /* Force parity update even if all the data is not changed */
+ 377 : { "test-force-parity-update", 0, 0, OPT_TEST_FORCE_PARITY_UPDATE },
+ 378 :
+ 379 : { 0, 0, 0, 0 }
+ 380 : };
+ 381 : #endif
+ 382 :
+ 383 : #define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFahTC:vqHVG"
+ 384 :
+ 385 : volatile int global_interrupt = 0;
+ 386 :
+ 387 : /* LCOV_EXCL_START */
+ 388 : void signal_handler(int signum)
+ 389 : {
+ 390 : (void)signum;
391 :
- 392 208 : sigaction(SIGHUP, &sa, 0);
- 393 208 : sigaction(SIGTERM, &sa, 0);
- 394 208 : sigaction(SIGINT, &sa, 0);
- 395 208 : sigaction(SIGQUIT, &sa, 0);
- 396 : #else
- 397 : signal(SIGINT, signal_handler);
- 398 : #endif
- 399 208 : }
- 400 :
- 401 : #define OPERATION_DIFF 0
- 402 : #define OPERATION_SYNC 1
- 403 : #define OPERATION_CHECK 2
- 404 : #define OPERATION_FIX 3
- 405 : #define OPERATION_DRY 4
- 406 : #define OPERATION_DUP 5
- 407 : #define OPERATION_LIST 6
- 408 : #define OPERATION_POOL 7
- 409 : #define OPERATION_REHASH 8
- 410 : #define OPERATION_SCRUB 9
- 411 : #define OPERATION_STATUS 10
- 412 : #define OPERATION_REWRITE 11
- 413 : #define OPERATION_READ 12
- 414 : #define OPERATION_NANO 13
- 415 : #define OPERATION_SPINUP 14
- 416 : #define OPERATION_SPINDOWN 15
- 417 : #define OPERATION_DEVICES 16
- 418 : #define OPERATION_SMART 17
- 419 :
- 420 257 : int main(int argc, char* argv[])
- 421 : {
- 422 : int c;
- 423 : struct snapraid_option opt;
- 424 : char conf[PATH_MAX];
- 425 : struct snapraid_state state;
- 426 : int operation;
- 427 : block_off_t blockstart;
- 428 : block_off_t blockcount;
- 429 : int ret;
- 430 : tommy_list filterlist_file;
- 431 : tommy_list filterlist_disk;
- 432 : int filter_missing;
- 433 : int filter_error;
- 434 : int plan;
- 435 : int olderthan;
- 436 : char* e;
- 437 : const char* command;
- 438 : const char* import_timestamp;
- 439 : const char* import_content;
- 440 : const char* log_file;
- 441 : int lock;
- 442 : const char* gen_conf;
- 443 : const char* run;
- 444 : int speedtest;
- 445 : int period;
- 446 : time_t t;
- 447 : struct tm* tm;
- 448 : int i;
- 449 :
- 450 : /* defaults */
- 451 257 : config(conf, sizeof(conf), argv[0]);
- 452 257 : memset(&opt, 0, sizeof(opt));
- 453 257 : opt.io_error_limit = 100;
- 454 257 : blockstart = 0;
- 455 257 : blockcount = 0;
- 456 257 : tommy_list_init(&filterlist_file);
- 457 257 : tommy_list_init(&filterlist_disk);
- 458 257 : period = 1000;
- 459 257 : filter_missing = 0;
- 460 257 : filter_error = 0;
- 461 257 : plan = SCRUB_AUTO;
- 462 257 : olderthan = SCRUB_AUTO;
- 463 257 : import_timestamp = 0;
- 464 257 : import_content = 0;
- 465 257 : log_file = 0;
- 466 257 : lock = 0;
- 467 257 : gen_conf = 0;
- 468 257 : speedtest = 0;
- 469 257 : run = 0;
- 470 :
- 471 257 : opterr = 0;
- 472 2722 : while ((c =
- 473 : #if HAVE_GETOPT_LONG
- 474 : getopt_long(argc, argv, OPTIONS, long_options, 0))
- 475 : #else
- 476 : getopt(argc, argv, OPTIONS))
- 477 : #endif
- 478 : != EOF) {
- 479 2213 : switch (c) {
- 480 : case 'c' :
- 481 250 : pathimport(conf, sizeof(conf), optarg);
- 482 250 : break;
- 483 : case 'f' : {
- 484 6 : struct snapraid_filter* filter = filter_alloc_file(1, optarg);
- 485 6 : if (!filter) {
- 486 : /* LCOV_EXCL_START */
- 487 : log_fatal("Invalid filter specification '%s'\n", optarg);
- 488 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
- 489 : exit(EXIT_FAILURE);
- 490 : /* LCOV_EXCL_STOP */
- 491 : }
- 492 3 : tommy_list_insert_tail(&filterlist_file, &filter->node, filter);
- 493 3 : } break;
- 494 : case 'd' : {
- 495 8 : struct snapraid_filter* filter = filter_alloc_disk(1, optarg);
- 496 8 : if (!filter) {
- 497 : /* LCOV_EXCL_START */
- 498 : log_fatal("Invalid filter specification '%s'\n", optarg);
- 499 : exit(EXIT_FAILURE);
- 500 : /* LCOV_EXCL_STOP */
- 501 : }
- 502 8 : tommy_list_insert_tail(&filterlist_disk, &filter->node, filter);
- 503 8 : } break;
- 504 : case 'm' :
- 505 2 : filter_missing = 1;
- 506 2 : opt.expected_missing = 1;
- 507 2 : break;
- 508 : case 'e' :
- 509 : /* when processing only error, we filter both files and blocks */
- 510 : /* and we apply fixes only to synced ones */
- 511 2 : filter_error = 1;
- 512 2 : opt.badonly = 1;
- 513 2 : opt.syncedonly = 1;
- 514 2 : break;
- 515 : case 'p' :
- 516 5 : if (strcmp(optarg, "bad") == 0) {
- 517 1 : plan = SCRUB_BAD;
- 518 4 : } else if (strcmp(optarg, "new") == 0) {
- 519 1 : plan = SCRUB_NEW;
- 520 3 : } else if (strcmp(optarg, "full") == 0) {
- 521 2 : plan = SCRUB_FULL;
- 522 : } else {
- 523 1 : plan = strtoul(optarg, &e, 10);
- 524 1 : if (!e || *e || plan > 100) {
- 525 : /* LCOV_EXCL_START */
- 526 : log_fatal("Invalid plan/percentage '%s'\n", optarg);
- 527 : exit(EXIT_FAILURE);
- 528 : /* LCOV_EXCL_STOP */
- 529 : }
- 530 : }
- 531 5 : break;
- 532 : case 'o' :
- 533 1 : olderthan = strtoul(optarg, &e, 10);
- 534 1 : if (!e || *e || olderthan > 1000) {
- 535 : /* LCOV_EXCL_START */
- 536 : log_fatal("Invalid number of days '%s'\n", optarg);
- 537 : exit(EXIT_FAILURE);
- 538 : /* LCOV_EXCL_STOP */
- 539 : }
- 540 1 : break;
- 541 : case 'S' :
- 542 2 : blockstart = strtoul(optarg, &e, 0);
- 543 2 : if (!e || *e) {
- 544 : /* LCOV_EXCL_START */
- 545 : log_fatal("Invalid start position '%s'\n", optarg);
- 546 : exit(EXIT_FAILURE);
- 547 : /* LCOV_EXCL_STOP */
- 548 : }
- 549 2 : break;
- 550 : case 'B' :
- 551 7 : blockcount = strtoul(optarg, &e, 0);
- 552 7 : if (!e || *e) {
- 553 : /* LCOV_EXCL_START */
- 554 : log_fatal("Invalid count number '%s'\n", optarg);
- 555 : exit(EXIT_FAILURE);
- 556 : /* LCOV_EXCL_STOP */
- 557 : }
- 558 7 : break;
- 559 : case 'L' :
- 560 0 : opt.io_error_limit = strtoul(optarg, &e, 0);
- 561 0 : if (!e || *e) {
- 562 : /* LCOV_EXCL_START */
- 563 : log_fatal("Invalid error limit number '%s'\n", optarg);
- 564 : exit(EXIT_FAILURE);
- 565 : /* LCOV_EXCL_STOP */
- 566 : }
- 567 0 : break;
- 568 : case 'i' :
- 569 1 : if (import_timestamp) {
- 570 : /* LCOV_EXCL_START */
- 571 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp);
- 572 : exit(EXIT_FAILURE);
- 573 : /* LCOV_EXCL_STOP */
- 574 : }
- 575 1 : import_timestamp = optarg;
- 576 1 : break;
- 577 : case OPT_TEST_IMPORT_CONTENT :
- 578 1 : if (import_content) {
- 579 : /* LCOV_EXCL_START */
- 580 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content);
- 581 : exit(EXIT_FAILURE);
- 582 : /* LCOV_EXCL_STOP */
- 583 : }
- 584 1 : import_content = optarg;
- 585 1 : break;
- 586 : case 'l' :
- 587 77 : if (log_file) {
- 588 : /* LCOV_EXCL_START */
- 589 : log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file);
- 590 : exit(EXIT_FAILURE);
- 591 : /* LCOV_EXCL_STOP */
- 592 : }
- 593 77 : log_file = optarg;
- 594 77 : break;
- 595 : case 'Z' :
- 596 0 : opt.force_zero = 1;
- 597 0 : break;
- 598 : case 'E' :
- 599 5 : opt.force_empty = 1;
- 600 5 : break;
- 601 : case 'U' :
- 602 0 : opt.force_uuid = 1;
- 603 0 : break;
- 604 : case 'D' :
- 605 1 : opt.force_device = 1;
- 606 1 : break;
- 607 : case 'N' :
- 608 1 : opt.force_nocopy = 1;
- 609 1 : break;
- 610 : case 'F' :
- 611 1 : opt.force_full = 1;
- 612 1 : break;
- 613 : case 'a' :
- 614 6 : opt.auditonly = 1;
- 615 6 : break;
- 616 : case 'h' :
- 617 7 : opt.prehash = 1;
- 618 7 : break;
- 619 : case 'v' :
- 620 23 : ++msg_level;
- 621 23 : break;
- 622 : case 'q' :
- 623 681 : --msg_level;
- 624 681 : break;
- 625 : case 'G' :
- 626 23 : opt.gui = 1;
- 627 23 : break;
- 628 : case 'H' :
- 629 1 : usage();
- 630 1 : exit(EXIT_SUCCESS);
- 631 : case 'V' :
- 632 1 : version();
- 633 1 : exit(EXIT_SUCCESS);
- 634 : case 'T' :
- 635 4 : speedtest = 1;
- 636 4 : break;
- 637 : case 'C' :
- 638 1 : gen_conf = optarg;
- 639 1 : break;
- 640 : case OPT_TEST_KILL_AFTER_SYNC :
- 641 9 : opt.kill_after_sync = 1;
- 642 9 : break;
- 643 : case OPT_TEST_EXPECT_UNRECOVERABLE :
- 644 13 : opt.expect_unrecoverable = 1;
- 645 13 : break;
- 646 : case OPT_TEST_EXPECT_RECOVERABLE :
- 647 23 : opt.expect_recoverable = 1;
- 648 23 : break;
- 649 : case OPT_TEST_SKIP_SELF :
- 650 250 : opt.skip_self = 1;
- 651 250 : break;
- 652 : case OPT_TEST_SKIP_SIGN :
- 653 0 : opt.skip_sign = 1;
- 654 0 : break;
- 655 : case OPT_TEST_SKIP_FALLOCATE :
- 656 1 : opt.skip_fallocate = 1;
- 657 1 : break;
- 658 : case OPT_TEST_SKIP_SEQUENTIAL :
- 659 1 : opt.skip_sequential = 1;
- 660 1 : break;
- 661 : case OPT_TEST_SKIP_DEVICE :
- 662 257 : opt.skip_device = 1;
- 663 257 : period = 50; /* reduce period of the speed test */
- 664 257 : break;
- 665 : case OPT_TEST_SKIP_CONTENT_CHECK :
- 666 0 : opt.skip_content_check = 1;
- 667 0 : break;
- 668 : case OPT_TEST_SKIP_PARITY_ACCESS :
- 669 0 : opt.skip_parity_access = 1;
+ 392 : /* report the request of interruption */
+ 393 : global_interrupt = 1;
+ 394 : }
+ 395 : /* LCOV_EXCL_STOP */
+ 396 :
+ 397 216 : void signal_init(void)
+ 398 : {
+ 399 : #if HAVE_SIGACTION
+ 400 : struct sigaction sa;
+ 401 :
+ 402 216 : sa.sa_handler = signal_handler;
+ 403 216 : sigemptyset(&sa.sa_mask);
+ 404 :
+ 405 : /* use the SA_RESTART to automatically restart interrupted system calls */
+ 406 216 : sa.sa_flags = SA_RESTART;
+ 407 :
+ 408 216 : sigaction(SIGHUP, &sa, 0);
+ 409 216 : sigaction(SIGTERM, &sa, 0);
+ 410 216 : sigaction(SIGINT, &sa, 0);
+ 411 216 : sigaction(SIGQUIT, &sa, 0);
+ 412 : #else
+ 413 : signal(SIGINT, signal_handler);
+ 414 : #endif
+ 415 216 : }
+ 416 :
+ 417 : #define OPERATION_DIFF 0
+ 418 : #define OPERATION_SYNC 1
+ 419 : #define OPERATION_CHECK 2
+ 420 : #define OPERATION_FIX 3
+ 421 : #define OPERATION_DRY 4
+ 422 : #define OPERATION_DUP 5
+ 423 : #define OPERATION_LIST 6
+ 424 : #define OPERATION_POOL 7
+ 425 : #define OPERATION_REHASH 8
+ 426 : #define OPERATION_SCRUB 9
+ 427 : #define OPERATION_STATUS 10
+ 428 : #define OPERATION_REWRITE 11
+ 429 : #define OPERATION_READ 12
+ 430 : #define OPERATION_NANO 13
+ 431 : #define OPERATION_SPINUP 14
+ 432 : #define OPERATION_SPINDOWN 15
+ 433 : #define OPERATION_DEVICES 16
+ 434 : #define OPERATION_SMART 17
+ 435 :
+ 436 265 : int main(int argc, char* argv[])
+ 437 : {
+ 438 : int c;
+ 439 : struct snapraid_option opt;
+ 440 : char conf[PATH_MAX];
+ 441 : struct snapraid_state state;
+ 442 : int operation;
+ 443 : block_off_t blockstart;
+ 444 : block_off_t blockcount;
+ 445 : int ret;
+ 446 : tommy_list filterlist_file;
+ 447 : tommy_list filterlist_disk;
+ 448 : int filter_missing;
+ 449 : int filter_error;
+ 450 : int plan;
+ 451 : int olderthan;
+ 452 : char* e;
+ 453 : const char* command;
+ 454 : const char* import_timestamp;
+ 455 : const char* import_content;
+ 456 : const char* log_file;
+ 457 : int lock;
+ 458 : const char* gen_conf;
+ 459 : const char* run;
+ 460 : int speedtest;
+ 461 : int period;
+ 462 : time_t t;
+ 463 : struct tm* tm;
+ 464 : int i;
+ 465 :
+ 466 : /* defaults */
+ 467 265 : config(conf, sizeof(conf), argv[0]);
+ 468 265 : memset(&opt, 0, sizeof(opt));
+ 469 265 : opt.io_error_limit = 100;
+ 470 265 : blockstart = 0;
+ 471 265 : blockcount = 0;
+ 472 265 : tommy_list_init(&filterlist_file);
+ 473 265 : tommy_list_init(&filterlist_disk);
+ 474 265 : period = 1000;
+ 475 265 : filter_missing = 0;
+ 476 265 : filter_error = 0;
+ 477 265 : plan = SCRUB_AUTO;
+ 478 265 : olderthan = SCRUB_AUTO;
+ 479 265 : import_timestamp = 0;
+ 480 265 : import_content = 0;
+ 481 265 : log_file = 0;
+ 482 265 : lock = 0;
+ 483 265 : gen_conf = 0;
+ 484 265 : speedtest = 0;
+ 485 265 : run = 0;
+ 486 :
+ 487 265 : opterr = 0;
+ 488 2809 : while ((c =
+ 489 : #if HAVE_GETOPT_LONG
+ 490 : getopt_long(argc, argv, OPTIONS, long_options, 0))
+ 491 : #else
+ 492 : getopt(argc, argv, OPTIONS))
+ 493 : #endif
+ 494 : != EOF) {
+ 495 2284 : switch (c) {
+ 496 : case 'c' :
+ 497 258 : pathimport(conf, sizeof(conf), optarg);
+ 498 258 : break;
+ 499 : case 'f' : {
+ 500 6 : struct snapraid_filter* filter = filter_alloc_file(1, optarg);
+ 501 6 : if (!filter) {
+ 502 : /* LCOV_EXCL_START */
+ 503 : log_fatal("Invalid filter specification '%s'\n", optarg);
+ 504 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
+ 505 : exit(EXIT_FAILURE);
+ 506 : /* LCOV_EXCL_STOP */
+ 507 : }
+ 508 3 : tommy_list_insert_tail(&filterlist_file, &filter->node, filter);
+ 509 3 : } break;
+ 510 : case 'd' : {
+ 511 8 : struct snapraid_filter* filter = filter_alloc_disk(1, optarg);
+ 512 8 : if (!filter) {
+ 513 : /* LCOV_EXCL_START */
+ 514 : log_fatal("Invalid filter specification '%s'\n", optarg);
+ 515 : exit(EXIT_FAILURE);
+ 516 : /* LCOV_EXCL_STOP */
+ 517 : }
+ 518 8 : tommy_list_insert_tail(&filterlist_disk, &filter->node, filter);
+ 519 8 : } break;
+ 520 : case 'm' :
+ 521 2 : filter_missing = 1;
+ 522 2 : opt.expected_missing = 1;
+ 523 2 : break;
+ 524 : case 'e' :
+ 525 : /* when processing only error, we filter both files and blocks */
+ 526 : /* and we apply fixes only to synced ones */
+ 527 2 : filter_error = 1;
+ 528 2 : opt.badonly = 1;
+ 529 2 : opt.syncedonly = 1;
+ 530 2 : break;
+ 531 : case 'p' :
+ 532 5 : if (strcmp(optarg, "bad") == 0) {
+ 533 1 : plan = SCRUB_BAD;
+ 534 4 : } else if (strcmp(optarg, "new") == 0) {
+ 535 1 : plan = SCRUB_NEW;
+ 536 3 : } else if (strcmp(optarg, "full") == 0) {
+ 537 2 : plan = SCRUB_FULL;
+ 538 : } else {
+ 539 1 : plan = strtoul(optarg, &e, 10);
+ 540 1 : if (!e || *e || plan > 100) {
+ 541 : /* LCOV_EXCL_START */
+ 542 : log_fatal("Invalid plan/percentage '%s'\n", optarg);
+ 543 : exit(EXIT_FAILURE);
+ 544 : /* LCOV_EXCL_STOP */
+ 545 : }
+ 546 : }
+ 547 5 : break;
+ 548 : case 'o' :
+ 549 1 : olderthan = strtoul(optarg, &e, 10);
+ 550 1 : if (!e || *e || olderthan > 1000) {
+ 551 : /* LCOV_EXCL_START */
+ 552 : log_fatal("Invalid number of days '%s'\n", optarg);
+ 553 : exit(EXIT_FAILURE);
+ 554 : /* LCOV_EXCL_STOP */
+ 555 : }
+ 556 1 : break;
+ 557 : case 'S' :
+ 558 2 : blockstart = strtoul(optarg, &e, 0);
+ 559 2 : if (!e || *e) {
+ 560 : /* LCOV_EXCL_START */
+ 561 : log_fatal("Invalid start position '%s'\n", optarg);
+ 562 : exit(EXIT_FAILURE);
+ 563 : /* LCOV_EXCL_STOP */
+ 564 : }
+ 565 2 : break;
+ 566 : case 'B' :
+ 567 7 : blockcount = strtoul(optarg, &e, 0);
+ 568 7 : if (!e || *e) {
+ 569 : /* LCOV_EXCL_START */
+ 570 : log_fatal("Invalid count number '%s'\n", optarg);
+ 571 : exit(EXIT_FAILURE);
+ 572 : /* LCOV_EXCL_STOP */
+ 573 : }
+ 574 7 : break;
+ 575 : case 'L' :
+ 576 0 : opt.io_error_limit = strtoul(optarg, &e, 0);
+ 577 0 : if (!e || *e) {
+ 578 : /* LCOV_EXCL_START */
+ 579 : log_fatal("Invalid error limit number '%s'\n", optarg);
+ 580 : exit(EXIT_FAILURE);
+ 581 : /* LCOV_EXCL_STOP */
+ 582 : }
+ 583 0 : break;
+ 584 : case 'i' :
+ 585 1 : if (import_timestamp) {
+ 586 : /* LCOV_EXCL_START */
+ 587 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp);
+ 588 : exit(EXIT_FAILURE);
+ 589 : /* LCOV_EXCL_STOP */
+ 590 : }
+ 591 1 : import_timestamp = optarg;
+ 592 1 : break;
+ 593 : case OPT_TEST_IMPORT_CONTENT :
+ 594 1 : if (import_content) {
+ 595 : /* LCOV_EXCL_START */
+ 596 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content);
+ 597 : exit(EXIT_FAILURE);
+ 598 : /* LCOV_EXCL_STOP */
+ 599 : }
+ 600 1 : import_content = optarg;
+ 601 1 : break;
+ 602 : case 'l' :
+ 603 77 : if (log_file) {
+ 604 : /* LCOV_EXCL_START */
+ 605 : log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file);
+ 606 : exit(EXIT_FAILURE);
+ 607 : /* LCOV_EXCL_STOP */
+ 608 : }
+ 609 77 : log_file = optarg;
+ 610 77 : break;
+ 611 : case 'Z' :
+ 612 0 : opt.force_zero = 1;
+ 613 0 : break;
+ 614 : case 'E' :
+ 615 6 : opt.force_empty = 1;
+ 616 6 : break;
+ 617 : case 'U' :
+ 618 0 : opt.force_uuid = 1;
+ 619 0 : break;
+ 620 : case 'D' :
+ 621 1 : opt.force_device = 1;
+ 622 1 : break;
+ 623 : case 'N' :
+ 624 1 : opt.force_nocopy = 1;
+ 625 1 : break;
+ 626 : case 'F' :
+ 627 2 : opt.force_full = 1;
+ 628 2 : break;
+ 629 : case 'a' :
+ 630 6 : opt.auditonly = 1;
+ 631 6 : break;
+ 632 : case 'h' :
+ 633 7 : opt.prehash = 1;
+ 634 7 : break;
+ 635 : case 'v' :
+ 636 23 : ++msg_level;
+ 637 23 : break;
+ 638 : case 'q' :
+ 639 705 : --msg_level;
+ 640 705 : break;
+ 641 : case 'G' :
+ 642 23 : opt.gui = 1;
+ 643 23 : break;
+ 644 : case 'H' :
+ 645 1 : usage();
+ 646 1 : exit(EXIT_SUCCESS);
+ 647 : case 'V' :
+ 648 1 : version();
+ 649 1 : exit(EXIT_SUCCESS);
+ 650 : case 'T' :
+ 651 4 : speedtest = 1;
+ 652 4 : break;
+ 653 : case 'C' :
+ 654 1 : gen_conf = optarg;
+ 655 1 : break;
+ 656 : case OPT_TEST_KILL_AFTER_SYNC :
+ 657 10 : opt.kill_after_sync = 1;
+ 658 10 : break;
+ 659 : case OPT_TEST_EXPECT_UNRECOVERABLE :
+ 660 13 : opt.expect_unrecoverable = 1;
+ 661 13 : break;
+ 662 : case OPT_TEST_EXPECT_RECOVERABLE :
+ 663 23 : opt.expect_recoverable = 1;
+ 664 23 : break;
+ 665 : case OPT_TEST_SKIP_SELF :
+ 666 258 : opt.skip_self = 1;
+ 667 258 : break;
+ 668 : case OPT_TEST_SKIP_SIGN :
+ 669 0 : opt.skip_sign = 1;
670 0 : break;
- 671 : case OPT_TEST_SKIP_DISK_ACCESS :
- 672 0 : opt.skip_disk_access = 1;
- 673 0 : break;
- 674 : case OPT_TEST_FORCE_MURMUR3 :
- 675 1 : opt.force_murmur3 = 1;
+ 671 : case OPT_TEST_SKIP_FALLOCATE :
+ 672 1 : opt.skip_fallocate = 1;
+ 673 1 : break;
+ 674 : case OPT_TEST_SKIP_SEQUENTIAL :
+ 675 1 : opt.skip_sequential = 1;
676 1 : break;
- 677 : case OPT_TEST_FORCE_SPOOKY2 :
- 678 1 : opt.force_spooky2 = 1;
- 679 1 : break;
- 680 : case OPT_TEST_SKIP_LOCK :
- 681 0 : opt.skip_lock = 1;
- 682 0 : break;
- 683 : case OPT_TEST_FORCE_ORDER_PHYSICAL :
- 684 2 : opt.force_order = SORT_PHYSICAL;
- 685 2 : break;
- 686 : case OPT_TEST_FORCE_ORDER_INODE :
- 687 0 : opt.force_order = SORT_INODE;
- 688 0 : break;
- 689 : case OPT_TEST_FORCE_ORDER_ALPHA :
- 690 248 : opt.force_order = SORT_ALPHA;
- 691 248 : break;
- 692 : case OPT_TEST_FORCE_ORDER_DIR :
- 693 0 : opt.force_order = SORT_DIR;
- 694 0 : break;
- 695 : case OPT_TEST_FORCE_SCRUB_AT :
- 696 4 : opt.force_scrub_at = atoi(optarg);
- 697 4 : break;
- 698 : case OPT_TEST_FORCE_SCRUB_EVEN :
- 699 1 : opt.force_scrub_even = 1;
- 700 1 : break;
- 701 : case OPT_TEST_FORCE_CONTENT_WRITE :
- 702 0 : opt.force_content_write = 1;
- 703 0 : break;
- 704 : case OPT_TEST_EXPECT_FAILURE :
- 705 : /* invert the exit codes */
- 706 19 : exit_success = 1;
- 707 19 : exit_failure = 0;
- 708 19 : break;
- 709 : case OPT_TEST_EXPECT_NEED_SYNC :
- 710 : /* invert the exit codes */
- 711 6 : exit_success = 1;
- 712 6 : exit_sync_needed = 0;
- 713 6 : break;
- 714 : case OPT_TEST_RUN :
- 715 10 : run = optarg;
- 716 10 : break;
- 717 : case OPT_TEST_FORCE_SCAN_WINFIND :
- 718 0 : opt.force_scan_winfind = 1;
+ 677 : case OPT_TEST_SKIP_DEVICE :
+ 678 265 : opt.skip_device = 1;
+ 679 265 : period = 50; /* reduce period of the speed test */
+ 680 265 : break;
+ 681 : case OPT_TEST_SKIP_CONTENT_CHECK :
+ 682 0 : opt.skip_content_check = 1;
+ 683 0 : break;
+ 684 : case OPT_TEST_SKIP_PARITY_ACCESS :
+ 685 0 : opt.skip_parity_access = 1;
+ 686 0 : break;
+ 687 : case OPT_TEST_SKIP_DISK_ACCESS :
+ 688 0 : opt.skip_disk_access = 1;
+ 689 0 : break;
+ 690 : case OPT_TEST_FORCE_MURMUR3 :
+ 691 1 : opt.force_murmur3 = 1;
+ 692 1 : break;
+ 693 : case OPT_TEST_FORCE_SPOOKY2 :
+ 694 1 : opt.force_spooky2 = 1;
+ 695 1 : break;
+ 696 : case OPT_TEST_SKIP_LOCK :
+ 697 0 : opt.skip_lock = 1;
+ 698 0 : break;
+ 699 : case OPT_TEST_FORCE_ORDER_PHYSICAL :
+ 700 2 : opt.force_order = SORT_PHYSICAL;
+ 701 2 : break;
+ 702 : case OPT_TEST_FORCE_ORDER_INODE :
+ 703 0 : opt.force_order = SORT_INODE;
+ 704 0 : break;
+ 705 : case OPT_TEST_FORCE_ORDER_ALPHA :
+ 706 256 : opt.force_order = SORT_ALPHA;
+ 707 256 : break;
+ 708 : case OPT_TEST_FORCE_ORDER_DIR :
+ 709 0 : opt.force_order = SORT_DIR;
+ 710 0 : break;
+ 711 : case OPT_TEST_FORCE_SCRUB_AT :
+ 712 4 : opt.force_scrub_at = atoi(optarg);
+ 713 4 : break;
+ 714 : case OPT_TEST_FORCE_SCRUB_EVEN :
+ 715 1 : opt.force_scrub_even = 1;
+ 716 1 : break;
+ 717 : case OPT_TEST_FORCE_CONTENT_WRITE :
+ 718 0 : opt.force_content_write = 1;
719 0 : break;
- 720 : case OPT_TEST_FORCE_PROGRESS :
- 721 248 : opt.force_progress = 1;
- 722 248 : break;
- 723 : case OPT_TEST_FORCE_AUTOSAVE_AT :
- 724 1 : opt.force_autosave_at = atoi(optarg);
- 725 1 : break;
- 726 : case OPT_TEST_FAKE_DEVICE :
- 727 1 : opt.fake_device = 1;
- 728 1 : break;
- 729 : default :
- 730 : /* LCOV_EXCL_START */
- 731 : log_fatal("Unknown option '%c'\n", (char)c);
- 732 : exit(EXIT_FAILURE);
- 733 : /* LCOV_EXCL_STOP */
- 734 : }
- 735 : }
- 736 :
- 737 252 : os_init(opt.force_scan_winfind);
- 738 252 : raid_init();
- 739 252 : crc32c_init();
- 740 :
- 741 252 : if (speedtest != 0) {
- 742 4 : speed(period);
- 743 4 : os_done();
- 744 4 : exit(EXIT_SUCCESS);
- 745 : }
- 746 :
- 747 248 : if (gen_conf != 0) {
- 748 1 : generate_configuration(gen_conf);
- 749 1 : os_done();
- 750 1 : exit(EXIT_SUCCESS);
- 751 : }
- 752 :
- 753 247 : if (optind + 1 != argc) {
- 754 : /* LCOV_EXCL_START */
- 755 : usage();
- 756 : exit(EXIT_FAILURE);
- 757 : /* LCOV_EXCL_STOP */
- 758 : }
- 759 :
- 760 247 : command = argv[optind];
- 761 247 : if (strcmp(command, "diff") == 0) {
- 762 7 : operation = OPERATION_DIFF;
- 763 240 : } else if (strcmp(argv[optind], "sync") == 0) {
- 764 74 : operation = OPERATION_SYNC;
- 765 166 : } else if (strcmp(argv[optind], "check") == 0) {
- 766 75 : operation = OPERATION_CHECK;
- 767 91 : } else if (strcmp(argv[optind], "fix") == 0) {
- 768 46 : operation = OPERATION_FIX;
- 769 45 : } else if (strcmp(argv[optind], "test-dry") == 0) {
- 770 2 : operation = OPERATION_DRY;
- 771 43 : } else if (strcmp(argv[optind], "dup") == 0) {
- 772 3 : operation = OPERATION_DUP;
- 773 40 : } else if (strcmp(argv[optind], "list") == 0) {
- 774 3 : operation = OPERATION_LIST;
- 775 37 : } else if (strcmp(argv[optind], "pool") == 0) {
- 776 3 : operation = OPERATION_POOL;
- 777 34 : } else if (strcmp(argv[optind], "rehash") == 0) {
- 778 1 : operation = OPERATION_REHASH;
- 779 33 : } else if (strcmp(argv[optind], "scrub") == 0) {
- 780 11 : operation = OPERATION_SCRUB;
- 781 22 : } else if (strcmp(argv[optind], "status") == 0) {
- 782 14 : operation = OPERATION_STATUS;
- 783 8 : } else if (strcmp(argv[optind], "test-rewrite") == 0) {
- 784 1 : operation = OPERATION_REWRITE;
- 785 7 : } else if (strcmp(argv[optind], "test-read") == 0) {
- 786 1 : operation = OPERATION_READ;
- 787 6 : } else if (strcmp(argv[optind], "test-nano") == 0) {
- 788 1 : operation = OPERATION_NANO;
- 789 5 : } else if (strcmp(argv[optind], "up") == 0) {
- 790 1 : operation = OPERATION_SPINUP;
- 791 4 : } else if (strcmp(argv[optind], "down") == 0) {
- 792 1 : operation = OPERATION_SPINDOWN;
- 793 3 : } else if (strcmp(argv[optind], "devices") == 0) {
- 794 1 : operation = OPERATION_DEVICES;
- 795 2 : } else if (strcmp(argv[optind], "smart") == 0) {
- 796 2 : operation = OPERATION_SMART;
- 797 : } else {
- 798 : /* LCOV_EXCL_START */
- 799 : log_fatal("Unknown command '%s'\n", argv[optind]);
- 800 : exit(EXIT_FAILURE);
- 801 : /* LCOV_EXCL_STOP */
- 802 : }
- 803 :
- 804 : /* check options compatibility */
- 805 247 : switch (operation) {
- 806 : case OPERATION_CHECK :
- 807 75 : break;
- 808 : default :
- 809 172 : if (opt.auditonly) {
- 810 : /* LCOV_EXCL_START */
- 811 : log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command);
- 812 : exit(EXIT_FAILURE);
- 813 : /* LCOV_EXCL_STOP */
- 814 : }
- 815 : }
- 816 :
- 817 247 : switch (operation) {
- 818 : case OPERATION_FIX :
- 819 46 : break;
- 820 : default :
- 821 201 : if (opt.force_device) {
- 822 : /* LCOV_EXCL_START */
- 823 : log_fatal("You cannot use -D, --force-device with the '%s' command\n", command);
- 824 : exit(EXIT_FAILURE);
- 825 : /* LCOV_EXCL_STOP */
- 826 : }
- 827 : }
- 828 :
- 829 247 : switch (operation) {
- 830 : case OPERATION_SYNC :
- 831 : case OPERATION_CHECK :
- 832 : case OPERATION_FIX :
- 833 195 : break;
- 834 : default :
- 835 52 : if (opt.force_nocopy) {
- 836 : /* LCOV_EXCL_START */
- 837 : log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command);
- 838 : exit(EXIT_FAILURE);
- 839 : /* LCOV_EXCL_STOP */
- 840 : }
- 841 : }
- 842 :
- 843 247 : switch (operation) {
- 844 : case OPERATION_SYNC :
- 845 74 : break;
- 846 : default :
- 847 173 : if (opt.prehash) {
- 848 : /* LCOV_EXCL_START */
- 849 : log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command);
- 850 : exit(EXIT_FAILURE);
- 851 : /* LCOV_EXCL_STOP */
- 852 : }
- 853 :
- 854 173 : if (opt.force_full) {
- 855 : /* LCOV_EXCL_START */
- 856 : log_fatal("You cannot use -F, --force-full with the '%s' command\n", command);
- 857 : exit(EXIT_FAILURE);
- 858 : /* LCOV_EXCL_STOP */
- 859 : }
- 860 : }
- 861 :
- 862 247 : if (opt.force_full && opt.force_nocopy) {
- 863 : /* LCOV_EXCL_START */
- 864 : log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n");
- 865 : exit(EXIT_FAILURE);
- 866 : /* LCOV_EXCL_STOP */
- 867 : }
- 868 :
- 869 247 : if (opt.prehash && opt.force_nocopy) {
- 870 : /* LCOV_EXCL_START */
- 871 : log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n");
- 872 : exit(EXIT_FAILURE);
- 873 : /* LCOV_EXCL_STOP */
- 874 : }
- 875 :
- 876 247 : switch (operation) {
- 877 : case OPERATION_CHECK :
- 878 : case OPERATION_FIX :
- 879 : case OPERATION_DRY :
- 880 123 : break;
- 881 : default :
- 882 124 : if (!tommy_list_empty(&filterlist_file)) {
+ 720 : case OPT_TEST_EXPECT_FAILURE :
+ 721 : /* invert the exit codes */
+ 722 19 : exit_success = 1;
+ 723 19 : exit_failure = 0;
+ 724 19 : break;
+ 725 : case OPT_TEST_EXPECT_NEED_SYNC :
+ 726 : /* invert the exit codes */
+ 727 6 : exit_success = 1;
+ 728 6 : exit_sync_needed = 0;
+ 729 6 : break;
+ 730 : case OPT_TEST_RUN :
+ 731 10 : run = optarg;
+ 732 10 : break;
+ 733 : case OPT_TEST_FORCE_SCAN_WINFIND :
+ 734 0 : opt.force_scan_winfind = 1;
+ 735 0 : break;
+ 736 : case OPT_TEST_FORCE_PROGRESS :
+ 737 256 : opt.force_progress = 1;
+ 738 256 : break;
+ 739 : case OPT_TEST_FORCE_AUTOSAVE_AT :
+ 740 1 : opt.force_autosave_at = atoi(optarg);
+ 741 1 : break;
+ 742 : case OPT_TEST_FAKE_DEVICE :
+ 743 1 : opt.fake_device = 1;
+ 744 1 : break;
+ 745 : case OPT_NO_WARNINGS :
+ 746 1 : opt.no_warnings = 1;
+ 747 1 : break;
+ 748 : case OPT_TEST_FAKE_UUID :
+ 749 1 : opt.fake_uuid = 2;
+ 750 1 : break;
+ 751 : case OPT_TEST_MATCH_FIRST_UUID :
+ 752 2 : opt.match_first_uuid = 1;
+ 753 2 : break;
+ 754 : case OPT_TEST_FORCE_PARITY_UPDATE :
+ 755 0 : opt.force_parity_update = 1;
+ 756 0 : break;
+ 757 : default :
+ 758 : /* LCOV_EXCL_START */
+ 759 : log_fatal("Unknown option '%c'\n", (char)c);
+ 760 : exit(EXIT_FAILURE);
+ 761 : /* LCOV_EXCL_STOP */
+ 762 : }
+ 763 : }
+ 764 :
+ 765 260 : os_init(opt.force_scan_winfind);
+ 766 260 : raid_init();
+ 767 260 : crc32c_init();
+ 768 :
+ 769 260 : if (speedtest != 0) {
+ 770 4 : speed(period);
+ 771 4 : os_done();
+ 772 4 : exit(EXIT_SUCCESS);
+ 773 : }
+ 774 :
+ 775 256 : if (gen_conf != 0) {
+ 776 1 : generate_configuration(gen_conf);
+ 777 1 : os_done();
+ 778 1 : exit(EXIT_SUCCESS);
+ 779 : }
+ 780 :
+ 781 255 : if (optind + 1 != argc) {
+ 782 : /* LCOV_EXCL_START */
+ 783 : usage();
+ 784 : exit(EXIT_FAILURE);
+ 785 : /* LCOV_EXCL_STOP */
+ 786 : }
+ 787 :
+ 788 255 : command = argv[optind];
+ 789 255 : if (strcmp(command, "diff") == 0) {
+ 790 7 : operation = OPERATION_DIFF;
+ 791 248 : } else if (strcmp(argv[optind], "sync") == 0) {
+ 792 82 : operation = OPERATION_SYNC;
+ 793 166 : } else if (strcmp(argv[optind], "check") == 0) {
+ 794 75 : operation = OPERATION_CHECK;
+ 795 91 : } else if (strcmp(argv[optind], "fix") == 0) {
+ 796 46 : operation = OPERATION_FIX;
+ 797 45 : } else if (strcmp(argv[optind], "test-dry") == 0) {
+ 798 2 : operation = OPERATION_DRY;
+ 799 43 : } else if (strcmp(argv[optind], "dup") == 0) {
+ 800 3 : operation = OPERATION_DUP;
+ 801 40 : } else if (strcmp(argv[optind], "list") == 0) {
+ 802 3 : operation = OPERATION_LIST;
+ 803 37 : } else if (strcmp(argv[optind], "pool") == 0) {
+ 804 3 : operation = OPERATION_POOL;
+ 805 34 : } else if (strcmp(argv[optind], "rehash") == 0) {
+ 806 1 : operation = OPERATION_REHASH;
+ 807 33 : } else if (strcmp(argv[optind], "scrub") == 0) {
+ 808 11 : operation = OPERATION_SCRUB;
+ 809 22 : } else if (strcmp(argv[optind], "status") == 0) {
+ 810 14 : operation = OPERATION_STATUS;
+ 811 8 : } else if (strcmp(argv[optind], "test-rewrite") == 0) {
+ 812 1 : operation = OPERATION_REWRITE;
+ 813 7 : } else if (strcmp(argv[optind], "test-read") == 0) {
+ 814 1 : operation = OPERATION_READ;
+ 815 6 : } else if (strcmp(argv[optind], "test-nano") == 0) {
+ 816 1 : operation = OPERATION_NANO;
+ 817 5 : } else if (strcmp(argv[optind], "up") == 0) {
+ 818 1 : operation = OPERATION_SPINUP;
+ 819 4 : } else if (strcmp(argv[optind], "down") == 0) {
+ 820 1 : operation = OPERATION_SPINDOWN;
+ 821 3 : } else if (strcmp(argv[optind], "devices") == 0) {
+ 822 1 : operation = OPERATION_DEVICES;
+ 823 2 : } else if (strcmp(argv[optind], "smart") == 0) {
+ 824 2 : operation = OPERATION_SMART;
+ 825 : } else {
+ 826 : /* LCOV_EXCL_START */
+ 827 : log_fatal("Unknown command '%s'\n", argv[optind]);
+ 828 : exit(EXIT_FAILURE);
+ 829 : /* LCOV_EXCL_STOP */
+ 830 : }
+ 831 :
+ 832 : /* check options compatibility */
+ 833 255 : switch (operation) {
+ 834 : case OPERATION_CHECK :
+ 835 75 : break;
+ 836 : default :
+ 837 180 : if (opt.auditonly) {
+ 838 : /* LCOV_EXCL_START */
+ 839 : log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command);
+ 840 : exit(EXIT_FAILURE);
+ 841 : /* LCOV_EXCL_STOP */
+ 842 : }
+ 843 : }
+ 844 :
+ 845 255 : switch (operation) {
+ 846 : case OPERATION_FIX :
+ 847 46 : break;
+ 848 : default :
+ 849 209 : if (opt.force_device) {
+ 850 : /* LCOV_EXCL_START */
+ 851 : log_fatal("You cannot use -D, --force-device with the '%s' command\n", command);
+ 852 : exit(EXIT_FAILURE);
+ 853 : /* LCOV_EXCL_STOP */
+ 854 : }
+ 855 : }
+ 856 :
+ 857 255 : switch (operation) {
+ 858 : case OPERATION_SYNC :
+ 859 : case OPERATION_CHECK :
+ 860 : case OPERATION_FIX :
+ 861 203 : break;
+ 862 : default :
+ 863 52 : if (opt.force_nocopy) {
+ 864 : /* LCOV_EXCL_START */
+ 865 : log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command);
+ 866 : exit(EXIT_FAILURE);
+ 867 : /* LCOV_EXCL_STOP */
+ 868 : }
+ 869 : }
+ 870 :
+ 871 255 : switch (operation) {
+ 872 : case OPERATION_SYNC :
+ 873 82 : break;
+ 874 : default :
+ 875 173 : if (opt.prehash) {
+ 876 : /* LCOV_EXCL_START */
+ 877 : log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command);
+ 878 : exit(EXIT_FAILURE);
+ 879 : /* LCOV_EXCL_STOP */
+ 880 : }
+ 881 :
+ 882 173 : if (opt.force_full) {
883 : /* LCOV_EXCL_START */
- 884 : log_fatal("You cannot use -f, --filter with the '%s' command\n", command);
+ 884 : log_fatal("You cannot use -F, --force-full with the '%s' command\n", command);
885 : exit(EXIT_FAILURE);
886 : /* LCOV_EXCL_STOP */
887 : }
- 888 124 : if (!tommy_list_empty(&filterlist_disk)) {
- 889 : /* LCOV_EXCL_START */
- 890 : log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command);
- 891 : exit(EXIT_FAILURE);
- 892 : /* LCOV_EXCL_STOP */
- 893 : }
- 894 124 : if (filter_missing != 0) {
- 895 : /* LCOV_EXCL_START */
- 896 : log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command);
- 897 : exit(EXIT_FAILURE);
- 898 : /* LCOV_EXCL_STOP */
- 899 : }
- 900 124 : if (filter_error != 0) {
- 901 : /* LCOV_EXCL_START */
- 902 : log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command);
- 903 : exit(EXIT_FAILURE);
- 904 : /* LCOV_EXCL_STOP */
- 905 : }
- 906 : }
- 907 :
- 908 : /* errors must be always fixed on all disks */
- 909 : /* becasue we don't keep the information on what disk is the error */
- 910 247 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) {
- 911 : /* LCOV_EXCL_START */
- 912 : log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n");
- 913 : exit(EXIT_FAILURE);
- 914 : /* LCOV_EXCL_STOP */
- 915 : }
- 916 :
- 917 247 : switch (operation) {
- 918 : case OPERATION_CHECK :
- 919 : case OPERATION_FIX :
- 920 121 : break;
- 921 : default :
- 922 126 : if (import_timestamp != 0 || import_content != 0) {
+ 888 : }
+ 889 :
+ 890 255 : if (opt.force_full && opt.force_nocopy) {
+ 891 : /* LCOV_EXCL_START */
+ 892 : log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n");
+ 893 : exit(EXIT_FAILURE);
+ 894 : /* LCOV_EXCL_STOP */
+ 895 : }
+ 896 :
+ 897 255 : if (opt.prehash && opt.force_nocopy) {
+ 898 : /* LCOV_EXCL_START */
+ 899 : log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n");
+ 900 : exit(EXIT_FAILURE);
+ 901 : /* LCOV_EXCL_STOP */
+ 902 : }
+ 903 :
+ 904 255 : switch (operation) {
+ 905 : case OPERATION_CHECK :
+ 906 : case OPERATION_FIX :
+ 907 : case OPERATION_DRY :
+ 908 123 : break;
+ 909 : default :
+ 910 132 : if (!tommy_list_empty(&filterlist_file)) {
+ 911 : /* LCOV_EXCL_START */
+ 912 : log_fatal("You cannot use -f, --filter with the '%s' command\n", command);
+ 913 : exit(EXIT_FAILURE);
+ 914 : /* LCOV_EXCL_STOP */
+ 915 : }
+ 916 132 : if (!tommy_list_empty(&filterlist_disk)) {
+ 917 : /* LCOV_EXCL_START */
+ 918 : log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command);
+ 919 : exit(EXIT_FAILURE);
+ 920 : /* LCOV_EXCL_STOP */
+ 921 : }
+ 922 132 : if (filter_missing != 0) {
923 : /* LCOV_EXCL_START */
- 924 : log_fatal("You cannot import with the '%s' command\n", command);
+ 924 : log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command);
925 : exit(EXIT_FAILURE);
926 : /* LCOV_EXCL_STOP */
927 : }
- 928 : }
- 929 :
- 930 247 : switch (operation) {
- 931 : case OPERATION_LIST :
- 932 : case OPERATION_DUP :
- 933 : case OPERATION_STATUS :
- 934 : case OPERATION_REWRITE :
- 935 : case OPERATION_READ :
- 936 : case OPERATION_REHASH :
- 937 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
- 938 : /* avoid to check and access data disks if not needed */
- 939 24 : opt.skip_disk_access = 1;
- 940 24 : break;
- 941 : }
- 942 :
- 943 247 : switch (operation) {
- 944 : case OPERATION_DIFF :
- 945 : case OPERATION_LIST :
- 946 : case OPERATION_DUP :
- 947 : case OPERATION_POOL :
- 948 : case OPERATION_STATUS :
- 949 : case OPERATION_REWRITE :
- 950 : case OPERATION_READ :
- 951 : case OPERATION_REHASH :
- 952 : case OPERATION_NANO :
- 953 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
- 954 : /* avoid to check and access parity disks if not needed */
- 955 35 : opt.skip_parity_access = 1;
- 956 35 : break;
- 957 : }
- 958 :
- 959 247 : switch (operation) {
- 960 : case OPERATION_FIX :
- 961 : case OPERATION_CHECK :
- 962 : /* avoid to stop processing if a content file is not accessible */
- 963 121 : opt.skip_content_access = 1;
- 964 121 : break;
- 965 : }
- 966 :
- 967 247 : switch (operation) {
- 968 : case OPERATION_DIFF :
- 969 : case OPERATION_LIST :
- 970 : case OPERATION_DUP :
- 971 : case OPERATION_POOL :
- 972 : case OPERATION_NANO :
- 973 : case OPERATION_SPINUP :
- 974 : case OPERATION_SPINDOWN :
- 975 : case OPERATION_DEVICES :
- 976 : case OPERATION_SMART :
- 977 22 : opt.skip_self = 1;
- 978 22 : break;
- 979 : }
- 980 :
- 981 247 : switch (operation) {
- 982 : case OPERATION_DEVICES :
- 983 : case OPERATION_SMART :
- 984 : /* we may need to use these commands during operations */
- 985 3 : opt.skip_lock = 1;
- 986 3 : break;
- 987 : }
- 988 :
- 989 : /* open the log file */
- 990 247 : log_open(log_file);
- 991 :
- 992 : /* print generic info into the log */
- 993 247 : t = time(0);
- 994 247 : tm = localtime(&t);
- 995 247 : log_tag("version:%s\n", PACKAGE_VERSION);
- 996 247 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t);
- 997 247 : if (tm) {
- 998 : char datetime[64];
- 999 247 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm);
- 1000 247 : log_tag("time:%s\n", datetime);
- 1001 : }
- 1002 247 : log_tag("command:%s\n", command);
- 1003 3274 : for (i = 0; i < argc; ++i)
- 1004 3027 : log_tag("argv:%u:%s\n", i, argv[i]);
- 1005 247 : log_flush();
- 1006 :
- 1007 247 : if (!opt.skip_self)
- 1008 1 : selftest();
- 1009 :
- 1010 247 : state_init(&state);
- 1011 :
- 1012 : /* read the configuration file */
- 1013 247 : state_config(&state, conf, command, &opt, &filterlist_disk);
- 1014 :
- 1015 : /* set the raid mode */
- 1016 246 : raid_mode(state.raid_mode);
- 1017 :
- 1018 : #if HAVE_LOCKFILE
- 1019 : /* create the lock file */
- 1020 246 : if (!opt.skip_lock && state.lockfile[0]) {
- 1021 243 : lock = lock_lock(state.lockfile);
- 1022 243 : if (lock == -1) {
- 1023 : /* LCOV_EXCL_START */
- 1024 : if (errno != EWOULDBLOCK) {
- 1025 : log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
- 1026 : } else {
- 1027 : log_fatal("The lock file '%s' is already locked!\n", state.lockfile);
- 1028 : log_fatal("SnapRAID is already in use!\n");
- 1029 : }
- 1030 : exit(EXIT_FAILURE);
- 1031 : /* LCOV_EXCL_STOP */
- 1032 : }
- 1033 : }
- 1034 : #else
- 1035 : (void)lock;
- 1036 : #endif
+ 928 132 : if (filter_error != 0) {
+ 929 : /* LCOV_EXCL_START */
+ 930 : log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command);
+ 931 : exit(EXIT_FAILURE);
+ 932 : /* LCOV_EXCL_STOP */
+ 933 : }
+ 934 : }
+ 935 :
+ 936 : /* errors must be always fixed on all disks */
+ 937 : /* because we don't keep the information on what disk is the error */
+ 938 255 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) {
+ 939 : /* LCOV_EXCL_START */
+ 940 : log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n");
+ 941 : exit(EXIT_FAILURE);
+ 942 : /* LCOV_EXCL_STOP */
+ 943 : }
+ 944 :
+ 945 255 : switch (operation) {
+ 946 : case OPERATION_CHECK :
+ 947 : case OPERATION_FIX :
+ 948 121 : break;
+ 949 : default :
+ 950 134 : if (import_timestamp != 0 || import_content != 0) {
+ 951 : /* LCOV_EXCL_START */
+ 952 : log_fatal("You cannot import with the '%s' command\n", command);
+ 953 : exit(EXIT_FAILURE);
+ 954 : /* LCOV_EXCL_STOP */
+ 955 : }
+ 956 : }
+ 957 :
+ 958 255 : switch (operation) {
+ 959 : case OPERATION_LIST :
+ 960 : case OPERATION_DUP :
+ 961 : case OPERATION_STATUS :
+ 962 : case OPERATION_REWRITE :
+ 963 : case OPERATION_READ :
+ 964 : case OPERATION_REHASH :
+ 965 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
+ 966 : /* avoid to check and access data disks if not needed */
+ 967 24 : opt.skip_disk_access = 1;
+ 968 24 : break;
+ 969 : }
+ 970 :
+ 971 255 : switch (operation) {
+ 972 : case OPERATION_DIFF :
+ 973 : case OPERATION_LIST :
+ 974 : case OPERATION_DUP :
+ 975 : case OPERATION_POOL :
+ 976 : case OPERATION_STATUS :
+ 977 : case OPERATION_REWRITE :
+ 978 : case OPERATION_READ :
+ 979 : case OPERATION_REHASH :
+ 980 : case OPERATION_NANO :
+ 981 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
+ 982 : /* avoid to check and access parity disks if not needed */
+ 983 35 : opt.skip_parity_access = 1;
+ 984 35 : break;
+ 985 : }
+ 986 :
+ 987 255 : switch (operation) {
+ 988 : case OPERATION_FIX :
+ 989 : case OPERATION_CHECK :
+ 990 : /* avoid to stop processing if a content file is not accessible */
+ 991 121 : opt.skip_content_access = 1;
+ 992 121 : break;
+ 993 : }
+ 994 :
+ 995 255 : switch (operation) {
+ 996 : case OPERATION_DIFF :
+ 997 : case OPERATION_LIST :
+ 998 : case OPERATION_DUP :
+ 999 : case OPERATION_POOL :
+ 1000 : case OPERATION_NANO :
+ 1001 : case OPERATION_SPINUP :
+ 1002 : case OPERATION_SPINDOWN :
+ 1003 : case OPERATION_DEVICES :
+ 1004 : case OPERATION_SMART :
+ 1005 22 : opt.skip_self = 1;
+ 1006 22 : break;
+ 1007 : }
+ 1008 :
+ 1009 255 : switch (operation) {
+ 1010 : case OPERATION_DEVICES :
+ 1011 : case OPERATION_SMART :
+ 1012 : /* we may need to use these commands during operations */
+ 1013 3 : opt.skip_lock = 1;
+ 1014 3 : break;
+ 1015 : }
+ 1016 :
+ 1017 : /* open the log file */
+ 1018 255 : log_open(log_file);
+ 1019 :
+ 1020 : /* print generic info into the log */
+ 1021 255 : t = time(0);
+ 1022 255 : tm = localtime(&t);
+ 1023 255 : log_tag("version:%s\n", PACKAGE_VERSION);
+ 1024 255 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t);
+ 1025 255 : if (tm) {
+ 1026 : char datetime[64];
+ 1027 255 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm);
+ 1028 255 : log_tag("time:%s\n", datetime);
+ 1029 : }
+ 1030 255 : log_tag("command:%s\n", command);
+ 1031 3377 : for (i = 0; i < argc; ++i)
+ 1032 3122 : log_tag("argv:%u:%s\n", i, argv[i]);
+ 1033 255 : log_flush();
+ 1034 :
+ 1035 255 : if (!opt.skip_self)
+ 1036 1 : selftest();
1037 :
- 1038 246 : if (operation == OPERATION_DIFF) {
- 1039 7 : state_read(&state);
- 1040 :
- 1041 7 : ret = state_diff(&state);
+ 1038 255 : state_init(&state);
+ 1039 :
+ 1040 : /* read the configuration file */
+ 1041 255 : state_config(&state, conf, command, &opt, &filterlist_disk);
1042 :
- 1043 : /* abort if sync needed */
- 1044 7 : if (ret > 0)
- 1045 6 : exit(EXIT_SYNC_NEEDED);
- 1046 239 : } else if (operation == OPERATION_SYNC) {
- 1047 :
- 1048 : /* in the next state read ensures to clear all the past hashes in case */
- 1049 : /* we are reading from an incomplete sync */
- 1050 : /* The undeterminated hash are only for CHG/DELETED blocks for which we don't */
- 1051 : /* know if the previous interrupted sync was able to update or not the parity. */
- 1052 : /* The sync process instead needs to trust this information because it's used */
- 1053 : /* to avoid to recompute the parity if all the input are equals as before. */
- 1054 :
- 1055 : /* In these cases we don't know if the old state is still the one */
- 1056 : /* stored inside the parity, because after an aborted sync, the parity */
- 1057 : /* may be or may be not have been updated with the data that may be now */
- 1058 : /* deleted. Then we reset the hash to a bogus value. */
- 1059 :
- 1060 : /* An example for CHG blocks is: */
- 1061 : /* - One file is added creating a CHG block with ZERO state */
- 1062 : /* - Sync aborted after updating the parity to the new state, */
- 1063 : /* but without saving the content file representing this new BLK state. */
- 1064 : /* - File is now deleted after the aborted sync */
- 1065 : /* - Sync again, deleting the blocks overt the CHG ones */
- 1066 : /* with the hash of CHG blocks not represeting the real parity state */
- 1067 :
- 1068 : /* An example for DELETED blocks is: */
- 1069 : /* - One file is deleted creating DELETED blocks */
- 1070 : /* - Sync aborted after, updating the parity to the new state, */
- 1071 : /* but without saving the content file representing this new EMPTY state. */
- 1072 : /* - Another file is added again over the DELETE ones */
- 1073 : /* with the hash of DELETED blocks not represeting the real parity state */
- 1074 74 : state.clear_past_hash = 1;
+ 1043 : /* set the raid mode */
+ 1044 254 : raid_mode(state.raid_mode);
+ 1045 :
+ 1046 : #if HAVE_LOCKFILE
+ 1047 : /* create the lock file */
+ 1048 254 : if (!opt.skip_lock && state.lockfile[0]) {
+ 1049 251 : lock = lock_lock(state.lockfile);
+ 1050 251 : if (lock == -1) {
+ 1051 : /* LCOV_EXCL_START */
+ 1052 : if (errno != EWOULDBLOCK) {
+ 1053 : log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
+ 1054 : } else {
+ 1055 : log_fatal("The lock file '%s' is already locked!\n", state.lockfile);
+ 1056 : log_fatal("SnapRAID is already in use!\n");
+ 1057 : }
+ 1058 : exit(EXIT_FAILURE);
+ 1059 : /* LCOV_EXCL_STOP */
+ 1060 : }
+ 1061 : }
+ 1062 : #else
+ 1063 : (void)lock;
+ 1064 : #endif
+ 1065 :
+ 1066 254 : if (operation == OPERATION_DIFF) {
+ 1067 7 : state_read(&state);
+ 1068 :
+ 1069 7 : ret = state_diff(&state);
+ 1070 :
+ 1071 : /* abort if sync needed */
+ 1072 7 : if (ret > 0)
+ 1073 6 : exit(EXIT_SYNC_NEEDED);
+ 1074 247 : } else if (operation == OPERATION_SYNC) {
1075 :
- 1076 74 : state_read(&state);
- 1077 :
- 1078 73 : state_scan(&state);
- 1079 :
- 1080 : /* refresh the size info before the content write */
- 1081 72 : state_refresh(&state);
+ 1076 : /* in the next state read ensures to clear all the past hashes in case */
+ 1077 : /* we are reading from an incomplete sync */
+ 1078 : /* The indeterminate hash are only for CHG/DELETED blocks for which we don't */
+ 1079 : /* know if the previous interrupted sync was able to update or not the parity. */
+ 1080 : /* The sync process instead needs to trust this information because it's used */
+ 1081 : /* to avoid to recompute the parity if all the input are equals as before. */
1082 :
- 1083 72 : memory();
- 1084 :
- 1085 : /* intercept signals while operating */
- 1086 72 : signal_init();
+ 1083 : /* In these cases we don't know if the old state is still the one */
+ 1084 : /* stored inside the parity, because after an aborted sync, the parity */
+ 1085 : /* may be or may be not have been updated with the data that may be now */
+ 1086 : /* deleted. Then we reset the hash to a bogus value. */
1087 :
- 1088 : /* save the new state before the sync */
- 1089 : /* this allow to recover the case of the changes in the array after an aborted sync. */
- 1090 :
- 1091 : /* for example, think at this case: */
- 1092 : /* - add some files at the array */
- 1093 : /* - run a sync command, it will recompute the parity adding the new files */
- 1094 : /* - abort the sync command before it stores the new content file */
- 1095 : /* - delete the not yet synced files from the array */
- 1096 : /* - run a new sync command */
- 1097 :
- 1098 : /* the new sync command has now way to know that the parity file was modified */
- 1099 : /* because the files triggering these changes are now deleted */
- 1100 : /* and they aren't listed in the content file */
- 1101 :
- 1102 72 : if (state.need_write)
- 1103 70 : state_write(&state);
- 1104 :
- 1105 : /* run a test command if required */
- 1106 72 : if (run != 0) {
- 1107 10 : ret = system(run); /* ignore error */
- 1108 10 : if (ret != 0) {
- 1109 : /* LCOV_EXCL_START */
- 1110 : log_fatal("Error in running command '%s'.\n", run);
- 1111 : exit(EXIT_FAILURE);
- 1112 : /* LCOV_EXCL_STOP */
- 1113 : }
- 1114 : }
+ 1088 : /* An example for CHG blocks is: */
+ 1089 : /* - One file is added creating a CHG block with ZERO state */
+ 1090 : /* - Sync aborted after updating the parity to the new state, */
+ 1091 : /* but without saving the content file representing this new BLK state. */
+ 1092 : /* - File is now deleted after the aborted sync */
+ 1093 : /* - Sync again, deleting the blocks over the CHG ones */
+ 1094 : /* with the hash of CHG blocks not representing the real parity state */
+ 1095 :
+ 1096 : /* An example for DELETED blocks is: */
+ 1097 : /* - One file is deleted creating DELETED blocks */
+ 1098 : /* - Sync aborted after, updating the parity to the new state, */
+ 1099 : /* but without saving the content file representing this new EMPTY state. */
+ 1100 : /* - Another file is added again over the DELETE ones */
+ 1101 : /* with the hash of DELETED blocks not representing the real parity state */
+ 1102 82 : state.clear_past_hash = 1;
+ 1103 :
+ 1104 82 : state_read(&state);
+ 1105 :
+ 1106 81 : state_scan(&state);
+ 1107 :
+ 1108 : /* refresh the size info before the content write */
+ 1109 80 : state_refresh(&state);
+ 1110 :
+ 1111 80 : memory();
+ 1112 :
+ 1113 : /* intercept signals while operating */
+ 1114 80 : signal_init();
1115 :
- 1116 : /* waits some time to ensure that any concurrent modification done at the files, */
- 1117 : /* using the same mtime read by the scan process, will be read by sync. */
- 1118 : /* Note that any later modification done, potentially not read by sync, will have */
- 1119 : /* a different mtime, and it will be syncronized at the next sync. */
- 1120 : /* The worst case is the FAT filesystem with a two seconds resolution for mtime. */
- 1121 : /* If you don't use FAT, the wait is not needed, because most filesystems have now */
- 1122 : /* at least microseconds resolution, but better to be safe. */
- 1123 72 : if (!opt.skip_self)
- 1124 0 : sleep(2);
+ 1116 : /* save the new state before the sync */
+ 1117 : /* this allow to recover the case of the changes in the array after an aborted sync. */
+ 1118 :
+ 1119 : /* for example, think at this case: */
+ 1120 : /* - add some files at the array */
+ 1121 : /* - run a sync command, it will recompute the parity adding the new files */
+ 1122 : /* - abort the sync command before it stores the new content file */
+ 1123 : /* - delete the not yet synced files from the array */
+ 1124 : /* - run a new sync command */
1125 :
- 1126 72 : ret = state_sync(&state, blockstart, blockcount);
- 1127 :
- 1128 : /* save the new state if required */
- 1129 72 : if (!opt.kill_after_sync && (state.need_write || state.opt.force_content_write))
- 1130 47 : state_write(&state);
- 1131 :
- 1132 : /* abort if required */
- 1133 72 : if (ret != 0) {
- 1134 : /* LCOV_EXCL_START */
- 1135 : exit(EXIT_FAILURE);
- 1136 : /* LCOV_EXCL_STOP */
- 1137 : }
- 1138 165 : } else if (operation == OPERATION_DRY) {
- 1139 2 : state_read(&state);
- 1140 :
- 1141 : /* filter */
- 1142 2 : state_skip(&state);
- 1143 2 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
- 1144 :
- 1145 2 : memory();
- 1146 :
- 1147 : /* intercept signals while operating */
- 1148 2 : signal_init();
- 1149 :
- 1150 2 : state_dry(&state, blockstart, blockcount);
- 1151 163 : } else if (operation == OPERATION_REHASH) {
- 1152 1 : state_read(&state);
+ 1126 : /* the new sync command has now way to know that the parity file was modified */
+ 1127 : /* because the files triggering these changes are now deleted */
+ 1128 : /* and they aren't listed in the content file */
+ 1129 :
+ 1130 80 : if (state.need_write)
+ 1131 78 : state_write(&state);
+ 1132 :
+ 1133 : /* run a test command if required */
+ 1134 80 : if (run != 0) {
+ 1135 10 : ret = system(run); /* ignore error */
+ 1136 10 : if (ret != 0) {
+ 1137 : /* LCOV_EXCL_START */
+ 1138 : log_fatal("Error in running command '%s'.\n", run);
+ 1139 : exit(EXIT_FAILURE);
+ 1140 : /* LCOV_EXCL_STOP */
+ 1141 : }
+ 1142 : }
+ 1143 :
+ 1144 : /* waits some time to ensure that any concurrent modification done at the files, */
+ 1145 : /* using the same mtime read by the scan process, will be read by sync. */
+ 1146 : /* Note that any later modification done, potentially not read by sync, will have */
+ 1147 : /* a different mtime, and it will be synchronized at the next sync. */
+ 1148 : /* The worst case is the FAT file-system with a two seconds resolution for mtime. */
+ 1149 : /* If you don't use FAT, the wait is not needed, because most file-systems have now */
+ 1150 : /* at least microseconds resolution, but better to be safe. */
+ 1151 80 : if (!opt.skip_self)
+ 1152 0 : sleep(2);
1153 :
- 1154 : /* intercept signals while operating */
- 1155 1 : signal_init();
- 1156 :
- 1157 1 : state_rehash(&state);
- 1158 :
- 1159 : /* save the new state if required */
- 1160 1 : if (state.need_write)
- 1161 1 : state_write(&state);
- 1162 162 : } else if (operation == OPERATION_SCRUB) {
- 1163 11 : state_read(&state);
- 1164 :
- 1165 11 : memory();
- 1166 :
- 1167 : /* intercept signals while operating */
- 1168 11 : signal_init();
- 1169 :
- 1170 11 : ret = state_scrub(&state, plan, olderthan);
- 1171 :
- 1172 : /* save the new state if required */
- 1173 11 : if (state.need_write || state.opt.force_content_write)
- 1174 10 : state_write(&state);
- 1175 :
- 1176 : /* abort if required */
- 1177 11 : if (ret != 0) {
- 1178 : /* LCOV_EXCL_START */
- 1179 : exit(EXIT_FAILURE);
- 1180 : /* LCOV_EXCL_STOP */
- 1181 : }
- 1182 151 : } else if (operation == OPERATION_REWRITE) {
- 1183 1 : state_read(&state);
- 1184 :
- 1185 : /* intercept signals while operating */
- 1186 1 : signal_init();
- 1187 :
- 1188 1 : state_write(&state);
- 1189 :
- 1190 1 : memory();
- 1191 150 : } else if (operation == OPERATION_READ) {
- 1192 1 : state_read(&state);
- 1193 :
- 1194 1 : memory();
- 1195 149 : } else if (operation == OPERATION_NANO) {
- 1196 1 : state_read(&state);
- 1197 :
- 1198 1 : state_nano(&state);
- 1199 :
- 1200 : /* intercept signals while operating */
- 1201 1 : signal_init();
- 1202 :
- 1203 1 : state_write(&state);
- 1204 :
- 1205 1 : memory();
- 1206 148 : } else if (operation == OPERATION_SPINUP) {
- 1207 1 : state_device(&state, DEVICE_UP);
- 1208 147 : } else if (operation == OPERATION_SPINDOWN) {
- 1209 1 : state_device(&state, DEVICE_DOWN);
- 1210 146 : } else if (operation == OPERATION_DEVICES) {
- 1211 1 : state_device(&state, DEVICE_LIST);
- 1212 145 : } else if (operation == OPERATION_SMART) {
- 1213 2 : state_device(&state, DEVICE_SMART);
- 1214 143 : } else if (operation == OPERATION_STATUS) {
- 1215 14 : state_read(&state);
+ 1154 80 : ret = state_sync(&state, blockstart, blockcount);
+ 1155 :
+ 1156 : /* save the new state if required */
+ 1157 80 : if (!opt.kill_after_sync) {
+ 1158 70 : if ((state.need_write || state.opt.force_content_write))
+ 1159 51 : state_write(&state);
+ 1160 : } else {
+ 1161 10 : log_fatal("WARNING! Skipped state write for --test-kill-after-sync option.\n");
+ 1162 : }
+ 1163 :
+ 1164 : /* abort if required */
+ 1165 80 : if (ret != 0) {
+ 1166 : /* LCOV_EXCL_START */
+ 1167 : exit(EXIT_FAILURE);
+ 1168 : /* LCOV_EXCL_STOP */
+ 1169 : }
+ 1170 165 : } else if (operation == OPERATION_DRY) {
+ 1171 2 : state_read(&state);
+ 1172 :
+ 1173 : /* filter */
+ 1174 2 : state_skip(&state);
+ 1175 2 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
+ 1176 :
+ 1177 2 : memory();
+ 1178 :
+ 1179 : /* intercept signals while operating */
+ 1180 2 : signal_init();
+ 1181 :
+ 1182 2 : state_dry(&state, blockstart, blockcount);
+ 1183 163 : } else if (operation == OPERATION_REHASH) {
+ 1184 1 : state_read(&state);
+ 1185 :
+ 1186 : /* intercept signals while operating */
+ 1187 1 : signal_init();
+ 1188 :
+ 1189 1 : state_rehash(&state);
+ 1190 :
+ 1191 : /* save the new state if required */
+ 1192 1 : if (state.need_write)
+ 1193 1 : state_write(&state);
+ 1194 162 : } else if (operation == OPERATION_SCRUB) {
+ 1195 11 : state_read(&state);
+ 1196 :
+ 1197 11 : memory();
+ 1198 :
+ 1199 : /* intercept signals while operating */
+ 1200 11 : signal_init();
+ 1201 :
+ 1202 11 : ret = state_scrub(&state, plan, olderthan);
+ 1203 :
+ 1204 : /* save the new state if required */
+ 1205 11 : if (state.need_write || state.opt.force_content_write)
+ 1206 10 : state_write(&state);
+ 1207 :
+ 1208 : /* abort if required */
+ 1209 11 : if (ret != 0) {
+ 1210 : /* LCOV_EXCL_START */
+ 1211 : exit(EXIT_FAILURE);
+ 1212 : /* LCOV_EXCL_STOP */
+ 1213 : }
+ 1214 151 : } else if (operation == OPERATION_REWRITE) {
+ 1215 1 : state_read(&state);
1216 :
- 1217 14 : memory();
- 1218 :
- 1219 14 : state_status(&state);
- 1220 129 : } else if (operation == OPERATION_DUP) {
- 1221 3 : state_read(&state);
- 1222 :
- 1223 3 : state_dup(&state);
- 1224 126 : } else if (operation == OPERATION_LIST) {
- 1225 3 : state_read(&state);
- 1226 :
- 1227 3 : state_list(&state);
- 1228 123 : } else if (operation == OPERATION_POOL) {
- 1229 3 : state_read(&state);
- 1230 :
- 1231 3 : state_pool(&state);
- 1232 : } else {
- 1233 120 : state_read(&state);
+ 1217 : /* intercept signals while operating */
+ 1218 1 : signal_init();
+ 1219 :
+ 1220 1 : state_write(&state);
+ 1221 :
+ 1222 1 : memory();
+ 1223 150 : } else if (operation == OPERATION_READ) {
+ 1224 1 : state_read(&state);
+ 1225 :
+ 1226 1 : memory();
+ 1227 149 : } else if (operation == OPERATION_NANO) {
+ 1228 1 : state_read(&state);
+ 1229 :
+ 1230 1 : state_nano(&state);
+ 1231 :
+ 1232 : /* intercept signals while operating */
+ 1233 1 : signal_init();
1234 :
- 1235 : /* if we are also trying to recover */
- 1236 120 : if (!state.opt.auditonly) {
- 1237 : /* import the user specified dirs */
- 1238 114 : if (import_timestamp != 0)
- 1239 1 : state_search(&state, import_timestamp);
- 1240 114 : if (import_content != 0)
- 1241 1 : state_import(&state, import_content);
- 1242 :
- 1243 : /* import from all the array */
- 1244 114 : if (!state.opt.force_nocopy)
- 1245 114 : state_search_array(&state);
- 1246 : }
- 1247 :
- 1248 : /* filter */
- 1249 120 : state_skip(&state);
- 1250 120 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
- 1251 :
- 1252 120 : memory();
- 1253 :
- 1254 : /* intercept signals while operating */
- 1255 120 : signal_init();
- 1256 :
- 1257 120 : if (operation == OPERATION_CHECK) {
- 1258 75 : ret = state_check(&state, 0, blockstart, blockcount);
- 1259 : } else { /* it's fix */
- 1260 45 : ret = state_check(&state, 1, blockstart, blockcount);
- 1261 : }
+ 1235 1 : state_write(&state);
+ 1236 :
+ 1237 1 : memory();
+ 1238 148 : } else if (operation == OPERATION_SPINUP) {
+ 1239 1 : state_device(&state, DEVICE_UP);
+ 1240 147 : } else if (operation == OPERATION_SPINDOWN) {
+ 1241 1 : state_device(&state, DEVICE_DOWN);
+ 1242 146 : } else if (operation == OPERATION_DEVICES) {
+ 1243 1 : state_device(&state, DEVICE_LIST);
+ 1244 145 : } else if (operation == OPERATION_SMART) {
+ 1245 2 : state_device(&state, DEVICE_SMART);
+ 1246 143 : } else if (operation == OPERATION_STATUS) {
+ 1247 14 : state_read(&state);
+ 1248 :
+ 1249 14 : memory();
+ 1250 :
+ 1251 14 : state_status(&state);
+ 1252 129 : } else if (operation == OPERATION_DUP) {
+ 1253 3 : state_read(&state);
+ 1254 :
+ 1255 3 : state_dup(&state);
+ 1256 126 : } else if (operation == OPERATION_LIST) {
+ 1257 3 : state_read(&state);
+ 1258 :
+ 1259 3 : state_list(&state);
+ 1260 123 : } else if (operation == OPERATION_POOL) {
+ 1261 3 : state_read(&state);
1262 :
- 1263 : /* abort if required */
- 1264 120 : if (ret != 0) {
- 1265 : /* LCOV_EXCL_START */
- 1266 : exit(EXIT_FAILURE);
- 1267 : /* LCOV_EXCL_STOP */
- 1268 : }
- 1269 : }
- 1270 :
- 1271 : /* close log file */
- 1272 225 : log_close(log_file);
- 1273 :
- 1274 : #if HAVE_LOCKFILE
- 1275 225 : if (!opt.skip_lock && state.lockfile[0]) {
- 1276 223 : if (lock_unlock(lock) == -1) {
- 1277 : /* LCOV_EXCL_START */
- 1278 : log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
- 1279 : exit(EXIT_FAILURE);
- 1280 : /* LCOV_EXCL_STOP */
- 1281 : }
- 1282 : }
- 1283 : #endif
- 1284 :
- 1285 225 : state_done(&state);
- 1286 225 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free);
- 1287 225 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free);
+ 1263 3 : state_pool(&state);
+ 1264 : } else {
+ 1265 120 : state_read(&state);
+ 1266 :
+ 1267 : /* if we are also trying to recover */
+ 1268 120 : if (!state.opt.auditonly) {
+ 1269 : /* import the user specified dirs */
+ 1270 114 : if (import_timestamp != 0)
+ 1271 1 : state_search(&state, import_timestamp);
+ 1272 114 : if (import_content != 0)
+ 1273 1 : state_import(&state, import_content);
+ 1274 :
+ 1275 : /* import from all the array */
+ 1276 114 : if (!state.opt.force_nocopy)
+ 1277 114 : state_search_array(&state);
+ 1278 : }
+ 1279 :
+ 1280 : /* filter */
+ 1281 120 : state_skip(&state);
+ 1282 120 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
+ 1283 :
+ 1284 120 : memory();
+ 1285 :
+ 1286 : /* intercept signals while operating */
+ 1287 120 : signal_init();
1288 :
- 1289 225 : os_done();
- 1290 :
- 1291 225 : return EXIT_SUCCESS;
- 1292 : }
- 1293 :
+ 1289 120 : if (operation == OPERATION_CHECK) {
+ 1290 75 : ret = state_check(&state, 0, blockstart, blockcount);
+ 1291 : } else { /* it's fix */
+ 1292 45 : ret = state_check(&state, 1, blockstart, blockcount);
+ 1293 : }
+ 1294 :
+ 1295 : /* abort if required */
+ 1296 120 : if (ret != 0) {
+ 1297 : /* LCOV_EXCL_START */
+ 1298 : exit(EXIT_FAILURE);
+ 1299 : /* LCOV_EXCL_STOP */
+ 1300 : }
+ 1301 : }
+ 1302 :
+ 1303 : /* close log file */
+ 1304 233 : log_close(log_file);
+ 1305 :
+ 1306 : #if HAVE_LOCKFILE
+ 1307 233 : if (!opt.skip_lock && state.lockfile[0]) {
+ 1308 231 : if (lock_unlock(lock) == -1) {
+ 1309 : /* LCOV_EXCL_START */
+ 1310 : log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
+ 1311 : exit(EXIT_FAILURE);
+ 1312 : /* LCOV_EXCL_STOP */
+ 1313 : }
+ 1314 : }
+ 1315 : #endif
+ 1316 :
+ 1317 233 : state_done(&state);
+ 1318 233 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free);
+ 1319 233 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free);
+ 1320 :
+ 1321 233 : os_done();
+ 1322 :
+ 1323 233 : return EXIT_SUCCESS;
+ 1324 : }
+ 1325 :
diff --git a/cov/cmdline/speed.c.func-sort-c.html b/cov/cmdline/speed.c.func-sort-c.html
index af5d7d8f..4b48a521 100644
--- a/cov/cmdline/speed.c.func-sort-c.html
+++ b/cov/cmdline/speed.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| diffgettimeofday |
- 1866 |
+ 1878 |
| speed |
diff --git a/cov/cmdline/speed.c.func.html b/cov/cmdline/speed.c.func.html
index eb03f6a4..2ea02544 100644
--- a/cov/cmdline/speed.c.func.html
+++ b/cov/cmdline/speed.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| diffgettimeofday |
- 1866 |
+ 1878 |
| speed |
diff --git a/cov/cmdline/speed.c.gcov.html b/cov/cmdline/speed.c.gcov.html
index edf49280..3d202c50 100644
--- a/cov/cmdline/speed.c.gcov.html
+++ b/cov/cmdline/speed.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -100,14 +100,14 @@
38 : /**
39 : * Differential us of two timeval.
40 : */
- 41 1866 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop)
+ 41 1878 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop)
42 : {
43 : int64_t d;
44 :
- 45 1866 : d = 1000000LL * (stop->tv_sec - start->tv_sec);
- 46 1866 : d += stop->tv_usec - start->tv_usec;
+ 45 1878 : d = 1000000LL * (stop->tv_sec - start->tv_sec);
+ 46 1878 : d += stop->tv_usec - start->tv_usec;
47 :
- 48 1866 : return d;
+ 48 1878 : return d;
49 : }
50 :
51 : /**
@@ -232,10 +232,10 @@
170 4 : printf("%8s", "memset");
171 4 : fflush(stdout);
172 :
- 173 385 : SPEED_START {
- 174 3429 : for (j = 0; j < nd; ++j)
- 175 3048 : memset(v[j], j, size);
- 176 381 : } SPEED_STOP
+ 173 375 : SPEED_START {
+ 174 3339 : for (j = 0; j < nd; ++j)
+ 175 2968 : memset(v[j], j, size);
+ 176 371 : } SPEED_STOP
177 :
178 4 : printf("%8" PRIu64, ds / dt);
179 4 : printf("\n");
@@ -247,10 +247,10 @@
185 4 : printf("%8s", "table");
186 4 : fflush(stdout);
187 :
- 188 46 : SPEED_START {
- 189 378 : for (j = 0; j < nd; ++j)
- 190 336 : side_effect += crc32c_gen(0, v[j], size);
- 191 42 : } SPEED_STOP
+ 188 48 : SPEED_START {
+ 189 396 : for (j = 0; j < nd; ++j)
+ 190 352 : side_effect += crc32c_gen(0, v[j], size);
+ 191 44 : } SPEED_STOP
192 :
193 4 : printf("%8" PRIu64, ds / dt);
194 4 : printf("\n");
@@ -302,10 +302,10 @@
240 4 : printf("%8" PRIu64, ds / dt);
241 4 : fflush(stdout);
242 :
- 243 35 : SPEED_START {
- 244 279 : for (j = 0; j < nd; ++j)
- 245 248 : memhash(HASH_SPOOKY2, seed, digest, v[j], size);
- 246 31 : } SPEED_STOP
+ 243 36 : SPEED_START {
+ 244 288 : for (j = 0; j < nd; ++j)
+ 245 256 : memhash(HASH_SPOOKY2, seed, digest, v[j], size);
+ 246 32 : } SPEED_STOP
247 :
248 4 : printf("%8" PRIu64, ds / dt);
249 4 : printf("\n");
@@ -341,16 +341,16 @@
279 :
280 4 : printf("%8s", "");
281 :
- 282 118 : SPEED_START {
- 283 114 : raid_gen1_int32(nd, size, v);
- 284 114 : } SPEED_STOP
+ 282 120 : SPEED_START {
+ 283 116 : raid_gen1_int32(nd, size, v);
+ 284 116 : } SPEED_STOP
285 :
286 4 : printf("%8" PRIu64, ds / dt);
287 4 : fflush(stdout);
288 :
- 289 189 : SPEED_START {
- 290 185 : raid_gen1_int64(nd, size, v);
- 291 185 : } SPEED_STOP
+ 289 192 : SPEED_START {
+ 290 188 : raid_gen1_int64(nd, size, v);
+ 291 188 : } SPEED_STOP
292 :
293 4 : printf("%8" PRIu64, ds / dt);
294 4 : fflush(stdout);
@@ -358,9 +358,9 @@
296 : #ifdef CONFIG_X86
297 : #ifdef CONFIG_SSE2
298 4 : if (raid_cpu_has_sse2()) {
- 299 310 : SPEED_START {
- 300 306 : raid_gen1_sse2(nd, size, v);
- 301 306 : } SPEED_STOP
+ 299 317 : SPEED_START {
+ 300 313 : raid_gen1_sse2(nd, size, v);
+ 301 313 : } SPEED_STOP
302 :
303 4 : printf("%8" PRIu64, ds / dt);
304 4 : fflush(stdout);
@@ -411,9 +411,9 @@
349 : #ifdef CONFIG_X86
350 : #ifdef CONFIG_SSE2
351 4 : if (raid_cpu_has_sse2()) {
- 352 147 : SPEED_START {
- 353 143 : raid_gen2_sse2(nd, size, v);
- 354 143 : } SPEED_STOP
+ 352 151 : SPEED_START {
+ 353 147 : raid_gen2_sse2(nd, size, v);
+ 354 147 : } SPEED_STOP
355 :
356 4 : printf("%8" PRIu64, ds / dt);
357 4 : fflush(stdout);
@@ -470,9 +470,9 @@
408 : #ifdef CONFIG_X86
409 : #ifdef CONFIG_SSE2
410 4 : if (raid_cpu_has_sse2()) {
- 411 88 : SPEED_START {
- 412 84 : raid_genz_sse2(nd, size, v);
- 413 84 : } SPEED_STOP
+ 411 89 : SPEED_START {
+ 412 85 : raid_genz_sse2(nd, size, v);
+ 413 85 : } SPEED_STOP
414 :
415 4 : printf("%8" PRIu64, ds / dt);
416 4 : fflush(stdout);
@@ -707,9 +707,9 @@
645 4 : printf("%8s", raid_gen6_tag());
646 4 : fflush(stdout);
647 :
- 648 10 : SPEED_START {
- 649 6 : raid_gen6_int8(nd, size, v);
- 650 6 : } SPEED_STOP
+ 648 12 : SPEED_START {
+ 649 8 : raid_gen6_int8(nd, size, v);
+ 650 8 : } SPEED_STOP
651 :
652 4 : printf("%8" PRIu64, ds / dt);
653 4 : fflush(stdout);
diff --git a/cov/cmdline/spooky2.c.func-sort-c.html b/cov/cmdline/spooky2.c.func-sort-c.html
index d52512e6..8c286716 100644
--- a/cov/cmdline/spooky2.c.func-sort-c.html
+++ b/cov/cmdline/spooky2.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| SpookyHash128 |
- 3472174 |
+ 3855152 |
diff --git a/cov/cmdline/spooky2.c.func.html b/cov/cmdline/spooky2.c.func.html
index d22d4cbf..6c188d72 100644
--- a/cov/cmdline/spooky2.c.func.html
+++ b/cov/cmdline/spooky2.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| SpookyHash128 |
- 3472174 |
+ 3855152 |
diff --git a/cov/cmdline/spooky2.c.gcov.html b/cov/cmdline/spooky2.c.gcov.html
index 06596abb..8e1b9ebc 100644
--- a/cov/cmdline/spooky2.c.gcov.html
+++ b/cov/cmdline/spooky2.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -170,7 +170,7 @@
108 : //
109 : #define sc_const 0xdeadbeefdeadbeefLL
110 :
- 111 3472174 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
+ 111 3855152 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
112 : {
113 : uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
114 : uint64_t buf[sc_numVars];
@@ -182,39 +182,39 @@
120 : unsigned i;
121 : #endif
122 :
- 123 3472174 : h9 = ((const uint64_t*)seed)[0];
- 124 3472174 : h10 = ((const uint64_t*)seed)[1];
+ 123 3855152 : h9 = ((const uint64_t*)seed)[0];
+ 124 3855152 : h10 = ((const uint64_t*)seed)[1];
125 :
126 : #if WORDS_BIGENDIAN
127 : h9 = util_swap64(h9);
128 : h10 = util_swap64(h10);
129 : #endif
130 :
- 131 3472174 : h0 = h3 = h6 = h9;
- 132 3472174 : h1 = h4 = h7 = h10;
- 133 3472174 : h2 = h5 = h8 = h11 = sc_const;
+ 131 3855152 : h0 = h3 = h6 = h9;
+ 132 3855152 : h1 = h4 = h7 = h10;
+ 133 3855152 : h2 = h5 = h8 = h11 = sc_const;
134 :
- 135 3472174 : nblocks = size / sc_blockSize;
- 136 3472174 : blocks = data;
- 137 3472174 : end = blocks + nblocks * sc_numVars;
+ 135 3855152 : nblocks = size / sc_blockSize;
+ 136 3855152 : blocks = data;
+ 137 3855152 : end = blocks + nblocks * sc_numVars;
138 :
139 : /* body */
- 140 34945798 : while (blocks < end) {
+ 140 38762369 : while (blocks < end) {
141 : #if WORDS_BIGENDIAN
142 : for (i = 0; i < sc_numVars; ++i)
143 : buf[i] = util_swap64(blocks[i]);
144 : Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
145 : #else
- 146 28001450 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
+ 146 31052065 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
147 : #endif
- 148 28001450 : blocks += sc_numVars;
+ 148 31052065 : blocks += sc_numVars;
149 : }
150 :
151 : /* tail */
- 152 3472174 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
- 153 3472174 : memcpy(buf, end, size_remainder);
- 154 3472174 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
- 155 3472174 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
+ 152 3855152 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
+ 153 3855152 : memcpy(buf, end, size_remainder);
+ 154 3855152 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
+ 155 3855152 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
156 :
157 : /* finalization */
158 : #if WORDS_BIGENDIAN
@@ -222,16 +222,16 @@
160 : buf[i] = util_swap64(buf[i]);
161 : #endif
162 :
- 163 3472174 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
+ 163 3855152 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
164 :
165 : #if WORDS_BIGENDIAN
166 : h0 = util_swap64(h0);
167 : h1 = util_swap64(h1);
168 : #endif
169 :
- 170 3472174 : ((uint64_t*)digest)[0] = h0;
- 171 3472174 : ((uint64_t*)digest)[1] = h1;
- 172 3472174 : }
+ 170 3855152 : ((uint64_t*)digest)[0] = h0;
+ 171 3855152 : ((uint64_t*)digest)[1] = h1;
+ 172 3855152 : }
173 :
diff --git a/cov/cmdline/state.c.func-sort-c.html b/cov/cmdline/state.c.func-sort-c.html
index 7cf9b431..f380d70f 100644
--- a/cov/cmdline/state.c.func-sort-c.html
+++ b/cov/cmdline/state.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,147 +60,151 @@
Hit count  |
- | fs_is_block_deleted_ts |
- 29344162 |
+ fs_is_block_deleted_ts |
+ 4507856 |
- | fs_info_is_required |
- 1491820 |
+ fs_info_is_required |
+ 1513218 |
- | state_progress |
- 1038958 |
+ state_progress |
+ 1048979 |
- | fs_position_is_required |
- 729418 |
+ fs_position_is_required |
+ 752491 |
- | lev_config_name |
- 178766 |
+ lev_config_name |
+ 178997 |
- | find_disk |
- 11051 |
+ find_disk_by_name |
+ 6723 |
- | lev_config_scan |
- 5905 |
+ lev_config_scan |
+ 6118 |
- | state_write_thread |
- 913 |
+ state_verify_thread |
+ 990 |
- | state_verify_thread |
- 912 |
+ state_fscheck |
+ 474 |
- | state_fscheck |
- 447 |
+ validate_smartctl |
+ 358 |
- | validate_smartctl |
- 344 |
+ state_init |
+ 256 |
- | state_init |
- 248 |
+ state_config |
+ 255 |
- | state_config |
- 247 |
+ lev_raid_name |
+ 254 |
- | lev_raid_name |
- 246 |
+ state_config_check |
+ 254 |
- | state_config_check |
- 246 |
+ state_read |
+ 250 |
- | state_read |
+ state_map |
+ 249 |
+
+
+ | state_read_content |
+ 243 |
+
+
+ | state_content_check |
242 |
- | state_map |
- 241 |
-
-
- | state_read_content |
- 235 |
-
-
- | state_content_check |
+ state_done |
234 |
- | state_done |
- 226 |
+ state_progress_end |
+ 214 |
- | state_progress_end |
- 206 |
+ state_progress_begin |
+ 214 |
- | state_progress_begin |
- 206 |
+ state_refresh |
+ 160 |
- | state_refresh |
- 144 |
+ state_write |
+ 145 |
- | state_write |
- 134 |
+ state_write_thread |
+ 145 |
- | state_write_content |
- 134 |
+ state_write_content |
+ 145 |
- | state_verify_content |
- 134 |
+ state_verify_content |
+ 145 |
- | state_rename_content |
- 134 |
+ state_rename_content |
+ 145 |
- | state_skip |
+ state_skip |
122 |
- | state_filter |
+ state_filter |
122 |
- | state_usage_print |
- 81 |
+ state_usage_print |
+ 89 |
- | lev_name |
+ lev_name |
7 |
- | state_progress_restart |
+ find_disk_by_uuid |
+ 2 |
+
+
+ | state_progress_restart |
1 |
- | generate_configuration |
+ generate_configuration |
1 |
- | decoding_error |
+ decoding_error |
1 |
- | state_progress_stop |
+ state_progress_stop |
1 |
- | fs_position_clear_deleted |
+ fs_position_clear_deleted |
0 |
diff --git a/cov/cmdline/state.c.func.html b/cov/cmdline/state.c.func.html
index c610d3af..912c6cfc 100644
--- a/cov/cmdline/state.c.func.html
+++ b/cov/cmdline/state.c.func.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,148 +60,152 @@
Hit count  |
- | decoding_error |
+ decoding_error |
1 |
- | find_disk |
- 11051 |
+ find_disk_by_name |
+ 6723 |
- | fs_info_is_required |
- 1491820 |
+ find_disk_by_uuid |
+ 2 |
- | fs_is_block_deleted_ts |
- 29344162 |
+ fs_info_is_required |
+ 1513218 |
- | fs_position_clear_deleted |
+ fs_is_block_deleted_ts |
+ 4507856 |
+
+
+ | fs_position_clear_deleted |
0 |
- | fs_position_is_required |
- 729418 |
+ fs_position_is_required |
+ 752491 |
- | generate_configuration |
+ generate_configuration |
1 |
- | lev_config_name |
- 178766 |
+ lev_config_name |
+ 178997 |
- | lev_config_scan |
- 5905 |
+ lev_config_scan |
+ 6118 |
- | lev_name |
+ lev_name |
7 |
- | lev_raid_name |
- 246 |
+ lev_raid_name |
+ 254 |
- | state_config |
- 247 |
+ state_config |
+ 255 |
- | state_config_check |
- 246 |
+ state_config_check |
+ 254 |
- | state_content_check |
- 234 |
-
-
- | state_done |
- 226 |
-
-
- | state_filter |
- 122 |
-
-
- | state_fscheck |
- 447 |
-
-
- | state_init |
- 248 |
-
-
- | state_map |
- 241 |
-
-
- | state_progress |
- 1038958 |
-
-
- | state_progress_begin |
- 206 |
-
-
- | state_progress_end |
- 206 |
-
-
- | state_progress_restart |
- 1 |
-
-
- | state_progress_stop |
- 1 |
-
-
- | state_read |
+ state_content_check |
242 |
- | state_read_content |
- 235 |
+ state_done |
+ 234 |
- | state_refresh |
- 144 |
-
-
- | state_rename_content |
- 134 |
-
-
- | state_skip |
+ state_filter |
122 |
- | state_usage_print |
- 81 |
+ state_fscheck |
+ 474 |
- | state_verify_content |
- 134 |
+ state_init |
+ 256 |
- | state_verify_thread |
- 912 |
+ state_map |
+ 249 |
- | state_write |
- 134 |
+ state_progress |
+ 1048979 |
- | state_write_content |
- 134 |
+ state_progress_begin |
+ 214 |
- | state_write_thread |
- 913 |
+ state_progress_end |
+ 214 |
- | validate_smartctl |
- 344 |
+ state_progress_restart |
+ 1 |
+
+
+ | state_progress_stop |
+ 1 |
+
+
+ | state_read |
+ 250 |
+
+
+ | state_read_content |
+ 243 |
+
+
+ | state_refresh |
+ 160 |
+
+
+ | state_rename_content |
+ 145 |
+
+
+ | state_skip |
+ 122 |
+
+
+ | state_usage_print |
+ 89 |
+
+
+ | state_verify_content |
+ 145 |
+
+
+ | state_verify_thread |
+ 990 |
+
+
+ | state_write |
+ 145 |
+
+
+ | state_write_content |
+ 145 |
+
+
+ | state_write_thread |
+ 145 |
+
+
+ | validate_smartctl |
+ 358 |
diff --git a/cov/cmdline/state.c.gcov.html b/cov/cmdline/state.c.gcov.html
index 17e83360..f17512ad 100644
--- a/cov/cmdline/state.c.gcov.html
+++ b/cov/cmdline/state.c.gcov.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -87,3948 +87,4120 @@
25 : #include "parity.h"
26 : #include "stream.h"
27 : #include "raid/raid.h"
- 28 : #include "raid/cpu.h"
+ 28 : #include "raid/cpu.h"
29 :
- 30 7 : const char* lev_name(unsigned l)
- 31 : {
- 32 7 : switch (l) {
- 33 2 : case 0 : return "Parity";
- 34 1 : case 1 : return "2-Parity";
- 35 1 : case 2 : return "3-Parity";
- 36 1 : case 3 : return "4-Parity";
- 37 1 : case 4 : return "5-Parity";
- 38 1 : case 5 : return "6-Parity";
- 39 : }
- 40 :
- 41 0 : return 0;
- 42 : }
- 43 :
- 44 178766 : const char* lev_config_name(unsigned l)
- 45 : {
- 46 178766 : switch (l) {
- 47 70476 : case 0 : return "parity";
- 48 57423 : case 1 : return "2-parity";
- 49 12723 : case 2 : return "3-parity";
- 50 12719 : case 3 : return "4-parity";
- 51 12715 : case 4 : return "5-parity";
- 52 12710 : case 5 : return "6-parity";
- 53 : }
- 54 :
- 55 0 : return 0;
- 56 : }
- 57 :
- 58 5905 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode)
- 59 : {
- 60 5905 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) {
- 61 419 : *level = 0;
- 62 419 : return 0;
- 63 : }
- 64 :
- 65 5486 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) {
- 66 213 : *level = 1;
- 67 213 : return 0;
- 68 : }
- 69 :
- 70 5273 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) {
- 71 188 : *level = 2;
- 72 188 : return 0;
+ 30 : /**
+ 31 : * Configure the multithread support.
+ 32 : *
+ 33 : * Multi thread for write could be either faster or slower, depending
+ 34 : * on the specific conditions. With multithreads it's likely faster
+ 35 : * writing to disk, but you'll need to access multiple times the same data,
+ 36 : * being potentially slower.
+ 37 : *
+ 38 : * For upcoming SnapRAID version it's planned to add a mutex protection
+ 39 : * at the file-system structure, slowing down multiple data access,
+ 40 : * so we disable it.
+ 41 : *
+ 42 : * Multi thread for verify is instead always generally faster,
+ 43 : * so we enable it if possible.
+ 44 : */
+ 45 : #if HAVE_PTHREAD
+ 46 : /* #define HAVE_MT_WRITE 1 */
+ 47 : #define HAVE_MT_VERIFY 1
+ 48 : #endif
+ 49 :
+ 50 7 : const char* lev_name(unsigned l)
+ 51 : {
+ 52 7 : switch (l) {
+ 53 2 : case 0 : return "Parity";
+ 54 1 : case 1 : return "2-Parity";
+ 55 1 : case 2 : return "3-Parity";
+ 56 1 : case 3 : return "4-Parity";
+ 57 1 : case 4 : return "5-Parity";
+ 58 1 : case 5 : return "6-Parity";
+ 59 : }
+ 60 :
+ 61 0 : return 0;
+ 62 : }
+ 63 :
+ 64 178997 : const char* lev_config_name(unsigned l)
+ 65 : {
+ 66 178997 : switch (l) {
+ 67 70574 : case 0 : return "parity";
+ 68 57456 : case 1 : return "2-parity";
+ 69 12748 : case 2 : return "3-parity";
+ 70 12744 : case 3 : return "4-parity";
+ 71 12740 : case 4 : return "5-parity";
+ 72 12735 : case 5 : return "6-parity";
73 : }
74 :
- 75 5085 : if (strcmp(s, "4-parity") == 0) {
- 76 185 : *level = 3;
- 77 185 : return 0;
- 78 : }
- 79 :
- 80 4900 : if (strcmp(s, "5-parity") == 0) {
- 81 182 : *level = 4;
- 82 182 : return 0;
+ 75 0 : return 0;
+ 76 : }
+ 77 :
+ 78 6118 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode)
+ 79 : {
+ 80 6118 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) {
+ 81 434 : *level = 0;
+ 82 434 : return 0;
83 : }
84 :
- 85 4718 : if (strcmp(s, "6-parity") == 0) {
- 86 178 : *level = 5;
- 87 178 : return 0;
+ 85 5684 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) {
+ 86 221 : *level = 1;
+ 87 221 : return 0;
88 : }
89 :
- 90 4540 : if (strcmp(s, "z-parity") == 0) {
- 91 0 : *level = 2;
- 92 0 : if (mode)
- 93 0 : *mode = RAID_MODE_VANDERMONDE;
- 94 0 : return 0;
- 95 : }
- 96 :
- 97 4540 : return -1;
- 98 : }
+ 90 5463 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) {
+ 91 196 : *level = 2;
+ 92 196 : return 0;
+ 93 : }
+ 94 :
+ 95 5267 : if (strcmp(s, "4-parity") == 0) {
+ 96 193 : *level = 3;
+ 97 193 : return 0;
+ 98 : }
99 :
- 100 246 : const char* lev_raid_name(unsigned mode, unsigned n)
- 101 : {
- 102 246 : switch (n) {
- 103 34 : case 1 : return "par1";
- 104 25 : case 2 : return "par2";
- 105 3 : case 3 : if (mode == RAID_MODE_CAUCHY)
- 106 3 : return "par3";
- 107 : else
- 108 0 : return "parz";
- 109 3 : case 4 : return "par4";
- 110 4 : case 5 : return "par5";
- 111 177 : case 6 : return "par6";
- 112 : }
- 113 :
- 114 0 : return 0;
- 115 : }
+ 100 5074 : if (strcmp(s, "5-parity") == 0) {
+ 101 190 : *level = 4;
+ 102 190 : return 0;
+ 103 : }
+ 104 :
+ 105 4884 : if (strcmp(s, "6-parity") == 0) {
+ 106 186 : *level = 5;
+ 107 186 : return 0;
+ 108 : }
+ 109 :
+ 110 4698 : if (strcmp(s, "z-parity") == 0) {
+ 111 0 : *level = 2;
+ 112 0 : if (mode)
+ 113 0 : *mode = RAID_MODE_VANDERMONDE;
+ 114 0 : return 0;
+ 115 : }
116 :
- 117 248 : void state_init(struct snapraid_state* state)
- 118 : {
- 119 : unsigned l;
- 120 :
- 121 248 : memset(&state->opt, 0, sizeof(state->opt));
- 122 248 : state->filter_hidden = 0;
- 123 248 : state->autosave = 0;
- 124 248 : state->need_write = 0;
- 125 248 : state->checked_read = 0;
- 126 248 : state->block_size = 256 * 1024; /* default 256 KiB */
- 127 248 : state->raid_mode = RAID_MODE_CAUCHY;
- 128 248 : state->file_mode = MODE_SEQUENTIAL;
- 129 1736 : for (l = 0; l < LEV_MAX; ++l) {
- 130 1488 : state->parity[l].path[0] = 0;
- 131 1488 : state->parity[l].smartctl[0] = 0;
- 132 1488 : state->parity[l].uuid[0] = 0;
- 133 1488 : state->parity[l].device = 0;
- 134 1488 : state->parity[l].total_blocks = 0;
- 135 1488 : state->parity[l].free_blocks = 0;
- 136 1488 : state->parity[l].tick = 0;
- 137 1488 : state->parity[l].skip_access = 0;
- 138 1488 : state->parity[l].is_excluded = 0;
- 139 : }
- 140 248 : state->tick_io = 0;
- 141 248 : state->tick_cpu = 0;
- 142 248 : state->tick_last = tick();
- 143 248 : state->share[0] = 0;
- 144 248 : state->pool[0] = 0;
- 145 248 : state->pool_device = 0;
- 146 248 : state->lockfile[0] = 0;
- 147 248 : state->level = 1; /* default is the lowest protection */
- 148 248 : state->clear_past_hash = 0;
- 149 248 : state->no_conf = 0;
- 150 :
- 151 248 : tommy_list_init(&state->disklist);
- 152 248 : tommy_list_init(&state->maplist);
- 153 248 : tommy_list_init(&state->contentlist);
- 154 248 : tommy_list_init(&state->filterlist);
- 155 248 : tommy_list_init(&state->importlist);
- 156 248 : tommy_hashdyn_init(&state->importset);
- 157 248 : tommy_hashdyn_init(&state->previmportset);
- 158 248 : tommy_hashdyn_init(&state->searchset);
- 159 248 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info));
- 160 248 : }
- 161 :
- 162 226 : void state_done(struct snapraid_state* state)
- 163 : {
- 164 226 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free);
- 165 226 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free);
- 166 226 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free);
- 167 226 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free);
- 168 226 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free);
- 169 226 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free);
- 170 226 : tommy_hashdyn_done(&state->importset);
- 171 226 : tommy_hashdyn_done(&state->previmportset);
- 172 226 : tommy_hashdyn_done(&state->searchset);
- 173 226 : tommy_arrayblkof_done(&state->infoarr);
- 174 226 : }
- 175 :
- 176 : /**
- 177 : * Check the configuration.
- 178 : */
- 179 246 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk)
- 180 : {
- 181 : tommy_node* i;
- 182 : unsigned l;
- 183 :
- 184 : /* check for parity level */
- 185 246 : if (state->raid_mode == RAID_MODE_VANDERMONDE) {
- 186 0 : if (state->level > 3) {
- 187 : /* LCOV_EXCL_START */
- 188 : log_fatal("If you use the z-parity you cannot have more than 3 parities.\n");
- 189 : exit(EXIT_FAILURE);
- 190 : /* LCOV_EXCL_STIO */
- 191 : }
- 192 : }
- 193 :
- 194 : for (l = 0; l < state->level; ++l) {
- 195 : if (state->parity[l].path[0] == 0) {
- 196 : /* LCOV_EXCL_START */
- 197 : log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path);
- 198 : exit(EXIT_FAILURE);
- 199 : /* LCOV_EXCL_STOP */
- 200 : }
- 201 : }
- 202 :
- 203 246 : if (tommy_list_empty(&state->contentlist)) {
- 204 : /* LCOV_EXCL_START */
- 205 : log_fatal("No 'content' specification in '%s'\n", path);
- 206 : exit(EXIT_FAILURE);
- 207 : /* LCOV_EXCL_STOP */
- 208 : }
- 209 :
- 210 : /* check for equal paths */
- 211 1679 : for (i = state->contentlist; i != 0; i = i->next) {
- 212 1433 : struct snapraid_content* content = i->data;
+ 117 4698 : return -1;
+ 118 : }
+ 119 :
+ 120 254 : const char* lev_raid_name(unsigned mode, unsigned n)
+ 121 : {
+ 122 254 : switch (n) {
+ 123 34 : case 1 : return "par1";
+ 124 25 : case 2 : return "par2";
+ 125 3 : case 3 : if (mode == RAID_MODE_CAUCHY)
+ 126 3 : return "par3";
+ 127 : else
+ 128 0 : return "parz";
+ 129 3 : case 4 : return "par4";
+ 130 4 : case 5 : return "par5";
+ 131 185 : case 6 : return "par6";
+ 132 : }
+ 133 :
+ 134 0 : return 0;
+ 135 : }
+ 136 :
+ 137 256 : void state_init(struct snapraid_state* state)
+ 138 : {
+ 139 : unsigned l;
+ 140 :
+ 141 256 : memset(&state->opt, 0, sizeof(state->opt));
+ 142 256 : state->filter_hidden = 0;
+ 143 256 : state->autosave = 0;
+ 144 256 : state->need_write = 0;
+ 145 256 : state->checked_read = 0;
+ 146 256 : state->block_size = 256 * 1024; /* default 256 KiB */
+ 147 256 : state->raid_mode = RAID_MODE_CAUCHY;
+ 148 256 : state->file_mode = MODE_SEQUENTIAL;
+ 149 1792 : for (l = 0; l < LEV_MAX; ++l) {
+ 150 1536 : state->parity[l].path[0] = 0;
+ 151 1536 : state->parity[l].smartctl[0] = 0;
+ 152 1536 : state->parity[l].uuid[0] = 0;
+ 153 1536 : state->parity[l].device = 0;
+ 154 1536 : state->parity[l].total_blocks = 0;
+ 155 1536 : state->parity[l].free_blocks = 0;
+ 156 1536 : state->parity[l].tick = 0;
+ 157 1536 : state->parity[l].skip_access = 0;
+ 158 1536 : state->parity[l].is_excluded = 0;
+ 159 : }
+ 160 256 : state->tick_io = 0;
+ 161 256 : state->tick_cpu = 0;
+ 162 256 : state->tick_last = tick();
+ 163 256 : state->share[0] = 0;
+ 164 256 : state->pool[0] = 0;
+ 165 256 : state->pool_device = 0;
+ 166 256 : state->lockfile[0] = 0;
+ 167 256 : state->level = 1; /* default is the lowest protection */
+ 168 256 : state->clear_past_hash = 0;
+ 169 256 : state->no_conf = 0;
+ 170 :
+ 171 256 : tommy_list_init(&state->disklist);
+ 172 256 : tommy_list_init(&state->maplist);
+ 173 256 : tommy_list_init(&state->contentlist);
+ 174 256 : tommy_list_init(&state->filterlist);
+ 175 256 : tommy_list_init(&state->importlist);
+ 176 256 : tommy_hashdyn_init(&state->importset);
+ 177 256 : tommy_hashdyn_init(&state->previmportset);
+ 178 256 : tommy_hashdyn_init(&state->searchset);
+ 179 256 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info));
+ 180 256 : }
+ 181 :
+ 182 234 : void state_done(struct snapraid_state* state)
+ 183 : {
+ 184 234 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free);
+ 185 234 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free);
+ 186 234 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free);
+ 187 234 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free);
+ 188 234 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free);
+ 189 234 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free);
+ 190 234 : tommy_hashdyn_done(&state->importset);
+ 191 234 : tommy_hashdyn_done(&state->previmportset);
+ 192 234 : tommy_hashdyn_done(&state->searchset);
+ 193 234 : tommy_arrayblkof_done(&state->infoarr);
+ 194 234 : }
+ 195 :
+ 196 : /**
+ 197 : * Check the configuration.
+ 198 : */
+ 199 254 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk)
+ 200 : {
+ 201 : tommy_node* i;
+ 202 : unsigned l;
+ 203 :
+ 204 : /* check for parity level */
+ 205 254 : if (state->raid_mode == RAID_MODE_VANDERMONDE) {
+ 206 0 : if (state->level > 3) {
+ 207 : /* LCOV_EXCL_START */
+ 208 : log_fatal("If you use the z-parity you cannot have more than 3 parities.\n");
+ 209 : exit(EXIT_FAILURE);
+ 210 : /* LCOV_EXCL_STIO */
+ 211 : }
+ 212 : }
213 :
- 214 9301 : for (l = 0; l < state->level; ++l) {
- 215 7868 : if (pathcmp(state->parity[l].path, content->content) == 0) {
- 216 : /* LCOV_EXCL_START */
- 217 : log_fatal("Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content);
- 218 : exit(EXIT_FAILURE);
- 219 : /* LCOV_EXCL_STOP */
- 220 : }
- 221 : }
- 222 : }
- 223 :
- 224 : /* check device of data disks */
- 225 246 : if (!state->opt.skip_device && !state->opt.skip_disk_access) {
- 226 0 : for (i = state->disklist; i != 0; i = i->next) {
- 227 : tommy_node* j;
- 228 0 : struct snapraid_disk* disk = i->data;
+ 214 : for (l = 0; l < state->level; ++l) {
+ 215 : if (state->parity[l].path[0] == 0) {
+ 216 : /* LCOV_EXCL_START */
+ 217 : log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path);
+ 218 : exit(EXIT_FAILURE);
+ 219 : /* LCOV_EXCL_STOP */
+ 220 : }
+ 221 : }
+ 222 :
+ 223 254 : if (tommy_list_empty(&state->contentlist)) {
+ 224 : /* LCOV_EXCL_START */
+ 225 : log_fatal("No 'content' specification in '%s'\n", path);
+ 226 : exit(EXIT_FAILURE);
+ 227 : /* LCOV_EXCL_STOP */
+ 228 : }
229 :
- 230 : /* skip data disks that are not accessible */
- 231 0 : if (disk->skip_access)
- 232 0 : continue;
+ 230 : /* check for equal paths */
+ 231 1743 : for (i = state->contentlist; i != 0; i = i->next) {
+ 232 1489 : struct snapraid_content* content = i->data;
233 :
- 234 : #ifdef _WIN32
- 235 : if (disk->device == 0) {
+ 234 9693 : for (l = 0; l < state->level; ++l) {
+ 235 8204 : if (pathcmp(state->parity[l].path, content->content) == 0) {
236 : /* LCOV_EXCL_START */
- 237 : log_fatal("Disk '%s' has a zero serial number.\n", disk->dir);
- 238 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n");
- 239 : log_fatal("it's better to change the serial number of the disk.\n");
- 240 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
- 241 : exit(EXIT_FAILURE);
- 242 : /* LCOV_EXCL_STOP */
- 243 : }
- 244 : #endif
- 245 :
- 246 0 : for (j = i->next; j != 0; j = j->next) {
- 247 0 : struct snapraid_disk* other = j->data;
- 248 0 : if (disk->device == other->device) {
- 249 0 : if (state->opt.force_device) {
- 250 : /* mark disks to be skipped */
- 251 0 : disk->skip_access = 1;
- 252 0 : other->skip_access = 1;
- 253 0 : log_fatal("DANGER! Ignoring that disks '%s' and '%s' are on the same device\n", disk->name, other->name);
- 254 : } else {
- 255 : /* LCOV_EXCL_START */
- 256 : log_fatal("Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir);
- 257 : #ifdef _WIN32
- 258 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
- 259 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
- 260 : log_fatal("to change one of the disk serial.\n");
- 261 : #endif
- 262 : /* in "fix" we allow to continue anyway */
- 263 : if (strcmp(state->command, "fix") == 0) {
- 264 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 265 : }
- 266 : exit(EXIT_FAILURE);
- 267 : /* LCOV_EXCL_STOP */
- 268 : }
- 269 : }
- 270 : }
- 271 :
- 272 : /* skip data disks that are not accessible */
- 273 0 : if (disk->skip_access)
- 274 0 : continue;
- 275 :
- 276 0 : if (!state->opt.skip_parity_access) {
- 277 0 : for (l = 0; l < state->level; ++l) {
- 278 0 : if (disk->device == state->parity[l].device) {
- 279 : /* LCOV_EXCL_START */
- 280 : log_fatal("Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity[l].path);
- 281 : #ifdef _WIN32
- 282 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
- 283 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
- 284 : log_fatal("to change one of the disk serial.\n");
- 285 : #endif
- 286 : exit(EXIT_FAILURE);
- 287 : /* LCOV_EXCL_STOP */
- 288 : }
- 289 : }
- 290 : }
- 291 :
- 292 0 : if (state->pool[0] != 0 && disk->device == state->pool_device) {
- 293 : /* LCOV_EXCL_START */
- 294 : log_fatal("Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool);
- 295 : #ifdef _WIN32
- 296 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
- 297 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
- 298 : log_fatal("to change one of the disk serial.\n");
- 299 : #endif
- 300 : exit(EXIT_FAILURE);
- 301 : /* LCOV_EXCL_STOP */
- 302 : }
- 303 : }
- 304 : }
- 305 :
- 306 : /* check device of parity disks */
- 307 246 : if (!state->opt.skip_device && !state->opt.skip_parity_access) {
- 308 0 : for (l = 0; l < state->level; ++l) {
- 309 : unsigned j;
- 310 :
- 311 : /* skip parity disks that are not accessible */
- 312 0 : if (state->parity[l].skip_access)
- 313 0 : continue;
- 314 :
- 315 : #ifdef _WIN32
- 316 : if (state->parity[l].device == 0) {
- 317 : /* LCOV_EXCL_START */
- 318 : log_fatal("Disk '%s' has a zero serial number.\n", state->parity[l].path);
- 319 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n");
- 320 : log_fatal("it's better to change the serial number of the disk.\n");
- 321 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
- 322 : exit(EXIT_FAILURE);
- 323 : /* LCOV_EXCL_STOP */
- 324 : }
- 325 : #endif
+ 237 : log_fatal("Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content);
+ 238 : exit(EXIT_FAILURE);
+ 239 : /* LCOV_EXCL_STOP */
+ 240 : }
+ 241 : }
+ 242 : }
+ 243 :
+ 244 : /* check device of data disks */
+ 245 254 : if (!state->opt.skip_device && !state->opt.skip_disk_access) {
+ 246 0 : for (i = state->disklist; i != 0; i = i->next) {
+ 247 : tommy_node* j;
+ 248 0 : struct snapraid_disk* disk = i->data;
+ 249 :
+ 250 : /* skip data disks that are not accessible */
+ 251 0 : if (disk->skip_access)
+ 252 0 : continue;
+ 253 :
+ 254 : #ifdef _WIN32
+ 255 : if (disk->device == 0) {
+ 256 : /* LCOV_EXCL_START */
+ 257 : log_fatal("Disk '%s' has a zero serial number.\n", disk->dir);
+ 258 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n");
+ 259 : log_fatal("it's better to change the serial number of the disk.\n");
+ 260 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
+ 261 : exit(EXIT_FAILURE);
+ 262 : /* LCOV_EXCL_STOP */
+ 263 : }
+ 264 : #endif
+ 265 :
+ 266 0 : for (j = i->next; j != 0; j = j->next) {
+ 267 0 : struct snapraid_disk* other = j->data;
+ 268 0 : if (disk->device == other->device) {
+ 269 0 : if (state->opt.force_device) {
+ 270 : /* mark disks to be skipped */
+ 271 0 : disk->skip_access = 1;
+ 272 0 : other->skip_access = 1;
+ 273 0 : if (!state->opt.no_warnings)
+ 274 0 : log_fatal("DANGER! Ignoring that disks '%s' and '%s' are on the same device\n", disk->name, other->name);
+ 275 : } else {
+ 276 : /* LCOV_EXCL_START */
+ 277 : log_fatal("Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir);
+ 278 : #ifdef _WIN32
+ 279 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
+ 280 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
+ 281 : log_fatal("to change one of the disk serial.\n");
+ 282 : #endif
+ 283 : /* in "fix" we allow to continue anyway */
+ 284 : if (strcmp(state->command, "fix") == 0) {
+ 285 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 286 : }
+ 287 : exit(EXIT_FAILURE);
+ 288 : /* LCOV_EXCL_STOP */
+ 289 : }
+ 290 : }
+ 291 : }
+ 292 :
+ 293 : /* skip data disks that are not accessible */
+ 294 0 : if (disk->skip_access)
+ 295 0 : continue;
+ 296 :
+ 297 0 : if (!state->opt.skip_parity_access) {
+ 298 0 : for (l = 0; l < state->level; ++l) {
+ 299 0 : if (disk->device == state->parity[l].device) {
+ 300 : /* LCOV_EXCL_START */
+ 301 : log_fatal("Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity[l].path);
+ 302 : #ifdef _WIN32
+ 303 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
+ 304 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
+ 305 : log_fatal("to change one of the disk serial.\n");
+ 306 : #endif
+ 307 : exit(EXIT_FAILURE);
+ 308 : /* LCOV_EXCL_STOP */
+ 309 : }
+ 310 : }
+ 311 : }
+ 312 :
+ 313 0 : if (state->pool[0] != 0 && disk->device == state->pool_device) {
+ 314 : /* LCOV_EXCL_START */
+ 315 : log_fatal("Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool);
+ 316 : #ifdef _WIN32
+ 317 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device);
+ 318 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
+ 319 : log_fatal("to change one of the disk serial.\n");
+ 320 : #endif
+ 321 : exit(EXIT_FAILURE);
+ 322 : /* LCOV_EXCL_STOP */
+ 323 : }
+ 324 : }
+ 325 : }
326 :
- 327 0 : for (j = l + 1; j < state->level; ++j) {
- 328 0 : if (state->parity[l].device == state->parity[j].device) {
- 329 0 : if (state->opt.force_device) {
- 330 : /* mark disks to be skipped */
- 331 0 : state->parity[l].skip_access = 1;
- 332 0 : state->parity[j].skip_access = 1;
- 333 0 : log_fatal("DANGER! Skipping parities '%s' and '%s' on the same device\n", lev_config_name(l), lev_config_name(j));
- 334 : } else {
- 335 : /* LCOV_EXCL_START */
- 336 : log_fatal("Parity '%s' and '%s' are on the same device.\n", state->parity[l].path, state->parity[j].path);
- 337 : #ifdef _WIN32
- 338 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->parity[l].device);
- 339 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
- 340 : log_fatal("to change one of the disk serial.\n");
- 341 : #endif
- 342 : /* in "fix" we allow to continue anyway */
- 343 : if (strcmp(state->command, "fix") == 0) {
- 344 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 345 : }
- 346 : exit(EXIT_FAILURE);
- 347 : /* LCOV_EXCL_STOP */
- 348 : }
- 349 : }
- 350 : }
- 351 :
- 352 : /* skip parity disks that are not accessible */
- 353 0 : if (state->parity[l].skip_access)
- 354 0 : continue;
- 355 :
- 356 0 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].device) {
- 357 : /* LCOV_EXCL_START */
- 358 : log_fatal("Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].path);
+ 327 : /* check device of parity disks */
+ 328 254 : if (!state->opt.skip_device && !state->opt.skip_parity_access) {
+ 329 0 : for (l = 0; l < state->level; ++l) {
+ 330 : unsigned j;
+ 331 :
+ 332 : /* skip parity disks that are not accessible */
+ 333 0 : if (state->parity[l].skip_access)
+ 334 0 : continue;
+ 335 :
+ 336 : #ifdef _WIN32
+ 337 : if (state->parity[l].device == 0) {
+ 338 : /* LCOV_EXCL_START */
+ 339 : log_fatal("Disk '%s' has a zero serial number.\n", state->parity[l].path);
+ 340 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n");
+ 341 : log_fatal("it's better to change the serial number of the disk.\n");
+ 342 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
+ 343 : exit(EXIT_FAILURE);
+ 344 : /* LCOV_EXCL_STOP */
+ 345 : }
+ 346 : #endif
+ 347 :
+ 348 0 : for (j = l + 1; j < state->level; ++j) {
+ 349 0 : if (state->parity[l].device == state->parity[j].device) {
+ 350 0 : if (state->opt.force_device) {
+ 351 : /* mark disks to be skipped */
+ 352 0 : state->parity[l].skip_access = 1;
+ 353 0 : state->parity[j].skip_access = 1;
+ 354 0 : if (!state->opt.no_warnings)
+ 355 0 : log_fatal("DANGER! Skipping parities '%s' and '%s' on the same device\n", lev_config_name(l), lev_config_name(j));
+ 356 : } else {
+ 357 : /* LCOV_EXCL_START */
+ 358 : log_fatal("Parity '%s' and '%s' are on the same device.\n", state->parity[l].path, state->parity[j].path);
359 : #ifdef _WIN32
- 360 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->pool_device);
- 361 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
- 362 : log_fatal("to change one of the disk serial.\n");
+ 360 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->parity[l].device);
+ 361 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
+ 362 : log_fatal("to change one of the disk serial.\n");
363 : #endif
- 364 : exit(EXIT_FAILURE);
- 365 : /* LCOV_EXCL_STOP */
- 366 : }
- 367 : }
- 368 : }
- 369 :
- 370 : /* check device of pool disk */
- 371 : #ifdef _WIN32
- 372 : if (!state->opt.skip_device) {
- 373 : if (state->pool[0] != 0 && state->pool_device == 0) {
- 374 : /* LCOV_EXCL_START */
- 375 : log_fatal("Disk '%s' has a zero serial number.\n", state->pool);
- 376 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n");
- 377 : log_fatal("it's better to change the serial number of the disk.\n");
- 378 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
- 379 : exit(EXIT_FAILURE);
- 380 : /* LCOV_EXCL_STOP */
- 381 : }
- 382 : }
- 383 : #endif
- 384 :
- 385 : /* count the content files */
- 386 246 : if (!state->opt.skip_device && !state->opt.skip_content_access) {
- 387 : unsigned content_count;
- 388 :
- 389 0 : content_count = 0;
- 390 0 : for (i = state->contentlist; i != 0; i = i->next) {
- 391 : tommy_node* j;
- 392 0 : struct snapraid_content* content = i->data;
- 393 :
- 394 : /* check if there are others in the same disk */
- 395 0 : for (j = i->next; j != 0; j = j->next) {
- 396 0 : struct snapraid_content* other = j->data;
- 397 0 : if (content->device == other->device) {
- 398 0 : break;
- 399 : }
- 400 : }
- 401 0 : if (j != 0) {
- 402 : /* skip it */
- 403 0 : continue;
- 404 : }
- 405 :
- 406 0 : ++content_count;
- 407 : }
- 408 :
- 409 0 : if (content_count < state->level + 1) {
- 410 : /* LCOV_EXCL_START */
- 411 : log_fatal("You must have at least %d 'content' files in different disks.\n", state->level + 1);
- 412 : exit(EXIT_FAILURE);
- 413 : /* LCOV_EXCL_STOP */
- 414 : }
- 415 : }
- 416 :
- 417 : /* check for speed */
- 418 : #ifdef CONFIG_X86
- 419 246 : if (!raid_cpu_has_ssse3())
- 420 : #endif
- 421 0 : if (state->raid_mode == RAID_MODE_CAUCHY) {
- 422 0 : if (state->level == 3) {
- 423 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation for triple parity.\n");
- 424 0 : log_fatal("WARNING! It's recommended to switch to 'z-parity' instead than '3-parity'.\n");
- 425 0 : } else if (state->level > 3) {
- 426 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n");
- 427 0 : log_fatal("WARNING! It's recommended to reduce the parity levels to triple parity.\n");
- 428 : }
- 429 : }
+ 364 : /* in "fix" we allow to continue anyway */
+ 365 : if (strcmp(state->command, "fix") == 0) {
+ 366 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 367 : }
+ 368 : exit(EXIT_FAILURE);
+ 369 : /* LCOV_EXCL_STOP */
+ 370 : }
+ 371 : }
+ 372 : }
+ 373 :
+ 374 : /* skip parity disks that are not accessible */
+ 375 0 : if (state->parity[l].skip_access)
+ 376 0 : continue;
+ 377 :
+ 378 0 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].device) {
+ 379 : /* LCOV_EXCL_START */
+ 380 : log_fatal("Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].path);
+ 381 : #ifdef _WIN32
+ 382 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->pool_device);
+ 383 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n");
+ 384 : log_fatal("to change one of the disk serial.\n");
+ 385 : #endif
+ 386 : exit(EXIT_FAILURE);
+ 387 : /* LCOV_EXCL_STOP */
+ 388 : }
+ 389 : }
+ 390 : }
+ 391 :
+ 392 : /* check device of pool disk */
+ 393 : #ifdef _WIN32
+ 394 : if (!state->opt.skip_device) {
+ 395 : if (state->pool[0] != 0 && state->pool_device == 0) {
+ 396 : /* LCOV_EXCL_START */
+ 397 : log_fatal("Disk '%s' has a zero serial number.\n", state->pool);
+ 398 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n");
+ 399 : log_fatal("it's better to change the serial number of the disk.\n");
+ 400 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n");
+ 401 : exit(EXIT_FAILURE);
+ 402 : /* LCOV_EXCL_STOP */
+ 403 : }
+ 404 : }
+ 405 : #endif
+ 406 :
+ 407 : /* count the content files */
+ 408 254 : if (!state->opt.skip_device && !state->opt.skip_content_access) {
+ 409 : unsigned content_count;
+ 410 :
+ 411 0 : content_count = 0;
+ 412 0 : for (i = state->contentlist; i != 0; i = i->next) {
+ 413 : tommy_node* j;
+ 414 0 : struct snapraid_content* content = i->data;
+ 415 :
+ 416 : /* check if there are others in the same disk */
+ 417 0 : for (j = i->next; j != 0; j = j->next) {
+ 418 0 : struct snapraid_content* other = j->data;
+ 419 0 : if (content->device == other->device) {
+ 420 0 : break;
+ 421 : }
+ 422 : }
+ 423 0 : if (j != 0) {
+ 424 : /* skip it */
+ 425 0 : continue;
+ 426 : }
+ 427 :
+ 428 0 : ++content_count;
+ 429 : }
430 :
- 431 : /* ensure that specified filter disks are valid ones */
- 432 254 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
- 433 : tommy_node* j;
- 434 8 : struct snapraid_filter* filter = i->data;
- 435 43 : for (j = state->disklist; j != 0; j = j->next) {
- 436 38 : struct snapraid_disk* disk = j->data;
- 437 38 : if (fnmatch(filter->pattern, disk->name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
- 438 3 : break;
- 439 : }
- 440 8 : if (j == 0) {
- 441 : /* check matching with parity disks */
- 442 20 : for (l = 0; l < state->level; ++l)
- 443 20 : if (fnmatch(filter->pattern, lev_config_name(l), FNM_CASEINSENSITIVE_FOR_WIN) == 0)
- 444 5 : break;
- 445 5 : if (l == state->level) {
- 446 : /* LCOV_EXCL_START */
- 447 : log_fatal("Option -d, --filter-disk %s doesn't match any data or parity disk.\n", filter->pattern);
- 448 : exit(EXIT_FAILURE);
- 449 : /* LCOV_EXCL_STOP */
- 450 : }
- 451 : }
- 452 : }
- 453 246 : }
- 454 :
- 455 : /**
- 456 : * Validate the smartctl command.
- 457 : *
- 458 : * It must contains only one %s string, and not other % chars.
- 459 : */
- 460 344 : static int validate_smartctl(const char* custom)
- 461 : {
- 462 344 : const char* s = custom;
- 463 344 : int arg = 0;
- 464 :
- 465 2408 : while (*s) {
- 466 1720 : if (s[0] == '%' && s[1] == 's') {
- 467 172 : if (arg) {
+ 431 0 : if (content_count < state->level + 1) {
+ 432 : /* LCOV_EXCL_START */
+ 433 : log_fatal("You must have at least %d 'content' files in different disks.\n", state->level + 1);
+ 434 : exit(EXIT_FAILURE);
+ 435 : /* LCOV_EXCL_STOP */
+ 436 : }
+ 437 : }
+ 438 :
+ 439 : /* check for speed */
+ 440 : #ifdef CONFIG_X86
+ 441 254 : if (!raid_cpu_has_ssse3())
+ 442 : #endif
+ 443 0 : if (state->raid_mode == RAID_MODE_CAUCHY && !state->opt.no_warnings) {
+ 444 0 : if (state->level == 3) {
+ 445 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation for triple parity.\n");
+ 446 0 : log_fatal("WARNING! It's recommended to switch to 'z-parity' instead than '3-parity'.\n");
+ 447 0 : } else if (state->level > 3) {
+ 448 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n");
+ 449 0 : log_fatal("WARNING! It's recommended to reduce the parity levels to triple parity.\n");
+ 450 : }
+ 451 : }
+ 452 :
+ 453 : /* ensure that specified filter disks are valid ones */
+ 454 262 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
+ 455 : tommy_node* j;
+ 456 8 : struct snapraid_filter* filter = i->data;
+ 457 43 : for (j = state->disklist; j != 0; j = j->next) {
+ 458 38 : struct snapraid_disk* disk = j->data;
+ 459 38 : if (fnmatch(filter->pattern, disk->name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 460 3 : break;
+ 461 : }
+ 462 8 : if (j == 0) {
+ 463 : /* check matching with parity disks */
+ 464 20 : for (l = 0; l < state->level; ++l)
+ 465 20 : if (fnmatch(filter->pattern, lev_config_name(l), FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 466 5 : break;
+ 467 5 : if (l == state->level) {
468 : /* LCOV_EXCL_START */
- 469 : return -1;
- 470 : /* LCOV_EXCL_STOP */
- 471 : }
- 472 172 : arg = 1;
- 473 1548 : } else if (s[0] == '%') {
- 474 : /* LCOV_EXCL_START */
- 475 : return -1;
- 476 : /* LCOV_EXCL_STOP */
- 477 : }
- 478 :
- 479 1720 : ++s;
- 480 : }
- 481 :
- 482 344 : return 0;
- 483 : }
- 484 :
- 485 247 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk)
- 486 : {
- 487 : STREAM* f;
- 488 : unsigned line;
- 489 : tommy_node* i;
- 490 : unsigned l;
- 491 :
- 492 : /* copy the options */
- 493 247 : state->opt = *opt;
- 494 :
- 495 : /* if unset, sort by physical order */
- 496 247 : if (!state->opt.force_order)
- 497 1 : state->opt.force_order = SORT_PHYSICAL;
- 498 :
- 499 : /* adjust file mode */
- 500 247 : if (state->opt.skip_sequential)
- 501 1 : state->file_mode &= ~MODE_SEQUENTIAL;
- 502 :
- 503 : /* store current command */
- 504 247 : state->command = command;
- 505 :
- 506 247 : log_tag("conf:%s\n", path);
- 507 :
- 508 247 : f = sopen_read(path);
- 509 247 : if (!f) {
- 510 : /* LCOV_EXCL_START */
- 511 : if (errno == ENOENT) {
- 512 : log_fatal("No configuration file found at '%s'\n", path);
- 513 : } else if (errno == EACCES) {
- 514 : log_fatal("You do not have rights to access the configuration file '%s'\n", path);
- 515 : } else {
- 516 : log_fatal("Error opening the configuration file '%s'. %s.\n", path, strerror(errno));
- 517 : }
- 518 : exit(EXIT_FAILURE);
- 519 : /* LCOV_EXCL_STOP */
- 520 : }
- 521 :
- 522 247 : line = 1;
- 523 : while (1) {
- 524 : char tag[PATH_MAX];
- 525 : char buffer[PATH_MAX];
- 526 : int ret;
- 527 : int c;
- 528 : unsigned level;
+ 469 : log_fatal("Option -d, --filter-disk %s doesn't match any data or parity disk.\n", filter->pattern);
+ 470 : exit(EXIT_FAILURE);
+ 471 : /* LCOV_EXCL_STOP */
+ 472 : }
+ 473 : }
+ 474 : }
+ 475 254 : }
+ 476 :
+ 477 : /**
+ 478 : * Validate the smartctl command.
+ 479 : *
+ 480 : * It must contains only one %s string, and not other % chars.
+ 481 : */
+ 482 358 : static int validate_smartctl(const char* custom)
+ 483 : {
+ 484 358 : const char* s = custom;
+ 485 358 : int arg = 0;
+ 486 :
+ 487 2506 : while (*s) {
+ 488 1790 : if (s[0] == '%' && s[1] == 's') {
+ 489 179 : if (arg) {
+ 490 : /* LCOV_EXCL_START */
+ 491 : return -1;
+ 492 : /* LCOV_EXCL_STOP */
+ 493 : }
+ 494 179 : arg = 1;
+ 495 1611 : } else if (s[0] == '%') {
+ 496 : /* LCOV_EXCL_START */
+ 497 : return -1;
+ 498 : /* LCOV_EXCL_STOP */
+ 499 : }
+ 500 :
+ 501 1790 : ++s;
+ 502 : }
+ 503 :
+ 504 358 : return 0;
+ 505 : }
+ 506 :
+ 507 255 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk)
+ 508 : {
+ 509 : STREAM* f;
+ 510 : unsigned line;
+ 511 : tommy_node* i;
+ 512 : unsigned l;
+ 513 :
+ 514 : /* copy the options */
+ 515 255 : state->opt = *opt;
+ 516 :
+ 517 : /* if unset, sort by physical order */
+ 518 255 : if (!state->opt.force_order)
+ 519 1 : state->opt.force_order = SORT_PHYSICAL;
+ 520 :
+ 521 : /* adjust file mode */
+ 522 255 : if (state->opt.skip_sequential)
+ 523 1 : state->file_mode &= ~MODE_SEQUENTIAL;
+ 524 :
+ 525 : /* store current command */
+ 526 255 : state->command = command;
+ 527 :
+ 528 255 : log_tag("conf:%s\n", path);
529 :
- 530 : /* skip initial spaces */
- 531 5808 : sgetspace(f);
- 532 :
- 533 : /* read the command */
- 534 5808 : ret = sgettok(f, tag, sizeof(tag));
- 535 5808 : if (ret < 0) {
- 536 : /* LCOV_EXCL_START */
- 537 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
- 538 : exit(EXIT_FAILURE);
- 539 : /* LCOV_EXCL_STOP */
- 540 : }
- 541 :
- 542 : /* skip spaces after the command */
- 543 5808 : sgetspace(f);
- 544 :
- 545 5808 : if (strcmp(tag, "blocksize") == 0
- 546 : /* block_size is the old format of the option */
- 547 5561 : || strcmp(tag, "block_size") == 0) {
- 548 :
- 549 247 : ret = sgetu32(f, &state->block_size);
- 550 247 : if (ret < 0) {
- 551 : /* LCOV_EXCL_START */
- 552 : log_fatal("Invalid 'blocksize' specification in '%s' at line %u\n", path, line);
- 553 : exit(EXIT_FAILURE);
- 554 : /* LCOV_EXCL_STOP */
- 555 : }
- 556 247 : if (state->block_size < 1) {
- 557 : /* LCOV_EXCL_START */
- 558 : log_fatal("Too small 'blocksize' specification in '%s' at line %u\n", path, line);
- 559 : exit(EXIT_FAILURE);
- 560 : /* LCOV_EXCL_STOP */
- 561 : }
- 562 247 : if (state->block_size > 16 * 1024) {
- 563 : /* LCOV_EXCL_START */
- 564 : log_fatal("Too big 'blocksize' specification in '%s' at line %u\n", path, line);
- 565 : exit(EXIT_FAILURE);
- 566 : /* LCOV_EXCL_STOP */
- 567 : }
- 568 : /* check if it's a power of 2 */
- 569 247 : if ((state->block_size & (state->block_size - 1)) != 0) {
- 570 : /* LCOV_EXCL_START */
- 571 : log_fatal("Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line);
- 572 : exit(EXIT_FAILURE);
- 573 : /* LCOV_EXCL_STOP */
- 574 : }
- 575 247 : state->block_size *= 1024;
- 576 5561 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) {
- 577 : char device[PATH_MAX];
- 578 : char* slash;
- 579 : uint64_t dev;
- 580 : int skip_access;
- 581 :
- 582 1193 : if (*state->parity[level].path) {
- 583 : /* LCOV_EXCL_START */
- 584 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line);
- 585 : exit(EXIT_FAILURE);
- 586 : /* LCOV_EXCL_STOP */
- 587 : }
- 588 :
- 589 1193 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 590 1193 : if (ret < 0) {
- 591 : /* LCOV_EXCL_START */
- 592 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line);
- 593 : exit(EXIT_FAILURE);
- 594 : /* LCOV_EXCL_STOP */
- 595 : }
- 596 :
- 597 1193 : if (!*buffer) {
- 598 : /* LCOV_EXCL_START */
- 599 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line);
- 600 : exit(EXIT_FAILURE);
- 601 : /* LCOV_EXCL_STOP */
- 602 : }
+ 530 255 : f = sopen_read(path);
+ 531 255 : if (!f) {
+ 532 : /* LCOV_EXCL_START */
+ 533 : if (errno == ENOENT) {
+ 534 : log_fatal("No configuration file found at '%s'\n", path);
+ 535 : } else if (errno == EACCES) {
+ 536 : log_fatal("You do not have rights to access the configuration file '%s'\n", path);
+ 537 : } else {
+ 538 : log_fatal("Error opening the configuration file '%s'. %s.\n", path, strerror(errno));
+ 539 : }
+ 540 : exit(EXIT_FAILURE);
+ 541 : /* LCOV_EXCL_STOP */
+ 542 : }
+ 543 :
+ 544 255 : line = 1;
+ 545 : while (1) {
+ 546 : char tag[PATH_MAX];
+ 547 : char buffer[PATH_MAX];
+ 548 : int ret;
+ 549 : int c;
+ 550 : unsigned level;
+ 551 :
+ 552 : /* skip initial spaces */
+ 553 6015 : sgetspace(f);
+ 554 :
+ 555 : /* read the command */
+ 556 6015 : ret = sgettok(f, tag, sizeof(tag));
+ 557 6015 : if (ret < 0) {
+ 558 : /* LCOV_EXCL_START */
+ 559 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
+ 560 : exit(EXIT_FAILURE);
+ 561 : /* LCOV_EXCL_STOP */
+ 562 : }
+ 563 :
+ 564 : /* skip spaces after the command */
+ 565 6015 : sgetspace(f);
+ 566 :
+ 567 6015 : if (strcmp(tag, "blocksize") == 0
+ 568 : /* block_size is the old format of the option */
+ 569 5760 : || strcmp(tag, "block_size") == 0) {
+ 570 :
+ 571 255 : ret = sgetu32(f, &state->block_size);
+ 572 255 : if (ret < 0) {
+ 573 : /* LCOV_EXCL_START */
+ 574 : log_fatal("Invalid 'blocksize' specification in '%s' at line %u\n", path, line);
+ 575 : exit(EXIT_FAILURE);
+ 576 : /* LCOV_EXCL_STOP */
+ 577 : }
+ 578 255 : if (state->block_size < 1) {
+ 579 : /* LCOV_EXCL_START */
+ 580 : log_fatal("Too small 'blocksize' specification in '%s' at line %u\n", path, line);
+ 581 : exit(EXIT_FAILURE);
+ 582 : /* LCOV_EXCL_STOP */
+ 583 : }
+ 584 255 : if (state->block_size > 16 * 1024) {
+ 585 : /* LCOV_EXCL_START */
+ 586 : log_fatal("Too big 'blocksize' specification in '%s' at line %u\n", path, line);
+ 587 : exit(EXIT_FAILURE);
+ 588 : /* LCOV_EXCL_STOP */
+ 589 : }
+ 590 : /* check if it's a power of 2 */
+ 591 255 : if ((state->block_size & (state->block_size - 1)) != 0) {
+ 592 : /* LCOV_EXCL_START */
+ 593 : log_fatal("Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line);
+ 594 : exit(EXIT_FAILURE);
+ 595 : /* LCOV_EXCL_STOP */
+ 596 : }
+ 597 255 : state->block_size *= 1024;
+ 598 5760 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) {
+ 599 : char device[PATH_MAX];
+ 600 : char* slash;
+ 601 : uint64_t dev;
+ 602 : int skip_access;
603 :
- 604 1193 : pathimport(state->parity[level].path, sizeof(state->parity[level].path), buffer);
- 605 :
- 606 1193 : skip_access = 0;
- 607 1193 : if (!state->opt.skip_parity_access) {
- 608 : struct stat st;
- 609 :
- 610 : /* get the device of the directory containing the parity file */
- 611 1018 : pathimport(device, sizeof(device), buffer);
- 612 1018 : slash = strrchr(device, '/');
- 613 1018 : if (slash)
- 614 1018 : *slash = 0;
- 615 : else
- 616 0 : pathcpy(device, sizeof(device), ".");
- 617 :
- 618 1018 : if (stat(device, &st) == 0) {
- 619 1016 : dev = st.st_dev;
- 620 : } else {
- 621 : /* if the disk can be skipped */
- 622 2 : if (state->opt.force_device) {
- 623 : /* use a fake device, and mark the disk to be skipped */
- 624 1 : dev = 0;
- 625 1 : skip_access = 1;
- 626 1 : log_fatal("DANGER! Skipping unaccessible parity disk '%s'...\n", tag);
- 627 : } else {
- 628 : /* LCOV_EXCL_START */
- 629 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line);
- 630 :
- 631 : /* in "fix" we allow to continue anyway */
- 632 : if (strcmp(state->command, "fix") == 0) {
- 633 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 634 : }
- 635 : exit(EXIT_FAILURE);
- 636 : /* LCOV_EXCL_STOP */
- 637 : }
- 638 : }
- 639 : } else {
- 640 : /* use a fake device */
- 641 175 : dev = 0;
- 642 : }
- 643 :
- 644 1192 : state->parity[level].device = dev;
- 645 1192 : state->parity[level].skip_access = skip_access;
- 646 :
- 647 : /* adjust the level */
- 648 1192 : if (state->level < level + 1)
- 649 945 : state->level = level + 1;
- 650 4368 : } else if (strcmp(tag, "share") == 0) {
- 651 34 : if (*state->share) {
- 652 : /* LCOV_EXCL_START */
- 653 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line);
- 654 : exit(EXIT_FAILURE);
- 655 : /* LCOV_EXCL_STOP */
- 656 : }
- 657 :
- 658 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 659 34 : if (ret < 0) {
- 660 : /* LCOV_EXCL_START */
- 661 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line);
- 662 : exit(EXIT_FAILURE);
- 663 : /* LCOV_EXCL_STOP */
+ 604 1241 : if (*state->parity[level].path) {
+ 605 : /* LCOV_EXCL_START */
+ 606 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line);
+ 607 : exit(EXIT_FAILURE);
+ 608 : /* LCOV_EXCL_STOP */
+ 609 : }
+ 610 :
+ 611 1241 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 612 1241 : if (ret < 0) {
+ 613 : /* LCOV_EXCL_START */
+ 614 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line);
+ 615 : exit(EXIT_FAILURE);
+ 616 : /* LCOV_EXCL_STOP */
+ 617 : }
+ 618 :
+ 619 1241 : if (!*buffer) {
+ 620 : /* LCOV_EXCL_START */
+ 621 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line);
+ 622 : exit(EXIT_FAILURE);
+ 623 : /* LCOV_EXCL_STOP */
+ 624 : }
+ 625 :
+ 626 1241 : pathimport(state->parity[level].path, sizeof(state->parity[level].path), buffer);
+ 627 :
+ 628 1241 : skip_access = 0;
+ 629 1241 : if (!state->opt.skip_parity_access) {
+ 630 : struct stat st;
+ 631 :
+ 632 : /* get the device of the directory containing the parity file */
+ 633 1066 : pathimport(device, sizeof(device), buffer);
+ 634 1066 : slash = strrchr(device, '/');
+ 635 1066 : if (slash)
+ 636 1066 : *slash = 0;
+ 637 : else
+ 638 0 : pathcpy(device, sizeof(device), ".");
+ 639 :
+ 640 1066 : if (stat(device, &st) == 0) {
+ 641 1064 : dev = st.st_dev;
+ 642 : } else {
+ 643 : /* if the disk can be skipped */
+ 644 2 : if (state->opt.force_device) {
+ 645 : /* use a fake device, and mark the disk to be skipped */
+ 646 1 : dev = 0;
+ 647 1 : skip_access = 1;
+ 648 1 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag);
+ 649 : } else {
+ 650 : /* LCOV_EXCL_START */
+ 651 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line);
+ 652 :
+ 653 : /* in "fix" we allow to continue anyway */
+ 654 : if (strcmp(state->command, "fix") == 0) {
+ 655 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 656 : }
+ 657 : exit(EXIT_FAILURE);
+ 658 : /* LCOV_EXCL_STOP */
+ 659 : }
+ 660 : }
+ 661 : } else {
+ 662 : /* use a fake device */
+ 663 175 : dev = 0;
664 : }
665 :
- 666 34 : if (!*buffer) {
- 667 : /* LCOV_EXCL_START */
- 668 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line);
- 669 : exit(EXIT_FAILURE);
- 670 : /* LCOV_EXCL_STOP */
- 671 : }
- 672 :
- 673 34 : pathimport(state->share, sizeof(state->share), buffer);
- 674 4334 : } else if (strcmp(tag, "pool") == 0) {
- 675 : struct stat st;
- 676 :
- 677 34 : if (*state->pool) {
- 678 : /* LCOV_EXCL_START */
- 679 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line);
- 680 : exit(EXIT_FAILURE);
- 681 : /* LCOV_EXCL_STOP */
- 682 : }
- 683 :
- 684 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 685 34 : if (ret < 0) {
- 686 : /* LCOV_EXCL_START */
- 687 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line);
- 688 : exit(EXIT_FAILURE);
- 689 : /* LCOV_EXCL_STOP */
- 690 : }
- 691 :
- 692 34 : if (!*buffer) {
- 693 : /* LCOV_EXCL_START */
- 694 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line);
- 695 : exit(EXIT_FAILURE);
- 696 : /* LCOV_EXCL_STOP */
- 697 : }
+ 666 1240 : state->parity[level].device = dev;
+ 667 1240 : state->parity[level].skip_access = skip_access;
+ 668 :
+ 669 : /* adjust the level */
+ 670 1240 : if (state->level < level + 1)
+ 671 985 : state->level = level + 1;
+ 672 4519 : } else if (strcmp(tag, "share") == 0) {
+ 673 34 : if (*state->share) {
+ 674 : /* LCOV_EXCL_START */
+ 675 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line);
+ 676 : exit(EXIT_FAILURE);
+ 677 : /* LCOV_EXCL_STOP */
+ 678 : }
+ 679 :
+ 680 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 681 34 : if (ret < 0) {
+ 682 : /* LCOV_EXCL_START */
+ 683 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line);
+ 684 : exit(EXIT_FAILURE);
+ 685 : /* LCOV_EXCL_STOP */
+ 686 : }
+ 687 :
+ 688 34 : if (!*buffer) {
+ 689 : /* LCOV_EXCL_START */
+ 690 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line);
+ 691 : exit(EXIT_FAILURE);
+ 692 : /* LCOV_EXCL_STOP */
+ 693 : }
+ 694 :
+ 695 34 : pathimport(state->share, sizeof(state->share), buffer);
+ 696 4485 : } else if (strcmp(tag, "pool") == 0) {
+ 697 : struct stat st;
698 :
- 699 34 : pathimport(state->pool, sizeof(state->pool), buffer);
- 700 :
- 701 : /* get the device of the directory containing the pool tree */
- 702 34 : if (stat(buffer, &st) != 0) {
- 703 : /* LCOV_EXCL_START */
- 704 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line);
- 705 : exit(EXIT_FAILURE);
- 706 : /* LCOV_EXCL_STOP */
- 707 : }
- 708 :
- 709 34 : state->pool_device = st.st_dev;
- 710 4300 : } else if (strcmp(tag, "content") == 0) {
- 711 : struct snapraid_content* content;
- 712 : char device[PATH_MAX];
- 713 : char* slash;
- 714 : struct stat st;
- 715 : uint64_t dev;
- 716 :
- 717 1433 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 718 1433 : if (ret < 0) {
- 719 : /* LCOV_EXCL_START */
- 720 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line);
- 721 : exit(EXIT_FAILURE);
- 722 : /* LCOV_EXCL_STOP */
- 723 : }
- 724 :
- 725 1433 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) {
- 726 : /* LCOV_EXCL_START */
- 727 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line);
- 728 : exit(EXIT_FAILURE);
- 729 : /* LCOV_EXCL_STOP */
- 730 : }
- 731 :
- 732 1433 : if (!*buffer) {
- 733 : /* LCOV_EXCL_START */
- 734 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line);
- 735 : exit(EXIT_FAILURE);
- 736 : /* LCOV_EXCL_STOP */
- 737 : }
+ 699 34 : if (*state->pool) {
+ 700 : /* LCOV_EXCL_START */
+ 701 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line);
+ 702 : exit(EXIT_FAILURE);
+ 703 : /* LCOV_EXCL_STOP */
+ 704 : }
+ 705 :
+ 706 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 707 34 : if (ret < 0) {
+ 708 : /* LCOV_EXCL_START */
+ 709 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line);
+ 710 : exit(EXIT_FAILURE);
+ 711 : /* LCOV_EXCL_STOP */
+ 712 : }
+ 713 :
+ 714 34 : if (!*buffer) {
+ 715 : /* LCOV_EXCL_START */
+ 716 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line);
+ 717 : exit(EXIT_FAILURE);
+ 718 : /* LCOV_EXCL_STOP */
+ 719 : }
+ 720 :
+ 721 34 : pathimport(state->pool, sizeof(state->pool), buffer);
+ 722 :
+ 723 : /* get the device of the directory containing the pool tree */
+ 724 34 : if (stat(buffer, &st) != 0) {
+ 725 : /* LCOV_EXCL_START */
+ 726 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line);
+ 727 : exit(EXIT_FAILURE);
+ 728 : /* LCOV_EXCL_STOP */
+ 729 : }
+ 730 :
+ 731 34 : state->pool_device = st.st_dev;
+ 732 4451 : } else if (strcmp(tag, "content") == 0) {
+ 733 : struct snapraid_content* content;
+ 734 : char device[PATH_MAX];
+ 735 : char* slash;
+ 736 : struct stat st;
+ 737 : uint64_t dev;
738 :
- 739 : /* check if the content file is already specified */
- 740 5367 : for (i = state->contentlist; i != 0; i = i->next) {
- 741 3934 : content = i->data;
- 742 3934 : if (pathcmp(content->content, buffer) == 0)
- 743 0 : break;
- 744 : }
- 745 1433 : if (i) {
- 746 : /* LCOV_EXCL_START */
- 747 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line);
- 748 : exit(EXIT_FAILURE);
- 749 : /* LCOV_EXCL_STOP */
- 750 : }
- 751 :
- 752 : /* get the device of the directory containing the content file */
- 753 1433 : pathimport(device, sizeof(device), buffer);
- 754 1433 : slash = strrchr(device, '/');
- 755 1433 : if (slash)
- 756 1433 : *slash = 0;
- 757 : else
- 758 0 : pathcpy(device, sizeof(device), ".");
- 759 1433 : if (stat(device, &st) == 0) {
- 760 1432 : dev = st.st_dev;
- 761 : } else {
- 762 1 : if (state->opt.skip_content_access) {
- 763 : /* use a fake device */
- 764 1 : dev = 0;
- 765 1 : log_fatal("WARNING! Skipping unaccessible content file '%s'...\n", buffer);
- 766 : } else {
- 767 : /* LCOV_EXCL_START */
- 768 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line);
- 769 : exit(EXIT_FAILURE);
- 770 : /* LCOV_EXCL_STOP */
- 771 : }
+ 739 1489 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 740 1489 : if (ret < 0) {
+ 741 : /* LCOV_EXCL_START */
+ 742 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line);
+ 743 : exit(EXIT_FAILURE);
+ 744 : /* LCOV_EXCL_STOP */
+ 745 : }
+ 746 :
+ 747 1489 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) {
+ 748 : /* LCOV_EXCL_START */
+ 749 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line);
+ 750 : exit(EXIT_FAILURE);
+ 751 : /* LCOV_EXCL_STOP */
+ 752 : }
+ 753 :
+ 754 1489 : if (!*buffer) {
+ 755 : /* LCOV_EXCL_START */
+ 756 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line);
+ 757 : exit(EXIT_FAILURE);
+ 758 : /* LCOV_EXCL_STOP */
+ 759 : }
+ 760 :
+ 761 : /* check if the content file is already specified */
+ 762 5591 : for (i = state->contentlist; i != 0; i = i->next) {
+ 763 4102 : content = i->data;
+ 764 4102 : if (pathcmp(content->content, buffer) == 0)
+ 765 0 : break;
+ 766 : }
+ 767 1489 : if (i) {
+ 768 : /* LCOV_EXCL_START */
+ 769 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line);
+ 770 : exit(EXIT_FAILURE);
+ 771 : /* LCOV_EXCL_STOP */
772 : }
773 :
- 774 : /* set the lock file at the first accessible content file */
- 775 1433 : if (state->lockfile[0] == 0 && dev != 0) {
- 776 246 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer);
- 777 246 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock");
- 778 : }
- 779 :
- 780 1433 : content = content_alloc(buffer, dev);
- 781 :
- 782 1433 : tommy_list_insert_tail(&state->contentlist, &content->node, content);
- 783 2867 : } else if (strcmp(tag, "disk") == 0) {
- 784 : char dir[PATH_MAX];
- 785 : char device[PATH_MAX];
- 786 : struct snapraid_disk* disk;
- 787 : uint64_t dev;
- 788 : int skip_access;
- 789 :
- 790 1471 : ret = sgettok(f, buffer, sizeof(buffer));
- 791 1471 : if (ret < 0) {
- 792 : /* LCOV_EXCL_START */
- 793 : log_fatal("Invalid 'disk' name specification in '%s' at line %u\n", path, line);
- 794 : exit(EXIT_FAILURE);
- 795 : /* LCOV_EXCL_STOP */
- 796 : }
- 797 :
- 798 1471 : if (!*buffer) {
- 799 : /* LCOV_EXCL_START */
- 800 : log_fatal("Empty 'disk' name specification in '%s' at line %u\n", path, line);
- 801 : exit(EXIT_FAILURE);
- 802 : /* LCOV_EXCL_STOP */
- 803 : }
- 804 :
- 805 1471 : sgetspace(f);
- 806 :
- 807 1471 : ret = sgetlasttok(f, dir, sizeof(dir));
- 808 1471 : if (ret < 0) {
- 809 : /* LCOV_EXCL_START */
- 810 : log_fatal("Invalid 'disk' dir specification in '%s' at line %u\n", path, line);
- 811 : exit(EXIT_FAILURE);
- 812 : /* LCOV_EXCL_STOP */
- 813 : }
- 814 :
- 815 1471 : if (!*dir) {
- 816 : /* LCOV_EXCL_START */
- 817 : log_fatal("Empty 'disk' dir specification in '%s' at line %u\n", path, line);
- 818 : exit(EXIT_FAILURE);
- 819 : /* LCOV_EXCL_STOP */
- 820 : }
- 821 :
- 822 : /* get the device of the dir */
- 823 1471 : pathimport(device, sizeof(device), dir);
- 824 :
- 825 : /* check if the disk name already exists */
- 826 5136 : for (i = state->disklist; i != 0; i = i->next) {
- 827 3665 : disk = i->data;
- 828 3665 : if (strcmp(disk->name, buffer) == 0)
- 829 0 : break;
- 830 : }
- 831 1471 : if (i) {
+ 774 : /* get the device of the directory containing the content file */
+ 775 1489 : pathimport(device, sizeof(device), buffer);
+ 776 1489 : slash = strrchr(device, '/');
+ 777 1489 : if (slash)
+ 778 1489 : *slash = 0;
+ 779 : else
+ 780 0 : pathcpy(device, sizeof(device), ".");
+ 781 1489 : if (stat(device, &st) == 0) {
+ 782 1488 : dev = st.st_dev;
+ 783 : } else {
+ 784 1 : if (state->opt.skip_content_access) {
+ 785 : /* use a fake device */
+ 786 1 : dev = 0;
+ 787 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer);
+ 788 : } else {
+ 789 : /* LCOV_EXCL_START */
+ 790 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line);
+ 791 : exit(EXIT_FAILURE);
+ 792 : /* LCOV_EXCL_STOP */
+ 793 : }
+ 794 : }
+ 795 :
+ 796 : /* set the lock file at the first accessible content file */
+ 797 1489 : if (state->lockfile[0] == 0 && dev != 0) {
+ 798 254 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer);
+ 799 254 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock");
+ 800 : }
+ 801 :
+ 802 1489 : content = content_alloc(buffer, dev);
+ 803 :
+ 804 1489 : tommy_list_insert_tail(&state->contentlist, &content->node, content);
+ 805 2962 : } else if (strcmp(tag, "disk") == 0) {
+ 806 : char dir[PATH_MAX];
+ 807 : char device[PATH_MAX];
+ 808 : char uuid[UUID_MAX];
+ 809 : struct snapraid_disk* disk;
+ 810 : uint64_t dev;
+ 811 : int skip_access;
+ 812 :
+ 813 1519 : ret = sgettok(f, buffer, sizeof(buffer));
+ 814 1519 : if (ret < 0) {
+ 815 : /* LCOV_EXCL_START */
+ 816 : log_fatal("Invalid 'disk' name specification in '%s' at line %u\n", path, line);
+ 817 : exit(EXIT_FAILURE);
+ 818 : /* LCOV_EXCL_STOP */
+ 819 : }
+ 820 :
+ 821 1519 : if (!*buffer) {
+ 822 : /* LCOV_EXCL_START */
+ 823 : log_fatal("Empty 'disk' name specification in '%s' at line %u\n", path, line);
+ 824 : exit(EXIT_FAILURE);
+ 825 : /* LCOV_EXCL_STOP */
+ 826 : }
+ 827 :
+ 828 1519 : sgetspace(f);
+ 829 :
+ 830 1519 : ret = sgetlasttok(f, dir, sizeof(dir));
+ 831 1519 : if (ret < 0) {
832 : /* LCOV_EXCL_START */
- 833 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
+ 833 : log_fatal("Invalid 'disk' dir specification in '%s' at line %u\n", path, line);
834 : exit(EXIT_FAILURE);
835 : /* LCOV_EXCL_STOP */
836 : }
837 :
- 838 : /* if the disk has to be present */
- 839 1471 : skip_access = 0;
- 840 1471 : if (!state->opt.skip_disk_access) {
- 841 : struct stat st;
- 842 :
- 843 1327 : if (stat(device, &st) == 0) {
- 844 1326 : dev = st.st_dev;
- 845 : } else {
- 846 : /* if the disk can be skipped */
- 847 1 : if (state->opt.force_device) {
- 848 : /* use a fake device, and mark the disk to be skipped */
- 849 1 : dev = 0;
- 850 1 : skip_access = 1;
- 851 1 : log_fatal("DANGER! Skipping unaccessible data disk '%s'...\n", buffer);
- 852 : } else {
- 853 : /* LCOV_EXCL_START */
- 854 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line);
- 855 :
- 856 : /* in "fix" we allow to continue anyway */
- 857 : if (strcmp(state->command, "fix") == 0) {
- 858 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 859 : }
- 860 : exit(EXIT_FAILURE);
- 861 : /* LCOV_EXCL_STOP */
- 862 : }
- 863 : }
- 864 : } else {
- 865 : /* use a fake device */
- 866 144 : dev = 0;
- 867 : }
+ 838 1519 : if (!*dir) {
+ 839 : /* LCOV_EXCL_START */
+ 840 : log_fatal("Empty 'disk' dir specification in '%s' at line %u\n", path, line);
+ 841 : exit(EXIT_FAILURE);
+ 842 : /* LCOV_EXCL_STOP */
+ 843 : }
+ 844 :
+ 845 : /* get the device of the dir */
+ 846 1519 : pathimport(device, sizeof(device), dir);
+ 847 :
+ 848 : /* check if the disk name already exists */
+ 849 5304 : for (i = state->disklist; i != 0; i = i->next) {
+ 850 3785 : disk = i->data;
+ 851 3785 : if (strcmp(disk->name, buffer) == 0)
+ 852 0 : break;
+ 853 : }
+ 854 1519 : if (i) {
+ 855 : /* LCOV_EXCL_START */
+ 856 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
+ 857 : exit(EXIT_FAILURE);
+ 858 : /* LCOV_EXCL_STOP */
+ 859 : }
+ 860 :
+ 861 : /* if the disk has to be present */
+ 862 1519 : skip_access = 0;
+ 863 1519 : if (!state->opt.skip_disk_access) {
+ 864 : struct stat st;
+ 865 :
+ 866 1375 : if (stat(device, &st) == 0) {
+ 867 1374 : dev = st.st_dev;
868 :
- 869 1471 : disk = disk_alloc(buffer, dir, dev, skip_access);
- 870 :
- 871 1471 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
- 872 1396 : } else if (strcmp(tag, "smartctl") == 0) {
- 873 : char custom[PATH_MAX];
- 874 :
- 875 344 : ret = sgettok(f, buffer, sizeof(buffer));
- 876 344 : if (ret < 0) {
- 877 : /* LCOV_EXCL_START */
- 878 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line);
- 879 : exit(EXIT_FAILURE);
- 880 : /* LCOV_EXCL_STOP */
- 881 : }
- 882 :
- 883 344 : if (!*buffer) {
- 884 : /* LCOV_EXCL_START */
- 885 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line);
- 886 : exit(EXIT_FAILURE);
- 887 : /* LCOV_EXCL_STOP */
- 888 : }
- 889 :
- 890 344 : sgetspace(f);
- 891 :
- 892 344 : ret = sgetlasttok(f, custom, sizeof(custom));
- 893 344 : if (ret < 0) {
- 894 : /* LCOV_EXCL_START */
- 895 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
- 896 : exit(EXIT_FAILURE);
- 897 : /* LCOV_EXCL_STOP */
- 898 : }
- 899 :
- 900 344 : if (!*custom) {
- 901 : /* LCOV_EXCL_START */
- 902 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line);
- 903 : exit(EXIT_FAILURE);
- 904 : /* LCOV_EXCL_STOP */
- 905 : }
+ 869 : /* read the uuid, if unsupported use an empty one */
+ 870 1374 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) {
+ 871 0 : *uuid = 0;
+ 872 : }
+ 873 :
+ 874 : /* fake a different UUID when testing */
+ 875 1374 : if (state->opt.fake_uuid) {
+ 876 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid);
+ 877 2 : --state->opt.fake_uuid;
+ 878 : }
+ 879 : } else {
+ 880 : /* if the disk can be skipped */
+ 881 1 : if (state->opt.force_device) {
+ 882 : /* use a fake device, and mark the disk to be skipped */
+ 883 1 : dev = 0;
+ 884 1 : *uuid = 0;
+ 885 1 : skip_access = 1;
+ 886 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer);
+ 887 : } else {
+ 888 : /* LCOV_EXCL_START */
+ 889 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line);
+ 890 :
+ 891 : /* in "fix" we allow to continue anyway */
+ 892 : if (strcmp(state->command, "fix") == 0) {
+ 893 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 894 : }
+ 895 : exit(EXIT_FAILURE);
+ 896 : /* LCOV_EXCL_STOP */
+ 897 : }
+ 898 : }
+ 899 : } else {
+ 900 : /* use a fake device */
+ 901 144 : dev = 0;
+ 902 144 : *uuid = 0;
+ 903 : }
+ 904 :
+ 905 1519 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access);
906 :
- 907 344 : if (validate_smartctl(custom) != 0) {
- 908 : /* LCOV_EXCL_START */
- 909 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
- 910 : exit(EXIT_FAILURE);
- 911 : /* LCOV_EXCL_STOP */
- 912 : }
- 913 :
- 914 : /* search for parity */
- 915 344 : if (lev_config_scan(buffer, &level, 0) == 0) {
- 916 172 : if (state->parity[level].smartctl[0] != 0) {
- 917 : /* LCOV_EXCL_START */
- 918 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line);
- 919 : exit(EXIT_FAILURE);
- 920 : /* LCOV_EXCL_STOP */
- 921 : }
- 922 :
- 923 172 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom);
- 924 : } else {
- 925 : /* search the disk */
- 926 : struct snapraid_disk* disk;
- 927 172 : for (i = state->disklist; i != 0; i = i->next) {
- 928 172 : disk = i->data;
- 929 172 : if (strcmp(disk->name, buffer) == 0)
- 930 172 : break;
- 931 : }
- 932 172 : if (!i) {
- 933 : /* LCOV_EXCL_START */
- 934 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line);
- 935 : exit(EXIT_FAILURE);
- 936 : /* LCOV_EXCL_STOP */
- 937 : }
- 938 172 : if (disk->smartctl[0] != 0) {
- 939 : /* LCOV_EXCL_START */
- 940 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
- 941 : exit(EXIT_FAILURE);
- 942 : /* LCOV_EXCL_STOP */
- 943 : }
- 944 :
- 945 172 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom);
- 946 : }
- 947 1052 : } else if (strcmp(tag, "nohidden") == 0) {
- 948 0 : state->filter_hidden = 1;
- 949 1052 : } else if (strcmp(tag, "exclude") == 0) {
- 950 : struct snapraid_filter* filter;
- 951 :
- 952 246 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 953 246 : if (ret < 0) {
- 954 : /* LCOV_EXCL_START */
- 955 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line);
- 956 : exit(EXIT_FAILURE);
- 957 : /* LCOV_EXCL_STOP */
- 958 : }
- 959 :
- 960 246 : if (!*buffer) {
- 961 : /* LCOV_EXCL_START */
- 962 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line);
- 963 : exit(EXIT_FAILURE);
- 964 : /* LCOV_EXCL_STOP */
- 965 : }
- 966 :
- 967 246 : filter = filter_alloc_file(-1, buffer);
- 968 246 : if (!filter) {
- 969 : /* LCOV_EXCL_START */
- 970 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
- 971 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
- 972 : exit(EXIT_FAILURE);
- 973 : /* LCOV_EXCL_STOP */
- 974 : }
- 975 246 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
- 976 806 : } else if (strcmp(tag, "include") == 0) {
- 977 : struct snapraid_filter* filter;
- 978 :
- 979 246 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 980 246 : if (ret < 0) {
- 981 : /* LCOV_EXCL_START */
- 982 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line);
- 983 : exit(EXIT_FAILURE);
- 984 : /* LCOV_EXCL_STOP */
- 985 : }
- 986 :
- 987 246 : if (!*buffer) {
- 988 : /* LCOV_EXCL_START */
- 989 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line);
- 990 : exit(EXIT_FAILURE);
- 991 : /* LCOV_EXCL_STOP */
- 992 : }
- 993 :
- 994 246 : filter = filter_alloc_file(1, buffer);
- 995 246 : if (!filter) {
- 996 : /* LCOV_EXCL_START */
- 997 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
- 998 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
- 999 : exit(EXIT_FAILURE);
- 1000 : /* LCOV_EXCL_STOP */
- 1001 : }
- 1002 246 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
- 1003 560 : } else if (strcmp(tag, "autosave") == 0) {
- 1004 : char* e;
- 1005 :
- 1006 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 1007 34 : if (ret < 0) {
- 1008 : /* LCOV_EXCL_START */
- 1009 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
+ 907 1519 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
+ 908 1443 : } else if (strcmp(tag, "smartctl") == 0) {
+ 909 : char custom[PATH_MAX];
+ 910 :
+ 911 358 : ret = sgettok(f, buffer, sizeof(buffer));
+ 912 358 : if (ret < 0) {
+ 913 : /* LCOV_EXCL_START */
+ 914 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line);
+ 915 : exit(EXIT_FAILURE);
+ 916 : /* LCOV_EXCL_STOP */
+ 917 : }
+ 918 :
+ 919 358 : if (!*buffer) {
+ 920 : /* LCOV_EXCL_START */
+ 921 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line);
+ 922 : exit(EXIT_FAILURE);
+ 923 : /* LCOV_EXCL_STOP */
+ 924 : }
+ 925 :
+ 926 358 : sgetspace(f);
+ 927 :
+ 928 358 : ret = sgetlasttok(f, custom, sizeof(custom));
+ 929 358 : if (ret < 0) {
+ 930 : /* LCOV_EXCL_START */
+ 931 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 932 : exit(EXIT_FAILURE);
+ 933 : /* LCOV_EXCL_STOP */
+ 934 : }
+ 935 :
+ 936 358 : if (!*custom) {
+ 937 : /* LCOV_EXCL_START */
+ 938 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 939 : exit(EXIT_FAILURE);
+ 940 : /* LCOV_EXCL_STOP */
+ 941 : }
+ 942 :
+ 943 358 : if (validate_smartctl(custom) != 0) {
+ 944 : /* LCOV_EXCL_START */
+ 945 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 946 : exit(EXIT_FAILURE);
+ 947 : /* LCOV_EXCL_STOP */
+ 948 : }
+ 949 :
+ 950 : /* search for parity */
+ 951 358 : if (lev_config_scan(buffer, &level, 0) == 0) {
+ 952 179 : if (state->parity[level].smartctl[0] != 0) {
+ 953 : /* LCOV_EXCL_START */
+ 954 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line);
+ 955 : exit(EXIT_FAILURE);
+ 956 : /* LCOV_EXCL_STOP */
+ 957 : }
+ 958 :
+ 959 179 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom);
+ 960 : } else {
+ 961 : struct snapraid_disk* disk;
+ 962 :
+ 963 : /* search the disk */
+ 964 179 : disk = 0;
+ 965 179 : for (i = state->disklist; i != 0; i = i->next) {
+ 966 179 : disk = i->data;
+ 967 179 : if (strcmp(disk->name, buffer) == 0)
+ 968 179 : break;
+ 969 : }
+ 970 179 : if (!disk) {
+ 971 : /* LCOV_EXCL_START */
+ 972 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line);
+ 973 : exit(EXIT_FAILURE);
+ 974 : /* LCOV_EXCL_STOP */
+ 975 : }
+ 976 179 : if (disk->smartctl[0] != 0) {
+ 977 : /* LCOV_EXCL_START */
+ 978 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
+ 979 : exit(EXIT_FAILURE);
+ 980 : /* LCOV_EXCL_STOP */
+ 981 : }
+ 982 :
+ 983 179 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom);
+ 984 : }
+ 985 1085 : } else if (strcmp(tag, "nohidden") == 0) {
+ 986 0 : state->filter_hidden = 1;
+ 987 1085 : } else if (strcmp(tag, "exclude") == 0) {
+ 988 : struct snapraid_filter* filter;
+ 989 :
+ 990 254 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 991 254 : if (ret < 0) {
+ 992 : /* LCOV_EXCL_START */
+ 993 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line);
+ 994 : exit(EXIT_FAILURE);
+ 995 : /* LCOV_EXCL_STOP */
+ 996 : }
+ 997 :
+ 998 254 : if (!*buffer) {
+ 999 : /* LCOV_EXCL_START */
+ 1000 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line);
+ 1001 : exit(EXIT_FAILURE);
+ 1002 : /* LCOV_EXCL_STOP */
+ 1003 : }
+ 1004 :
+ 1005 254 : filter = filter_alloc_file(-1, buffer);
+ 1006 254 : if (!filter) {
+ 1007 : /* LCOV_EXCL_START */
+ 1008 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
+ 1009 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
1010 : exit(EXIT_FAILURE);
1011 : /* LCOV_EXCL_STOP */
1012 : }
- 1013 :
- 1014 34 : if (!*buffer) {
- 1015 : /* LCOV_EXCL_START */
- 1016 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line);
- 1017 : exit(EXIT_FAILURE);
- 1018 : /* LCOV_EXCL_STOP */
- 1019 : }
- 1020 :
- 1021 34 : state->autosave = strtoul(buffer, &e, 0);
- 1022 :
- 1023 34 : if (!e || *e) {
- 1024 : /* LCOV_EXCL_START */
- 1025 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
- 1026 : exit(EXIT_FAILURE);
- 1027 : /* LCOV_EXCL_STOP */
- 1028 : }
- 1029 :
- 1030 : /* convert to GB */
- 1031 34 : state->autosave *= GIGA;
- 1032 526 : } else if (tag[0] == 0) {
- 1033 : /* allow empty lines */
- 1034 34 : } else if (tag[0] == '#') {
- 1035 34 : ret = sgetline(f, buffer, sizeof(buffer));
- 1036 34 : if (ret < 0) {
- 1037 : /* LCOV_EXCL_START */
- 1038 : log_fatal("Invalid comment in '%s' at line %u\n", path, line);
- 1039 : exit(EXIT_FAILURE);
- 1040 : /* LCOV_EXCL_STOP */
- 1041 : }
- 1042 : } else {
- 1043 : /* LCOV_EXCL_START */
- 1044 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line);
- 1045 : exit(EXIT_FAILURE);
- 1046 : /* LCOV_EXCL_STOP */
- 1047 : }
- 1048 :
- 1049 : /* skip final spaces */
- 1050 5807 : sgetspace(f);
+ 1013 254 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
+ 1014 831 : } else if (strcmp(tag, "include") == 0) {
+ 1015 : struct snapraid_filter* filter;
+ 1016 :
+ 1017 254 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 1018 254 : if (ret < 0) {
+ 1019 : /* LCOV_EXCL_START */
+ 1020 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line);
+ 1021 : exit(EXIT_FAILURE);
+ 1022 : /* LCOV_EXCL_STOP */
+ 1023 : }
+ 1024 :
+ 1025 254 : if (!*buffer) {
+ 1026 : /* LCOV_EXCL_START */
+ 1027 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line);
+ 1028 : exit(EXIT_FAILURE);
+ 1029 : /* LCOV_EXCL_STOP */
+ 1030 : }
+ 1031 :
+ 1032 254 : filter = filter_alloc_file(1, buffer);
+ 1033 254 : if (!filter) {
+ 1034 : /* LCOV_EXCL_START */
+ 1035 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
+ 1036 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
+ 1037 : exit(EXIT_FAILURE);
+ 1038 : /* LCOV_EXCL_STOP */
+ 1039 : }
+ 1040 254 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
+ 1041 577 : } else if (strcmp(tag, "autosave") == 0) {
+ 1042 : char* e;
+ 1043 :
+ 1044 34 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 1045 34 : if (ret < 0) {
+ 1046 : /* LCOV_EXCL_START */
+ 1047 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
+ 1048 : exit(EXIT_FAILURE);
+ 1049 : /* LCOV_EXCL_STOP */
+ 1050 : }
1051 :
- 1052 : /* next line */
- 1053 5807 : c = sgeteol(f);
- 1054 5807 : if (c == EOF) {
- 1055 246 : break;
- 1056 : }
- 1057 5561 : if (c != '\n') {
- 1058 : /* LCOV_EXCL_START */
- 1059 : log_fatal("Extra data in '%s' at line %u\n", path, line);
- 1060 : exit(EXIT_FAILURE);
- 1061 : /* LCOV_EXCL_STOP */
- 1062 : }
- 1063 5561 : ++line;
- 1064 5561 : }
- 1065 :
- 1066 246 : if (serror(f)) {
- 1067 : /* LCOV_EXCL_START */
- 1068 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
- 1069 : exit(EXIT_FAILURE);
- 1070 : /* LCOV_EXCL_STOP */
- 1071 : }
- 1072 :
- 1073 246 : sclose(f);
- 1074 :
- 1075 246 : state_config_check(state, path, filterlist_disk);
- 1076 :
- 1077 : /* select the default hash */
- 1078 246 : if (state->opt.force_murmur3) {
- 1079 1 : state->besthash = HASH_MURMUR3;
- 1080 245 : } else if (state->opt.force_spooky2) {
- 1081 1 : state->besthash = HASH_SPOOKY2;
- 1082 : } else {
- 1083 : #ifdef CONFIG_X86
- 1084 244 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult())
- 1085 244 : state->besthash = HASH_MURMUR3;
- 1086 : else
- 1087 0 : state->besthash = HASH_SPOOKY2;
- 1088 : #else
- 1089 : if (sizeof(void*) == 4)
- 1090 : state->besthash = HASH_MURMUR3;
- 1091 : else
- 1092 : state->besthash = HASH_SPOOKY2;
- 1093 : #endif
- 1094 : }
- 1095 :
- 1096 : /* by default use the best hash */
- 1097 246 : state->hash = state->besthash;
- 1098 :
- 1099 : /* by default use a random hash seed */
- 1100 246 : if (randomize(state->hashseed, HASH_SIZE) != 0) {
- 1101 : /* LCOV_EXCL_START */
- 1102 : log_fatal("Failed to get random values.\n");
- 1103 : exit(EXIT_FAILURE);
- 1104 : /* LCOV_EXCL_STOP */
- 1105 : }
- 1106 :
- 1107 : /* no previous hash by default */
- 1108 246 : state->prevhash = HASH_UNDEFINED;
- 1109 :
- 1110 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
- 1111 :
- 1112 246 : log_tag("blocksize:%u\n", state->block_size);
- 1113 1717 : for (i = state->disklist; i != 0; i = i->next) {
- 1114 1471 : struct snapraid_disk* disk = i->data;
- 1115 1471 : log_tag("disk:%s:%s\n", disk->name, disk->dir);
- 1116 : }
- 1117 :
- 1118 246 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level));
- 1119 1433 : for (l = 0; l < state->level; ++l)
- 1120 1187 : log_tag("%s:%s\n", lev_config_name(l), state->parity[l].path);
- 1121 246 : if (state->pool[0] != 0)
- 1122 34 : log_tag("pool:%s\n", state->pool);
- 1123 246 : if (state->share[0] != 0)
- 1124 34 : log_tag("share:%s\n", state->share);
- 1125 246 : if (state->autosave != 0)
- 1126 34 : log_tag("autosave:%" PRIu64 "\n", state->autosave);
- 1127 738 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) {
- 1128 : char out[PATH_MAX];
- 1129 492 : struct snapraid_filter* filter = i->data;
- 1130 492 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out)));
- 1131 : }
- 1132 246 : if (state->filter_hidden)
- 1133 0 : log_tag("filter:nohidden:\n");
- 1134 246 : log_flush();
- 1135 246 : }
+ 1052 34 : if (!*buffer) {
+ 1053 : /* LCOV_EXCL_START */
+ 1054 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line);
+ 1055 : exit(EXIT_FAILURE);
+ 1056 : /* LCOV_EXCL_STOP */
+ 1057 : }
+ 1058 :
+ 1059 34 : state->autosave = strtoul(buffer, &e, 0);
+ 1060 :
+ 1061 34 : if (!e || *e) {
+ 1062 : /* LCOV_EXCL_START */
+ 1063 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
+ 1064 : exit(EXIT_FAILURE);
+ 1065 : /* LCOV_EXCL_STOP */
+ 1066 : }
+ 1067 :
+ 1068 : /* convert to GB */
+ 1069 34 : state->autosave *= GIGA;
+ 1070 543 : } else if (tag[0] == 0) {
+ 1071 : /* allow empty lines */
+ 1072 34 : } else if (tag[0] == '#') {
+ 1073 34 : ret = sgetline(f, buffer, sizeof(buffer));
+ 1074 34 : if (ret < 0) {
+ 1075 : /* LCOV_EXCL_START */
+ 1076 : log_fatal("Invalid comment in '%s' at line %u\n", path, line);
+ 1077 : exit(EXIT_FAILURE);
+ 1078 : /* LCOV_EXCL_STOP */
+ 1079 : }
+ 1080 : } else {
+ 1081 : /* LCOV_EXCL_START */
+ 1082 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line);
+ 1083 : exit(EXIT_FAILURE);
+ 1084 : /* LCOV_EXCL_STOP */
+ 1085 : }
+ 1086 :
+ 1087 : /* skip final spaces */
+ 1088 6014 : sgetspace(f);
+ 1089 :
+ 1090 : /* next line */
+ 1091 6014 : c = sgeteol(f);
+ 1092 6014 : if (c == EOF) {
+ 1093 254 : break;
+ 1094 : }
+ 1095 5760 : if (c != '\n') {
+ 1096 : /* LCOV_EXCL_START */
+ 1097 : log_fatal("Extra data in '%s' at line %u\n", path, line);
+ 1098 : exit(EXIT_FAILURE);
+ 1099 : /* LCOV_EXCL_STOP */
+ 1100 : }
+ 1101 5760 : ++line;
+ 1102 5760 : }
+ 1103 :
+ 1104 254 : if (serror(f)) {
+ 1105 : /* LCOV_EXCL_START */
+ 1106 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
+ 1107 : exit(EXIT_FAILURE);
+ 1108 : /* LCOV_EXCL_STOP */
+ 1109 : }
+ 1110 :
+ 1111 254 : sclose(f);
+ 1112 :
+ 1113 254 : state_config_check(state, path, filterlist_disk);
+ 1114 :
+ 1115 : /* select the default hash */
+ 1116 254 : if (state->opt.force_murmur3) {
+ 1117 1 : state->besthash = HASH_MURMUR3;
+ 1118 253 : } else if (state->opt.force_spooky2) {
+ 1119 1 : state->besthash = HASH_SPOOKY2;
+ 1120 : } else {
+ 1121 : #ifdef CONFIG_X86
+ 1122 252 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult())
+ 1123 252 : state->besthash = HASH_MURMUR3;
+ 1124 : else
+ 1125 0 : state->besthash = HASH_SPOOKY2;
+ 1126 : #else
+ 1127 : if (sizeof(void*) == 4)
+ 1128 : state->besthash = HASH_MURMUR3;
+ 1129 : else
+ 1130 : state->besthash = HASH_SPOOKY2;
+ 1131 : #endif
+ 1132 : }
+ 1133 :
+ 1134 : /* by default use the best hash */
+ 1135 254 : state->hash = state->besthash;
1136 :
- 1137 : /**
- 1138 : * Find a disk by name.
- 1139 : */
- 1140 11051 : static struct snapraid_disk* find_disk(struct snapraid_state* state, const char* name)
- 1141 : {
- 1142 : tommy_node* i;
- 1143 :
- 1144 38600 : for (i = state->disklist; i != 0; i = i->next) {
- 1145 38594 : struct snapraid_disk* disk = i->data;
- 1146 38594 : if (strcmp(disk->name, name) == 0)
- 1147 11045 : return disk;
- 1148 : }
+ 1137 : /* by default use a random hash seed */
+ 1138 254 : if (randomize(state->hashseed, HASH_SIZE) != 0) {
+ 1139 : /* LCOV_EXCL_START */
+ 1140 : log_fatal("Failed to get random values.\n");
+ 1141 : exit(EXIT_FAILURE);
+ 1142 : /* LCOV_EXCL_STOP */
+ 1143 : }
+ 1144 :
+ 1145 : /* no previous hash by default */
+ 1146 254 : state->prevhash = HASH_UNDEFINED;
+ 1147 :
+ 1148 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
1149 :
- 1150 6 : if (state->no_conf) {
- 1151 : /* without a configuration file, add disks automatically */
- 1152 : struct snapraid_disk* disk;
- 1153 :
- 1154 6 : disk = disk_alloc(name, "DUMMY/", -1, 0);
+ 1150 254 : log_tag("blocksize:%u\n", state->block_size);
+ 1151 1773 : for (i = state->disklist; i != 0; i = i->next) {
+ 1152 1519 : struct snapraid_disk* disk = i->data;
+ 1153 1519 : log_tag("disk:%s:%s\n", disk->name, disk->dir);
+ 1154 : }
1155 :
- 1156 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
- 1157 :
- 1158 6 : return disk;
- 1159 : }
- 1160 :
- 1161 0 : return 0;
- 1162 : }
- 1163 :
- 1164 : /**
- 1165 : * Update the disk mapping if required.
- 1166 : */
- 1167 241 : static void state_map(struct snapraid_state* state)
- 1168 : {
- 1169 : unsigned hole;
- 1170 : tommy_node* i;
- 1171 : unsigned uuid_mismatch;
- 1172 : unsigned diskcount;
- 1173 : unsigned l;
+ 1156 254 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level));
+ 1157 1489 : for (l = 0; l < state->level; ++l)
+ 1158 1235 : log_tag("%s:%s\n", lev_config_name(l), state->parity[l].path);
+ 1159 254 : if (state->pool[0] != 0)
+ 1160 34 : log_tag("pool:%s\n", state->pool);
+ 1161 254 : if (state->share[0] != 0)
+ 1162 34 : log_tag("share:%s\n", state->share);
+ 1163 254 : if (state->autosave != 0)
+ 1164 34 : log_tag("autosave:%" PRIu64 "\n", state->autosave);
+ 1165 762 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) {
+ 1166 : char out[PATH_MAX];
+ 1167 508 : struct snapraid_filter* filter = i->data;
+ 1168 508 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out)));
+ 1169 : }
+ 1170 254 : if (state->filter_hidden)
+ 1171 0 : log_tag("filter:nohidden:\n");
+ 1172 254 : log_flush();
+ 1173 254 : }
1174 :
- 1175 : /* remove all the mapping without a disk */
- 1176 : /* this happens when a disk is removed from the configuration file */
- 1177 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */
- 1178 : /* when saving the content file, but we keep this code to import older content files. */
- 1179 1781 : for (i = state->maplist; i != 0; ) {
- 1180 1299 : struct snapraid_map* map = i->data;
- 1181 : struct snapraid_disk* disk;
- 1182 :
- 1183 1299 : disk = find_disk(state, map->name);
- 1184 :
- 1185 : /* go to the next mapping before removing */
- 1186 1299 : i = i->next;
+ 1175 : /**
+ 1176 : * Find a disk by name.
+ 1177 : */
+ 1178 6723 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name)
+ 1179 : {
+ 1180 : tommy_node* i;
+ 1181 :
+ 1182 23463 : for (i = state->disklist; i != 0; i = i->next) {
+ 1183 23455 : struct snapraid_disk* disk = i->data;
+ 1184 23455 : if (strcmp(disk->name, name) == 0)
+ 1185 6715 : return disk;
+ 1186 : }
1187 :
- 1188 1299 : if (disk == 0) {
- 1189 : /* disk not found, remove the mapping */
- 1190 0 : tommy_list_remove_existing(&state->maplist, &map->node);
- 1191 0 : map_free(map);
- 1192 : }
- 1193 : }
- 1194 :
- 1195 : /* maps each unmapped disk present in the configuration file in the first available hole */
- 1196 : /* this happens when you add disks for the first time in the configuration file */
- 1197 241 : hole = 0; /* first position to try */
- 1198 1682 : for (i = state->disklist; i != 0; i = i->next) {
- 1199 1441 : struct snapraid_disk* disk = i->data;
- 1200 : struct snapraid_map* map;
- 1201 : tommy_node* j;
- 1202 :
- 1203 : /* check if the disk is already mapped */
- 1204 5031 : for (j = state->maplist; j != 0; j = j->next) {
- 1205 4889 : map = j->data;
- 1206 4889 : if (strcmp(disk->name, map->name) == 0) {
- 1207 : /* mapping found */
- 1208 1299 : break;
- 1209 : }
- 1210 : }
- 1211 1441 : if (j != 0) {
- 1212 : /* mapping is present, then copy the free blocks into to disk */
- 1213 1299 : disk->total_blocks = map->total_blocks;
- 1214 1299 : disk->free_blocks = map->free_blocks;
- 1215 1299 : continue;
- 1216 : }
- 1217 :
- 1218 : /* mapping not found, search for an hole */
- 1219 : while (1) {
- 1220 900 : for (j = state->maplist; j != 0; j = j->next) {
- 1221 758 : map = j->data;
- 1222 758 : if (map->position == hole) {
- 1223 : /* position already used */
- 1224 127 : break;
- 1225 : }
- 1226 : }
- 1227 269 : if (j == 0) {
- 1228 : /* hole found */
- 1229 142 : break;
- 1230 : }
- 1231 :
- 1232 : /* try with the next one */
- 1233 127 : ++hole;
- 1234 127 : }
- 1235 :
- 1236 : /* insert the new mapping */
- 1237 142 : map = map_alloc(disk->name, hole, 0, 0, "");
- 1238 :
- 1239 142 : tommy_list_insert_tail(&state->maplist, &map->node, map);
- 1240 : }
- 1241 :
- 1242 : /* without configuration don't check for number of data disks or uuid changes */
- 1243 241 : if (state->no_conf)
- 1244 242 : return;
+ 1188 8 : if (state->no_conf) {
+ 1189 : /* without a configuration file, add disks automatically */
+ 1190 : struct snapraid_disk* disk;
+ 1191 :
+ 1192 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0);
+ 1193 :
+ 1194 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
+ 1195 :
+ 1196 6 : return disk;
+ 1197 : }
+ 1198 :
+ 1199 2 : return 0;
+ 1200 : }
+ 1201 :
+ 1202 : /**
+ 1203 : * Find a disk by UUID.
+ 1204 : */
+ 1205 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid)
+ 1206 : {
+ 1207 : tommy_node* i;
+ 1208 2 : struct snapraid_disk* found = 0;
+ 1209 :
+ 1210 : /* special test case to find the first matching UUID */
+ 1211 : /* when testing UUID are all equal or not supported */
+ 1212 : /* and we should handle this case specifically */
+ 1213 2 : if (state->opt.match_first_uuid)
+ 1214 2 : return state->disklist->data;
+ 1215 :
+ 1216 : /* LCOV_EXCL_START */
+ 1217 : /* never find an empty uuid */
+ 1218 : if (!*uuid)
+ 1219 : return 0;
+ 1220 :
+ 1221 : for (i = state->disklist; i != 0; i = i->next) {
+ 1222 : struct snapraid_disk* disk = i->data;
+ 1223 : if (strcmp(disk->uuid, uuid) == 0) {
+ 1224 : /* never match duplicate UUID */
+ 1225 : if (found)
+ 1226 : return 0;
+ 1227 : found = disk;
+ 1228 : }
+ 1229 : }
+ 1230 :
+ 1231 : return found;
+ 1232 : /* LCOV_EXCL_STOP */
+ 1233 : }
+ 1234 :
+ 1235 : /**
+ 1236 : * Update the disk mapping if required.
+ 1237 : */
+ 1238 249 : static void state_map(struct snapraid_state* state)
+ 1239 : {
+ 1240 : unsigned hole;
+ 1241 : tommy_node* i;
+ 1242 : unsigned uuid_mismatch;
+ 1243 : unsigned diskcount;
+ 1244 : unsigned l;
1245 :
- 1246 : /* counter for the number of UUID mismatches */
- 1247 240 : uuid_mismatch = 0;
- 1248 :
- 1249 : /* check if mapping match the disk uuid */
- 1250 240 : if (!state->opt.skip_disk_access) {
- 1251 1514 : for (i = state->maplist; i != 0; i = i->next) {
- 1252 1297 : struct snapraid_map* map = i->data;
- 1253 : struct snapraid_disk* disk;
- 1254 : char uuid[UUID_MAX];
- 1255 : int ret;
- 1256 :
- 1257 1297 : disk = find_disk(state, map->name);
- 1258 1297 : if (disk == 0) {
- 1259 : /* LCOV_EXCL_START */
- 1260 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
- 1261 : exit(EXIT_FAILURE);
- 1262 : /* LCOV_EXCL_STOP */
- 1263 : }
- 1264 :
- 1265 1297 : ret = devuuid(disk->device, uuid, sizeof(uuid));
- 1266 1297 : if (ret != 0) {
- 1267 : /* uuid not available, just ignore but marks the disk with unsupported UUID */
- 1268 1 : disk->has_unsupported_uuid = 1;
- 1269 1 : continue;
- 1270 : }
- 1271 :
- 1272 : /* if the uuid is changed */
- 1273 1296 : if (strcmp(uuid, map->uuid) != 0) {
- 1274 : /* mark the disk as with an UUID change */
- 1275 94 : disk->has_different_uuid = 1;
- 1276 :
- 1277 : /* if the previous uuid is available */
- 1278 94 : if (map->uuid[0] != 0) {
- 1279 : /* count the number of uuid change */
- 1280 0 : ++uuid_mismatch;
- 1281 0 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, uuid);
- 1282 : } else {
- 1283 : /* no message here, because having a disk without */
- 1284 : /* UUID is the normal state of an empty disk */
- 1285 94 : disk->had_empty_uuid = 1;
- 1286 : }
- 1287 :
- 1288 : /* update the uuid in the mapping, */
- 1289 94 : pathcpy(map->uuid, sizeof(map->uuid), uuid);
- 1290 :
- 1291 : /* write the new state with the new uuid */
- 1292 94 : state->need_write = 1;
- 1293 : }
- 1294 : }
- 1295 : }
- 1296 :
- 1297 : /* check the parity uuid */
- 1298 240 : if (!state->opt.skip_parity_access) {
- 1299 1188 : for (l = 0; l < state->level; ++l) {
- 1300 : char uuid[UUID_MAX];
- 1301 : int ret;
+ 1246 : /* remove all the mapping without a disk */
+ 1247 : /* this happens when a disk is removed from the configuration file */
+ 1248 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */
+ 1249 : /* when saving the content file, but we keep this code to import older content files. */
+ 1250 1832 : for (i = state->maplist; i != 0; ) {
+ 1251 1334 : struct snapraid_map* map = i->data;
+ 1252 : struct snapraid_disk* disk;
+ 1253 :
+ 1254 1334 : disk = find_disk_by_name(state, map->name);
+ 1255 :
+ 1256 : /* go to the next mapping before removing */
+ 1257 1334 : i = i->next;
+ 1258 :
+ 1259 1334 : if (disk == 0) {
+ 1260 : /* disk not found, remove the mapping */
+ 1261 0 : tommy_list_remove_existing(&state->maplist, &map->node);
+ 1262 0 : map_free(map);
+ 1263 : }
+ 1264 : }
+ 1265 :
+ 1266 : /* maps each unmapped disk present in the configuration file in the first available hole */
+ 1267 : /* this happens when you add disks for the first time in the configuration file */
+ 1268 249 : hole = 0; /* first position to try */
+ 1269 1738 : for (i = state->disklist; i != 0; i = i->next) {
+ 1270 1489 : struct snapraid_disk* disk = i->data;
+ 1271 : struct snapraid_map* map;
+ 1272 : tommy_node* j;
+ 1273 :
+ 1274 : /* check if the disk is already mapped */
+ 1275 5199 : for (j = state->maplist; j != 0; j = j->next) {
+ 1276 5044 : map = j->data;
+ 1277 5044 : if (strcmp(disk->name, map->name) == 0) {
+ 1278 : /* mapping found */
+ 1279 1334 : break;
+ 1280 : }
+ 1281 : }
+ 1282 1489 : if (j != 0) {
+ 1283 : /* mapping is present, then copy the free blocks into to disk */
+ 1284 1334 : disk->total_blocks = map->total_blocks;
+ 1285 1334 : disk->free_blocks = map->free_blocks;
+ 1286 1334 : continue;
+ 1287 : }
+ 1288 :
+ 1289 : /* mapping not found, search for an hole */
+ 1290 : while (1) {
+ 1291 1025 : for (j = state->maplist; j != 0; j = j->next) {
+ 1292 870 : map = j->data;
+ 1293 870 : if (map->position == hole) {
+ 1294 : /* position already used */
+ 1295 144 : break;
+ 1296 : }
+ 1297 : }
+ 1298 299 : if (j == 0) {
+ 1299 : /* hole found */
+ 1300 155 : break;
+ 1301 : }
1302 :
- 1303 982 : ret = devuuid(state->parity[l].device, uuid, sizeof(uuid));
- 1304 982 : if (ret != 0) {
- 1305 : /* uuid not available, just ignore */
- 1306 1 : continue;
- 1307 : }
- 1308 :
- 1309 : /* if the uuid is changed */
- 1310 981 : if (strcmp(uuid, state->parity[l].uuid) != 0) {
- 1311 : /* if the previous uuid is available */
- 1312 46 : if (state->parity[l].uuid[0] != 0) {
- 1313 : /* count the number of uuid change */
- 1314 0 : ++uuid_mismatch;
- 1315 0 : log_fatal("UUID change for parity '%s' from '%s' to '%s'\n", lev_config_name(l), state->parity[l].uuid, uuid);
- 1316 : }
- 1317 :
- 1318 : /* update the uuid */
- 1319 46 : pathcpy(state->parity[l].uuid, sizeof(state->parity[l].uuid), uuid);
- 1320 :
- 1321 : /* write the new state with the new uuid */
- 1322 46 : state->need_write = 1;
- 1323 : }
- 1324 : }
- 1325 : }
- 1326 :
- 1327 240 : if (!state->opt.force_uuid && uuid_mismatch > state->level) {
- 1328 : /* LCOV_EXCL_START */
- 1329 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n");
- 1330 : log_fatal("If this happens because you really replaced them,\n");
- 1331 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command);
- 1332 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n");
- 1333 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n");
- 1334 : exit(EXIT_FAILURE);
- 1335 : /* LCOV_EXCL_STOP */
- 1336 : }
- 1337 :
- 1338 : /* count the number of data disks, including holes left after removing some */
- 1339 240 : diskcount = 0;
- 1340 1675 : for (i = state->maplist; i != 0; i = i->next) {
- 1341 1435 : struct snapraid_map* map = i->data;
- 1342 :
- 1343 1435 : if (map->position + 1 > diskcount)
- 1344 1304 : diskcount = map->position + 1;
- 1345 : }
- 1346 :
- 1347 : /* ensure to don't go over the limit of the RAID engine */
- 1348 240 : if (diskcount > RAID_DATA_MAX) {
- 1349 : /* LCOV_EXCL_START */
- 1350 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX);
- 1351 : exit(EXIT_FAILURE);
- 1352 : /* LCOV_EXCL_STOP */
- 1353 : }
+ 1303 : /* try with the next one */
+ 1304 144 : ++hole;
+ 1305 144 : }
+ 1306 :
+ 1307 : /* insert the new mapping */
+ 1308 155 : map = map_alloc(disk->name, hole, 0, 0, "");
+ 1309 :
+ 1310 155 : tommy_list_insert_tail(&state->maplist, &map->node, map);
+ 1311 : }
+ 1312 :
+ 1313 : /* without configuration don't check for number of data disks or uuid changes */
+ 1314 249 : if (state->no_conf)
+ 1315 250 : return;
+ 1316 :
+ 1317 : /* counter for the number of UUID mismatches */
+ 1318 248 : uuid_mismatch = 0;
+ 1319 :
+ 1320 : /* check if mapping match the disk uuid */
+ 1321 248 : if (!state->opt.skip_disk_access) {
+ 1322 1570 : for (i = state->maplist; i != 0; i = i->next) {
+ 1323 1345 : struct snapraid_map* map = i->data;
+ 1324 : struct snapraid_disk* disk;
+ 1325 :
+ 1326 1345 : disk = find_disk_by_name(state, map->name);
+ 1327 1345 : if (disk == 0) {
+ 1328 : /* LCOV_EXCL_START */
+ 1329 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
+ 1330 : os_abort();
+ 1331 : /* LCOV_EXCL_STOP */
+ 1332 : }
+ 1333 :
+ 1334 1345 : if (disk->has_unsupported_uuid) {
+ 1335 : /* if uuid is not available, skip this one */
+ 1336 1 : continue;
+ 1337 : }
+ 1338 :
+ 1339 : /* if the uuid is changed */
+ 1340 1344 : if (strcmp(disk->uuid, map->uuid) != 0) {
+ 1341 : /* mark the disk as with an UUID change */
+ 1342 109 : disk->has_different_uuid = 1;
+ 1343 :
+ 1344 : /* if the previous uuid is available */
+ 1345 109 : if (map->uuid[0] != 0) {
+ 1346 : /* count the number of uuid change */
+ 1347 2 : ++uuid_mismatch;
+ 1348 2 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid);
+ 1349 : } else {
+ 1350 : /* no message here, because having a disk without */
+ 1351 : /* UUID is the normal state of an empty disk */
+ 1352 107 : disk->had_empty_uuid = 1;
+ 1353 : }
1354 :
- 1355 : /* now count the real number of data disks, excluding holes left after removing some */
- 1356 240 : diskcount = tommy_list_count(&state->maplist);
+ 1355 : /* update the uuid in the mapping, */
+ 1356 109 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid);
1357 :
- 1358 : /* recommend number of parities */
- 1359 240 : if (diskcount >= 36 && state->level < 6) {
- 1360 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
- 1361 240 : } else if (diskcount >= 29 && state->level < 5) {
- 1362 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
- 1363 240 : } else if (diskcount >= 22 && state->level < 4) {
- 1364 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount);
- 1365 240 : } else if (diskcount >= 15 && state->level < 3) {
- 1366 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
- 1367 240 : } else if (diskcount >= 5 && state->level < 2) {
- 1368 34 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
- 1369 : }
- 1370 : }
- 1371 :
- 1372 144 : void state_refresh(struct snapraid_state* state)
- 1373 : {
- 1374 : tommy_node* i;
- 1375 : unsigned l;
- 1376 :
- 1377 : /* for all disks */
- 1378 1006 : for (i = state->maplist; i != 0; i = i->next) {
- 1379 862 : struct snapraid_map* map = i->data;
- 1380 : struct snapraid_disk* disk;
- 1381 : uint64_t total_space;
- 1382 : uint64_t free_space;
- 1383 : int ret;
+ 1358 : /* write the new state with the new uuid */
+ 1359 109 : state->need_write = 1;
+ 1360 : }
+ 1361 : }
+ 1362 : }
+ 1363 :
+ 1364 : /* check the parity uuid */
+ 1365 248 : if (!state->opt.skip_parity_access) {
+ 1366 1244 : for (l = 0; l < state->level; ++l) {
+ 1367 : char uuid[UUID_MAX];
+ 1368 : int ret;
+ 1369 :
+ 1370 1030 : ret = devuuid(state->parity[l].device, uuid, sizeof(uuid));
+ 1371 1030 : if (ret != 0) {
+ 1372 : /* uuid not available, just ignore */
+ 1373 1 : continue;
+ 1374 : }
+ 1375 :
+ 1376 : /* if the uuid is changed */
+ 1377 1029 : if (strcmp(uuid, state->parity[l].uuid) != 0) {
+ 1378 : /* if the previous uuid is available */
+ 1379 46 : if (state->parity[l].uuid[0] != 0) {
+ 1380 : /* count the number of uuid change */
+ 1381 0 : ++uuid_mismatch;
+ 1382 0 : log_fatal("UUID change for parity '%s' from '%s' to '%s'\n", lev_config_name(l), state->parity[l].uuid, uuid);
+ 1383 : }
1384 :
- 1385 862 : disk = find_disk(state, map->name);
- 1386 862 : if (disk == 0) {
- 1387 : /* LCOV_EXCL_START */
- 1388 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
- 1389 : exit(EXIT_FAILURE);
- 1390 : /* LCOV_EXCL_STOP */
+ 1385 : /* update the uuid */
+ 1386 46 : pathcpy(state->parity[l].uuid, sizeof(state->parity[l].uuid), uuid);
+ 1387 :
+ 1388 : /* write the new state with the new uuid */
+ 1389 46 : state->need_write = 1;
+ 1390 : }
1391 : }
- 1392 :
- 1393 862 : ret = fsinfo(disk->dir, 0, &total_space, &free_space);
- 1394 862 : if (ret != 0) {
- 1395 : /* LCOV_EXCL_START */
- 1396 : log_fatal("Error accessing disk '%s' to get filesystem info. %s.\n", disk->dir, strerror(errno));
- 1397 : exit(EXIT_FAILURE);
- 1398 : /* LCOV_EXCL_STOP */
- 1399 : }
- 1400 :
- 1401 : /* set the new free blocks */
- 1402 862 : map->total_blocks = total_space / state->block_size;
- 1403 862 : map->free_blocks = free_space / state->block_size;
+ 1392 : }
+ 1393 :
+ 1394 248 : if (!state->opt.force_uuid && uuid_mismatch > state->level) {
+ 1395 : /* LCOV_EXCL_START */
+ 1396 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n");
+ 1397 : log_fatal("If this happens because you really replaced them,\n");
+ 1398 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command);
+ 1399 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n");
+ 1400 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n");
+ 1401 : exit(EXIT_FAILURE);
+ 1402 : /* LCOV_EXCL_STOP */
+ 1403 : }
1404 :
- 1405 : /* also update the disk info */
- 1406 862 : disk->total_blocks = map->total_blocks;
- 1407 862 : disk->free_blocks = map->free_blocks;
- 1408 : }
+ 1405 : /* count the number of data disks, including holes left after removing some */
+ 1406 248 : diskcount = 0;
+ 1407 1731 : for (i = state->maplist; i != 0; i = i->next) {
+ 1408 1483 : struct snapraid_map* map = i->data;
1409 :
- 1410 : /* for all parities */
- 1411 978 : for (l = 0; l < state->level; ++l) {
- 1412 : uint64_t total_space;
- 1413 : uint64_t free_space;
- 1414 : int ret;
- 1415 :
- 1416 834 : ret = fsinfo(state->parity[l].path, 0, &total_space, &free_space);
- 1417 834 : if (ret != 0) {
- 1418 : /* LCOV_EXCL_START */
- 1419 : log_fatal("Error accessing file '%s' to get filesystem info. %s.\n", state->parity[l].path, strerror(errno));
- 1420 : exit(EXIT_FAILURE);
- 1421 : /* LCOV_EXCL_STOP */
- 1422 : }
- 1423 :
- 1424 : /* set the new free blocks */
- 1425 834 : state->parity[l].total_blocks = total_space / state->block_size;
- 1426 834 : state->parity[l].free_blocks = free_space / state->block_size;
- 1427 : }
- 1428 :
- 1429 : /* note what we don't set need_write = 1, because we don't want */
- 1430 : /* to update the content file only for the free space info. */
- 1431 144 : }
- 1432 :
- 1433 : /**
- 1434 : * Check the content.
- 1435 : */
- 1436 234 : static void state_content_check(struct snapraid_state* state, const char* path)
- 1437 : {
- 1438 : tommy_node* i;
- 1439 :
- 1440 : /* check that any map has different name and position */
- 1441 1633 : for (i = state->maplist; i != 0; i = i->next) {
- 1442 1399 : struct snapraid_map* map = i->data;
- 1443 : tommy_node* j;
- 1444 4884 : for (j = i->next; j != 0; j = j->next) {
- 1445 3485 : struct snapraid_map* other = j->data;
- 1446 3485 : if (strcmp(map->name, other->name) == 0) {
- 1447 : /* LCOV_EXCL_START */
- 1448 : log_fatal("Colliding 'map' disk specification in '%s'\n", path);
- 1449 : exit(EXIT_FAILURE);
- 1450 : /* LCOV_EXCL_STOP */
- 1451 : }
- 1452 3485 : if (map->position == other->position) {
- 1453 : /* LCOV_EXCL_START */
- 1454 : log_fatal("Colliding 'map' index specification in '%s'\n", path);
- 1455 : exit(EXIT_FAILURE);
- 1456 : /* LCOV_EXCL_STOP */
- 1457 : }
- 1458 : }
- 1459 : }
- 1460 234 : }
+ 1410 1483 : if (map->position + 1 > diskcount)
+ 1411 1339 : diskcount = map->position + 1;
+ 1412 : }
+ 1413 :
+ 1414 : /* ensure to don't go over the limit of the RAID engine */
+ 1415 248 : if (diskcount > RAID_DATA_MAX) {
+ 1416 : /* LCOV_EXCL_START */
+ 1417 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX);
+ 1418 : exit(EXIT_FAILURE);
+ 1419 : /* LCOV_EXCL_STOP */
+ 1420 : }
+ 1421 :
+ 1422 : /* now count the real number of data disks, excluding holes left after removing some */
+ 1423 248 : diskcount = tommy_list_count(&state->maplist);
+ 1424 :
+ 1425 : /* recommend number of parities */
+ 1426 248 : if (!state->opt.no_warnings) {
+ 1427 248 : if (diskcount >= 36 && state->level < 6) {
+ 1428 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
+ 1429 248 : } else if (diskcount >= 29 && state->level < 5) {
+ 1430 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
+ 1431 248 : } else if (diskcount >= 22 && state->level < 4) {
+ 1432 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount);
+ 1433 248 : } else if (diskcount >= 15 && state->level < 3) {
+ 1434 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
+ 1435 248 : } else if (diskcount >= 5 && state->level < 2) {
+ 1436 34 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
+ 1437 : }
+ 1438 : }
+ 1439 : }
+ 1440 :
+ 1441 160 : void state_refresh(struct snapraid_state* state)
+ 1442 : {
+ 1443 : tommy_node* i;
+ 1444 : unsigned l;
+ 1445 :
+ 1446 : /* for all disks */
+ 1447 1118 : for (i = state->maplist; i != 0; i = i->next) {
+ 1448 958 : struct snapraid_map* map = i->data;
+ 1449 : struct snapraid_disk* disk;
+ 1450 : uint64_t total_space;
+ 1451 : uint64_t free_space;
+ 1452 : int ret;
+ 1453 :
+ 1454 958 : disk = find_disk_by_name(state, map->name);
+ 1455 958 : if (disk == 0) {
+ 1456 : /* LCOV_EXCL_START */
+ 1457 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
+ 1458 : os_abort();
+ 1459 : /* LCOV_EXCL_STOP */
+ 1460 : }
1461 :
- 1462 : /**
- 1463 : * Check if the position is REQUIRED, or we can completely clear it from the state.
- 1464 : *
- 1465 : * Note that position with only DELETED blocks are discarged.
- 1466 : */
- 1467 729418 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos)
- 1468 : {
- 1469 : tommy_node* i;
- 1470 :
- 1471 : /* check for each disk */
- 1472 773475 : for (i = state->disklist; i != 0; i = i->next) {
- 1473 773475 : struct snapraid_disk* disk = i->data;
- 1474 773475 : struct snapraid_block* block = fs_par2block_get(disk, pos);
- 1475 :
- 1476 : /* if we have at least one file, the position is needed */
- 1477 773475 : if (block_has_file(block))
- 1478 729418 : return 1;
- 1479 : }
- 1480 :
- 1481 0 : return 0;
- 1482 : }
- 1483 :
- 1484 : /**
- 1485 : * Check if the info block is REQUIREQ.
- 1486 : *
- 1487 : * This is used to ensure that we keep the last check used for scrubbing.
- 1488 : * and that we add it when importing old context files.
- 1489 : *
- 1490 : * Note that you can have position without info blocks, for example
- 1491 : * if all the blocks are not synced.
- 1492 : *
- 1493 : * Note also that not requiring an info block, doesn't mean that if present it
- 1494 : * can be discarded.
- 1495 : */
- 1496 1491820 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos)
- 1497 : {
- 1498 : tommy_node* i;
- 1499 :
- 1500 : /* check for each disk */
- 1501 1985452 : for (i = state->disklist; i != 0; i = i->next) {
- 1502 1927007 : struct snapraid_disk* disk = i->data;
- 1503 1927007 : struct snapraid_block* block = fs_par2block_get(disk, pos);
- 1504 :
- 1505 : /* if we have at least one synced file, the info is required */
- 1506 1927007 : if (block_state_get(block) == BLOCK_STATE_BLK)
- 1507 1433375 : return 1;
- 1508 : }
- 1509 :
- 1510 58445 : return 0;
- 1511 : }
- 1512 :
- 1513 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos)
- 1514 : {
- 1515 : tommy_node* i;
- 1516 :
- 1517 : /* check for each disk if block is really used */
- 1518 0 : for (i = state->disklist; i != 0; i = i->next) {
- 1519 0 : struct snapraid_disk* disk = i->data;
- 1520 0 : struct snapraid_block* block = fs_par2block_get(disk, pos);
- 1521 :
- 1522 : /* if the block is deleted */
- 1523 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
- 1524 : /* set it to empty */
- 1525 0 : fs_deallocate(disk, pos);
- 1526 : }
- 1527 : }
- 1528 0 : }
- 1529 :
- 1530 : /**
- 1531 : * Check if a block position in a disk is deleted.
- 1532 : */
- 1533 29344162 : static int fs_is_block_deleted_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t pos)
- 1534 : {
- 1535 29344162 : struct snapraid_block* block = fs_par2block_get_ts(disk, fs_last, pos);
- 1536 :
- 1537 29163541 : return block_state_get(block) == BLOCK_STATE_DELETED;
- 1538 : }
+ 1462 958 : ret = fsinfo(disk->dir, 0, &total_space, &free_space);
+ 1463 958 : if (ret != 0) {
+ 1464 : /* LCOV_EXCL_START */
+ 1465 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
+ 1466 : exit(EXIT_FAILURE);
+ 1467 : /* LCOV_EXCL_STOP */
+ 1468 : }
+ 1469 :
+ 1470 : /* set the new free blocks */
+ 1471 958 : map->total_blocks = total_space / state->block_size;
+ 1472 958 : map->free_blocks = free_space / state->block_size;
+ 1473 :
+ 1474 : /* also update the disk info */
+ 1475 958 : disk->total_blocks = map->total_blocks;
+ 1476 958 : disk->free_blocks = map->free_blocks;
+ 1477 : }
+ 1478 :
+ 1479 : /* for all parities */
+ 1480 1090 : for (l = 0; l < state->level; ++l) {
+ 1481 : uint64_t total_space;
+ 1482 : uint64_t free_space;
+ 1483 : int ret;
+ 1484 :
+ 1485 930 : ret = fsinfo(state->parity[l].path, 0, &total_space, &free_space);
+ 1486 930 : if (ret != 0) {
+ 1487 : /* LCOV_EXCL_START */
+ 1488 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].path, strerror(errno));
+ 1489 : exit(EXIT_FAILURE);
+ 1490 : /* LCOV_EXCL_STOP */
+ 1491 : }
+ 1492 :
+ 1493 : /* set the new free blocks */
+ 1494 930 : state->parity[l].total_blocks = total_space / state->block_size;
+ 1495 930 : state->parity[l].free_blocks = free_space / state->block_size;
+ 1496 : }
+ 1497 :
+ 1498 : /* note what we don't set need_write = 1, because we don't want */
+ 1499 : /* to update the content file only for the free space info. */
+ 1500 160 : }
+ 1501 :
+ 1502 : /**
+ 1503 : * Check the content.
+ 1504 : */
+ 1505 242 : static void state_content_check(struct snapraid_state* state, const char* path)
+ 1506 : {
+ 1507 : tommy_node* i;
+ 1508 :
+ 1509 : /* check that any map has different name and position */
+ 1510 1689 : for (i = state->maplist; i != 0; i = i->next) {
+ 1511 1447 : struct snapraid_map* map = i->data;
+ 1512 : tommy_node* j;
+ 1513 5052 : for (j = i->next; j != 0; j = j->next) {
+ 1514 3605 : struct snapraid_map* other = j->data;
+ 1515 3605 : if (strcmp(map->name, other->name) == 0) {
+ 1516 : /* LCOV_EXCL_START */
+ 1517 : log_fatal("Colliding 'map' disk specification in '%s'\n", path);
+ 1518 : exit(EXIT_FAILURE);
+ 1519 : /* LCOV_EXCL_STOP */
+ 1520 : }
+ 1521 3605 : if (map->position == other->position) {
+ 1522 : /* LCOV_EXCL_START */
+ 1523 : log_fatal("Colliding 'map' index specification in '%s'\n", path);
+ 1524 : exit(EXIT_FAILURE);
+ 1525 : /* LCOV_EXCL_STOP */
+ 1526 : }
+ 1527 : }
+ 1528 : }
+ 1529 242 : }
+ 1530 :
+ 1531 : /**
+ 1532 : * Check if the position is REQUIRED, or we can completely clear it from the state.
+ 1533 : *
+ 1534 : * Note that position with only DELETED blocks are discarged.
+ 1535 : */
+ 1536 752491 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos)
+ 1537 : {
+ 1538 : tommy_node* i;
1539 :
- 1540 : /**
- 1541 : * Flush the file checking the final CRC.
- 1542 : * We exploit the fact that the CRC is always stored in the last 4 bytes.
- 1543 : */
- 1544 1 : static void decoding_error(const char* path, STREAM* f)
- 1545 : {
- 1546 : unsigned char buf[4];
- 1547 : uint32_t crc_stored;
- 1548 : uint32_t crc_computed;
+ 1540 : /* check for each disk */
+ 1541 797220 : for (i = state->disklist; i != 0; i = i->next) {
+ 1542 797220 : struct snapraid_disk* disk = i->data;
+ 1543 797220 : struct snapraid_block* block = fs_par2block_get(disk, pos);
+ 1544 :
+ 1545 : /* if we have at least one file, the position is needed */
+ 1546 797220 : if (block_has_file(block))
+ 1547 752491 : return 1;
+ 1548 : }
1549 :
- 1550 1 : if (seof(f)) {
- 1551 : /* LCOV_EXCL_START */
- 1552 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1553 : log_fatal("This content file is truncated. Use an alternate copy.\n");
- 1554 : exit(EXIT_FAILURE);
- 1555 : /* LCOV_EXCL_STOP */
- 1556 : }
- 1557 :
- 1558 1 : if (serror(f)) {
- 1559 : /* LCOV_EXCL_START */
- 1560 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1561 : exit(EXIT_FAILURE);
- 1562 : /* LCOV_EXCL_STOP */
- 1563 : }
- 1564 :
- 1565 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1566 :
- 1567 1 : if (sdeplete(f, buf) != 0) {
- 1568 : /* LCOV_EXCL_START */
- 1569 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1570 : exit(EXIT_FAILURE);
- 1571 : /* LCOV_EXCL_STOP */
- 1572 : }
+ 1550 0 : return 0;
+ 1551 : }
+ 1552 :
+ 1553 : /**
+ 1554 : * Check if the info block is REQUIREQ.
+ 1555 : *
+ 1556 : * This is used to ensure that we keep the last check used for scrubbing.
+ 1557 : * and that we add it when importing old context files.
+ 1558 : *
+ 1559 : * Note that you can have position without info blocks, for example
+ 1560 : * if all the blocks are not synced.
+ 1561 : *
+ 1562 : * Note also that not requiring an info block, doesn't mean that if present it
+ 1563 : * can be discarded.
+ 1564 : */
+ 1565 1513218 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos)
+ 1566 : {
+ 1567 : tommy_node* i;
+ 1568 :
+ 1569 : /* check for each disk */
+ 1570 2062203 : for (i = state->disklist; i != 0; i = i->next) {
+ 1571 1994271 : struct snapraid_disk* disk = i->data;
+ 1572 1994271 : struct snapraid_block* block = fs_par2block_get(disk, pos);
1573 :
- 1574 : /* get the stored crc from the last four bytes */
- 1575 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
- 1576 :
- 1577 : /* get the computed crc */
- 1578 1 : crc_computed = scrc(f);
- 1579 :
- 1580 : /* adjust the stored crc to include itself */
- 1581 1 : crc_stored = crc32c(crc_stored, buf, 4);
- 1582 :
- 1583 1 : if (crc_computed != crc_stored) {
- 1584 1 : log_fatal("Mismatching CRC in '%s'\n", path);
- 1585 1 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 1586 1 : exit(EXIT_FAILURE);
- 1587 : } else {
- 1588 0 : log_fatal("The file CRC is correct!\n");
- 1589 : }
- 1590 0 : }
- 1591 :
- 1592 235 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f)
- 1593 : {
- 1594 : block_off_t blockmax;
- 1595 : unsigned count_file;
- 1596 : unsigned count_hardlink;
- 1597 : unsigned count_symlink;
- 1598 : unsigned count_dir;
- 1599 : int crc_checked;
- 1600 : char buffer[PATH_MAX];
- 1601 : int ret;
- 1602 : tommy_array disk_mapping;
- 1603 : uint32_t mapping_max;
- 1604 :
- 1605 235 : blockmax = 0;
- 1606 235 : count_file = 0;
- 1607 235 : count_hardlink = 0;
- 1608 235 : count_symlink = 0;
- 1609 235 : count_dir = 0;
- 1610 235 : crc_checked = 0;
- 1611 235 : mapping_max = 0;
- 1612 235 : tommy_array_init(&disk_mapping);
- 1613 :
- 1614 235 : ret = sread(f, buffer, 12);
- 1615 235 : if (ret < 0) {
- 1616 : /* LCOV_EXCL_START */
- 1617 : decoding_error(path, f);
- 1618 : log_fatal("Invalid header!\n");
- 1619 : exit(EXIT_FAILURE);
- 1620 : /* LCOV_EXCL_STOP */
- 1621 : }
- 1622 :
- 1623 : /*
- 1624 : * File format versions:
- 1625 : * - SNAPCNT1/SnapRAID 4.0 First version.
- 1626 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support.
- 1627 : * The previous 'm' entry is now deprecated, but supported for importing.
- 1628 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'.
- 1629 : */
- 1630 235 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0
- 1631 235 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0) {
- 1632 : /* LCOV_EXCL_START */
- 1633 : if (memcmp(buffer, "SNAPCNT", 7) != 0) {
- 1634 : decoding_error(path, f);
- 1635 : log_fatal("Invalid header!\n");
- 1636 : } else {
- 1637 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path);
- 1638 : }
+ 1574 : /* if we have at least one synced file, the info is required */
+ 1575 1994271 : if (block_state_get(block) == BLOCK_STATE_BLK)
+ 1576 1445286 : return 1;
+ 1577 : }
+ 1578 :
+ 1579 67932 : return 0;
+ 1580 : }
+ 1581 :
+ 1582 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos)
+ 1583 : {
+ 1584 : tommy_node* i;
+ 1585 :
+ 1586 : /* check for each disk if block is really used */
+ 1587 0 : for (i = state->disklist; i != 0; i = i->next) {
+ 1588 0 : struct snapraid_disk* disk = i->data;
+ 1589 0 : struct snapraid_block* block = fs_par2block_get(disk, pos);
+ 1590 :
+ 1591 : /* if the block is deleted */
+ 1592 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
+ 1593 : /* set it to empty */
+ 1594 0 : fs_deallocate(disk, pos);
+ 1595 : }
+ 1596 : }
+ 1597 0 : }
+ 1598 :
+ 1599 : /**
+ 1600 : * Check if a block position in a disk is deleted.
+ 1601 : */
+ 1602 4507856 : static int fs_is_block_deleted_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t pos)
+ 1603 : {
+ 1604 4507856 : struct snapraid_block* block = fs_par2block_get_ts(disk, fs_last, pos);
+ 1605 :
+ 1606 4507856 : return block_state_get(block) == BLOCK_STATE_DELETED;
+ 1607 : }
+ 1608 :
+ 1609 : /**
+ 1610 : * Flush the file checking the final CRC.
+ 1611 : * We exploit the fact that the CRC is always stored in the last 4 bytes.
+ 1612 : */
+ 1613 1 : static void decoding_error(const char* path, STREAM* f)
+ 1614 : {
+ 1615 : unsigned char buf[4];
+ 1616 : uint32_t crc_stored;
+ 1617 : uint32_t crc_computed;
+ 1618 :
+ 1619 1 : if (seof(f)) {
+ 1620 : /* LCOV_EXCL_START */
+ 1621 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1622 : log_fatal("This content file is truncated. Use an alternate copy.\n");
+ 1623 : exit(EXIT_FAILURE);
+ 1624 : /* LCOV_EXCL_STOP */
+ 1625 : }
+ 1626 :
+ 1627 1 : if (serror(f)) {
+ 1628 : /* LCOV_EXCL_START */
+ 1629 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1630 : exit(EXIT_FAILURE);
+ 1631 : /* LCOV_EXCL_STOP */
+ 1632 : }
+ 1633 :
+ 1634 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1635 :
+ 1636 1 : if (sdeplete(f, buf) != 0) {
+ 1637 : /* LCOV_EXCL_START */
+ 1638 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
1639 : exit(EXIT_FAILURE);
1640 : /* LCOV_EXCL_STOP */
1641 : }
1642 :
- 1643 : while (1) {
- 1644 : int c;
+ 1643 : /* get the stored crc from the last four bytes */
+ 1644 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
1645 :
- 1646 : /* read the command */
- 1647 3605061 : c = sgetc(f);
- 1648 3605061 : if (c == EOF) {
- 1649 234 : break;
- 1650 : }
+ 1646 : /* get the computed crc */
+ 1647 1 : crc_computed = scrc(f);
+ 1648 :
+ 1649 : /* adjust the stored crc to include itself */
+ 1650 1 : crc_stored = crc32c(crc_stored, buf, 4);
1651 :
- 1652 3604827 : if (c == 'f') {
- 1653 : /* file */
- 1654 : char sub[PATH_MAX];
- 1655 : uint64_t v_size;
- 1656 : uint64_t v_mtime_sec;
- 1657 : uint32_t v_mtime_nsec;
- 1658 : uint64_t v_inode;
- 1659 : uint32_t v_idx;
- 1660 : struct snapraid_file* file;
- 1661 : struct snapraid_disk* disk;
- 1662 : uint32_t mapping;
- 1663 :
- 1664 3485915 : ret = sgetb32(f, &mapping);
- 1665 3485915 : if (ret < 0 || mapping >= mapping_max) {
- 1666 : /* LCOV_EXCL_START */
- 1667 : decoding_error(path, f);
- 1668 : log_fatal("Internal inconsistency in mapping index!\n");
- 1669 : exit(EXIT_FAILURE);
- 1670 : /* LCOV_EXCL_STOP */
- 1671 : }
- 1672 3485915 : disk = tommy_array_get(&disk_mapping, mapping);
+ 1652 1 : if (crc_computed != crc_stored) {
+ 1653 1 : log_fatal("Mismatching CRC in '%s'\n", path);
+ 1654 1 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 1655 1 : exit(EXIT_FAILURE);
+ 1656 : } else {
+ 1657 0 : log_fatal("The file CRC is correct!\n");
+ 1658 : }
+ 1659 0 : }
+ 1660 :
+ 1661 243 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f)
+ 1662 : {
+ 1663 : block_off_t blockmax;
+ 1664 : unsigned count_file;
+ 1665 : unsigned count_hardlink;
+ 1666 : unsigned count_symlink;
+ 1667 : unsigned count_dir;
+ 1668 : int crc_checked;
+ 1669 : char buffer[PATH_MAX];
+ 1670 : int ret;
+ 1671 : tommy_array disk_mapping;
+ 1672 : uint32_t mapping_max;
1673 :
- 1674 3485915 : ret = sgetb64(f, &v_size);
- 1675 3485915 : if (ret < 0) {
- 1676 : /* LCOV_EXCL_START */
- 1677 : decoding_error(path, f);
- 1678 : exit(EXIT_FAILURE);
- 1679 : /* LCOV_EXCL_STOP */
- 1680 : }
- 1681 :
- 1682 : /* check for impossible file size to avoid to crash for a too big allocation */
- 1683 3485915 : if (v_size / state->block_size > blockmax) {
- 1684 : /* LCOV_EXCL_START */
- 1685 : decoding_error(path, f);
- 1686 : log_fatal("Internal inconsistency in file size too big!\n");
- 1687 : exit(EXIT_FAILURE);
- 1688 : /* LCOV_EXCL_STOP */
- 1689 : }
- 1690 :
- 1691 3485915 : ret = sgetb64(f, &v_mtime_sec);
- 1692 3485915 : if (ret < 0) {
- 1693 : /* LCOV_EXCL_START */
- 1694 : decoding_error(path, f);
- 1695 : exit(EXIT_FAILURE);
- 1696 : /* LCOV_EXCL_STOP */
- 1697 : }
- 1698 :
- 1699 3485915 : ret = sgetb32(f, &v_mtime_nsec);
- 1700 3485915 : if (ret < 0) {
- 1701 : /* LCOV_EXCL_START */
- 1702 : decoding_error(path, f);
- 1703 : exit(EXIT_FAILURE);
- 1704 : /* LCOV_EXCL_STOP */
- 1705 : }
- 1706 :
- 1707 : /* STAT_NSEC_INVALID is encoded as 0 */
- 1708 3485915 : if (v_mtime_nsec == 0)
- 1709 0 : v_mtime_nsec = STAT_NSEC_INVALID;
- 1710 : else
- 1711 3485915 : --v_mtime_nsec;
+ 1674 243 : blockmax = 0;
+ 1675 243 : count_file = 0;
+ 1676 243 : count_hardlink = 0;
+ 1677 243 : count_symlink = 0;
+ 1678 243 : count_dir = 0;
+ 1679 243 : crc_checked = 0;
+ 1680 243 : mapping_max = 0;
+ 1681 243 : tommy_array_init(&disk_mapping);
+ 1682 :
+ 1683 243 : ret = sread(f, buffer, 12);
+ 1684 243 : if (ret < 0) {
+ 1685 : /* LCOV_EXCL_START */
+ 1686 : decoding_error(path, f);
+ 1687 : log_fatal("Invalid header!\n");
+ 1688 : os_abort();
+ 1689 : /* LCOV_EXCL_STOP */
+ 1690 : }
+ 1691 :
+ 1692 : /*
+ 1693 : * File format versions:
+ 1694 : * - SNAPCNT1/SnapRAID 4.0 First version.
+ 1695 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support.
+ 1696 : * The previous 'm' entry is now deprecated, but supported for importing.
+ 1697 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'.
+ 1698 : */
+ 1699 243 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0
+ 1700 243 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0) {
+ 1701 : /* LCOV_EXCL_START */
+ 1702 : if (memcmp(buffer, "SNAPCNT", 7) != 0) {
+ 1703 : decoding_error(path, f);
+ 1704 : log_fatal("Invalid header!\n");
+ 1705 : os_abort();
+ 1706 : } else {
+ 1707 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path);
+ 1708 : exit(EXIT_FAILURE);
+ 1709 : }
+ 1710 : /* LCOV_EXCL_STOP */
+ 1711 : }
1712 :
- 1713 3485915 : ret = sgetb64(f, &v_inode);
- 1714 3485915 : if (ret < 0) {
- 1715 : /* LCOV_EXCL_START */
- 1716 : decoding_error(path, f);
- 1717 : exit(EXIT_FAILURE);
- 1718 : /* LCOV_EXCL_STOP */
- 1719 : }
- 1720 :
- 1721 3485915 : ret = sgetbs(f, sub, sizeof(sub));
- 1722 3485915 : if (ret < 0) {
- 1723 : /* LCOV_EXCL_START */
- 1724 : decoding_error(path, f);
- 1725 : exit(EXIT_FAILURE);
- 1726 : /* LCOV_EXCL_STOP */
- 1727 : }
- 1728 3485915 : if (!*sub) {
- 1729 : /* LCOV_EXCL_START */
- 1730 : decoding_error(path, f);
- 1731 : exit(EXIT_FAILURE);
- 1732 : /* LCOV_EXCL_STOP */
- 1733 : }
- 1734 :
- 1735 : /* allocate the file */
- 1736 3485915 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0);
- 1737 :
- 1738 : /* insert the file in the file containers */
- 1739 3485915 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
- 1740 3485915 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
- 1741 3485915 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
- 1742 3485915 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
+ 1713 : while (1) {
+ 1714 : int c;
+ 1715 :
+ 1716 : /* read the command */
+ 1717 3653019 : c = sgetc(f);
+ 1718 3653019 : if (c == EOF) {
+ 1719 242 : break;
+ 1720 : }
+ 1721 :
+ 1722 3652777 : if (c == 'f') {
+ 1723 : /* file */
+ 1724 : char sub[PATH_MAX];
+ 1725 : uint64_t v_size;
+ 1726 : uint64_t v_mtime_sec;
+ 1727 : uint32_t v_mtime_nsec;
+ 1728 : uint64_t v_inode;
+ 1729 : uint32_t v_idx;
+ 1730 : struct snapraid_file* file;
+ 1731 : struct snapraid_disk* disk;
+ 1732 : uint32_t mapping;
+ 1733 :
+ 1734 3532322 : ret = sgetb32(f, &mapping);
+ 1735 3532322 : if (ret < 0 || mapping >= mapping_max) {
+ 1736 : /* LCOV_EXCL_START */
+ 1737 : decoding_error(path, f);
+ 1738 : log_fatal("Internal inconsistency in mapping index!\n");
+ 1739 : os_abort();
+ 1740 : /* LCOV_EXCL_STOP */
+ 1741 : }
+ 1742 3532322 : disk = tommy_array_get(&disk_mapping, mapping);
1743 :
- 1744 : /* read all the blocks */
- 1745 3485915 : v_idx = 0;
- 1746 10477653 : while (v_idx < file->blockmax) {
- 1747 : block_off_t v_pos;
- 1748 : uint32_t v_count;
- 1749 :
- 1750 : /* get the "subcommand */
- 1751 3505823 : c = sgetc(f);
- 1752 :
- 1753 3505823 : ret = sgetb32(f, &v_pos);
- 1754 3505823 : if (ret < 0) {
- 1755 : /* LCOV_EXCL_START */
- 1756 : decoding_error(path, f);
- 1757 : exit(EXIT_FAILURE);
- 1758 : /* LCOV_EXCL_STOP */
- 1759 : }
+ 1744 3532322 : ret = sgetb64(f, &v_size);
+ 1745 3532322 : if (ret < 0) {
+ 1746 : /* LCOV_EXCL_START */
+ 1747 : decoding_error(path, f);
+ 1748 : os_abort();
+ 1749 : /* LCOV_EXCL_STOP */
+ 1750 : }
+ 1751 :
+ 1752 : /* check for impossible file size to avoid to crash for a too big allocation */
+ 1753 3532322 : if (v_size / state->block_size > blockmax) {
+ 1754 : /* LCOV_EXCL_START */
+ 1755 : decoding_error(path, f);
+ 1756 : log_fatal("Internal inconsistency in file size too big!\n");
+ 1757 : os_abort();
+ 1758 : /* LCOV_EXCL_STOP */
+ 1759 : }
1760 :
- 1761 3505823 : ret = sgetb32(f, &v_count);
- 1762 3505823 : if (ret < 0) {
- 1763 : /* LCOV_EXCL_START */
- 1764 : decoding_error(path, f);
- 1765 : exit(EXIT_FAILURE);
- 1766 : /* LCOV_EXCL_STOP */
- 1767 : }
+ 1761 3532322 : ret = sgetb64(f, &v_mtime_sec);
+ 1762 3532322 : if (ret < 0) {
+ 1763 : /* LCOV_EXCL_START */
+ 1764 : decoding_error(path, f);
+ 1765 : os_abort();
+ 1766 : /* LCOV_EXCL_STOP */
+ 1767 : }
1768 :
- 1769 3505823 : if (v_idx + v_count > file->blockmax) {
- 1770 : /* LCOV_EXCL_START */
- 1771 : decoding_error(path, f);
- 1772 : log_fatal("Internal inconsistency in block number!\n");
- 1773 : exit(EXIT_FAILURE);
- 1774 : /* LCOV_EXCL_STOP */
- 1775 : }
+ 1769 3532322 : ret = sgetb32(f, &v_mtime_nsec);
+ 1770 3532322 : if (ret < 0) {
+ 1771 : /* LCOV_EXCL_START */
+ 1772 : decoding_error(path, f);
+ 1773 : os_abort();
+ 1774 : /* LCOV_EXCL_STOP */
+ 1775 : }
1776 :
- 1777 3505823 : if (v_pos + v_count > blockmax) {
- 1778 : /* LCOV_EXCL_START */
- 1779 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count);
- 1780 : decoding_error(path, f);
- 1781 : exit(EXIT_FAILURE);
- 1782 : /* LCOV_EXCL_START */
- 1783 : }
- 1784 :
- 1785 : /* fill the blocks in the run */
- 1786 : while (v_count) {
- 1787 : struct snapraid_block* block = fs_file2block_get(file, v_idx);
- 1788 :
- 1789 : switch (c) {
- 1790 : case 'b' :
- 1791 : block_state_set(block, BLOCK_STATE_BLK);
- 1792 : break;
- 1793 : case 'n' :
- 1794 : /* deprecated NEW blocks are converted to CHG ones */
- 1795 : block_state_set(block, BLOCK_STATE_CHG);
- 1796 : break;
- 1797 : case 'g' :
- 1798 : block_state_set(block, BLOCK_STATE_CHG);
- 1799 : break;
- 1800 : case 'p' :
- 1801 : block_state_set(block, BLOCK_STATE_REP);
- 1802 : break;
- 1803 : default :
- 1804 : /* LCOV_EXCL_START */
- 1805 : decoding_error(path, f);
- 1806 : log_fatal("Invalid block type!\n");
- 1807 : exit(EXIT_FAILURE);
- 1808 : /* LCOV_EXCL_STOP */
- 1809 : }
- 1810 :
- 1811 : /* read the hash only for 'blk/chg/rep', and not for 'new' */
- 1812 8573249 : if (c != 'n') {
- 1813 8573249 : ret = sread(f, block->hash, HASH_SIZE);
- 1814 8573249 : if (ret < 0) {
- 1815 : /* LCOV_EXCL_START */
- 1816 : decoding_error(path, f);
- 1817 : exit(EXIT_FAILURE);
- 1818 : /* LCOV_EXCL_STOP */
- 1819 : }
- 1820 : } else {
- 1821 : /* set the ZERO hash for deprecated NEW blocks */
- 1822 0 : hash_zero_set(block->hash);
- 1823 : }
- 1824 :
- 1825 : /* if the block contains a hash of past data */
- 1826 : /* and we are clearing such undeterminated hashes */
- 1827 8573249 : if (state->clear_past_hash
- 1828 2287366 : && block_has_past_hash(block)
- 1829 : ) {
- 1830 : /* set the hash value to INVALID */
- 1831 57602 : hash_invalid_set(block->hash);
- 1832 : }
- 1833 :
- 1834 : /* if we are disabling the copy optimization */
- 1835 : /* we want also to clear any already previously stored information */
- 1836 : /* in other sync commands */
- 1837 : /* note that this is required only in sync, and we detect */
- 1838 : /* this using the clear_past_hash flag */
- 1839 8573249 : if (state->clear_past_hash
- 1840 2287366 : && state->opt.force_nocopy
- 1841 14115 : && block_state_get(block) == BLOCK_STATE_REP
- 1842 : ) {
- 1843 : /* set the hash value to INVALID */
- 1844 1 : hash_invalid_set(block->hash);
- 1845 : /* convert from REP to CHG block */
- 1846 1 : block_state_set(block, BLOCK_STATE_CHG);
- 1847 : }
- 1848 :
- 1849 : /* if we want a full sync, marks block as invalid parity */
- 1850 : /* note that we do this after the force_nocopy option */
- 1851 : /* to avoid to mixup the two things */
- 1852 8573249 : if (state->opt.force_full
- 1853 27746 : && block_state_get(block) == BLOCK_STATE_BLK) {
- 1854 : /* convert from BLK to REP */
- 1855 27746 : block_state_set(block, BLOCK_STATE_REP);
- 1856 : }
- 1857 :
- 1858 : /* set the parity association */
- 1859 8573249 : fs_allocate(disk, v_pos, file, v_idx);
- 1860 :
- 1861 : /* go to the next block */
- 1862 8573249 : ++v_idx;
- 1863 8573249 : ++v_pos;
- 1864 8573249 : --v_count;
- 1865 : }
- 1866 : }
- 1867 :
- 1868 : /* stat */
- 1869 3485915 : ++count_file;
- 1870 118912 : } else if (c == 'i') {
- 1871 : /* "inf" command */
- 1872 : snapraid_info info;
- 1873 : uint32_t v_pos;
- 1874 : uint32_t v_oldest;
- 1875 :
- 1876 234 : ret = sgetb32(f, &v_oldest);
- 1877 234 : if (ret < 0) {
- 1878 : /* LCOV_EXCL_START */
- 1879 : decoding_error(path, f);
- 1880 : exit(EXIT_FAILURE);
- 1881 : /* LCOV_EXCL_STOP */
- 1882 : }
- 1883 :
- 1884 234 : v_pos = 0;
- 1885 288815 : while (v_pos < blockmax) {
- 1886 : int bad;
- 1887 : int rehash;
- 1888 : int justsynced;
- 1889 : uint32_t t;
- 1890 : uint32_t flag;
- 1891 : uint32_t v_count;
- 1892 :
- 1893 288347 : ret = sgetb32(f, &v_count);
- 1894 288347 : if (ret < 0) {
- 1895 : /* LCOV_EXCL_START */
- 1896 : decoding_error(path, f);
- 1897 : exit(EXIT_FAILURE);
- 1898 : /* LCOV_EXCL_STOP */
- 1899 : }
- 1900 :
- 1901 288347 : if (v_pos + v_count > blockmax) {
- 1902 : /* LCOV_EXCL_START */
- 1903 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count);
- 1904 : decoding_error(path, f);
- 1905 : exit(EXIT_FAILURE);
- 1906 : /* LCOV_EXCL_STOP */
- 1907 : }
- 1908 :
- 1909 288347 : ret = sgetb32(f, &flag);
- 1910 288347 : if (ret < 0) {
- 1911 : /* LCOV_EXCL_START */
- 1912 : decoding_error(path, f);
- 1913 : exit(EXIT_FAILURE);
- 1914 : /* LCOV_EXCL_STOP */
- 1915 : }
- 1916 :
- 1917 : /* if there is an info */
- 1918 288347 : if ((flag & 1) != 0) {
- 1919 : /* read the time */
- 1920 288332 : ret = sgetb32(f, &t);
- 1921 288332 : if (ret < 0) {
- 1922 : /* LCOV_EXCL_START */
- 1923 : decoding_error(path, f);
- 1924 : exit(EXIT_FAILURE);
- 1925 : /* LCOV_EXCL_STOP */
- 1926 : }
- 1927 :
- 1928 : /* analyze the flags */
- 1929 288332 : bad = (flag & 2) != 0;
- 1930 288332 : rehash = (flag & 4) != 0;
- 1931 288332 : justsynced = (flag & 8) != 0;
- 1932 :
- 1933 288332 : if (rehash && state->prevhash == HASH_UNDEFINED) {
- 1934 : /* LCOV_EXCL_START */
- 1935 : decoding_error(path, f);
- 1936 : log_fatal("Internal inconsistency for missing previous checksum!\n");
- 1937 : exit(EXIT_FAILURE);
- 1938 : /* LCOV_EXCL_STOP */
- 1939 : }
- 1940 :
- 1941 288332 : info = info_make(t + v_oldest, bad, rehash, justsynced);
- 1942 : } else {
- 1943 15 : info = 0;
- 1944 : }
- 1945 :
- 1946 2068514 : while (v_count) {
- 1947 : /* insert the info in the array */
- 1948 1491820 : info_set(&state->infoarr, v_pos, info);
- 1949 :
- 1950 : /* ensure that an info is present only for used positions */
- 1951 1491820 : if (fs_info_is_required(state, v_pos)) {
- 1952 1433375 : if (!info) {
- 1953 : /* LCOV_EXCL_START */
- 1954 : decoding_error(path, f);
- 1955 : log_fatal("Internal inconsistency for missing info!\n");
- 1956 : exit(EXIT_FAILURE);
- 1957 : /* LCOV_EXCL_STOP */
- 1958 : }
- 1959 : } else {
- 1960 : /* extra info are accepted for backward compatibility */
- 1961 : /* they are discarged at the first write */
- 1962 : }
+ 1777 : /* STAT_NSEC_INVALID is encoded as 0 */
+ 1778 3532322 : if (v_mtime_nsec == 0)
+ 1779 0 : v_mtime_nsec = STAT_NSEC_INVALID;
+ 1780 : else
+ 1781 3532322 : --v_mtime_nsec;
+ 1782 :
+ 1783 3532322 : ret = sgetb64(f, &v_inode);
+ 1784 3532322 : if (ret < 0) {
+ 1785 : /* LCOV_EXCL_START */
+ 1786 : decoding_error(path, f);
+ 1787 : os_abort();
+ 1788 : /* LCOV_EXCL_STOP */
+ 1789 : }
+ 1790 :
+ 1791 3532322 : ret = sgetbs(f, sub, sizeof(sub));
+ 1792 3532322 : if (ret < 0) {
+ 1793 : /* LCOV_EXCL_START */
+ 1794 : decoding_error(path, f);
+ 1795 : os_abort();
+ 1796 : /* LCOV_EXCL_STOP */
+ 1797 : }
+ 1798 3532321 : if (!*sub) {
+ 1799 : /* LCOV_EXCL_START */
+ 1800 : decoding_error(path, f);
+ 1801 : log_fatal("Internal inconsistency for null file!\n");
+ 1802 : os_abort();
+ 1803 : /* LCOV_EXCL_STOP */
+ 1804 : }
+ 1805 :
+ 1806 : /* allocate the file */
+ 1807 3532321 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0);
+ 1808 :
+ 1809 : /* insert the file in the file containers */
+ 1810 3532321 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 1811 3532321 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
+ 1812 3532321 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
+ 1813 3532321 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
+ 1814 :
+ 1815 : /* read all the blocks */
+ 1816 3532321 : v_idx = 0;
+ 1817 10617218 : while (v_idx < file->blockmax) {
+ 1818 : block_off_t v_pos;
+ 1819 : uint32_t v_count;
+ 1820 :
+ 1821 : /* get the "subcommand */
+ 1822 3552576 : c = sgetc(f);
+ 1823 :
+ 1824 3552576 : ret = sgetb32(f, &v_pos);
+ 1825 3552576 : if (ret < 0) {
+ 1826 : /* LCOV_EXCL_START */
+ 1827 : decoding_error(path, f);
+ 1828 : os_abort();
+ 1829 : /* LCOV_EXCL_STOP */
+ 1830 : }
+ 1831 :
+ 1832 3552576 : ret = sgetb32(f, &v_count);
+ 1833 3552576 : if (ret < 0) {
+ 1834 : /* LCOV_EXCL_START */
+ 1835 : decoding_error(path, f);
+ 1836 : os_abort();
+ 1837 : /* LCOV_EXCL_STOP */
+ 1838 : }
+ 1839 :
+ 1840 3552576 : if (v_idx + v_count > file->blockmax) {
+ 1841 : /* LCOV_EXCL_START */
+ 1842 : decoding_error(path, f);
+ 1843 : log_fatal("Internal inconsistency in block number!\n");
+ 1844 : os_abort();
+ 1845 : /* LCOV_EXCL_STOP */
+ 1846 : }
+ 1847 :
+ 1848 3552576 : if (v_pos + v_count > blockmax) {
+ 1849 : /* LCOV_EXCL_START */
+ 1850 : decoding_error(path, f);
+ 1851 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count);
+ 1852 : os_abort();
+ 1853 : /* LCOV_EXCL_START */
+ 1854 : }
+ 1855 :
+ 1856 : /* fill the blocks in the run */
+ 1857 : while (v_count) {
+ 1858 : struct snapraid_block* block = fs_file2block_get(file, v_idx);
+ 1859 :
+ 1860 : switch (c) {
+ 1861 : case 'b' :
+ 1862 : block_state_set(block, BLOCK_STATE_BLK);
+ 1863 : break;
+ 1864 : case 'n' :
+ 1865 : /* deprecated NEW blocks are converted to CHG ones */
+ 1866 : block_state_set(block, BLOCK_STATE_CHG);
+ 1867 : break;
+ 1868 : case 'g' :
+ 1869 : block_state_set(block, BLOCK_STATE_CHG);
+ 1870 : break;
+ 1871 : case 'p' :
+ 1872 : block_state_set(block, BLOCK_STATE_REP);
+ 1873 : break;
+ 1874 : default :
+ 1875 : /* LCOV_EXCL_START */
+ 1876 : decoding_error(path, f);
+ 1877 : log_fatal("Invalid block type!\n");
+ 1878 : os_abort();
+ 1879 : /* LCOV_EXCL_STOP */
+ 1880 : }
+ 1881 :
+ 1882 : /* read the hash only for 'blk/chg/rep', and not for 'new' */
+ 1883 8696195 : if (c != 'n') {
+ 1884 8696195 : ret = sread(f, block->hash, HASH_SIZE);
+ 1885 8696195 : if (ret < 0) {
+ 1886 : /* LCOV_EXCL_START */
+ 1887 : decoding_error(path, f);
+ 1888 : os_abort();
+ 1889 : /* LCOV_EXCL_STOP */
+ 1890 : }
+ 1891 : } else {
+ 1892 : /* set the ZERO hash for deprecated NEW blocks */
+ 1893 0 : hash_zero_set(block->hash);
+ 1894 : }
+ 1895 :
+ 1896 : /* if the block contains a hash of past data */
+ 1897 : /* and we are clearing such undeterminated hashes */
+ 1898 8696195 : if (state->clear_past_hash
+ 1899 2401624 : && block_has_past_hash(block)
+ 1900 : ) {
+ 1901 : /* set the hash value to INVALID */
+ 1902 28006 : hash_invalid_set(block->hash);
+ 1903 : }
+ 1904 :
+ 1905 : /* if we are disabling the copy optimization */
+ 1906 : /* we want also to clear any already previously stored information */
+ 1907 : /* in other sync commands */
+ 1908 : /* note that this is required only in sync, and we detect */
+ 1909 : /* this using the clear_past_hash flag */
+ 1910 8696195 : if (state->clear_past_hash
+ 1911 2401624 : && state->opt.force_nocopy
+ 1912 14171 : && block_state_get(block) == BLOCK_STATE_REP
+ 1913 : ) {
+ 1914 : /* set the hash value to INVALID */
+ 1915 1 : hash_invalid_set(block->hash);
+ 1916 : /* convert from REP to CHG block */
+ 1917 1 : block_state_set(block, BLOCK_STATE_CHG);
+ 1918 : }
+ 1919 :
+ 1920 : /* if we want a full sync, marks block as invalid parity */
+ 1921 : /* note that we do this after the force_nocopy option */
+ 1922 : /* to avoid to mixup the two things */
+ 1923 8696195 : if (state->opt.force_full
+ 1924 82268 : && block_state_get(block) == BLOCK_STATE_BLK) {
+ 1925 : /* convert from BLK to REP */
+ 1926 82268 : block_state_set(block, BLOCK_STATE_REP);
+ 1927 : }
+ 1928 :
+ 1929 : /* set the parity association */
+ 1930 8696195 : fs_allocate(disk, v_pos, file, v_idx);
+ 1931 :
+ 1932 : /* go to the next block */
+ 1933 8696195 : ++v_idx;
+ 1934 8696195 : ++v_pos;
+ 1935 8696195 : --v_count;
+ 1936 : }
+ 1937 : }
+ 1938 :
+ 1939 : /* stat */
+ 1940 3532321 : ++count_file;
+ 1941 120455 : } else if (c == 'i') {
+ 1942 : /* "inf" command */
+ 1943 : snapraid_info info;
+ 1944 : uint32_t v_pos;
+ 1945 : uint32_t v_oldest;
+ 1946 :
+ 1947 242 : ret = sgetb32(f, &v_oldest);
+ 1948 242 : if (ret < 0) {
+ 1949 : /* LCOV_EXCL_START */
+ 1950 : decoding_error(path, f);
+ 1951 : os_abort();
+ 1952 : /* LCOV_EXCL_STOP */
+ 1953 : }
+ 1954 :
+ 1955 242 : v_pos = 0;
+ 1956 59307 : while (v_pos < blockmax) {
+ 1957 : int bad;
+ 1958 : int rehash;
+ 1959 : int justsynced;
+ 1960 : uint32_t t;
+ 1961 : uint32_t flag;
+ 1962 : uint32_t v_count;
1963 :
- 1964 : /* go to next block */
- 1965 1491820 : ++v_pos;
- 1966 1491820 : --v_count;
- 1967 : }
- 1968 : }
- 1969 118678 : } else if (c == 'h') {
- 1970 : /* hole */
- 1971 : uint32_t v_pos;
- 1972 : struct snapraid_disk* disk;
- 1973 : uint32_t mapping;
- 1974 :
- 1975 1299 : ret = sgetb32(f, &mapping);
- 1976 1299 : if (ret < 0 || mapping >= mapping_max) {
- 1977 : /* LCOV_EXCL_START */
- 1978 : decoding_error(path, f);
- 1979 : log_fatal("Internal inconsistency in mapping index!\n");
- 1980 : exit(EXIT_FAILURE);
- 1981 : /* LCOV_EXCL_STOP */
- 1982 : }
- 1983 1299 : disk = tommy_array_get(&disk_mapping, mapping);
- 1984 :
- 1985 1299 : v_pos = 0;
- 1986 3965 : while (v_pos < blockmax) {
- 1987 : uint32_t v_idx;
- 1988 : uint32_t v_count;
- 1989 : struct snapraid_file* deleted;
- 1990 :
- 1991 1367 : ret = sgetb32(f, &v_count);
- 1992 1367 : if (ret < 0) {
- 1993 : /* LCOV_EXCL_START */
- 1994 : decoding_error(path, f);
- 1995 : exit(EXIT_FAILURE);
- 1996 : /* LCOV_EXCL_STOP */
- 1997 : }
+ 1964 58823 : ret = sgetb32(f, &v_count);
+ 1965 58823 : if (ret < 0) {
+ 1966 : /* LCOV_EXCL_START */
+ 1967 : decoding_error(path, f);
+ 1968 : os_abort();
+ 1969 : /* LCOV_EXCL_STOP */
+ 1970 : }
+ 1971 :
+ 1972 58823 : if (v_pos + v_count > blockmax) {
+ 1973 : /* LCOV_EXCL_START */
+ 1974 : decoding_error(path, f);
+ 1975 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count);
+ 1976 : os_abort();
+ 1977 : /* LCOV_EXCL_STOP */
+ 1978 : }
+ 1979 :
+ 1980 58823 : ret = sgetb32(f, &flag);
+ 1981 58823 : if (ret < 0) {
+ 1982 : /* LCOV_EXCL_START */
+ 1983 : decoding_error(path, f);
+ 1984 : os_abort();
+ 1985 : /* LCOV_EXCL_STOP */
+ 1986 : }
+ 1987 :
+ 1988 : /* if there is an info */
+ 1989 58823 : if ((flag & 1) != 0) {
+ 1990 : /* read the time */
+ 1991 58808 : ret = sgetb32(f, &t);
+ 1992 58808 : if (ret < 0) {
+ 1993 : /* LCOV_EXCL_START */
+ 1994 : decoding_error(path, f);
+ 1995 : os_abort();
+ 1996 : /* LCOV_EXCL_STOP */
+ 1997 : }
1998 :
- 1999 1367 : if (v_pos + v_count > blockmax) {
- 2000 : /* LCOV_EXCL_START */
- 2001 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count);
- 2002 : decoding_error(path, f);
- 2003 : exit(EXIT_FAILURE);
- 2004 : /* LCOV_EXCL_STOP */
- 2005 : }
- 2006 :
- 2007 : /* get the subcommand */
- 2008 1367 : c = sgetc(f);
- 2009 :
- 2010 1367 : switch (c) {
- 2011 : case 'o' :
- 2012 : /* if it's a run of deleted blocks */
- 2013 :
- 2014 : /* allocate a fake deleted file */
- 2015 36 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0);
+ 1999 : /* analyze the flags */
+ 2000 58808 : bad = (flag & 2) != 0;
+ 2001 58808 : rehash = (flag & 4) != 0;
+ 2002 58808 : justsynced = (flag & 8) != 0;
+ 2003 :
+ 2004 58808 : if (rehash && state->prevhash == HASH_UNDEFINED) {
+ 2005 : /* LCOV_EXCL_START */
+ 2006 : decoding_error(path, f);
+ 2007 : log_fatal("Internal inconsistency for missing previous checksum!\n");
+ 2008 : os_abort();
+ 2009 : /* LCOV_EXCL_STOP */
+ 2010 : }
+ 2011 :
+ 2012 58808 : info = info_make(t + v_oldest, bad, rehash, justsynced);
+ 2013 : } else {
+ 2014 15 : info = 0;
+ 2015 : }
2016 :
- 2017 : /* mark the file as deleted */
- 2018 36 : file_flag_set(deleted, FILE_IS_DELETED);
- 2019 :
- 2020 : /* insert it in the list of deleted files */
- 2021 36 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted);
- 2022 :
- 2023 : /* process all blocks */
- 2024 36 : v_idx = 0;
- 2025 27959 : while (v_count) {
- 2026 27887 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx);
- 2027 :
- 2028 : /* set the block as deleted */
- 2029 27887 : block_state_set(block, BLOCK_STATE_DELETED);
- 2030 :
- 2031 : /* read the hash */
- 2032 27887 : ret = sread(f, block->hash, HASH_SIZE);
- 2033 27887 : if (ret < 0) {
- 2034 : /* LCOV_EXCL_START */
- 2035 : decoding_error(path, f);
- 2036 : exit(EXIT_FAILURE);
- 2037 : /* LCOV_EXCL_STOP */
- 2038 : }
- 2039 :
- 2040 : /* if we are clearing undeterminated hashes */
- 2041 27887 : if (state->clear_past_hash) {
- 2042 : /* set the hash value to INVALID */
- 2043 9433 : hash_invalid_set(block->hash);
- 2044 : }
+ 2017 1630864 : while (v_count) {
+ 2018 : /* insert the info in the array */
+ 2019 1513218 : info_set(&state->infoarr, v_pos, info);
+ 2020 :
+ 2021 : /* ensure that an info is present only for used positions */
+ 2022 1513218 : if (fs_info_is_required(state, v_pos)) {
+ 2023 1445286 : if (!info) {
+ 2024 : /* LCOV_EXCL_START */
+ 2025 : decoding_error(path, f);
+ 2026 : log_fatal("Internal inconsistency for missing info!\n");
+ 2027 : os_abort();
+ 2028 : /* LCOV_EXCL_STOP */
+ 2029 : }
+ 2030 : } else {
+ 2031 : /* extra info are accepted for backward compatibility */
+ 2032 : /* they are discarded at the first write */
+ 2033 : }
+ 2034 :
+ 2035 : /* go to next block */
+ 2036 1513218 : ++v_pos;
+ 2037 1513218 : --v_count;
+ 2038 : }
+ 2039 : }
+ 2040 120213 : } else if (c == 'h') {
+ 2041 : /* hole */
+ 2042 : uint32_t v_pos;
+ 2043 : struct snapraid_disk* disk;
+ 2044 : uint32_t mapping;
2045 :
- 2046 : /* insert the block in the block array */
- 2047 27887 : fs_allocate(disk, v_pos, deleted, v_idx);
- 2048 :
- 2049 : /* go to next block */
- 2050 27887 : ++v_pos;
- 2051 27887 : ++v_idx;
- 2052 27887 : --v_count;
- 2053 : }
- 2054 36 : break;
- 2055 : case 'O' :
- 2056 : /* go to the next run */
- 2057 1331 : v_pos += v_count;
- 2058 1331 : break;
- 2059 : default :
- 2060 : /* LCOV_EXCL_START */
- 2061 : decoding_error(path, f);
- 2062 : log_fatal("Invalid hole type!\n");
- 2063 : exit(EXIT_FAILURE);
- 2064 : /* LCOV_EXCL_STOP */
- 2065 : }
- 2066 : }
- 2067 117379 : } else if (c == 's') {
- 2068 : /* symlink */
- 2069 : char sub[PATH_MAX];
- 2070 : char linkto[PATH_MAX];
- 2071 : struct snapraid_link* slink;
- 2072 : struct snapraid_disk* disk;
- 2073 : uint32_t mapping;
- 2074 :
- 2075 112395 : ret = sgetb32(f, &mapping);
- 2076 112395 : if (ret < 0 || mapping >= mapping_max) {
- 2077 : /* LCOV_EXCL_START */
- 2078 : decoding_error(path, f);
- 2079 : log_fatal("Internal inconsistency in mapping index!\n");
- 2080 : exit(EXIT_FAILURE);
- 2081 : /* LCOV_EXCL_STOP */
- 2082 : }
- 2083 112395 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2046 1334 : ret = sgetb32(f, &mapping);
+ 2047 1334 : if (ret < 0 || mapping >= mapping_max) {
+ 2048 : /* LCOV_EXCL_START */
+ 2049 : decoding_error(path, f);
+ 2050 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2051 : os_abort();
+ 2052 : /* LCOV_EXCL_STOP */
+ 2053 : }
+ 2054 1334 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2055 :
+ 2056 1334 : v_pos = 0;
+ 2057 4080 : while (v_pos < blockmax) {
+ 2058 : uint32_t v_idx;
+ 2059 : uint32_t v_count;
+ 2060 : struct snapraid_file* deleted;
+ 2061 :
+ 2062 1412 : ret = sgetb32(f, &v_count);
+ 2063 1412 : if (ret < 0) {
+ 2064 : /* LCOV_EXCL_START */
+ 2065 : decoding_error(path, f);
+ 2066 : os_abort();
+ 2067 : /* LCOV_EXCL_STOP */
+ 2068 : }
+ 2069 :
+ 2070 1412 : if (v_pos + v_count > blockmax) {
+ 2071 : /* LCOV_EXCL_START */
+ 2072 : decoding_error(path, f);
+ 2073 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count);
+ 2074 : os_abort();
+ 2075 : /* LCOV_EXCL_STOP */
+ 2076 : }
+ 2077 :
+ 2078 : /* get the sub-command */
+ 2079 1412 : c = sgetc(f);
+ 2080 :
+ 2081 1412 : switch (c) {
+ 2082 : case 'o' :
+ 2083 : /* if it's a run of deleted blocks */
2084 :
- 2085 112395 : ret = sgetbs(f, sub, sizeof(sub));
- 2086 112395 : if (ret < 0) {
- 2087 : /* LCOV_EXCL_START */
- 2088 : decoding_error(path, f);
- 2089 : exit(EXIT_FAILURE);
- 2090 : /* LCOV_EXCL_STOP */
- 2091 : }
- 2092 :
- 2093 112395 : ret = sgetbs(f, linkto, sizeof(linkto));
- 2094 112395 : if (ret < 0) {
- 2095 : /* LCOV_EXCL_START */
- 2096 : decoding_error(path, f);
- 2097 : exit(EXIT_FAILURE);
- 2098 : /* LCOV_EXCL_STOP */
- 2099 : }
- 2100 :
- 2101 112395 : if (!*sub || !*linkto) {
- 2102 : /* LCOV_EXCL_START */
- 2103 : decoding_error(path, f);
- 2104 : exit(EXIT_FAILURE);
- 2105 : /* LCOV_EXCL_STOP */
- 2106 : }
- 2107 :
- 2108 : /* allocate the link as symbolic link */
- 2109 112395 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK);
+ 2085 : /* allocate a fake deleted file */
+ 2086 41 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0);
+ 2087 :
+ 2088 : /* mark the file as deleted */
+ 2089 41 : file_flag_set(deleted, FILE_IS_DELETED);
+ 2090 :
+ 2091 : /* insert it in the list of deleted files */
+ 2092 41 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted);
+ 2093 :
+ 2094 : /* process all blocks */
+ 2095 41 : v_idx = 0;
+ 2096 27968 : while (v_count) {
+ 2097 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx);
+ 2098 :
+ 2099 : /* set the block as deleted */
+ 2100 27886 : block_state_set(block, BLOCK_STATE_DELETED);
+ 2101 :
+ 2102 : /* read the hash */
+ 2103 27886 : ret = sread(f, block->hash, HASH_SIZE);
+ 2104 27886 : if (ret < 0) {
+ 2105 : /* LCOV_EXCL_START */
+ 2106 : decoding_error(path, f);
+ 2107 : os_abort();
+ 2108 : /* LCOV_EXCL_STOP */
+ 2109 : }
2110 :
- 2111 : /* insert the link in the link containers */
- 2112 112395 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
- 2113 112395 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
- 2114 :
- 2115 : /* stat */
- 2116 112395 : ++count_symlink;
- 2117 4984 : } else if (c == 'a') {
- 2118 : /* hardlink */
- 2119 : char sub[PATH_MAX];
- 2120 : char linkto[PATH_MAX];
- 2121 : struct snapraid_link* slink;
- 2122 : struct snapraid_disk* disk;
- 2123 : uint32_t mapping;
- 2124 :
- 2125 567 : ret = sgetb32(f, &mapping);
- 2126 567 : if (ret < 0 || mapping >= mapping_max) {
- 2127 : /* LCOV_EXCL_START */
- 2128 : decoding_error(path, f);
- 2129 : log_fatal("Internal inconsistency in mapping index!\n");
- 2130 : exit(EXIT_FAILURE);
- 2131 : /* LCOV_EXCL_STOP */
- 2132 : }
- 2133 567 : disk = tommy_array_get(&disk_mapping, mapping);
- 2134 :
- 2135 567 : ret = sgetbs(f, sub, sizeof(sub));
- 2136 567 : if (ret < 0) {
- 2137 : /* LCOV_EXCL_START */
- 2138 : decoding_error(path, f);
- 2139 : exit(EXIT_FAILURE);
- 2140 : /* LCOV_EXCL_STOP */
- 2141 : }
- 2142 :
- 2143 567 : ret = sgetbs(f, linkto, sizeof(linkto));
- 2144 567 : if (ret < 0) {
- 2145 : /* LCOV_EXCL_START */
- 2146 : decoding_error(path, f);
- 2147 : exit(EXIT_FAILURE);
- 2148 : /* LCOV_EXCL_STOP */
- 2149 : }
- 2150 :
- 2151 567 : if (!*sub || !*linkto) {
- 2152 : /* LCOV_EXCL_START */
- 2153 : decoding_error(path, f);
- 2154 : exit(EXIT_FAILURE);
- 2155 : /* LCOV_EXCL_STOP */
- 2156 : }
- 2157 :
- 2158 : /* allocate the link as hard link */
- 2159 567 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK);
- 2160 :
- 2161 : /* insert the link in the link containers */
- 2162 567 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
- 2163 567 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
- 2164 :
- 2165 : /* stat */
- 2166 567 : ++count_hardlink;
- 2167 4417 : } else if (c == 'r') {
- 2168 : /* dir */
- 2169 : char sub[PATH_MAX];
- 2170 : struct snapraid_dir* dir;
- 2171 : struct snapraid_disk* disk;
- 2172 : uint32_t mapping;
- 2173 :
- 2174 750 : ret = sgetb32(f, &mapping);
- 2175 750 : if (ret < 0 || mapping >= mapping_max) {
- 2176 : /* LCOV_EXCL_START */
- 2177 : decoding_error(path, f);
- 2178 : log_fatal("Internal inconsistency in mapping index!\n");
- 2179 : exit(EXIT_FAILURE);
- 2180 : /* LCOV_EXCL_STOP */
- 2181 : }
- 2182 750 : disk = tommy_array_get(&disk_mapping, mapping);
- 2183 :
- 2184 750 : ret = sgetbs(f, sub, sizeof(sub));
- 2185 750 : if (ret < 0) {
- 2186 : /* LCOV_EXCL_START */
- 2187 : decoding_error(path, f);
- 2188 : exit(EXIT_FAILURE);
- 2189 : /* LCOV_EXCL_STOP */
- 2190 : }
- 2191 :
- 2192 750 : if (!*sub) {
- 2193 : /* LCOV_EXCL_START */
- 2194 : decoding_error(path, f);
- 2195 : exit(EXIT_FAILURE);
- 2196 : /* LCOV_EXCL_STOP */
- 2197 : }
- 2198 :
- 2199 : /* allocate the dir */
- 2200 750 : dir = dir_alloc(sub);
- 2201 :
- 2202 : /* insert the dir in the dir containers */
- 2203 750 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
- 2204 750 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir);
- 2205 :
- 2206 : /* stat */
- 2207 750 : ++count_dir;
- 2208 3667 : } else if (c == 'c') {
- 2209 : /* get the subcommand */
- 2210 235 : c = sgetc(f);
- 2211 :
- 2212 235 : switch (c) {
- 2213 : case 'u' :
- 2214 148 : state->hash = HASH_MURMUR3;
- 2215 148 : break;
- 2216 : case 'k' :
- 2217 87 : state->hash = HASH_SPOOKY2;
- 2218 87 : break;
- 2219 : default :
- 2220 : /* LCOV_EXCL_START */
- 2221 : decoding_error(path, f);
- 2222 : log_fatal("Invalid checksum!\n");
- 2223 : exit(EXIT_FAILURE);
- 2224 : /* LCOV_EXCL_STOP */
- 2225 : }
- 2226 :
- 2227 : /* read the seed */
- 2228 235 : ret = sread(f, state->hashseed, HASH_SIZE);
- 2229 235 : if (ret < 0) {
- 2230 : /* LCOV_EXCL_START */
- 2231 : decoding_error(path, f);
- 2232 : exit(EXIT_FAILURE);
- 2233 : /* LCOV_EXCL_STOP */
- 2234 : }
- 2235 3432 : } else if (c == 'C') {
- 2236 : /* get the subcommand */
- 2237 87 : c = sgetc(f);
+ 2111 : /* if we are clearing indeterminate hashes */
+ 2112 27886 : if (state->clear_past_hash) {
+ 2113 : /* set the hash value to INVALID */
+ 2114 9432 : hash_invalid_set(block->hash);
+ 2115 : }
+ 2116 :
+ 2117 : /* insert the block in the block array */
+ 2118 27886 : fs_allocate(disk, v_pos, deleted, v_idx);
+ 2119 :
+ 2120 : /* go to next block */
+ 2121 27886 : ++v_pos;
+ 2122 27886 : ++v_idx;
+ 2123 27886 : --v_count;
+ 2124 : }
+ 2125 41 : break;
+ 2126 : case 'O' :
+ 2127 : /* go to the next run */
+ 2128 1371 : v_pos += v_count;
+ 2129 1371 : break;
+ 2130 : default :
+ 2131 : /* LCOV_EXCL_START */
+ 2132 : decoding_error(path, f);
+ 2133 : log_fatal("Invalid hole type!\n");
+ 2134 : os_abort();
+ 2135 : /* LCOV_EXCL_STOP */
+ 2136 : }
+ 2137 : }
+ 2138 118879 : } else if (c == 's') {
+ 2139 : /* symlink */
+ 2140 : char sub[PATH_MAX];
+ 2141 : char linkto[PATH_MAX];
+ 2142 : struct snapraid_link* slink;
+ 2143 : struct snapraid_disk* disk;
+ 2144 : uint32_t mapping;
+ 2145 :
+ 2146 113843 : ret = sgetb32(f, &mapping);
+ 2147 113843 : if (ret < 0 || mapping >= mapping_max) {
+ 2148 : /* LCOV_EXCL_START */
+ 2149 : decoding_error(path, f);
+ 2150 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2151 : os_abort();
+ 2152 : /* LCOV_EXCL_STOP */
+ 2153 : }
+ 2154 113843 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2155 :
+ 2156 113843 : ret = sgetbs(f, sub, sizeof(sub));
+ 2157 113843 : if (ret < 0) {
+ 2158 : /* LCOV_EXCL_START */
+ 2159 : decoding_error(path, f);
+ 2160 : os_abort();
+ 2161 : /* LCOV_EXCL_STOP */
+ 2162 : }
+ 2163 :
+ 2164 113843 : if (!*sub) {
+ 2165 : /* LCOV_EXCL_START */
+ 2166 : decoding_error(path, f);
+ 2167 : log_fatal("Internal inconsistency for null symlink!\n");
+ 2168 : os_abort();
+ 2169 : /* LCOV_EXCL_STOP */
+ 2170 : }
+ 2171 :
+ 2172 113843 : ret = sgetbs(f, linkto, sizeof(linkto));
+ 2173 113843 : if (ret < 0) {
+ 2174 : /* LCOV_EXCL_START */
+ 2175 : decoding_error(path, f);
+ 2176 : os_abort();
+ 2177 : /* LCOV_EXCL_STOP */
+ 2178 : }
+ 2179 :
+ 2180 : /* allocate the link as symbolic link */
+ 2181 113843 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK);
+ 2182 :
+ 2183 : /* insert the link in the link containers */
+ 2184 113843 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
+ 2185 113843 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
+ 2186 :
+ 2187 : /* stat */
+ 2188 113843 : ++count_symlink;
+ 2189 5036 : } else if (c == 'a') {
+ 2190 : /* hardlink */
+ 2191 : char sub[PATH_MAX];
+ 2192 : char linkto[PATH_MAX];
+ 2193 : struct snapraid_link* slink;
+ 2194 : struct snapraid_disk* disk;
+ 2195 : uint32_t mapping;
+ 2196 :
+ 2197 576 : ret = sgetb32(f, &mapping);
+ 2198 576 : if (ret < 0 || mapping >= mapping_max) {
+ 2199 : /* LCOV_EXCL_START */
+ 2200 : decoding_error(path, f);
+ 2201 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2202 : os_abort();
+ 2203 : /* LCOV_EXCL_STOP */
+ 2204 : }
+ 2205 576 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2206 :
+ 2207 576 : ret = sgetbs(f, sub, sizeof(sub));
+ 2208 576 : if (ret < 0) {
+ 2209 : /* LCOV_EXCL_START */
+ 2210 : decoding_error(path, f);
+ 2211 : os_abort();
+ 2212 : /* LCOV_EXCL_STOP */
+ 2213 : }
+ 2214 :
+ 2215 576 : if (!*sub) {
+ 2216 : /* LCOV_EXCL_START */
+ 2217 : decoding_error(path, f);
+ 2218 : log_fatal("Internal inconsistency for null hardlink!\n");
+ 2219 : os_abort();
+ 2220 : /* LCOV_EXCL_STOP */
+ 2221 : }
+ 2222 :
+ 2223 576 : ret = sgetbs(f, linkto, sizeof(linkto));
+ 2224 576 : if (ret < 0) {
+ 2225 : /* LCOV_EXCL_START */
+ 2226 : decoding_error(path, f);
+ 2227 : os_abort();
+ 2228 : /* LCOV_EXCL_STOP */
+ 2229 : }
+ 2230 :
+ 2231 576 : if (!*linkto) {
+ 2232 : /* LCOV_EXCL_START */
+ 2233 : decoding_error(path, f);
+ 2234 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub);
+ 2235 : os_abort();
+ 2236 : /* LCOV_EXCL_STOP */
+ 2237 : }
2238 :
- 2239 87 : switch (c) {
- 2240 : case 'u' :
- 2241 87 : state->prevhash = HASH_MURMUR3;
- 2242 87 : break;
- 2243 : case 'k' :
- 2244 0 : state->prevhash = HASH_SPOOKY2;
- 2245 0 : break;
- 2246 : default :
- 2247 : /* LCOV_EXCL_START */
- 2248 : decoding_error(path, f);
- 2249 : log_fatal("Invalid checksum!\n");
- 2250 : exit(EXIT_FAILURE);
- 2251 : /* LCOV_EXCL_STOP */
- 2252 : }
- 2253 :
- 2254 : /* read the seed */
- 2255 87 : ret = sread(f, state->prevhashseed, HASH_SIZE);
- 2256 87 : if (ret < 0) {
+ 2239 : /* allocate the link as hard link */
+ 2240 576 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK);
+ 2241 :
+ 2242 : /* insert the link in the link containers */
+ 2243 576 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
+ 2244 576 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
+ 2245 :
+ 2246 : /* stat */
+ 2247 576 : ++count_hardlink;
+ 2248 4460 : } else if (c == 'r') {
+ 2249 : /* dir */
+ 2250 : char sub[PATH_MAX];
+ 2251 : struct snapraid_dir* dir;
+ 2252 : struct snapraid_disk* disk;
+ 2253 : uint32_t mapping;
+ 2254 :
+ 2255 762 : ret = sgetb32(f, &mapping);
+ 2256 762 : if (ret < 0 || mapping >= mapping_max) {
2257 : /* LCOV_EXCL_START */
2258 : decoding_error(path, f);
- 2259 : exit(EXIT_FAILURE);
- 2260 : /* LCOV_EXCL_STOP */
- 2261 : }
- 2262 3345 : } else if (c == 'z') {
- 2263 : block_off_t blksize;
+ 2259 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2260 : os_abort();
+ 2261 : /* LCOV_EXCL_STOP */
+ 2262 : }
+ 2263 762 : disk = tommy_array_get(&disk_mapping, mapping);
2264 :
- 2265 235 : ret = sgetb32(f, &blksize);
- 2266 235 : if (ret < 0) {
+ 2265 762 : ret = sgetbs(f, sub, sizeof(sub));
+ 2266 762 : if (ret < 0) {
2267 : /* LCOV_EXCL_START */
2268 : decoding_error(path, f);
- 2269 : exit(EXIT_FAILURE);
+ 2269 : os_abort();
2270 : /* LCOV_EXCL_STOP */
2271 : }
2272 :
- 2273 : /* without configuration, auto assign the block size */
- 2274 235 : if (state->no_conf) {
- 2275 1 : state->block_size = blksize;
- 2276 : }
- 2277 :
- 2278 235 : if (blksize != state->block_size) {
- 2279 : /* LCOV_EXCL_START */
- 2280 : decoding_error(path, f);
- 2281 : log_fatal("Mismatching 'blksize' and 'blocksize' specification!\n");
- 2282 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", blksize / 1024);
- 2283 : exit(EXIT_FAILURE);
- 2284 : /* LCOV_EXCL_STOP */
- 2285 : }
- 2286 3110 : } else if (c == 'x') {
- 2287 235 : ret = sgetb32(f, &blockmax);
- 2288 235 : if (ret < 0) {
- 2289 : /* LCOV_EXCL_START */
- 2290 : decoding_error(path, f);
- 2291 : exit(EXIT_FAILURE);
- 2292 : /* LCOV_EXCL_STOP */
- 2293 : }
- 2294 4180 : } else if (c == 'm' || c == 'M') {
- 2295 : struct snapraid_map* map;
- 2296 : char uuid[UUID_MAX];
- 2297 : uint32_t v_pos;
- 2298 : uint32_t v_total_blocks;
- 2299 : uint32_t v_free_blocks;
- 2300 : struct snapraid_disk* disk;
- 2301 :
- 2302 1305 : ret = sgetbs(f, buffer, sizeof(buffer));
- 2303 1305 : if (ret < 0) {
- 2304 : /* LCOV_EXCL_START */
- 2305 : decoding_error(path, f);
- 2306 : exit(EXIT_FAILURE);
- 2307 : /* LCOV_EXCL_STOP */
- 2308 : }
- 2309 :
- 2310 1305 : ret = sgetb32(f, &v_pos);
- 2311 1305 : if (ret < 0) {
+ 2273 762 : if (!*sub) {
+ 2274 : /* LCOV_EXCL_START */
+ 2275 : decoding_error(path, f);
+ 2276 : log_fatal("Internal inconsistency for null dir!\n");
+ 2277 : os_abort();
+ 2278 : /* LCOV_EXCL_STOP */
+ 2279 : }
+ 2280 :
+ 2281 : /* allocate the dir */
+ 2282 762 : dir = dir_alloc(sub);
+ 2283 :
+ 2284 : /* insert the dir in the dir containers */
+ 2285 762 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
+ 2286 762 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir);
+ 2287 :
+ 2288 : /* stat */
+ 2289 762 : ++count_dir;
+ 2290 3698 : } else if (c == 'c') {
+ 2291 : /* get the subcommand */
+ 2292 243 : c = sgetc(f);
+ 2293 :
+ 2294 243 : switch (c) {
+ 2295 : case 'u' :
+ 2296 155 : state->hash = HASH_MURMUR3;
+ 2297 155 : break;
+ 2298 : case 'k' :
+ 2299 88 : state->hash = HASH_SPOOKY2;
+ 2300 88 : break;
+ 2301 : default :
+ 2302 : /* LCOV_EXCL_START */
+ 2303 : decoding_error(path, f);
+ 2304 : log_fatal("Invalid checksum!\n");
+ 2305 : os_abort();
+ 2306 : /* LCOV_EXCL_STOP */
+ 2307 : }
+ 2308 :
+ 2309 : /* read the seed */
+ 2310 243 : ret = sread(f, state->hashseed, HASH_SIZE);
+ 2311 243 : if (ret < 0) {
2312 : /* LCOV_EXCL_START */
2313 : decoding_error(path, f);
- 2314 : exit(EXIT_FAILURE);
+ 2314 : os_abort();
2315 : /* LCOV_EXCL_STOP */
2316 : }
- 2317 :
- 2318 : /* from SnapRAID 7.0 the 'M' command includes the free space */
- 2319 1305 : if (c == 'M') {
- 2320 1305 : ret = sgetb32(f, &v_total_blocks);
- 2321 1305 : if (ret < 0) {
- 2322 : /* LCOV_EXCL_START */
- 2323 : decoding_error(path, f);
- 2324 : exit(EXIT_FAILURE);
- 2325 : /* LCOV_EXCL_STOP */
- 2326 : }
- 2327 :
- 2328 1305 : ret = sgetb32(f, &v_free_blocks);
- 2329 1305 : if (ret < 0) {
- 2330 : /* LCOV_EXCL_START */
- 2331 : decoding_error(path, f);
- 2332 : exit(EXIT_FAILURE);
- 2333 : /* LCOV_EXCL_STOP */
- 2334 : }
- 2335 : } else {
- 2336 0 : v_total_blocks = 0;
- 2337 0 : v_free_blocks = 0;
- 2338 : }
- 2339 :
- 2340 : /* read the uuid */
- 2341 1305 : ret = sgetbs(f, uuid, sizeof(uuid));
- 2342 1305 : if (ret < 0) {
- 2343 : /* LCOV_EXCL_START */
- 2344 : decoding_error(path, f);
- 2345 : exit(EXIT_FAILURE);
- 2346 : /* LCOV_EXCL_STOP */
- 2347 : }
- 2348 :
- 2349 1305 : map = map_alloc(buffer, v_pos, v_total_blocks, v_free_blocks, uuid);
- 2350 :
- 2351 1305 : tommy_list_insert_tail(&state->maplist, &map->node, map);
- 2352 :
- 2353 : /* find the disk */
- 2354 1305 : disk = find_disk(state, buffer);
- 2355 1305 : if (!disk) {
- 2356 : /* LCOV_EXCL_START */
- 2357 : decoding_error(path, f);
- 2358 : log_fatal("Disk named '%s' not present in the configuration file!\n", buffer);
- 2359 : log_fatal("If you have removed it from the configuration file, please restore it\n");
- 2360 : exit(EXIT_FAILURE);
- 2361 : /* LCOV_EXCL_STOP */
- 2362 : }
- 2363 :
- 2364 : /* insert in the mapping vector */
- 2365 1305 : tommy_array_grow(&disk_mapping, mapping_max + 1);
- 2366 1305 : tommy_array_set(&disk_mapping, mapping_max, disk);
- 2367 1305 : ++mapping_max;
- 2368 1570 : } else if (c == 'P') {
- 2369 : /* from SnapRAID 7.0 the 'P' command includes the free space */
- 2370 : char uuid[UUID_MAX];
- 2371 : uint32_t v_level;
- 2372 : uint32_t v_total_blocks;
- 2373 : uint32_t v_free_blocks;
- 2374 :
- 2375 1335 : ret = sgetb32(f, &v_level);
- 2376 1335 : if (ret < 0) {
- 2377 : /* LCOV_EXCL_START */
- 2378 : decoding_error(path, f);
- 2379 : exit(EXIT_FAILURE);
- 2380 : /* LCOV_EXCL_STOP */
- 2381 : }
- 2382 :
- 2383 1335 : ret = sgetb32(f, &v_total_blocks);
- 2384 1335 : if (ret < 0) {
- 2385 : /* LCOV_EXCL_START */
- 2386 : decoding_error(path, f);
- 2387 : exit(EXIT_FAILURE);
- 2388 : /* LCOV_EXCL_STOP */
- 2389 : }
- 2390 :
- 2391 1335 : ret = sgetb32(f, &v_free_blocks);
- 2392 1335 : if (ret < 0) {
- 2393 : /* LCOV_EXCL_START */
- 2394 : decoding_error(path, f);
- 2395 : exit(EXIT_FAILURE);
- 2396 : /* LCOV_EXCL_STOP */
- 2397 : }
- 2398 :
- 2399 1335 : ret = sgetbs(f, uuid, sizeof(uuid));
- 2400 1335 : if (ret < 0) {
- 2401 : /* LCOV_EXCL_START */
- 2402 : decoding_error(path, f);
- 2403 : exit(EXIT_FAILURE);
- 2404 : /* LCOV_EXCL_STOP */
- 2405 : }
- 2406 :
- 2407 : /* auto configure if configuration is missing */
- 2408 1335 : if (state->no_conf && v_level < LEV_MAX && v_level >= state->level)
- 2409 5 : state->level = v_level + 1;
- 2410 :
- 2411 : /* if we use this parity entry */
- 2412 1335 : if (v_level < state->level) {
- 2413 : /* set the parity info */
- 2414 1081 : pathcpy(state->parity[v_level].uuid, sizeof(state->parity[v_level].uuid), uuid);
- 2415 1081 : state->parity[v_level].total_blocks = v_total_blocks;
- 2416 1081 : state->parity[v_level].free_blocks = v_free_blocks;
- 2417 : }
- 2418 235 : } else if (c == 'N') {
- 2419 : uint32_t crc_stored;
- 2420 : uint32_t crc_computed;
+ 2317 3455 : } else if (c == 'C') {
+ 2318 : /* get the sub-command */
+ 2319 4 : c = sgetc(f);
+ 2320 :
+ 2321 4 : switch (c) {
+ 2322 : case 'u' :
+ 2323 4 : state->prevhash = HASH_MURMUR3;
+ 2324 4 : break;
+ 2325 : case 'k' :
+ 2326 0 : state->prevhash = HASH_SPOOKY2;
+ 2327 0 : break;
+ 2328 : default :
+ 2329 : /* LCOV_EXCL_START */
+ 2330 : decoding_error(path, f);
+ 2331 : log_fatal("Invalid checksum!\n");
+ 2332 : os_abort();
+ 2333 : /* LCOV_EXCL_STOP */
+ 2334 : }
+ 2335 :
+ 2336 : /* read the seed */
+ 2337 4 : ret = sread(f, state->prevhashseed, HASH_SIZE);
+ 2338 4 : if (ret < 0) {
+ 2339 : /* LCOV_EXCL_START */
+ 2340 : decoding_error(path, f);
+ 2341 : os_abort();
+ 2342 : /* LCOV_EXCL_STOP */
+ 2343 : }
+ 2344 3451 : } else if (c == 'z') {
+ 2345 : block_off_t blksize;
+ 2346 :
+ 2347 243 : ret = sgetb32(f, &blksize);
+ 2348 243 : if (ret < 0) {
+ 2349 : /* LCOV_EXCL_START */
+ 2350 : decoding_error(path, f);
+ 2351 : os_abort();
+ 2352 : /* LCOV_EXCL_STOP */
+ 2353 : }
+ 2354 :
+ 2355 : /* without configuration, auto assign the block size */
+ 2356 243 : if (state->no_conf) {
+ 2357 1 : state->block_size = blksize;
+ 2358 : }
+ 2359 :
+ 2360 243 : if (blksize != state->block_size) {
+ 2361 : /* LCOV_EXCL_START */
+ 2362 : decoding_error(path, f);
+ 2363 : log_fatal("Mismatching 'blksize' and 'blocksize' specification!\n");
+ 2364 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", blksize / 1024);
+ 2365 : exit(EXIT_FAILURE);
+ 2366 : /* LCOV_EXCL_STOP */
+ 2367 : }
+ 2368 3208 : } else if (c == 'x') {
+ 2369 243 : ret = sgetb32(f, &blockmax);
+ 2370 243 : if (ret < 0) {
+ 2371 : /* LCOV_EXCL_START */
+ 2372 : decoding_error(path, f);
+ 2373 : os_abort();
+ 2374 : /* LCOV_EXCL_STOP */
+ 2375 : }
+ 2376 4305 : } else if (c == 'm' || c == 'M') {
+ 2377 : struct snapraid_map* map;
+ 2378 : char uuid[UUID_MAX];
+ 2379 : uint32_t v_pos;
+ 2380 : uint32_t v_total_blocks;
+ 2381 : uint32_t v_free_blocks;
+ 2382 : struct snapraid_disk* disk;
+ 2383 :
+ 2384 1340 : ret = sgetbs(f, buffer, sizeof(buffer));
+ 2385 1340 : if (ret < 0) {
+ 2386 : /* LCOV_EXCL_START */
+ 2387 : decoding_error(path, f);
+ 2388 : os_abort();
+ 2389 : /* LCOV_EXCL_STOP */
+ 2390 : }
+ 2391 :
+ 2392 1340 : ret = sgetb32(f, &v_pos);
+ 2393 1340 : if (ret < 0) {
+ 2394 : /* LCOV_EXCL_START */
+ 2395 : decoding_error(path, f);
+ 2396 : os_abort();
+ 2397 : /* LCOV_EXCL_STOP */
+ 2398 : }
+ 2399 :
+ 2400 : /* from SnapRAID 7.0 the 'M' command includes the free space */
+ 2401 1340 : if (c == 'M') {
+ 2402 1340 : ret = sgetb32(f, &v_total_blocks);
+ 2403 1340 : if (ret < 0) {
+ 2404 : /* LCOV_EXCL_START */
+ 2405 : decoding_error(path, f);
+ 2406 : os_abort();
+ 2407 : /* LCOV_EXCL_STOP */
+ 2408 : }
+ 2409 :
+ 2410 1340 : ret = sgetb32(f, &v_free_blocks);
+ 2411 1340 : if (ret < 0) {
+ 2412 : /* LCOV_EXCL_START */
+ 2413 : decoding_error(path, f);
+ 2414 : os_abort();
+ 2415 : /* LCOV_EXCL_STOP */
+ 2416 : }
+ 2417 : } else {
+ 2418 0 : v_total_blocks = 0;
+ 2419 0 : v_free_blocks = 0;
+ 2420 : }
2421 :
- 2422 : /* get the crc before reading it from the file */
- 2423 234 : crc_computed = scrc(f);
- 2424 :
- 2425 234 : ret = sgetble32(f, &crc_stored);
- 2426 234 : if (ret < 0) {
- 2427 : /* LCOV_EXCL_START */
- 2428 : /* here don't call decoding_error() because it's too late to get the crc */
- 2429 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f));
- 2430 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 2431 : exit(EXIT_FAILURE);
- 2432 : /* LCOV_EXCL_STOP */
- 2433 : }
- 2434 :
- 2435 234 : if (crc_stored != crc_computed) {
- 2436 : /* LCOV_EXCL_START */
- 2437 : /* here don't call decoding_error() because it's too late to get the crc */
- 2438 : log_fatal("Mismatching CRC in '%s'\n", path);
- 2439 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 2440 : exit(EXIT_FAILURE);
- 2441 : /* LCOV_EXCL_STOP */
+ 2422 : /* read the uuid */
+ 2423 1340 : ret = sgetbs(f, uuid, sizeof(uuid));
+ 2424 1340 : if (ret < 0) {
+ 2425 : /* LCOV_EXCL_START */
+ 2426 : decoding_error(path, f);
+ 2427 : os_abort();
+ 2428 : /* LCOV_EXCL_STOP */
+ 2429 : }
+ 2430 :
+ 2431 : /* find the disk */
+ 2432 1340 : disk = find_disk_by_name(state, buffer);
+ 2433 1340 : if (!disk) {
+ 2434 : /* search by UUID if renamed */
+ 2435 2 : disk = find_disk_by_uuid(state, uuid);
+ 2436 2 : if (disk) {
+ 2437 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name);
+ 2438 :
+ 2439 : /* write the new state with the new name */
+ 2440 2 : state->need_write = 1;
+ 2441 : }
2442 : }
- 2443 :
- 2444 234 : crc_checked = 1;
- 2445 : } else {
- 2446 : /* LCOV_EXCL_START */
- 2447 : decoding_error(path, f);
- 2448 : log_fatal("Invalid command '%c'!\n", (char)c);
- 2449 : exit(EXIT_FAILURE);
- 2450 : /* LCOV_EXCL_STOP */
- 2451 : }
- 2452 3604826 : }
- 2453 :
- 2454 234 : tommy_array_done(&disk_mapping);
- 2455 :
- 2456 234 : if (serror(f)) {
- 2457 : /* LCOV_EXCL_START */
- 2458 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 2459 : exit(EXIT_FAILURE);
- 2460 : /* LCOV_EXCL_STOP */
- 2461 : }
- 2462 :
- 2463 234 : if (!crc_checked) {
- 2464 : /* LCOV_EXCL_START */
- 2465 : log_fatal("Finished reading '%s' without finding the CRC\n", path);
- 2466 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n");
- 2467 : exit(EXIT_FAILURE);
- 2468 : /* LCOV_EXCL_STOP */
- 2469 : }
- 2470 :
- 2471 : /* check the filesystem on all disks */
- 2472 234 : state_fscheck(state, "after read");
- 2473 :
- 2474 : /* check that the stored parity size matches the loaded state */
- 2475 234 : if (blockmax != parity_allocated_size(state)) {
- 2476 : /* LCOV_EXCL_START */
- 2477 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
- 2478 : if (state->opt.skip_content_check) {
- 2479 : log_fatal("Overriding.\n");
- 2480 : blockmax = parity_allocated_size(state);
- 2481 : } else {
- 2482 : exit(EXIT_FAILURE);
- 2483 : }
- 2484 : /* LCOV_EXCL_STOP */
- 2485 : }
- 2486 :
- 2487 234 : msg_verbose("%8u files\n", count_file);
- 2488 234 : msg_verbose("%8u hardlinks\n", count_hardlink);
- 2489 234 : msg_verbose("%8u symlinks\n", count_symlink);
- 2490 234 : msg_verbose("%8u empty dirs\n", count_dir);
- 2491 234 : }
- 2492 :
- 2493 : struct state_write_thread_context {
- 2494 : struct snapraid_state* state;
- 2495 : struct snapraid_content* content;
- 2496 : #if HAVE_PTHREAD_CREATE
- 2497 : pthread_t thread;
- 2498 : #else
- 2499 : void* retval;
- 2500 : #endif
- 2501 : /* input */
- 2502 : block_off_t blockmax;
- 2503 : time_t info_oldest;
- 2504 : int info_has_rehash;
- 2505 : /* output */
- 2506 : uint32_t crc;
- 2507 : unsigned count_file;
- 2508 : unsigned count_hardlink;
- 2509 : unsigned count_symlink;
- 2510 : unsigned count_dir;
- 2511 : };
- 2512 :
- 2513 913 : static void* state_write_thread(void* arg)
- 2514 : {
- 2515 913 : struct state_write_thread_context* context = arg;
- 2516 913 : struct snapraid_content* content = context->content;
- 2517 913 : struct snapraid_state* state = context->state;
- 2518 913 : block_off_t blockmax = context->blockmax;
- 2519 913 : time_t info_oldest = context->info_oldest;
- 2520 913 : int info_has_rehash = context->info_has_rehash;
- 2521 : uint32_t crc;
- 2522 : unsigned count_file;
- 2523 : unsigned count_hardlink;
- 2524 : unsigned count_symlink;
- 2525 : unsigned count_dir;
- 2526 : char tmp[PATH_MAX];
- 2527 : STREAM* f;
- 2528 : tommy_node* i;
- 2529 : block_off_t idx;
- 2530 : block_off_t begin;
- 2531 : unsigned l;
- 2532 :
- 2533 913 : count_file = 0;
- 2534 913 : count_hardlink = 0;
- 2535 913 : count_symlink = 0;
- 2536 913 : count_dir = 0;
- 2537 :
- 2538 913 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 2539 904 : f = sopen_write(tmp);
- 2540 913 : if (f == 0) {
- 2541 : /* LCOV_EXCL_START */
- 2542 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
- 2543 : goto bail;
- 2544 : /* LCOV_EXCL_STOP */
- 2545 : }
- 2546 :
- 2547 : /* write header */
- 2548 913 : swrite("SNAPCNT2\n\3\0\0", 12, f);
- 2549 :
- 2550 : /* write block size and block max */
- 2551 913 : sputc('z', f);
- 2552 913 : sputb32(state->block_size, f);
- 2553 913 : sputc('x', f);
- 2554 913 : sputb32(blockmax, f);
- 2555 913 : if (serror(f)) {
- 2556 : /* LCOV_EXCL_START */
- 2557 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2558 : goto bail;
- 2559 : /* LCOV_EXCL_STOP */
- 2560 : }
- 2561 :
- 2562 913 : sputc('c', f);
- 2563 913 : if (state->hash == HASH_MURMUR3) {
- 2564 715 : sputc('u', f);
- 2565 198 : } else if (state->hash == HASH_SPOOKY2) {
- 2566 198 : sputc('k', f);
- 2567 : } else {
- 2568 : /* LCOV_EXCL_START */
- 2569 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f));
- 2570 : goto bail;
- 2571 : /* LCOV_EXCL_STOP */
- 2572 : }
- 2573 913 : swrite(state->hashseed, HASH_SIZE, f);
- 2574 913 : if (serror(f)) {
- 2575 : /* LCOV_EXCL_START */
- 2576 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2577 : goto bail;
- 2578 : /* LCOV_EXCL_STOP */
- 2579 : }
- 2580 :
- 2581 : /* previous hash only present */
- 2582 913 : if (state->prevhash != HASH_UNDEFINED) {
- 2583 : /* if at least one rehash tag found, we have to save the previous hash */
- 2584 198 : if (info_has_rehash) {
- 2585 198 : sputc('C', f);
- 2586 198 : if (state->prevhash == HASH_MURMUR3) {
- 2587 198 : sputc('u', f);
- 2588 0 : } else if (state->prevhash == HASH_SPOOKY2) {
- 2589 0 : sputc('k', f);
- 2590 : } else {
- 2591 : /* LCOV_EXCL_START */
- 2592 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f));
- 2593 : goto bail;
- 2594 : /* LCOV_EXCL_STOP */
- 2595 : }
- 2596 198 : swrite(state->prevhashseed, HASH_SIZE, f);
- 2597 198 : if (serror(f)) {
- 2598 : /* LCOV_EXCL_START */
- 2599 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2600 : goto bail;
- 2601 : /* LCOV_EXCL_STOP */
- 2602 : }
- 2603 : }
- 2604 : }
+ 2443 1340 : if (!disk) {
+ 2444 : /* LCOV_EXCL_START */
+ 2445 : decoding_error(path, f);
+ 2446 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid);
+ 2447 : log_fatal("If you have removed it from the configuration file, please restore it\n");
+ 2448 : /* if it's a command without UUID, it cannot autorename using UUID */
+ 2449 : if (state->opt.skip_disk_access)
+ 2450 : log_fatal("If you have renamed it, run 'sync' to update the new name\n");
+ 2451 : exit(EXIT_FAILURE);
+ 2452 : /* LCOV_EXCL_STOP */
+ 2453 : }
+ 2454 :
+ 2455 1340 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid);
+ 2456 :
+ 2457 1340 : tommy_list_insert_tail(&state->maplist, &map->node, map);
+ 2458 :
+ 2459 : /* insert in the mapping vector */
+ 2460 1340 : tommy_array_grow(&disk_mapping, mapping_max + 1);
+ 2461 1340 : tommy_array_set(&disk_mapping, mapping_max, disk);
+ 2462 1340 : ++mapping_max;
+ 2463 1625 : } else if (c == 'P') {
+ 2464 : /* from SnapRAID 7.0 the 'P' command includes the free space */
+ 2465 : char uuid[UUID_MAX];
+ 2466 : uint32_t v_level;
+ 2467 : uint32_t v_total_blocks;
+ 2468 : uint32_t v_free_blocks;
+ 2469 :
+ 2470 1383 : ret = sgetb32(f, &v_level);
+ 2471 1383 : if (ret < 0) {
+ 2472 : /* LCOV_EXCL_START */
+ 2473 : decoding_error(path, f);
+ 2474 : os_abort();
+ 2475 : /* LCOV_EXCL_STOP */
+ 2476 : }
+ 2477 :
+ 2478 1383 : ret = sgetb32(f, &v_total_blocks);
+ 2479 1383 : if (ret < 0) {
+ 2480 : /* LCOV_EXCL_START */
+ 2481 : decoding_error(path, f);
+ 2482 : os_abort();
+ 2483 : /* LCOV_EXCL_STOP */
+ 2484 : }
+ 2485 :
+ 2486 1383 : ret = sgetb32(f, &v_free_blocks);
+ 2487 1383 : if (ret < 0) {
+ 2488 : /* LCOV_EXCL_START */
+ 2489 : decoding_error(path, f);
+ 2490 : os_abort();
+ 2491 : /* LCOV_EXCL_STOP */
+ 2492 : }
+ 2493 :
+ 2494 1383 : ret = sgetbs(f, uuid, sizeof(uuid));
+ 2495 1383 : if (ret < 0) {
+ 2496 : /* LCOV_EXCL_START */
+ 2497 : decoding_error(path, f);
+ 2498 : os_abort();
+ 2499 : /* LCOV_EXCL_STOP */
+ 2500 : }
+ 2501 :
+ 2502 : /* auto configure if configuration is missing */
+ 2503 1383 : if (state->no_conf && v_level < LEV_MAX && v_level >= state->level)
+ 2504 5 : state->level = v_level + 1;
+ 2505 :
+ 2506 : /* if we use this parity entry */
+ 2507 1383 : if (v_level < state->level) {
+ 2508 : /* set the parity info */
+ 2509 1129 : pathcpy(state->parity[v_level].uuid, sizeof(state->parity[v_level].uuid), uuid);
+ 2510 1129 : state->parity[v_level].total_blocks = v_total_blocks;
+ 2511 1129 : state->parity[v_level].free_blocks = v_free_blocks;
+ 2512 : }
+ 2513 242 : } else if (c == 'N') {
+ 2514 : uint32_t crc_stored;
+ 2515 : uint32_t crc_computed;
+ 2516 :
+ 2517 : /* get the crc before reading it from the file */
+ 2518 242 : crc_computed = scrc(f);
+ 2519 :
+ 2520 242 : ret = sgetble32(f, &crc_stored);
+ 2521 242 : if (ret < 0) {
+ 2522 : /* LCOV_EXCL_START */
+ 2523 : /* here don't call decoding_error() because it's too late to get the crc */
+ 2524 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 2525 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 2526 : exit(EXIT_FAILURE);
+ 2527 : /* LCOV_EXCL_STOP */
+ 2528 : }
+ 2529 :
+ 2530 242 : if (crc_stored != crc_computed) {
+ 2531 : /* LCOV_EXCL_START */
+ 2532 : /* here don't call decoding_error() because it's too late to get the crc */
+ 2533 : log_fatal("Mismatching CRC in '%s'\n", path);
+ 2534 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 2535 : exit(EXIT_FAILURE);
+ 2536 : /* LCOV_EXCL_STOP */
+ 2537 : }
+ 2538 :
+ 2539 242 : crc_checked = 1;
+ 2540 : } else {
+ 2541 : /* LCOV_EXCL_START */
+ 2542 : decoding_error(path, f);
+ 2543 : log_fatal("Invalid command '%c'!\n", (char)c);
+ 2544 : os_abort();
+ 2545 : /* LCOV_EXCL_STOP */
+ 2546 : }
+ 2547 3652776 : }
+ 2548 :
+ 2549 242 : tommy_array_done(&disk_mapping);
+ 2550 :
+ 2551 242 : if (serror(f)) {
+ 2552 : /* LCOV_EXCL_START */
+ 2553 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 2554 : exit(EXIT_FAILURE);
+ 2555 : /* LCOV_EXCL_STOP */
+ 2556 : }
+ 2557 :
+ 2558 242 : if (!crc_checked) {
+ 2559 : /* LCOV_EXCL_START */
+ 2560 : log_fatal("Finished reading '%s' without finding the CRC\n", path);
+ 2561 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n");
+ 2562 : exit(EXIT_FAILURE);
+ 2563 : /* LCOV_EXCL_STOP */
+ 2564 : }
+ 2565 :
+ 2566 : /* check the file-system on all disks */
+ 2567 242 : state_fscheck(state, "after read");
+ 2568 :
+ 2569 : /* check that the stored parity size matches the loaded state */
+ 2570 242 : if (blockmax != parity_allocated_size(state)) {
+ 2571 : /* LCOV_EXCL_START */
+ 2572 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
+ 2573 : if (state->opt.skip_content_check) {
+ 2574 : log_fatal("Overriding.\n");
+ 2575 : blockmax = parity_allocated_size(state);
+ 2576 : } else {
+ 2577 : exit(EXIT_FAILURE);
+ 2578 : }
+ 2579 : /* LCOV_EXCL_STOP */
+ 2580 : }
+ 2581 :
+ 2582 242 : msg_verbose("%8u files\n", count_file);
+ 2583 242 : msg_verbose("%8u hardlinks\n", count_hardlink);
+ 2584 242 : msg_verbose("%8u symlinks\n", count_symlink);
+ 2585 242 : msg_verbose("%8u empty dirs\n", count_dir);
+ 2586 242 : }
+ 2587 :
+ 2588 : struct state_write_thread_context {
+ 2589 : struct snapraid_state* state;
+ 2590 : #if HAVE_MT_WRITE
+ 2591 : pthread_t thread;
+ 2592 : #endif
+ 2593 : /* input */
+ 2594 : block_off_t blockmax;
+ 2595 : time_t info_oldest;
+ 2596 : int info_has_rehash;
+ 2597 : STREAM* f;
+ 2598 : /* output */
+ 2599 : uint32_t crc;
+ 2600 : unsigned count_file;
+ 2601 : unsigned count_hardlink;
+ 2602 : unsigned count_symlink;
+ 2603 : unsigned count_dir;
+ 2604 : };
2605 :
- 2606 : /* for each map */
- 2607 6391 : for (i = state->maplist; i != 0; i = i->next) {
- 2608 5478 : struct snapraid_map* map = i->data;
- 2609 : struct snapraid_disk* disk;
- 2610 :
- 2611 : /* find the disk for this mapping */
- 2612 5478 : disk = find_disk(state, map->name);
- 2613 5478 : if (!disk) {
- 2614 : /* LCOV_EXCL_START */
- 2615 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
- 2616 : goto bail;
- 2617 : /* LCOV_EXCL_STOP */
- 2618 : }
- 2619 :
- 2620 : /* save the mapping only if disk is mapped */
- 2621 5478 : if (disk->mapping_idx != -1) {
- 2622 5037 : sputc('M', f);
- 2623 5037 : sputbs(map->name, f);
- 2624 5037 : sputb32(map->position, f);
- 2625 5037 : sputb32(map->total_blocks, f);
- 2626 5037 : sputb32(map->free_blocks, f);
- 2627 5037 : sputbs(map->uuid, f);
- 2628 5037 : if (serror(f)) {
- 2629 : /* LCOV_EXCL_START */
- 2630 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2631 : goto bail;
- 2632 : /* LCOV_EXCL_STOP */
- 2633 : }
- 2634 : }
- 2635 : }
- 2636 :
- 2637 : /* for each parity */
- 2638 6341 : for (l = 0; l < state->level; ++l) {
- 2639 5428 : sputc('P', f);
- 2640 5428 : sputb32(l, f);
- 2641 5428 : sputb32(state->parity[l].total_blocks, f);
- 2642 5428 : sputb32(state->parity[l].free_blocks, f);
- 2643 5427 : sputbs(state->parity[l].uuid, f);
- 2644 5428 : if (serror(f)) {
- 2645 : /* LCOV_EXCL_START */
- 2646 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2647 : goto bail;
- 2648 : /* LCOV_EXCL_STOP */
- 2649 : }
- 2650 : }
- 2651 :
- 2652 : /* for each disk */
- 2653 6391 : for (i = state->disklist; i != 0; i = i->next) {
- 2654 : tommy_node* j;
- 2655 5478 : struct snapraid_disk* disk = i->data;
- 2656 : struct snapraid_chunk* fs_last;
- 2657 :
- 2658 : /**
- 2659 : * This is the last accessed chunk in the tree operations.
- 2660 : * Here we are inside a thread, and we cannot use the
- 2661 : * ::disk member to store this information.
- 2662 : */
- 2663 5478 : fs_last = 0;
- 2664 :
- 2665 : /* if the disk is not mapped, skip it */
- 2666 5478 : if (disk->mapping_idx < 0)
- 2667 441 : continue;
- 2668 :
- 2669 : /* for each file */
- 2670 11578188 : for (j = disk->filelist; j != 0; j = j->next) {
- 2671 11573152 : struct snapraid_file* file = j->data;
- 2672 : uint64_t size;
- 2673 : uint64_t mtime_sec;
- 2674 : int32_t mtime_nsec;
- 2675 : uint64_t inode;
- 2676 :
- 2677 11573152 : size = file->size;
- 2678 11573152 : mtime_sec = file->mtime_sec;
- 2679 11573152 : mtime_nsec = file->mtime_nsec;
- 2680 11573152 : inode = file->inode;
- 2681 :
- 2682 11573152 : sputc('f', f);
- 2683 11523322 : sputb32(disk->mapping_idx, f);
- 2684 11531504 : sputb64(size, f);
- 2685 11543059 : sputb64(mtime_sec, f);
- 2686 : /* encode STAT_NSEC_INVALID as 0 */
- 2687 11521684 : if (mtime_nsec == STAT_NSEC_INVALID)
- 2688 0 : sputb32(0, f);
- 2689 : else
- 2690 11521684 : sputb32(mtime_nsec + 1, f);
- 2691 11530611 : sputb64(inode, f);
- 2692 11526825 : sputbs(file->sub, f);
- 2693 11546662 : if (serror(f)) {
- 2694 : /* LCOV_EXCL_START */
- 2695 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2696 : goto bail;
- 2697 : /* LCOV_EXCL_STOP */
- 2698 : }
- 2699 :
- 2700 : /* for all the blocks of the file */
- 2701 11560751 : begin = 0;
- 2702 34754559 : while (begin < file->blockmax) {
- 2703 11620657 : unsigned v_state = block_state_get(fs_file2block_get(file, begin));
- 2704 11635419 : block_off_t v_pos = fs_file2par_get_ts(disk, &fs_last, file, begin);
- 2705 : uint32_t v_count;
- 2706 :
- 2707 : block_off_t end;
- 2708 :
- 2709 : /* find the end of run of blocks */
- 2710 11602915 : end = begin + 1;
- 2711 40021161 : while (end < file->blockmax) {
- 2712 16868038 : if (v_state != block_state_get(fs_file2block_get(file, end)))
- 2713 63 : break;
- 2714 16887534 : if (v_pos + (end - begin) != fs_file2par_get_ts(disk, &fs_last, file, end))
- 2715 83317 : break;
- 2716 16815331 : ++end;
- 2717 : }
+ 2606 145 : static void* state_write_thread(void* arg)
+ 2607 : {
+ 2608 145 : struct state_write_thread_context* context = arg;
+ 2609 145 : struct snapraid_state* state = context->state;
+ 2610 145 : block_off_t blockmax = context->blockmax;
+ 2611 145 : time_t info_oldest = context->info_oldest;
+ 2612 145 : int info_has_rehash = context->info_has_rehash;
+ 2613 145 : STREAM* f = context->f;
+ 2614 : uint32_t crc;
+ 2615 : unsigned count_file;
+ 2616 : unsigned count_hardlink;
+ 2617 : unsigned count_symlink;
+ 2618 : unsigned count_dir;
+ 2619 : tommy_node* i;
+ 2620 : block_off_t idx;
+ 2621 : block_off_t begin;
+ 2622 : unsigned l;
+ 2623 :
+ 2624 145 : count_file = 0;
+ 2625 145 : count_hardlink = 0;
+ 2626 145 : count_symlink = 0;
+ 2627 145 : count_dir = 0;
+ 2628 :
+ 2629 : /* write header */
+ 2630 145 : swrite("SNAPCNT2\n\3\0\0", 12, f);
+ 2631 :
+ 2632 : /* write block size and block max */
+ 2633 145 : sputc('z', f);
+ 2634 145 : sputb32(state->block_size, f);
+ 2635 145 : sputc('x', f);
+ 2636 145 : sputb32(blockmax, f);
+ 2637 145 : if (serror(f)) {
+ 2638 : /* LCOV_EXCL_START */
+ 2639 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2640 : return context;
+ 2641 : /* LCOV_EXCL_STOP */
+ 2642 : }
+ 2643 :
+ 2644 145 : sputc('c', f);
+ 2645 145 : if (state->hash == HASH_MURMUR3) {
+ 2646 115 : sputc('u', f);
+ 2647 30 : } else if (state->hash == HASH_SPOOKY2) {
+ 2648 30 : sputc('k', f);
+ 2649 : } else {
+ 2650 : /* LCOV_EXCL_START */
+ 2651 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f));
+ 2652 : return context;
+ 2653 : /* LCOV_EXCL_STOP */
+ 2654 : }
+ 2655 145 : swrite(state->hashseed, HASH_SIZE, f);
+ 2656 145 : if (serror(f)) {
+ 2657 : /* LCOV_EXCL_START */
+ 2658 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2659 : return context;
+ 2660 : /* LCOV_EXCL_STOP */
+ 2661 : }
+ 2662 :
+ 2663 : /* previous hash only present */
+ 2664 145 : if (state->prevhash != HASH_UNDEFINED) {
+ 2665 : /* if at least one rehash tag found, we have to save the previous hash */
+ 2666 4 : if (info_has_rehash) {
+ 2667 3 : sputc('C', f);
+ 2668 3 : if (state->prevhash == HASH_MURMUR3) {
+ 2669 3 : sputc('u', f);
+ 2670 0 : } else if (state->prevhash == HASH_SPOOKY2) {
+ 2671 0 : sputc('k', f);
+ 2672 : } else {
+ 2673 : /* LCOV_EXCL_START */
+ 2674 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f));
+ 2675 : return context;
+ 2676 : /* LCOV_EXCL_STOP */
+ 2677 : }
+ 2678 3 : swrite(state->prevhashseed, HASH_SIZE, f);
+ 2679 3 : if (serror(f)) {
+ 2680 : /* LCOV_EXCL_START */
+ 2681 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2682 : return context;
+ 2683 : /* LCOV_EXCL_STOP */
+ 2684 : }
+ 2685 : }
+ 2686 : }
+ 2687 :
+ 2688 : /* for each map */
+ 2689 1015 : for (i = state->maplist; i != 0; i = i->next) {
+ 2690 870 : struct snapraid_map* map = i->data;
+ 2691 : struct snapraid_disk* disk;
+ 2692 :
+ 2693 : /* find the disk for this mapping */
+ 2694 870 : disk = find_disk_by_name(state, map->name);
+ 2695 870 : if (!disk) {
+ 2696 : /* LCOV_EXCL_START */
+ 2697 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
+ 2698 : return context;
+ 2699 : /* LCOV_EXCL_STOP */
+ 2700 : }
+ 2701 :
+ 2702 : /* save the mapping only if disk is mapped */
+ 2703 870 : if (disk->mapping_idx != -1) {
+ 2704 786 : sputc('M', f);
+ 2705 786 : sputbs(map->name, f);
+ 2706 786 : sputb32(map->position, f);
+ 2707 786 : sputb32(map->total_blocks, f);
+ 2708 786 : sputb32(map->free_blocks, f);
+ 2709 786 : sputbs(map->uuid, f);
+ 2710 786 : if (serror(f)) {
+ 2711 : /* LCOV_EXCL_START */
+ 2712 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2713 : return context;
+ 2714 : /* LCOV_EXCL_STOP */
+ 2715 : }
+ 2716 : }
+ 2717 : }
2718 :
- 2719 11633588 : switch (v_state) {
- 2720 : case BLOCK_STATE_BLK :
- 2721 10922665 : sputc('b', f);
- 2722 10930254 : break;
- 2723 : case BLOCK_STATE_CHG :
- 2724 559524 : sputc('g', f);
- 2725 559519 : break;
- 2726 : case BLOCK_STATE_REP :
- 2727 151399 : sputc('p', f);
- 2728 151402 : break;
- 2729 : default :
- 2730 : /* LCOV_EXCL_START */
- 2731 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state);
- 2732 : goto bail;
- 2733 : /* LCOV_EXCL_STOP */
- 2734 : }
- 2735 :
- 2736 11641175 : sputb32(v_pos, f);
- 2737 :
- 2738 11622679 : v_count = end - begin;
- 2739 11622679 : sputb32(v_count, f);
- 2740 :
- 2741 : /* write hashes */
- 2742 39768736 : for (idx = begin; idx < end; ++idx) {
- 2743 28155837 : struct snapraid_block* block = fs_file2block_get(file, idx);
- 2744 :
- 2745 28133584 : swrite(block->hash, HASH_SIZE, f);
- 2746 : }
- 2747 :
- 2748 11612899 : if (serror(f)) {
- 2749 : /* LCOV_EXCL_START */
- 2750 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2751 : goto bail;
- 2752 : /* LCOV_EXCL_STOP */
- 2753 : }
- 2754 :
- 2755 : /* next begin position */
- 2756 11633057 : begin = end;
- 2757 : }
+ 2719 : /* for each parity */
+ 2720 990 : for (l = 0; l < state->level; ++l) {
+ 2721 845 : sputc('P', f);
+ 2722 845 : sputb32(l, f);
+ 2723 845 : sputb32(state->parity[l].total_blocks, f);
+ 2724 845 : sputb32(state->parity[l].free_blocks, f);
+ 2725 845 : sputbs(state->parity[l].uuid, f);
+ 2726 845 : if (serror(f)) {
+ 2727 : /* LCOV_EXCL_START */
+ 2728 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2729 : return context;
+ 2730 : /* LCOV_EXCL_STOP */
+ 2731 : }
+ 2732 : }
+ 2733 :
+ 2734 : /* for each disk */
+ 2735 1015 : for (i = state->disklist; i != 0; i = i->next) {
+ 2736 : tommy_node* j;
+ 2737 870 : struct snapraid_disk* disk = i->data;
+ 2738 : struct snapraid_chunk* fs_last;
+ 2739 :
+ 2740 : /**
+ 2741 : * This is the last accessed chunk in the tree operations.
+ 2742 : * Here we are inside a thread, and we cannot use the
+ 2743 : * ::disk member to store this information.
+ 2744 : */
+ 2745 870 : fs_last = 0;
+ 2746 :
+ 2747 : /* if the disk is not mapped, skip it */
+ 2748 870 : if (disk->mapping_idx < 0)
+ 2749 84 : continue;
+ 2750 :
+ 2751 : /* for each file */
+ 2752 1765094 : for (j = disk->filelist; j != 0; j = j->next) {
+ 2753 1764308 : struct snapraid_file* file = j->data;
+ 2754 : uint64_t size;
+ 2755 : uint64_t mtime_sec;
+ 2756 : int32_t mtime_nsec;
+ 2757 : uint64_t inode;
2758 :
- 2759 11573151 : ++count_file;
- 2760 : }
- 2761 :
- 2762 : /* for each link */
- 2763 385485 : for (j = disk->linklist; j != 0; j = j->next) {
- 2764 380448 : struct snapraid_link* slink = j->data;
- 2765 :
- 2766 380448 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) {
- 2767 : case FILE_IS_HARDLINK :
- 2768 2046 : sputc('a', f);
- 2769 2046 : ++count_hardlink;
- 2770 2046 : break;
- 2771 : case FILE_IS_SYMLINK :
- 2772 378402 : sputc('s', f);
- 2773 378020 : ++count_symlink;
- 2774 378020 : break;
- 2775 : }
- 2776 :
- 2777 380066 : sputb32(disk->mapping_idx, f);
- 2778 380422 : sputbs(slink->sub, f);
- 2779 380445 : sputbs(slink->linkto, f);
- 2780 380449 : if (serror(f)) {
- 2781 : /* LCOV_EXCL_START */
- 2782 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2783 : goto bail;
- 2784 : /* LCOV_EXCL_STOP */
- 2785 : }
- 2786 : }
- 2787 :
- 2788 : /* for each dir */
- 2789 7758 : for (j = disk->dirlist; j != 0; j = j->next) {
- 2790 2721 : struct snapraid_dir* dir = j->data;
- 2791 :
- 2792 2721 : sputc('r', f);
- 2793 2721 : sputb32(disk->mapping_idx, f);
- 2794 2721 : sputbs(dir->sub, f);
- 2795 2721 : if (serror(f)) {
- 2796 : /* LCOV_EXCL_START */
- 2797 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2798 : goto bail;
- 2799 : /* LCOV_EXCL_STOP */
- 2800 : }
- 2801 :
- 2802 2721 : ++count_dir;
- 2803 : }
- 2804 :
- 2805 : /* deleted blocks of the disk */
- 2806 5037 : sputc('h', f);
- 2807 5037 : sputb32(disk->mapping_idx, f);
- 2808 5037 : if (serror(f)) {
- 2809 : /* LCOV_EXCL_START */
- 2810 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2811 : goto bail;
- 2812 : /* LCOV_EXCL_STOP */
- 2813 : }
- 2814 5037 : begin = 0;
- 2815 15643 : while (begin < blockmax) {
- 2816 : int is_deleted;
- 2817 : block_off_t end;
- 2818 :
- 2819 5569 : is_deleted = fs_is_block_deleted_ts(disk, &fs_last, begin);
- 2820 :
- 2821 : /* find the end of run of blocks */
- 2822 5569 : end = begin + 1;
- 2823 29396439 : while (end < blockmax
- 2824 29341613 : && is_deleted == fs_is_block_deleted_ts(disk, &fs_last, end)
- 2825 : ) {
- 2826 29385301 : ++end;
- 2827 : }
- 2828 :
- 2829 0 : sputb32(end - begin, f);
- 2830 :
- 2831 5569 : if (is_deleted) {
- 2832 : /* write the run of deleted blocks with hash */
- 2833 329 : sputc('o', f);
- 2834 :
- 2835 : /* write all the hash */
- 2836 112525 : while (begin < end) {
- 2837 111867 : struct snapraid_block* block = fs_par2block_get_ts(disk, &fs_last, begin);
- 2838 :
- 2839 111867 : swrite(block->hash, HASH_SIZE, f);
+ 2759 1764308 : size = file->size;
+ 2760 1764308 : mtime_sec = file->mtime_sec;
+ 2761 1764308 : mtime_nsec = file->mtime_nsec;
+ 2762 1764308 : inode = file->inode;
+ 2763 :
+ 2764 1764308 : sputc('f', f);
+ 2765 1764308 : sputb32(disk->mapping_idx, f);
+ 2766 1764308 : sputb64(size, f);
+ 2767 1764308 : sputb64(mtime_sec, f);
+ 2768 : /* encode STAT_NSEC_INVALID as 0 */
+ 2769 1764308 : if (mtime_nsec == STAT_NSEC_INVALID)
+ 2770 0 : sputb32(0, f);
+ 2771 : else
+ 2772 1764308 : sputb32(mtime_nsec + 1, f);
+ 2773 1764308 : sputb64(inode, f);
+ 2774 1764308 : sputbs(file->sub, f);
+ 2775 1764308 : if (serror(f)) {
+ 2776 : /* LCOV_EXCL_START */
+ 2777 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2778 : return context;
+ 2779 : /* LCOV_EXCL_STOP */
+ 2780 : }
+ 2781 :
+ 2782 : /* for all the blocks of the file */
+ 2783 1764308 : begin = 0;
+ 2784 5303306 : while (begin < file->blockmax) {
+ 2785 1774690 : unsigned v_state = block_state_get(fs_file2block_get(file, begin));
+ 2786 1774690 : block_off_t v_pos = fs_file2par_get_ts(disk, &fs_last, file, begin);
+ 2787 : uint32_t v_count;
+ 2788 :
+ 2789 : block_off_t end;
+ 2790 :
+ 2791 : /* find the end of run of blocks */
+ 2792 1774690 : end = begin + 1;
+ 2793 6121077 : while (end < file->blockmax) {
+ 2794 2584536 : if (v_state != block_state_get(fs_file2block_get(file, end)))
+ 2795 11 : break;
+ 2796 2584525 : if (v_pos + (end - begin) != fs_file2par_get_ts(disk, &fs_last, file, end))
+ 2797 12828 : break;
+ 2798 2571697 : ++end;
+ 2799 : }
+ 2800 :
+ 2801 1774690 : switch (v_state) {
+ 2802 : case BLOCK_STATE_BLK :
+ 2803 1650586 : sputc('b', f);
+ 2804 1650586 : break;
+ 2805 : case BLOCK_STATE_CHG :
+ 2806 67711 : sputc('g', f);
+ 2807 67711 : break;
+ 2808 : case BLOCK_STATE_REP :
+ 2809 56393 : sputc('p', f);
+ 2810 56393 : break;
+ 2811 : default :
+ 2812 : /* LCOV_EXCL_START */
+ 2813 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state);
+ 2814 : return context;
+ 2815 : /* LCOV_EXCL_STOP */
+ 2816 : }
+ 2817 :
+ 2818 1774690 : sputb32(v_pos, f);
+ 2819 :
+ 2820 1774690 : v_count = end - begin;
+ 2821 1774690 : sputb32(v_count, f);
+ 2822 :
+ 2823 : /* write hashes */
+ 2824 6121077 : for (idx = begin; idx < end; ++idx) {
+ 2825 4346387 : struct snapraid_block* block = fs_file2block_get(file, idx);
+ 2826 :
+ 2827 4346387 : swrite(block->hash, HASH_SIZE, f);
+ 2828 : }
+ 2829 :
+ 2830 1774690 : if (serror(f)) {
+ 2831 : /* LCOV_EXCL_START */
+ 2832 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2833 : return context;
+ 2834 : /* LCOV_EXCL_STOP */
+ 2835 : }
+ 2836 :
+ 2837 : /* next begin position */
+ 2838 1774690 : begin = end;
+ 2839 : }
2840 :
- 2841 111867 : ++begin;
- 2842 : }
- 2843 : } else {
- 2844 : /* write the run of blocks without hash */
- 2845 : /* they can be either used or empty blocks */
- 2846 5240 : sputc('O', f);
+ 2841 1764308 : ++count_file;
+ 2842 : }
+ 2843 :
+ 2844 : /* for each link */
+ 2845 58592 : for (j = disk->linklist; j != 0; j = j->next) {
+ 2846 57806 : struct snapraid_link* slink = j->data;
2847 :
- 2848 : /* next begin position */
- 2849 5240 : begin = end;
- 2850 : }
- 2851 :
- 2852 5569 : if (serror(f)) {
- 2853 : /* LCOV_EXCL_START */
- 2854 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2855 : goto bail;
- 2856 : /* LCOV_EXCL_STOP */
+ 2848 57806 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) {
+ 2849 : case FILE_IS_HARDLINK :
+ 2850 315 : sputc('a', f);
+ 2851 315 : ++count_hardlink;
+ 2852 315 : break;
+ 2853 : case FILE_IS_SYMLINK :
+ 2854 57491 : sputc('s', f);
+ 2855 57491 : ++count_symlink;
+ 2856 57491 : break;
2857 : }
- 2858 : }
- 2859 : }
- 2860 :
- 2861 : /* write the info for each block */
- 2862 913 : sputc('i', f);
- 2863 913 : sputb32(info_oldest, f);
- 2864 929 : begin = 0;
- 2865 1427365 : while (begin < blockmax) {
- 2866 : snapraid_info info;
- 2867 : block_off_t end;
- 2868 : time_t t;
- 2869 : unsigned flag;
- 2870 :
- 2871 1425523 : info = info_get(&state->infoarr, begin);
- 2872 :
- 2873 : /* find the end of run of blocks */
- 2874 1426289 : end = begin + 1;
- 2875 6350808 : while (end < blockmax
- 2876 4922834 : && info == info_get(&state->infoarr, end)
- 2877 : ) {
- 2878 3498230 : ++end;
- 2879 : }
- 2880 :
- 2881 1427382 : sputb32(end - begin, f);
- 2882 :
- 2883 : /* if there is info */
- 2884 1426642 : if (info) {
- 2885 : /* other flags */
- 2886 1426512 : flag = 1; /* info is present */
- 2887 1426512 : if (info_get_bad(info))
- 2888 9590 : flag |= 2;
- 2889 1425847 : if (info_get_rehash(info))
- 2890 673003 : flag |= 4;
- 2891 1425736 : if (info_get_justsynced(info))
- 2892 724485 : flag |= 8;
- 2893 1425766 : sputb32(flag, f);
- 2894 :
- 2895 1425741 : t = info_get_time(info) - info_oldest;
- 2896 1425676 : sputb32(t, f);
- 2897 : } else {
- 2898 : /* write a special 0 flag to mark missing info */
- 2899 130 : sputb32(0, f);
- 2900 : }
- 2901 :
- 2902 1425342 : if (serror(f)) {
- 2903 : /* LCOV_EXCL_START */
- 2904 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2905 : goto bail;
- 2906 : /* LCOV_EXCL_STOP */
- 2907 : }
- 2908 :
- 2909 : /* next begin position */
- 2910 1425507 : begin = end;
- 2911 : }
+ 2858 :
+ 2859 57806 : sputb32(disk->mapping_idx, f);
+ 2860 57806 : sputbs(slink->sub, f);
+ 2861 57806 : sputbs(slink->linkto, f);
+ 2862 57806 : if (serror(f)) {
+ 2863 : /* LCOV_EXCL_START */
+ 2864 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2865 : return context;
+ 2866 : /* LCOV_EXCL_STOP */
+ 2867 : }
+ 2868 : }
+ 2869 :
+ 2870 : /* for each dir */
+ 2871 1205 : for (j = disk->dirlist; j != 0; j = j->next) {
+ 2872 419 : struct snapraid_dir* dir = j->data;
+ 2873 :
+ 2874 419 : sputc('r', f);
+ 2875 419 : sputb32(disk->mapping_idx, f);
+ 2876 419 : sputbs(dir->sub, f);
+ 2877 419 : if (serror(f)) {
+ 2878 : /* LCOV_EXCL_START */
+ 2879 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2880 : return context;
+ 2881 : /* LCOV_EXCL_STOP */
+ 2882 : }
+ 2883 :
+ 2884 419 : ++count_dir;
+ 2885 : }
+ 2886 :
+ 2887 : /* deleted blocks of the disk */
+ 2888 786 : sputc('h', f);
+ 2889 786 : sputb32(disk->mapping_idx, f);
+ 2890 786 : if (serror(f)) {
+ 2891 : /* LCOV_EXCL_START */
+ 2892 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2893 : return context;
+ 2894 : /* LCOV_EXCL_STOP */
+ 2895 : }
+ 2896 786 : begin = 0;
+ 2897 2435 : while (begin < blockmax) {
+ 2898 : int is_deleted;
+ 2899 : block_off_t end;
+ 2900 :
+ 2901 863 : is_deleted = fs_is_block_deleted_ts(disk, &fs_last, begin);
+ 2902 :
+ 2903 : /* find the end of run of blocks */
+ 2904 863 : end = begin + 1;
+ 2905 4508642 : while (end < blockmax
+ 2906 4506993 : && is_deleted == fs_is_block_deleted_ts(disk, &fs_last, end)
+ 2907 : ) {
+ 2908 4506916 : ++end;
+ 2909 : }
+ 2910 :
+ 2911 863 : sputb32(end - begin, f);
2912 :
- 2913 913 : sputc('N', f);
- 2914 :
- 2915 : /* flush data written to the disk */
- 2916 913 : if (sflush(f)) {
- 2917 : /* LCOV_EXCL_START */
- 2918 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno));
- 2919 : goto bail;
- 2920 : /* LCOV_EXCL_STOP */
- 2921 : }
+ 2913 863 : if (is_deleted) {
+ 2914 : /* write the run of deleted blocks with hash */
+ 2915 49 : sputc('o', f);
+ 2916 :
+ 2917 : /* write all the hash */
+ 2918 15941 : while (begin < end) {
+ 2919 15843 : struct snapraid_block* block = fs_par2block_get_ts(disk, &fs_last, begin);
+ 2920 :
+ 2921 15843 : swrite(block->hash, HASH_SIZE, f);
2922 :
- 2923 : /* get the file crc */
- 2924 913 : crc = scrc(f);
- 2925 :
- 2926 : /* compare the crc of the data written to file */
- 2927 : /* with the one of the data written to the stream */
- 2928 913 : if (crc != scrc_stream(f)) {
- 2929 : /* LCOV_EXCL_START */
- 2930 : log_fatal("CRC mismatch writing the content stream.\n");
- 2931 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
- 2932 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
- 2933 : goto bail;
- 2934 : /* LCOV_EXCL_STOP */
- 2935 : }
- 2936 :
- 2937 913 : sputble32(crc, f);
- 2938 913 : if (serror(f)) {
- 2939 : /* LCOV_EXCL_START */
- 2940 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2941 : goto bail;
- 2942 : /* LCOV_EXCL_STOP */
- 2943 : }
- 2944 :
- 2945 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
- 2946 : /* than even in a system crash event we have one valid copy of the file. */
- 2947 913 : if (sflush(f) != 0) {
- 2948 : /* LCOV_EXCL_START */
- 2949 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
- 2950 : goto bail;
- 2951 : /* LCOV_EXCL_STOP */
- 2952 : }
- 2953 :
- 2954 : #if HAVE_FSYNC
- 2955 913 : if (ssync(f) != 0) {
- 2956 : /* LCOV_EXCL_START */
- 2957 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
- 2958 : goto bail;
- 2959 : /* LCOV_EXCL_STOP */
- 2960 : }
- 2961 : #endif
+ 2923 15843 : ++begin;
+ 2924 : }
+ 2925 : } else {
+ 2926 : /* write the run of blocks without hash */
+ 2927 : /* they can be either used or empty blocks */
+ 2928 814 : sputc('O', f);
+ 2929 :
+ 2930 : /* next begin position */
+ 2931 814 : begin = end;
+ 2932 : }
+ 2933 :
+ 2934 863 : if (serror(f)) {
+ 2935 : /* LCOV_EXCL_START */
+ 2936 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2937 : return context;
+ 2938 : /* LCOV_EXCL_STOP */
+ 2939 : }
+ 2940 : }
+ 2941 : }
+ 2942 :
+ 2943 : /* write the info for each block */
+ 2944 145 : sputc('i', f);
+ 2945 145 : sputb32(info_oldest, f);
+ 2946 145 : begin = 0;
+ 2947 30551 : while (begin < blockmax) {
+ 2948 : snapraid_info info;
+ 2949 : block_off_t end;
+ 2950 : time_t t;
+ 2951 : unsigned flag;
+ 2952 :
+ 2953 30261 : info = info_get(&state->infoarr, begin);
+ 2954 :
+ 2955 : /* find the end of run of blocks */
+ 2956 30261 : end = begin + 1;
+ 2957 782752 : while (end < blockmax
+ 2958 752349 : && info == info_get(&state->infoarr, end)
+ 2959 : ) {
+ 2960 722230 : ++end;
+ 2961 : }
2962 :
- 2963 913 : if (sclose(f) != 0) {
- 2964 : /* LCOV_EXCL_START */
- 2965 : f = 0;
- 2966 : log_fatal("Error closing the content files. %s.\n", strerror(errno));
- 2967 : goto bail;
- 2968 : /* LCOV_EXCL_STOP */
- 2969 : }
- 2970 :
- 2971 : /* set output variables */
- 2972 913 : context->crc = crc;
- 2973 913 : context->count_file = count_file;
- 2974 913 : context->count_hardlink = count_hardlink;
- 2975 913 : context->count_symlink = count_symlink;
- 2976 913 : context->count_dir = count_dir;
- 2977 :
- 2978 913 : return 0;
- 2979 :
- 2980 : /* LCOV_EXCL_START */
- 2981 : bail:
- 2982 : /* cleanup resources */
- 2983 : if (f != 0)
- 2984 : sclose(f);
- 2985 : return context;
- 2986 : /* LCOV_EXCL_STOP */
- 2987 : }
- 2988 :
- 2989 134 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
- 2990 : {
- 2991 : tommy_node* i;
- 2992 : int fail;
- 2993 : block_off_t blockmax;
- 2994 : time_t info_oldest;
- 2995 : int info_has_rehash;
- 2996 : int mapping_idx;
- 2997 : block_off_t idx;
- 2998 : uint32_t crc;
- 2999 : unsigned count_file;
- 3000 : unsigned count_hardlink;
- 3001 : unsigned count_symlink;
- 3002 : unsigned count_dir;
- 3003 : int first;
+ 2963 30261 : sputb32(end - begin, f);
+ 2964 :
+ 2965 : /* if there is info */
+ 2966 30261 : if (info) {
+ 2967 : /* other flags */
+ 2968 30239 : flag = 1; /* info is present */
+ 2969 30239 : if (info_get_bad(info))
+ 2970 1351 : flag |= 2;
+ 2971 30239 : if (info_get_rehash(info))
+ 2972 9806 : flag |= 4;
+ 2973 30239 : if (info_get_justsynced(info))
+ 2974 18186 : flag |= 8;
+ 2975 30239 : sputb32(flag, f);
+ 2976 :
+ 2977 30239 : t = info_get_time(info) - info_oldest;
+ 2978 30239 : sputb32(t, f);
+ 2979 : } else {
+ 2980 : /* write a special 0 flag to mark missing info */
+ 2981 22 : sputb32(0, f);
+ 2982 : }
+ 2983 :
+ 2984 30261 : if (serror(f)) {
+ 2985 : /* LCOV_EXCL_START */
+ 2986 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2987 : return context;
+ 2988 : /* LCOV_EXCL_STOP */
+ 2989 : }
+ 2990 :
+ 2991 : /* next begin position */
+ 2992 30261 : begin = end;
+ 2993 : }
+ 2994 :
+ 2995 145 : sputc('N', f);
+ 2996 :
+ 2997 : /* flush data written to the disk */
+ 2998 145 : if (sflush(f)) {
+ 2999 : /* LCOV_EXCL_START */
+ 3000 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno));
+ 3001 : return context;
+ 3002 : /* LCOV_EXCL_STOP */
+ 3003 : }
3004 :
- 3005 : /* blocks of all array */
- 3006 134 : blockmax = parity_allocated_size(state);
+ 3005 : /* get the file crc */
+ 3006 145 : crc = scrc(f);
3007 :
- 3008 : /* check the filesystem on all disks */
- 3009 134 : state_fscheck(state, "before write");
- 3010 :
- 3011 : /* clear the info for unused blocks */
- 3012 : /* and get some other info */
- 3013 134 : info_oldest = 0; /* oldest time in info */
- 3014 134 : info_has_rehash = 0; /* if there is a rehash info */
- 3015 729552 : for (idx = 0; idx < blockmax; ++idx) {
- 3016 : /* if the position is used */
- 3017 729418 : if (fs_position_is_required(state, idx)) {
- 3018 729418 : snapraid_info info = info_get(&state->infoarr, idx);
- 3019 :
- 3020 : /* only if there is some info to store */
- 3021 729418 : if (info) {
- 3022 680773 : time_t info_time = info_get_time(info);
- 3023 :
- 3024 680773 : if (!info_oldest || info_time < info_oldest)
- 3025 170 : info_oldest = info_time;
+ 3008 : /* compare the crc of the data written to file */
+ 3009 : /* with the one of the data written to the stream */
+ 3010 145 : if (crc != scrc_stream(f)) {
+ 3011 : /* LCOV_EXCL_START */
+ 3012 : log_fatal("CRC mismatch writing the content stream.\n");
+ 3013 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
+ 3014 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
+ 3015 : return context;
+ 3016 : /* LCOV_EXCL_STOP */
+ 3017 : }
+ 3018 :
+ 3019 145 : sputble32(crc, f);
+ 3020 145 : if (serror(f)) {
+ 3021 : /* LCOV_EXCL_START */
+ 3022 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3023 : return context;
+ 3024 : /* LCOV_EXCL_STOP */
+ 3025 : }
3026 :
- 3027 680773 : if (info_get_rehash(info))
- 3028 108421 : info_has_rehash = 1;
- 3029 : }
- 3030 : } else {
- 3031 : /* clear any previous info */
- 3032 0 : info_set(&state->infoarr, idx, 0);
+ 3027 : /* set output variables */
+ 3028 145 : context->crc = crc;
+ 3029 145 : context->count_file = count_file;
+ 3030 145 : context->count_hardlink = count_hardlink;
+ 3031 145 : context->count_symlink = count_symlink;
+ 3032 145 : context->count_dir = count_dir;
3033 :
- 3034 : /* and clear any deleted blocks */
- 3035 0 : fs_position_clear_deleted(state, idx);
- 3036 : }
- 3037 : }
- 3038 :
- 3039 : /* map disks */
- 3040 134 : mapping_idx = 0;
- 3041 938 : for (i = state->maplist; i != 0; i = i->next) {
- 3042 804 : struct snapraid_map* map = i->data;
- 3043 : struct snapraid_disk* disk;
- 3044 :
- 3045 : /* find the disk for this mapping */
- 3046 804 : disk = find_disk(state, map->name);
- 3047 804 : if (!disk) {
- 3048 : /* LCOV_EXCL_START */
- 3049 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
- 3050 : exit(EXIT_FAILURE);
- 3051 : /* LCOV_EXCL_STOP */
- 3052 : }
- 3053 :
- 3054 : /* save the mapping only for not empty disks */
- 3055 804 : if (!disk_is_empty(disk, blockmax)) {
- 3056 : /* assign the mapping index used to identify disks */
- 3057 741 : disk->mapping_idx = mapping_idx;
- 3058 741 : ++mapping_idx;
- 3059 : } else {
- 3060 : /* mark the disk as without mapping */
- 3061 63 : disk->mapping_idx = -1;
- 3062 : }
- 3063 : }
- 3064 :
- 3065 : /* start all writing threads */
- 3066 134 : i = tommy_list_head(&state->contentlist);
- 3067 1181 : while (i) {
- 3068 913 : struct snapraid_content* content = i->data;
- 3069 : struct state_write_thread_context* context;
- 3070 :
- 3071 : /* allocate the thread context */
- 3072 913 : context = malloc_nofail(sizeof(struct state_write_thread_context));
- 3073 913 : content->context = context;
- 3074 :
- 3075 : /* initialize */
- 3076 913 : context->state = state;
- 3077 913 : context->content = content;
- 3078 913 : context->blockmax = blockmax;
- 3079 913 : context->info_oldest = info_oldest;
- 3080 913 : context->info_has_rehash = info_has_rehash;
- 3081 :
- 3082 913 : msg_progress("Saving state to %s...\n", content->content);
- 3083 :
- 3084 : #if HAVE_PTHREAD_CREATE
- 3085 913 : if (pthread_create(&context->thread, 0, state_write_thread, context) != 0) {
- 3086 : /* LCOV_EXCL_START */
- 3087 : log_fatal("Failed to create thread.\n");
- 3088 : exit(EXIT_FAILURE);
- 3089 : /* LCOV_EXCL_STOP */
- 3090 : }
- 3091 : #else
- 3092 : context->retval = state_write_thread(context);
- 3093 : #endif
+ 3034 145 : return 0;
+ 3035 : }
+ 3036 :
+ 3037 145 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
+ 3038 : {
+ 3039 : #if HAVE_MT_WRITE
+ 3040 : int fail;
+ 3041 : int first;
+ 3042 : #else
+ 3043 : STREAM* f;
+ 3044 : unsigned count_content;
+ 3045 : unsigned k;
+ 3046 : struct state_write_thread_context* context;
+ 3047 : void* retval;
+ 3048 : #endif
+ 3049 : tommy_node* i;
+ 3050 : block_off_t blockmax;
+ 3051 : time_t info_oldest;
+ 3052 : int info_has_rehash;
+ 3053 : int mapping_idx;
+ 3054 : block_off_t idx;
+ 3055 : uint32_t crc;
+ 3056 : unsigned count_file;
+ 3057 : unsigned count_hardlink;
+ 3058 : unsigned count_symlink;
+ 3059 : unsigned count_dir;
+ 3060 :
+ 3061 : /* blocks of all array */
+ 3062 145 : blockmax = parity_allocated_size(state);
+ 3063 :
+ 3064 : /* check the file-system on all disks */
+ 3065 145 : state_fscheck(state, "before write");
+ 3066 :
+ 3067 : /* clear the info for unused blocks */
+ 3068 : /* and get some other info */
+ 3069 145 : info_oldest = 0; /* oldest time in info */
+ 3070 145 : info_has_rehash = 0; /* if there is a rehash info */
+ 3071 752636 : for (idx = 0; idx < blockmax; ++idx) {
+ 3072 : /* if the position is used */
+ 3073 752491 : if (fs_position_is_required(state, idx)) {
+ 3074 752491 : snapraid_info info = info_get(&state->infoarr, idx);
+ 3075 :
+ 3076 : /* only if there is some info to store */
+ 3077 752491 : if (info) {
+ 3078 708014 : time_t info_time = info_get_time(info);
+ 3079 :
+ 3080 708014 : if (!info_oldest || info_time < info_oldest)
+ 3081 155 : info_oldest = info_time;
+ 3082 :
+ 3083 708014 : if (info_get_rehash(info))
+ 3084 18413 : info_has_rehash = 1;
+ 3085 : }
+ 3086 : } else {
+ 3087 : /* clear any previous info */
+ 3088 0 : info_set(&state->infoarr, idx, 0);
+ 3089 :
+ 3090 : /* and clear any deleted blocks */
+ 3091 0 : fs_position_clear_deleted(state, idx);
+ 3092 : }
+ 3093 : }
3094 :
- 3095 913 : i = i->next;
- 3096 : }
- 3097 :
- 3098 : /* join all thread */
- 3099 134 : fail = 0;
- 3100 134 : first = 1;
- 3101 134 : crc = 0;
- 3102 134 : count_file = 0;
- 3103 134 : count_hardlink = 0;
- 3104 134 : count_symlink = 0;
- 3105 134 : count_dir = 0;
- 3106 134 : i = tommy_list_head(&state->contentlist);
- 3107 1181 : while (i) {
- 3108 913 : struct snapraid_content* content = i->data;
- 3109 913 : struct state_write_thread_context* context = content->context;
- 3110 : void* retval;
- 3111 :
- 3112 : #if HAVE_PTHREAD_CREATE
- 3113 913 : if (pthread_join(context->thread, &retval) != 0) {
- 3114 : /* LCOV_EXCL_START */
- 3115 : log_fatal("Failed to join thread.\n");
- 3116 : exit(EXIT_FAILURE);
- 3117 : /* LCOV_EXCL_STOP */
+ 3095 : /* map disks */
+ 3096 145 : mapping_idx = 0;
+ 3097 1015 : for (i = state->maplist; i != 0; i = i->next) {
+ 3098 870 : struct snapraid_map* map = i->data;
+ 3099 : struct snapraid_disk* disk;
+ 3100 :
+ 3101 : /* find the disk for this mapping */
+ 3102 870 : disk = find_disk_by_name(state, map->name);
+ 3103 870 : if (!disk) {
+ 3104 : /* LCOV_EXCL_START */
+ 3105 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
+ 3106 : os_abort();
+ 3107 : /* LCOV_EXCL_STOP */
+ 3108 : }
+ 3109 :
+ 3110 : /* save the mapping only for not empty disks */
+ 3111 870 : if (!disk_is_empty(disk, blockmax)) {
+ 3112 : /* assign the mapping index used to identify disks */
+ 3113 786 : disk->mapping_idx = mapping_idx;
+ 3114 786 : ++mapping_idx;
+ 3115 : } else {
+ 3116 : /* mark the disk as without mapping */
+ 3117 84 : disk->mapping_idx = -1;
3118 : }
- 3119 : #else
- 3120 : retval = context->retval;
- 3121 : #endif
- 3122 913 : if (retval) {
- 3123 : /* LCOV_EXCL_START */
- 3124 : fail = 1;
- 3125 : /* LCOV_EXCL_STOP */
- 3126 : } else {
- 3127 913 : if (first) {
- 3128 134 : first = 0;
- 3129 134 : crc = context->crc;
- 3130 134 : count_file = context->count_file;
- 3131 134 : count_hardlink = context->count_hardlink;
- 3132 134 : count_symlink = context->count_symlink;
- 3133 134 : count_dir = context->count_dir;
- 3134 : } else {
- 3135 779 : if (crc != context->crc) {
- 3136 : /* LCOV_EXCL_START */
- 3137 : log_fatal("Different CRCs writing content streams.\n");
- 3138 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
- 3139 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
- 3140 : exit(EXIT_FAILURE);
- 3141 : /* LCOV_EXCL_STOP */
- 3142 : }
- 3143 : }
- 3144 : }
- 3145 :
- 3146 913 : free(context);
- 3147 :
- 3148 913 : i = i->next;
- 3149 : }
- 3150 :
- 3151 : /* abort on failure */
- 3152 134 : if (fail) {
- 3153 : /* LCOV_EXCL_START */
- 3154 : exit(EXIT_FAILURE);
- 3155 : /* LCOV_EXCL_STOP */
- 3156 : }
- 3157 :
- 3158 134 : msg_verbose("%8u files\n", count_file);
- 3159 134 : msg_verbose("%8u hardlinks\n", count_hardlink);
- 3160 134 : msg_verbose("%8u symlinks\n", count_symlink);
- 3161 134 : msg_verbose("%8u empty dirs\n", count_dir);
- 3162 :
- 3163 134 : *out_crc = crc;
- 3164 134 : }
- 3165 :
- 3166 242 : void state_read(struct snapraid_state* state)
- 3167 : {
- 3168 : STREAM* f;
- 3169 : char path[PATH_MAX];
- 3170 : struct stat st;
- 3171 : tommy_node* node;
- 3172 : int ret;
- 3173 : int c;
- 3174 :
- 3175 : /* iterate over all the available content files and load the first one present */
- 3176 242 : f = 0;
- 3177 242 : node = tommy_list_head(&state->contentlist);
- 3178 534 : while (node) {
- 3179 285 : struct snapraid_content* content = node->data;
- 3180 285 : pathcpy(path, sizeof(path), content->content);
- 3181 :
- 3182 285 : if (!state->no_conf) {
- 3183 284 : log_tag("content:%s\n", path);
- 3184 284 : log_flush();
- 3185 : }
- 3186 285 : msg_progress("Loading state from %s...\n", path);
- 3187 :
- 3188 285 : f = sopen_read(path);
- 3189 285 : if (f != 0) {
- 3190 : /* if openend stop the search */
- 3191 235 : break;
- 3192 : } else {
- 3193 : /* if it's real error of an existing file, abort */
- 3194 50 : if (errno != ENOENT) {
- 3195 : /* LCOV_EXCL_START */
- 3196 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno));
- 3197 : exit(EXIT_FAILURE);
- 3198 : /* LCOV_EXCL_STOP */
- 3199 : }
- 3200 :
- 3201 : /* otherwise continue */
- 3202 50 : if (node->next) {
- 3203 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path);
- 3204 :
- 3205 : /* ensure to rewrite all the content files */
- 3206 43 : state->need_write = 1;
- 3207 : }
- 3208 : }
- 3209 :
- 3210 : /* next content file */
- 3211 50 : node = node->next;
- 3212 : }
- 3213 :
- 3214 : /* if not found, assume empty */
- 3215 242 : if (!f) {
- 3216 7 : log_fatal("No content file found. Assuming empty.\n");
- 3217 :
- 3218 : /* create the initial mapping */
- 3219 7 : state_map(state);
- 3220 248 : return;
- 3221 : }
- 3222 :
- 3223 : /* get the stat of the content file */
- 3224 235 : ret = fstat(shandle(f), &st);
- 3225 235 : if (ret != 0) {
- 3226 : /* LCOV_EXCL_START */
- 3227 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno));
- 3228 : exit(EXIT_FAILURE);
- 3229 : /* LCOV_EXCL_STOP */
- 3230 : }
- 3231 :
- 3232 : /* go further to check other content files */
- 3233 1819 : while (node) {
- 3234 : char other_path[PATH_MAX];
- 3235 : struct stat other_st;
- 3236 1349 : struct snapraid_content* content = node->data;
- 3237 1349 : pathcpy(other_path, sizeof(other_path), content->content);
+ 3119 : }
+ 3120 :
+ 3121 : #if HAVE_MT_WRITE
+ 3122 : /* start all writing threads */
+ 3123 : i = tommy_list_head(&state->contentlist);
+ 3124 : while (i) {
+ 3125 : struct snapraid_content* content = i->data;
+ 3126 : struct state_write_thread_context* context;
+ 3127 : char tmp[PATH_MAX];
+ 3128 : STREAM* f;
+ 3129 :
+ 3130 : msg_progress("Saving state to %s...\n", content->content);
+ 3131 :
+ 3132 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3133 : f = sopen_write(tmp);
+ 3134 : if (f == 0) {
+ 3135 : /* LCOV_EXCL_START */
+ 3136 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3137 : exit(EXIT_FAILURE);
+ 3138 : /* LCOV_EXCL_STOP */
+ 3139 : }
+ 3140 :
+ 3141 : /* allocate the thread context */
+ 3142 : context = malloc_nofail(sizeof(struct state_write_thread_context));
+ 3143 : content->context = context;
+ 3144 :
+ 3145 : /* initialize */
+ 3146 : context->state = state;
+ 3147 : context->blockmax = blockmax;
+ 3148 : context->info_oldest = info_oldest;
+ 3149 : context->info_has_rehash = info_has_rehash;
+ 3150 : context->f = f;
+ 3151 :
+ 3152 : if (pthread_create(&context->thread, 0, state_write_thread, context) != 0) {
+ 3153 : /* LCOV_EXCL_START */
+ 3154 : log_fatal("Failed to create thread.\n");
+ 3155 : exit(EXIT_FAILURE);
+ 3156 : /* LCOV_EXCL_STOP */
+ 3157 : }
+ 3158 :
+ 3159 : i = i->next;
+ 3160 : }
+ 3161 :
+ 3162 : /* join all thread */
+ 3163 : fail = 0;
+ 3164 : first = 1;
+ 3165 : crc = 0;
+ 3166 : count_file = 0;
+ 3167 : count_hardlink = 0;
+ 3168 : count_symlink = 0;
+ 3169 : count_dir = 0;
+ 3170 : i = tommy_list_head(&state->contentlist);
+ 3171 : while (i) {
+ 3172 : struct snapraid_content* content = i->data;
+ 3173 : struct state_write_thread_context* context = content->context;
+ 3174 : void* retval;
+ 3175 :
+ 3176 : if (pthread_join(context->thread, &retval) != 0) {
+ 3177 : /* LCOV_EXCL_START */
+ 3178 : log_fatal("Failed to join thread.\n");
+ 3179 : exit(EXIT_FAILURE);
+ 3180 : /* LCOV_EXCL_STOP */
+ 3181 : }
+ 3182 :
+ 3183 : if (retval) {
+ 3184 : /* LCOV_EXCL_START */
+ 3185 : fail = 1;
+ 3186 : /* LCOV_EXCL_STOP */
+ 3187 : } else {
+ 3188 : STREAM* f = context->f;
+ 3189 :
+ 3190 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
+ 3191 : /* than even in a system crash event we have one valid copy of the file. */
+ 3192 : if (sflush(f) != 0) {
+ 3193 : /* LCOV_EXCL_START */
+ 3194 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
+ 3195 : exit(EXIT_FAILURE);
+ 3196 : /* LCOV_EXCL_STOP */
+ 3197 : }
+ 3198 :
+ 3199 : #if HAVE_FSYNC
+ 3200 : if (ssync(f) != 0) {
+ 3201 : /* LCOV_EXCL_START */
+ 3202 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
+ 3203 : exit(EXIT_FAILURE);
+ 3204 : /* LCOV_EXCL_STOP */
+ 3205 : }
+ 3206 : #endif
+ 3207 :
+ 3208 : if (sclose(f) != 0) {
+ 3209 : /* LCOV_EXCL_START */
+ 3210 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3211 : exit(EXIT_FAILURE);
+ 3212 : /* LCOV_EXCL_STOP */
+ 3213 : }
+ 3214 :
+ 3215 : if (first) {
+ 3216 : first = 0;
+ 3217 : crc = context->crc;
+ 3218 : count_file = context->count_file;
+ 3219 : count_hardlink = context->count_hardlink;
+ 3220 : count_symlink = context->count_symlink;
+ 3221 : count_dir = context->count_dir;
+ 3222 : } else {
+ 3223 : if (crc != context->crc) {
+ 3224 : /* LCOV_EXCL_START */
+ 3225 : log_fatal("Different CRCs writing content streams.\n");
+ 3226 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
+ 3227 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
+ 3228 : exit(EXIT_FAILURE);
+ 3229 : /* LCOV_EXCL_STOP */
+ 3230 : }
+ 3231 : }
+ 3232 : }
+ 3233 :
+ 3234 : free(context);
+ 3235 :
+ 3236 : i = i->next;
+ 3237 : }
3238 :
- 3239 1349 : ret = stat(other_path, &other_st);
- 3240 1349 : if (ret != 0) {
- 3241 : /* allow missing content files, but not any other kind of error */
- 3242 1 : if (errno != ENOENT) {
- 3243 : /* LCOV_EXCL_START */
- 3244 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno));
- 3245 : exit(EXIT_FAILURE);
- 3246 : /* LCOV_EXCL_STOP */
- 3247 : }
- 3248 :
- 3249 : /* ensure to rewrite all the content files */
- 3250 1 : state->need_write = 1;
- 3251 : } else {
- 3252 : /* if the size is different */
- 3253 1348 : if (other_st.st_size != st.st_size) {
- 3254 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path);
- 3255 39 : log_fatal("Likely one of the two is broken!\n");
- 3256 :
- 3257 : /* ensure to rewrite all the content files */
- 3258 39 : state->need_write = 1;
- 3259 : }
- 3260 : }
- 3261 :
- 3262 : /* next content file */
- 3263 1349 : node = node->next;
- 3264 : }
- 3265 :
- 3266 : /* start with a undefined default. */
- 3267 : /* it's for compatibility with version 1.0 where MD5 was implicit. */
- 3268 235 : state->hash = HASH_UNDEFINED;
- 3269 :
- 3270 : /* start with a zero seed, it was the default in old versions */
- 3271 235 : memset(state->hashseed, 0, HASH_SIZE);
- 3272 :
- 3273 : /* previous hash, start with an undefined value */
- 3274 235 : state->prevhash = HASH_UNDEFINED;
- 3275 :
- 3276 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
- 3277 :
- 3278 : /* get the first char to detect the file type */
- 3279 235 : c = sgetc(f);
- 3280 235 : sungetc(c, f);
- 3281 :
- 3282 : /* guess the file type from the first char */
- 3283 235 : if (c == 'S') {
- 3284 235 : state_read_content(state, path, f);
- 3285 : } else {
- 3286 : /* LCOV_EXCL_START */
- 3287 : log_fatal("The text file format is not supported anymore.\n");
- 3288 : exit(EXIT_FAILURE);
- 3289 : /* LCOV_EXCL_STOP */
- 3290 : }
- 3291 :
- 3292 234 : sclose(f);
- 3293 :
- 3294 234 : if (state->hash == HASH_UNDEFINED) {
+ 3239 : /* abort on failure */
+ 3240 : if (fail) {
+ 3241 : /* LCOV_EXCL_START */
+ 3242 : exit(EXIT_FAILURE);
+ 3243 : /* LCOV_EXCL_STOP */
+ 3244 : }
+ 3245 : #else
+ 3246 : /* count the content files */
+ 3247 145 : count_content = 0;
+ 3248 145 : i = tommy_list_head(&state->contentlist);
+ 3249 1280 : while (i) {
+ 3250 990 : struct snapraid_content* content = i->data;
+ 3251 990 : msg_progress("Saving state to %s...\n", content->content);
+ 3252 990 : ++count_content;
+ 3253 990 : i = i->next;
+ 3254 : }
+ 3255 :
+ 3256 : /* open all the content files */
+ 3257 145 : f = sopen_multi_write(count_content);
+ 3258 145 : if (!f) {
+ 3259 : /* LCOV_EXCL_START */
+ 3260 : log_fatal("Error opening the content files.\n");
+ 3261 : exit(EXIT_FAILURE);
+ 3262 : /* LCOV_EXCL_STOP */
+ 3263 : }
+ 3264 :
+ 3265 145 : k = 0;
+ 3266 145 : i = tommy_list_head(&state->contentlist);
+ 3267 1280 : while (i) {
+ 3268 990 : struct snapraid_content* content = i->data;
+ 3269 : char tmp[PATH_MAX];
+ 3270 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3271 990 : if (sopen_multi_file(f, k, tmp) != 0) {
+ 3272 : /* LCOV_EXCL_START */
+ 3273 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3274 : exit(EXIT_FAILURE);
+ 3275 : /* LCOV_EXCL_STOP */
+ 3276 : }
+ 3277 990 : ++k;
+ 3278 990 : i = i->next;
+ 3279 : }
+ 3280 :
+ 3281 : /* allocate the thread context */
+ 3282 145 : context = malloc_nofail(sizeof(struct state_write_thread_context));
+ 3283 :
+ 3284 : /* initialize */
+ 3285 145 : context->state = state;
+ 3286 145 : context->blockmax = blockmax;
+ 3287 145 : context->info_oldest = info_oldest;
+ 3288 145 : context->info_has_rehash = info_has_rehash;
+ 3289 145 : context->f = f;
+ 3290 :
+ 3291 145 : retval = state_write_thread(context);
+ 3292 :
+ 3293 : /* abort on failure */
+ 3294 145 : if (retval) {
3295 : /* LCOV_EXCL_START */
- 3296 : log_fatal("The checksum to use is not specified.\n");
- 3297 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n");
- 3298 : log_fatal("To use a new SnapRAID you must restart from scratch,\n");
- 3299 : log_fatal("deleting all the content and parity files.\n");
- 3300 : exit(EXIT_FAILURE);
- 3301 : /* LCOV_EXCL_STOP */
- 3302 : }
- 3303 :
- 3304 : /* update the mapping */
- 3305 234 : state_map(state);
- 3306 :
- 3307 234 : state_content_check(state, path);
+ 3296 : exit(EXIT_FAILURE);
+ 3297 : /* LCOV_EXCL_STOP */
+ 3298 : }
+ 3299 :
+ 3300 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
+ 3301 : /* than even in a system crash event we have one valid copy of the file. */
+ 3302 145 : if (sflush(f) != 0) {
+ 3303 : /* LCOV_EXCL_START */
+ 3304 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
+ 3305 : exit(EXIT_FAILURE);
+ 3306 : /* LCOV_EXCL_STOP */
+ 3307 : }
3308 :
- 3309 : /* mark that we read the content file, and it passed all the checks */
- 3310 234 : state->checked_read = 1;
- 3311 : }
- 3312 :
- 3313 : struct state_verify_thread_context {
- 3314 : struct snapraid_state* state;
- 3315 : struct snapraid_content* content;
- 3316 : #if HAVE_PTHREAD_CREATE
- 3317 : pthread_t thread;
- 3318 : #else
- 3319 : void* retval;
- 3320 : #endif
- 3321 : /* input */
- 3322 : uint32_t crc;
- 3323 : };
+ 3309 : #if HAVE_FSYNC
+ 3310 145 : if (ssync(f) != 0) {
+ 3311 : /* LCOV_EXCL_START */
+ 3312 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
+ 3313 : exit(EXIT_FAILURE);
+ 3314 : /* LCOV_EXCL_STOP */
+ 3315 : }
+ 3316 : #endif
+ 3317 :
+ 3318 145 : if (sclose(f) != 0) {
+ 3319 : /* LCOV_EXCL_START */
+ 3320 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3321 : exit(EXIT_FAILURE);
+ 3322 : /* LCOV_EXCL_STOP */
+ 3323 : }
3324 :
- 3325 912 : static void* state_verify_thread(void* arg)
- 3326 : {
- 3327 912 : struct state_verify_thread_context* context = arg;
- 3328 912 : struct snapraid_content* content = context->content;
- 3329 : STREAM* f;
- 3330 : char tmp[PATH_MAX];
- 3331 : unsigned char buf[4];
- 3332 : uint32_t crc_stored;
- 3333 : uint32_t crc_computed;
- 3334 :
- 3335 912 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3336 :
- 3337 913 : f = sopen_read(tmp);
- 3338 913 : if (f == 0) {
- 3339 : /* LCOV_EXCL_START */
- 3340 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno));
- 3341 : goto bail;
- 3342 : /* LCOV_EXCL_STOP */
- 3343 : }
- 3344 :
- 3345 913 : if (sdeplete(f, buf) != 0) {
- 3346 : /* LCOV_EXCL_START */
- 3347 : log_fatal("Error flushing the content file '%s'. %s.\n", tmp, strerror(errno));
- 3348 : goto bail;
- 3349 : /* LCOV_EXCL_STOP */
- 3350 : }
- 3351 :
- 3352 : /* get the stored crc from the last four bytes */
- 3353 913 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
- 3354 :
- 3355 913 : if (crc_stored != context->crc) {
- 3356 : /* LCOV_EXCL_START */
- 3357 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", tmp);
- 3358 : goto bail;
- 3359 : /* LCOV_EXCL_STOP */
- 3360 : }
- 3361 :
- 3362 : /* get the computed crc */
- 3363 913 : crc_computed = scrc(f);
- 3364 :
- 3365 : /* adjust the stored crc to include itself */
- 3366 913 : crc_stored = crc32c(crc_stored, buf, 4);
- 3367 :
- 3368 913 : if (crc_computed != crc_stored) {
- 3369 : /* LCOV_EXCL_START */
- 3370 : log_fatal("DANGER! Wrong file CRC in '%s'\n", tmp);
- 3371 : goto bail;
- 3372 : /* LCOV_EXCL_STOP */
- 3373 : }
- 3374 :
- 3375 913 : if (sclose(f) != 0) {
- 3376 : /* LCOV_EXCL_START */
- 3377 : f = 0;
- 3378 : log_fatal("Error closing the content file '%s'. %s.\n", tmp, strerror(errno));
- 3379 : goto bail;
- 3380 : /* LCOV_EXCL_STOP */
- 3381 : }
- 3382 :
- 3383 913 : return 0;
- 3384 :
- 3385 : bail:
- 3386 : /* LCOV_EXCL_START */
- 3387 : /* cleanup resources */
- 3388 : if (f != 0)
- 3389 : sclose(f);
- 3390 : return context;
- 3391 : /* LCOV_EXCL_STOP */
- 3392 : }
+ 3325 145 : crc = context->crc;
+ 3326 145 : count_file = context->count_file;
+ 3327 145 : count_hardlink = context->count_hardlink;
+ 3328 145 : count_symlink = context->count_symlink;
+ 3329 145 : count_dir = context->count_dir;
+ 3330 :
+ 3331 145 : free(context);
+ 3332 : #endif
+ 3333 :
+ 3334 145 : msg_verbose("%8u files\n", count_file);
+ 3335 145 : msg_verbose("%8u hardlinks\n", count_hardlink);
+ 3336 145 : msg_verbose("%8u symlinks\n", count_symlink);
+ 3337 145 : msg_verbose("%8u empty dirs\n", count_dir);
+ 3338 :
+ 3339 145 : *out_crc = crc;
+ 3340 145 : }
+ 3341 :
+ 3342 250 : void state_read(struct snapraid_state* state)
+ 3343 : {
+ 3344 : STREAM* f;
+ 3345 : char path[PATH_MAX];
+ 3346 : struct stat st;
+ 3347 : tommy_node* node;
+ 3348 : int ret;
+ 3349 : int c;
+ 3350 :
+ 3351 : /* iterate over all the available content files and load the first one present */
+ 3352 250 : f = 0;
+ 3353 250 : node = tommy_list_head(&state->contentlist);
+ 3354 550 : while (node) {
+ 3355 293 : struct snapraid_content* content = node->data;
+ 3356 293 : pathcpy(path, sizeof(path), content->content);
+ 3357 :
+ 3358 293 : if (!state->no_conf) {
+ 3359 292 : log_tag("content:%s\n", path);
+ 3360 292 : log_flush();
+ 3361 : }
+ 3362 293 : msg_progress("Loading state from %s...\n", path);
+ 3363 :
+ 3364 293 : f = sopen_read(path);
+ 3365 293 : if (f != 0) {
+ 3366 : /* if opened stop the search */
+ 3367 243 : break;
+ 3368 : } else {
+ 3369 : /* if it's real error of an existing file, abort */
+ 3370 50 : if (errno != ENOENT) {
+ 3371 : /* LCOV_EXCL_START */
+ 3372 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno));
+ 3373 : exit(EXIT_FAILURE);
+ 3374 : /* LCOV_EXCL_STOP */
+ 3375 : }
+ 3376 :
+ 3377 : /* otherwise continue */
+ 3378 50 : if (node->next) {
+ 3379 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path);
+ 3380 :
+ 3381 : /* ensure to rewrite all the content files */
+ 3382 43 : state->need_write = 1;
+ 3383 : }
+ 3384 : }
+ 3385 :
+ 3386 : /* next content file */
+ 3387 50 : node = node->next;
+ 3388 : }
+ 3389 :
+ 3390 : /* if not found, assume empty */
+ 3391 250 : if (!f) {
+ 3392 7 : log_fatal("No content file found. Assuming empty.\n");
3393 :
- 3394 134 : static void state_verify_content(struct snapraid_state* state, uint32_t crc)
- 3395 : {
- 3396 : tommy_node* i;
- 3397 : int fail;
+ 3394 : /* create the initial mapping */
+ 3395 7 : state_map(state);
+ 3396 256 : return;
+ 3397 : }
3398 :
- 3399 : /* start all reading threads */
- 3400 134 : i = tommy_list_head(&state->contentlist);
- 3401 1181 : while (i) {
- 3402 913 : struct snapraid_content* content = i->data;
- 3403 : struct state_verify_thread_context* context;
- 3404 :
- 3405 : /* allocate the thread context */
- 3406 913 : context = malloc_nofail(sizeof(struct state_verify_thread_context));
- 3407 913 : content->context = context;
- 3408 :
- 3409 : /* initialize */
- 3410 913 : context->state = state;
- 3411 913 : context->content = content;
- 3412 913 : context->crc = crc;
- 3413 :
- 3414 913 : msg_progress("Verifying %s...\n", content->content);
- 3415 :
- 3416 : #if HAVE_PTHREAD_CREATE
- 3417 913 : if (pthread_create(&context->thread, 0, state_verify_thread, context) != 0) {
- 3418 : /* LCOV_EXCL_START */
- 3419 : log_fatal("Failed to create thread.\n");
- 3420 : exit(EXIT_FAILURE);
- 3421 : /* LCOV_EXCL_STOP */
- 3422 : }
- 3423 : #else
- 3424 : content->retval = state_verify_thread(context);
- 3425 : #endif
- 3426 :
- 3427 913 : i = i->next;
- 3428 : }
- 3429 :
- 3430 : /* join all thread */
- 3431 134 : fail = 0;
- 3432 134 : i = tommy_list_head(&state->contentlist);
- 3433 1181 : while (i) {
- 3434 913 : struct snapraid_content* content = i->data;
- 3435 913 : struct state_verify_thread_context* context = content->context;
- 3436 : void* retval;
+ 3399 : /* get the stat of the content file */
+ 3400 243 : ret = fstat(shandle(f), &st);
+ 3401 243 : if (ret != 0) {
+ 3402 : /* LCOV_EXCL_START */
+ 3403 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno));
+ 3404 : exit(EXIT_FAILURE);
+ 3405 : /* LCOV_EXCL_STOP */
+ 3406 : }
+ 3407 :
+ 3408 : /* go further to check other content files */
+ 3409 1891 : while (node) {
+ 3410 : char other_path[PATH_MAX];
+ 3411 : struct stat other_st;
+ 3412 1405 : struct snapraid_content* content = node->data;
+ 3413 1405 : pathcpy(other_path, sizeof(other_path), content->content);
+ 3414 :
+ 3415 1405 : ret = stat(other_path, &other_st);
+ 3416 1405 : if (ret != 0) {
+ 3417 : /* allow missing content files, but not any other kind of error */
+ 3418 1 : if (errno != ENOENT) {
+ 3419 : /* LCOV_EXCL_START */
+ 3420 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno));
+ 3421 : exit(EXIT_FAILURE);
+ 3422 : /* LCOV_EXCL_STOP */
+ 3423 : }
+ 3424 :
+ 3425 : /* ensure to rewrite all the content files */
+ 3426 1 : state->need_write = 1;
+ 3427 : } else {
+ 3428 : /* if the size is different */
+ 3429 1404 : if (other_st.st_size != st.st_size) {
+ 3430 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path);
+ 3431 39 : log_fatal("Likely one of the two is broken!\n");
+ 3432 :
+ 3433 : /* ensure to rewrite all the content files */
+ 3434 39 : state->need_write = 1;
+ 3435 : }
+ 3436 : }
3437 :
- 3438 : #if HAVE_PTHREAD_CREATE
- 3439 913 : if (pthread_join(context->thread, &retval) != 0) {
- 3440 : /* LCOV_EXCL_START */
- 3441 : log_fatal("Failed to join thread.\n");
- 3442 : exit(EXIT_FAILURE);
- 3443 : /* LCOV_EXCL_STOP */
- 3444 : }
- 3445 : #else
- 3446 : retval = context->retval;
- 3447 : #endif
- 3448 913 : if (retval) {
- 3449 : /* LCOV_EXCL_START */
- 3450 : fail = 1;
- 3451 : /* LCOV_EXCL_STOP */
- 3452 : }
+ 3438 : /* next content file */
+ 3439 1405 : node = node->next;
+ 3440 : }
+ 3441 :
+ 3442 : /* start with a undefined default. */
+ 3443 : /* it's for compatibility with version 1.0 where MD5 was implicit. */
+ 3444 243 : state->hash = HASH_UNDEFINED;
+ 3445 :
+ 3446 : /* start with a zero seed, it was the default in old versions */
+ 3447 243 : memset(state->hashseed, 0, HASH_SIZE);
+ 3448 :
+ 3449 : /* previous hash, start with an undefined value */
+ 3450 243 : state->prevhash = HASH_UNDEFINED;
+ 3451 :
+ 3452 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
3453 :
- 3454 913 : free(context);
- 3455 :
- 3456 913 : i = i->next;
- 3457 : }
- 3458 :
- 3459 : /* abort on failure */
- 3460 134 : if (fail) {
- 3461 : /* LCOV_EXCL_START */
- 3462 : exit(EXIT_FAILURE);
- 3463 : /* LCOV_EXCL_STOP */
- 3464 : }
- 3465 134 : }
- 3466 :
- 3467 134 : static void state_rename_content(struct snapraid_state* state)
- 3468 : {
- 3469 : tommy_node* i;
+ 3454 : /* get the first char to detect the file type */
+ 3455 243 : c = sgetc(f);
+ 3456 243 : sungetc(c, f);
+ 3457 :
+ 3458 : /* guess the file type from the first char */
+ 3459 243 : if (c == 'S') {
+ 3460 243 : state_read_content(state, path, f);
+ 3461 : } else {
+ 3462 : /* LCOV_EXCL_START */
+ 3463 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n");
+ 3464 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n");
+ 3465 : exit(EXIT_FAILURE);
+ 3466 : /* LCOV_EXCL_STOP */
+ 3467 : }
+ 3468 :
+ 3469 242 : sclose(f);
3470 :
- 3471 134 : i = tommy_list_head(&state->contentlist);
- 3472 1181 : while (i) {
- 3473 913 : struct snapraid_content* content = i->data;
- 3474 : char tmp[PATH_MAX];
- 3475 :
- 3476 : /* now renames the just written copy with the correct name */
- 3477 913 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3478 913 : if (rename(tmp, content->content) != 0) {
- 3479 : /* LCOV_EXCL_START */
- 3480 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno));
- 3481 : exit(EXIT_FAILURE);
- 3482 : /* LCOV_EXCL_STOP */
- 3483 : }
- 3484 :
- 3485 913 : i = i->next;
- 3486 : }
- 3487 134 : }
- 3488 :
- 3489 134 : void state_write(struct snapraid_state* state)
- 3490 : {
- 3491 : uint32_t crc;
- 3492 :
- 3493 : /* write all the content files */
- 3494 134 : state_write_content(state, &crc);
- 3495 :
- 3496 : /* verify the just written files */
- 3497 134 : state_verify_content(state, crc);
- 3498 :
- 3499 : /* rename the new files, over the old ones */
- 3500 134 : state_rename_content(state);
- 3501 :
- 3502 134 : state->need_write = 0; /* no write needed anymore */
- 3503 134 : state->checked_read = 0; /* what we wrote is not checked in read */
- 3504 134 : }
- 3505 :
- 3506 122 : void state_skip(struct snapraid_state* state)
- 3507 : {
- 3508 : tommy_node* i;
- 3509 :
- 3510 : /* for each disk */
- 3511 850 : for (i = state->disklist; i != 0; i = i->next) {
- 3512 : tommy_node* j;
- 3513 728 : struct snapraid_disk* disk = i->data;
- 3514 :
- 3515 728 : if (!disk->skip_access)
- 3516 727 : continue;
+ 3471 242 : if (state->hash == HASH_UNDEFINED) {
+ 3472 : /* LCOV_EXCL_START */
+ 3473 : log_fatal("The checksum to use is not specified.\n");
+ 3474 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n");
+ 3475 : log_fatal("To use a new SnapRAID you must restart from scratch,\n");
+ 3476 : log_fatal("deleting all the content and parity files.\n");
+ 3477 : exit(EXIT_FAILURE);
+ 3478 : /* LCOV_EXCL_STOP */
+ 3479 : }
+ 3480 :
+ 3481 : /* update the mapping */
+ 3482 242 : state_map(state);
+ 3483 :
+ 3484 242 : state_content_check(state, path);
+ 3485 :
+ 3486 : /* mark that we read the content file, and it passed all the checks */
+ 3487 242 : state->checked_read = 1;
+ 3488 : }
+ 3489 :
+ 3490 : struct state_verify_thread_context {
+ 3491 : struct snapraid_state* state;
+ 3492 : struct snapraid_content* content;
+ 3493 : #if HAVE_MT_VERIFY
+ 3494 : pthread_t thread;
+ 3495 : #else
+ 3496 : void* retval;
+ 3497 : #endif
+ 3498 : /* input */
+ 3499 : uint32_t crc;
+ 3500 : STREAM* f;
+ 3501 : };
+ 3502 :
+ 3503 990 : static void* state_verify_thread(void* arg)
+ 3504 : {
+ 3505 990 : struct state_verify_thread_context* context = arg;
+ 3506 990 : STREAM* f = context->f;
+ 3507 : unsigned char buf[4];
+ 3508 : uint32_t crc_stored;
+ 3509 : uint32_t crc_computed;
+ 3510 :
+ 3511 990 : if (sdeplete(f, buf) != 0) {
+ 3512 : /* LCOV_EXCL_START */
+ 3513 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3514 : return context;
+ 3515 : /* LCOV_EXCL_STOP */
+ 3516 : }
3517 :
- 3518 : /* for each file */
- 3519 1883 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
- 3520 1882 : struct snapraid_file* file = j->data;
- 3521 1882 : file_flag_set(file, FILE_IS_EXCLUDED);
- 3522 : }
- 3523 :
- 3524 : /* for each link */
- 3525 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
- 3526 56 : struct snapraid_link* slink = j->data;
- 3527 56 : link_flag_set(slink, FILE_IS_EXCLUDED);
- 3528 : }
- 3529 :
- 3530 : /* for each dir */
- 3531 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
- 3532 0 : struct snapraid_dir* dir = j->data;
- 3533 0 : dir_flag_set(dir, FILE_IS_EXCLUDED);
- 3534 : }
- 3535 : }
- 3536 122 : }
- 3537 :
- 3538 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error)
- 3539 : {
- 3540 : tommy_node* i;
- 3541 : unsigned l;
- 3542 :
- 3543 : /* if no filter, include all */
- 3544 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk))
- 3545 235 : return;
- 3546 :
- 3547 9 : msg_progress("Filtering...\n");
+ 3518 : /* get the stored crc from the last four bytes */
+ 3519 990 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
+ 3520 :
+ 3521 990 : if (crc_stored != context->crc) {
+ 3522 : /* LCOV_EXCL_START */
+ 3523 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f));
+ 3524 : return context;
+ 3525 : /* LCOV_EXCL_STOP */
+ 3526 : }
+ 3527 :
+ 3528 : /* get the computed crc */
+ 3529 990 : crc_computed = scrc(f);
+ 3530 :
+ 3531 : /* adjust the stored crc to include itself */
+ 3532 990 : crc_stored = crc32c(crc_stored, buf, 4);
+ 3533 :
+ 3534 990 : if (crc_computed != crc_stored) {
+ 3535 : /* LCOV_EXCL_START */
+ 3536 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f));
+ 3537 : return context;
+ 3538 : /* LCOV_EXCL_STOP */
+ 3539 : }
+ 3540 :
+ 3541 990 : return 0;
+ 3542 : }
+ 3543 :
+ 3544 145 : static void state_verify_content(struct snapraid_state* state, uint32_t crc)
+ 3545 : {
+ 3546 : tommy_node* i;
+ 3547 : int fail;
3548 :
- 3549 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
- 3550 8 : struct snapraid_filter* filter = i->data;
- 3551 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : "");
- 3552 : }
- 3553 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) {
- 3554 3 : struct snapraid_filter* filter = i->data;
- 3555 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : "");
- 3556 : }
- 3557 9 : if (filter_missing)
- 3558 2 : msg_verbose("\t<missing>\n");
- 3559 9 : if (filter_error)
- 3560 2 : msg_verbose("\t<error>\n");
- 3561 :
- 3562 : /* for each disk */
- 3563 63 : for (i = state->disklist; i != 0; i = i->next) {
- 3564 : tommy_node* j;
- 3565 54 : struct snapraid_disk* disk = i->data;
- 3566 :
- 3567 : /* if we filter for presence, we have to access the disk, so better to print something */
- 3568 54 : if (filter_missing)
- 3569 12 : msg_progress("Scanning disk %s...\n", disk->name);
- 3570 :
- 3571 : /* for each file */
- 3572 133854 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
- 3573 133800 : struct snapraid_file* file = j->data;
- 3574 :
- 3575 133800 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0
- 3576 80924 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0
- 3577 78090 : || filter_existence(filter_missing, disk->dir, file->sub) != 0
- 3578 38806 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0
- 3579 : ) {
- 3580 109102 : file_flag_set(file, FILE_IS_EXCLUDED);
- 3581 : }
- 3582 : }
- 3583 :
- 3584 : /* for each link */
- 3585 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
- 3586 4360 : struct snapraid_link* slink = j->data;
- 3587 :
- 3588 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0
- 3589 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0
- 3590 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0
- 3591 : ) {
- 3592 3221 : link_flag_set(slink, FILE_IS_EXCLUDED);
- 3593 : }
- 3594 : }
- 3595 :
- 3596 : /* for each dir */
- 3597 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
- 3598 28 : struct snapraid_dir* dir = j->data;
- 3599 :
- 3600 28 : if (filter_dir(filterlist_disk, 0, disk->name, dir->sub) != 0
- 3601 28 : || filter_dir(filterlist_file, 0, disk->name, dir->sub) != 0
- 3602 28 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0
- 3603 : ) {
- 3604 8 : dir_flag_set(dir, FILE_IS_EXCLUDED);
- 3605 : }
- 3606 : }
- 3607 : }
- 3608 :
- 3609 : /* if we are filtering by disk */
- 3610 9 : if (!tommy_list_empty(filterlist_disk)) {
- 3611 : /* for each parity disk */
- 3612 20 : for (l = 0; l < state->level; ++l) {
- 3613 : /* check if the parity is excluded by name */
- 3614 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) {
- 3615 : /* excluded the parity from further operation */
- 3616 11 : state->parity[l].is_excluded = 1;
- 3617 : }
- 3618 : }
- 3619 : } else {
- 3620 : /* if we are filtering by file, exclude all parity */
- 3621 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) {
- 3622 : /* for each parity disk */
- 3623 16 : for (l = 0; l < state->level; ++l) {
- 3624 13 : state->parity[l].is_excluded = 1;
- 3625 : }
- 3626 : }
- 3627 : }
- 3628 : }
- 3629 :
- 3630 206 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax)
- 3631 : {
- 3632 : time_t now;
- 3633 :
- 3634 206 : if (state->opt.gui) {
- 3635 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax);
- 3636 5 : log_flush();
- 3637 : }
+ 3549 : /* start all reading threads */
+ 3550 145 : i = tommy_list_head(&state->contentlist);
+ 3551 1280 : while (i) {
+ 3552 990 : struct snapraid_content* content = i->data;
+ 3553 : struct state_verify_thread_context* context;
+ 3554 : char tmp[PATH_MAX];
+ 3555 : STREAM* f;
+ 3556 :
+ 3557 990 : msg_progress("Verifying %s...\n", content->content);
+ 3558 :
+ 3559 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3560 :
+ 3561 990 : f = sopen_read(tmp);
+ 3562 990 : if (f == 0) {
+ 3563 : /* LCOV_EXCL_START */
+ 3564 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3565 : exit(EXIT_FAILURE);
+ 3566 : /* LCOV_EXCL_STOP */
+ 3567 : }
+ 3568 :
+ 3569 : /* allocate the thread context */
+ 3570 990 : context = malloc_nofail(sizeof(struct state_verify_thread_context));
+ 3571 990 : content->context = context;
+ 3572 :
+ 3573 : /* initialize */
+ 3574 990 : context->state = state;
+ 3575 990 : context->content = content;
+ 3576 990 : context->crc = crc;
+ 3577 990 : context->f = f;
+ 3578 :
+ 3579 : #if HAVE_MT_VERIFY
+ 3580 990 : if (pthread_create(&context->thread, 0, state_verify_thread, context) != 0) {
+ 3581 : /* LCOV_EXCL_START */
+ 3582 : log_fatal("Failed to create thread.\n");
+ 3583 : exit(EXIT_FAILURE);
+ 3584 : /* LCOV_EXCL_STOP */
+ 3585 : }
+ 3586 : #else
+ 3587 : context->retval = state_verify_thread(context);
+ 3588 : #endif
+ 3589 :
+ 3590 990 : i = i->next;
+ 3591 : }
+ 3592 :
+ 3593 : /* join all thread */
+ 3594 145 : fail = 0;
+ 3595 145 : i = tommy_list_head(&state->contentlist);
+ 3596 1280 : while (i) {
+ 3597 990 : struct snapraid_content* content = i->data;
+ 3598 990 : struct state_verify_thread_context* context = content->context;
+ 3599 : void* retval;
+ 3600 :
+ 3601 : #if HAVE_MT_VERIFY
+ 3602 990 : if (pthread_join(context->thread, &retval) != 0) {
+ 3603 : /* LCOV_EXCL_START */
+ 3604 : log_fatal("Failed to join thread.\n");
+ 3605 : exit(EXIT_FAILURE);
+ 3606 : /* LCOV_EXCL_STOP */
+ 3607 : }
+ 3608 : #else
+ 3609 : retval = context->retval;
+ 3610 : #endif
+ 3611 990 : if (retval) {
+ 3612 : /* LCOV_EXCL_START */
+ 3613 : fail = 1;
+ 3614 : /* LCOV_EXCL_STOP */
+ 3615 : } else {
+ 3616 990 : STREAM* f = context->f;
+ 3617 :
+ 3618 990 : if (sclose(f) != 0) {
+ 3619 : /* LCOV_EXCL_START */
+ 3620 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3621 : exit(EXIT_FAILURE);
+ 3622 : /* LCOV_EXCL_STOP */
+ 3623 : }
+ 3624 : }
+ 3625 :
+ 3626 990 : free(context);
+ 3627 :
+ 3628 990 : i = i->next;
+ 3629 : }
+ 3630 :
+ 3631 : /* abort on failure */
+ 3632 145 : if (fail) {
+ 3633 : /* LCOV_EXCL_START */
+ 3634 : exit(EXIT_FAILURE);
+ 3635 : /* LCOV_EXCL_STOP */
+ 3636 : }
+ 3637 145 : }
3638 :
- 3639 206 : now = time(0);
- 3640 :
- 3641 206 : state->progress_whole_start = now;
+ 3639 145 : static void state_rename_content(struct snapraid_state* state)
+ 3640 : {
+ 3641 : tommy_node* i;
3642 :
- 3643 206 : state->progress_tick = 0;
- 3644 206 : state->progress_ptr = 0;
- 3645 206 : state->progress_wasted = 0;
- 3646 :
- 3647 : /* stop if requested */
- 3648 206 : if (global_interrupt) {
- 3649 : /* LCOV_EXCL_START */
- 3650 : if (!state->opt.gui) {
- 3651 : msg_status("Not starting for interruption\n");
- 3652 : }
- 3653 : log_tag("sigint:0: SIGINT received\n");
- 3654 : log_flush();
- 3655 : return 0;
- 3656 : /* LCOV_EXCL_STOP */
- 3657 : }
- 3658 :
- 3659 206 : return 1;
- 3660 : }
- 3661 :
- 3662 206 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize)
- 3663 : {
- 3664 206 : if (state->opt.gui) {
- 3665 5 : log_tag("run:end\n");
- 3666 5 : log_flush();
- 3667 201 : } else if (countmax == 0) {
- 3668 15 : msg_status("Nothing to do\n");
- 3669 : } else {
- 3670 : time_t now;
- 3671 : time_t elapsed;
- 3672 :
- 3673 186 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA;
- 3674 :
- 3675 186 : now = time(0);
- 3676 :
- 3677 186 : elapsed = now - state->progress_whole_start - state->progress_wasted;
- 3678 :
- 3679 186 : msg_bar("%u%% completed, %u MB processed", countpos * 100 / countmax, countsize_MB);
- 3680 186 : if (elapsed >= 60)
- 3681 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
- 3682 186 : msg_bar("\n");
- 3683 186 : msg_flush();
- 3684 : }
- 3685 206 : }
+ 3643 145 : i = tommy_list_head(&state->contentlist);
+ 3644 1280 : while (i) {
+ 3645 990 : struct snapraid_content* content = i->data;
+ 3646 : char tmp[PATH_MAX];
+ 3647 :
+ 3648 : /* now renames the just written copy with the correct name */
+ 3649 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3650 990 : if (rename(tmp, content->content) != 0) {
+ 3651 : /* LCOV_EXCL_START */
+ 3652 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno));
+ 3653 : exit(EXIT_FAILURE);
+ 3654 : /* LCOV_EXCL_STOP */
+ 3655 : }
+ 3656 :
+ 3657 990 : i = i->next;
+ 3658 : }
+ 3659 145 : }
+ 3660 :
+ 3661 145 : void state_write(struct snapraid_state* state)
+ 3662 : {
+ 3663 : uint32_t crc;
+ 3664 :
+ 3665 : /* write all the content files */
+ 3666 145 : state_write_content(state, &crc);
+ 3667 :
+ 3668 : /* verify the just written files */
+ 3669 145 : state_verify_content(state, crc);
+ 3670 :
+ 3671 : /* rename the new files, over the old ones */
+ 3672 145 : state_rename_content(state);
+ 3673 :
+ 3674 145 : state->need_write = 0; /* no write needed anymore */
+ 3675 145 : state->checked_read = 0; /* what we wrote is not checked in read */
+ 3676 145 : }
+ 3677 :
+ 3678 122 : void state_skip(struct snapraid_state* state)
+ 3679 : {
+ 3680 : tommy_node* i;
+ 3681 :
+ 3682 : /* for each disk */
+ 3683 850 : for (i = state->disklist; i != 0; i = i->next) {
+ 3684 : tommy_node* j;
+ 3685 728 : struct snapraid_disk* disk = i->data;
3686 :
- 3687 1 : void state_progress_stop(struct snapraid_state* state)
- 3688 : {
- 3689 : time_t now;
- 3690 :
- 3691 1 : now = time(0);
- 3692 :
- 3693 1 : if (!state->opt.gui) {
- 3694 1 : msg_bar("\n");
- 3695 1 : msg_flush();
- 3696 : }
- 3697 :
- 3698 1 : state->progress_interruption = now;
- 3699 1 : }
- 3700 :
- 3701 1 : void state_progress_restart(struct snapraid_state* state)
- 3702 : {
- 3703 : time_t now;
- 3704 :
- 3705 1 : now = time(0);
- 3706 :
- 3707 : /* reset the progress counter */
- 3708 1 : state->progress_tick = 0;
- 3709 1 : state->progress_ptr = 0;
- 3710 :
- 3711 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */
- 3712 1 : state->progress_wasted += now - state->progress_interruption;
- 3713 1 : }
+ 3687 728 : if (!disk->skip_access)
+ 3688 727 : continue;
+ 3689 :
+ 3690 : /* for each file */
+ 3691 1884 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
+ 3692 1883 : struct snapraid_file* file = j->data;
+ 3693 1883 : file_flag_set(file, FILE_IS_EXCLUDED);
+ 3694 : }
+ 3695 :
+ 3696 : /* for each link */
+ 3697 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
+ 3698 56 : struct snapraid_link* slink = j->data;
+ 3699 56 : link_flag_set(slink, FILE_IS_EXCLUDED);
+ 3700 : }
+ 3701 :
+ 3702 : /* for each dir */
+ 3703 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
+ 3704 0 : struct snapraid_dir* dir = j->data;
+ 3705 0 : dir_flag_set(dir, FILE_IS_EXCLUDED);
+ 3706 : }
+ 3707 : }
+ 3708 122 : }
+ 3709 :
+ 3710 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error)
+ 3711 : {
+ 3712 : tommy_node* i;
+ 3713 : unsigned l;
3714 :
- 3715 : #define PROGRESS_CLEAR " "
- 3716 :
- 3717 1038958 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize)
- 3718 : {
- 3719 : time_t now;
- 3720 : int pred;
- 3721 :
- 3722 1038958 : now = time(0);
- 3723 :
- 3724 : /* previous position */
- 3725 1038958 : pred = state->progress_ptr + PROGRESS_MAX - 1;
- 3726 1038958 : if (pred >= PROGRESS_MAX)
- 3727 1038770 : pred -= PROGRESS_MAX;
- 3728 :
- 3729 : /* if the previous measure is different */
- 3730 1038958 : if (state->progress_tick == 0
- 3731 1038770 : || state->progress_time[pred] != now
- 3732 : ) {
- 3733 : uint64_t tick_total;
- 3734 : uint64_t tick_cpu;
- 3735 : time_t elapsed;
- 3736 260 : unsigned out_perc = 0;
- 3737 260 : unsigned out_speed = 0;
- 3738 260 : unsigned out_cpu = 0;
- 3739 260 : unsigned out_eta = 0;
- 3740 :
- 3741 260 : tick_total = state->tick_cpu + state->tick_io;
- 3742 260 : tick_cpu = state->tick_cpu;
- 3743 260 : elapsed = now - state->progress_whole_start - state->progress_wasted;
- 3744 :
- 3745 : /* completion percentage */
- 3746 260 : if (countmax)
- 3747 260 : out_perc = countpos * 100 / countmax;
- 3748 :
- 3749 : /* if we have at least 5 measures */
- 3750 260 : if (state->progress_tick >= 5
- 3751 : /* or if we are running in test mode, with at least one measure */
- 3752 260 : || (state->opt.force_progress && state->progress_tick >= 1)
- 3753 : ) {
- 3754 : int oldest;
- 3755 : int past;
- 3756 : time_t delta_time;
- 3757 : block_off_t delta_pos;
- 3758 : data_off_t delta_size;
- 3759 : uint64_t delta_tick_total;
- 3760 : uint64_t delta_tick_cpu;
- 3761 :
- 3762 : /* number of past measures */
- 3763 72 : past = state->progress_tick;
- 3764 :
- 3765 : /* drop the oldest ones, to promptly */
- 3766 : /* skip the startup phase */
- 3767 72 : past -= past / 5;
- 3768 :
- 3769 : /* check how much we can go in the past */
- 3770 72 : if (past >= PROGRESS_MAX) {
- 3771 : /* the vector is filled, so we are already in position */
- 3772 : /* to get the possible oldest one */
- 3773 0 : oldest = state->progress_ptr;
- 3774 : } else {
- 3775 : /* go backward the number of positions selected */
- 3776 72 : oldest = state->progress_ptr + PROGRESS_MAX - past;
- 3777 72 : if (oldest >= PROGRESS_MAX)
- 3778 72 : oldest -= PROGRESS_MAX;
- 3779 : }
+ 3715 : /* if no filter, include all */
+ 3716 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk))
+ 3717 235 : return;
+ 3718 :
+ 3719 9 : msg_progress("Filtering...\n");
+ 3720 :
+ 3721 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
+ 3722 8 : struct snapraid_filter* filter = i->data;
+ 3723 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : "");
+ 3724 : }
+ 3725 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) {
+ 3726 3 : struct snapraid_filter* filter = i->data;
+ 3727 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : "");
+ 3728 : }
+ 3729 9 : if (filter_missing)
+ 3730 2 : msg_verbose("\t<missing>\n");
+ 3731 9 : if (filter_error)
+ 3732 2 : msg_verbose("\t<error>\n");
+ 3733 :
+ 3734 : /* for each disk */
+ 3735 63 : for (i = state->disklist; i != 0; i = i->next) {
+ 3736 : tommy_node* j;
+ 3737 54 : struct snapraid_disk* disk = i->data;
+ 3738 :
+ 3739 : /* if we filter for presence, we have to access the disk, so better to print something */
+ 3740 54 : if (filter_missing)
+ 3741 12 : msg_progress("Scanning disk %s...\n", disk->name);
+ 3742 :
+ 3743 : /* for each file */
+ 3744 133917 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
+ 3745 133863 : struct snapraid_file* file = j->data;
+ 3746 :
+ 3747 133863 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0
+ 3748 80965 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0
+ 3749 78124 : || filter_existence(filter_missing, disk->dir, file->sub) != 0
+ 3750 38732 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0
+ 3751 : ) {
+ 3752 109341 : file_flag_set(file, FILE_IS_EXCLUDED);
+ 3753 : }
+ 3754 : }
+ 3755 :
+ 3756 : /* for each link */
+ 3757 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
+ 3758 4360 : struct snapraid_link* slink = j->data;
+ 3759 :
+ 3760 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0
+ 3761 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0
+ 3762 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0
+ 3763 : ) {
+ 3764 3221 : link_flag_set(slink, FILE_IS_EXCLUDED);
+ 3765 : }
+ 3766 : }
+ 3767 :
+ 3768 : /* for each dir */
+ 3769 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
+ 3770 28 : struct snapraid_dir* dir = j->data;
+ 3771 :
+ 3772 28 : if (filter_dir(filterlist_disk, 0, disk->name, dir->sub) != 0
+ 3773 28 : || filter_dir(filterlist_file, 0, disk->name, dir->sub) != 0
+ 3774 28 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0
+ 3775 : ) {
+ 3776 8 : dir_flag_set(dir, FILE_IS_EXCLUDED);
+ 3777 : }
+ 3778 : }
+ 3779 : }
3780 :
- 3781 72 : delta_time = now - state->progress_time[oldest];
- 3782 72 : delta_pos = countpos - state->progress_pos[oldest];
- 3783 72 : delta_size = countsize - state->progress_size[oldest];
- 3784 72 : delta_tick_total = tick_total - state->progress_tick_total[oldest];
- 3785 72 : delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest];
- 3786 :
- 3787 : /* estimate the speed in MiB/s */
- 3788 72 : if (delta_time != 0)
- 3789 72 : out_speed = (unsigned)(delta_size / MEGA / delta_time);
- 3790 :
- 3791 : /* estimate the cpu usage percentage */
- 3792 72 : if (delta_tick_total != 0)
- 3793 10 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total);
- 3794 :
- 3795 : /* estimate the remaining time in minutes */
- 3796 72 : if (delta_pos != 0)
- 3797 72 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos);
+ 3781 : /* if we are filtering by disk */
+ 3782 9 : if (!tommy_list_empty(filterlist_disk)) {
+ 3783 : /* for each parity disk */
+ 3784 20 : for (l = 0; l < state->level; ++l) {
+ 3785 : /* check if the parity is excluded by name */
+ 3786 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) {
+ 3787 : /* excluded the parity from further operation */
+ 3788 11 : state->parity[l].is_excluded = 1;
+ 3789 : }
+ 3790 : }
+ 3791 : } else {
+ 3792 : /* if we are filtering by file, exclude all parity */
+ 3793 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) {
+ 3794 : /* for each parity disk */
+ 3795 16 : for (l = 0; l < state->level; ++l) {
+ 3796 13 : state->parity[l].is_excluded = 1;
+ 3797 : }
3798 : }
- 3799 :
- 3800 260 : if (state->opt.gui) {
- 3801 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed);
- 3802 7 : log_flush();
- 3803 : } else {
- 3804 253 : msg_bar("%u%%, %u MiB", out_perc, (unsigned)(countsize / MEGA));
- 3805 253 : if (out_speed)
- 3806 63 : msg_bar(", %u MiB/s", out_speed);
- 3807 253 : if (out_cpu)
- 3808 10 : msg_bar(", CPU %u%%", out_cpu);
- 3809 253 : if (out_eta)
- 3810 0 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
- 3811 253 : msg_bar("%s\r", PROGRESS_CLEAR);
- 3812 253 : msg_flush();
- 3813 : }
+ 3799 : }
+ 3800 : }
+ 3801 :
+ 3802 214 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax)
+ 3803 : {
+ 3804 : time_t now;
+ 3805 :
+ 3806 214 : if (state->opt.gui) {
+ 3807 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax);
+ 3808 5 : log_flush();
+ 3809 : }
+ 3810 :
+ 3811 214 : now = time(0);
+ 3812 :
+ 3813 214 : state->progress_whole_start = now;
3814 :
- 3815 : /* store the new measure */
- 3816 260 : state->progress_time[state->progress_ptr] = now;
- 3817 260 : state->progress_pos[state->progress_ptr] = countpos;
- 3818 260 : state->progress_size[state->progress_ptr] = countsize;
- 3819 260 : state->progress_tick_cpu[state->progress_ptr] = tick_cpu;
- 3820 260 : state->progress_tick_total[state->progress_ptr] = tick_total;
- 3821 :
- 3822 : /* next position */
- 3823 260 : ++state->progress_ptr;
- 3824 260 : if (state->progress_ptr >= PROGRESS_MAX)
- 3825 0 : state->progress_ptr -= PROGRESS_MAX;
- 3826 :
- 3827 : /* one more measure */
- 3828 260 : ++state->progress_tick;
+ 3815 214 : state->progress_tick = 0;
+ 3816 214 : state->progress_ptr = 0;
+ 3817 214 : state->progress_wasted = 0;
+ 3818 :
+ 3819 : /* stop if requested */
+ 3820 214 : if (global_interrupt) {
+ 3821 : /* LCOV_EXCL_START */
+ 3822 : if (!state->opt.gui) {
+ 3823 : msg_status("Not starting for interruption\n");
+ 3824 : }
+ 3825 : log_tag("sigint:0: SIGINT received\n");
+ 3826 : log_flush();
+ 3827 : return 0;
+ 3828 : /* LCOV_EXCL_STOP */
3829 : }
3830 :
- 3831 : /* stop if requested */
- 3832 1038958 : if (global_interrupt) {
- 3833 : /* LCOV_EXCL_START */
- 3834 : if (!state->opt.gui) {
- 3835 : log_fatal("\n");
- 3836 : log_fatal("Stopping for interruption at block %u\n", blockpos);
- 3837 : }
- 3838 : log_tag("sigint:%u: SIGINT received\n", blockpos);
- 3839 : log_flush();
- 3840 : return 1;
- 3841 : /* LCOV_EXCL_STOP */
- 3842 : }
- 3843 :
- 3844 1038958 : return 0;
- 3845 : }
+ 3831 214 : return 1;
+ 3832 : }
+ 3833 :
+ 3834 214 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize)
+ 3835 : {
+ 3836 214 : if (state->opt.gui) {
+ 3837 5 : log_tag("run:end\n");
+ 3838 5 : log_flush();
+ 3839 209 : } else if (countmax == 0) {
+ 3840 18 : msg_status("Nothing to do\n");
+ 3841 : } else {
+ 3842 : time_t now;
+ 3843 : time_t elapsed;
+ 3844 :
+ 3845 191 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA;
3846 :
- 3847 81 : void state_usage_print(struct snapraid_state* state)
- 3848 : {
- 3849 : uint64_t tick_total;
- 3850 : uint64_t tick_max;
- 3851 : tommy_node* i;
- 3852 : unsigned l;
- 3853 :
- 3854 81 : tick_max = 0;
- 3855 81 : tick_total = 0;
- 3856 565 : for (i = state->disklist; i != 0; i = i->next) {
- 3857 484 : struct snapraid_disk* disk = i->data;
- 3858 484 : tick_total += disk->tick;
- 3859 484 : if (disk->tick > tick_max)
- 3860 99 : tick_max = disk->tick;
- 3861 : }
- 3862 552 : for (l = 0; l < state->level; ++l) {
- 3863 471 : tick_total += state->parity[l].tick;
- 3864 471 : if (state->parity[l].tick > tick_max)
- 3865 17 : tick_max = state->parity[l].tick;
- 3866 : }
- 3867 :
- 3868 81 : if (!tick_total)
- 3869 96 : return;
- 3870 :
- 3871 66 : if (msg_level >= MSG_PROGRESS) {
- 3872 : /* here we don't use msg_progress() because it doesn't allow partial output */
- 3873 1 : printf("Time for disk:");
- 3874 7 : for (i = state->disklist; i != 0; i = i->next) {
- 3875 6 : struct snapraid_disk* disk = i->data;
- 3876 6 : if (disk->tick == tick_max)
- 3877 1 : printf(" %s:", disk->name);
- 3878 : else
- 3879 5 : printf(" ");
- 3880 6 : printf("%" PRIu64 "%%", disk->tick * 100U / tick_total);
- 3881 : }
- 3882 1 : printf("\n");
- 3883 :
- 3884 1 : printf("Time for parity:");
- 3885 7 : for (l = 0; l < state->level; ++l) {
- 3886 6 : if (state->parity[l].tick == tick_max)
- 3887 0 : printf(" %s:", lev_config_name(l));
- 3888 : else
- 3889 6 : printf(" ");
- 3890 6 : printf("%" PRIu64 "%%", state->parity[l].tick * 100U / tick_total);
- 3891 : }
- 3892 1 : printf("\n");
- 3893 : }
- 3894 : }
+ 3847 191 : now = time(0);
+ 3848 :
+ 3849 191 : elapsed = now - state->progress_whole_start - state->progress_wasted;
+ 3850 :
+ 3851 191 : msg_bar("%u%% completed, %u MB processed", countpos * 100 / countmax, countsize_MB);
+ 3852 191 : if (elapsed >= 60)
+ 3853 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
+ 3854 191 : msg_bar("\n");
+ 3855 191 : msg_flush();
+ 3856 : }
+ 3857 214 : }
+ 3858 :
+ 3859 1 : void state_progress_stop(struct snapraid_state* state)
+ 3860 : {
+ 3861 : time_t now;
+ 3862 :
+ 3863 1 : now = time(0);
+ 3864 :
+ 3865 1 : if (!state->opt.gui) {
+ 3866 1 : msg_bar("\n");
+ 3867 1 : msg_flush();
+ 3868 : }
+ 3869 :
+ 3870 1 : state->progress_interruption = now;
+ 3871 1 : }
+ 3872 :
+ 3873 1 : void state_progress_restart(struct snapraid_state* state)
+ 3874 : {
+ 3875 : time_t now;
+ 3876 :
+ 3877 1 : now = time(0);
+ 3878 :
+ 3879 : /* reset the progress counter */
+ 3880 1 : state->progress_tick = 0;
+ 3881 1 : state->progress_ptr = 0;
+ 3882 :
+ 3883 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */
+ 3884 1 : state->progress_wasted += now - state->progress_interruption;
+ 3885 1 : }
+ 3886 :
+ 3887 : #define PROGRESS_CLEAR " "
+ 3888 :
+ 3889 1048979 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize)
+ 3890 : {
+ 3891 : time_t now;
+ 3892 : int pred;
+ 3893 :
+ 3894 1048979 : now = time(0);
3895 :
- 3896 447 : void state_fscheck(struct snapraid_state* state, const char* ope)
- 3897 : {
- 3898 : tommy_node* i;
- 3899 :
- 3900 : /* check the filesystem on all disks */
- 3901 3123 : for (i = state->disklist; i != 0; i = i->next) {
- 3902 2676 : struct snapraid_disk* disk = i->data;
- 3903 :
- 3904 2676 : if (fs_check(disk) != 0) {
- 3905 : /* LCOV_EXCL_START */
- 3906 : log_fatal("Internal inconsistency in filesystem for disk '%s' %s\n", disk->name, ope);
- 3907 : exit(EXIT_FAILURE);
- 3908 : /* LCOV_EXCL_STOP */
- 3909 : }
- 3910 : }
- 3911 447 : }
+ 3896 : /* previous position */
+ 3897 1048979 : pred = state->progress_ptr + PROGRESS_MAX - 1;
+ 3898 1048979 : if (pred >= PROGRESS_MAX)
+ 3899 1048786 : pred -= PROGRESS_MAX;
+ 3900 :
+ 3901 : /* if the previous measure is different */
+ 3902 1048979 : if (state->progress_tick == 0
+ 3903 1048786 : || state->progress_time[pred] != now
+ 3904 : ) {
+ 3905 : uint64_t tick_total;
+ 3906 : uint64_t tick_cpu;
+ 3907 : time_t elapsed;
+ 3908 257 : unsigned out_perc = 0;
+ 3909 257 : unsigned out_speed = 0;
+ 3910 257 : unsigned out_cpu = 0;
+ 3911 257 : unsigned out_eta = 0;
3912 :
- 3913 1 : void generate_configuration(const char* path)
- 3914 : {
- 3915 : struct snapraid_state state;
- 3916 : struct snapraid_content* content;
- 3917 : unsigned i;
- 3918 : tommy_node* j;
- 3919 :
- 3920 1 : state_init(&state);
- 3921 :
- 3922 : /* mark that we are without a configuration file */
- 3923 1 : state.no_conf = 1;
- 3924 :
- 3925 : /* create the dummy content entry */
- 3926 1 : content = content_alloc(path, -1);
- 3927 :
- 3928 : /* adds the content entry */
- 3929 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content);
- 3930 :
- 3931 : /* read the content file */
- 3932 1 : state_read(&state);
+ 3913 257 : tick_total = state->tick_cpu + state->tick_io;
+ 3914 257 : tick_cpu = state->tick_cpu;
+ 3915 257 : elapsed = now - state->progress_whole_start - state->progress_wasted;
+ 3916 :
+ 3917 : /* completion percentage */
+ 3918 257 : if (countmax)
+ 3919 257 : out_perc = countpos * 100 / countmax;
+ 3920 :
+ 3921 : /* if we have at least 5 measures */
+ 3922 257 : if (state->progress_tick >= 5
+ 3923 : /* or if we are running in test mode, with at least one measure */
+ 3924 257 : || (state->opt.force_progress && state->progress_tick >= 1)
+ 3925 : ) {
+ 3926 : int oldest;
+ 3927 : int past;
+ 3928 : time_t delta_time;
+ 3929 : block_off_t delta_pos;
+ 3930 : data_off_t delta_size;
+ 3931 : uint64_t delta_tick_total;
+ 3932 : uint64_t delta_tick_cpu;
3933 :
- 3934 : /* output a dummy configuration file */
- 3935 1 : printf("# Configuration file generated from %s\n", path);
- 3936 1 : printf("\n");
- 3937 1 : printf("# Use this blocksize\n");
- 3938 1 : printf("blocksize %u\n", state.block_size / 1024);
- 3939 1 : printf("\n");
- 3940 7 : for (i = 0; i < state.level; ++i) {
- 3941 6 : printf("# Set the correct path for the %s file\n", lev_name(i));
- 3942 6 : if (state.parity[i].uuid[0])
- 3943 6 : printf("# The file was in the disk with id '%s'\n", state.parity[i].uuid);
- 3944 6 : printf("%s ENTER_HERE_THE_PARITY_FILE\n", lev_config_name(i));
- 3945 6 : printf("\n");
- 3946 : }
- 3947 1 : printf("# Add any other content file\n");
- 3948 1 : printf("content %s\n", path);
- 3949 1 : printf("\n");
- 3950 7 : for (j = state.maplist; j; j = j->next) {
- 3951 6 : struct snapraid_map* map = j->data;
- 3952 : struct snapraid_disk* disk;
- 3953 6 : printf("# Set the correct dir for disk '%s'\n", map->name);
- 3954 6 : if (map->uuid[0])
- 3955 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid);
- 3956 6 : disk = find_disk(&state, map->name);
- 3957 6 : if (disk && disk->filelist) {
- 3958 6 : struct snapraid_file* file = disk->filelist->data;
- 3959 6 : if (file) {
- 3960 6 : printf("# and containing: %s\n", file->sub);
- 3961 : }
- 3962 : }
- 3963 6 : printf("disk %s ENTER_HERE_THE_DIR\n", map->name);
- 3964 6 : printf("\n");
- 3965 : }
+ 3934 : /* number of past measures */
+ 3935 63 : past = state->progress_tick;
+ 3936 :
+ 3937 : /* drop the oldest ones, to promptly */
+ 3938 : /* skip the startup phase */
+ 3939 63 : past -= past / 5;
+ 3940 :
+ 3941 : /* check how much we can go in the past */
+ 3942 63 : if (past >= PROGRESS_MAX) {
+ 3943 : /* the vector is filled, so we are already in position */
+ 3944 : /* to get the possible oldest one */
+ 3945 0 : oldest = state->progress_ptr;
+ 3946 : } else {
+ 3947 : /* go backward the number of positions selected */
+ 3948 63 : oldest = state->progress_ptr + PROGRESS_MAX - past;
+ 3949 63 : if (oldest >= PROGRESS_MAX)
+ 3950 63 : oldest -= PROGRESS_MAX;
+ 3951 : }
+ 3952 :
+ 3953 63 : delta_time = now - state->progress_time[oldest];
+ 3954 63 : delta_pos = countpos - state->progress_pos[oldest];
+ 3955 63 : delta_size = countsize - state->progress_size[oldest];
+ 3956 63 : delta_tick_total = tick_total - state->progress_tick_total[oldest];
+ 3957 63 : delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest];
+ 3958 :
+ 3959 : /* estimate the speed in MiB/s */
+ 3960 63 : if (delta_time != 0)
+ 3961 63 : out_speed = (unsigned)(delta_size / MEGA / delta_time);
+ 3962 :
+ 3963 : /* estimate the cpu usage percentage */
+ 3964 63 : if (delta_tick_total != 0)
+ 3965 9 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total);
3966 :
- 3967 1 : state_done(&state);
- 3968 1 : }
- 3969 :
+ 3967 : /* estimate the remaining time in minutes */
+ 3968 63 : if (delta_pos != 0)
+ 3969 63 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos);
+ 3970 : }
+ 3971 :
+ 3972 257 : if (state->opt.gui) {
+ 3973 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed);
+ 3974 7 : log_flush();
+ 3975 : } else {
+ 3976 250 : msg_bar("%u%%, %u MiB", out_perc, (unsigned)(countsize / MEGA));
+ 3977 250 : if (out_speed)
+ 3978 49 : msg_bar(", %u MiB/s", out_speed);
+ 3979 250 : if (out_cpu)
+ 3980 9 : msg_bar(", CPU %u%%", out_cpu);
+ 3981 250 : if (out_eta)
+ 3982 4 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
+ 3983 250 : msg_bar("%s\r", PROGRESS_CLEAR);
+ 3984 250 : msg_flush();
+ 3985 : }
+ 3986 :
+ 3987 : /* store the new measure */
+ 3988 257 : state->progress_time[state->progress_ptr] = now;
+ 3989 257 : state->progress_pos[state->progress_ptr] = countpos;
+ 3990 257 : state->progress_size[state->progress_ptr] = countsize;
+ 3991 257 : state->progress_tick_cpu[state->progress_ptr] = tick_cpu;
+ 3992 257 : state->progress_tick_total[state->progress_ptr] = tick_total;
+ 3993 :
+ 3994 : /* next position */
+ 3995 257 : ++state->progress_ptr;
+ 3996 257 : if (state->progress_ptr >= PROGRESS_MAX)
+ 3997 0 : state->progress_ptr -= PROGRESS_MAX;
+ 3998 :
+ 3999 : /* one more measure */
+ 4000 257 : ++state->progress_tick;
+ 4001 : }
+ 4002 :
+ 4003 : /* stop if requested */
+ 4004 1048979 : if (global_interrupt) {
+ 4005 : /* LCOV_EXCL_START */
+ 4006 : if (!state->opt.gui) {
+ 4007 : log_fatal("\n");
+ 4008 : log_fatal("Stopping for interruption at block %u\n", blockpos);
+ 4009 : }
+ 4010 : log_tag("sigint:%u: SIGINT received\n", blockpos);
+ 4011 : log_flush();
+ 4012 : return 1;
+ 4013 : /* LCOV_EXCL_STOP */
+ 4014 : }
+ 4015 :
+ 4016 1048979 : return 0;
+ 4017 : }
+ 4018 :
+ 4019 89 : void state_usage_print(struct snapraid_state* state)
+ 4020 : {
+ 4021 : uint64_t tick_total;
+ 4022 : uint64_t tick_max;
+ 4023 : tommy_node* i;
+ 4024 : unsigned l;
+ 4025 :
+ 4026 89 : tick_max = 0;
+ 4027 89 : tick_total = 0;
+ 4028 621 : for (i = state->disklist; i != 0; i = i->next) {
+ 4029 532 : struct snapraid_disk* disk = i->data;
+ 4030 532 : tick_total += disk->tick;
+ 4031 532 : if (disk->tick > tick_max)
+ 4032 100 : tick_max = disk->tick;
+ 4033 : }
+ 4034 608 : for (l = 0; l < state->level; ++l) {
+ 4035 519 : tick_total += state->parity[l].tick;
+ 4036 519 : if (state->parity[l].tick > tick_max)
+ 4037 19 : tick_max = state->parity[l].tick;
+ 4038 : }
+ 4039 :
+ 4040 89 : if (!tick_total)
+ 4041 107 : return;
+ 4042 :
+ 4043 71 : if (msg_level >= MSG_PROGRESS) {
+ 4044 : /* here we don't use msg_progress() because it doesn't allow partial output */
+ 4045 1 : printf("Time for disk:");
+ 4046 7 : for (i = state->disklist; i != 0; i = i->next) {
+ 4047 6 : struct snapraid_disk* disk = i->data;
+ 4048 6 : if (disk->tick == tick_max)
+ 4049 1 : printf(" %s:", disk->name);
+ 4050 : else
+ 4051 5 : printf(" ");
+ 4052 6 : printf("%" PRIu64 "%%", disk->tick * 100U / tick_total);
+ 4053 : }
+ 4054 1 : printf("\n");
+ 4055 :
+ 4056 1 : printf("Time for parity:");
+ 4057 7 : for (l = 0; l < state->level; ++l) {
+ 4058 6 : if (state->parity[l].tick == tick_max)
+ 4059 0 : printf(" %s:", lev_config_name(l));
+ 4060 : else
+ 4061 6 : printf(" ");
+ 4062 6 : printf("%" PRIu64 "%%", state->parity[l].tick * 100U / tick_total);
+ 4063 : }
+ 4064 1 : printf("\n");
+ 4065 : }
+ 4066 : }
+ 4067 :
+ 4068 474 : void state_fscheck(struct snapraid_state* state, const char* ope)
+ 4069 : {
+ 4070 : tommy_node* i;
+ 4071 :
+ 4072 : /* check the file-system on all disks */
+ 4073 3312 : for (i = state->disklist; i != 0; i = i->next) {
+ 4074 2838 : struct snapraid_disk* disk = i->data;
+ 4075 :
+ 4076 2838 : if (fs_check(disk) != 0) {
+ 4077 : /* LCOV_EXCL_START */
+ 4078 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope);
+ 4079 : os_abort();
+ 4080 : /* LCOV_EXCL_STOP */
+ 4081 : }
+ 4082 : }
+ 4083 474 : }
+ 4084 :
+ 4085 1 : void generate_configuration(const char* path)
+ 4086 : {
+ 4087 : struct snapraid_state state;
+ 4088 : struct snapraid_content* content;
+ 4089 : unsigned i;
+ 4090 : tommy_node* j;
+ 4091 :
+ 4092 1 : state_init(&state);
+ 4093 :
+ 4094 : /* mark that we are without a configuration file */
+ 4095 1 : state.no_conf = 1;
+ 4096 :
+ 4097 : /* create the dummy content entry */
+ 4098 1 : content = content_alloc(path, -1);
+ 4099 :
+ 4100 : /* adds the content entry */
+ 4101 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content);
+ 4102 :
+ 4103 : /* read the content file */
+ 4104 1 : state_read(&state);
+ 4105 :
+ 4106 : /* output a dummy configuration file */
+ 4107 1 : printf("# Configuration file generated from %s\n", path);
+ 4108 1 : printf("\n");
+ 4109 1 : printf("# Use this blocksize\n");
+ 4110 1 : printf("blocksize %u\n", state.block_size / 1024);
+ 4111 1 : printf("\n");
+ 4112 7 : for (i = 0; i < state.level; ++i) {
+ 4113 6 : printf("# Set the correct path for the %s file\n", lev_name(i));
+ 4114 6 : if (state.parity[i].uuid[0])
+ 4115 6 : printf("# The file was in the disk with id '%s'\n", state.parity[i].uuid);
+ 4116 6 : printf("%s ENTER_HERE_THE_PARITY_FILE\n", lev_config_name(i));
+ 4117 6 : printf("\n");
+ 4118 : }
+ 4119 1 : printf("# Add any other content file\n");
+ 4120 1 : printf("content %s\n", path);
+ 4121 1 : printf("\n");
+ 4122 7 : for (j = state.maplist; j; j = j->next) {
+ 4123 6 : struct snapraid_map* map = j->data;
+ 4124 : struct snapraid_disk* disk;
+ 4125 6 : printf("# Set the correct dir for disk '%s'\n", map->name);
+ 4126 6 : if (map->uuid[0])
+ 4127 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid);
+ 4128 6 : disk = find_disk_by_name(&state, map->name);
+ 4129 6 : if (disk && disk->filelist) {
+ 4130 6 : struct snapraid_file* file = disk->filelist->data;
+ 4131 6 : if (file) {
+ 4132 6 : printf("# and containing: %s\n", file->sub);
+ 4133 : }
+ 4134 : }
+ 4135 6 : printf("disk %s ENTER_HERE_THE_DIR\n", map->name);
+ 4136 6 : printf("\n");
+ 4137 : }
+ 4138 :
+ 4139 1 : state_done(&state);
+ 4140 1 : }
+ 4141 :
diff --git a/cov/cmdline/state.h.func-sort-c.html b/cov/cmdline/state.h.func-sort-c.html
index 05fa4cc0..220cc8c0 100644
--- a/cov/cmdline/state.h.func-sort-c.html
+++ b/cov/cmdline/state.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,20 +60,20 @@
Hit count  |
- | state_usage_cpu |
- 772778 |
+ state_usage_cpu |
+ 833206 |
- | state_usage_parity |
- 653350 |
+ state_usage_parity |
+ 706913 |
- | state_usage_disk |
- 622545 |
+ state_usage_disk |
+ 673880 |
- | state_usage_waste |
- 89 |
+ state_usage_waste |
+ 97 |
diff --git a/cov/cmdline/state.h.func.html b/cov/cmdline/state.h.func.html
index 37c5849d..2c89482c 100644
--- a/cov/cmdline/state.h.func.html
+++ b/cov/cmdline/state.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,20 +60,20 @@
Hit count  |
- | state_usage_cpu |
- 772778 |
+ state_usage_cpu |
+ 833206 |
- | state_usage_disk |
- 622545 |
+ state_usage_disk |
+ 673880 |
- | state_usage_parity |
- 653350 |
+ state_usage_parity |
+ 706913 |
- | state_usage_waste |
- 89 |
+ state_usage_waste |
+ 97 |
diff --git a/cov/cmdline/state.h.gcov.html b/cov/cmdline/state.h.gcov.html
index 0cdf4d7f..6a6fac5f 100644
--- a/cov/cmdline/state.h.gcov.html
+++ b/cov/cmdline/state.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -136,11 +136,11 @@
74 : int syncedonly; /**< In fix, fixes only files that are synced. */
75 : int prehash; /**< Enables the prehash mode for sync. */
76 : unsigned io_error_limit; /**< Max number of input/output errors before aborting. */
- 77 : int force_zero; /**< Forced dangerous operations of synching files now with zero size. */
- 78 : int force_empty; /**< Forced dangerous operations of synching disks now empty. */
- 79 : int force_uuid; /**< Forced dangerous operations of synching disks with uuid changed. */
+ 77 : int force_zero; /**< Forced dangerous operations of syncing files now with zero size. */
+ 78 : int force_empty; /**< Forced dangerous operations of syncing disks now empty. */
+ 79 : int force_uuid; /**< Forced dangerous operations of syncing disks with uuid changed. */
80 : int force_device; /**< Forced dangerous operations of using disks with save device id. */
- 81 : int force_nocopy; /**< Force dangerous operations of synching files without using copy detection. */
+ 81 : int force_nocopy; /**< Force dangerous operations of syncing files without using copy detection. */
82 : int force_full; /**< Force a full sync when using an old content file. */
83 : int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */
84 : int expect_recoverable; /**< Expect presence of recoverable error in checking. */
@@ -165,299 +165,303 @@
103 : int force_progress; /**< Force the use of the progress status. */
104 : unsigned force_autosave_at; /**< Force autosave at the specified block. */
105 : int fake_device; /**< Fake device data. */
- 106 : int expected_missing; /**< If missing files are expected and should not be reported. */
- 107 : };
- 108 :
- 109 : /**
- 110 : * Number of measures of the operation progress.
- 111 : */
- 112 : #define PROGRESS_MAX 100
- 113 :
- 114 : struct snapraid_state {
- 115 : struct snapraid_option opt; /**< Setup options. */
- 116 : int filter_hidden; /**< Filter out hidden files. */
- 117 : uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */
- 118 : int need_write; /**< If the state is changed. */
- 119 : int checked_read; /**< If the state was read and checked. */
- 120 : uint32_t block_size; /**< Block size in bytes. */
- 121 : unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */
- 122 : int file_mode; /**< File access mode. Combination of MODE_* flags. */
- 123 : struct snapraid_parity parity[LEV_MAX]; /**< Parity vector. */
- 124 : char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */
- 125 : char pool[PATH_MAX]; /**< Path of the pool tree. */
- 126 : uint64_t pool_device; /**< Device identifier of the pool. */
- 127 : unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */
- 128 : unsigned char prevhashseed[HASH_SIZE]; /**< Previous hash seed. In case of rehash. */
- 129 : char lockfile[PATH_MAX]; /**< Path of the lock file to use. */
- 130 : unsigned level; /**< Number of parity levels. 1 for PAR1, 2 for PAR2. */
- 131 : unsigned hash; /**< Hash kind used. */
- 132 : unsigned prevhash; /**< Previous hash kind used. In case of rehash. */
- 133 : unsigned besthash; /**< Best hash suggested. */
- 134 : const char* command; /**< Command running. */
- 135 : tommy_list contentlist; /**< List of content files. */
- 136 : tommy_list disklist; /**< List of all the disks. */
- 137 : tommy_list maplist; /**< List of all the disk mappings. */
- 138 : tommy_list filterlist; /**< List of inclusion/exclusion. */
- 139 : tommy_list importlist; /**< List of import file. */
- 140 : tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */
- 141 : tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */
- 142 : tommy_hashdyn searchset; /**< Hashtable by timestamp of all the search files. */
- 143 : tommy_arrayblkof infoarr; /**< Block information array. */
- 144 :
- 145 : /**
- 146 : * Cumulative time used for computations.
- 147 : */
- 148 : uint64_t tick_cpu;
- 149 :
- 150 : /**
- 151 : * Cumulative time used for all io operations of disks.
- 152 : */
- 153 : uint64_t tick_io;
- 154 :
- 155 : /**
- 156 : * Last time used for time measure.
- 157 : */
- 158 : uint64_t tick_last;
- 159 :
- 160 : int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */
- 161 :
- 162 : time_t progress_whole_start; /**< Initial start of the whole process. */
- 163 : time_t progress_interruption; /**< Time of the start of the progress interruption. */
- 164 : time_t progress_wasted; /**< Time wasted in interruptions. */
+ 106 : int no_warnings; /**< Remove some warning messages. */
+ 107 : int expected_missing; /**< If missing files are expected and should not be reported. */
+ 108 : int fake_uuid; /**< Set fakes UUID for testing. */
+ 109 : int match_first_uuid; /**< Force the matching of the first UUID. */
+ 110 : int force_parity_update; /**< Force parity update even if data is not changed. */
+ 111 : };
+ 112 :
+ 113 : /**
+ 114 : * Number of measures of the operation progress.
+ 115 : */
+ 116 : #define PROGRESS_MAX 100
+ 117 :
+ 118 : struct snapraid_state {
+ 119 : struct snapraid_option opt; /**< Setup options. */
+ 120 : int filter_hidden; /**< Filter out hidden files. */
+ 121 : uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */
+ 122 : int need_write; /**< If the state is changed. */
+ 123 : int checked_read; /**< If the state was read and checked. */
+ 124 : uint32_t block_size; /**< Block size in bytes. */
+ 125 : unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */
+ 126 : int file_mode; /**< File access mode. Combination of MODE_* flags. */
+ 127 : struct snapraid_parity parity[LEV_MAX]; /**< Parity vector. */
+ 128 : char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */
+ 129 : char pool[PATH_MAX]; /**< Path of the pool tree. */
+ 130 : uint64_t pool_device; /**< Device identifier of the pool. */
+ 131 : unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */
+ 132 : unsigned char prevhashseed[HASH_SIZE]; /**< Previous hash seed. In case of rehash. */
+ 133 : char lockfile[PATH_MAX]; /**< Path of the lock file to use. */
+ 134 : unsigned level; /**< Number of parity levels. 1 for PAR1, 2 for PAR2. */
+ 135 : unsigned hash; /**< Hash kind used. */
+ 136 : unsigned prevhash; /**< Previous hash kind used. In case of rehash. */
+ 137 : unsigned besthash; /**< Best hash suggested. */
+ 138 : const char* command; /**< Command running. */
+ 139 : tommy_list contentlist; /**< List of content files. */
+ 140 : tommy_list disklist; /**< List of all the disks. */
+ 141 : tommy_list maplist; /**< List of all the disk mappings. */
+ 142 : tommy_list filterlist; /**< List of inclusion/exclusion. */
+ 143 : tommy_list importlist; /**< List of import file. */
+ 144 : tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */
+ 145 : tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */
+ 146 : tommy_hashdyn searchset; /**< Hashtable by timestamp of all the search files. */
+ 147 : tommy_arrayblkof infoarr; /**< Block information array. */
+ 148 :
+ 149 : /**
+ 150 : * Cumulative time used for computations.
+ 151 : */
+ 152 : uint64_t tick_cpu;
+ 153 :
+ 154 : /**
+ 155 : * Cumulative time used for all io operations of disks.
+ 156 : */
+ 157 : uint64_t tick_io;
+ 158 :
+ 159 : /**
+ 160 : * Last time used for time measure.
+ 161 : */
+ 162 : uint64_t tick_last;
+ 163 :
+ 164 : int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */
165 :
- 166 : time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */
- 167 : block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */
- 168 : data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */
- 169 : uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
- 170 : uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */
- 171 :
- 172 : int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */
- 173 : int progress_tick; /**< Number of measures done. */
- 174 :
- 175 : int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */
- 176 : };
- 177 :
- 178 : /**
- 179 : * Initialize the state.
- 180 : */
- 181 : void state_init(struct snapraid_state* state);
- 182 :
- 183 : /**
- 184 : * Deinitialize the state.
- 185 : */
- 186 : void state_done(struct snapraid_state* state);
- 187 :
- 188 : /**
- 189 : * Read the configuration file.
- 190 : */
- 191 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk);
- 192 :
- 193 : /**
- 194 : * Read the state.
- 195 : */
- 196 : void state_read(struct snapraid_state* state);
- 197 :
- 198 : /**
- 199 : * Write the new state.
- 200 : */
- 201 : void state_write(struct snapraid_state* state);
- 202 :
- 203 : /**
- 204 : * Diff all the disks.
- 205 : */
- 206 : int state_diff(struct snapraid_state* state);
- 207 :
- 208 : /**
- 209 : * Scan all the disks to update the state.
- 210 : */
- 211 : void state_scan(struct snapraid_state* state);
- 212 :
- 213 : /**
- 214 : * Set the nanosecond timestamp of all files that have a zero value.
- 215 : */
- 216 : void state_nano(struct snapraid_state* state);
- 217 :
- 218 : /**
- 219 : * Devices operations.
- 220 : */
- 221 : void state_device(struct snapraid_state* state, int operation);
- 222 :
- 223 : /**
- 224 : * Sync the parity data.
- 225 : */
- 226 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount);
- 227 :
- 228 : /**
- 229 : * Check (and fixes) all the files and parity data.
- 230 : * \param fix If we have to fix, after checking.
- 231 : */
- 232 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount);
- 233 :
- 234 : /**
- 235 : * Dry the files.
- 236 : */
- 237 : void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount);
- 238 :
- 239 : /**
- 240 : * Rehash the files.
- 241 : */
- 242 : void state_rehash(struct snapraid_state* state);
- 243 :
- 244 : /**
- 245 : * Scrub levels.
- 246 : */
- 247 : #define SCRUB_AUTO -1 /**< Automatic selection. */
- 248 : #define SCRUB_BAD -2 /**< Scrub only the bad blocks. */
- 249 : #define SCRUB_NEW -3 /**< Scub the new blocks. */
- 250 : #define SCRUB_FULL -4 /**< Scrub everything. */
- 251 : #define SCRUB_EVEN -5 /**< Even blocks. */
- 252 :
- 253 : /**
- 254 : * Scrub the files.
- 255 : */
- 256 : int state_scrub(struct snapraid_state* state, int plan, int olderthan);
- 257 :
- 258 : /**
- 259 : * Print the status.
- 260 : */
- 261 : int state_status(struct snapraid_state* state);
- 262 :
- 263 : /**
- 264 : * Find duplicates.
- 265 : */
- 266 : void state_dup(struct snapraid_state* state);
- 267 :
- 268 : /**
- 269 : * List content.
- 270 : */
- 271 : void state_list(struct snapraid_state* state);
- 272 :
- 273 : /**
- 274 : * Create pool tree.
- 275 : */
- 276 : void state_pool(struct snapraid_state* state);
- 277 :
- 278 : /**
- 279 : * Refresh the free space info.
- 280 : *
- 281 : * Note that it requires disks access.
- 282 : */
- 283 : void state_refresh(struct snapraid_state* state);
- 284 :
- 285 : /**
- 286 : * Skip files, symlinks and dirs.
- 287 : * Apply any skip access disk.
- 288 : */
- 289 : void state_skip(struct snapraid_state* state);
- 290 :
- 291 : /**
- 292 : * Filter files, symlinks and dirs.
- 293 : * Apply an additional filter to the list currently loaded.
- 294 : */
- 295 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error);
- 296 :
- 297 : /**
- 298 : * Begin the progress visualization.
- 299 : */
- 300 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax);
- 301 :
- 302 : /**
- 303 : * End the progress visualization.
- 304 : */
- 305 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize);
- 306 :
- 307 : /**
- 308 : * Write the progress.
- 309 : */
- 310 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize);
- 311 :
- 312 : /**
- 313 : * Stop temporarely the progress.
- 314 : */
- 315 : void state_progress_stop(struct snapraid_state* state);
- 316 :
- 317 : /**
- 318 : * Restart the progress.
- 319 : */
- 320 : void state_progress_restart(struct snapraid_state* state);
- 321 :
- 322 : /**
- 323 : * Set the usage time as wasted one not counted.
- 324 : */
- 325 89 : static inline void state_usage_waste(struct snapraid_state* state)
- 326 : {
- 327 89 : uint64_t now = tick();
- 328 :
- 329 89 : state->tick_last = now;
- 330 89 : }
- 331 :
- 332 : /**
- 333 : * Set the usage time for CPU.
- 334 : */
- 335 772778 : static inline void state_usage_cpu(struct snapraid_state* state)
- 336 : {
- 337 772778 : uint64_t now = tick();
- 338 772778 : uint64_t delta = now - state->tick_last;
- 339 :
- 340 : /* increment the time spent in computations */
- 341 772778 : state->tick_cpu += delta;
- 342 :
- 343 772778 : state->tick_last = now;
- 344 772778 : }
- 345 :
- 346 : /**
- 347 : * Set the usage time for data disk.
- 348 : */
- 349 622545 : static inline void state_usage_disk(struct snapraid_state* state, struct snapraid_disk* disk)
- 350 : {
- 351 622545 : uint64_t now = tick();
- 352 622545 : uint64_t delta = now - state->tick_last;
- 353 :
- 354 : /* increment the time spent in the data disk */
- 355 622545 : disk->tick += delta;
- 356 622545 : state->tick_io += delta;
+ 166 : time_t progress_whole_start; /**< Initial start of the whole process. */
+ 167 : time_t progress_interruption; /**< Time of the start of the progress interruption. */
+ 168 : time_t progress_wasted; /**< Time wasted in interruptions. */
+ 169 :
+ 170 : time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */
+ 171 : block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */
+ 172 : data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */
+ 173 : uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
+ 174 : uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */
+ 175 :
+ 176 : int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */
+ 177 : int progress_tick; /**< Number of measures done. */
+ 178 :
+ 179 : int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */
+ 180 : };
+ 181 :
+ 182 : /**
+ 183 : * Initialize the state.
+ 184 : */
+ 185 : void state_init(struct snapraid_state* state);
+ 186 :
+ 187 : /**
+ 188 : * Deinitialize the state.
+ 189 : */
+ 190 : void state_done(struct snapraid_state* state);
+ 191 :
+ 192 : /**
+ 193 : * Read the configuration file.
+ 194 : */
+ 195 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk);
+ 196 :
+ 197 : /**
+ 198 : * Read the state.
+ 199 : */
+ 200 : void state_read(struct snapraid_state* state);
+ 201 :
+ 202 : /**
+ 203 : * Write the new state.
+ 204 : */
+ 205 : void state_write(struct snapraid_state* state);
+ 206 :
+ 207 : /**
+ 208 : * Diff all the disks.
+ 209 : */
+ 210 : int state_diff(struct snapraid_state* state);
+ 211 :
+ 212 : /**
+ 213 : * Scan all the disks to update the state.
+ 214 : */
+ 215 : void state_scan(struct snapraid_state* state);
+ 216 :
+ 217 : /**
+ 218 : * Set the nanosecond timestamp of all files that have a zero value.
+ 219 : */
+ 220 : void state_nano(struct snapraid_state* state);
+ 221 :
+ 222 : /**
+ 223 : * Devices operations.
+ 224 : */
+ 225 : void state_device(struct snapraid_state* state, int operation);
+ 226 :
+ 227 : /**
+ 228 : * Sync the parity data.
+ 229 : */
+ 230 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount);
+ 231 :
+ 232 : /**
+ 233 : * Check (and fixes) all the files and parity data.
+ 234 : * \param fix If we have to fix, after checking.
+ 235 : */
+ 236 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount);
+ 237 :
+ 238 : /**
+ 239 : * Dry the files.
+ 240 : */
+ 241 : void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount);
+ 242 :
+ 243 : /**
+ 244 : * Rehash the files.
+ 245 : */
+ 246 : void state_rehash(struct snapraid_state* state);
+ 247 :
+ 248 : /**
+ 249 : * Scrub levels.
+ 250 : */
+ 251 : #define SCRUB_AUTO -1 /**< Automatic selection. */
+ 252 : #define SCRUB_BAD -2 /**< Scrub only the bad blocks. */
+ 253 : #define SCRUB_NEW -3 /**< Scub the new blocks. */
+ 254 : #define SCRUB_FULL -4 /**< Scrub everything. */
+ 255 : #define SCRUB_EVEN -5 /**< Even blocks. */
+ 256 :
+ 257 : /**
+ 258 : * Scrub the files.
+ 259 : */
+ 260 : int state_scrub(struct snapraid_state* state, int plan, int olderthan);
+ 261 :
+ 262 : /**
+ 263 : * Print the status.
+ 264 : */
+ 265 : int state_status(struct snapraid_state* state);
+ 266 :
+ 267 : /**
+ 268 : * Find duplicates.
+ 269 : */
+ 270 : void state_dup(struct snapraid_state* state);
+ 271 :
+ 272 : /**
+ 273 : * List content.
+ 274 : */
+ 275 : void state_list(struct snapraid_state* state);
+ 276 :
+ 277 : /**
+ 278 : * Create pool tree.
+ 279 : */
+ 280 : void state_pool(struct snapraid_state* state);
+ 281 :
+ 282 : /**
+ 283 : * Refresh the free space info.
+ 284 : *
+ 285 : * Note that it requires disks access.
+ 286 : */
+ 287 : void state_refresh(struct snapraid_state* state);
+ 288 :
+ 289 : /**
+ 290 : * Skip files, symlinks and dirs.
+ 291 : * Apply any skip access disk.
+ 292 : */
+ 293 : void state_skip(struct snapraid_state* state);
+ 294 :
+ 295 : /**
+ 296 : * Filter files, symlinks and dirs.
+ 297 : * Apply an additional filter to the list currently loaded.
+ 298 : */
+ 299 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error);
+ 300 :
+ 301 : /**
+ 302 : * Begin the progress visualization.
+ 303 : */
+ 304 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax);
+ 305 :
+ 306 : /**
+ 307 : * End the progress visualization.
+ 308 : */
+ 309 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize);
+ 310 :
+ 311 : /**
+ 312 : * Write the progress.
+ 313 : */
+ 314 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize);
+ 315 :
+ 316 : /**
+ 317 : * Stop temporarily the progress.
+ 318 : */
+ 319 : void state_progress_stop(struct snapraid_state* state);
+ 320 :
+ 321 : /**
+ 322 : * Restart the progress.
+ 323 : */
+ 324 : void state_progress_restart(struct snapraid_state* state);
+ 325 :
+ 326 : /**
+ 327 : * Set the usage time as wasted one not counted.
+ 328 : */
+ 329 97 : static inline void state_usage_waste(struct snapraid_state* state)
+ 330 : {
+ 331 97 : uint64_t now = tick();
+ 332 :
+ 333 97 : state->tick_last = now;
+ 334 97 : }
+ 335 :
+ 336 : /**
+ 337 : * Set the usage time for CPU.
+ 338 : */
+ 339 833206 : static inline void state_usage_cpu(struct snapraid_state* state)
+ 340 : {
+ 341 833206 : uint64_t now = tick();
+ 342 833206 : uint64_t delta = now - state->tick_last;
+ 343 :
+ 344 : /* increment the time spent in computations */
+ 345 833206 : state->tick_cpu += delta;
+ 346 :
+ 347 833206 : state->tick_last = now;
+ 348 833206 : }
+ 349 :
+ 350 : /**
+ 351 : * Set the usage time for data disk.
+ 352 : */
+ 353 673880 : static inline void state_usage_disk(struct snapraid_state* state, struct snapraid_disk* disk)
+ 354 : {
+ 355 673880 : uint64_t now = tick();
+ 356 673880 : uint64_t delta = now - state->tick_last;
357 :
- 358 622545 : state->tick_last = now;
- 359 622545 : }
- 360 :
- 361 : /**
- 362 : * Set the usage time for parity disk.
- 363 : */
- 364 653350 : static inline void state_usage_parity(struct snapraid_state* state, unsigned level)
- 365 : {
- 366 653350 : uint64_t now = tick();
- 367 653350 : uint64_t delta = now - state->tick_last;
- 368 :
- 369 653350 : assert(level < LEV_MAX);
- 370 :
- 371 : /* increment the time spent in the parity disk */
- 372 653350 : state->parity[level].tick += delta;
- 373 653350 : state->tick_io += delta;
+ 358 : /* increment the time spent in the data disk */
+ 359 673880 : disk->tick += delta;
+ 360 673880 : state->tick_io += delta;
+ 361 :
+ 362 673880 : state->tick_last = now;
+ 363 673880 : }
+ 364 :
+ 365 : /**
+ 366 : * Set the usage time for parity disk.
+ 367 : */
+ 368 706913 : static inline void state_usage_parity(struct snapraid_state* state, unsigned level)
+ 369 : {
+ 370 706913 : uint64_t now = tick();
+ 371 706913 : uint64_t delta = now - state->tick_last;
+ 372 :
+ 373 706913 : assert(level < LEV_MAX);
374 :
- 375 653350 : state->tick_last = now;
- 376 653350 : }
- 377 :
- 378 : /**
- 379 : * Print the stats of the usage time.
- 380 : */
- 381 : void state_usage_print(struct snapraid_state* state);
- 382 :
- 383 : /**
- 384 : * Check the filesystem on all disks.
- 385 : * On error it aborts.
- 386 : */
- 387 : void state_fscheck(struct snapraid_state* state, const char* ope);
- 388 :
- 389 : /****************************************************************************/
- 390 : /* misc */
- 391 :
- 392 : /**
- 393 : * Generate a dummy configuration file from a content file.
- 394 : */
- 395 : void generate_configuration(const char* content);
- 396 :
- 397 : #endif
- 398 :
+ 375 : /* increment the time spent in the parity disk */
+ 376 706913 : state->parity[level].tick += delta;
+ 377 706913 : state->tick_io += delta;
+ 378 :
+ 379 706913 : state->tick_last = now;
+ 380 706913 : }
+ 381 :
+ 382 : /**
+ 383 : * Print the stats of the usage time.
+ 384 : */
+ 385 : void state_usage_print(struct snapraid_state* state);
+ 386 :
+ 387 : /**
+ 388 : * Check the file-system on all disks.
+ 389 : * On error it aborts.
+ 390 : */
+ 391 : void state_fscheck(struct snapraid_state* state, const char* ope);
+ 392 :
+ 393 : /****************************************************************************/
+ 394 : /* misc */
+ 395 :
+ 396 : /**
+ 397 : * Generate a dummy configuration file from a content file.
+ 398 : */
+ 399 : void generate_configuration(const char* content);
+ 400 :
+ 401 : #endif
+ 402 :
diff --git a/cov/cmdline/status.c.func-sort-c.html b/cov/cmdline/status.c.func-sort-c.html
index 3a3013e8..1c2639e5 100644
--- a/cov/cmdline/status.c.func-sort-c.html
+++ b/cov/cmdline/status.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/status.c.func.html b/cov/cmdline/status.c.func.html
index fd04e329..4558d05e 100644
--- a/cov/cmdline/status.c.func.html
+++ b/cov/cmdline/status.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/status.c.gcov.html b/cov/cmdline/status.c.gcov.html
index 59c5f405..6c2b85f8 100644
--- a/cov/cmdline/status.c.gcov.html
+++ b/cov/cmdline/status.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -159,9 +159,9 @@
97 84 : log_tag("summary:parity_block_total:%s:%u\n", lev_config_name(l), state->parity[l].total_blocks);
98 84 : log_tag("summary:parity_block_free:%s:%u\n", lev_config_name(l), state->parity[l].free_blocks);
99 84 : if (state->parity[l].free_blocks < parity_block_free)
- 100 4 : parity_block_free = state->parity[l].free_blocks;
+ 100 1 : parity_block_free = state->parity[l].free_blocks;
101 84 : if (state->parity[l].free_blocks != 0)
- 102 58 : free_not_zero = 1;
+ 102 73 : free_not_zero = 1;
103 : }
104 14 : log_tag("summary:parity_block_free_min:%u\n", parity_block_free);
105 :
@@ -195,50 +195,50 @@
133 :
134 : /* for each file in the disk */
135 84 : node = disk->filelist;
- 136 95610 : while (node) {
+ 136 95666 : while (node) {
137 : struct snapraid_file* file;
138 :
- 139 95442 : file = node->data;
- 140 95442 : node = node->next; /* next node */
+ 139 95498 : file = node->data;
+ 140 95498 : node = node->next; /* next node */
141 :
142 : /* check fragmentation */
- 143 95442 : if (file->blockmax != 0) {
+ 143 95498 : if (file->blockmax != 0) {
144 : block_off_t prev_pos;
145 : block_off_t last_pos;
146 : int fragmented;
147 :
- 148 95304 : fragmented = 0;
- 149 95304 : prev_pos = fs_file2par_get(disk, file, 0);
- 150 234999 : for (j = 1; j < file->blockmax; ++j) {
- 151 139695 : block_off_t parity_pos = fs_file2par_get(disk, file, j);
- 152 139695 : if (prev_pos + 1 != parity_pos) {
+ 148 95360 : fragmented = 0;
+ 149 95360 : prev_pos = fs_file2par_get(disk, file, 0);
+ 150 235447 : for (j = 1; j < file->blockmax; ++j) {
+ 151 140087 : block_off_t parity_pos = fs_file2par_get(disk, file, j);
+ 152 140087 : if (prev_pos + 1 != parity_pos) {
153 698 : fragmented = 1;
154 698 : ++extra_fragment;
155 698 : ++disk_extra_fragment;
156 : }
- 157 139695 : prev_pos = parity_pos;
+ 157 140087 : prev_pos = parity_pos;
158 : }
159 :
160 : /* keep track of latest block used */
- 161 95304 : last_pos = fs_file2par_get(disk, file, file->blockmax - 1);
- 162 95304 : if (last_pos > disk_block_latest_used) {
- 163 92447 : disk_block_latest_used = last_pos;
+ 161 95360 : last_pos = fs_file2par_get(disk, file, file->blockmax - 1);
+ 162 95360 : if (last_pos > disk_block_latest_used) {
+ 163 92502 : disk_block_latest_used = last_pos;
164 : }
165 :
- 166 95304 : if (fragmented) {
+ 166 95360 : if (fragmented) {
167 582 : ++file_fragmented;
168 582 : ++disk_file_fragmented;
169 : }
170 :
- 171 95304 : disk_block_count += file->blockmax;
+ 171 95360 : disk_block_count += file->blockmax;
172 : }
173 :
174 : /* count files */
- 175 95442 : ++file_count;
- 176 95442 : ++disk_file_count;
- 177 95442 : file_size += file->size;
- 178 95442 : file_block_count += file->blockmax;
- 179 95442 : disk_file_size += file->size;
+ 175 95498 : ++file_count;
+ 176 95498 : ++disk_file_count;
+ 177 95498 : file_size += file->size;
+ 178 95498 : file_block_count += file->blockmax;
+ 179 95498 : disk_file_size += file->size;
180 : }
181 :
182 84 : if (disk->free_blocks != 0)
@@ -253,9 +253,9 @@
191 : /* the wasted space is the space that we have to leave */
192 : /* free on the data disk, when the parity is filled up */
193 84 : if (disk_block_max_by_space < disk_block_max_by_parity) {
- 194 50 : disk_block_max = disk_block_max_by_space;
+ 194 65 : disk_block_max = disk_block_max_by_space;
195 : } else {
- 196 34 : disk_block_max = disk_block_max_by_parity;
+ 196 19 : disk_block_max = disk_block_max_by_parity;
197 : }
198 :
199 : /* wasted space is the difference of the two maximum size */
@@ -264,7 +264,7 @@
202 84 : wasted *= state->block_size;
203 :
204 84 : if (wasted > 0)
- 205 24 : all_wasted += wasted;
+ 205 6 : all_wasted += wasted;
206 84 : file_block_free += disk_block_max - disk_block_count;
207 :
208 84 : printf("%8u", disk_file_count);
@@ -338,57 +338,57 @@
276 14 : unsynced_blocks = 0;
277 14 : unscrubbed_blocks = 0;
278 14 : log_tag("block_count:%u\n", blockmax);
- 279 39620 : for (i = 0; i < blockmax; ++i) {
+ 279 39702 : for (i = 0; i < blockmax; ++i) {
280 : int one_invalid;
281 : int one_valid;
282 :
- 283 39606 : snapraid_info info = info_get(&state->infoarr, i);
+ 283 39688 : snapraid_info info = info_get(&state->infoarr, i);
284 :
285 : /* for each disk */
- 286 39606 : one_invalid = 0;
- 287 39606 : one_valid = 0;
- 288 277242 : for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
- 289 237636 : struct snapraid_disk* disk = node_disk->data;
- 290 237636 : struct snapraid_block* block = fs_par2block_get(disk, i);
+ 286 39688 : one_invalid = 0;
+ 287 39688 : one_valid = 0;
+ 288 277816 : for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
+ 289 238128 : struct snapraid_disk* disk = node_disk->data;
+ 290 238128 : struct snapraid_block* block = fs_par2block_get(disk, i);
291 :
- 292 237636 : if (block_has_file(block))
- 293 234999 : one_valid = 1;
- 294 237636 : if (block_has_invalid_parity(block))
+ 292 238128 : if (block_has_file(block))
+ 293 235447 : one_valid = 1;
+ 294 238128 : if (block_has_invalid_parity(block))
295 0 : one_invalid = 1;
296 : }
297 :
298 : /* if both valid and invalid, we need to update */
- 299 39606 : if (one_invalid && one_valid) {
+ 299 39688 : if (one_invalid && one_valid) {
300 0 : ++unsynced_blocks;
301 : }
302 :
303 : /* skip unused blocks */
- 304 39606 : if (info != 0) {
+ 304 39688 : if (info != 0) {
305 : time_t scrub_time;
306 :
- 307 39606 : if (info_get_bad(info)) {
- 308 1802 : if (bad == 0)
+ 307 39688 : if (info_get_bad(info)) {
+ 308 1771 : if (bad == 0)
309 2 : bad_first = i;
- 310 1802 : bad_last = i;
- 311 1802 : ++bad;
+ 310 1771 : bad_last = i;
+ 311 1771 : ++bad;
312 : }
313 :
- 314 39606 : if (info_get_rehash(info))
- 315 4599 : ++rehash;
+ 314 39688 : if (info_get_rehash(info))
+ 315 4603 : ++rehash;
316 :
- 317 39606 : scrub_time = info_get_time(info);
+ 317 39688 : scrub_time = info_get_time(info);
318 :
- 319 39606 : if (info_get_justsynced(info)) {
- 320 20364 : ++unscrubbed_blocks;
+ 319 39688 : if (info_get_justsynced(info)) {
+ 320 20419 : ++unscrubbed_blocks;
321 :
322 : /* mark the time as not scrubbed */
- 323 20364 : scrub_time |= TIME_NEW;
+ 323 20419 : scrub_time |= TIME_NEW;
324 : }
325 :
- 326 39606 : timemap[count++] = scrub_time;
+ 326 39688 : timemap[count++] = scrub_time;
327 : }
328 :
- 329 39606 : if (state->opt.gui) {
+ 329 39688 : if (state->opt.gui) {
330 0 : if (info != 0)
331 0 : log_tag("block:%u:%" PRIu64 ":%s:%s:%s:%s\n", i, (uint64_t)info_get_time(info), one_valid ? "used" : "", one_invalid ? "unsynced" : "", info_get_bad(info) ? "bad" : "", info_get_rehash(info) ? "rehash" : "");
332 : else
@@ -414,16 +414,16 @@
352 : /* output the info map */
353 8 : i = 0;
354 8 : log_tag("info_count:%u\n", count);
- 355 41 : while (i < count) {
- 356 25 : unsigned j = i + 1;
- 357 39631 : while (j < count && timemap[i] == timemap[j])
- 358 39581 : ++j;
- 359 25 : if ((timemap[i] & TIME_NEW) == 0) {
- 360 9 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i);
+ 355 39 : while (i < count) {
+ 356 23 : unsigned j = i + 1;
+ 357 39711 : while (j < count && timemap[i] == timemap[j])
+ 358 39665 : ++j;
+ 359 23 : if ((timemap[i] & TIME_NEW) == 0) {
+ 360 8 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i);
361 : } else {
- 362 16 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i);
+ 362 15 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i);
363 : }
- 364 25 : i = j;
+ 364 23 : i = j;
365 : }
366 :
367 8 : oldest = timemap[0];
@@ -444,12 +444,12 @@
382 :
383 560 : step_scrubbed = 0;
384 560 : step_new = 0;
- 385 40726 : while (barpos < count && timemap[barpos] <= limit) {
- 386 39606 : if ((timemap[barpos] & TIME_NEW) != 0)
- 387 20364 : ++step_new;
+ 385 40808 : while (barpos < count && timemap[barpos] <= limit) {
+ 386 39688 : if ((timemap[barpos] & TIME_NEW) != 0)
+ 387 20419 : ++step_new;
388 : else
- 389 19242 : ++step_scrubbed;
- 390 39606 : ++barpos;
+ 389 19269 : ++step_scrubbed;
+ 390 39688 : ++barpos;
391 : }
392 :
393 560 : if (step_new + step_scrubbed > barmax)
@@ -478,20 +478,20 @@
416 8400 : unsigned scrubbed = bar_scrubbed[x];
417 :
418 8400 : if (both > pivot_upper) {
- 419 168 : if (scrubbed > pivot_lower)
- 420 74 : printf("*");
+ 419 171 : if (scrubbed > pivot_lower)
+ 420 75 : printf("*");
421 : else
- 422 94 : printf("o");
- 423 8232 : } else if (both > pivot_lower) {
- 424 25 : if (scrubbed == both)
- 425 9 : printf("*");
+ 422 96 : printf("o");
+ 423 8229 : } else if (both > pivot_lower) {
+ 424 23 : if (scrubbed == both)
+ 425 8 : printf("*");
426 : else
- 427 16 : printf("o");
+ 427 15 : printf("o");
428 : } else {
- 429 8207 : if (y == GRAPH_ROW - 1)
- 430 535 : printf("_");
+ 429 8206 : if (y == GRAPH_ROW - 1)
+ 430 537 : printf("_");
431 : else
- 432 7672 : printf(" ");
+ 432 7669 : printf(" ");
433 : }
434 : }
435 120 : printf("\n");
@@ -536,19 +536,19 @@
474 :
475 : /* print some of the errors */
476 2 : bad_print = 0;
- 477 609 : for (i = 0; i < blockmax; ++i) {
- 478 609 : snapraid_info info = info_get(&state->infoarr, i);
+ 477 709 : for (i = 0; i < blockmax; ++i) {
+ 478 709 : snapraid_info info = info_get(&state->infoarr, i);
479 :
480 : /* skip unused blocks */
- 481 609 : if (info == 0)
+ 481 709 : if (info == 0)
482 0 : continue;
483 :
- 484 609 : if (info_get_bad(info)) {
+ 484 709 : if (info_get_bad(info)) {
485 202 : printf(" %u", i);
486 202 : ++bad_print;
487 : }
488 :
- 489 609 : if (bad_print > 100) {
+ 489 709 : if (bad_print > 100) {
490 2 : printf(" and %u more...", bad - bad_print);
491 2 : break;
492 : }
diff --git a/cov/cmdline/stream.c.func-sort-c.html b/cov/cmdline/stream.c.func-sort-c.html
index 929397e4..94e5987f 100644
--- a/cov/cmdline/stream.c.func-sort-c.html
+++ b/cov/cmdline/stream.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -61,116 +61,116 @@
| swrite |
- 129597634 |
-
-
- | sputb32 |
- 62339359 |
-
-
- | sputb64 |
- 34173479 |
+ 20661703 |
| sgetb32 |
- 18710390 |
+ 18259411 |
| sread |
- 12342909 |
-
-
- | sputbs |
- 12306366 |
+ 12515245 |
| sgetb64 |
- 10465937 |
+ 10605158 |
+
+
+ | sputb32 |
+ 9119259 |
+
+
+ | sputb64 |
+ 5293948 |
| sgetbs |
- 3732790 |
+ 3782241 |
+
+
+ | sputbs |
+ 1884788 |
| sfill |
- 606496 |
+ 607118 |
| sgetc_uncached |
- 298585 |
+ 298684 |
| sflush |
- 52590 |
+ 39024 |
| sgettok |
- 7623 |
+ 7892 |
| sgetline |
- 5069 |
+ 5251 |
| sgetlasttok |
- 5035 |
+ 5217 |
| sclose |
- 2575 |
-
-
- | scrc |
- 2333 |
+ 1903 |
| sopen_read |
- 1701 |
+ 1794 |
+
+
+ | scrc |
+ 1650 |
| sdeplete |
- 1042 |
+ 1119 |
| sopen_multi_file |
- 1041 |
-
-
- | scrc_stream |
- 929 |
-
-
- | sputble32 |
- 929 |
-
-
- | sopen_multi_write |
- 928 |
-
-
- | sopen_write |
- 913 |
-
-
- | ssync |
- 912 |
+ 1118 |
| sgetble32 |
- 362 |
+ 370 |
| sgetu32 |
- 247 |
+ 255 |
| shandle |
- 235 |
+ 243 |
+
+
+ | scrc_stream |
+ 161 |
+
+
+ | sopen_multi_write |
+ 161 |
+
+
+ | sputble32 |
+ 161 |
+
+
+ | ssync |
+ 145 |
| stell |
1 |
+
+ | sopen_write |
+ 0 |
+
diff --git a/cov/cmdline/stream.c.func.html b/cov/cmdline/stream.c.func.html
index 518a0543..e0d1e567 100644
--- a/cov/cmdline/stream.c.func.html
+++ b/cov/cmdline/stream.c.func.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -61,107 +61,107 @@
| sclose |
- 2575 |
+ 1903 |
| scrc |
- 2333 |
+ 1650 |
| scrc_stream |
- 929 |
+ 161 |
| sdeplete |
- 1042 |
+ 1119 |
| sfill |
- 606496 |
+ 607118 |
| sflush |
- 52590 |
+ 39024 |
| sgetb32 |
- 18710390 |
+ 18259411 |
| sgetb64 |
- 10465937 |
+ 10605158 |
| sgetble32 |
- 362 |
+ 370 |
| sgetbs |
- 3732790 |
+ 3782241 |
| sgetc_uncached |
- 298585 |
+ 298684 |
| sgetlasttok |
- 5035 |
+ 5217 |
| sgetline |
- 5069 |
+ 5251 |
| sgettok |
- 7623 |
+ 7892 |
| sgetu32 |
- 247 |
+ 255 |
| shandle |
- 235 |
+ 243 |
| sopen_multi_file |
- 1041 |
+ 1118 |
| sopen_multi_write |
- 928 |
+ 161 |
| sopen_read |
- 1701 |
+ 1794 |
| sopen_write |
- 913 |
+ 0 |
| sputb32 |
- 62339359 |
+ 9119259 |
| sputb64 |
- 34173479 |
+ 5293948 |
| sputble32 |
- 929 |
+ 161 |
| sputbs |
- 12306366 |
+ 1884788 |
| sread |
- 12342909 |
+ 12515245 |
| ssync |
- 912 |
+ 145 |
| stell |
@@ -169,7 +169,7 @@
| swrite |
- 129597634 |
+ 20661703 |
diff --git a/cov/cmdline/stream.c.gcov.html b/cov/cmdline/stream.c.gcov.html
index 93ec3984..10fc5b3f 100644
--- a/cov/cmdline/stream.c.gcov.html
+++ b/cov/cmdline/stream.c.gcov.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
+
-
-
+
 |
@@ -88,19 +88,19 @@
26 :
27 : unsigned STREAM_SIZE = 1024 * 64;
28 :
- 29 1701 : STREAM* sopen_read(const char* file)
+ 29 1794 : STREAM* sopen_read(const char* file)
30 : {
31 : #if HAVE_POSIX_FADVISE
32 : int ret;
33 : #endif
- 34 1701 : STREAM* s = malloc_nofail(sizeof(STREAM));
+ 34 1794 : STREAM* s = malloc_nofail(sizeof(STREAM));
35 :
- 36 1701 : s->handle_size = 1;
- 37 1701 : s->handle = malloc_nofail(sizeof(struct stream_handle));
+ 36 1794 : s->handle_size = 1;
+ 37 1794 : s->handle = malloc_nofail(sizeof(struct stream_handle));
38 :
- 39 1700 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file);
- 40 1701 : s->handle[0].f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL);
- 41 1700 : if (s->handle[0].f == -1) {
+ 39 1794 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file);
+ 40 1794 : s->handle[0].f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL);
+ 41 1794 : if (s->handle[0].f == -1) {
42 50 : free(s->handle);
43 50 : free(s);
44 50 : return 0;
@@ -108,8 +108,8 @@
46 :
47 : #if HAVE_POSIX_FADVISE
48 : /* advise sequential access */
- 49 1650 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 50 1644 : if (ret != 0) {
+ 49 1744 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 50 1744 : if (ret != 0) {
51 : /* LCOV_EXCL_START */
52 : close(s->handle[0].f);
53 : free(s->handle);
@@ -119,57 +119,57 @@
57 : }
58 : #endif
59 :
- 60 1644 : s->buffer = malloc_nofail_test(STREAM_SIZE);
- 61 1650 : s->pos = s->buffer;
- 62 1650 : s->end = s->buffer;
- 63 1650 : s->state = STREAM_STATE_READ;
- 64 1650 : s->state_index = 0;
- 65 1650 : s->offset = 0;
- 66 1650 : s->offset_uncached = 0;
- 67 1650 : s->crc = 0;
- 68 1650 : s->crc_uncached = 0;
- 69 1650 : s->crc_stream = CRC_IV;
+ 60 1744 : s->buffer = malloc_nofail_test(STREAM_SIZE);
+ 61 1744 : s->pos = s->buffer;
+ 62 1744 : s->end = s->buffer;
+ 63 1744 : s->state = STREAM_STATE_READ;
+ 64 1744 : s->state_index = 0;
+ 65 1744 : s->offset = 0;
+ 66 1744 : s->offset_uncached = 0;
+ 67 1744 : s->crc = 0;
+ 68 1744 : s->crc_uncached = 0;
+ 69 1744 : s->crc_stream = CRC_IV;
70 :
- 71 1650 : return s;
+ 71 1744 : return s;
72 : }
73 :
- 74 928 : STREAM* sopen_multi_write(unsigned count)
+ 74 161 : STREAM* sopen_multi_write(unsigned count)
75 : {
76 : unsigned i;
77 :
- 78 928 : STREAM* s = malloc_nofail(sizeof(STREAM));
+ 78 161 : STREAM* s = malloc_nofail(sizeof(STREAM));
79 :
- 80 929 : s->handle_size = count;
- 81 929 : s->handle = malloc_nofail(count * sizeof(struct stream_handle));
+ 80 161 : s->handle_size = count;
+ 81 161 : s->handle = malloc_nofail(count * sizeof(struct stream_handle));
82 :
- 83 1968 : for (i = 0; i < count; ++i)
- 84 1040 : s->handle[i].f = -1;
+ 83 1279 : for (i = 0; i < count; ++i)
+ 84 1118 : s->handle[i].f = -1;
85 :
- 86 928 : s->buffer = malloc_nofail_test(STREAM_SIZE);
- 87 929 : s->pos = s->buffer;
- 88 929 : s->end = s->buffer + STREAM_SIZE;
- 89 929 : s->state = STREAM_STATE_WRITE;
- 90 929 : s->state_index = 0;
- 91 929 : s->offset = 0;
- 92 929 : s->offset_uncached = 0;
- 93 929 : s->crc = 0;
- 94 929 : s->crc_uncached = 0;
- 95 929 : s->crc_stream = CRC_IV;
+ 86 161 : s->buffer = malloc_nofail_test(STREAM_SIZE);
+ 87 161 : s->pos = s->buffer;
+ 88 161 : s->end = s->buffer + STREAM_SIZE;
+ 89 161 : s->state = STREAM_STATE_WRITE;
+ 90 161 : s->state_index = 0;
+ 91 161 : s->offset = 0;
+ 92 161 : s->offset_uncached = 0;
+ 93 161 : s->crc = 0;
+ 94 161 : s->crc_uncached = 0;
+ 95 161 : s->crc_stream = CRC_IV;
96 :
- 97 929 : return s;
+ 97 161 : return s;
98 : }
99 :
- 100 1041 : int sopen_multi_file(STREAM* s, unsigned i, const char* file)
+ 100 1118 : int sopen_multi_file(STREAM* s, unsigned i, const char* file)
101 : {
102 : #if HAVE_POSIX_FADVISE
103 : int ret;
104 : #endif
105 : int f;
106 :
- 107 1041 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file);
+ 107 1118 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file);
108 :
- 109 1041 : f = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_SEQUENTIAL, 0600);
- 110 1041 : if (f == -1) {
+ 109 1118 : f = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_SEQUENTIAL, 0600);
+ 110 1118 : if (f == -1) {
111 : /* LCOV_EXCL_START */
112 : return -1;
113 : /* LCOV_EXCL_STOP */
@@ -177,8 +177,8 @@
115 :
116 : #if HAVE_POSIX_FADVISE
117 : /* advise sequential access */
- 118 1041 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 119 1041 : if (ret != 0) {
+ 118 1118 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 119 1118 : if (ret != 0) {
120 : /* LCOV_EXCL_START */
121 : close(f);
122 : return -1;
@@ -186,167 +186,167 @@
124 : }
125 : #endif
126 :
- 127 1041 : s->handle[i].f = f;
+ 127 1118 : s->handle[i].f = f;
128 :
- 129 1041 : return 0;
+ 129 1118 : return 0;
130 : }
131 :
- 132 913 : STREAM* sopen_write(const char* file)
+ 132 0 : STREAM* sopen_write(const char* file)
133 : {
- 134 913 : STREAM* s = sopen_multi_write(1);
+ 134 0 : STREAM* s = sopen_multi_write(1);
135 :
- 136 913 : if (sopen_multi_file(s, 0, file) != 0) {
+ 136 0 : if (sopen_multi_file(s, 0, file) != 0) {
137 0 : sclose(s);
138 0 : return 0;
139 : }
140 :
- 141 913 : return s;
+ 141 0 : return s;
142 : }
143 :
- 144 2575 : int sclose(STREAM* s)
+ 144 1903 : int sclose(STREAM* s)
145 : {
- 146 2575 : int fail = 0;
+ 146 1903 : int fail = 0;
147 : unsigned i;
148 :
- 149 2575 : if (s->state == STREAM_STATE_WRITE) {
- 150 927 : if (sflush(s) != 0) {
+ 149 1903 : if (s->state == STREAM_STATE_WRITE) {
+ 150 161 : if (sflush(s) != 0) {
151 : /* LCOV_EXCL_START */
152 : fail = 1;
153 : /* LCOV_EXCL_STOP */
154 : }
155 : }
156 :
- 157 5266 : for (i = 0; i < s->handle_size; ++i) {
- 158 2688 : if (close(s->handle[i].f) != 0) {
+ 157 4763 : for (i = 0; i < s->handle_size; ++i) {
+ 158 2860 : if (close(s->handle[i].f) != 0) {
159 : /* LCOV_EXCL_START */
160 : fail = 1;
161 : /* LCOV_EXCL_STOP */
162 : }
163 : }
164 :
- 165 2578 : free(s->handle);
- 166 2578 : free(s->buffer);
- 167 2578 : free(s);
+ 165 1903 : free(s->handle);
+ 166 1903 : free(s->buffer);
+ 167 1903 : free(s);
168 :
- 169 2578 : if (fail) {
+ 169 1903 : if (fail) {
170 : /* LCOV_EXCL_START */
171 : return -1;
172 : /* LCOV_EXCL_STOP */
173 : }
174 :
- 175 2578 : return 0;
+ 175 1903 : return 0;
176 : }
177 :
- 178 235 : int shandle(STREAM* s)
+ 178 243 : int shandle(STREAM* s)
179 : {
- 180 235 : if (!s->handle_size) {
+ 180 243 : if (!s->handle_size) {
181 : /* LCOV_EXCL_START */
182 : return -1;
183 : /* LCOV_EXCL_STOP */
184 : }
185 :
- 186 235 : return s->handle[0].f;
+ 186 243 : return s->handle[0].f;
187 : }
188 :
189 : /**
190 : * Fill the read stream buffer.
191 : * \return 0 if at least on char is read, or EOF on error.
192 : */
- 193 606496 : static int sfill(STREAM* s)
+ 193 607118 : static int sfill(STREAM* s)
194 : {
195 : ssize_t ret;
196 :
- 197 606496 : if (s->state != STREAM_STATE_READ) {
+ 197 607118 : if (s->state != STREAM_STATE_READ) {
198 : /* LCOV_EXCL_START */
199 : return EOF;
200 : /* LCOV_EXCL_STOP */
201 : }
202 :
- 203 605512 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE);
+ 203 606102 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE);
204 :
- 205 605512 : if (ret < 0) {
+ 205 606102 : if (ret < 0) {
206 : /* LCOV_EXCL_START */
207 : s->state = STREAM_STATE_ERROR;
208 : return EOF;
209 : /* LCOV_EXCL_STOP */
210 : }
- 211 605512 : if (ret == 0) {
- 212 1522 : s->state = STREAM_STATE_EOF;
- 213 1522 : return EOF;
+ 211 606102 : if (ret == 0) {
+ 212 1615 : s->state = STREAM_STATE_EOF;
+ 213 1615 : return EOF;
214 : }
215 :
216 : /* update the crc */
- 217 603990 : s->crc_uncached = s->crc;
- 218 603990 : s->crc = crc32c(s->crc, s->buffer, ret);
+ 217 604487 : s->crc_uncached = s->crc;
+ 218 604487 : s->crc = crc32c(s->crc, s->buffer, ret);
219 :
220 : /* update the offset */
- 221 603990 : s->offset_uncached = s->offset;
- 222 603990 : s->offset += ret;
+ 221 604487 : s->offset_uncached = s->offset;
+ 222 604487 : s->offset += ret;
223 :
- 224 603990 : s->pos = s->buffer;
- 225 603990 : s->end = s->buffer + ret;
+ 224 604487 : s->pos = s->buffer;
+ 225 604487 : s->end = s->buffer + ret;
226 :
- 227 603990 : return 0;
+ 227 604487 : return 0;
228 : }
229 :
- 230 1042 : int sdeplete(STREAM* s, unsigned char* last)
+ 230 1119 : int sdeplete(STREAM* s, unsigned char* last)
231 : {
232 : /* last four bytes */
- 233 1042 : last[0] = 0;
- 234 1042 : last[1] = 0;
- 235 1042 : last[2] = 0;
- 236 1042 : last[3] = 0;
+ 233 1119 : last[0] = 0;
+ 234 1119 : last[1] = 0;
+ 235 1119 : last[2] = 0;
+ 236 1119 : last[3] = 0;
237 :
238 : while (1) {
239 : /* increase the position up to 4 bytes before the end */
- 240 307911 : if (s->pos + 4 <= s->end)
- 241 148134 : s->pos = s->end - 4;
+ 240 308434 : if (s->pos + 4 <= s->end)
+ 241 148580 : s->pos = s->end - 4;
242 :
243 : /* insert the last 4 bytes */
- 244 1468126 : while (s->pos < s->end) {
- 245 852304 : last[0] = last[1];
- 246 852304 : last[1] = last[2];
- 247 852304 : last[2] = last[3];
- 248 852304 : last[3] = *s->pos++;
+ 244 1470956 : while (s->pos < s->end) {
+ 245 854088 : last[0] = last[1];
+ 246 854088 : last[1] = last[2];
+ 247 854088 : last[2] = last[3];
+ 248 854088 : last[3] = *s->pos++;
249 : }
250 :
251 : /* fill again the buffer until the end of the file */
- 252 307911 : if (sfill(s) != 0) {
+ 252 308434 : if (sfill(s) != 0) {
253 : /* on error fail */
- 254 1042 : if (serror(s)) {
+ 254 1119 : if (serror(s)) {
255 : /* LCOV_EXCL_START */
256 : return EOF;
257 : /* LCOV_EXCL_STOP */
258 : }
259 :
260 : /* on EOF terminate */
- 261 1042 : break;
+ 261 1119 : break;
262 : }
- 263 306869 : }
+ 263 307315 : }
264 :
- 265 1042 : return 0;
+ 265 1119 : return 0;
266 : }
267 :
- 268 52590 : int sflush(STREAM* s)
+ 268 39024 : int sflush(STREAM* s)
269 : {
270 : ssize_t ret;
271 : ssize_t size;
272 : unsigned i;
273 :
- 274 52590 : if (s->state != STREAM_STATE_WRITE) {
+ 274 39024 : if (s->state != STREAM_STATE_WRITE) {
275 : /* LCOV_EXCL_START */
276 : return EOF;
277 : /* LCOV_EXCL_STOP */
278 : }
279 :
- 280 52590 : size = s->pos - s->buffer;
- 281 52590 : if (!size)
- 282 909 : return 0;
+ 280 39024 : size = s->pos - s->buffer;
+ 281 39024 : if (!size)
+ 282 145 : return 0;
283 :
- 284 359449 : for (i = 0; i < s->handle_size; ++i) {
- 285 307768 : ret = write(s->handle[i].f, s->buffer, size);
+ 284 347171 : for (i = 0; i < s->handle_size; ++i) {
+ 285 308292 : ret = write(s->handle[i].f, s->buffer, size);
286 :
- 287 307768 : if (ret != size) {
+ 287 308292 : if (ret != size) {
288 : /* LCOV_EXCL_START */
289 : s->state = STREAM_STATE_ERROR;
290 : s->state_index = i;
@@ -362,16 +362,16 @@
300 : * to be able to detect memory errors on the buffer,
301 : * happening during the write.
302 : */
- 303 51681 : s->crc = crc32c(s->crc, s->buffer, size);
- 304 51680 : s->crc_uncached = s->crc;
+ 303 38879 : s->crc = crc32c(s->crc, s->buffer, size);
+ 304 38879 : s->crc_uncached = s->crc;
305 :
306 : /* update the offset */
- 307 51680 : s->offset += size;
- 308 51680 : s->offset_uncached = s->offset;
+ 307 38879 : s->offset += size;
+ 308 38879 : s->offset_uncached = s->offset;
309 :
- 310 51680 : s->pos = s->buffer;
+ 310 38879 : s->pos = s->buffer;
311 :
- 312 51680 : return 0;
+ 312 38879 : return 0;
313 : }
314 :
315 1 : int64_t stell(STREAM* s)
@@ -379,100 +379,100 @@
317 1 : return s->offset_uncached + (s->pos - s->buffer);
318 : }
319 :
- 320 2333 : uint32_t scrc(STREAM*s)
+ 320 1650 : uint32_t scrc(STREAM*s)
321 : {
- 322 2333 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer);
+ 322 1650 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer);
323 : }
324 :
- 325 929 : uint32_t scrc_stream(STREAM*s)
+ 325 161 : uint32_t scrc_stream(STREAM*s)
326 : {
- 327 929 : return s->crc_stream ^ CRC_IV;
+ 327 161 : return s->crc_stream ^ CRC_IV;
328 : }
329 :
- 330 298585 : int sgetc_uncached(STREAM* s)
+ 330 298684 : int sgetc_uncached(STREAM* s)
331 : {
332 : /* if at the end of the buffer, fill it */
- 333 298585 : if (s->pos == s->end && sfill(s) != 0)
- 334 1464 : return EOF;
- 335 297121 : return *s->pos++;
+ 333 298684 : if (s->pos == s->end && sfill(s) != 0)
+ 334 1512 : return EOF;
+ 335 297172 : return *s->pos++;
336 : }
337 :
- 338 7623 : int sgettok(STREAM* f, char* str, int size)
+ 338 7892 : int sgettok(STREAM* f, char* str, int size)
339 : {
- 340 7623 : char* i = str;
- 341 7623 : char* send = str + size;
+ 340 7892 : char* i = str;
+ 341 7892 : char* send = str + size;
342 : int c;
343 :
344 : while (1) {
- 345 50866 : c = sgetc(f);
- 346 50866 : if (c == EOF) {
- 347 246 : break;
+ 345 52707 : c = sgetc(f);
+ 346 52707 : if (c == EOF) {
+ 347 254 : break;
348 : }
- 349 50620 : if (c == ' ' || c == '\t') {
- 350 7131 : sungetc(c, f);
- 351 7131 : break;
+ 349 52453 : if (c == ' ' || c == '\t') {
+ 350 7383 : sungetc(c, f);
+ 351 7383 : break;
352 : }
- 353 43489 : if (c == '\n') {
+ 353 45070 : if (c == '\n') {
354 : /* remove ending carrige return to support the Windows CR+LF format */
- 355 246 : if (i != str && i[-1] == '\r')
+ 355 255 : if (i != str && i[-1] == '\r')
356 0 : --i;
- 357 246 : sungetc(c, f);
- 358 246 : break;
+ 357 255 : sungetc(c, f);
+ 358 255 : break;
359 : }
360 :
- 361 43243 : *i++ = c;
+ 361 44815 : *i++ = c;
362 :
- 363 43243 : if (i == send) {
+ 363 44815 : if (i == send) {
364 : /* LCOV_EXCL_START */
365 : return -1;
366 : /* LCOV_EXCL_STOP */
367 : }
- 368 43243 : }
+ 368 44815 : }
369 :
- 370 7623 : *i = 0;
+ 370 7892 : *i = 0;
371 :
- 372 7623 : return i - str;
+ 372 7892 : return i - str;
373 : }
374 :
- 375 12342909 : int sread(STREAM* f, void* void_data, unsigned size)
+ 375 12515245 : int sread(STREAM* f, void* void_data, unsigned size)
376 : {
- 377 12342909 : unsigned char* data = void_data;
+ 377 12515245 : unsigned char* data = void_data;
378 :
379 : /* if there is enough space in memory */
- 380 12342909 : if (sptrlookup(f, size)) {
+ 380 12515245 : if (sptrlookup(f, size)) {
381 : /* optimized version with all the data in memory */
- 382 12316849 : unsigned char* pos = sptrget(f);
+ 382 12489054 : unsigned char* pos = sptrget(f);
383 :
384 : /* copy it */
- 385 209697747 : while (size--)
- 386 185064049 : *data++ = *pos++;
+ 385 212622570 : while (size--)
+ 386 187644462 : *data++ = *pos++;
387 :
- 388 12316849 : sptrset(f, pos);
+ 388 12489054 : sptrset(f, pos);
389 : } else {
390 : /* standard version using sgetc() */
- 391 1373859 : while (size--) {
- 392 1321739 : int c = sgetc(f);
- 393 1321739 : if (c == EOF) {
+ 391 1376682 : while (size--) {
+ 392 1324300 : int c = sgetc(f);
+ 393 1324300 : if (c == EOF) {
394 : /* LCOV_EXCL_START */
395 : return -1;
396 : /* LCOV_EXCL_STOP */
397 : }
398 :
- 399 1321739 : *data++ = c;
+ 399 1324300 : *data++ = c;
400 : }
401 : }
402 :
- 403 12342909 : return 0;
+ 403 12515245 : return 0;
404 : }
405 :
- 406 5069 : int sgetline(STREAM* f, char* str, int size)
+ 406 5251 : int sgetline(STREAM* f, char* str, int size)
407 : {
- 408 5069 : char* i = str;
- 409 5069 : char* send = str + size;
+ 408 5251 : char* i = str;
+ 409 5251 : char* send = str + size;
410 : int c;
411 :
412 : /* if there is enough data in memory */
- 413 5069 : if (sptrlookup(f, size)) {
+ 413 5251 : if (sptrlookup(f, size)) {
414 : /* optimized version with all the data in memory */
415 0 : unsigned char* pos = sptrget(f);
416 :
@@ -498,75 +498,75 @@
436 0 : sptrset(f, pos);
437 : } else {
438 : while (1) {
- 439 68948 : c = sgetc(f);
- 440 68948 : if (c == EOF) {
+ 439 71440 : c = sgetc(f);
+ 440 71440 : if (c == EOF) {
441 : /* LCOV_EXCL_START */
442 : break;
443 : /* LCOV_EXCL_STOP */
444 : }
- 445 68948 : if (c == '\n') {
+ 445 71440 : if (c == '\n') {
446 : /* remove ending carrige return to support the Windows CR+LF format */
- 447 5069 : if (i != str && i[-1] == '\r')
+ 447 5251 : if (i != str && i[-1] == '\r')
448 0 : --i;
- 449 5069 : sungetc(c, f);
- 450 5069 : break;
+ 449 5251 : sungetc(c, f);
+ 450 5251 : break;
451 : }
452 :
- 453 63879 : *i++ = c;
+ 453 66189 : *i++ = c;
454 :
- 455 63879 : if (i == send) {
+ 455 66189 : if (i == send) {
456 : /* LCOV_EXCL_START */
457 : return -1;
458 : /* LCOV_EXCL_STOP */
459 : }
- 460 63879 : }
+ 460 66189 : }
461 : }
462 :
- 463 5069 : *i = 0;
+ 463 5251 : *i = 0;
464 :
- 465 5069 : return i - str;
+ 465 5251 : return i - str;
466 : }
467 :
- 468 5035 : int sgetlasttok(STREAM* f, char* str, int size)
+ 468 5217 : int sgetlasttok(STREAM* f, char* str, int size)
469 : {
470 : int ret;
471 :
- 472 5035 : ret = sgetline(f, str, size);
- 473 5035 : if (ret < 0) {
+ 472 5217 : ret = sgetline(f, str, size);
+ 473 5217 : if (ret < 0) {
474 : /* LCOV_EXCL_START */
475 : return ret;
476 : /* LCOV_EXCL_STOP */
477 : }
478 :
- 479 10070 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t'))
+ 479 10434 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t'))
480 0 : --ret;
481 :
- 482 5035 : str[ret] = 0;
+ 482 5217 : str[ret] = 0;
483 :
- 484 5035 : return ret;
+ 484 5217 : return ret;
485 : }
486 :
- 487 247 : int sgetu32(STREAM* f, uint32_t* value)
+ 487 255 : int sgetu32(STREAM* f, uint32_t* value)
488 : {
489 : int c;
490 :
- 491 247 : c = sgetc(f);
- 492 247 : if (c >= '0' && c <= '9') {
+ 491 255 : c = sgetc(f);
+ 492 255 : if (c >= '0' && c <= '9') {
493 : uint32_t v;
494 :
- 495 247 : v = c - '0';
+ 495 255 : v = c - '0';
496 :
- 497 247 : c = sgetc(f);
- 498 494 : while (c >= '0' && c <= '9') {
+ 497 255 : c = sgetc(f);
+ 498 510 : while (c >= '0' && c <= '9') {
499 0 : v *= 10;
500 0 : v += c - '0';
501 0 : c = sgetc(f);
502 : }
503 :
- 504 247 : *value = v;
+ 504 255 : *value = v;
505 :
- 506 247 : sungetc(c, f);
- 507 247 : return 0;
+ 506 255 : sungetc(c, f);
+ 507 255 : return 0;
508 : } else {
509 : /* LCOV_EXCL_START */
510 : /* nothing read */
@@ -575,122 +575,122 @@
513 : }
514 : }
515 :
- 516 18710390 : int sgetb32(STREAM* f, uint32_t* value)
+ 516 18259411 : int sgetb32(STREAM* f, uint32_t* value)
517 : {
518 : uint32_t v;
519 : unsigned char b;
520 : unsigned char s;
521 : int c;
522 :
- 523 18710390 : v = 0;
- 524 18710390 : s = 0;
+ 523 18259411 : v = 0;
+ 524 18259411 : s = 0;
525 : loop:
- 526 35314985 : c = sgetc(f);
- 527 35314985 : if (c == EOF) {
+ 526 35244347 : c = sgetc(f);
+ 527 35244347 : if (c == EOF) {
528 : /* LCOV_EXCL_START */
529 : return -1;
530 : /* LCOV_EXCL_STOP */
531 : }
532 :
- 533 35314985 : b = (unsigned char)c;
- 534 35314985 : if ((b & 0x80) == 0) {
- 535 16604595 : v |= (uint32_t)b << s;
- 536 16604595 : s += 7;
- 537 16604595 : if (s >= 32) {
+ 533 35244347 : b = (unsigned char)c;
+ 534 35244347 : if ((b & 0x80) == 0) {
+ 535 16984936 : v |= (uint32_t)b << s;
+ 536 16984936 : s += 7;
+ 537 16984936 : if (s >= 32) {
538 : /* LCOV_EXCL_START */
539 : return -1;
540 : /* LCOV_EXCL_STOP */
541 : }
- 542 16604595 : goto loop;
+ 542 16984936 : goto loop;
543 : }
544 :
- 545 18710390 : v |= (uint32_t)(b & 0x7f) << s;
+ 545 18259411 : v |= (uint32_t)(b & 0x7f) << s;
546 :
- 547 18710390 : *value = v;
+ 547 18259411 : *value = v;
548 :
- 549 18710390 : return 0;
+ 549 18259411 : return 0;
550 : }
551 :
- 552 10465937 : int sgetb64(STREAM* f, uint64_t* value)
+ 552 10605158 : int sgetb64(STREAM* f, uint64_t* value)
553 : {
554 : uint64_t v;
555 : unsigned char b;
556 : unsigned char s;
557 : int c;
558 :
- 559 10465937 : v = 0;
- 560 10465937 : s = 0;
+ 559 10605158 : v = 0;
+ 560 10605158 : s = 0;
561 : loop:
- 562 38271575 : c = sgetc(f);
- 563 38271575 : if (c == EOF) {
+ 562 38780587 : c = sgetc(f);
+ 563 38780587 : if (c == EOF) {
564 : /* LCOV_EXCL_START */
565 : return -1;
566 : /* LCOV_EXCL_STOP */
567 : }
568 :
- 569 38271575 : b = (unsigned char)c;
- 570 38271575 : if ((b & 0x80) == 0) {
- 571 27805638 : v |= (uint64_t)b << s;
- 572 27805638 : s += 7;
- 573 27805638 : if (s >= 64) {
+ 569 38780587 : b = (unsigned char)c;
+ 570 38780587 : if ((b & 0x80) == 0) {
+ 571 28175429 : v |= (uint64_t)b << s;
+ 572 28175429 : s += 7;
+ 573 28175429 : if (s >= 64) {
574 : /* LCOV_EXCL_START */
575 : return -1;
576 : /* LCOV_EXCL_STOP */
577 : }
- 578 27805638 : goto loop;
+ 578 28175429 : goto loop;
579 : }
580 :
- 581 10465937 : v |= (uint64_t)(b & 0x7f) << s;
+ 581 10605158 : v |= (uint64_t)(b & 0x7f) << s;
582 :
- 583 10465937 : *value = v;
+ 583 10605158 : *value = v;
584 :
- 585 10465937 : return 0;
+ 585 10605158 : return 0;
586 : }
587 :
- 588 362 : int sgetble32(STREAM* f, uint32_t* value)
+ 588 370 : int sgetble32(STREAM* f, uint32_t* value)
589 : {
590 : unsigned char buf[4];
591 :
- 592 362 : if (sread(f, buf, 4) != 0) {
+ 592 370 : if (sread(f, buf, 4) != 0) {
593 : /* LCOV_EXCL_START */
594 : return -1;
595 : /* LCOV_EXCL_STOP */
596 : }
597 :
- 598 362 : *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
+ 598 370 : *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
599 :
- 600 362 : return 0;
+ 600 370 : return 0;
601 : }
602 :
- 603 3732790 : int sgetbs(STREAM* f, char* str, int size)
+ 603 3782241 : int sgetbs(STREAM* f, char* str, int size)
604 : {
605 : uint32_t len;
606 :
- 607 3732790 : if (sgetb32(f, &len) < 0) {
+ 607 3782241 : if (sgetb32(f, &len) < 0) {
608 : /* LCOV_EXCL_START */
609 : return -1;
610 : /* LCOV_EXCL_STOP */
611 : }
612 :
- 613 3732790 : if (len + 1 > (uint32_t)size) {
+ 613 3782241 : if (len + 1 > (uint32_t)size) {
614 : /* LCOV_EXCL_START */
615 : return -1;
616 : /* LCOV_EXCL_STOP */
617 : }
618 :
- 619 3732790 : str[len] = 0;
+ 619 3782240 : str[len] = 0;
620 :
- 621 3732790 : return sread(f, str, (int)len);
+ 621 3782240 : return sread(f, str, (int)len);
622 : }
623 :
- 624 129597634 : int swrite(const void* void_data, unsigned size, STREAM* f)
+ 624 20661703 : int swrite(const void* void_data, unsigned size, STREAM* f)
625 : {
- 626 129597634 : const unsigned char* data = void_data;
+ 626 20661703 : const unsigned char* data = void_data;
627 :
628 : /* if there is enough space in memory */
- 629 129597634 : if (sptrlookup(f, size)) {
+ 629 20661703 : if (sptrlookup(f, size)) {
630 : /* optimized version with all the data in memory */
- 631 128366511 : unsigned char* pos = sptrget(f);
+ 631 20655549 : unsigned char* pos = sptrget(f);
632 :
633 : /**
634 : * Update the crc *before* writing the data in the buffer
@@ -699,17 +699,17 @@
637 : * to be able to detect memory errors on the buffer,
638 : * happening before we write it on the file.
639 : */
- 640 127220529 : f->crc_stream = crc32c_plain(f->crc_stream, data, size);
+ 640 20655549 : f->crc_stream = crc32c_plain(f->crc_stream, data, size);
641 :
642 : /* copy it */
- 643 984312399 : while (size--)
- 644 729779043 : *pos++ = *data++;
+ 643 172057609 : while (size--)
+ 644 130746511 : *pos++ = *data++;
645 :
- 646 127266678 : sptrset(f, pos);
+ 646 20655549 : sptrset(f, pos);
647 : } else {
648 : /* standard version using sputc() */
- 649 352837 : while (size--) {
- 650 318158 : if (sputc(*data++, f) != 0) {
+ 649 201458 : while (size--) {
+ 650 189150 : if (sputc(*data++, f) != 0) {
651 : /* LCOV_EXCL_START */
652 : return -1;
653 : /* LCOV_EXCL_STOP */
@@ -717,83 +717,83 @@
655 : }
656 : }
657 :
- 658 129224881 : return 0;
+ 658 20661703 : return 0;
659 : }
660 :
- 661 62339359 : int sputb32(uint32_t value, STREAM* s)
+ 661 9119259 : int sputb32(uint32_t value, STREAM* s)
662 : {
663 : unsigned char b;
664 : unsigned char buf[16];
665 : unsigned i;
666 :
- 667 62339359 : i = 0;
+ 667 9119259 : i = 0;
668 : loop:
- 669 117525500 : b = value & 0x7f;
- 670 117525500 : value >>= 7;
+ 669 17637493 : b = value & 0x7f;
+ 670 17637493 : value >>= 7;
671 :
- 672 117525500 : if (value) {
- 673 55186141 : buf[i++] = b;
- 674 55186141 : goto loop;
+ 672 17637493 : if (value) {
+ 673 8518234 : buf[i++] = b;
+ 674 8518234 : goto loop;
675 : }
676 :
- 677 62339359 : buf[i++] = b | 0x80;
+ 677 9119259 : buf[i++] = b | 0x80;
678 :
- 679 62339359 : return swrite(buf, i, s);
+ 679 9119259 : return swrite(buf, i, s);
680 : }
681 :
- 682 34173479 : int sputb64(uint64_t value, STREAM* s)
+ 682 5293948 : int sputb64(uint64_t value, STREAM* s)
683 : {
684 : unsigned char b;
685 : unsigned char buf[16];
686 : unsigned i;
687 :
- 688 34173479 : i = 0;
+ 688 5293948 : i = 0;
689 : loop:
- 690 124705929 : b = value & 0x7f;
- 691 124705929 : value >>= 7;
+ 690 19354594 : b = value & 0x7f;
+ 691 19354594 : value >>= 7;
692 :
- 693 124705929 : if (value) {
- 694 90532450 : buf[i++] = b;
- 695 90532450 : goto loop;
+ 693 19354594 : if (value) {
+ 694 14060646 : buf[i++] = b;
+ 695 14060646 : goto loop;
696 : }
697 :
- 698 34173479 : buf[i++] = b | 0x80;
+ 698 5293948 : buf[i++] = b | 0x80;
699 :
- 700 34173479 : return swrite(buf, i, s);
+ 700 5293948 : return swrite(buf, i, s);
701 : }
702 :
- 703 929 : int sputble32(uint32_t value, STREAM* s)
+ 703 161 : int sputble32(uint32_t value, STREAM* s)
704 : {
705 : unsigned char buf[4];
706 :
- 707 929 : buf[0] = value & 0xFF;
- 708 929 : buf[1] = (value >> 8) & 0xFF;
- 709 929 : buf[2] = (value >> 16) & 0xFF;
- 710 929 : buf[3] = (value >> 24) & 0xFF;
+ 707 161 : buf[0] = value & 0xFF;
+ 708 161 : buf[1] = (value >> 8) & 0xFF;
+ 709 161 : buf[2] = (value >> 16) & 0xFF;
+ 710 161 : buf[3] = (value >> 24) & 0xFF;
711 :
- 712 929 : return swrite(buf, 4, s);
+ 712 161 : return swrite(buf, 4, s);
713 : }
714 :
- 715 12306366 : int sputbs(const char* str, STREAM* f)
+ 715 1884788 : int sputbs(const char* str, STREAM* f)
716 : {
- 717 12306366 : size_t len = strlen(str);
+ 717 1884788 : size_t len = strlen(str);
718 :
- 719 12306366 : if (sputb32(len, f) != 0) {
+ 719 1884788 : if (sputb32(len, f) != 0) {
720 : /* LCOV_EXCL_START */
721 : return -1;
722 : /* LCOV_EXCL_STOP */
723 : }
724 :
- 725 12287997 : return swrite(str, len, f);
+ 725 1884788 : return swrite(str, len, f);
726 : }
727 :
728 : #if HAVE_FSYNC
- 729 912 : int ssync(STREAM* s)
+ 729 145 : int ssync(STREAM* s)
730 : {
731 : unsigned i;
732 :
- 733 1824 : for (i = 0; i < s->handle_size; ++i) {
- 734 913 : if (fsync(s->handle[i].f) != 0) {
+ 733 1135 : for (i = 0; i < s->handle_size; ++i) {
+ 734 990 : if (fsync(s->handle[i].f) != 0) {
735 : /* LCOV_EXCL_START */
736 : s->state = STREAM_STATE_ERROR;
737 : s->state_index = i;
@@ -802,7 +802,7 @@
740 : }
741 : }
742 :
- 743 911 : return 0;
+ 743 145 : return 0;
744 : }
745 : #endif
746 :
diff --git a/cov/cmdline/stream.h.func-sort-c.html b/cov/cmdline/stream.h.func-sort-c.html
index 6fd4d017..3d5cc907 100644
--- a/cov/cmdline/stream.h.func-sort-c.html
+++ b/cov/cmdline/stream.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,40 +60,40 @@
Hit count  |
- | sptrlookup |
- 140471390 |
+ sgetc |
+ 82747474 |
- | sptrget |
- 140020205 |
+ sptrlookup |
+ 33182199 |
| sptrset |
- 138951723 |
+ 33144603 |
- | sgetc |
- 82206359 |
-
-
- | serror |
- 24784868 |
+ sptrget |
+ 33144603 |
| sputc |
- 23611223 |
+ 3794625 |
+
+
+ | serror |
+ 3632818 |
| sungetc |
- 32166 |
+ 33308 |
| sgetspace |
- 19238 |
+ 19921 |
| sgeteol |
- 5807 |
+ 6014 |
| seof |
diff --git a/cov/cmdline/stream.h.func.html b/cov/cmdline/stream.h.func.html
index 50565355..b6043b90 100644
--- a/cov/cmdline/stream.h.func.html
+++ b/cov/cmdline/stream.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,7 +65,7 @@
| serror |
- 24784868 |
+ 3632818 |
| serrorfile |
@@ -73,35 +73,35 @@
| sgetc |
- 82206359 |
+ 82747474 |
| sgeteol |
- 5807 |
+ 6014 |
| sgetspace |
- 19238 |
+ 19921 |
| sptrget |
- 140020205 |
+ 33144603 |
| sptrlookup |
- 140471390 |
+ 33182199 |
| sptrset |
- 138951723 |
+ 33144603 |
| sputc |
- 23611223 |
+ 3794625 |
| sungetc |
- 32166 |
+ 33308 |
diff --git a/cov/cmdline/stream.h.gcov.html b/cov/cmdline/stream.h.gcov.html
index 04b9f268..cf65bf9c 100644
--- a/cov/cmdline/stream.h.gcov.html
+++ b/cov/cmdline/stream.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,8 +94,8 @@
32 :
33 : #define STREAM_STATE_READ 0 /**< The stream is in a normal state of read. */
34 : #define STREAM_STATE_WRITE 1 /**< The stream is in a normal state of write. */
- 35 : #define STREAM_STATE_ERROR -1 /**< An error was encoutered. */
- 36 : #define STREAM_STATE_EOF 2 /**< The end of file was encoutered. */
+ 35 : #define STREAM_STATE_ERROR -1 /**< An error was encountered. */
+ 36 : #define STREAM_STATE_EOF 2 /**< The end of file was encountered. */
37 :
38 : struct stream_handle {
39 : int f; /**< Handle of the file. */
@@ -221,33 +221,33 @@
159 : /**
160 : * Check if the buffer has enough data loaded.
161 : */
- 162 140471390 : static inline int sptrlookup(STREAM* s, int size)
+ 162 33182199 : static inline int sptrlookup(STREAM* s, int size)
163 : {
- 164 140471390 : return s->pos + size <= s->end;
+ 164 33182199 : return s->pos + size <= s->end;
165 : }
166 :
167 : /**
168 : * Get the current stream ptr.
169 : */
- 170 140020205 : static inline unsigned char* sptrget(STREAM* s)
+ 170 33144603 : static inline unsigned char* sptrget(STREAM* s)
171 : {
- 172 140020205 : return s->pos;
+ 172 33144603 : return s->pos;
173 : }
174 :
175 : /**
176 : * Set the current stream ptr.
177 : */
- 178 138951723 : static inline void sptrset(STREAM* s, unsigned char* ptr)
+ 178 33144603 : static inline void sptrset(STREAM* s, unsigned char* ptr)
179 : {
- 180 138951723 : s->pos = ptr;
- 181 138951723 : }
+ 180 33144603 : s->pos = ptr;
+ 181 33144603 : }
182 :
183 : /**
184 : * Check the error status. Like ferror().
185 : */
- 186 24784868 : static inline int serror(STREAM* s)
+ 186 3632818 : static inline int serror(STREAM* s)
187 : {
- 188 24784868 : return s->state == STREAM_STATE_ERROR;
+ 188 3632818 : return s->state == STREAM_STATE_ERROR;
189 : }
190 :
191 : /**
@@ -291,22 +291,22 @@
229 : /**
230 : * Read a char. Like fgetc().
231 : */
- 232 82206359 : static inline int sgetc(STREAM* s)
+ 232 82747474 : static inline int sgetc(STREAM* s)
233 : {
- 234 82206359 : if (tommy_unlikely(s->pos == s->end))
- 235 298585 : return sgetc_uncached(s);
- 236 81907774 : return *s->pos++;
+ 234 82747474 : if (tommy_unlikely(s->pos == s->end))
+ 235 298684 : return sgetc_uncached(s);
+ 236 82448790 : return *s->pos++;
237 : }
238 :
239 : /**
240 : * Unread a char.
241 : * Like ungetc() but you have to unget the same char read.
242 : */
- 243 32166 : static inline void sungetc(int c, STREAM* s)
+ 243 33308 : static inline void sungetc(int c, STREAM* s)
244 : {
- 245 32166 : if (c != EOF)
- 246 31428 : --s->pos;
- 247 32166 : }
+ 245 33308 : if (c != EOF)
+ 246 32546 : --s->pos;
+ 247 33308 : }
248 :
249 : /**
250 : * Read a fixed amount of chars.
@@ -317,34 +317,34 @@
255 : /**
256 : * Get a char from a stream, ignoring one '\r'.
257 : */
- 258 5807 : static inline int sgeteol(STREAM* f)
+ 258 6014 : static inline int sgeteol(STREAM* f)
259 : {
260 : int c;
261 :
- 262 5807 : c = sgetc(f);
- 263 5807 : if (c == '\r')
+ 262 6014 : c = sgetc(f);
+ 263 6014 : if (c == '\r')
264 0 : c = sgetc(f);
265 :
- 266 5807 : return c;
+ 266 6014 : return c;
267 : }
268 :
269 : /**
270 : * Read all the spaces and tabs.
271 : * Return the number of spaces and tabs read.
272 : */
- 273 19238 : static inline int sgetspace(STREAM* f)
+ 273 19921 : static inline int sgetspace(STREAM* f)
274 : {
- 275 19238 : int count = 0;
+ 275 19921 : int count = 0;
276 : int c;
277 :
- 278 19238 : c = sgetc(f);
- 279 45607 : while (c == ' ' || c == '\t') {
- 280 7131 : ++count;
- 281 7131 : c = sgetc(f);
+ 278 19921 : c = sgetc(f);
+ 279 47225 : while (c == ' ' || c == '\t') {
+ 280 7383 : ++count;
+ 281 7383 : c = sgetc(f);
282 : }
283 :
- 284 19238 : sungetc(c, f);
- 285 19238 : return count;
+ 284 19921 : sungetc(c, f);
+ 285 19921 : return count;
286 : }
287 :
288 : /**
@@ -407,10 +407,10 @@
345 : * Write a char. Like fputc().
346 : * Return 0 on success or -1 on error.
347 : */
- 348 23611223 : static inline int sputc(int c, STREAM* s)
+ 348 3794625 : static inline int sputc(int c, STREAM* s)
349 : {
- 350 23611223 : if (s->pos == s->end) {
- 351 49838 : if (sflush(s) != 0)
+ 350 3794625 : if (s->pos == s->end) {
+ 351 38573 : if (sflush(s) != 0)
352 0 : return -1;
353 : }
354 :
@@ -421,11 +421,11 @@
359 : * to be able to detect memory errors on the buffer,
360 : * happening before we write it on the file.
361 : */
- 362 23611224 : s->crc_stream = crc32c_plain_char(s->crc_stream, c);
+ 362 3794625 : s->crc_stream = crc32c_plain_char(s->crc_stream, c);
363 :
- 364 23809904 : *s->pos++ = c;
+ 364 3794625 : *s->pos++ = c;
365 :
- 366 23809904 : return 0;
+ 366 3794625 : return 0;
367 : }
368 :
369 : /**
diff --git a/cov/cmdline/support.c.func-sort-c.html b/cov/cmdline/support.c.func-sort-c.html
index e77ef92a..468d779e 100644
--- a/cov/cmdline/support.c.func-sort-c.html
+++ b/cov/cmdline/support.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -60,88 +60,92 @@
Hit count  |
- | pathcmp |
- 50336221 |
+ pathcmp |
+ 51328958 |
| pathprint |
- 50030363 |
+ 50908928 |
- | malloc_nofail |
- 13871886 |
+ malloc_counter_inc |
+ 19792624 |
+
+
+ | malloc_nofail |
+ 14067108 |
| pathcpy |
- 6858601 |
+ 6956056 |
- | strdup_nofail |
- 5663011 |
+ strdup_nofail |
+ 5715940 |
| log_tag |
- 4041705 |
+ 4058806 |
| esc |
- 3592843 |
+ 3612178 |
- | mkancestor |
- 792978 |
+ mkancestor |
+ 793073 |
| log_error |
- 614592 |
+ 615188 |
| msg_info |
- 295863 |
+ 295974 |
| msg_verbose |
- 126936 |
+ 127002 |
- | fmtime |
- 117937 |
+ fmtime |
+ 119629 |
| pathexport |
- 17569 |
+ 17583 |
| log_expected |
- 11751 |
+ 11440 |
- | calloc_nofail |
- 9283 |
+ calloc_nofail |
+ 9576 |
| pathimport |
- 8852 |
+ 9180 |
- | pathslash |
- 7319 |
+ pathslash |
+ 7469 |
| msg_progress |
- 3911 |
+ 4145 |
| log_flush |
- 1108 |
+ 1148 |
| msg_bar |
- 952 |
+ 945 |
| log_fatal |
- 804 |
+ 822 |
| pathcatc |
@@ -149,30 +153,30 @@
| msg_status |
- 569 |
+ 577 |
- | malloc_counter |
- 444 |
+ malloc_counter_get |
+ 460 |
| msg_flush |
- 440 |
+ 442 |
| pathcat |
- 248 |
+ 256 |
- | pathcut |
+ pathcut |
30 |
- | smartctl_attribute |
+ smartctl_attribute |
25 |
- | smartctl_flush |
+ smartctl_flush |
12 |
@@ -180,7 +184,7 @@
| 0 |
- | smatch |
+ smatch |
0 |
diff --git a/cov/cmdline/support.c.func.html b/cov/cmdline/support.c.func.html
index 65c60503..9872d2eb 100644
--- a/cov/cmdline/support.c.func.html
+++ b/cov/cmdline/support.c.func.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -60,128 +60,132 @@
Hit count  |
- | calloc_nofail |
- 9283 |
+ calloc_nofail |
+ 9576 |
| esc |
- 3592843 |
+ 3612178 |
- | fmtime |
- 117937 |
+ fmtime |
+ 119629 |
| log_error |
- 614592 |
+ 615188 |
| log_expected |
- 11751 |
+ 11440 |
| log_fatal |
- 804 |
+ 822 |
| log_flush |
- 1108 |
+ 1148 |
| log_tag |
- 4041705 |
+ 4058806 |
- | malloc_counter |
- 444 |
+ malloc_counter_get |
+ 460 |
- | malloc_nofail |
- 13871886 |
+ malloc_counter_inc |
+ 19792624 |
- | mkancestor |
- 792978 |
+ malloc_nofail |
+ 14067108 |
+
+
+ | mkancestor |
+ 793073 |
| msg_bar |
- 952 |
+ 945 |
| msg_flush |
- 440 |
+ 442 |
| msg_info |
- 295863 |
+ 295974 |
| msg_progress |
- 3911 |
+ 4145 |
| msg_status |
- 569 |
+ 577 |
| msg_verbose |
- 126936 |
+ 127002 |
| pathcat |
- 248 |
+ 256 |
| pathcatc |
788 |
- | pathcmp |
- 50336221 |
+ pathcmp |
+ 51328958 |
| pathcpy |
- 6858601 |
+ 6956056 |
- | pathcut |
+ pathcut |
30 |
| pathexport |
- 17569 |
+ 17583 |
| pathimport |
- 8852 |
+ 9180 |
| pathprint |
- 50030363 |
+ 50908928 |
- | pathslash |
- 7319 |
+ pathslash |
+ 7469 |
| polish |
0 |
- | smartctl_attribute |
+ smartctl_attribute |
25 |
- | smartctl_flush |
+ smartctl_flush |
12 |
- | smatch |
+ smatch |
0 |
- | strdup_nofail |
- 5663011 |
+ strdup_nofail |
+ 5715940 |
diff --git a/cov/cmdline/support.c.gcov.html b/cov/cmdline/support.c.gcov.html
index 07fccc29..265ef117 100644
--- a/cov/cmdline/support.c.gcov.html
+++ b/cov/cmdline/support.c.gcov.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -116,13 +116,13 @@
54 : * caller should use log_flush().
55 : */
56 :
- 57 804 : void log_fatal(const char* format, ...)
+ 57 822 : void log_fatal(const char* format, ...)
58 : {
59 : va_list ap;
60 :
- 61 804 : pthread_mutex_lock(&msg_lock);
+ 61 822 : pthread_mutex_lock(&msg_lock);
62 :
- 63 804 : if (stdlog) {
+ 63 822 : if (stdlog) {
64 103 : va_start(ap, format);
65 103 : fprintf(stdlog, "msg:fatal: ");
66 103 : vfprintf(stdlog, format, ap);
@@ -130,89 +130,89 @@
68 103 : va_end(ap);
69 : }
70 :
- 71 804 : va_start(ap, format);
- 72 804 : vfprintf(stderr, format, ap);
- 73 804 : fflush(stderr);
- 74 804 : va_end(ap);
+ 71 822 : va_start(ap, format);
+ 72 822 : vfprintf(stderr, format, ap);
+ 73 822 : fflush(stderr);
+ 74 822 : va_end(ap);
75 :
- 76 804 : pthread_mutex_unlock(&msg_lock);
- 77 804 : }
+ 76 822 : pthread_mutex_unlock(&msg_lock);
+ 77 822 : }
78 :
- 79 614592 : void log_error(const char* format, ...)
+ 79 615188 : void log_error(const char* format, ...)
80 : {
81 : va_list ap;
82 :
- 83 614592 : pthread_mutex_lock(&msg_lock);
+ 83 615188 : pthread_mutex_lock(&msg_lock);
84 :
- 85 614592 : if (stdlog) {
- 86 612682 : va_start(ap, format);
- 87 612682 : fprintf(stdlog, "msg:error: ");
- 88 612682 : vfprintf(stdlog, format, ap);
- 89 612682 : fflush(stdlog);
- 90 612682 : va_end(ap);
+ 85 615188 : if (stdlog) {
+ 86 613309 : va_start(ap, format);
+ 87 613309 : fprintf(stdlog, "msg:error: ");
+ 88 613309 : vfprintf(stdlog, format, ap);
+ 89 613309 : fflush(stdlog);
+ 90 613309 : va_end(ap);
91 : } else {
- 92 1910 : va_start(ap, format);
- 93 1910 : vfprintf(stderr, format, ap);
- 94 1910 : fflush(stderr);
- 95 1910 : va_end(ap);
+ 92 1879 : va_start(ap, format);
+ 93 1879 : vfprintf(stderr, format, ap);
+ 94 1879 : fflush(stderr);
+ 95 1879 : va_end(ap);
96 : }
97 :
- 98 614592 : pthread_mutex_unlock(&msg_lock);
- 99 614592 : }
+ 98 615188 : pthread_mutex_unlock(&msg_lock);
+ 99 615188 : }
100 :
- 101 11751 : void log_expected(const char* format, ...)
+ 101 11440 : void log_expected(const char* format, ...)
102 : {
103 : va_list ap;
104 :
- 105 11751 : pthread_mutex_lock(&msg_lock);
+ 105 11440 : pthread_mutex_lock(&msg_lock);
106 :
- 107 11751 : if (stdlog) {
- 108 11751 : va_start(ap, format);
- 109 11751 : fprintf(stdlog, "msg:expected: ");
- 110 11751 : vfprintf(stdlog, format, ap);
- 111 11751 : fflush(stdlog);
- 112 11751 : va_end(ap);
+ 107 11440 : if (stdlog) {
+ 108 11440 : va_start(ap, format);
+ 109 11440 : fprintf(stdlog, "msg:expected: ");
+ 110 11440 : vfprintf(stdlog, format, ap);
+ 111 11440 : fflush(stdlog);
+ 112 11440 : va_end(ap);
113 : }
114 :
- 115 11751 : pthread_mutex_unlock(&msg_lock);
- 116 11751 : }
+ 115 11440 : pthread_mutex_unlock(&msg_lock);
+ 116 11440 : }
117 :
- 118 4041705 : void log_tag(const char* format, ...)
+ 118 4058806 : void log_tag(const char* format, ...)
119 : {
120 : va_list ap;
121 :
- 122 4041705 : pthread_mutex_lock(&msg_lock);
+ 122 4058806 : pthread_mutex_lock(&msg_lock);
123 :
- 124 4041705 : if (stdlog) {
- 125 2962677 : va_start(ap, format);
- 126 2962677 : vfprintf(stdlog, format, ap);
+ 124 4058806 : if (stdlog) {
+ 125 2977413 : va_start(ap, format);
+ 126 2977413 : vfprintf(stdlog, format, ap);
127 : /* here we intentionally don't flush */
128 : /* to make the output faster */
- 129 2962677 : va_end(ap);
+ 129 2977413 : va_end(ap);
130 : }
131 :
- 132 4041705 : pthread_mutex_unlock(&msg_lock);
- 133 4041705 : }
+ 132 4058806 : pthread_mutex_unlock(&msg_lock);
+ 133 4058806 : }
134 :
- 135 1108 : void log_flush(void)
+ 135 1148 : void log_flush(void)
136 : {
- 137 1108 : pthread_mutex_lock(&msg_lock);
+ 137 1148 : pthread_mutex_lock(&msg_lock);
138 :
- 139 1108 : if (stdlog)
+ 139 1148 : if (stdlog)
140 326 : fflush(stdlog);
- 141 1108 : fflush(stdout);
- 142 1108 : fflush(stderr);
+ 141 1148 : fflush(stdout);
+ 142 1148 : fflush(stderr);
143 :
- 144 1108 : pthread_mutex_unlock(&msg_lock);
- 145 1108 : }
+ 144 1148 : pthread_mutex_unlock(&msg_lock);
+ 145 1148 : }
146 :
- 147 569 : void msg_status(const char* format, ...)
+ 147 577 : void msg_status(const char* format, ...)
148 : {
149 : va_list ap;
150 :
- 151 569 : pthread_mutex_lock(&msg_lock);
+ 151 577 : pthread_mutex_lock(&msg_lock);
152 :
- 153 569 : if (stdlog) {
+ 153 577 : if (stdlog) {
154 276 : va_start(ap, format);
155 276 : fprintf(stdlog, "msg:status: ");
156 276 : vfprintf(stdlog, format, ap);
@@ -220,42 +220,42 @@
158 276 : va_end(ap);
159 : }
160 :
- 161 569 : if (msg_level >= MSG_STATUS) {
- 162 569 : va_start(ap, format);
- 163 569 : vfprintf(stdout, format, ap);
- 164 569 : fflush(stdout);
- 165 569 : va_end(ap);
+ 161 577 : if (msg_level >= MSG_STATUS) {
+ 162 577 : va_start(ap, format);
+ 163 577 : vfprintf(stdout, format, ap);
+ 164 577 : fflush(stdout);
+ 165 577 : va_end(ap);
166 : }
167 :
- 168 569 : pthread_mutex_unlock(&msg_lock);
- 169 569 : }
+ 168 577 : pthread_mutex_unlock(&msg_lock);
+ 169 577 : }
170 :
- 171 295863 : void msg_info(const char* format, ...)
+ 171 295974 : void msg_info(const char* format, ...)
172 : {
173 : va_list ap;
174 :
- 175 295863 : pthread_mutex_lock(&msg_lock);
+ 175 295974 : pthread_mutex_lock(&msg_lock);
176 :
177 : /* don't output in stdlog as these messages */
178 : /* are always paired with a msg_tag() call */
179 :
- 180 295863 : if (msg_level >= MSG_INFO) {
- 181 28776 : va_start(ap, format);
- 182 28776 : vfprintf(stdout, format, ap);
- 183 28776 : fflush(stdout);
- 184 28776 : va_end(ap);
+ 180 295974 : if (msg_level >= MSG_INFO) {
+ 181 28827 : va_start(ap, format);
+ 182 28827 : vfprintf(stdout, format, ap);
+ 183 28827 : fflush(stdout);
+ 184 28827 : va_end(ap);
185 : }
186 :
- 187 295863 : pthread_mutex_unlock(&msg_lock);
- 188 295863 : }
+ 187 295974 : pthread_mutex_unlock(&msg_lock);
+ 188 295974 : }
189 :
- 190 3911 : void msg_progress(const char* format, ...)
+ 190 4145 : void msg_progress(const char* format, ...)
191 : {
192 : va_list ap;
193 :
- 194 3911 : pthread_mutex_lock(&msg_lock);
+ 194 4145 : pthread_mutex_lock(&msg_lock);
195 :
- 196 3911 : if (stdlog) {
+ 196 4145 : if (stdlog) {
197 775 : va_start(ap, format);
198 775 : fprintf(stdlog, "msg:progress: ");
199 775 : vfprintf(stdlog, format, ap);
@@ -263,68 +263,68 @@
201 775 : va_end(ap);
202 : }
203 :
- 204 3911 : if (msg_level >= MSG_PROGRESS) {
+ 204 4145 : if (msg_level >= MSG_PROGRESS) {
205 153 : va_start(ap, format);
206 153 : vfprintf(stdout, format, ap);
207 153 : fflush(stdout);
208 153 : va_end(ap);
209 : }
210 :
- 211 3911 : pthread_mutex_unlock(&msg_lock);
- 212 3911 : }
+ 211 4145 : pthread_mutex_unlock(&msg_lock);
+ 212 4145 : }
213 :
- 214 952 : void msg_bar(const char* format, ...)
+ 214 945 : void msg_bar(const char* format, ...)
215 : {
216 : va_list ap;
217 :
- 218 952 : pthread_mutex_lock(&msg_lock);
+ 218 945 : pthread_mutex_lock(&msg_lock);
219 :
220 : /* don't output in stdlog as these messages */
221 : /* are intended for screen only */
222 : /* also don't flush stdout as they are intended to be partial messages */
223 :
- 224 952 : if (msg_level >= MSG_BAR) {
+ 224 945 : if (msg_level >= MSG_BAR) {
225 0 : va_start(ap, format);
226 0 : vfprintf(stdout, format, ap);
227 0 : va_end(ap);
228 : }
229 :
- 230 952 : pthread_mutex_unlock(&msg_lock);
- 231 952 : }
+ 230 945 : pthread_mutex_unlock(&msg_lock);
+ 231 945 : }
232 :
- 233 126936 : void msg_verbose(const char* format, ...)
+ 233 127002 : void msg_verbose(const char* format, ...)
234 : {
235 : va_list ap;
236 :
- 237 126936 : pthread_mutex_lock(&msg_lock);
+ 237 127002 : pthread_mutex_lock(&msg_lock);
238 :
- 239 126936 : if (stdlog) {
- 240 125292 : va_start(ap, format);
- 241 125292 : fprintf(stdlog, "msg:verbose: ");
- 242 125292 : vfprintf(stdlog, format, ap);
- 243 125292 : fflush(stdlog);
- 244 125292 : va_end(ap);
+ 239 127002 : if (stdlog) {
+ 240 125226 : va_start(ap, format);
+ 241 125226 : fprintf(stdlog, "msg:verbose: ");
+ 242 125226 : vfprintf(stdlog, format, ap);
+ 243 125226 : fflush(stdlog);
+ 244 125226 : va_end(ap);
245 : }
246 :
- 247 126936 : if (msg_level >= MSG_VERBOSE) {
+ 247 127002 : if (msg_level >= MSG_VERBOSE) {
248 79 : va_start(ap, format);
249 79 : vfprintf(stdout, format, ap);
250 79 : fflush(stdout);
251 79 : va_end(ap);
252 : }
253 :
- 254 126936 : pthread_mutex_unlock(&msg_lock);
- 255 126936 : }
+ 254 127002 : pthread_mutex_unlock(&msg_lock);
+ 255 127002 : }
256 :
- 257 440 : void msg_flush(void)
+ 257 442 : void msg_flush(void)
258 : {
- 259 440 : pthread_mutex_lock(&msg_lock);
+ 259 442 : pthread_mutex_lock(&msg_lock);
260 :
- 261 440 : fflush(stdout);
- 262 440 : fflush(stderr);
+ 261 442 : fflush(stdout);
+ 262 442 : fflush(stderr);
263 :
- 264 440 : pthread_mutex_unlock(&msg_lock);
- 265 440 : }
+ 264 442 : pthread_mutex_unlock(&msg_lock);
+ 265 442 : }
266 :
267 : /**
268 : * Number of buffers for esc().
@@ -351,20 +351,20 @@
289 : *p++ = to; \
290 : break
291 :
- 292 3592843 : const char* esc(const char* str)
+ 292 3612178 : const char* esc(const char* str)
293 : {
- 294 3592843 : char* begin = esc_table[esc_index];
- 295 3592843 : char* end = begin + PATH_MAX;
- 296 3592843 : char* p = begin;
+ 294 3612178 : char* begin = esc_table[esc_index];
+ 295 3612178 : char* end = begin + PATH_MAX;
+ 296 3612178 : char* p = begin;
297 :
298 : /* next call uses the next buffer */
- 299 3592843 : esc_index = (esc_index + 1) % ESC_MAX;
+ 299 3612178 : esc_index = (esc_index + 1) % ESC_MAX;
300 :
301 : /* copy string with escaping */
- 302 53695808 : while (*str) {
- 303 46510122 : char c = *str;
+ 302 53980125 : while (*str) {
+ 303 46755769 : char c = *str;
304 :
- 305 46510122 : switch (c) {
+ 305 46755769 : switch (c) {
306 :
307 0 : ESCAPE('\n', 'n');
308 0 : ESCAPE('\r', 'r');
@@ -372,21 +372,21 @@
310 0 : ESCAPE('\\', '\\');
311 :
312 : default:
- 313 46510122 : if (p == end)
+ 313 46755769 : if (p == end)
314 0 : goto bail;
- 315 46510122 : *p++ = c;
- 316 46510122 : break;
+ 315 46755769 : *p++ = c;
+ 316 46755769 : break;
317 : }
318 :
- 319 46510122 : ++str;
+ 319 46755769 : ++str;
320 : }
321 :
322 : /* put final 0 */
- 323 3592843 : if (p == end)
+ 323 3612178 : if (p == end)
324 0 : goto bail;
- 325 3592843 : *p = 0;
+ 325 3612178 : *p = 0;
326 :
- 327 7185686 : return begin;
+ 327 7224356 : return begin;
328 :
329 : bail:
330 : /* LCOV_EXCL_START */
@@ -411,34 +411,34 @@
349 : /****************************************************************************/
350 : /* path */
351 :
- 352 6858601 : void pathcpy(char* dst, size_t size, const char* src)
+ 352 6956056 : void pathcpy(char* dst, size_t size, const char* src)
353 : {
- 354 6858601 : size_t len = strlen(src);
+ 354 6956056 : size_t len = strlen(src);
355 :
- 356 6858601 : if (len + 1 > size) {
+ 356 6956056 : if (len + 1 > size) {
357 : /* LCOV_EXCL_START */
- 358 : log_fatal("Path too long\n");
- 359 : exit(EXIT_FAILURE);
+ 358 : log_fatal("Path too long '%s'\n", src);
+ 359 : os_abort();
360 : /* LCOV_EXCL_STOP */
361 : }
362 :
- 363 6858601 : memcpy(dst, src, len + 1);
- 364 6858601 : }
+ 363 6956056 : memcpy(dst, src, len + 1);
+ 364 6956056 : }
365 :
- 366 248 : void pathcat(char* dst, size_t size, const char* src)
+ 366 256 : void pathcat(char* dst, size_t size, const char* src)
367 : {
- 368 248 : size_t dst_len = strlen(dst);
- 369 248 : size_t src_len = strlen(src);
+ 368 256 : size_t dst_len = strlen(dst);
+ 369 256 : size_t src_len = strlen(src);
370 :
- 371 248 : if (dst_len + src_len + 1 > size) {
+ 371 256 : if (dst_len + src_len + 1 > size) {
372 : /* LCOV_EXCL_START */
- 373 : log_fatal("Path too long\n");
- 374 : exit(EXIT_FAILURE);
+ 373 : log_fatal("Path too long '%s%s'\n", dst, src);
+ 374 : os_abort();
375 : /* LCOV_EXCL_STOP */
376 : }
377 :
- 378 248 : memcpy(dst + dst_len, src, src_len + 1);
- 379 248 : }
+ 378 256 : memcpy(dst + dst_len, src, src_len + 1);
+ 379 256 : }
380 :
381 788 : void pathcatc(char* dst, size_t size, char c)
382 : {
@@ -446,8 +446,8 @@
384 :
385 788 : if (dst_len + 2 > size) {
386 : /* LCOV_EXCL_START */
- 387 : log_fatal("Path too long\n");
- 388 : exit(EXIT_FAILURE);
+ 387 : log_fatal("Path too long '%s%c'\n", dst, c);
+ 388 : os_abort();
389 : /* LCOV_EXCL_STOP */
390 : }
391 :
@@ -455,9 +455,9 @@
393 788 : dst[dst_len + 1] = 0;
394 788 : }
395 :
- 396 8852 : void pathimport(char* dst, size_t size, const char* src)
+ 396 9180 : void pathimport(char* dst, size_t size, const char* src)
397 : {
- 398 8852 : pathcpy(dst, size, src);
+ 398 9180 : pathcpy(dst, size, src);
399 :
400 : #ifdef _WIN32
401 : /* convert all Windows '\' to C '/' */
@@ -467,11 +467,11 @@
405 : ++dst;
406 : }
407 : #endif
- 408 8852 : }
+ 408 9180 : }
409 :
- 410 17569 : void pathexport(char* dst, size_t size, const char* src)
+ 410 17583 : void pathexport(char* dst, size_t size, const char* src)
411 : {
- 412 17569 : pathcpy(dst, size, src);
+ 412 17583 : pathcpy(dst, size, src);
413 :
414 : #ifdef _WIN32
415 : /* convert all C '/' to Windows '\' */
@@ -481,434 +481,465 @@
419 : ++dst;
420 : }
421 : #endif
- 422 17569 : }
+ 422 17583 : }
423 :
- 424 50030363 : void pathprint(char* dst, size_t size, const char* format, ...)
+ 424 50908928 : void pathprint(char* dst, size_t size, const char* format, ...)
425 : {
426 : size_t len;
427 : va_list ap;
428 :
- 429 50030363 : va_start(ap, format);
- 430 50030363 : len = vsnprintf(dst, size, format, ap);
- 431 50030363 : va_end(ap);
+ 429 50908928 : va_start(ap, format);
+ 430 50908928 : len = vsnprintf(dst, size, format, ap);
+ 431 50908928 : va_end(ap);
432 :
- 433 50030363 : if (len >= size) {
+ 433 50908928 : if (len >= size) {
434 : /* LCOV_EXCL_START */
- 435 : log_fatal("Path too long\n");
- 436 : exit(EXIT_FAILURE);
- 437 : /* LCOV_EXCL_STOP */
- 438 : }
- 439 50030363 : }
- 440 :
- 441 7319 : void pathslash(char* dst, size_t size)
- 442 : {
- 443 7319 : size_t len = strlen(dst);
- 444 :
- 445 7319 : if (len > 0 && dst[len - 1] != '/') {
- 446 5842 : if (len + 2 >= size) {
- 447 : /* LCOV_EXCL_START */
- 448 : log_fatal("Path too long\n");
- 449 : exit(EXIT_FAILURE);
- 450 : /* LCOV_EXCL_STOP */
- 451 : }
- 452 :
- 453 5842 : dst[len] = '/';
- 454 5842 : dst[len + 1] = 0;
- 455 : }
- 456 7319 : }
+ 435 : if (size > 0) {
+ 436 : dst[size - 1] = 0;
+ 437 : log_fatal("Path too long '%s...'\n", dst);
+ 438 : } else {
+ 439 : log_fatal("Path too long for empty size'\n");
+ 440 : }
+ 441 : os_abort();
+ 442 : /* LCOV_EXCL_STOP */
+ 443 : }
+ 444 50908928 : }
+ 445 :
+ 446 7469 : void pathslash(char* dst, size_t size)
+ 447 : {
+ 448 7469 : size_t len = strlen(dst);
+ 449 :
+ 450 7469 : if (len > 0 && dst[len - 1] != '/') {
+ 451 5944 : if (len + 2 >= size) {
+ 452 : /* LCOV_EXCL_START */
+ 453 : log_fatal("Path too long '%s/'\n", dst);
+ 454 : os_abort();
+ 455 : /* LCOV_EXCL_STOP */
+ 456 : }
457 :
- 458 30 : void pathcut(char* dst)
- 459 : {
- 460 30 : char* slash = strrchr(dst, '/');
- 461 30 : if (slash)
- 462 30 : slash[1] = 0;
- 463 : else
- 464 0 : dst[0] = 0;
- 465 30 : }
- 466 :
- 467 50336221 : int pathcmp(const char* a, const char* b)
- 468 : {
- 469 : #ifdef _WIN32
- 470 : char ai[PATH_MAX];
- 471 : char bi[PATH_MAX];
- 472 :
- 473 : /* import to convert \ to / */
- 474 : pathimport(ai, sizeof(ai), a);
- 475 : pathimport(bi, sizeof(bi), b);
- 476 :
- 477 : /* case insensitive compare in Windows */
- 478 : return stricmp(ai, bi);
- 479 : #else
- 480 50336221 : return strcmp(a, b);
- 481 : #endif
- 482 : }
- 483 :
- 484 : /****************************************************************************/
- 485 : /* filesystem */
- 486 :
- 487 792978 : int mkancestor(const char* file)
- 488 : {
- 489 : char dir[PATH_MAX];
- 490 : struct stat st;
- 491 : char* c;
- 492 :
- 493 792978 : pathcpy(dir, sizeof(dir), file);
- 494 :
- 495 792978 : c = strrchr(dir, '/');
- 496 792978 : if (!c) {
- 497 : /* no ancestor */
- 498 0 : return 0;
- 499 : }
- 500 :
- 501 : /* clear the file */
- 502 792978 : *c = 0;
- 503 :
- 504 : /* if it's the root dir */
- 505 792978 : if (*dir == 0) {
- 506 : /* nothing more to do */
- 507 0 : return 0;
- 508 : }
- 509 :
- 510 : #ifdef _WIN32
- 511 : /* if it's a drive specificaion like "C:" */
- 512 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
- 513 : /* nothing more to do */
- 514 : return 0;
- 515 : }
- 516 : #endif
- 517 :
- 518 : /*
- 519 : * Check if the dir already exists using lstat().
- 520 : *
- 521 : * Note that in Windows when dealing with read-only media
- 522 : * you cannot try to create the directory, and expecting
- 523 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
- 524 : *
- 525 : * Also in Windows it's better to use lstat() than stat() because it
- 526 : * doen't need to open the dir with CreateFile().
- 527 : */
- 528 792978 : if (lstat(dir, &st) == 0) {
- 529 : /* it already exists */
- 530 792898 : return 0;
- 531 : }
- 532 :
- 533 : /* recursively create them all */
- 534 80 : if (mkancestor(dir) != 0) {
- 535 : /* LCOV_EXCL_START */
- 536 : return -1;
- 537 : /* LCOV_EXCL_STOP */
- 538 : }
- 539 :
- 540 : /* create it */
- 541 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
- 542 : /* LCOV_EXCL_START */
- 543 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno));
- 544 : return -1;
- 545 : /* LCOV_EXCL_STOP */
- 546 : }
- 547 :
- 548 80 : return 0;
- 549 : }
- 550 :
- 551 117937 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
- 552 : {
- 553 : #if HAVE_FUTIMENS
- 554 : struct timespec tv[2];
- 555 : #else
- 556 : struct timeval tv[2];
- 557 : #endif
- 558 : int ret;
- 559 :
- 560 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
- 561 117937 : tv[0].tv_sec = mtime_sec;
- 562 117937 : if (mtime_nsec != STAT_NSEC_INVALID)
- 563 117937 : tv[0].tv_nsec = mtime_nsec;
- 564 : else
- 565 0 : tv[0].tv_nsec = 0;
- 566 117937 : tv[1].tv_sec = tv[0].tv_sec;
- 567 117937 : tv[1].tv_nsec = tv[0].tv_nsec;
- 568 :
- 569 117937 : ret = futimens(f, tv);
- 570 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
- 571 : tv[0].tv_sec = mtime_sec;
- 572 : if (mtime_nsec != STAT_NSEC_INVALID)
- 573 : tv[0].tv_usec = mtime_nsec / 1000;
- 574 : else
- 575 : tv[0].tv_usec = 0;
- 576 : tv[1].tv_sec = tv[0].tv_sec;
- 577 : tv[1].tv_usec = tv[0].tv_usec;
- 578 :
- 579 : ret = futimes(f, tv);
- 580 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
- 581 : tv[0].tv_sec = mtime_sec;
- 582 : if (mtime_nsec != STAT_NSEC_INVALID)
- 583 : tv[0].tv_usec = mtime_nsec / 1000;
- 584 : else
- 585 : tv[0].tv_usec = 0;
- 586 : tv[1].tv_sec = tv[0].tv_sec;
- 587 : tv[1].tv_usec = tv[0].tv_usec;
- 588 :
- 589 : ret = futimesat(f, 0, tv);
- 590 : #else
- 591 : #error No function available to set file timestamps with sub-second precision
- 592 : #endif
+ 458 5944 : dst[len] = '/';
+ 459 5944 : dst[len + 1] = 0;
+ 460 : }
+ 461 7469 : }
+ 462 :
+ 463 30 : void pathcut(char* dst)
+ 464 : {
+ 465 30 : char* slash = strrchr(dst, '/');
+ 466 30 : if (slash)
+ 467 30 : slash[1] = 0;
+ 468 : else
+ 469 0 : dst[0] = 0;
+ 470 30 : }
+ 471 :
+ 472 51328958 : int pathcmp(const char* a, const char* b)
+ 473 : {
+ 474 : #ifdef _WIN32
+ 475 : char ai[PATH_MAX];
+ 476 : char bi[PATH_MAX];
+ 477 :
+ 478 : /* import to convert \ to / */
+ 479 : pathimport(ai, sizeof(ai), a);
+ 480 : pathimport(bi, sizeof(bi), b);
+ 481 :
+ 482 : /* case insensitive compare in Windows */
+ 483 : return stricmp(ai, bi);
+ 484 : #else
+ 485 51328958 : return strcmp(a, b);
+ 486 : #endif
+ 487 : }
+ 488 :
+ 489 : /****************************************************************************/
+ 490 : /* file-system */
+ 491 :
+ 492 793073 : int mkancestor(const char* file)
+ 493 : {
+ 494 : char dir[PATH_MAX];
+ 495 : struct stat st;
+ 496 : char* c;
+ 497 :
+ 498 793073 : pathcpy(dir, sizeof(dir), file);
+ 499 :
+ 500 793073 : c = strrchr(dir, '/');
+ 501 793073 : if (!c) {
+ 502 : /* no ancestor */
+ 503 0 : return 0;
+ 504 : }
+ 505 :
+ 506 : /* clear the file */
+ 507 793073 : *c = 0;
+ 508 :
+ 509 : /* if it's the root dir */
+ 510 793073 : if (*dir == 0) {
+ 511 : /* nothing more to do */
+ 512 0 : return 0;
+ 513 : }
+ 514 :
+ 515 : #ifdef _WIN32
+ 516 : /* if it's a drive specificaion like "C:" */
+ 517 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
+ 518 : /* nothing more to do */
+ 519 : return 0;
+ 520 : }
+ 521 : #endif
+ 522 :
+ 523 : /*
+ 524 : * Check if the dir already exists using lstat().
+ 525 : *
+ 526 : * Note that in Windows when dealing with read-only media
+ 527 : * you cannot try to create the directory, and expecting
+ 528 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
+ 529 : *
+ 530 : * Also in Windows it's better to use lstat() than stat() because it
+ 531 : * doen't need to open the dir with CreateFile().
+ 532 : */
+ 533 793073 : if (lstat(dir, &st) == 0) {
+ 534 : /* it already exists */
+ 535 792993 : return 0;
+ 536 : }
+ 537 :
+ 538 : /* recursively create them all */
+ 539 80 : if (mkancestor(dir) != 0) {
+ 540 : /* LCOV_EXCL_START */
+ 541 : return -1;
+ 542 : /* LCOV_EXCL_STOP */
+ 543 : }
+ 544 :
+ 545 : /* create it */
+ 546 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
+ 547 : /* LCOV_EXCL_START */
+ 548 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno));
+ 549 : return -1;
+ 550 : /* LCOV_EXCL_STOP */
+ 551 : }
+ 552 :
+ 553 80 : return 0;
+ 554 : }
+ 555 :
+ 556 119629 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
+ 557 : {
+ 558 : #if HAVE_FUTIMENS
+ 559 : struct timespec tv[2];
+ 560 : #else
+ 561 : struct timeval tv[2];
+ 562 : #endif
+ 563 : int ret;
+ 564 :
+ 565 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
+ 566 119629 : tv[0].tv_sec = mtime_sec;
+ 567 119629 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 568 119629 : tv[0].tv_nsec = mtime_nsec;
+ 569 : else
+ 570 0 : tv[0].tv_nsec = 0;
+ 571 119629 : tv[1].tv_sec = tv[0].tv_sec;
+ 572 119629 : tv[1].tv_nsec = tv[0].tv_nsec;
+ 573 :
+ 574 119629 : ret = futimens(f, tv);
+ 575 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
+ 576 : tv[0].tv_sec = mtime_sec;
+ 577 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 578 : tv[0].tv_usec = mtime_nsec / 1000;
+ 579 : else
+ 580 : tv[0].tv_usec = 0;
+ 581 : tv[1].tv_sec = tv[0].tv_sec;
+ 582 : tv[1].tv_usec = tv[0].tv_usec;
+ 583 :
+ 584 : ret = futimes(f, tv);
+ 585 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
+ 586 : tv[0].tv_sec = mtime_sec;
+ 587 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 588 : tv[0].tv_usec = mtime_nsec / 1000;
+ 589 : else
+ 590 : tv[0].tv_usec = 0;
+ 591 : tv[1].tv_sec = tv[0].tv_sec;
+ 592 : tv[1].tv_usec = tv[0].tv_usec;
593 :
- 594 117937 : return ret;
- 595 : }
- 596 :
- 597 : /****************************************************************************/
- 598 : /* memory */
- 599 :
- 600 : /**
- 601 : * Total amount of memory allocated.
- 602 : */
- 603 : static size_t mcounter;
+ 594 : ret = futimesat(f, 0, tv);
+ 595 : #else
+ 596 : #error No function available to set file timestamps with sub-second precision
+ 597 : #endif
+ 598 :
+ 599 119629 : return ret;
+ 600 : }
+ 601 :
+ 602 : /****************************************************************************/
+ 603 : /* memory */
604 :
- 605 444 : size_t malloc_counter(void)
- 606 : {
- 607 444 : return mcounter;
- 608 : }
+ 605 : /**
+ 606 : * Total amount of memory allocated.
+ 607 : */
+ 608 : static size_t mcounter;
609 :
- 610 : /* LCOV_EXCL_START */
- 611 : static ssize_t malloc_print(int f, const char* str)
- 612 : {
- 613 : ssize_t len = 0;
- 614 : while (str[len])
- 615 : ++len;
- 616 : return write(f, str, len);
- 617 : }
- 618 : /* LCOV_EXCL_STOP */
- 619 :
- 620 : /* LCOV_EXCL_START */
- 621 : static ssize_t malloc_printn(int f, size_t value)
- 622 : {
- 623 : char buf[32];
- 624 : int i;
- 625 :
- 626 : if (!value)
- 627 : return write(f, "0", 1);
- 628 :
- 629 : i = sizeof(buf);
- 630 : while (value) {
- 631 : buf[--i] = (value % 10) + '0';
- 632 : value /= 10;
- 633 : }
- 634 :
- 635 : return write(f, buf + i, sizeof(buf) - i);
- 636 : }
- 637 : /* LCOV_EXCL_STOP */
- 638 :
- 639 : /* LCOV_EXCL_START */
- 640 : void malloc_fail(size_t size)
- 641 : {
- 642 : /* don't use printf to avoid any possible extra allocation */
- 643 : int f = 2; /* stderr */
- 644 :
- 645 : malloc_print(f, "Failed for Low Memory!\n");
- 646 : malloc_print(f, "Allocating ");
- 647 : malloc_printn(f, size);
- 648 : malloc_print(f, " bytes.\n");
- 649 : malloc_print(f, "Already allocated ");
- 650 : malloc_printn(f, malloc_counter());
- 651 : malloc_print(f, " bytes.\n");
- 652 : if (sizeof(void*) == 4) {
- 653 : malloc_print(f, "You are currently using a 32 bits executable.\n");
- 654 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
- 655 : }
- 656 : }
- 657 : /* LCOV_EXCL_STOP */
- 658 :
- 659 13871886 : void* malloc_nofail(size_t size)
- 660 : {
- 661 13871886 : void* ptr = malloc(size);
- 662 :
- 663 13871886 : if (!ptr) {
- 664 : /* LCOV_EXCL_START */
- 665 : malloc_fail(size);
- 666 : exit(EXIT_FAILURE);
- 667 : /* LCOV_EXCL_STOP */
- 668 : }
+ 610 : /**
+ 611 : * Mutex protection for the global memory counter.
+ 612 : */
+ 613 : #if HAVE_PTHREAD
+ 614 : pthread_mutex_t mcounter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ 615 : #endif
+ 616 :
+ 617 460 : size_t malloc_counter_get(void)
+ 618 : {
+ 619 : size_t ret;
+ 620 : #if HAVE_PTHREAD
+ 621 460 : pthread_mutex_lock(&mcounter_mutex);
+ 622 : #endif
+ 623 460 : ret = mcounter;
+ 624 : #if HAVE_PTHREAD
+ 625 460 : pthread_mutex_unlock(&mcounter_mutex);
+ 626 : #endif
+ 627 460 : return ret;
+ 628 : }
+ 629 :
+ 630 19792624 : void malloc_counter_inc(size_t inc)
+ 631 : {
+ 632 : #if HAVE_PTHREAD
+ 633 19792624 : pthread_mutex_lock(&mcounter_mutex);
+ 634 : #endif
+ 635 19792624 : mcounter += inc;
+ 636 : #if HAVE_PTHREAD
+ 637 19792624 : pthread_mutex_unlock(&mcounter_mutex);
+ 638 : #endif
+ 639 19792624 : }
+ 640 :
+ 641 : /* LCOV_EXCL_START */
+ 642 : static ssize_t malloc_print(int f, const char* str)
+ 643 : {
+ 644 : ssize_t len = 0;
+ 645 : while (str[len])
+ 646 : ++len;
+ 647 : return write(f, str, len);
+ 648 : }
+ 649 : /* LCOV_EXCL_STOP */
+ 650 :
+ 651 : /* LCOV_EXCL_START */
+ 652 : static ssize_t malloc_printn(int f, size_t value)
+ 653 : {
+ 654 : char buf[32];
+ 655 : int i;
+ 656 :
+ 657 : if (!value)
+ 658 : return write(f, "0", 1);
+ 659 :
+ 660 : i = sizeof(buf);
+ 661 : while (value) {
+ 662 : buf[--i] = (value % 10) + '0';
+ 663 : value /= 10;
+ 664 : }
+ 665 :
+ 666 : return write(f, buf + i, sizeof(buf) - i);
+ 667 : }
+ 668 : /* LCOV_EXCL_STOP */
669 :
- 670 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */
- 671 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */
- 672 : /* and not only reserving the addressable space. */
- 673 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
- 674 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
- 675 : /* get a real error from malloc() instead than a process killed. */
- 676 : /* Note that calloc() doesn't have the same effect. */
- 677 13871886 : memset(ptr, 0xA5, size);
- 678 : #endif
- 679 :
- 680 13871886 : mcounter += size;
- 681 :
- 682 13871886 : return ptr;
- 683 : }
- 684 :
- 685 9283 : void* calloc_nofail(size_t count, size_t size)
- 686 : {
- 687 : void* ptr;
- 688 :
- 689 9283 : size *= count;
- 690 :
- 691 : /* see the note in malloc_nofail() of why we don't use calloc() */
- 692 9283 : ptr = malloc(size);
+ 670 : /* LCOV_EXCL_START */
+ 671 : void malloc_fail(size_t size)
+ 672 : {
+ 673 : /* don't use printf to avoid any possible extra allocation */
+ 674 : int f = 2; /* stderr */
+ 675 :
+ 676 : malloc_print(f, "Failed for Low Memory!\n");
+ 677 : malloc_print(f, "Allocating ");
+ 678 : malloc_printn(f, size);
+ 679 : malloc_print(f, " bytes.\n");
+ 680 : malloc_print(f, "Already allocated ");
+ 681 : malloc_printn(f, malloc_counter_get());
+ 682 : malloc_print(f, " bytes.\n");
+ 683 : if (sizeof(void*) == 4) {
+ 684 : malloc_print(f, "You are currently using a 32 bits executable.\n");
+ 685 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
+ 686 : }
+ 687 : }
+ 688 : /* LCOV_EXCL_STOP */
+ 689 :
+ 690 14067108 : void* malloc_nofail(size_t size)
+ 691 : {
+ 692 14067108 : void* ptr = malloc(size);
693 :
- 694 9283 : if (!ptr) {
+ 694 14067108 : if (!ptr) {
695 : /* LCOV_EXCL_START */
696 : malloc_fail(size);
697 : exit(EXIT_FAILURE);
698 : /* LCOV_EXCL_STOP */
699 : }
700 :
- 701 9283 : memset(ptr, 0, size);
- 702 :
- 703 9283 : mcounter += size;
- 704 :
- 705 9283 : return ptr;
- 706 : }
- 707 :
- 708 5663011 : char* strdup_nofail(const char* str)
- 709 : {
- 710 : size_t size;
- 711 : char* ptr;
+ 701 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */
+ 702 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */
+ 703 : /* and not only reserving the addressable space. */
+ 704 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
+ 705 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
+ 706 : /* get a real error from malloc() instead than a process killed. */
+ 707 : /* Note that calloc() doesn't have the same effect. */
+ 708 14067108 : memset(ptr, 0xA5, size);
+ 709 : #endif
+ 710 :
+ 711 14067108 : malloc_counter_inc(size);
712 :
- 713 5663011 : size = strlen(str) + 1;
- 714 :
- 715 5663011 : ptr = malloc(size);
- 716 :
- 717 5663011 : if (!ptr) {
- 718 : /* LCOV_EXCL_START */
- 719 : malloc_fail(size);
- 720 : exit(EXIT_FAILURE);
- 721 : /* LCOV_EXCL_STOP */
- 722 : }
- 723 :
- 724 5663011 : memcpy(ptr, str, size);
- 725 :
- 726 5663011 : mcounter += size;
- 727 :
- 728 5663011 : return ptr;
- 729 : }
- 730 :
- 731 : /****************************************************************************/
- 732 : /* smartctl */
+ 713 14067108 : return ptr;
+ 714 : }
+ 715 :
+ 716 9576 : void* calloc_nofail(size_t count, size_t size)
+ 717 : {
+ 718 : void* ptr;
+ 719 :
+ 720 9576 : size *= count;
+ 721 :
+ 722 : /* see the note in malloc_nofail() of why we don't use calloc() */
+ 723 9576 : ptr = malloc(size);
+ 724 :
+ 725 9576 : if (!ptr) {
+ 726 : /* LCOV_EXCL_START */
+ 727 : malloc_fail(size);
+ 728 : exit(EXIT_FAILURE);
+ 729 : /* LCOV_EXCL_STOP */
+ 730 : }
+ 731 :
+ 732 9576 : memset(ptr, 0, size);
733 :
- 734 : /**
- 735 : * Match a string with the specified pattern.
- 736 : * Like sscanf() a space match any sequence of spaces.
- 737 : * Return 0 if it matches.
- 738 : */
- 739 0 : static int smatch(const char* str, const char* pattern)
+ 734 9576 : malloc_counter_inc(size);
+ 735 :
+ 736 9576 : return ptr;
+ 737 : }
+ 738 :
+ 739 5715940 : char* strdup_nofail(const char* str)
740 : {
- 741 0 : while (*pattern) {
- 742 0 : if (isspace(*pattern)) {
- 743 0 : ++pattern;
- 744 0 : while (isspace(*str))
- 745 0 : ++str;
- 746 0 : } else if (*pattern == *str) {
- 747 0 : ++pattern;
- 748 0 : ++str;
- 749 : } else
- 750 0 : return -1;
- 751 : }
- 752 :
- 753 0 : return 0;
- 754 : }
- 755 :
- 756 25 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial)
- 757 : {
- 758 : unsigned i;
- 759 : int inside;
- 760 :
- 761 : /* preclear attribute */
- 762 25 : *serial = 0;
- 763 6501 : for (i = 0; i < SMART_COUNT; ++i)
- 764 6476 : smart[i] = SMART_UNASSIGNED;
- 765 :
- 766 : /* read the file */
- 767 25 : inside = 0;
- 768 : while (1) {
- 769 : char buf[256];
- 770 : char attr[64];
- 771 : unsigned id;
- 772 : uint64_t raw;
- 773 : char* s;
- 774 :
- 775 25 : s = fgets(buf, sizeof(buf), f);
- 776 25 : if (s == 0)
- 777 25 : break;
- 778 :
- 779 : /* remove extraneous chars */
- 780 0 : s = polish(buf);
- 781 :
- 782 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
+ 741 : size_t size;
+ 742 : char* ptr;
+ 743 :
+ 744 5715940 : size = strlen(str) + 1;
+ 745 :
+ 746 5715940 : ptr = malloc(size);
+ 747 :
+ 748 5715940 : if (!ptr) {
+ 749 : /* LCOV_EXCL_START */
+ 750 : malloc_fail(size);
+ 751 : exit(EXIT_FAILURE);
+ 752 : /* LCOV_EXCL_STOP */
+ 753 : }
+ 754 :
+ 755 5715940 : memcpy(ptr, str, size);
+ 756 :
+ 757 5715940 : malloc_counter_inc(size);
+ 758 :
+ 759 5715940 : return ptr;
+ 760 : }
+ 761 :
+ 762 : /****************************************************************************/
+ 763 : /* smartctl */
+ 764 :
+ 765 : /**
+ 766 : * Match a string with the specified pattern.
+ 767 : * Like sscanf() a space match any sequence of spaces.
+ 768 : * Return 0 if it matches.
+ 769 : */
+ 770 0 : static int smatch(const char* str, const char* pattern)
+ 771 : {
+ 772 0 : while (*pattern) {
+ 773 0 : if (isspace(*pattern)) {
+ 774 0 : ++pattern;
+ 775 0 : while (isspace(*str))
+ 776 0 : ++str;
+ 777 0 : } else if (*pattern == *str) {
+ 778 0 : ++pattern;
+ 779 0 : ++str;
+ 780 : } else
+ 781 0 : return -1;
+ 782 : }
783 :
- 784 : /* skip initial spaces */
- 785 0 : while (isspace(*s))
- 786 0 : ++s;
- 787 :
- 788 0 : if (*s == 0) {
- 789 0 : inside = 0;
- 790 0 : } else if (smatch(s, "ID#") == 0) {
- 791 0 : inside = 1;
- 792 0 : } else if (smatch(s, "No Errors Logged") == 0) {
- 793 0 : smart[SMART_ERROR] = 0;
- 794 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
- 795 0 : smart[SMART_ERROR] = raw;
- 796 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
- 797 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) {
- 798 0 : smart[SMART_ROTATION_RATE] = 0;
- 799 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) {
- 800 0 : } else if (sscanf(s, "User Capacity: %63s", attr) == 1) {
- 801 0 : smart[SMART_SIZE] = 0;
- 802 0 : for (i = 0; attr[i]; ++i) {
- 803 0 : if (isdigit(attr[i])) {
- 804 0 : smart[SMART_SIZE] *= 10;
- 805 0 : smart[SMART_SIZE] += attr[i] - '0';
- 806 : }
- 807 : }
- 808 0 : } else if (inside) {
- 809 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
- 810 : /* LCOV_EXCL_START */
- 811 : log_fatal("Invalid smartctl line '%s'.\n", s);
- 812 : return -1;
- 813 : /* LCOV_EXCL_STOP */
- 814 : }
- 815 :
- 816 0 : if (id >= 256) {
- 817 : /* LCOV_EXCL_START */
- 818 : log_fatal("Invalid SMART id '%u'.\n", id);
- 819 : return -1;
- 820 : /* LCOV_EXCL_STOP */
- 821 : }
- 822 :
- 823 0 : smart[id] = raw;
- 824 : }
- 825 0 : }
- 826 :
- 827 25 : return 0;
- 828 : }
- 829 :
- 830 12 : int smartctl_flush(FILE* f, const char* file, const char* name)
- 831 : {
- 832 : /* read the file */
- 833 : while (1) {
- 834 : char buf[256];
- 835 : char* s;
- 836 :
- 837 12 : s = fgets(buf, sizeof(buf), f);
- 838 12 : if (s == 0)
- 839 12 : break;
- 840 :
- 841 : /* remove extraneous chars */
- 842 0 : s = polish(buf);
- 843 :
- 844 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
- 845 0 : }
+ 784 0 : return 0;
+ 785 : }
+ 786 :
+ 787 25 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial)
+ 788 : {
+ 789 : unsigned i;
+ 790 : int inside;
+ 791 :
+ 792 : /* preclear attribute */
+ 793 25 : *serial = 0;
+ 794 6525 : for (i = 0; i < SMART_COUNT; ++i)
+ 795 6500 : smart[i] = SMART_UNASSIGNED;
+ 796 :
+ 797 : /* read the file */
+ 798 25 : inside = 0;
+ 799 : while (1) {
+ 800 : char buf[256];
+ 801 : char attr[64];
+ 802 : unsigned id;
+ 803 : uint64_t raw;
+ 804 : char* s;
+ 805 :
+ 806 25 : s = fgets(buf, sizeof(buf), f);
+ 807 24 : if (s == 0)
+ 808 24 : break;
+ 809 :
+ 810 : /* remove extraneous chars */
+ 811 0 : s = polish(buf);
+ 812 :
+ 813 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
+ 814 :
+ 815 : /* skip initial spaces */
+ 816 0 : while (isspace(*s))
+ 817 0 : ++s;
+ 818 :
+ 819 0 : if (*s == 0) {
+ 820 0 : inside = 0;
+ 821 0 : } else if (smatch(s, "ID#") == 0) {
+ 822 0 : inside = 1;
+ 823 0 : } else if (smatch(s, "No Errors Logged") == 0) {
+ 824 0 : smart[SMART_ERROR] = 0;
+ 825 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
+ 826 0 : smart[SMART_ERROR] = raw;
+ 827 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
+ 828 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) {
+ 829 0 : smart[SMART_ROTATION_RATE] = 0;
+ 830 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) {
+ 831 0 : } else if (sscanf(s, "User Capacity: %63s", attr) == 1) {
+ 832 0 : smart[SMART_SIZE] = 0;
+ 833 0 : for (i = 0; attr[i]; ++i) {
+ 834 0 : if (isdigit(attr[i])) {
+ 835 0 : smart[SMART_SIZE] *= 10;
+ 836 0 : smart[SMART_SIZE] += attr[i] - '0';
+ 837 : }
+ 838 : }
+ 839 0 : } else if (inside) {
+ 840 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
+ 841 : /* LCOV_EXCL_START */
+ 842 : log_fatal("Invalid smartctl line '%s'.\n", s);
+ 843 : return -1;
+ 844 : /* LCOV_EXCL_STOP */
+ 845 : }
846 :
- 847 24 : return 0;
- 848 : }
- 849 :
+ 847 0 : if (id >= 256) {
+ 848 : /* LCOV_EXCL_START */
+ 849 : log_fatal("Invalid SMART id '%u'.\n", id);
+ 850 : return -1;
+ 851 : /* LCOV_EXCL_STOP */
+ 852 : }
+ 853 :
+ 854 0 : smart[id] = raw;
+ 855 : }
+ 856 0 : }
+ 857 :
+ 858 24 : return 0;
+ 859 : }
+ 860 :
+ 861 12 : int smartctl_flush(FILE* f, const char* file, const char* name)
+ 862 : {
+ 863 : /* read the file */
+ 864 : while (1) {
+ 865 : char buf[256];
+ 866 : char* s;
+ 867 :
+ 868 12 : s = fgets(buf, sizeof(buf), f);
+ 869 12 : if (s == 0)
+ 870 12 : break;
+ 871 :
+ 872 : /* remove extraneous chars */
+ 873 0 : s = polish(buf);
+ 874 :
+ 875 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
+ 876 0 : }
+ 877 :
+ 878 24 : return 0;
+ 879 : }
+ 880 :
diff --git a/cov/cmdline/sync.c.func-sort-c.html b/cov/cmdline/sync.c.func-sort-c.html
index f3bdcd37..bb2fb51e 100644
--- a/cov/cmdline/sync.c.func-sort-c.html
+++ b/cov/cmdline/sync.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| block_is_enabled |
- 733118 |
+ 772244 |
| state_sync |
- 72 |
+ 80 |
| state_sync_process |
- 68 |
+ 76 |
| state_hash_process |
diff --git a/cov/cmdline/sync.c.func.html b/cov/cmdline/sync.c.func.html
index e5f48fb5..b1272bb6 100644
--- a/cov/cmdline/sync.c.func.html
+++ b/cov/cmdline/sync.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| block_is_enabled |
- 733118 |
+ 772244 |
| state_hash_process |
@@ -69,11 +69,11 @@
| state_sync |
- 72 |
+ 80 |
| state_sync_process |
- 68 |
+ 76 |
diff --git a/cov/cmdline/sync.c.gcov.html b/cov/cmdline/sync.c.gcov.html
index 36ec1bda..c1ef01a5 100644
--- a/cov/cmdline/sync.c.gcov.html
+++ b/cov/cmdline/sync.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -123,18 +123,18 @@
61 42 : if (!disk)
62 0 : continue;
63 :
- 64 235986 : for (i = blockstart; i < blockmax; ++i) {
+ 64 236382 : for (i = blockstart; i < blockmax; ++i) {
65 : struct snapraid_block* block;
66 : unsigned block_state;
67 :
- 68 235944 : block = fs_par2block_get(disk, i);
+ 68 236340 : block = fs_par2block_get(disk, i);
69 :
70 : /* get the state of the block */
- 71 235944 : block_state = block_state_get(block);
+ 71 236340 : block_state = block_state_get(block);
72 :
73 : /* process REP and CHG blocks */
- 74 235944 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG)
- 75 222594 : continue;
+ 74 236340 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG)
+ 75 222990 : continue;
76 :
77 13350 : ++countmax;
78 : }
@@ -155,7 +155,7 @@
93 42 : if (!disk)
94 0 : continue;
95 :
- 96 235986 : for (i = blockstart; i < blockmax; ++i) {
+ 96 236382 : for (i = blockstart; i < blockmax; ++i) {
97 : snapraid_info info;
98 : int rehash;
99 : struct snapraid_block* block;
@@ -165,14 +165,14 @@
103 : struct snapraid_file* file;
104 : block_off_t file_pos;
105 :
- 106 235944 : block = fs_par2block_get(disk, i);
+ 106 236340 : block = fs_par2block_get(disk, i);
107 :
108 : /* get the state of the block */
- 109 235944 : block_state = block_state_get(block);
+ 109 236340 : block_state = block_state_get(block);
110 :
111 : /* process REP and CHG blocks */
- 112 235944 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG)
- 113 445198 : continue;
+ 112 236340 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG)
+ 113 445990 : continue;
114 :
115 : /* get the file of this block */
116 13350 : file = fs_par2file_get(disk, i, &file_pos);
@@ -316,7 +316,7 @@
254 :
255 13341 : if (block_state == BLOCK_STATE_REP) {
256 : /* compare the hash */
- 257 673 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 257 13339 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
258 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc(file->sub));
259 1 : log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos);
260 1 : log_error("WARNING! Unexpected data modification of a file without parity!\n");
@@ -339,16 +339,16 @@
277 : }
278 : } else {
279 : /* the only other case is BLOCK_STATE_CHG */
- 280 12668 : assert(block_state == BLOCK_STATE_CHG);
+ 280 2 : assert(block_state == BLOCK_STATE_CHG);
281 :
282 : /* copy the hash in the block */
- 283 12668 : memcpy(block->hash, hash, HASH_SIZE);
+ 283 2 : memcpy(block->hash, hash, HASH_SIZE);
284 :
285 : /* and mark the block as hashed */
- 286 12668 : block_state_set(block, BLOCK_STATE_REP);
+ 286 2 : block_state_set(block, BLOCK_STATE_REP);
287 :
288 : /* mark the state as needing write */
- 289 12668 : state->need_write = 1;
+ 289 2 : state->need_write = 1;
290 : }
291 :
292 : /* count the number of processed block */
@@ -466,39 +466,39 @@
404 : /**
405 : * Check if we have to process the specified block index ::i.
406 : */
- 407 733118 : static int block_is_enabled(block_off_t i, struct snapraid_handle* handle, unsigned diskmax)
+ 407 772244 : static int block_is_enabled(block_off_t i, struct snapraid_handle* handle, unsigned diskmax)
408 : {
409 : unsigned j;
410 : int one_invalid;
411 : int one_valid;
412 :
413 : /* for each disk */
- 414 733118 : one_invalid = 0;
- 415 733118 : one_valid = 0;
- 416 5131826 : for (j = 0; j < diskmax; ++j) {
+ 414 772244 : one_invalid = 0;
+ 415 772244 : one_valid = 0;
+ 416 5405708 : for (j = 0; j < diskmax; ++j) {
417 : struct snapraid_block* block;
418 :
419 : /* if no disk, nothing to check */
- 420 4398708 : if (!handle[j].disk)
- 421 9342 : continue;
+ 420 4633464 : if (!handle[j].disk)
+ 421 9358 : continue;
422 :
- 423 4389366 : block = fs_par2block_get(handle[j].disk, i);
+ 423 4624106 : block = fs_par2block_get(handle[j].disk, i);
424 :
- 425 4389366 : if (block_has_file(block))
- 426 4180078 : one_valid = 1;
+ 425 4624106 : if (block_has_file(block))
+ 426 4407290 : one_valid = 1;
427 :
- 428 4389366 : if (block_has_invalid_parity(block))
- 429 361206 : one_invalid = 1;
+ 428 4624106 : if (block_has_invalid_parity(block))
+ 429 469940 : one_invalid = 1;
430 : }
431 :
432 : /* if none valid or none invalid, we don't need to update */
- 433 733118 : if (!one_invalid || !one_valid)
- 434 568436 : return 0;
+ 433 772244 : if (!one_invalid || !one_valid)
+ 434 589930 : return 0;
435 :
- 436 164682 : return 1;
+ 436 182314 : return 1;
437 : }
438 :
- 439 68 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax)
+ 439 76 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax)
440 : {
441 : struct snapraid_handle* handle;
442 : void* rehandle_alloc;
@@ -526,59 +526,59 @@
464 :
465 : /* the sync process assumes that all the hashes are correct */
466 : /* including the ones from CHG and DELETED blocks */
- 467 68 : assert(state->clear_past_hash != 0);
+ 467 76 : assert(state->clear_past_hash != 0);
468 :
469 : /* get the present time */
- 470 68 : now = time(0);
+ 470 76 : now = time(0);
471 :
472 : /* maps the disks to handles */
- 473 68 : handle = handle_map(state, &diskmax);
+ 473 76 : handle = handle_map(state, &diskmax);
474 :
475 : /* rehash buffers */
- 476 68 : rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc);
+ 476 76 : rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc);
477 :
478 : /* we need 2 * data + 1 * parity + 1 * zero */
- 479 68 : buffermax = 2 * diskmax + state->level + 1;
+ 479 76 : buffermax = 2 * diskmax + state->level + 1;
480 :
- 481 68 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
- 482 68 : if (!state->opt.skip_self)
+ 481 76 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
+ 482 76 : if (!state->opt.skip_self)
483 0 : mtest_vector(buffermax, state->block_size, buffer);
484 :
485 : /* fill up the zero buffer */
- 486 68 : memset(buffer[buffermax - 1], 0, state->block_size);
- 487 68 : raid_zero(buffer[buffermax - 1]);
+ 486 76 : memset(buffer[buffermax - 1], 0, state->block_size);
+ 487 76 : raid_zero(buffer[buffermax - 1]);
488 :
- 489 68 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct));
- 490 68 : failed_map = malloc_nofail(diskmax * sizeof(unsigned));
+ 489 76 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct));
+ 490 76 : failed_map = malloc_nofail(diskmax * sizeof(unsigned));
491 :
- 492 68 : error = 0;
- 493 68 : silent_error = 0;
- 494 68 : io_error = 0;
+ 492 76 : error = 0;
+ 493 76 : silent_error = 0;
+ 494 76 : io_error = 0;
495 :
496 : /* first count the number of blocks to process */
- 497 68 : countmax = 0;
- 498 366627 : for (i = blockstart; i < blockmax; ++i) {
- 499 366559 : if (!block_is_enabled(i, handle, diskmax))
- 500 284218 : continue;
- 501 82341 : ++countmax;
+ 497 76 : countmax = 0;
+ 498 386198 : for (i = blockstart; i < blockmax; ++i) {
+ 499 386122 : if (!block_is_enabled(i, handle, diskmax))
+ 500 294965 : continue;
+ 501 91157 : ++countmax;
502 : }
503 :
504 : /* compute the autosave size for all disk, even if not read */
505 : /* this makes sense because the speed should be almost the same */
506 : /* if the disks are read in parallel */
- 507 68 : autosavelimit = state->autosave / (diskmax * state->block_size);
- 508 68 : autosavemissing = countmax; /* blocks to do */
- 509 68 : autosavedone = 0; /* blocks done */
+ 507 76 : autosavelimit = state->autosave / (diskmax * state->block_size);
+ 508 76 : autosavemissing = countmax; /* blocks to do */
+ 509 76 : autosavedone = 0; /* blocks done */
510 :
511 : /* drop until now */
- 512 68 : state_usage_waste(state);
+ 512 76 : state_usage_waste(state);
513 :
- 514 68 : countsize = 0;
- 515 68 : countpos = 0;
- 516 68 : if (!state_progress_begin(state, blockstart, blockmax, countmax))
+ 514 76 : countsize = 0;
+ 515 76 : countpos = 0;
+ 516 76 : if (!state_progress_begin(state, blockstart, blockmax, countmax))
517 0 : goto end;
518 :
- 519 366627 : for (i = blockstart; i < blockmax; ++i) {
+ 519 386198 : for (i = blockstart; i < blockmax; ++i) {
520 : unsigned failed_count;
521 : int error_on_this_block;
522 : int silent_error_on_this_block;
@@ -588,27 +588,27 @@
526 : snapraid_info info;
527 : int rehash;
528 :
- 529 366559 : if (!block_is_enabled(i, handle, diskmax))
- 530 284218 : continue;
+ 529 386122 : if (!block_is_enabled(i, handle, diskmax))
+ 530 294965 : continue;
531 :
532 : /* one more block processed for autosave */
- 533 82341 : ++autosavedone;
- 534 82341 : --autosavemissing;
+ 533 91157 : ++autosavedone;
+ 534 91157 : --autosavemissing;
535 :
536 : /* by default process the block, and skip it if something go wrong */
- 537 82341 : error_on_this_block = 0;
- 538 82341 : silent_error_on_this_block = 0;
- 539 82341 : io_error_on_this_block = 0;
- 540 82341 : fixed_error_on_this_block = 0;
+ 537 91157 : error_on_this_block = 0;
+ 538 91157 : silent_error_on_this_block = 0;
+ 539 91157 : io_error_on_this_block = 0;
+ 540 91157 : fixed_error_on_this_block = 0;
541 :
542 : /* keep track of the number of failed blocks */
- 543 82341 : failed_count = 0;
+ 543 91157 : failed_count = 0;
544 :
545 : /* get block specific info */
- 546 82341 : info = info_get(&state->infoarr, i);
+ 546 91157 : info = info_get(&state->infoarr, i);
547 :
548 : /* if we have to use the old hash */
- 549 82341 : rehash = info_get_rehash(info);
+ 549 91157 : rehash = info_get_rehash(info);
550 :
551 : /* it could happens that all the blocks are EMPTY/BLK and CHG but with the hash */
552 : /* still matching because the specific CHG block was not modified. */
@@ -616,55 +616,55 @@
554 : /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */
555 : /* We are treating only CHG blocks created at runtime. */
556 : /* In such case, we can avoid to update parity, because it would be the same as before */
- 557 82341 : parity_needs_to_be_updated = 0;
+ 557 91157 : parity_needs_to_be_updated = state->opt.force_parity_update;
558 :
559 : /* if the block is marked as bad, we force the parity update */
560 : /* because the bad block may be the result of a wrong parity */
- 561 82341 : if (info_get_bad(info))
+ 561 91157 : if (info_get_bad(info))
562 0 : parity_needs_to_be_updated = 1;
563 :
564 : /* for each disk, process the block */
- 565 576387 : for (j = 0; j < diskmax; ++j) {
+ 565 638099 : for (j = 0; j < diskmax; ++j) {
566 : int read_size;
567 : unsigned char hash[HASH_SIZE];
568 : struct snapraid_block* block;
569 : unsigned block_state;
- 570 494046 : struct snapraid_disk* disk = handle[j].disk;
+ 570 546942 : struct snapraid_disk* disk = handle[j].disk;
571 : struct snapraid_file* file;
572 : block_off_t file_pos;
573 :
574 : /* by default no rehash in case of "continue" */
- 575 494046 : rehandle[j].block = 0;
+ 575 546942 : rehandle[j].block = 0;
576 :
577 : /* if the disk position is not used */
- 578 494046 : if (!disk) {
+ 578 546942 : if (!disk) {
579 : /* use an empty block */
580 0 : memset(buffer[j], 0, state->block_size);
- 581 89194 : continue;
+ 581 91088 : continue;
582 : }
583 :
584 : /* get the block */
- 585 494046 : block = fs_par2block_get(disk, i);
+ 585 546942 : block = fs_par2block_get(disk, i);
586 :
587 : /* get the state of the block */
- 588 494046 : block_state = block_state_get(block);
+ 588 546942 : block_state = block_state_get(block);
589 :
590 : /* if the block has invalid parity, */
591 : /* we have to take care of it in case of recover */
- 592 494046 : if (block_has_invalid_parity(block)) {
+ 592 546942 : if (block_has_invalid_parity(block)) {
593 : /* store it in the failed set, because */
594 : /* the parity may be still computed with the previous content */
- 595 180603 : failed[failed_count].index = j;
- 596 180603 : failed[failed_count].size = state->block_size;
- 597 180603 : failed[failed_count].block = block;
- 598 180603 : ++failed_count;
+ 595 234970 : failed[failed_count].index = j;
+ 596 234970 : failed[failed_count].size = state->block_size;
+ 597 234970 : failed[failed_count].block = block;
+ 598 234970 : ++failed_count;
599 :
600 : /* if the block has invalid parity, we have to update the parity */
601 : /* to include this block change */
602 : /* This also apply to CHG blocks, but we are going to handle */
603 : /* later this case to do the updates only if really needed */
- 604 180603 : if (block_state != BLOCK_STATE_CHG)
- 605 56266 : parity_needs_to_be_updated = 1;
+ 604 234970 : if (block_state != BLOCK_STATE_CHG)
+ 605 140521 : parity_needs_to_be_updated = 1;
606 :
607 : /* note that DELETE blocks are skipped in the next check */
608 : /* and we have to store them in the failed blocks */
@@ -675,24 +675,24 @@
613 :
614 : /* if the block has no file, meanining that it's EMPTY or DELETED, */
615 : /* it doesn't partecipate in the new parity computation */
- 616 494046 : if (!block_has_file(block)) {
+ 616 546942 : if (!block_has_file(block)) {
617 : /* use an empty block */
- 618 88293 : memset(buffer[j], 0, state->block_size);
- 619 88293 : continue;
+ 618 90218 : memset(buffer[j], 0, state->block_size);
+ 619 90218 : continue;
620 : }
621 :
622 : /* get the file of this block */
- 623 405753 : file = fs_par2file_get(disk, i, &file_pos);
+ 623 456724 : file = fs_par2file_get(disk, i, &file_pos);
624 :
625 : /* until now is CPU */
- 626 405753 : state_usage_cpu(state);
+ 626 456724 : state_usage_cpu(state);
627 :
628 : /* if the file is different than the current one, close it */
- 629 405753 : if (handle[j].file != 0 && handle[j].file != file) {
+ 629 456724 : if (handle[j].file != 0 && handle[j].file != file) {
630 : /* keep a pointer at the file we are going to close for error reporting */
- 631 168779 : struct snapraid_file* report = handle[j].file;
- 632 168779 : ret = handle_close(&handle[j]);
- 633 168779 : if (ret == -1) {
+ 631 189542 : struct snapraid_file* report = handle[j].file;
+ 632 189542 : ret = handle_close(&handle[j]);
+ 633 189542 : if (ret == -1) {
634 : /* LCOV_EXCL_START */
635 : /* This one is really an unexpected error, because we are only reading */
636 : /* and closing a descriptor should never fail */
@@ -715,8 +715,8 @@
653 : }
654 : }
655 :
- 656 405753 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
- 657 405753 : if (ret == -1) {
+ 656 456724 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
+ 657 456724 : if (ret == -1) {
658 12 : if (errno == EIO) {
659 : /* LCOV_EXCL_START */
660 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
@@ -762,10 +762,10 @@
700 : }
701 :
702 : /* check if the file is changed */
- 703 405741 : if (handle[j].st.st_size != file->size
- 704 405739 : || handle[j].st.st_mtime != file->mtime_sec
- 705 405737 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
- 706 405737 : || handle[j].st.st_ino != file->inode
+ 703 456712 : if (handle[j].st.st_size != file->size
+ 704 456710 : || handle[j].st.st_mtime != file->mtime_sec
+ 705 456708 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
+ 706 456708 : || handle[j].st.st_ino != file->inode
707 : ) {
708 6 : log_tag("error:%u:%s:%s: Unexpected attribute change\n", i, disk->name, esc(file->sub));
709 6 : if (handle[j].st.st_size != file->size) {
@@ -785,8 +785,8 @@
723 6 : continue;
724 : }
725 :
- 726 405735 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0);
- 727 405735 : if (read_size == -1) {
+ 726 456706 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0);
+ 727 456706 : if (read_size == -1) {
728 : /* LCOV_EXCL_START */
729 : if (errno == EIO) {
730 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc(file->sub), file_pos, strerror(errno));
@@ -814,26 +814,26 @@
752 : }
753 :
754 : /* until now is disk */
- 755 405735 : state_usage_disk(state, disk);
+ 755 456706 : state_usage_disk(state, disk);
756 :
- 757 405735 : countsize += read_size;
+ 757 456706 : countsize += read_size;
758 :
759 : /* now compute the hash */
- 760 405735 : if (rehash) {
- 761 52244 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
+ 760 456706 : if (rehash) {
+ 761 27231 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
762 :
763 : /* compute the new hash, and store it */
- 764 52244 : rehandle[j].block = block;
- 765 52244 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size);
+ 764 27231 : rehandle[j].block = block;
+ 765 27231 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size);
766 : } else {
- 767 353491 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
+ 767 429475 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
768 : }
769 :
- 770 405735 : if (block_has_updated_hash(block)) {
+ 770 456706 : if (block_has_updated_hash(block)) {
771 : /* compare the hash */
- 772 281416 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 772 362275 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
773 : /* if the file has invalid parity, it's a REP changed during the sync */
- 774 883 : if (block_has_invalid_parity(block)) {
+ 774 852 : if (block_has_invalid_parity(block)) {
775 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc(file->sub));
776 1 : log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos);
777 1 : log_error("WARNING! Unexpected data modification of a file without parity!\n");
@@ -854,48 +854,48 @@
792 1 : error_on_this_block = 1;
793 1 : continue;
794 : } else { /* otherwise it's a BLK with silent error */
- 795 882 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE);
- 796 882 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff);
- 797 882 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", handle[j].path, file_pos, diff);
+ 795 851 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE);
+ 796 851 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff);
+ 797 851 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", handle[j].path, file_pos, diff);
798 :
799 : /* save the failed block for the fix */
- 800 882 : failed[failed_count].index = j;
- 801 882 : failed[failed_count].size = read_size;
- 802 882 : failed[failed_count].block = block;
- 803 882 : ++failed_count;
+ 800 851 : failed[failed_count].index = j;
+ 801 851 : failed[failed_count].size = read_size;
+ 802 851 : failed[failed_count].block = block;
+ 803 851 : ++failed_count;
804 :
805 : /* silent errors are very rare, and are not a signal that a disk */
806 : /* is going to fail. So, we just continue marking the block as bad */
807 : /* just like in scrub */
- 808 882 : ++silent_error;
- 809 882 : silent_error_on_this_block = 1;
- 810 882 : continue;
+ 808 851 : ++silent_error;
+ 809 851 : silent_error_on_this_block = 1;
+ 810 851 : continue;
811 : }
812 : }
813 : } else {
814 : /* if until now the parity doesn't need to be updated */
- 815 124319 : if (!parity_needs_to_be_updated) {
+ 815 94431 : if (!parity_needs_to_be_updated) {
816 : /* for sure it's a CHG block, because EMPTY are processed before with "continue" */
817 : /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */
818 : /* have "parity_needs_to_be_updated" already at 1 */
- 819 56741 : assert(block_state_get(block) == BLOCK_STATE_CHG);
+ 819 35089 : assert(block_state_get(block) == BLOCK_STATE_CHG);
820 :
821 : /* if there is an hash */
- 822 56741 : if (hash_is_real(block->hash)) {
+ 822 35089 : if (hash_is_real(block->hash)) {
823 : /* check if the hash is changed */
- 824 13014 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
+ 824 8465 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
825 : /* the block is different, and we must update parity */
- 826 10443 : parity_needs_to_be_updated = 1;
+ 826 5991 : parity_needs_to_be_updated = 1;
827 : }
828 : } else {
829 : /* if the hash is already invalid, we update parity */
- 830 43727 : parity_needs_to_be_updated = 1;
+ 830 26624 : parity_needs_to_be_updated = 1;
831 : }
832 : }
833 :
834 : /* copy the hash in the block, but doesn't mark the block as hashed */
835 : /* this allow in case of skipped block to do not save the failed computation */
- 836 124319 : memcpy(block->hash, hash, HASH_SIZE);
+ 836 94431 : memcpy(block->hash, hash, HASH_SIZE);
837 :
838 : /* note that in case of rehash, this is the wrong hash, */
839 : /* but it will be overwritten later */
@@ -905,52 +905,52 @@
843 : /* if we have only silent errors we can try to fix them on-the-fly */
844 : /* note the the fix is not written to disk, but used only to */
845 : /* compute the new parity */
- 846 82341 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) {
+ 846 91157 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) {
847 : unsigned failed_mac;
- 848 882 : int something_to_recover = 0;
+ 848 851 : int something_to_recover = 0;
849 :
850 : /* setup the blocks to recover */
- 851 882 : failed_mac = 0;
- 852 2646 : for (j = 0; j < failed_count; ++j) {
- 853 1764 : unsigned char* block_buffer = buffer[failed[j].index];
- 854 1764 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index];
- 855 1764 : unsigned block_state = block_state_get(failed[j].block);
+ 851 851 : failed_mac = 0;
+ 852 2553 : for (j = 0; j < failed_count; ++j) {
+ 853 1702 : unsigned char* block_buffer = buffer[failed[j].index];
+ 854 1702 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index];
+ 855 1702 : unsigned block_state = block_state_get(failed[j].block);
856 :
857 : /* we try to recover only if at least one BLK is present */
- 858 1764 : if (block_state == BLOCK_STATE_BLK)
- 859 882 : something_to_recover = 1;
+ 858 1702 : if (block_state == BLOCK_STATE_BLK)
+ 859 851 : something_to_recover = 1;
860 :
861 : /* save a copy of the content just read */
862 : /* that it's going to be overwritten by the recovering function */
- 863 1764 : memcpy(block_copy, block_buffer, state->block_size);
+ 863 1702 : memcpy(block_copy, block_buffer, state->block_size);
864 :
- 865 1764 : if (block_state == BLOCK_STATE_CHG
- 866 882 : && hash_is_zero(failed[j].block->hash)
+ 865 1702 : if (block_state == BLOCK_STATE_CHG
+ 866 851 : && hash_is_zero(failed[j].block->hash)
867 : ) {
868 : /* if the block was filled with 0, restore this state */
869 : /* and avoid to recover it */
870 0 : memset(block_buffer, 0, state->block_size);
871 : } else {
872 : /* if we have too many failures, we cannot recover */
- 873 1764 : if (failed_mac >= state->level)
+ 873 1702 : if (failed_mac >= state->level)
874 0 : break;
875 :
876 : /* otherwise it has to be recovered */
- 877 1764 : failed_map[failed_mac++] = failed[j].index;
+ 877 1702 : failed_map[failed_mac++] = failed[j].index;
878 : }
879 : }
880 :
881 : /* if we have something to recover and enough parity */
- 882 882 : if (something_to_recover && j == failed_count) {
+ 882 851 : if (something_to_recover && j == failed_count) {
883 : /* until now is CPU */
- 884 882 : state_usage_cpu(state);
+ 884 851 : state_usage_cpu(state);
885 :
886 : /* read the parity */
887 : /* we are sure that parity exists because */
888 : /* we have at least one BLK block */
- 889 6174 : for (l = 0; l < state->level; ++l) {
- 890 5292 : ret = parity_read(parity[l], i, buffer[diskmax + l], state->block_size, log_error);
- 891 5292 : if (ret == -1) {
+ 889 5957 : for (l = 0; l < state->level; ++l) {
+ 890 5106 : ret = parity_read(parity[l], i, buffer[diskmax + l], state->block_size, log_error);
+ 891 5106 : if (ret == -1) {
892 : /* LCOV_EXCL_START */
893 : if (errno == EIO) {
894 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", i, lev_config_name(l), strerror(errno));
@@ -978,74 +978,74 @@
916 : }
917 :
918 : /* until now is parity */
- 919 5292 : state_usage_parity(state, l);
+ 919 5106 : state_usage_parity(state, l);
920 : }
921 :
922 : /* if no error in parity read */
- 923 882 : if (!io_error_on_this_block) {
+ 923 851 : if (!io_error_on_this_block) {
924 : /* try to fix the data */
925 : /* note that this is a simple fix algorithm, that doesn't take into */
926 : /* account the case of a wrong parity */
927 : /* only 'fix' supports the most advanced fixing */
- 928 882 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer);
+ 928 851 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer);
929 :
930 : /* check the result and prepare the data */
- 931 5292 : for (j = 0; j < failed_count; ++j) {
+ 931 5106 : for (j = 0; j < failed_count; ++j) {
932 : unsigned char hash[HASH_SIZE];
- 933 1764 : unsigned char* block_buffer = buffer[failed[j].index];
- 934 1764 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index];
- 935 1764 : unsigned block_state = block_state_get(failed[j].block);
+ 933 1702 : unsigned char* block_buffer = buffer[failed[j].index];
+ 934 1702 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index];
+ 935 1702 : unsigned block_state = block_state_get(failed[j].block);
936 :
- 937 1764 : if (block_state == BLOCK_STATE_BLK) {
- 938 882 : unsigned size = failed[j].size;
+ 937 1702 : if (block_state == BLOCK_STATE_BLK) {
+ 938 851 : unsigned size = failed[j].size;
939 :
940 : /* compute the hash of the recovered block */
- 941 882 : if (rehash) {
+ 941 851 : if (rehash) {
942 0 : memhash(state->prevhash, state->prevhashseed, hash, block_buffer, size);
943 : } else {
- 944 882 : memhash(state->hash, state->hashseed, hash, block_buffer, size);
+ 944 851 : memhash(state->hash, state->hashseed, hash, block_buffer, size);
945 : }
946 :
947 : /* if the hash doesn't match */
- 948 882 : if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) {
+ 948 851 : if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) {
949 : /* we have not recovered */
950 0 : break;
951 : }
952 :
953 : /* pad with 0 if needed */
- 954 882 : if (size < state->block_size)
- 955 342 : memset(block_buffer + size, 0, state->block_size - size);
+ 954 851 : if (size < state->block_size)
+ 955 325 : memset(block_buffer + size, 0, state->block_size - size);
956 : } else {
957 : /* otherwise restore the content */
958 : /* because we are not interested in the old state */
959 : /* that it's recovered for CHG, REP and DELETED blocks */
- 960 882 : memcpy(block_buffer, block_copy, state->block_size);
+ 960 851 : memcpy(block_buffer, block_copy, state->block_size);
961 : }
962 : }
963 :
964 : /* if all is processed, we have fixed it */
- 965 882 : if (j == failed_count)
- 966 882 : fixed_error_on_this_block = 1;
+ 965 851 : if (j == failed_count)
+ 966 851 : fixed_error_on_this_block = 1;
967 : }
968 : }
969 : }
970 :
971 : /* if we have read all the data required and it's correct, proceed with the parity */
- 972 82341 : if (!error_on_this_block && !io_error_on_this_block
- 973 82322 : && (!silent_error_on_this_block || fixed_error_on_this_block)
+ 972 91157 : if (!error_on_this_block && !io_error_on_this_block
+ 973 91138 : && (!silent_error_on_this_block || fixed_error_on_this_block)
974 : ) {
975 : /* update the parity only if really needed */
- 976 82322 : if (parity_needs_to_be_updated) {
+ 976 91138 : if (parity_needs_to_be_updated) {
977 : /* compute the parity */
- 978 79972 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 978 88856 : raid_gen(diskmax, state->level, state->block_size, buffer);
979 :
980 : /* until now is CPU */
- 981 79972 : state_usage_cpu(state);
+ 981 88856 : state_usage_cpu(state);
982 :
983 : /* write the parity */
- 984 523484 : for (l = 0; l < state->level; ++l) {
- 985 443512 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
- 986 443512 : if (ret == -1) {
+ 984 585697 : for (l = 0; l < state->level; ++l) {
+ 985 496841 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
+ 986 496841 : if (ret == -1) {
987 : /* LCOV_EXCL_START */
988 : if (errno == EIO) {
989 : log_tag("parity_error:%u:%s: Write EIO error. %s\n", i, lev_config_name(l), strerror(errno));
@@ -1073,35 +1073,35 @@
1011 : }
1012 :
1013 : /* until now is parity */
- 1014 443512 : state_usage_parity(state, l);
+ 1014 496841 : state_usage_parity(state, l);
1015 : }
1016 : }
1017 :
1018 : /* if no error in parity write */
- 1019 82322 : if (!io_error_on_this_block) {
+ 1019 91138 : if (!io_error_on_this_block) {
1020 : /* for each disk, mark the blocks as processed */
- 1021 576254 : for (j = 0; j < diskmax; ++j) {
+ 1021 637966 : for (j = 0; j < diskmax; ++j) {
1022 : struct snapraid_block* block;
1023 :
- 1024 493932 : if (!handle[j].disk)
+ 1024 546828 : if (!handle[j].disk)
1025 0 : continue;
1026 :
- 1027 493932 : block = fs_par2block_get(handle[j].disk, i);
+ 1027 546828 : block = fs_par2block_get(handle[j].disk, i);
1028 :
- 1029 493932 : if (block == BLOCK_EMPTY) {
+ 1029 546828 : if (block == BLOCK_EMPTY) {
1030 : /* nothing to do */
- 1031 77225 : continue;
+ 1031 79287 : continue;
1032 : }
1033 :
1034 : /* if it's a deleted block */
- 1035 416707 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
+ 1035 467541 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
1036 : /* the parity is now updated without this block, so it's now empty */
- 1037 11066 : fs_deallocate(handle[j].disk, i);
- 1038 11066 : continue;
+ 1037 10929 : fs_deallocate(handle[j].disk, i);
+ 1038 10929 : continue;
1039 : }
1040 :
1041 : /* now all the blocks have the hash and the parity computed */
- 1042 405641 : block_state_set(block, BLOCK_STATE_BLK);
+ 1042 456612 : block_state_set(block, BLOCK_STATE_BLK);
1043 : }
1044 : }
1045 :
@@ -1110,52 +1110,52 @@
1048 : /* wrote the parity at this time */
1049 : /* we also update the info block only if no silent error was found */
1050 : /* because has no sense to refresh the time for data that we know bad */
- 1051 82322 : if (parity_needs_to_be_updated
- 1052 79972 : && !silent_error_on_this_block
- 1053 79625 : && !io_error_on_this_block
+ 1051 91138 : if (parity_needs_to_be_updated
+ 1052 88856 : && !silent_error_on_this_block
+ 1053 88511 : && !io_error_on_this_block
1054 : ) {
1055 : /* if rehash is neeed */
- 1056 79625 : if (rehash) {
+ 1056 88511 : if (rehash) {
1057 : /* store all the new hash already computed */
- 1058 64358 : for (j = 0; j < diskmax; ++j) {
- 1059 55164 : if (rehandle[j].block)
- 1060 52244 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE);
+ 1058 32221 : for (j = 0; j < diskmax; ++j) {
+ 1059 27618 : if (rehandle[j].block)
+ 1060 27231 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE);
1061 : }
1062 : }
1063 :
1064 : /* update the time info of the block */
1065 : /* we are also clearing any previous bad and rehash flag */
- 1066 79625 : info_set(&state->infoarr, i, info_make(now, 0, 0, 1));
+ 1066 88511 : info_set(&state->infoarr, i, info_make(now, 0, 0, 1));
1067 : }
1068 : }
1069 :
1070 : /* if a silent (even if corrected) or input/output error was found */
1071 : /* mark the block as bad to have check/fix to handle it */
1072 : /* because our correction is in memory only and not yet written */
- 1073 82341 : if (silent_error_on_this_block || io_error_on_this_block) {
+ 1073 91157 : if (silent_error_on_this_block || io_error_on_this_block) {
1074 : /* set the error status keeping the other info */
- 1075 882 : info_set(&state->infoarr, i, info_set_bad(info));
+ 1075 851 : info_set(&state->infoarr, i, info_set_bad(info));
1076 : }
1077 :
1078 : /* mark the state as needing write */
- 1079 82341 : state->need_write = 1;
+ 1079 91157 : state->need_write = 1;
1080 :
1081 : /* count the number of processed block */
- 1082 82341 : ++countpos;
+ 1082 91157 : ++countpos;
1083 :
1084 : /* progress */
- 1085 82341 : if (state_progress(state, i, countpos, countmax, countsize)) {
+ 1085 91157 : if (state_progress(state, i, countpos, countmax, countsize)) {
1086 : /* LCOV_EXCL_START */
1087 : break;
1088 : /* LCOV_EXCL_STOP */
1089 : }
1090 :
1091 : /* autosave */
- 1092 82341 : if ((state->autosave != 0
- 1093 7264 : && autosavedone >= autosavelimit /* if we have reached the limit */
+ 1092 91157 : if ((state->autosave != 0
+ 1093 7259 : && autosavedone >= autosavelimit /* if we have reached the limit */
1094 0 : && autosavemissing >= autosavelimit) /* if we have at least a full step to do */
1095 : /* or if we have a forced autosave at the specified block */
- 1096 82341 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == i)
+ 1096 91157 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == i)
1097 : ) {
1098 1 : autosavedone = 0; /* restart the counter */
1099 :
@@ -1193,15 +1193,15 @@
1131 : }
1132 :
1133 : end:
- 1134 68 : state_progress_end(state, countpos, countmax, countsize);
+ 1134 76 : state_progress_end(state, countpos, countmax, countsize);
1135 :
- 1136 68 : state_usage_print(state);
+ 1136 76 : state_usage_print(state);
1137 :
1138 : /* before returning we ensure that */
1139 : /* the parity is really written flushing the disk cache */
- 1140 461 : for (l = 0; l < state->level; ++l) {
- 1141 393 : ret = parity_sync(parity[l]);
- 1142 393 : if (ret == -1) {
+ 1140 517 : for (l = 0; l < state->level; ++l) {
+ 1141 441 : ret = parity_sync(parity[l]);
+ 1142 441 : if (ret == -1) {
1143 : /* LCOV_EXCL_START */
1144 : log_tag("parity_error:%u:%s: Sync error\n", i, lev_config_name(l));
1145 : log_fatal("DANGER! Unexpected sync error in %s disk.\n", lev_name(l));
@@ -1213,43 +1213,43 @@
1151 : }
1152 : }
1153 :
- 1154 68 : if (error || silent_error || io_error) {
+ 1154 76 : if (error || silent_error || io_error) {
1155 12 : msg_status("\n");
1156 12 : msg_status("%8u file errors\n", error);
1157 12 : msg_status("%8u io errors\n", io_error);
1158 12 : msg_status("%8u data errors\n", silent_error);
1159 : } else {
1160 : /* print the result only if processed something */
- 1161 56 : if (countpos != 0)
- 1162 42 : msg_status("Everything OK\n");
+ 1161 64 : if (countpos != 0)
+ 1162 47 : msg_status("Everything OK\n");
1163 : }
1164 :
- 1165 68 : if (error)
+ 1165 76 : if (error)
1166 11 : log_fatal("WARNING! Unexpected file errors!\n");
- 1167 68 : if (io_error)
+ 1167 76 : if (io_error)
1168 0 : log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n");
- 1169 68 : if (silent_error)
+ 1169 76 : if (silent_error)
1170 1 : log_fatal("DANGER! Unexpected data errors! The failing blocks are now marked as bad!\n");
- 1171 68 : if (io_error || silent_error) {
+ 1171 76 : if (io_error || silent_error) {
1172 1 : log_fatal("Use 'snapraid status' to list the bad blocks.\n");
1173 1 : log_fatal("Use 'snapraid -e fix' to recover.\n");
1174 : }
1175 :
- 1176 68 : log_tag("summary:error_file:%u\n", error);
- 1177 68 : log_tag("summary:error_io:%u\n", io_error);
- 1178 68 : log_tag("summary:error_data:%u\n", silent_error);
- 1179 68 : if (error + silent_error + io_error == 0)
- 1180 56 : log_tag("summary:exit:ok\n");
+ 1176 76 : log_tag("summary:error_file:%u\n", error);
+ 1177 76 : log_tag("summary:error_io:%u\n", io_error);
+ 1178 76 : log_tag("summary:error_data:%u\n", silent_error);
+ 1179 76 : if (error + silent_error + io_error == 0)
+ 1180 64 : log_tag("summary:exit:ok\n");
1181 : else
1182 12 : log_tag("summary:exit:error\n");
- 1183 68 : log_flush();
+ 1183 76 : log_flush();
1184 :
1185 : bail:
- 1186 476 : for (j = 0; j < diskmax; ++j) {
- 1187 408 : struct snapraid_file* file = handle[j].file;
- 1188 408 : struct snapraid_disk* disk = handle[j].disk;
- 1189 408 : ret = handle_close(&handle[j]);
- 1190 408 : if (ret == -1) {
+ 1186 532 : for (j = 0; j < diskmax; ++j) {
+ 1187 456 : struct snapraid_file* file = handle[j].file;
+ 1188 456 : struct snapraid_disk* disk = handle[j].disk;
+ 1189 456 : ret = handle_close(&handle[j]);
+ 1190 456 : if (ret == -1) {
1191 : /* LCOV_EXCL_START */
1192 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno));
1193 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -1259,24 +1259,24 @@
1197 : }
1198 : }
1199 :
- 1200 68 : free(handle);
- 1201 68 : free(buffer_alloc);
- 1202 68 : free(buffer);
- 1203 68 : free(rehandle_alloc);
- 1204 68 : free(failed);
- 1205 68 : free(failed_map);
+ 1200 76 : free(handle);
+ 1201 76 : free(buffer_alloc);
+ 1202 76 : free(buffer);
+ 1203 76 : free(rehandle_alloc);
+ 1204 76 : free(failed);
+ 1205 76 : free(failed_map);
1206 :
- 1207 68 : if (state->opt.expect_recoverable) {
+ 1207 76 : if (state->opt.expect_recoverable) {
1208 1 : if (error + silent_error + io_error == 0)
1209 0 : return -1;
1210 : } else {
- 1211 67 : if (error + silent_error + io_error != 0)
+ 1211 75 : if (error + silent_error + io_error != 0)
1212 11 : return -1;
1213 : }
- 1214 57 : return 0;
+ 1214 65 : return 0;
1215 : }
1216 :
- 1217 72 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount)
+ 1217 80 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount)
1218 : {
1219 : block_off_t blockmax;
1220 : block_off_t used_paritymax;
@@ -1287,23 +1287,23 @@
1225 : struct snapraid_parity_handle parity[LEV_MAX];
1226 : /* the following initialization is to avoid clang warnings about */
1227 : /* potential state->level change, that never happens */
- 1228 72 : struct snapraid_parity_handle* parity_ptr[LEV_MAX] = { 0 };
+ 1228 80 : struct snapraid_parity_handle* parity_ptr[LEV_MAX] = { 0 };
1229 : unsigned unrecoverable_error;
1230 : unsigned l;
- 1231 72 : int skip_sync = 0;
+ 1231 80 : int skip_sync = 0;
1232 :
- 1233 72 : msg_progress("Initializing...\n");
+ 1233 80 : msg_progress("Initializing...\n");
1234 :
- 1235 72 : blockmax = parity_allocated_size(state);
- 1236 72 : size = blockmax * (data_off_t)state->block_size;
+ 1235 80 : blockmax = parity_allocated_size(state);
+ 1236 80 : size = blockmax * (data_off_t)state->block_size;
1237 :
1238 : /* minum size of the parity files we expect */
- 1239 72 : used_paritymax = parity_used_size(state);
+ 1239 80 : used_paritymax = parity_used_size(state);
1240 :
1241 : /* effective size of the parity files */
- 1242 72 : file_paritymax = 0;
+ 1242 80 : file_paritymax = 0;
1243 :
- 1244 72 : if (blockstart > blockmax) {
+ 1244 80 : if (blockstart > blockmax) {
1245 : /* LCOV_EXCL_START */
1246 : log_fatal("Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
1247 : exit(EXIT_FAILURE);
@@ -1311,17 +1311,17 @@
1249 : }
1250 :
1251 : /* adjust the number of block to process */
- 1252 72 : if (blockcount != 0 && blockstart + blockcount < blockmax) {
+ 1252 80 : if (blockcount != 0 && blockstart + blockcount < blockmax) {
1253 6 : blockmax = blockstart + blockcount;
1254 : }
1255 :
- 1256 489 : for (l = 0; l < state->level; ++l) {
+ 1256 545 : for (l = 0; l < state->level; ++l) {
1257 : block_off_t parityblocks;
1258 :
1259 : /* create the file and open for writing */
- 1260 417 : parity_ptr[l] = &parity[l];
- 1261 417 : ret = parity_create(parity_ptr[l], state->parity[l].path, &out_size, state->file_mode);
- 1262 417 : if (ret == -1) {
+ 1260 465 : parity_ptr[l] = &parity[l];
+ 1261 465 : ret = parity_create(parity_ptr[l], state->parity[l].path, &out_size, state->file_mode);
+ 1262 465 : if (ret == -1) {
1263 : /* LCOV_EXCL_START */
1264 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
1265 : exit(EXIT_FAILURE);
@@ -1329,22 +1329,22 @@
1267 : }
1268 :
1269 : /* number of block in the parity file */
- 1270 417 : parityblocks = out_size / state->block_size;
+ 1270 465 : parityblocks = out_size / state->block_size;
1271 :
1272 : /* if the file is too small */
- 1273 417 : if (parityblocks < used_paritymax) {
+ 1273 465 : if (parityblocks < used_paritymax) {
1274 0 : log_fatal("WARNING! The %s file %s has data only %u blocks instead of %u.\n", lev_name(l), state->parity[l].path, parityblocks, used_paritymax);
1275 : }
1276 :
1277 : /* keep the smallest parity number of blocks */
- 1278 417 : if (l == 0 || file_paritymax > parityblocks)
- 1279 72 : file_paritymax = parityblocks;
+ 1278 465 : if (l == 0 || file_paritymax > parityblocks)
+ 1279 80 : file_paritymax = parityblocks;
1280 : }
1281 :
1282 : /* if we do a full sync, having a wrong parity size is expected */
- 1283 72 : if (!state->opt.force_full) {
+ 1283 80 : if (!state->opt.force_full) {
1284 : /* if the parities are too small */
- 1285 71 : if (file_paritymax < used_paritymax) {
+ 1285 78 : if (file_paritymax < used_paritymax) {
1286 : /* LCOV_EXCL_START */
1287 : log_fatal("DANGER! One or more the parity files are smaller than expected!\n");
1288 : if (file_paritymax != 0) {
@@ -1362,12 +1362,12 @@
1300 : }
1301 :
1302 : /* now change the size of all parities */
- 1303 489 : for (l = 0; l < state->level; ++l) {
+ 1303 545 : for (l = 0; l < state->level; ++l) {
1304 : /* change the size of the parity file, truncating or extending it */
1305 : /* from this point all the DELETED blocks after the end of the parity are invalid */
1306 : /* and they are automatically removed when we save the new content file */
- 1307 417 : ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate);
- 1308 417 : if (ret == -1) {
+ 1307 465 : ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate);
+ 1308 465 : if (ret == -1) {
1309 : /* LCOV_EXCL_START */
1310 : parity_overflow(state, out_size);
1311 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
@@ -1377,11 +1377,11 @@
1315 : }
1316 :
1317 : /* after resizing parity files, refresh again the free info */
- 1318 72 : state_refresh(state);
+ 1318 80 : state_refresh(state);
1319 :
- 1320 72 : unrecoverable_error = 0;
+ 1320 80 : unrecoverable_error = 0;
1321 :
- 1322 72 : if (state->opt.prehash) {
+ 1322 80 : if (state->opt.prehash) {
1323 7 : msg_progress("Hashing...\n");
1324 :
1325 7 : ret = state_hash_process(state, blockstart, blockmax, &skip_sync);
@@ -1394,16 +1394,16 @@
1332 :
1333 : /* save with the new hash information */
1334 7 : if (state->need_write)
- 1335 3 : state_write(state);
+ 1335 2 : state_write(state);
1336 : }
1337 :
- 1338 72 : if (!skip_sync) {
- 1339 71 : msg_progress("Syncing...\n");
+ 1338 80 : if (!skip_sync) {
+ 1339 79 : msg_progress("Syncing...\n");
1340 :
1341 : /* skip degenerated cases of empty parity, or skipping all */
- 1342 71 : if (blockstart < blockmax) {
- 1343 68 : ret = state_sync_process(state, parity_ptr, blockstart, blockmax);
- 1344 68 : if (ret == -1) {
+ 1342 79 : if (blockstart < blockmax) {
+ 1343 76 : ret = state_sync_process(state, parity_ptr, blockstart, blockmax);
+ 1344 76 : if (ret == -1) {
1345 : /* LCOV_EXCL_START */
1346 : ++unrecoverable_error;
1347 : /* continue, as we are already exiting */
@@ -1414,9 +1414,9 @@
1352 : }
1353 : }
1354 :
- 1355 489 : for (l = 0; l < state->level; ++l) {
- 1356 417 : ret = parity_close(parity_ptr[l]);
- 1357 417 : if (ret == -1) {
+ 1355 545 : for (l = 0; l < state->level; ++l) {
+ 1356 465 : ret = parity_close(parity_ptr[l]);
+ 1357 465 : if (ret == -1) {
1358 : /* LCOV_EXCL_START */
1359 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
1360 : ++unrecoverable_error;
@@ -1426,9 +1426,9 @@
1364 : }
1365 :
1366 : /* abort if required */
- 1367 72 : if (unrecoverable_error != 0)
+ 1367 80 : if (unrecoverable_error != 0)
1368 12 : return -1;
- 1369 60 : return 0;
+ 1369 68 : return 0;
1370 : }
1371 :
diff --git a/cov/cmdline/unix.c.func-sort-c.html b/cov/cmdline/unix.c.func-sort-c.html
index 5b352a9b..c194779e 100644
--- a/cov/cmdline/unix.c.func-sort-c.html
+++ b/cov/cmdline/unix.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,87 +60,95 @@
Hit count  |
- | tick |
- 2049010 |
+ tick |
+ 2214352 |
| open_noatime |
- 1640600 |
+ 1661733 |
- | filephy |
+ filephy |
11432 |
- | devuuid |
- 2279 |
+ fsinfo |
+ 2415 |
- | fsinfo |
- 2175 |
+ devuuid |
+ 2404 |
- | randomize |
- 263 |
+ devuuid_dev |
+ 2404 |
- | os_init |
- 252 |
+ randomize |
+ 271 |
- | os_done |
- 230 |
+ os_init |
+ 260 |
- | devresolve |
+ os_done |
+ 238 |
+
+
+ | devresolve |
97 |
- | devread |
+ devread |
86 |
- | devtree |
+ devtree |
72 |
- | tick_ms |
+ tick_ms |
36 |
- | thread_smart |
+ devsmart |
25 |
- | devsmart |
- 25 |
+ thread_smart |
+ 22 |
- | thread_spindown |
+ thread_spindown |
12 |
- | devdown |
+ devdown |
12 |
- | devup |
+ devup |
12 |
- | thread_spinup |
+ thread_spinup |
12 |
- | devquery |
+ devquery |
4 |
- | device_thread |
+ device_thread |
3 |
- | devscan |
+ devscan |
+ 1 |
+
+
+ | devuuid_blkid |
1 |
diff --git a/cov/cmdline/unix.c.func.html b/cov/cmdline/unix.c.func.html
index bd939ad7..c3a13d67 100644
--- a/cov/cmdline/unix.c.func.html
+++ b/cov/cmdline/unix.c.func.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,95 +60,103 @@
Hit count  |
- | devdown |
+ devdown |
12 |
- | device_thread |
+ device_thread |
3 |
- | devquery |
+ devquery |
4 |
- | devread |
+ devread |
86 |
- | devresolve |
+ devresolve |
97 |
- | devscan |
+ devscan |
1 |
- | devsmart |
+ devsmart |
25 |
- | devtree |
+ devtree |
72 |
- | devup |
+ devup |
12 |
- | devuuid |
- 2279 |
+ devuuid |
+ 2404 |
+
+
+ | devuuid_blkid |
+ 1 |
+
+
+ | devuuid_dev |
+ 2404 |
| dirent_hidden |
0 |
- | filephy |
+ filephy |
11432 |
- | fsinfo |
- 2175 |
+ fsinfo |
+ 2415 |
| open_noatime |
- 1640600 |
+ 1661733 |
- | os_done |
- 230 |
+ os_done |
+ 238 |
- | os_init |
- 252 |
+ os_init |
+ 260 |
- | randomize |
- 263 |
+ randomize |
+ 271 |
| stat_desc |
0 |
- | thread_smart |
- 25 |
+ thread_smart |
+ 22 |
- | thread_spindown |
+ thread_spindown |
12 |
- | thread_spinup |
+ thread_spinup |
12 |
- | tick |
- 2049010 |
+ tick |
+ 2214352 |
- | tick_ms |
+ tick_ms |
36 |
diff --git a/cov/cmdline/unix.c.gcov.html b/cov/cmdline/unix.c.gcov.html
index 3a428fcf..59fb3346 100644
--- a/cov/cmdline/unix.c.gcov.html
+++ b/cov/cmdline/unix.c.gcov.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -90,15 +90,15 @@
28 : int exit_failure = 1;
29 : int exit_sync_needed = 2;
30 :
- 31 1640600 : int open_noatime(const char* file, int flags)
+ 31 1661733 : int open_noatime(const char* file, int flags)
32 : {
33 : #ifdef O_NOATIME
- 34 1640600 : int f = open(file, flags | O_NOATIME);
+ 34 1661733 : int f = open(file, flags | O_NOATIME);
35 :
36 : /* only root is allowed to use O_NOATIME, in case retry without it */
- 37 1640600 : if (f == -1 && errno == EPERM)
+ 37 1661733 : if (f == -1 && errno == EPERM)
38 0 : f = open(file, flags);
- 39 1640600 : return f;
+ 39 1661733 : return f;
40 : #else
41 : return open(file, flags);
42 : #endif
@@ -130,952 +130,1123 @@
68 0 : return "unknown";
69 : }
70 :
- 71 : #if HAVE_FSTATAT
- 72 : /**
- 73 : * This function get the UUID using the /dev/disk/by-uuid/ links.
- 74 : * Comparing with the libblkid library, it works also from not root processes.
- 75 : */
- 76 2279 : int devuuid(uint64_t device, char* uuid, size_t uuid_size)
- 77 : {
- 78 : int ret;
- 79 : DIR* d;
- 80 : struct dirent* dd;
- 81 : struct stat st;
- 82 :
- 83 : /* scan the UUID directory searching for the device */
- 84 2279 : d = opendir("/dev/disk/by-uuid");
- 85 2279 : if (!d) {
- 86 : /* directory missing?, likely we are not in Linux */
- 87 0 : return -1;
- 88 : }
- 89 :
- 90 38781 : while ((dd = readdir(d)) != 0) {
- 91 : /* skip "." and ".." files, UUIDs never start with '.' */
- 92 36500 : if (dd->d_name[0] == '.')
- 93 4558 : continue;
- 94 :
- 95 31942 : ret = fstatat(dirfd(d), dd->d_name, &st, 0);
- 96 31942 : if (ret != 0) {
- 97 : /* generic error, ignore and continue the search */
- 98 0 : continue;
- 99 : }
- 100 :
- 101 : /* if it matches, we have the uuid */
- 102 31942 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) {
- 103 : /* found */
- 104 2277 : pathcpy(uuid, uuid_size, dd->d_name);
- 105 2277 : closedir(d);
- 106 2277 : return 0;
- 107 : }
- 108 : }
- 109 :
- 110 : /* not found */
- 111 2 : closedir(d);
- 112 2 : return -1;
- 113 : }
- 114 : #else
- 115 : int devuuid(uint64_t device, char* uuid, size_t uuid_size)
- 116 : {
- 117 : (void)device;
- 118 : (void)uuid;
- 119 : (void)uuid_size;
- 120 :
- 121 : /* not supported */
- 122 : return -1;
- 123 : }
- 124 : #endif
- 125 :
- 126 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical)
- 127 : {
- 128 : #if HAVE_LINUX_FIEMAP_H
- 129 : /* In Linux get the real physical address of the file */
- 130 : /* Note that FIEMAP doesn't require root permission */
- 131 : int f;
- 132 : struct {
- 133 : struct fiemap fiemap;
- 134 : struct fiemap_extent extent;
- 135 : } fm;
- 136 : unsigned int blknum;
- 137 :
- 138 11432 : f = open(path, O_RDONLY);
- 139 11432 : if (f == -1) {
- 140 0 : return -1;
- 141 : }
+ 71 : /**
+ 72 : * Cache used by blkid.
+ 73 : */
+ 74 : #if HAVE_BLKID
+ 75 : static blkid_cache cache = 0;
+ 76 : #endif
+ 77 :
+ 78 : /**
+ 79 : * Get the UUID using the /dev/disk/by-uuid/ links.
+ 80 : * It doesn't require root permission, and the uuid are always updated.
+ 81 : * It doesn't work with Btrfs file-systems that don't export the main UUID
+ 82 : * in /dev/disk/by-uuid/.
+ 83 : */
+ 84 : #if HAVE_FSTATAT
+ 85 2404 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
+ 86 : {
+ 87 : int ret;
+ 88 : DIR* d;
+ 89 : struct dirent* dd;
+ 90 : struct stat st;
+ 91 :
+ 92 : /* scan the UUID directory searching for the device */
+ 93 2404 : d = opendir("/dev/disk/by-uuid");
+ 94 2404 : if (!d) {
+ 95 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed\n", major(device), minor(device));
+ 96 : /* directory missing?, likely we are not in Linux */
+ 97 0 : return -1;
+ 98 : }
+ 99 :
+ 100 40887 : while ((dd = readdir(d)) != 0) {
+ 101 : /* skip "." and ".." files, UUIDs never start with '.' */
+ 102 38482 : if (dd->d_name[0] == '.')
+ 103 4808 : continue;
+ 104 :
+ 105 33674 : ret = fstatat(dirfd(d), dd->d_name, &st, 0);
+ 106 33674 : if (ret != 0) {
+ 107 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed\n", major(device), minor(device), dd->d_name);
+ 108 : /* generic error, ignore and continue the search */
+ 109 0 : continue;
+ 110 : }
+ 111 :
+ 112 : /* if it matches, we have the uuid */
+ 113 33674 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) {
+ 114 : char buf[PATH_MAX];
+ 115 : char path[PATH_MAX];
+ 116 :
+ 117 : /* resolve the link */
+ 118 2403 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name);
+ 119 2403 : ret = readlink(path, buf, sizeof(buf));
+ 120 2403 : if (ret < 0 || ret == sizeof(buf)) {
+ 121 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed\n", major(device), minor(device), dd->d_name);
+ 122 : /* generic error, ignore and continue the search */
+ 123 0 : continue;
+ 124 : }
+ 125 2403 : buf[ret] = 0;
+ 126 :
+ 127 : /* found */
+ 128 2403 : pathcpy(uuid, uuid_size, dd->d_name);
+ 129 :
+ 130 2403 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf);
+ 131 :
+ 132 2403 : closedir(d);
+ 133 2403 : return 0;
+ 134 : }
+ 135 : }
+ 136 :
+ 137 : /* not found */
+ 138 1 : closedir(d);
+ 139 1 : return -1;
+ 140 : }
+ 141 : #endif
142 :
- 143 : /* first try with FIEMAP */
- 144 : /* if works for ext2, ext3, ext4, xfs, btrfs */
- 145 11432 : memset(&fm, 0, sizeof(fm));
- 146 11432 : fm.fiemap.fm_start = 0;
- 147 11432 : fm.fiemap.fm_length = ~0ULL;
- 148 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
- 149 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
- 150 :
- 151 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) {
- 152 11432 : *physical = fm.fiemap.fm_extents[0].fe_physical + FILEPHY_REAL_OFFSET;
- 153 11432 : if (close(f) == -1)
- 154 0 : return -1;
- 155 11432 : return 0;
- 156 : }
- 157 :
- 158 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */
- 159 0 : if (size == 0) {
- 160 0 : *physical = FILEPHY_WITHOUT_OFFSET;
- 161 0 : if (close(f) == -1)
- 162 0 : return -1;
- 163 0 : return 0;
- 164 : }
- 165 :
- 166 : /* then try with FIBMAP */
- 167 : /* it works for jfs, reiserfs, ntfs-3g */
- 168 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */
- 169 0 : blknum = 0; /* first block */
- 170 0 : if (ioctl(f, FIBMAP, &blknum) != -1) {
- 171 0 : *physical = blknum + FILEPHY_REAL_OFFSET;
- 172 0 : if (close(f) == -1)
- 173 0 : return -1;
- 174 0 : return 0;
- 175 : }
- 176 :
- 177 : /* otherwise don't use anything, and keep the directory traversal order */
- 178 : /* at now this should happen only for vfat */
- 179 : /* and it's surely better than using fake inodes */
- 180 0 : *physical = FILEPHY_UNREPORTED_OFFSET;
- 181 0 : if (close(f) == -1)
- 182 0 : return -1;
- 183 : #else
- 184 : /* In a generic Unix use a dummy value for all the files */
- 185 : /* We don't want to risk to use the inode without knowing */
- 186 : /* if it really improves performance. */
- 187 : /* In this way we keep them in the directory traversal order */
- 188 : /* that at least keeps files in the same directory together. */
- 189 : /* Note also that in newer filesystem with snapshot, like ZFS, */
- 190 : /* the inode doesn't represent even less the disk position, because files */
- 191 : /* are not overwritten in place, but rewritten in another location */
- 192 : /* of the disk. */
- 193 : *physical = FILEPHY_UNREPORTED_OFFSET;
- 194 :
- 195 : (void)path; /* not used here */
- 196 : (void)size;
- 197 : #endif
- 198 :
- 199 0 : return 0;
- 200 : }
- 201 :
- 202 2175 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space)
- 203 : {
- 204 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
- 205 : struct statfs st;
- 206 :
- 207 2175 : if (statfs(path, &st) != 0) {
- 208 : char dir[PATH_MAX];
- 209 : char* slash;
- 210 :
- 211 6 : if (errno != ENOENT) {
- 212 0 : return -1;
- 213 : }
- 214 :
- 215 : /* if it doesn't exist, we assume a file */
- 216 : /* and we check for the containing dir */
- 217 6 : if (strlen(path) + 1 > sizeof(dir)) {
- 218 0 : errno = ENAMETOOLONG;
- 219 0 : return -1;
- 220 : }
- 221 :
- 222 6 : strcpy(dir, path);
- 223 :
- 224 6 : slash = strrchr(dir, '/');
- 225 6 : if (!slash)
- 226 0 : return -1;
- 227 :
- 228 6 : *slash = 0;
- 229 6 : if (statfs(dir, &st) != 0)
- 230 0 : return -1;
- 231 : }
+ 143 : /**
+ 144 : * Get the UUID using liblkid.
+ 145 : * It uses a cache to work without root permission, resultin in UUID
+ 146 : * not necessarily recent.
+ 147 : * We could call blkid_probe_all() to refresh the UUID, but it would
+ 148 : * require root permission to read the superblocks, and to have
+ 149 : * all the disks spinning.
+ 150 : */
+ 151 : #if HAVE_BLKID
+ 152 1 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size)
+ 153 : {
+ 154 : char* devname;
+ 155 : char* uuidname;
+ 156 :
+ 157 1 : devname = blkid_devno_to_devname(device);
+ 158 1 : if (!devname) {
+ 159 1 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed\n", major(device), minor(device));
+ 160 : /* device mapping failed */
+ 161 1 : return -1;
+ 162 : }
+ 163 :
+ 164 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname);
+ 165 0 : if (!uuidname) {
+ 166 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(%s) failed\n", major(device), minor(device), devname);
+ 167 : /* uuid mapping failed */
+ 168 0 : free(devname);
+ 169 0 : return -1;
+ 170 : }
+ 171 :
+ 172 0 : pathcpy(uuid, uuid_size, uuidname);
+ 173 :
+ 174 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname);
+ 175 :
+ 176 0 : free(devname);
+ 177 0 : free(uuidname);
+ 178 0 : return 0;
+ 179 : }
+ 180 : #endif
+ 181 :
+ 182 2404 : int devuuid(uint64_t device, char* uuid, size_t uuid_size)
+ 183 : {
+ 184 : /* first try with the /dev/disk/by-uuid version */
+ 185 : #if HAVE_FSTATAT
+ 186 2404 : if (devuuid_dev(device, uuid, uuid_size) == 0)
+ 187 2403 : return 0;
+ 188 : #endif
+ 189 :
+ 190 : /* fall back to blkid for other cases */
+ 191 : #if HAVE_BLKID
+ 192 1 : if (devuuid_blkid(device, uuid, uuid_size) == 0)
+ 193 0 : return 0;
+ 194 : #endif
+ 195 :
+ 196 1 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device));
+ 197 :
+ 198 : /* not supported */
+ 199 : (void)uuid;
+ 200 : (void)uuid_size;
+ 201 1 : return -1;
+ 202 : }
+ 203 :
+ 204 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical)
+ 205 : {
+ 206 : #if HAVE_LINUX_FIEMAP_H
+ 207 : /* In Linux get the real physical address of the file */
+ 208 : /* Note that FIEMAP doesn't require root permission */
+ 209 : int f;
+ 210 : struct {
+ 211 : struct fiemap fiemap;
+ 212 : struct fiemap_extent extent;
+ 213 : } fm;
+ 214 : unsigned int blknum;
+ 215 :
+ 216 11432 : f = open(path, O_RDONLY);
+ 217 11432 : if (f == -1) {
+ 218 0 : return -1;
+ 219 : }
+ 220 :
+ 221 : /* first try with FIEMAP */
+ 222 : /* if works for ext2, ext3, ext4, xfs, btrfs */
+ 223 11432 : memset(&fm, 0, sizeof(fm));
+ 224 11432 : fm.fiemap.fm_start = 0;
+ 225 11432 : fm.fiemap.fm_length = ~0ULL;
+ 226 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
+ 227 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
+ 228 :
+ 229 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) {
+ 230 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags;
+ 231 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical;
232 :
- 233 : /* to get the fs type check "man stat" or "stat -f -t FILE" */
- 234 2175 : if (has_persistent_inode)
- 235 479 : switch (st.f_type) {
- 236 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */
- 237 : case 0x4d44 : /* VFAT, "msdos" in the stat command */
- 238 0 : *has_persistent_inode = 0;
- 239 0 : break;
- 240 : default :
- 241 : /* by default assume yes */
- 242 479 : *has_persistent_inode = 1;
- 243 479 : break;
- 244 : }
- 245 :
- 246 2175 : if (total_space)
- 247 1696 : *total_space = st.f_bsize * (uint64_t)st.f_blocks;
- 248 2175 : if (free_space)
- 249 1696 : *free_space = st.f_bsize * (uint64_t)st.f_bfree;
- 250 : #else
- 251 : (void)path;
- 252 :
- 253 : /* by default assume yes */
- 254 : if (has_persistent_inode)
- 255 : *has_persistent_inode = 1;
- 256 : if (total_space)
- 257 : *total_space = 0;
- 258 : if (free_space)
- 259 : *free_space = 0;
- 260 : #endif
+ 233 : /* check some condition for validating the offset */
+ 234 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) {
+ 235 : /* if the data is inline, we don't have an offset to report */
+ 236 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 237 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) {
+ 238 : /* if the offset is unknown, we don't have an offset to report */
+ 239 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 240 11432 : } else if (offset == 0) {
+ 241 : /* 0 is the general fallback for file-systems when */
+ 242 : /* they don't have an offset to report */
+ 243 14 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 244 : } else {
+ 245 : /* finally report the real offset */
+ 246 11418 : *physical = offset + FILEPHY_REAL_OFFSET;
+ 247 : }
+ 248 :
+ 249 11432 : if (close(f) == -1)
+ 250 0 : return -1;
+ 251 11432 : return 0;
+ 252 : }
+ 253 :
+ 254 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */
+ 255 0 : if (size == 0) {
+ 256 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 257 0 : if (close(f) == -1)
+ 258 0 : return -1;
+ 259 0 : return 0;
+ 260 : }
261 :
- 262 2175 : return 0;
- 263 : }
- 264 :
- 265 2049010 : uint64_t tick(void)
- 266 : {
- 267 : #if HAVE_MACH_ABSOLUTE_TIME
- 268 : /* for Mac OS X */
- 269 : return mach_absolute_time();
- 270 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW))
- 271 : /* for Linux */
- 272 : struct timespec tv;
- 273 :
- 274 : /* nanosecond precision with clock_gettime() */
- 275 : #if defined(CLOCK_MONOTONIC_RAW)
- 276 2049010 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) {
- 277 : #else
- 278 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) {
- 279 : #endif
- 280 0 : return 0;
- 281 : }
- 282 :
- 283 2049010 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec;
- 284 : #else
- 285 : /* other platforms */
- 286 : struct timeval tv;
- 287 :
- 288 : /* microsecond precision with gettimeofday() */
- 289 : if (gettimeofday(&tv, 0) != 0) {
- 290 : return 0;
- 291 : }
- 292 :
- 293 : return tv.tv_sec * 1000000ULL + tv.tv_usec;
- 294 : #endif
- 295 : }
- 296 :
- 297 36 : uint64_t tick_ms(void)
- 298 : {
- 299 : struct timeval tv;
- 300 :
- 301 36 : if (gettimeofday(&tv, 0) != 0)
- 302 0 : return 0;
- 303 :
- 304 36 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
- 305 : }
+ 262 : /* then try with FIBMAP */
+ 263 : /* it works for jfs, reiserfs, ntfs-3g */
+ 264 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */
+ 265 0 : blknum = 0; /* first block */
+ 266 0 : if (ioctl(f, FIBMAP, &blknum) != -1) {
+ 267 0 : *physical = blknum + FILEPHY_REAL_OFFSET;
+ 268 0 : if (close(f) == -1)
+ 269 0 : return -1;
+ 270 0 : return 0;
+ 271 : }
+ 272 :
+ 273 : /* otherwise don't use anything, and keep the directory traversal order */
+ 274 : /* at now this should happen only for vfat */
+ 275 : /* and it's surely better than using fake inodes */
+ 276 0 : *physical = FILEPHY_UNREPORTED_OFFSET;
+ 277 0 : if (close(f) == -1)
+ 278 0 : return -1;
+ 279 : #else
+ 280 : /* In a generic Unix use a dummy value for all the files */
+ 281 : /* We don't want to risk to use the inode without knowing */
+ 282 : /* if it really improves performance. */
+ 283 : /* In this way we keep them in the directory traversal order */
+ 284 : /* that at least keeps files in the same directory together. */
+ 285 : /* Note also that in newer file-system with snapshot, like ZFS, */
+ 286 : /* the inode doesn't represent even less the disk position, because files */
+ 287 : /* are not overwritten in place, but rewritten in another location */
+ 288 : /* of the disk. */
+ 289 : *physical = FILEPHY_UNREPORTED_OFFSET;
+ 290 :
+ 291 : (void)path; /* not used here */
+ 292 : (void)size;
+ 293 : #endif
+ 294 :
+ 295 0 : return 0;
+ 296 : }
+ 297 :
+ 298 2415 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space)
+ 299 : {
+ 300 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
+ 301 : struct statfs st;
+ 302 :
+ 303 2415 : if (statfs(path, &st) != 0) {
+ 304 : char dir[PATH_MAX];
+ 305 : char* slash;
306 :
- 307 263 : int randomize(void* ptr, size_t size)
- 308 : {
- 309 : int f;
- 310 : ssize_t ret;
- 311 :
- 312 263 : f = open("/dev/urandom", O_RDONLY);
- 313 263 : if (f == -1)
- 314 0 : return -1;
- 315 :
- 316 263 : ret = read(f, ptr, size);
- 317 263 : if (ret < 0 || (size_t)ret != size) {
- 318 0 : close(f);
- 319 0 : return -1;
- 320 : }
- 321 :
- 322 263 : if (close(f) != 0)
- 323 0 : return -1;
- 324 :
- 325 263 : return 0;
- 326 : }
- 327 :
- 328 : /**
- 329 : * Read a file extracting the contained device number in %u:%u format.
- 330 : * Return 0 on error.
- 331 : */
- 332 : #if HAVE_LINUX_DEVICE
- 333 86 : static dev_t devread(const char* path)
- 334 : {
- 335 : int f;
- 336 : int ret;
- 337 : char buf[64];
- 338 : char* e;
- 339 : unsigned ma;
- 340 : unsigned mi;
+ 307 6 : if (errno != ENOENT) {
+ 308 0 : return -1;
+ 309 : }
+ 310 :
+ 311 : /* if it doesn't exist, we assume a file */
+ 312 : /* and we check for the containing dir */
+ 313 6 : if (strlen(path) + 1 > sizeof(dir)) {
+ 314 0 : errno = ENAMETOOLONG;
+ 315 0 : return -1;
+ 316 : }
+ 317 :
+ 318 6 : strcpy(dir, path);
+ 319 :
+ 320 6 : slash = strrchr(dir, '/');
+ 321 6 : if (!slash)
+ 322 0 : return -1;
+ 323 :
+ 324 6 : *slash = 0;
+ 325 6 : if (statfs(dir, &st) != 0)
+ 326 0 : return -1;
+ 327 : }
+ 328 :
+ 329 : /* to get the fs type check "man stat" or "stat -f -t FILE" */
+ 330 2415 : if (has_persistent_inode)
+ 331 527 : switch (st.f_type) {
+ 332 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */
+ 333 : case 0x4d44 : /* VFAT, "msdos" in the stat command */
+ 334 0 : *has_persistent_inode = 0;
+ 335 0 : break;
+ 336 : default :
+ 337 : /* by default assume yes */
+ 338 527 : *has_persistent_inode = 1;
+ 339 527 : break;
+ 340 : }
341 :
- 342 86 : f = open(path, O_RDONLY);
- 343 86 : if (f == -1) {
- 344 : /* LCOV_EXCL_START */
- 345 : log_fatal("Failed to open '%s'.\n", path);
- 346 : return 0;
- 347 : /* LCOV_EXCL_STOP */
- 348 : }
- 349 :
- 350 86 : ret = read(f, buf, sizeof(buf));
- 351 86 : if (ret < 0) {
- 352 : /* LCOV_EXCL_START */
- 353 : close(f);
- 354 : log_fatal("Failed to read '%s'.\n", path);
- 355 : return 0;
- 356 : /* LCOV_EXCL_STOP */
- 357 : }
- 358 86 : if (ret == sizeof(buf)) {
- 359 : /* LCOV_EXCL_START */
- 360 : close(f);
- 361 : log_fatal("Too long read '%s'.\n", path);
- 362 : return 0;
- 363 : /* LCOV_EXCL_STOP */
- 364 : }
- 365 :
- 366 86 : buf[ret] = 0;
- 367 :
- 368 86 : ma = strtoul(buf, &e, 10);
- 369 86 : if (*e != ':') {
- 370 : /* LCOV_EXCL_START */
- 371 : close(f);
- 372 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
- 373 : return 0;
- 374 : /* LCOV_EXCL_STOP */
- 375 : }
- 376 :
- 377 86 : mi = strtoul(e+1, &e, 10);
- 378 86 : if (*e != 0 && !isspace(*e)) {
- 379 : /* LCOV_EXCL_START */
- 380 : close(f);
- 381 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
- 382 : return 0;
- 383 : /* LCOV_EXCL_STOP */
- 384 : }
- 385 :
- 386 86 : ret = close(f);
- 387 86 : if (ret != 0) {
- 388 : /* LCOV_EXCL_START */
- 389 : log_fatal("Failed to close '%s'.\n", path);
- 390 : return 0;
- 391 : /* LCOV_EXCL_STOP */
- 392 : }
- 393 :
- 394 86 : return makedev(ma, mi);
- 395 : }
- 396 : #endif
- 397 :
- 398 : #if HAVE_LINUX_DEVICE
- 399 : /**
- 400 : * Get the device file from the device number.
- 401 : */
- 402 97 : static int devresolve(dev_t device, char* path, size_t path_size)
- 403 : {
- 404 : struct stat st;
- 405 : char buf[PATH_MAX];
- 406 : int ret;
+ 342 2415 : if (total_space)
+ 343 1888 : *total_space = st.f_bsize * (uint64_t)st.f_blocks;
+ 344 2415 : if (free_space)
+ 345 1888 : *free_space = st.f_bsize * (uint64_t)st.f_bfree;
+ 346 : #else
+ 347 : (void)path;
+ 348 :
+ 349 : /* by default assume yes */
+ 350 : if (has_persistent_inode)
+ 351 : *has_persistent_inode = 1;
+ 352 : if (total_space)
+ 353 : *total_space = 0;
+ 354 : if (free_space)
+ 355 : *free_space = 0;
+ 356 : #endif
+ 357 :
+ 358 2415 : return 0;
+ 359 : }
+ 360 :
+ 361 2214352 : uint64_t tick(void)
+ 362 : {
+ 363 : #if HAVE_MACH_ABSOLUTE_TIME
+ 364 : /* for Mac OS X */
+ 365 : return mach_absolute_time();
+ 366 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW))
+ 367 : /* for Linux */
+ 368 : struct timespec tv;
+ 369 :
+ 370 : /* nanosecond precision with clock_gettime() */
+ 371 : #if defined(CLOCK_MONOTONIC_RAW)
+ 372 2214352 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) {
+ 373 : #else
+ 374 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) {
+ 375 : #endif
+ 376 0 : return 0;
+ 377 : }
+ 378 :
+ 379 2214352 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec;
+ 380 : #else
+ 381 : /* other platforms */
+ 382 : struct timeval tv;
+ 383 :
+ 384 : /* microsecond precision with gettimeofday() */
+ 385 : if (gettimeofday(&tv, 0) != 0) {
+ 386 : return 0;
+ 387 : }
+ 388 :
+ 389 : return tv.tv_sec * 1000000ULL + tv.tv_usec;
+ 390 : #endif
+ 391 : }
+ 392 :
+ 393 36 : uint64_t tick_ms(void)
+ 394 : {
+ 395 : struct timeval tv;
+ 396 :
+ 397 36 : if (gettimeofday(&tv, 0) != 0)
+ 398 0 : return 0;
+ 399 :
+ 400 36 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
+ 401 : }
+ 402 :
+ 403 271 : int randomize(void* ptr, size_t size)
+ 404 : {
+ 405 : int f;
+ 406 : ssize_t ret;
407 :
- 408 : /* default device path from device number */
- 409 97 : pathprint(path, path_size, "/dev/block/%u:%u", major(device), minor(device));
- 410 :
- 411 : /* resolve the link from /dev/block */
- 412 97 : ret = readlink(path, buf, sizeof(buf));
- 413 97 : if (ret < 0) {
- 414 : /* LCOV_EXCL_START */
- 415 : log_fatal("Failed to readlink '%s'.\n", path);
- 416 : return -1;
- 417 : /* LCOV_EXCL_STOP */
- 418 : }
- 419 97 : if (ret == sizeof(buf)) {
- 420 : /* LCOV_EXCL_START */
- 421 : log_fatal("Too long readlink '%s'.\n", path);
- 422 : return -1;
- 423 : /* LCOV_EXCL_STOP */
- 424 : }
- 425 :
- 426 97 : buf[ret] = 0;
- 427 :
- 428 97 : if (buf[0] != '.' || buf[1] != '.' || buf[2] != '/') {
- 429 : /* LCOV_EXCL_START */
- 430 : log_fatal("Unexpected link '%s' at '%s'.\n", buf, path);
- 431 : return -1;
- 432 : /* LCOV_EXCL_STOP */
- 433 : }
- 434 :
- 435 : /* set the real device path */
- 436 97 : pathprint(path, path_size, "/dev/%s", buf + 3);
+ 408 271 : f = open("/dev/urandom", O_RDONLY);
+ 409 271 : if (f == -1)
+ 410 0 : return -1;
+ 411 :
+ 412 271 : ret = read(f, ptr, size);
+ 413 271 : if (ret < 0 || (size_t)ret != size) {
+ 414 0 : close(f);
+ 415 0 : return -1;
+ 416 : }
+ 417 :
+ 418 271 : if (close(f) != 0)
+ 419 0 : return -1;
+ 420 :
+ 421 271 : return 0;
+ 422 : }
+ 423 :
+ 424 : /**
+ 425 : * Read a file extracting the contained device number in %u:%u format.
+ 426 : * Return 0 on error.
+ 427 : */
+ 428 : #if HAVE_LINUX_DEVICE
+ 429 86 : static dev_t devread(const char* path)
+ 430 : {
+ 431 : int f;
+ 432 : int ret;
+ 433 : char buf[64];
+ 434 : char* e;
+ 435 : unsigned ma;
+ 436 : unsigned mi;
437 :
- 438 : /* check the device */
- 439 97 : if (stat(path, &st) != 0) {
+ 438 86 : f = open(path, O_RDONLY);
+ 439 86 : if (f == -1) {
440 : /* LCOV_EXCL_START */
- 441 : log_fatal("Failed to stat '%s'.\n", path);
- 442 : return -1;
+ 441 : log_fatal("Failed to open '%s'.\n", path);
+ 442 : return 0;
443 : /* LCOV_EXCL_STOP */
444 : }
- 445 97 : if (st.st_rdev != device) {
- 446 : /* LCOV_EXCL_START */
- 447 : log_fatal("Unexpected device '%u:%u' instead of '%u:%u' for '%s'.\n", major(st.st_rdev), minor(st.st_rdev), major(device), minor(device), path);
- 448 : return -1;
- 449 : /* LCOV_EXCL_STOP */
- 450 : }
- 451 :
- 452 97 : return 0;
- 453 : }
- 454 : #endif
- 455 :
- 456 : /**
- 457 : * Read a device tree filling the specified list of disk_t entries.
- 458 : */
- 459 : #if HAVE_LINUX_DEVICE
- 460 72 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list)
- 461 : {
- 462 : char path[PATH_MAX];
- 463 : DIR* d;
- 464 72 : int slaves = 0;
- 465 :
- 466 72 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device));
- 467 :
- 468 : /* check if there is a slaves list */
- 469 72 : d = opendir(path);
- 470 72 : if (d != 0) {
- 471 : struct dirent* dd;
+ 445 :
+ 446 86 : ret = read(f, buf, sizeof(buf));
+ 447 86 : if (ret < 0) {
+ 448 : /* LCOV_EXCL_START */
+ 449 : close(f);
+ 450 : log_fatal("Failed to read '%s'.\n", path);
+ 451 : return 0;
+ 452 : /* LCOV_EXCL_STOP */
+ 453 : }
+ 454 86 : if (ret == sizeof(buf)) {
+ 455 : /* LCOV_EXCL_START */
+ 456 : close(f);
+ 457 : log_fatal("Too long read '%s'.\n", path);
+ 458 : return 0;
+ 459 : /* LCOV_EXCL_STOP */
+ 460 : }
+ 461 :
+ 462 86 : buf[ret] = 0;
+ 463 :
+ 464 86 : ma = strtoul(buf, &e, 10);
+ 465 86 : if (*e != ':') {
+ 466 : /* LCOV_EXCL_START */
+ 467 : close(f);
+ 468 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
+ 469 : return 0;
+ 470 : /* LCOV_EXCL_STOP */
+ 471 : }
472 :
- 473 180 : while ((dd = readdir(d)) != 0) {
- 474 108 : if (dd->d_name[0] != '.') {
- 475 : /* for each slave, expand the full potential tree */
- 476 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name);
- 477 :
- 478 36 : device = devread(path);
- 479 36 : if (!device) {
- 480 : /* LCOV_EXCL_START */
- 481 : closedir(d);
- 482 : return -1;
- 483 : /* LCOV_EXCL_STOP */
- 484 : }
- 485 :
- 486 36 : if (devtree(name, custom, device, parent, list) != 0) {
- 487 : /* LCOV_EXCL_START */
- 488 : closedir(d);
- 489 : return -1;
- 490 : /* LCOV_EXCL_STOP */
- 491 : }
- 492 :
- 493 36 : ++slaves;
- 494 : }
- 495 : }
- 496 :
- 497 36 : closedir(d);
- 498 : }
- 499 :
- 500 : /* if no slaves found */
- 501 72 : if (!slaves) {
- 502 : /* this is a raw device */
- 503 : devinfo_t* devinfo;
- 504 :
- 505 : /* check if it's a real device */
- 506 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device));
- 507 36 : if (access(path, F_OK) != 0) {
- 508 : /* get the parent device */
- 509 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device));
- 510 :
- 511 36 : device = devread(path);
- 512 36 : if (!device) {
- 513 : /* LCOV_EXCL_START */
- 514 : return -1;
- 515 : /* LCOV_EXCL_STOP */
- 516 : }
- 517 : }
- 518 :
- 519 : /* get the device file */
- 520 36 : if (devresolve(device, path, sizeof(path)) != 0) {
- 521 : /* LCOV_EXCL_START */
- 522 : return -1;
- 523 : /* LCOV_EXCL_STOP */
- 524 : }
- 525 :
- 526 36 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
- 527 :
- 528 36 : devinfo->device = device;
- 529 36 : pathcpy(devinfo->name, sizeof(devinfo->name), name);
- 530 36 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom);
- 531 36 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
- 532 36 : devinfo->parent = parent;
+ 473 86 : mi = strtoul(e+1, &e, 10);
+ 474 86 : if (*e != 0 && !isspace(*e)) {
+ 475 : /* LCOV_EXCL_START */
+ 476 : close(f);
+ 477 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
+ 478 : return 0;
+ 479 : /* LCOV_EXCL_STOP */
+ 480 : }
+ 481 :
+ 482 86 : ret = close(f);
+ 483 86 : if (ret != 0) {
+ 484 : /* LCOV_EXCL_START */
+ 485 : log_fatal("Failed to close '%s'.\n", path);
+ 486 : return 0;
+ 487 : /* LCOV_EXCL_STOP */
+ 488 : }
+ 489 :
+ 490 86 : return makedev(ma, mi);
+ 491 : }
+ 492 : #endif
+ 493 :
+ 494 : #if HAVE_LINUX_DEVICE
+ 495 : /**
+ 496 : * Get the device file from the device number.
+ 497 : */
+ 498 97 : static int devresolve(dev_t device, char* path, size_t path_size)
+ 499 : {
+ 500 : struct stat st;
+ 501 : char buf[PATH_MAX];
+ 502 : int ret;
+ 503 :
+ 504 : /* default device path from device number */
+ 505 97 : pathprint(path, path_size, "/dev/block/%u:%u", major(device), minor(device));
+ 506 :
+ 507 : /* resolve the link from /dev/block */
+ 508 97 : ret = readlink(path, buf, sizeof(buf));
+ 509 97 : if (ret < 0) {
+ 510 : /* LCOV_EXCL_START */
+ 511 : log_fatal("Failed to readlink '%s'.\n", path);
+ 512 : return -1;
+ 513 : /* LCOV_EXCL_STOP */
+ 514 : }
+ 515 97 : if (ret == sizeof(buf)) {
+ 516 : /* LCOV_EXCL_START */
+ 517 : log_fatal("Too long readlink '%s'.\n", path);
+ 518 : return -1;
+ 519 : /* LCOV_EXCL_STOP */
+ 520 : }
+ 521 :
+ 522 97 : buf[ret] = 0;
+ 523 :
+ 524 97 : if (buf[0] != '.' || buf[1] != '.' || buf[2] != '/') {
+ 525 : /* LCOV_EXCL_START */
+ 526 : log_fatal("Unexpected link '%s' at '%s'.\n", buf, path);
+ 527 : return -1;
+ 528 : /* LCOV_EXCL_STOP */
+ 529 : }
+ 530 :
+ 531 : /* set the real device path */
+ 532 97 : pathprint(path, path_size, "/dev/%s", buf + 3);
533 :
- 534 : /* insert in the list */
- 535 36 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
- 536 : }
- 537 :
- 538 72 : return 0;
- 539 : }
- 540 : #endif
- 541 :
- 542 : /**
- 543 : * Scan all the devices.
- 544 : *
- 545 : * If a device is already in, it's not added again.
- 546 : */
- 547 : #if HAVE_LINUX_DEVICE
- 548 1 : static int devscan(tommy_list* list)
- 549 : {
- 550 : char dir[PATH_MAX];
- 551 : DIR* d;
- 552 : struct dirent* dd;
- 553 :
- 554 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/");
- 555 :
- 556 : /* check if there is a slaves list */
- 557 1 : d = opendir(dir);
- 558 1 : if (d == 0) {
- 559 : /* LCOV_EXCL_START */
- 560 : log_fatal("Failed to open dir '%s'.\n", dir);
- 561 : return -1;
- 562 : /* LCOV_EXCL_STOP */
- 563 : }
- 564 :
- 565 75 : while ((dd = readdir(d)) != 0) {
- 566 73 : if (dd->d_name[0] != '.') {
- 567 : char path[PATH_MAX];
+ 534 : /* check the device */
+ 535 97 : if (stat(path, &st) != 0) {
+ 536 : /* LCOV_EXCL_START */
+ 537 : log_fatal("Failed to stat '%s'.\n", path);
+ 538 : return -1;
+ 539 : /* LCOV_EXCL_STOP */
+ 540 : }
+ 541 97 : if (st.st_rdev != device) {
+ 542 : /* LCOV_EXCL_START */
+ 543 : log_fatal("Unexpected device '%u:%u' instead of '%u:%u' for '%s'.\n", major(st.st_rdev), minor(st.st_rdev), major(device), minor(device), path);
+ 544 : return -1;
+ 545 : /* LCOV_EXCL_STOP */
+ 546 : }
+ 547 :
+ 548 97 : return 0;
+ 549 : }
+ 550 : #endif
+ 551 :
+ 552 : /**
+ 553 : * Read a device tree filling the specified list of disk_t entries.
+ 554 : */
+ 555 : #if HAVE_LINUX_DEVICE
+ 556 72 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list)
+ 557 : {
+ 558 : char path[PATH_MAX];
+ 559 : DIR* d;
+ 560 72 : int slaves = 0;
+ 561 :
+ 562 72 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device));
+ 563 :
+ 564 : /* check if there is a slaves list */
+ 565 72 : d = opendir(path);
+ 566 72 : if (d != 0) {
+ 567 : struct dirent* dd;
568 :
- 569 71 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name);
- 570 :
- 571 : /* check if it's a real device */
- 572 71 : if (access(path, F_OK) == 0) {
- 573 : tommy_node* i;
- 574 : dev_t device;
- 575 :
- 576 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name);
- 577 :
- 578 14 : device = devread(path);
- 579 14 : if (!device) {
- 580 : /* LCOV_EXCL_START */
- 581 : closedir(d);
- 582 : return -1;
- 583 : /* LCOV_EXCL_STOP */
- 584 : }
- 585 :
- 586 : /* check if already present */
- 587 248 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 588 235 : devinfo_t* devinfo = i->data;
- 589 235 : if (devinfo->device == device)
- 590 1 : break;
- 591 : }
+ 569 180 : while ((dd = readdir(d)) != 0) {
+ 570 108 : if (dd->d_name[0] != '.') {
+ 571 : /* for each slave, expand the full potential tree */
+ 572 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name);
+ 573 :
+ 574 36 : device = devread(path);
+ 575 36 : if (!device) {
+ 576 : /* LCOV_EXCL_START */
+ 577 : closedir(d);
+ 578 : return -1;
+ 579 : /* LCOV_EXCL_STOP */
+ 580 : }
+ 581 :
+ 582 36 : if (devtree(name, custom, device, parent, list) != 0) {
+ 583 : /* LCOV_EXCL_START */
+ 584 : closedir(d);
+ 585 : return -1;
+ 586 : /* LCOV_EXCL_STOP */
+ 587 : }
+ 588 :
+ 589 36 : ++slaves;
+ 590 : }
+ 591 : }
592 :
- 593 : /* if not found */
- 594 14 : if (i == 0) {
- 595 : devinfo_t* devinfo;
- 596 :
- 597 : /* get the device file */
- 598 13 : if (devresolve(device, path, sizeof(path)) != 0) {
- 599 : /* LCOV_EXCL_START */
- 600 : closedir(d);
- 601 : return -1;
- 602 : /* LCOV_EXCL_STOP */
- 603 : }
- 604 :
- 605 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
+ 593 36 : closedir(d);
+ 594 : }
+ 595 :
+ 596 : /* if no slaves found */
+ 597 72 : if (!slaves) {
+ 598 : /* this is a raw device */
+ 599 : devinfo_t* devinfo;
+ 600 :
+ 601 : /* check if it's a real device */
+ 602 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device));
+ 603 36 : if (access(path, F_OK) != 0) {
+ 604 : /* get the parent device */
+ 605 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device));
606 :
- 607 13 : devinfo->device = device;
- 608 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
- 609 :
- 610 : /* insert in the list */
- 611 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
- 612 : }
- 613 : }
- 614 : }
- 615 : }
- 616 :
- 617 1 : closedir(d);
- 618 1 : return 0;
- 619 : }
- 620 : #endif
+ 607 36 : device = devread(path);
+ 608 36 : if (!device) {
+ 609 : /* LCOV_EXCL_START */
+ 610 : return -1;
+ 611 : /* LCOV_EXCL_STOP */
+ 612 : }
+ 613 : }
+ 614 :
+ 615 : /* get the device file */
+ 616 36 : if (devresolve(device, path, sizeof(path)) != 0) {
+ 617 : /* LCOV_EXCL_START */
+ 618 : return -1;
+ 619 : /* LCOV_EXCL_STOP */
+ 620 : }
621 :
- 622 : /**
- 623 : * Get SMART attributes.
- 624 : */
- 625 25 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial)
- 626 : {
- 627 : char cmd[128];
- 628 : char file[128];
- 629 : FILE* f;
- 630 : int ret;
- 631 :
- 632 25 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device));
+ 622 36 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
+ 623 :
+ 624 36 : devinfo->device = device;
+ 625 36 : pathcpy(devinfo->name, sizeof(devinfo->name), name);
+ 626 36 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom);
+ 627 36 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
+ 628 36 : devinfo->parent = parent;
+ 629 :
+ 630 : /* insert in the list */
+ 631 36 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
+ 632 : }
633 :
- 634 : /* if there is a custom command */
- 635 25 : if (custom[0]) {
- 636 : char option[128];
- 637 2 : snprintf(option, sizeof(option), custom, file);
- 638 2 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option);
- 639 : } else {
- 640 23 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file);
- 641 : }
- 642 :
- 643 25 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
- 644 :
- 645 25 : f = popen(cmd, "r");
- 646 25 : if (!f) {
- 647 : /* LCOV_EXCL_START */
- 648 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
- 649 : return -1;
- 650 : /* LCOV_EXCL_STOP */
- 651 : }
- 652 :
- 653 25 : if (smartctl_attribute(f, file, name, smart, serial) != 0) {
- 654 : /* LCOV_EXCL_START */
- 655 : pclose(f);
- 656 : return -1;
- 657 : /* LCOV_EXCL_STOP */
- 658 : }
- 659 :
- 660 25 : ret = pclose(f);
- 661 :
- 662 25 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
- 663 :
- 664 25 : if (!WIFEXITED(ret)) {
- 665 : /* LCOV_EXCL_START */
- 666 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
- 667 : return -1;
- 668 : /* LCOV_EXCL_STOP */
- 669 : }
- 670 25 : if (WEXITSTATUS(ret) == 127) {
- 671 : /* LCOV_EXCL_START */
- 672 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
- 673 : return -1;
- 674 : /* LCOV_EXCL_STOP */
- 675 : }
- 676 :
- 677 : /* store the return smartctl return value */
- 678 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret);
- 679 :
- 680 0 : return 0;
- 681 : }
- 682 :
- 683 : /**
- 684 : * Spin down a specific device.
- 685 : */
- 686 : #if HAVE_LINUX_DEVICE
- 687 12 : static int devdown(dev_t device, const char* name, const char* custom)
- 688 : {
- 689 : char cmd[128];
- 690 : char file[128];
- 691 : FILE* f;
- 692 : int ret;
- 693 :
- 694 12 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device));
- 695 :
- 696 : /* if there is a custom command */
- 697 12 : if (custom[0]) {
- 698 : char option[128];
- 699 2 : snprintf(option, sizeof(option), custom, file);
- 700 2 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option);
- 701 : } else {
- 702 10 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file);
- 703 : }
- 704 :
- 705 12 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
- 706 :
- 707 12 : f = popen(cmd, "r");
- 708 12 : if (!f) {
- 709 : /* LCOV_EXCL_START */
- 710 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
- 711 : return -1;
- 712 : /* LCOV_EXCL_STOP */
- 713 : }
- 714 :
- 715 12 : if (smartctl_flush(f, file, name) != 0) {
- 716 : /* LCOV_EXCL_START */
- 717 : pclose(f);
- 718 : return -1;
- 719 : /* LCOV_EXCL_STOP */
- 720 : }
- 721 :
- 722 12 : ret = pclose(f);
- 723 :
- 724 12 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
- 725 :
- 726 12 : if (!WIFEXITED(ret)) {
- 727 : /* LCOV_EXCL_START */
- 728 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
- 729 : return -1;
- 730 : /* LCOV_EXCL_STOP */
- 731 : }
- 732 12 : if (WEXITSTATUS(ret) == 127) {
- 733 : /* LCOV_EXCL_START */
- 734 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
- 735 : return -1;
- 736 : /* LCOV_EXCL_STOP */
+ 634 72 : return 0;
+ 635 : }
+ 636 : #endif
+ 637 :
+ 638 : /**
+ 639 : * Scan all the devices.
+ 640 : *
+ 641 : * If a device is already in, it's not added again.
+ 642 : */
+ 643 : #if HAVE_LINUX_DEVICE
+ 644 1 : static int devscan(tommy_list* list)
+ 645 : {
+ 646 : char dir[PATH_MAX];
+ 647 : DIR* d;
+ 648 : struct dirent* dd;
+ 649 :
+ 650 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/");
+ 651 :
+ 652 : /* check if there is a slaves list */
+ 653 1 : d = opendir(dir);
+ 654 1 : if (d == 0) {
+ 655 : /* LCOV_EXCL_START */
+ 656 : log_fatal("Failed to open dir '%s'.\n", dir);
+ 657 : return -1;
+ 658 : /* LCOV_EXCL_STOP */
+ 659 : }
+ 660 :
+ 661 74 : while ((dd = readdir(d)) != 0) {
+ 662 72 : if (dd->d_name[0] != '.') {
+ 663 : char path[PATH_MAX];
+ 664 :
+ 665 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name);
+ 666 :
+ 667 : /* check if it's a real device */
+ 668 70 : if (access(path, F_OK) == 0) {
+ 669 : tommy_node* i;
+ 670 : dev_t device;
+ 671 :
+ 672 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name);
+ 673 :
+ 674 14 : device = devread(path);
+ 675 14 : if (!device) {
+ 676 : /* LCOV_EXCL_START */
+ 677 : closedir(d);
+ 678 : return -1;
+ 679 : /* LCOV_EXCL_STOP */
+ 680 : }
+ 681 :
+ 682 : /* check if already present */
+ 683 248 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 684 235 : devinfo_t* devinfo = i->data;
+ 685 235 : if (devinfo->device == device)
+ 686 1 : break;
+ 687 : }
+ 688 :
+ 689 : /* if not found */
+ 690 14 : if (i == 0) {
+ 691 : devinfo_t* devinfo;
+ 692 :
+ 693 : /* get the device file */
+ 694 13 : if (devresolve(device, path, sizeof(path)) != 0) {
+ 695 : /* LCOV_EXCL_START */
+ 696 : closedir(d);
+ 697 : return -1;
+ 698 : /* LCOV_EXCL_STOP */
+ 699 : }
+ 700 :
+ 701 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
+ 702 :
+ 703 13 : devinfo->device = device;
+ 704 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
+ 705 :
+ 706 : /* insert in the list */
+ 707 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
+ 708 : }
+ 709 : }
+ 710 : }
+ 711 : }
+ 712 :
+ 713 1 : closedir(d);
+ 714 1 : return 0;
+ 715 : }
+ 716 : #endif
+ 717 :
+ 718 : /**
+ 719 : * Get SMART attributes.
+ 720 : */
+ 721 25 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial)
+ 722 : {
+ 723 : char cmd[128];
+ 724 : char file[128];
+ 725 : FILE* f;
+ 726 : int ret;
+ 727 :
+ 728 25 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device));
+ 729 :
+ 730 : /* if there is a custom command */
+ 731 25 : if (custom[0]) {
+ 732 : char option[128];
+ 733 2 : snprintf(option, sizeof(option), custom, file);
+ 734 2 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option);
+ 735 : } else {
+ 736 23 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file);
737 : }
- 738 0 : if (WEXITSTATUS(ret) != 0) {
- 739 : /* LCOV_EXCL_START */
- 740 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret));
- 741 : return -1;
- 742 : /* LCOV_EXCL_STOP */
- 743 : }
- 744 :
- 745 0 : return 0;
- 746 : }
- 747 : #endif
+ 738 :
+ 739 25 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
+ 740 :
+ 741 25 : f = popen(cmd, "r");
+ 742 25 : if (!f) {
+ 743 : /* LCOV_EXCL_START */
+ 744 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 745 : return -1;
+ 746 : /* LCOV_EXCL_STOP */
+ 747 : }
748 :
- 749 : /**
- 750 : * Spin up a device.
- 751 : *
- 752 : * There isn't a defined way to spin up a device,
- 753 : * so we just do a generic write.
- 754 : */
- 755 12 : static int devup(const char* mountpoint)
- 756 : {
- 757 : int ret;
- 758 : char path[PATH_MAX];
+ 749 25 : if (smartctl_attribute(f, file, name, smart, serial) != 0) {
+ 750 : /* LCOV_EXCL_START */
+ 751 : pclose(f);
+ 752 : return -1;
+ 753 : /* LCOV_EXCL_STOP */
+ 754 : }
+ 755 :
+ 756 24 : ret = pclose(f);
+ 757 :
+ 758 25 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
759 :
- 760 : /* add a temporary name used for writing */
- 761 12 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint);
- 762 :
- 763 : /* do a generic write, and immediately undo it */
- 764 12 : ret = mkdir(path, 0);
- 765 12 : if (ret != 0 && errno != EEXIST) {
- 766 : /* LCOV_EXCL_START */
- 767 : log_fatal("Failed to create dir '%s'.\n", path);
- 768 : return -1;
- 769 : /* LCOV_EXCL_STOP */
- 770 : }
- 771 :
- 772 : /* remove the just created dir */
- 773 12 : rmdir(path);
- 774 :
- 775 12 : return 0;
- 776 : }
- 777 :
- 778 : /**
- 779 : * Thread for spinning up.
- 780 : *
- 781 : * Note that filling up the devinfo object is done inside this thread,
- 782 : * to avoid to block the main thread if the device need to be spin up
- 783 : * to handle stat/resolve requests.
- 784 : */
- 785 12 : static void* thread_spinup(void* arg)
- 786 : {
- 787 12 : devinfo_t* devinfo = arg;
- 788 : struct stat st;
- 789 : uint64_t start;
- 790 :
- 791 12 : start = tick_ms();
- 792 :
- 793 : /* first get the device number, this usually doesn't trigger a thread_spinup */
- 794 12 : if (stat(devinfo->mount, &st) != 0) {
- 795 : /* LCOV_EXCL_START */
- 796 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount);
- 797 : return (void*)-1;
- 798 : /* LCOV_EXCL_STOP */
+ 760 25 : if (!WIFEXITED(ret)) {
+ 761 : /* LCOV_EXCL_START */
+ 762 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
+ 763 : return -1;
+ 764 : /* LCOV_EXCL_STOP */
+ 765 : }
+ 766 25 : if (WEXITSTATUS(ret) == 127) {
+ 767 : /* LCOV_EXCL_START */
+ 768 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
+ 769 : return -1;
+ 770 : /* LCOV_EXCL_STOP */
+ 771 : }
+ 772 :
+ 773 : /* store the return smartctl return value */
+ 774 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret);
+ 775 :
+ 776 0 : return 0;
+ 777 : }
+ 778 :
+ 779 : /**
+ 780 : * Spin down a specific device.
+ 781 : */
+ 782 : #if HAVE_LINUX_DEVICE
+ 783 12 : static int devdown(dev_t device, const char* name, const char* custom)
+ 784 : {
+ 785 : char cmd[128];
+ 786 : char file[128];
+ 787 : FILE* f;
+ 788 : int ret;
+ 789 :
+ 790 12 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device));
+ 791 :
+ 792 : /* if there is a custom command */
+ 793 12 : if (custom[0]) {
+ 794 : char option[128];
+ 795 2 : snprintf(option, sizeof(option), custom, file);
+ 796 2 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option);
+ 797 : } else {
+ 798 10 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file);
799 : }
800 :
- 801 : /* set the device number for printing */
- 802 12 : devinfo->device = st.st_dev;
- 803 :
- 804 : #if HAVE_LINUX_DEVICE
- 805 : /* get the device file, but only in Linux and only for the message */
- 806 12 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) {
- 807 : /* LCOV_EXCL_START */
- 808 : return (void*)-1;
- 809 : /* LCOV_EXCL_STOP */
- 810 : }
- 811 : #endif
- 812 :
- 813 12 : if (devup(devinfo->mount) != 0) {
- 814 : /* LCOV_EXCL_START */
- 815 : return (void*)-1;
- 816 : /* LCOV_EXCL_STOP */
- 817 : }
- 818 :
- 819 : #if HAVE_LINUX_DEVICE
- 820 12 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
- 821 : #else
- 822 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start);
- 823 : #endif
- 824 :
- 825 12 : return 0;
- 826 : }
- 827 :
- 828 : /**
- 829 : * Thread for spinning down.
- 830 : */
- 831 12 : static void* thread_spindown(void* arg)
- 832 : {
- 833 : #if HAVE_LINUX_DEVICE
- 834 12 : devinfo_t* devinfo = arg;
- 835 : uint64_t start;
- 836 :
- 837 12 : start = tick_ms();
- 838 :
- 839 12 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
- 840 : /* LCOV_EXCL_START */
- 841 : return (void*)-1;
- 842 : /* LCOV_EXCL_STOP */
- 843 : }
+ 801 12 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
+ 802 :
+ 803 12 : f = popen(cmd, "r");
+ 804 12 : if (!f) {
+ 805 : /* LCOV_EXCL_START */
+ 806 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 807 : return -1;
+ 808 : /* LCOV_EXCL_STOP */
+ 809 : }
+ 810 :
+ 811 12 : if (smartctl_flush(f, file, name) != 0) {
+ 812 : /* LCOV_EXCL_START */
+ 813 : pclose(f);
+ 814 : return -1;
+ 815 : /* LCOV_EXCL_STOP */
+ 816 : }
+ 817 :
+ 818 12 : ret = pclose(f);
+ 819 :
+ 820 12 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
+ 821 :
+ 822 12 : if (!WIFEXITED(ret)) {
+ 823 : /* LCOV_EXCL_START */
+ 824 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
+ 825 : return -1;
+ 826 : /* LCOV_EXCL_STOP */
+ 827 : }
+ 828 12 : if (WEXITSTATUS(ret) == 127) {
+ 829 : /* LCOV_EXCL_START */
+ 830 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
+ 831 : return -1;
+ 832 : /* LCOV_EXCL_STOP */
+ 833 : }
+ 834 0 : if (WEXITSTATUS(ret) != 0) {
+ 835 : /* LCOV_EXCL_START */
+ 836 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret));
+ 837 : return -1;
+ 838 : /* LCOV_EXCL_STOP */
+ 839 : }
+ 840 :
+ 841 0 : return 0;
+ 842 : }
+ 843 : #endif
844 :
- 845 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
- 846 :
- 847 0 : return 0;
- 848 : #else
- 849 : (void)arg;
- 850 : return (void*)-1;
- 851 : #endif
- 852 : }
- 853 :
- 854 : /**
- 855 : * Thread for getting smart info.
- 856 : */
- 857 25 : static void* thread_smart(void* arg)
- 858 : {
- 859 25 : devinfo_t* devinfo = arg;
- 860 :
- 861 25 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) {
+ 845 : /**
+ 846 : * Spin up a device.
+ 847 : *
+ 848 : * There isn't a defined way to spin up a device,
+ 849 : * so we just do a generic write.
+ 850 : */
+ 851 12 : static int devup(const char* mountpoint)
+ 852 : {
+ 853 : int ret;
+ 854 : char path[PATH_MAX];
+ 855 :
+ 856 : /* add a temporary name used for writing */
+ 857 12 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint);
+ 858 :
+ 859 : /* do a generic write, and immediately undo it */
+ 860 12 : ret = mkdir(path, 0);
+ 861 12 : if (ret != 0 && errno != EEXIST) {
862 : /* LCOV_EXCL_START */
- 863 : return (void*)-1;
- 864 : /* LCOV_EXCL_STOP */
- 865 : }
- 866 :
- 867 0 : return 0;
- 868 : }
- 869 :
- 870 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg))
- 871 : {
- 872 3 : int fail = 0;
- 873 : tommy_node* i;
- 874 :
- 875 : #if HAVE_PTHREAD_CREATE
- 876 : /* start all threads */
- 877 52 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 878 49 : devinfo_t* devinfo = i->data;
- 879 :
- 880 49 : if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) {
- 881 : /* LCOV_EXCL_START */
- 882 : log_fatal("Failed to create thread.\n");
- 883 : exit(EXIT_FAILURE);
- 884 : /* LCOV_EXCL_STOP */
- 885 : }
- 886 : }
- 887 :
- 888 : /* join all threads */
- 889 52 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 890 49 : devinfo_t* devinfo = i->data;
- 891 : void* retval;
- 892 :
- 893 49 : if (pthread_join(devinfo->thread, &retval) != 0) {
- 894 : /* LCOV_EXCL_START */
- 895 : log_fatal("Failed to join thread.\n");
- 896 : exit(EXIT_FAILURE);
- 897 : /* LCOV_EXCL_STOP */
- 898 : }
+ 863 : log_fatal("Failed to create dir '%s'.\n", path);
+ 864 : return -1;
+ 865 : /* LCOV_EXCL_STOP */
+ 866 : }
+ 867 :
+ 868 : /* remove the just created dir */
+ 869 12 : rmdir(path);
+ 870 :
+ 871 12 : return 0;
+ 872 : }
+ 873 :
+ 874 : /**
+ 875 : * Thread for spinning up.
+ 876 : *
+ 877 : * Note that filling up the devinfo object is done inside this thread,
+ 878 : * to avoid to block the main thread if the device need to be spin up
+ 879 : * to handle stat/resolve requests.
+ 880 : */
+ 881 12 : static void* thread_spinup(void* arg)
+ 882 : {
+ 883 12 : devinfo_t* devinfo = arg;
+ 884 : struct stat st;
+ 885 : uint64_t start;
+ 886 :
+ 887 12 : start = tick_ms();
+ 888 :
+ 889 : /* first get the device number, this usually doesn't trigger a thread_spinup */
+ 890 12 : if (stat(devinfo->mount, &st) != 0) {
+ 891 : /* LCOV_EXCL_START */
+ 892 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount);
+ 893 : return (void*)-1;
+ 894 : /* LCOV_EXCL_STOP */
+ 895 : }
+ 896 :
+ 897 : /* set the device number for printing */
+ 898 12 : devinfo->device = st.st_dev;
899 :
- 900 49 : if (retval != 0)
- 901 37 : ++fail;
- 902 : }
- 903 : #else
- 904 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 905 : devinfo_t* devinfo = i->data;
- 906 :
- 907 : if (func(devinfo) != 0)
- 908 : ++fail;
- 909 : }
- 910 : #endif
- 911 3 : if (fail != 0) {
- 912 : /* LCOV_EXCL_START */
- 913 : return -1;
- 914 : /* LCOV_EXCL_STOP */
- 915 : }
- 916 :
- 917 1 : return 0;
- 918 : }
- 919 :
- 920 4 : int devquery(tommy_list* high, tommy_list* low, int operation)
- 921 : {
- 922 : tommy_node* i;
- 923 4 : void* (*func)(void* arg) = 0;
- 924 :
- 925 : #if HAVE_LINUX_DEVICE
- 926 4 : if (operation != DEVICE_UP) {
- 927 : struct stat st;
- 928 : /* sysfs and devfs interfaces are required */
- 929 3 : if (stat("/sys/dev/block", &st) != 0) {
- 930 : /* LCOV_EXCL_START */
- 931 : log_fatal("Missing interface /sys/dev/block.\n");
- 932 : return -1;
- 933 : /* LCOV_EXCL_STOP */
- 934 : }
- 935 3 : if (stat("/dev/block", &st) != 0) {
- 936 : /* LCOV_EXCL_START */
- 937 : log_fatal("Missing interface /dev/block.\n");
- 938 : return -1;
- 939 : /* LCOV_EXCL_STOP */
- 940 : }
- 941 :
- 942 : /* for each device */
- 943 39 : for (i = tommy_list_head(high); i != 0; i = i->next) {
- 944 36 : devinfo_t* devinfo = i->data;
- 945 :
- 946 : /* get the device file */
- 947 36 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) {
- 948 : /* LCOV_EXCL_START */
- 949 : log_fatal("Failed to resolve device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device));
- 950 : return -1;
- 951 : /* LCOV_EXCL_STOP */
- 952 : }
- 953 :
- 954 : /* expand the tree of devices */
- 955 36 : if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) {
- 956 : /* LCOV_EXCL_START */
- 957 : log_fatal("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device));
- 958 : return -1;
- 959 : /* LCOV_EXCL_STOP */
- 960 : }
- 961 : }
- 962 : }
- 963 : #endif
- 964 :
- 965 4 : if (operation == DEVICE_UP) {
- 966 : /* duplicate the high */
- 967 13 : for (i = tommy_list_head(high); i != 0; i = i->next) {
- 968 12 : devinfo_t* devinfo = i->data;
- 969 : devinfo_t* entry;
+ 900 : #if HAVE_LINUX_DEVICE
+ 901 : /* get the device file, but only in Linux and only for the message */
+ 902 12 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) {
+ 903 : /* LCOV_EXCL_START */
+ 904 : return (void*)-1;
+ 905 : /* LCOV_EXCL_STOP */
+ 906 : }
+ 907 : #endif
+ 908 :
+ 909 12 : if (devup(devinfo->mount) != 0) {
+ 910 : /* LCOV_EXCL_START */
+ 911 : return (void*)-1;
+ 912 : /* LCOV_EXCL_STOP */
+ 913 : }
+ 914 :
+ 915 : #if HAVE_LINUX_DEVICE
+ 916 12 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
+ 917 : #else
+ 918 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start);
+ 919 : #endif
+ 920 :
+ 921 12 : return 0;
+ 922 : }
+ 923 :
+ 924 : /**
+ 925 : * Thread for spinning down.
+ 926 : */
+ 927 12 : static void* thread_spindown(void* arg)
+ 928 : {
+ 929 : #if HAVE_LINUX_DEVICE
+ 930 12 : devinfo_t* devinfo = arg;
+ 931 : uint64_t start;
+ 932 :
+ 933 12 : start = tick_ms();
+ 934 :
+ 935 12 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
+ 936 : /* LCOV_EXCL_START */
+ 937 : return (void*)-1;
+ 938 : /* LCOV_EXCL_STOP */
+ 939 : }
+ 940 :
+ 941 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
+ 942 :
+ 943 0 : return 0;
+ 944 : #else
+ 945 : (void)arg;
+ 946 : return (void*)-1;
+ 947 : #endif
+ 948 : }
+ 949 :
+ 950 : /**
+ 951 : * Thread for getting smart info.
+ 952 : */
+ 953 22 : static void* thread_smart(void* arg)
+ 954 : {
+ 955 22 : devinfo_t* devinfo = arg;
+ 956 :
+ 957 22 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) {
+ 958 : /* LCOV_EXCL_START */
+ 959 : return (void*)-1;
+ 960 : /* LCOV_EXCL_STOP */
+ 961 : }
+ 962 :
+ 963 0 : return 0;
+ 964 : }
+ 965 :
+ 966 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg))
+ 967 : {
+ 968 3 : int fail = 0;
+ 969 : tommy_node* i;
970 :
- 971 12 : entry = calloc_nofail(1, sizeof(devinfo_t));
- 972 :
- 973 12 : entry->device = devinfo->device;
- 974 12 : pathcpy(entry->name, sizeof(entry->name), devinfo->name);
- 975 12 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount);
- 976 :
- 977 : /* insert in the high */
- 978 12 : tommy_list_insert_tail(low, &entry->node, entry);
- 979 : }
- 980 : }
- 981 :
- 982 : #if HAVE_LINUX_DEVICE
- 983 : /* add other devices */
- 984 4 : if (operation == DEVICE_SMART) {
- 985 1 : if (devscan(low) != 0) {
- 986 : /* LCOV_EXCL_START */
- 987 : log_fatal("Failed to list other devices.\n");
- 988 : return -1;
- 989 : /* LCOV_EXCL_STOP */
- 990 : }
- 991 : }
- 992 : #endif
- 993 :
- 994 4 : switch (operation) {
- 995 1 : case DEVICE_UP : func = thread_spinup; break;
- 996 1 : case DEVICE_DOWN : func = thread_spindown; break;
- 997 1 : case DEVICE_SMART : func = thread_smart; break;
+ 971 : #if HAVE_PTHREAD
+ 972 : /* start all threads */
+ 973 52 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 974 49 : devinfo_t* devinfo = i->data;
+ 975 :
+ 976 49 : if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) {
+ 977 : /* LCOV_EXCL_START */
+ 978 : log_fatal("Failed to create thread.\n");
+ 979 : exit(EXIT_FAILURE);
+ 980 : /* LCOV_EXCL_STOP */
+ 981 : }
+ 982 : }
+ 983 :
+ 984 : /* join all threads */
+ 985 52 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 986 49 : devinfo_t* devinfo = i->data;
+ 987 : void* retval;
+ 988 :
+ 989 49 : if (pthread_join(devinfo->thread, &retval) != 0) {
+ 990 : /* LCOV_EXCL_START */
+ 991 : log_fatal("Failed to join thread.\n");
+ 992 : exit(EXIT_FAILURE);
+ 993 : /* LCOV_EXCL_STOP */
+ 994 : }
+ 995 :
+ 996 49 : if (retval != 0)
+ 997 37 : ++fail;
998 : }
- 999 :
- 1000 4 : if (!func)
- 1001 1 : return 0;
+ 999 : #else
+ 1000 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 1001 : devinfo_t* devinfo = i->data;
1002 :
- 1003 3 : return device_thread(low, func);
- 1004 : }
- 1005 :
- 1006 252 : void os_init(int opt)
- 1007 : {
- 1008 : (void)opt;
- 1009 252 : }
- 1010 :
- 1011 230 : void os_done(void)
- 1012 : {
- 1013 230 : }
- 1014 :
- 1015 : #endif
- 1016 :
+ 1003 : if (func(devinfo) != 0)
+ 1004 : ++fail;
+ 1005 : }
+ 1006 : #endif
+ 1007 3 : if (fail != 0) {
+ 1008 : /* LCOV_EXCL_START */
+ 1009 : return -1;
+ 1010 : /* LCOV_EXCL_STOP */
+ 1011 : }
+ 1012 :
+ 1013 1 : return 0;
+ 1014 : }
+ 1015 :
+ 1016 4 : int devquery(tommy_list* high, tommy_list* low, int operation)
+ 1017 : {
+ 1018 : tommy_node* i;
+ 1019 4 : void* (*func)(void* arg) = 0;
+ 1020 :
+ 1021 : #if HAVE_LINUX_DEVICE
+ 1022 4 : if (operation != DEVICE_UP) {
+ 1023 : struct stat st;
+ 1024 : /* sysfs and devfs interfaces are required */
+ 1025 3 : if (stat("/sys/dev/block", &st) != 0) {
+ 1026 : /* LCOV_EXCL_START */
+ 1027 : log_fatal("Missing interface /sys/dev/block.\n");
+ 1028 : return -1;
+ 1029 : /* LCOV_EXCL_STOP */
+ 1030 : }
+ 1031 3 : if (stat("/dev/block", &st) != 0) {
+ 1032 : /* LCOV_EXCL_START */
+ 1033 : log_fatal("Missing interface /dev/block.\n");
+ 1034 : return -1;
+ 1035 : /* LCOV_EXCL_STOP */
+ 1036 : }
+ 1037 :
+ 1038 : /* for each device */
+ 1039 39 : for (i = tommy_list_head(high); i != 0; i = i->next) {
+ 1040 36 : devinfo_t* devinfo = i->data;
+ 1041 :
+ 1042 : /* get the device file */
+ 1043 36 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) {
+ 1044 : /* LCOV_EXCL_START */
+ 1045 : log_fatal("Failed to resolve device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device));
+ 1046 : return -1;
+ 1047 : /* LCOV_EXCL_STOP */
+ 1048 : }
+ 1049 :
+ 1050 : /* expand the tree of devices */
+ 1051 36 : if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) {
+ 1052 : /* LCOV_EXCL_START */
+ 1053 : log_fatal("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device));
+ 1054 : return -1;
+ 1055 : /* LCOV_EXCL_STOP */
+ 1056 : }
+ 1057 : }
+ 1058 : }
+ 1059 : #endif
+ 1060 :
+ 1061 4 : if (operation == DEVICE_UP) {
+ 1062 : /* duplicate the high */
+ 1063 13 : for (i = tommy_list_head(high); i != 0; i = i->next) {
+ 1064 12 : devinfo_t* devinfo = i->data;
+ 1065 : devinfo_t* entry;
+ 1066 :
+ 1067 12 : entry = calloc_nofail(1, sizeof(devinfo_t));
+ 1068 :
+ 1069 12 : entry->device = devinfo->device;
+ 1070 12 : pathcpy(entry->name, sizeof(entry->name), devinfo->name);
+ 1071 12 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount);
+ 1072 :
+ 1073 : /* insert in the high */
+ 1074 12 : tommy_list_insert_tail(low, &entry->node, entry);
+ 1075 : }
+ 1076 : }
+ 1077 :
+ 1078 : #if HAVE_LINUX_DEVICE
+ 1079 : /* add other devices */
+ 1080 4 : if (operation == DEVICE_SMART) {
+ 1081 1 : if (devscan(low) != 0) {
+ 1082 : /* LCOV_EXCL_START */
+ 1083 : log_fatal("Failed to list other devices.\n");
+ 1084 : return -1;
+ 1085 : /* LCOV_EXCL_STOP */
+ 1086 : }
+ 1087 : }
+ 1088 : #endif
+ 1089 :
+ 1090 4 : switch (operation) {
+ 1091 1 : case DEVICE_UP : func = thread_spinup; break;
+ 1092 1 : case DEVICE_DOWN : func = thread_spindown; break;
+ 1093 1 : case DEVICE_SMART : func = thread_smart; break;
+ 1094 : }
+ 1095 :
+ 1096 4 : if (!func)
+ 1097 1 : return 0;
+ 1098 :
+ 1099 3 : return device_thread(low, func);
+ 1100 : }
+ 1101 :
+ 1102 260 : void os_init(int opt)
+ 1103 : {
+ 1104 : #if HAVE_BLKID
+ 1105 : int ret;
+ 1106 260 : ret = blkid_get_cache(&cache, NULL);
+ 1107 260 : if (ret != 0) {
+ 1108 : /* LCOV_EXCL_START */
+ 1109 : log_fatal("WARNING Failed to get blkid cache\n");
+ 1110 : /* LCOV_EXCL_STOP */
+ 1111 : }
+ 1112 : #endif
+ 1113 :
+ 1114 : (void)opt;
+ 1115 260 : }
+ 1116 :
+ 1117 238 : void os_done(void)
+ 1118 : {
+ 1119 : #if HAVE_BLKID
+ 1120 238 : if (cache != 0)
+ 1121 238 : blkid_put_cache(cache);
+ 1122 : #endif
+ 1123 238 : }
+ 1124 :
+ 1125 : /* LCOV_EXCL_START */
+ 1126 : void os_abort(void)
+ 1127 : {
+ 1128 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
+ 1129 : void* stack[32];
+ 1130 : char** messages;
+ 1131 : size_t size;
+ 1132 : unsigned i;
+ 1133 : #endif
+ 1134 :
+ 1135 : printf("Stacktrace of " PACKAGE " v" VERSION);
+ 1136 : #ifdef _linux
+ 1137 : printf(", linux");
+ 1138 : #endif
+ 1139 : #ifdef __GNUC__
+ 1140 : printf(", gcc " __VERSION__);
+ 1141 : #endif
+ 1142 : printf(", %d-bit", (int)sizeof(void *) * 8);
+ 1143 : printf(", PATH_MAX=%d", PATH_MAX);
+ 1144 : printf("\n");
+ 1145 :
+ 1146 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
+ 1147 : size = backtrace(stack, 32);
+ 1148 :
+ 1149 : messages = backtrace_symbols(stack, size);
+ 1150 :
+ 1151 : for (i=1; i<size; ++i) {
+ 1152 : const char* msg;
+ 1153 :
+ 1154 : if (messages)
+ 1155 : msg = messages[i];
+ 1156 : else
+ 1157 : msg = "<unknown>";
+ 1158 :
+ 1159 : printf("[bt] %02u: %s\n", i, msg);
+ 1160 :
+ 1161 : if (messages) {
+ 1162 : int ret;
+ 1163 : char addr2line[1024];
+ 1164 : size_t j = 0;
+ 1165 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0)
+ 1166 : ++j;
+ 1167 :
+ 1168 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg);
+ 1169 :
+ 1170 : ret = system(addr2line);
+ 1171 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)
+ 1172 : printf("exit:%d\n", WEXITSTATUS(ret));
+ 1173 : if (WIFSIGNALED(ret))
+ 1174 : printf("signal:%d\n", WTERMSIG(ret));
+ 1175 : }
+ 1176 : }
+ 1177 : #endif
+ 1178 :
+ 1179 : printf("Please report this error to the SnapRAID Forum:\n");
+ 1180 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n");
+ 1181 :
+ 1182 : abort();
+ 1183 : }
+ 1184 : /* LCOV_EXCL_STOP */
+ 1185 :
+ 1186 : #endif
+ 1187 :
diff --git a/cov/cmdline/util.c.func-sort-c.html b/cov/cmdline/util.c.func-sort-c.html
index 8fc8b9ea..83cf470e 100644
--- a/cov/cmdline/util.c.func-sort-c.html
+++ b/cov/cmdline/util.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,55 +61,55 @@
| util_rotl32 |
- 924861211 |
+ 796761149 |
| util_rotl64 |
- 461015664 |
+ 511410252 |
| memhash |
- 5724756 |
+ 5791413 |
| crc32c_x86 |
- 659527 |
+ 646616 |
| memdiff |
- 25190 |
+ 25329 |
| malloc_nofail_test |
- 2580 |
+ 1905 |
| mtest_vector |
- 2580 |
+ 1905 |
| crc32c_gen |
- 353 |
+ 369 |
| crc32c_init |
- 268 |
+ 276 |
| lock_lock |
- 243 |
+ 251 |
| lock_unlock |
- 223 |
+ 231 |
| malloc_nofail_vector_align |
- 201 |
+ 209 |
| malloc_nofail_align |
- 83 |
+ 91 |
| hash_config_name |
diff --git a/cov/cmdline/util.c.func.html b/cov/cmdline/util.c.func.html
index a05830bd..24210007 100644
--- a/cov/cmdline/util.c.func.html
+++ b/cov/cmdline/util.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| crc32c_gen |
- 353 |
+ 369 |
| crc32c_init |
- 268 |
+ 276 |
| crc32c_x86 |
- 659527 |
+ 646616 |
| hash_config_name |
@@ -77,43 +77,43 @@
| lock_lock |
- 243 |
+ 251 |
| lock_unlock |
- 223 |
+ 231 |
| malloc_nofail_align |
- 83 |
+ 91 |
| malloc_nofail_test |
- 2580 |
+ 1905 |
| malloc_nofail_vector_align |
- 201 |
+ 209 |
| memdiff |
- 25190 |
+ 25329 |
| memhash |
- 5724756 |
+ 5791413 |
| mtest_vector |
- 2580 |
+ 1905 |
| util_rotl32 |
- 924861211 |
+ 796761149 |
| util_rotl64 |
- 461015664 |
+ 511410252 |
diff --git a/cov/cmdline/util.c.gcov.html b/cov/cmdline/util.c.gcov.html
index 501f3b20..f023adf7 100644
--- a/cov/cmdline/util.c.gcov.html
+++ b/cov/cmdline/util.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -87,59 +87,59 @@
25 : /****************************************************************************/
26 : /* memory */
27 :
- 28 83 : void* malloc_nofail_align(size_t size, void** freeptr)
+ 28 91 : void* malloc_nofail_align(size_t size, void** freeptr)
29 : {
30 : void* ptr;
31 :
- 32 83 : ptr = raid_malloc_align(size, freeptr);
+ 32 91 : ptr = raid_malloc_align(size, freeptr);
33 :
- 34 83 : if (!ptr) {
+ 34 91 : if (!ptr) {
35 : /* LCOV_EXCL_START */
36 : malloc_fail(size);
37 : exit(EXIT_FAILURE);
38 : /* LCOV_EXCL_STOP */
39 : }
40 :
- 41 83 : return ptr;
+ 41 91 : return ptr;
42 : }
43 :
- 44 201 : void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr)
+ 44 209 : void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr)
45 : {
46 : void* ptr;
47 :
- 48 201 : ptr = raid_malloc_vector(nd, n, size, freeptr);
+ 48 209 : ptr = raid_malloc_vector(nd, n, size, freeptr);
49 :
- 50 201 : if (!ptr) {
+ 50 209 : if (!ptr) {
51 : /* LCOV_EXCL_START */
52 : malloc_fail(n * size);
53 : exit(EXIT_FAILURE);
54 : /* LCOV_EXCL_STOP */
55 : }
56 :
- 57 201 : return ptr;
+ 57 209 : return ptr;
58 : }
59 :
- 60 2580 : void* malloc_nofail_test(size_t size)
+ 60 1905 : void* malloc_nofail_test(size_t size)
61 : {
62 : void* ptr;
63 :
- 64 2580 : ptr = malloc_nofail(size);
+ 64 1905 : ptr = malloc_nofail(size);
65 :
- 66 2580 : mtest_vector(1, size, &ptr);
+ 66 1905 : mtest_vector(1, size, &ptr);
67 :
- 68 2580 : return ptr;
+ 68 1905 : return ptr;
69 : }
70 :
- 71 2580 : void mtest_vector(int n, size_t size, void** vv)
+ 71 1905 : void mtest_vector(int n, size_t size, void** vv)
72 : {
- 73 2580 : if (raid_mtest_vector(n, size, vv) != 0) {
+ 73 1905 : if (raid_mtest_vector(n, size, vv) != 0) {
74 : /* LCOV_EXCL_START */
75 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
76 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
77 : exit(EXIT_FAILURE);
78 : /* LCOV_EXCL_STOP */
79 : }
- 80 2580 : }
+ 80 1905 : }
81 :
82 : /****************************************************************************/
83 : /* crc */
@@ -416,42 +416,42 @@
354 : int crc_x86;
355 : #endif
356 :
- 357 353 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 357 369 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size)
358 : {
- 359 353 : crc ^= CRC_IV;
+ 359 369 : crc ^= CRC_IV;
360 :
- 361 353 : crc = crc32c_gen_plain(crc, ptr, size);
+ 361 369 : crc = crc32c_gen_plain(crc, ptr, size);
362 :
- 363 353 : crc ^= CRC_IV;
+ 363 369 : crc ^= CRC_IV;
364 :
- 365 353 : return crc;
+ 365 369 : return crc;
366 : }
367 :
368 : #if HAVE_SSE42
- 369 659527 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 369 646616 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size)
370 : {
- 371 659527 : crc ^= CRC_IV;
+ 371 646616 : crc ^= CRC_IV;
372 :
- 373 659527 : crc = crc32c_x86_plain(crc, ptr, size);
+ 373 646616 : crc = crc32c_x86_plain(crc, ptr, size);
374 :
- 375 659526 : crc ^= CRC_IV;
+ 375 646616 : crc ^= CRC_IV;
376 :
- 377 659526 : return crc;
+ 377 646616 : return crc;
378 : }
379 : #endif
380 :
381 : uint32_t (*crc32c)(uint32_t crc, const unsigned char* ptr, unsigned size);
382 :
- 383 268 : void crc32c_init(void)
+ 383 276 : void crc32c_init(void)
384 : {
- 385 268 : crc32c = crc32c_gen;
+ 385 276 : crc32c = crc32c_gen;
386 : #if HAVE_SSE42
- 387 268 : if (raid_cpu_has_crc32()) {
- 388 266 : crc_x86 = 1;
- 389 266 : crc32c = crc32c_x86;
+ 387 276 : if (raid_cpu_has_crc32()) {
+ 388 274 : crc_x86 = 1;
+ 389 274 : crc32c = crc32c_x86;
390 : }
391 : #endif
- 392 268 : }
+ 392 276 : }
393 :
394 : /****************************************************************************/
395 : /* byte operations */
@@ -460,14 +460,14 @@
398 : * Rotate left.
399 : * In x86/x64 they are optimized with a single assembler instruction.
400 : */
- 401 924861211 : static inline uint32_t util_rotl32(uint32_t x, int8_t r)
+ 401 796761149 : static inline uint32_t util_rotl32(uint32_t x, int8_t r)
402 : {
- 403 924861211 : return (x << r) | (x >> (32 - r));
+ 403 796761149 : return (x << r) | (x >> (32 - r));
404 : }
405 :
- 406 461015664 : static inline uint64_t util_rotl64(uint64_t x, int8_t r)
+ 406 511410252 : static inline uint64_t util_rotl64(uint64_t x, int8_t r)
407 : {
- 408 461015664 : return (x << r) | (x >> (64 - r));
+ 408 511410252 : return (x << r) | (x >> (64 - r));
409 : }
410 :
411 : /**
@@ -508,15 +508,15 @@
446 : #include "murmur3.c"
447 : #include "spooky2.c"
448 :
- 449 5724756 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size)
+ 449 5791413 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size)
450 : {
- 451 5724756 : switch (kind) {
+ 451 5791413 : switch (kind) {
452 : case HASH_MURMUR3 :
- 453 2252582 : MurmurHash3_x86_128(src, size, seed, digest);
- 454 2252582 : break;
+ 453 1936261 : MurmurHash3_x86_128(src, size, seed, digest);
+ 454 1936261 : break;
455 : case HASH_SPOOKY2 :
- 456 3472174 : SpookyHash128(src, size, seed, digest);
- 457 3472174 : break;
+ 456 3855152 : SpookyHash128(src, size, seed, digest);
+ 457 3855152 : break;
458 : default :
459 : /* LCOV_EXCL_START */
460 : log_fatal("Internal inconsistency in hash function %u\n", kind);
@@ -524,7 +524,7 @@
462 : break;
463 : /* LCOV_EXCL_STOP */
464 : }
- 465 5724756 : }
+ 465 5791413 : }
466 :
467 42 : const char* hash_config_name(unsigned kind)
468 : {
@@ -539,67 +539,67 @@
477 : }
478 : }
479 :
- 480 25190 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size)
+ 480 25329 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size)
481 : {
482 : size_t i;
483 : unsigned count;
484 :
- 485 25190 : count = 0;
- 486 11153350 : for (i = 0; i < size; ++i) {
+ 485 25329 : count = 0;
+ 486 11266593 : for (i = 0; i < size; ++i) {
487 : unsigned j;
- 488 11128160 : unsigned char diff = data1[i] ^ data2[i];
- 489 100153440 : for (j = 0; j < 8; ++j) {
- 490 89025280 : if ((diff & 1) != 0)
- 491 39291929 : ++count;
- 492 89025280 : diff >>= 1;
+ 488 11241264 : unsigned char diff = data1[i] ^ data2[i];
+ 489 101171376 : for (j = 0; j < 8; ++j) {
+ 490 89930112 : if ((diff & 1) != 0)
+ 491 39652202 : ++count;
+ 492 89930112 : diff >>= 1;
493 : }
494 : }
495 :
- 496 25190 : return 0;
+ 496 25329 : return count;
497 : }
498 :
499 : /****************************************************************************/
500 : /* lock */
501 :
502 : #if HAVE_LOCKFILE
- 503 243 : int lock_lock(const char* file)
+ 503 251 : int lock_lock(const char* file)
504 : {
505 : int f;
506 :
- 507 243 : f = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
- 508 243 : if (f == -1) {
+ 507 251 : f = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+ 508 251 : if (f == -1) {
509 : /* LCOV_EXCL_START */
510 : return -1;
511 : /* LCOV_EXCL_STOP */
512 : }
513 :
514 : /* exclusive lock, not blocking */
- 515 243 : if (flock(f, LOCK_EX | LOCK_NB) == -1) {
+ 515 251 : if (flock(f, LOCK_EX | LOCK_NB) == -1) {
516 : /* LCOV_EXCL_START */
517 : close(f);
518 : return -1;
519 : /* LCOV_EXCL_STOP */
520 : }
521 :
- 522 243 : return f;
+ 522 251 : return f;
523 : }
524 : #endif
525 :
526 : #if HAVE_LOCKFILE
- 527 223 : int lock_unlock(int f)
+ 527 231 : int lock_unlock(int f)
528 : {
529 : /*
530 : * Intentionally don't remove the lock file.
531 : * Removing it just introduces race course with other process
532 : * that could have already opened it.
533 : */
- 534 223 : if (close(f) == -1) {
+ 534 231 : if (close(f) == -1) {
535 : /* LCOV_EXCL_START */
536 : return -1;
537 : /* LCOV_EXCL_STOP */
538 : }
539 :
- 540 223 : return 0;
+ 540 231 : return 0;
541 : }
542 : #endif
543 :
diff --git a/cov/cmdline/util.h.func-sort-c.html b/cov/cmdline/util.h.func-sort-c.html
index aba2a712..d5e05907 100644
--- a/cov/cmdline/util.h.func-sort-c.html
+++ b/cov/cmdline/util.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| crc32c_x86_plain |
- 131602718 |
+ 21302165 |
| crc32c_plain |
- 128046334 |
+ 20655549 |
| crc32c_plain_char |
- 23675077 |
+ 3794625 |
| crc32c_gen_plain |
- 353 |
+ 369 |
diff --git a/cov/cmdline/util.h.func.html b/cov/cmdline/util.h.func.html
index 92bc1cda..de250087 100644
--- a/cov/cmdline/util.h.func.html
+++ b/cov/cmdline/util.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| crc32c_gen_plain |
- 353 |
+ 369 |
| crc32c_plain |
- 128046334 |
+ 20655549 |
| crc32c_plain_char |
- 23675077 |
+ 3794625 |
| crc32c_x86_plain |
- 131602718 |
+ 21302165 |
diff --git a/cov/cmdline/util.h.gcov.html b/cov/cmdline/util.h.gcov.html
index a736fd08..0023bf5a 100644
--- a/cov/cmdline/util.h.gcov.html
+++ b/cov/cmdline/util.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -133,12 +133,12 @@
71 : /**
72 : * Compute CRC-32 (Castagnoli) for a single byte without the IV.
73 : */
- 74 23675077 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c)
+ 74 3794625 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c)
75 : {
76 : #if HAVE_SSE42
- 77 23675077 : if (tommy_likely(crc_x86)) {
- 78 23675077 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c));
- 79 23675077 : return crc;
+ 77 3794625 : if (tommy_likely(crc_x86)) {
+ 78 3794625 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c));
+ 79 3794625 : return crc;
80 : }
81 : #endif
82 0 : return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8);
@@ -147,29 +147,29 @@
85 : /**
86 : * Compute the CRC-32 (Castagnoli) without the IV.
87 : */
- 88 353 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 88 369 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
89 : {
- 90 22020969 : while (size >= 4) {
- 91 22020263 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24;
- 92 22020263 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24];
- 93 22020263 : ptr += 4;
- 94 22020263 : size -= 4;
+ 90 23069577 : while (size >= 4) {
+ 91 23068839 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24;
+ 92 23068839 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24];
+ 93 23068839 : ptr += 4;
+ 94 23068839 : size -= 4;
95 : }
96 :
- 97 715 : while (size) {
+ 97 747 : while (size) {
98 9 : crc = CRC32C_0[(crc ^ *ptr) & 0xff] ^ (crc >> 8);
99 9 : ++ptr;
100 9 : --size;
101 : }
102 :
- 103 353 : return crc;
+ 103 369 : return crc;
104 : }
105 :
106 : /**
107 : * Compute the CRC-32 (Castagnoli) without the IV.
108 : */
109 : #if HAVE_SSE42
- 110 131602718 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 110 21302165 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
111 : {
112 : #ifdef CONFIG_X86_64
113 : uint64_t crc64 = crc;
@@ -180,30 +180,30 @@
118 : }
119 : crc = crc64;
120 : #else
- 121 969717854 : while (size >= 4) {
- 122 706512418 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr));
- 123 706512418 : ptr += 4;
- 124 706512418 : size -= 4;
+ 121 437931649 : while (size >= 4) {
+ 122 395327319 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr));
+ 123 395327319 : ptr += 4;
+ 124 395327319 : size -= 4;
125 : }
126 : #endif
- 127 382941674 : while (size) {
- 128 119736238 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr));
- 129 119736238 : ++ptr;
- 130 119736238 : --size;
+ 127 62072231 : while (size) {
+ 128 19467901 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr));
+ 129 19467901 : ++ptr;
+ 130 19467901 : --size;
131 : }
132 :
- 133 131602718 : return crc;
+ 133 21302165 : return crc;
134 : }
135 : #endif
136 :
137 : /**
138 : * Compute CRC-32 (Castagnoli) without the IV.
139 : */
- 140 128046334 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 140 20655549 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
141 : {
142 : #if HAVE_SSE42
- 143 128046334 : if (tommy_likely(crc_x86)) {
- 144 128046334 : return crc32c_x86_plain(crc, ptr, size);
+ 143 20655549 : if (tommy_likely(crc_x86)) {
+ 144 20655549 : return crc32c_x86_plain(crc, ptr, size);
145 : }
146 : #endif
147 0 : return crc32c_gen_plain(crc, ptr, size);
diff --git a/cov/index-sort-f.html b/cov/index-sort-f.html
index bc18c20f..4839cf1f 100644
--- a/cov/index-sort-f.html
+++ b/cov/index-sort-f.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 91.4 % |
- 7344 / 8033 |
- 97.7 % |
- 388 / 397 |
+ 91.6 % |
+ 7401 / 8084 |
+ 97.3 % |
+ 390 / 401 |
| tommyds |
diff --git a/cov/index-sort-l.html b/cov/index-sort-l.html
index 5f59d954..1ebddaa3 100644
--- a/cov/index-sort-l.html
+++ b/cov/index-sort-l.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 91.4 % |
- 7344 / 8033 |
- 97.7 % |
- 388 / 397 |
+ 91.6 % |
+ 7401 / 8084 |
+ 97.3 % |
+ 390 / 401 |
| raid |
diff --git a/cov/index.html b/cov/index.html
index abaf833c..b78b1c9d 100644
--- a/cov/index.html
+++ b/cov/index.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 91.4 % |
- 7344 / 8033 |
- 97.7 % |
- 388 / 397 |
+ 91.6 % |
+ 7401 / 8084 |
+ 97.3 % |
+ 390 / 401 |
| raid |
diff --git a/cov/raid/check.c.func-sort-c.html b/cov/raid/check.c.func-sort-c.html
index 0c9b19f8..f959d7cc 100644
--- a/cov/raid/check.c.func-sort-c.html
+++ b/cov/raid/check.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/check.c.func.html b/cov/raid/check.c.func.html
index eaef437a..0521de7f 100644
--- a/cov/raid/check.c.func.html
+++ b/cov/raid/check.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/check.c.gcov.html b/cov/raid/check.c.gcov.html
index 7b809175..adb2d25e 100644
--- a/cov/raid/check.c.gcov.html
+++ b/cov/raid/check.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/combo.h.func-sort-c.html b/cov/raid/combo.h.func-sort-c.html
index 9dc0148a..acdfb314 100644
--- a/cov/raid/combo.h.func-sort-c.html
+++ b/cov/raid/combo.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/combo.h.func.html b/cov/raid/combo.h.func.html
index 428b1c38..38c5a666 100644
--- a/cov/raid/combo.h.func.html
+++ b/cov/raid/combo.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/combo.h.gcov.html b/cov/raid/combo.h.gcov.html
index b8f76138..2ab1cb73 100644
--- a/cov/raid/combo.h.gcov.html
+++ b/cov/raid/combo.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -170,10 +170,10 @@
108 : int i;
109 :
110 : (void)n; /* unused, but kept for clarity */
- 111 215930 : assert(0 < r && r <= n);
+ 111 209410 : assert(0 < r && r <= n);
112 :
- 113 713829 : for (i = 0; i < r; ++i)
- 114 497899 : c[i] = i;
+ 113 691629 : for (i = 0; i < r; ++i)
+ 114 482219 : c[i] = i;
115 : }
116 :
117 : /**
@@ -182,19 +182,19 @@
120 : */
121 : static __always_inline int combination_next(int r, int n, int *c)
122 : {
- 123 51676 : int i = r - 1; /* present position */
- 124 51676 : int h = n; /* high limit for this position */
+ 123 51718 : int i = r - 1; /* present position */
+ 124 51718 : int h = n; /* high limit for this position */
125 :
126 : recurse:
127 : /* next element at position i */
- 128 84549 : ++c[i];
+ 128 84591 : ++c[i];
129 :
130 : /* if the position has reached the max */
- 131 84549 : if (c[i] >= h) {
+ 131 84591 : if (c[i] >= h) {
132 :
133 : /* if we are at the first level, we have finished */
- 134 44859 : if (i == 0)
- 135 11986 : return 0;
+ 134 44873 : if (i == 0)
+ 135 12000 : return 0;
136 :
137 : /* increase the previous position */
138 32873 : --i;
@@ -202,16 +202,16 @@
140 : goto recurse;
141 : }
142 :
- 143 39690 : ++i;
+ 143 39718 : ++i;
144 :
145 : /* initialize all the next positions, if any */
- 146 62235 : while (i < r) {
+ 146 62263 : while (i < r) {
147 : /* each position start at the next value of the previous one */
148 22545 : c[i] = c[i - 1] + 1;
149 22545 : ++i;
150 : }
151 :
- 152 39690 : return 1;
+ 152 39718 : return 1;
153 : }
154 : #endif
155 :
diff --git a/cov/raid/cpu.h.func-sort-c.html b/cov/raid/cpu.h.func-sort-c.html
index 8c4e735a..0c37739e 100644
--- a/cov/raid/cpu.h.func-sort-c.html
+++ b/cov/raid/cpu.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,43 +61,43 @@
| raid_cpuid |
- 1960 |
+ 2016 |
| raid_cpu_match_sse |
- 1117 |
+ 1149 |
| raid_cpu_has_ssse3 |
- 553 |
+ 569 |
| raid_cpu_match_avx |
- 300 |
+ 308 |
| raid_cpu_has_avx2 |
- 300 |
+ 308 |
| raid_cpu_has_sse2 |
- 288 |
+ 296 |
| raid_cpu_has_crc32 |
- 276 |
+ 284 |
| raid_cpu_info |
- 260 |
+ 268 |
| raid_cpu_is_atom |
- 256 |
+ 264 |
| raid_cpu_has_slowmult |
- 252 |
+ 260 |
| raid_xgetbv |
diff --git a/cov/raid/cpu.h.func.html b/cov/raid/cpu.h.func.html
index d313f5e0..738406d1 100644
--- a/cov/raid/cpu.h.func.html
+++ b/cov/raid/cpu.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| raid_cpu_has_avx2 |
- 300 |
+ 308 |
| raid_cpu_has_crc32 |
- 276 |
+ 284 |
| raid_cpu_has_slowextendedreg |
@@ -73,35 +73,35 @@
| raid_cpu_has_slowmult |
- 252 |
-
-
- | raid_cpu_has_sse2 |
- 288 |
-
-
- | raid_cpu_has_ssse3 |
- 553 |
-
-
- | raid_cpu_info |
260 |
+
+ | raid_cpu_has_sse2 |
+ 296 |
+
+
+ | raid_cpu_has_ssse3 |
+ 569 |
+
+
+ | raid_cpu_info |
+ 268 |
+
| raid_cpu_is_atom |
- 256 |
+ 264 |
| raid_cpu_match_avx |
- 300 |
+ 308 |
| raid_cpu_match_sse |
- 1117 |
+ 1149 |
| raid_cpuid |
- 1960 |
+ 2016 |
| raid_xgetbv |
diff --git a/cov/raid/cpu.h.gcov.html b/cov/raid/cpu.h.gcov.html
index af6259db..18c79d61 100644
--- a/cov/raid/cpu.h.gcov.html
+++ b/cov/raid/cpu.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -79,9 +79,9 @@
17 :
18 : #ifdef CONFIG_X86
19 :
- 20 1960 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg)
+ 20 2016 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg)
21 : {
- 22 1960 : asm volatile (
+ 22 2016 : asm volatile (
23 : #if defined(__i386__) && defined(__PIC__)
24 : /* allow compilation in PIC mode saving ebx */
25 : "xchgl %%ebx, %1\n"
@@ -91,11 +91,11 @@
29 : : "0" (func_eax), "2" (sub_ecx)
30 : #else
31 : "cpuid\n"
- 32 1960 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3])
+ 32 2016 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3])
33 : : "0" (func_eax), "2" (sub_ecx)
34 : #endif
35 : );
- 36 1960 : }
+ 36 2016 : }
37 :
38 23 : static inline void raid_xgetbv(uint32_t* reg)
39 : {
@@ -112,26 +112,26 @@
50 :
51 : #define CPU_VENDOR_MAX 13
52 :
- 53 260 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model)
+ 53 268 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model)
54 : {
55 : uint32_t reg[4];
56 : unsigned f, ef, m, em;
57 :
- 58 260 : raid_cpuid(0, 0, reg);
+ 58 268 : raid_cpuid(0, 0, reg);
59 :
- 60 260 : ((uint32_t*)vendor)[0] = reg[1];
- 61 260 : ((uint32_t*)vendor)[1] = reg[3];
- 62 260 : ((uint32_t*)vendor)[2] = reg[2];
- 63 260 : vendor[12] = 0;
+ 60 268 : ((uint32_t*)vendor)[0] = reg[1];
+ 61 268 : ((uint32_t*)vendor)[1] = reg[3];
+ 62 268 : ((uint32_t*)vendor)[2] = reg[2];
+ 63 268 : vendor[12] = 0;
64 :
- 65 260 : raid_cpuid(1, 0, reg);
+ 65 268 : raid_cpuid(1, 0, reg);
66 :
- 67 260 : f = (reg[0] >> 8) & 0xF;
- 68 260 : ef = (reg[0] >> 20) & 0xFF;
- 69 260 : m = (reg[0] >> 4) & 0xF;
- 70 260 : em = (reg[0] >> 16) & 0xF;
+ 67 268 : f = (reg[0] >> 8) & 0xF;
+ 68 268 : ef = (reg[0] >> 20) & 0xFF;
+ 69 268 : m = (reg[0] >> 4) & 0xF;
+ 70 268 : em = (reg[0] >> 16) & 0xF;
71 :
- 72 260 : if (strcmp(vendor, "AuthenticAMD") == 0) {
+ 72 268 : if (strcmp(vendor, "AuthenticAMD") == 0) {
73 0 : if (f < 15) {
74 0 : *family = f;
75 0 : *model = m;
@@ -140,31 +140,31 @@
78 0 : *model = m + (em << 4);
79 : }
80 : } else {
- 81 260 : *family = f + ef;
- 82 260 : *model = m + (em << 4);
+ 81 268 : *family = f + ef;
+ 82 268 : *model = m + (em << 4);
83 : }
- 84 260 : }
+ 84 268 : }
85 :
- 86 1117 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx)
+ 86 1149 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx)
87 : {
88 : uint32_t reg[4];
89 :
- 90 1117 : raid_cpuid(1, 0, reg);
- 91 1117 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx)
+ 90 1149 : raid_cpuid(1, 0, reg);
+ 91 1149 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx)
92 18 : return 0;
- 93 1099 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx)
+ 93 1131 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx)
94 0 : return 0;
95 :
- 96 1099 : return 1;
+ 96 1131 : return 1;
97 : }
98 :
- 99 300 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0)
+ 99 308 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0)
100 : {
101 : uint32_t reg[4];
102 :
- 103 300 : raid_cpuid(1, 0, reg);
- 104 300 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx)
- 105 277 : return 0;
+ 103 308 : raid_cpuid(1, 0, reg);
+ 104 308 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx)
+ 105 285 : return 0;
106 :
107 23 : raid_xgetbv(reg);
108 23 : if ((reg[0] & xcr0) != xcr0)
@@ -177,7 +177,7 @@
115 23 : return 1;
116 : }
117 :
- 118 288 : static inline int raid_cpu_has_sse2(void)
+ 118 296 : static inline int raid_cpu_has_sse2(void)
119 : {
120 : /*
121 : * Intel® 64 and IA-32 Architectures Software Developer's Manual
@@ -191,12 +191,12 @@
129 : * 2. Check that the processor supports the SSE and/or SSE2 extensions (true if
130 : * CPUID.01H:EDX.SSE[bit 25] = 1 and/or CPUID.01H:EDX.SSE2[bit 26] = 1).
131 : */
- 132 288 : return raid_cpu_match_sse(
+ 132 296 : return raid_cpu_match_sse(
133 : 0,
134 : 1 << 26); /* SSE2 */
135 : }
136 :
- 137 553 : static inline int raid_cpu_has_ssse3(void)
+ 137 569 : static inline int raid_cpu_has_ssse3(void)
138 : {
139 : /*
140 : * Intel® 64 and IA-32 Architectures Software Developer's Manual
@@ -208,12 +208,12 @@
146 : * Next, use the additional step provided below:
147 : * Check that the processor supports SSSE3 (if CPUID.01H:ECX.SSSE3[bit 9] = 1).
148 : */
- 149 553 : return raid_cpu_match_sse(
+ 149 569 : return raid_cpu_match_sse(
150 : 1 << 9, /* SSSE3 */
151 : 1 << 26); /* SSE2 */
152 : }
153 :
- 154 276 : static inline int raid_cpu_has_crc32(void)
+ 154 284 : static inline int raid_cpu_has_crc32(void)
155 : {
156 : /*
157 : * Intel® 64 and IA-32 Architectures Software Developer's Manual
@@ -224,12 +224,12 @@
162 : * Before an application attempts to use the CRC32 instruction, it must check
163 : * that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1).
164 : */
- 165 276 : return raid_cpu_match_sse(
+ 165 284 : return raid_cpu_match_sse(
166 : 1 << 20, /* CRC32 */
167 : 0);
168 : }
169 :
- 170 300 : static inline int raid_cpu_has_avx2(void)
+ 170 308 : static inline int raid_cpu_has_avx2(void)
171 : {
172 : /*
173 : * Intel Architecture Instruction Set Extensions Programming Reference
@@ -246,7 +246,7 @@
184 : * Application Software must identify that hardware supports AVX, after that it must
185 : * also detect support for AVX2 by checking CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5].
186 : */
- 187 300 : return raid_cpu_match_avx(
+ 187 308 : return raid_cpu_match_avx(
188 : (1 << 27) | (1 << 28), /* OSXSAVE and AVX */
189 : 1 << 5, /* AVX2 */
190 : 3 << 1); /* OS saves XMM and YMM registers */
@@ -277,9 +277,9 @@
215 : /**
216 : * Check if it's an Intel Atom CPU.
217 : */
- 218 256 : static inline int raid_cpu_is_atom(unsigned family, unsigned model)
+ 218 264 : static inline int raid_cpu_is_atom(unsigned family, unsigned model)
219 : {
- 220 256 : if (family != 6)
+ 220 264 : if (family != 6)
221 3 : return 0;
222 :
223 : /*
@@ -300,17 +300,17 @@
238 : * 4D (77) Atom 8C (22 nm) 4 MB L2 (AVN)
239 : * ?? Atom ?C (14 nm) ? MB L2 (DVN)
240 : */
- 241 506 : return model == 28 || model == 38 || model == 54
- 242 253 : || model == 39 || model == 53 || model == 74
- 243 253 : || model == 90 || model == 55 || model == 76
- 244 506 : || model == 93 || model == 77;
+ 241 522 : return model == 28 || model == 38 || model == 54
+ 242 261 : || model == 39 || model == 53 || model == 74
+ 243 261 : || model == 90 || model == 55 || model == 76
+ 244 522 : || model == 93 || model == 77;
245 : }
246 :
247 : /**
248 : * Check if the processor has a slow MULT implementation.
249 : * If yes, it's better to use a hash not based on multiplication.
250 : */
- 251 252 : static inline int raid_cpu_has_slowmult(void)
+ 251 260 : static inline int raid_cpu_has_slowmult(void)
252 : {
253 : char vendor[CPU_VENDOR_MAX];
254 : unsigned family;
@@ -320,9 +320,9 @@
258 : * In some cases Murmur3 based on MUL instruction,
259 : * is a LOT slower than Spooky2 based on SHIFTs.
260 : */
- 261 252 : raid_cpu_info(vendor, &family, &model);
+ 261 260 : raid_cpu_info(vendor, &family, &model);
262 :
- 263 252 : if (strcmp(vendor, "GenuineIntel") == 0) {
+ 263 260 : if (strcmp(vendor, "GenuineIntel") == 0) {
264 : /*
265 : * Intel Atom (Model 28)
266 : * murmur3:378 MB/s, spooky2:3413 MB/s (x86)
@@ -330,11 +330,11 @@
268 : * Intel Atom (Model 77)
269 : * murmur3:1311 MB/s, spooky2:4056 MB/s (x64)
270 : */
- 271 252 : if (raid_cpu_is_atom(family, model))
+ 271 260 : if (raid_cpu_is_atom(family, model))
272 0 : return 1;
273 : }
274 :
- 275 252 : return 0;
+ 275 260 : return 0;
276 : }
277 :
278 : /**
@@ -368,17 +368,29 @@
306 : * Intel Atom (Model 77)
307 : * par2_sse2:5686 MB/s, par2_sse2e:5250 MB/s
308 : * parz_sse2:3100 MB/s, parz_sse2e:3400 MB/s
- 309 : */
- 310 4 : if (raid_cpu_is_atom(family, model))
- 311 0 : return 1;
- 312 : }
- 313 :
- 314 4 : return 0;
- 315 : }
- 316 : #endif
- 317 :
- 318 : #endif
- 319 :
+ 309 : * par3_sse3:1921 MB/s, par3_sse3e:1813 MB/s
+ 310 : * par4_sse3:1175 MB/s, par4_sse3e:1113 MB/s
+ 311 : * par5_sse3:876 MB/s, par5_sse3e:675 MB/s
+ 312 : * par6_sse3:705 MB/s, par6_sse3e:529 MB/s
+ 313 : *
+ 314 : * Intel Atom (Model 77) "Avoton C2750"
+ 315 : * par2_sse2:5661 MB/s, par2_sse2e:5382 MB/s
+ 316 : * parz_sse2:3110 MB/s, parz_sse2e:3450 MB/s
+ 317 : * par3_sse3:1769 MB/s, par3_sse3e:1856 MB/s
+ 318 : * par4_sse3:1221 MB/s, par4_sse3e:1141 MB/s
+ 319 : * par5_sse3:910 MB/s, par5_sse3e:675 MB/s
+ 320 : * par6_sse3:720 MB/s, par6_sse3e:534 MB/s
+ 321 : */
+ 322 4 : if (raid_cpu_is_atom(family, model))
+ 323 0 : return 1;
+ 324 : }
+ 325 :
+ 326 4 : return 0;
+ 327 : }
+ 328 : #endif
+ 329 :
+ 330 : #endif
+ 331 :
diff --git a/cov/raid/gf.h.func-sort-c.html b/cov/raid/gf.h.func-sort-c.html
index 38e50d01..7af0ce91 100644
--- a/cov/raid/gf.h.func-sort-c.html
+++ b/cov/raid/gf.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/gf.h.func.html b/cov/raid/gf.h.func.html
index d99cf543..888e7000 100644
--- a/cov/raid/gf.h.func.html
+++ b/cov/raid/gf.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/gf.h.gcov.html b/cov/raid/gf.h.gcov.html
index f7076a13..df951c95 100644
--- a/cov/raid/gf.h.gcov.html
+++ b/cov/raid/gf.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -88,7 +88,7 @@
26 : */
27 : static __always_inline uint8_t mul(uint8_t a, uint8_t b)
28 : {
- 29 23813346 : return gfmul[a][b];
+ 29 23756618 : return gfmul[a][b];
30 : }
31 :
32 : /*
@@ -97,9 +97,9 @@
35 : */
36 : static __always_inline uint8_t inv(uint8_t v)
37 : {
- 38 635522 : BUG_ON(v == 0); /* division by zero */
+ 38 634222 : BUG_ON(v == 0); /* division by zero */
39 :
- 40 635522 : return gfinv[v];
+ 40 634222 : return gfinv[v];
41 : }
42 :
43 : /*
@@ -125,7 +125,7 @@
63 : */
64 : static __always_inline uint8_t A(int p, int d)
65 : {
- 66 2605866 : return gfgen[p][d];
+ 66 2600612 : return gfgen[p][d];
67 : }
68 :
69 : /*
diff --git a/cov/raid/helper.c.func-sort-c.html b/cov/raid/helper.c.func-sort-c.html
index 47ed9277..108d31b9 100644
--- a/cov/raid/helper.c.func-sort-c.html
+++ b/cov/raid/helper.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/helper.c.func.html b/cov/raid/helper.c.func.html
index d1b46f34..0d73260c 100644
--- a/cov/raid/helper.c.func.html
+++ b/cov/raid/helper.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/helper.c.gcov.html b/cov/raid/helper.c.gcov.html
index 16b6e3f4..884204c0 100644
--- a/cov/raid/helper.c.gcov.html
+++ b/cov/raid/helper.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/index-sort-f.html b/cov/raid/index-sort-f.html
index 53f2d677..c85a5cc2 100644
--- a/cov/raid/index-sort-f.html
+++ b/cov/raid/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/index-sort-l.html b/cov/raid/index-sort-l.html
index 194b0b2c..f03066e7 100644
--- a/cov/raid/index-sort-l.html
+++ b/cov/raid/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/index.html b/cov/raid/index.html
index c0b34a7b..bf806d40 100644
--- a/cov/raid/index.html
+++ b/cov/raid/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/int.c.func-sort-c.html b/cov/raid/int.c.func-sort-c.html
index 1e9686f8..660780c1 100644
--- a/cov/raid/int.c.func-sort-c.html
+++ b/cov/raid/int.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -69,7 +69,7 @@
| raid_gen1_int64 |
- 188 |
+ 191 |
| raid_rec1_int8 |
@@ -77,7 +77,7 @@
| raid_gen1_int32 |
- 117 |
+ 119 |
| raid_gen2_int64 |
@@ -101,7 +101,7 @@
| raid_gen6_int8 |
- 16 |
+ 18 |
diff --git a/cov/raid/int.c.func.html b/cov/raid/int.c.func.html
index a9474d76..15c0b92e 100644
--- a/cov/raid/int.c.func.html
+++ b/cov/raid/int.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| raid_gen1_int32 |
- 117 |
+ 119 |
| raid_gen1_int64 |
- 188 |
+ 191 |
| raid_gen2_int32 |
@@ -89,7 +89,7 @@
| raid_gen6_int8 |
- 16 |
+ 18 |
| raid_rec1_int8 |
diff --git a/cov/raid/int.c.gcov.html b/cov/raid/int.c.gcov.html
index c6a492cd..861cd372 100644
--- a/cov/raid/int.c.gcov.html
+++ b/cov/raid/int.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -80,9 +80,9 @@
18 : /*
19 : * GEN1 (RAID5 with xor) 32bit C implementation
20 : */
- 21 117 : void raid_gen1_int32(int nd, size_t size, void **vv)
+ 21 119 : void raid_gen1_int32(int nd, size_t size, void **vv)
22 : {
- 23 117 : uint8_t **v = (uint8_t **)vv;
+ 23 119 : uint8_t **v = (uint8_t **)vv;
24 : uint8_t *p;
25 : int d, l;
26 : size_t i;
@@ -90,27 +90,27 @@
28 : uint32_t p0;
29 : uint32_t p1;
30 :
- 31 117 : l = nd - 1;
- 32 117 : p = v[nd];
+ 31 119 : l = nd - 1;
+ 32 119 : p = v[nd];
33 :
- 34 3735765 : for (i = 0; i < size; i += 8) {
- 35 3735648 : p0 = v_32(v[l][i]);
- 36 3735648 : p1 = v_32(v[l][i + 4]);
- 37 29886496 : for (d = l - 1; d >= 0; --d) {
- 38 26150848 : p0 ^= v_32(v[d][i]);
- 39 26150848 : p1 ^= v_32(v[d][i + 4]);
+ 34 3801303 : for (i = 0; i < size; i += 8) {
+ 35 3801184 : p0 = v_32(v[l][i]);
+ 36 3801184 : p1 = v_32(v[l][i + 4]);
+ 37 30410784 : for (d = l - 1; d >= 0; --d) {
+ 38 26609600 : p0 ^= v_32(v[d][i]);
+ 39 26609600 : p1 ^= v_32(v[d][i + 4]);
40 : }
- 41 3735648 : v_32(p[i]) = p0;
- 42 3735648 : v_32(p[i + 4]) = p1;
+ 41 3801184 : v_32(p[i]) = p0;
+ 42 3801184 : v_32(p[i + 4]) = p1;
43 : }
- 44 117 : }
+ 44 119 : }
45 :
46 : /*
47 : * GEN1 (RAID5 with xor) 64bit C implementation
48 : */
- 49 188 : void raid_gen1_int64(int nd, size_t size, void **vv)
+ 49 191 : void raid_gen1_int64(int nd, size_t size, void **vv)
50 : {
- 51 188 : uint8_t **v = (uint8_t **)vv;
+ 51 191 : uint8_t **v = (uint8_t **)vv;
52 : uint8_t *p;
53 : int d, l;
54 : size_t i;
@@ -118,20 +118,20 @@
56 : uint64_t p0;
57 : uint64_t p1;
58 :
- 59 188 : l = nd - 1;
- 60 188 : p = v[nd];
+ 59 191 : l = nd - 1;
+ 60 191 : p = v[nd];
61 :
- 62 3031276 : for (i = 0; i < size; i += 16) {
- 63 3031088 : p0 = v_64(v[l][i]);
- 64 3031088 : p1 = v_64(v[l][i + 8]);
- 65 24249360 : for (d = l - 1; d >= 0; --d) {
- 66 21218272 : p0 ^= v_64(v[d][i]);
- 67 21218272 : p1 ^= v_64(v[d][i + 8]);
+ 62 3080431 : for (i = 0; i < size; i += 16) {
+ 63 3080240 : p0 = v_64(v[l][i]);
+ 64 3080240 : p1 = v_64(v[l][i + 8]);
+ 65 24642576 : for (d = l - 1; d >= 0; --d) {
+ 66 21562336 : p0 ^= v_64(v[d][i]);
+ 67 21562336 : p1 ^= v_64(v[d][i + 8]);
68 : }
- 69 3031088 : v_64(p[i]) = p0;
- 70 3031088 : v_64(p[i + 8]) = p1;
+ 69 3080240 : v_64(p[i]) = p0;
+ 70 3080240 : v_64(p[i + 8]) = p1;
71 : }
- 72 188 : }
+ 72 191 : }
73 :
74 : /*
75 : * GEN2 (RAID6 with powers of 2) 32bit C implementation
@@ -379,9 +379,9 @@
317 : * But this is only a kind of reference function, and we are not really
318 : * interested in speed.
319 : */
- 320 16 : void raid_gen6_int8(int nd, size_t size, void **vv)
+ 320 18 : void raid_gen6_int8(int nd, size_t size, void **vv)
321 : {
- 322 16 : uint8_t **v = (uint8_t **)vv;
+ 322 18 : uint8_t **v = (uint8_t **)vv;
323 : uint8_t *p;
324 : uint8_t *q;
325 : uint8_t *r;
@@ -393,45 +393,45 @@
331 :
332 : uint8_t d0, u0, t0, s0, r0, q0, p0;
333 :
- 334 16 : l = nd - 1;
- 335 16 : p = v[nd];
- 336 16 : q = v[nd + 1];
- 337 16 : r = v[nd + 2];
- 338 16 : s = v[nd + 3];
- 339 16 : t = v[nd + 4];
- 340 16 : u = v[nd + 5];
+ 334 18 : l = nd - 1;
+ 335 18 : p = v[nd];
+ 336 18 : q = v[nd + 1];
+ 337 18 : r = v[nd + 2];
+ 338 18 : s = v[nd + 3];
+ 339 18 : t = v[nd + 4];
+ 340 18 : u = v[nd + 5];
341 :
- 342 3670544 : for (i = 0; i < size; i += 1) {
- 343 3670528 : p0 = q0 = r0 = s0 = t0 = u0 = 0;
- 344 29368576 : for (d = l; d > 0; --d) {
- 345 25698048 : d0 = v_8(v[d][i]);
+ 342 4194834 : for (i = 0; i < size; i += 1) {
+ 343 4194816 : p0 = q0 = r0 = s0 = t0 = u0 = 0;
+ 344 33562880 : for (d = l; d > 0; --d) {
+ 345 29368064 : d0 = v_8(v[d][i]);
346 :
- 347 25698048 : p0 ^= d0;
- 348 25698048 : q0 ^= gfmul[d0][gfgen[1][d]];
- 349 25698048 : r0 ^= gfmul[d0][gfgen[2][d]];
- 350 25698048 : s0 ^= gfmul[d0][gfgen[3][d]];
- 351 25698048 : t0 ^= gfmul[d0][gfgen[4][d]];
- 352 25698048 : u0 ^= gfmul[d0][gfgen[5][d]];
+ 347 29368064 : p0 ^= d0;
+ 348 29368064 : q0 ^= gfmul[d0][gfgen[1][d]];
+ 349 29368064 : r0 ^= gfmul[d0][gfgen[2][d]];
+ 350 29368064 : s0 ^= gfmul[d0][gfgen[3][d]];
+ 351 29368064 : t0 ^= gfmul[d0][gfgen[4][d]];
+ 352 29368064 : u0 ^= gfmul[d0][gfgen[5][d]];
353 : }
354 :
355 : /* first disk with all coefficients at 1 */
- 356 3670528 : d0 = v_8(v[0][i]);
+ 356 4194816 : d0 = v_8(v[0][i]);
357 :
- 358 3670528 : p0 ^= d0;
- 359 3670528 : q0 ^= d0;
- 360 3670528 : r0 ^= d0;
- 361 3670528 : s0 ^= d0;
- 362 3670528 : t0 ^= d0;
- 363 3670528 : u0 ^= d0;
+ 358 4194816 : p0 ^= d0;
+ 359 4194816 : q0 ^= d0;
+ 360 4194816 : r0 ^= d0;
+ 361 4194816 : s0 ^= d0;
+ 362 4194816 : t0 ^= d0;
+ 363 4194816 : u0 ^= d0;
364 :
- 365 3670528 : v_8(p[i]) = p0;
- 366 3670528 : v_8(q[i]) = q0;
- 367 3670528 : v_8(r[i]) = r0;
- 368 3670528 : v_8(s[i]) = s0;
- 369 3670528 : v_8(t[i]) = t0;
- 370 3670528 : v_8(u[i]) = u0;
+ 365 4194816 : v_8(p[i]) = p0;
+ 366 4194816 : v_8(q[i]) = q0;
+ 367 4194816 : v_8(r[i]) = r0;
+ 368 4194816 : v_8(s[i]) = s0;
+ 369 4194816 : v_8(t[i]) = t0;
+ 370 4194816 : v_8(u[i]) = u0;
371 : }
- 372 16 : }
+ 372 18 : }
373 :
374 : /*
375 : * Recover failure of one data block at index id[0] using parity at index
diff --git a/cov/raid/internal.h.func-sort-c.html b/cov/raid/internal.h.func-sort-c.html
index 3b75e83e..7dd87557 100644
--- a/cov/raid/internal.h.func-sort-c.html
+++ b/cov/raid/internal.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/internal.h.func.html b/cov/raid/internal.h.func.html
index ee4ceee8..967a0919 100644
--- a/cov/raid/internal.h.func.html
+++ b/cov/raid/internal.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/internal.h.gcov.html b/cov/raid/internal.h.gcov.html
index 3e410102..ebbd007d 100644
--- a/cov/raid/internal.h.gcov.html
+++ b/cov/raid/internal.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -159,11 +159,11 @@
97 : */
98 : static __always_inline void *__align_ptr(void *ptr, uintptr_t size)
99 : {
- 100 696987 : uintptr_t offset = (uintptr_t)ptr;
+ 100 706415 : uintptr_t offset = (uintptr_t)ptr;
101 :
- 102 696987 : offset = (offset + size - 1U) & ~(size - 1U);
+ 102 706415 : offset = (offset + size - 1U) & ~(size - 1U);
103 :
- 104 696987 : return (void *)offset;
+ 104 706415 : return (void *)offset;
105 : }
106 :
107 : /*
@@ -284,7 +284,7 @@
222 : /* that use a weak memory model. To ensure that other processors */
223 : /* see correctly the data written, we use a store-store memory */
224 : /* barrier at the end of the asm code */
- 225 1365700 : asm volatile ("sfence" : : : "memory");
+ 225 1360449 : asm volatile ("sfence" : : : "memory");
226 :
227 : /* clobbers registers used in the asm code */
228 : /* this is required because in the Windows ABI, */
diff --git a/cov/raid/intz.c.func-sort-c.html b/cov/raid/intz.c.func-sort-c.html
index b79b344c..55b7b56a 100644
--- a/cov/raid/intz.c.func-sort-c.html
+++ b/cov/raid/intz.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/intz.c.func.html b/cov/raid/intz.c.func.html
index 081fcf8b..53b342cf 100644
--- a/cov/raid/intz.c.func.html
+++ b/cov/raid/intz.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/intz.c.gcov.html b/cov/raid/intz.c.gcov.html
index 68473b3c..5e3bd004 100644
--- a/cov/raid/intz.c.gcov.html
+++ b/cov/raid/intz.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/memory.c.func-sort-c.html b/cov/raid/memory.c.func-sort-c.html
index fd1f5017..5c3a69d2 100644
--- a/cov/raid/memory.c.func-sort-c.html
+++ b/cov/raid/memory.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| raid_mtest_vector |
- 2579 |
+ 1908 |
| raid_malloc_align |
- 290 |
+ 306 |
| raid_malloc_vector |
- 207 |
+ 215 |
| raid_mrand_vector |
diff --git a/cov/raid/memory.c.func.html b/cov/raid/memory.c.func.html
index 25536f02..cc06ef36 100644
--- a/cov/raid/memory.c.func.html
+++ b/cov/raid/memory.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| raid_malloc_align |
- 290 |
+ 306 |
| raid_malloc_vector |
- 207 |
+ 215 |
| raid_mrand_vector |
@@ -73,7 +73,7 @@
| raid_mtest_vector |
- 2579 |
+ 1908 |
diff --git a/cov/raid/memory.c.gcov.html b/cov/raid/memory.c.gcov.html
index 3830eccb..aa6061b4 100644
--- a/cov/raid/memory.c.gcov.html
+++ b/cov/raid/memory.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -77,66 +77,66 @@
15 : #include "internal.h"
16 : #include "memory.h"
17 :
- 18 290 : void *raid_malloc_align(size_t size, void **freeptr)
+ 18 306 : void *raid_malloc_align(size_t size, void **freeptr)
19 : {
20 : unsigned char *ptr;
21 : uintptr_t offset;
22 :
- 23 290 : ptr = malloc(size + RAID_MALLOC_ALIGN);
- 24 290 : if (!ptr) {
+ 23 306 : ptr = malloc(size + RAID_MALLOC_ALIGN);
+ 24 306 : if (!ptr) {
25 : /* LCOV_EXCL_START */
26 : return 0;
27 : /* LCOV_EXCL_STOP */
28 : }
29 :
- 30 290 : *freeptr = ptr;
+ 30 306 : *freeptr = ptr;
31 :
- 32 290 : offset = ((uintptr_t)ptr) % RAID_MALLOC_ALIGN;
+ 32 306 : offset = ((uintptr_t)ptr) % RAID_MALLOC_ALIGN;
33 :
- 34 290 : if (offset != 0)
- 35 287 : ptr += RAID_MALLOC_ALIGN - offset;
+ 34 306 : if (offset != 0)
+ 35 297 : ptr += RAID_MALLOC_ALIGN - offset;
36 :
- 37 290 : return ptr;
+ 37 306 : return ptr;
38 : }
39 :
- 40 207 : void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr)
+ 40 215 : void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr)
41 : {
42 : void **v;
43 : unsigned char *va;
44 : int i;
45 :
- 46 207 : BUG_ON(n <= 0 || nd < 0);
+ 46 215 : BUG_ON(n <= 0 || nd < 0);
47 :
- 48 207 : v = malloc(n * sizeof(void *));
- 49 207 : if (!v) {
+ 48 215 : v = malloc(n * sizeof(void *));
+ 49 215 : if (!v) {
50 : /* LCOV_EXCL_START */
51 : return 0;
52 : /* LCOV_EXCL_STOP */
53 : }
54 :
- 55 207 : va = raid_malloc_align(n * (size + RAID_MALLOC_DISPLACEMENT), freeptr);
- 56 207 : if (!va) {
+ 55 215 : va = raid_malloc_align(n * (size + RAID_MALLOC_DISPLACEMENT), freeptr);
+ 56 215 : if (!va) {
57 : /* LCOV_EXCL_START */
58 : free(v);
59 : return 0;
60 : /* LCOV_EXCL_STOP */
61 : }
62 :
- 63 3676 : for (i = 0; i < n; ++i) {
- 64 3469 : v[i] = va;
- 65 3469 : va += size + RAID_MALLOC_DISPLACEMENT;
+ 63 3836 : for (i = 0; i < n; ++i) {
+ 64 3621 : v[i] = va;
+ 65 3621 : va += size + RAID_MALLOC_DISPLACEMENT;
66 : }
67 :
68 : /* reverse order of the data blocks */
69 : /* because they are usually accessed from the last one */
- 70 866 : for (i = 0; i < nd / 2; ++i) {
- 71 659 : void *ptr = v[i];
+ 70 898 : for (i = 0; i < nd / 2; ++i) {
+ 71 683 : void *ptr = v[i];
72 :
- 73 659 : v[i] = v[nd - 1 - i];
- 74 659 : v[nd - 1 - i] = ptr;
+ 73 683 : v[i] = v[nd - 1 - i];
+ 74 683 : v[nd - 1 - i] = ptr;
75 : }
76 :
- 77 207 : return v;
+ 77 215 : return v;
78 : }
79 :
80 5 : void raid_mrand_vector(unsigned seed, int n, size_t size, void **vv)
@@ -154,9 +154,9 @@
92 : }
93 5 : }
94 :
- 95 2579 : int raid_mtest_vector(int n, size_t size, void **vv)
+ 95 1908 : int raid_mtest_vector(int n, size_t size, void **vv)
96 : {
- 97 2579 : unsigned char **v = (unsigned char **)vv;
+ 97 1908 : unsigned char **v = (unsigned char **)vv;
98 : int i;
99 : size_t j;
100 : unsigned k;
@@ -164,44 +164,44 @@
102 : unsigned char p;
103 :
104 : /* fill with 0 */
- 105 2579 : d = 0;
- 106 5254 : for (i = 0; i < n; ++i)
- 107 137567034 : for (j = 0; j < size; ++j)
- 108 137564359 : v[i][j] = d;
+ 105 1908 : d = 0;
+ 106 3908 : for (i = 0; i < n; ++i)
+ 107 107048920 : for (j = 0; j < size; ++j)
+ 108 107046920 : v[i][j] = d;
109 :
110 : /* test with all the byte patterns */
- 111 661244 : for (k = 1; k < 256; ++k) {
- 112 658661 : p = d;
- 113 658661 : d = k;
+ 111 488448 : for (k = 1; k < 256; ++k) {
+ 112 486540 : p = d;
+ 113 486540 : d = k;
114 :
115 : /* forward fill */
- 116 1340781 : for (i = 0; i < n; ++i) {
- 117 24484944507 : for (j = 0; j < size; ++j) {
- 118 24484262387 : if (v[i][j] != p) {
+ 116 996540 : for (i = 0; i < n; ++i) {
+ 117 27297474600 : for (j = 0; j < size; ++j) {
+ 118 27296964600 : if (v[i][j] != p) {
119 : /* LCOV_EXCL_START */
120 : return -1;
121 : /* LCOV_EXCL_STOP */
122 : }
- 123 24484262387 : v[i][j] = d;
+ 123 27296964600 : v[i][j] = d;
124 : }
125 : }
126 :
- 127 658661 : p = d;
- 128 658661 : d = ~p;
+ 127 486540 : p = d;
+ 128 486540 : d = ~p;
129 : /* backward fill with complement */
- 130 1340786 : for (i = 0; i < n; ++i) {
- 131 24126962138 : for (j = size; j > 0; --j) {
- 132 24126280013 : if (v[i][j - 1] != p) {
+ 130 996540 : for (i = 0; i < n; ++i) {
+ 131 27297474600 : for (j = size; j > 0; --j) {
+ 132 27296964600 : if (v[i][j - 1] != p) {
133 : /* LCOV_EXCL_START */
134 : return -1;
135 : /* LCOV_EXCL_STOP */
136 : }
- 137 24126280017 : v[i][j - 1] = d;
+ 137 27296964600 : v[i][j - 1] = d;
138 : }
139 : }
140 : }
141 :
- 142 2583 : return 0;
+ 142 1908 : return 0;
143 : }
144 :
diff --git a/cov/raid/module.c.func-sort-c.html b/cov/raid/module.c.func-sort-c.html
index 3a1aa0e0..7e3f1ccb 100644
--- a/cov/raid/module.c.func-sort-c.html
+++ b/cov/raid/module.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,30 +61,30 @@
| raid_init |
- 252 |
+ 260 |
- | raid_test_rec |
+ raid_test_rec |
18 |
- | raid_test_data |
+ raid_test_data |
18 |
- | raid_test_scan |
+ raid_test_scan |
7 |
- | raid_gen_ref |
+ raid_gen_ref |
6 |
- | raid_test_par |
+ raid_test_par |
6 |
- | raid_selftest |
+ raid_selftest |
1 |
diff --git a/cov/raid/module.c.func.html b/cov/raid/module.c.func.html
index a93ef0a6..b40762dd 100644
--- a/cov/raid/module.c.func.html
+++ b/cov/raid/module.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,31 +60,31 @@
Hit count  |
- | raid_gen_ref |
+ raid_gen_ref |
6 |
| raid_init |
- 252 |
+ 260 |
- | raid_selftest |
+ raid_selftest |
1 |
- | raid_test_data |
+ raid_test_data |
18 |
- | raid_test_par |
+ raid_test_par |
6 |
- | raid_test_rec |
+ raid_test_rec |
18 |
- | raid_test_scan |
+ raid_test_scan |
7 |
diff --git a/cov/raid/module.c.gcov.html b/cov/raid/module.c.gcov.html
index 5769f207..ffb20426 100644
--- a/cov/raid/module.c.gcov.html
+++ b/cov/raid/module.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -81,34 +81,34 @@
19 : /*
20 : * Initializes and selects the best algorithm.
21 : */
- 22 252 : void raid_init(void)
+ 22 260 : void raid_init(void)
23 : {
- 24 252 : raid_gen3_ptr = raid_gen3_int8;
- 25 252 : raid_gen_ptr[3] = raid_gen4_int8;
- 26 252 : raid_gen_ptr[4] = raid_gen5_int8;
- 27 252 : raid_gen_ptr[5] = raid_gen6_int8;
+ 24 260 : raid_gen3_ptr = raid_gen3_int8;
+ 25 260 : raid_gen_ptr[3] = raid_gen4_int8;
+ 26 260 : raid_gen_ptr[4] = raid_gen5_int8;
+ 27 260 : raid_gen_ptr[5] = raid_gen6_int8;
28 :
29 : if (sizeof(void *) == 4) {
- 30 252 : raid_gen_ptr[0] = raid_gen1_int32;
- 31 252 : raid_gen_ptr[1] = raid_gen2_int32;
- 32 252 : raid_genz_ptr = raid_genz_int32;
+ 30 260 : raid_gen_ptr[0] = raid_gen1_int32;
+ 31 260 : raid_gen_ptr[1] = raid_gen2_int32;
+ 32 260 : raid_genz_ptr = raid_genz_int32;
33 : } else {
34 : raid_gen_ptr[0] = raid_gen1_int64;
35 : raid_gen_ptr[1] = raid_gen2_int64;
36 : raid_genz_ptr = raid_genz_int64;
37 : }
38 :
- 39 252 : raid_rec_ptr[0] = raid_rec1_int8;
- 40 252 : raid_rec_ptr[1] = raid_rec2_int8;
- 41 252 : raid_rec_ptr[2] = raid_recX_int8;
- 42 252 : raid_rec_ptr[3] = raid_recX_int8;
- 43 252 : raid_rec_ptr[4] = raid_recX_int8;
- 44 252 : raid_rec_ptr[5] = raid_recX_int8;
+ 39 260 : raid_rec_ptr[0] = raid_rec1_int8;
+ 40 260 : raid_rec_ptr[1] = raid_rec2_int8;
+ 41 260 : raid_rec_ptr[2] = raid_recX_int8;
+ 42 260 : raid_rec_ptr[3] = raid_recX_int8;
+ 43 260 : raid_rec_ptr[4] = raid_recX_int8;
+ 44 260 : raid_rec_ptr[5] = raid_recX_int8;
45 :
46 : #ifdef CONFIG_X86
47 : #ifdef CONFIG_SSE2
- 48 252 : if (raid_cpu_has_sse2()) {
- 49 252 : raid_gen_ptr[0] = raid_gen1_sse2;
+ 48 260 : if (raid_cpu_has_sse2()) {
+ 49 260 : raid_gen_ptr[0] = raid_gen1_sse2;
50 : #ifdef CONFIG_X86_64
51 : if (raid_cpu_has_slowextendedreg()) {
52 : raid_gen_ptr[1] = raid_gen2_sse2;
@@ -118,414 +118,421 @@
56 : /* note that raid_cpu_has_slowextendedreg() doesn't affect parz */
57 : raid_genz_ptr = raid_genz_sse2ext;
58 : #else
- 59 252 : raid_gen_ptr[1] = raid_gen2_sse2;
- 60 252 : raid_genz_ptr = raid_genz_sse2;
+ 59 260 : raid_gen_ptr[1] = raid_gen2_sse2;
+ 60 260 : raid_genz_ptr = raid_genz_sse2;
61 : #endif
62 : }
63 : #endif
64 :
65 : #ifdef CONFIG_SSSE3
- 66 252 : if (raid_cpu_has_ssse3()) {
+ 66 260 : if (raid_cpu_has_ssse3()) {
67 : #ifdef CONFIG_X86_64
- 68 : raid_gen3_ptr = raid_gen3_ssse3ext;
- 69 : raid_gen_ptr[3] = raid_gen4_ssse3ext;
- 70 : raid_gen_ptr[4] = raid_gen5_ssse3ext;
- 71 : raid_gen_ptr[5] = raid_gen6_ssse3ext;
- 72 : #else
- 73 251 : raid_gen3_ptr = raid_gen3_ssse3;
- 74 251 : raid_gen_ptr[3] = raid_gen4_ssse3;
- 75 251 : raid_gen_ptr[4] = raid_gen5_ssse3;
- 76 251 : raid_gen_ptr[5] = raid_gen6_ssse3;
- 77 : #endif
- 78 251 : raid_rec_ptr[0] = raid_rec1_ssse3;
- 79 251 : raid_rec_ptr[1] = raid_rec2_ssse3;
- 80 251 : raid_rec_ptr[2] = raid_recX_ssse3;
- 81 251 : raid_rec_ptr[3] = raid_recX_ssse3;
- 82 251 : raid_rec_ptr[4] = raid_recX_ssse3;
- 83 251 : raid_rec_ptr[5] = raid_recX_ssse3;
- 84 : }
- 85 : #endif
- 86 :
- 87 : #ifdef CONFIG_AVX2
- 88 252 : if (raid_cpu_has_avx2()) {
- 89 2 : raid_gen_ptr[0] = raid_gen1_avx2;
- 90 2 : raid_gen_ptr[1] = raid_gen2_avx2;
- 91 : #ifdef CONFIG_X86_64
- 92 : raid_gen3_ptr = raid_gen3_avx2ext;
- 93 : raid_genz_ptr = raid_genz_avx2ext;
- 94 : raid_gen_ptr[3] = raid_gen4_avx2ext;
- 95 : raid_gen_ptr[4] = raid_gen5_avx2ext;
- 96 : raid_gen_ptr[5] = raid_gen6_avx2ext;
- 97 : #endif
- 98 2 : raid_rec_ptr[0] = raid_rec1_avx2;
- 99 2 : raid_rec_ptr[1] = raid_rec2_avx2;
- 100 2 : raid_rec_ptr[2] = raid_recX_avx2;
- 101 2 : raid_rec_ptr[3] = raid_recX_avx2;
- 102 2 : raid_rec_ptr[4] = raid_recX_avx2;
- 103 2 : raid_rec_ptr[5] = raid_recX_avx2;
- 104 : }
- 105 : #endif
- 106 : #endif /* CONFIG_X86 */
- 107 :
- 108 : /* set the default mode */
- 109 252 : raid_mode(RAID_MODE_CAUCHY);
- 110 252 : }
- 111 :
- 112 : /*
- 113 : * Reference parity computation.
- 114 : */
- 115 6 : void raid_gen_ref(int nd, int np, size_t size, void **vv)
- 116 : {
- 117 6 : uint8_t **v = (uint8_t **)vv;
- 118 : size_t i;
- 119 :
- 120 5382 : for (i = 0; i < size; ++i) {
- 121 : uint8_t p[RAID_PARITY_MAX];
- 122 : int j, d;
- 123 :
- 124 36096 : for (j = 0; j < np; ++j)
- 125 30720 : p[j] = 0;
+ 68 : if (raid_cpu_has_slowextendedreg()) {
+ 69 : raid_gen3_ptr = raid_gen3_ssse3;
+ 70 : raid_gen_ptr[3] = raid_gen4_ssse3;
+ 71 : raid_gen_ptr[4] = raid_gen5_ssse3;
+ 72 : raid_gen_ptr[5] = raid_gen6_ssse3;
+ 73 : } else {
+ 74 : raid_gen3_ptr = raid_gen3_ssse3ext;
+ 75 : raid_gen_ptr[3] = raid_gen4_ssse3ext;
+ 76 : raid_gen_ptr[4] = raid_gen5_ssse3ext;
+ 77 : raid_gen_ptr[5] = raid_gen6_ssse3ext;
+ 78 : }
+ 79 : #else
+ 80 259 : raid_gen3_ptr = raid_gen3_ssse3;
+ 81 259 : raid_gen_ptr[3] = raid_gen4_ssse3;
+ 82 259 : raid_gen_ptr[4] = raid_gen5_ssse3;
+ 83 259 : raid_gen_ptr[5] = raid_gen6_ssse3;
+ 84 : #endif
+ 85 259 : raid_rec_ptr[0] = raid_rec1_ssse3;
+ 86 259 : raid_rec_ptr[1] = raid_rec2_ssse3;
+ 87 259 : raid_rec_ptr[2] = raid_recX_ssse3;
+ 88 259 : raid_rec_ptr[3] = raid_recX_ssse3;
+ 89 259 : raid_rec_ptr[4] = raid_recX_ssse3;
+ 90 259 : raid_rec_ptr[5] = raid_recX_ssse3;
+ 91 : }
+ 92 : #endif
+ 93 :
+ 94 : #ifdef CONFIG_AVX2
+ 95 260 : if (raid_cpu_has_avx2()) {
+ 96 2 : raid_gen_ptr[0] = raid_gen1_avx2;
+ 97 2 : raid_gen_ptr[1] = raid_gen2_avx2;
+ 98 : #ifdef CONFIG_X86_64
+ 99 : raid_gen3_ptr = raid_gen3_avx2ext;
+ 100 : raid_genz_ptr = raid_genz_avx2ext;
+ 101 : raid_gen_ptr[3] = raid_gen4_avx2ext;
+ 102 : raid_gen_ptr[4] = raid_gen5_avx2ext;
+ 103 : raid_gen_ptr[5] = raid_gen6_avx2ext;
+ 104 : #endif
+ 105 2 : raid_rec_ptr[0] = raid_rec1_avx2;
+ 106 2 : raid_rec_ptr[1] = raid_rec2_avx2;
+ 107 2 : raid_rec_ptr[2] = raid_recX_avx2;
+ 108 2 : raid_rec_ptr[3] = raid_recX_avx2;
+ 109 2 : raid_rec_ptr[4] = raid_recX_avx2;
+ 110 2 : raid_rec_ptr[5] = raid_recX_avx2;
+ 111 : }
+ 112 : #endif
+ 113 : #endif /* CONFIG_X86 */
+ 114 :
+ 115 : /* set the default mode */
+ 116 260 : raid_mode(RAID_MODE_CAUCHY);
+ 117 260 : }
+ 118 :
+ 119 : /*
+ 120 : * Reference parity computation.
+ 121 : */
+ 122 6 : void raid_gen_ref(int nd, int np, size_t size, void **vv)
+ 123 : {
+ 124 6 : uint8_t **v = (uint8_t **)vv;
+ 125 : size_t i;
126 :
- 127 93696 : for (d = 0; d < nd; ++d) {
- 128 88320 : uint8_t b = v[d][i];
- 129 :
- 130 584448 : for (j = 0; j < np; ++j)
- 131 496128 : p[j] ^= gfmul[b][gfgen[j][d]];
- 132 : }
+ 127 5382 : for (i = 0; i < size; ++i) {
+ 128 : uint8_t p[RAID_PARITY_MAX];
+ 129 : int j, d;
+ 130 :
+ 131 36096 : for (j = 0; j < np; ++j)
+ 132 30720 : p[j] = 0;
133 :
- 134 36096 : for (j = 0; j < np; ++j)
- 135 30720 : v[nd + j][i] = p[j];
- 136 : }
- 137 6 : }
- 138 :
- 139 : /*
- 140 : * Size of the blocks to test.
- 141 : */
- 142 : #define TEST_SIZE 4096
- 143 :
- 144 : /*
- 145 : * Number of data blocks to test.
- 146 : */
- 147 : #define TEST_COUNT (65536 / TEST_SIZE)
- 148 :
- 149 : /*
- 150 : * Parity generation test.
- 151 : */
- 152 6 : static int raid_test_par(int nd, int np, size_t size, void **v, void **ref)
- 153 : {
- 154 : int i;
- 155 : void *t[TEST_COUNT + RAID_PARITY_MAX];
- 156 :
- 157 : /* setup data */
- 158 102 : for (i = 0; i < nd; ++i)
- 159 96 : t[i] = ref[i];
- 160 :
- 161 : /* setup parity */
- 162 27 : for (i = 0; i < np; ++i)
- 163 21 : t[nd + i] = v[nd + i];
- 164 :
- 165 6 : raid_gen(nd, np, size, t);
- 166 :
- 167 : /* compare parity */
- 168 27 : for (i = 0; i < np; ++i) {
- 169 21 : if (memcmp(t[nd + i], ref[nd + i], size) != 0) {
- 170 : /* LCOV_EXCL_START */
- 171 : return -1;
- 172 : /* LCOV_EXCL_STOP */
- 173 : }
- 174 : }
- 175 :
- 176 6 : return 0;
- 177 : }
- 178 :
- 179 : /*
- 180 : * Recovering test.
- 181 : */
- 182 18 : static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
- 183 : {
- 184 : int i, j;
- 185 : void *t[TEST_COUNT + RAID_PARITY_MAX];
- 186 :
- 187 : /* setup data and parity vector */
- 188 369 : for (i = 0, j = 0; i < nd + np; ++i) {
- 189 351 : if (j < nr && ir[j] == i) {
- 190 : /* this block has to be recovered */
- 191 63 : t[i] = v[i];
- 192 63 : ++j;
- 193 : } else {
- 194 : /* this block is used for recovering */
- 195 288 : t[i] = ref[i];
- 196 : }
- 197 : }
- 198 :
- 199 18 : raid_rec(nr, ir, nd, np, size, t);
- 200 :
- 201 : /* compare all data and parity */
- 202 369 : for (i = 0; i < nd + np; ++i) {
- 203 351 : if (t[i] != ref[i]
- 204 63 : && memcmp(t[i], ref[i], size) != 0) {
- 205 : /* LCOV_EXCL_START */
- 206 : return -1;
- 207 : /* LCOV_EXCL_STOP */
- 208 : }
- 209 : }
- 210 :
- 211 18 : return 0;
- 212 : }
- 213 :
- 214 : /*
- 215 : * Recovering test for data.
- 216 : */
- 217 18 : static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref)
- 218 : {
- 219 : int i, j;
- 220 : void *t[TEST_COUNT + RAID_PARITY_MAX];
- 221 :
- 222 : /* setup data vector */
- 223 306 : for (i = 0, j = 0; i < nd; ++i) {
- 224 288 : if (j < nr && id[j] == i) {
- 225 : /* this block has to be recovered */
- 226 39 : t[i] = v[i];
- 227 39 : ++j;
- 228 : } else {
- 229 : /* this block is left unchanged */
- 230 249 : t[i] = ref[i];
- 231 : }
- 232 : }
- 233 :
- 234 : /* setup parity vector */
- 235 81 : for (i = 0, j = 0; i < np; ++i) {
- 236 63 : if (j < nr && ip[j] == i) {
- 237 : /* this block is used for recovering */
- 238 39 : t[nd + i] = ref[nd + i];
- 239 39 : ++j;
- 240 : } else {
- 241 : /* this block should not be read or written */
- 242 24 : t[nd + i] = 0;
- 243 : }
- 244 : }
- 245 :
- 246 18 : raid_data(nr, id, ip, nd, size, t);
- 247 :
- 248 : /* compare all data and parity */
- 249 306 : for (i = 0; i < nd; ++i) {
- 250 288 : if (t[i] != ref[i]
- 251 39 : && t[i] != 0
- 252 39 : && memcmp(t[i], ref[i], size) != 0) {
- 253 : /* LCOV_EXCL_START */
- 254 : return -1;
- 255 : /* LCOV_EXCL_STOP */
- 256 : }
- 257 : }
- 258 :
- 259 18 : return 0;
- 260 : }
- 261 :
- 262 : /*
- 263 : * Scan test.
- 264 : */
- 265 7 : static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
- 266 : {
- 267 : int i, j, ret;
- 268 : void *t[TEST_COUNT + RAID_PARITY_MAX];
- 269 : int is[RAID_PARITY_MAX];
- 270 :
- 271 : /* setup data and parity vector */
- 272 140 : for (i = 0, j = 0; i < nd + np; ++i) {
- 273 133 : if (j < nr && ir[j] == i) {
- 274 : /* this block is bad */
- 275 15 : t[i] = v[i];
- 276 15 : ++j;
- 277 : } else {
- 278 : /* this block is used for recovering */
- 279 118 : t[i] = ref[i];
- 280 : }
- 281 : }
- 282 :
- 283 7 : ret = raid_scan(is, nd, np, size, t);
- 284 :
- 285 : /* compare identified bad blocks */
- 286 7 : if (ret != nr)
- 287 1 : return -1;
- 288 21 : for (i = 0; i < nr; ++i) {
- 289 15 : if (ir[i] != is[i]) {
- 290 : /* LCOV_EXCL_START */
- 291 : return -1;
- 292 : /* LCOV_EXCL_STOP */
- 293 : }
- 294 : }
- 295 :
- 296 6 : return 0;
- 297 : }
- 298 :
- 299 : /*
- 300 : * Basic functionality self test.
- 301 : */
- 302 1 : int raid_selftest(void)
- 303 : {
- 304 1 : const int nd = TEST_COUNT;
- 305 1 : const size_t size = TEST_SIZE;
- 306 1 : const int nv = nd + RAID_PARITY_MAX * 2 + 1;
- 307 : void *v_alloc;
- 308 : void **v;
- 309 1 : void *ref[nd + RAID_PARITY_MAX];
- 310 : int ir[RAID_PARITY_MAX];
- 311 : int ip[RAID_PARITY_MAX];
- 312 : int i, np;
- 313 1 : int ret = 0;
- 314 :
- 315 : /* ensure to have enough space for data */
- 316 1 : BUG_ON(nd * size > 65536);
- 317 :
- 318 1 : v = raid_malloc_vector(nd, nv, size, &v_alloc);
- 319 1 : if (!v) {
- 320 : /* LCOV_EXCL_START */
- 321 : return -1;
- 322 : /* LCOV_EXCL_STOP */
- 323 : }
+ 134 93696 : for (d = 0; d < nd; ++d) {
+ 135 88320 : uint8_t b = v[d][i];
+ 136 :
+ 137 584448 : for (j = 0; j < np; ++j)
+ 138 496128 : p[j] ^= gfmul[b][gfgen[j][d]];
+ 139 : }
+ 140 :
+ 141 36096 : for (j = 0; j < np; ++j)
+ 142 30720 : v[nd + j][i] = p[j];
+ 143 : }
+ 144 6 : }
+ 145 :
+ 146 : /*
+ 147 : * Size of the blocks to test.
+ 148 : */
+ 149 : #define TEST_SIZE 4096
+ 150 :
+ 151 : /*
+ 152 : * Number of data blocks to test.
+ 153 : */
+ 154 : #define TEST_COUNT (65536 / TEST_SIZE)
+ 155 :
+ 156 : /*
+ 157 : * Parity generation test.
+ 158 : */
+ 159 6 : static int raid_test_par(int nd, int np, size_t size, void **v, void **ref)
+ 160 : {
+ 161 : int i;
+ 162 : void *t[TEST_COUNT + RAID_PARITY_MAX];
+ 163 :
+ 164 : /* setup data */
+ 165 102 : for (i = 0; i < nd; ++i)
+ 166 96 : t[i] = ref[i];
+ 167 :
+ 168 : /* setup parity */
+ 169 27 : for (i = 0; i < np; ++i)
+ 170 21 : t[nd + i] = v[nd + i];
+ 171 :
+ 172 6 : raid_gen(nd, np, size, t);
+ 173 :
+ 174 : /* compare parity */
+ 175 27 : for (i = 0; i < np; ++i) {
+ 176 21 : if (memcmp(t[nd + i], ref[nd + i], size) != 0) {
+ 177 : /* LCOV_EXCL_START */
+ 178 : return -1;
+ 179 : /* LCOV_EXCL_STOP */
+ 180 : }
+ 181 : }
+ 182 :
+ 183 6 : return 0;
+ 184 : }
+ 185 :
+ 186 : /*
+ 187 : * Recovering test.
+ 188 : */
+ 189 18 : static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
+ 190 : {
+ 191 : int i, j;
+ 192 : void *t[TEST_COUNT + RAID_PARITY_MAX];
+ 193 :
+ 194 : /* setup data and parity vector */
+ 195 369 : for (i = 0, j = 0; i < nd + np; ++i) {
+ 196 351 : if (j < nr && ir[j] == i) {
+ 197 : /* this block has to be recovered */
+ 198 63 : t[i] = v[i];
+ 199 63 : ++j;
+ 200 : } else {
+ 201 : /* this block is used for recovering */
+ 202 288 : t[i] = ref[i];
+ 203 : }
+ 204 : }
+ 205 :
+ 206 18 : raid_rec(nr, ir, nd, np, size, t);
+ 207 :
+ 208 : /* compare all data and parity */
+ 209 369 : for (i = 0; i < nd + np; ++i) {
+ 210 351 : if (t[i] != ref[i]
+ 211 63 : && memcmp(t[i], ref[i], size) != 0) {
+ 212 : /* LCOV_EXCL_START */
+ 213 : return -1;
+ 214 : /* LCOV_EXCL_STOP */
+ 215 : }
+ 216 : }
+ 217 :
+ 218 18 : return 0;
+ 219 : }
+ 220 :
+ 221 : /*
+ 222 : * Recovering test for data.
+ 223 : */
+ 224 18 : static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref)
+ 225 : {
+ 226 : int i, j;
+ 227 : void *t[TEST_COUNT + RAID_PARITY_MAX];
+ 228 :
+ 229 : /* setup data vector */
+ 230 306 : for (i = 0, j = 0; i < nd; ++i) {
+ 231 288 : if (j < nr && id[j] == i) {
+ 232 : /* this block has to be recovered */
+ 233 39 : t[i] = v[i];
+ 234 39 : ++j;
+ 235 : } else {
+ 236 : /* this block is left unchanged */
+ 237 249 : t[i] = ref[i];
+ 238 : }
+ 239 : }
+ 240 :
+ 241 : /* setup parity vector */
+ 242 81 : for (i = 0, j = 0; i < np; ++i) {
+ 243 63 : if (j < nr && ip[j] == i) {
+ 244 : /* this block is used for recovering */
+ 245 39 : t[nd + i] = ref[nd + i];
+ 246 39 : ++j;
+ 247 : } else {
+ 248 : /* this block should not be read or written */
+ 249 24 : t[nd + i] = 0;
+ 250 : }
+ 251 : }
+ 252 :
+ 253 18 : raid_data(nr, id, ip, nd, size, t);
+ 254 :
+ 255 : /* compare all data and parity */
+ 256 306 : for (i = 0; i < nd; ++i) {
+ 257 288 : if (t[i] != ref[i]
+ 258 39 : && t[i] != 0
+ 259 39 : && memcmp(t[i], ref[i], size) != 0) {
+ 260 : /* LCOV_EXCL_START */
+ 261 : return -1;
+ 262 : /* LCOV_EXCL_STOP */
+ 263 : }
+ 264 : }
+ 265 :
+ 266 18 : return 0;
+ 267 : }
+ 268 :
+ 269 : /*
+ 270 : * Scan test.
+ 271 : */
+ 272 7 : static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
+ 273 : {
+ 274 : int i, j, ret;
+ 275 : void *t[TEST_COUNT + RAID_PARITY_MAX];
+ 276 : int is[RAID_PARITY_MAX];
+ 277 :
+ 278 : /* setup data and parity vector */
+ 279 140 : for (i = 0, j = 0; i < nd + np; ++i) {
+ 280 133 : if (j < nr && ir[j] == i) {
+ 281 : /* this block is bad */
+ 282 15 : t[i] = v[i];
+ 283 15 : ++j;
+ 284 : } else {
+ 285 : /* this block is used for recovering */
+ 286 118 : t[i] = ref[i];
+ 287 : }
+ 288 : }
+ 289 :
+ 290 7 : ret = raid_scan(is, nd, np, size, t);
+ 291 :
+ 292 : /* compare identified bad blocks */
+ 293 7 : if (ret != nr)
+ 294 1 : return -1;
+ 295 21 : for (i = 0; i < nr; ++i) {
+ 296 15 : if (ir[i] != is[i]) {
+ 297 : /* LCOV_EXCL_START */
+ 298 : return -1;
+ 299 : /* LCOV_EXCL_STOP */
+ 300 : }
+ 301 : }
+ 302 :
+ 303 6 : return 0;
+ 304 : }
+ 305 :
+ 306 : /*
+ 307 : * Basic functionality self test.
+ 308 : */
+ 309 1 : int raid_selftest(void)
+ 310 : {
+ 311 1 : const int nd = TEST_COUNT;
+ 312 1 : const size_t size = TEST_SIZE;
+ 313 1 : const int nv = nd + RAID_PARITY_MAX * 2 + 1;
+ 314 : void *v_alloc;
+ 315 : void **v;
+ 316 1 : void *ref[nd + RAID_PARITY_MAX];
+ 317 : int ir[RAID_PARITY_MAX];
+ 318 : int ip[RAID_PARITY_MAX];
+ 319 : int i, np;
+ 320 1 : int ret = 0;
+ 321 :
+ 322 : /* ensure to have enough space for data */
+ 323 1 : BUG_ON(nd * size > 65536);
324 :
- 325 1 : memset(v[nv - 1], 0, size);
- 326 1 : raid_zero(v[nv - 1]);
- 327 :
- 328 : /* use the multiplication table as data */
- 329 17 : for (i = 0; i < nd; ++i)
- 330 16 : ref[i] = ((uint8_t *)gfmul) + size * i;
+ 325 1 : v = raid_malloc_vector(nd, nv, size, &v_alloc);
+ 326 1 : if (!v) {
+ 327 : /* LCOV_EXCL_START */
+ 328 : return -1;
+ 329 : /* LCOV_EXCL_STOP */
+ 330 : }
331 :
- 332 : /* setup reference parity */
- 333 7 : for (i = 0; i < RAID_PARITY_MAX; ++i)
- 334 6 : ref[nd + i] = v[nd + RAID_PARITY_MAX + i];
- 335 :
- 336 : /* compute reference parity */
- 337 1 : raid_gen_ref(nd, RAID_PARITY_MAX, size, ref);
+ 332 1 : memset(v[nv - 1], 0, size);
+ 333 1 : raid_zero(v[nv - 1]);
+ 334 :
+ 335 : /* use the multiplication table as data */
+ 336 17 : for (i = 0; i < nd; ++i)
+ 337 16 : ref[i] = ((uint8_t *)gfmul) + size * i;
338 :
- 339 : /* test for each parity level */
- 340 7 : for (np = 1; np <= RAID_PARITY_MAX; ++np) {
- 341 : /* test parity generation */
- 342 6 : ret = raid_test_par(nd, np, size, v, ref);
- 343 6 : if (ret != 0) {
- 344 : /* LCOV_EXCL_START */
- 345 : goto bail;
- 346 : /* LCOV_EXCL_STOP */
- 347 : }
- 348 :
- 349 : /* test recovering with broken ending data disks */
- 350 27 : for (i = 0; i < np; ++i) {
- 351 : /* bad data */
- 352 21 : ir[i] = nd - np + i;
- 353 :
- 354 : /* good parity */
- 355 21 : ip[i] = i;
- 356 : }
- 357 :
- 358 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
- 359 6 : if (ret != 0) {
- 360 : /* LCOV_EXCL_START */
- 361 : goto bail;
- 362 : /* LCOV_EXCL_STOP */
+ 339 : /* setup reference parity */
+ 340 7 : for (i = 0; i < RAID_PARITY_MAX; ++i)
+ 341 6 : ref[nd + i] = v[nd + RAID_PARITY_MAX + i];
+ 342 :
+ 343 : /* compute reference parity */
+ 344 1 : raid_gen_ref(nd, RAID_PARITY_MAX, size, ref);
+ 345 :
+ 346 : /* test for each parity level */
+ 347 7 : for (np = 1; np <= RAID_PARITY_MAX; ++np) {
+ 348 : /* test parity generation */
+ 349 6 : ret = raid_test_par(nd, np, size, v, ref);
+ 350 6 : if (ret != 0) {
+ 351 : /* LCOV_EXCL_START */
+ 352 : goto bail;
+ 353 : /* LCOV_EXCL_STOP */
+ 354 : }
+ 355 :
+ 356 : /* test recovering with broken ending data disks */
+ 357 27 : for (i = 0; i < np; ++i) {
+ 358 : /* bad data */
+ 359 21 : ir[i] = nd - np + i;
+ 360 :
+ 361 : /* good parity */
+ 362 21 : ip[i] = i;
363 : }
364 :
- 365 6 : ret = raid_test_data(np, ir, ip, nd, np, size, v, ref);
+ 365 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
366 6 : if (ret != 0) {
367 : /* LCOV_EXCL_START */
368 : goto bail;
369 : /* LCOV_EXCL_STOP */
370 : }
371 :
- 372 : /* test recovering with broken leading data and broken leading parity */
- 373 15 : for (i = 0; i < np / 2; ++i) {
- 374 : /* bad data */
- 375 9 : ir[i] = i;
- 376 :
- 377 : /* good parity */
- 378 9 : ip[i] = (np + 1) / 2 + i;
- 379 : }
- 380 :
- 381 : /* bad parity */
- 382 18 : for (i = 0; i < (np + 1) / 2; ++i)
- 383 12 : ir[np / 2 + i] = nd + i;
- 384 :
- 385 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
- 386 6 : if (ret != 0) {
- 387 : /* LCOV_EXCL_START */
- 388 : goto bail;
- 389 : /* LCOV_EXCL_STOP */
- 390 : }
+ 372 6 : ret = raid_test_data(np, ir, ip, nd, np, size, v, ref);
+ 373 6 : if (ret != 0) {
+ 374 : /* LCOV_EXCL_START */
+ 375 : goto bail;
+ 376 : /* LCOV_EXCL_STOP */
+ 377 : }
+ 378 :
+ 379 : /* test recovering with broken leading data and broken leading parity */
+ 380 15 : for (i = 0; i < np / 2; ++i) {
+ 381 : /* bad data */
+ 382 9 : ir[i] = i;
+ 383 :
+ 384 : /* good parity */
+ 385 9 : ip[i] = (np + 1) / 2 + i;
+ 386 : }
+ 387 :
+ 388 : /* bad parity */
+ 389 18 : for (i = 0; i < (np + 1) / 2; ++i)
+ 390 12 : ir[np / 2 + i] = nd + i;
391 :
- 392 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
+ 392 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
393 6 : if (ret != 0) {
394 : /* LCOV_EXCL_START */
395 : goto bail;
396 : /* LCOV_EXCL_STOP */
397 : }
398 :
- 399 : /* test recovering with broken leading data and broken ending parity */
- 400 15 : for (i = 0; i < np / 2; ++i) {
- 401 : /* bad data */
- 402 9 : ir[i] = i;
- 403 :
- 404 : /* good parity */
- 405 9 : ip[i] = i;
- 406 : }
- 407 :
- 408 : /* bad parity */
- 409 18 : for (i = 0; i < (np + 1) / 2; ++i)
- 410 12 : ir[np / 2 + i] = nd + np - (np + 1) / 2 + i;
- 411 :
- 412 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
- 413 6 : if (ret != 0) {
- 414 : /* LCOV_EXCL_START */
- 415 : goto bail;
- 416 : /* LCOV_EXCL_STOP */
- 417 : }
+ 399 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
+ 400 6 : if (ret != 0) {
+ 401 : /* LCOV_EXCL_START */
+ 402 : goto bail;
+ 403 : /* LCOV_EXCL_STOP */
+ 404 : }
+ 405 :
+ 406 : /* test recovering with broken leading data and broken ending parity */
+ 407 15 : for (i = 0; i < np / 2; ++i) {
+ 408 : /* bad data */
+ 409 9 : ir[i] = i;
+ 410 :
+ 411 : /* good parity */
+ 412 9 : ip[i] = i;
+ 413 : }
+ 414 :
+ 415 : /* bad parity */
+ 416 18 : for (i = 0; i < (np + 1) / 2; ++i)
+ 417 12 : ir[np / 2 + i] = nd + np - (np + 1) / 2 + i;
418 :
- 419 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
+ 419 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref);
420 6 : if (ret != 0) {
421 : /* LCOV_EXCL_START */
422 : goto bail;
423 : /* LCOV_EXCL_STOP */
424 : }
425 :
- 426 : /* scan test with broken data and parity */
- 427 15 : for (i = 0; i < np / 2; ++i) {
- 428 : /* bad data */
- 429 9 : ir[i] = i;
- 430 : }
- 431 12 : for (i = 0; i < (np - 1) / 2; ++i) {
- 432 : /* bad parity */
- 433 6 : ir[np / 2 + i] = nd + i;
- 434 : }
- 435 21 : for (i = 0; i < np - 1; ++i) {
- 436 : /* make blocks bad */
- 437 : /* we cannot fill them with 0, because the original */
- 438 : /* data may be already filled with 0 */
- 439 15 : memset(v[ir[i]], 0x55, size);
- 440 : }
- 441 :
- 442 6 : ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref);
- 443 6 : if (ret != 0) {
- 444 : /* LCOV_EXCL_START */
- 445 : goto bail;
- 446 : /* LCOV_EXCL_STOP */
+ 426 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref);
+ 427 6 : if (ret != 0) {
+ 428 : /* LCOV_EXCL_START */
+ 429 : goto bail;
+ 430 : /* LCOV_EXCL_STOP */
+ 431 : }
+ 432 :
+ 433 : /* scan test with broken data and parity */
+ 434 15 : for (i = 0; i < np / 2; ++i) {
+ 435 : /* bad data */
+ 436 9 : ir[i] = i;
+ 437 : }
+ 438 12 : for (i = 0; i < (np - 1) / 2; ++i) {
+ 439 : /* bad parity */
+ 440 6 : ir[np / 2 + i] = nd + i;
+ 441 : }
+ 442 21 : for (i = 0; i < np - 1; ++i) {
+ 443 : /* make blocks bad */
+ 444 : /* we cannot fill them with 0, because the original */
+ 445 : /* data may be already filled with 0 */
+ 446 15 : memset(v[ir[i]], 0x55, size);
447 : }
- 448 : }
- 449 :
- 450 : /* scan test with no parity */
- 451 1 : ret = raid_test_scan(0, 0, nd, 0, size, v, ref);
- 452 1 : if (ret != -1) {
- 453 : /* LCOV_EXCL_START */
- 454 : goto bail;
- 455 : /* LCOV_EXCL_STOP */
- 456 : }
- 457 :
- 458 1 : ret = 0;
- 459 :
- 460 : bail:
- 461 1 : free(v);
- 462 1 : free(v_alloc);
- 463 :
- 464 1 : return ret;
- 465 : }
+ 448 :
+ 449 6 : ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref);
+ 450 6 : if (ret != 0) {
+ 451 : /* LCOV_EXCL_START */
+ 452 : goto bail;
+ 453 : /* LCOV_EXCL_STOP */
+ 454 : }
+ 455 : }
+ 456 :
+ 457 : /* scan test with no parity */
+ 458 1 : ret = raid_test_scan(0, 0, nd, 0, size, v, ref);
+ 459 1 : if (ret != -1) {
+ 460 : /* LCOV_EXCL_START */
+ 461 : goto bail;
+ 462 : /* LCOV_EXCL_STOP */
+ 463 : }
+ 464 :
+ 465 1 : ret = 0;
466 :
+ 467 : bail:
+ 468 1 : free(v);
+ 469 1 : free(v_alloc);
+ 470 :
+ 471 1 : return ret;
+ 472 : }
+ 473 :
diff --git a/cov/raid/raid.c.func-sort-c.html b/cov/raid/raid.c.func-sort-c.html
index 77b192da..aa6d9f7a 100644
--- a/cov/raid/raid.c.func-sort-c.html
+++ b/cov/raid/raid.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,35 +61,35 @@
| raid_gen |
- 1212946 |
+ 1208170 |
| raid_data |
- 217853 |
+ 211361 |
| raid_invert |
- 172667 |
+ 172152 |
| raid_delta_gen |
- 171311 |
+ 170824 |
| raid_rec1of1 |
- 104953 |
+ 98917 |
| raid_rec |
- 900 |
+ 869 |
| raid_mode |
- 503 |
+ 519 |
| raid_zero |
- 193 |
+ 201 |
| raid_rec2of2_int8 |
diff --git a/cov/raid/raid.c.func.html b/cov/raid/raid.c.func.html
index 88ff8f70..6978ce2b 100644
--- a/cov/raid/raid.c.func.html
+++ b/cov/raid/raid.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,31 +61,31 @@
| raid_data |
- 217853 |
+ 211361 |
| raid_delta_gen |
- 171311 |
+ 170824 |
| raid_gen |
- 1212946 |
+ 1208170 |
| raid_invert |
- 172667 |
+ 172152 |
| raid_mode |
- 503 |
+ 519 |
| raid_rec |
- 900 |
+ 869 |
| raid_rec1of1 |
- 104953 |
+ 98917 |
| raid_rec2of2_int8 |
@@ -93,7 +93,7 @@
| raid_zero |
- 193 |
+ 201 |
diff --git a/cov/raid/raid.c.gcov.html b/cov/raid/raid.c.gcov.html
index 54d53596..ce8ab3b6 100644
--- a/cov/raid/raid.c.gcov.html
+++ b/cov/raid/raid.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -235,26 +235,26 @@
173 : */
174 : const uint8_t (*raid_gfgen)[256];
175 :
- 176 503 : void raid_mode(int mode)
+ 176 519 : void raid_mode(int mode)
177 : {
- 178 503 : if (mode == RAID_MODE_VANDERMONDE) {
+ 178 519 : if (mode == RAID_MODE_VANDERMONDE) {
179 2 : raid_gen_ptr[2] = raid_genz_ptr;
180 2 : raid_gfgen = gfvandermonde;
181 : } else {
- 182 501 : raid_gen_ptr[2] = raid_gen3_ptr;
- 183 501 : raid_gfgen = gfcauchy;
+ 182 517 : raid_gen_ptr[2] = raid_gen3_ptr;
+ 183 517 : raid_gfgen = gfcauchy;
184 : }
- 185 503 : }
+ 185 519 : }
186 :
187 : /**
188 : * Buffer filled with 0 used in recovering.
189 : */
190 : static void *raid_zero_block;
191 :
- 192 193 : void raid_zero(void *zero)
+ 192 201 : void raid_zero(void *zero)
193 : {
- 194 193 : raid_zero_block = zero;
- 195 193 : }
+ 194 201 : raid_zero_block = zero;
+ 195 201 : }
196 :
197 : /*
198 : * Forwarders for parity computation.
@@ -282,17 +282,17 @@
220 : void (*raid_gen3_ptr)(int nd, size_t size, void **vv);
221 : void (*raid_genz_ptr)(int nd, size_t size, void **vv);
222 :
- 223 1212946 : void raid_gen(int nd, int np, size_t size, void **v)
+ 223 1208170 : void raid_gen(int nd, int np, size_t size, void **v)
224 : {
225 : /* enforce limit on size */
- 226 1212946 : BUG_ON(size % 64 != 0);
+ 226 1208170 : BUG_ON(size % 64 != 0);
227 :
228 : /* enforce limit on number of failures */
- 229 1212946 : BUG_ON(np < 1);
- 230 1212946 : BUG_ON(np > RAID_PARITY_MAX);
+ 229 1208170 : BUG_ON(np < 1);
+ 230 1208170 : BUG_ON(np > RAID_PARITY_MAX);
231 :
- 232 1212946 : raid_gen_ptr[np - 1](nd, size, v);
- 233 1212946 : }
+ 232 1208170 : raid_gen_ptr[np - 1](nd, size, v);
+ 233 1208170 : }
234 :
235 : /**
236 : * Inverts the square matrix M of size nxn into V.
@@ -305,44 +305,44 @@
243 : * @V Destination matrix where the result is put.
244 : * @n Number of rows and columns of the matrix.
245 : */
- 246 172667 : void raid_invert(uint8_t *M, uint8_t *V, int n)
+ 246 172152 : void raid_invert(uint8_t *M, uint8_t *V, int n)
247 : {
248 : int i, j, k;
249 :
250 : /* set the identity matrix in V */
- 251 798158 : for (i = 0; i < n; ++i)
- 252 3221590 : for (j = 0; j < n; ++j)
- 253 2596099 : V[i * n + j] = i == j;
+ 251 796315 : for (i = 0; i < n; ++i)
+ 252 3214980 : for (j = 0; j < n; ++j)
+ 253 2590817 : V[i * n + j] = i == j;
254 :
255 : /* for each element in the diagonal */
- 256 798158 : for (k = 0; k < n; ++k) {
+ 256 796315 : for (k = 0; k < n; ++k) {
257 : uint8_t f;
258 :
259 : /* the diagonal element cannot be 0 because */
260 : /* we are inverting matrices with all the square */
261 : /* submatrices not singular */
- 262 625491 : BUG_ON(M[k * n + k] == 0);
+ 262 624163 : BUG_ON(M[k * n + k] == 0);
263 :
264 : /* make the diagonal element to be 1 */
- 265 1250982 : f = inv(M[k * n + k]);
- 266 3221590 : for (j = 0; j < n; ++j) {
- 267 5192198 : M[k * n + j] = mul(f, M[k * n + j]);
- 268 5192198 : V[k * n + j] = mul(f, V[k * n + j]);
+ 265 1248326 : f = inv(M[k * n + k]);
+ 266 3214980 : for (j = 0; j < n; ++j) {
+ 267 5181634 : M[k * n + j] = mul(f, M[k * n + j]);
+ 268 5181634 : V[k * n + j] = mul(f, V[k * n + j]);
269 : }
270 :
271 : /* make all the elements over and under the diagonal */
272 : /* to be zero */
- 273 3221590 : for (i = 0; i < n; ++i) {
- 274 2596099 : if (i == k)
- 275 625491 : continue;
- 276 1970608 : f = M[i * n + k];
- 277 11281182 : for (j = 0; j < n; ++j) {
- 278 18621148 : M[i * n + j] ^= mul(f, M[k * n + j]);
- 279 18621148 : V[i * n + j] ^= mul(f, V[k * n + j]);
+ 273 3214980 : for (i = 0; i < n; ++i) {
+ 274 2590817 : if (i == k)
+ 275 624163 : continue;
+ 276 1966654 : f = M[i * n + k];
+ 277 11254146 : for (j = 0; j < n; ++j) {
+ 278 18574984 : M[i * n + j] ^= mul(f, M[k * n + j]);
+ 279 18574984 : V[i * n + j] ^= mul(f, V[k * n + j]);
280 : }
281 : }
282 : }
- 283 172667 : }
+ 283 172152 : }
284 :
285 : /**
286 : * Computes the parity without the missing data blocks
@@ -350,7 +350,7 @@
288 : *
289 : * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua in the equations.
290 : */
- 291 171311 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v)
+ 291 170824 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v)
292 : {
293 : void *p[RAID_PARITY_MAX];
294 : void *pa[RAID_PARITY_MAX];
@@ -360,17 +360,17 @@
298 :
299 : /* total number of parities we are going to process */
300 : /* they are both the used and the unused ones */
- 301 171311 : np = ip[nr - 1] + 1;
+ 301 170824 : np = ip[nr - 1] + 1;
302 :
303 : /* latest missing data block */
- 304 171311 : latest = v[id[nr - 1]];
+ 304 170824 : latest = v[id[nr - 1]];
305 :
306 : /* setup pointers for delta computation */
- 307 872577 : for (i = 0, j = 0; i < np; ++i) {
+ 307 870818 : for (i = 0, j = 0; i < np; ++i) {
308 : /* keep a copy of the original parity vector */
- 309 701266 : p[i] = v[nd + i];
+ 309 699994 : p[i] = v[nd + i];
310 :
- 311 701266 : if (ip[j] == i) {
+ 311 699994 : if (ip[j] == i) {
312 : /*
313 : * Set used parities to point to the missing
314 : * data blocks.
@@ -381,19 +381,19 @@
319 :
320 : /* the latest parity to use ends the for loop and */
321 : /* then it cannot happen to process more of them */
- 322 605461 : BUG_ON(j >= nr);
+ 322 604161 : BUG_ON(j >= nr);
323 :
324 : /* buffer for missing data blocks */
- 325 605461 : pa[j] = v[id[j]];
+ 325 604161 : pa[j] = v[id[j]];
326 :
327 : /* set at zero the missing data blocks */
- 328 605461 : v[id[j]] = raid_zero_block;
+ 328 604161 : v[id[j]] = raid_zero_block;
329 :
330 : /* compute the parity over the missing data blocks */
- 331 605461 : v[nd + i] = pa[j];
+ 331 604161 : v[nd + i] = pa[j];
332 :
333 : /* check for the next used entry */
- 334 605461 : ++j;
+ 334 604161 : ++j;
335 : } else {
336 : /*
337 : * Unused parities are going to be rewritten with
@@ -413,25 +413,25 @@
351 : * multiple times and only the latest write will
352 : * contain the correct data.
353 : */
- 354 95805 : v[nd + i] = latest;
+ 354 95833 : v[nd + i] = latest;
355 : }
356 : }
357 :
358 : /* all the parities have to be processed */
- 359 171311 : BUG_ON(j != nr);
+ 359 170824 : BUG_ON(j != nr);
360 :
361 : /* recompute the parity, note that np may be smaller than the */
362 : /* total number of parities available */
- 363 171311 : raid_gen(nd, np, size, v);
+ 363 170824 : raid_gen(nd, np, size, v);
364 :
365 : /* restore data buffers as before */
- 366 776772 : for (j = 0; j < nr; ++j)
- 367 605461 : v[id[j]] = pa[j];
+ 366 774985 : for (j = 0; j < nr; ++j)
+ 367 604161 : v[id[j]] = pa[j];
368 :
369 : /* restore parity buffers as before */
- 370 872577 : for (i = 0; i < np; ++i)
- 371 701266 : v[nd + i] = p[i];
- 372 171311 : }
+ 370 870818 : for (i = 0; i < np; ++i)
+ 371 699994 : v[nd + i] = p[i];
+ 372 170824 : }
373 :
374 : /**
375 : * Recover failure of one data block for PAR1.
@@ -444,29 +444,29 @@
382 : *
383 : * Dx = Pd
384 : */
- 385 104953 : void raid_rec1of1(int *id, int nd, size_t size, void **v)
+ 385 98917 : void raid_rec1of1(int *id, int nd, size_t size, void **v)
386 : {
387 : void *p;
388 : void *pa;
389 :
390 : /* for PAR1 we can directly compute the missing block */
391 : /* and we don't need to use the zero buffer */
- 392 104953 : p = v[nd];
- 393 104953 : pa = v[id[0]];
+ 392 98917 : p = v[nd];
+ 393 98917 : pa = v[id[0]];
394 :
395 : /* use the parity as missing data block */
- 396 104953 : v[id[0]] = p;
+ 396 98917 : v[id[0]] = p;
397 :
398 : /* compute the parity over the missing data block */
- 399 104953 : v[nd] = pa;
+ 399 98917 : v[nd] = pa;
400 :
401 : /* compute */
- 402 104953 : raid_gen(nd, 1, size, v);
+ 402 98917 : raid_gen(nd, 1, size, v);
403 :
404 : /* restore as before */
- 405 104953 : v[id[0]] = pa;
- 406 104953 : v[nd] = p;
- 407 104953 : }
+ 405 98917 : v[id[0]] = pa;
+ 406 98917 : v[nd] = p;
+ 407 98917 : }
408 :
409 : /**
410 : * Recover failure of two data blocks for PAR2.
@@ -554,97 +554,97 @@
492 : void (*raid_rec_ptr[RAID_PARITY_MAX])(
493 : int nr, int *id, int *ip, int nd, size_t size, void **vv);
494 :
- 495 900 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v)
+ 495 869 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v)
496 : {
497 : int nrd; /* number of data blocks to recover */
498 : int nrp; /* number of parity blocks to recover */
499 :
500 : /* enforce limit on size */
- 501 900 : BUG_ON(size % 64 != 0);
+ 501 869 : BUG_ON(size % 64 != 0);
502 :
503 : /* enforce limit on number of failures */
- 504 900 : BUG_ON(nr > np);
- 505 900 : BUG_ON(np > RAID_PARITY_MAX);
+ 504 869 : BUG_ON(nr > np);
+ 505 869 : BUG_ON(np > RAID_PARITY_MAX);
506 :
507 : /* enforce order in index vector */
- 508 900 : BUG_ON(nr >= 2 && ir[0] >= ir[1]);
- 509 900 : BUG_ON(nr >= 3 && ir[1] >= ir[2]);
- 510 900 : BUG_ON(nr >= 4 && ir[2] >= ir[3]);
- 511 900 : BUG_ON(nr >= 5 && ir[3] >= ir[4]);
- 512 900 : BUG_ON(nr >= 6 && ir[4] >= ir[5]);
+ 508 869 : BUG_ON(nr >= 2 && ir[0] >= ir[1]);
+ 509 869 : BUG_ON(nr >= 3 && ir[1] >= ir[2]);
+ 510 869 : BUG_ON(nr >= 4 && ir[2] >= ir[3]);
+ 511 869 : BUG_ON(nr >= 5 && ir[3] >= ir[4]);
+ 512 869 : BUG_ON(nr >= 6 && ir[4] >= ir[5]);
513 :
514 : /* enforce limit on index vector */
- 515 900 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np);
+ 515 869 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np);
516 :
517 : /* count the number of data blocks to recover */
- 518 900 : nrd = 0;
- 519 3603 : while (nrd < nr && ir[nrd] < nd)
- 520 1803 : ++nrd;
+ 518 869 : nrd = 0;
+ 519 3479 : while (nrd < nr && ir[nrd] < nd)
+ 520 1741 : ++nrd;
521 :
522 : /* all the remaining are parity */
- 523 900 : nrp = nr - nrd;
+ 523 869 : nrp = nr - nrd;
524 :
525 : /* enforce limit on number of failures */
- 526 900 : BUG_ON(nrd > nd);
- 527 900 : BUG_ON(nrp > np);
+ 526 869 : BUG_ON(nrd > nd);
+ 527 869 : BUG_ON(nrp > np);
528 :
529 : /* if failed data is present */
- 530 900 : if (nrd != 0) {
+ 530 869 : if (nrd != 0) {
531 : int ip[RAID_PARITY_MAX];
532 : int i, j, k;
533 :
534 : /* setup the vector of parities to use */
- 535 6251 : for (i = 0, j = 0, k = 0; i < np; ++i) {
- 536 5353 : if (j < nrp && ir[nrd + j] == nd + i) {
+ 535 6034 : for (i = 0, j = 0, k = 0; i < np; ++i) {
+ 536 5167 : if (j < nrp && ir[nrd + j] == nd + i) {
537 : /* this parity has to be recovered */
538 22 : ++j;
539 : } else {
540 : /* this parity is used for recovering */
- 541 5331 : ip[k] = i;
- 542 5331 : ++k;
+ 541 5145 : ip[k] = i;
+ 542 5145 : ++k;
543 : }
544 : }
545 :
546 : /* recover the nrd data blocks specified in ir[], */
547 : /* using the first nrd parity in ip[] for recovering */
- 548 898 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v);
+ 548 867 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v);
549 : }
550 :
551 : /* recompute all the parities up to the last bad one */
- 552 900 : if (nrp != 0)
+ 552 869 : if (nrp != 0)
553 12 : raid_gen(nd, ir[nr - 1] - nd + 1, size, v);
- 554 900 : }
+ 554 869 : }
555 :
- 556 217853 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
+ 556 211361 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
557 : {
558 : /* enforce limit on size */
- 559 217853 : BUG_ON(size % 64 != 0);
+ 559 211361 : BUG_ON(size % 64 != 0);
560 :
561 : /* enforce limit on number of failures */
- 562 217853 : BUG_ON(nr > nd);
- 563 217853 : BUG_ON(nr > RAID_PARITY_MAX);
+ 562 211361 : BUG_ON(nr > nd);
+ 563 211361 : BUG_ON(nr > RAID_PARITY_MAX);
564 :
565 : /* enforce order in index vector for data */
- 566 217853 : BUG_ON(nr >= 2 && id[0] >= id[1]);
- 567 217853 : BUG_ON(nr >= 3 && id[1] >= id[2]);
- 568 217853 : BUG_ON(nr >= 4 && id[2] >= id[3]);
- 569 217853 : BUG_ON(nr >= 5 && id[3] >= id[4]);
- 570 217853 : BUG_ON(nr >= 6 && id[4] >= id[5]);
+ 566 211361 : BUG_ON(nr >= 2 && id[0] >= id[1]);
+ 567 211361 : BUG_ON(nr >= 3 && id[1] >= id[2]);
+ 568 211361 : BUG_ON(nr >= 4 && id[2] >= id[3]);
+ 569 211361 : BUG_ON(nr >= 5 && id[3] >= id[4]);
+ 570 211361 : BUG_ON(nr >= 6 && id[4] >= id[5]);
571 :
572 : /* enforce limit on index vector for data */
- 573 217853 : BUG_ON(nr > 0 && id[nr-1] >= nd);
+ 573 211361 : BUG_ON(nr > 0 && id[nr-1] >= nd);
574 :
575 : /* enforce order in index vector for parity */
- 576 217853 : BUG_ON(nr >= 2 && ip[0] >= ip[1]);
- 577 217853 : BUG_ON(nr >= 3 && ip[1] >= ip[2]);
- 578 217853 : BUG_ON(nr >= 4 && ip[2] >= ip[3]);
- 579 217853 : BUG_ON(nr >= 5 && ip[3] >= ip[4]);
- 580 217853 : BUG_ON(nr >= 6 && ip[4] >= ip[5]);
+ 576 211361 : BUG_ON(nr >= 2 && ip[0] >= ip[1]);
+ 577 211361 : BUG_ON(nr >= 3 && ip[1] >= ip[2]);
+ 578 211361 : BUG_ON(nr >= 4 && ip[2] >= ip[3]);
+ 579 211361 : BUG_ON(nr >= 5 && ip[3] >= ip[4]);
+ 580 211361 : BUG_ON(nr >= 6 && ip[4] >= ip[5]);
581 :
582 : /* if failed data is present */
- 583 217853 : if (nr != 0)
- 584 217851 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
- 585 217853 : }
+ 583 211361 : if (nr != 0)
+ 584 211359 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
+ 585 211361 : }
586 :
diff --git a/cov/raid/tag.c.func-sort-c.html b/cov/raid/tag.c.func-sort-c.html
index 31c0d253..3fd08c9b 100644
--- a/cov/raid/tag.c.func-sort-c.html
+++ b/cov/raid/tag.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/tag.c.func.html b/cov/raid/tag.c.func.html
index 14aa49dc..3d1d2299 100644
--- a/cov/raid/tag.c.func.html
+++ b/cov/raid/tag.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/tag.c.gcov.html b/cov/raid/tag.c.gcov.html
index 942fdb77..57254a98 100644
--- a/cov/raid/tag.c.gcov.html
+++ b/cov/raid/tag.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/test.c.func-sort-c.html b/cov/raid/test.c.func-sort-c.html
index 98effa0b..3e30deb8 100644
--- a/cov/raid/test.c.func-sort-c.html
+++ b/cov/raid/test.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/test.c.func.html b/cov/raid/test.c.func.html
index 7a09c565..3fcc40a8 100644
--- a/cov/raid/test.c.func.html
+++ b/cov/raid/test.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/test.c.gcov.html b/cov/raid/test.c.gcov.html
index 6104fd17..46a5ea0a 100644
--- a/cov/raid/test.c.gcov.html
+++ b/cov/raid/test.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/x86.c.func-sort-c.html b/cov/raid/x86.c.func-sort-c.html
index 5c4222d3..576bb3bc 100644
--- a/cov/raid/x86.c.func-sort-c.html
+++ b/cov/raid/x86.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,39 +61,39 @@
| raid_gen6_ssse3 |
- 549666 |
+ 559030 |
| raid_gen2_sse2 |
- 276492 |
+ 267701 |
| raid_gen1_sse2 |
- 273337 |
+ 267673 |
| raid_rec1_ssse3 |
- 114430 |
+ 108422 |
| raid_recX_ssse3 |
- 79298 |
+ 79451 |
| raid_gen5_ssse3 |
- 50258 |
+ 50169 |
| raid_rec2_ssse3 |
- 44206 |
+ 43538 |
| raid_gen4_ssse3 |
- 32613 |
+ 32723 |
| raid_gen3_ssse3 |
- 29451 |
+ 29756 |
| raid_recX_avx2 |
diff --git a/cov/raid/x86.c.func.html b/cov/raid/x86.c.func.html
index adc9e8a9..ee9d7e4c 100644
--- a/cov/raid/x86.c.func.html
+++ b/cov/raid/x86.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,7 +65,7 @@
| raid_gen1_sse2 |
- 273337 |
+ 267673 |
| raid_gen2_avx2 |
@@ -73,23 +73,23 @@
| raid_gen2_sse2 |
- 276492 |
+ 267701 |
| raid_gen3_ssse3 |
- 29451 |
+ 29756 |
| raid_gen4_ssse3 |
- 32613 |
+ 32723 |
| raid_gen5_ssse3 |
- 50258 |
+ 50169 |
| raid_gen6_ssse3 |
- 549666 |
+ 559030 |
| raid_rec1_avx2 |
@@ -97,7 +97,7 @@
| raid_rec1_ssse3 |
- 114430 |
+ 108422 |
| raid_rec2_avx2 |
@@ -105,7 +105,7 @@
| raid_rec2_ssse3 |
- 44206 |
+ 43538 |
| raid_recX_avx2 |
@@ -113,7 +113,7 @@
| raid_recX_ssse3 |
- 79298 |
+ 79451 |
diff --git a/cov/raid/x86.c.gcov.html b/cov/raid/x86.c.gcov.html
index 8835cf3b..da2e429e 100644
--- a/cov/raid/x86.c.gcov.html
+++ b/cov/raid/x86.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -95,37 +95,37 @@
33 : * cache block, and processing 128 bytes doesn't increase performance, and in
34 : * some cases it even decreases it.
35 : */
- 36 273337 : void raid_gen1_sse2(int nd, size_t size, void **vv)
+ 36 267673 : void raid_gen1_sse2(int nd, size_t size, void **vv)
37 : {
- 38 273337 : uint8_t **v = (uint8_t **)vv;
+ 38 267673 : uint8_t **v = (uint8_t **)vv;
39 : uint8_t *p;
40 : int d, l;
41 : size_t i;
42 :
- 43 273337 : l = nd - 1;
- 44 273337 : p = v[nd];
+ 43 267673 : l = nd - 1;
+ 44 267673 : p = v[nd];
45 :
46 : raid_sse_begin();
47 :
- 48 5895173 : for (i = 0; i < size; i += 64) {
- 49 5621836 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 50 5621836 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
- 51 5621836 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32]));
- 52 5621836 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48]));
- 53 36237956 : for (d = l - 1; d >= 0; --d) {
- 54 30616120 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i]));
- 55 30616120 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16]));
- 56 30616120 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32]));
- 57 30616120 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48]));
+ 48 5827445 : for (i = 0; i < size; i += 64) {
+ 49 5559772 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 50 5559772 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
+ 51 5559772 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32]));
+ 52 5559772 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48]));
+ 53 35922916 : for (d = l - 1; d >= 0; --d) {
+ 54 30363144 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i]));
+ 55 30363144 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16]));
+ 56 30363144 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32]));
+ 57 30363144 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48]));
58 : }
- 59 5621836 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 60 5621836 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
- 61 5621836 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32]));
- 62 5621836 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48]));
+ 59 5559772 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 60 5559772 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
+ 61 5559772 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32]));
+ 62 5559772 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48]));
63 : }
64 :
65 : raid_sse_end();
- 66 273337 : }
+ 66 267673 : }
67 : #endif
68 :
69 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2)
@@ -183,54 +183,54 @@
121 : /*
122 : * GEN2 (RAID6 with powers of 2) SSE2 implementation
123 : */
- 124 276492 : void raid_gen2_sse2(int nd, size_t size, void **vv)
+ 124 267701 : void raid_gen2_sse2(int nd, size_t size, void **vv)
125 : {
- 126 276492 : uint8_t **v = (uint8_t **)vv;
+ 126 267701 : uint8_t **v = (uint8_t **)vv;
127 : uint8_t *p;
128 : uint8_t *q;
129 : int d, l;
130 : size_t i;
131 :
- 132 276492 : l = nd - 1;
- 133 276492 : p = v[nd];
- 134 276492 : q = v[nd + 1];
+ 132 267701 : l = nd - 1;
+ 133 267701 : p = v[nd];
+ 134 267701 : q = v[nd + 1];
135 :
136 : raid_sse_begin();
137 :
- 138 276492 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 138 267701 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
139 :
- 140 11074404 : for (i = 0; i < size; i += 32) {
- 141 10797912 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 142 10797912 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
- 143 10797912 : asm volatile ("movdqa %xmm0,%xmm2");
- 144 10797912 : asm volatile ("movdqa %xmm1,%xmm3");
- 145 68703624 : for (d = l - 1; d >= 0; --d) {
- 146 57905712 : asm volatile ("pxor %xmm4,%xmm4");
- 147 57905712 : asm volatile ("pxor %xmm5,%xmm5");
- 148 57905712 : asm volatile ("pcmpgtb %xmm2,%xmm4");
- 149 57905712 : asm volatile ("pcmpgtb %xmm3,%xmm5");
- 150 57905712 : asm volatile ("paddb %xmm2,%xmm2");
- 151 57905712 : asm volatile ("paddb %xmm3,%xmm3");
- 152 57905712 : asm volatile ("pand %xmm7,%xmm4");
- 153 57905712 : asm volatile ("pand %xmm7,%xmm5");
- 154 57905712 : asm volatile ("pxor %xmm4,%xmm2");
- 155 57905712 : asm volatile ("pxor %xmm5,%xmm3");
+ 140 10816941 : for (i = 0; i < size; i += 32) {
+ 141 10549240 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 142 10549240 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
+ 143 10549240 : asm volatile ("movdqa %xmm0,%xmm2");
+ 144 10549240 : asm volatile ("movdqa %xmm1,%xmm3");
+ 145 67277128 : for (d = l - 1; d >= 0; --d) {
+ 146 56727888 : asm volatile ("pxor %xmm4,%xmm4");
+ 147 56727888 : asm volatile ("pxor %xmm5,%xmm5");
+ 148 56727888 : asm volatile ("pcmpgtb %xmm2,%xmm4");
+ 149 56727888 : asm volatile ("pcmpgtb %xmm3,%xmm5");
+ 150 56727888 : asm volatile ("paddb %xmm2,%xmm2");
+ 151 56727888 : asm volatile ("paddb %xmm3,%xmm3");
+ 152 56727888 : asm volatile ("pand %xmm7,%xmm4");
+ 153 56727888 : asm volatile ("pand %xmm7,%xmm5");
+ 154 56727888 : asm volatile ("pxor %xmm4,%xmm2");
+ 155 56727888 : asm volatile ("pxor %xmm5,%xmm3");
156 :
- 157 57905712 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 158 57905712 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16]));
- 159 57905712 : asm volatile ("pxor %xmm4,%xmm0");
- 160 57905712 : asm volatile ("pxor %xmm5,%xmm1");
- 161 57905712 : asm volatile ("pxor %xmm4,%xmm2");
- 162 57905712 : asm volatile ("pxor %xmm5,%xmm3");
+ 157 56727888 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 158 56727888 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16]));
+ 159 56727888 : asm volatile ("pxor %xmm4,%xmm0");
+ 160 56727888 : asm volatile ("pxor %xmm5,%xmm1");
+ 161 56727888 : asm volatile ("pxor %xmm4,%xmm2");
+ 162 56727888 : asm volatile ("pxor %xmm5,%xmm3");
163 : }
- 164 10797912 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 165 10797912 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
- 166 10797912 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i]));
- 167 10797912 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16]));
+ 164 10549240 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 165 10549240 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
+ 166 10549240 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i]));
+ 167 10549240 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16]));
168 : }
169 :
170 : raid_sse_end();
- 171 276492 : }
+ 171 267701 : }
172 : #endif
173 :
174 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2)
@@ -370,93 +370,93 @@
308 : /*
309 : * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation
310 : */
- 311 29451 : void raid_gen3_ssse3(int nd, size_t size, void **vv)
+ 311 29756 : void raid_gen3_ssse3(int nd, size_t size, void **vv)
312 : {
- 313 29451 : uint8_t **v = (uint8_t **)vv;
+ 313 29756 : uint8_t **v = (uint8_t **)vv;
314 : uint8_t *p;
315 : uint8_t *q;
316 : uint8_t *r;
317 : int d, l;
318 : size_t i;
319 :
- 320 29451 : l = nd - 1;
- 321 29451 : p = v[nd];
- 322 29451 : q = v[nd + 1];
- 323 29451 : r = v[nd + 2];
+ 320 29756 : l = nd - 1;
+ 321 29756 : p = v[nd];
+ 322 29756 : q = v[nd + 1];
+ 323 29756 : r = v[nd + 2];
324 :
325 : /* special case with only one data disk */
- 326 29451 : if (l == 0) {
+ 326 29756 : if (l == 0) {
327 4 : for (i = 0; i < 3; ++i)
328 3 : memcpy(v[1 + i], v[0], size);
- 329 29452 : return;
+ 329 29757 : return;
330 : }
331 :
332 : raid_sse_begin();
333 :
334 : /* generic case with at least two data disks */
- 335 29450 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
- 336 29450 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 335 29755 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
+ 336 29755 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
337 :
- 338 4915546 : for (i = 0; i < size; i += 16) {
+ 338 4935371 : for (i = 0; i < size; i += 16) {
339 : /* last disk without the by two multiplication */
- 340 4886096 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 340 4905616 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
341 :
- 342 4886096 : asm volatile ("movdqa %xmm4,%xmm0");
- 343 4886096 : asm volatile ("movdqa %xmm4,%xmm1");
+ 342 4905616 : asm volatile ("movdqa %xmm4,%xmm0");
+ 343 4905616 : asm volatile ("movdqa %xmm4,%xmm1");
344 :
- 345 4886096 : asm volatile ("movdqa %xmm4,%xmm5");
- 346 4886096 : asm volatile ("psrlw $4,%xmm5");
- 347 4886096 : asm volatile ("pand %xmm7,%xmm4");
- 348 4886096 : asm volatile ("pand %xmm7,%xmm5");
+ 345 4905616 : asm volatile ("movdqa %xmm4,%xmm5");
+ 346 4905616 : asm volatile ("psrlw $4,%xmm5");
+ 347 4905616 : asm volatile ("pand %xmm7,%xmm4");
+ 348 4905616 : asm volatile ("pand %xmm7,%xmm5");
349 :
- 350 4886096 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
- 351 4886096 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0]));
- 352 4886096 : asm volatile ("pshufb %xmm4,%xmm2");
- 353 4886096 : asm volatile ("pshufb %xmm5,%xmm6");
- 354 4886096 : asm volatile ("pxor %xmm6,%xmm2");
+ 350 4905616 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
+ 351 4905616 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0]));
+ 352 4905616 : asm volatile ("pshufb %xmm4,%xmm2");
+ 353 4905616 : asm volatile ("pshufb %xmm5,%xmm6");
+ 354 4905616 : asm volatile ("pxor %xmm6,%xmm2");
355 :
356 : /* intermediate disks */
- 357 30688944 : for (d = l - 1; d > 0; --d) {
- 358 25802848 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 357 30786544 : for (d = l - 1; d > 0; --d) {
+ 358 25880928 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
359 :
- 360 25802848 : asm volatile ("pxor %xmm5,%xmm5");
- 361 25802848 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 362 25802848 : asm volatile ("paddb %xmm1,%xmm1");
- 363 25802848 : asm volatile ("pand %xmm3,%xmm5");
- 364 25802848 : asm volatile ("pxor %xmm5,%xmm1");
+ 360 25880928 : asm volatile ("pxor %xmm5,%xmm5");
+ 361 25880928 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 362 25880928 : asm volatile ("paddb %xmm1,%xmm1");
+ 363 25880928 : asm volatile ("pand %xmm3,%xmm5");
+ 364 25880928 : asm volatile ("pxor %xmm5,%xmm1");
365 :
- 366 25802848 : asm volatile ("pxor %xmm4,%xmm0");
- 367 25802848 : asm volatile ("pxor %xmm4,%xmm1");
+ 366 25880928 : asm volatile ("pxor %xmm4,%xmm0");
+ 367 25880928 : asm volatile ("pxor %xmm4,%xmm1");
368 :
- 369 25802848 : asm volatile ("movdqa %xmm4,%xmm5");
- 370 25802848 : asm volatile ("psrlw $4,%xmm5");
- 371 25802848 : asm volatile ("pand %xmm7,%xmm4");
- 372 25802848 : asm volatile ("pand %xmm7,%xmm5");
+ 369 25880928 : asm volatile ("movdqa %xmm4,%xmm5");
+ 370 25880928 : asm volatile ("psrlw $4,%xmm5");
+ 371 25880928 : asm volatile ("pand %xmm7,%xmm4");
+ 372 25880928 : asm volatile ("pand %xmm7,%xmm5");
373 :
- 374 25802848 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 375 25802848 : asm volatile ("pshufb %xmm4,%xmm6");
- 376 25802848 : asm volatile ("pxor %xmm6,%xmm2");
- 377 25802848 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0]));
- 378 25802848 : asm volatile ("pshufb %xmm5,%xmm6");
- 379 25802848 : asm volatile ("pxor %xmm6,%xmm2");
+ 374 25880928 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 375 25880928 : asm volatile ("pshufb %xmm4,%xmm6");
+ 376 25880928 : asm volatile ("pxor %xmm6,%xmm2");
+ 377 25880928 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0]));
+ 378 25880928 : asm volatile ("pshufb %xmm5,%xmm6");
+ 379 25880928 : asm volatile ("pxor %xmm6,%xmm2");
380 : }
381 :
382 : /* first disk with all coefficients at 1 */
- 383 4886096 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 383 4905616 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
384 :
- 385 4886096 : asm volatile ("pxor %xmm5,%xmm5");
- 386 4886096 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 387 4886096 : asm volatile ("paddb %xmm1,%xmm1");
- 388 4886096 : asm volatile ("pand %xmm3,%xmm5");
- 389 4886096 : asm volatile ("pxor %xmm5,%xmm1");
+ 385 4905616 : asm volatile ("pxor %xmm5,%xmm5");
+ 386 4905616 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 387 4905616 : asm volatile ("paddb %xmm1,%xmm1");
+ 388 4905616 : asm volatile ("pand %xmm3,%xmm5");
+ 389 4905616 : asm volatile ("pxor %xmm5,%xmm1");
390 :
- 391 4886096 : asm volatile ("pxor %xmm4,%xmm0");
- 392 4886096 : asm volatile ("pxor %xmm4,%xmm1");
- 393 4886096 : asm volatile ("pxor %xmm4,%xmm2");
+ 391 4905616 : asm volatile ("pxor %xmm4,%xmm0");
+ 392 4905616 : asm volatile ("pxor %xmm4,%xmm1");
+ 393 4905616 : asm volatile ("pxor %xmm4,%xmm2");
394 :
- 395 4886096 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 396 4886096 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
- 397 4886096 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
+ 395 4905616 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 396 4905616 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
+ 397 4905616 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
398 : }
399 :
400 : raid_sse_end();
@@ -741,9 +741,9 @@
679 : /*
680 : * GEN4 (quad parity with Cauchy matrix) SSSE3 implementation
681 : */
- 682 32613 : void raid_gen4_ssse3(int nd, size_t size, void **vv)
+ 682 32723 : void raid_gen4_ssse3(int nd, size_t size, void **vv)
683 : {
- 684 32613 : uint8_t **v = (uint8_t **)vv;
+ 684 32723 : uint8_t **v = (uint8_t **)vv;
685 : uint8_t *p;
686 : uint8_t *q;
687 : uint8_t *r;
@@ -751,102 +751,102 @@
689 : int d, l;
690 : size_t i;
691 :
- 692 32613 : l = nd - 1;
- 693 32613 : p = v[nd];
- 694 32613 : q = v[nd + 1];
- 695 32613 : r = v[nd + 2];
- 696 32613 : s = v[nd + 3];
+ 692 32723 : l = nd - 1;
+ 693 32723 : p = v[nd];
+ 694 32723 : q = v[nd + 1];
+ 695 32723 : r = v[nd + 2];
+ 696 32723 : s = v[nd + 3];
697 :
698 : /* special case with only one data disk */
- 699 32613 : if (l == 0) {
+ 699 32723 : if (l == 0) {
700 5 : for (i = 0; i < 4; ++i)
701 4 : memcpy(v[1 + i], v[0], size);
- 702 32614 : return;
+ 702 32724 : return;
703 : }
704 :
705 : raid_sse_begin();
706 :
707 : /* generic case with at least two data disks */
- 708 3376804 : for (i = 0; i < size; i += 16) {
+ 708 3383954 : for (i = 0; i < size; i += 16) {
709 : /* last disk without the by two multiplication */
- 710 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 711 3344192 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 710 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 711 3351232 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
712 :
- 713 3344192 : asm volatile ("movdqa %xmm4,%xmm0");
- 714 3344192 : asm volatile ("movdqa %xmm4,%xmm1");
+ 713 3351232 : asm volatile ("movdqa %xmm4,%xmm0");
+ 714 3351232 : asm volatile ("movdqa %xmm4,%xmm1");
715 :
- 716 3344192 : asm volatile ("movdqa %xmm4,%xmm5");
- 717 3344192 : asm volatile ("psrlw $4,%xmm5");
- 718 3344192 : asm volatile ("pand %xmm7,%xmm4");
- 719 3344192 : asm volatile ("pand %xmm7,%xmm5");
+ 716 3351232 : asm volatile ("movdqa %xmm4,%xmm5");
+ 717 3351232 : asm volatile ("psrlw $4,%xmm5");
+ 718 3351232 : asm volatile ("pand %xmm7,%xmm4");
+ 719 3351232 : asm volatile ("pand %xmm7,%xmm5");
720 :
- 721 3344192 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
- 722 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
- 723 3344192 : asm volatile ("pshufb %xmm4,%xmm2");
- 724 3344192 : asm volatile ("pshufb %xmm5,%xmm7");
- 725 3344192 : asm volatile ("pxor %xmm7,%xmm2");
+ 721 3351232 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
+ 722 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
+ 723 3351232 : asm volatile ("pshufb %xmm4,%xmm2");
+ 724 3351232 : asm volatile ("pshufb %xmm5,%xmm7");
+ 725 3351232 : asm volatile ("pxor %xmm7,%xmm2");
726 :
- 727 3344192 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0]));
- 728 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
- 729 3344192 : asm volatile ("pshufb %xmm4,%xmm3");
- 730 3344192 : asm volatile ("pshufb %xmm5,%xmm7");
- 731 3344192 : asm volatile ("pxor %xmm7,%xmm3");
+ 727 3351232 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0]));
+ 728 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
+ 729 3351232 : asm volatile ("pshufb %xmm4,%xmm3");
+ 730 3351232 : asm volatile ("pshufb %xmm5,%xmm7");
+ 731 3351232 : asm volatile ("pxor %xmm7,%xmm3");
732 :
733 : /* intermediate disks */
- 734 20046208 : for (d = l - 1; d > 0; --d) {
- 735 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
- 736 16702016 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 734 20081408 : for (d = l - 1; d > 0; --d) {
+ 735 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 736 16730176 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
737 :
- 738 16702016 : asm volatile ("pxor %xmm5,%xmm5");
- 739 16702016 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 740 16702016 : asm volatile ("paddb %xmm1,%xmm1");
- 741 16702016 : asm volatile ("pand %xmm7,%xmm5");
- 742 16702016 : asm volatile ("pxor %xmm5,%xmm1");
+ 738 16730176 : asm volatile ("pxor %xmm5,%xmm5");
+ 739 16730176 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 740 16730176 : asm volatile ("paddb %xmm1,%xmm1");
+ 741 16730176 : asm volatile ("pand %xmm7,%xmm5");
+ 742 16730176 : asm volatile ("pxor %xmm5,%xmm1");
743 :
- 744 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 744 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
745 :
- 746 16702016 : asm volatile ("pxor %xmm4,%xmm0");
- 747 16702016 : asm volatile ("pxor %xmm4,%xmm1");
+ 746 16730176 : asm volatile ("pxor %xmm4,%xmm0");
+ 747 16730176 : asm volatile ("pxor %xmm4,%xmm1");
748 :
- 749 16702016 : asm volatile ("movdqa %xmm4,%xmm5");
- 750 16702016 : asm volatile ("psrlw $4,%xmm5");
- 751 16702016 : asm volatile ("pand %xmm7,%xmm4");
- 752 16702016 : asm volatile ("pand %xmm7,%xmm5");
+ 749 16730176 : asm volatile ("movdqa %xmm4,%xmm5");
+ 750 16730176 : asm volatile ("psrlw $4,%xmm5");
+ 751 16730176 : asm volatile ("pand %xmm7,%xmm4");
+ 752 16730176 : asm volatile ("pand %xmm7,%xmm5");
753 :
- 754 16702016 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 755 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
- 756 16702016 : asm volatile ("pshufb %xmm4,%xmm6");
- 757 16702016 : asm volatile ("pshufb %xmm5,%xmm7");
- 758 16702016 : asm volatile ("pxor %xmm6,%xmm2");
- 759 16702016 : asm volatile ("pxor %xmm7,%xmm2");
+ 754 16730176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 755 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
+ 756 16730176 : asm volatile ("pshufb %xmm4,%xmm6");
+ 757 16730176 : asm volatile ("pshufb %xmm5,%xmm7");
+ 758 16730176 : asm volatile ("pxor %xmm6,%xmm2");
+ 759 16730176 : asm volatile ("pxor %xmm7,%xmm2");
760 :
- 761 16702016 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
- 762 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
- 763 16702016 : asm volatile ("pshufb %xmm4,%xmm6");
- 764 16702016 : asm volatile ("pshufb %xmm5,%xmm7");
- 765 16702016 : asm volatile ("pxor %xmm6,%xmm3");
- 766 16702016 : asm volatile ("pxor %xmm7,%xmm3");
+ 761 16730176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
+ 762 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
+ 763 16730176 : asm volatile ("pshufb %xmm4,%xmm6");
+ 764 16730176 : asm volatile ("pshufb %xmm5,%xmm7");
+ 765 16730176 : asm volatile ("pxor %xmm6,%xmm3");
+ 766 16730176 : asm volatile ("pxor %xmm7,%xmm3");
767 : }
768 :
769 : /* first disk with all coefficients at 1 */
- 770 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
- 771 3344192 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 770 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 771 3351232 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
772 :
- 773 3344192 : asm volatile ("pxor %xmm5,%xmm5");
- 774 3344192 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 775 3344192 : asm volatile ("paddb %xmm1,%xmm1");
- 776 3344192 : asm volatile ("pand %xmm7,%xmm5");
- 777 3344192 : asm volatile ("pxor %xmm5,%xmm1");
+ 773 3351232 : asm volatile ("pxor %xmm5,%xmm5");
+ 774 3351232 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 775 3351232 : asm volatile ("paddb %xmm1,%xmm1");
+ 776 3351232 : asm volatile ("pand %xmm7,%xmm5");
+ 777 3351232 : asm volatile ("pxor %xmm5,%xmm1");
778 :
- 779 3344192 : asm volatile ("pxor %xmm4,%xmm0");
- 780 3344192 : asm volatile ("pxor %xmm4,%xmm1");
- 781 3344192 : asm volatile ("pxor %xmm4,%xmm2");
- 782 3344192 : asm volatile ("pxor %xmm4,%xmm3");
+ 779 3351232 : asm volatile ("pxor %xmm4,%xmm0");
+ 780 3351232 : asm volatile ("pxor %xmm4,%xmm1");
+ 781 3351232 : asm volatile ("pxor %xmm4,%xmm2");
+ 782 3351232 : asm volatile ("pxor %xmm4,%xmm3");
783 :
- 784 3344192 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 785 3344192 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
- 786 3344192 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
- 787 3344192 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i]));
+ 784 3351232 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 785 3351232 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
+ 786 3351232 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
+ 787 3351232 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i]));
788 : }
789 :
790 : raid_sse_end();
@@ -1191,9 +1191,9 @@
1129 : /*
1130 : * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation
1131 : */
- 1132 50258 : void raid_gen5_ssse3(int nd, size_t size, void **vv)
+ 1132 50169 : void raid_gen5_ssse3(int nd, size_t size, void **vv)
1133 : {
- 1134 50258 : uint8_t **v = (uint8_t **)vv;
+ 1134 50169 : uint8_t **v = (uint8_t **)vv;
1135 : uint8_t *p;
1136 : uint8_t *q;
1137 : uint8_t *r;
@@ -1202,122 +1202,122 @@
1140 : int d, l;
1141 : size_t i;
1142 : uint8_t buffer[16+16];
- 1143 50258 : uint8_t *pd = __align_ptr(buffer, 16);
+ 1143 50169 : uint8_t *pd = __align_ptr(buffer, 16);
1144 :
- 1145 50258 : l = nd - 1;
- 1146 50258 : p = v[nd];
- 1147 50258 : q = v[nd + 1];
- 1148 50258 : r = v[nd + 2];
- 1149 50258 : s = v[nd + 3];
- 1150 50258 : t = v[nd + 4];
+ 1145 50169 : l = nd - 1;
+ 1146 50169 : p = v[nd];
+ 1147 50169 : q = v[nd + 1];
+ 1148 50169 : r = v[nd + 2];
+ 1149 50169 : s = v[nd + 3];
+ 1150 50169 : t = v[nd + 4];
1151 :
1152 : /* special case with only one data disk */
- 1153 50258 : if (l == 0) {
+ 1153 50169 : if (l == 0) {
1154 6 : for (i = 0; i < 5; ++i)
1155 5 : memcpy(v[1 + i], v[0], size);
- 1156 50259 : return;
+ 1156 50170 : return;
1157 : }
1158 :
1159 : raid_sse_begin();
1160 :
1161 : /* generic case with at least two data disks */
- 1162 3944417 : for (i = 0; i < size; i += 16) {
+ 1162 3938632 : for (i = 0; i < size; i += 16) {
1163 : /* last disk without the by two multiplication */
- 1164 3894160 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 1164 3888464 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
1165 :
- 1166 3894160 : asm volatile ("movdqa %xmm4,%xmm0");
- 1167 3894160 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
+ 1166 3888464 : asm volatile ("movdqa %xmm4,%xmm0");
+ 1167 3888464 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
1168 :
- 1169 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1170 3894160 : asm volatile ("movdqa %xmm4,%xmm5");
- 1171 3894160 : asm volatile ("psrlw $4,%xmm5");
- 1172 3894160 : asm volatile ("pand %xmm7,%xmm4");
- 1173 3894160 : asm volatile ("pand %xmm7,%xmm5");
+ 1169 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1170 3888464 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1171 3888464 : asm volatile ("psrlw $4,%xmm5");
+ 1172 3888464 : asm volatile ("pand %xmm7,%xmm4");
+ 1173 3888464 : asm volatile ("pand %xmm7,%xmm5");
1174 :
- 1175 3894160 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0]));
- 1176 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
- 1177 3894160 : asm volatile ("pshufb %xmm4,%xmm1");
- 1178 3894160 : asm volatile ("pshufb %xmm5,%xmm7");
- 1179 3894160 : asm volatile ("pxor %xmm7,%xmm1");
+ 1175 3888464 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0]));
+ 1176 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
+ 1177 3888464 : asm volatile ("pshufb %xmm4,%xmm1");
+ 1178 3888464 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1179 3888464 : asm volatile ("pxor %xmm7,%xmm1");
1180 :
- 1181 3894160 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0]));
- 1182 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
- 1183 3894160 : asm volatile ("pshufb %xmm4,%xmm2");
- 1184 3894160 : asm volatile ("pshufb %xmm5,%xmm7");
- 1185 3894160 : asm volatile ("pxor %xmm7,%xmm2");
+ 1181 3888464 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0]));
+ 1182 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
+ 1183 3888464 : asm volatile ("pshufb %xmm4,%xmm2");
+ 1184 3888464 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1185 3888464 : asm volatile ("pxor %xmm7,%xmm2");
1186 :
- 1187 3894160 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0]));
- 1188 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
- 1189 3894160 : asm volatile ("pshufb %xmm4,%xmm3");
- 1190 3894160 : asm volatile ("pshufb %xmm5,%xmm7");
- 1191 3894160 : asm volatile ("pxor %xmm7,%xmm3");
+ 1187 3888464 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0]));
+ 1188 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
+ 1189 3888464 : asm volatile ("pshufb %xmm4,%xmm3");
+ 1190 3888464 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1191 3888464 : asm volatile ("pxor %xmm7,%xmm3");
1192 :
1193 : /* intermediate disks */
- 1194 23366000 : for (d = l - 1; d > 0; --d) {
- 1195 19471840 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 1196 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
- 1197 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1194 23337520 : for (d = l - 1; d > 0; --d) {
+ 1195 19449056 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 1196 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
+ 1197 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1198 :
- 1199 19471840 : asm volatile ("pxor %xmm5,%xmm5");
- 1200 19471840 : asm volatile ("pcmpgtb %xmm0,%xmm5");
- 1201 19471840 : asm volatile ("paddb %xmm0,%xmm0");
- 1202 19471840 : asm volatile ("pand %xmm7,%xmm5");
- 1203 19471840 : asm volatile ("pxor %xmm5,%xmm0");
+ 1199 19449056 : asm volatile ("pxor %xmm5,%xmm5");
+ 1200 19449056 : asm volatile ("pcmpgtb %xmm0,%xmm5");
+ 1201 19449056 : asm volatile ("paddb %xmm0,%xmm0");
+ 1202 19449056 : asm volatile ("pand %xmm7,%xmm5");
+ 1203 19449056 : asm volatile ("pxor %xmm5,%xmm0");
1204 :
- 1205 19471840 : asm volatile ("pxor %xmm4,%xmm0");
- 1206 19471840 : asm volatile ("pxor %xmm4,%xmm6");
- 1207 19471840 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0]));
+ 1205 19449056 : asm volatile ("pxor %xmm4,%xmm0");
+ 1206 19449056 : asm volatile ("pxor %xmm4,%xmm6");
+ 1207 19449056 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0]));
1208 :
- 1209 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1210 19471840 : asm volatile ("movdqa %xmm4,%xmm5");
- 1211 19471840 : asm volatile ("psrlw $4,%xmm5");
- 1212 19471840 : asm volatile ("pand %xmm7,%xmm4");
- 1213 19471840 : asm volatile ("pand %xmm7,%xmm5");
+ 1209 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1210 19449056 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1211 19449056 : asm volatile ("psrlw $4,%xmm5");
+ 1212 19449056 : asm volatile ("pand %xmm7,%xmm4");
+ 1213 19449056 : asm volatile ("pand %xmm7,%xmm5");
1214 :
- 1215 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 1216 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
- 1217 19471840 : asm volatile ("pshufb %xmm4,%xmm6");
- 1218 19471840 : asm volatile ("pshufb %xmm5,%xmm7");
- 1219 19471840 : asm volatile ("pxor %xmm6,%xmm1");
- 1220 19471840 : asm volatile ("pxor %xmm7,%xmm1");
+ 1215 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 1216 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
+ 1217 19449056 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1218 19449056 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1219 19449056 : asm volatile ("pxor %xmm6,%xmm1");
+ 1220 19449056 : asm volatile ("pxor %xmm7,%xmm1");
1221 :
- 1222 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
- 1223 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
- 1224 19471840 : asm volatile ("pshufb %xmm4,%xmm6");
- 1225 19471840 : asm volatile ("pshufb %xmm5,%xmm7");
- 1226 19471840 : asm volatile ("pxor %xmm6,%xmm2");
- 1227 19471840 : asm volatile ("pxor %xmm7,%xmm2");
+ 1222 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
+ 1223 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
+ 1224 19449056 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1225 19449056 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1226 19449056 : asm volatile ("pxor %xmm6,%xmm2");
+ 1227 19449056 : asm volatile ("pxor %xmm7,%xmm2");
1228 :
- 1229 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
- 1230 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
- 1231 19471840 : asm volatile ("pshufb %xmm4,%xmm6");
- 1232 19471840 : asm volatile ("pshufb %xmm5,%xmm7");
- 1233 19471840 : asm volatile ("pxor %xmm6,%xmm3");
- 1234 19471840 : asm volatile ("pxor %xmm7,%xmm3");
+ 1229 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
+ 1230 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
+ 1231 19449056 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1232 19449056 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1233 19449056 : asm volatile ("pxor %xmm6,%xmm3");
+ 1234 19449056 : asm volatile ("pxor %xmm7,%xmm3");
1235 : }
1236 :
1237 : /* first disk with all coefficients at 1 */
- 1238 3894160 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
- 1239 3894160 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
- 1240 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1238 3888464 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 1239 3888464 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
+ 1240 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1241 :
- 1242 3894160 : asm volatile ("pxor %xmm5,%xmm5");
- 1243 3894160 : asm volatile ("pcmpgtb %xmm0,%xmm5");
- 1244 3894160 : asm volatile ("paddb %xmm0,%xmm0");
- 1245 3894160 : asm volatile ("pand %xmm7,%xmm5");
- 1246 3894160 : asm volatile ("pxor %xmm5,%xmm0");
+ 1242 3888464 : asm volatile ("pxor %xmm5,%xmm5");
+ 1243 3888464 : asm volatile ("pcmpgtb %xmm0,%xmm5");
+ 1244 3888464 : asm volatile ("paddb %xmm0,%xmm0");
+ 1245 3888464 : asm volatile ("pand %xmm7,%xmm5");
+ 1246 3888464 : asm volatile ("pxor %xmm5,%xmm0");
1247 :
- 1248 3894160 : asm volatile ("pxor %xmm4,%xmm0");
- 1249 3894160 : asm volatile ("pxor %xmm4,%xmm1");
- 1250 3894160 : asm volatile ("pxor %xmm4,%xmm2");
- 1251 3894160 : asm volatile ("pxor %xmm4,%xmm3");
- 1252 3894160 : asm volatile ("pxor %xmm4,%xmm6");
+ 1248 3888464 : asm volatile ("pxor %xmm4,%xmm0");
+ 1249 3888464 : asm volatile ("pxor %xmm4,%xmm1");
+ 1250 3888464 : asm volatile ("pxor %xmm4,%xmm2");
+ 1251 3888464 : asm volatile ("pxor %xmm4,%xmm3");
+ 1252 3888464 : asm volatile ("pxor %xmm4,%xmm6");
1253 :
- 1254 3894160 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i]));
- 1255 3894160 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i]));
- 1256 3894160 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i]));
- 1257 3894160 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i]));
- 1258 3894160 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i]));
+ 1254 3888464 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i]));
+ 1255 3888464 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i]));
+ 1256 3888464 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i]));
+ 1257 3888464 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i]));
+ 1258 3888464 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i]));
1259 : }
1260 :
1261 : raid_sse_end();
@@ -1591,9 +1591,9 @@
1529 : /*
1530 : * GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation
1531 : */
- 1532 549666 : void raid_gen6_ssse3(int nd, size_t size, void **vv)
+ 1532 559030 : void raid_gen6_ssse3(int nd, size_t size, void **vv)
1533 : {
- 1534 549666 : uint8_t **v = (uint8_t **)vv;
+ 1534 559030 : uint8_t **v = (uint8_t **)vv;
1535 : uint8_t *p;
1536 : uint8_t *q;
1537 : uint8_t *r;
@@ -1603,142 +1603,142 @@
1541 : int d, l;
1542 : size_t i;
1543 : uint8_t buffer[2*16+16];
- 1544 549666 : uint8_t *pd = __align_ptr(buffer, 16);
+ 1544 559030 : uint8_t *pd = __align_ptr(buffer, 16);
1545 :
- 1546 549666 : l = nd - 1;
- 1547 549666 : p = v[nd];
- 1548 549666 : q = v[nd + 1];
- 1549 549666 : r = v[nd + 2];
- 1550 549666 : s = v[nd + 3];
- 1551 549666 : t = v[nd + 4];
- 1552 549666 : u = v[nd + 5];
+ 1546 559030 : l = nd - 1;
+ 1547 559030 : p = v[nd];
+ 1548 559030 : q = v[nd + 1];
+ 1549 559030 : r = v[nd + 2];
+ 1550 559030 : s = v[nd + 3];
+ 1551 559030 : t = v[nd + 4];
+ 1552 559030 : u = v[nd + 5];
1553 :
1554 : /* special case with only one data disk */
- 1555 549666 : if (l == 0) {
+ 1555 559030 : if (l == 0) {
1556 7 : for (i = 0; i < 6; ++i)
1557 6 : memcpy(v[1 + i], v[0], size);
- 1558 549667 : return;
+ 1558 559031 : return;
1559 : }
1560 :
1561 : raid_sse_begin();
1562 :
1563 : /* generic case with at least two data disks */
- 1564 35154865 : for (i = 0; i < size; i += 16) {
+ 1564 35763525 : for (i = 0; i < size; i += 16) {
1565 : /* last disk without the by two multiplication */
- 1566 34605200 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 1566 35204496 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
1567 :
- 1568 34605200 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
- 1569 34605200 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16]));
+ 1568 35204496 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
+ 1569 35204496 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16]));
1570 :
- 1571 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1572 34605200 : asm volatile ("movdqa %xmm4,%xmm5");
- 1573 34605200 : asm volatile ("psrlw $4,%xmm5");
- 1574 34605200 : asm volatile ("pand %xmm7,%xmm4");
- 1575 34605200 : asm volatile ("pand %xmm7,%xmm5");
+ 1571 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1572 35204496 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1573 35204496 : asm volatile ("psrlw $4,%xmm5");
+ 1574 35204496 : asm volatile ("pand %xmm7,%xmm4");
+ 1575 35204496 : asm volatile ("pand %xmm7,%xmm5");
1576 :
- 1577 34605200 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0]));
- 1578 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
- 1579 34605200 : asm volatile ("pshufb %xmm4,%xmm0");
- 1580 34605200 : asm volatile ("pshufb %xmm5,%xmm7");
- 1581 34605200 : asm volatile ("pxor %xmm7,%xmm0");
+ 1577 35204496 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0]));
+ 1578 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
+ 1579 35204496 : asm volatile ("pshufb %xmm4,%xmm0");
+ 1580 35204496 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1581 35204496 : asm volatile ("pxor %xmm7,%xmm0");
1582 :
- 1583 34605200 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0]));
- 1584 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
- 1585 34605200 : asm volatile ("pshufb %xmm4,%xmm1");
- 1586 34605200 : asm volatile ("pshufb %xmm5,%xmm7");
- 1587 34605200 : asm volatile ("pxor %xmm7,%xmm1");
+ 1583 35204496 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0]));
+ 1584 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
+ 1585 35204496 : asm volatile ("pshufb %xmm4,%xmm1");
+ 1586 35204496 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1587 35204496 : asm volatile ("pxor %xmm7,%xmm1");
1588 :
- 1589 34605200 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0]));
- 1590 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
- 1591 34605200 : asm volatile ("pshufb %xmm4,%xmm2");
- 1592 34605200 : asm volatile ("pshufb %xmm5,%xmm7");
- 1593 34605200 : asm volatile ("pxor %xmm7,%xmm2");
+ 1589 35204496 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0]));
+ 1590 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
+ 1591 35204496 : asm volatile ("pshufb %xmm4,%xmm2");
+ 1592 35204496 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1593 35204496 : asm volatile ("pxor %xmm7,%xmm2");
1594 :
- 1595 34605200 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0]));
- 1596 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0]));
- 1597 34605200 : asm volatile ("pshufb %xmm4,%xmm3");
- 1598 34605200 : asm volatile ("pshufb %xmm5,%xmm7");
- 1599 34605200 : asm volatile ("pxor %xmm7,%xmm3");
+ 1595 35204496 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0]));
+ 1596 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0]));
+ 1597 35204496 : asm volatile ("pshufb %xmm4,%xmm3");
+ 1598 35204496 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1599 35204496 : asm volatile ("pxor %xmm7,%xmm3");
1600 :
1601 : /* intermediate disks */
- 1602 179030896 : for (d = l - 1; d > 0; --d) {
- 1603 144425696 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
- 1604 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
- 1605 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1602 182027376 : for (d = l - 1; d > 0; --d) {
+ 1603 146822880 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
+ 1604 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
+ 1605 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1606 :
- 1607 144425696 : asm volatile ("pxor %xmm4,%xmm4");
- 1608 144425696 : asm volatile ("pcmpgtb %xmm6,%xmm4");
- 1609 144425696 : asm volatile ("paddb %xmm6,%xmm6");
- 1610 144425696 : asm volatile ("pand %xmm7,%xmm4");
- 1611 144425696 : asm volatile ("pxor %xmm4,%xmm6");
+ 1607 146822880 : asm volatile ("pxor %xmm4,%xmm4");
+ 1608 146822880 : asm volatile ("pcmpgtb %xmm6,%xmm4");
+ 1609 146822880 : asm volatile ("paddb %xmm6,%xmm6");
+ 1610 146822880 : asm volatile ("pand %xmm7,%xmm4");
+ 1611 146822880 : asm volatile ("pxor %xmm4,%xmm6");
1612 :
- 1613 144425696 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 1613 146822880 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
1614 :
- 1615 144425696 : asm volatile ("pxor %xmm4,%xmm5");
- 1616 144425696 : asm volatile ("pxor %xmm4,%xmm6");
- 1617 144425696 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0]));
- 1618 144425696 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16]));
+ 1615 146822880 : asm volatile ("pxor %xmm4,%xmm5");
+ 1616 146822880 : asm volatile ("pxor %xmm4,%xmm6");
+ 1617 146822880 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0]));
+ 1618 146822880 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16]));
1619 :
- 1620 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1621 144425696 : asm volatile ("movdqa %xmm4,%xmm5");
- 1622 144425696 : asm volatile ("psrlw $4,%xmm5");
- 1623 144425696 : asm volatile ("pand %xmm7,%xmm4");
- 1624 144425696 : asm volatile ("pand %xmm7,%xmm5");
+ 1620 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1621 146822880 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1622 146822880 : asm volatile ("psrlw $4,%xmm5");
+ 1623 146822880 : asm volatile ("pand %xmm7,%xmm4");
+ 1624 146822880 : asm volatile ("pand %xmm7,%xmm5");
1625 :
- 1626 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 1627 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
- 1628 144425696 : asm volatile ("pshufb %xmm4,%xmm6");
- 1629 144425696 : asm volatile ("pshufb %xmm5,%xmm7");
- 1630 144425696 : asm volatile ("pxor %xmm6,%xmm0");
- 1631 144425696 : asm volatile ("pxor %xmm7,%xmm0");
+ 1626 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 1627 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
+ 1628 146822880 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1629 146822880 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1630 146822880 : asm volatile ("pxor %xmm6,%xmm0");
+ 1631 146822880 : asm volatile ("pxor %xmm7,%xmm0");
1632 :
- 1633 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
- 1634 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
- 1635 144425696 : asm volatile ("pshufb %xmm4,%xmm6");
- 1636 144425696 : asm volatile ("pshufb %xmm5,%xmm7");
- 1637 144425696 : asm volatile ("pxor %xmm6,%xmm1");
- 1638 144425696 : asm volatile ("pxor %xmm7,%xmm1");
+ 1633 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
+ 1634 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
+ 1635 146822880 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1636 146822880 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1637 146822880 : asm volatile ("pxor %xmm6,%xmm1");
+ 1638 146822880 : asm volatile ("pxor %xmm7,%xmm1");
1639 :
- 1640 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
- 1641 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
- 1642 144425696 : asm volatile ("pshufb %xmm4,%xmm6");
- 1643 144425696 : asm volatile ("pshufb %xmm5,%xmm7");
- 1644 144425696 : asm volatile ("pxor %xmm6,%xmm2");
- 1645 144425696 : asm volatile ("pxor %xmm7,%xmm2");
+ 1640 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
+ 1641 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
+ 1642 146822880 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1643 146822880 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1644 146822880 : asm volatile ("pxor %xmm6,%xmm2");
+ 1645 146822880 : asm volatile ("pxor %xmm7,%xmm2");
1646 :
- 1647 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0]));
- 1648 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0]));
- 1649 144425696 : asm volatile ("pshufb %xmm4,%xmm6");
- 1650 144425696 : asm volatile ("pshufb %xmm5,%xmm7");
- 1651 144425696 : asm volatile ("pxor %xmm6,%xmm3");
- 1652 144425696 : asm volatile ("pxor %xmm7,%xmm3");
+ 1647 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0]));
+ 1648 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0]));
+ 1649 146822880 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1650 146822880 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1651 146822880 : asm volatile ("pxor %xmm6,%xmm3");
+ 1652 146822880 : asm volatile ("pxor %xmm7,%xmm3");
1653 : }
1654 :
1655 : /* first disk with all coefficients at 1 */
- 1656 34605200 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
- 1657 34605200 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
- 1658 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1656 35204496 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
+ 1657 35204496 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
+ 1658 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1659 :
- 1660 34605200 : asm volatile ("pxor %xmm4,%xmm4");
- 1661 34605200 : asm volatile ("pcmpgtb %xmm6,%xmm4");
- 1662 34605200 : asm volatile ("paddb %xmm6,%xmm6");
- 1663 34605200 : asm volatile ("pand %xmm7,%xmm4");
- 1664 34605200 : asm volatile ("pxor %xmm4,%xmm6");
+ 1660 35204496 : asm volatile ("pxor %xmm4,%xmm4");
+ 1661 35204496 : asm volatile ("pcmpgtb %xmm6,%xmm4");
+ 1662 35204496 : asm volatile ("paddb %xmm6,%xmm6");
+ 1663 35204496 : asm volatile ("pand %xmm7,%xmm4");
+ 1664 35204496 : asm volatile ("pxor %xmm4,%xmm6");
1665 :
- 1666 34605200 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
- 1667 34605200 : asm volatile ("pxor %xmm4,%xmm0");
- 1668 34605200 : asm volatile ("pxor %xmm4,%xmm1");
- 1669 34605200 : asm volatile ("pxor %xmm4,%xmm2");
- 1670 34605200 : asm volatile ("pxor %xmm4,%xmm3");
- 1671 34605200 : asm volatile ("pxor %xmm4,%xmm5");
- 1672 34605200 : asm volatile ("pxor %xmm4,%xmm6");
+ 1666 35204496 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 1667 35204496 : asm volatile ("pxor %xmm4,%xmm0");
+ 1668 35204496 : asm volatile ("pxor %xmm4,%xmm1");
+ 1669 35204496 : asm volatile ("pxor %xmm4,%xmm2");
+ 1670 35204496 : asm volatile ("pxor %xmm4,%xmm3");
+ 1671 35204496 : asm volatile ("pxor %xmm4,%xmm5");
+ 1672 35204496 : asm volatile ("pxor %xmm4,%xmm6");
1673 :
- 1674 34605200 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i]));
- 1675 34605200 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i]));
- 1676 34605200 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i]));
- 1677 34605200 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i]));
- 1678 34605200 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i]));
- 1679 34605200 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i]));
+ 1674 35204496 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i]));
+ 1675 35204496 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i]));
+ 1676 35204496 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i]));
+ 1677 35204496 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i]));
+ 1678 35204496 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i]));
+ 1679 35204496 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i]));
1680 : }
1681 :
1682 : raid_sse_end();
@@ -2046,9 +2046,9 @@
1984 : /*
1985 : * RAID recovering for one disk SSSE3 implementation
1986 : */
- 1987 114430 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
+ 1987 108422 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
1988 : {
- 1989 114430 : uint8_t **v = (uint8_t **)vv;
+ 1989 108422 : uint8_t **v = (uint8_t **)vv;
1990 : uint8_t *p;
1991 : uint8_t *pa;
1992 : uint8_t G;
@@ -2058,43 +2058,43 @@
1996 : (void)nr; /* unused, it's always 1 */
1997 :
1998 : /* if it's RAID5 uses the faster function */
- 1999 114430 : if (ip[0] == 0) {
- 2000 104899 : raid_rec1of1(id, nd, size, vv);
- 2001 219329 : return;
+ 1999 108422 : if (ip[0] == 0) {
+ 2000 98863 : raid_rec1of1(id, nd, size, vv);
+ 2001 207285 : return;
2002 : }
2003 :
2004 : /* setup the coefficients matrix */
- 2005 19062 : G = A(ip[0], id[0]);
+ 2005 19118 : G = A(ip[0], id[0]);
2006 :
2007 : /* invert it to solve the system of linear equations */
- 2008 19062 : V = inv(G);
+ 2008 19118 : V = inv(G);
2009 :
2010 : /* compute delta parity */
- 2011 9531 : raid_delta_gen(1, id, ip, nd, size, vv);
+ 2011 9559 : raid_delta_gen(1, id, ip, nd, size, vv);
2012 :
- 2013 9531 : p = v[nd + ip[0]];
- 2014 9531 : pa = v[id[0]];
+ 2013 9559 : p = v[nd + ip[0]];
+ 2014 9559 : pa = v[id[0]];
2015 :
2016 : raid_sse_begin();
2017 :
- 2018 9531 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 2019 9531 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
- 2020 9531 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
+ 2018 9559 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 2019 9559 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
+ 2020 9559 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
2021 :
- 2022 1529403 : for (i = 0; i < size; i += 16) {
- 2023 1519872 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i]));
- 2024 1519872 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i]));
- 2025 1519872 : asm volatile ("movdqa %xmm4,%xmm2");
- 2026 1519872 : asm volatile ("movdqa %xmm5,%xmm3");
- 2027 1519872 : asm volatile ("pxor %xmm0,%xmm1");
- 2028 1519872 : asm volatile ("movdqa %xmm1,%xmm0");
- 2029 1519872 : asm volatile ("psrlw $4,%xmm1");
- 2030 1519872 : asm volatile ("pand %xmm7,%xmm0");
- 2031 1519872 : asm volatile ("pand %xmm7,%xmm1");
- 2032 1519872 : asm volatile ("pshufb %xmm0,%xmm2");
- 2033 1519872 : asm volatile ("pshufb %xmm1,%xmm3");
- 2034 1519872 : asm volatile ("pxor %xmm3,%xmm2");
- 2035 1519872 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i]));
+ 2022 1531223 : for (i = 0; i < size; i += 16) {
+ 2023 1521664 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i]));
+ 2024 1521664 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i]));
+ 2025 1521664 : asm volatile ("movdqa %xmm4,%xmm2");
+ 2026 1521664 : asm volatile ("movdqa %xmm5,%xmm3");
+ 2027 1521664 : asm volatile ("pxor %xmm0,%xmm1");
+ 2028 1521664 : asm volatile ("movdqa %xmm1,%xmm0");
+ 2029 1521664 : asm volatile ("psrlw $4,%xmm1");
+ 2030 1521664 : asm volatile ("pand %xmm7,%xmm0");
+ 2031 1521664 : asm volatile ("pand %xmm7,%xmm1");
+ 2032 1521664 : asm volatile ("pshufb %xmm0,%xmm2");
+ 2033 1521664 : asm volatile ("pshufb %xmm1,%xmm3");
+ 2034 1521664 : asm volatile ("pxor %xmm3,%xmm2");
+ 2035 1521664 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i]));
2036 : }
2037 :
2038 : raid_sse_end();
@@ -2105,182 +2105,182 @@
2043 : /*
2044 : * RAID recovering for two disks SSSE3 implementation
2045 : */
- 2046 44206 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
+ 2046 43538 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
2047 : {
- 2048 44206 : uint8_t **v = (uint8_t **)vv;
- 2049 44206 : const int N = 2;
- 2050 44206 : uint8_t *p[N];
- 2051 44206 : uint8_t *pa[N];
- 2052 44206 : uint8_t G[N * N];
- 2053 44206 : uint8_t V[N * N];
+ 2048 43538 : uint8_t **v = (uint8_t **)vv;
+ 2049 43538 : const int N = 2;
+ 2050 43538 : uint8_t *p[N];
+ 2051 43538 : uint8_t *pa[N];
+ 2052 43538 : uint8_t G[N * N];
+ 2053 43538 : uint8_t V[N * N];
2054 : size_t i;
2055 : int j, k;
2056 :
2057 : (void)nr; /* unused, it's always 2 */
2058 :
2059 : /* setup the coefficients matrix */
- 2060 132618 : for (j = 0; j < N; ++j)
- 2061 265236 : for (k = 0; k < N; ++k)
- 2062 353648 : G[j * N + k] = A(ip[j], id[k]);
+ 2060 130614 : for (j = 0; j < N; ++j)
+ 2061 261228 : for (k = 0; k < N; ++k)
+ 2062 348304 : G[j * N + k] = A(ip[j], id[k]);
2063 :
2064 : /* invert it to solve the system of linear equations */
- 2065 44206 : raid_invert(G, V, N);
+ 2065 43538 : raid_invert(G, V, N);
2066 :
2067 : /* compute delta parity */
- 2068 44206 : raid_delta_gen(N, id, ip, nd, size, vv);
+ 2068 43538 : raid_delta_gen(N, id, ip, nd, size, vv);
2069 :
- 2070 132618 : for (j = 0; j < N; ++j) {
- 2071 88412 : p[j] = v[nd + ip[j]];
- 2072 88412 : pa[j] = v[id[j]];
+ 2070 130614 : for (j = 0; j < N; ++j) {
+ 2071 87076 : p[j] = v[nd + ip[j]];
+ 2072 87076 : pa[j] = v[id[j]];
2073 : }
2074 :
2075 : raid_sse_begin();
2076 :
- 2077 44206 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 2077 43538 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
2078 :
- 2079 3599726 : for (i = 0; i < size; i += 16) {
- 2080 3555520 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i]));
- 2081 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i]));
- 2082 3555520 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i]));
- 2083 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i]));
- 2084 3555520 : asm volatile ("pxor %xmm2,%xmm0");
- 2085 3555520 : asm volatile ("pxor %xmm3,%xmm1");
+ 2079 3556306 : for (i = 0; i < size; i += 16) {
+ 2080 3512768 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i]));
+ 2081 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i]));
+ 2082 3512768 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i]));
+ 2083 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i]));
+ 2084 3512768 : asm volatile ("pxor %xmm2,%xmm0");
+ 2085 3512768 : asm volatile ("pxor %xmm3,%xmm1");
2086 :
- 2087 3555520 : asm volatile ("pxor %xmm6,%xmm6");
+ 2087 3512768 : asm volatile ("pxor %xmm6,%xmm6");
2088 :
- 2089 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0]));
- 2090 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0]));
- 2091 3555520 : asm volatile ("movdqa %xmm0,%xmm4");
- 2092 3555520 : asm volatile ("movdqa %xmm0,%xmm5");
- 2093 3555520 : asm volatile ("psrlw $4,%xmm5");
- 2094 3555520 : asm volatile ("pand %xmm7,%xmm4");
- 2095 3555520 : asm volatile ("pand %xmm7,%xmm5");
- 2096 3555520 : asm volatile ("pshufb %xmm4,%xmm2");
- 2097 3555520 : asm volatile ("pshufb %xmm5,%xmm3");
- 2098 3555520 : asm volatile ("pxor %xmm2,%xmm6");
- 2099 3555520 : asm volatile ("pxor %xmm3,%xmm6");
+ 2089 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0]));
+ 2090 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0]));
+ 2091 3512768 : asm volatile ("movdqa %xmm0,%xmm4");
+ 2092 3512768 : asm volatile ("movdqa %xmm0,%xmm5");
+ 2093 3512768 : asm volatile ("psrlw $4,%xmm5");
+ 2094 3512768 : asm volatile ("pand %xmm7,%xmm4");
+ 2095 3512768 : asm volatile ("pand %xmm7,%xmm5");
+ 2096 3512768 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2097 3512768 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2098 3512768 : asm volatile ("pxor %xmm2,%xmm6");
+ 2099 3512768 : asm volatile ("pxor %xmm3,%xmm6");
2100 :
- 2101 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0]));
- 2102 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0]));
- 2103 3555520 : asm volatile ("movdqa %xmm1,%xmm4");
- 2104 3555520 : asm volatile ("movdqa %xmm1,%xmm5");
- 2105 3555520 : asm volatile ("psrlw $4,%xmm5");
- 2106 3555520 : asm volatile ("pand %xmm7,%xmm4");
- 2107 3555520 : asm volatile ("pand %xmm7,%xmm5");
- 2108 3555520 : asm volatile ("pshufb %xmm4,%xmm2");
- 2109 3555520 : asm volatile ("pshufb %xmm5,%xmm3");
- 2110 3555520 : asm volatile ("pxor %xmm2,%xmm6");
- 2111 3555520 : asm volatile ("pxor %xmm3,%xmm6");
+ 2101 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0]));
+ 2102 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0]));
+ 2103 3512768 : asm volatile ("movdqa %xmm1,%xmm4");
+ 2104 3512768 : asm volatile ("movdqa %xmm1,%xmm5");
+ 2105 3512768 : asm volatile ("psrlw $4,%xmm5");
+ 2106 3512768 : asm volatile ("pand %xmm7,%xmm4");
+ 2107 3512768 : asm volatile ("pand %xmm7,%xmm5");
+ 2108 3512768 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2109 3512768 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2110 3512768 : asm volatile ("pxor %xmm2,%xmm6");
+ 2111 3512768 : asm volatile ("pxor %xmm3,%xmm6");
2112 :
- 2113 3555520 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i]));
+ 2113 3512768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i]));
2114 :
- 2115 3555520 : asm volatile ("pxor %xmm6,%xmm6");
+ 2115 3512768 : asm volatile ("pxor %xmm6,%xmm6");
2116 :
- 2117 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0]));
- 2118 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0]));
- 2119 3555520 : asm volatile ("movdqa %xmm0,%xmm4");
- 2120 3555520 : asm volatile ("movdqa %xmm0,%xmm5");
- 2121 3555520 : asm volatile ("psrlw $4,%xmm5");
- 2122 3555520 : asm volatile ("pand %xmm7,%xmm4");
- 2123 3555520 : asm volatile ("pand %xmm7,%xmm5");
- 2124 3555520 : asm volatile ("pshufb %xmm4,%xmm2");
- 2125 3555520 : asm volatile ("pshufb %xmm5,%xmm3");
- 2126 3555520 : asm volatile ("pxor %xmm2,%xmm6");
- 2127 3555520 : asm volatile ("pxor %xmm3,%xmm6");
+ 2117 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0]));
+ 2118 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0]));
+ 2119 3512768 : asm volatile ("movdqa %xmm0,%xmm4");
+ 2120 3512768 : asm volatile ("movdqa %xmm0,%xmm5");
+ 2121 3512768 : asm volatile ("psrlw $4,%xmm5");
+ 2122 3512768 : asm volatile ("pand %xmm7,%xmm4");
+ 2123 3512768 : asm volatile ("pand %xmm7,%xmm5");
+ 2124 3512768 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2125 3512768 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2126 3512768 : asm volatile ("pxor %xmm2,%xmm6");
+ 2127 3512768 : asm volatile ("pxor %xmm3,%xmm6");
2128 :
- 2129 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0]));
- 2130 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0]));
- 2131 3555520 : asm volatile ("movdqa %xmm1,%xmm4");
- 2132 3555520 : asm volatile ("movdqa %xmm1,%xmm5");
- 2133 3555520 : asm volatile ("psrlw $4,%xmm5");
- 2134 3555520 : asm volatile ("pand %xmm7,%xmm4");
- 2135 3555520 : asm volatile ("pand %xmm7,%xmm5");
- 2136 3555520 : asm volatile ("pshufb %xmm4,%xmm2");
- 2137 3555520 : asm volatile ("pshufb %xmm5,%xmm3");
- 2138 3555520 : asm volatile ("pxor %xmm2,%xmm6");
- 2139 3555520 : asm volatile ("pxor %xmm3,%xmm6");
+ 2129 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0]));
+ 2130 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0]));
+ 2131 3512768 : asm volatile ("movdqa %xmm1,%xmm4");
+ 2132 3512768 : asm volatile ("movdqa %xmm1,%xmm5");
+ 2133 3512768 : asm volatile ("psrlw $4,%xmm5");
+ 2134 3512768 : asm volatile ("pand %xmm7,%xmm4");
+ 2135 3512768 : asm volatile ("pand %xmm7,%xmm5");
+ 2136 3512768 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2137 3512768 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2138 3512768 : asm volatile ("pxor %xmm2,%xmm6");
+ 2139 3512768 : asm volatile ("pxor %xmm3,%xmm6");
2140 :
- 2141 3555520 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i]));
+ 2141 3512768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i]));
2142 : }
2143 :
2144 : raid_sse_end();
- 2145 44206 : }
+ 2145 43538 : }
2146 : #endif
2147 :
2148 : #if defined(CONFIG_X86) && defined(CONFIG_SSSE3)
2149 : /*
2150 : * RAID recovering SSSE3 implementation
2151 : */
- 2152 79298 : void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
+ 2152 79451 : void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
2153 : {
- 2154 79298 : uint8_t **v = (uint8_t **)vv;
- 2155 79298 : int N = nr;
+ 2154 79451 : uint8_t **v = (uint8_t **)vv;
+ 2155 79451 : int N = nr;
2156 : uint8_t *p[RAID_PARITY_MAX];
2157 : uint8_t *pa[RAID_PARITY_MAX];
2158 : uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX];
2159 : uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX];
2160 : uint8_t buffer[RAID_PARITY_MAX*16+16];
- 2161 79298 : uint8_t *pd = __align_ptr(buffer, 16);
+ 2161 79451 : uint8_t *pd = __align_ptr(buffer, 16);
2162 : size_t i;
2163 : int j, k;
2164 :
2165 : /* setup the coefficients matrix */
- 2166 435232 : for (j = 0; j < N; ++j)
- 2167 2047624 : for (k = 0; k < N; ++k)
- 2168 3383380 : G[j * N + k] = A(ip[j], id[k]);
+ 2166 435393 : for (j = 0; j < N; ++j)
+ 2167 2045022 : for (k = 0; k < N; ++k)
+ 2168 3378160 : G[j * N + k] = A(ip[j], id[k]);
2169 :
2170 : /* invert it to solve the system of linear equations */
- 2171 79298 : raid_invert(G, V, N);
+ 2171 79451 : raid_invert(G, V, N);
2172 :
2173 : /* compute delta parity */
- 2174 79298 : raid_delta_gen(N, id, ip, nd, size, vv);
+ 2174 79451 : raid_delta_gen(N, id, ip, nd, size, vv);
2175 :
- 2176 435232 : for (j = 0; j < N; ++j) {
- 2177 355934 : p[j] = v[nd + ip[j]];
- 2178 355934 : pa[j] = v[id[j]];
+ 2176 435393 : for (j = 0; j < N; ++j) {
+ 2177 355942 : p[j] = v[nd + ip[j]];
+ 2178 355942 : pa[j] = v[id[j]];
2179 : }
2180 :
2181 : raid_sse_begin();
2182 :
- 2183 79298 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 2183 79451 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
2184 :
- 2185 5870482 : for (i = 0; i < size; i += 16) {
+ 2185 5880427 : for (i = 0; i < size; i += 16) {
2186 : /* delta */
- 2187 32123728 : for (j = 0; j < N; ++j) {
- 2188 26332544 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[j][i]));
- 2189 26332544 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[j][i]));
- 2190 26332544 : asm volatile ("pxor %xmm1,%xmm0");
- 2191 26332544 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pd[j*16]));
+ 2187 32134032 : for (j = 0; j < N; ++j) {
+ 2188 26333056 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[j][i]));
+ 2189 26333056 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[j][i]));
+ 2190 26333056 : asm volatile ("pxor %xmm1,%xmm0");
+ 2191 26333056 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pd[j*16]));
2192 : }
2193 :
2194 : /* reconstruct */
- 2195 32123728 : for (j = 0; j < N; ++j) {
- 2196 26332544 : asm volatile ("pxor %xmm0,%xmm0");
- 2197 26332544 : asm volatile ("pxor %xmm1,%xmm1");
+ 2195 32134032 : for (j = 0; j < N; ++j) {
+ 2196 26333056 : asm volatile ("pxor %xmm0,%xmm0");
+ 2197 26333056 : asm volatile ("pxor %xmm1,%xmm1");
2198 :
- 2199 153287872 : for (k = 0; k < N; ++k) {
- 2200 126955328 : uint8_t m = V[j * N + k];
+ 2199 153121344 : for (k = 0; k < N; ++k) {
+ 2200 126788288 : uint8_t m = V[j * N + k];
2201 :
- 2202 126955328 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0]));
- 2203 126955328 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0]));
- 2204 126955328 : asm volatile ("movdqa %0,%%xmm4" : : "m" (pd[k*16]));
- 2205 126955328 : asm volatile ("movdqa %xmm4,%xmm5");
- 2206 126955328 : asm volatile ("psrlw $4,%xmm5");
- 2207 126955328 : asm volatile ("pand %xmm7,%xmm4");
- 2208 126955328 : asm volatile ("pand %xmm7,%xmm5");
- 2209 126955328 : asm volatile ("pshufb %xmm4,%xmm2");
- 2210 126955328 : asm volatile ("pshufb %xmm5,%xmm3");
- 2211 126955328 : asm volatile ("pxor %xmm2,%xmm0");
- 2212 126955328 : asm volatile ("pxor %xmm3,%xmm1");
+ 2202 126788288 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0]));
+ 2203 126788288 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0]));
+ 2204 126788288 : asm volatile ("movdqa %0,%%xmm4" : : "m" (pd[k*16]));
+ 2205 126788288 : asm volatile ("movdqa %xmm4,%xmm5");
+ 2206 126788288 : asm volatile ("psrlw $4,%xmm5");
+ 2207 126788288 : asm volatile ("pand %xmm7,%xmm4");
+ 2208 126788288 : asm volatile ("pand %xmm7,%xmm5");
+ 2209 126788288 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2210 126788288 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2211 126788288 : asm volatile ("pxor %xmm2,%xmm0");
+ 2212 126788288 : asm volatile ("pxor %xmm3,%xmm1");
2213 : }
2214 :
- 2215 26332544 : asm volatile ("pxor %xmm1,%xmm0");
- 2216 26332544 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pa[j][i]));
+ 2215 26333056 : asm volatile ("pxor %xmm1,%xmm0");
+ 2216 26333056 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pa[j][i]));
2217 : }
2218 : }
2219 :
2220 : raid_sse_end();
- 2221 79298 : }
+ 2221 79451 : }
2222 : #endif
2223 :
2224 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2)
diff --git a/cov/raid/x86z.c.func-sort-c.html b/cov/raid/x86z.c.func-sort-c.html
index cb2cfb47..65751eb9 100644
--- a/cov/raid/x86z.c.func-sort-c.html
+++ b/cov/raid/x86z.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| raid_genz_sse2 |
- 1177 |
+ 1178 |
diff --git a/cov/raid/x86z.c.func.html b/cov/raid/x86z.c.func.html
index f498b4e6..3fb78598 100644
--- a/cov/raid/x86z.c.func.html
+++ b/cov/raid/x86z.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| raid_genz_sse2 |
- 1177 |
+ 1178 |
diff --git a/cov/raid/x86z.c.gcov.html b/cov/raid/x86z.c.gcov.html
index 9039ba20..fb6c8977 100644
--- a/cov/raid/x86z.c.gcov.html
+++ b/cov/raid/x86z.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -102,58 +102,58 @@
40 : /*
41 : * GENz (triple parity with powers of 2^-1) SSE2 implementation
42 : */
- 43 1177 : void raid_genz_sse2(int nd, size_t size, void **vv)
+ 43 1178 : void raid_genz_sse2(int nd, size_t size, void **vv)
44 : {
- 45 1177 : uint8_t **v = (uint8_t**)vv;
+ 45 1178 : uint8_t **v = (uint8_t**)vv;
46 : uint8_t *p;
47 : uint8_t *q;
48 : uint8_t *r;
49 : int d, l;
50 : size_t i;
51 :
- 52 1177 : l = nd - 1;
- 53 1177 : p = v[nd];
- 54 1177 : q = v[nd + 1];
- 55 1177 : r = v[nd + 2];
+ 52 1178 : l = nd - 1;
+ 53 1178 : p = v[nd];
+ 54 1178 : q = v[nd + 1];
+ 55 1178 : r = v[nd + 2];
56 :
57 : raid_sse_begin();
58 :
- 59 1177 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0]));
- 60 1177 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0]));
- 61 1177 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0]));
+ 59 1178 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0]));
+ 60 1178 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0]));
+ 61 1178 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0]));
62 :
- 63 1394921 : for (i = 0; i < size; i += 16) {
- 64 1393744 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 65 1393744 : asm volatile ("movdqa %xmm0,%xmm1");
- 66 1393744 : asm volatile ("movdqa %xmm0,%xmm2");
- 67 11220224 : for (d = l - 1; d >= 0; --d) {
- 68 9826480 : asm volatile ("pxor %xmm4,%xmm4");
- 69 9826480 : asm volatile ("pcmpgtb %xmm1,%xmm4");
- 70 9826480 : asm volatile ("paddb %xmm1,%xmm1");
- 71 9826480 : asm volatile ("pand %xmm7,%xmm4");
- 72 9826480 : asm volatile ("pxor %xmm4,%xmm1");
+ 63 1411306 : for (i = 0; i < size; i += 16) {
+ 64 1410128 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 65 1410128 : asm volatile ("movdqa %xmm0,%xmm1");
+ 66 1410128 : asm volatile ("movdqa %xmm0,%xmm2");
+ 67 11351296 : for (d = l - 1; d >= 0; --d) {
+ 68 9941168 : asm volatile ("pxor %xmm4,%xmm4");
+ 69 9941168 : asm volatile ("pcmpgtb %xmm1,%xmm4");
+ 70 9941168 : asm volatile ("paddb %xmm1,%xmm1");
+ 71 9941168 : asm volatile ("pand %xmm7,%xmm4");
+ 72 9941168 : asm volatile ("pxor %xmm4,%xmm1");
73 :
- 74 9826480 : asm volatile ("movdqa %xmm2,%xmm4");
- 75 9826480 : asm volatile ("pxor %xmm5,%xmm5");
- 76 9826480 : asm volatile ("psllw $7,%xmm4");
- 77 9826480 : asm volatile ("psrlw $1,%xmm2");
- 78 9826480 : asm volatile ("pcmpgtb %xmm4,%xmm5");
- 79 9826480 : asm volatile ("pand %xmm6,%xmm2");
- 80 9826480 : asm volatile ("pand %xmm3,%xmm5");
- 81 9826480 : asm volatile ("pxor %xmm5,%xmm2");
+ 74 9941168 : asm volatile ("movdqa %xmm2,%xmm4");
+ 75 9941168 : asm volatile ("pxor %xmm5,%xmm5");
+ 76 9941168 : asm volatile ("psllw $7,%xmm4");
+ 77 9941168 : asm volatile ("psrlw $1,%xmm2");
+ 78 9941168 : asm volatile ("pcmpgtb %xmm4,%xmm5");
+ 79 9941168 : asm volatile ("pand %xmm6,%xmm2");
+ 80 9941168 : asm volatile ("pand %xmm3,%xmm5");
+ 81 9941168 : asm volatile ("pxor %xmm5,%xmm2");
82 :
- 83 9826480 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 84 9826480 : asm volatile ("pxor %xmm4,%xmm0");
- 85 9826480 : asm volatile ("pxor %xmm4,%xmm1");
- 86 9826480 : asm volatile ("pxor %xmm4,%xmm2");
+ 83 9941168 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 84 9941168 : asm volatile ("pxor %xmm4,%xmm0");
+ 85 9941168 : asm volatile ("pxor %xmm4,%xmm1");
+ 86 9941168 : asm volatile ("pxor %xmm4,%xmm2");
87 : }
- 88 1393744 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 89 1393744 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
- 90 1393744 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
+ 88 1410128 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 89 1410128 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
+ 90 1410128 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
91 : }
92 :
93 : raid_sse_end();
- 94 1177 : }
+ 94 1178 : }
95 : #endif
96 :
97 : #if defined(CONFIG_X86_64) && defined(CONFIG_SSE2)
diff --git a/cov/tommyds/index-sort-f.html b/cov/tommyds/index-sort-f.html
index 10ac305b..9a76fe79 100644
--- a/cov/tommyds/index-sort-f.html
+++ b/cov/tommyds/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/index-sort-l.html b/cov/tommyds/index-sort-l.html
index ac04e945..f9780f3b 100644
--- a/cov/tommyds/index-sort-l.html
+++ b/cov/tommyds/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/index.html b/cov/tommyds/index.html
index ecd00113..6fdcec83 100644
--- a/cov/tommyds/index.html
+++ b/cov/tommyds/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarray.c.func-sort-c.html b/cov/tommyds/tommyarray.c.func-sort-c.html
index eb0f50ec..79c98e30 100644
--- a/cov/tommyds/tommyarray.c.func-sort-c.html
+++ b/cov/tommyds/tommyarray.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| tommy_array_grow |
- 2086 |
+ 2134 |
| tommy_array_init |
- 486 |
+ 502 |
| tommy_array_done |
- 463 |
+ 479 |
| tommy_array_memory_usage |
diff --git a/cov/tommyds/tommyarray.c.func.html b/cov/tommyds/tommyarray.c.func.html
index ea4d5acb..e35a328c 100644
--- a/cov/tommyds/tommyarray.c.func.html
+++ b/cov/tommyds/tommyarray.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| tommy_array_done |
- 463 |
+ 479 |
| tommy_array_grow |
- 2086 |
+ 2134 |
| tommy_array_init |
- 486 |
+ 502 |
| tommy_array_memory_usage |
diff --git a/cov/tommyds/tommyarray.c.gcov.html b/cov/tommyds/tommyarray.c.gcov.html
index 1e28d9b1..86c90ec9 100644
--- a/cov/tommyds/tommyarray.c.gcov.html
+++ b/cov/tommyds/tommyarray.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -92,38 +92,38 @@
30 : /******************************************************************************/
31 : /* array */
32 :
- 33 486 : void tommy_array_init(tommy_array* array)
+ 33 502 : void tommy_array_init(tommy_array* array)
34 : {
35 : tommy_uint_t i;
36 :
37 : /* fixed initial size */
- 38 486 : array->bucket_bit = TOMMY_ARRAY_BIT;
- 39 486 : array->bucket_max = 1 << array->bucket_bit;
- 40 486 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*)));
- 41 2916 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i)
- 42 2430 : array->bucket[i] = array->bucket[0];
+ 38 502 : array->bucket_bit = TOMMY_ARRAY_BIT;
+ 39 502 : array->bucket_max = 1 << array->bucket_bit;
+ 40 502 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*)));
+ 41 3012 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i)
+ 42 2510 : array->bucket[i] = array->bucket[0];
43 :
- 44 486 : array->count = 0;
- 45 486 : }
+ 44 502 : array->count = 0;
+ 45 502 : }
46 :
- 47 463 : void tommy_array_done(tommy_array* array)
+ 47 479 : void tommy_array_done(tommy_array* array)
48 : {
49 : tommy_uint_t i;
50 :
- 51 463 : tommy_free(array->bucket[0]);
- 52 465 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) {
+ 51 479 : tommy_free(array->bucket[0]);
+ 52 481 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) {
53 2 : void** segment = array->bucket[i];
54 2 : tommy_free(&segment[((tommy_ptrdiff_t)1) << i]);
55 : }
- 56 463 : }
+ 56 479 : }
57 :
- 58 2086 : void tommy_array_grow(tommy_array* array, tommy_count_t count)
+ 58 2134 : void tommy_array_grow(tommy_array* array, tommy_count_t count)
59 : {
- 60 2086 : if (array->count >= count)
- 61 2086 : return;
- 62 2086 : array->count = count;
+ 60 2134 : if (array->count >= count)
+ 61 2134 : return;
+ 62 2134 : array->count = count;
63 :
- 64 4174 : while (count > array->bucket_max) {
+ 64 4270 : while (count > array->bucket_max) {
65 : void** segment;
66 :
67 : /* allocate one more segment */
diff --git a/cov/tommyds/tommyarray.h.func-sort-c.html b/cov/tommyds/tommyarray.h.func-sort-c.html
index 47f38cb2..eae84ff6 100644
--- a/cov/tommyds/tommyarray.h.func-sort-c.html
+++ b/cov/tommyds/tommyarray.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,20 +60,20 @@
Hit count  |
- | tommy_array_get |
- 15295882 |
+ tommy_array_ref |
+ 10133914 |
- | tommy_array_ref |
- 15273609 |
+ tommy_array_get |
+ 10131780 |
| tommy_array_size |
- 1519764 |
+ 1541305 |
| tommy_array_set |
- 2086 |
+ 2134 |
| tommy_array_insert |
diff --git a/cov/tommyds/tommyarray.h.func.html b/cov/tommyds/tommyarray.h.func.html
index 094f71fc..8232c615 100644
--- a/cov/tommyds/tommyarray.h.func.html
+++ b/cov/tommyds/tommyarray.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| tommy_array_get |
- 15295882 |
+ 10131780 |
| tommy_array_insert |
@@ -69,15 +69,15 @@
| tommy_array_ref |
- 15273609 |
+ 10133914 |
| tommy_array_set |
- 2086 |
+ 2134 |
| tommy_array_size |
- 1519764 |
+ 1541305 |
diff --git a/cov/tommyds/tommyarray.h.gcov.html b/cov/tommyds/tommyarray.h.gcov.html
index 306db8c1..43dd4250 100644
--- a/cov/tommyds/tommyarray.h.gcov.html
+++ b/cov/tommyds/tommyarray.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -152,16 +152,16 @@
90 : * You must be sure that space for this position is already
91 : * allocated calling tommy_array_grow().
92 : */
- 93 15273609 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
+ 93 10133914 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
94 : {
95 : tommy_uint_t bsr;
96 :
- 97 15273609 : assert(pos < array->count);
+ 97 10133914 : assert(pos < array->count);
98 :
99 : /* get the highest bit set, in case of all 0, return 0 */
- 100 15273609 : bsr = tommy_ilog2_u32(pos | 1);
+ 100 10133914 : bsr = tommy_ilog2_u32(pos | 1);
101 :
- 102 15288941 : return &array->bucket[bsr][pos];
+ 102 10133914 : return &array->bucket[bsr][pos];
103 : }
104 :
105 : /**
@@ -169,19 +169,19 @@
107 : * You must be sure that space for this position is already
108 : * allocated calling tommy_array_grow().
109 : */
- 110 2086 : tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element)
+ 110 2134 : tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element)
111 : {
- 112 2086 : *tommy_array_ref(array, pos) = element;
- 113 2086 : }
+ 112 2134 : *tommy_array_ref(array, pos) = element;
+ 113 2134 : }
114 :
115 : /**
116 : * Gets the element at the specified position.
117 : * You must be sure that space for this position is already
118 : * allocated calling tommy_array_grow().
119 : */
- 120 15295882 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
+ 120 10131780 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
121 : {
- 122 15295882 : return *tommy_array_ref(array, pos);
+ 122 10131780 : return *tommy_array_ref(array, pos);
123 : }
124 :
125 : /**
@@ -199,9 +199,9 @@
137 : /**
138 : * Gets the initialized size of the array.
139 : */
- 140 1519764 : tommy_inline tommy_count_t tommy_array_size(tommy_array* array)
+ 140 1541305 : tommy_inline tommy_count_t tommy_array_size(tommy_array* array)
141 : {
- 142 1519764 : return array->count;
+ 142 1541305 : return array->count;
143 : }
144 :
145 : /**
diff --git a/cov/tommyds/tommyarrayblk.c.func-sort-c.html b/cov/tommyds/tommyarrayblk.c.func-sort-c.html
index b81595fd..f95f1c5f 100644
--- a/cov/tommyds/tommyarrayblk.c.func-sort-c.html
+++ b/cov/tommyds/tommyarrayblk.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblk.c.func.html b/cov/tommyds/tommyarrayblk.c.func.html
index 06bbfd2d..127cd197 100644
--- a/cov/tommyds/tommyarrayblk.c.func.html
+++ b/cov/tommyds/tommyarrayblk.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblk.c.gcov.html b/cov/tommyds/tommyarrayblk.c.gcov.html
index deef2d86..5de3ddaf 100644
--- a/cov/tommyds/tommyarrayblk.c.gcov.html
+++ b/cov/tommyds/tommyarrayblk.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblk.h.func-sort-c.html b/cov/tommyds/tommyarrayblk.h.func-sort-c.html
index 774c7f4c..c47df152 100644
--- a/cov/tommyds/tommyarrayblk.h.func-sort-c.html
+++ b/cov/tommyds/tommyarrayblk.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblk.h.func.html b/cov/tommyds/tommyarrayblk.h.func.html
index 0c988a32..c9e1a0b7 100644
--- a/cov/tommyds/tommyarrayblk.h.func.html
+++ b/cov/tommyds/tommyarrayblk.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblk.h.gcov.html b/cov/tommyds/tommyarrayblk.h.gcov.html
index dd4893ab..78cb8df9 100644
--- a/cov/tommyds/tommyarrayblk.h.gcov.html
+++ b/cov/tommyds/tommyarrayblk.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
index 9b15c5a4..a308945e 100644
--- a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
+++ b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| tommy_arrayblkof_grow |
- 1609741 |
+ 1640038 |
| tommy_arrayblkof_init |
- 249 |
+ 257 |
| tommy_arrayblkof_done |
- 227 |
+ 235 |
| tommy_arrayblkof_memory_usage |
diff --git a/cov/tommyds/tommyarrayblkof.c.func.html b/cov/tommyds/tommyarrayblkof.c.func.html
index 17140f12..1549efe9 100644
--- a/cov/tommyds/tommyarrayblkof.c.func.html
+++ b/cov/tommyds/tommyarrayblkof.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| tommy_arrayblkof_done |
- 227 |
+ 235 |
| tommy_arrayblkof_grow |
- 1609741 |
+ 1640038 |
| tommy_arrayblkof_init |
- 249 |
+ 257 |
| tommy_arrayblkof_memory_usage |
diff --git a/cov/tommyds/tommyarrayblkof.c.gcov.html b/cov/tommyds/tommyarrayblkof.c.gcov.html
index 4da680ca..414b307c 100644
--- a/cov/tommyds/tommyarrayblkof.c.gcov.html
+++ b/cov/tommyds/tommyarrayblkof.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -92,48 +92,48 @@
30 : /******************************************************************************/
31 : /* array */
32 :
- 33 249 : void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size)
+ 33 257 : void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size)
34 : {
- 35 249 : tommy_array_init(&array->block);
+ 35 257 : tommy_array_init(&array->block);
36 :
- 37 249 : array->element_size = element_size;
- 38 249 : array->count = 0;
- 39 249 : }
+ 37 257 : array->element_size = element_size;
+ 38 257 : array->count = 0;
+ 39 257 : }
40 :
- 41 227 : void tommy_arrayblkof_done(tommy_arrayblkof* array)
+ 41 235 : void tommy_arrayblkof_done(tommy_arrayblkof* array)
42 : {
43 : tommy_count_t i;
44 :
- 45 723 : for (i = 0; i < tommy_array_size(&array->block); ++i)
- 46 496 : tommy_free(tommy_array_get(&array->block, i));
+ 45 743 : for (i = 0; i < tommy_array_size(&array->block); ++i)
+ 46 508 : tommy_free(tommy_array_get(&array->block, i));
47 :
- 48 227 : tommy_array_done(&array->block);
- 49 227 : }
+ 48 235 : tommy_array_done(&array->block);
+ 49 235 : }
50 :
- 51 1609741 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count)
+ 51 1640038 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count)
52 : {
53 : tommy_count_t block_max;
54 : tommy_count_t block_mac;
55 :
- 56 1609741 : if (array->count >= count)
- 57 1700701 : return;
- 58 1518781 : array->count = count;
+ 56 1640038 : if (array->count >= count)
+ 57 1739774 : return;
+ 58 1540302 : array->count = count;
59 :
- 60 1518781 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE;
- 61 1518781 : block_mac = tommy_array_size(&array->block);
+ 60 1540302 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE;
+ 61 1540302 : block_mac = tommy_array_size(&array->block);
62 :
- 63 1518781 : if (block_mac < block_max) {
+ 63 1540302 : if (block_mac < block_max) {
64 : /* grow the block array */
- 65 524 : tommy_array_grow(&array->block, block_max);
+ 65 537 : tommy_array_grow(&array->block, block_max);
66 :
67 : /* allocate new blocks */
- 68 1572 : while (block_mac < block_max) {
- 69 524 : void** ptr = tommy_cast(void**, tommy_calloc(TOMMY_ARRAYBLKOF_SIZE, array->element_size));
+ 68 1611 : while (block_mac < block_max) {
+ 69 537 : void** ptr = tommy_cast(void**, tommy_calloc(TOMMY_ARRAYBLKOF_SIZE, array->element_size));
70 :
71 : /* set the new block */
- 72 524 : tommy_array_set(&array->block, block_mac, ptr);
+ 72 537 : tommy_array_set(&array->block, block_mac, ptr);
73 :
- 74 524 : ++block_mac;
+ 74 537 : ++block_mac;
75 : }
76 : }
77 : }
diff --git a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html
index 5a904630..52261451 100644
--- a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html
+++ b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_arrayblkof_ref |
- 11688426 |
+ 6481666 |
| tommy_arrayblkof_size |
- 10571361 |
+ 5104110 |
diff --git a/cov/tommyds/tommyarrayblkof.h.func.html b/cov/tommyds/tommyarrayblkof.h.func.html
index aab7c7c9..75b07f3a 100644
--- a/cov/tommyds/tommyarrayblkof.h.func.html
+++ b/cov/tommyds/tommyarrayblkof.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_arrayblkof_ref |
- 11688426 |
+ 6481666 |
| tommy_arrayblkof_size |
- 10571361 |
+ 5104110 |
diff --git a/cov/tommyds/tommyarrayblkof.h.gcov.html b/cov/tommyds/tommyarrayblkof.h.gcov.html
index 41d4c08a..a9b2c14e 100644
--- a/cov/tommyds/tommyarrayblkof.h.gcov.html
+++ b/cov/tommyds/tommyarrayblkof.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -148,23 +148,23 @@
86 : * You must be sure that space for this position is already
87 : * allocated calling tommy_arrayblkof_grow().
88 : */
- 89 11688426 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
+ 89 6481666 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
90 : {
91 : unsigned char* base;
92 :
- 93 11688426 : assert(pos < array->count);
+ 93 6481666 : assert(pos < array->count);
94 :
- 95 11688426 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE));
+ 95 6481666 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE));
96 :
- 97 11693987 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size;
+ 97 6481666 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size;
98 : }
99 :
100 : /**
101 : * Gets the initialized size of the array.
102 : */
- 103 10571361 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
+ 103 5104110 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
104 : {
- 105 10571361 : return array->count;
+ 105 5104110 : return array->count;
106 : }
107 :
108 : /**
diff --git a/cov/tommyds/tommychain.h.func-sort-c.html b/cov/tommyds/tommychain.h.func-sort-c.html
index 9f911f5f..ddbb6bb4 100644
--- a/cov/tommyds/tommychain.h.func-sort-c.html
+++ b/cov/tommyds/tommychain.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| tommy_chain_splice |
- 4073661 |
+ 4261933 |
| tommy_chain_merge_degenerated |
- 1153954 |
+ 1203475 |
| tommy_chain_concat |
- 1147870 |
+ 1197191 |
| tommy_chain_merge |
- 427121 |
+ 446438 |
| tommy_chain_mergesort |
- 1473 |
+ 1558 |
diff --git a/cov/tommyds/tommychain.h.func.html b/cov/tommyds/tommychain.h.func.html
index 5ac1a9e6..2298e9b8 100644
--- a/cov/tommyds/tommychain.h.func.html
+++ b/cov/tommyds/tommychain.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| tommy_chain_concat |
- 1147870 |
+ 1197191 |
| tommy_chain_merge |
- 427121 |
+ 446438 |
| tommy_chain_merge_degenerated |
- 1153954 |
+ 1203475 |
| tommy_chain_mergesort |
- 1473 |
+ 1558 |
| tommy_chain_splice |
- 4073661 |
+ 4261933 |
diff --git a/cov/tommyds/tommychain.h.gcov.html b/cov/tommyds/tommychain.h.gcov.html
index 8ed60019..a9d47b12 100644
--- a/cov/tommyds/tommychain.h.gcov.html
+++ b/cov/tommyds/tommychain.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -119,83 +119,83 @@
57 : /**
58 : * Splices a chain in the middle of another chain.
59 : */
- 60 4073661 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail)
+ 60 4261933 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail)
61 : {
62 : /* set the prev list */
- 63 4073661 : first_after->prev = second_tail;
- 64 4073661 : second_head->prev = first_before;
+ 63 4261933 : first_after->prev = second_tail;
+ 64 4261933 : second_head->prev = first_before;
65 :
66 : /* set the next list */
- 67 4073661 : first_before->next = second_head;
- 68 4073661 : second_tail->next = first_after;
- 69 4073661 : }
+ 67 4261933 : first_before->next = second_head;
+ 68 4261933 : second_tail->next = first_after;
+ 69 4261933 : }
70 :
71 : /**
72 : * Concats two chains.
73 : */
- 74 1147870 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head)
+ 74 1197191 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head)
75 : {
76 : /* set the prev list */
- 77 1147870 : second_head->prev = first_tail;
+ 77 1197191 : second_head->prev = first_tail;
78 :
79 : /* set the next list */
- 80 1147870 : first_tail->next = second_head;
- 81 1147870 : }
+ 80 1197191 : first_tail->next = second_head;
+ 81 1197191 : }
82 :
83 : /**
84 : * Merges two chains.
85 : */
- 86 427121 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
+ 86 446438 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
87 : {
- 88 427121 : tommy_node* first_i = first->head;
- 89 427121 : tommy_node* second_i = second->head;
+ 88 446438 : tommy_node* first_i = first->head;
+ 89 446438 : tommy_node* second_i = second->head;
90 :
91 : /* merge */
92 : while (1) {
- 93 8866117 : if (cmp(first_i->data, second_i->data) > 0) {
- 94 4284467 : tommy_node* next = second_i->next;
- 95 4284467 : if (first_i == first->head) {
- 96 210806 : tommy_chain_concat(second_i, first_i);
- 97 210806 : first->head = second_i;
+ 93 9274986 : if (cmp(first_i->data, second_i->data) > 0) {
+ 94 4482275 : tommy_node* next = second_i->next;
+ 95 4482275 : if (first_i == first->head) {
+ 96 220342 : tommy_chain_concat(second_i, first_i);
+ 97 220342 : first->head = second_i;
98 : } else {
- 99 4073661 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i);
+ 99 4261933 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i);
100 : }
- 101 4284467 : if (second_i == second->tail)
- 102 216890 : break;
- 103 4067577 : second_i = next;
+ 101 4482275 : if (second_i == second->tail)
+ 102 226626 : break;
+ 103 4255649 : second_i = next;
104 : } else {
- 105 4581650 : if (first_i == first->tail) {
- 106 210231 : tommy_chain_concat(first_i, second_i);
- 107 210231 : first->tail = second->tail;
- 108 210231 : break;
+ 105 4792711 : if (first_i == first->tail) {
+ 106 219812 : tommy_chain_concat(first_i, second_i);
+ 107 219812 : first->tail = second->tail;
+ 108 219812 : break;
109 : }
- 110 4371419 : first_i = first_i->next;
+ 110 4572899 : first_i = first_i->next;
111 : }
- 112 8438996 : }
- 113 427121 : }
+ 112 8828548 : }
+ 113 446438 : }
114 :
115 : /**
116 : * Merges two chains managing special degenerated cases.
117 : * It's funtionally equivalent at tommy_chain_merge() but faster with already ordered chains.
118 : */
- 119 1153954 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
+ 119 1203475 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
120 : {
121 : /* identify the condition first <= second */
- 122 1153954 : if (cmp(first->tail->data, second->head->data) <= 0) {
- 123 422991 : tommy_chain_concat(first->tail, second->head);
- 124 422991 : first->tail = second->tail;
- 125 422991 : return;
+ 122 1203475 : if (cmp(first->tail->data, second->head->data) <= 0) {
+ 123 439434 : tommy_chain_concat(first->tail, second->head);
+ 124 439434 : first->tail = second->tail;
+ 125 439434 : return;
126 : }
127 :
128 : /* identify the condition second < first */
129 : /* here we must be strict on comparison to keep the sort stable */
- 130 730963 : if (cmp(second->tail->data, first->head->data) < 0) {
- 131 303842 : tommy_chain_concat(second->tail, first->head);
- 132 303842 : first->head = second->head;
- 133 303842 : return;
+ 130 764041 : if (cmp(second->tail->data, first->head->data) < 0) {
+ 131 317603 : tommy_chain_concat(second->tail, first->head);
+ 132 317603 : first->head = second->head;
+ 133 317603 : return;
134 : }
135 :
- 136 427121 : tommy_chain_merge(first, second, cmp);
+ 136 446438 : tommy_chain_merge(first, second, cmp);
137 : }
138 :
139 : /**
@@ -215,7 +215,7 @@
153 : * Linux Kernel lib/list_sort.c
154 : * http://lxr.linux.no/#linux+v2.6.36/lib/list_sort.c
155 : */
- 156 1473 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp)
+ 156 1558 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp)
157 : {
158 : /*
159 : * Bit buckets of chains.
@@ -230,57 +230,57 @@
168 : * It's used to know which bucket is empty of full.
169 : */
170 : tommy_count_t counter;
- 171 1473 : tommy_node* node = chain->head;
- 172 1473 : tommy_node* tail = chain->tail;
+ 171 1558 : tommy_node* node = chain->head;
+ 172 1558 : tommy_node* tail = chain->tail;
173 : tommy_count_t mask;
174 : tommy_count_t i;
175 :
- 176 1473 : counter = 0;
+ 176 1558 : counter = 0;
177 : while (1) {
178 : tommy_node* next;
179 : tommy_chain* last;
180 :
181 : /* carry bit to add */
- 182 1155427 : last = &bit[TOMMY_CHAIN_BIT_MAX];
- 183 1155427 : bit[TOMMY_CHAIN_BIT_MAX].head = node;
- 184 1155427 : bit[TOMMY_CHAIN_BIT_MAX].tail = node;
- 185 1155427 : next = node->next;
+ 182 1205033 : last = &bit[TOMMY_CHAIN_BIT_MAX];
+ 183 1205033 : bit[TOMMY_CHAIN_BIT_MAX].head = node;
+ 184 1205033 : bit[TOMMY_CHAIN_BIT_MAX].tail = node;
+ 185 1205033 : next = node->next;
186 :
187 : /* add the bit, propagating the carry */
- 188 1155427 : i = 0;
- 189 1155427 : mask = counter;
- 190 3459506 : while ((mask & 1) != 0) {
- 191 1148652 : tommy_chain_merge_degenerated(&bit[i], last, cmp);
- 192 1148652 : mask >>= 1;
- 193 1148652 : last = &bit[i];
- 194 1148652 : ++i;
+ 188 1205033 : i = 0;
+ 189 1205033 : mask = counter;
+ 190 3607881 : while ((mask & 1) != 0) {
+ 191 1197815 : tommy_chain_merge_degenerated(&bit[i], last, cmp);
+ 192 1197815 : mask >>= 1;
+ 193 1197815 : last = &bit[i];
+ 194 1197815 : ++i;
195 : }
196 :
197 : /* copy the carry in the first empty bit */
- 198 1155427 : bit[i] = *last;
+ 198 1205033 : bit[i] = *last;
199 :
200 : /* add the carry in the counter */
- 201 1155427 : ++counter;
+ 201 1205033 : ++counter;
202 :
- 203 1155427 : if (node == tail)
- 204 1473 : break;
- 205 1153954 : node = next;
- 206 1153954 : }
+ 203 1205033 : if (node == tail)
+ 204 1558 : break;
+ 205 1203475 : node = next;
+ 206 1203475 : }
207 :
208 : /* merge the buckets */
- 209 1473 : i = tommy_ctz_u32(counter);
- 210 1473 : mask = counter >> i;
- 211 10792 : while (mask != 1) {
- 212 7846 : mask >>= 1;
- 213 7846 : if (mask & 1)
- 214 5302 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp);
+ 209 1558 : i = tommy_ctz_u32(counter);
+ 210 1558 : mask = counter >> i;
+ 211 11511 : while (mask != 1) {
+ 212 8395 : mask >>= 1;
+ 213 8395 : if (mask & 1)
+ 214 5660 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp);
215 : else
- 216 2544 : bit[i + 1] = bit[i];
- 217 7846 : ++i;
+ 216 2735 : bit[i + 1] = bit[i];
+ 217 8395 : ++i;
218 : }
219 :
- 220 1473 : *chain = bit[i];
- 221 1473 : }
+ 220 1558 : *chain = bit[i];
+ 221 1558 : }
222 :
223 : #endif
224 :
diff --git a/cov/tommyds/tommyhash.c.func-sort-c.html b/cov/tommyds/tommyhash.c.func-sort-c.html
index 9466aeab..7a44421b 100644
--- a/cov/tommyds/tommyhash.c.func-sort-c.html
+++ b/cov/tommyds/tommyhash.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_le_uint32_read |
- 11236438 |
+ 11379991 |
| tommy_hash_u32 |
- 3932841 |
+ 3984897 |
| tommy_hash_u64 |
diff --git a/cov/tommyds/tommyhash.c.func.html b/cov/tommyds/tommyhash.c.func.html
index 311a42c9..6e925c33 100644
--- a/cov/tommyds/tommyhash.c.func.html
+++ b/cov/tommyds/tommyhash.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| tommy_hash_u32 |
- 3932841 |
+ 3984897 |
| tommy_hash_u64 |
@@ -69,7 +69,7 @@
| tommy_le_uint32_read |
- 11236438 |
+ 11379991 |
diff --git a/cov/tommyds/tommyhash.c.gcov.html b/cov/tommyds/tommyhash.c.gcov.html
index 30b59be8..e0683e1f 100644
--- a/cov/tommyds/tommyhash.c.gcov.html
+++ b/cov/tommyds/tommyhash.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -92,12 +92,12 @@
30 : /******************************************************************************/
31 : /* hash */
32 :
- 33 11236438 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr)
+ 33 11379991 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr)
34 : {
35 : /* allow unaligned read on Intel x86 and x86_64 platforms */
36 : #if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__x86_64__) || defined(_M_X64)
37 : /* defines from http://predef.sourceforge.net/ */
- 38 11236438 : return *(const tommy_uint32_t*)ptr;
+ 38 11379991 : return *(const tommy_uint32_t*)ptr;
39 : #else
40 : const unsigned char* ptr8 = tommy_cast(const unsigned char*, ptr);
41 : return ptr8[0] + ((tommy_uint32_t)ptr8[1] << 8) + ((tommy_uint32_t)ptr8[2] << 16) + ((tommy_uint32_t)ptr8[3] << 24);
@@ -128,53 +128,53 @@
66 : c ^= b; c -= tommy_rot(b, 24); \
67 : } while (0)
68 :
- 69 3932841 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len)
+ 69 3984897 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len)
70 : {
- 71 3932841 : const unsigned char* key = tommy_cast(const unsigned char*, void_key);
+ 71 3984897 : const unsigned char* key = tommy_cast(const unsigned char*, void_key);
72 : tommy_uint32_t a, b, c;
73 :
- 74 3932841 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val;
+ 74 3984897 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val;
75 :
- 76 9922648 : while (key_len > 12) {
- 77 2056966 : a += tommy_le_uint32_read(key + 0);
- 78 2056966 : b += tommy_le_uint32_read(key + 4);
- 79 2056966 : c += tommy_le_uint32_read(key + 8);
+ 76 10052462 : while (key_len > 12) {
+ 77 2082668 : a += tommy_le_uint32_read(key + 0);
+ 78 2082668 : b += tommy_le_uint32_read(key + 4);
+ 79 2082668 : c += tommy_le_uint32_read(key + 8);
80 :
- 81 2056966 : tommy_mix(a, b, c);
+ 81 2082668 : tommy_mix(a, b, c);
82 :
- 83 2056966 : key_len -= 12;
- 84 2056966 : key += 12;
+ 83 2082668 : key_len -= 12;
+ 84 2082668 : key += 12;
85 : }
86 :
- 87 3932841 : switch (key_len) {
+ 87 3984897 : switch (key_len) {
88 : case 0 :
89 1 : return c; /* used only when called with a zero length */
90 : case 12 :
- 91 201770 : c += tommy_le_uint32_read(key + 8);
- 92 201770 : b += tommy_le_uint32_read(key + 4);
- 93 201770 : a += tommy_le_uint32_read(key + 0);
- 94 201770 : break;
- 95 210915 : case 11 : c += ((tommy_uint32_t)key[10]) << 16;
- 96 620733 : case 10 : c += ((tommy_uint32_t)key[9]) << 8;
- 97 1027724 : case 9 : c += key[8];
+ 91 204266 : c += tommy_le_uint32_read(key + 8);
+ 92 204266 : b += tommy_le_uint32_read(key + 4);
+ 93 204266 : a += tommy_le_uint32_read(key + 0);
+ 94 204266 : break;
+ 95 213540 : case 11 : c += ((tommy_uint32_t)key[10]) << 16;
+ 96 628617 : case 10 : c += ((tommy_uint32_t)key[9]) << 8;
+ 97 1040835 : case 9 : c += key[8];
98 : case 8 :
- 99 1425951 : b += tommy_le_uint32_read(key + 4);
- 100 1425951 : a += tommy_le_uint32_read(key + 0);
- 101 1425951 : break;
- 102 400019 : case 7 : b += ((tommy_uint32_t)key[6]) << 16;
- 103 787136 : case 6 : b += ((tommy_uint32_t)key[5]) << 8;
- 104 1189288 : case 5 : b += key[4];
+ 99 1444224 : b += tommy_le_uint32_read(key + 4);
+ 100 1444224 : a += tommy_le_uint32_read(key + 0);
+ 101 1444224 : break;
+ 102 405262 : case 7 : b += ((tommy_uint32_t)key[6]) << 16;
+ 103 797887 : case 6 : b += ((tommy_uint32_t)key[5]) << 8;
+ 104 1206407 : case 5 : b += key[4];
105 : case 4 :
- 106 1608279 : a += tommy_le_uint32_read(key + 0);
- 107 1608279 : break;
- 108 291874 : case 3 : a += ((tommy_uint32_t)key[2]) << 16;
- 109 493291 : case 2 : a += ((tommy_uint32_t)key[1]) << 8;
- 110 696840 : case 1 : a += key[0];
+ 106 1630692 : a += tommy_le_uint32_read(key + 0);
+ 107 1630692 : break;
+ 108 295633 : case 3 : a += ((tommy_uint32_t)key[2]) << 16;
+ 109 499608 : case 2 : a += ((tommy_uint32_t)key[1]) << 8;
+ 110 705714 : case 1 : a += key[0];
111 : }
112 :
- 113 3932840 : tommy_final(a, b, c);
+ 113 3984896 : tommy_final(a, b, c);
114 :
- 115 3932840 : return c;
+ 115 3984896 : return c;
116 : }
117 :
118 19 : tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len)
diff --git a/cov/tommyds/tommyhash.h.func-sort-c.html b/cov/tommyds/tommyhash.h.func-sort-c.html
index bd9b8354..45a1fc87 100644
--- a/cov/tommyds/tommyhash.h.func-sort-c.html
+++ b/cov/tommyds/tommyhash.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_inthash_u32 |
- 18417414 |
+ 18594807 |
| tommy_inthash_u64 |
- 4822298 |
+ 4924816 |
diff --git a/cov/tommyds/tommyhash.h.func.html b/cov/tommyds/tommyhash.h.func.html
index d1761086..8e649746 100644
--- a/cov/tommyds/tommyhash.h.func.html
+++ b/cov/tommyds/tommyhash.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_inthash_u32 |
- 18417414 |
+ 18594807 |
| tommy_inthash_u64 |
- 4822298 |
+ 4924816 |
diff --git a/cov/tommyds/tommyhash.h.gcov.html b/cov/tommyds/tommyhash.h.gcov.html
index 33130e85..ef81f711 100644
--- a/cov/tommyds/tommyhash.h.gcov.html
+++ b/cov/tommyds/tommyhash.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -139,17 +139,17 @@
77 : * Implementation of the Robert Jenkins "4-byte Integer Hashing",
78 : * from http://burtleburtle.net/bob/hash/integer.html
79 : */
- 80 18417414 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key)
+ 80 18594807 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key)
81 : {
- 82 18417414 : key -= key << 6;
- 83 18417414 : key ^= key >> 17;
- 84 18417414 : key -= key << 9;
- 85 18417414 : key ^= key << 4;
- 86 18417414 : key -= key << 3;
- 87 18417414 : key ^= key << 10;
- 88 18417414 : key ^= key >> 15;
+ 82 18594807 : key -= key << 6;
+ 83 18594807 : key ^= key >> 17;
+ 84 18594807 : key -= key << 9;
+ 85 18594807 : key ^= key << 4;
+ 86 18594807 : key -= key << 3;
+ 87 18594807 : key ^= key << 10;
+ 88 18594807 : key ^= key >> 15;
89 :
- 90 18417414 : return key;
+ 90 18594807 : return key;
91 : }
92 :
93 : /**
@@ -157,17 +157,17 @@
95 : * Implementation of the Thomas Wang "Integer Hash Function",
96 : * from http://www.cris.com/~Ttwang/tech/inthash.htm
97 : */
- 98 4822298 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key)
+ 98 4924816 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key)
99 : {
- 100 4822298 : key = ~key + (key << 21);
- 101 4822298 : key = key ^ (key >> 24);
- 102 4822298 : key = key + (key << 3) + (key << 8);
- 103 4822298 : key = key ^ (key >> 14);
- 104 4822298 : key = key + (key << 2) + (key << 4);
- 105 4822298 : key = key ^ (key >> 28);
- 106 4822298 : key = key + (key << 31);
+ 100 4924816 : key = ~key + (key << 21);
+ 101 4924816 : key = key ^ (key >> 24);
+ 102 4924816 : key = key + (key << 3) + (key << 8);
+ 103 4924816 : key = key ^ (key >> 14);
+ 104 4924816 : key = key + (key << 2) + (key << 4);
+ 105 4924816 : key = key ^ (key >> 28);
+ 106 4924816 : key = key + (key << 31);
107 :
- 108 4822298 : return key;
+ 108 4924816 : return key;
109 : }
110 :
111 : #endif
diff --git a/cov/tommyds/tommyhashdyn.c.func-sort-c.html b/cov/tommyds/tommyhashdyn.c.func-sort-c.html
index 13e53317..cd0ec00e 100644
--- a/cov/tommyds/tommyhashdyn.c.func-sort-c.html
+++ b/cov/tommyds/tommyhashdyn.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,31 +61,31 @@
| hashdyn_grow_step |
- 12860296 |
+ 13012162 |
| tommy_hashdyn_insert |
- 12860296 |
+ 13012162 |
| hashdyn_shrink_step |
- 284348 |
+ 299207 |
| tommy_hashdyn_remove_existing |
- 284220 |
+ 299079 |
| tommy_hashdyn_resize |
- 39860 |
+ 40383 |
| tommy_hashdyn_init |
- 8133 |
+ 8397 |
| tommy_hashdyn_done |
- 7437 |
+ 7701 |
| tommy_hashdyn_remove |
@@ -93,7 +93,7 @@
| tommy_hashdyn_foreach |
- 230 |
+ 238 |
| tommy_hashdyn_foreach_arg |
diff --git a/cov/tommyds/tommyhashdyn.c.func.html b/cov/tommyds/tommyhashdyn.c.func.html
index 190f8d85..d3cc0bca 100644
--- a/cov/tommyds/tommyhashdyn.c.func.html
+++ b/cov/tommyds/tommyhashdyn.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| hashdyn_grow_step |
- 12860296 |
+ 13012162 |
| hashdyn_shrink_step |
- 284348 |
+ 299207 |
| tommy_hashdyn_done |
- 7437 |
+ 7701 |
| tommy_hashdyn_foreach |
- 230 |
+ 238 |
| tommy_hashdyn_foreach_arg |
@@ -81,11 +81,11 @@
| tommy_hashdyn_init |
- 8133 |
+ 8397 |
| tommy_hashdyn_insert |
- 12860296 |
+ 13012162 |
| tommy_hashdyn_memory_usage |
@@ -97,11 +97,11 @@
| tommy_hashdyn_remove_existing |
- 284220 |
+ 299079 |
| tommy_hashdyn_resize |
- 39860 |
+ 40383 |
diff --git a/cov/tommyds/tommyhashdyn.c.gcov.html b/cov/tommyds/tommyhashdyn.c.gcov.html
index b140fbee..6e43758a 100644
--- a/cov/tommyds/tommyhashdyn.c.gcov.html
+++ b/cov/tommyds/tommyhashdyn.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -93,26 +93,26 @@
31 : /******************************************************************************/
32 : /* hashdyn */
33 :
- 34 8133 : void tommy_hashdyn_init(tommy_hashdyn* hashdyn)
+ 34 8397 : void tommy_hashdyn_init(tommy_hashdyn* hashdyn)
35 : {
36 : /* fixed initial size */
- 37 8133 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT;
- 38 8133 : hashdyn->bucket_max = 1 << hashdyn->bucket_bit;
- 39 8133 : hashdyn->bucket_mask = hashdyn->bucket_max - 1;
- 40 8133 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*)));
+ 37 8397 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT;
+ 38 8397 : hashdyn->bucket_max = 1 << hashdyn->bucket_bit;
+ 39 8397 : hashdyn->bucket_mask = hashdyn->bucket_max - 1;
+ 40 8397 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*)));
41 :
- 42 8133 : hashdyn->count = 0;
- 43 8133 : }
+ 42 8397 : hashdyn->count = 0;
+ 43 8397 : }
44 :
- 45 7437 : void tommy_hashdyn_done(tommy_hashdyn* hashdyn)
+ 45 7701 : void tommy_hashdyn_done(tommy_hashdyn* hashdyn)
46 : {
- 47 7437 : tommy_free(hashdyn->bucket);
- 48 7437 : }
+ 47 7701 : tommy_free(hashdyn->bucket);
+ 48 7701 : }
49 :
50 : /**
51 : * Resize the bucket vector.
52 : */
- 53 39860 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit)
+ 53 40383 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit)
54 : {
55 : tommy_count_t bucket_bit;
56 : tommy_count_t bucket_max;
@@ -120,38 +120,38 @@
58 : tommy_count_t new_bucket_mask;
59 : tommy_hashdyn_node** new_bucket;
60 :
- 61 39860 : bucket_bit = hashdyn->bucket_bit;
- 62 39860 : bucket_max = hashdyn->bucket_max;
+ 61 40383 : bucket_bit = hashdyn->bucket_bit;
+ 62 40383 : bucket_max = hashdyn->bucket_max;
63 :
- 64 39860 : new_bucket_max = 1 << new_bucket_bit;
- 65 39860 : new_bucket_mask = new_bucket_max - 1;
+ 64 40383 : new_bucket_max = 1 << new_bucket_bit;
+ 65 40383 : new_bucket_mask = new_bucket_max - 1;
66 :
67 : /* allocate the new vector using malloc() and not calloc() */
68 : /* because data is fully initialized in the update process */
- 69 39860 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*)));
+ 69 40383 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*)));
70 :
71 : /* reinsert all the elements */
- 72 39860 : if (new_bucket_bit > bucket_bit) {
+ 72 40383 : if (new_bucket_bit > bucket_bit) {
73 : tommy_count_t i;
74 :
75 : /* grow */
- 76 31390627 : for (i = 0; i < bucket_max; ++i) {
+ 76 31674382 : for (i = 0; i < bucket_max; ++i) {
77 : tommy_hashdyn_node* j;
78 :
79 : /* setup the new two buckets */
- 80 31350816 : new_bucket[i] = 0;
- 81 31350816 : new_bucket[i + bucket_max] = 0;
+ 80 31634048 : new_bucket[i] = 0;
+ 81 31634048 : new_bucket[i + bucket_max] = 0;
82 :
83 : /* reinsert the bucket */
- 84 31350816 : j = hashdyn->bucket[i];
- 85 78377040 : while (j) {
- 86 15675408 : tommy_hashdyn_node* j_next = j->next;
- 87 15675408 : tommy_count_t pos = j->key & new_bucket_mask;
- 88 15675408 : if (new_bucket[pos])
- 89 1860861 : tommy_list_insert_tail_not_empty(new_bucket[pos], j);
+ 84 31634048 : j = hashdyn->bucket[i];
+ 85 79085120 : while (j) {
+ 86 15817024 : tommy_hashdyn_node* j_next = j->next;
+ 87 15817024 : tommy_count_t pos = j->key & new_bucket_mask;
+ 88 15817024 : if (new_bucket[pos])
+ 89 1907725 : tommy_list_insert_tail_not_empty(new_bucket[pos], j);
90 : else
- 91 13814547 : tommy_list_insert_first(&new_bucket[pos], j);
- 92 15675408 : j = j_next;
+ 91 13909299 : tommy_list_insert_first(&new_bucket[pos], j);
+ 92 15817024 : j = j_next;
93 : }
94 : }
95 : } else {
@@ -167,59 +167,59 @@
105 : }
106 : }
107 :
- 108 39860 : tommy_free(hashdyn->bucket);
+ 108 40383 : tommy_free(hashdyn->bucket);
109 :
110 : /* setup */
- 111 39860 : hashdyn->bucket_bit = new_bucket_bit;
- 112 39860 : hashdyn->bucket_max = new_bucket_max;
- 113 39860 : hashdyn->bucket_mask = new_bucket_mask;
- 114 39860 : hashdyn->bucket = new_bucket;
- 115 39860 : }
+ 111 40383 : hashdyn->bucket_bit = new_bucket_bit;
+ 112 40383 : hashdyn->bucket_max = new_bucket_max;
+ 113 40383 : hashdyn->bucket_mask = new_bucket_mask;
+ 114 40383 : hashdyn->bucket = new_bucket;
+ 115 40383 : }
116 :
117 : /**
118 : * Grow.
119 : */
- 120 12860296 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn)
+ 120 13012162 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn)
121 : {
122 : /* grow if more than 50% full */
- 123 12860296 : if (hashdyn->count >= hashdyn->bucket_max / 2)
- 124 39811 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1);
- 125 12860296 : }
+ 123 13012162 : if (hashdyn->count >= hashdyn->bucket_max / 2)
+ 124 40334 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1);
+ 125 13012162 : }
126 :
127 : /**
128 : * Shrink.
129 : */
- 130 284348 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
+ 130 299207 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
131 : {
132 : /* shrink if less than 12.5% full */
- 133 284348 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT)
+ 133 299207 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT)
134 49 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1);
- 135 284348 : }
+ 135 299207 : }
136 :
- 137 12860296 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
+ 137 13012162 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
138 : {
- 139 12860296 : tommy_count_t pos = hash & hashdyn->bucket_mask;
+ 139 13012162 : tommy_count_t pos = hash & hashdyn->bucket_mask;
140 :
- 141 12860296 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
+ 141 13012162 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
142 :
- 143 12860296 : node->key = hash;
+ 143 13012162 : node->key = hash;
144 :
- 145 12860296 : ++hashdyn->count;
+ 145 13012162 : ++hashdyn->count;
146 :
- 147 12860296 : hashdyn_grow_step(hashdyn);
- 148 12860296 : }
+ 147 13012162 : hashdyn_grow_step(hashdyn);
+ 148 13012162 : }
149 :
- 150 284220 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
+ 150 299079 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
151 : {
- 152 284220 : tommy_count_t pos = node->key & hashdyn->bucket_mask;
+ 152 299079 : tommy_count_t pos = node->key & hashdyn->bucket_mask;
153 :
- 154 284220 : tommy_list_remove_existing(&hashdyn->bucket[pos], node);
+ 154 299079 : tommy_list_remove_existing(&hashdyn->bucket[pos], node);
155 :
- 156 284220 : --hashdyn->count;
+ 156 299079 : --hashdyn->count;
157 :
- 158 284220 : hashdyn_shrink_step(hashdyn);
+ 158 299079 : hashdyn_shrink_step(hashdyn);
159 :
- 160 284220 : return node->data;
+ 160 299079 : return node->data;
161 : }
162 :
163 256 : void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
@@ -244,22 +244,22 @@
182 128 : return 0;
183 : }
184 :
- 185 230 : void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func)
+ 185 238 : void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func)
186 : {
- 187 230 : tommy_count_t bucket_max = hashdyn->bucket_max;
- 188 230 : tommy_hashdyn_node** bucket = hashdyn->bucket;
+ 187 238 : tommy_count_t bucket_max = hashdyn->bucket_max;
+ 188 238 : tommy_hashdyn_node** bucket = hashdyn->bucket;
189 : tommy_count_t pos;
190 :
- 191 5812246 : for (pos = 0; pos < bucket_max; ++pos) {
- 192 5812016 : tommy_hashdyn_node* node = bucket[pos];
+ 191 5812382 : for (pos = 0; pos < bucket_max; ++pos) {
+ 192 5812144 : tommy_hashdyn_node* node = bucket[pos];
193 :
- 194 13483818 : while (node) {
- 195 1859786 : void* data = node->data;
- 196 1859786 : node = node->next;
- 197 1859786 : func(data);
+ 194 13484803 : while (node) {
+ 195 1860515 : void* data = node->data;
+ 196 1860515 : node = node->next;
+ 197 1860515 : func(data);
198 : }
199 : }
- 200 230 : }
+ 200 238 : }
201 :
202 1 : void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg)
203 : {
diff --git a/cov/tommyds/tommyhashdyn.h.func-sort-c.html b/cov/tommyds/tommyhashdyn.h.func-sort-c.html
index 524259cb..58911c95 100644
--- a/cov/tommyds/tommyhashdyn.h.func-sort-c.html
+++ b/cov/tommyds/tommyhashdyn.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_hashdyn_bucket |
- 3070554 |
+ 3059036 |
| tommy_hashdyn_search |
- 3070554 |
+ 3059036 |
| tommy_hashdyn_count |
diff --git a/cov/tommyds/tommyhashdyn.h.func.html b/cov/tommyds/tommyhashdyn.h.func.html
index 204c62c7..a87b29ec 100644
--- a/cov/tommyds/tommyhashdyn.h.func.html
+++ b/cov/tommyds/tommyhashdyn.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| tommy_hashdyn_bucket |
- 3070554 |
+ 3059036 |
| tommy_hashdyn_count |
@@ -69,7 +69,7 @@
| tommy_hashdyn_search |
- 3070554 |
+ 3059036 |
diff --git a/cov/tommyds/tommyhashdyn.h.gcov.html b/cov/tommyds/tommyhashdyn.h.gcov.html
index 448c8108..0751c333 100644
--- a/cov/tommyds/tommyhashdyn.h.gcov.html
+++ b/cov/tommyds/tommyhashdyn.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -267,9 +267,9 @@
205 : * \param hash Hash of the element to find.
206 : * \return The head of the bucket, or 0 if empty.
207 : */
- 208 3070554 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash)
+ 208 3059036 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash)
209 : {
- 210 3070554 : return hashdyn->bucket[hash & hashdyn->bucket_mask];
+ 210 3059036 : return hashdyn->bucket[hash & hashdyn->bucket_mask];
211 : }
212 :
213 : /**
@@ -282,17 +282,17 @@
220 : * \param hash Hash of the element to find.
221 : * \return The first element found, or 0 if none.
222 : */
- 223 3070554 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
+ 223 3059036 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
224 : {
- 225 3070554 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash);
+ 225 3059036 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash);
226 :
- 227 6829396 : while (i) {
+ 227 6783670 : while (i) {
228 : /* we first check if the hash matches, as in the same bucket we may have multiples hash values */
- 229 1728517 : if (i->key == hash && cmp(cmp_arg, i->data) == 0)
- 230 1040229 : return i->data;
- 231 688288 : i = i->next;
+ 229 1775604 : if (i->key == hash && cmp(cmp_arg, i->data) == 0)
+ 230 1110006 : return i->data;
+ 231 665598 : i = i->next;
232 : }
- 233 2030325 : return 0;
+ 233 1949030 : return 0;
234 : }
235 :
236 : /**
diff --git a/cov/tommyds/tommylist.c.func-sort-c.html b/cov/tommyds/tommylist.c.func-sort-c.html
index 50240eef..b292b5c8 100644
--- a/cov/tommyds/tommylist.c.func-sort-c.html
+++ b/cov/tommyds/tommylist.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,11 +65,11 @@
| tommy_list_sort |
- 2129 |
+ 2276 |
| tommy_list_set |
- 1473 |
+ 1558 |
diff --git a/cov/tommyds/tommylist.c.func.html b/cov/tommyds/tommylist.c.func.html
index 4a3655e5..f3b2b5cb 100644
--- a/cov/tommyds/tommylist.c.func.html
+++ b/cov/tommyds/tommylist.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,11 +65,11 @@
| tommy_list_set |
- 1473 |
+ 1558 |
| tommy_list_sort |
- 2129 |
+ 2276 |
diff --git a/cov/tommyds/tommylist.c.gcov.html b/cov/tommyds/tommylist.c.gcov.html
index a3fd03cb..200bf008 100644
--- a/cov/tommyds/tommylist.c.gcov.html
+++ b/cov/tommyds/tommylist.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -97,53 +97,53 @@
35 : tommy_node* second_head;
36 :
37 63152 : if (tommy_list_empty(second))
- 38 55942 : return;
+ 38 55862 : return;
39 :
- 40 7210 : if (tommy_list_empty(first)) {
- 41 6347 : *first = *second;
- 42 6347 : return;
+ 40 7290 : if (tommy_list_empty(first)) {
+ 41 6456 : *first = *second;
+ 42 6456 : return;
43 : }
44 :
- 45 863 : first_head = tommy_list_head(first);
- 46 863 : second_head = tommy_list_head(second);
- 47 863 : first_tail = tommy_list_tail(first);
+ 45 834 : first_head = tommy_list_head(first);
+ 46 834 : second_head = tommy_list_head(second);
+ 47 834 : first_tail = tommy_list_tail(first);
48 :
49 : /* set the "circular" prev list */
- 50 863 : first_head->prev = second_head->prev;
- 51 863 : second_head->prev = first_tail;
+ 50 834 : first_head->prev = second_head->prev;
+ 51 834 : second_head->prev = first_tail;
52 :
53 : /* set the "0 terminated" next list */
- 54 863 : first_tail->next = second_head;
+ 54 834 : first_tail->next = second_head;
55 : }
56 :
57 : /** \internal
58 : * Setup a list.
59 : */
- 60 1473 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail)
+ 60 1558 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail)
61 : {
- 62 1473 : head->prev = tail;
- 63 1473 : tail->next = 0;
- 64 1473 : *list = head;
- 65 1473 : }
+ 62 1558 : head->prev = tail;
+ 63 1558 : tail->next = 0;
+ 64 1558 : *list = head;
+ 65 1558 : }
66 :
- 67 2129 : void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp)
+ 67 2276 : void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp)
68 : {
69 : tommy_chain chain;
70 : tommy_node* head;
71 :
- 72 2129 : if (tommy_list_empty(list))
- 73 2785 : return;
+ 72 2276 : if (tommy_list_empty(list))
+ 73 2994 : return;
74 :
- 75 1473 : head = tommy_list_head(list);
+ 75 1558 : head = tommy_list_head(list);
76 :
77 : /* create a chain from the list */
- 78 1473 : chain.head = head;
- 79 1473 : chain.tail = head->prev;
+ 78 1558 : chain.head = head;
+ 79 1558 : chain.tail = head->prev;
80 :
- 81 1473 : tommy_chain_mergesort(&chain, cmp);
+ 81 1558 : tommy_chain_mergesort(&chain, cmp);
82 :
83 : /* restore the list */
- 84 1473 : tommy_list_set(list, chain.head, chain.tail);
+ 84 1558 : tommy_list_set(list, chain.head, chain.tail);
85 : }
86 :
diff --git a/cov/tommyds/tommylist.h.func-sort-c.html b/cov/tommyds/tommylist.h.func-sort-c.html
index 9c8d2d57..5d6d527a 100644
--- a/cov/tommyds/tommylist.h.func-sort-c.html
+++ b/cov/tommyds/tommylist.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,43 +61,43 @@
| tommy_list_head |
- 24488786 |
+ 24857398 |
| tommy_list_insert_first |
- 22741744 |
+ 22927997 |
| tommy_list_insert_tail |
- 17767092 |
+ 18022355 |
| tommy_list_insert_tail_not_empty |
- 10700756 |
+ 10911382 |
| tommy_list_remove_existing |
- 341445 |
+ 359148 |
| tommy_list_empty |
- 74175 |
+ 74540 |
| tommy_list_init |
- 10804 |
+ 11303 |
| tommy_list_foreach |
- 7071 |
+ 7327 |
| tommy_list_tail |
- 864 |
+ 835 |
| tommy_list_count |
- 241 |
+ 249 |
diff --git a/cov/tommyds/tommylist.h.func.html b/cov/tommyds/tommylist.h.func.html
index c10d1292..14b14b56 100644
--- a/cov/tommyds/tommylist.h.func.html
+++ b/cov/tommyds/tommylist.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,43 +61,43 @@
| tommy_list_count |
- 241 |
+ 249 |
| tommy_list_empty |
- 74175 |
+ 74540 |
| tommy_list_foreach |
- 7071 |
+ 7327 |
| tommy_list_head |
- 24488786 |
+ 24857398 |
| tommy_list_init |
- 10804 |
+ 11303 |
| tommy_list_insert_first |
- 22741744 |
+ 22927997 |
| tommy_list_insert_tail |
- 17767092 |
+ 18022355 |
| tommy_list_insert_tail_not_empty |
- 10700756 |
+ 10911382 |
| tommy_list_remove_existing |
- 341445 |
+ 359148 |
| tommy_list_tail |
- 864 |
+ 835 |
diff --git a/cov/tommyds/tommylist.h.gcov.html b/cov/tommyds/tommylist.h.gcov.html
index 34f2c18f..b69a338e 100644
--- a/cov/tommyds/tommylist.h.gcov.html
+++ b/cov/tommyds/tommylist.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -173,32 +173,32 @@
111 : * Initializes the list.
112 : * The list is completely inplace, so it doesn't need to be deinitialized.
113 : */
- 114 10804 : tommy_inline void tommy_list_init(tommy_list* list)
+ 114 11303 : tommy_inline void tommy_list_init(tommy_list* list)
115 : {
- 116 10804 : *list = 0;
- 117 10804 : }
+ 116 11303 : *list = 0;
+ 117 11303 : }
118 :
119 : /**
120 : * Gets the head of the list.
121 : * \return The head node. For empty lists 0 is returned.
122 : */
- 123 24488786 : tommy_inline tommy_node* tommy_list_head(tommy_list* list)
+ 123 24857398 : tommy_inline tommy_node* tommy_list_head(tommy_list* list)
124 : {
- 125 24488786 : return *list;
+ 125 24857398 : return *list;
126 : }
127 :
128 : /**
129 : * Gets the tail of the list.
130 : * \return The tail node. For empty lists 0 is returned.
131 : */
- 132 864 : tommy_inline tommy_node* tommy_list_tail(tommy_list* list)
+ 132 835 : tommy_inline tommy_node* tommy_list_tail(tommy_list* list)
133 : {
- 134 864 : tommy_node* head = tommy_list_head(list);
+ 134 835 : tommy_node* head = tommy_list_head(list);
135 :
- 136 864 : if (!head)
+ 136 835 : if (!head)
137 1 : return 0;
138 :
- 139 863 : return head->prev;
+ 139 834 : return head->prev;
140 : }
141 :
142 : /** \internal
@@ -206,16 +206,16 @@
144 : * \param list The list to initialize.
145 : * \param node The node to insert.
146 : */
- 147 22741744 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node)
+ 147 22927997 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node)
148 : {
149 : /* one element "circular" prev list */
- 150 22741744 : node->prev = node;
+ 150 22927997 : node->prev = node;
151 :
152 : /* one element "0 terminated" next list */
- 153 22741744 : node->next = 0;
+ 153 22927997 : node->next = 0;
154 :
- 155 22741744 : *list = node;
- 156 22741744 : }
+ 155 22927997 : *list = node;
+ 156 22927997 : }
157 :
158 : /** \internal
159 : * Inserts an element at the head of a not empty list.
@@ -243,16 +243,16 @@
181 : * \param head The node at the list head. It cannot be 0.
182 : * \param node The node to insert.
183 : */
- 184 10700756 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node)
+ 184 10911382 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node)
185 : {
186 : /* insert in the "circular" prev list */
- 187 10700756 : node->prev = head->prev;
- 188 10700756 : head->prev = node;
+ 187 10911382 : node->prev = head->prev;
+ 188 10911382 : head->prev = node;
189 :
190 : /* insert in the "0 terminated" next list */
- 191 10700756 : node->next = 0;
- 192 10700756 : node->prev->next = node;
- 193 10700756 : }
+ 191 10911382 : node->next = 0;
+ 192 10911382 : node->prev->next = node;
+ 193 10911382 : }
194 :
195 : /**
196 : * Inserts an element at the head of a list.
@@ -276,17 +276,17 @@
214 : * \param node The node to insert.
215 : * \param data The object containing the node. It's used to set the tommy_node::data field of the node.
216 : */
- 217 17767092 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data)
+ 217 18022355 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data)
218 : {
- 219 17767092 : tommy_node* head = tommy_list_head(list);
+ 219 18022355 : tommy_node* head = tommy_list_head(list);
220 :
- 221 17767092 : if (head)
- 222 8839895 : tommy_list_insert_tail_not_empty(head, node);
+ 221 18022355 : if (head)
+ 222 9003657 : tommy_list_insert_tail_not_empty(head, node);
223 : else
- 224 8927197 : tommy_list_insert_first(list, node);
+ 224 9018698 : tommy_list_insert_first(list, node);
225 :
- 226 17767092 : node->data = data;
- 227 17767092 : }
+ 226 18022355 : node->data = data;
+ 227 18022355 : }
228 :
229 : /** \internal
230 : * Removes an element from the head of a not empty list.
@@ -314,23 +314,23 @@
252 : * \param node The node to remove. The node must be in the list.
253 : * \return The tommy_node::data field of the node removed.
254 : */
- 255 341445 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node)
+ 255 359148 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node)
256 : {
- 257 341445 : tommy_node* head = tommy_list_head(list);
+ 257 359148 : tommy_node* head = tommy_list_head(list);
258 :
259 : /* remove from the "circular" prev list */
- 260 341445 : if (node->next)
- 261 118988 : node->next->prev = node->prev;
+ 260 359148 : if (node->next)
+ 261 122485 : node->next->prev = node->prev;
262 : else
- 263 222457 : head->prev = node->prev; /* the last */
+ 263 236663 : head->prev = node->prev; /* the last */
264 :
265 : /* remove from the "0 terminated" next list */
- 266 341445 : if (head == node)
- 267 241019 : *list = node->next; /* the new head, in case 0 */
+ 266 359148 : if (head == node)
+ 267 252248 : *list = node->next; /* the new head, in case 0 */
268 : else
- 269 100426 : node->prev->next = node->next;
+ 269 106900 : node->prev->next = node->next;
270 :
- 271 341445 : return node->data;
+ 271 359148 : return node->data;
272 : }
273 :
274 : /**
@@ -355,26 +355,26 @@
293 : * Checks if empty.
294 : * \return If the list is empty.
295 : */
- 296 74175 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list)
+ 296 74540 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list)
297 : {
- 298 74175 : return tommy_list_head(list) == 0;
+ 298 74540 : return tommy_list_head(list) == 0;
299 : }
300 :
301 : /**
302 : * Gets the number of elements.
303 : * \note This operation is O(n).
304 : */
- 305 241 : tommy_inline tommy_count_t tommy_list_count(tommy_list* list)
+ 305 249 : tommy_inline tommy_count_t tommy_list_count(tommy_list* list)
306 : {
- 307 241 : tommy_count_t count = 0;
- 308 241 : tommy_node* i = tommy_list_head(list);
+ 307 249 : tommy_count_t count = 0;
+ 308 249 : tommy_node* i = tommy_list_head(list);
309 :
- 310 1923 : while (i) {
- 311 1441 : ++count;
- 312 1441 : i = i->next;
+ 310 1987 : while (i) {
+ 311 1489 : ++count;
+ 312 1489 : i = i->next;
313 : }
314 :
- 315 241 : return count;
+ 315 249 : return count;
316 : }
317 :
318 : /**
@@ -405,16 +405,16 @@
343 : * tommy_list_foreach(&list, free);
344 : * \endcode
345 : */
- 346 7071 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func)
+ 346 7327 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func)
347 : {
- 348 7071 : tommy_node* node = tommy_list_head(list);
+ 348 7327 : tommy_node* node = tommy_list_head(list);
349 :
- 350 3547533 : while (node) {
- 351 3533391 : void* data = node->data;
- 352 3533391 : node = node->next;
- 353 3533391 : func(data);
+ 350 3598724 : while (node) {
+ 351 3584070 : void* data = node->data;
+ 352 3584070 : node = node->next;
+ 353 3584070 : func(data);
354 : }
- 355 7071 : }
+ 355 7327 : }
356 :
357 : /**
358 : * Calls the specified function with an argument for each element in the list.
diff --git a/cov/tommyds/tommytree.c.func-sort-c.html b/cov/tommyds/tommytree.c.func-sort-c.html
index b79d2f99..c432723c 100644
--- a/cov/tommyds/tommytree.c.func-sort-c.html
+++ b/cov/tommyds/tommytree.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,67 +61,67 @@
| tommy_tree_search_node |
- 324348165 |
+ 125457281 |
| tommy_tree_delta |
- 108663041 |
+ 109388905 |
| tommy_tree_balance |
- 101410069 |
+ 102241942 |
| tommy_tree_insert_node |
- 93001793 |
-
-
- | tommy_tree_search_compare |
- 31336465 |
+ 93986144 |
| tommy_tree_foreach_arg_node |
- 25171385 |
+ 25770381 |
- | tommy_tree_rotate_left |
- 7241652 |
+ tommy_tree_search_compare |
+ 11217144 |
| tommy_tree_insert |
- 7215779 |
+ 7315111 |
+
+
+ | tommy_tree_rotate_left |
+ 7135360 |
| tommy_tree_foreach_node |
- 6799230 |
+ 6892468 |
| tommy_tree_remove_node |
- 775421 |
-
-
- | tommy_tree_move_right |
- 183618 |
+ 838361 |
| tommy_tree_rotate_right |
- 168850 |
+ 218129 |
+
+
+ | tommy_tree_move_right |
+ 192710 |
| tommy_tree_remove |
- 78058 |
+ 83634 |
| tommy_tree_foreach_arg |
- 5353 |
+ 5677 |
| tommy_tree_init |
- 2955 |
+ 3051 |
| tommy_tree_foreach |
- 1352 |
+ 1400 |
| tommy_tree_remove_existing |
diff --git a/cov/tommyds/tommytree.c.func.html b/cov/tommyds/tommytree.c.func.html
index c84d6f4c..6d0cebe5 100644
--- a/cov/tommyds/tommytree.c.func.html
+++ b/cov/tommyds/tommytree.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,39 +61,39 @@
| tommy_tree_balance |
- 101410069 |
+ 102241942 |
| tommy_tree_delta |
- 108663041 |
+ 109388905 |
| tommy_tree_foreach |
- 1352 |
+ 1400 |
| tommy_tree_foreach_arg |
- 5353 |
+ 5677 |
| tommy_tree_foreach_arg_node |
- 25171385 |
+ 25770381 |
| tommy_tree_foreach_node |
- 6799230 |
+ 6892468 |
| tommy_tree_init |
- 2955 |
+ 3051 |
| tommy_tree_insert |
- 7215779 |
+ 7315111 |
| tommy_tree_insert_node |
- 93001793 |
+ 93986144 |
| tommy_tree_memory_usage |
@@ -101,11 +101,11 @@
| tommy_tree_move_right |
- 183618 |
+ 192710 |
| tommy_tree_remove |
- 78058 |
+ 83634 |
| tommy_tree_remove_existing |
@@ -113,15 +113,15 @@
| tommy_tree_remove_node |
- 775421 |
+ 838361 |
| tommy_tree_rotate_left |
- 7241652 |
+ 7135360 |
| tommy_tree_rotate_right |
- 168850 |
+ 218129 |
| tommy_tree_search |
@@ -129,11 +129,11 @@
| tommy_tree_search_compare |
- 31336465 |
+ 11217144 |
| tommy_tree_search_node |
- 324348165 |
+ 125457281 |
diff --git a/cov/tommyds/tommytree.c.gcov.html b/cov/tommyds/tommytree.c.gcov.html
index 4658bf45..2035f253 100644
--- a/cov/tommyds/tommytree.c.gcov.html
+++ b/cov/tommyds/tommytree.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,104 +94,104 @@
32 : /******************************************************************************/
33 : /* tree */
34 :
- 35 2955 : void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp)
+ 35 3051 : void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp)
36 : {
- 37 2955 : tree->root = 0;
- 38 2955 : tree->count = 0;
- 39 2955 : tree->cmp = cmp;
- 40 2955 : }
+ 37 3051 : tree->root = 0;
+ 38 3051 : tree->count = 0;
+ 39 3051 : tree->cmp = cmp;
+ 40 3051 : }
41 :
- 42 108663041 : static int tommy_tree_delta(tommy_tree_node* root)
+ 42 109388905 : static int tommy_tree_delta(tommy_tree_node* root)
43 : {
- 44 108663041 : int left_height = root->prev ? root->prev->key : 0;
- 45 108663041 : int right_height = root->next ? root->next->key : 0;
+ 44 109388905 : int left_height = root->prev ? root->prev->key : 0;
+ 45 109388905 : int right_height = root->next ? root->next->key : 0;
46 :
- 47 108663041 : return left_height - right_height;
+ 47 109388905 : return left_height - right_height;
48 : }
49 :
50 : /* AVL tree operations */
51 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*);
52 :
- 53 7241652 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root)
+ 53 7135360 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root)
54 : {
- 55 7241652 : tommy_tree_node* next = root->next;
+ 55 7135360 : tommy_tree_node* next = root->next;
56 :
- 57 7241652 : root->next = next->prev;
+ 57 7135360 : root->next = next->prev;
58 :
- 59 7241652 : next->prev = tommy_tree_balance(root);
+ 59 7135360 : next->prev = tommy_tree_balance(root);
60 :
- 61 7241652 : return tommy_tree_balance(next);
+ 61 7135360 : return tommy_tree_balance(next);
62 : }
63 :
- 64 168850 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root)
+ 64 218129 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root)
65 : {
- 66 168850 : tommy_tree_node* prev = root->prev;
+ 66 218129 : tommy_tree_node* prev = root->prev;
67 :
- 68 168850 : root->prev = prev->next;
+ 68 218129 : root->prev = prev->next;
69 :
- 70 168850 : prev->next = tommy_tree_balance(root);
+ 70 218129 : prev->next = tommy_tree_balance(root);
71 :
- 72 168850 : return tommy_tree_balance(prev);
+ 72 218129 : return tommy_tree_balance(prev);
73 : }
74 :
- 75 183618 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node)
+ 75 192710 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node)
76 : {
- 77 183618 : if (!root)
- 78 77930 : return node;
+ 77 192710 : if (!root)
+ 78 83506 : return node;
79 :
- 80 105688 : root->next = tommy_tree_move_right(root->next, node);
+ 80 109204 : root->next = tommy_tree_move_right(root->next, node);
81 :
- 82 105688 : return tommy_tree_balance(root);
+ 82 109204 : return tommy_tree_balance(root);
83 : }
84 :
- 85 101410069 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
+ 85 102241942 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
86 : {
- 87 101410069 : int delta = tommy_tree_delta(root);
+ 87 102241942 : int delta = tommy_tree_delta(root);
88 :
- 89 101410069 : if (delta < -1) {
- 90 7125675 : if (tommy_tree_delta(root->next) > 0)
- 91 41553 : root->next = tommy_tree_rotate_right(root->next);
- 92 7125675 : return tommy_tree_rotate_left(root);
+ 89 102241942 : if (delta < -1) {
+ 90 6971745 : if (tommy_tree_delta(root->next) > 0)
+ 91 42911 : root->next = tommy_tree_rotate_right(root->next);
+ 92 6971745 : return tommy_tree_rotate_left(root);
93 : }
94 :
- 95 94284394 : if (delta > 1) {
- 96 127297 : if (tommy_tree_delta(root->prev) < 0)
- 97 115977 : root->prev = tommy_tree_rotate_left(root->prev);
- 98 127297 : return tommy_tree_rotate_right(root);
+ 95 95270197 : if (delta > 1) {
+ 96 175218 : if (tommy_tree_delta(root->prev) < 0)
+ 97 163615 : root->prev = tommy_tree_rotate_left(root->prev);
+ 98 175218 : return tommy_tree_rotate_right(root);
99 : }
100 :
101 : /* recompute key */
- 102 94157097 : root->key = 0;
+ 102 95094979 : root->key = 0;
103 :
- 104 94157097 : if (root->prev && root->prev->key > root->key)
- 105 76188949 : root->key = root->prev->key;
+ 104 95094979 : if (root->prev && root->prev->key > root->key)
+ 105 77186914 : root->key = root->prev->key;
106 :
- 107 94157097 : if (root->next && root->next->key > root->key)
- 108 43401597 : root->key = root->next->key;
+ 107 95094979 : if (root->next && root->next->key > root->key)
+ 108 43098001 : root->key = root->next->key;
109 :
110 : /* count itself */
- 111 94157097 : root->key += 1;
+ 111 95094979 : root->key += 1;
112 :
- 113 94157097 : return root;
+ 113 95094979 : return root;
114 : }
115 :
- 116 93001793 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let)
+ 116 93986144 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let)
117 : {
118 : int c;
119 :
- 120 93001793 : if (!root)
- 121 7215778 : return *let;
+ 120 93986144 : if (!root)
+ 121 7315110 : return *let;
122 :
- 123 85786015 : c = cmp((*let)->data, root->data);
+ 123 86671034 : c = cmp((*let)->data, root->data);
124 :
- 125 85786015 : if (c < 0) {
- 126 1492912 : root->prev = tommy_tree_insert_node(cmp, root->prev, let);
- 127 1492912 : return tommy_tree_balance(root);
+ 125 86671034 : if (c < 0) {
+ 126 2767362 : root->prev = tommy_tree_insert_node(cmp, root->prev, let);
+ 127 2767362 : return tommy_tree_balance(root);
128 : }
129 :
- 130 84293103 : if (c > 0) {
- 131 84293102 : root->next = tommy_tree_insert_node(cmp, root->next, let);
- 132 84293102 : return tommy_tree_balance(root);
+ 130 83903672 : if (c > 0) {
+ 131 83903671 : root->next = tommy_tree_insert_node(cmp, root->next, let);
+ 132 83903671 : return tommy_tree_balance(root);
133 : }
134 :
135 : /* already present, set the return pointer */
@@ -200,78 +200,78 @@
138 1 : return root;
139 : }
140 :
- 141 7215779 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
+ 141 7315111 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
142 : {
- 143 7215779 : tommy_tree_node* insert = node;
+ 143 7315111 : tommy_tree_node* insert = node;
144 :
- 145 7215779 : insert->data = data;
- 146 7215779 : insert->prev = 0;
- 147 7215779 : insert->next = 0;
- 148 7215779 : insert->key = 0;
+ 145 7315111 : insert->data = data;
+ 146 7315111 : insert->prev = 0;
+ 147 7315111 : insert->next = 0;
+ 148 7315111 : insert->key = 0;
149 :
- 150 7215779 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
+ 150 7315111 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
151 :
- 152 7215779 : if (insert == node)
- 153 7215778 : ++tree->count;
+ 152 7315111 : if (insert == node)
+ 153 7315110 : ++tree->count;
154 :
- 155 7215779 : return node->data;
+ 155 7315111 : return node->data;
156 : }
157 :
- 158 775421 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let)
+ 158 838361 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let)
159 : {
160 : int c;
161 :
- 162 775421 : if (!root)
+ 162 838361 : if (!root)
163 128 : return 0;
164 :
- 165 775293 : c = cmp(data, root->data);
+ 165 838233 : c = cmp(data, root->data);
166 :
- 167 775293 : if (c < 0) {
- 168 298766 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let);
- 169 298766 : return tommy_tree_balance(root);
+ 167 838233 : if (c < 0) {
+ 168 330789 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let);
+ 169 330789 : return tommy_tree_balance(root);
170 : }
171 :
- 172 476527 : if (c > 0) {
- 173 398597 : root->next = tommy_tree_remove_node(cmp, root->next, data, let);
- 174 398597 : return tommy_tree_balance(root);
+ 172 507444 : if (c > 0) {
+ 173 423938 : root->next = tommy_tree_remove_node(cmp, root->next, data, let);
+ 174 423938 : return tommy_tree_balance(root);
175 : }
176 :
177 : /* found */
- 178 77930 : *let = root;
+ 178 83506 : *let = root;
179 :
- 180 77930 : return tommy_tree_move_right(root->prev, root->next);
+ 180 83506 : return tommy_tree_move_right(root->prev, root->next);
181 : }
182 :
- 183 78058 : void* tommy_tree_remove(tommy_tree* tree, void* data)
+ 183 83634 : void* tommy_tree_remove(tommy_tree* tree, void* data)
184 : {
- 185 78058 : tommy_tree_node* node = 0;
+ 185 83634 : tommy_tree_node* node = 0;
186 :
- 187 78058 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node);
+ 187 83634 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node);
188 :
- 189 78058 : if (!node)
+ 189 83634 : if (!node)
190 128 : return 0;
191 :
- 192 77930 : --tree->count;
+ 192 83506 : --tree->count;
193 :
- 194 77930 : return node->data;
+ 194 83506 : return node->data;
195 : }
196 :
- 197 324348165 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data)
+ 197 125457281 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data)
198 : {
199 : int c;
200 :
- 201 324348165 : if (!root)
- 202 2354776 : return 0;
+ 201 125457281 : if (!root)
+ 202 1561728 : return 0;
203 :
- 204 321993389 : c = cmp(data, root->data);
+ 204 123895553 : c = cmp(data, root->data);
205 :
- 206 330820889 : if (c < 0)
- 207 130151880 : return tommy_tree_search_node(cmp, root->prev, data);
+ 206 123895553 : if (c < 0)
+ 207 44385963 : return tommy_tree_search_node(cmp, root->prev, data);
208 :
- 209 200669009 : if (c > 0)
- 210 171722863 : return tommy_tree_search_node(cmp, root->next, data);
+ 209 79509590 : if (c > 0)
+ 210 69854172 : return tommy_tree_search_node(cmp, root->next, data);
211 :
- 212 28946146 : return root;
+ 212 9655418 : return root;
213 : }
214 :
215 2 : void* tommy_tree_search(tommy_tree* tree, void* data)
@@ -284,14 +284,14 @@
222 1 : return node->data;
223 : }
224 :
- 225 31336465 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg)
+ 225 11217144 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg)
226 : {
- 227 31336465 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg);
+ 227 11217144 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg);
228 :
- 229 31273364 : if (!node)
- 230 2346177 : return 0;
+ 229 11217144 : if (!node)
+ 230 1561727 : return 0;
231 :
- 232 28927187 : return node->data;
+ 232 9655417 : return node->data;
233 : }
234 :
235 128 : void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node)
@@ -303,49 +303,49 @@
241 128 : return data;
242 : }
243 :
- 244 6799230 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func)
+ 244 6892468 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func)
245 : {
246 : tommy_tree_node* next;
247 :
- 248 6799230 : if (!root)
- 249 10199521 : return;
+ 248 6892468 : if (!root)
+ 249 10339402 : return;
250 :
- 251 3398939 : tommy_tree_foreach_node(root->prev, func);
+ 251 3445534 : tommy_tree_foreach_node(root->prev, func);
252 :
253 : /* make a copy in case func is free() */
- 254 3398939 : next = root->next;
+ 254 3445534 : next = root->next;
255 :
- 256 3398939 : func(root->data);
+ 256 3445534 : func(root->data);
257 :
- 258 3398939 : tommy_tree_foreach_node(next, func);
+ 258 3445534 : tommy_tree_foreach_node(next, func);
259 : }
260 :
- 261 1352 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func)
+ 261 1400 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func)
262 : {
- 263 1352 : tommy_tree_foreach_node(tree->root, func);
- 264 1352 : }
+ 263 1400 : tommy_tree_foreach_node(tree->root, func);
+ 264 1400 : }
265 :
- 266 25171385 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg)
+ 266 25770381 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg)
267 : {
268 : tommy_tree_node* next;
269 :
- 270 25171385 : if (!root)
- 271 37759754 : return;
+ 270 25770381 : if (!root)
+ 271 38658410 : return;
272 :
- 273 12583016 : tommy_tree_foreach_arg_node(root->prev, func, arg);
+ 273 12882352 : tommy_tree_foreach_arg_node(root->prev, func, arg);
274 :
275 : /* make a copy in case func is free() */
- 276 12583016 : next = root->next;
+ 276 12882352 : next = root->next;
277 :
- 278 12583016 : func(arg, root->data);
+ 278 12882352 : func(arg, root->data);
279 :
- 280 12583016 : tommy_tree_foreach_arg_node(next, func, arg);
+ 280 12882352 : tommy_tree_foreach_arg_node(next, func, arg);
281 : }
282 :
- 283 5353 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg)
+ 283 5677 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg)
284 : {
- 285 5353 : tommy_tree_foreach_arg_node(tree->root, func, arg);
- 286 5353 : }
+ 285 5677 : tommy_tree_foreach_arg_node(tree->root, func, arg);
+ 286 5677 : }
287 :
288 1 : tommy_size_t tommy_tree_memory_usage(tommy_tree* tree)
289 : {
diff --git a/cov/tommyds/tommytree.h.func-sort-c.html b/cov/tommyds/tommytree.h.func-sort-c.html
index 402c3c72..6e568820 100644
--- a/cov/tommyds/tommytree.h.func-sort-c.html
+++ b/cov/tommyds/tommytree.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommytree.h.func.html b/cov/tommyds/tommytree.h.func.html
index 6566356b..e8884ad1 100644
--- a/cov/tommyds/tommytree.h.func.html
+++ b/cov/tommyds/tommytree.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommytree.h.gcov.html b/cov/tommyds/tommytree.h.gcov.html
index ec3ff04a..637a5c9c 100644
--- a/cov/tommyds/tommytree.h.gcov.html
+++ b/cov/tommyds/tommytree.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommytypes.h.func-sort-c.html b/cov/tommyds/tommytypes.h.func-sort-c.html
index 5b79e95e..473c3b65 100644
--- a/cov/tommyds/tommytypes.h.func-sort-c.html
+++ b/cov/tommyds/tommytypes.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_ilog2_u32 |
- 15297694 |
+ 10133914 |
| tommy_ctz_u32 |
- 1473 |
+ 1558 |
diff --git a/cov/tommyds/tommytypes.h.func.html b/cov/tommyds/tommytypes.h.func.html
index e495be7b..be1af3e9 100644
--- a/cov/tommyds/tommytypes.h.func.html
+++ b/cov/tommyds/tommytypes.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_ctz_u32 |
- 1473 |
+ 1558 |
| tommy_ilog2_u32 |
- 15297694 |
+ 10133914 |
diff --git a/cov/tommyds/tommytypes.h.gcov.html b/cov/tommyds/tommytypes.h.gcov.html
index 018a04b9..52e2afdd 100644
--- a/cov/tommyds/tommytypes.h.gcov.html
+++ b/cov/tommyds/tommytypes.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -385,7 +385,7 @@
323 : * \param value Value to scan. 0 is not allowed.
324 : * \return The index of the most significant bit set.
325 : */
- 326 15297694 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
+ 326 10133914 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
327 : {
328 : #if defined(_MSC_VER)
329 : unsigned long count;
@@ -401,7 +401,7 @@
339 : * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)",
340 : * to allow the double xor to be optimized out.
341 : */
- 342 15297694 : return __builtin_clz(value) ^ 31;
+ 342 10133914 : return __builtin_clz(value) ^ 31;
343 : #else
344 : /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */
345 : /* from http://graphics.stanford.edu/~seander/bithacks.html */
@@ -428,14 +428,14 @@
366 : * \param value Value to scan. 0 is not allowed.
367 : * \return The index of the least significant bit set.
368 : */
- 369 1473 : tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value)
+ 369 1558 : tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value)
370 : {
371 : #if defined(_MSC_VER)
372 : unsigned long count;
373 : _BitScanForward(&count, value);
374 : return count;
375 : #elif defined(__GNUC__)
- 376 1473 : return __builtin_ctz(value);
+ 376 1558 : return __builtin_ctz(value);
377 : #else
378 : /* Count the consecutive zero bits (trailing) on the right with multiply and lookup */
379 : /* from http://graphics.stanford.edu/~seander/bithacks.html */