diff --git a/cov/cmdline/check.c.func-sort-c.html b/cov/cmdline/check.c.func-sort-c.html
index cf689f09..4cfb7ec2 100644
--- a/cov/cmdline/check.c.func-sort-c.html
+++ b/cov/cmdline/check.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -73,22 +73,22 @@
| blockcmp |
- 473119 |
+ 473361 |
| repair_step |
- 252549 |
+ 252783 |
| is_hash_matching |
- 214644 |
+ 214767 |
- | state_check |
+ state_check |
120 |
- | state_check_process |
+ state_check_process |
118 |
diff --git a/cov/cmdline/check.c.func.html b/cov/cmdline/check.c.func.html
index d1422056..facd5d69 100644
--- a/cov/cmdline/check.c.func.html
+++ b/cov/cmdline/check.c.func.html
@@ -31,13 +31,13 @@
|
-
-
+
+
-
+
|
@@ -65,7 +65,7 @@
| blockcmp |
- 473119 |
+ 473361 |
| file_post |
@@ -73,7 +73,7 @@
| is_hash_matching |
- 214644 |
+ 214767 |
| is_parity_matching |
@@ -85,14 +85,14 @@
| repair_step |
- 252549 |
+ 252783 |
- | state_check |
+ state_check |
120 |
- | state_check_process |
+ state_check_process |
118 |
diff --git a/cov/cmdline/check.c.gcov.html b/cov/cmdline/check.c.gcov.html
index a9fbb187..530d8a18 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 473119 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero)
+ 70 473361 : 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_MAX];
73 :
74 : /* now compute the hash of the valid part */
- 75 473119 : if (rehash) {
+ 75 473361 : if (rehash) {
76 0 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size);
77 : } else {
- 78 473119 : memhash(state->hash, state->hashseed, hash, buffer, pos_size);
+ 78 473361 : memhash(state->hash, state->hashseed, hash, buffer, pos_size);
79 : }
80 :
81 : /* compare the hash */
- 82 473119 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
- 83 19028 : return -1;
+ 82 473361 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
+ 83 19016 : return -1;
84 : }
85 :
86 : /* compare to the end of the block */
- 87 454091 : if (pos_size < state->block_size) {
- 88 187372 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) {
- 89 54 : return -1;
+ 87 454345 : if (pos_size < state->block_size) {
+ 88 187561 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) {
+ 89 36 : return -1;
90 : }
91 : }
92 :
- 93 454037 : return 0;
+ 93 454309 : 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 214644 : 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 214767 : 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 214644 : hash_checked = 0; /* keep track if we check at least one block */
+ 104 214767 : hash_checked = 0; /* keep track if we check at least one block */
105 :
106 : /* check if the recovered blocks are OK */
- 107 673203 : for (j = 0; j < failed_count; ++j) {
+ 107 673598 : for (j = 0; j < failed_count; ++j) {
108 : /* if we are expected to recover this block */
- 109 477641 : if (!failed[failed_map[j]].is_outofdate
+ 109 477883 : if (!failed[failed_map[j]].is_outofdate
110 : /* if the block has a hash to check */
- 111 473119 : && block_has_updated_hash(failed[failed_map[j]].block)
+ 111 473361 : && block_has_updated_hash(failed[failed_map[j]].block)
112 : ) {
113 : /* if a hash doesn't match, fail the check */
- 114 473119 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size);
- 115 473119 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) {
- 116 19082 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]);
- 117 19082 : return 0;
+ 114 473361 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size);
+ 115 473361 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) {
+ 116 19052 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]);
+ 117 19052 : return 0;
118 : }
119 :
- 120 454037 : hash_checked = 1;
+ 120 454309 : 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 195562 : if (!hash_checked) {
+ 127 195715 : if (!hash_checked) {
128 : /* LCOV_EXCL_START */
129 : return 0;
130 : /* LCOV_EXCL_STOP */
@@ -194,8 +194,8 @@
132 :
133 : /* if we checked something, and no block failed the check */
134 : /* recompute all the redundancy information */
- 135 195562 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 136 195562 : return 1;
+ 135 195715 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 136 195715 : return 1;
137 : }
138 :
139 : /**
@@ -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 252549 : 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 252783 : 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 252549 : if (failed_count == 0) {
+ 171 252783 : if (failed_count == 0) {
172 : /* LCOV_EXCL_START */
173 : /* recompute only the parity */
174 : raid_gen(diskmax, state->level, state->block_size, buffer);
@@ -238,28 +238,28 @@
176 : /* LCOV_EXCL_STOP */
177 : }
178 :
- 179 252549 : n = state->level;
- 180 252549 : error = 0;
+ 179 252783 : n = state->level;
+ 180 252783 : error = 0;
181 :
182 : /* setup vector of failed disk indexes */
- 183 891351 : for (i = 0; i < failed_count; ++i)
- 184 638802 : id[i] = failed[failed_map[i]].index;
+ 183 892029 : for (i = 0; i < failed_count; ++i)
+ 184 639246 : 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 252549 : has_hash = 0;
- 189 891351 : for (i = 0; i < failed_count; ++i) {
+ 188 252783 : has_hash = 0;
+ 189 892029 : for (i = 0; i < failed_count; ++i) {
190 : /* if we are expected to recover this block */
- 191 638802 : if (!failed[failed_map[i]].is_outofdate
+ 191 639246 : if (!failed[failed_map[i]].is_outofdate
192 : /* if the block has a hash to check */
- 193 629758 : && block_has_updated_hash(failed[failed_map[i]].block)
+ 193 630202 : && block_has_updated_hash(failed[failed_map[i]].block)
194 : )
- 195 629750 : has_hash = 1;
+ 195 630194 : 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 252549 : if (!has_hash && failed_count < n) {
+ 200 252783 : if (!has_hash && failed_count < n) {
201 : /* number of parity to use, one more to check the recovering */
202 8 : unsigned r = failed_count + 1;
203 :
@@ -299,51 +299,51 @@
237 :
238 : /* if we have a hash, and enough parities */
239 : /* (less-or-equal failures than number of parities) */
- 240 252541 : if (has_hash && failed_count <= n) {
+ 240 252775 : if (has_hash && failed_count <= n) {
241 : /* number of parities to use equal at the number of failures */
- 242 204895 : unsigned r = failed_count;
+ 242 205038 : unsigned r = failed_count;
243 :
244 : /* all combinations (r of n) parities */
- 245 204895 : combination_first(r, n, ip);
+ 245 205038 : combination_first(r, n, ip);
246 : do {
247 : /* if a parity is missing, do nothing */
- 248 692285 : for (i = 0; i < r; ++i) {
- 249 477641 : if (buffer_recov[ip[i]] == 0)
+ 248 692650 : for (i = 0; i < r; ++i) {
+ 249 477883 : if (buffer_recov[ip[i]] == 0)
250 0 : break;
251 : }
- 252 214644 : if (i != r)
+ 252 214767 : if (i != r)
253 0 : continue;
254 :
255 : /* copy the parities to use */
- 256 692285 : for (i = 0; i < r; ++i)
- 257 477641 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
+ 256 692650 : for (i = 0; i < r; ++i)
+ 257 477883 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size);
258 :
259 : /* recover */
- 260 214644 : raid_data(r, id, ip, diskmax, state->block_size, buffer);
+ 260 214767 : raid_data(r, id, ip, diskmax, state->block_size, buffer);
261 :
262 : /* use the hash to check the result */
- 263 214644 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
- 264 195562 : return 0;
+ 263 214767 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
+ 264 195715 : return 0;
265 :
266 : /* log */
- 267 19082 : log_tag("parity_error:%u:", pos);
- 268 38164 : for (i = 0; i < r; ++i) {
- 269 19082 : if (i != 0)
+ 267 19052 : log_tag("parity_error:%u:", pos);
+ 268 38104 : for (i = 0; i < r; ++i) {
+ 269 19052 : if (i != 0)
270 0 : log_tag("/");
- 271 19082 : log_tag("%s", lev_config_name(ip[i]));
+ 271 19052 : log_tag("%s", lev_config_name(ip[i]));
272 : }
- 273 19082 : log_tag(":hash: Hash mismatch\n");
- 274 19082 : ++error;
- 275 38164 : } while (combination_next(r, n, ip));
+ 273 19052 : log_tag(":hash: Hash mismatch\n");
+ 274 19052 : ++error;
+ 275 38104 : } while (combination_next(r, n, ip));
276 : }
277 :
278 : /* return the number of failed attempts, or -1 if no strategy */
- 279 56979 : if (error)
- 280 9333 : return error;
+ 279 57060 : if (error)
+ 280 9323 : return error;
281 :
- 282 47646 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n",
+ 282 47737 : 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 47646 : return -1;
+ 284 47737 : return -1;
285 : }
286 :
287 870958 : 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)
@@ -360,47 +360,47 @@
298 :
299 : /* if nothing failed, just recompute the parity */
300 870958 : if (failed_count == 0) {
- 301 583497 : raid_gen(diskmax, state->level, state->block_size, buffer);
- 302 583497 : return 0;
+ 301 583263 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 302 583263 : return 0;
303 : }
304 :
305 : /* logs the status */
- 306 1016282 : for (j = 0; j < failed_count; ++j) {
+ 306 1016960 : for (j = 0; j < failed_count; ++j) {
307 : const char* desc;
308 : const char* hash;
309 : const char* data;
- 310 728821 : struct snapraid_block* block = failed[j].block;
- 311 728821 : unsigned block_state = block_state_get(block);
+ 310 729265 : struct snapraid_block* block = failed[j].block;
+ 311 729265 : unsigned block_state = block_state_get(block);
312 :
- 313 728821 : switch (block_state) {
+ 313 729265 : switch (block_state) {
314 18454 : case BLOCK_STATE_DELETED : desc = "delete"; break;
315 13851 : case BLOCK_STATE_CHG : desc = "change"; break;
316 62282 : case BLOCK_STATE_REP : desc = "replace"; break;
- 317 634234 : case BLOCK_STATE_BLK : desc = "block"; break;
+ 317 634678 : case BLOCK_STATE_BLK : desc = "block"; break;
318 : /* LCOV_EXCL_START */
319 : default : desc = "unknown"; break;
320 : /* LCOV_EXCL_STOP */
321 : }
322 :
- 323 728821 : if (hash_is_invalid(block->hash)) {
+ 323 729265 : if (hash_is_invalid(block->hash)) {
324 13843 : hash = "lost";
- 325 714978 : } else if (hash_is_zero(block->hash)) {
+ 325 715422 : } else if (hash_is_zero(block->hash)) {
326 8 : hash = "zero";
327 : } else {
- 328 714970 : hash = "known";
+ 328 715414 : hash = "known";
329 : }
330 :
- 331 728821 : if (failed[j].is_bad)
- 332 643096 : data = "bad";
+ 331 729265 : if (failed[j].is_bad)
+ 332 643540 : data = "bad";
333 : else
334 85725 : data = "good";
335 :
- 336 728821 : if (failed[j].file) {
- 337 710367 : struct snapraid_disk* disk = failed[j].disk;
- 338 710367 : struct snapraid_file* file = failed[j].file;
- 339 710367 : block_off_t file_pos = failed[j].file_pos;
+ 336 729265 : if (failed[j].file) {
+ 337 710811 : struct snapraid_disk* disk = failed[j].disk;
+ 338 710811 : struct snapraid_file* file = failed[j].file;
+ 339 710811 : block_off_t file_pos = failed[j].file_pos;
340 :
- 341 710367 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
+ 341 710811 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
342 : } else {
343 18454 : log_tag("entry:%u:%s:%s:%s:\n", j, desc, hash, data);
344 : }
@@ -422,35 +422,35 @@
360 : /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */
361 : /* but we are not interested in DELETED ones. */
362 :
- 363 287461 : n = 0;
- 364 287461 : something_to_recover = 0; /* keep track if there is at least one block to fix */
- 365 1016282 : for (j = 0; j < failed_count; ++j) {
- 366 728821 : if (failed[j].is_bad) {
- 367 643096 : unsigned block_state = block_state_get(failed[j].block);
+ 363 287695 : n = 0;
+ 364 287695 : something_to_recover = 0; /* keep track if there is at least one block to fix */
+ 365 1016960 : for (j = 0; j < failed_count; ++j) {
+ 366 729265 : if (failed[j].is_bad) {
+ 367 643540 : unsigned block_state = block_state_get(failed[j].block);
368 :
- 369 643096 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */
+ 369 643540 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */
370 :
371 : /* if we have the hash for it */
- 372 643096 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP)
+ 372 643540 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP)
373 : /* try to fetch the block using the known hash */
- 374 643088 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0
- 375 638616 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0)
+ 374 643532 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0
+ 375 639060 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0)
376 : ) {
377 : /* we already have corrected it! */
378 22382 : log_tag("hash_import: Fixed entry %u\n", j);
379 : } else {
380 : /* otherwise try to recover it */
- 381 620714 : failed_map[n] = j;
- 382 620714 : ++n;
+ 381 621158 : failed_map[n] = j;
+ 382 621158 : ++n;
383 :
384 : /* we have something to try to recover */
- 385 620714 : something_to_recover = 1;
+ 385 621158 : something_to_recover = 1;
386 : }
387 : }
388 : }
389 :
390 : /* if nothing to fix */
- 391 287461 : if (!something_to_recover) {
+ 391 287695 : if (!something_to_recover) {
392 43956 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n);
393 :
394 : /* recompute only the parity */
@@ -458,22 +458,22 @@
396 43956 : return 0;
397 : }
398 :
- 399 243505 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
- 400 243505 : if (ret == 0) {
+ 399 243739 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
+ 400 243739 : if (ret == 0) {
401 : /* reprocess the CHG blocks, for which we don't have a hash to check */
402 : /* if they were BAD we have to use some heuristics to ensure that we have recovered */
403 : /* the state after the sync. If unsure, we assume the worst case */
404 :
- 405 667198 : for (j = 0; j < failed_count; ++j) {
+ 405 667623 : for (j = 0; j < failed_count; ++j) {
406 : /* we take care only of BAD blocks we have to write back */
- 407 476150 : if (failed[j].is_bad) {
- 408 462678 : unsigned block_state = block_state_get(failed[j].block);
+ 407 476422 : if (failed[j].is_bad) {
+ 408 462950 : unsigned block_state = block_state_get(failed[j].block);
409 :
410 : /* BLK and REP blocks are always OK, because at this point */
411 : /* we have already checked their hash */
- 412 462678 : if (block_state != BLOCK_STATE_CHG) {
- 413 462670 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
- 414 462670 : continue;
+ 412 462950 : if (block_state != BLOCK_STATE_CHG) {
+ 413 462942 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
+ 414 462942 : continue;
415 : }
416 :
417 : /* for CHG blocks we have to 'guess' if they are correct or not */
@@ -515,15 +515,15 @@
453 : }
454 : }
455 :
- 456 191048 : return 0;
+ 456 191201 : return 0;
457 : }
- 458 52457 : if (ret > 0)
- 459 9333 : error += ret;
+ 458 52538 : if (ret > 0)
+ 459 9323 : error += ret;
460 :
- 461 52457 : if (ret < 0)
- 462 43124 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n);
+ 461 52538 : if (ret < 0)
+ 462 43215 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n);
463 : else
- 464 9333 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret);
+ 464 9323 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret);
465 :
466 : /* Now assume that the parity IS NOT updated at the current state, */
467 : /* but still represent the state before the last 'sync' process. */
@@ -533,15 +533,15 @@
471 : /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */
472 : /* even if marked as bad, because we don't have parity for them and it's just impossible, */
473 : /* and we are not interested to recover DELETED ones. */
- 474 52457 : n = 0;
- 475 52457 : something_to_recover = 0; /* keep track if there is at least one block to fix */
- 476 52457 : something_unsynced = 0; /* keep track if we have some unsynced info to process */
- 477 232692 : for (j = 0; j < failed_count; ++j) {
- 478 180235 : unsigned block_state = block_state_get(failed[j].block);
+ 474 52538 : n = 0;
+ 475 52538 : something_to_recover = 0; /* keep track if there is at least one block to fix */
+ 476 52538 : something_unsynced = 0; /* keep track if we have some unsynced info to process */
+ 477 232945 : for (j = 0; j < failed_count; ++j) {
+ 478 180407 : unsigned block_state = block_state_get(failed[j].block);
479 :
- 480 180235 : if (block_state == BLOCK_STATE_DELETED
- 481 171191 : || block_state == BLOCK_STATE_CHG
- 482 171191 : || block_state == BLOCK_STATE_REP
+ 480 180407 : if (block_state == BLOCK_STATE_DELETED
+ 481 171363 : || block_state == BLOCK_STATE_CHG
+ 482 171363 : || block_state == BLOCK_STATE_REP
483 : ) {
484 : /* If the block is CHG, REP or DELETED, we don't have the original content of block, */
485 : /* and we must try to recover it. */
@@ -583,24 +583,24 @@
521 : /* it also applies to CHG and DELETE blocks because we want to have */
522 : /* a successful recovering only if a BLK one is matching */
523 9044 : failed[j].is_outofdate = 1;
- 524 171191 : } else if (failed[j].is_bad) {
+ 524 171363 : } else if (failed[j].is_bad) {
525 : /* If the block is bad we don't know its content, and we try to recover it */
526 : /* At this point, we can have only BLK ones */
527 :
- 528 171191 : assert(block_state == BLOCK_STATE_BLK);
+ 528 171363 : assert(block_state == BLOCK_STATE_BLK);
529 :
530 : /* we have something we are interested to recover */
- 531 171191 : something_to_recover = 1;
+ 531 171363 : something_to_recover = 1;
532 :
533 : /* we try to recover it */
- 534 171191 : failed_map[n] = j;
- 535 171191 : ++n;
+ 534 171363 : failed_map[n] = j;
+ 535 171363 : ++n;
536 : }
537 : }
538 :
539 : /* if nothing to fix, we just don't try */
540 : /* if nothing unsynced we also don't retry, because it's the same try as before */
- 541 52457 : if (something_to_recover && something_unsynced) {
+ 541 52538 : if (something_to_recover && something_unsynced) {
542 9044 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
543 9044 : if (ret == 0) {
544 : /* reprocess the REP and CHG blocks, for which we have recovered and old state */
@@ -634,17 +634,17 @@
572 : else
573 0 : log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret);
574 : } else {
- 575 43413 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n,
+ 575 43494 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n,
576 : !something_to_recover ? " nothing to recover" : "",
577 : !something_unsynced ? " nothing unsynched" : ""
578 : );
579 : }
580 :
581 : /* return the number of failed attempts, or -1 if no strategy */
- 582 47935 : if (error)
- 583 4811 : return error;
+ 582 48016 : if (error)
+ 583 4801 : return error;
584 : else
- 585 43124 : return -1;
+ 585 43215 : return -1;
586 : }
587 :
588 : /**
@@ -718,12 +718,12 @@
656 : /* rename it to .unrecoverable */
657 : char path_to[PATH_MAX];
658 :
- 659 63275 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
+ 659 63324 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
660 :
661 : /* ensure to close the file before renaming */
- 662 63275 : if (handle[j].file == file) {
- 663 63275 : ret = handle_close(&handle[j]);
- 664 63275 : if (ret != 0) {
+ 662 63324 : if (handle[j].file == file) {
+ 663 63324 : ret = handle_close(&handle[j]);
+ 664 63324 : if (ret != 0) {
665 : /* LCOV_EXCL_START */
666 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
667 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -732,8 +732,8 @@
670 : }
671 : }
672 :
- 673 63275 : ret = rename(path, path_to);
- 674 63275 : if (ret != 0) {
+ 673 63324 : ret = rename(path, path_to);
+ 674 63324 : if (ret != 0) {
675 : /* LCOV_EXCL_START */
676 : log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno));
677 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
@@ -741,22 +741,22 @@
679 : /* LCOV_EXCL_STOP */
680 : }
681 :
- 682 63275 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 683 63275 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 682 63324 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 683 63324 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
684 :
685 : /* and do not set the time if damaged */
- 686 63275 : goto close_and_continue;
+ 686 63324 : goto close_and_continue;
687 : }
688 :
689 : /* if the file is not fixed, meaning that it is untouched */
- 690 693959 : if (!file_flag_has(file, FILE_IS_FIXED)) {
+ 690 693910 : if (!file_flag_has(file, FILE_IS_FIXED)) {
691 : /* nothing to do, but close the file */
- 692 574554 : goto close_and_continue;
+ 692 574448 : goto close_and_continue;
693 : }
694 :
695 : /* if the file is closed or different than the one expected, reopen it */
696 : /* a different open file could happen when filtering for bad blocks */
- 697 119405 : if (handle[j].file != file) {
+ 697 119462 : if (handle[j].file != file) {
698 : /* close a potential different file */
699 0 : ret = handle_close(&handle[j]);
700 0 : if (ret != 0) {
@@ -779,13 +779,13 @@
717 : }
718 : }
719 :
- 720 119405 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 721 119405 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 720 119462 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 721 119462 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer));
722 :
- 723 119405 : inode = handle[j].st.st_ino;
+ 723 119462 : inode = handle[j].st.st_ino;
724 :
725 : /* search for the corresponding inode */
- 726 119405 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
+ 726 119462 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
727 :
728 : /* if the inode is already in the database and it refers at a different file name, */
729 : /* we can fix the file time ONLY if the time and size allow to differentiate */
@@ -795,15 +795,15 @@
733 : /* when recreating them the inodes may be reused in a different order, */
734 : /* and at the next sync some files may have matching inode/size/time even if different name */
735 : /* not allowing sync to detect that the file is changed and not renamed */
- 736 119405 : if (!collide_file /* if not in the database, there is no collision */
- 737 31334 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */
- 738 22534 : || collide_file->size != file->size /* if the size is different, the collision is identified */
- 739 2 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */
- 740 1 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */
+ 736 119462 : if (!collide_file /* if not in the database, there is no collision */
+ 737 42083 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */
+ 738 39012 : || collide_file->size != file->size /* if the size is different, the collision is identified */
+ 739 7 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */
+ 740 5 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */
741 : ) {
742 : /* set the original modification time */
- 743 119405 : ret = handle_utime(&handle[j]);
- 744 238810 : if (ret == -1) {
+ 743 119462 : ret = handle_utime(&handle[j]);
+ 744 238924 : if (ret == -1) {
745 : /* LCOV_EXCL_START */
746 : /* mark the file as damaged */
747 : file_flag_set(file, FILE_IS_DAMAGED);
@@ -818,21 +818,21 @@
756 : /* we are not fixing, but only checking */
757 : /* print just the final status */
758 1308032 : if (file_flag_has(file, FILE_IS_DAMAGED)) {
- 759 9420 : if (state->opt.auditonly) {
- 760 2798 : log_tag("status:damaged:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 761 2798 : msg_info("damaged %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 759 9546 : if (state->opt.auditonly) {
+ 760 2866 : log_tag("status:damaged:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 761 2866 : msg_info("damaged %s\n", fmt_term(disk, file->sub, esc_buffer));
762 : } else {
- 763 6622 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 764 6622 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 763 6680 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 764 6680 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
765 : }
- 766 1298612 : } else if (file_flag_has(file, FILE_IS_FIXED)) {
- 767 76223 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 768 76223 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 766 1298486 : } else if (file_flag_has(file, FILE_IS_FIXED)) {
+ 767 76269 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 768 76269 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer));
769 : } else {
770 : /* we don't use msg_verbose() because it also goes into the log */
- 771 1222389 : if (msg_level >= MSG_VERBOSE) {
- 772 23229 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 773 23229 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer));
+ 771 1222217 : if (msg_level >= MSG_VERBOSE) {
+ 772 23189 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 773 23189 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer));
774 : }
775 : }
776 : }
@@ -844,8 +844,8 @@
782 2162259 : if (handle[j].file == file) {
783 : /* ensure to close the file just after finishing with it */
784 : /* to avoid to keep it open without any possible use */
- 785 1978605 : ret = handle_close(&handle[j]);
- 786 1978605 : if (ret != 0) {
+ 785 1978363 : ret = handle_close(&handle[j]);
+ 786 1978363 : if (ret != 0) {
787 : /* LCOV_EXCL_START */
788 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
789 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
@@ -877,1216 +877,1238 @@
815 15204 : return 0;
816 : }
817 :
- 818 : /* for each parity */
- 819 2125818 : for (l = 0; l < state->level; ++l) {
- 820 2042438 : if (!state->parity[l].is_excluded) {
- 821 1772374 : return 1;
- 822 : }
- 823 : }
- 824 :
- 825 : /* for each disk */
- 826 386636 : for (j = 0; j < diskmax; ++j) {
- 827 : struct snapraid_block* block;
- 828 :
- 829 : /* if no disk, nothing to check */
- 830 351348 : if (!handle[j].disk)
- 831 0 : continue;
- 832 :
- 833 351348 : block = fs_par2block_find(handle[j].disk, i);
+ 818 : /* now apply the filters */
+ 819 :
+ 820 : /* if a parity is not excluded, include all blocks, even unused ones */
+ 821 2125818 : for (l = 0; l < state->level; ++l) {
+ 822 2042438 : if (!state->parity[l].is_excluded_by_filter) {
+ 823 1772374 : return 1;
+ 824 : }
+ 825 : }
+ 826 :
+ 827 : /* otherwise include only used blocks */
+ 828 386636 : for (j = 0; j < diskmax; ++j) {
+ 829 : struct snapraid_block* block;
+ 830 :
+ 831 : /* if no disk, nothing to check */
+ 832 351348 : if (!handle[j].disk)
+ 833 0 : continue;
834 :
- 835 : /* try to recover all files, even the ones without hash */
- 836 : /* because in some cases we can recover also them */
- 837 351348 : if (block_has_file(block)) {
- 838 344686 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0);
- 839 344686 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */
- 840 48092 : return 1;
- 841 : }
- 842 : }
- 843 : }
- 844 :
- 845 35288 : return 0;
- 846 : }
- 847 :
- 848 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)
- 849 : {
- 850 : struct snapraid_handle* handle;
- 851 : unsigned diskmax;
- 852 : block_off_t i;
- 853 : unsigned j;
- 854 : void* buffer_alloc;
- 855 : void** buffer;
- 856 : unsigned buffermax;
- 857 : int ret;
- 858 : data_off_t countsize;
- 859 : block_off_t countpos;
- 860 : block_off_t countmax;
- 861 : unsigned error;
- 862 : unsigned unrecoverable_error;
- 863 : unsigned recovered_error;
- 864 : struct failed_struct* failed;
- 865 : unsigned* failed_map;
- 866 : unsigned l;
- 867 : char esc_buffer[ESC_MAX];
- 868 : char esc_buffer_alt[ESC_MAX];
- 869 :
- 870 118 : handle = handle_mapping(state, &diskmax);
+ 835 351348 : block = fs_par2block_find(handle[j].disk, i);
+ 836 :
+ 837 : /* try to recover all files, even the ones without hash */
+ 838 : /* because in some cases we can recover also them */
+ 839 351348 : if (block_has_file(block)) {
+ 840 344686 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0);
+ 841 344686 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */
+ 842 48092 : return 1;
+ 843 : }
+ 844 : }
+ 845 : }
+ 846 :
+ 847 35288 : return 0;
+ 848 : }
+ 849 :
+ 850 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)
+ 851 : {
+ 852 : struct snapraid_handle* handle;
+ 853 : unsigned diskmax;
+ 854 : block_off_t i;
+ 855 : unsigned j;
+ 856 : void* buffer_alloc;
+ 857 : void** buffer;
+ 858 : unsigned buffermax;
+ 859 : int ret;
+ 860 : data_off_t countsize;
+ 861 : block_off_t countpos;
+ 862 : block_off_t countmax;
+ 863 : unsigned error;
+ 864 : unsigned unrecoverable_error;
+ 865 : unsigned recovered_error;
+ 866 : struct failed_struct* failed;
+ 867 : unsigned* failed_map;
+ 868 : unsigned l;
+ 869 : char esc_buffer[ESC_MAX];
+ 870 : char esc_buffer_alt[ESC_MAX];
871 :
- 872 : /* we need 1 * data + 2 * parity + 1 * zero */
- 873 118 : buffermax = diskmax + 2 * state->level + 1;
- 874 :
- 875 118 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
- 876 118 : if (!state->opt.skip_self)
- 877 0 : mtest_vector(buffermax, state->block_size, buffer);
- 878 :
- 879 : /* fill up the zero buffer */
- 880 118 : memset(buffer[buffermax - 1], 0, state->block_size);
- 881 118 : raid_zero(buffer[buffermax - 1]);
- 882 :
- 883 118 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct));
- 884 118 : failed_map = malloc_nofail(diskmax * sizeof(unsigned));
- 885 :
- 886 118 : error = 0;
- 887 118 : unrecoverable_error = 0;
- 888 118 : recovered_error = 0;
- 889 :
- 890 : /* first count the number of blocks to process */
- 891 118 : countmax = 0;
- 892 935597 : for (i = blockstart; i < blockmax; ++i) {
- 893 935479 : if (!block_is_enabled(state, i, handle, diskmax))
- 894 25246 : continue;
- 895 910233 : ++countmax;
- 896 : }
- 897 :
- 898 : /* check all the blocks in files */
- 899 118 : countsize = 0;
- 900 118 : countpos = 0;
- 901 118 : state_progress_begin(state, blockstart, blockmax, countmax);
- 902 935597 : for (i = blockstart; i < blockmax; ++i) {
- 903 : unsigned failed_count;
- 904 : int valid_parity;
- 905 : snapraid_info info;
- 906 : int rehash;
- 907 :
- 908 935479 : if (!block_is_enabled(state, i, handle, diskmax)) {
- 909 : /* post process the files */
- 910 25246 : ret = file_post(state, fix, i, handle, diskmax);
- 911 25246 : if (ret == -1) {
- 912 : /* LCOV_EXCL_START */
- 913 : log_fatal("Stopping at block %u\n", i);
- 914 : ++unrecoverable_error;
- 915 : goto bail;
- 916 : /* LCOV_EXCL_STOP */
- 917 : }
- 918 :
- 919 : /* and now continue with the next block */
- 920 25246 : continue;
- 921 : }
- 922 :
- 923 : /* If we have valid parity, and it makes sense to check its content. */
- 924 : /* If we already know that the parity is invalid, we just read the file */
- 925 : /* but we don't report parity errors */
- 926 : /* Note that with auditonly, we anyway skip the full parity check, */
- 927 : /* because we also don't read it at all */
- 928 910233 : valid_parity = 1;
- 929 :
- 930 : /* keep track of the number of failed blocks */
- 931 910233 : failed_count = 0;
+ 872 118 : handle = handle_mapping(state, &diskmax);
+ 873 :
+ 874 : /* we need 1 * data + 2 * parity + 1 * zero */
+ 875 118 : buffermax = diskmax + 2 * state->level + 1;
+ 876 :
+ 877 118 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
+ 878 118 : if (!state->opt.skip_self)
+ 879 0 : mtest_vector(buffermax, state->block_size, buffer);
+ 880 :
+ 881 : /* fill up the zero buffer */
+ 882 118 : memset(buffer[buffermax - 1], 0, state->block_size);
+ 883 118 : raid_zero(buffer[buffermax - 1]);
+ 884 :
+ 885 118 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct));
+ 886 118 : failed_map = malloc_nofail(diskmax * sizeof(unsigned));
+ 887 :
+ 888 118 : error = 0;
+ 889 118 : unrecoverable_error = 0;
+ 890 118 : recovered_error = 0;
+ 891 :
+ 892 : /* first count the number of blocks to process */
+ 893 118 : countmax = 0;
+ 894 935597 : for (i = blockstart; i < blockmax; ++i) {
+ 895 935479 : if (!block_is_enabled(state, i, handle, diskmax))
+ 896 25246 : continue;
+ 897 910233 : ++countmax;
+ 898 : }
+ 899 :
+ 900 : /* check all the blocks in files */
+ 901 118 : countsize = 0;
+ 902 118 : countpos = 0;
+ 903 118 : state_progress_begin(state, blockstart, blockmax, countmax);
+ 904 935597 : for (i = blockstart; i < blockmax; ++i) {
+ 905 : unsigned failed_count;
+ 906 : int valid_parity;
+ 907 : int used_parity;
+ 908 : snapraid_info info;
+ 909 : int rehash;
+ 910 :
+ 911 935479 : if (!block_is_enabled(state, i, handle, diskmax)) {
+ 912 : /* post process the files */
+ 913 25246 : ret = file_post(state, fix, i, handle, diskmax);
+ 914 25246 : if (ret == -1) {
+ 915 : /* LCOV_EXCL_START */
+ 916 : log_fatal("Stopping at block %u\n", i);
+ 917 : ++unrecoverable_error;
+ 918 : goto bail;
+ 919 : /* LCOV_EXCL_STOP */
+ 920 : }
+ 921 :
+ 922 : /* and now continue with the next block */
+ 923 25246 : continue;
+ 924 : }
+ 925 :
+ 926 : /* If we have valid parity, and it makes sense to check its content. */
+ 927 : /* If we already know that the parity is invalid, we just read the file */
+ 928 : /* but we don't report parity errors */
+ 929 : /* Note that with auditonly, we anyway skip the full parity check, */
+ 930 : /* because we also don't read it at all */
+ 931 910233 : valid_parity = 1;
932 :
- 933 : /* get block specific info */
- 934 910233 : info = info_get(&state->infoarr, i);
+ 933 : /* If the parity is used by at least one file */
+ 934 910233 : used_parity = 0;
935 :
- 936 : /* if we have to use the old hash */
- 937 910233 : rehash = info_get_rehash(info);
+ 936 : /* keep track of the number of failed blocks */
+ 937 910233 : failed_count = 0;
938 :
- 939 : /* for each disk, process the block */
- 940 6371631 : for (j = 0; j < diskmax; ++j) {
- 941 : int read_size;
- 942 : unsigned char hash[HASH_MAX];
- 943 : struct snapraid_disk* disk;
- 944 : struct snapraid_block* block;
- 945 : struct snapraid_file* file;
- 946 : block_off_t file_pos;
- 947 : unsigned block_state;
- 948 :
- 949 : /* if the disk position is not used */
- 950 5461398 : disk = handle[j].disk;
- 951 5461398 : if (!disk) {
- 952 : /* use an empty block */
- 953 14061 : memset(buffer[j], 0, state->block_size);
- 954 954823 : continue;
- 955 : }
- 956 :
- 957 : /* if the disk block is not used */
- 958 5447337 : block = fs_par2block_find(disk, i);
- 959 5447337 : if (block == BLOCK_NULL) {
- 960 : /* use an empty block */
- 961 192063 : memset(buffer[j], 0, state->block_size);
- 962 192063 : continue;
- 963 : }
- 964 :
- 965 : /* get the state of the block */
- 966 5255274 : block_state = block_state_get(block);
- 967 :
- 968 : /* if the parity is not valid */
- 969 5255274 : if (block_has_invalid_parity(block)) {
- 970 : /* mark the parity as invalid, and don't try to check/fix it */
- 971 : /* because it will be recomputed at the next sync */
- 972 94587 : valid_parity = 0;
- 973 : /* follow */
- 974 : }
- 975 :
- 976 : /* if the block is DELETED */
- 977 5255274 : if (block_state == BLOCK_STATE_DELETED) {
- 978 : /* use an empty block */
- 979 18454 : memset(buffer[j], 0, state->block_size);
- 980 :
- 981 : /* store it in the failed set, because potentially */
- 982 : /* the parity may be still computed with the previous content */
- 983 18454 : failed[failed_count].is_bad = 0; /* note that is_bad==0 <=> file==0 */
- 984 18454 : failed[failed_count].is_outofdate = 0;
- 985 18454 : failed[failed_count].index = j;
- 986 18454 : failed[failed_count].block = block;
- 987 18454 : failed[failed_count].disk = disk;
- 988 18454 : failed[failed_count].file = 0;
- 989 18454 : failed[failed_count].file_pos = 0;
- 990 18454 : failed[failed_count].handle = 0;
- 991 18454 : ++failed_count;
- 992 18454 : continue;
- 993 : }
- 994 :
- 995 : /* get the file of this block */
- 996 5236820 : file = fs_par2file_get(disk, i, &file_pos);
- 997 :
- 998 : /* if we are only hashing, we can skip excluded files and don't even read them */
- 999 5236820 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) {
- 1000 : /* use an empty block */
- 1001 : /* in true, this is unnecessary, because we are not checking any parity */
- 1002 : /* but we keep it for completeness */
- 1003 0 : memset(buffer[j], 0, state->block_size);
- 1004 0 : continue;
- 1005 : }
+ 939 : /* get block specific info */
+ 940 910233 : info = info_get(&state->infoarr, i);
+ 941 :
+ 942 : /* if we have to use the old hash */
+ 943 910233 : rehash = info_get_rehash(info);
+ 944 :
+ 945 : /* for each disk, process the block */
+ 946 6371631 : for (j = 0; j < diskmax; ++j) {
+ 947 : int read_size;
+ 948 : unsigned char hash[HASH_MAX];
+ 949 : struct snapraid_disk* disk;
+ 950 : struct snapraid_block* block;
+ 951 : struct snapraid_file* file;
+ 952 : block_off_t file_pos;
+ 953 : unsigned block_state;
+ 954 :
+ 955 : /* if the disk position is not used */
+ 956 5461398 : disk = handle[j].disk;
+ 957 5461398 : if (!disk) {
+ 958 : /* use an empty block */
+ 959 14061 : memset(buffer[j], 0, state->block_size);
+ 960 955476 : continue;
+ 961 : }
+ 962 :
+ 963 : /* if the disk block is not used */
+ 964 5447337 : block = fs_par2block_find(disk, i);
+ 965 5447337 : if (block == BLOCK_NULL) {
+ 966 : /* use an empty block */
+ 967 192063 : memset(buffer[j], 0, state->block_size);
+ 968 192063 : continue;
+ 969 : }
+ 970 :
+ 971 : /* get the state of the block */
+ 972 5255274 : block_state = block_state_get(block);
+ 973 :
+ 974 : /* if the parity is not valid */
+ 975 5255274 : if (block_has_invalid_parity(block)) {
+ 976 : /* mark the parity as invalid, and don't try to check/fix it */
+ 977 : /* because it will be recomputed at the next sync */
+ 978 94587 : valid_parity = 0;
+ 979 : /* follow */
+ 980 : }
+ 981 :
+ 982 : /* if the block is DELETED */
+ 983 5255274 : if (block_state == BLOCK_STATE_DELETED) {
+ 984 : /* use an empty block */
+ 985 18454 : memset(buffer[j], 0, state->block_size);
+ 986 :
+ 987 : /* store it in the failed set, because potentially */
+ 988 : /* the parity may be still computed with the previous content */
+ 989 18454 : failed[failed_count].is_bad = 0; /* note that is_bad==0 <=> file==0 */
+ 990 18454 : failed[failed_count].is_outofdate = 0;
+ 991 18454 : failed[failed_count].index = j;
+ 992 18454 : failed[failed_count].block = block;
+ 993 18454 : failed[failed_count].disk = disk;
+ 994 18454 : failed[failed_count].file = 0;
+ 995 18454 : failed[failed_count].file_pos = 0;
+ 996 18454 : failed[failed_count].handle = 0;
+ 997 18454 : ++failed_count;
+ 998 18454 : continue;
+ 999 : }
+ 1000 :
+ 1001 : /* here we are sure that the parity is used by a file */
+ 1002 5236820 : used_parity = 1;
+ 1003 :
+ 1004 : /* get the file of this block */
+ 1005 5236820 : file = fs_par2file_get(disk, i, &file_pos);
1006 :
- 1007 : /* if the file is closed or different than the current one */
- 1008 5236820 : if (handle[j].file == 0 || handle[j].file != file) {
- 1009 : /* close the old one, if any */
- 1010 2259576 : ret = handle_close(&handle[j]);
- 1011 2259576 : if (ret == -1) {
- 1012 : /* LCOV_EXCL_START */
- 1013 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno));
- 1014 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
- 1015 : log_fatal("Stopping at block %u\n", i);
- 1016 : ++unrecoverable_error;
- 1017 : goto bail;
- 1018 : /* LCOV_EXCL_STOP */
- 1019 : }
- 1020 :
- 1021 : /* if fixing, and the file is not excluded, we must open for writing */
- 1022 2259576 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) {
- 1023 : /* if fixing, create the file, open for writing and resize if required */
- 1024 771283 : ret = handle_create(&handle[j], file, state->file_mode);
- 1025 771283 : if (ret == -1) {
- 1026 : /* LCOV_EXCL_START */
- 1027 : if (errno == EACCES) {
- 1028 : log_fatal("WARNING! Please give write permission to the file.\n");
- 1029 : } else {
- 1030 : log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1031 : }
- 1032 : log_fatal("Stopping at block %u\n", i);
- 1033 : ++unrecoverable_error;
- 1034 : goto bail;
- 1035 : /* LCOV_EXCL_STOP */
- 1036 : }
- 1037 :
- 1038 : /* check if the file was just created */
- 1039 1542566 : if (handle[j].created != 0) {
- 1040 : /* if fragmented, it may be reopened, so remember that the file */
- 1041 : /* was originally missing */
- 1042 113044 : file_flag_set(file, FILE_IS_CREATED);
- 1043 : }
- 1044 : } else {
- 1045 : /* open the file only for reading */
- 1046 1488293 : if (!file_flag_has(file, FILE_IS_MISSING))
- 1047 1372856 : ret = handle_open(&handle[j], file, state->file_mode,
- 1048 1372856 : log_error, state->opt.expected_missing ? log_expected : 0);
- 1049 : else
- 1050 115437 : ret = -1; /* if the file is missing, we cannot open it */
- 1051 1488293 : if (ret == -1) {
- 1052 : /* save the failed block for the check/fix */
- 1053 194019 : failed[failed_count].is_bad = 1;
- 1054 194019 : failed[failed_count].is_outofdate = 0;
- 1055 194019 : failed[failed_count].index = j;
- 1056 194019 : failed[failed_count].block = block;
- 1057 194019 : failed[failed_count].disk = disk;
- 1058 194019 : failed[failed_count].file = file;
- 1059 194019 : failed[failed_count].file_pos = file_pos;
- 1060 194019 : failed[failed_count].handle = &handle[j];
- 1061 194019 : ++failed_count;
- 1062 :
- 1063 194019 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
- 1064 194019 : ++error;
- 1065 :
- 1066 : /* mark the file as missing, to avoid to retry to open it again */
- 1067 : /* note that this can be done only if we are not fixing it */
- 1068 : /* otherwise, it could be recreated */
- 1069 194019 : file_flag_set(file, FILE_IS_MISSING);
- 1070 194019 : continue;
- 1071 : }
- 1072 : }
- 1073 :
- 1074 : /* if it's the first open, and not excluded */
- 1075 2065557 : if (!file_flag_has(file, FILE_IS_OPENED)
- 1076 2050191 : && !file_flag_has(file, FILE_IS_EXCLUDED)) {
- 1077 :
- 1078 : /* check if the file is changed */
- 1079 1998760 : if (handle[j].st.st_size != file->size
- 1080 1805894 : || handle[j].st.st_mtime != file->mtime_sec
- 1081 1781363 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
- 1082 : /* don't check the inode to support file-system without persistent inodes */
- 1083 : ) {
- 1084 : /* report that the file is not synced */
- 1085 217397 : file_flag_set(file, FILE_IS_UNSYNCED);
- 1086 : }
- 1087 : }
- 1088 :
- 1089 : /* if it's the first open, and not excluded and larger */
- 1090 2065557 : if (!file_flag_has(file, FILE_IS_OPENED)
- 1091 2050191 : && !file_flag_has(file, FILE_IS_EXCLUDED)
- 1092 1998760 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))
- 1093 1998760 : && handle[j].st.st_size > file->size
- 1094 : ) {
- 1095 8819 : log_error("File '%s' is larger than expected.\n", handle[j].path);
- 1096 8819 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer));
- 1097 8819 : ++error;
- 1098 :
- 1099 8819 : if (fix) {
- 1100 3254 : ret = handle_truncate(&handle[j], file);
- 1101 3254 : if (ret == -1) {
- 1102 : /* LCOV_EXCL_START */
- 1103 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n");
- 1104 : log_fatal("Stopping at block %u\n", i);
- 1105 : ++unrecoverable_error;
- 1106 : goto bail;
- 1107 : /* LCOV_EXCL_STOP */
- 1108 : }
- 1109 :
- 1110 3254 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer));
- 1111 3254 : ++recovered_error;
- 1112 : }
- 1113 : }
- 1114 :
- 1115 : /* mark the file as opened at least one time */
- 1116 : /* this is used to avoid to check the unsynced and size */
- 1117 : /* more than one time, in case the file is reopened later */
- 1118 2065557 : file_flag_set(file, FILE_IS_OPENED);
- 1119 : }
- 1120 :
- 1121 : /* read from the file */
- 1122 5042801 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size,
- 1123 5042801 : log_error, state->opt.expected_missing ? log_expected : 0);
- 1124 5042801 : if (read_size == -1) {
- 1125 : /* save the failed block for the check/fix */
- 1126 442126 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */
- 1127 442126 : failed[failed_count].is_outofdate = 0;
- 1128 442126 : failed[failed_count].index = j;
- 1129 442126 : failed[failed_count].block = block;
- 1130 442126 : failed[failed_count].disk = disk;
- 1131 442126 : failed[failed_count].file = file;
- 1132 442126 : failed[failed_count].file_pos = file_pos;
- 1133 442126 : failed[failed_count].handle = &handle[j];
- 1134 442126 : ++failed_count;
- 1135 :
- 1136 442126 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
- 1137 442126 : ++error;
- 1138 442126 : continue;
- 1139 : }
- 1140 :
- 1141 4600675 : countsize += read_size;
- 1142 :
- 1143 : /* always insert CHG blocks, the repair functions needs all of them */
- 1144 : /* because the parity may be still referring at the old state */
- 1145 : /* and the repair must be aware of it */
- 1146 4600675 : if (block_state == BLOCK_STATE_CHG) {
- 1147 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */
- 1148 : /* if we don't have a hash, we always assume the first read of the block correct. */
- 1149 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */
- 1150 13843 : failed[failed_count].is_outofdate = 0;
- 1151 13843 : failed[failed_count].index = j;
- 1152 13843 : failed[failed_count].block = block;
- 1153 13843 : failed[failed_count].disk = disk;
- 1154 13843 : failed[failed_count].file = file;
- 1155 13843 : failed[failed_count].file_pos = file_pos;
- 1156 13843 : failed[failed_count].handle = &handle[j];
- 1157 13843 : ++failed_count;
- 1158 13843 : continue;
- 1159 : }
- 1160 :
- 1161 4586832 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
- 1162 :
- 1163 : /* compute the hash of the block just read */
- 1164 4586832 : if (rehash) {
- 1165 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
- 1166 : } else {
- 1167 4559589 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
+ 1007 : /* if we are only hashing, we can skip excluded files and don't even read them */
+ 1008 5236820 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1009 : /* use an empty block */
+ 1010 : /* in true, this is unnecessary, because we are not checking any parity */
+ 1011 : /* but we keep it for completeness */
+ 1012 0 : memset(buffer[j], 0, state->block_size);
+ 1013 0 : continue;
+ 1014 : }
+ 1015 :
+ 1016 : /* if the file is closed or different than the current one */
+ 1017 5236820 : if (handle[j].file == 0 || handle[j].file != file) {
+ 1018 : /* close the old one, if any */
+ 1019 2259927 : ret = handle_close(&handle[j]);
+ 1020 2259927 : if (ret == -1) {
+ 1021 : /* LCOV_EXCL_START */
+ 1022 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno));
+ 1023 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
+ 1024 : log_fatal("Stopping at block %u\n", i);
+ 1025 : ++unrecoverable_error;
+ 1026 : goto bail;
+ 1027 : /* LCOV_EXCL_STOP */
+ 1028 : }
+ 1029 :
+ 1030 : /* if fixing, and the file is not excluded, we must open for writing */
+ 1031 2259927 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1032 : /* if fixing, create the file, open for writing and resize if required */
+ 1033 771310 : ret = handle_create(&handle[j], file, state->file_mode);
+ 1034 771310 : if (ret == -1) {
+ 1035 : /* LCOV_EXCL_START */
+ 1036 : if (errno == EACCES) {
+ 1037 : log_fatal("WARNING! Please give write permission to the file.\n");
+ 1038 : } else {
+ 1039 : log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1040 : }
+ 1041 : log_fatal("Stopping at block %u\n", i);
+ 1042 : ++unrecoverable_error;
+ 1043 : goto bail;
+ 1044 : /* LCOV_EXCL_STOP */
+ 1045 : }
+ 1046 :
+ 1047 : /* check if the file was just created */
+ 1048 1542620 : if (handle[j].created != 0) {
+ 1049 : /* if fragmented, it may be reopened, so remember that the file */
+ 1050 : /* was originally missing */
+ 1051 113118 : file_flag_set(file, FILE_IS_CREATED);
+ 1052 : }
+ 1053 : } else {
+ 1054 : /* open the file only for reading */
+ 1055 1488617 : if (!file_flag_has(file, FILE_IS_MISSING))
+ 1056 1372878 : ret = handle_open(&handle[j], file, state->file_mode,
+ 1057 1372878 : log_error, state->opt.expected_missing ? log_expected : 0);
+ 1058 : else
+ 1059 115739 : ret = -1; /* if the file is missing, we cannot open it */
+ 1060 1488617 : if (ret == -1) {
+ 1061 : /* save the failed block for the check/fix */
+ 1062 194514 : failed[failed_count].is_bad = 1;
+ 1063 194514 : failed[failed_count].is_outofdate = 0;
+ 1064 194514 : failed[failed_count].index = j;
+ 1065 194514 : failed[failed_count].block = block;
+ 1066 194514 : failed[failed_count].disk = disk;
+ 1067 194514 : failed[failed_count].file = file;
+ 1068 194514 : failed[failed_count].file_pos = file_pos;
+ 1069 194514 : failed[failed_count].handle = &handle[j];
+ 1070 194514 : ++failed_count;
+ 1071 :
+ 1072 194514 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
+ 1073 194514 : ++error;
+ 1074 :
+ 1075 : /* mark the file as missing, to avoid to retry to open it again */
+ 1076 : /* note that this can be done only if we are not fixing it */
+ 1077 : /* otherwise, it could be recreated */
+ 1078 194514 : file_flag_set(file, FILE_IS_MISSING);
+ 1079 194514 : continue;
+ 1080 : }
+ 1081 : }
+ 1082 :
+ 1083 : /* if it's the first open, and not excluded */
+ 1084 2065413 : if (!file_flag_has(file, FILE_IS_OPENED)
+ 1085 2050030 : && !file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1086 :
+ 1087 : /* check if the file is changed */
+ 1088 1998599 : if (handle[j].st.st_size != file->size
+ 1089 1805915 : || handle[j].st.st_mtime != file->mtime_sec
+ 1090 1781217 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec
+ 1091 : /* don't check the inode to support file-system without persistent inodes */
+ 1092 : ) {
+ 1093 : /* report that the file is not synced */
+ 1094 217382 : file_flag_set(file, FILE_IS_UNSYNCED);
+ 1095 : }
+ 1096 : }
+ 1097 :
+ 1098 : /* if it's the first open, and not excluded and larger */
+ 1099 2065413 : if (!file_flag_has(file, FILE_IS_OPENED)
+ 1100 2050030 : && !file_flag_has(file, FILE_IS_EXCLUDED)
+ 1101 1998599 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))
+ 1102 1998599 : && handle[j].st.st_size > file->size
+ 1103 : ) {
+ 1104 8668 : log_error("File '%s' is larger than expected.\n", handle[j].path);
+ 1105 8668 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer));
+ 1106 8668 : ++error;
+ 1107 :
+ 1108 8668 : if (fix) {
+ 1109 3189 : ret = handle_truncate(&handle[j], file);
+ 1110 3189 : if (ret == -1) {
+ 1111 : /* LCOV_EXCL_START */
+ 1112 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n");
+ 1113 : log_fatal("Stopping at block %u\n", i);
+ 1114 : ++unrecoverable_error;
+ 1115 : goto bail;
+ 1116 : /* LCOV_EXCL_STOP */
+ 1117 : }
+ 1118 :
+ 1119 3189 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer));
+ 1120 3189 : ++recovered_error;
+ 1121 : }
+ 1122 : }
+ 1123 :
+ 1124 : /* mark the file as opened at least one time */
+ 1125 : /* this is used to avoid to check the unsynced and size */
+ 1126 : /* more than one time, in case the file is reopened later */
+ 1127 2065413 : file_flag_set(file, FILE_IS_OPENED);
+ 1128 : }
+ 1129 :
+ 1130 : /* read from the file */
+ 1131 5042306 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size,
+ 1132 5042306 : log_error, state->opt.expected_missing ? log_expected : 0);
+ 1133 5042306 : if (read_size == -1) {
+ 1134 : /* save the failed block for the check/fix */
+ 1135 442190 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */
+ 1136 442190 : failed[failed_count].is_outofdate = 0;
+ 1137 442190 : failed[failed_count].index = j;
+ 1138 442190 : failed[failed_count].block = block;
+ 1139 442190 : failed[failed_count].disk = disk;
+ 1140 442190 : failed[failed_count].file = file;
+ 1141 442190 : failed[failed_count].file_pos = file_pos;
+ 1142 442190 : failed[failed_count].handle = &handle[j];
+ 1143 442190 : ++failed_count;
+ 1144 :
+ 1145 442190 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
+ 1146 442190 : ++error;
+ 1147 442190 : continue;
+ 1148 : }
+ 1149 :
+ 1150 4600116 : countsize += read_size;
+ 1151 :
+ 1152 : /* always insert CHG blocks, the repair functions needs all of them */
+ 1153 : /* because the parity may be still referring at the old state */
+ 1154 : /* and the repair must be aware of it */
+ 1155 4600116 : if (block_state == BLOCK_STATE_CHG) {
+ 1156 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */
+ 1157 : /* if we don't have a hash, we always assume the first read of the block correct. */
+ 1158 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */
+ 1159 13843 : failed[failed_count].is_outofdate = 0;
+ 1160 13843 : failed[failed_count].index = j;
+ 1161 13843 : failed[failed_count].block = block;
+ 1162 13843 : failed[failed_count].disk = disk;
+ 1163 13843 : failed[failed_count].file = file;
+ 1164 13843 : failed[failed_count].file_pos = file_pos;
+ 1165 13843 : failed[failed_count].handle = &handle[j];
+ 1166 13843 : ++failed_count;
+ 1167 13843 : continue;
1168 : }
1169 :
- 1170 : /* compare the hash */
- 1171 4586832 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
- 1172 12768 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE);
- 1173 :
- 1174 : /* save the failed block for the check/fix */
- 1175 12768 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */
- 1176 12768 : failed[failed_count].is_outofdate = 0;
- 1177 12768 : failed[failed_count].index = j;
- 1178 12768 : failed[failed_count].block = block;
- 1179 12768 : failed[failed_count].disk = disk;
- 1180 12768 : failed[failed_count].file = file;
- 1181 12768 : failed[failed_count].file_pos = file_pos;
- 1182 12768 : failed[failed_count].handle = &handle[j];
- 1183 12768 : ++failed_count;
- 1184 :
- 1185 12768 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff);
- 1186 12768 : ++error;
- 1187 12768 : continue;
- 1188 : }
- 1189 :
- 1190 : /* always insert REP blocks, the repair functions needs all of them */
- 1191 : /* because the parity may be still referring at the old state */
- 1192 : /* and the repair must be aware of it */
- 1193 4574064 : if (block_state == BLOCK_STATE_REP) {
- 1194 53428 : failed[failed_count].is_bad = 0; /* it's not bad */
- 1195 53428 : failed[failed_count].is_outofdate = 0;
- 1196 53428 : failed[failed_count].index = j;
- 1197 53428 : failed[failed_count].block = block;
- 1198 53428 : failed[failed_count].disk = disk;
- 1199 53428 : failed[failed_count].file = file;
- 1200 53428 : failed[failed_count].file_pos = file_pos;
- 1201 53428 : failed[failed_count].handle = &handle[j];
- 1202 53428 : ++failed_count;
- 1203 53428 : continue;
- 1204 : }
- 1205 : }
- 1206 :
- 1207 : /* now read and check the parity if requested */
- 1208 910233 : if (!state->opt.auditonly) {
- 1209 : void* buffer_recov[LEV_MAX];
- 1210 : void* buffer_zero;
- 1211 :
- 1212 : /* buffers for parity read and not computed */
- 1213 4170787 : for (l = 0; l < state->level; ++l)
- 1214 3299829 : buffer_recov[l] = buffer[diskmax + state->level + l];
- 1215 2796877 : for (; l < LEV_MAX; ++l)
- 1216 1925919 : buffer_recov[l] = 0;
- 1217 :
- 1218 : /* the zero buffer is the last one */
- 1219 870958 : buffer_zero = buffer[buffermax - 1];
+ 1170 4586273 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP);
+ 1171 :
+ 1172 : /* compute the hash of the block just read */
+ 1173 4586273 : if (rehash) {
+ 1174 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size);
+ 1175 : } else {
+ 1176 4559030 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
+ 1177 : }
+ 1178 :
+ 1179 : /* compare the hash */
+ 1180 4586273 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
+ 1181 12862 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE);
+ 1182 :
+ 1183 : /* save the failed block for the check/fix */
+ 1184 12862 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */
+ 1185 12862 : failed[failed_count].is_outofdate = 0;
+ 1186 12862 : failed[failed_count].index = j;
+ 1187 12862 : failed[failed_count].block = block;
+ 1188 12862 : failed[failed_count].disk = disk;
+ 1189 12862 : failed[failed_count].file = file;
+ 1190 12862 : failed[failed_count].file_pos = file_pos;
+ 1191 12862 : failed[failed_count].handle = &handle[j];
+ 1192 12862 : ++failed_count;
+ 1193 :
+ 1194 12862 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8);
+ 1195 12862 : ++error;
+ 1196 12862 : continue;
+ 1197 : }
+ 1198 :
+ 1199 : /* always insert REP blocks, the repair functions needs all of them */
+ 1200 : /* because the parity may be still referring at the old state */
+ 1201 : /* and the repair must be aware of it */
+ 1202 4573411 : if (block_state == BLOCK_STATE_REP) {
+ 1203 53428 : failed[failed_count].is_bad = 0; /* it's not bad */
+ 1204 53428 : failed[failed_count].is_outofdate = 0;
+ 1205 53428 : failed[failed_count].index = j;
+ 1206 53428 : failed[failed_count].block = block;
+ 1207 53428 : failed[failed_count].disk = disk;
+ 1208 53428 : failed[failed_count].file = file;
+ 1209 53428 : failed[failed_count].file_pos = file_pos;
+ 1210 53428 : failed[failed_count].handle = &handle[j];
+ 1211 53428 : ++failed_count;
+ 1212 53428 : continue;
+ 1213 : }
+ 1214 : }
+ 1215 :
+ 1216 : /* now read and check the parity if requested */
+ 1217 910233 : if (!state->opt.auditonly) {
+ 1218 : void* buffer_recov[LEV_MAX];
+ 1219 : void* buffer_zero;
1220 :
- 1221 : /* read the parity */
- 1222 4170787 : for (l = 0; l < state->level; ++l) {
- 1223 3299829 : if (parity[l]) {
- 1224 3285927 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
- 1225 3285927 : if (ret == -1) {
- 1226 11360 : buffer_recov[l] = 0; /* no parity to use */
- 1227 :
- 1228 11360 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
- 1229 11360 : ++error;
- 1230 : }
- 1231 : } else {
- 1232 13902 : buffer_recov[l] = 0;
- 1233 : }
- 1234 : }
- 1235 :
- 1236 : /* try all the recovering strategies */
- 1237 870958 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero);
- 1238 870958 : if (ret != 0) {
- 1239 : /* increment the number of errors */
- 1240 47935 : if (ret > 0)
- 1241 4811 : error += ret;
- 1242 47935 : ++unrecoverable_error;
- 1243 :
- 1244 : /* print a list of all the errors in files */
- 1245 219126 : for (j = 0; j < failed_count; ++j) {
- 1246 171191 : if (failed[j].is_bad)
- 1247 166669 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
- 1248 : }
- 1249 :
- 1250 : /* keep track of damaged files */
- 1251 219126 : for (j = 0; j < failed_count; ++j) {
- 1252 171191 : if (failed[j].is_bad)
- 1253 166669 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
- 1254 : }
- 1255 : } else {
- 1256 : /* now counts partial recovers */
- 1257 : /* note that this could happen only when we have an incomplete 'sync' */
- 1258 : /* and that we have recovered is the state before the 'sync' */
- 1259 823023 : int partial_recover_error = 0;
- 1260 :
- 1261 : /* print a list of all the errors in files */
- 1262 1380653 : for (j = 0; j < failed_count; ++j) {
- 1263 557630 : if (failed[j].is_bad && failed[j].is_outofdate) {
- 1264 8 : ++partial_recover_error;
- 1265 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
- 1266 : }
- 1267 : }
- 1268 823023 : if (partial_recover_error != 0) {
- 1269 8 : error += partial_recover_error;
- 1270 8 : ++unrecoverable_error;
- 1271 : }
- 1272 :
- 1273 : /* now check parities, but only if all the blocks have it computed */
- 1274 : /* if you check/fix after a partial sync, it's OK to have parity errors on the blocks with invalid parity */
- 1275 : /* and doesn't make sense to try to fix it */
- 1276 823023 : if (valid_parity) {
- 1277 : /* check the parity */
- 1278 3728946 : for (l = 0; l < state->level; ++l) {
- 1279 2967508 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) {
- 1280 78680 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size);
+ 1221 : /* buffers for parity read and not computed */
+ 1222 4170787 : for (l = 0; l < state->level; ++l)
+ 1223 3299829 : buffer_recov[l] = buffer[diskmax + state->level + l];
+ 1224 2796877 : for (; l < LEV_MAX; ++l)
+ 1225 1925919 : buffer_recov[l] = 0;
+ 1226 :
+ 1227 : /* the zero buffer is the last one */
+ 1228 870958 : buffer_zero = buffer[buffermax - 1];
+ 1229 :
+ 1230 : /* read the parity */
+ 1231 4170787 : for (l = 0; l < state->level; ++l) {
+ 1232 3299829 : if (parity[l]) {
+ 1233 3285927 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
+ 1234 3285927 : if (ret == -1) {
+ 1235 11360 : buffer_recov[l] = 0; /* no parity to use */
+ 1236 :
+ 1237 11360 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
+ 1238 11360 : ++error;
+ 1239 : }
+ 1240 : } else {
+ 1241 13902 : buffer_recov[l] = 0;
+ 1242 : }
+ 1243 : }
+ 1244 :
+ 1245 : /* try all the recovering strategies */
+ 1246 870958 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero);
+ 1247 870958 : if (ret != 0) {
+ 1248 : /* increment the number of errors */
+ 1249 48016 : if (ret > 0)
+ 1250 4801 : error += ret;
+ 1251 48016 : ++unrecoverable_error;
+ 1252 :
+ 1253 : /* print a list of all the errors in files */
+ 1254 219379 : for (j = 0; j < failed_count; ++j) {
+ 1255 171363 : if (failed[j].is_bad)
+ 1256 166841 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
+ 1257 : }
+ 1258 :
+ 1259 : /* keep track of damaged files */
+ 1260 219379 : for (j = 0; j < failed_count; ++j) {
+ 1261 171363 : if (failed[j].is_bad)
+ 1262 166841 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1263 : }
+ 1264 : } else {
+ 1265 : /* now counts partial recovers */
+ 1266 : /* note that this could happen only when we have an incomplete 'sync' */
+ 1267 : /* and that we have recovered is the state before the 'sync' */
+ 1268 822942 : int partial_recover_error = 0;
+ 1269 :
+ 1270 : /* print a list of all the errors in files */
+ 1271 1380844 : for (j = 0; j < failed_count; ++j) {
+ 1272 557902 : if (failed[j].is_bad && failed[j].is_outofdate) {
+ 1273 8 : ++partial_recover_error;
+ 1274 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
+ 1275 : }
+ 1276 : }
+ 1277 822942 : if (partial_recover_error != 0) {
+ 1278 8 : error += partial_recover_error;
+ 1279 8 : ++unrecoverable_error;
+ 1280 : }
1281 :
- 1282 : /* mark that the read parity is wrong, setting ptr to 0 */
- 1283 78680 : buffer_recov[l] = 0;
- 1284 :
- 1285 78680 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff);
- 1286 78680 : ++error;
- 1287 : }
- 1288 : }
- 1289 : }
- 1290 :
- 1291 : /* now write recovered files */
- 1292 823023 : if (fix) {
- 1293 : /* update the fixed files */
- 1294 652640 : for (j = 0; j < failed_count; ++j) {
- 1295 : /* nothing to do if it doesn't need recovering */
- 1296 337975 : if (!failed[j].is_bad)
- 1297 40318 : continue;
- 1298 :
- 1299 : /* do not fix if the file is excluded */
- 1300 297657 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED)
- 1301 288377 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED)))
- 1302 9280 : continue;
- 1303 :
- 1304 288377 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size);
- 1305 288377 : if (ret == -1) {
- 1306 : /* LCOV_EXCL_START */
- 1307 : /* mark the file as damaged */
- 1308 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
- 1309 :
- 1310 : if (errno == EACCES) {
- 1311 : log_fatal("WARNING! Please give write permission to the file.\n");
- 1312 : } else {
- 1313 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1314 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1315 : }
- 1316 : log_fatal("Stopping at block %u\n", i);
- 1317 : ++unrecoverable_error;
- 1318 : goto bail;
- 1319 : /* LCOV_EXCL_STOP */
- 1320 : }
- 1321 :
- 1322 : /* if we are not sure that the recovered content is uptodate */
- 1323 288377 : if (failed[j].is_outofdate) {
- 1324 : /* mark the file as damaged */
- 1325 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
- 1326 8 : continue;
- 1327 : }
- 1328 :
- 1329 : /* mark the file as containing some fixes */
- 1330 : /* note that it could be also marked as damaged in other iterations */
- 1331 288369 : file_flag_set(failed[j].file, FILE_IS_FIXED);
- 1332 :
- 1333 288369 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
- 1334 288369 : ++recovered_error;
- 1335 : }
+ 1282 : /*
+ 1283 : * Check parities, but only if all the blocks have it computed and it's used.
+ 1284 : *
+ 1285 : * If you check/fix after a partial sync, it's OK to have parity errors
+ 1286 : * on the blocks with invalid parity and doesn't make sense to try to fix it.
+ 1287 : *
+ 1288 : * It's also OK to have data errors on unused parity, because sync doesn't
+ 1289 : * update it.
+ 1290 : */
+ 1291 822942 : if (used_parity && valid_parity) {
+ 1292 : /* check the parity */
+ 1293 3728784 : for (l = 0; l < state->level; ++l) {
+ 1294 2967427 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) {
+ 1295 78690 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size);
+ 1296 :
+ 1297 : /* mark that the read parity is wrong, setting ptr to 0 */
+ 1298 78690 : buffer_recov[l] = 0;
+ 1299 :
+ 1300 78690 : log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", i, lev_config_name(l), diff, state->block_size*8);
+ 1301 78690 : ++error;
+ 1302 : }
+ 1303 : }
+ 1304 : }
+ 1305 :
+ 1306 : /* now write recovered files */
+ 1307 822942 : if (fix) {
+ 1308 : /* update the fixed files */
+ 1309 652736 : for (j = 0; j < failed_count; ++j) {
+ 1310 : /* nothing to do if it doesn't need recovering */
+ 1311 338113 : if (!failed[j].is_bad)
+ 1312 40318 : continue;
+ 1313 :
+ 1314 : /* do not fix if the file is excluded */
+ 1315 297795 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED)
+ 1316 288515 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED)))
+ 1317 9280 : continue;
+ 1318 :
+ 1319 288515 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size);
+ 1320 288515 : if (ret == -1) {
+ 1321 : /* LCOV_EXCL_START */
+ 1322 : /* mark the file as damaged */
+ 1323 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1324 :
+ 1325 : if (errno == EACCES) {
+ 1326 : log_fatal("WARNING! Please give write permission to the file.\n");
+ 1327 : } else {
+ 1328 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1329 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1330 : }
+ 1331 : log_fatal("Stopping at block %u\n", i);
+ 1332 : ++unrecoverable_error;
+ 1333 : goto bail;
+ 1334 : /* LCOV_EXCL_STOP */
+ 1335 : }
1336 :
- 1337 : /* update parity only if all the blocks have it computed */
- 1338 : /* if you check/fix after a partial sync, you do not want to fix parity */
- 1339 : /* for blocks that are going to have it computed in the sync completion */
- 1340 314665 : if (valid_parity) {
- 1341 : /* update the parity */
- 1342 964055 : for (l = 0; l < state->level; ++l) {
- 1343 : /* if the parity on disk is wrong */
- 1344 698570 : if (buffer_recov[l] == 0
- 1345 : /* and we have access at the parity */
- 1346 72150 : && parity[l] != 0
- 1347 : /* and the parity is not excluded */
- 1348 67463 : && !state->parity[l].is_excluded
- 1349 : ) {
- 1350 67463 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
- 1351 67463 : if (ret == -1) {
- 1352 : /* LCOV_EXCL_START */
- 1353 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1354 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l));
- 1355 : log_fatal("Stopping at block %u\n", i);
- 1356 : ++unrecoverable_error;
- 1357 : goto bail;
- 1358 : /* LCOV_EXCL_STOP */
- 1359 : }
- 1360 :
- 1361 67463 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l));
- 1362 67463 : ++recovered_error;
- 1363 : }
- 1364 : }
- 1365 : }
- 1366 : } else {
- 1367 : /* if we are not fixing, we just set the FIXED flag */
- 1368 : /* meaning that we could fix this file if we try */
- 1369 728013 : for (j = 0; j < failed_count; ++j) {
- 1370 219655 : if (failed[j].is_bad) {
- 1371 178770 : file_flag_set(failed[j].file, FILE_IS_FIXED);
- 1372 : }
- 1373 : }
- 1374 : }
- 1375 : }
- 1376 : } else {
- 1377 : /* if we are not checking, we just set the DAMAGED flag */
- 1378 : /* to report that the file is damaged, and we don't know if we can fix it */
- 1379 45092 : for (j = 0; j < failed_count; ++j) {
- 1380 5817 : if (failed[j].is_bad) {
- 1381 5817 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
- 1382 : }
- 1383 : }
- 1384 : }
- 1385 :
- 1386 : /* post process the files */
- 1387 910233 : ret = file_post(state, fix, i, handle, diskmax);
- 1388 910233 : if (ret == -1) {
- 1389 : /* LCOV_EXCL_START */
- 1390 : log_fatal("Stopping at block %u\n", i);
- 1391 : ++unrecoverable_error;
- 1392 : goto bail;
- 1393 : /* LCOV_EXCL_STOP */
- 1394 : }
- 1395 :
- 1396 : /* count the number of processed block */
- 1397 910233 : ++countpos;
- 1398 :
- 1399 : /* progress */
- 1400 910233 : if (state_progress(state, 0, i, countpos, countmax, countsize)) {
- 1401 : /* LCOV_EXCL_START */
- 1402 : break;
- 1403 : /* LCOV_EXCL_STOP */
- 1404 : }
- 1405 : }
- 1406 :
- 1407 : /* for each disk, recover empty files, symlinks and empty dirs */
- 1408 826 : for (i = 0; i < diskmax; ++i) {
- 1409 : tommy_node* node;
- 1410 : struct snapraid_disk* disk;
- 1411 :
- 1412 708 : if (!handle[i].disk)
- 1413 3 : continue;
- 1414 :
- 1415 : /* for each empty file in the disk */
- 1416 705 : disk = handle[i].disk;
- 1417 705 : node = disk->filelist;
- 1418 2189135 : while (node) {
- 1419 : char path[PATH_MAX];
- 1420 : struct stat st;
- 1421 : struct snapraid_file* file;
- 1422 2187725 : int unsuccesful = 0;
- 1423 :
- 1424 2187725 : file = node->data;
- 1425 2187725 : node = node->next; /* next node */
- 1426 :
- 1427 : /* if not empty, it's already checked and continue to the next one */
- 1428 2187725 : if (file->size != 0) {
- 1429 4369715 : continue;
- 1430 : }
- 1431 :
- 1432 : /* if excluded continue to the next one */
- 1433 2952 : if (file_flag_has(file, FILE_IS_EXCLUDED)) {
- 1434 169 : continue;
- 1435 : }
+ 1337 : /* if we are not sure that the recovered content is uptodate */
+ 1338 288515 : if (failed[j].is_outofdate) {
+ 1339 : /* mark the file as damaged */
+ 1340 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1341 8 : continue;
+ 1342 : }
+ 1343 :
+ 1344 : /* mark the file as containing some fixes */
+ 1345 : /* note that it could be also marked as damaged in other iterations */
+ 1346 288507 : file_flag_set(failed[j].file, FILE_IS_FIXED);
+ 1347 :
+ 1348 288507 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos);
+ 1349 288507 : ++recovered_error;
+ 1350 : }
+ 1351 :
+ 1352 : /*
+ 1353 : * Update parity only if all the blocks have it computed and it's used.
+ 1354 : *
+ 1355 : * If you check/fix after a partial sync, you do not want to fix parity
+ 1356 : * for blocks that are going to have it computed in the sync completion.
+ 1357 : *
+ 1358 : * For unused parity there is no need to write it, because when fixing
+ 1359 : * we already have allocated space for it on parity file creation,
+ 1360 : * and its content doesn't matter.
+ 1361 : */
+ 1362 314623 : if (used_parity && valid_parity) {
+ 1363 : /* update the parity */
+ 1364 963971 : for (l = 0; l < state->level; ++l) {
+ 1365 : /* if the parity on disk is wrong */
+ 1366 698528 : if (buffer_recov[l] == 0
+ 1367 : /* and we have access at the parity */
+ 1368 72150 : && parity[l] != 0
+ 1369 : /* and the parity is not excluded */
+ 1370 67463 : && !state->parity[l].is_excluded_by_filter
+ 1371 : ) {
+ 1372 67463 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
+ 1373 67463 : if (ret == -1) {
+ 1374 : /* LCOV_EXCL_START */
+ 1375 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1376 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l));
+ 1377 : log_fatal("Stopping at block %u\n", i);
+ 1378 : ++unrecoverable_error;
+ 1379 : goto bail;
+ 1380 : /* LCOV_EXCL_STOP */
+ 1381 : }
+ 1382 :
+ 1383 67463 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l));
+ 1384 67463 : ++recovered_error;
+ 1385 : }
+ 1386 : }
+ 1387 : }
+ 1388 : } else {
+ 1389 : /* if we are not fixing, we just set the FIXED flag */
+ 1390 : /* meaning that we could fix this file if we try */
+ 1391 728108 : for (j = 0; j < failed_count; ++j) {
+ 1392 219789 : if (failed[j].is_bad) {
+ 1393 178904 : file_flag_set(failed[j].file, FILE_IS_FIXED);
+ 1394 : }
+ 1395 : }
+ 1396 : }
+ 1397 : }
+ 1398 : } else {
+ 1399 : /* if we are not checking, we just set the DAMAGED flag */
+ 1400 : /* to report that the file is damaged, and we don't know if we can fix it */
+ 1401 45301 : for (j = 0; j < failed_count; ++j) {
+ 1402 6026 : if (failed[j].is_bad) {
+ 1403 6026 : file_flag_set(failed[j].file, FILE_IS_DAMAGED);
+ 1404 : }
+ 1405 : }
+ 1406 : }
+ 1407 :
+ 1408 : /* post process the files */
+ 1409 910233 : ret = file_post(state, fix, i, handle, diskmax);
+ 1410 910233 : if (ret == -1) {
+ 1411 : /* LCOV_EXCL_START */
+ 1412 : log_fatal("Stopping at block %u\n", i);
+ 1413 : ++unrecoverable_error;
+ 1414 : goto bail;
+ 1415 : /* LCOV_EXCL_STOP */
+ 1416 : }
+ 1417 :
+ 1418 : /* count the number of processed block */
+ 1419 910233 : ++countpos;
+ 1420 :
+ 1421 : /* progress */
+ 1422 910233 : if (state_progress(state, 0, i, countpos, countmax, countsize)) {
+ 1423 : /* LCOV_EXCL_START */
+ 1424 : break;
+ 1425 : /* LCOV_EXCL_STOP */
+ 1426 : }
+ 1427 : }
+ 1428 :
+ 1429 : /* for each disk, recover empty files, symlinks and empty dirs */
+ 1430 826 : for (i = 0; i < diskmax; ++i) {
+ 1431 : tommy_node* node;
+ 1432 : struct snapraid_disk* disk;
+ 1433 :
+ 1434 708 : if (!handle[i].disk)
+ 1435 3 : continue;
1436 :
- 1437 : /* stat the file */
- 1438 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
- 1439 2783 : ret = stat(path, &st);
- 1440 2783 : if (ret == -1) {
- 1441 179 : unsuccesful = 1;
- 1442 :
- 1443 179 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno));
- 1444 179 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer));
- 1445 179 : ++error;
- 1446 2604 : } else if (!S_ISREG(st.st_mode)) {
- 1447 0 : unsuccesful = 1;
+ 1437 : /* for each empty file in the disk */
+ 1438 705 : disk = handle[i].disk;
+ 1439 705 : node = disk->filelist;
+ 1440 2189135 : while (node) {
+ 1441 : char path[PATH_MAX];
+ 1442 : struct stat st;
+ 1443 : struct snapraid_file* file;
+ 1444 2187725 : int unsuccesful = 0;
+ 1445 :
+ 1446 2187725 : file = node->data;
+ 1447 2187725 : node = node->next; /* next node */
1448 :
- 1449 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer));
- 1450 0 : ++error;
- 1451 2604 : } else if (st.st_size != 0) {
- 1452 6 : unsuccesful = 1;
+ 1449 : /* if not empty, it's already checked and continue to the next one */
+ 1450 2187725 : if (file->size != 0) {
+ 1451 4369715 : continue;
+ 1452 : }
1453 :
- 1454 6 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), st.st_size);
- 1455 6 : ++error;
- 1456 : }
- 1457 :
- 1458 2783 : if (fix && unsuccesful) {
- 1459 : int f;
- 1460 :
- 1461 : /* create the ancestor directories */
- 1462 159 : ret = mkancestor(path);
- 1463 159 : if (ret != 0) {
- 1464 : /* LCOV_EXCL_START */
- 1465 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1466 : log_fatal("Stopping\n");
- 1467 : ++unrecoverable_error;
- 1468 : goto bail;
- 1469 : /* LCOV_EXCL_STOP */
- 1470 : }
- 1471 :
- 1472 : /* create it */
- 1473 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
- 1474 159 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600);
- 1475 159 : if (f == -1) {
- 1476 : /* LCOV_EXCL_START */
- 1477 : log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno));
- 1478 : if (errno == EACCES) {
- 1479 : log_fatal("WARNING! Please give write permission to the file.\n");
- 1480 : } else {
- 1481 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1482 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1483 : }
- 1484 : log_fatal("Stopping\n");
- 1485 : ++unrecoverable_error;
- 1486 : goto bail;
- 1487 : /* LCOV_EXCL_STOP */
- 1488 : }
- 1489 :
- 1490 : /* set the original modification time */
- 1491 159 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec);
- 1492 159 : if (ret != 0) {
- 1493 : /* LCOV_EXCL_START */
- 1494 : close(f);
- 1495 :
- 1496 : log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno));
- 1497 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1498 : log_fatal("Stopping\n");
- 1499 : ++unrecoverable_error;
- 1500 : goto bail;
- 1501 : /* LCOV_EXCL_STOP */
- 1502 : }
- 1503 :
- 1504 : /* close it */
- 1505 159 : ret = close(f);
- 1506 159 : if (ret != 0) {
- 1507 : /* LCOV_EXCL_START */
- 1508 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1509 : log_fatal("Stopping\n");
- 1510 : ++unrecoverable_error;
- 1511 : goto bail;
- 1512 : /* LCOV_EXCL_STOP */
- 1513 : }
- 1514 :
- 1515 159 : log_tag("fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer));
- 1516 159 : ++recovered_error;
+ 1454 : /* if excluded continue to the next one */
+ 1455 2952 : if (file_flag_has(file, FILE_IS_EXCLUDED)) {
+ 1456 169 : continue;
+ 1457 : }
+ 1458 :
+ 1459 : /* stat the file */
+ 1460 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
+ 1461 2783 : ret = stat(path, &st);
+ 1462 2783 : if (ret == -1) {
+ 1463 171 : unsuccesful = 1;
+ 1464 :
+ 1465 171 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno));
+ 1466 171 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 1467 171 : ++error;
+ 1468 2612 : } else if (!S_ISREG(st.st_mode)) {
+ 1469 0 : unsuccesful = 1;
+ 1470 :
+ 1471 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 1472 0 : ++error;
+ 1473 2612 : } else if (st.st_size != 0) {
+ 1474 9 : unsuccesful = 1;
+ 1475 :
+ 1476 9 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), st.st_size);
+ 1477 9 : ++error;
+ 1478 : }
+ 1479 :
+ 1480 2783 : if (fix && unsuccesful) {
+ 1481 : int f;
+ 1482 :
+ 1483 : /* create the ancestor directories */
+ 1484 158 : ret = mkancestor(path);
+ 1485 158 : if (ret != 0) {
+ 1486 : /* LCOV_EXCL_START */
+ 1487 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1488 : log_fatal("Stopping\n");
+ 1489 : ++unrecoverable_error;
+ 1490 : goto bail;
+ 1491 : /* LCOV_EXCL_STOP */
+ 1492 : }
+ 1493 :
+ 1494 : /* create it */
+ 1495 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
+ 1496 158 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600);
+ 1497 158 : if (f == -1) {
+ 1498 : /* LCOV_EXCL_START */
+ 1499 : log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno));
+ 1500 : if (errno == EACCES) {
+ 1501 : log_fatal("WARNING! Please give write permission to the file.\n");
+ 1502 : } else {
+ 1503 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1504 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1505 : }
+ 1506 : log_fatal("Stopping\n");
+ 1507 : ++unrecoverable_error;
+ 1508 : goto bail;
+ 1509 : /* LCOV_EXCL_STOP */
+ 1510 : }
+ 1511 :
+ 1512 : /* set the original modification time */
+ 1513 158 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec);
+ 1514 158 : if (ret != 0) {
+ 1515 : /* LCOV_EXCL_START */
+ 1516 : close(f);
1517 :
- 1518 159 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
- 1519 159 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer));
- 1520 : }
- 1521 : }
- 1522 :
- 1523 : /* for each link in the disk */
- 1524 705 : disk = handle[i].disk;
- 1525 705 : node = disk->linklist;
- 1526 71537 : while (node) {
- 1527 : char path[PATH_MAX];
- 1528 : char pathto[PATH_MAX];
- 1529 : char linkto[PATH_MAX];
- 1530 : struct stat st;
- 1531 : struct stat stto;
- 1532 : struct snapraid_link* slink;
- 1533 70127 : int unsuccesful = 0;
- 1534 70127 : int unrecoverable = 0;
- 1535 :
- 1536 70127 : slink = node->data;
- 1537 70127 : node = node->next; /* next node */
- 1538 :
- 1539 : /* if excluded continue to the next one */
- 1540 70127 : if (link_flag_has(slink, FILE_IS_EXCLUDED)) {
- 1541 3277 : continue;
+ 1518 : log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno));
+ 1519 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1520 : log_fatal("Stopping\n");
+ 1521 : ++unrecoverable_error;
+ 1522 : goto bail;
+ 1523 : /* LCOV_EXCL_STOP */
+ 1524 : }
+ 1525 :
+ 1526 : /* close it */
+ 1527 158 : ret = close(f);
+ 1528 158 : if (ret != 0) {
+ 1529 : /* LCOV_EXCL_START */
+ 1530 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1531 : log_fatal("Stopping\n");
+ 1532 : ++unrecoverable_error;
+ 1533 : goto bail;
+ 1534 : /* LCOV_EXCL_STOP */
+ 1535 : }
+ 1536 :
+ 1537 158 : log_tag("fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 1538 158 : ++recovered_error;
+ 1539 :
+ 1540 158 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
+ 1541 158 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer));
1542 : }
- 1543 :
- 1544 66850 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
- 1545 : /* stat the link */
- 1546 318 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub);
- 1547 318 : ret = stat(path, &st);
- 1548 318 : if (ret == -1) {
- 1549 36 : unsuccesful = 1;
- 1550 :
- 1551 36 : log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno));
- 1552 36 : log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
- 1553 36 : ++error;
- 1554 282 : } else if (!S_ISREG(st.st_mode)) {
- 1555 0 : unsuccesful = 1;
- 1556 :
- 1557 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
- 1558 0 : ++error;
- 1559 : }
+ 1543 : }
+ 1544 :
+ 1545 : /* for each link in the disk */
+ 1546 705 : disk = handle[i].disk;
+ 1547 705 : node = disk->linklist;
+ 1548 71537 : while (node) {
+ 1549 : char path[PATH_MAX];
+ 1550 : char pathto[PATH_MAX];
+ 1551 : char linkto[PATH_MAX];
+ 1552 : struct stat st;
+ 1553 : struct stat stto;
+ 1554 : struct snapraid_link* slink;
+ 1555 70127 : int unsuccesful = 0;
+ 1556 70127 : int unrecoverable = 0;
+ 1557 :
+ 1558 70127 : slink = node->data;
+ 1559 70127 : node = node->next; /* next node */
1560 :
- 1561 : /* stat the "to" file */
- 1562 318 : pathprint(pathto, sizeof(pathto), "%s%s", disk->dir, slink->linkto);
- 1563 318 : ret = stat(pathto, &stto);
- 1564 318 : if (ret == -1) {
- 1565 24 : unsuccesful = 1;
- 1566 :
- 1567 24 : if (errno == ENOENT) {
- 1568 24 : unrecoverable = 1;
- 1569 24 : if (fix) {
- 1570 : /* if the target doesn't exist, it's unrecoverable */
- 1571 : /* because we cannot create an hardlink of a file that */
- 1572 : /* doesn't exists */
- 1573 12 : ++unrecoverable_error;
- 1574 : } else {
- 1575 : /* but in check, we can assume that fixing will recover */
- 1576 : /* such missing file, so we assume a less drastic error */
- 1577 12 : ++error;
- 1578 : }
- 1579 : }
- 1580 :
- 1581 24 : log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno));
- 1582 24 : log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
- 1583 24 : ++error;
- 1584 294 : } else if (!S_ISREG(stto.st_mode)) {
- 1585 0 : unsuccesful = 1;
- 1586 :
- 1587 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
- 1588 0 : ++error;
- 1589 294 : } else if (!unsuccesful && st.st_ino != stto.st_ino) {
- 1590 0 : unsuccesful = 1;
- 1591 :
- 1592 0 : log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto);
- 1593 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
- 1594 0 : ++error;
- 1595 : }
- 1596 : } else {
- 1597 : /* read the symlink */
- 1598 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub);
- 1599 66532 : ret = readlink(path, linkto, sizeof(linkto));
- 1600 66532 : if (ret < 0) {
- 1601 4278 : unsuccesful = 1;
+ 1561 : /* if excluded continue to the next one */
+ 1562 70127 : if (link_flag_has(slink, FILE_IS_EXCLUDED)) {
+ 1563 3277 : continue;
+ 1564 : }
+ 1565 :
+ 1566 66850 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
+ 1567 : /* stat the link */
+ 1568 318 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub);
+ 1569 318 : ret = stat(path, &st);
+ 1570 318 : if (ret == -1) {
+ 1571 36 : unsuccesful = 1;
+ 1572 :
+ 1573 36 : log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno));
+ 1574 36 : log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
+ 1575 36 : ++error;
+ 1576 282 : } else if (!S_ISREG(st.st_mode)) {
+ 1577 0 : unsuccesful = 1;
+ 1578 :
+ 1579 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
+ 1580 0 : ++error;
+ 1581 : }
+ 1582 :
+ 1583 : /* stat the "to" file */
+ 1584 318 : pathprint(pathto, sizeof(pathto), "%s%s", disk->dir, slink->linkto);
+ 1585 318 : ret = stat(pathto, &stto);
+ 1586 318 : if (ret == -1) {
+ 1587 24 : unsuccesful = 1;
+ 1588 :
+ 1589 24 : if (errno == ENOENT) {
+ 1590 24 : unrecoverable = 1;
+ 1591 24 : if (fix) {
+ 1592 : /* if the target doesn't exist, it's unrecoverable */
+ 1593 : /* because we cannot create an hardlink of a file that */
+ 1594 : /* doesn't exists */
+ 1595 12 : ++unrecoverable_error;
+ 1596 : } else {
+ 1597 : /* but in check, we can assume that fixing will recover */
+ 1598 : /* such missing file, so we assume a less drastic error */
+ 1599 12 : ++error;
+ 1600 : }
+ 1601 : }
1602 :
- 1603 4278 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno));
- 1604 4278 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
- 1605 4278 : ++error;
- 1606 62254 : } else if (ret >= PATH_MAX) {
+ 1603 24 : log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno));
+ 1604 24 : log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
+ 1605 24 : ++error;
+ 1606 294 : } else if (!S_ISREG(stto.st_mode)) {
1607 0 : unsuccesful = 1;
1608 :
- 1609 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path);
- 1610 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
- 1611 0 : ++error;
- 1612 : } else {
- 1613 62254 : linkto[ret] = 0;
- 1614 :
- 1615 62254 : if (strcmp(linkto, slink->linkto) != 0) {
- 1616 555 : unsuccesful = 1;
- 1617 :
- 1618 555 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto);
- 1619 555 : ++error;
- 1620 : }
- 1621 : }
- 1622 : }
- 1623 :
- 1624 66850 : if (fix && unsuccesful && !unrecoverable) {
- 1625 : /* create the ancestor directories */
- 1626 3941 : ret = mkancestor(path);
- 1627 3941 : if (ret != 0) {
- 1628 : /* LCOV_EXCL_START */
- 1629 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1630 : log_fatal("Stopping\n");
- 1631 : ++unrecoverable_error;
- 1632 : goto bail;
- 1633 : /* LCOV_EXCL_STOP */
- 1634 : }
- 1635 :
- 1636 : /* if it exists, it must be deleted before recreating */
- 1637 3941 : ret = remove(path);
- 1638 3941 : if (ret != 0 && errno != ENOENT) {
- 1639 : /* LCOV_EXCL_START */
- 1640 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
- 1641 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1642 : log_fatal("Stopping\n");
- 1643 : ++unrecoverable_error;
- 1644 : goto bail;
- 1645 : /* LCOV_EXCL_STOP */
- 1646 : }
- 1647 :
- 1648 : /* create it */
- 1649 3941 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
- 1650 12 : ret = hardlink(pathto, path);
- 1651 12 : if (ret != 0) {
- 1652 : /* LCOV_EXCL_START */
- 1653 : log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno));
- 1654 : if (errno == EACCES) {
- 1655 : log_fatal("WARNING! Please give write permission to the hardlink.\n");
- 1656 : } else {
- 1657 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1658 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1659 : }
- 1660 : log_fatal("Stopping\n");
- 1661 : ++unrecoverable_error;
- 1662 : goto bail;
- 1663 : /* LCOV_EXCL_STOP */
- 1664 : }
- 1665 :
- 1666 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc_tag(slink->sub, esc_buffer));
- 1667 12 : ++recovered_error;
- 1668 : } else {
- 1669 3929 : ret = symlink(slink->linkto, path);
- 1670 3929 : if (ret != 0) {
- 1671 : /* LCOV_EXCL_START */
- 1672 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno));
- 1673 : if (errno == EACCES) {
- 1674 : log_fatal("WARNING! Please give write permission to the symlink.\n");
- 1675 : } else {
- 1676 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1677 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1678 : }
- 1679 : log_fatal("Stopping\n");
- 1680 : ++unrecoverable_error;
- 1681 : goto bail;
- 1682 : /* LCOV_EXCL_STOP */
- 1683 : }
- 1684 :
- 1685 3929 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc_tag(slink->sub, esc_buffer));
- 1686 3929 : ++recovered_error;
- 1687 : }
- 1688 :
- 1689 3941 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
- 1690 3941 : msg_info("recovered %s\n", fmt_term(disk, slink->sub, esc_buffer));
- 1691 : }
- 1692 : }
- 1693 :
- 1694 : /* for each dir in the disk */
- 1695 705 : disk = handle[i].disk;
- 1696 705 : node = disk->dirlist;
- 1697 1850 : while (node) {
- 1698 : char path[PATH_MAX];
- 1699 : struct stat st;
- 1700 : struct snapraid_dir* dir;
- 1701 440 : int unsuccesful = 0;
- 1702 :
- 1703 440 : dir = node->data;
- 1704 440 : node = node->next; /* next node */
- 1705 :
- 1706 : /* if excluded continue to the next one */
- 1707 440 : if (dir_flag_has(dir, FILE_IS_EXCLUDED)) {
- 1708 19 : continue;
- 1709 : }
+ 1609 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
+ 1610 0 : ++error;
+ 1611 294 : } else if (!unsuccesful && st.st_ino != stto.st_ino) {
+ 1612 0 : unsuccesful = 1;
+ 1613 :
+ 1614 0 : log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto);
+ 1615 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
+ 1616 0 : ++error;
+ 1617 : }
+ 1618 : } else {
+ 1619 : /* read the symlink */
+ 1620 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub);
+ 1621 66532 : ret = readlink(path, linkto, sizeof(linkto));
+ 1622 66532 : if (ret < 0) {
+ 1623 4300 : unsuccesful = 1;
+ 1624 :
+ 1625 4300 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno));
+ 1626 4300 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
+ 1627 4300 : ++error;
+ 1628 62232 : } else if (ret >= PATH_MAX) {
+ 1629 0 : unsuccesful = 1;
+ 1630 :
+ 1631 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path);
+ 1632 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
+ 1633 0 : ++error;
+ 1634 : } else {
+ 1635 62232 : linkto[ret] = 0;
+ 1636 :
+ 1637 62232 : if (strcmp(linkto, slink->linkto) != 0) {
+ 1638 536 : unsuccesful = 1;
+ 1639 :
+ 1640 536 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto);
+ 1641 536 : ++error;
+ 1642 : }
+ 1643 : }
+ 1644 : }
+ 1645 :
+ 1646 66850 : if (fix && unsuccesful && !unrecoverable) {
+ 1647 : /* create the ancestor directories */
+ 1648 3942 : ret = mkancestor(path);
+ 1649 3942 : if (ret != 0) {
+ 1650 : /* LCOV_EXCL_START */
+ 1651 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1652 : log_fatal("Stopping\n");
+ 1653 : ++unrecoverable_error;
+ 1654 : goto bail;
+ 1655 : /* LCOV_EXCL_STOP */
+ 1656 : }
+ 1657 :
+ 1658 : /* if it exists, it must be deleted before recreating */
+ 1659 3942 : ret = remove(path);
+ 1660 3942 : if (ret != 0 && errno != ENOENT) {
+ 1661 : /* LCOV_EXCL_START */
+ 1662 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
+ 1663 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1664 : log_fatal("Stopping\n");
+ 1665 : ++unrecoverable_error;
+ 1666 : goto bail;
+ 1667 : /* LCOV_EXCL_STOP */
+ 1668 : }
+ 1669 :
+ 1670 : /* create it */
+ 1671 3942 : if (link_flag_has(slink, FILE_IS_HARDLINK)) {
+ 1672 12 : ret = hardlink(pathto, path);
+ 1673 12 : if (ret != 0) {
+ 1674 : /* LCOV_EXCL_START */
+ 1675 : log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno));
+ 1676 : if (errno == EACCES) {
+ 1677 : log_fatal("WARNING! Please give write permission to the hardlink.\n");
+ 1678 : } else {
+ 1679 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1680 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1681 : }
+ 1682 : log_fatal("Stopping\n");
+ 1683 : ++unrecoverable_error;
+ 1684 : goto bail;
+ 1685 : /* LCOV_EXCL_STOP */
+ 1686 : }
+ 1687 :
+ 1688 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc_tag(slink->sub, esc_buffer));
+ 1689 12 : ++recovered_error;
+ 1690 : } else {
+ 1691 3930 : ret = symlink(slink->linkto, path);
+ 1692 3930 : if (ret != 0) {
+ 1693 : /* LCOV_EXCL_START */
+ 1694 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno));
+ 1695 : if (errno == EACCES) {
+ 1696 : log_fatal("WARNING! Please give write permission to the symlink.\n");
+ 1697 : } else {
+ 1698 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1699 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1700 : }
+ 1701 : log_fatal("Stopping\n");
+ 1702 : ++unrecoverable_error;
+ 1703 : goto bail;
+ 1704 : /* LCOV_EXCL_STOP */
+ 1705 : }
+ 1706 :
+ 1707 3930 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc_tag(slink->sub, esc_buffer));
+ 1708 3930 : ++recovered_error;
+ 1709 : }
1710 :
- 1711 : /* stat the dir */
- 1712 421 : pathprint(path, sizeof(path), "%s%s", disk->dir, dir->sub);
- 1713 421 : ret = stat(path, &st);
- 1714 421 : if (ret == -1) {
- 1715 23 : unsuccesful = 1;
- 1716 :
- 1717 23 : log_error("Error stating dir '%s'. %s.\n", path, strerror(errno));
- 1718 23 : log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer));
- 1719 23 : ++error;
- 1720 398 : } else if (!S_ISDIR(st.st_mode)) {
- 1721 0 : unsuccesful = 1;
- 1722 :
- 1723 0 : log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer));
- 1724 0 : ++error;
- 1725 : }
- 1726 :
- 1727 421 : if (fix && unsuccesful) {
- 1728 : /* create the ancestor directories */
- 1729 21 : ret = mkancestor(path);
- 1730 21 : if (ret != 0) {
- 1731 : /* LCOV_EXCL_START */
- 1732 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1733 : log_fatal("Stopping\n");
- 1734 : ++unrecoverable_error;
- 1735 : goto bail;
- 1736 : /* LCOV_EXCL_STOP */
- 1737 : }
+ 1711 3942 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
+ 1712 3942 : msg_info("recovered %s\n", fmt_term(disk, slink->sub, esc_buffer));
+ 1713 : }
+ 1714 : }
+ 1715 :
+ 1716 : /* for each dir in the disk */
+ 1717 705 : disk = handle[i].disk;
+ 1718 705 : node = disk->dirlist;
+ 1719 1850 : while (node) {
+ 1720 : char path[PATH_MAX];
+ 1721 : struct stat st;
+ 1722 : struct snapraid_dir* dir;
+ 1723 440 : int unsuccesful = 0;
+ 1724 :
+ 1725 440 : dir = node->data;
+ 1726 440 : node = node->next; /* next node */
+ 1727 :
+ 1728 : /* if excluded continue to the next one */
+ 1729 440 : if (dir_flag_has(dir, FILE_IS_EXCLUDED)) {
+ 1730 19 : continue;
+ 1731 : }
+ 1732 :
+ 1733 : /* stat the dir */
+ 1734 421 : pathprint(path, sizeof(path), "%s%s", disk->dir, dir->sub);
+ 1735 421 : ret = stat(path, &st);
+ 1736 421 : if (ret == -1) {
+ 1737 23 : unsuccesful = 1;
1738 :
- 1739 : /* create it */
- 1740 21 : ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
- 1741 21 : if (ret != 0) {
- 1742 : /* LCOV_EXCL_START */
- 1743 : log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno));
- 1744 : if (errno == EACCES) {
- 1745 : log_fatal("WARNING! Please give write permission to the dir.\n");
- 1746 : } else {
- 1747 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
- 1748 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1749 : }
- 1750 : log_fatal("Stopping\n");
- 1751 : ++unrecoverable_error;
- 1752 : goto bail;
- 1753 : /* LCOV_EXCL_STOP */
- 1754 : }
- 1755 :
- 1756 21 : log_tag("dir_fixed:%s:%s: Fixed dir error\n", disk->name, esc_tag(dir->sub, esc_buffer));
- 1757 21 : ++recovered_error;
- 1758 :
- 1759 21 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(dir->sub, esc_buffer));
- 1760 21 : msg_info("recovered %s\n", fmt_term(disk, dir->sub, esc_buffer));
- 1761 : }
- 1762 : }
- 1763 : }
- 1764 :
- 1765 118 : state_progress_end(state, countpos, countmax, countsize);
- 1766 :
- 1767 : bail:
- 1768 : /* close all the files left open */
- 1769 826 : for (j = 0; j < diskmax; ++j) {
- 1770 708 : struct snapraid_file* file = handle[j].file;
- 1771 708 : struct snapraid_disk* disk = handle[j].disk;
- 1772 708 : ret = handle_close(&handle[j]);
- 1773 708 : if (ret == -1) {
- 1774 : /* LCOV_EXCL_START */
- 1775 : log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
- 1776 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
- 1777 : ++unrecoverable_error;
- 1778 : /* continue, as we are already exiting */
- 1779 : /* LCOV_EXCL_STOP */
- 1780 : }
- 1781 : }
- 1782 :
- 1783 : /* remove all the files created from scratch that have not finished the processing */
- 1784 : /* it happens only when aborting pressing Ctrl+C or other reason. */
- 1785 118 : if (fix) {
- 1786 : /* for each disk */
- 1787 315 : for (i = 0; i < diskmax; ++i) {
- 1788 : tommy_node* node;
- 1789 : struct snapraid_disk* disk;
- 1790 :
- 1791 270 : if (!handle[i].disk)
- 1792 1 : continue;
- 1793 :
- 1794 : /* for each file in the disk */
- 1795 269 : disk = handle[i].disk;
- 1796 269 : node = disk->filelist;
- 1797 870849 : while (node) {
- 1798 : char path[PATH_MAX];
- 1799 : struct snapraid_file* file;
- 1800 :
- 1801 870311 : file = node->data;
- 1802 870311 : node = node->next; /* next node */
- 1803 :
- 1804 : /* if the file was not created, meaning that it was already existing */
- 1805 870311 : if (!file_flag_has(file, FILE_IS_CREATED)) {
- 1806 : /* nothing to do */
- 1807 1627578 : continue;
- 1808 : }
- 1809 :
- 1810 : /* if processing was finished */
- 1811 113044 : if (file_flag_has(file, FILE_IS_FINISHED)) {
- 1812 : /* nothing to do */
- 1813 113044 : continue;
- 1814 : }
+ 1739 23 : log_error("Error stating dir '%s'. %s.\n", path, strerror(errno));
+ 1740 23 : log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer));
+ 1741 23 : ++error;
+ 1742 398 : } else if (!S_ISDIR(st.st_mode)) {
+ 1743 0 : unsuccesful = 1;
+ 1744 :
+ 1745 0 : log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer));
+ 1746 0 : ++error;
+ 1747 : }
+ 1748 :
+ 1749 421 : if (fix && unsuccesful) {
+ 1750 : /* create the ancestor directories */
+ 1751 21 : ret = mkancestor(path);
+ 1752 21 : if (ret != 0) {
+ 1753 : /* LCOV_EXCL_START */
+ 1754 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1755 : log_fatal("Stopping\n");
+ 1756 : ++unrecoverable_error;
+ 1757 : goto bail;
+ 1758 : /* LCOV_EXCL_STOP */
+ 1759 : }
+ 1760 :
+ 1761 : /* create it */
+ 1762 21 : ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ 1763 21 : if (ret != 0) {
+ 1764 : /* LCOV_EXCL_START */
+ 1765 : log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno));
+ 1766 : if (errno == EACCES) {
+ 1767 : log_fatal("WARNING! Please give write permission to the dir.\n");
+ 1768 : } else {
+ 1769 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
+ 1770 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1771 : }
+ 1772 : log_fatal("Stopping\n");
+ 1773 : ++unrecoverable_error;
+ 1774 : goto bail;
+ 1775 : /* LCOV_EXCL_STOP */
+ 1776 : }
+ 1777 :
+ 1778 21 : log_tag("dir_fixed:%s:%s: Fixed dir error\n", disk->name, esc_tag(dir->sub, esc_buffer));
+ 1779 21 : ++recovered_error;
+ 1780 :
+ 1781 21 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(dir->sub, esc_buffer));
+ 1782 21 : msg_info("recovered %s\n", fmt_term(disk, dir->sub, esc_buffer));
+ 1783 : }
+ 1784 : }
+ 1785 : }
+ 1786 :
+ 1787 118 : state_progress_end(state, countpos, countmax, countsize);
+ 1788 :
+ 1789 : bail:
+ 1790 : /* close all the files left open */
+ 1791 826 : for (j = 0; j < diskmax; ++j) {
+ 1792 708 : struct snapraid_file* file = handle[j].file;
+ 1793 708 : struct snapraid_disk* disk = handle[j].disk;
+ 1794 708 : ret = handle_close(&handle[j]);
+ 1795 708 : if (ret == -1) {
+ 1796 : /* LCOV_EXCL_START */
+ 1797 : log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
+ 1798 : log_fatal("DANGER! Unexpected close error in a data disk.\n");
+ 1799 : ++unrecoverable_error;
+ 1800 : /* continue, as we are already exiting */
+ 1801 : /* LCOV_EXCL_STOP */
+ 1802 : }
+ 1803 : }
+ 1804 :
+ 1805 : /* remove all the files created from scratch that have not finished the processing */
+ 1806 : /* it happens only when aborting pressing Ctrl+C or other reason. */
+ 1807 118 : if (fix) {
+ 1808 : /* for each disk */
+ 1809 315 : for (i = 0; i < diskmax; ++i) {
+ 1810 : tommy_node* node;
+ 1811 : struct snapraid_disk* disk;
+ 1812 :
+ 1813 270 : if (!handle[i].disk)
+ 1814 1 : continue;
1815 :
- 1816 : /* if the file was originally missing, and processing not yet finished */
- 1817 : /* we have to throw it away to ensure that at the next run we will retry */
- 1818 : /* to fix it, in case we select to undelete missing files */
- 1819 0 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
- 1820 :
- 1821 0 : ret = remove(path);
- 1822 0 : if (ret != 0) {
- 1823 : /* LCOV_EXCL_START */
- 1824 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
- 1825 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
- 1826 : ++unrecoverable_error;
- 1827 : /* continue, as we are already exiting */
- 1828 : /* LCOV_EXCL_STOP */
- 1829 : }
- 1830 : }
- 1831 : }
- 1832 : }
- 1833 :
- 1834 118 : if (error || recovered_error || unrecoverable_error) {
- 1835 67 : msg_status("\n");
- 1836 67 : msg_status("%8u errors\n", error);
- 1837 67 : if (fix) {
- 1838 43 : msg_status("%8u recovered errors\n", recovered_error);
- 1839 : }
- 1840 134 : if (unrecoverable_error) {
- 1841 13 : msg_status("%8u UNRECOVERABLE errors\n", unrecoverable_error);
- 1842 : } else {
- 1843 : /* without checking, we don't know if they are really recoverable or not */
- 1844 54 : if (!state->opt.auditonly)
- 1845 52 : msg_status("%8u unrecoverable errors\n", unrecoverable_error);
- 1846 54 : if (fix)
- 1847 34 : msg_status("Everything OK\n");
- 1848 : }
- 1849 : } else {
- 1850 51 : msg_status("Everything OK\n");
- 1851 : }
- 1852 :
- 1853 118 : if (error && !fix)
- 1854 24 : log_fatal("WARNING! There are errors!\n");
- 1855 118 : if (unrecoverable_error)
- 1856 13 : log_fatal("DANGER! There are unrecoverable errors!\n");
- 1857 :
- 1858 118 : log_tag("summary:error:%u\n", error);
- 1859 118 : if (fix)
- 1860 45 : log_tag("summary:error_recovered:%u\n", recovered_error);
- 1861 118 : if (!state->opt.auditonly)
- 1862 113 : log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error);
- 1863 118 : if (fix) {
- 1864 45 : if (error + recovered_error + unrecoverable_error == 0)
- 1865 2 : log_tag("summary:exit:ok\n");
- 1866 43 : else if (unrecoverable_error == 0)
- 1867 34 : log_tag("summary:exit:recovered\n");
- 1868 : else
- 1869 9 : log_tag("summary:exit:unrecoverable\n");
- 1870 73 : } else if (!state->opt.auditonly) {
- 1871 68 : if (error + unrecoverable_error == 0)
- 1872 46 : log_tag("summary:exit:ok\n");
- 1873 22 : else if (unrecoverable_error == 0)
- 1874 18 : log_tag("summary:exit:recoverable\n");
- 1875 : else
- 1876 4 : log_tag("summary:exit:unrecoverable\n");
- 1877 : } else { /* audit only */
- 1878 5 : if (error == 0)
- 1879 3 : log_tag("summary:exit:ok\n");
- 1880 : else
- 1881 2 : log_tag("summary:exit:error\n");
- 1882 : }
- 1883 118 : log_flush();
- 1884 :
- 1885 118 : free(failed);
- 1886 118 : free(failed_map);
- 1887 118 : free(handle);
- 1888 118 : free(buffer_alloc);
- 1889 118 : free(buffer);
- 1890 :
- 1891 : /* fail if some error are present after the run */
- 1892 118 : if (fix) {
- 1893 45 : if (state->opt.expect_unrecoverable) {
- 1894 9 : if (unrecoverable_error == 0)
- 1895 0 : return -1;
- 1896 : } else {
- 1897 36 : if (unrecoverable_error != 0)
- 1898 0 : return -1;
- 1899 : }
- 1900 : } else {
- 1901 73 : if (state->opt.expect_unrecoverable) {
- 1902 4 : if (unrecoverable_error == 0)
- 1903 0 : return -1;
- 1904 69 : } else if (state->opt.expect_recoverable) {
- 1905 20 : if (unrecoverable_error != 0 || error == 0)
- 1906 0 : return -1;
- 1907 : } else {
- 1908 49 : if (error != 0 || unrecoverable_error != 0)
- 1909 0 : return -1;
- 1910 : }
- 1911 : }
+ 1816 : /* for each file in the disk */
+ 1817 269 : disk = handle[i].disk;
+ 1818 269 : node = disk->filelist;
+ 1819 870849 : while (node) {
+ 1820 : char path[PATH_MAX];
+ 1821 : struct snapraid_file* file;
+ 1822 :
+ 1823 870311 : file = node->data;
+ 1824 870311 : node = node->next; /* next node */
+ 1825 :
+ 1826 : /* if the file was not created, meaning that it was already existing */
+ 1827 870311 : if (!file_flag_has(file, FILE_IS_CREATED)) {
+ 1828 : /* nothing to do */
+ 1829 1627504 : continue;
+ 1830 : }
+ 1831 :
+ 1832 : /* if processing was finished */
+ 1833 113118 : if (file_flag_has(file, FILE_IS_FINISHED)) {
+ 1834 : /* nothing to do */
+ 1835 113118 : continue;
+ 1836 : }
+ 1837 :
+ 1838 : /* if the file was originally missing, and processing not yet finished */
+ 1839 : /* we have to throw it away to ensure that at the next run we will retry */
+ 1840 : /* to fix it, in case we select to undelete missing files */
+ 1841 0 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
+ 1842 :
+ 1843 0 : ret = remove(path);
+ 1844 0 : if (ret != 0) {
+ 1845 : /* LCOV_EXCL_START */
+ 1846 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
+ 1847 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
+ 1848 : ++unrecoverable_error;
+ 1849 : /* continue, as we are already exiting */
+ 1850 : /* LCOV_EXCL_STOP */
+ 1851 : }
+ 1852 : }
+ 1853 : }
+ 1854 : }
+ 1855 :
+ 1856 118 : if (error || recovered_error || unrecoverable_error) {
+ 1857 67 : msg_status("\n");
+ 1858 67 : msg_status("%8u errors\n", error);
+ 1859 67 : if (fix) {
+ 1860 43 : msg_status("%8u recovered errors\n", recovered_error);
+ 1861 : }
+ 1862 134 : if (unrecoverable_error) {
+ 1863 13 : msg_status("%8u UNRECOVERABLE errors\n", unrecoverable_error);
+ 1864 : } else {
+ 1865 : /* without checking, we don't know if they are really recoverable or not */
+ 1866 54 : if (!state->opt.auditonly)
+ 1867 52 : msg_status("%8u unrecoverable errors\n", unrecoverable_error);
+ 1868 54 : if (fix)
+ 1869 34 : msg_status("Everything OK\n");
+ 1870 : }
+ 1871 : } else {
+ 1872 51 : msg_status("Everything OK\n");
+ 1873 : }
+ 1874 :
+ 1875 118 : if (error && !fix)
+ 1876 24 : log_fatal("WARNING! There are errors!\n");
+ 1877 118 : if (unrecoverable_error)
+ 1878 13 : log_fatal("DANGER! There are unrecoverable errors!\n");
+ 1879 :
+ 1880 118 : log_tag("summary:error:%u\n", error);
+ 1881 118 : if (fix)
+ 1882 45 : log_tag("summary:error_recovered:%u\n", recovered_error);
+ 1883 118 : if (!state->opt.auditonly)
+ 1884 113 : log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error);
+ 1885 118 : if (fix) {
+ 1886 45 : if (error + recovered_error + unrecoverable_error == 0)
+ 1887 2 : log_tag("summary:exit:ok\n");
+ 1888 43 : else if (unrecoverable_error == 0)
+ 1889 34 : log_tag("summary:exit:recovered\n");
+ 1890 : else
+ 1891 9 : log_tag("summary:exit:unrecoverable\n");
+ 1892 73 : } else if (!state->opt.auditonly) {
+ 1893 68 : if (error + unrecoverable_error == 0)
+ 1894 46 : log_tag("summary:exit:ok\n");
+ 1895 22 : else if (unrecoverable_error == 0)
+ 1896 18 : log_tag("summary:exit:recoverable\n");
+ 1897 : else
+ 1898 4 : log_tag("summary:exit:unrecoverable\n");
+ 1899 : } else { /* audit only */
+ 1900 5 : if (error == 0)
+ 1901 3 : log_tag("summary:exit:ok\n");
+ 1902 : else
+ 1903 2 : log_tag("summary:exit:error\n");
+ 1904 : }
+ 1905 118 : log_flush();
+ 1906 :
+ 1907 118 : free(failed);
+ 1908 118 : free(failed_map);
+ 1909 118 : free(handle);
+ 1910 118 : free(buffer_alloc);
+ 1911 118 : free(buffer);
1912 :
- 1913 118 : return 0;
- 1914 : }
- 1915 :
- 1916 120 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount)
- 1917 : {
- 1918 : block_off_t blockmax;
- 1919 : data_off_t size;
- 1920 : int ret;
- 1921 : struct snapraid_parity_handle parity[LEV_MAX];
- 1922 : struct snapraid_parity_handle* parity_ptr[LEV_MAX];
- 1923 : unsigned error;
- 1924 : unsigned l;
- 1925 :
- 1926 120 : msg_progress("Initializing...\n");
- 1927 :
- 1928 120 : blockmax = parity_allocated_size(state);
- 1929 120 : size = blockmax * (data_off_t)state->block_size;
- 1930 :
- 1931 120 : if (blockstart > blockmax) {
- 1932 : /* LCOV_EXCL_START */
- 1933 : log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
- 1934 : exit(EXIT_FAILURE);
- 1935 : /* LCOV_EXCL_STOP */
- 1936 : }
+ 1913 : /* fail if some error are present after the run */
+ 1914 118 : if (fix) {
+ 1915 45 : if (state->opt.expect_unrecoverable) {
+ 1916 9 : if (unrecoverable_error == 0)
+ 1917 0 : return -1;
+ 1918 : } else {
+ 1919 36 : if (unrecoverable_error != 0)
+ 1920 0 : return -1;
+ 1921 : }
+ 1922 : } else {
+ 1923 73 : if (state->opt.expect_unrecoverable) {
+ 1924 4 : if (unrecoverable_error == 0)
+ 1925 0 : return -1;
+ 1926 69 : } else if (state->opt.expect_recoverable) {
+ 1927 20 : if (unrecoverable_error != 0 || error == 0)
+ 1928 0 : return -1;
+ 1929 : } else {
+ 1930 49 : if (error != 0 || unrecoverable_error != 0)
+ 1931 0 : return -1;
+ 1932 : }
+ 1933 : }
+ 1934 :
+ 1935 118 : return 0;
+ 1936 : }
1937 :
- 1938 : /* adjust the number of block to process */
- 1939 120 : if (blockcount != 0 && blockstart + blockcount < blockmax) {
- 1940 0 : blockmax = blockstart + blockcount;
- 1941 : }
- 1942 :
- 1943 120 : if (fix) {
- 1944 : /* if fixing, create the file and open for writing */
- 1945 : /* if it fails, we cannot continue */
- 1946 180 : for (l = 0; l < state->level; ++l) {
- 1947 : /* skip parity disks that are not accessible */
- 1948 135 : if (state->parity[l].skip_access) {
- 1949 1 : parity_ptr[l] = 0;
- 1950 1 : continue;
- 1951 : }
+ 1938 120 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount)
+ 1939 : {
+ 1940 : block_off_t blockmax;
+ 1941 : data_off_t size;
+ 1942 : int ret;
+ 1943 : struct snapraid_parity_handle parity[LEV_MAX];
+ 1944 : struct snapraid_parity_handle* parity_ptr[LEV_MAX];
+ 1945 : unsigned error;
+ 1946 : unsigned l;
+ 1947 :
+ 1948 120 : msg_progress("Initializing...\n");
+ 1949 :
+ 1950 120 : blockmax = parity_allocated_size(state);
+ 1951 120 : size = blockmax * (data_off_t)state->block_size;
1952 :
- 1953 134 : parity_ptr[l] = &parity[l];
- 1954 134 : ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
- 1955 134 : if (ret == -1) {
- 1956 : /* LCOV_EXCL_START */
- 1957 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l));
- 1958 : exit(EXIT_FAILURE);
- 1959 : /* LCOV_EXCL_STOP */
- 1960 : }
- 1961 :
- 1962 134 : ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder);
- 1963 134 : if (ret == -1) {
- 1964 : /* LCOV_EXCL_START */
- 1965 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
- 1966 : exit(EXIT_FAILURE);
- 1967 : /* LCOV_EXCL_STOP */
- 1968 : }
- 1969 : }
- 1970 75 : } else if (!state->opt.auditonly) {
- 1971 : /* if checking, open the file for reading */
- 1972 : /* it may fail if the file doesn't exist, in this case we continue to check the files */
- 1973 393 : for (l = 0; l < state->level; ++l) {
- 1974 324 : parity_ptr[l] = &parity[l];
- 1975 324 : ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
- 1976 324 : if (ret == -1) {
- 1977 1 : msg_status("No accessible %s file, only files will be checked.\n", lev_name(l));
- 1978 : /* continue anyway */
- 1979 1 : parity_ptr[l] = 0;
- 1980 : }
- 1981 : }
- 1982 : } else {
- 1983 : /* otherwise don't use any parity */
- 1984 28 : for (l = 0; l < state->level; ++l)
- 1985 22 : parity_ptr[l] = 0;
- 1986 : }
- 1987 :
- 1988 120 : if (fix)
- 1989 45 : msg_progress("Fixing...\n");
- 1990 75 : else if (!state->opt.auditonly)
- 1991 69 : msg_progress("Checking...\n");
- 1992 : else
- 1993 6 : msg_progress("Hashing...\n");
- 1994 :
- 1995 120 : error = 0;
- 1996 :
- 1997 : /* skip degenerated cases of empty parity, or skipping all */
- 1998 120 : if (blockstart < blockmax) {
- 1999 118 : ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax);
- 2000 118 : if (ret == -1) {
- 2001 : /* LCOV_EXCL_START */
- 2002 : ++error;
- 2003 : /* continue, as we are already exiting */
- 2004 : /* LCOV_EXCL_STOP */
- 2005 : }
- 2006 : }
- 2007 :
- 2008 : /* try to close only if opened */
- 2009 601 : for (l = 0; l < state->level; ++l) {
- 2010 481 : if (parity_ptr[l]) {
- 2011 457 : ret = parity_close(parity_ptr[l]);
- 2012 : /* LCOV_EXCL_START */
- 2013 : if (ret == -1) {
- 2014 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
- 2015 : ++error;
- 2016 : /* continue, as we are already exiting */
- 2017 : }
- 2018 : /* LCOV_EXCL_STOP */
- 2019 : }
- 2020 : }
- 2021 :
- 2022 : /* abort if error are present */
- 2023 120 : if (error != 0)
- 2024 0 : return -1;
- 2025 120 : return 0;
- 2026 : }
- 2027 :
+ 1953 120 : if (blockstart > blockmax) {
+ 1954 : /* LCOV_EXCL_START */
+ 1955 : log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
+ 1956 : exit(EXIT_FAILURE);
+ 1957 : /* LCOV_EXCL_STOP */
+ 1958 : }
+ 1959 :
+ 1960 : /* adjust the number of block to process */
+ 1961 120 : if (blockcount != 0 && blockstart + blockcount < blockmax) {
+ 1962 0 : blockmax = blockstart + blockcount;
+ 1963 : }
+ 1964 :
+ 1965 120 : if (fix) {
+ 1966 : /* if fixing, create the file and open for writing */
+ 1967 : /* if it fails, we cannot continue */
+ 1968 180 : for (l = 0; l < state->level; ++l) {
+ 1969 : /* skip parity disks that are not accessible */
+ 1970 135 : if (state->parity[l].skip_access) {
+ 1971 1 : parity_ptr[l] = 0;
+ 1972 1 : continue;
+ 1973 : }
+ 1974 :
+ 1975 134 : parity_ptr[l] = &parity[l];
+ 1976 134 : ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
+ 1977 134 : if (ret == -1) {
+ 1978 : /* LCOV_EXCL_START */
+ 1979 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l));
+ 1980 : exit(EXIT_FAILURE);
+ 1981 : /* LCOV_EXCL_STOP */
+ 1982 : }
+ 1983 :
+ 1984 134 : ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder);
+ 1985 134 : if (ret == -1) {
+ 1986 : /* LCOV_EXCL_START */
+ 1987 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
+ 1988 : exit(EXIT_FAILURE);
+ 1989 : /* LCOV_EXCL_STOP */
+ 1990 : }
+ 1991 : }
+ 1992 75 : } else if (!state->opt.auditonly) {
+ 1993 : /* if checking, open the file for reading */
+ 1994 : /* it may fail if the file doesn't exist, in this case we continue to check the files */
+ 1995 393 : for (l = 0; l < state->level; ++l) {
+ 1996 324 : parity_ptr[l] = &parity[l];
+ 1997 324 : ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
+ 1998 324 : if (ret == -1) {
+ 1999 1 : msg_status("No accessible %s file, only files will be checked.\n", lev_name(l));
+ 2000 : /* continue anyway */
+ 2001 1 : parity_ptr[l] = 0;
+ 2002 : }
+ 2003 : }
+ 2004 : } else {
+ 2005 : /* otherwise don't use any parity */
+ 2006 28 : for (l = 0; l < state->level; ++l)
+ 2007 22 : parity_ptr[l] = 0;
+ 2008 : }
+ 2009 :
+ 2010 120 : if (fix)
+ 2011 45 : msg_progress("Fixing...\n");
+ 2012 75 : else if (!state->opt.auditonly)
+ 2013 69 : msg_progress("Checking...\n");
+ 2014 : else
+ 2015 6 : msg_progress("Hashing...\n");
+ 2016 :
+ 2017 120 : error = 0;
+ 2018 :
+ 2019 : /* skip degenerated cases of empty parity, or skipping all */
+ 2020 120 : if (blockstart < blockmax) {
+ 2021 118 : ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax);
+ 2022 118 : if (ret == -1) {
+ 2023 : /* LCOV_EXCL_START */
+ 2024 : ++error;
+ 2025 : /* continue, as we are already exiting */
+ 2026 : /* LCOV_EXCL_STOP */
+ 2027 : }
+ 2028 : }
+ 2029 :
+ 2030 : /* try to close only if opened */
+ 2031 601 : for (l = 0; l < state->level; ++l) {
+ 2032 481 : if (parity_ptr[l]) {
+ 2033 457 : ret = parity_close(parity_ptr[l]);
+ 2034 : /* LCOV_EXCL_START */
+ 2035 : if (ret == -1) {
+ 2036 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
+ 2037 : ++error;
+ 2038 : /* continue, as we are already exiting */
+ 2039 : }
+ 2040 : /* LCOV_EXCL_STOP */
+ 2041 : }
+ 2042 : }
+ 2043 :
+ 2044 : /* abort if error are present */
+ 2045 120 : if (error != 0)
+ 2046 0 : return -1;
+ 2047 120 : return 0;
+ 2048 : }
+ 2049 :
diff --git a/cov/cmdline/device.c.func-sort-c.html b/cov/cmdline/device.c.func-sort-c.html
index 4e4f2c23..e3e5564e 100644
--- a/cov/cmdline/device.c.func-sort-c.html
+++ b/cov/cmdline/device.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/device.c.func.html b/cov/cmdline/device.c.func.html
index 4891bbe1..b3af7c19 100644
--- a/cov/cmdline/device.c.func.html
+++ b/cov/cmdline/device.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/device.c.gcov.html b/cov/cmdline/device.c.gcov.html
index d2d91e48..b5f7e1bc 100644
--- a/cov/cmdline/device.c.gcov.html
+++ b/cov/cmdline/device.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/dry.c.func-sort-c.html b/cov/cmdline/dry.c.func-sort-c.html
index aebd4849..7bf68dc0 100644
--- a/cov/cmdline/dry.c.func-sort-c.html
+++ b/cov/cmdline/dry.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -60,12 +60,12 @@
Hit count  |
- | dry_data_reader |
- 42601 |
+ dry_parity_reader |
+ 42579 |
- | dry_parity_reader |
- 42274 |
+ dry_data_reader |
+ 42575 |
| block_is_enabled |
diff --git a/cov/cmdline/dry.c.func.html b/cov/cmdline/dry.c.func.html
index 7a6439a5..d92de451 100644
--- a/cov/cmdline/dry.c.func.html
+++ b/cov/cmdline/dry.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,11 +65,11 @@
| dry_data_reader |
- 42601 |
+ 42575 |
| dry_parity_reader |
- 42274 |
+ 42579 |
| state_dry |
diff --git a/cov/cmdline/dry.c.gcov.html b/cov/cmdline/dry.c.gcov.html
index a8f0bb53..426c362f 100644
--- a/cov/cmdline/dry.c.gcov.html
+++ b/cov/cmdline/dry.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -101,45 +101,45 @@
39 7102 : return 1;
40 : }
41 :
- 42 42601 : static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
+ 42 42575 : static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
43 : {
- 44 42601 : struct snapraid_io* io = worker->io;
- 45 42601 : struct snapraid_state* state = io->state;
- 46 42601 : struct snapraid_handle* handle = worker->handle;
- 47 42601 : struct snapraid_disk* disk = handle->disk;
- 48 42601 : block_off_t blockcur = task->position;
- 49 42601 : unsigned char* buffer = task->buffer;
+ 44 42575 : struct snapraid_io* io = worker->io;
+ 45 42575 : struct snapraid_state* state = io->state;
+ 46 42575 : struct snapraid_handle* handle = worker->handle;
+ 47 42575 : struct snapraid_disk* disk = handle->disk;
+ 48 42575 : block_off_t blockcur = task->position;
+ 49 42575 : unsigned char* buffer = task->buffer;
50 : int ret;
51 : char esc_buffer[ESC_MAX];
52 :
53 : /* if the disk position is not used */
- 54 42601 : if (!disk) {
+ 54 42575 : if (!disk) {
55 : /* use an empty block */
56 4686 : memset(buffer, 0, state->block_size);
57 4686 : task->state = TASK_STATE_DONE;
- 58 9917 : return;
+ 58 9912 : return;
59 : }
60 :
61 : /* get the block */
- 62 37915 : task->block = fs_par2block_find(disk, blockcur);
+ 62 37889 : task->block = fs_par2block_find(disk, blockcur);
63 :
64 : /* if the block is not used */
- 65 37902 : if (!block_has_file(task->block)) {
+ 65 37855 : if (!block_has_file(task->block)) {
66 : /* use an empty block */
- 67 545 : memset(buffer, 0, state->block_size);
- 68 545 : task->state = TASK_STATE_DONE;
- 69 545 : return;
+ 67 540 : memset(buffer, 0, state->block_size);
+ 68 540 : task->state = TASK_STATE_DONE;
+ 69 540 : return;
70 : }
71 :
72 : /* get the file of this block */
- 73 37352 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
+ 73 37298 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
74 :
75 : /* if the file is different than the current one, close it */
- 76 37365 : if (handle->file != 0 && handle->file != task->file) {
+ 76 37356 : if (handle->file != 0 && handle->file != task->file) {
77 : /* keep a pointer at the file we are going to close for error reporting */
- 78 15088 : struct snapraid_file* report = handle->file;
- 79 15088 : ret = handle_close(handle);
- 80 15084 : if (ret == -1) {
+ 78 15083 : struct snapraid_file* report = handle->file;
+ 79 15083 : ret = handle_close(handle);
+ 80 15069 : if (ret == -1) {
81 : /* LCOV_EXCL_START */
82 : /* This one is really an unexpected error, because we are only reading */
83 : /* and closing a descriptor should never fail */
@@ -162,8 +162,8 @@
100 : }
101 : }
102 :
- 103 37361 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
- 104 37368 : if (ret == -1) {
+ 103 37342 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
+ 104 37201 : if (ret == -1) {
105 0 : if (errno == EIO) {
106 : /* LCOV_EXCL_START */
107 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
@@ -180,8 +180,8 @@
118 0 : return;
119 : }
120 :
- 121 37368 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
- 122 37305 : if (task->read_size == -1) {
+ 121 37201 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
+ 122 37222 : if (task->read_size == -1) {
123 0 : if (errno == EIO) {
124 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
125 0 : log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
@@ -195,24 +195,24 @@
133 : }
134 :
135 : /* store the path of the opened file */
- 136 37305 : pathcpy(task->path, sizeof(task->path), handle->path);
+ 136 37222 : pathcpy(task->path, sizeof(task->path), handle->path);
137 :
- 138 37345 : task->state = TASK_STATE_DONE;
+ 138 37240 : task->state = TASK_STATE_DONE;
139 : }
140 :
- 141 42274 : static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task)
+ 141 42579 : static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task)
142 : {
- 143 42274 : struct snapraid_io* io = worker->io;
- 144 42274 : struct snapraid_state* state = io->state;
- 145 42274 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
- 146 42274 : unsigned level = parity_handle->level;
- 147 42274 : block_off_t blockcur = task->position;
- 148 42274 : unsigned char* buffer = task->buffer;
+ 143 42579 : struct snapraid_io* io = worker->io;
+ 144 42579 : struct snapraid_state* state = io->state;
+ 145 42579 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
+ 146 42579 : unsigned level = parity_handle->level;
+ 147 42579 : block_off_t blockcur = task->position;
+ 148 42579 : unsigned char* buffer = task->buffer;
149 : int ret;
150 :
151 : /* read the parity */
- 152 42274 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
- 153 42574 : if (ret == -1) {
+ 152 42579 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
+ 153 42483 : if (ret == -1) {
154 0 : if (errno == EIO) {
155 0 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
156 0 : log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur);
@@ -225,7 +225,7 @@
163 0 : return;
164 : }
165 :
- 166 42574 : task->state = TASK_STATE_DONE;
+ 166 42483 : task->state = TASK_STATE_DONE;
167 : }
168 :
169 2 : static int state_dry_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax)
diff --git a/cov/cmdline/dup.c.func-sort-c.html b/cov/cmdline/dup.c.func-sort-c.html
index dac74296..3c467d81 100644
--- a/cov/cmdline/dup.c.func-sort-c.html
+++ b/cov/cmdline/dup.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/dup.c.func.html b/cov/cmdline/dup.c.func.html
index 2517f6af..3b96aafc 100644
--- a/cov/cmdline/dup.c.func.html
+++ b/cov/cmdline/dup.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/dup.c.gcov.html b/cov/cmdline/dup.c.gcov.html
index c96f63d9..852b0f32 100644
--- a/cov/cmdline/dup.c.gcov.html
+++ b/cov/cmdline/dup.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/elem.c.func-sort-c.html b/cov/cmdline/elem.c.func-sort-c.html
index 90931dd5..04917e92 100644
--- a/cov/cmdline/elem.c.func-sort-c.html
+++ b/cov/cmdline/elem.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -61,71 +61,71 @@
| extent_parity_inside_compare_unlock |
- 114575009 |
-
-
- | fs_lock |
- 53195526 |
+ 113415111 |
| fs_unlock |
- 53195112 |
+ 53194752 |
+
+
+ | fs_lock |
+ 53193825 |
| extent_file_compare |
- 45005658 |
+ 45007474 |
| fs_file2block_get |
- 44945354 |
+ 44945861 |
| extent_parity_compare |
- 44509325 |
+ 44510915 |
| fs_par2extent_get_unlock |
- 39143508 |
+ 39142622 |
| fs_par2file_find |
- 39036978 |
+ 39034767 |
| fs_par2block_find |
- 27313631 |
+ 27313617 |
| extent_file_inside_compare_unlock |
- 21310995 |
+ 21313929 |
| filter_apply |
- 12457044 |
+ 12456472 |
| fs_file2extent_get_unlock |
- 10336255 |
+ 10336367 |
| fs_allocate |
- 9175178 |
+ 9175254 |
| file_block_size |
- 6823038 |
+ 6820121 |
| extent_file_check_foreach_unlock |
- 6584473 |
+ 6584561 |
| extent_parity_check_foreach_unlock |
- 6584473 |
+ 6584561 |
| filter_recurse |
- 6236629 |
+ 6236343 |
| file_block_is_last |
@@ -133,55 +133,55 @@
| fs_file2par_find |
- 4869703 |
+ 4869735 |
| extent_alloc |
- 3735289 |
+ 3735329 |
| file_alloc |
- 3690991 |
+ 3690989 |
| extent_free |
- 3564865 |
+ 3564905 |
| file_free |
- 3543815 |
+ 3543813 |
| filter_element |
- 3332859 |
+ 3332716 |
| filter_path |
- 3329762 |
+ 3329619 |
| filter_content |
- 3173372 |
+ 3173210 |
| file_inode_compare_to_arg |
- 975235 |
+ 987374 |
| time_compare |
- 691801 |
+ 675269 |
| fmt_term |
- 355906 |
+ 356144 |
| file_path_compare |
- 189475 |
+ 189473 |
| filter_type |
- 125233 |
+ 125331 |
| link_alloc |
@@ -193,27 +193,27 @@
| fs_deallocate |
- 106232 |
+ 106308 |
| file_path_compare_to_arg |
- 97871 |
+ 103588 |
| filter_existence |
80691 |
+
+ | file_physical_compare |
+ 53902 |
+
| extent_disk_size_compare_unlock |
- 50514 |
+ 50518 |
| file_name |
- 47954 |
-
-
- | file_physical_compare |
- 44212 |
+ 47970 |
| filter_correctness |
@@ -225,11 +225,11 @@
| file_namestamp_compare |
- 23977 |
+ 23985 |
| file_name_compare |
- 23977 |
+ 23985 |
| file_stamp_compare |
diff --git a/cov/cmdline/elem.c.func.html b/cov/cmdline/elem.c.func.html
index 63f4cf7d..6b79b04f 100644
--- a/cov/cmdline/elem.c.func.html
+++ b/cov/cmdline/elem.c.func.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -89,7 +89,7 @@
| extent_alloc |
- 3735289 |
+ 3735329 |
| extent_disk_empty_compare_unlock |
@@ -97,39 +97,39 @@
| extent_disk_size_compare_unlock |
- 50514 |
+ 50518 |
| extent_file_check_foreach_unlock |
- 6584473 |
+ 6584561 |
| extent_file_compare |
- 45005658 |
+ 45007474 |
| extent_file_inside_compare_unlock |
- 21310995 |
+ 21313929 |
| extent_free |
- 3564865 |
+ 3564905 |
| extent_parity_check_foreach_unlock |
- 6584473 |
+ 6584561 |
| extent_parity_compare |
- 44509325 |
+ 44510915 |
| extent_parity_inside_compare_unlock |
- 114575009 |
+ 113415111 |
| file_alloc |
- 3690991 |
+ 3690989 |
| file_block_is_last |
@@ -137,7 +137,7 @@
| file_block_size |
- 6823038 |
+ 6820121 |
| file_copy |
@@ -149,7 +149,7 @@
| file_free |
- 3543815 |
+ 3543813 |
| file_inode_compare |
@@ -157,27 +157,27 @@
| file_inode_compare_to_arg |
- 975235 |
+ 987374 |
| file_name |
- 47954 |
+ 47970 |
| file_name_compare |
- 23977 |
+ 23985 |
| file_namestamp_compare |
- 23977 |
+ 23985 |
| file_path_compare |
- 189475 |
+ 189473 |
| file_path_compare_to_arg |
- 97871 |
+ 103588 |
| file_pathstamp_compare |
@@ -185,7 +185,7 @@
| file_physical_compare |
- 44212 |
+ 53902 |
| file_rename |
@@ -205,11 +205,11 @@
| filter_apply |
- 12457044 |
+ 12456472 |
| filter_content |
- 3173372 |
+ 3173210 |
| filter_correctness |
@@ -217,7 +217,7 @@
| filter_element |
- 3332859 |
+ 3332716 |
| filter_emptydir |
@@ -233,11 +233,11 @@
| filter_path |
- 3329762 |
+ 3329619 |
| filter_recurse |
- 6236629 |
+ 6236343 |
| filter_subdir |
@@ -245,7 +245,7 @@
| filter_type |
- 125233 |
+ 125331 |
| fmt_poll |
@@ -253,11 +253,11 @@
| fmt_term |
- 355906 |
+ 356144 |
| fs_allocate |
- 9175178 |
+ 9175254 |
| fs_check |
@@ -265,19 +265,19 @@
| fs_deallocate |
- 106232 |
+ 106308 |
| fs_file2block_get |
- 44945354 |
+ 44945861 |
| fs_file2extent_get_unlock |
- 10336255 |
+ 10336367 |
| fs_file2par_find |
- 4869703 |
+ 4869735 |
| fs_is_empty |
@@ -285,19 +285,19 @@
| fs_lock |
- 53195526 |
+ 53193825 |
| fs_par2block_find |
- 27313631 |
+ 27313617 |
| fs_par2extent_get_unlock |
- 39143508 |
+ 39142622 |
| fs_par2file_find |
- 39036978 |
+ 39034767 |
| fs_size |
@@ -305,7 +305,7 @@
| fs_unlock |
- 53195112 |
+ 53194752 |
| link_alloc |
@@ -333,7 +333,7 @@
| time_compare |
- 691801 |
+ 675269 |
diff --git a/cov/cmdline/elem.c.gcov.html b/cov/cmdline/elem.c.gcov.html
index 2f2b118f..bed1d37a 100644
--- a/cov/cmdline/elem.c.gcov.html
+++ b/cov/cmdline/elem.c.gcov.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -212,96 +212,96 @@
150 499 : free(filter);
151 499 : }
152 :
- 153 125233 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size)
+ 153 125331 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size)
154 : {
155 : const char* direction;
156 :
- 157 125233 : if (filter->direction < 0)
- 158 124968 : direction = "exclude";
+ 157 125331 : if (filter->direction < 0)
+ 158 125066 : direction = "exclude";
159 : else
160 265 : direction = "include";
161 :
- 162 125233 : if (filter->is_disk)
+ 162 125331 : if (filter->is_disk)
163 0 : pathprint(out, out_size, "%s %s:", direction, filter->pattern);
- 164 125233 : else if (filter->is_dir)
+ 164 125331 : else if (filter->is_dir)
165 0 : pathprint(out, out_size, "%s %s/", direction, filter->pattern);
166 : else
- 167 125233 : pathprint(out, out_size, "%s %s", direction, filter->pattern);
+ 167 125331 : pathprint(out, out_size, "%s %s", direction, filter->pattern);
168 :
- 169 125233 : return out;
+ 169 125331 : return out;
170 : }
171 :
- 172 12457044 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir)
+ 172 12456472 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir)
173 : {
- 174 12457044 : int ret = 0;
+ 174 12456472 : int ret = 0;
175 :
176 : /* match dirs with dirs and files with files */
- 177 12457044 : if (filter->is_dir && !is_dir)
+ 177 12456472 : if (filter->is_dir && !is_dir)
178 2949 : return 0;
- 179 12454095 : if (!filter->is_dir && is_dir)
- 180 6223584 : return 0;
+ 179 12453523 : if (!filter->is_dir && is_dir)
+ 180 6223298 : return 0;
181 :
- 182 6230511 : if (filter->is_path) {
+ 182 6230225 : if (filter->is_path) {
183 : /* skip initial slash, as always missing from the path */
184 2949 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0)
185 0 : ret = filter->direction;
186 : } else {
- 187 6227562 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
- 188 127693 : ret = filter->direction;
+ 187 6227276 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
+ 188 127791 : ret = filter->direction;
189 : }
190 :
- 191 6230511 : if (reason != 0 && ret < 0)
- 192 124703 : *reason = filter;
+ 191 6230225 : if (reason != 0 && ret < 0)
+ 192 124801 : *reason = filter;
193 :
- 194 6230511 : return ret;
+ 194 6230225 : return ret;
195 : }
196 :
- 197 6236629 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir)
+ 197 6236343 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir)
198 : {
199 : char path[PATH_MAX];
200 : char* name;
201 : unsigned i;
202 :
- 203 6236629 : pathcpy(path, sizeof(path), const_path);
+ 203 6236343 : pathcpy(path, sizeof(path), const_path);
204 :
205 : /* filter for all the directories */
- 206 6236629 : name = path;
- 207 89821180 : for (i = 0; path[i] != 0; ++i) {
- 208 83587541 : if (path[i] == '/') {
+ 206 6236343 : name = path;
+ 207 89822608 : for (i = 0; path[i] != 0; ++i) {
+ 208 83589255 : if (path[i] == '/') {
209 : /* set a terminator */
- 210 6223405 : path[i] = 0;
+ 210 6223119 : path[i] = 0;
211 :
212 : /* filter the directory */
- 213 6223405 : if (filter_apply(filter, reason, path, name, 1) != 0)
+ 213 6223119 : if (filter_apply(filter, reason, path, name, 1) != 0)
214 2990 : return filter->direction;
215 :
216 : /* restore the slash */
- 217 6220415 : path[i] = '/';
+ 217 6220129 : path[i] = '/';
218 :
219 : /* next name */
- 220 6220415 : name = path + i + 1;
+ 220 6220129 : name = path + i + 1;
221 : }
222 : }
223 :
224 : /* filter the final file */
- 225 6233639 : if (filter_apply(filter, reason, path, name, is_dir) != 0)
- 226 124703 : return filter->direction;
+ 225 6233353 : if (filter_apply(filter, reason, path, name, is_dir) != 0)
+ 226 124801 : return filter->direction;
227 :
- 228 6108936 : return 0;
+ 228 6108552 : return 0;
229 : }
230 :
- 231 3332859 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include)
+ 231 3332716 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include)
232 : {
233 : tommy_node* i;
234 :
- 235 3332859 : int direction = 1; /* by default include all */
+ 235 3332716 : int direction = 1; /* by default include all */
236 :
237 : /* for each filter */
- 238 9543103 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) {
+ 238 9542576 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) {
239 : int ret;
- 240 6346617 : struct snapraid_filter* filter = i->data;
+ 240 6346331 : struct snapraid_filter* filter = i->data;
241 :
- 242 6346617 : if (filter->is_disk) {
+ 242 6346331 : if (filter->is_disk) {
243 109988 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0)
244 8680 : ret = filter->direction;
245 : else
@@ -309,39 +309,39 @@
247 109988 : if (reason != 0 && ret < 0)
248 0 : *reason = filter;
249 : } else {
- 250 6236629 : ret = filter_recurse(filter, reason, sub, is_dir);
+ 250 6236343 : ret = filter_recurse(filter, reason, sub, is_dir);
251 : }
252 :
- 253 6346617 : if (ret > 0) {
+ 253 6346331 : if (ret > 0) {
254 : /* include the file */
255 11670 : return 0;
- 256 6334947 : } else if (ret < 0) {
+ 256 6334661 : } else if (ret < 0) {
257 : /* exclude the file */
- 258 124703 : return -1;
+ 258 124801 : return -1;
259 : } else {
260 : /* default is opposite of the last filter */
- 261 6210244 : direction = -filter->direction;
- 262 6210244 : if (reason != 0 && direction < 0)
- 263 3110901 : *reason = filter;
+ 261 6209860 : direction = -filter->direction;
+ 262 6209860 : if (reason != 0 && direction < 0)
+ 263 3110758 : *reason = filter;
264 : /* continue with the next one */
265 : }
266 : }
267 :
268 : /* directories are always included by default, otherwise we cannot apply rules */
269 : /* to the contained files */
- 270 3196486 : if (is_def_include)
+ 270 3196245 : if (is_def_include)
271 3052 : return 0;
272 :
273 : /* files are excluded/included depending of the last rule processed */
- 274 3193434 : if (direction < 0)
+ 274 3193193 : if (direction < 0)
275 57608 : return -1;
276 :
- 277 3135826 : return 0;
+ 277 3135585 : return 0;
278 : }
279 :
- 280 3329762 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
+ 280 3329619 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
281 : {
- 282 3329762 : return filter_element(filterlist, reason, disk, sub, 0, 0);
+ 282 3329619 : return filter_element(filterlist, reason, disk, sub, 0, 0);
283 : }
284 :
285 3052 : int filter_subdir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub)
@@ -387,67 +387,67 @@
325 16098 : return 0;
326 :
327 : /* check each block of the file */
- 328 60692 : for (i = 0; i < file->blockmax; ++i) {
- 329 46446 : block_off_t parity_pos = fs_file2par_get(disk, file, i);
- 330 46446 : snapraid_info info = info_get(infoarr, parity_pos);
+ 328 60648 : for (i = 0; i < file->blockmax; ++i) {
+ 329 46434 : block_off_t parity_pos = fs_file2par_get(disk, file, i);
+ 330 46434 : snapraid_info info = info_get(infoarr, parity_pos);
331 :
332 : /* if the file has a bad block, don't exclude it */
- 333 46446 : if (info_get_bad(info))
- 334 8302 : return 0;
+ 333 46434 : if (info_get_bad(info))
+ 334 8334 : return 0;
335 : }
336 :
337 : /* the file is correct, so we filter it out */
- 338 14246 : return 1;
+ 338 14214 : return 1;
339 : }
340 :
- 341 3173372 : int filter_content(tommy_list* contentlist, const char* path)
+ 341 3173210 : int filter_content(tommy_list* contentlist, const char* path)
342 : {
343 : tommy_node* i;
344 :
- 345 40913052 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) {
- 346 17283154 : struct snapraid_content* content = i->data;
+ 345 40912088 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) {
+ 346 17282834 : struct snapraid_content* content = i->data;
347 : char tmp[PATH_MAX];
348 :
- 349 17283154 : if (pathcmp(content->content, path) == 0)
+ 349 17282834 : if (pathcmp(content->content, path) == 0)
350 0 : return -1;
351 :
352 : /* exclude also the ".tmp" copy used to save it */
- 353 17283154 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 354 17283154 : if (pathcmp(tmp, path) == 0)
+ 353 17282834 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 354 17282834 : if (pathcmp(tmp, path) == 0)
355 0 : return -1;
356 :
357 : /* exclude also the ".lock" file */
- 358 17283154 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content);
- 359 17283154 : if (pathcmp(tmp, path) == 0)
+ 358 17282834 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content);
+ 359 17282834 : if (pathcmp(tmp, path) == 0)
360 0 : return -1;
361 : }
362 :
- 363 3173372 : return 0;
+ 363 3173210 : return 0;
364 : }
365 :
- 366 3690991 : 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)
+ 366 3690989 : 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)
367 : {
368 : struct snapraid_file* file;
369 : block_off_t i;
370 :
- 371 3690991 : file = malloc_nofail(sizeof(struct snapraid_file));
- 372 3690991 : file->sub = strdup_nofail(sub);
- 373 3690991 : file->size = size;
- 374 3690991 : file->blockmax = (size + block_size - 1) / block_size;
- 375 3690991 : file->mtime_sec = mtime_sec;
- 376 3690991 : file->mtime_nsec = mtime_nsec;
- 377 3690991 : file->inode = inode;
- 378 3690991 : file->physical = physical;
- 379 3690991 : file->flag = 0;
- 380 3690991 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof());
+ 371 3690989 : file = malloc_nofail(sizeof(struct snapraid_file));
+ 372 3690989 : file->sub = strdup_nofail(sub);
+ 373 3690989 : file->size = size;
+ 374 3690989 : file->blockmax = (size + block_size - 1) / block_size;
+ 375 3690989 : file->mtime_sec = mtime_sec;
+ 376 3690989 : file->mtime_nsec = mtime_nsec;
+ 377 3690989 : file->inode = inode;
+ 378 3690989 : file->physical = physical;
+ 379 3690989 : file->flag = 0;
+ 380 3690989 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof());
381 :
- 382 12810201 : for (i = 0; i < file->blockmax; ++i) {
- 383 9119210 : struct snapraid_block* block = file_block(file, i);
- 384 9119210 : block_state_set(block, BLOCK_STATE_CHG);
- 385 9119210 : hash_invalid_set(block->hash);
+ 382 12810275 : for (i = 0; i < file->blockmax; ++i) {
+ 383 9119286 : struct snapraid_block* block = file_block(file, i);
+ 384 9119286 : block_state_set(block, BLOCK_STATE_CHG);
+ 385 9119286 : hash_invalid_set(block->hash);
386 : }
387 :
- 388 3690991 : return file;
+ 388 3690989 : return file;
389 : }
390 :
391 22687 : struct snapraid_file* file_dup(struct snapraid_file* copy)
@@ -476,14 +476,14 @@
414 22687 : return file;
415 : }
416 :
- 417 3543815 : void file_free(struct snapraid_file* file)
+ 417 3543813 : void file_free(struct snapraid_file* file)
418 : {
- 419 3543815 : free(file->sub);
- 420 3543815 : file->sub = 0;
- 421 3543815 : free(file->blockvec);
- 422 3543815 : file->blockvec = 0;
- 423 3543815 : free(file);
- 424 3543815 : }
+ 419 3543813 : free(file->sub);
+ 420 3543813 : file->sub = 0;
+ 421 3543813 : free(file->blockvec);
+ 422 3543813 : file->blockvec = 0;
+ 423 3543813 : free(file);
+ 424 3543813 : }
425 :
426 155 : void file_rename(struct snapraid_file* file, const char* sub)
427 : {
@@ -527,31 +527,31 @@
465 23636 : file_flag_set(dst_file, FILE_IS_COPY);
466 23636 : }
467 :
- 468 47954 : const char* file_name(const struct snapraid_file* file)
+ 468 47970 : const char* file_name(const struct snapraid_file* file)
469 : {
- 470 47954 : const char* r = strrchr(file->sub, '/');
+ 470 47970 : const char* r = strrchr(file->sub, '/');
471 :
- 472 47954 : if (!r)
+ 472 47970 : if (!r)
473 78 : r = file->sub;
474 : else
- 475 47876 : ++r;
- 476 47954 : return r;
+ 475 47892 : ++r;
+ 476 47970 : return r;
477 : }
478 :
- 479 6823038 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size)
+ 479 6820121 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size)
480 : {
481 : /* if it's the last block */
- 482 6823038 : if (file_pos + 1 == file->blockmax) {
+ 482 6820121 : if (file_pos + 1 == file->blockmax) {
483 : unsigned block_remainder;
- 484 2775121 : if (file->size == 0)
+ 484 2774907 : if (file->size == 0)
485 0 : return 0;
- 486 2775121 : block_remainder = file->size % block_size;
- 487 2775121 : if (block_remainder == 0)
+ 486 2774907 : block_remainder = file->size % block_size;
+ 487 2774907 : if (block_remainder == 0)
488 3044 : block_remainder = block_size;
- 489 2775121 : return block_remainder;
+ 489 2774907 : return block_remainder;
490 : }
491 :
- 492 4047917 : return block_size;
+ 492 4045214 : return block_size;
493 : }
494 :
495 5329167 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos)
@@ -569,16 +569,16 @@
507 5329167 : return file_pos == file->blockmax - 1;
508 : }
509 :
- 510 975235 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data)
+ 510 987374 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data)
511 : {
- 512 975235 : const uint64_t* arg = void_arg;
- 513 975235 : const struct snapraid_file* file = void_data;
+ 512 987374 : const uint64_t* arg = void_arg;
+ 513 987374 : const struct snapraid_file* file = void_data;
514 :
- 515 975235 : if (*arg < file->inode)
- 516 0 : return -1;
- 517 975235 : if (*arg > file->inode)
+ 515 987374 : if (*arg < file->inode)
+ 516 1 : return -1;
+ 517 987373 : if (*arg > file->inode)
518 0 : return 1;
- 519 975235 : return 0;
+ 519 987373 : return 0;
520 : }
521 :
522 0 : int file_inode_compare(const void* void_a, const void* void_b)
@@ -593,42 +593,42 @@
531 0 : return 0;
532 : }
533 :
- 534 189475 : int file_path_compare(const void* void_a, const void* void_b)
+ 534 189473 : int file_path_compare(const void* void_a, const void* void_b)
535 : {
- 536 189475 : const struct snapraid_file* file_a = void_a;
- 537 189475 : const struct snapraid_file* file_b = void_b;
+ 536 189473 : const struct snapraid_file* file_a = void_a;
+ 537 189473 : const struct snapraid_file* file_b = void_b;
538 :
- 539 189475 : return strcmp(file_a->sub, file_b->sub);
+ 539 189473 : return strcmp(file_a->sub, file_b->sub);
540 : }
541 :
- 542 44212 : int file_physical_compare(const void* void_a, const void* void_b)
+ 542 53902 : int file_physical_compare(const void* void_a, const void* void_b)
543 : {
- 544 44212 : const struct snapraid_file* file_a = void_a;
- 545 44212 : const struct snapraid_file* file_b = void_b;
+ 544 53902 : const struct snapraid_file* file_a = void_a;
+ 545 53902 : const struct snapraid_file* file_b = void_b;
546 :
- 547 44212 : if (file_a->physical < file_b->physical)
- 548 31866 : return -1;
- 549 12346 : if (file_a->physical > file_b->physical)
- 550 12344 : return 1;
+ 547 53902 : if (file_a->physical < file_b->physical)
+ 548 37798 : return -1;
+ 549 16104 : if (file_a->physical > file_b->physical)
+ 550 16102 : return 1;
551 2 : return 0;
552 : }
553 :
- 554 97871 : int file_path_compare_to_arg(const void* void_arg, const void* void_data)
+ 554 103588 : int file_path_compare_to_arg(const void* void_arg, const void* void_data)
555 : {
- 556 97871 : const char* arg = void_arg;
- 557 97871 : const struct snapraid_file* file = void_data;
+ 556 103588 : const char* arg = void_arg;
+ 557 103588 : const struct snapraid_file* file = void_data;
558 :
- 559 97871 : return strcmp(arg, file->sub);
+ 559 103588 : return strcmp(arg, file->sub);
560 : }
561 :
- 562 23977 : int file_name_compare(const void* void_a, const void* void_b)
+ 562 23985 : int file_name_compare(const void* void_a, const void* void_b)
563 : {
- 564 23977 : const struct snapraid_file* file_a = void_a;
- 565 23977 : const struct snapraid_file* file_b = void_b;
- 566 23977 : const char* name_a = file_name(file_a);
- 567 23977 : const char* name_b = file_name(file_b);
+ 564 23985 : const struct snapraid_file* file_a = void_a;
+ 565 23985 : const struct snapraid_file* file_b = void_b;
+ 566 23985 : const char* name_a = file_name(file_a);
+ 567 23985 : const char* name_b = file_name(file_b);
568 :
- 569 23977 : return strcmp(name_a, name_b);
+ 569 23985 : return strcmp(name_a, name_b);
570 : }
571 :
572 23670 : int file_stamp_compare(const void* void_a, const void* void_b)
@@ -654,13 +654,13 @@
592 23670 : return 0;
593 : }
594 :
- 595 23977 : int file_namestamp_compare(const void* void_a, const void* void_b)
+ 595 23985 : int file_namestamp_compare(const void* void_a, const void* void_b)
596 : {
597 : int ret;
598 :
- 599 23977 : ret = file_name_compare(void_a, void_b);
- 600 23977 : if (ret != 0)
- 601 307 : return ret;
+ 599 23985 : ret = file_name_compare(void_a, void_b);
+ 600 23985 : if (ret != 0)
+ 601 315 : return ret;
602 :
603 23670 : return file_stamp_compare(void_a, void_b);
604 : }
@@ -676,66 +676,66 @@
614 0 : return file_stamp_compare(void_a, void_b);
615 : }
616 :
- 617 3735289 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count)
+ 617 3735329 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count)
618 : {
619 : struct snapraid_extent* extent;
620 :
- 621 3735289 : if (count == 0) {
+ 621 3735329 : if (count == 0) {
622 : /* LCOV_EXCL_START */
623 : log_fatal("Internal inconsistency when allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
624 : os_abort();
625 : /* LCOV_EXCL_STOP */
626 : }
- 627 3735289 : if (file_pos + count > file->blockmax) {
+ 627 3735329 : if (file_pos + count > file->blockmax) {
628 : /* LCOV_EXCL_START */
629 : log_fatal("Internal inconsistency when allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax);
630 : os_abort();
631 : /* LCOV_EXCL_STOP */
632 : }
633 :
- 634 3735289 : extent = malloc_nofail(sizeof(struct snapraid_extent));
- 635 3735289 : extent->parity_pos = parity_pos;
- 636 3735289 : extent->file = file;
- 637 3735289 : extent->file_pos = file_pos;
- 638 3735289 : extent->count = count;
+ 634 3735329 : extent = malloc_nofail(sizeof(struct snapraid_extent));
+ 635 3735329 : extent->parity_pos = parity_pos;
+ 636 3735329 : extent->file = file;
+ 637 3735329 : extent->file_pos = file_pos;
+ 638 3735329 : extent->count = count;
639 :
- 640 3735289 : return extent;
+ 640 3735329 : return extent;
641 : }
642 :
- 643 3564865 : void extent_free(struct snapraid_extent* extent)
+ 643 3564905 : void extent_free(struct snapraid_extent* extent)
644 : {
- 645 3564865 : free(extent);
- 646 3564865 : }
+ 645 3564905 : free(extent);
+ 646 3564905 : }
647 :
- 648 44509325 : int extent_parity_compare(const void* void_a, const void* void_b)
+ 648 44510915 : int extent_parity_compare(const void* void_a, const void* void_b)
649 : {
- 650 44509325 : const struct snapraid_extent* arg_a = void_a;
- 651 44509325 : const struct snapraid_extent* arg_b = void_b;
+ 650 44510915 : const struct snapraid_extent* arg_a = void_a;
+ 651 44510915 : const struct snapraid_extent* arg_b = void_b;
652 :
- 653 44509325 : if (arg_a->parity_pos < arg_b->parity_pos)
- 654 960426 : return -1;
- 655 43548899 : if (arg_a->parity_pos > arg_b->parity_pos)
- 656 43509241 : return 1;
+ 653 44510915 : if (arg_a->parity_pos < arg_b->parity_pos)
+ 654 961025 : return -1;
+ 655 43549890 : if (arg_a->parity_pos > arg_b->parity_pos)
+ 656 43510236 : return 1;
657 :
- 658 39658 : return 0;
+ 658 39654 : return 0;
659 : }
660 :
- 661 45005658 : int extent_file_compare(const void* void_a, const void* void_b)
+ 661 45007474 : int extent_file_compare(const void* void_a, const void* void_b)
662 : {
- 663 45005658 : const struct snapraid_extent* arg_a = void_a;
- 664 45005658 : const struct snapraid_extent* arg_b = void_b;
+ 663 45007474 : const struct snapraid_extent* arg_a = void_a;
+ 664 45007474 : const struct snapraid_extent* arg_b = void_b;
665 :
- 666 45005658 : if (arg_a->file < arg_b->file)
- 667 875311 : return -1;
- 668 44130347 : if (arg_a->file > arg_b->file)
- 669 44059546 : return 1;
+ 666 45007474 : if (arg_a->file < arg_b->file)
+ 667 874959 : return -1;
+ 668 44132515 : if (arg_a->file > arg_b->file)
+ 669 44061652 : return 1;
670 :
- 671 70801 : if (arg_a->file_pos < arg_b->file_pos)
+ 671 70863 : if (arg_a->file_pos < arg_b->file_pos)
672 208 : return -1;
- 673 70593 : if (arg_a->file_pos > arg_b->file_pos)
- 674 30935 : return 1;
+ 673 70655 : if (arg_a->file_pos > arg_b->file_pos)
+ 674 31001 : return 1;
675 :
- 676 39658 : return 0;
+ 676 39654 : return 0;
677 : }
678 :
679 119522 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag)
@@ -864,23 +864,23 @@
802 1459 : free(disk);
803 1459 : }
804 :
- 805 53195526 : static inline void fs_lock(struct snapraid_disk* disk)
+ 805 53193825 : static inline void fs_lock(struct snapraid_disk* disk)
806 : {
807 : #if HAVE_PTHREAD
- 808 53195526 : thread_mutex_lock(&disk->fs_mutex);
+ 808 53193825 : thread_mutex_lock(&disk->fs_mutex);
809 : #else
810 : (void)disk;
811 : #endif
- 812 53196097 : }
+ 812 53196398 : }
813 :
- 814 53195112 : static inline void fs_unlock(struct snapraid_disk* disk)
+ 814 53194752 : static inline void fs_unlock(struct snapraid_disk* disk)
815 : {
816 : #if HAVE_PTHREAD
- 817 53195112 : thread_mutex_unlock(&disk->fs_mutex);
+ 817 53194752 : thread_mutex_unlock(&disk->fs_mutex);
818 : #else
819 : (void)disk;
820 : #endif
- 821 53196272 : }
+ 821 53196925 : }
822 :
823 : struct extent_disk_empty {
824 : block_off_t blockmax;
@@ -937,17 +937,17 @@
875 : *
876 : * The maximum parity position is stored as size.
877 : */
- 878 50514 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b)
+ 878 50518 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b)
879 : {
- 880 50514 : struct extent_disk_size* arg_a = (void*)void_a;
- 881 50514 : const struct snapraid_extent* arg_b = void_b;
+ 880 50518 : struct extent_disk_size* arg_a = (void*)void_a;
+ 881 50518 : const struct snapraid_extent* arg_b = void_b;
882 :
883 : /* get the maximum size */
- 884 50514 : if (arg_a->size < arg_b->parity_pos + arg_b->count)
- 885 50514 : arg_a->size = arg_b->parity_pos + arg_b->count;
+ 884 50518 : if (arg_a->size < arg_b->parity_pos + arg_b->count)
+ 885 50518 : arg_a->size = arg_b->parity_pos + arg_b->count;
886 :
887 : /* search always for a bigger one */
- 888 50514 : return 1;
+ 888 50518 : return 1;
889 : }
890 :
891 4363 : block_off_t fs_size(struct snapraid_disk* disk)
@@ -968,23 +968,23 @@
906 : int result;
907 : };
908 :
- 909 6584473 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj)
+ 909 6584561 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj)
910 : {
- 911 6584473 : struct extent_check* arg = void_arg;
- 912 6584473 : const struct snapraid_extent* obj = void_obj;
- 913 6584473 : const struct snapraid_extent* prev = arg->prev;
+ 911 6584561 : struct extent_check* arg = void_arg;
+ 912 6584561 : const struct snapraid_extent* obj = void_obj;
+ 913 6584561 : const struct snapraid_extent* prev = arg->prev;
914 :
915 : /* set the next previous block */
- 916 6584473 : arg->prev = obj;
+ 916 6584561 : arg->prev = obj;
917 :
918 : /* stop reporting if too many errors */
- 919 6584473 : if (arg->result > 100) {
+ 919 6584561 : if (arg->result > 100) {
920 : /* LCOV_EXCL_START */
921 : return;
922 : /* LCOV_EXCL_STOP */
923 : }
924 :
- 925 6584473 : if (obj->count == 0) {
+ 925 6584561 : if (obj->count == 0) {
926 : /* LCOV_EXCL_START */
927 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n",
928 : obj->file->sub, obj->parity_pos);
@@ -994,11 +994,11 @@
932 : }
933 :
934 : /* check only if there is a previous block */
- 935 6584473 : if (!prev)
+ 935 6584561 : if (!prev)
936 2723 : return;
937 :
938 : /* check the order */
- 939 6581750 : if (prev->parity_pos >= obj->parity_pos) {
+ 939 6581838 : if (prev->parity_pos >= obj->parity_pos) {
940 : /* LCOV_EXCL_START */
941 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
942 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
@@ -1008,7 +1008,7 @@
946 : }
947 :
948 : /* check that the extents don't overlap */
- 949 6581750 : if (prev->parity_pos + prev->count > obj->parity_pos) {
+ 949 6581838 : if (prev->parity_pos + prev->count > obj->parity_pos) {
950 : /* LCOV_EXCL_START */
951 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
952 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
@@ -1018,23 +1018,23 @@
956 : }
957 : }
958 :
- 959 6584473 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
+ 959 6584561 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
960 : {
- 961 6584473 : struct extent_check* arg = void_arg;
- 962 6584473 : const struct snapraid_extent* obj = void_obj;
- 963 6584473 : const struct snapraid_extent* prev = arg->prev;
+ 961 6584561 : struct extent_check* arg = void_arg;
+ 962 6584561 : const struct snapraid_extent* obj = void_obj;
+ 963 6584561 : const struct snapraid_extent* prev = arg->prev;
964 :
965 : /* set the next previous block */
- 966 6584473 : arg->prev = obj;
+ 966 6584561 : arg->prev = obj;
967 :
968 : /* stop reporting if too many errors */
- 969 6584473 : if (arg->result > 100) {
+ 969 6584561 : if (arg->result > 100) {
970 : /* LCOV_EXCL_START */
971 : return;
972 : /* LCOV_EXCL_STOP */
973 : }
974 :
- 975 6584473 : if (obj->count == 0) {
+ 975 6584561 : if (obj->count == 0) {
976 : /* LCOV_EXCL_START */
977 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n",
978 : obj->file->sub, obj->file_pos);
@@ -1046,7 +1046,7 @@
984 : /* note that for deleted files, some extents may be missing */
985 :
986 : /* if the files are different */
- 987 6584473 : if (!prev || prev->file != obj->file) {
+ 987 6584561 : if (!prev || prev->file != obj->file) {
988 6538269 : if (prev != 0) {
989 6535546 : if (file_flag_has(prev->file, FILE_IS_DELETED)) {
990 : /* check that the extent doesn't overflow the file */
@@ -1094,7 +1094,7 @@
1032 : }
1033 : } else {
1034 : /* check the order */
- 1035 46204 : if (prev->file_pos >= obj->file_pos) {
+ 1035 46292 : if (prev->file_pos >= obj->file_pos) {
1036 : /* LCOV_EXCL_START */
1037 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n",
1038 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
@@ -1103,7 +1103,7 @@
1041 : /* LCOV_EXCL_STOP */
1042 : }
1043 :
- 1044 46204 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
+ 1044 46292 : if (file_flag_has(obj->file, FILE_IS_DELETED)) {
1045 : /* check that the extents don't overlap */
1046 27 : if (prev->file_pos + prev->count > obj->file_pos) {
1047 : /* LCOV_EXCL_START */
@@ -1115,7 +1115,7 @@
1053 : }
1054 : } else {
1055 : /* check that the extents are sequential */
- 1056 46177 : if (prev->file_pos + prev->count != obj->file_pos) {
+ 1056 46265 : if (prev->file_pos + prev->count != obj->file_pos) {
1057 : /* LCOV_EXCL_START */
1058 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
1059 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
@@ -1159,17 +1159,17 @@
1097 : /**
1098 : * Compare the extent if containing the specified parity position.
1099 : */
- 1100 114575009 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b)
+ 1100 113415111 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b)
1101 : {
- 1102 114575009 : const struct extent_parity_inside* arg_a = void_a;
- 1103 114575009 : const struct snapraid_extent* arg_b = void_b;
+ 1102 113415111 : const struct extent_parity_inside* arg_a = void_a;
+ 1103 113415111 : const struct snapraid_extent* arg_b = void_b;
1104 :
- 1105 114575009 : if (arg_a->parity_pos < arg_b->parity_pos)
- 1106 40547890 : return -1;
- 1107 74027119 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count)
- 1108 65245847 : return 1;
+ 1105 113415111 : if (arg_a->parity_pos < arg_b->parity_pos)
+ 1106 40067087 : return -1;
+ 1107 73348024 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count)
+ 1108 64675056 : return 1;
1109 :
- 1110 8781272 : return 0;
+ 1110 8672968 : return 0;
1111 : }
1112 :
1113 : /**
@@ -1177,28 +1177,28 @@
1115 : * The search is optimized for sequential accesses.
1116 : * \return If not found return 0
1117 : */
- 1118 39143508 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos)
+ 1118 39142622 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos)
1119 : {
1120 : struct snapraid_extent* extent;
1121 :
1122 : /* check if the last accessed extent matches */
- 1123 39143508 : if (*fs_last
- 1124 39125091 : && parity_pos >= (*fs_last)->parity_pos
- 1125 38408678 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count
+ 1123 39142622 : if (*fs_last
+ 1124 39124369 : && parity_pos >= (*fs_last)->parity_pos
+ 1125 38409994 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count
1126 : ) {
- 1127 28777623 : extent = *fs_last;
+ 1127 28886530 : extent = *fs_last;
1128 : } else {
- 1129 10365885 : struct extent_parity_inside arg = { parity_pos };
- 1130 10365885 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg);
+ 1129 10256092 : struct extent_parity_inside arg = { parity_pos };
+ 1130 10256092 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg);
1131 : }
1132 :
- 1133 39143433 : if (!extent)
- 1134 1584679 : return 0;
+ 1133 39144071 : if (!extent)
+ 1134 1584630 : return 0;
1135 :
1136 : /* store the last accessed extent */
- 1137 37558754 : *fs_last = extent;
+ 1137 37559441 : *fs_last = extent;
1138 :
- 1139 37558754 : return extent;
+ 1139 37559441 : return extent;
1140 : }
1141 :
1142 : struct extent_file_inside {
@@ -1209,22 +1209,22 @@
1147 : /**
1148 : * Compare the extent if containing the specified file position.
1149 : */
- 1150 21310995 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b)
+ 1150 21313929 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b)
1151 : {
- 1152 21310995 : const struct extent_file_inside* arg_a = void_a;
- 1153 21310995 : const struct snapraid_extent* arg_b = void_b;
+ 1152 21313929 : const struct extent_file_inside* arg_a = void_a;
+ 1153 21313929 : const struct snapraid_extent* arg_b = void_b;
1154 :
- 1155 21310995 : if (arg_a->file < arg_b->file)
- 1156 8885792 : return -1;
- 1157 12425203 : if (arg_a->file > arg_b->file)
- 1158 10405515 : return 1;
+ 1155 21313929 : if (arg_a->file < arg_b->file)
+ 1156 8885403 : return -1;
+ 1157 12428526 : if (arg_a->file > arg_b->file)
+ 1158 10408652 : return 1;
1159 :
- 1160 2019688 : if (arg_a->file_pos < arg_b->file_pos)
- 1161 8333 : return -1;
- 1162 2011355 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count)
- 1163 7947 : return 1;
+ 1160 2019874 : if (arg_a->file_pos < arg_b->file_pos)
+ 1161 8344 : return -1;
+ 1162 2011530 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count)
+ 1163 7997 : return 1;
1164 :
- 1165 2003408 : return 0;
+ 1165 2003533 : return 0;
1166 : }
1167 :
1168 : /**
@@ -1232,88 +1232,88 @@
1170 : * The search is optimized for sequential accesses.
1171 : * \return If not found return 0
1172 : */
- 1173 10336255 : static struct snapraid_extent* fs_file2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, struct snapraid_file* file, block_off_t file_pos)
+ 1173 10336367 : static struct snapraid_extent* fs_file2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, struct snapraid_file* file, block_off_t file_pos)
1174 : {
1175 : struct snapraid_extent* extent;
1176 :
1177 : /* check if the last accessed extent matches */
- 1178 10336255 : if (*fs_last
- 1179 10312569 : && file == (*fs_last)->file
- 1180 8347073 : && file_pos >= (*fs_last)->file_pos
- 1181 8347073 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count
+ 1178 10336367 : if (*fs_last
+ 1179 10312681 : && file == (*fs_last)->file
+ 1180 8347105 : && file_pos >= (*fs_last)->file_pos
+ 1181 8347105 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count
1182 : ) {
- 1183 8332839 : extent = *fs_last;
+ 1183 8332826 : extent = *fs_last;
1184 : } else {
- 1185 2003416 : struct extent_file_inside arg = { file, file_pos };
- 1186 2003416 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg);
+ 1185 2003541 : struct extent_file_inside arg = { file, file_pos };
+ 1186 2003541 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg);
1187 : }
1188 :
- 1189 10336255 : if (!extent)
+ 1189 10336367 : if (!extent)
1190 8 : return 0;
1191 :
1192 : /* store the last accessed extent */
- 1193 10336247 : *fs_last = extent;
+ 1193 10336359 : *fs_last = extent;
1194 :
- 1195 10336247 : return extent;
+ 1195 10336359 : return extent;
1196 : }
1197 :
- 1198 39036978 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
+ 1198 39034767 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
1199 : {
1200 : struct snapraid_extent* extent;
1201 : struct snapraid_file* file;
1202 :
- 1203 39036978 : fs_lock(disk);
+ 1203 39034767 : fs_lock(disk);
1204 :
- 1205 39037785 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos);
+ 1205 39037534 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos);
1206 :
- 1207 39036721 : if (!extent) {
- 1208 1584680 : fs_unlock(disk);
- 1209 1584723 : return 0;
+ 1207 39037013 : if (!extent) {
+ 1208 1584625 : fs_unlock(disk);
+ 1209 1584635 : return 0;
1210 : }
1211 :
- 1212 37452041 : if (file_pos)
- 1213 37107540 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos);
+ 1212 37452388 : if (file_pos)
+ 1213 37108181 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos);
1214 :
- 1215 37452041 : file = extent->file;
+ 1215 37452388 : file = extent->file;
1216 :
- 1217 37452041 : fs_unlock(disk);
- 1218 37453073 : return file;
+ 1217 37452388 : fs_unlock(disk);
+ 1218 37453620 : return file;
1219 : }
1220 :
- 1221 4869703 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
+ 1221 4869735 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
1222 : {
1223 : struct snapraid_extent* extent;
1224 : block_off_t ret;
1225 :
- 1226 4869703 : fs_lock(disk);
+ 1226 4869735 : fs_lock(disk);
1227 :
- 1228 4869703 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos);
- 1229 4869703 : if (!extent) {
+ 1228 4869735 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos);
+ 1229 4869735 : if (!extent) {
1230 8 : fs_unlock(disk);
1231 8 : return POS_NULL;
1232 : }
1233 :
- 1234 4869695 : ret = extent->parity_pos + (file_pos - extent->file_pos);
+ 1234 4869727 : ret = extent->parity_pos + (file_pos - extent->file_pos);
1235 :
- 1236 4869695 : fs_unlock(disk);
- 1237 4869695 : return ret;
+ 1236 4869727 : fs_unlock(disk);
+ 1237 4869727 : return ret;
1238 : }
1239 :
- 1240 9175178 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos)
+ 1240 9175254 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos)
1241 : {
1242 : struct snapraid_extent* extent;
1243 : struct snapraid_extent* parity_extent;
1244 : struct snapraid_extent* file_extent;
1245 :
- 1246 9175178 : fs_lock(disk);
+ 1246 9175254 : fs_lock(disk);
1247 :
- 1248 9175178 : if (file_pos > 0) {
+ 1248 9175254 : if (file_pos > 0) {
1249 : /* search an existing extent for the previous file_pos */
- 1250 5466552 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1);
+ 1250 5466632 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1);
1251 :
- 1252 5466552 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) {
+ 1252 5466632 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) {
1253 : /* ensure that we are extending the extent at the end */
- 1254 5439890 : if (file_pos != extent->file_pos + extent->count) {
+ 1254 5439926 : if (file_pos != extent->file_pos + extent->count) {
1255 : /* LCOV_EXCL_START */
1256 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
1257 : os_abort();
@@ -1321,21 +1321,21 @@
1259 : }
1260 :
1261 : /* extend the existing extent */
- 1262 5439890 : ++extent->count;
+ 1262 5439926 : ++extent->count;
1263 :
- 1264 5439890 : fs_unlock(disk);
- 1265 14615068 : return;
+ 1264 5439926 : fs_unlock(disk);
+ 1265 14615180 : return;
1266 : }
1267 : }
1268 :
1269 : /* a extent doesn't exist, and we have to create a new one */
- 1270 3735288 : extent = extent_alloc(parity_pos, file, file_pos, 1);
+ 1270 3735328 : extent = extent_alloc(parity_pos, file, file_pos, 1);
1271 :
1272 : /* insert the extent in the trees */
- 1273 3735288 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent);
- 1274 3735288 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent);
+ 1273 3735328 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent);
+ 1274 3735328 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent);
1275 :
- 1276 3735288 : if (parity_extent != extent || file_extent != extent) {
+ 1276 3735328 : if (parity_extent != extent || file_extent != extent) {
1277 : /* LCOV_EXCL_START */
1278 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
1279 : os_abort();
@@ -1343,12 +1343,12 @@
1281 : }
1282 :
1283 : /* store the last accessed extent */
- 1284 3735288 : disk->fs_last = extent;
+ 1284 3735328 : disk->fs_last = extent;
1285 :
- 1286 3735288 : fs_unlock(disk);
+ 1286 3735328 : fs_unlock(disk);
1287 : }
1288 :
- 1289 106232 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
+ 1289 106308 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
1290 : {
1291 : struct snapraid_extent* extent;
1292 : struct snapraid_extent* second_extent;
@@ -1356,10 +1356,10 @@
1294 : struct snapraid_extent* file_extent;
1295 : block_off_t first_count, second_count;
1296 :
- 1297 106232 : fs_lock(disk);
+ 1297 106308 : fs_lock(disk);
1298 :
- 1299 106232 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos);
- 1300 106232 : if (!extent) {
+ 1299 106308 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos);
+ 1300 106308 : if (!extent) {
1301 : /* LCOV_EXCL_START */
1302 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name);
1303 : os_abort();
@@ -1367,29 +1367,29 @@
1305 : }
1306 :
1307 : /* if it's the only block of the extent, delete it */
- 1308 106232 : if (extent->count == 1) {
+ 1308 106308 : if (extent->count == 1) {
1309 : /* remove from the trees */
- 1310 39658 : tommy_tree_remove(&disk->fs_parity, extent);
- 1311 39658 : tommy_tree_remove(&disk->fs_file, extent);
+ 1310 39654 : tommy_tree_remove(&disk->fs_parity, extent);
+ 1311 39654 : tommy_tree_remove(&disk->fs_file, extent);
1312 :
1313 : /* deallocate */
- 1314 39658 : extent_free(extent);
+ 1314 39654 : extent_free(extent);
1315 :
1316 : /* clear the last accessed extent */
- 1317 39658 : disk->fs_last = 0;
+ 1317 39654 : disk->fs_last = 0;
1318 :
- 1319 39658 : fs_unlock(disk);
- 1320 39658 : return;
+ 1319 39654 : fs_unlock(disk);
+ 1320 39654 : return;
1321 : }
1322 :
1323 : /* if it's at the start of the extent, shrink the extent */
- 1324 66574 : if (parity_pos == extent->parity_pos) {
- 1325 66572 : ++extent->parity_pos;
- 1326 66572 : ++extent->file_pos;
- 1327 66572 : --extent->count;
+ 1324 66654 : if (parity_pos == extent->parity_pos) {
+ 1325 66652 : ++extent->parity_pos;
+ 1326 66652 : ++extent->file_pos;
+ 1327 66652 : --extent->count;
1328 :
- 1329 66572 : fs_unlock(disk);
- 1330 66572 : return;
+ 1329 66652 : fs_unlock(disk);
+ 1330 66652 : return;
1331 : }
1332 :
1333 : /* if it's at the end of the extent, shrink the extent */
@@ -1427,28 +1427,28 @@
1365 1 : fs_unlock(disk);
1366 : }
1367 :
- 1368 44945354 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos)
+ 1368 44945861 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos)
1369 : {
- 1370 44945354 : if (file_pos >= file->blockmax) {
+ 1370 44945861 : if (file_pos >= file->blockmax) {
1371 : /* LCOV_EXCL_START */
1372 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
1373 : os_abort();
1374 : /* LCOV_EXCL_STOP */
1375 : }
1376 :
- 1377 44945354 : return file_block(file, file_pos);
+ 1377 44945861 : return file_block(file, file_pos);
1378 : }
1379 :
- 1380 27313631 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos)
+ 1380 27313617 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos)
1381 : {
1382 : struct snapraid_file* file;
1383 : block_off_t file_pos;
1384 :
- 1385 27313631 : file = fs_par2file_find(disk, parity_pos, &file_pos);
- 1386 27313916 : if (file == 0)
- 1387 1584719 : return BLOCK_NULL;
+ 1385 27313617 : file = fs_par2file_find(disk, parity_pos, &file_pos);
+ 1386 27314375 : if (file == 0)
+ 1387 1584611 : return BLOCK_NULL;
1388 :
- 1389 25729197 : return fs_file2block_get(file, file_pos);
+ 1389 25729764 : return fs_file2block_get(file, file_pos);
1390 : }
1391 :
1392 1561 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid)
@@ -1470,16 +1470,16 @@
1408 1435 : free(map);
1409 1435 : }
1410 :
- 1411 691801 : int time_compare(const void* void_a, const void* void_b)
+ 1411 675269 : int time_compare(const void* void_a, const void* void_b)
1412 : {
- 1413 691801 : const time_t* time_a = void_a;
- 1414 691801 : const time_t* time_b = void_b;
+ 1413 675269 : const time_t* time_a = void_a;
+ 1414 675269 : const time_t* time_b = void_b;
1415 :
- 1416 691801 : if (*time_a < *time_b)
- 1417 18310 : return -1;
- 1418 673491 : if (*time_a > *time_b)
- 1419 129297 : return 1;
- 1420 544194 : return 0;
+ 1416 675269 : if (*time_a < *time_b)
+ 1417 16327 : return -1;
+ 1418 658942 : if (*time_a > *time_b)
+ 1419 110431 : return 1;
+ 1420 548511 : return 0;
1421 : }
1422 :
1423 : /****************************************************************************/
@@ -1499,14 +1499,14 @@
1437 : /**
1438 : * Format a path name for terminal reference
1439 : */
- 1440 355906 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer)
+ 1440 356144 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer)
1441 : {
1442 : const char* out[3];
1443 :
- 1444 355906 : switch (FMT_MODE) {
+ 1444 356144 : switch (FMT_MODE) {
1445 : case FMT_FILE :
1446 : default :
- 1447 331846 : return esc_shell(str, buffer);
+ 1447 332084 : return esc_shell(str, buffer);
1448 : case FMT_DISK :
1449 12030 : out[0] = disk->name;
1450 12030 : out[1] = ":";
diff --git a/cov/cmdline/elem.h.func-sort-c.html b/cov/cmdline/elem.h.func-sort-c.html
index b2224709..7535ce31 100644
--- a/cov/cmdline/elem.h.func-sort-c.html
+++ b/cov/cmdline/elem.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,67 +61,67 @@
| block_sizeof |
- 58065128 |
+ 58065229 |
| file_block |
- 54351316 |
+ 54351162 |
| block_state_get |
- 52304023 |
+ 52305826 |
| file_flag_has |
- 34089332 |
+ 34102051 |
| block_state_set |
- 19117096 |
+ 19117692 |
| block_has_file |
- 14591493 |
+ 14589756 |
| block_has_invalid_parity |
- 12320585 |
+ 12320925 |
| fs_par2file_get |
- 11723835 |
+ 11722518 |
| hash_invalid_set |
- 9234067 |
+ 9234143 |
| file_stamp_hash |
- 6275421 |
+ 6275620 |
| file_flag_set |
- 5295048 |
+ 5303183 |
| info_get |
- 5098669 |
+ 5098731 |
| file_inode_hash |
- 5042449 |
+ 5055357 |
| fs_file2par_get |
- 4755492 |
+ 4755524 |
| file_path_hash |
- 3886182 |
+ 3891897 |
| filter_hidden |
- 3173372 |
+ 3173210 |
| block_has_past_hash |
@@ -129,43 +129,43 @@
| block_has_updated_hash |
- 2217099 |
+ 2218229 |
| info_get_rehash |
- 2046851 |
+ 2046849 |
| info_set |
- 1698121 |
+ 1698196 |
| info_get_time |
- 883203 |
+ 883145 |
| hash_is_zero |
- 760108 |
+ 760608 |
| hash_is_invalid |
- 758645 |
+ 759146 |
| info_get_bad |
- 352076 |
+ 352062 |
| block_has_file_and_valid_parity |
- 220962 |
+ 220963 |
| link_flag_has |
- 209328 |
+ 209329 |
| info_make |
- 194583 |
+ 194621 |
| link_name_hash |
@@ -181,23 +181,23 @@
| info_get_justsynced |
- 68634 |
+ 68576 |
| hash_is_unique |
- 44270 |
+ 44326 |
| link_flag_set |
39461 |
- | fs_par2block_get |
- 15867 |
+ file_flag_clear |
+ 18420 |
- | file_flag_clear |
- 11286 |
+ fs_par2block_get |
+ 15867 |
| info_set_rehash |
diff --git a/cov/cmdline/elem.h.func.html b/cov/cmdline/elem.h.func.html
index 36d3ea93..4729ebe7 100644
--- a/cov/cmdline/elem.h.func.html
+++ b/cov/cmdline/elem.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| block_has_file |
- 14591493 |
+ 14589756 |
| block_has_file_and_valid_parity |
- 220962 |
+ 220963 |
| block_has_invalid_parity |
- 12320585 |
+ 12320925 |
| block_has_past_hash |
@@ -77,19 +77,19 @@
| block_has_updated_hash |
- 2217099 |
+ 2218229 |
| block_sizeof |
- 58065128 |
+ 58065229 |
| block_state_get |
- 52304023 |
+ 52305826 |
| block_state_set |
- 19117096 |
+ 19117692 |
| dir_flag_has |
@@ -105,39 +105,39 @@
| file_block |
- 54351316 |
+ 54351162 |
| file_flag_clear |
- 11286 |
+ 18420 |
| file_flag_has |
- 34089332 |
+ 34102051 |
| file_flag_set |
- 5295048 |
+ 5303183 |
| file_inode_hash |
- 5042449 |
+ 5055357 |
| file_path_hash |
- 3886182 |
+ 3891897 |
| file_stamp_hash |
- 6275421 |
+ 6275620 |
| filter_hidden |
- 3173372 |
+ 3173210 |
| fs_file2par_get |
- 4755492 |
+ 4755524 |
| fs_par2block_get |
@@ -145,23 +145,23 @@
| fs_par2file_get |
- 11723835 |
+ 11722518 |
| hash_invalid_set |
- 9234067 |
+ 9234143 |
| hash_is_invalid |
- 758645 |
+ 759146 |
| hash_is_unique |
- 44270 |
+ 44326 |
| hash_is_zero |
- 760108 |
+ 760608 |
| hash_zero_set |
@@ -169,31 +169,31 @@
| info_get |
- 5098669 |
+ 5098731 |
| info_get_bad |
- 352076 |
+ 352062 |
| info_get_justsynced |
- 68634 |
+ 68576 |
| info_get_rehash |
- 2046851 |
+ 2046849 |
| info_get_time |
- 883203 |
+ 883145 |
| info_make |
- 194583 |
+ 194621 |
| info_set |
- 1698121 |
+ 1698196 |
| info_set_bad |
@@ -209,7 +209,7 @@
| link_flag_has |
- 209328 |
+ 209329 |
| link_flag_let |
diff --git a/cov/cmdline/elem.h.gcov.html b/cov/cmdline/elem.h.gcov.html
index ddba0d94..ebdda3ae 100644
--- a/cov/cmdline/elem.h.gcov.html
+++ b/cov/cmdline/elem.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -525,7 +525,7 @@
463 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
464 : block_off_t total_blocks; /**< Number of total blocks. */
465 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */
- 466 : int is_excluded; /**< If the parity is excluded by disk filter. */
+ 466 : int is_excluded_by_filter; /**< If the parity is excluded by filters. */
467 : int skip_access; /**< If at least one of the parity disk is inaccessible and it should be skipped. */
468 : uint64_t tick; /**< Usage time. */
469 : uint64_t progress_tick[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
@@ -571,13 +571,13 @@
509 : * Filter hidden files.
510 : * Return !=0 if it matches and it should be excluded.
511 : */
- 512 3173372 : static inline int filter_hidden(int enable, struct dirent* dd)
+ 512 3173210 : static inline int filter_hidden(int enable, struct dirent* dd)
513 : {
- 514 3173372 : if (enable && dirent_hidden(dd)) {
+ 514 3173210 : if (enable && dirent_hidden(dd)) {
515 0 : return 1; /* filter out */
516 : }
517 :
- 518 3173372 : return 0;
+ 518 3173210 : return 0;
519 : }
520 :
521 : /**
@@ -628,17 +628,17 @@
566 : *
567 : * If working with reduced hash lengths, this function always return 0.
568 : */
- 569 758645 : static inline int hash_is_invalid(const unsigned char* hash)
+ 569 759146 : static inline int hash_is_invalid(const unsigned char* hash)
570 : {
571 : int i;
572 :
573 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */
- 574 758645 : if (BLOCK_HASH_SIZE != HASH_MAX)
+ 574 759146 : if (BLOCK_HASH_SIZE != HASH_MAX)
575 0 : return 0;
576 :
- 577 1178483 : for (i = 0; i < BLOCK_HASH_SIZE; ++i)
- 578 1152419 : if (hash[i] != 0x00)
- 579 732581 : return 0;
+ 577 1179527 : for (i = 0; i < BLOCK_HASH_SIZE; ++i)
+ 578 1153463 : if (hash[i] != 0x00)
+ 579 733082 : return 0;
580 :
581 26064 : return 1;
582 : }
@@ -650,19 +650,19 @@
588 : *
589 : * If working with reduced hash lengths, this function always return 0.
590 : */
- 591 760108 : static inline int hash_is_zero(const unsigned char* hash)
+ 591 760608 : static inline int hash_is_zero(const unsigned char* hash)
592 : {
593 : int i;
594 :
595 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */
- 596 760108 : if (BLOCK_HASH_SIZE != HASH_MAX)
+ 596 760608 : if (BLOCK_HASH_SIZE != HASH_MAX)
597 0 : return 0;
598 :
- 599 994848 : for (i = 0; i < BLOCK_HASH_SIZE; ++i)
- 600 980378 : if (hash[i] != 0xFF)
- 601 745638 : return 0;
+ 599 995114 : for (i = 0; i < BLOCK_HASH_SIZE; ++i)
+ 600 980645 : if (hash[i] != 0xFF)
+ 601 746139 : return 0;
602 :
- 603 14470 : return 1;
+ 603 14469 : return 1;
604 : }
605 :
606 : /**
@@ -670,22 +670,22 @@
608 : *
609 : * If working with reduced hash lengths, this function always return 0.
610 : */
- 611 44270 : static inline int hash_is_unique(const unsigned char* hash)
+ 611 44326 : static inline int hash_is_unique(const unsigned char* hash)
612 : {
613 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */
- 614 44270 : if (BLOCK_HASH_SIZE != HASH_MAX)
+ 614 44326 : if (BLOCK_HASH_SIZE != HASH_MAX)
615 0 : return 0;
616 :
- 617 44270 : return !hash_is_zero(hash) && !hash_is_invalid(hash);
+ 617 44326 : return !hash_is_zero(hash) && !hash_is_invalid(hash);
618 : }
619 :
620 : /**
621 : * Set the hash to the special INVALID value.
622 : */
- 623 9234067 : static inline void hash_invalid_set(unsigned char* hash)
+ 623 9234143 : static inline void hash_invalid_set(unsigned char* hash)
624 : {
- 625 9234067 : memset(hash, 0x00, BLOCK_HASH_SIZE);
- 626 9234067 : }
+ 625 9234143 : memset(hash, 0x00, BLOCK_HASH_SIZE);
+ 626 9234143 : }
627 :
628 : /**
629 : * Set the hash to the special ZERO value.
@@ -698,9 +698,9 @@
636 : /**
637 : * Allocated space for block.
638 : */
- 639 58065128 : static inline size_t block_sizeof(void)
+ 639 58065229 : static inline size_t block_sizeof(void)
640 : {
- 641 58065128 : return 1 + BLOCK_HASH_SIZE;
+ 641 58065229 : return 1 + BLOCK_HASH_SIZE;
642 : }
643 :
644 : /**
@@ -709,32 +709,32 @@
647 : * For this function, it's allowed to pass a NULL block
648 : * pointer than results in the BLOCK_STATE_EMPTY state.
649 : */
- 650 52304023 : static inline unsigned block_state_get(const struct snapraid_block* block)
+ 650 52305826 : static inline unsigned block_state_get(const struct snapraid_block* block)
651 : {
- 652 52304023 : if (block == BLOCK_NULL)
- 653 1722497 : return BLOCK_STATE_EMPTY;
+ 652 52305826 : if (block == BLOCK_NULL)
+ 653 1722139 : return BLOCK_STATE_EMPTY;
654 :
- 655 50581526 : return block->state;
+ 655 50583687 : return block->state;
656 : }
657 :
658 : /**
659 : * Set the state of the block.
660 : */
- 661 19117096 : static inline void block_state_set(struct snapraid_block* block, unsigned state)
+ 661 19117692 : static inline void block_state_set(struct snapraid_block* block, unsigned state)
662 : {
- 663 19117096 : block->state = state;
- 664 19117096 : }
+ 663 19117692 : block->state = state;
+ 664 19117692 : }
665 :
666 : /**
667 : * Check if the specified block has an updated hash.
668 : *
669 : * Note that EMPTY / CHG / DELETED return 0.
670 : */
- 671 2217099 : static inline int block_has_updated_hash(const struct snapraid_block* block)
+ 671 2218229 : static inline int block_has_updated_hash(const struct snapraid_block* block)
672 : {
- 673 2217099 : unsigned state = block_state_get(block);
+ 673 2218229 : unsigned state = block_state_get(block);
674 :
- 675 2217099 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP;
+ 675 2218229 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP;
676 : }
677 :
678 : /**
@@ -755,12 +755,12 @@
693 : *
694 : * Note that EMPTY / DELETED return 0.
695 : */
- 696 14591493 : static inline int block_has_file(const struct snapraid_block* block)
+ 696 14589756 : static inline int block_has_file(const struct snapraid_block* block)
697 : {
- 698 14591493 : unsigned state = block_state_get(block);
+ 698 14589756 : unsigned state = block_state_get(block);
699 :
- 700 14591444 : return state == BLOCK_STATE_BLK
- 701 14591444 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
+ 700 14590663 : return state == BLOCK_STATE_BLK
+ 701 14590663 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
702 : }
703 :
704 : /**
@@ -768,12 +768,12 @@
706 : *
707 : * Note that EMPTY / BLK return 0.
708 : */
- 709 12320585 : static inline int block_has_invalid_parity(const struct snapraid_block* block)
+ 709 12320925 : static inline int block_has_invalid_parity(const struct snapraid_block* block)
710 : {
- 711 12320585 : unsigned state = block_state_get(block);
+ 711 12320925 : unsigned state = block_state_get(block);
712 :
- 713 12320585 : return state == BLOCK_STATE_DELETED
- 714 12320585 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
+ 713 12320925 : return state == BLOCK_STATE_DELETED
+ 714 12320925 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP;
715 : }
716 :
717 : /**
@@ -781,27 +781,27 @@
719 : *
720 : * Note that anything different than BLK return 0.
721 : */
- 722 220962 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block)
+ 722 220963 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block)
723 : {
- 724 220962 : unsigned state = block_state_get(block);
+ 724 220963 : unsigned state = block_state_get(block);
725 :
- 726 220962 : return state == BLOCK_STATE_BLK;
+ 726 220963 : return state == BLOCK_STATE_BLK;
727 : }
728 :
- 729 34089332 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask)
+ 729 34102051 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask)
730 : {
- 731 34089332 : return (file->flag & mask) == mask;
+ 731 34102051 : return (file->flag & mask) == mask;
732 : }
733 :
- 734 5295048 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask)
+ 734 5303183 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask)
735 : {
- 736 5295048 : file->flag |= mask;
- 737 5295048 : }
+ 736 5303183 : file->flag |= mask;
+ 737 5303183 : }
738 :
- 739 11286 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask)
+ 739 18420 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask)
740 : {
- 741 11286 : file->flag &= ~mask;
- 742 11286 : }
+ 741 18420 : file->flag &= ~mask;
+ 742 18420 : }
743 :
744 : /**
745 : * Allocate a file.
@@ -833,11 +833,11 @@
771 : *
772 : * Note that the block size if a runtime value.
773 : */
- 774 54351316 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos)
+ 774 54351162 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos)
775 : {
- 776 54351316 : unsigned char* ptr = (unsigned char*)file->blockvec;
+ 776 54351162 : unsigned char* ptr = (unsigned char*)file->blockvec;
777 :
- 778 54351316 : return (struct snapraid_block*)(ptr + pos * block_sizeof());
+ 778 54351162 : return (struct snapraid_block*)(ptr + pos * block_sizeof());
779 : }
780 :
781 : /**
@@ -879,9 +879,9 @@
817 : /**
818 : * Compute the hash of a file inode.
819 : */
- 820 5042449 : static inline tommy_uint32_t file_inode_hash(uint64_t inode)
+ 820 5055357 : static inline tommy_uint32_t file_inode_hash(uint64_t inode)
821 : {
- 822 5042449 : return (tommy_uint32_t)tommy_inthash_u64(inode);
+ 822 5055357 : return (tommy_uint32_t)tommy_inthash_u64(inode);
823 : }
824 :
825 : /**
@@ -900,17 +900,17 @@
838 : /**
839 : * Compute the hash of a file path.
840 : */
- 841 3886182 : static inline tommy_uint32_t file_path_hash(const char* sub)
+ 841 3891897 : static inline tommy_uint32_t file_path_hash(const char* sub)
842 : {
- 843 3886182 : return tommy_hash_u32(0, sub, strlen(sub));
+ 843 3891897 : return tommy_hash_u32(0, sub, strlen(sub));
844 : }
845 :
846 : /**
847 : * Compute the hash of a file stamp.
848 : */
- 849 6275421 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec)
+ 849 6275620 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec)
850 : {
- 851 6275421 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec)));
+ 851 6275620 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec)));
852 : }
853 :
854 : /**
@@ -933,9 +933,9 @@
871 : */
872 : int extent_file_compare(const void* void_a, const void* void_b);
873 :
- 874 209328 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask)
+ 874 209329 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask)
875 : {
- 876 209328 : return (slink->flag & mask) == mask;
+ 876 209329 : return (slink->flag & mask) == mask;
877 : }
878 :
879 39461 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask)
@@ -1088,19 +1088,19 @@
1026 : /**
1027 : * Get the file position from the parity position.
1028 : */
- 1029 11723835 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
+ 1029 11722518 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos)
1030 : {
1031 : struct snapraid_file* ret;
1032 :
- 1033 11723835 : ret = fs_par2file_find(disk, parity_pos, file_pos);
- 1034 11724079 : if (ret == 0) {
+ 1033 11722518 : ret = fs_par2file_find(disk, parity_pos, file_pos);
+ 1034 11724212 : if (ret == 0) {
1035 : /* LCOV_EXCL_START */
1036 : log_fatal("Internal inconsistency when deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name);
1037 : os_abort();
1038 : /* LCOV_EXCL_STOP */
1039 : }
1040 :
- 1041 11724079 : return ret;
+ 1041 11724212 : return ret;
1042 : }
1043 :
1044 : /**
@@ -1112,19 +1112,19 @@
1050 : /**
1051 : * Get the parity position from the file position.
1052 : */
- 1053 4755492 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
+ 1053 4755524 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
1054 : {
1055 : block_off_t ret;
1056 :
- 1057 4755492 : ret = fs_file2par_find(disk, file, file_pos);
- 1058 4755492 : if (ret == POS_NULL) {
+ 1057 4755524 : ret = fs_file2par_find(disk, file, file_pos);
+ 1058 4755524 : if (ret == POS_NULL) {
1059 : /* LCOV_EXCL_START */
1060 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
1061 : os_abort();
1062 : /* LCOV_EXCL_STOP */
1063 : }
1064 :
- 1065 4755492 : return ret;
+ 1065 4755524 : return ret;
1066 : }
1067 :
1068 : /**
@@ -1172,18 +1172,18 @@
1110 : /**
1111 : * Make an info.
1112 : */
- 1113 194583 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced)
+ 1113 194621 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced)
1114 : {
1115 : /* clear the lowest bits as reserved for other information */
- 1116 194583 : snapraid_info info = last_access & ~INFO_MASK;
+ 1116 194621 : snapraid_info info = last_access & ~INFO_MASK;
1117 :
- 1118 194583 : if (error != 0)
- 1119 5278 : info |= 0x1;
- 1120 194583 : if (rehash != 0)
+ 1118 194621 : if (error != 0)
+ 1119 5330 : info |= 0x1;
+ 1120 194621 : if (rehash != 0)
1121 14426 : info |= 0x2;
- 1122 194583 : if (justsynced != 0)
- 1123 143045 : info |= 0x4;
- 1124 194583 : return info;
+ 1122 194621 : if (justsynced != 0)
+ 1123 143140 : info |= 0x4;
+ 1124 194621 : return info;
1125 : }
1126 :
1127 : /**
@@ -1191,36 +1191,36 @@
1129 : * This is the last time when the block was know to be correct.
1130 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub.
1131 : */
- 1132 883203 : static inline time_t info_get_time(snapraid_info info)
+ 1132 883145 : static inline time_t info_get_time(snapraid_info info)
1133 : {
- 1134 883203 : return info & ~INFO_MASK;
+ 1134 883145 : return info & ~INFO_MASK;
1135 : }
1136 :
1137 : /**
1138 : * Extract the error information.
1139 : * Report if the block address had some problem.
1140 : */
- 1141 352076 : static inline int info_get_bad(snapraid_info info)
+ 1141 352062 : static inline int info_get_bad(snapraid_info info)
1142 : {
- 1143 352076 : return (info & 0x1) != 0;
+ 1143 352062 : return (info & 0x1) != 0;
1144 : }
1145 :
1146 : /**
1147 : * Extract the rehash information.
1148 : * Report if the block address is using the old hash and needs to be rehashed.
1149 : */
- 1150 2046851 : static inline int info_get_rehash(snapraid_info info)
+ 1150 2046849 : static inline int info_get_rehash(snapraid_info info)
1151 : {
- 1152 2046851 : return (info & 0x2) != 0;
+ 1152 2046849 : return (info & 0x2) != 0;
1153 : }
1154 :
1155 : /**
1156 : * Extract the scrubbed information.
1157 : * Report if the block address was never scrubbed.
1158 : */
- 1159 68634 : static inline int info_get_justsynced(snapraid_info info)
+ 1159 68576 : static inline int info_get_justsynced(snapraid_info info)
1160 : {
- 1161 68634 : return (info & 0x4) != 0;
+ 1161 68576 : return (info & 0x4) != 0;
1162 : }
1163 :
1164 : /**
@@ -1243,27 +1243,27 @@
1181 : * Set the info at the specified position.
1182 : * The position is allocated if not yet done.
1183 : */
- 1184 1698121 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info)
+ 1184 1698196 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info)
1185 : {
- 1186 1698121 : tommy_arrayblkof_grow(array, pos + 1);
+ 1186 1698196 : tommy_arrayblkof_grow(array, pos + 1);
1187 :
- 1188 1698121 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info));
- 1189 1698121 : }
+ 1188 1698196 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info));
+ 1189 1698196 : }
1190 :
1191 : /**
1192 : * Get the info at the specified position.
1193 : * For not allocated position, 0 is returned.
1194 : */
- 1195 5098669 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos)
+ 1195 5098731 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos)
1196 : {
1197 : snapraid_info info;
1198 :
- 1199 5098669 : if (pos >= tommy_arrayblkof_size(array))
+ 1199 5098731 : if (pos >= tommy_arrayblkof_size(array))
1200 262643 : return 0;
1201 :
- 1202 4836026 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info));
+ 1202 4836088 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info));
1203 :
- 1204 4836026 : return info;
+ 1204 4836088 : return info;
1205 : }
1206 :
1207 : /**
diff --git a/cov/cmdline/handle.c.func-sort-c.html b/cov/cmdline/handle.c.func-sort-c.html
index 3014505f..a0e7b803 100644
--- a/cov/cmdline/handle.c.func-sort-c.html
+++ b/cov/cmdline/handle.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,31 +61,31 @@
| handle_read |
- 5856126 |
+ 5854217 |
| handle_close |
- 4647204 |
+ 4646580 |
| handle_open |
- 2185997 |
+ 2184769 |
| handle_create |
- 771283 |
+ 771310 |
| handle_write |
- 288377 |
+ 288515 |
| handle_utime |
- 119405 |
+ 119462 |
| handle_truncate |
- 3254 |
+ 3189 |
| handle_mapping |
diff --git a/cov/cmdline/handle.c.func.html b/cov/cmdline/handle.c.func.html
index 75b05487..9cac3192 100644
--- a/cov/cmdline/handle.c.func.html
+++ b/cov/cmdline/handle.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| handle_close |
- 4647204 |
+ 4646580 |
| handle_create |
- 771283 |
+ 771310 |
| handle_mapping |
@@ -73,23 +73,23 @@
| handle_open |
- 2185997 |
+ 2184769 |
| handle_read |
- 5856126 |
+ 5854217 |
| handle_truncate |
- 3254 |
+ 3189 |
| handle_utime |
- 119405 |
+ 119462 |
| handle_write |
- 288377 |
+ 288515 |
diff --git a/cov/cmdline/handle.c.gcov.html b/cov/cmdline/handle.c.gcov.html
index 3d2ab90a..86c64076 100644
--- a/cov/cmdline/handle.c.gcov.html
+++ b/cov/cmdline/handle.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -86,64 +86,64 @@
24 : /****************************************************************************/
25 : /* handle */
26 :
- 27 771283 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode)
+ 27 771310 : 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 771283 : if (handle->file == file && handle->f != -1) {
+ 33 771310 : if (handle->file == file && handle->f != -1) {
34 0 : return 0;
35 : }
36 :
- 37 771283 : advise_init(&handle->advise, mode);
- 38 771283 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
+ 37 771310 : advise_init(&handle->advise, mode);
+ 38 771310 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
39 :
- 40 771283 : ret = mkancestor(handle->path);
- 41 771283 : if (ret != 0) {
+ 40 771310 : ret = mkancestor(handle->path);
+ 41 771310 : if (ret != 0) {
42 : /* LCOV_EXCL_START */
43 : return -1;
44 : /* LCOV_EXCL_STOP */
45 : }
46 :
47 : /* initial values, changed later if required */
- 48 771283 : handle->created = 0;
+ 48 771310 : handle->created = 0;
49 :
50 : /* flags for opening */
51 : /* O_BINARY: open as binary file (Windows only) */
52 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
- 53 771283 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise);
+ 53 771310 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise);
54 :
55 : /* open for read write */
- 56 771283 : handle->f = open(handle->path, flags | O_RDWR);
+ 56 771310 : handle->f = open(handle->path, flags | O_RDWR);
57 :
58 : /* if failed for missing write permission */
- 59 771283 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
+ 59 771310 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
60 : /* open for real-only */
61 0 : handle->f = open(handle->path, flags | O_RDONLY);
62 : }
63 :
64 : /* if failed for missing file */
- 65 771283 : if (handle->f == -1 && errno == ENOENT) {
+ 65 771310 : if (handle->f == -1 && errno == ENOENT) {
66 : char path_from[PATH_MAX];
67 :
68 : /* check if exists a .unrecoverable copy, and rename to the real one */
- 69 176318 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path);
+ 69 176441 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path);
70 :
- 71 176318 : if (rename(path_from, handle->path) == 0) {
+ 71 176441 : if (rename(path_from, handle->path) == 0) {
72 : /* open for read write */
- 73 63274 : handle->f = open(handle->path, flags | O_RDWR);
+ 73 63323 : handle->f = open(handle->path, flags | O_RDWR);
74 : } else {
75 : /* create it */
- 76 113044 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600);
- 77 113044 : if (handle->f != -1) {
+ 76 113118 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600);
+ 77 113118 : if (handle->f != -1) {
78 : /* mark it as created if really done */
- 79 113044 : handle->created = 1;
+ 79 113118 : handle->created = 1;
80 : }
81 : }
82 : }
83 :
- 84 771283 : if (handle->f == -1) {
+ 84 771310 : if (handle->f == -1) {
85 : /* LCOV_EXCL_START */
86 : /* invalidate for error */
87 : handle->file = 0;
@@ -156,11 +156,11 @@
94 : }
95 :
96 : /* just opened */
- 97 771283 : handle->file = file;
+ 97 771310 : handle->file = file;
98 :
99 : /* get the stat info */
- 100 771283 : ret = fstat(handle->f, &handle->st);
- 101 771283 : if (ret != 0) {
+ 100 771310 : ret = fstat(handle->f, &handle->st);
+ 101 771310 : if (ret != 0) {
102 : /* LCOV_EXCL_START */
103 : log_fatal("Error accessing file '%s'. %s.\n", handle->path, strerror(errno));
104 : return -1;
@@ -168,25 +168,25 @@
106 : }
107 :
108 : /* get the size of the existing data */
- 109 771283 : handle->valid_size = handle->st.st_size;
+ 109 771310 : handle->valid_size = handle->st.st_size;
110 :
- 111 771283 : ret = advise_open(&handle->advise, handle->f);
- 112 771283 : if (ret != 0) {
+ 111 771310 : ret = advise_open(&handle->advise, handle->f);
+ 112 771310 : if (ret != 0) {
113 : /* LCOV_EXCL_START */
114 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno));
115 : return -1;
116 : /* LCOV_EXCL_STOP */
117 : }
118 :
- 119 771283 : return 0;
+ 119 771310 : return 0;
120 : }
121 :
- 122 3254 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
+ 122 3189 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
123 : {
124 : int ret;
125 :
- 126 3254 : ret = ftruncate(handle->f, file->size);
- 127 3254 : if (ret != 0) {
+ 126 3189 : ret = ftruncate(handle->f, file->size);
+ 127 3189 : if (ret != 0) {
128 : /* LCOV_EXCL_START */
129 : if (errno == EACCES) {
130 : log_fatal("Failed to truncate file '%s' for missing write permission.\n", handle->path);
@@ -198,56 +198,56 @@
136 : }
137 :
138 : /* adjust the size to the truncated size */
- 139 3254 : handle->valid_size = file->size;
+ 139 3189 : handle->valid_size = file->size;
140 :
- 141 3254 : return 0;
+ 141 3189 : return 0;
142 : }
143 :
- 144 2185997 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing)
+ 144 2184769 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing)
145 : {
146 : int ret;
147 : int flags;
148 :
- 149 2185997 : if (!out_missing)
- 150 2185561 : out_missing = out;
+ 149 2184769 : if (!out_missing)
+ 150 2184975 : out_missing = out;
151 :
152 : /* if already opened, nothing to do */
- 153 2185997 : if (handle->file == file && handle->file != 0 && handle->f != -1) {
- 154 468413 : return 0;
+ 153 2184769 : if (handle->file == file && handle->file != 0 && handle->f != -1) {
+ 154 468469 : return 0;
155 : }
156 :
- 157 1717584 : advise_init(&handle->advise, mode);
- 158 1717759 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
+ 157 1716300 : advise_init(&handle->advise, mode);
+ 158 1717209 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
159 :
160 : /* for sure not created */
- 161 1717867 : handle->created = 0;
+ 161 1717080 : handle->created = 0;
162 :
163 : /* flags for opening */
164 : /* O_BINARY: open as binary file (Windows only) */
165 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */
- 166 1717867 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise);
+ 166 1717080 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise);
167 :
168 : /* open for read */
- 169 1717825 : handle->f = open_noatime(handle->path, flags | O_RDONLY);
- 170 1717829 : if (handle->f == -1) {
+ 169 1717490 : handle->f = open_noatime(handle->path, flags | O_RDONLY);
+ 170 1715996 : if (handle->f == -1) {
171 : /* invalidate for error */
- 172 78600 : handle->file = 0;
- 173 78600 : handle->f = -1;
- 174 78600 : handle->valid_size = 0;
+ 172 78793 : handle->file = 0;
+ 173 78793 : handle->f = -1;
+ 174 78793 : handle->valid_size = 0;
175 :
- 176 78600 : if (errno == ENOENT)
- 177 78588 : out_missing("Missing file '%s'.\n", handle->path);
+ 176 78793 : if (errno == ENOENT)
+ 177 78781 : out_missing("Missing file '%s'.\n", handle->path);
178 : else
179 12 : out("Error opening file '%s'. %s.\n", handle->path, strerror(errno));
- 180 78600 : return -1;
+ 180 78793 : return -1;
181 : }
182 :
183 : /* just opened */
- 184 1639229 : handle->file = file;
+ 184 1637203 : handle->file = file;
185 :
186 : /* get the stat info */
- 187 1639229 : ret = fstat(handle->f, &handle->st);
- 188 1639236 : if (ret != 0) {
+ 187 1637203 : ret = fstat(handle->f, &handle->st);
+ 188 1636791 : if (ret != 0) {
189 : /* LCOV_EXCL_START */
190 : out("Error accessing file '%s'. %s.\n", handle->path, strerror(errno));
191 : return -1;
@@ -255,27 +255,27 @@
193 : }
194 :
195 : /* get the size of the existing data */
- 196 1639236 : handle->valid_size = handle->st.st_size;
+ 196 1636791 : handle->valid_size = handle->st.st_size;
197 :
- 198 1639236 : ret = advise_open(&handle->advise, handle->f);
- 199 1639253 : if (ret != 0) {
+ 198 1636791 : ret = advise_open(&handle->advise, handle->f);
+ 199 1634580 : if (ret != 0) {
200 : /* LCOV_EXCL_START */
201 : out("Error advising file '%s'. %s.\n", handle->path, strerror(errno));
202 : return -1;
203 : /* LCOV_EXCL_STOP */
204 : }
205 :
- 206 1639253 : return 0;
+ 206 1634580 : return 0;
207 : }
208 :
- 209 4647204 : int handle_close(struct snapraid_handle* handle)
+ 209 4646580 : int handle_close(struct snapraid_handle* handle)
210 : {
211 : int ret;
212 :
213 : /* close if open */
- 214 4647204 : if (handle->f != -1) {
- 215 2410548 : ret = close(handle->f);
- 216 2410577 : if (ret != 0) {
+ 214 4646580 : if (handle->f != -1) {
+ 215 2410222 : ret = close(handle->f);
+ 216 2410480 : if (ret != 0) {
217 : /* LCOV_EXCL_START */
218 : log_fatal("Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno));
219 :
@@ -289,14 +289,14 @@
227 : }
228 :
229 : /* reset the descriptor */
- 230 4647233 : handle->file = 0;
- 231 4647233 : handle->f = -1;
- 232 4647233 : handle->valid_size = 0;
+ 230 4646838 : handle->file = 0;
+ 231 4646838 : handle->f = -1;
+ 232 4646838 : handle->valid_size = 0;
233 :
- 234 4647233 : return 0;
+ 234 4646838 : return 0;
235 : }
236 :
- 237 5856126 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing)
+ 237 5854217 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing)
238 : {
239 : ssize_t read_ret;
240 : data_off_t offset;
@@ -304,70 +304,70 @@
242 : unsigned count;
243 : int ret;
244 :
- 245 5856126 : offset = file_pos * (data_off_t)block_size;
+ 245 5854217 : offset = file_pos * (data_off_t)block_size;
246 :
- 247 5856126 : if (!out_missing)
- 248 5843207 : out_missing = out;
+ 247 5854217 : if (!out_missing)
+ 248 5837298 : out_missing = out;
249 :
250 : /* check if we are going to read only not initialized data */
- 251 5856126 : if (offset >= handle->valid_size) {
+ 251 5854217 : if (offset >= handle->valid_size) {
252 : /* if the file is missing, it's at 0 size, or it's rebuilt while reading */
- 253 433247 : if (offset == handle->valid_size || handle->valid_size == 0)
- 254 431947 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
+ 253 433443 : if (offset == handle->valid_size || handle->valid_size == 0)
+ 254 432152 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
255 : else
- 256 1300 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
- 257 433247 : return -1;
+ 256 1291 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
+ 257 433443 : return -1;
258 : }
259 :
- 260 5422879 : read_size = file_block_size(handle->file, file_pos, block_size);
+ 260 5420774 : read_size = file_block_size(handle->file, file_pos, block_size);
261 :
- 262 5422871 : count = 0;
+ 262 5418955 : count = 0;
263 : do {
264 : /* read the full block to support O_DIRECT */
- 265 5431700 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count);
- 266 5431360 : if (read_ret < 0) {
+ 265 5429094 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count);
+ 266 5428298 : if (read_ret < 0) {
267 : /* LCOV_EXCL_START */
268 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, block_size - count, strerror(errno));
269 : return -1;
270 : /* LCOV_EXCL_STOP */
271 : }
- 272 5431360 : if (read_ret == 0) {
- 273 8879 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
- 274 8879 : return -1;
+ 272 5428298 : if (read_ret == 0) {
+ 273 8747 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
+ 274 8747 : return -1;
275 : }
276 :
- 277 5422481 : count += read_ret;
- 278 5422481 : } while (count < read_size);
+ 277 5419551 : count += read_ret;
+ 278 5419551 : } while (count < read_size);
279 :
280 : /* pad with 0 */
- 281 5413652 : if (read_size < block_size) {
- 282 2188671 : memset(block_buffer + read_size, 0, block_size - read_size);
+ 281 5409412 : if (read_size < block_size) {
+ 282 2188268 : memset(block_buffer + read_size, 0, block_size - read_size);
283 : }
284 :
- 285 5413652 : ret = advise_read(&handle->advise, handle->f, offset, block_size);
- 286 5413607 : if (ret != 0) {
+ 285 5409412 : ret = advise_read(&handle->advise, handle->f, offset, block_size);
+ 286 5410633 : if (ret != 0) {
287 : /* LCOV_EXCL_START */
288 : out("Error advising file '%s'. %s.\n", handle->path, strerror(errno));
289 : return -1;
290 : /* LCOV_EXCL_STOP */
291 : }
292 :
- 293 5413607 : return read_size;
+ 293 5410633 : return read_size;
294 : }
295 :
- 296 288377 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size)
+ 296 288515 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size)
297 : {
298 : ssize_t write_ret;
299 : data_off_t offset;
300 : unsigned write_size;
301 : int ret;
302 :
- 303 288377 : offset = file_pos * (data_off_t)block_size;
+ 303 288515 : offset = file_pos * (data_off_t)block_size;
304 :
- 305 288377 : write_size = file_block_size(handle->file, file_pos, block_size);
+ 305 288515 : write_size = file_block_size(handle->file, file_pos, block_size);
306 :
- 307 288377 : write_ret = pwrite(handle->f, block_buffer, write_size, offset);
- 308 288377 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */
+ 307 288515 : write_ret = pwrite(handle->f, block_buffer, write_size, offset);
+ 308 288515 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */
309 : /* LCOV_EXCL_START */
310 : log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno));
311 : return -1;
@@ -375,39 +375,39 @@
313 : }
314 :
315 : /* adjust the size of the valid data */
- 316 288377 : if (handle->valid_size < offset + write_size) {
- 317 282355 : handle->valid_size = offset + write_size;
+ 316 288515 : if (handle->valid_size < offset + write_size) {
+ 317 282439 : handle->valid_size = offset + write_size;
318 : }
319 :
- 320 288377 : ret = advise_write(&handle->advise, handle->f, offset, block_size);
- 321 288377 : if (ret != 0) {
+ 320 288515 : ret = advise_write(&handle->advise, handle->f, offset, block_size);
+ 321 288515 : if (ret != 0) {
322 : /* LCOV_EXCL_START */
323 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno));
324 : return -1;
325 : /* LCOV_EXCL_STOP */
326 : }
327 :
- 328 288377 : return 0;
+ 328 288515 : return 0;
329 : }
330 :
- 331 119405 : int handle_utime(struct snapraid_handle* handle)
+ 331 119462 : int handle_utime(struct snapraid_handle* handle)
332 : {
333 : int ret;
334 :
335 : /* do nothing if not opened */
- 336 119405 : if (handle->f == -1)
+ 336 119462 : if (handle->f == -1)
337 0 : return 0;
338 :
- 339 119405 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec);
+ 339 119462 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec);
340 :
- 341 119405 : if (ret != 0) {
+ 341 119462 : if (ret != 0) {
342 : /* LCOV_EXCL_START */
343 : log_fatal("Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno));
344 : return -1;
345 : /* LCOV_EXCL_STOP */
346 : }
347 :
- 348 119405 : return 0;
+ 348 119462 : return 0;
349 : }
350 :
351 221 : struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* handlemax)
diff --git a/cov/cmdline/import.c.func-sort-c.html b/cov/cmdline/import.c.func-sort-c.html
index 458a15a3..099061f5 100644
--- a/cov/cmdline/import.c.func-sort-c.html
+++ b/cov/cmdline/import.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| import_block_hash |
- 656604 |
+ 657048 |
| state_import_fetch |
- 652132 |
+ 652576 |
| import_block_hash_compare |
diff --git a/cov/cmdline/import.c.func.html b/cov/cmdline/import.c.func.html
index 384ffe57..20e9ef26 100644
--- a/cov/cmdline/import.c.func.html
+++ b/cov/cmdline/import.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| import_block_hash |
- 656604 |
+ 657048 |
| import_block_hash_compare |
@@ -89,7 +89,7 @@
| state_import_fetch |
- 652132 |
+ 652576 |
diff --git a/cov/cmdline/import.c.gcov.html b/cov/cmdline/import.c.gcov.html
index 307cb412..e1673ac2 100644
--- a/cov/cmdline/import.c.gcov.html
+++ b/cov/cmdline/import.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -108,10 +108,10 @@
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 656604 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash)
+ 49 657048 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash)
50 : {
51 : /* the hash data is not aligned, and we cannot access it with a direct cast */
- 52 656604 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24);
+ 52 657048 : 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)
@@ -207,24 +207,24 @@
145 1750 : free(file);
146 1750 : }
147 :
- 148 652132 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer)
+ 148 652576 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer)
149 : {
150 : struct snapraid_import_block* block;
151 : int ret;
152 : int f;
- 153 652132 : const unsigned char* hash = missing_block->hash;
- 154 652132 : unsigned block_size = state->block_size;
+ 153 652576 : const unsigned char* hash = missing_block->hash;
+ 154 652576 : unsigned block_size = state->block_size;
155 : unsigned read_size;
156 : unsigned char buffer_hash[HASH_MAX];
157 : const char* path;
158 :
- 159 652132 : if (rehash) {
+ 159 652576 : if (rehash) {
160 0 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash));
161 : } else {
- 162 652132 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash));
+ 162 652576 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash));
163 : }
- 164 652132 : if (!block)
- 165 647660 : return -1;
+ 164 652576 : if (!block)
+ 165 648104 : return -1;
166 :
167 4472 : path = block->file->path;
168 4472 : read_size = block->size;
diff --git a/cov/cmdline/index-sort-f.html b/cov/cmdline/index-sort-f.html
index 90111741..036a3312 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  |
+
+ | unix.c |
+
+
+ |
+ 70.2 % |
+ 314 / 447 |
+ 87.1 % |
+ 27 / 31 |
+
| import.c |
@@ -80,12 +90,12 @@
| 7 / 8 |
- | unix.c |
+ io.c |
-
+
|
- 72.4 % |
- 320 / 442 |
+ 92.6 % |
+ 386 / 417 |
90.3 % |
28 / 31 |
@@ -99,16 +109,6 @@
90.9 % |
10 / 11 |
-
- | io.c |
-
-
- |
- 97.6 % |
- 407 / 417 |
- 93.5 % |
- 29 / 31 |
-
| parity.c |
@@ -142,30 +142,30 @@
|
| support.c |
-
+
|
- 80.2 % |
- 441 / 550 |
+ 80.3 % |
+ 449 / 559 |
96.8 % |
- 60 / 62 |
+ 61 / 63 |
| elem.c |
-
+
|
- 94.5 % |
- 597 / 632 |
+ 94.6 % |
+ 598 / 632 |
97.1 % |
67 / 69 |
| state.c |
-
+
|
- 91.7 % |
- 1478 / 1612 |
+ 89.8 % |
+ 1450 / 1615 |
97.8 % |
45 / 46 |
@@ -262,10 +262,10 @@
| pool.c |
-
+
|
- 94.1 % |
- 64 / 68 |
+ 94.4 % |
+ 67 / 71 |
100.0 % |
3 / 3 |
@@ -332,10 +332,10 @@
| sync.c |
-
+
|
- 91.8 % |
- 501 / 546 |
+ 91.4 % |
+ 499 / 546 |
100.0 % |
7 / 7 |
@@ -372,10 +372,10 @@
| check.c |
-
+
|
91.5 % |
- 709 / 775 |
+ 711 / 777 |
100.0 % |
9 / 9 |
diff --git a/cov/cmdline/index-sort-l.html b/cov/cmdline/index-sort-l.html
index 7f0baa1d..c484c863 100644
--- a/cov/cmdline/index-sort-l.html
+++ b/cov/cmdline/index-sort-l.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| unix.c |
-
+
|
- 72.4 % |
- 320 / 442 |
- 90.3 % |
- 28 / 31 |
+ 70.2 % |
+ 314 / 447 |
+ 87.1 % |
+ 27 / 31 |
| dry.c |
@@ -92,12 +92,12 @@
| support.c |
-
+
|
- 80.2 % |
- 441 / 550 |
+ 80.3 % |
+ 449 / 559 |
96.8 % |
- 60 / 62 |
+ 61 / 63 |
| scrub.c |
@@ -119,6 +119,16 @@
100.0 % |
23 / 23 |
+
+ | state.c |
+
+
+ |
+ 89.8 % |
+ 1450 / 1615 |
+ 97.8 % |
+ 45 / 46 |
+
| stream.h |
@@ -169,36 +179,26 @@
| 100.0 % |
9 / 9 |
-
- | check.c |
-
-
- |
- 91.5 % |
- 709 / 775 |
- 100.0 % |
- 9 / 9 |
-
-
- | state.c |
-
-
- |
- 91.7 % |
- 1478 / 1612 |
- 97.8 % |
- 45 / 46 |
-
| sync.c |
-
+
|
- 91.8 % |
- 501 / 546 |
+ 91.4 % |
+ 499 / 546 |
100.0 % |
7 / 7 |
+
+ | check.c |
+
+
+ |
+ 91.5 % |
+ 711 / 777 |
+ 100.0 % |
+ 9 / 9 |
+
| parity.c |
@@ -209,6 +209,16 @@
| 94.7 % |
18 / 19 |
+
+ | io.c |
+
+
+ |
+ 92.6 % |
+ 386 / 417 |
+ 90.3 % |
+ 28 / 31 |
+
| mktest.c |
@@ -252,20 +262,20 @@
|
| pool.c |
-
+
|
- 94.1 % |
- 64 / 68 |
+ 94.4 % |
+ 67 / 71 |
100.0 % |
3 / 3 |
| elem.c |
-
+
|
- 94.5 % |
- 597 / 632 |
+ 94.6 % |
+ 598 / 632 |
97.1 % |
67 / 69 |
@@ -329,16 +339,6 @@
100.0 % |
8 / 8 |
-
- | io.c |
-
-
- |
- 97.6 % |
- 407 / 417 |
- 93.5 % |
- 29 / 31 |
-
| speed.c |
diff --git a/cov/cmdline/index.html b/cov/cmdline/index.html
index 4531671e..054a9a21 100644
--- a/cov/cmdline/index.html
+++ b/cov/cmdline/index.html
@@ -31,18 +31,18 @@
|
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,10 +72,10 @@
| check.c |
-
+
|
91.5 % |
- 709 / 775 |
+ 711 / 777 |
100.0 % |
9 / 9 |
@@ -112,10 +112,10 @@
| elem.c |
-
+
|
- 94.5 % |
- 597 / 632 |
+ 94.6 % |
+ 598 / 632 |
97.1 % |
67 / 69 |
@@ -152,12 +152,12 @@
| io.c |
-
+
|
- 97.6 % |
- 407 / 417 |
- 93.5 % |
- 29 / 31 |
+ 92.6 % |
+ 386 / 417 |
+ 90.3 % |
+ 28 / 31 |
| list.c |
@@ -212,10 +212,10 @@
| pool.c |
-
+
|
- 94.1 % |
- 64 / 68 |
+ 94.4 % |
+ 67 / 71 |
100.0 % |
3 / 3 |
@@ -312,10 +312,10 @@
| state.c |
-
+
|
- 91.7 % |
- 1478 / 1612 |
+ 89.8 % |
+ 1450 / 1615 |
97.8 % |
45 / 46 |
@@ -352,12 +352,12 @@
| support.c |
-
+
|
- 80.2 % |
- 441 / 550 |
+ 80.3 % |
+ 449 / 559 |
96.8 % |
- 60 / 62 |
+ 61 / 63 |
| support.h |
@@ -372,10 +372,10 @@
| sync.c |
-
+
|
- 91.8 % |
- 501 / 546 |
+ 91.4 % |
+ 499 / 546 |
100.0 % |
7 / 7 |
@@ -392,12 +392,12 @@
| unix.c |
-
+
|
- 72.4 % |
- 320 / 442 |
- 90.3 % |
- 28 / 31 |
+ 70.2 % |
+ 314 / 447 |
+ 87.1 % |
+ 27 / 31 |
| util.c |
diff --git a/cov/cmdline/io.c.func-sort-c.html b/cov/cmdline/io.c.func-sort-c.html
index c7526147..63937ef6 100644
--- a/cov/cmdline/io.c.func-sort-c.html
+++ b/cov/cmdline/io.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
-
+
-
+
 |
@@ -61,27 +61,27 @@
| io_reader_step |
- 1162708 |
+ 1156990 |
| io_task_read_thread |
- 1081860 |
+ 1082196 |
| io_reader_worker |
- 1081809 |
+ 1081760 |
| io_data_read_thread |
- 871056 |
+ 871392 |
| io_writer_step |
- 554042 |
+ 554063 |
| io_parity_write_thread |
- 553582 |
+ 553918 |
| io_parity_read_thread |
@@ -89,27 +89,27 @@
| io_position_next |
- 162024 |
+ 162080 |
| io_reader_sched |
- 162024 |
+ 162080 |
| io_read_next_thread |
- 145271 |
+ 145327 |
| io_writer_sched |
- 112438 |
+ 112510 |
| io_write_preset_thread |
- 110042 |
+ 110098 |
| io_write_next_thread |
- 110042 |
+ 110098 |
| io_task_read_mono |
@@ -137,15 +137,15 @@
| io_writer_sched_empty |
- 2291 |
+ 2275 |
| io_reader_thread |
- 648 |
+ 615 |
| io_writer_thread |
- 462 |
+ 461 |
| io_init |
@@ -163,10 +163,6 @@
io_stop_thread |
95 |
-
- | io_refresh_thread |
- 1 |
-
| io_start_mono |
1 |
@@ -179,6 +175,10 @@
io_refresh_mono |
0 |
+
+ | io_refresh_thread |
+ 0 |
+
| io_parity_read_mono |
0 |
diff --git a/cov/cmdline/io.c.func.html b/cov/cmdline/io.c.func.html
index 87d56824..3741101d 100644
--- a/cov/cmdline/io.c.func.html
+++ b/cov/cmdline/io.c.func.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
-
+
-
+
 |
@@ -65,7 +65,7 @@
| io_data_read_thread |
- 871056 |
+ 871392 |
| io_done |
@@ -89,11 +89,11 @@
| io_parity_write_thread |
- 553582 |
+ 553918 |
| io_position_next |
- 162024 |
+ 162080 |
| io_read_next_mono |
@@ -101,23 +101,23 @@
| io_read_next_thread |
- 145271 |
+ 145327 |
| io_reader_sched |
- 162024 |
+ 162080 |
| io_reader_step |
- 1162708 |
+ 1156990 |
| io_reader_thread |
- 648 |
+ 615 |
| io_reader_worker |
- 1081809 |
+ 1081760 |
| io_refresh_mono |
@@ -125,7 +125,7 @@
| io_refresh_thread |
- 1 |
+ 0 |
| io_start_mono |
@@ -149,7 +149,7 @@
| io_task_read_thread |
- 1081860 |
+ 1082196 |
| io_write_next_mono |
@@ -157,7 +157,7 @@
| io_write_next_thread |
- 110042 |
+ 110098 |
| io_write_preset_mono |
@@ -165,23 +165,23 @@
| io_write_preset_thread |
- 110042 |
+ 110098 |
| io_writer_sched |
- 112438 |
+ 112510 |
| io_writer_sched_empty |
- 2291 |
+ 2275 |
| io_writer_step |
- 554042 |
+ 554063 |
| io_writer_thread |
- 462 |
+ 461 |
diff --git a/cov/cmdline/io.c.gcov.html b/cov/cmdline/io.c.gcov.html
index c7a9d8f2..41143203 100644
--- a/cov/cmdline/io.c.gcov.html
+++ b/cov/cmdline/io.c.gcov.html
@@ -31,18 +31,18 @@
|
-
+
-
+
-
+
|
-
+
-
+
 |
@@ -84,103 +84,103 @@
22 : /**
23 : * Get the next block position to process.
24 : */
- 25 162024 : static block_off_t io_position_next(struct snapraid_io* io)
+ 25 162080 : static block_off_t io_position_next(struct snapraid_io* io)
26 : {
27 : block_off_t blockcur;
28 :
29 : /* get the next position */
- 30 647457 : while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next))
- 31 323409 : ++io->block_next;
+ 30 647513 : while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next))
+ 31 323353 : ++io->block_next;
32 :
- 33 162024 : blockcur = io->block_next;
+ 33 162080 : blockcur = io->block_next;
34 :
35 : /* next block for the next call */
- 36 162024 : ++io->block_next;
+ 36 162080 : ++io->block_next;
37 :
- 38 162024 : return blockcur;
+ 38 162080 : return blockcur;
39 : }
40 :
41 : /**
42 : * Setup the next pending task for all readers.
43 : */
- 44 162024 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur)
+ 44 162080 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur)
45 : {
46 : unsigned i;
47 :
- 48 1354956 : for (i = 0; i < io->reader_max; ++i) {
- 49 1192932 : struct snapraid_worker* worker = &io->reader_map[i];
- 50 1192932 : struct snapraid_task* task = &worker->task_map[task_index];
+ 48 1355348 : for (i = 0; i < io->reader_max; ++i) {
+ 49 1193268 : struct snapraid_worker* worker = &io->reader_map[i];
+ 50 1193268 : struct snapraid_task* task = &worker->task_map[task_index];
51 :
52 : /* setup the new pending task */
- 53 1192932 : if (blockcur < io->block_max)
- 54 1109982 : task->state = TASK_STATE_READY;
+ 53 1193268 : if (blockcur < io->block_max)
+ 54 1110318 : task->state = TASK_STATE_READY;
55 : else
56 82950 : task->state = TASK_STATE_EMPTY;
57 :
- 58 1192932 : task->path[0] = 0;
- 59 1192932 : if (worker->handle)
- 60 972144 : task->disk = worker->handle->disk;
+ 58 1193268 : task->path[0] = 0;
+ 59 1193268 : if (worker->handle)
+ 60 972480 : task->disk = worker->handle->disk;
61 : else
62 220788 : task->disk = 0;
- 63 1192932 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i];
- 64 1192932 : task->position = blockcur;
- 65 1192932 : task->block = 0;
- 66 1192932 : task->file = 0;
- 67 1192932 : task->file_pos = 0;
- 68 1192932 : task->read_size = 0;
- 69 1192932 : task->is_timestamp_different = 0;
+ 63 1193268 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i];
+ 64 1193268 : task->position = blockcur;
+ 65 1193268 : task->block = 0;
+ 66 1193268 : task->file = 0;
+ 67 1193268 : task->file_pos = 0;
+ 68 1193268 : task->read_size = 0;
+ 69 1193268 : task->is_timestamp_different = 0;
70 : }
- 71 162024 : }
+ 71 162080 : }
72 :
73 : /**
74 : * Setup the next pending task for all writers.
75 : */
- 76 112438 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur)
+ 76 112510 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur)
77 : {
78 : unsigned i;
79 :
- 80 656961 : for (i = 0; i < io->writer_max; ++i) {
- 81 544523 : struct snapraid_worker* worker = &io->writer_map[i];
- 82 544523 : struct snapraid_task* task = &worker->task_map[task_index];
+ 80 657465 : for (i = 0; i < io->writer_max; ++i) {
+ 81 544955 : struct snapraid_worker* worker = &io->writer_map[i];
+ 82 544955 : struct snapraid_task* task = &worker->task_map[task_index];
83 :
84 : /* setup the new pending task */
- 85 544523 : task->state = TASK_STATE_READY;
- 86 544523 : task->path[0] = 0;
- 87 544523 : task->disk = 0;
- 88 544523 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i];
- 89 544523 : task->position = blockcur;
- 90 544523 : task->block = 0;
- 91 544523 : task->file = 0;
- 92 544523 : task->file_pos = 0;
- 93 544523 : task->read_size = 0;
- 94 544523 : task->is_timestamp_different = 0;
+ 85 544955 : task->state = TASK_STATE_READY;
+ 86 544955 : task->path[0] = 0;
+ 87 544955 : task->disk = 0;
+ 88 544955 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i];
+ 89 544955 : task->position = blockcur;
+ 90 544955 : task->block = 0;
+ 91 544955 : task->file = 0;
+ 92 544955 : task->file_pos = 0;
+ 93 544955 : task->read_size = 0;
+ 94 544955 : task->is_timestamp_different = 0;
95 : }
- 96 112438 : }
+ 96 112510 : }
97 :
98 : /**
99 : * Setup an empty next pending task for all writers.
100 : */
- 101 2291 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur)
+ 101 2275 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur)
102 : {
103 : unsigned i;
104 :
- 105 16037 : for (i = 0; i < io->writer_max; ++i) {
- 106 13746 : struct snapraid_worker* worker = &io->writer_map[i];
- 107 13746 : struct snapraid_task* task = &worker->task_map[task_index];
+ 105 15925 : for (i = 0; i < io->writer_max; ++i) {
+ 106 13650 : struct snapraid_worker* worker = &io->writer_map[i];
+ 107 13650 : struct snapraid_task* task = &worker->task_map[task_index];
108 :
109 : /* setup the new pending task */
- 110 13746 : task->state = TASK_STATE_EMPTY;
- 111 13746 : task->path[0] = 0;
- 112 13746 : task->disk = 0;
- 113 13746 : task->buffer = 0;
- 114 13746 : task->position = blockcur;
- 115 13746 : task->block = 0;
- 116 13746 : task->file = 0;
- 117 13746 : task->file_pos = 0;
- 118 13746 : task->read_size = 0;
- 119 13746 : task->is_timestamp_different = 0;
+ 110 13650 : task->state = TASK_STATE_EMPTY;
+ 111 13650 : task->path[0] = 0;
+ 112 13650 : task->disk = 0;
+ 113 13650 : task->buffer = 0;
+ 114 13650 : task->position = blockcur;
+ 115 13650 : task->block = 0;
+ 116 13650 : task->file = 0;
+ 117 13650 : task->file_pos = 0;
+ 118 13650 : task->read_size = 0;
+ 119 13650 : task->is_timestamp_different = 0;
120 : }
- 121 2291 : }
+ 121 2275 : }
122 :
123 : /*****************************************************************************/
124 : /* mono thread */
@@ -331,55 +331,55 @@
269 : *
270 : * This is the synchronization point for workers with the io.
271 : */
- 272 1162708 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker)
+ 272 1156990 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker)
273 : {
- 274 1162708 : struct snapraid_io* io = worker->io;
+ 274 1156990 : struct snapraid_io* io = worker->io;
275 :
276 : /* the synchronization is protected by the io mutex */
- 277 1162708 : thread_mutex_lock(&io->io_mutex);
+ 277 1156990 : thread_mutex_lock(&io->io_mutex);
278 :
279 : while (1) {
280 : unsigned next_index;
281 :
282 : /* check if the worker has to exit */
283 : /* even if there is work to do */
- 284 2057573 : if (io->done) {
+ 284 2137549 : if (io->done) {
285 648 : thread_mutex_unlock(&io->io_mutex);
286 648 : return 0;
287 : }
288 :
289 : /* get the next pending task */
- 290 2056925 : next_index = (worker->index + 1) % io->io_max;
+ 290 2136901 : next_index = (worker->index + 1) % io->io_max;
291 :
292 : /* if the queue of pending tasks is not empty */
- 293 2056925 : if (next_index != io->reader_index) {
+ 293 2136901 : if (next_index != io->reader_index) {
294 : struct snapraid_task* task;
295 :
296 : /* the index that the IO may be waiting for */
- 297 1162618 : unsigned waiting_index = io->reader_index;
+ 297 1164456 : unsigned waiting_index = io->reader_index;
298 :
299 : /* the index that worker just completed */
- 300 1162618 : unsigned done_index = worker->index;
+ 300 1164456 : unsigned done_index = worker->index;
301 :
302 : /* get the new working task */
- 303 1162618 : worker->index = next_index;
- 304 1162618 : task = &worker->task_map[worker->index];
+ 303 1164456 : worker->index = next_index;
+ 304 1164456 : task = &worker->task_map[worker->index];
305 :
306 : /* if the just completed task is at this index */
- 307 1162618 : if (done_index == waiting_index) {
+ 307 1164456 : if (done_index == waiting_index) {
308 : /* notify the IO that a new read is complete */
- 309 2747 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex);
+ 309 1053 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex);
310 : } else {
- 311 1159871 : thread_mutex_unlock(&io->io_mutex);
+ 311 1163403 : thread_mutex_unlock(&io->io_mutex);
312 : }
313 :
314 : /* return the new task */
- 315 1162520 : return task;
+ 315 1163731 : return task;
316 : }
317 :
318 : /* otherwise wait for a read_sched event */
- 319 894307 : thread_cond_wait(&io->read_sched, &io->io_mutex);
- 320 894307 : }
+ 319 972445 : thread_cond_wait(&io->read_sched, &io->io_mutex);
+ 320 972445 : }
321 : }
322 :
323 : /**
@@ -387,61 +387,61 @@
325 : *
326 : * This is the synchronization point for workers with the io.
327 : */
- 328 554042 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state)
+ 328 554063 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state)
329 : {
- 330 554042 : struct snapraid_io* io = worker->io;
+ 330 554063 : struct snapraid_io* io = worker->io;
331 : int error_index;
332 :
333 : /* the synchronization is protected by the io mutex */
- 334 554042 : thread_mutex_lock(&io->io_mutex);
+ 334 554063 : thread_mutex_lock(&io->io_mutex);
335 :
336 : /* counts the number of errors in the global state */
- 337 554044 : error_index = state - IO_WRITER_ERROR_BASE;
- 338 554044 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX)
+ 337 554380 : error_index = state - IO_WRITER_ERROR_BASE;
+ 338 554380 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX)
339 0 : ++io->writer_error[error_index];
340 :
341 : while (1) {
342 : unsigned next_index;
343 :
344 : /* get the next pending task */
- 345 625754 : next_index = (worker->index + 1) % io->io_max;
+ 345 637383 : next_index = (worker->index + 1) % io->io_max;
346 :
347 : /* if the queue of pending tasks is not empty */
- 348 625754 : if (next_index != io->writer_index) {
+ 348 637383 : if (next_index != io->writer_index) {
349 : struct snapraid_task* task;
350 :
351 : /* the index that the IO may be waiting for */
- 352 553582 : unsigned waiting_index = (io->writer_index + 1) % io->io_max;
+ 352 553918 : unsigned waiting_index = (io->writer_index + 1) % io->io_max;
353 :
354 : /* the index that worker just completed */
- 355 553582 : unsigned done_index = worker->index;
+ 355 553918 : unsigned done_index = worker->index;
356 :
357 : /* get the new working task */
- 358 553582 : worker->index = next_index;
- 359 553582 : task = &worker->task_map[worker->index];
+ 358 553918 : worker->index = next_index;
+ 359 553918 : task = &worker->task_map[worker->index];
360 :
361 : /* if the just completed task is at this index */
- 362 553582 : if (done_index == waiting_index) {
+ 362 553918 : if (done_index == waiting_index) {
363 : /* notify the IO that a new write is complete */
- 364 83140 : thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex);
+ 364 86028 : thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex);
365 : } else {
- 366 470442 : thread_mutex_unlock(&io->io_mutex);
+ 366 467890 : thread_mutex_unlock(&io->io_mutex);
367 : }
368 :
369 : /* return the new task */
- 370 553581 : return task;
+ 370 553862 : return task;
371 : }
372 :
373 : /* check if the worker has to exit */
374 : /* but only if there is no work to do */
- 375 72172 : if (io->done) {
+ 375 83465 : if (io->done) {
376 462 : thread_mutex_unlock(&io->io_mutex);
- 377 462 : return 0;
+ 377 461 : return 0;
378 : }
379 :
380 : /* otherwise wait for a write_sched event */
- 381 71710 : thread_cond_wait(&io->write_sched, &io->io_mutex);
- 382 71710 : }
+ 381 83003 : thread_cond_wait(&io->write_sched, &io->io_mutex);
+ 382 83003 : }
383 : }
384 :
385 : /**
@@ -449,146 +449,146 @@
387 : *
388 : * This is the synchronization point for workers with the io.
389 : */
- 390 145271 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer)
+ 390 145327 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer)
391 : {
392 : block_off_t blockcur_schedule;
393 : block_off_t blockcur_caller;
394 : unsigned i;
395 :
396 : /* get the next parity position to process */
- 397 145271 : blockcur_schedule = io_position_next(io);
+ 397 145327 : blockcur_schedule = io_position_next(io);
398 :
399 : /* ensure that all data/parity was read */
- 400 145271 : assert(io->reader_list[0] == io->reader_max);
+ 400 145327 : assert(io->reader_list[0] == io->reader_max);
401 :
402 : /* setup the list of workers to process */
- 403 1373050 : for (i = 0; i <= io->reader_max; ++i)
- 404 1227779 : io->reader_list[i] = i;
+ 403 1373498 : for (i = 0; i <= io->reader_max; ++i)
+ 404 1228171 : io->reader_list[i] = i;
405 :
406 : /* the synchronization is protected by the io mutex */
- 407 145271 : thread_mutex_lock(&io->io_mutex);
+ 407 145327 : thread_mutex_lock(&io->io_mutex);
408 :
409 : /* schedule the next read */
- 410 145271 : io_reader_sched(io, io->reader_index, blockcur_schedule);
+ 410 145327 : io_reader_sched(io, io->reader_index, blockcur_schedule);
411 :
412 : /* set the index for the tasks to return to the caller */
- 413 145271 : io->reader_index = (io->reader_index + 1) % io->io_max;
+ 413 145327 : io->reader_index = (io->reader_index + 1) % io->io_max;
414 :
415 : /* get the position to operate at high level from one task */
- 416 145271 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position;
+ 416 145327 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position;
417 :
418 : /* set the buffer to use */
- 419 145271 : *buffer = io->buffer_map[io->reader_index];
+ 419 145327 : *buffer = io->buffer_map[io->reader_index];
420 :
421 : /* signal all the workers that there is a new pending task */
- 422 145271 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex);
+ 422 145327 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex);
423 :
- 424 145271 : return blockcur_caller;
+ 424 145327 : return blockcur_caller;
425 : }
426 :
- 427 110042 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip)
+ 427 110098 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip)
428 : {
429 : (void)io;
430 : (void)blockcur;
431 : (void)skip;
- 432 110042 : }
+ 432 110098 : }
433 :
- 434 110042 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error)
+ 434 110098 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error)
435 : {
436 : unsigned i;
437 :
438 : /* ensure that all parity was written */
- 439 110042 : assert(io->writer_list[0] == io->writer_max);
+ 439 110098 : assert(io->writer_list[0] == io->writer_max);
440 :
441 : /* setup the list of workers to process */
- 442 773666 : for (i = 0; i <= io->writer_max; ++i)
- 443 663624 : io->writer_list[i] = i;
+ 442 774114 : for (i = 0; i <= io->writer_max; ++i)
+ 443 664016 : io->writer_list[i] = i;
444 :
445 : /* the synchronization is protected by the io mutex */
- 446 110042 : thread_mutex_lock(&io->io_mutex);
+ 446 110098 : thread_mutex_lock(&io->io_mutex);
447 :
448 : /* report errors */
- 449 550210 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) {
- 450 440168 : writer_error[i] = io->writer_error[i];
- 451 440168 : io->writer_error[i] = 0;
+ 449 550490 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) {
+ 450 440392 : writer_error[i] = io->writer_error[i];
+ 451 440392 : io->writer_error[i] = 0;
452 : }
453 :
- 454 110042 : if (skip) {
+ 454 110098 : if (skip) {
455 : /* skip the next write */
- 456 2291 : io_writer_sched_empty(io, io->writer_index, blockcur);
+ 456 2275 : io_writer_sched_empty(io, io->writer_index, blockcur);
457 : } else {
458 : /* schedule the next write */
- 459 107751 : io_writer_sched(io, io->writer_index, blockcur);
+ 459 107823 : io_writer_sched(io, io->writer_index, blockcur);
460 : }
461 :
462 : /* at this point the writers must be in sync with the readers */
- 463 110042 : assert(io->writer_index == io->reader_index);
+ 463 110098 : assert(io->writer_index == io->reader_index);
464 :
465 : /* set the index to be used for the next write */
- 466 110042 : io->writer_index = (io->writer_index + 1) % io->io_max;
+ 466 110098 : io->writer_index = (io->writer_index + 1) % io->io_max;
467 :
468 : /* signal all the workers that there is a new pending task */
- 469 110042 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex);
- 470 110042 : }
+ 469 110098 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex);
+ 470 110098 : }
471 :
- 472 1 : static void io_refresh_thread(struct snapraid_io* io)
+ 472 0 : static void io_refresh_thread(struct snapraid_io* io)
473 : {
474 : unsigned i;
475 :
476 : /* the synchronization is protected by the io mutex */
- 477 1 : thread_mutex_lock(&io->io_mutex);
+ 477 0 : thread_mutex_lock(&io->io_mutex);
478 :
479 : /* for all readers, count the number of read blocks */
- 480 7 : for (i = 0; i < io->reader_max; ++i) {
+ 480 0 : for (i = 0; i < io->reader_max; ++i) {
481 : unsigned begin, end, cached;
- 482 6 : struct snapraid_worker* worker = &io->reader_map[i];
+ 482 0 : struct snapraid_worker* worker = &io->reader_map[i];
483 :
484 : /* the first block read */
- 485 6 : begin = io->reader_index + 1;
+ 485 0 : begin = io->reader_index + 1;
486 : /* the block in reading */
- 487 6 : end = worker->index;
- 488 6 : if (begin > end)
- 489 6 : end += io->io_max;
- 490 6 : cached = end - begin;
+ 487 0 : end = worker->index;
+ 488 0 : if (begin > end)
+ 489 0 : end += io->io_max;
+ 490 0 : cached = end - begin;
491 :
- 492 6 : if (worker->parity_handle)
+ 492 0 : if (worker->parity_handle)
493 0 : io->state->parity[worker->parity_handle->level].cached = cached;
494 : else
- 495 6 : worker->handle->disk->cached = cached;
+ 495 0 : worker->handle->disk->cached = cached;
496 : }
497 :
498 : /* for all writers, count the number of written blocks */
499 : /* note that this is a kind of "opposite" of cached blocks */
- 500 2 : for (i = 0; i < io->writer_max; ++i) {
+ 500 0 : for (i = 0; i < io->writer_max; ++i) {
501 : unsigned begin, end, cached;
- 502 1 : struct snapraid_worker* worker = &io->writer_map[i];
+ 502 0 : struct snapraid_worker* worker = &io->writer_map[i];
503 :
504 : /* the first block written */
- 505 1 : begin = io->writer_index + 1;
+ 505 0 : begin = io->writer_index + 1;
506 : /* the block in writing */
- 507 1 : end = worker->index;
- 508 1 : if (begin > end)
- 509 1 : end += io->io_max;
- 510 1 : cached = end - begin;
+ 507 0 : end = worker->index;
+ 508 0 : if (begin > end)
+ 509 0 : end += io->io_max;
+ 510 0 : cached = end - begin;
511 :
- 512 1 : io->state->parity[worker->parity_handle->level].cached = cached;
+ 512 0 : io->state->parity[worker->parity_handle->level].cached = cached;
513 : }
514 :
- 515 1 : thread_mutex_unlock(&io->io_mutex);
- 516 1 : }
+ 515 0 : thread_mutex_unlock(&io->io_mutex);
+ 516 0 : }
517 :
- 518 1081860 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
+ 518 1082196 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
519 : {
520 : unsigned waiting_cycle;
521 :
522 : /* count the waiting cycle */
- 523 1081860 : waiting_cycle = 0;
+ 523 1082196 : waiting_cycle = 0;
524 :
525 : /* clear the waiting indexes */
- 526 1081860 : *waiting_mac = 0;
+ 526 1082196 : *waiting_mac = 0;
527 :
528 : /* the synchronization is protected by the io mutex */
- 529 1081860 : thread_mutex_lock(&io->io_mutex);
+ 529 1082196 : thread_mutex_lock(&io->io_mutex);
530 :
531 : while (1) {
532 : unsigned char* let;
@@ -597,67 +597,67 @@
535 : /* get the index the IO is using */
536 : /* we must ensure that this index has not a read in progress */
537 : /* to avoid a concurrent access */
- 538 1084465 : busy_index = io->reader_index;
+ 538 1083198 : busy_index = io->reader_index;
539 :
540 : /* search for a worker that has already finished */
- 541 1084465 : let = &io->reader_list[0];
+ 541 1083198 : let = &io->reader_list[0];
542 : while (1) {
- 543 1097188 : unsigned i = *let;
+ 543 1087885 : unsigned i = *let;
544 :
545 : /* if we are at the end */
- 546 1097188 : if (i == io->reader_max)
- 547 2605 : break;
+ 546 1087885 : if (i == io->reader_max)
+ 547 1002 : break;
548 :
549 : /* if it's in range */
- 550 1094583 : if (base <= i && i < base + count) {
+ 550 1086883 : if (base <= i && i < base + count) {
551 : struct snapraid_worker* worker;
552 :
553 : /* if it's the first cycle */
- 554 1092105 : if (waiting_cycle == 0) {
+ 554 1085977 : if (waiting_cycle == 0) {
555 : /* store the waiting indexes */
- 556 1088986 : waiting_map[(*waiting_mac)++] = i - base;
+ 556 1084926 : waiting_map[(*waiting_mac)++] = i - base;
557 : }
558 :
- 559 1092105 : worker = &io->reader_map[i];
+ 559 1085977 : worker = &io->reader_map[i];
560 :
561 : /* if the worker has finished this index */
- 562 1092105 : if (busy_index != worker->index) {
+ 562 1085977 : if (busy_index != worker->index) {
563 : struct snapraid_task* task;
564 :
- 565 1081860 : task = &worker->task_map[io->reader_index];
+ 565 1082196 : task = &worker->task_map[io->reader_index];
566 :
- 567 1081860 : thread_mutex_unlock(&io->io_mutex);
+ 567 1082196 : thread_mutex_unlock(&io->io_mutex);
568 :
569 : /* mark the worker as processed */
570 : /* setting the previous one to point at the next one */
- 571 1081860 : *let = io->reader_list[i + 1];
+ 571 1082196 : *let = io->reader_list[i + 1];
572 :
573 : /* return the position */
- 574 1081860 : *pos = i - base;
+ 574 1082196 : *pos = i - base;
575 :
576 : /* on the first cycle, no one is waiting */
- 577 1081860 : if (waiting_cycle == 0)
- 578 1079288 : *waiting_mac = 0;
+ 577 1082196 : if (waiting_cycle == 0)
+ 578 1081206 : *waiting_mac = 0;
579 :
- 580 2163720 : return task;
+ 580 2164392 : return task;
581 : }
582 : }
583 :
584 : /* next position to check */
- 585 12723 : let = &io->reader_list[i + 1];
- 586 12723 : }
+ 585 4687 : let = &io->reader_list[i + 1];
+ 586 4687 : }
587 :
588 : /* if no worker is ready, wait for an event */
- 589 2605 : thread_cond_wait(&io->read_done, &io->io_mutex);
+ 589 1002 : thread_cond_wait(&io->read_done, &io->io_mutex);
590 :
591 : /* count the cycles */
- 592 2605 : ++waiting_cycle;
- 593 2605 : }
+ 592 1002 : ++waiting_cycle;
+ 593 1002 : }
594 : }
595 :
- 596 871056 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
+ 596 871392 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
597 : {
- 598 871056 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac);
+ 598 871392 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac);
599 : }
600 :
601 210804 : static struct snapraid_task* io_parity_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
@@ -665,18 +665,18 @@
603 210804 : return io_task_read_thread(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac);
604 : }
605 :
- 606 553582 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
+ 606 553918 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
607 : {
608 : unsigned waiting_cycle;
609 :
610 : /* count the waiting cycle */
- 611 553582 : waiting_cycle = 0;
+ 611 553918 : waiting_cycle = 0;
612 :
613 : /* clear the waiting indexes */
- 614 553582 : *waiting_mac = 0;
+ 614 553918 : *waiting_mac = 0;
615 :
616 : /* the synchronization is protected by the io mutex */
- 617 553582 : thread_mutex_lock(&io->io_mutex);
+ 617 553918 : thread_mutex_lock(&io->io_mutex);
618 :
619 : while (1) {
620 : unsigned char* let;
@@ -687,131 +687,131 @@
625 : /* to avoid a concurrent access */
626 : /* note that we are already sure that a write is not in progress */
627 : /* at the index the IO is using at now */
- 628 622113 : busy_index = (io->writer_index + 1) % io->io_max;
+ 628 622507 : busy_index = (io->writer_index + 1) % io->io_max;
629 :
630 : /* search for a worker that has already finished */
- 631 622113 : let = &io->writer_list[0];
+ 631 622507 : let = &io->writer_list[0];
632 : while (1) {
- 633 854835 : unsigned i = *let;
+ 633 899608 : unsigned i = *let;
634 : struct snapraid_worker* worker;
635 :
636 : /* if we are at the end */
- 637 854835 : if (i == io->writer_max)
- 638 68531 : break;
+ 637 899608 : if (i == io->writer_max)
+ 638 68589 : break;
639 :
640 : /* if it's the first cycle */
- 641 786304 : if (waiting_cycle == 0) {
+ 641 831019 : if (waiting_cycle == 0) {
642 : /* store the waiting indexes */
- 643 717089 : waiting_map[(*waiting_mac)++] = i;
+ 643 761956 : waiting_map[(*waiting_mac)++] = i;
644 : }
645 :
- 646 786304 : worker = &io->writer_map[i];
+ 646 831019 : worker = &io->writer_map[i];
647 :
648 : /* the two indexes cannot be equal */
- 649 786304 : assert(io->writer_index != worker->index);
+ 649 831019 : assert(io->writer_index != worker->index);
650 :
651 : /* if the worker has finished this index */
- 652 786304 : if (busy_index != worker->index) {
- 653 553582 : thread_mutex_unlock(&io->io_mutex);
+ 652 831019 : if (busy_index != worker->index) {
+ 653 553918 : thread_mutex_unlock(&io->io_mutex);
654 :
655 : /* mark the worker as processed */
656 : /* setting the previous one to point at the next one */
- 657 553582 : *let = io->writer_list[i + 1];
+ 657 553918 : *let = io->writer_list[i + 1];
658 :
659 : /* return the position */
- 660 553582 : *pos = i;
+ 660 553918 : *pos = i;
661 :
662 : /* on the first cycle, no one is waiting */
- 663 553582 : if (waiting_cycle == 0)
- 664 485051 : *waiting_mac = 0;
+ 663 553918 : if (waiting_cycle == 0)
+ 664 485329 : *waiting_mac = 0;
665 :
- 666 1107164 : return;
+ 666 1107836 : return;
667 : }
668 :
669 : /* next position to check */
- 670 232722 : let = &io->writer_list[i + 1];
- 671 232722 : }
+ 670 277101 : let = &io->writer_list[i + 1];
+ 671 277101 : }
672 :
673 : /* if no worker is ready, wait for an event */
- 674 68531 : thread_cond_wait(&io->write_done, &io->io_mutex);
+ 674 68589 : thread_cond_wait(&io->write_done, &io->io_mutex);
675 :
676 : /* count the cycles */
- 677 68531 : ++waiting_cycle;
- 678 68531 : }
+ 677 68589 : ++waiting_cycle;
+ 678 68589 : }
679 : }
680 :
- 681 1081809 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task)
+ 681 1081760 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task)
682 : {
683 : /* if we reached the end */
- 684 1081809 : if (task->position >= worker->io->block_max) {
+ 684 1081760 : if (task->position >= worker->io->block_max) {
685 : /* complete a dummy task */
- 686 120 : task->state = TASK_STATE_EMPTY;
+ 686 111 : task->state = TASK_STATE_EMPTY;
687 : } else {
- 688 1081689 : worker->func(worker, task);
+ 688 1081649 : worker->func(worker, task);
689 : }
- 690 1081474 : }
+ 690 1073313 : }
691 :
- 692 648 : static void* io_reader_thread(void* arg)
+ 692 615 : static void* io_reader_thread(void* arg)
693 : {
- 694 648 : struct snapraid_worker* worker = arg;
+ 694 615 : struct snapraid_worker* worker = arg;
695 :
696 : /* force completion of the first task */
- 697 648 : io_reader_worker(worker, &worker->task_map[0]);
+ 697 615 : io_reader_worker(worker, &worker->task_map[0]);
698 :
699 : while (1) {
700 : struct snapraid_task* task;
701 :
702 : /* get the new task */
- 703 1162742 : task = io_reader_step(worker);
+ 703 1159382 : task = io_reader_step(worker);
704 :
705 : /* if no task, it means to exit */
- 706 1163099 : if (!task)
- 707 647 : break;
+ 706 1164112 : if (!task)
+ 707 648 : break;
708 :
709 : /* nothing more to do */
- 710 1162452 : if (task->state == TASK_STATE_EMPTY)
- 711 81239 : continue;
+ 710 1163464 : if (task->state == TASK_STATE_EMPTY)
+ 711 82522 : continue;
712 :
- 713 1081213 : assert(task->state == TASK_STATE_READY);
+ 713 1080942 : assert(task->state == TASK_STATE_READY);
714 :
715 : /* work on the assigned task */
- 716 1081213 : io_reader_worker(worker, task);
- 717 1162097 : }
+ 716 1080942 : io_reader_worker(worker, task);
+ 717 1158768 : }
718 :
- 719 647 : return 0;
+ 719 648 : return 0;
720 : }
721 :
- 722 462 : static void* io_writer_thread(void* arg)
+ 722 461 : static void* io_writer_thread(void* arg)
723 : {
- 724 462 : struct snapraid_worker* worker = arg;
- 725 462 : int latest_state = TASK_STATE_DONE;
+ 724 461 : struct snapraid_worker* worker = arg;
+ 725 461 : int latest_state = TASK_STATE_DONE;
726 :
727 : while (1) {
728 : struct snapraid_task* task;
729 :
730 : /* get the new task */
- 731 554042 : task = io_writer_step(worker, latest_state);
+ 731 554142 : task = io_writer_step(worker, latest_state);
732 :
733 : /* if no task, it means to exit */
- 734 554046 : if (!task)
- 735 462 : break;
+ 734 554366 : if (!task)
+ 735 461 : break;
736 :
737 : /* nothing more to do */
- 738 553584 : if (task->state == TASK_STATE_EMPTY) {
- 739 13749 : latest_state = TASK_STATE_DONE;
- 740 13749 : continue;
+ 738 553905 : if (task->state == TASK_STATE_EMPTY) {
+ 739 13659 : latest_state = TASK_STATE_DONE;
+ 740 13659 : continue;
741 : }
742 :
- 743 539835 : assert(task->state == TASK_STATE_READY);
+ 743 540246 : assert(task->state == TASK_STATE_READY);
744 :
745 : /* work on the assigned task */
- 746 539835 : worker->func(worker, task);
+ 746 540246 : worker->func(worker, task);
747 :
748 : /* save the resulting state */
- 749 539831 : latest_state = task->state;
- 750 553580 : }
+ 749 540022 : latest_state = task->state;
+ 750 553681 : }
751 :
- 752 462 : return 0;
+ 752 461 : return 0;
753 : }
754 :
755 95 : static void io_start_thread(struct snapraid_io* io,
diff --git a/cov/cmdline/list.c.func-sort-c.html b/cov/cmdline/list.c.func-sort-c.html
index 2f6976a1..d0ccec74 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 e01efb55..5781b04e 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 8846cd26..8379ed5e 100644
--- a/cov/cmdline/list.c.gcov.html
+++ b/cov/cmdline/list.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/mkstream.c.func-sort-c.html b/cov/cmdline/mkstream.c.func-sort-c.html
index 763bb84b..95ea1869 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 3288f869..b9b8afb5 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 461671b3..f477ea41 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 2def4c3e..664571fa 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 |
- 56072909 |
+ 56053599 |
| rndnz |
- 55661691 |
+ 55642239 |
| file_cmp |
- 146571 |
+ 146564 |
| rndnz_range |
- 32723 |
+ 32684 |
| rnd_name |
- 26849 |
+ 26839 |
| cmd_generate |
@@ -93,19 +93,19 @@
| cmd_write |
- 6227 |
-
-
- | cmd_append |
- 3256 |
-
-
- | cmd_truncate |
- 3141 |
+ 6251 |
| cmd_delete |
- 3136 |
+ 3207 |
+
+
+ | cmd_append |
+ 3193 |
+
+
+ | cmd_truncate |
+ 3103 |
| cmd_damage |
@@ -121,7 +121,7 @@
| cmd_generate_symlink |
- 940 |
+ 930 |
| main |
diff --git a/cov/cmdline/mktest.c.func.html b/cov/cmdline/mktest.c.func.html
index 24136aa2..6c779ca9 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 |
- 3256 |
+ 3193 |
| cmd_change |
@@ -73,7 +73,7 @@
| cmd_delete |
- 3136 |
+ 3207 |
| cmd_generate |
@@ -85,15 +85,15 @@
| cmd_generate_symlink |
- 940 |
+ 930 |
| cmd_truncate |
- 3141 |
+ 3103 |
| cmd_write |
- 6227 |
+ 6251 |
| fallback |
@@ -101,7 +101,7 @@
| file_cmp |
- 146571 |
+ 146564 |
| help |
@@ -113,15 +113,15 @@
| rnd |
- 56072909 |
+ 56053599 |
| rnd_name |
- 26849 |
+ 26839 |
| rndnz |
- 55661691 |
+ 55642239 |
| rndnz_damage |
@@ -129,7 +129,7 @@
| rndnz_range |
- 32723 |
+ 32684 |
diff --git a/cov/cmdline/mktest.c.gcov.html b/cov/cmdline/mktest.c.gcov.html
index 584eab4f..bae0e142 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 56072909 : unsigned rnd(unsigned max)
+ 30 56053599 : unsigned rnd(unsigned max)
31 : {
- 32 56072909 : seed = seed * 6364136223846793005LL + 1442695040888963407LL;
+ 32 56053599 : seed = seed * 6364136223846793005LL + 1442695040888963407LL;
33 :
- 34 56072909 : return (seed >> 32) % max;
+ 34 56053599 : return (seed >> 32) % max;
35 : }
36 :
- 37 55661691 : unsigned rndnz(unsigned max)
+ 37 55642239 : unsigned rndnz(unsigned max)
38 : {
- 39 55661691 : if (max <= 1)
+ 39 55642239 : if (max <= 1)
40 2831 : return 1;
41 : else
- 42 55658860 : return rnd(max - 1) + 1;
+ 42 55639408 : return rnd(max - 1) + 1;
43 : }
44 :
- 45 32723 : void rndnz_range(unsigned char* data, int size)
+ 45 32684 : void rndnz_range(unsigned char* data, int size)
46 : {
47 : int i;
48 :
- 49 55687651 : for (i = 0; i < size; ++i)
- 50 55654928 : data[i] = rndnz(256);
- 51 32723 : }
+ 49 55668161 : for (i = 0; i < size; ++i)
+ 50 55635477 : data[i] = rndnz(256);
+ 51 32684 : }
52 :
53 1821 : void rndnz_damage(unsigned char* data, int size)
54 : {
@@ -121,8 +121,8 @@
59 : unsigned char c;
60 :
61 : do {
- 62 1832 : c = rndnz(256);
- 63 1832 : } while (c == data[i]);
+ 62 1831 : c = rndnz(256);
+ 63 1831 : } while (c == data[i]);
64 :
65 1821 : data[i] = c;
66 : }
@@ -131,23 +131,23 @@
69 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+";
70 : #define CHARSET_LEN (sizeof(CHARSET) - 1)
71 :
- 72 26849 : void rnd_name(char* file)
+ 72 26839 : void rnd_name(char* file)
73 : {
- 74 26849 : int l = 1 + rnd(20);
+ 74 26839 : int l = 1 + rnd(20);
75 :
- 76 335390 : while (l) {
- 77 281692 : *file++ = CHARSET[rnd(CHARSET_LEN)];
- 78 281692 : --l;
+ 76 335505 : while (l) {
+ 77 281827 : *file++ = CHARSET[rnd(CHARSET_LEN)];
+ 78 281827 : --l;
79 : }
- 80 26849 : *file = 0;
- 81 26849 : }
+ 80 26839 : *file = 0;
+ 81 26839 : }
82 :
83 : /****************************************************************************/
84 : /* file */
85 :
- 86 146571 : int file_cmp(const void* a, const void* b)
+ 86 146564 : int file_cmp(const void* a, const void* b)
87 : {
- 88 146571 : return strcmp(a, b);
+ 88 146564 : 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 940 : void cmd_generate_symlink(const char* path, const char* linkto)
+ 200 930 : void cmd_generate_symlink(const char* path, const char* linkto)
201 : {
202 : /* remove the existing file/symlink if any */
- 203 940 : if (remove(path) != 0) {
- 204 919 : if (errno != ENOENT) {
+ 203 930 : if (remove(path) != 0) {
+ 204 909 : 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 940 : if (symlink(linkto, path) != 0) {
+ 212 930 : 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 940 : }
+ 218 930 : }
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 6227 : void cmd_write(const char* path, int size)
+ 291 6251 : void cmd_write(const char* path, int size)
292 : {
293 : struct stat st;
294 :
- 295 6227 : if (lstat(path, &st) != 0) {
+ 295 6251 : 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 6227 : if (S_ISREG(st.st_mode)) {
+ 302 6251 : if (S_ISREG(st.st_mode)) {
303 : unsigned char* data;
304 : off_t off;
305 : int f;
306 :
307 : /* not over the end */
- 308 6200 : if (size > st.st_size)
- 309 695 : size = st.st_size;
+ 308 6224 : if (size > st.st_size)
+ 309 696 : size = st.st_size;
310 :
311 : /* start at random position inside the file */
- 312 6200 : if (size < st.st_size)
- 313 5504 : off = rnd(st.st_size - size);
+ 312 6224 : if (size < st.st_size)
+ 313 5526 : off = rnd(st.st_size - size);
314 : else
- 315 696 : off = 0;
+ 315 698 : off = 0;
316 :
- 317 6200 : data = malloc(size);
+ 317 6224 : data = malloc(size);
318 :
- 319 6200 : rndnz_range(data, size);
+ 319 6224 : rndnz_range(data, size);
320 :
- 321 6200 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
- 322 6200 : if (f < 0) {
+ 321 6224 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
+ 322 6224 : 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 6200 : if (lseek(f, off, SEEK_SET) != off) {
+ 329 6224 : 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 6200 : if (write(f, data, size) != size) {
+ 336 6224 : 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 6200 : if (close(f) != 0) {
+ 343 6224 : 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 6200 : free(data);
+ 350 6224 : free(data);
351 : }
- 352 6227 : }
+ 352 6251 : }
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 3256 : void cmd_append(const char* path, int size)
+ 459 3193 : void cmd_append(const char* path, int size)
460 : {
461 : struct stat st;
462 :
- 463 3256 : if (lstat(path, &st) != 0) {
+ 463 3193 : 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 3256 : if (S_ISREG(st.st_mode)) {
+ 470 3193 : if (S_ISREG(st.st_mode)) {
471 : unsigned char* data;
472 : int f;
473 :
- 474 3256 : data = malloc(size);
+ 474 3193 : data = malloc(size);
475 :
- 476 3256 : rndnz_range(data, size);
+ 476 3193 : rndnz_range(data, size);
477 :
- 478 3256 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW);
- 479 3256 : if (f < 0) {
+ 478 3193 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW);
+ 479 3193 : 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 3256 : if (write(f, data, size) != size) {
+ 486 3193 : 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 3256 : if (close(f) != 0) {
+ 493 3193 : 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 3256 : free(data);
+ 500 3193 : free(data);
501 : }
- 502 3256 : }
+ 502 3193 : }
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 3141 : void cmd_truncate(const char* path, int size)
+ 510 3103 : void cmd_truncate(const char* path, int size)
511 : {
512 : struct stat st;
513 :
- 514 3141 : if (lstat(path, &st) != 0) {
+ 514 3103 : 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 3141 : if (S_ISREG(st.st_mode)) {
+ 521 3103 : if (S_ISREG(st.st_mode)) {
522 : off_t off;
523 : int f;
524 :
525 : /* if file is empty, just rewrite it */
- 526 3141 : if (st.st_size == 0) {
- 527 1 : size = 0;
+ 526 3103 : if (st.st_size == 0) {
+ 527 3 : size = 0;
528 : } else {
529 : /* don't truncate files to 0 size to avoid ZERO file size protection */
- 530 3140 : if (size >= st.st_size)
- 531 200 : size = st.st_size - 1;
+ 530 3100 : if (size >= st.st_size)
+ 531 195 : size = st.st_size - 1;
532 : }
533 :
- 534 3141 : off = st.st_size - size;
+ 534 3103 : off = st.st_size - size;
535 :
- 536 3141 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
- 537 3141 : if (f < 0) {
+ 536 3103 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
+ 537 3103 : 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 3141 : if (ftruncate(f, off) != 0) {
+ 544 3103 : 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 3141 : if (close(f) != 0) {
+ 551 3103 : 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 3141 : }
+ 558 3103 : }
559 :
560 : /**
561 : * Delete a file.
562 : * - The file must exist.
563 : */
- 564 3136 : void cmd_delete(const char* path)
+ 564 3207 : void cmd_delete(const char* path)
565 : {
- 566 3136 : if (remove(path) != 0) {
+ 566 3207 : 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 3136 : }
+ 572 3207 : }
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 13157 : return;
584 :
- 585 13104 : if (lstat(path, &st) != 0) {
+ 585 13099 : 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 13099 : if (S_ISLNK(st.st_mode)) {
593 : /* symlink */
- 594 393 : if (rnd(2) == 0) {
+ 594 394 : if (rnd(2) == 0) {
595 : /* delete */
- 596 186 : if (remove(path) != 0) {
+ 596 197 : 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 207 : if (remove(path) != 0) {
+ 606 197 : 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 207 : rnd_name(linkto);
+ 613 197 : rnd_name(linkto);
614 :
- 615 207 : cmd_generate_symlink(path, linkto);
+ 615 197 : cmd_generate_symlink(path, linkto);
616 : }
- 617 12711 : } else if (S_ISREG(st.st_mode)) {
+ 617 12705 : } else if (S_ISREG(st.st_mode)) {
618 : int r;
619 :
- 620 12711 : r = rnd(4);
+ 620 12705 : r = rnd(4);
621 :
- 622 12711 : if (r == 0) {
- 623 3178 : cmd_write(path, size);
- 624 9533 : } else if (r == 1) {
- 625 3256 : cmd_append(path, size);
- 626 6277 : } else if (r == 2) {
- 627 3141 : cmd_truncate(path, size);
+ 622 12705 : if (r == 0) {
+ 623 3202 : cmd_write(path, size);
+ 624 9503 : } else if (r == 1) {
+ 625 3193 : cmd_append(path, size);
+ 626 6310 : } else if (r == 2) {
+ 627 3103 : cmd_truncate(path, size);
628 : } else {
- 629 3136 : cmd_delete(path);
+ 629 3207 : 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 b8fd330e..1fc77637 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 |
- 8307408 |
+ 8307428 |
| MurmurHash3_x86_128 |
- 2076852 |
+ 2076857 |
diff --git a/cov/cmdline/murmur3.c.func.html b/cov/cmdline/murmur3.c.func.html
index 40d30fc9..1cb04e4d 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 |
- 2076852 |
+ 2076857 |
| fmix32 |
- 8307408 |
+ 8307428 |
diff --git a/cov/cmdline/murmur3.c.gcov.html b/cov/cmdline/murmur3.c.gcov.html
index 5f7069e2..fee01498 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 8307408 : static inline uint32_t fmix32(uint32_t h)
+ 32 8307428 : static inline uint32_t fmix32(uint32_t h)
33 : {
- 34 8307408 : h ^= h >> 16;
- 35 8307408 : h *= 0x85ebca6b;
- 36 8307408 : h ^= h >> 13;
- 37 8307408 : h *= 0xc2b2ae35;
- 38 8307408 : h ^= h >> 16;
- 39 8307408 : return h;
+ 34 8307428 : h ^= h >> 16;
+ 35 8307428 : h *= 0x85ebca6b;
+ 36 8307428 : h ^= h >> 13;
+ 37 8307428 : h *= 0xc2b2ae35;
+ 38 8307428 : h ^= h >> 16;
+ 39 8307428 : return h;
40 : }
41 :
42 : /*
@@ -137,7 +137,7 @@
75 : uint32_t c3 = 0x38b34ae5;
76 : uint32_t c4 = 0xa1e38b93;
77 :
- 78 2076852 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest)
+ 78 2076857 : 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;
@@ -145,21 +145,21 @@
83 : size_t size_remainder;
84 : uint32_t h1, h2, h3, h4;
85 :
- 86 2076852 : h1 = util_read32(seed + 0);
- 87 2076852 : h2 = util_read32(seed + 4);
- 88 2076852 : h3 = util_read32(seed + 8);
- 89 2076852 : h4 = util_read32(seed + 12);
+ 86 2076857 : h1 = util_read32(seed + 0);
+ 87 2076857 : h2 = util_read32(seed + 4);
+ 88 2076857 : h3 = util_read32(seed + 8);
+ 89 2076857 : h4 = util_read32(seed + 12);
90 :
- 91 2076852 : nblocks = size / 16;
- 92 2076852 : blocks = data;
- 93 2076852 : end = blocks + nblocks * 4;
+ 91 2076857 : nblocks = size / 16;
+ 92 2076857 : blocks = data;
+ 93 2076857 : end = blocks + nblocks * 4;
94 :
95 : /* body */
- 96 110684486 : while (blocks < end) {
- 97 106530782 : uint32_t k1 = blocks[0];
- 98 106530782 : uint32_t k2 = blocks[1];
- 99 106530782 : uint32_t k3 = blocks[2];
- 100 106530782 : uint32_t k4 = blocks[3];
+ 96 110684757 : while (blocks < end) {
+ 97 106531043 : uint32_t k1 = blocks[0];
+ 98 106531043 : uint32_t k2 = blocks[1];
+ 99 106531043 : uint32_t k3 = blocks[2];
+ 100 106531043 : uint32_t k4 = blocks[3];
101 :
102 : #if WORDS_BIGENDIAN
103 : k1 = util_swap32(k1);
@@ -168,77 +168,77 @@
106 : k4 = util_swap32(k4);
107 : #endif
108 :
- 109 106530782 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
+ 109 106531043 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
110 :
- 111 106530782 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b;
+ 111 106531043 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b;
112 :
- 113 106530782 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
+ 113 106531043 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
114 :
- 115 106530782 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747;
+ 115 106531043 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747;
116 :
- 117 106530782 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
+ 117 106531043 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
118 :
- 119 106530782 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35;
+ 119 106531043 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35;
120 :
- 121 106530782 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
+ 121 106531043 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
122 :
- 123 106530782 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17;
+ 123 106531043 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17;
124 :
- 125 106530782 : blocks += 4;
+ 125 106531043 : blocks += 4;
126 : }
127 :
128 : /* tail */
- 129 2076852 : size_remainder = size & 15;
- 130 2076852 : if (size_remainder != 0) {
- 131 779223 : const uint8_t* tail = (const uint8_t*)blocks;
+ 129 2076857 : size_remainder = size & 15;
+ 130 2076857 : if (size_remainder != 0) {
+ 131 779280 : const uint8_t* tail = (const uint8_t*)blocks;
132 :
- 133 779223 : uint32_t k1 = 0;
- 134 779223 : uint32_t k2 = 0;
- 135 779223 : uint32_t k3 = 0;
- 136 779223 : uint32_t k4 = 0;
+ 133 779280 : uint32_t k1 = 0;
+ 134 779280 : uint32_t k2 = 0;
+ 135 779280 : uint32_t k3 = 0;
+ 136 779280 : uint32_t k4 = 0;
137 :
- 138 779223 : switch (size_remainder) {
- 139 51253 : case 15 : k4 ^= (uint32_t)tail[14] << 16;
- 140 103976 : case 14 : k4 ^= (uint32_t)tail[13] << 8;
- 141 156183 : case 13 : k4 ^= (uint32_t)tail[12] << 0;
- 142 156183 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
- 143 208955 : case 12 : k3 ^= (uint32_t)tail[11] << 24;
- 144 261477 : case 11 : k3 ^= (uint32_t)tail[10] << 16;
- 145 313646 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8;
- 146 366950 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0;
- 147 366950 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
- 148 420888 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24;
- 149 470405 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16;
- 150 523044 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8;
- 151 573538 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0;
- 152 573538 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
- 153 625492 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24;
- 154 675841 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16;
- 155 726916 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8;
- 156 779223 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0;
- 157 779223 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
+ 138 779280 : switch (size_remainder) {
+ 139 51283 : case 15 : k4 ^= (uint32_t)tail[14] << 16;
+ 140 104014 : case 14 : k4 ^= (uint32_t)tail[13] << 8;
+ 141 156219 : case 13 : k4 ^= (uint32_t)tail[12] << 0;
+ 142 156219 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4;
+ 143 208972 : case 12 : k3 ^= (uint32_t)tail[11] << 24;
+ 144 261514 : case 11 : k3 ^= (uint32_t)tail[10] << 16;
+ 145 313715 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8;
+ 146 366995 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0;
+ 147 366995 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3;
+ 148 420927 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24;
+ 149 470437 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16;
+ 150 523081 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8;
+ 151 573603 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0;
+ 152 573603 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2;
+ 153 625568 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24;
+ 154 675931 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16;
+ 155 726990 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8;
+ 156 779280 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0;
+ 157 779280 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1;
158 : }
159 : }
160 :
161 : /* finalization */
- 162 2076852 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size;
+ 162 2076857 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size;
163 :
- 164 2076852 : h1 += h2; h1 += h3; h1 += h4;
- 165 2076852 : h2 += h1; h3 += h1; h4 += h1;
+ 164 2076857 : h1 += h2; h1 += h3; h1 += h4;
+ 165 2076857 : h2 += h1; h3 += h1; h4 += h1;
166 :
- 167 2076852 : h1 = fmix32(h1);
- 168 2076852 : h2 = fmix32(h2);
- 169 2076852 : h3 = fmix32(h3);
- 170 2076852 : h4 = fmix32(h4);
+ 167 2076857 : h1 = fmix32(h1);
+ 168 2076857 : h2 = fmix32(h2);
+ 169 2076857 : h3 = fmix32(h3);
+ 170 2076857 : h4 = fmix32(h4);
171 :
- 172 2076852 : h1 += h2; h1 += h3; h1 += h4;
- 173 2076852 : h2 += h1; h3 += h1; h4 += h1;
+ 172 2076857 : h1 += h2; h1 += h3; h1 += h4;
+ 173 2076857 : h2 += h1; h3 += h1; h4 += h1;
174 :
- 175 2076852 : util_write32(digest + 0, h1);
- 176 2076852 : util_write32(digest + 4, h2);
- 177 2076852 : util_write32(digest + 8, h3);
- 178 2076852 : util_write32(digest + 12, h4);
- 179 2076852 : }
+ 175 2076857 : util_write32(digest + 0, h1);
+ 176 2076857 : util_write32(digest + 4, h2);
+ 177 2076857 : util_write32(digest + 8, h3);
+ 178 2076857 : util_write32(digest + 12, h4);
+ 179 2076857 : }
180 :
diff --git a/cov/cmdline/parity.c.func-sort-c.html b/cov/cmdline/parity.c.func-sort-c.html
index 494a1ed5..6be34ce5 100644
--- a/cov/cmdline/parity.c.func-sort-c.html
+++ b/cov/cmdline/parity.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| parity_split_find |
- 4113807 |
+ 4114072 |
| parity_read |
- 3501819 |
+ 3501740 |
| parity_write |
- 611983 |
+ 612363 |
| parity_handle_chsize |
diff --git a/cov/cmdline/parity.c.func.html b/cov/cmdline/parity.c.func.html
index 0610c73a..5a320fbc 100644
--- a/cov/cmdline/parity.c.func.html
+++ b/cov/cmdline/parity.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -109,7 +109,7 @@
| parity_read |
- 3501819 |
+ 3501740 |
| parity_size |
@@ -117,7 +117,7 @@
| parity_split_find |
- 4113807 |
+ 4114072 |
| parity_split_is_fixed |
@@ -133,7 +133,7 @@
| parity_write |
- 611983 |
+ 612363 |
diff --git a/cov/cmdline/parity.c.gcov.html b/cov/cmdline/parity.c.gcov.html
index b43a0239..af7bdf5c 100644
--- a/cov/cmdline/parity.c.gcov.html
+++ b/cov/cmdline/parity.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -135,8 +135,8 @@
73 521 : block_off_t block = fs_size(disk);
74 :
75 : /* decrease the block until an used one */
- 76 221718 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1)))
- 77 220676 : --block;
+ 76 221719 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1)))
+ 77 220677 : --block;
78 :
79 : /* get the highest value */
80 521 : if (block > parity_block)
@@ -826,44 +826,44 @@
764 1022 : return f_ret;
765 : }
766 :
- 767 4113807 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset)
+ 767 4114072 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset)
768 : {
769 : unsigned s;
770 :
- 771 4113807 : if (*offset < 0)
+ 771 4114072 : if (*offset < 0)
772 0 : return 0;
773 :
- 774 6502165 : for (s = 0;s < handle->split_mac;++s) {
- 775 6490805 : struct snapraid_split_handle* split = &handle->split_map[s];
+ 774 6502675 : for (s = 0;s < handle->split_mac;++s) {
+ 775 6491315 : struct snapraid_split_handle* split = &handle->split_map[s];
776 :
- 777 6490805 : if (*offset < split->size)
- 778 4102447 : return split;
+ 777 6491315 : if (*offset < split->size)
+ 778 4102712 : return split;
779 :
- 780 2388358 : *offset -= split->size;
+ 780 2388603 : *offset -= split->size;
781 : }
782 :
783 11360 : return 0;
784 : }
785 :
- 786 611983 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size)
+ 786 612363 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size)
787 : {
788 : ssize_t write_ret;
789 : data_off_t offset;
790 : struct snapraid_split_handle* split;
791 : int ret;
792 :
- 793 611983 : offset = pos * (data_off_t)block_size;
+ 793 612363 : offset = pos * (data_off_t)block_size;
794 :
- 795 611983 : split = parity_split_find(handle, &offset);
- 796 611984 : if (!split) {
+ 795 612363 : split = parity_split_find(handle, &offset);
+ 796 612400 : if (!split) {
797 : /* LCOV_EXCL_START */
798 : log_fatal("Writing parity data outside range at extra offset %" PRIu64 ".\n", offset);
799 : return -1;
800 : /* LCOV_EXCL_STOP */
801 : }
802 :
- 803 611984 : write_ret = pwrite(split->f, block_buffer, block_size, offset);
- 804 611983 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */
+ 803 612400 : write_ret = pwrite(split->f, block_buffer, block_size, offset);
+ 804 612277 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */
805 : /* LCOV_EXCL_START */
806 : if (errno == ENOSPC) {
807 : log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", split->path);
@@ -874,18 +874,18 @@
812 : /* LCOV_EXCL_STOP */
813 : }
814 :
- 815 611983 : ret = advise_write(&split->advise, split->f, offset, block_size);
- 816 611981 : if (ret != 0) {
+ 815 612277 : ret = advise_write(&split->advise, split->f, offset, block_size);
+ 816 612100 : if (ret != 0) {
817 : /* LCOV_EXCL_START */
818 : log_fatal("Error advising parity file '%s'. %s.\n", split->path, strerror(errno));
819 : return -1;
820 : /* LCOV_EXCL_STOP */
821 : }
822 :
- 823 611981 : return 0;
+ 823 612100 : return 0;
824 : }
825 :
- 826 3501819 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out)
+ 826 3501740 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out)
827 : {
828 : ssize_t read_ret;
829 : data_off_t offset;
@@ -893,44 +893,44 @@
831 : struct snapraid_split_handle* split;
832 : int ret;
833 :
- 834 3501819 : offset = pos * (data_off_t)block_size;
+ 834 3501740 : offset = pos * (data_off_t)block_size;
835 :
- 836 3501819 : split = parity_split_find(handle, &offset);
- 837 3501808 : if (!split) {
+ 836 3501740 : split = parity_split_find(handle, &offset);
+ 837 3501789 : if (!split) {
838 : /* LCOV_EXCL_START */
839 : out("Reading parity data outside range at extra offset %" PRIu64 ".\n", offset);
840 : return -1;
841 : /* LCOV_EXCL_STOP */
842 : }
843 :
- 844 3490448 : count = 0;
+ 844 3490429 : count = 0;
845 : do {
- 846 3490446 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count);
- 847 3490413 : if (read_ret < 0) {
+ 846 3490283 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count);
+ 847 3490289 : if (read_ret < 0) {
848 : /* LCOV_EXCL_START */
849 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno));
850 : return -1;
851 : /* LCOV_EXCL_STOP */
852 : }
- 853 3490413 : if (read_ret == 0) {
+ 853 3490289 : if (read_ret == 0) {
854 : /* LCOV_EXCL_START */
855 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno));
856 : return -1;
857 : /* LCOV_EXCL_STOP */
858 : }
859 :
- 860 3490413 : count += read_ret;
- 861 3490413 : } while (count < block_size);
+ 860 3490289 : count += read_ret;
+ 861 3490289 : } while (count < block_size);
862 :
- 863 3490415 : ret = advise_read(&split->advise, split->f, offset, block_size);
- 864 3490417 : if (ret != 0) {
+ 863 3490435 : ret = advise_read(&split->advise, split->f, offset, block_size);
+ 864 3490346 : if (ret != 0) {
865 : /* LCOV_EXCL_START */
866 : out("Error advising parity file '%s'. %s.\n", split->path, strerror(errno));
867 : return -1;
868 : /* LCOV_EXCL_STOP */
869 : }
870 :
- 871 3490417 : return block_size;
+ 871 3490346 : return block_size;
872 : }
873 :
diff --git a/cov/cmdline/pool.c.func-sort-c.html b/cov/cmdline/pool.c.func-sort-c.html
index 154e338e..06ab1417 100644
--- a/cov/cmdline/pool.c.func-sort-c.html
+++ b/cov/cmdline/pool.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -68,7 +68,7 @@
5 |
- | state_pool |
+ state_pool |
3 |
diff --git a/cov/cmdline/pool.c.func.html b/cov/cmdline/pool.c.func.html
index 97212d32..4d58039c 100644
--- a/cov/cmdline/pool.c.func.html
+++ b/cov/cmdline/pool.c.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -68,7 +68,7 @@
17589 |
- | state_pool |
+ state_pool |
3 |
diff --git a/cov/cmdline/pool.c.gcov.html b/cov/cmdline/pool.c.gcov.html
index c1a4eec7..9a3e0678 100644
--- a/cov/cmdline/pool.c.gcov.html
+++ b/cov/cmdline/pool.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -209,7 +209,7 @@
147 : /**
148 : * Create a link to the specified disk entry.
149 : */
- 150 17589 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub)
+ 150 17589 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub, int64_t mtime_sec, int mtime_nsec)
151 : {
152 : char path[PATH_MAX];
153 : char linkto[PATH_MAX];
@@ -258,70 +258,80 @@
196 : /* LCOV_EXCL_STOP */
197 : }
198 : }
- 199 17589 : }
- 200 :
- 201 3 : void state_pool(struct snapraid_state* state)
- 202 : {
- 203 : tommy_node* i;
- 204 : char pool_dir[PATH_MAX];
- 205 : char share_dir[PATH_MAX];
- 206 : unsigned count;
- 207 :
- 208 3 : if (state->pool[0] == 0) {
- 209 : /* LCOV_EXCL_START */
- 210 : log_fatal("To use the 'pool' command you must set the pool directory in the configuration file\n");
- 211 : exit(EXIT_FAILURE);
- 212 : /* LCOV_EXCL_STOP */
- 213 : }
- 214 :
- 215 3 : msg_progress("Cleaning...\n");
- 216 :
- 217 : /* pool directory with final slash */
- 218 3 : pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool);
- 219 3 : pathslash(pool_dir, sizeof(pool_dir));
- 220 :
- 221 : /* share directory with final slash */
- 222 3 : pathprint(share_dir, sizeof(share_dir), "%s", state->share);
- 223 3 : pathslash(share_dir, sizeof(share_dir));
+ 199 :
+ 200 17589 : if (mtime_sec) {
+ 201 17000 : ret = lmtime(path, mtime_sec, mtime_nsec);
+ 202 17000 : if (ret != 0) {
+ 203 : /* LCOV_EXCL_START */
+ 204 : log_fatal("Error setting time to symlink '%s'. %s.\n", path, strerror(errno));
+ 205 : exit(EXIT_FAILURE);
+ 206 : /* LCOV_EXCL_STOP */
+ 207 : }
+ 208 : }
+ 209 17589 : }
+ 210 :
+ 211 3 : void state_pool(struct snapraid_state* state)
+ 212 : {
+ 213 : tommy_node* i;
+ 214 : char pool_dir[PATH_MAX];
+ 215 : char share_dir[PATH_MAX];
+ 216 : unsigned count;
+ 217 :
+ 218 3 : if (state->pool[0] == 0) {
+ 219 : /* LCOV_EXCL_START */
+ 220 : log_fatal("To use the 'pool' command you must set the pool directory in the configuration file\n");
+ 221 : exit(EXIT_FAILURE);
+ 222 : /* LCOV_EXCL_STOP */
+ 223 : }
224 :
- 225 : /* first clear the previous pool tree */
- 226 3 : clean_dir(state, pool_dir);
- 227 :
- 228 3 : msg_progress("Pooling...\n");
- 229 :
- 230 : /* for each disk */
- 231 3 : count = 0;
- 232 21 : for (i = state->disklist; i != 0; i = i->next) {
- 233 : tommy_node* j;
- 234 18 : struct snapraid_disk* disk = i->data;
- 235 :
- 236 : /* for each file */
- 237 17018 : for (j = disk->filelist; j != 0; j = j->next) {
- 238 17000 : struct snapraid_file* file = j->data;
- 239 17000 : make_link(pool_dir, share_dir, disk, file->sub);
- 240 17000 : ++count;
- 241 : }
- 242 :
- 243 : /* for each link */
- 244 607 : for (j = disk->linklist; j != 0; j = j->next) {
- 245 589 : struct snapraid_link* slink = j->data;
- 246 589 : make_link(pool_dir, share_dir, disk, slink->sub);
- 247 589 : ++count;
- 248 : }
- 249 :
- 250 : /* we ignore empty dirs in disk->dir */
- 251 : }
+ 225 3 : msg_progress("Cleaning...\n");
+ 226 :
+ 227 : /* pool directory with final slash */
+ 228 3 : pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool);
+ 229 3 : pathslash(pool_dir, sizeof(pool_dir));
+ 230 :
+ 231 : /* share directory with final slash */
+ 232 3 : pathprint(share_dir, sizeof(share_dir), "%s", state->share);
+ 233 3 : pathslash(share_dir, sizeof(share_dir));
+ 234 :
+ 235 : /* first clear the previous pool tree */
+ 236 3 : clean_dir(state, pool_dir);
+ 237 :
+ 238 3 : msg_progress("Pooling...\n");
+ 239 :
+ 240 : /* for each disk */
+ 241 3 : count = 0;
+ 242 21 : for (i = state->disklist; i != 0; i = i->next) {
+ 243 : tommy_node* j;
+ 244 18 : struct snapraid_disk* disk = i->data;
+ 245 :
+ 246 : /* for each file */
+ 247 17018 : for (j = disk->filelist; j != 0; j = j->next) {
+ 248 17000 : struct snapraid_file* file = j->data;
+ 249 17000 : make_link(pool_dir, share_dir, disk, file->sub, file->mtime_sec, file->mtime_nsec);
+ 250 17000 : ++count;
+ 251 : }
252 :
- 253 3 : if (count)
- 254 2 : msg_status("%u links created\n", count);
- 255 : else
- 256 1 : msg_status("No link created\n");
- 257 :
- 258 3 : log_tag("summary:link_count::%u\n", count);
- 259 3 : log_tag("summary:exit:ok\n");
- 260 3 : log_flush();
- 261 3 : }
+ 253 : /* for each link */
+ 254 607 : for (j = disk->linklist; j != 0; j = j->next) {
+ 255 589 : struct snapraid_link* slink = j->data;
+ 256 589 : make_link(pool_dir, share_dir, disk, slink->sub, 0, 0);
+ 257 589 : ++count;
+ 258 : }
+ 259 :
+ 260 : /* we ignore empty dirs in disk->dir */
+ 261 : }
262 :
+ 263 3 : if (count)
+ 264 2 : msg_status("%u links created\n", count);
+ 265 : else
+ 266 1 : msg_status("No link created\n");
+ 267 :
+ 268 3 : log_tag("summary:link_count::%u\n", count);
+ 269 3 : log_tag("summary:exit:ok\n");
+ 270 3 : log_flush();
+ 271 3 : }
+ 272 :
diff --git a/cov/cmdline/portable.h.func-sort-c.html b/cov/cmdline/portable.h.func-sort-c.html
index fb8ed345..13fa0cdc 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 6ae6ba87..24081d3d 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 31070c84..7577fe1a 100644
--- a/cov/cmdline/portable.h.gcov.html
+++ b/cov/cmdline/portable.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -260,292 +260,298 @@
198 : #include <sys/types.h>
199 : #endif
200 :
- 201 : #if HAVE_SYS_STAT_H
- 202 : #include <sys/stat.h>
- 203 : #endif
- 204 :
- 205 : #if HAVE_SYS_WAIT_H
- 206 : #include <sys/wait.h>
- 207 : #endif
- 208 : #ifndef WEXITSTATUS
- 209 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
- 210 : #endif
- 211 : #ifndef WIFEXITED
- 212 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+ 201 : #if MAJOR_IN_MKDEV
+ 202 : #include <sys/mkdev.h>
+ 203 : #elif MAJOR_IN_SYSMACROS
+ 204 : #include <sys/sysmacros.h>
+ 205 : #endif
+ 206 :
+ 207 : #if HAVE_SYS_STAT_H
+ 208 : #include <sys/stat.h>
+ 209 : #endif
+ 210 :
+ 211 : #if HAVE_SYS_WAIT_H
+ 212 : #include <sys/wait.h>
213 : #endif
- 214 :
- 215 : #if HAVE_GETOPT_H
- 216 : #include <getopt.h>
- 217 : #endif
- 218 :
- 219 : #if HAVE_FNMATCH_H
- 220 : #include <fnmatch.h>
- 221 : #else
- 222 : #include "fnmatch.h"
+ 214 : #ifndef WEXITSTATUS
+ 215 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+ 216 : #endif
+ 217 : #ifndef WIFEXITED
+ 218 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+ 219 : #endif
+ 220 :
+ 221 : #if HAVE_GETOPT_H
+ 222 : #include <getopt.h>
223 : #endif
224 :
- 225 : #if HAVE_PTHREAD_H
- 226 : #include <pthread.h>
- 227 : #endif
- 228 :
- 229 : #if HAVE_MATH_H
- 230 : #include <math.h>
- 231 : #endif
- 232 :
- 233 : #if HAVE_EXECINFO_H
- 234 : #include <execinfo.h>
- 235 : #endif
- 236 :
- 237 : /**
- 238 : * Enable thread use.
- 239 : */
- 240 : #if HAVE_PTHREAD_CREATE
- 241 : #define HAVE_PTHREAD 1
- 242 : #endif
- 243 :
- 244 : /**
- 245 : * Disable case check in Windows.
- 246 : */
- 247 : #ifdef _WIN32
- 248 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD
- 249 : #else
- 250 : #define FNM_CASEINSENSITIVE_FOR_WIN 0
- 251 : #endif
- 252 :
- 253 : #if HAVE_IO_H
- 254 : #include <io.h>
- 255 : #endif
- 256 :
- 257 : #if HAVE_GETOPT_LONG
- 258 : #define SWITCH_GETOPT_LONG(a, b) a
- 259 : #else
- 260 : #define SWITCH_GETOPT_LONG(a, b) b
+ 225 : #if HAVE_FNMATCH_H
+ 226 : #include <fnmatch.h>
+ 227 : #else
+ 228 : #include "fnmatch.h"
+ 229 : #endif
+ 230 :
+ 231 : #if HAVE_PTHREAD_H
+ 232 : #include <pthread.h>
+ 233 : #endif
+ 234 :
+ 235 : #if HAVE_MATH_H
+ 236 : #include <math.h>
+ 237 : #endif
+ 238 :
+ 239 : #if HAVE_EXECINFO_H
+ 240 : #include <execinfo.h>
+ 241 : #endif
+ 242 :
+ 243 : /**
+ 244 : * Enable thread use.
+ 245 : */
+ 246 : #if HAVE_PTHREAD_CREATE
+ 247 : #define HAVE_PTHREAD 1
+ 248 : #endif
+ 249 :
+ 250 : /**
+ 251 : * Disable case check in Windows.
+ 252 : */
+ 253 : #ifdef _WIN32
+ 254 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD
+ 255 : #else
+ 256 : #define FNM_CASEINSENSITIVE_FOR_WIN 0
+ 257 : #endif
+ 258 :
+ 259 : #if HAVE_IO_H
+ 260 : #include <io.h>
261 : #endif
262 :
- 263 : /**
- 264 : * Enables lock file support.
- 265 : */
- 266 : #if HAVE_FLOCK && HAVE_FTRUNCATE
- 267 : #define HAVE_LOCKFILE 1
- 268 : #endif
- 269 :
- 270 : /**
- 271 : * Basic block position type.
- 272 : * With 32 bits and 128k blocks you can address 256 TB.
- 273 : */
- 274 : typedef uint32_t block_off_t;
+ 263 : #if HAVE_GETOPT_LONG
+ 264 : #define SWITCH_GETOPT_LONG(a, b) a
+ 265 : #else
+ 266 : #define SWITCH_GETOPT_LONG(a, b) b
+ 267 : #endif
+ 268 :
+ 269 : /**
+ 270 : * Enables lock file support.
+ 271 : */
+ 272 : #if HAVE_FLOCK && HAVE_FTRUNCATE
+ 273 : #define HAVE_LOCKFILE 1
+ 274 : #endif
275 :
276 : /**
- 277 : * Basic data position type.
- 278 : * It's signed as file size and offset are usually signed.
+ 277 : * Basic block position type.
+ 278 : * With 32 bits and 128k blocks you can address 256 TB.
279 : */
- 280 : typedef int64_t data_off_t;
+ 280 : typedef uint32_t block_off_t;
281 :
282 : /**
- 283 : * Includes specific support for Windows or Linux.
- 284 : */
- 285 : #ifdef __MINGW32__
- 286 : #include "mingw.h"
- 287 : #else
- 288 : #include "unix.h"
- 289 : #endif
- 290 :
- 291 : /**
- 292 : * Include list support to have tommy_node.
- 293 : */
- 294 : #include "tommyds/tommylist.h"
- 295 :
- 296 : /**
- 297 : * Another name for link() to avoid confusion with local variables called "link".
- 298 : */
- 299 12 : static inline int hardlink(const char* a, const char* b)
- 300 : {
- 301 12 : return link(a, b);
- 302 : }
- 303 :
- 304 : /**
- 305 : * Get the device UUID.
- 306 : * Return 0 on success.
- 307 : */
- 308 : int devuuid(uint64_t device, char* uuid, size_t size);
+ 283 : * Basic data position type.
+ 284 : * It's signed as file size and offset are usually signed.
+ 285 : */
+ 286 : typedef int64_t data_off_t;
+ 287 :
+ 288 : /**
+ 289 : * Includes specific support for Windows or Linux.
+ 290 : */
+ 291 : #ifdef __MINGW32__
+ 292 : #include "mingw.h"
+ 293 : #else
+ 294 : #include "unix.h"
+ 295 : #endif
+ 296 :
+ 297 : /**
+ 298 : * Include list support to have tommy_node.
+ 299 : */
+ 300 : #include "tommyds/tommylist.h"
+ 301 :
+ 302 : /**
+ 303 : * Another name for link() to avoid confusion with local variables called "link".
+ 304 : */
+ 305 12 : static inline int hardlink(const char* a, const char* b)
+ 306 : {
+ 307 12 : return link(a, b);
+ 308 : }
309 :
310 : /**
- 311 : * Physical offset not yet read.
- 312 : */
- 313 : #define FILEPHY_UNREAD_OFFSET 0
- 314 :
- 315 : /**
- 316 : * Special value returned when the file-system doesn't report any offset for unknown reason.
- 317 : */
- 318 : #define FILEPHY_UNREPORTED_OFFSET 1
- 319 :
- 320 : /**
- 321 : * Special value returned when the file doesn't have a real offset.
- 322 : * For example, because it's stored in the NTFS MFT.
+ 311 : * Get the device UUID.
+ 312 : * Return 0 on success.
+ 313 : */
+ 314 : int devuuid(uint64_t device, char* uuid, size_t size);
+ 315 :
+ 316 : /**
+ 317 : * Physical offset not yet read.
+ 318 : */
+ 319 : #define FILEPHY_UNREAD_OFFSET 0
+ 320 :
+ 321 : /**
+ 322 : * Special value returned when the file-system doesn't report any offset for unknown reason.
323 : */
- 324 : #define FILEPHY_WITHOUT_OFFSET 2
+ 324 : #define FILEPHY_UNREPORTED_OFFSET 1
325 :
326 : /**
- 327 : * Value indicating real offsets. All offsets greater or equal at this one are real.
- 328 : */
- 329 : #define FILEPHY_REAL_OFFSET 3
- 330 :
- 331 : /**
- 332 : * Get the physcal address of the specified file.
- 333 : * This is expected to be just a hint and not necessarily correct or unique.
- 334 : * Return 0 on success.
- 335 : */
- 336 : int filephy(const char* path, uint64_t size, uint64_t* physical);
- 337 :
- 338 : /**
- 339 : * Check if the underline file-system support persistent inodes.
- 340 : * Return -1 on error, 0 on success.
+ 327 : * Special value returned when the file doesn't have a real offset.
+ 328 : * For example, because it's stored in the NTFS MFT.
+ 329 : */
+ 330 : #define FILEPHY_WITHOUT_OFFSET 2
+ 331 :
+ 332 : /**
+ 333 : * Value indicating real offsets. All offsets greater or equal at this one are real.
+ 334 : */
+ 335 : #define FILEPHY_REAL_OFFSET 3
+ 336 :
+ 337 : /**
+ 338 : * Get the physcal address of the specified file.
+ 339 : * This is expected to be just a hint and not necessarily correct or unique.
+ 340 : * Return 0 on success.
341 : */
- 342 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space);
+ 342 : int filephy(const char* path, uint64_t size, uint64_t* physical);
343 :
344 : /**
- 345 : * Get the tick counter value.
- 346 : *
- 347 : * Note that the frequency is unspecified, because the time measure
- 348 : * is meant to be used to compare the ratio between usage times.
- 349 : */
- 350 : uint64_t tick(void);
- 351 :
- 352 : /**
- 353 : * Get the tick counter value in millisecond.
- 354 : */
- 355 : uint64_t tick_ms(void);
- 356 :
- 357 : /**
- 358 : * Initializes the system.
- 359 : */
- 360 : void os_init(int opt);
- 361 :
- 362 : /**
- 363 : * Deinitialize the system.
- 364 : */
- 365 : void os_done(void);
- 366 :
- 367 : /**
- 368 : * Abort the process with a stacktrace.
- 369 : */
- 370 : void os_abort(void) __noreturn;
- 371 :
- 372 : /**
- 373 : * Clear the screen.
- 374 : */
- 375 : void os_clear(void);
- 376 :
- 377 : /**
- 378 : * Log file.
- 379 : *
- 380 : * This stream if fully buffered.
- 381 : *
- 382 : * If no log file is selected, it's 0.
- 383 : */
- 384 : FILE* stdlog;
- 385 :
- 386 : /**
- 387 : * Exit codes for testing.
- 388 : */
- 389 : int exit_success;
- 390 : int exit_failure;
- 391 : int exit_sync_needed;
- 392 : #undef EXIT_SUCCESS
- 393 : #undef EXIT_FAILURE
- 394 : #define EXIT_SUCCESS exit_success
- 395 : #define EXIT_FAILURE exit_failure
- 396 : #define EXIT_SYNC_NEEDED exit_sync_needed
- 397 :
- 398 : /**
- 399 : * Fill memory with pseudo-random values.
- 400 : */
- 401 : int randomize(void* ptr, size_t size);
- 402 :
- 403 : /**
- 404 : * Standard SMART attributes.
- 405 : */
- 406 : #define SMART_START_STOP_COUNT 4
- 407 : #define SMART_REALLOCATED_SECTOR_COUNT 5
- 408 : #define SMART_POWER_ON_HOURS 9
- 409 : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190
- 410 : #define SMART_LOAD_CYCLE_COUNT 193
- 411 : #define SMART_TEMPERATURE_CELSIUS 194
- 412 :
- 413 : /**
- 414 : * Additional SMART attributes.
- 415 : */
- 416 : #define SMART_ERROR 256 /**< ATA Error count. */
- 417 : #define SMART_SIZE 257 /**< Size in bytes. */
- 418 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */
- 419 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */
- 420 :
- 421 : /**
- 422 : * SMART attributes count.
- 423 : */
- 424 : #define SMART_COUNT 260
- 425 :
- 426 : /**
- 427 : * Flags returned by smartctl.
- 428 : */
- 429 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */
- 430 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */
- 431 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */
- 432 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
- 433 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
- 434 : #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. */
- 435 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */
- 436 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
- 437 :
- 438 : /**
- 439 : * SMART max attribute length.
- 440 : */
- 441 : #define SMART_MAX 64
- 442 :
- 443 : /**
- 444 : * Value for unassigned SMART attribute.
- 445 : */
- 446 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL
- 447 :
- 448 : /**
- 449 : * Device info entry.
- 450 : */
- 451 : struct devinfo_struct {
- 452 : uint64_t device; /**< Device ID. */
- 453 : char name[PATH_MAX]; /**< Name of the disk. */
- 454 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */
- 455 : char smartctl[PATH_MAX]; /**< Options for smartctl. */
- 456 : char file[PATH_MAX]; /**< File device. */
- 457 : #ifdef _WIN32
- 458 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
- 459 : #endif
- 460 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */
- 461 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */
- 462 : char smart_serial[SMART_MAX]; /**< SMART serial number. */
- 463 : char smart_vendor[SMART_MAX]; /**< SMART vendor. */
- 464 : char smart_model[SMART_MAX]; /**< SMART model. */
- 465 : #if HAVE_PTHREAD
- 466 : pthread_t thread;
- 467 : #endif
- 468 : tommy_node node;
- 469 : };
- 470 : typedef struct devinfo_struct devinfo_t;
- 471 :
- 472 : #define DEVICE_LIST 0
- 473 : #define DEVICE_DOWN 1
- 474 : #define DEVICE_UP 2
- 475 : #define DEVICE_SMART 3
- 476 :
- 477 : /**
- 478 : * Query all the "high" level devices with the specified operation,
- 479 : * and produces a list of "low" level devices to operate on.
- 480 : *
- 481 : * The passed "low" device list must be already initialized.
- 482 : */
- 483 : int devquery(tommy_list* high, tommy_list* low, int operation, int others);
- 484 :
- 485 : #endif
- 486 :
+ 345 : * Check if the underline file-system support persistent inodes.
+ 346 : * Return -1 on error, 0 on success.
+ 347 : */
+ 348 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space);
+ 349 :
+ 350 : /**
+ 351 : * Get the tick counter value.
+ 352 : *
+ 353 : * Note that the frequency is unspecified, because the time measure
+ 354 : * is meant to be used to compare the ratio between usage times.
+ 355 : */
+ 356 : uint64_t tick(void);
+ 357 :
+ 358 : /**
+ 359 : * Get the tick counter value in millisecond.
+ 360 : */
+ 361 : uint64_t tick_ms(void);
+ 362 :
+ 363 : /**
+ 364 : * Initializes the system.
+ 365 : */
+ 366 : void os_init(int opt);
+ 367 :
+ 368 : /**
+ 369 : * Deinitialize the system.
+ 370 : */
+ 371 : void os_done(void);
+ 372 :
+ 373 : /**
+ 374 : * Abort the process with a stacktrace.
+ 375 : */
+ 376 : void os_abort(void) __noreturn;
+ 377 :
+ 378 : /**
+ 379 : * Clear the screen.
+ 380 : */
+ 381 : void os_clear(void);
+ 382 :
+ 383 : /**
+ 384 : * Log file.
+ 385 : *
+ 386 : * This stream if fully buffered.
+ 387 : *
+ 388 : * If no log file is selected, it's 0.
+ 389 : */
+ 390 : FILE* stdlog;
+ 391 :
+ 392 : /**
+ 393 : * Exit codes for testing.
+ 394 : */
+ 395 : int exit_success;
+ 396 : int exit_failure;
+ 397 : int exit_sync_needed;
+ 398 : #undef EXIT_SUCCESS
+ 399 : #undef EXIT_FAILURE
+ 400 : #define EXIT_SUCCESS exit_success
+ 401 : #define EXIT_FAILURE exit_failure
+ 402 : #define EXIT_SYNC_NEEDED exit_sync_needed
+ 403 :
+ 404 : /**
+ 405 : * Fill memory with pseudo-random values.
+ 406 : */
+ 407 : int randomize(void* ptr, size_t size);
+ 408 :
+ 409 : /**
+ 410 : * Standard SMART attributes.
+ 411 : */
+ 412 : #define SMART_START_STOP_COUNT 4
+ 413 : #define SMART_REALLOCATED_SECTOR_COUNT 5
+ 414 : #define SMART_POWER_ON_HOURS 9
+ 415 : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190
+ 416 : #define SMART_LOAD_CYCLE_COUNT 193
+ 417 : #define SMART_TEMPERATURE_CELSIUS 194
+ 418 :
+ 419 : /**
+ 420 : * Additional SMART attributes.
+ 421 : */
+ 422 : #define SMART_ERROR 256 /**< ATA Error count. */
+ 423 : #define SMART_SIZE 257 /**< Size in bytes. */
+ 424 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */
+ 425 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */
+ 426 :
+ 427 : /**
+ 428 : * SMART attributes count.
+ 429 : */
+ 430 : #define SMART_COUNT 260
+ 431 :
+ 432 : /**
+ 433 : * Flags returned by smartctl.
+ 434 : */
+ 435 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */
+ 436 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */
+ 437 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */
+ 438 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
+ 439 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
+ 440 : #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. */
+ 441 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */
+ 442 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
+ 443 :
+ 444 : /**
+ 445 : * SMART max attribute length.
+ 446 : */
+ 447 : #define SMART_MAX 64
+ 448 :
+ 449 : /**
+ 450 : * Value for unassigned SMART attribute.
+ 451 : */
+ 452 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL
+ 453 :
+ 454 : /**
+ 455 : * Device info entry.
+ 456 : */
+ 457 : struct devinfo_struct {
+ 458 : uint64_t device; /**< Device ID. */
+ 459 : char name[PATH_MAX]; /**< Name of the disk. */
+ 460 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */
+ 461 : char smartctl[PATH_MAX]; /**< Options for smartctl. */
+ 462 : char file[PATH_MAX]; /**< File device. */
+ 463 : #ifdef _WIN32
+ 464 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
+ 465 : #endif
+ 466 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */
+ 467 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */
+ 468 : char smart_serial[SMART_MAX]; /**< SMART serial number. */
+ 469 : char smart_vendor[SMART_MAX]; /**< SMART vendor. */
+ 470 : char smart_model[SMART_MAX]; /**< SMART model. */
+ 471 : #if HAVE_PTHREAD
+ 472 : pthread_t thread;
+ 473 : #endif
+ 474 : tommy_node node;
+ 475 : };
+ 476 : typedef struct devinfo_struct devinfo_t;
+ 477 :
+ 478 : #define DEVICE_LIST 0
+ 479 : #define DEVICE_DOWN 1
+ 480 : #define DEVICE_UP 2
+ 481 : #define DEVICE_SMART 3
+ 482 :
+ 483 : /**
+ 484 : * Query all the "high" level devices with the specified operation,
+ 485 : * and produces a list of "low" level devices to operate on.
+ 486 : *
+ 487 : * The passed "low" device list must be already initialized.
+ 488 : */
+ 489 : int devquery(tommy_list* high, tommy_list* low, int operation, int others);
+ 490 :
+ 491 : #endif
+ 492 :
diff --git a/cov/cmdline/rehash.c.func-sort-c.html b/cov/cmdline/rehash.c.func-sort-c.html
index 8a66d85e..a7888c53 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 84923317..091c105e 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 3d0d0126..d3f78e7d 100644
--- a/cov/cmdline/rehash.c.gcov.html
+++ b/cov/cmdline/rehash.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/scan.c.func-sort-c.html b/cov/cmdline/scan.c.func-sort-c.html
index ffed18f4..137bfc7d 100644
--- a/cov/cmdline/scan.c.func-sort-c.html
+++ b/cov/cmdline/scan.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -73,39 +73,39 @@
| scan_file_keep |
- 1025550 |
+ 1025552 |
| file_is_full_invalid_parity_and_stable |
- 1025550 |
+ 1025552 |
| dd_ino_compare |
- 103390 |
+ 103400 |
| scan_file_delayed_allocate |
- 101881 |
+ 101879 |
| scan_file_insert |
- 101881 |
+ 101879 |
| scan_file_allocate |
- 101881 |
+ 101879 |
| scan_file_refresh |
- 79194 |
+ 79192 |
| scan_file_remove |
- 57015 |
+ 57013 |
| scan_file_deallocate |
- 57015 |
+ 57013 |
| scan_link |
diff --git a/cov/cmdline/scan.c.func.html b/cov/cmdline/scan.c.func.html
index 28656181..78e78b2e 100644
--- a/cov/cmdline/scan.c.func.html
+++ b/cov/cmdline/scan.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| dd_ino_compare |
- 103390 |
+ 103400 |
| dd_name_compare |
@@ -77,7 +77,7 @@
| file_is_full_invalid_parity_and_stable |
- 1025550 |
+ 1025552 |
| scan_dir |
@@ -101,31 +101,31 @@
| scan_file_allocate |
- 101881 |
+ 101879 |
| scan_file_deallocate |
- 57015 |
+ 57013 |
| scan_file_delayed_allocate |
- 101881 |
+ 101879 |
| scan_file_insert |
- 101881 |
+ 101879 |
| scan_file_keep |
- 1025550 |
+ 1025552 |
| scan_file_refresh |
- 79194 |
+ 79192 |
| scan_file_remove |
- 57015 |
+ 57013 |
| scan_link |
diff --git a/cov/cmdline/scan.c.gcov.html b/cov/cmdline/scan.c.gcov.html
index 1e9ebb3c..43b28eee 100644
--- a/cov/cmdline/scan.c.gcov.html
+++ b/cov/cmdline/scan.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -220,42 +220,42 @@
158 : /**
159 : * Insert the specified file in the parity.
160 : */
- 161 101881 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 161 101879 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
162 : {
- 163 101881 : struct snapraid_state* state = scan->state;
- 164 101881 : struct snapraid_disk* disk = scan->disk;
+ 163 101879 : struct snapraid_state* state = scan->state;
+ 164 101879 : struct snapraid_disk* disk = scan->disk;
165 : block_off_t i;
166 : block_off_t parity_pos;
167 :
168 : /* state changed */
- 169 101881 : state->need_write = 1;
+ 169 101879 : state->need_write = 1;
170 :
171 : /* allocate the blocks of the file */
- 172 101881 : parity_pos = disk->first_free_block;
- 173 353073 : for (i = 0; i < file->blockmax; ++i) {
+ 172 101879 : parity_pos = disk->first_free_block;
+ 173 353147 : for (i = 0; i < file->blockmax; ++i) {
174 : struct snapraid_block* block;
175 : struct snapraid_block* over_block;
176 : snapraid_info info;
177 :
178 : /* increment the position until the first really free block */
- 179 1022715 : while (block_has_file(fs_par2block_find(disk, parity_pos)))
- 180 520331 : ++parity_pos;
+ 179 1022869 : while (block_has_file(fs_par2block_find(disk, parity_pos)))
+ 180 520333 : ++parity_pos;
181 :
182 : /* get block we are going to overwrite, if any */
- 183 251192 : over_block = fs_par2block_find(disk, parity_pos);
+ 183 251268 : over_block = fs_par2block_find(disk, parity_pos);
184 :
185 : /* deallocate it */
- 186 251192 : if (over_block != BLOCK_NULL)
- 187 95279 : fs_deallocate(disk, parity_pos);
+ 186 251268 : if (over_block != BLOCK_NULL)
+ 187 95355 : fs_deallocate(disk, parity_pos);
188 :
189 : /* get block specific info */
- 190 251192 : info = info_get(&state->infoarr, parity_pos);
+ 190 251268 : info = info_get(&state->infoarr, parity_pos);
191 :
192 : /* get the new block we are going to write */
- 193 251192 : block = fs_file2block_get(file, i);
+ 193 251268 : block = fs_file2block_get(file, i);
194 :
195 : /* if the file block already has an updated hash without rehash */
- 196 251192 : if (block_has_updated_hash(block) && !info_get_rehash(info)) {
+ 196 251268 : if (block_has_updated_hash(block) && !info_get_rehash(info)) {
197 : /* the only possible case is for REP blocks */
198 86215 : assert(block_state_get(block) == BLOCK_STATE_REP);
199 :
@@ -267,25 +267,25 @@
205 : unsigned over_state;
206 :
207 : /* convert to a CHG block */
- 208 164977 : block_state_set(block, BLOCK_STATE_CHG);
+ 208 165053 : block_state_set(block, BLOCK_STATE_CHG);
209 :
210 : /* state of the block we are going to overwrite */
- 211 164977 : over_state = block_state_get(over_block);
+ 211 165053 : over_state = block_state_get(over_block);
212 :
213 : /* if the block is an empty one */
- 214 164977 : if (over_state == BLOCK_STATE_EMPTY) {
+ 214 165053 : if (over_state == BLOCK_STATE_EMPTY) {
215 : /* the block was empty and filled with zeros */
216 : /* set the hash to the special ZERO value */
217 115543 : hash_zero_set(block->hash);
218 : } else {
219 : /* otherwise it's a DELETED one */
- 220 49434 : assert(over_state == BLOCK_STATE_DELETED);
+ 220 49510 : assert(over_state == BLOCK_STATE_DELETED);
221 :
222 : /* copy the past hash of the block */
- 223 49434 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE);
+ 223 49510 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE);
224 :
225 : /* if we have not already cleared the past hash */
- 226 49434 : if (!state->clear_past_hash) {
+ 226 49510 : if (!state->clear_past_hash) {
227 : /* in this case we don't know if the old state is still the one */
228 : /* stored inside the parity, because after an aborted sync, the parity */
229 : /* may be or may be not have been updated with the new data */
@@ -302,15 +302,15 @@
240 : }
241 :
242 : /* store in the disk map, after invalidating all the other blocks */
- 243 251192 : fs_allocate(disk, parity_pos, file, i);
+ 243 251268 : fs_allocate(disk, parity_pos, file, i);
244 :
245 : /* set the new free position */
- 246 251192 : disk->first_free_block = parity_pos + 1;
+ 246 251268 : disk->first_free_block = parity_pos + 1;
247 : }
248 :
249 : /* insert in the list of contained files */
- 250 101881 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
- 251 101881 : }
+ 250 101879 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
+ 251 101879 : }
252 :
253 : /**
254 : * Delete the specified file from the parity.
@@ -319,23 +319,23 @@
257 : * The file is then inserted in the deleted set, and it should not be deallocated,
258 : * as the parity still references it.
259 : */
- 260 57015 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 260 57013 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file)
261 : {
- 262 57015 : struct snapraid_state* state = scan->state;
- 263 57015 : struct snapraid_disk* disk = scan->disk;
+ 262 57013 : struct snapraid_state* state = scan->state;
+ 263 57013 : struct snapraid_disk* disk = scan->disk;
264 : block_off_t i;
265 :
266 : /* remove from the list of contained files */
- 267 57015 : tommy_list_remove_existing(&disk->filelist, &file->nodelist);
+ 267 57013 : tommy_list_remove_existing(&disk->filelist, &file->nodelist);
268 :
269 : /* state changed */
- 270 57015 : state->need_write = 1;
+ 270 57013 : state->need_write = 1;
271 :
272 : /* here we are supposed to adjust the ::first_free_block position */
273 : /* with the parity position we are deleting */
274 : /* but we also know that we do only delayed insert, after all the deletion, */
275 : /* so at this point ::first_free_block is always at 0, and we don't need to update it */
- 276 57015 : if (disk->first_free_block != 0) {
+ 276 57013 : if (disk->first_free_block != 0) {
277 : /* LCOV_EXCL_START */
278 : log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub);
279 : os_abort();
@@ -343,17 +343,17 @@
281 : }
282 :
283 : /* free all the blocks of the file */
- 284 197592 : for (i = 0; i < file->blockmax; ++i) {
- 285 140577 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 284 197666 : for (i = 0; i < file->blockmax; ++i) {
+ 285 140653 : struct snapraid_block* block = fs_file2block_get(file, i);
286 : unsigned block_state;
287 :
288 : /* in case we scan after an aborted sync, */
289 : /* we could get also intermediate states */
- 290 140577 : block_state = block_state_get(block);
- 291 140577 : switch (block_state) {
+ 290 140653 : block_state = block_state_get(block);
+ 291 140653 : switch (block_state) {
292 : case BLOCK_STATE_BLK :
293 : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */
- 294 35580 : break;
+ 294 35656 : break;
295 : case BLOCK_STATE_CHG :
296 : /* if we have not already cleared the past hash */
297 28040 : if (!state->clear_past_hash) {
@@ -383,23 +383,23 @@
321 : }
322 :
323 : /* set the block as deleted */
- 324 140577 : block_state_set(block, BLOCK_STATE_DELETED);
+ 324 140653 : block_state_set(block, BLOCK_STATE_DELETED);
325 : }
326 :
327 : /* mark the file as deleted */
- 328 57015 : file_flag_set(file, FILE_IS_DELETED);
+ 328 57013 : file_flag_set(file, FILE_IS_DELETED);
329 :
330 : /* insert it in the list of deleted blocks */
- 331 57015 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file);
- 332 57015 : }
+ 331 57013 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file);
+ 332 57013 : }
333 :
- 334 101881 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
+ 334 101879 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
335 : {
- 336 101881 : struct snapraid_state* state = scan->state;
- 337 101881 : struct snapraid_disk* disk = scan->disk;
+ 336 101879 : struct snapraid_state* state = scan->state;
+ 337 101879 : struct snapraid_disk* disk = scan->disk;
338 :
339 : /* if we sort for physical offsets we have to read them for new files */
- 340 101881 : if (state->opt.force_order == SORT_PHYSICAL
+ 340 101879 : if (state->opt.force_order == SORT_PHYSICAL
341 11432 : && file->physical == FILEPHY_UNREAD_OFFSET
342 : ) {
343 : char path_next[PATH_MAX];
@@ -415,30 +415,30 @@
353 : }
354 :
355 : /* insert in the delayed list */
- 356 101881 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file);
- 357 101881 : }
+ 356 101879 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file);
+ 357 101879 : }
358 :
359 : /**
360 : * Check if a file is completely formed of blocks with invalid parity,
361 : * and no rehash is tagged, and if it has at least one block.
362 : */
- 363 1025550 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
+ 363 1025552 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)
364 : {
365 : block_off_t i;
366 :
367 : /* with no block, it never has an invalid parity */
- 368 1025550 : if (file->blockmax == 0)
- 369 1439 : return 0;
+ 368 1025552 : if (file->blockmax == 0)
+ 369 1437 : return 0;
370 :
371 : /* check all blocks */
- 372 1080079 : for (i = 0; i < file->blockmax; ++i) {
+ 372 1080083 : for (i = 0; i < file->blockmax; ++i) {
373 : snapraid_info info;
- 374 1057392 : struct snapraid_block* block = fs_file2block_get(file, i);
+ 374 1057396 : struct snapraid_block* block = fs_file2block_get(file, i);
375 : block_off_t parity_pos;
376 :
377 : /* exclude blocks with parity */
- 378 1057392 : if (!block_has_invalid_parity(block))
- 379 1001424 : return 0;
+ 378 1057396 : if (!block_has_invalid_parity(block))
+ 379 1001428 : return 0;
380 :
381 : /*
382 : * Get the parity position.
@@ -525,7 +525,7 @@
463 : *
464 : * If this happens, we read also the physical offset, to avoid to read it later.
465 : */
- 466 79194 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)
+ 466 79192 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)
467 : {
468 : #if HAVE_LSTAT_SYNC
469 : struct snapraid_state* state = scan->state;
@@ -597,43 +597,43 @@
535 : (void)st;
536 : (void)physical;
537 : #endif
- 538 79194 : }
+ 538 79192 : }
539 :
540 : /**
541 : * Insert the file in the data set.
542 : */
- 543 101881 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)
+ 543 101879 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)
544 : {
- 545 101881 : struct snapraid_disk* disk = scan->disk;
+ 545 101879 : struct snapraid_disk* disk = scan->disk;
546 :
547 : /* insert the file in the containers */
- 548 101881 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
- 549 101881 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
- 550 101881 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
- 551 101881 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
+ 548 101879 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
+ 549 101879 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 550 101879 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
+ 551 101879 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
552 :
553 : /* delayed allocation of the parity */
- 554 101881 : scan_file_delayed_allocate(scan, file);
- 555 101881 : }
+ 554 101879 : scan_file_delayed_allocate(scan, file);
+ 555 101879 : }
556 :
557 : /**
558 : * Remove the file from the data set.
559 : *
560 : * File is then deleted.
561 : */
- 562 57015 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file)
+ 562 57013 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file)
563 : {
- 564 57015 : struct snapraid_disk* disk = scan->disk;
+ 564 57013 : struct snapraid_disk* disk = scan->disk;
565 :
566 : /* remove the file from the containers */
- 567 57015 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
- 568 56941 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
- 569 57015 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
- 570 57015 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
+ 567 57013 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
+ 568 56967 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 569 57013 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
+ 570 57013 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
571 :
572 : /* deallocate the file from the parity */
- 573 57015 : scan_file_deallocate(scan, file);
- 574 57015 : }
+ 573 57013 : scan_file_deallocate(scan, file);
+ 574 57013 : }
575 :
576 : /**
577 : * Keep the file as it's (or with only a name/inode modification).
@@ -646,12 +646,12 @@
584 : * This could happen after a failed sync, when some other files are deleted,
585 : * and then new ones can be moved backward to fill the hole created.
586 : */
- 587 1025550 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file)
+ 587 1025552 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file)
588 : {
- 589 1025550 : struct snapraid_disk* disk = scan->disk;
+ 589 1025552 : struct snapraid_disk* disk = scan->disk;
590 :
591 : /* if the file is full invalid, schedule a reinsert at later stage */
- 592 1025550 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {
+ 592 1025552 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {
593 22687 : struct snapraid_file* copy = file_dup(file);
594 :
595 : /* remove the file */
@@ -660,7 +660,7 @@
598 : /* reinsert the copy in the delayed list */
599 22687 : scan_file_insert(scan, copy);
600 : }
- 601 1025550 : }
+ 601 1025552 : }
602 :
603 : /**
604 : * Process a file.
@@ -717,17 +717,17 @@
655 : /* identify moved files with past inodes and hardlinks with the new inodes */
656 1104939 : if (file) {
657 : /* check if the file is not changed */
- 658 943901 : if (file->size == st->st_size
- 659 935613 : && file->mtime_sec == st->st_mtime
- 660 932556 : && (file->mtime_nsec == STAT_NSEC(st)
+ 658 945290 : if (file->size == st->st_size
+ 659 929850 : && file->mtime_sec == st->st_mtime
+ 660 926844 : && (file->mtime_nsec == STAT_NSEC(st)
661 : /* always accept the stored value if it's STAT_NSEC_INVALID */
662 : /* it happens when upgrading from an old version of SnapRAID */
663 : /* not yet supporting the nanosecond field */
- 664 1 : || file->mtime_nsec == STAT_NSEC_INVALID
+ 664 6 : || file->mtime_nsec == STAT_NSEC_INVALID
665 : )
666 : ) {
667 : /* check if multiple files have the same inode */
- 668 932555 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 668 926838 : if (file_flag_has(file, FILE_IS_PRESENT)) {
669 : #if HAVE_STRUCT_STAT_ST_NLINK
670 195 : if (st->st_nlink <= 1) {
671 : /* LCOV_EXCL_START */
@@ -742,11 +742,11 @@
680 : }
681 :
682 : /* mark as present */
- 683 932360 : file_flag_set(file, FILE_IS_PRESENT);
+ 683 926643 : file_flag_set(file, FILE_IS_PRESENT);
684 :
685 : /* update the nanoseconds mtime only if different */
686 : /* to avoid unneeded updates */
- 687 932360 : if (file->mtime_nsec == STAT_NSEC_INVALID
+ 687 926643 : if (file->mtime_nsec == STAT_NSEC_INVALID
688 0 : && STAT_NSEC(st) != file->mtime_nsec
689 : ) {
690 0 : file->mtime_nsec = STAT_NSEC(st);
@@ -755,7 +755,7 @@
693 0 : state->need_write = 1;
694 : }
695 :
- 696 932360 : if (strcmp(file->sub, sub) != 0) {
+ 696 926643 : if (strcmp(file->sub, sub) != 0) {
697 : /* if the path is different, it means a moved file with the same inode */
698 155 : ++scan->count_move;
699 :
@@ -777,18 +777,18 @@
715 155 : state->need_write = 1;
716 : } else {
717 : /* otherwise it's equal */
- 718 932205 : ++scan->count_equal;
+ 718 926488 : ++scan->count_equal;
719 :
- 720 932205 : if (state->opt.gui) {
+ 720 926488 : if (state->opt.gui) {
721 22611 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
722 : }
723 : }
724 :
725 : /* mark the file as kept */
- 726 932360 : scan_file_keep(scan, file);
+ 726 926643 : scan_file_keep(scan, file);
727 :
728 : /* nothing more to do */
- 729 932360 : return;
+ 729 926643 : return;
730 : }
731 :
732 : /* here the file matches the inode, but not the other info */
@@ -797,7 +797,7 @@
735 : /* or a file-system with not persistent inodes */
736 :
737 : /* for sure it cannot be already present */
- 738 11346 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 738 18452 : if (file_flag_has(file, FILE_IS_PRESENT)) {
739 : /* LCOV_EXCL_START */
740 : 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);
741 : os_abort();
@@ -810,44 +810,44 @@
748 : /* otherwise, it will get removed */
749 :
750 : /* remove from the inode set */
- 751 11346 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 751 18452 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
752 :
753 : /* clear the inode */
754 : /* this is not really needed for correct functionality */
755 : /* because we are going to set FILE_IS_WITHOUT_INODE */
756 : /* but it's easier for debugging to have invalid inodes set to 0 */
- 757 11346 : file->inode = 0;
+ 757 18452 : file->inode = 0;
758 :
759 : /* mark as missing inode */
- 760 11346 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
+ 760 18452 : file_flag_set(file, FILE_IS_WITHOUT_INODE);
761 :
762 : /* go further to find it by name */
763 : }
764 :
765 : /* initialize for later overwrite */
- 766 172384 : is_file_reported = 0;
- 767 172384 : is_original_file_size_different_than_zero = 0;
+ 766 178101 : is_file_reported = 0;
+ 767 178101 : is_original_file_size_different_than_zero = 0;
768 :
769 : /* then try finding it by name */
- 770 172384 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub));
+ 770 178101 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub));
771 :
772 : /* keep track if the file already exists */
- 773 172384 : is_file_already_present = file != 0;
+ 773 178101 : is_file_already_present = file != 0;
774 :
- 775 172384 : if (is_file_already_present) {
+ 775 178101 : if (is_file_already_present) {
776 : /* if the file is without an inode */
- 777 97871 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) {
+ 777 103588 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) {
778 : /* set it now */
- 779 11286 : file->inode = st->st_ino;
+ 779 18420 : file->inode = st->st_ino;
780 :
781 : /* insert in the set */
- 782 11286 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 782 18420 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
783 :
784 : /* unmark as missing inode */
- 785 11286 : file_flag_clear(file, FILE_IS_WITHOUT_INODE);
+ 785 18420 : file_flag_clear(file, FILE_IS_WITHOUT_INODE);
786 : } else {
787 : /* here the inode has to be different, otherwise we would have found it before */
- 788 86585 : if (file->inode == st->st_ino) {
+ 788 85168 : if (file->inode == st->st_ino) {
789 : /* LCOV_EXCL_START */
790 : log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub);
791 : os_abort();
@@ -856,7 +856,7 @@
794 : }
795 :
796 : /* for sure it cannot be already present */
- 797 97871 : if (file_flag_has(file, FILE_IS_PRESENT)) {
+ 797 103588 : if (file_flag_has(file, FILE_IS_PRESENT)) {
798 : /* LCOV_EXCL_START */
799 : log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub);
800 : os_abort();
@@ -864,9 +864,9 @@
802 : }
803 :
804 : /* check if the file is not changed */
- 805 97871 : if (file->size == st->st_size
- 806 97275 : && file->mtime_sec == st->st_mtime
- 807 93190 : && (file->mtime_nsec == STAT_NSEC(st)
+ 805 103588 : if (file->size == st->st_size
+ 806 102992 : && file->mtime_sec == st->st_mtime
+ 807 98909 : && (file->mtime_nsec == STAT_NSEC(st)
808 : /* always accept the stored value if it's STAT_NSEC_INVALID */
809 : /* it happens when upgrading from an old version of SnapRAID */
810 : /* not yet supporting the nanosecond field */
@@ -874,11 +874,11 @@
812 : )
813 : ) {
814 : /* mark as present */
- 815 93190 : file_flag_set(file, FILE_IS_PRESENT);
+ 815 98909 : file_flag_set(file, FILE_IS_PRESENT);
816 :
817 : /* update the nano seconds mtime only if different */
818 : /* to avoid unneeded updates */
- 819 93190 : if (file->mtime_nsec == STAT_NSEC_INVALID
+ 819 98909 : if (file->mtime_nsec == STAT_NSEC_INVALID
820 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID
821 : ) {
822 0 : file->mtime_nsec = STAT_NSEC(st);
@@ -888,30 +888,30 @@
826 : }
827 :
828 : /* if when processing the disk we used the past inodes values */
- 829 93190 : if (has_past_inodes) {
+ 829 98909 : if (has_past_inodes) {
830 : /* if persistent inodes are supported, we are sure that the inode number */
831 : /* is now different, because otherwise the file would have been found */
832 : /* when searching by inode. */
833 : /* if the inode is different, it means a rewritten file with the same path */
834 : /* like when restoring a backup that restores also the timestamp */
- 835 93176 : ++scan->count_restore;
+ 835 98895 : ++scan->count_restore;
836 :
- 837 93176 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
- 838 93176 : if (is_diff) {
+ 837 98895 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
+ 838 98895 : if (is_diff) {
839 0 : printf("restore %s\n", fmt_term(disk, sub, esc_buffer));
840 : }
841 :
842 : /* remove from the inode set */
- 843 93176 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
+ 843 98895 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
844 :
845 : /* save the new inode */
- 846 93176 : file->inode = st->st_ino;
+ 846 98895 : file->inode = st->st_ino;
847 :
848 : /* reinsert in the inode set */
- 849 93176 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 849 98895 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
850 :
851 : /* we have to save the new inode */
- 852 93176 : state->need_write = 1;
+ 852 98895 : state->need_write = 1;
853 : } else {
854 : /* otherwise it's the case of not persistent inode, where doesn't */
855 : /* matter if the inode is different or equal, because they have no */
@@ -924,24 +924,24 @@
862 : }
863 :
864 : /* mark the file as kept */
- 865 93190 : scan_file_keep(scan, file);
+ 865 98909 : scan_file_keep(scan, file);
866 :
867 : /* nothing more to do */
- 868 93190 : return;
+ 868 98909 : return;
869 : }
870 :
871 : /* here if the file is changed but with the correct name */
872 :
873 : /* save the info for later printout */
- 874 4681 : file_already_present_size = file->size;
- 875 4681 : file_already_present_mtime_sec = file->mtime_sec;
- 876 4681 : file_already_present_mtime_nsec = file->mtime_nsec;
+ 874 4679 : file_already_present_size = file->size;
+ 875 4679 : file_already_present_mtime_sec = file->mtime_sec;
+ 876 4679 : file_already_present_mtime_nsec = file->mtime_nsec;
877 :
878 : /* keep track if the original file was not of zero size */
- 879 4681 : is_original_file_size_different_than_zero = file->size != 0;
+ 879 4679 : is_original_file_size_different_than_zero = file->size != 0;
880 :
881 : /* remove it, and continue to insert it again */
- 882 4681 : scan_file_remove(scan, file);
+ 882 4679 : scan_file_remove(scan, file);
883 :
884 : /* and continue to insert it again */
885 : } else {
@@ -953,13 +953,13 @@
891 : /* refresh the info, to ensure that they are synced, */
892 : /* note that we refresh only the info of the new or modified files */
893 : /* because this is slow operation */
- 894 79194 : scan_file_refresh(scan, sub, st, &physical);
+ 894 79192 : scan_file_refresh(scan, sub, st, &physical);
895 :
896 : #ifndef _WIN32
897 : /* do a safety check to ensure that the common ext4 case of zeroing */
898 : /* the size of a file after a crash doesn't propagate to the backup */
899 : /* this check is specific for Linux, so we disable it on Windows */
- 900 79194 : if (is_original_file_size_different_than_zero && st->st_size == 0) {
+ 900 79192 : if (is_original_file_size_different_than_zero && st->st_size == 0) {
901 0 : if (!state->opt.force_zero) {
902 : /* LCOV_EXCL_START */
903 : log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub);
@@ -978,33 +978,33 @@
916 : #endif
917 :
918 : /* insert it */
- 919 79194 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical);
+ 919 79192 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical);
920 :
921 : /* mark it as present */
- 922 79194 : file_flag_set(file, FILE_IS_PRESENT);
+ 922 79192 : file_flag_set(file, FILE_IS_PRESENT);
923 :
924 : /* if copy detection is enabled */
925 : /* note that the copy detection is tried also for updated files */
926 : /* this makes sense because it may happen to have two different copies */
927 : /* of the same file, and we move the right one over the wrong one */
928 : /* in such case we have a "copy" over an "update" */
- 929 79194 : if (!state->opt.force_nocopy) {
- 930 79194 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
+ 929 79192 : if (!state->opt.force_nocopy) {
+ 930 79192 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
931 :
932 : /* search for a file with the same name and stamp in all the disks */
- 933 423410 : for (i = state->disklist; i != 0; i = i->next) {
- 934 367852 : struct snapraid_disk* other_disk = i->data;
+ 933 423396 : for (i = state->disklist; i != 0; i = i->next) {
+ 934 367840 : struct snapraid_disk* other_disk = i->data;
935 : struct snapraid_file* other_file;
936 :
937 : /* if the nanosecond part of the time stamp is valid, search */
938 : /* for name and stamp, otherwise for path and stamp */
- 939 367852 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
- 940 367744 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
+ 939 367840 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
+ 940 367732 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
941 : else
942 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash);
943 :
944 : /* if found, and it's a fully hashed file */
- 945 367852 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
+ 945 367840 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
946 : /* assume that the file is a copy, and reuse the hash */
947 23636 : file_copy(other_file, file);
948 :
@@ -1027,16 +1027,16 @@
965 :
966 : /* if not yet reported, do it now */
967 : /* we postpone this to avoid to print two times the copied files */
- 968 79194 : if (!is_file_reported) {
- 969 55558 : if (is_file_already_present) {
- 970 4681 : ++scan->count_change;
+ 968 79192 : if (!is_file_reported) {
+ 969 55556 : if (is_file_already_present) {
+ 970 4679 : ++scan->count_change;
971 :
- 972 14043 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer),
+ 972 14037 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer),
973 : (uint64_t)file_already_present_size, (uint64_t)file_already_present_mtime_sec, file_already_present_mtime_nsec,
- 974 9362 : (uint64_t)file->size, (uint64_t)file->mtime_sec, file->mtime_nsec
+ 974 9358 : (uint64_t)file->size, (uint64_t)file->mtime_sec, file->mtime_nsec
975 : );
976 :
- 977 4681 : if (is_diff) {
+ 977 4679 : if (is_diff) {
978 118 : printf("update %s\n", fmt_term(disk, sub, esc_buffer));
979 : }
980 : } else {
@@ -1050,7 +1050,7 @@
988 : }
989 :
990 : /* insert the file in the delayed list */
- 991 79194 : scan_file_insert(scan, file);
+ 991 79192 : scan_file_insert(scan, file);
992 : }
993 :
994 : /**
@@ -1143,15 +1143,15 @@
1081 : };
1082 :
1083 : #if HAVE_STRUCT_DIRENT_D_INO
- 1084 103390 : static int dd_ino_compare(const void* void_a, const void* void_b)
+ 1084 103400 : static int dd_ino_compare(const void* void_a, const void* void_b)
1085 : {
- 1086 103390 : const struct dirent_sorted* a = void_a;
- 1087 103390 : const struct dirent_sorted* b = void_b;
+ 1086 103400 : const struct dirent_sorted* a = void_a;
+ 1087 103400 : const struct dirent_sorted* b = void_b;
1088 :
- 1089 103390 : if (a->d_ino < b->d_ino)
- 1090 49438 : return -1;
- 1091 53952 : if (a->d_ino > b->d_ino)
- 1092 53952 : return 1;
+ 1089 103400 : if (a->d_ino < b->d_ino)
+ 1090 49432 : return -1;
+ 1091 53968 : if (a->d_ino > b->d_ino)
+ 1092 53968 : return 1;
1093 :
1094 0 : return 0;
1095 : }
@@ -1584,14 +1584,14 @@
1522 :
1523 : /* check for removed files */
1524 575 : node = disk->filelist;
- 1525 1033660 : while (node) {
- 1526 1032510 : struct snapraid_file* file = node->data;
+ 1525 1033662 : while (node) {
+ 1526 1032512 : struct snapraid_file* file = node->data;
1527 :
1528 : /* next node */
- 1529 1032510 : node = node->next;
+ 1529 1032512 : node = node->next;
1530 :
1531 : /* remove if not present */
- 1532 1032510 : if (!file_flag_has(file, FILE_IS_PRESENT)) {
+ 1532 1032512 : if (!file_flag_has(file, FILE_IS_PRESENT)) {
1533 29647 : ++scan->count_remove;
1534 :
1535 29647 : log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
@@ -1664,11 +1664,11 @@
1602 575 : phy_dup = 0;
1603 575 : phy_last = FILEPHY_UNREAD_OFFSET;
1604 575 : phy_file_last = 0;
- 1605 103031 : while (node) {
- 1606 101881 : struct snapraid_file* file = node->data;
+ 1605 103029 : while (node) {
+ 1606 101879 : struct snapraid_file* file = node->data;
1607 :
1608 : /* if the file is not empty, count duplicate physical offsets */
- 1609 101881 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {
+ 1609 101879 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {
1610 11418 : if (phy_file_last != 0 && file->physical == phy_last
1611 : /* files without offset are expected to have duplicates */
1612 0 : && phy_last != FILEPHY_WITHOUT_OFFSET
@@ -1686,10 +1686,10 @@
1624 : }
1625 :
1626 : /* next node */
- 1627 101881 : node = node->next;
+ 1627 101879 : node = node->next;
1628 :
1629 : /* insert in the parity */
- 1630 101881 : scan_file_allocate(scan, file);
+ 1630 101879 : scan_file_allocate(scan, file);
1631 : }
1632 :
1633 : /* mark the disk without reliable physical offset if it has duplicates */
diff --git a/cov/cmdline/scrub.c.func-sort-c.html b/cov/cmdline/scrub.c.func-sort-c.html
index 2a8c6b02..3037f874 100644
--- a/cov/cmdline/scrub.c.func-sort-c.html
+++ b/cov/cmdline/scrub.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| scrub_parity_reader |
- 168180 |
+ 168175 |
| scrub_data_reader |
- 168176 |
+ 168095 |
| block_is_enabled |
diff --git a/cov/cmdline/scrub.c.func.html b/cov/cmdline/scrub.c.func.html
index 9e501fea..ce569665 100644
--- a/cov/cmdline/scrub.c.func.html
+++ b/cov/cmdline/scrub.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -69,11 +69,11 @@
| scrub_data_reader |
- 168176 |
+ 168095 |
| scrub_parity_reader |
- 168180 |
+ 168175 |
| state_scrub |
diff --git a/cov/cmdline/scrub.c.gcov.html b/cov/cmdline/scrub.c.gcov.html
index c01a6687..d1db3045 100644
--- a/cov/cmdline/scrub.c.gcov.html
+++ b/cov/cmdline/scrub.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -164,45 +164,45 @@
102 21730 : return 1;
103 : }
104 :
- 105 168176 : static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
+ 105 168095 : static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
106 : {
- 107 168176 : struct snapraid_io* io = worker->io;
- 108 168176 : struct snapraid_state* state = io->state;
- 109 168176 : struct snapraid_handle* handle = worker->handle;
- 110 168176 : struct snapraid_disk* disk = handle->disk;
- 111 168176 : block_off_t blockcur = task->position;
- 112 168176 : unsigned char* buffer = task->buffer;
+ 107 168095 : struct snapraid_io* io = worker->io;
+ 108 168095 : struct snapraid_state* state = io->state;
+ 109 168095 : struct snapraid_handle* handle = worker->handle;
+ 110 168095 : struct snapraid_disk* disk = handle->disk;
+ 111 168095 : block_off_t blockcur = task->position;
+ 112 168095 : unsigned char* buffer = task->buffer;
113 : int ret;
114 : char esc_buffer[ESC_MAX];
115 :
116 : /* if the disk position is not used */
- 117 168176 : if (!disk) {
+ 117 168095 : if (!disk) {
118 : /* use an empty block */
119 0 : memset(buffer, 0, state->block_size);
120 0 : task->state = TASK_STATE_DONE;
- 121 1585 : return;
+ 121 1584 : return;
122 : }
123 :
124 : /* get the block */
- 125 168176 : task->block = fs_par2block_find(disk, blockcur);
+ 125 168095 : task->block = fs_par2block_find(disk, blockcur);
126 :
127 : /* if the block is not used */
- 128 168151 : if (!block_has_file(task->block)) {
+ 128 168015 : if (!block_has_file(task->block)) {
129 : /* use an empty block */
- 130 1585 : memset(buffer, 0, state->block_size);
- 131 1585 : task->state = TASK_STATE_DONE;
- 132 1585 : return;
+ 130 1584 : memset(buffer, 0, state->block_size);
+ 131 1584 : task->state = TASK_STATE_DONE;
+ 132 1584 : return;
133 : }
134 :
135 : /* get the file of this block */
- 136 166552 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
+ 136 166341 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
137 :
138 : /* if the file is different than the current one, close it */
- 139 166584 : if (handle->file != 0 && handle->file != task->file) {
+ 139 166530 : if (handle->file != 0 && handle->file != task->file) {
140 : /* keep a pointer at the file we are going to close for error reporting */
- 141 78061 : struct snapraid_file* report = handle->file;
- 142 78061 : ret = handle_close(handle);
- 143 78037 : if (ret == -1) {
+ 141 78070 : struct snapraid_file* report = handle->file;
+ 142 78070 : ret = handle_close(handle);
+ 143 77914 : if (ret == -1) {
144 : /* LCOV_EXCL_START */
145 : /* This one is really an unexpected error, because we are only reading */
146 : /* and closing a descriptor should never fail */
@@ -225,8 +225,8 @@
163 : }
164 : }
165 :
- 166 166560 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
- 167 166583 : if (ret == -1) {
+ 166 166374 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
+ 167 165524 : if (ret == -1) {
168 0 : if (errno == EIO) {
169 : /* LCOV_EXCL_START */
170 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
@@ -244,9 +244,9 @@
182 : }
183 :
184 : /* check if the file is changed */
- 185 166583 : if (handle->st.st_size != task->file->size
- 186 166587 : || handle->st.st_mtime != task->file->mtime_sec
- 187 160985 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec
+ 185 165524 : if (handle->st.st_size != task->file->size
+ 186 165815 : || handle->st.st_mtime != task->file->mtime_sec
+ 187 160635 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec
188 : /* don't check the inode to support filesystem without persistent inodes */
189 : ) {
190 : /* report that the block and the file are not synced */
@@ -258,8 +258,8 @@
196 : /* from the last sync, as we are expected to return errors if running */
197 : /* in an unsynced array. This is just like the check command. */
198 :
- 199 166583 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
- 200 166507 : if (task->read_size == -1) {
+ 199 165524 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
+ 200 166073 : if (task->read_size == -1) {
201 0 : if (errno == EIO) {
202 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
203 0 : log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
@@ -273,24 +273,24 @@
211 : }
212 :
213 : /* store the path of the opened file */
- 214 166507 : pathcpy(task->path, sizeof(task->path), handle->path);
+ 214 166073 : pathcpy(task->path, sizeof(task->path), handle->path);
215 :
- 216 166554 : task->state = TASK_STATE_DONE;
+ 216 165226 : task->state = TASK_STATE_DONE;
217 : }
218 :
- 219 168180 : static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task)
+ 219 168175 : static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task)
220 : {
- 221 168180 : struct snapraid_io* io = worker->io;
- 222 168180 : struct snapraid_state* state = io->state;
- 223 168180 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
- 224 168180 : unsigned level = parity_handle->level;
- 225 168180 : block_off_t blockcur = task->position;
- 226 168180 : unsigned char* buffer = task->buffer;
+ 221 168175 : struct snapraid_io* io = worker->io;
+ 222 168175 : struct snapraid_state* state = io->state;
+ 223 168175 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
+ 224 168175 : unsigned level = parity_handle->level;
+ 225 168175 : block_off_t blockcur = task->position;
+ 226 168175 : unsigned char* buffer = task->buffer;
227 : int ret;
228 :
229 : /* read the parity */
- 230 168180 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
- 231 168156 : if (ret == -1) {
+ 230 168175 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
+ 231 168065 : if (ret == -1) {
232 0 : if (errno == EIO) {
233 0 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
234 0 : log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur);
@@ -303,7 +303,7 @@
241 0 : return;
242 : }
243 :
- 244 168156 : task->state = TASK_STATE_DONE;
+ 244 168065 : task->state = TASK_STATE_DONE;
245 : }
246 :
247 11 : static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax, struct snapraid_plan* plan, time_t now)
@@ -535,14 +535,14 @@
473 166607 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
474 920 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE);
475 :
- 476 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff);
+ 476 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8);
477 :
478 : /* it's a silent error only if we are dealing with synced files */
479 920 : if (file_is_unsynced) {
480 0 : ++error;
481 0 : error_on_this_block = 1;
482 : } else {
- 483 920 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", task->path, file_pos, diff);
+ 483 920 : log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE*8);
484 920 : ++silent_error;
485 920 : silent_error_on_this_block = 1;
486 : }
@@ -628,14 +628,14 @@
566 162672 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) {
567 0 : unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size);
568 :
- 569 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", blockcur, lev_config_name(l), diff);
+ 569 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size*8);
570 :
571 : /* it's a silent error only if we are dealing with synced blocks */
572 0 : if (block_is_unsynced) {
573 0 : ++error;
574 0 : error_on_this_block = 1;
575 : } else {
- 576 0 : log_fatal("Data error in parity '%s' at position '%u', diff bits %u\n", lev_config_name(l), blockcur, diff);
+ 576 0 : log_fatal("Data error in parity '%s' at position '%u', diff bits %u/%u\n", lev_config_name(l), blockcur, diff, state->block_size*8);
577 0 : ++silent_error;
578 0 : silent_error_on_this_block = 1;
579 : }
@@ -880,12 +880,12 @@
818 : /* output the info map */
819 11 : i = 0;
820 11 : log_tag("info_count:%u\n", count);
- 821 45 : while (i < count) {
- 822 23 : unsigned j = i + 1;
- 823 56108 : while (j < count && timemap[i] == timemap[j])
- 824 56062 : ++j;
- 825 23 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i);
- 826 23 : i = j;
+ 821 44 : while (i < count) {
+ 822 22 : unsigned j = i + 1;
+ 823 56107 : while (j < count && timemap[i] == timemap[j])
+ 824 56063 : ++j;
+ 825 22 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i);
+ 826 22 : i = j;
827 : }
828 :
829 : /* compute the limits from count/recentlimit */
diff --git a/cov/cmdline/search.c.func-sort-c.html b/cov/cmdline/search.c.func-sort-c.html
index 031e5215..8a0c9c3b 100644
--- a/cov/cmdline/search.c.func-sort-c.html
+++ b/cov/cmdline/search.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| search_file |
- 1843968 |
+ 1843727 |
| search_file_free |
- 1843968 |
+ 1843727 |
| state_search_fetch |
- 638616 |
+ 639060 |
| search_file_compare |
- 20133 |
+ 20106 |
| search_dir |
diff --git a/cov/cmdline/search.c.func.html b/cov/cmdline/search.c.func.html
index 9631a1e2..4648f7f6 100644
--- a/cov/cmdline/search.c.func.html
+++ b/cov/cmdline/search.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,15 +65,15 @@
| search_file |
- 1843968 |
+ 1843727 |
| search_file_compare |
- 20133 |
+ 20106 |
| search_file_free |
- 1843968 |
+ 1843727 |
| state_search |
@@ -85,7 +85,7 @@
| state_search_fetch |
- 638616 |
+ 639060 |
diff --git a/cov/cmdline/search.c.gcov.html b/cov/cmdline/search.c.gcov.html
index 3485994f..328ba9d5 100644
--- a/cov/cmdline/search.c.gcov.html
+++ b/cov/cmdline/search.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -85,27 +85,27 @@
23 : /****************************************************************************/
24 : /* search */
25 :
- 26 1843968 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec)
+ 26 1843727 : 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 1843968 : file = malloc_nofail(sizeof(struct snapraid_search_file));
- 32 1843968 : file->path = strdup_nofail(path);
- 33 1843968 : file->size = size;
- 34 1843968 : file->mtime_sec = mtime_sec;
- 35 1843968 : file->mtime_nsec = mtime_nsec;
+ 31 1843727 : file = malloc_nofail(sizeof(struct snapraid_search_file));
+ 32 1843727 : file->path = strdup_nofail(path);
+ 33 1843727 : file->size = size;
+ 34 1843727 : file->mtime_sec = mtime_sec;
+ 35 1843727 : file->mtime_nsec = mtime_nsec;
36 :
- 37 1843968 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
+ 37 1843727 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);
38 :
- 39 1843968 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash);
- 40 1843968 : }
+ 39 1843727 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash);
+ 40 1843727 : }
41 :
- 42 1843968 : void search_file_free(struct snapraid_search_file* file)
+ 42 1843727 : void search_file_free(struct snapraid_search_file* file)
43 : {
- 44 1843968 : free(file->path);
- 45 1843968 : free(file);
- 46 1843968 : }
+ 44 1843727 : free(file->path);
+ 45 1843727 : free(file);
+ 46 1843727 : }
47 :
48 : struct search_file_compare_arg {
49 : const struct snapraid_state* state;
@@ -117,29 +117,29 @@
55 : int prevhash;
56 : };
57 :
- 58 20133 : int search_file_compare(const void* void_arg, const void* void_data)
+ 58 20106 : int search_file_compare(const void* void_arg, const void* void_data)
59 : {
- 60 20133 : const struct search_file_compare_arg* arg = void_arg;
- 61 20133 : const struct snapraid_search_file* file = void_data;
- 62 20133 : const struct snapraid_state* state = arg->state;
+ 60 20106 : const struct search_file_compare_arg* arg = void_arg;
+ 61 20106 : const struct snapraid_search_file* file = void_data;
+ 62 20106 : const struct snapraid_state* state = arg->state;
63 : unsigned char buffer_hash[HASH_MAX];
- 64 20133 : const char* path = file->path;
+ 64 20106 : const char* path = file->path;
65 : int f;
66 : ssize_t ret;
67 :
68 : /* compare file info */
- 69 20133 : if (arg->file->size != file->size)
+ 69 20106 : if (arg->file->size != file->size)
70 0 : return -1;
71 :
- 72 20133 : if (arg->file->mtime_sec != file->mtime_sec)
+ 72 20106 : if (arg->file->mtime_sec != file->mtime_sec)
73 0 : return -1;
74 :
- 75 20133 : if (arg->file->mtime_nsec != file->mtime_nsec)
+ 75 20106 : if (arg->file->mtime_nsec != file->mtime_nsec)
76 0 : return -1;
77 :
78 : /* read the block and compare the hash */
- 79 20133 : f = open(path, O_RDONLY | O_BINARY);
- 80 20133 : if (f == -1) {
+ 79 20106 : f = open(path, O_RDONLY | O_BINARY);
+ 80 20106 : if (f == -1) {
81 : /* LCOV_EXCL_START */
82 : if (errno == ENOENT) {
83 : log_fatal("DANGER! file '%s' disappeared.\n", path);
@@ -151,16 +151,16 @@
89 : /* LCOV_EXCL_STOP */
90 : }
91 :
- 92 20133 : ret = pread(f, arg->buffer, arg->read_size, arg->offset);
- 93 20133 : if (ret < 0 || (unsigned)ret != arg->read_size) {
+ 92 20106 : ret = pread(f, arg->buffer, arg->read_size, arg->offset);
+ 93 20106 : if (ret < 0 || (unsigned)ret != arg->read_size) {
94 : /* LCOV_EXCL_START */
95 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno));
96 : exit(EXIT_FAILURE);
97 : /* LCOV_EXCL_STOP */
98 : }
99 :
- 100 20133 : ret = close(f);
- 101 20133 : if (ret != 0) {
+ 100 20106 : ret = close(f);
+ 101 20106 : if (ret != 0) {
102 : /* LCOV_EXCL_START */
103 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno));
104 : exit(EXIT_FAILURE);
@@ -168,14 +168,14 @@
106 : }
107 :
108 : /* compute the hash */
- 109 20133 : if (arg->prevhash)
+ 109 20106 : if (arg->prevhash)
110 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size);
111 : else
- 112 20133 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size);
+ 112 20106 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size);
113 :
114 : /* check if the hash is matching */
- 115 20133 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0)
- 116 2223 : return -1;
+ 115 20106 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0)
+ 116 2196 : return -1;
117 :
118 17910 : if (arg->read_size != state->block_size) {
119 : /* fill the remaining with 0 */
@@ -185,26 +185,26 @@
123 17910 : return 0;
124 : }
125 :
- 126 638616 : 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)
+ 126 639060 : 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)
127 : {
128 : struct snapraid_search_file* file;
129 : tommy_uint32_t file_hash;
130 : struct search_file_compare_arg arg;
131 :
- 132 638616 : arg.state = state;
- 133 638616 : arg.block = missing_block;
- 134 638616 : arg.file = missing_file;
- 135 638616 : arg.buffer = buffer;
- 136 638616 : arg.offset = state->block_size * (data_off_t)missing_file_pos;
- 137 638616 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size);
- 138 638616 : arg.prevhash = prevhash;
+ 132 639060 : arg.state = state;
+ 133 639060 : arg.block = missing_block;
+ 134 639060 : arg.file = missing_file;
+ 135 639060 : arg.buffer = buffer;
+ 136 639060 : arg.offset = state->block_size * (data_off_t)missing_file_pos;
+ 137 639060 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size);
+ 138 639060 : arg.prevhash = prevhash;
139 :
- 140 638616 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec);
+ 140 639060 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec);
141 :
142 : /* search in the hashtable, and also check if the data matches the hash */
- 143 638616 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash);
- 144 638616 : if (!file)
- 145 620706 : return -1;
+ 143 639060 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash);
+ 144 639060 : if (!file)
+ 145 621150 : return -1;
146 :
147 : /* if found, buffer is already set with data */
148 17910 : return 0;
@@ -226,40 +226,40 @@
164 : char path_next[PATH_MAX];
165 : char sub_next[PATH_MAX];
166 : char out[PATH_MAX];
- 167 2040368 : struct snapraid_filter* reason = 0;
+ 167 2040206 : struct snapraid_filter* reason = 0;
168 : struct stat st;
169 : const char* name;
170 : struct dirent* dd;
171 :
172 : /* clear errno to detect erroneous conditions */
- 173 2040368 : errno = 0;
- 174 2040368 : dd = readdir(d);
- 175 2040368 : if (dd == 0 && errno != 0) {
+ 173 2040206 : errno = 0;
+ 174 2040206 : dd = readdir(d);
+ 175 2040206 : if (dd == 0 && errno != 0) {
176 : /* LCOV_EXCL_START */
177 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
178 : exit(EXIT_FAILURE);
179 : /* LCOV_EXCL_STOP */
180 : }
- 181 2040368 : if (dd == 0) {
+ 181 2040206 : if (dd == 0) {
182 2462 : break; /* finished */
183 : }
184 :
185 : /* skip "." and ".." files */
- 186 2037906 : name = dd->d_name;
- 187 2037906 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+ 186 2037744 : name = dd->d_name;
+ 187 2037744 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
188 9848 : continue;
189 :
- 190 2032982 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
- 191 2032982 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
+ 190 2032820 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
+ 191 2032820 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
192 :
193 : /* exclude hidden files even before calling lstat() */
- 194 2032982 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) {
+ 194 2032820 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) {
195 0 : msg_verbose("Excluding hidden '%s'\n", path_next);
196 0 : continue;
197 : }
198 :
199 : /* exclude content files even before calling lstat() */
- 200 2032982 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) {
+ 200 2032820 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) {
201 0 : msg_verbose("Excluding content '%s'\n", path_next);
202 0 : continue;
203 : }
@@ -283,7 +283,7 @@
221 : }
222 : #else
223 : /* get lstat info about the file */
- 224 2032982 : if (lstat(path_next, &st) != 0) {
+ 224 2032820 : if (lstat(path_next, &st) != 0) {
225 : /* LCOV_EXCL_START */
226 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
227 : exit(EXIT_FAILURE);
@@ -291,13 +291,13 @@
229 : }
230 : #endif
231 :
- 232 2032982 : if (S_ISREG(st.st_mode)) {
- 233 1968671 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
- 234 1843968 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st));
+ 232 2032820 : if (S_ISREG(st.st_mode)) {
+ 233 1968528 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
+ 234 1843727 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st));
235 : } else {
- 236 124703 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
+ 236 124801 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
237 : }
- 238 64311 : } else if (S_ISDIR(st.st_mode)) {
+ 238 64292 : } else if (S_ISDIR(st.st_mode)) {
239 1781 : if (disk == 0 || filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
240 1781 : pathslash(path_next, sizeof(path_next));
241 1781 : pathslash(sub_next, sizeof(sub_next));
@@ -306,7 +306,7 @@
244 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
245 : }
246 : }
- 247 2037906 : }
+ 247 2037744 : }
248 :
249 2462 : if (closedir(d) != 0) {
250 : /* LCOV_EXCL_START */
diff --git a/cov/cmdline/selftest.c.func-sort-c.html b/cov/cmdline/selftest.c.func-sort-c.html
index 65f3fb9d..038fd913 100644
--- a/cov/cmdline/selftest.c.func-sort-c.html
+++ b/cov/cmdline/selftest.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/selftest.c.func.html b/cov/cmdline/selftest.c.func.html
index 560f0b0f..eb01ebf0 100644
--- a/cov/cmdline/selftest.c.func.html
+++ b/cov/cmdline/selftest.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/selftest.c.gcov.html b/cov/cmdline/selftest.c.gcov.html
index 0c7c4c26..932ed1cb 100644
--- a/cov/cmdline/selftest.c.gcov.html
+++ b/cov/cmdline/selftest.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/snapraid.c.func-sort-c.html b/cov/cmdline/snapraid.c.func-sort-c.html
index d95907bb..df97fc21 100644
--- a/cov/cmdline/snapraid.c.func-sort-c.html
+++ b/cov/cmdline/snapraid.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/snapraid.c.func.html b/cov/cmdline/snapraid.c.func.html
index 07ec904e..084a15d6 100644
--- a/cov/cmdline/snapraid.c.func.html
+++ b/cov/cmdline/snapraid.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/snapraid.c.gcov.html b/cov/cmdline/snapraid.c.gcov.html
index c3a2aff1..64d66e89 100644
--- a/cov/cmdline/snapraid.c.gcov.html
+++ b/cov/cmdline/snapraid.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -526,7 +526,7 @@
464 : /* Skip space holder file in parity disks */
465 : { "test-skip-space-holder", 0, 0, OPT_TEST_SKIP_SPACE_HOLDER },
466 :
- 467 : /* Set the ourput format */
+ 467 : /* Set the output format */
468 : { "test-fmt", 1, 0, OPT_TEST_FORMAT },
469 :
470 : { 0, 0, 0, 0 }
diff --git a/cov/cmdline/speed.c.func-sort-c.html b/cov/cmdline/speed.c.func-sort-c.html
index 70d26600..790d9412 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 |
- 1814 |
+ 1849 |
| speed |
diff --git a/cov/cmdline/speed.c.func.html b/cov/cmdline/speed.c.func.html
index c6485ff8..4811a770 100644
--- a/cov/cmdline/speed.c.func.html
+++ b/cov/cmdline/speed.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| diffgettimeofday |
- 1814 |
+ 1849 |
| speed |
diff --git a/cov/cmdline/speed.c.gcov.html b/cov/cmdline/speed.c.gcov.html
index 24c2c5d8..26fc4c22 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 1814 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop)
+ 41 1849 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop)
42 : {
43 : int64_t d;
44 :
- 45 1814 : d = 1000000LL * (stop->tv_sec - start->tv_sec);
- 46 1814 : d += stop->tv_usec - start->tv_usec;
+ 45 1849 : d = 1000000LL * (stop->tv_sec - start->tv_sec);
+ 46 1849 : d += stop->tv_usec - start->tv_usec;
47 :
- 48 1814 : return d;
+ 48 1849 : return d;
49 : }
50 :
51 : /**
@@ -232,10 +232,10 @@
170 4 : printf("%8s", "memset");
171 4 : fflush(stdout);
172 :
- 173 374 : SPEED_START {
- 174 3330 : for (j = 0; j < nd; ++j)
- 175 2960 : memset(v[j], j, size);
- 176 370 : } 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");
@@ -260,10 +260,10 @@
198 :
199 : #if HAVE_SSE42
200 4 : if (raid_cpu_has_crc32()) {
- 201 58 : SPEED_START {
- 202 504 : for (j = 0; j < nd; ++j)
- 203 448 : side_effect += crc32c_x86(0, v[j], size);
- 204 56 : } SPEED_STOP
+ 201 60 : SPEED_START {
+ 202 522 : for (j = 0; j < nd; ++j)
+ 203 464 : side_effect += crc32c_x86(0, v[j], size);
+ 204 58 : } SPEED_STOP
205 :
206 2 : printf("%8" PRIu64, ds / dt);
207 : }
@@ -302,10 +302,10 @@
240 4 : printf("%8" PRIu64, ds / dt);
241 4 : fflush(stdout);
242 :
- 243 30 : SPEED_START {
- 244 234 : for (j = 0; j < nd; ++j)
- 245 208 : memhash(HASH_SPOOKY2, seed, digest, v[j], size);
- 246 26 : } SPEED_STOP
+ 243 32 : SPEED_START {
+ 244 252 : for (j = 0; j < nd; ++j)
+ 245 224 : memhash(HASH_SPOOKY2, seed, digest, v[j], size);
+ 246 28 : } 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 114 : SPEED_START {
- 283 110 : raid_gen1_int32(nd, size, v);
- 284 110 : } SPEED_STOP
+ 282 119 : SPEED_START {
+ 283 115 : raid_gen1_int32(nd, size, v);
+ 284 115 : } SPEED_STOP
285 :
286 4 : printf("%8" PRIu64, ds / dt);
287 4 : fflush(stdout);
288 :
- 289 181 : SPEED_START {
- 290 177 : raid_gen1_int64(nd, size, v);
- 291 177 : } SPEED_STOP
+ 289 184 : SPEED_START {
+ 290 180 : raid_gen1_int64(nd, size, v);
+ 291 180 : } 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 305 : SPEED_START {
- 300 301 : raid_gen1_sse2(nd, size, v);
- 301 301 : } SPEED_STOP
+ 299 309 : SPEED_START {
+ 300 305 : raid_gen1_sse2(nd, size, v);
+ 301 305 : } SPEED_STOP
302 :
303 4 : printf("%8" PRIu64, ds / dt);
304 4 : fflush(stdout);
@@ -376,9 +376,9 @@
314 : #endif
315 : #ifdef CONFIG_AVX2
316 4 : if (raid_cpu_has_avx2()) {
- 317 13 : SPEED_START {
- 318 12 : raid_gen1_avx2(nd, size, v);
- 319 12 : } SPEED_STOP
+ 317 14 : SPEED_START {
+ 318 13 : raid_gen1_avx2(nd, size, v);
+ 319 13 : } SPEED_STOP
320 :
321 1 : printf("%8" PRIu64, ds / dt);
322 1 : fflush(stdout);
@@ -394,16 +394,16 @@
332 :
333 4 : printf("%8s", "");
334 :
- 335 47 : SPEED_START {
- 336 43 : raid_gen2_int32(nd, size, v);
- 337 43 : } SPEED_STOP
+ 335 48 : SPEED_START {
+ 336 44 : raid_gen2_int32(nd, size, v);
+ 337 44 : } SPEED_STOP
338 :
339 4 : printf("%8" PRIu64, ds / dt);
340 4 : fflush(stdout);
341 :
- 342 47 : SPEED_START {
- 343 43 : raid_gen2_int64(nd, size, v);
- 344 43 : } SPEED_STOP
+ 342 48 : SPEED_START {
+ 343 44 : raid_gen2_int64(nd, size, v);
+ 344 44 : } SPEED_STOP
345 :
346 4 : printf("%8" PRIu64, ds / dt);
347 4 : fflush(stdout);
@@ -411,9 +411,9 @@
349 : #ifdef CONFIG_X86
350 : #ifdef CONFIG_SSE2
351 4 : if (raid_cpu_has_sse2()) {
- 352 143 : SPEED_START {
- 353 139 : raid_gen2_sse2(nd, size, v);
- 354 139 : } SPEED_STOP
+ 352 150 : SPEED_START {
+ 353 146 : raid_gen2_sse2(nd, size, v);
+ 354 146 : } 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 87 : SPEED_START {
- 412 83 : raid_genz_sse2(nd, size, v);
- 413 83 : } SPEED_STOP
+ 411 91 : SPEED_START {
+ 412 87 : raid_genz_sse2(nd, size, v);
+ 413 87 : } SPEED_STOP
414 :
415 4 : printf("%8" PRIu64, ds / dt);
416 4 : fflush(stdout);
@@ -537,9 +537,9 @@
475 : #ifdef CONFIG_X86
476 : #ifdef CONFIG_SSSE3
477 4 : if (raid_cpu_has_ssse3()) {
- 478 52 : SPEED_START {
- 479 49 : raid_gen3_ssse3(nd, size, v);
- 480 49 : } SPEED_STOP
+ 478 51 : SPEED_START {
+ 479 48 : raid_gen3_ssse3(nd, size, v);
+ 480 48 : } SPEED_STOP
481 :
482 3 : printf("%8" PRIu64, ds / dt);
483 3 : fflush(stdout);
@@ -667,9 +667,9 @@
605 : #ifdef CONFIG_X86
606 : #ifdef CONFIG_SSSE3
607 4 : if (raid_cpu_has_ssse3()) {
- 608 25 : SPEED_START {
- 609 22 : raid_gen5_ssse3(nd, size, v);
- 610 22 : } SPEED_STOP
+ 608 27 : SPEED_START {
+ 609 24 : raid_gen5_ssse3(nd, size, v);
+ 610 24 : } SPEED_STOP
611 :
612 3 : printf("%8" PRIu64, ds / dt);
613 3 : fflush(stdout);
@@ -707,9 +707,9 @@
645 4 : printf("%8s", raid_gen6_tag());
646 4 : fflush(stdout);
647 :
- 648 9 : SPEED_START {
- 649 5 : raid_gen6_int8(nd, size, v);
- 650 5 : } 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 fd355ad2..76b5571f 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 |
- 3861457 |
+ 3861492 |
diff --git a/cov/cmdline/spooky2.c.func.html b/cov/cmdline/spooky2.c.func.html
index 3dfa7070..b4ea5391 100644
--- a/cov/cmdline/spooky2.c.func.html
+++ b/cov/cmdline/spooky2.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| SpookyHash128 |
- 3861457 |
+ 3861492 |
diff --git a/cov/cmdline/spooky2.c.gcov.html b/cov/cmdline/spooky2.c.gcov.html
index 34fefeb4..1b9812b1 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 3861457 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
+ 111 3861492 : 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,45 +182,45 @@
120 : unsigned i;
121 : #endif
122 :
- 123 3861457 : h9 = util_read64(seed + 0);
- 124 3861457 : h10 = util_read64(seed + 8);
+ 123 3861492 : h9 = util_read64(seed + 0);
+ 124 3861492 : h10 = util_read64(seed + 8);
125 :
- 126 3861457 : h0 = h3 = h6 = h9;
- 127 3861457 : h1 = h4 = h7 = h10;
- 128 3861457 : h2 = h5 = h8 = h11 = sc_const;
+ 126 3861492 : h0 = h3 = h6 = h9;
+ 127 3861492 : h1 = h4 = h7 = h10;
+ 128 3861492 : h2 = h5 = h8 = h11 = sc_const;
129 :
- 130 3861457 : nblocks = size / sc_blockSize;
- 131 3861457 : blocks = data;
- 132 3861457 : end = blocks + nblocks * sc_numVars;
+ 130 3861492 : nblocks = size / sc_blockSize;
+ 131 3861492 : blocks = data;
+ 132 3861492 : end = blocks + nblocks * sc_numVars;
133 :
134 : /* body */
- 135 38698449 : while (blocks < end) {
+ 135 38741744 : while (blocks < end) {
136 : #if WORDS_BIGENDIAN
137 : for (i = 0; i < sc_numVars; ++i)
138 : buf[i] = util_swap64(blocks[i]);
139 : Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
140 : #else
- 141 30975535 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
+ 141 31018760 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
142 : #endif
- 143 30975535 : blocks += sc_numVars;
+ 143 31018760 : blocks += sc_numVars;
144 : }
145 :
146 : /* tail */
- 147 3861457 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
- 148 3861457 : memcpy(buf, end, size_remainder);
- 149 3861457 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
- 150 3861457 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
+ 147 3861492 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
+ 148 3861492 : memcpy(buf, end, size_remainder);
+ 149 3861492 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
+ 150 3861492 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
151 :
152 : /* finalization */
153 : #if WORDS_BIGENDIAN
154 : for (i = 0; i < sc_numVars; ++i)
155 : buf[i] = util_swap64(buf[i]);
156 : #endif
- 157 3861457 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
+ 157 3861492 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
158 :
- 159 3861457 : util_write64(digest + 0, h0);
- 160 3861457 : util_write64(digest + 8, h1);
- 161 3861457 : }
+ 159 3861492 : util_write64(digest + 0, h0);
+ 160 3861492 : util_write64(digest + 8, h1);
+ 161 3861492 : }
162 :
diff --git a/cov/cmdline/state.c.func-sort-c.html b/cov/cmdline/state.c.func-sort-c.html
index bd1dec5b..659e86c4 100644
--- a/cov/cmdline/state.c.func-sort-c.html
+++ b/cov/cmdline/state.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -60,51 +60,51 @@
Hit count  |
- | fs_is_block_deleted |
+ fs_is_block_deleted |
4529621 |
- | fs_info_is_required |
+ fs_info_is_required |
1547923 |
- | state_progress |
- 1073436 |
+ state_progress |
+ 1073492 |
- | state_usage_misc |
- 1063244 |
+ state_usage_misc |
+ 1063636 |
- | state_usage_disk |
- 912519 |
+ state_usage_disk |
+ 912855 |
- | state_usage_hash |
- 776953 |
+ state_usage_hash |
+ 777321 |
- | state_usage_parity |
- 774185 |
+ state_usage_parity |
+ 774521 |
- | fs_position_is_required |
+ fs_position_is_required |
756099 |
| lev_config_name |
- 186623 |
+ 186606 |
- | state_usage_sched |
- 149863 |
+ state_usage_sched |
+ 149919 |
- | state_usage_raid |
- 140402 |
+ state_usage_raid |
+ 140474 |
- | find_disk_by_name |
+ find_disk_by_name |
7047 |
@@ -112,17 +112,17 @@
| 6345 |
- | state_verify_thread |
- 1012 |
+ state_verify_thread |
+ 1009 |
- | state_progress_latest |
- 532 |
-
-
- | state_fscheck |
+ state_fscheck |
499 |
+
+ | state_progress_latest |
+ 478 |
+
| validate_smartctl |
366 |
@@ -144,19 +144,19 @@
265 |
- | state_read |
+ state_read |
261 |
- | state_map |
+ state_map |
260 |
- | state_read_content |
+ state_read_content |
254 |
- | state_content_check |
+ state_content_check |
253 |
@@ -164,51 +164,51 @@
| 244 |
- | state_progress_end |
+ state_progress_end |
221 |
- | state_progress_begin |
+ state_progress_begin |
221 |
- | state_refresh |
+ state_refresh |
173 |
- | state_write |
+ state_write |
151 |
- | state_write_thread |
+ state_write_thread |
151 |
- | state_write_content |
+ state_write_content |
151 |
- | state_verify_content |
+ state_verify_content |
151 |
- | state_rename_content |
+ state_rename_content |
151 |
- | state_skip |
+ state_skip |
122 |
- | state_filter |
+ state_filter |
122 |
- | state_usage_waste |
+ state_usage_waste |
104 |
- | state_usage_print |
+ state_usage_print |
96 |
@@ -216,31 +216,31 @@
| 7 |
- | state_progress_graph |
+ find_disk_by_uuid |
2 |
- | find_disk_by_uuid |
- 2 |
-
-
- | state_progress_restart |
+ state_progress_graph |
1 |
- | generate_configuration |
+ state_progress_restart |
1 |
- | decoding_error |
+ generate_configuration |
1 |
- | state_progress_stop |
+ decoding_error |
1 |
- | fs_position_clear_deleted |
+ state_progress_stop |
+ 1 |
+
+
+ | fs_position_clear_deleted |
0 |
diff --git a/cov/cmdline/state.c.func.html b/cov/cmdline/state.c.func.html
index a2f569e6..5cabaa59 100644
--- a/cov/cmdline/state.c.func.html
+++ b/cov/cmdline/state.c.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -60,40 +60,40 @@
Hit count  |
- | decoding_error |
+ decoding_error |
1 |
- | find_disk_by_name |
+ find_disk_by_name |
7047 |
- | find_disk_by_uuid |
+ find_disk_by_uuid |
2 |
- | fs_info_is_required |
+ fs_info_is_required |
1547923 |
- | fs_is_block_deleted |
+ fs_is_block_deleted |
4529621 |
- | fs_position_clear_deleted |
+ fs_position_clear_deleted |
0 |
- | fs_position_is_required |
+ fs_position_is_required |
756099 |
- | generate_configuration |
+ generate_configuration |
1 |
| lev_config_name |
- 186623 |
+ 186606 |
| lev_config_scan |
@@ -116,7 +116,7 @@
265 |
- | state_content_check |
+ state_content_check |
253 |
@@ -124,11 +124,11 @@
| 244 |
- | state_filter |
+ state_filter |
122 |
- | state_fscheck |
+ state_fscheck |
499 |
@@ -136,107 +136,107 @@
| 267 |
- | state_map |
+ state_map |
260 |
- | state_progress |
- 1073436 |
+ state_progress |
+ 1073492 |
- | state_progress_begin |
+ state_progress_begin |
221 |
- | state_progress_end |
+ state_progress_end |
221 |
- | state_progress_graph |
- 2 |
-
-
- | state_progress_latest |
- 532 |
-
-
- | state_progress_restart |
+ state_progress_graph |
1 |
- | state_progress_stop |
+ state_progress_latest |
+ 478 |
+
+
+ | state_progress_restart |
1 |
- | state_read |
+ state_progress_stop |
+ 1 |
+
+
+ | state_read |
261 |
- | state_read_content |
+ state_read_content |
254 |
- | state_refresh |
+ state_refresh |
173 |
- | state_rename_content |
+ state_rename_content |
151 |
- | state_skip |
+ state_skip |
122 |
- | state_usage_disk |
- 912519 |
+ state_usage_disk |
+ 912855 |
- | state_usage_hash |
- 776953 |
+ state_usage_hash |
+ 777321 |
- | state_usage_misc |
- 1063244 |
+ state_usage_misc |
+ 1063636 |
- | state_usage_parity |
- 774185 |
+ state_usage_parity |
+ 774521 |
- | state_usage_print |
+ state_usage_print |
96 |
- | state_usage_raid |
- 140402 |
+ state_usage_raid |
+ 140474 |
- | state_usage_sched |
- 149863 |
+ state_usage_sched |
+ 149919 |
- | state_usage_waste |
+ state_usage_waste |
104 |
- | state_verify_content |
+ state_verify_content |
151 |
- | state_verify_thread |
- 1012 |
+ state_verify_thread |
+ 1009 |
- | state_write |
+ state_write |
151 |
- | state_write_content |
+ state_write_content |
151 |
- | state_write_thread |
+ state_write_thread |
151 |
diff --git a/cov/cmdline/state.c.gcov.html b/cov/cmdline/state.c.gcov.html
index d4eda724..ed55a4e3 100644
--- a/cov/cmdline/state.c.gcov.html
+++ b/cov/cmdline/state.c.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -125,13 +125,13 @@
63 0 : return 0;
64 : }
65 :
- 66 186623 : const char* lev_config_name(unsigned l)
+ 66 186606 : const char* lev_config_name(unsigned l)
67 : {
- 68 186623 : switch (l) {
- 69 86887 : case 0 : return "parity";
+ 68 186606 : switch (l) {
+ 69 86864 : case 0 : return "parity";
70 60630 : case 1 : return "2-parity";
- 71 9816 : case 2 : return "3-parity";
- 72 9791 : case 3 : return "4-parity";
+ 71 9820 : case 2 : return "3-parity";
+ 72 9793 : case 3 : return "4-parity";
73 9766 : case 4 : return "5-parity";
74 9733 : case 5 : return "6-parity";
75 : }
@@ -224,7 +224,7 @@
162 1602 : state->parity[l].skip_access = 0;
163 1602 : state->parity[l].tick = 0;
164 1602 : state->parity[l].cached = 0;
- 165 1602 : state->parity[l].is_excluded = 0;
+ 165 1602 : state->parity[l].is_excluded_by_filter = 0;
166 : }
167 267 : state->tick_io = 0;
168 267 : state->tick_misc = 0;
@@ -683,4063 +683,4072 @@
621 : /* LCOV_EXCL_STOP */
622 : }
623 266 : state->block_size *= KIBI;
- 624 5979 : } else if (strcmp(tag, "hash_size") == 0) {
- 625 : uint32_t hash_size;
- 626 :
- 627 0 : ret = sgetu32(f, &hash_size);
- 628 0 : if (ret < 0) {
- 629 : /* LCOV_EXCL_START */
- 630 : log_fatal("Invalid 'hashsize' specification in '%s' at line %u\n", path, line);
- 631 : exit(EXIT_FAILURE);
- 632 : /* LCOV_EXCL_STOP */
- 633 : }
- 634 0 : if (hash_size < 2) {
- 635 : /* LCOV_EXCL_START */
- 636 : log_fatal("Too small 'hashsize' specification in '%s' at line %u\n", path, line);
- 637 : exit(EXIT_FAILURE);
- 638 : /* LCOV_EXCL_STOP */
- 639 : }
- 640 0 : if (hash_size > HASH_MAX) {
- 641 : /* LCOV_EXCL_START */
- 642 : log_fatal("Too big 'hashsize' specification in '%s' at line %u\n", path, line);
- 643 : exit(EXIT_FAILURE);
- 644 : /* LCOV_EXCL_STOP */
- 645 : }
- 646 : /* check if it's a power of 2 */
- 647 0 : if ((hash_size & (hash_size - 1)) != 0) {
- 648 : /* LCOV_EXCL_START */
- 649 : log_fatal("Not power of 2 'hashsize' specification in '%s' at line %u\n", path, line);
- 650 : exit(EXIT_FAILURE);
- 651 : /* LCOV_EXCL_STOP */
- 652 : }
- 653 :
- 654 0 : BLOCK_HASH_SIZE = hash_size;
- 655 5979 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) {
- 656 : char device[PATH_MAX];
- 657 : char* split_map[SPLIT_MAX+1];
- 658 : unsigned split_mac;
- 659 : char* slash;
- 660 : uint64_t dev;
- 661 : int skip_access;
- 662 :
- 663 1272 : if (state->parity[level].split_mac != 0) {
- 664 : /* LCOV_EXCL_START */
- 665 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line);
- 666 : exit(EXIT_FAILURE);
- 667 : /* LCOV_EXCL_STOP */
- 668 : }
- 669 :
- 670 1272 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 671 1272 : if (ret < 0) {
- 672 : /* LCOV_EXCL_START */
- 673 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line);
- 674 : exit(EXIT_FAILURE);
- 675 : /* LCOV_EXCL_STOP */
- 676 : }
- 677 :
- 678 1272 : if (!*buffer) {
- 679 : /* LCOV_EXCL_START */
- 680 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line);
- 681 : exit(EXIT_FAILURE);
- 682 : /* LCOV_EXCL_STOP */
- 683 : }
- 684 :
- 685 1272 : split_mac = strsplit(split_map, SPLIT_MAX+1, buffer, ",");
+ 624 5979 : } else if (strcmp(tag, "hashsize") == 0
+ 625 5979 : || strcmp(tag, "hash_size") == 0 /* v11.0 used incorretly this one, kept now for backward compatibility */
+ 626 0 : ) {
+ 627 : uint32_t hash_size;
+ 628 :
+ 629 0 : ret = sgetu32(f, &hash_size);
+ 630 0 : if (ret < 0) {
+ 631 : /* LCOV_EXCL_START */
+ 632 : log_fatal("Invalid 'hashsize' specification in '%s' at line %u\n", path, line);
+ 633 : exit(EXIT_FAILURE);
+ 634 : /* LCOV_EXCL_STOP */
+ 635 : }
+ 636 0 : if (hash_size < 2) {
+ 637 : /* LCOV_EXCL_START */
+ 638 : log_fatal("Too small 'hashsize' specification in '%s' at line %u\n", path, line);
+ 639 : exit(EXIT_FAILURE);
+ 640 : /* LCOV_EXCL_STOP */
+ 641 : }
+ 642 0 : if (hash_size > HASH_MAX) {
+ 643 : /* LCOV_EXCL_START */
+ 644 : log_fatal("Too big 'hashsize' specification in '%s' at line %u\n", path, line);
+ 645 : exit(EXIT_FAILURE);
+ 646 : /* LCOV_EXCL_STOP */
+ 647 : }
+ 648 : /* check if it's a power of 2 */
+ 649 0 : if ((hash_size & (hash_size - 1)) != 0) {
+ 650 : /* LCOV_EXCL_START */
+ 651 : log_fatal("Not power of 2 'hashsize' specification in '%s' at line %u\n", path, line);
+ 652 : exit(EXIT_FAILURE);
+ 653 : /* LCOV_EXCL_STOP */
+ 654 : }
+ 655 :
+ 656 0 : BLOCK_HASH_SIZE = hash_size;
+ 657 5979 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) {
+ 658 : char device[PATH_MAX];
+ 659 : char* split_map[SPLIT_MAX+1];
+ 660 : unsigned split_mac;
+ 661 : char* slash;
+ 662 : uint64_t dev;
+ 663 : int skip_access;
+ 664 :
+ 665 1272 : if (state->parity[level].split_mac != 0) {
+ 666 : /* LCOV_EXCL_START */
+ 667 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line);
+ 668 : exit(EXIT_FAILURE);
+ 669 : /* LCOV_EXCL_STOP */
+ 670 : }
+ 671 :
+ 672 1272 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 673 1272 : if (ret < 0) {
+ 674 : /* LCOV_EXCL_START */
+ 675 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line);
+ 676 : exit(EXIT_FAILURE);
+ 677 : /* LCOV_EXCL_STOP */
+ 678 : }
+ 679 :
+ 680 1272 : if (!*buffer) {
+ 681 : /* LCOV_EXCL_START */
+ 682 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line);
+ 683 : exit(EXIT_FAILURE);
+ 684 : /* LCOV_EXCL_STOP */
+ 685 : }
686 :
- 687 1272 : if (split_mac > SPLIT_MAX) {
- 688 : /* LCOV_EXCL_START */
- 689 : log_fatal("Too many files in '%s' specification in '%s' at line %u\n", tag, path, line);
- 690 : exit(EXIT_FAILURE);
- 691 : /* LCOV_EXCL_STOP */
- 692 : }
- 693 :
- 694 1272 : skip_access = 0;
- 695 1272 : state->parity[level].split_mac = split_mac;
- 696 6356 : for (s = 0; s < split_mac; ++s) {
- 697 5085 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]);
- 698 :
- 699 5085 : if (!state->opt.skip_parity_access) {
- 700 : struct stat st;
- 701 :
- 702 : /* get the device of the directory containing the parity file */
- 703 4349 : pathimport(device, sizeof(device), split_map[s]);
- 704 4349 : slash = strrchr(device, '/');
- 705 4349 : if (slash)
- 706 4349 : *slash = 0;
- 707 : else
- 708 0 : pathcpy(device, sizeof(device), ".");
- 709 :
- 710 4349 : if (stat(device, &st) == 0) {
- 711 4344 : dev = st.st_dev;
- 712 : } else {
- 713 : /* if the disk can be skipped */
- 714 5 : if (state->opt.force_device) {
- 715 : /* use a fake device, and mark the disk to be skipped */
- 716 4 : dev = 0;
- 717 4 : skip_access = 1;
- 718 4 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag);
- 719 : } else {
- 720 : /* LCOV_EXCL_START */
- 721 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line);
- 722 :
- 723 : /* in "fix" we allow to continue anyway */
- 724 : if (strcmp(state->command, "fix") == 0) {
- 725 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 726 : }
- 727 : exit(EXIT_FAILURE);
- 728 : /* LCOV_EXCL_STOP */
- 729 : }
- 730 : }
- 731 : } else {
- 732 : /* use a fake device */
- 733 736 : dev = 0;
- 734 : }
- 735 :
- 736 5084 : state->parity[level].split_map[s].device = dev;
- 737 : }
- 738 :
- 739 : /* store the global parity skip_access */
- 740 1271 : state->parity[level].skip_access = skip_access;
- 741 :
- 742 : /* adjust the level */
- 743 1271 : if (state->level < level + 1)
- 744 1005 : state->level = level + 1;
- 745 4707 : } else if (strcmp(tag, "share") == 0) {
- 746 41 : if (*state->share) {
- 747 : /* LCOV_EXCL_START */
- 748 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line);
- 749 : exit(EXIT_FAILURE);
- 750 : /* LCOV_EXCL_STOP */
- 751 : }
- 752 :
- 753 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 754 41 : if (ret < 0) {
- 755 : /* LCOV_EXCL_START */
- 756 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line);
- 757 : exit(EXIT_FAILURE);
- 758 : /* LCOV_EXCL_STOP */
- 759 : }
- 760 :
- 761 41 : if (!*buffer) {
- 762 : /* LCOV_EXCL_START */
- 763 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line);
- 764 : exit(EXIT_FAILURE);
- 765 : /* LCOV_EXCL_STOP */
- 766 : }
- 767 :
- 768 41 : pathimport(state->share, sizeof(state->share), buffer);
- 769 4666 : } else if (strcmp(tag, "pool") == 0) {
- 770 : struct stat st;
- 771 :
- 772 41 : if (*state->pool) {
- 773 : /* LCOV_EXCL_START */
- 774 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line);
- 775 : exit(EXIT_FAILURE);
- 776 : /* LCOV_EXCL_STOP */
- 777 : }
- 778 :
- 779 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 780 41 : if (ret < 0) {
- 781 : /* LCOV_EXCL_START */
- 782 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line);
- 783 : exit(EXIT_FAILURE);
- 784 : /* LCOV_EXCL_STOP */
- 785 : }
- 786 :
- 787 41 : if (!*buffer) {
- 788 : /* LCOV_EXCL_START */
- 789 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line);
- 790 : exit(EXIT_FAILURE);
- 791 : /* LCOV_EXCL_STOP */
- 792 : }
- 793 :
- 794 41 : pathimport(state->pool, sizeof(state->pool), buffer);
+ 687 1272 : split_mac = strsplit(split_map, SPLIT_MAX+1, buffer, ",");
+ 688 :
+ 689 1272 : if (split_mac > SPLIT_MAX) {
+ 690 : /* LCOV_EXCL_START */
+ 691 : log_fatal("Too many files in '%s' specification in '%s' at line %u\n", tag, path, line);
+ 692 : exit(EXIT_FAILURE);
+ 693 : /* LCOV_EXCL_STOP */
+ 694 : }
+ 695 :
+ 696 1272 : skip_access = 0;
+ 697 1272 : state->parity[level].split_mac = split_mac;
+ 698 6356 : for (s = 0; s < split_mac; ++s) {
+ 699 5085 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]);
+ 700 :
+ 701 5085 : if (!state->opt.skip_parity_access) {
+ 702 : struct stat st;
+ 703 :
+ 704 : /* get the device of the directory containing the parity file */
+ 705 4349 : pathimport(device, sizeof(device), split_map[s]);
+ 706 4349 : slash = strrchr(device, '/');
+ 707 4349 : if (slash)
+ 708 4349 : *slash = 0;
+ 709 : else
+ 710 0 : pathcpy(device, sizeof(device), ".");
+ 711 :
+ 712 4349 : if (stat(device, &st) == 0) {
+ 713 4344 : dev = st.st_dev;
+ 714 : } else {
+ 715 : /* if the disk can be skipped */
+ 716 5 : if (state->opt.force_device) {
+ 717 : /* use a fake device, and mark the disk to be skipped */
+ 718 4 : dev = 0;
+ 719 4 : skip_access = 1;
+ 720 4 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag);
+ 721 : } else {
+ 722 : /* LCOV_EXCL_START */
+ 723 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line);
+ 724 :
+ 725 : /* in "fix" we allow to continue anyway */
+ 726 : if (strcmp(state->command, "fix") == 0) {
+ 727 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 728 : }
+ 729 : exit(EXIT_FAILURE);
+ 730 : /* LCOV_EXCL_STOP */
+ 731 : }
+ 732 : }
+ 733 : } else {
+ 734 : /* use a fake device */
+ 735 736 : dev = 0;
+ 736 : }
+ 737 :
+ 738 5084 : state->parity[level].split_map[s].device = dev;
+ 739 : }
+ 740 :
+ 741 : /* store the global parity skip_access */
+ 742 1271 : state->parity[level].skip_access = skip_access;
+ 743 :
+ 744 : /* adjust the level */
+ 745 1271 : if (state->level < level + 1)
+ 746 1005 : state->level = level + 1;
+ 747 4707 : } else if (strcmp(tag, "share") == 0) {
+ 748 41 : if (*state->share) {
+ 749 : /* LCOV_EXCL_START */
+ 750 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line);
+ 751 : exit(EXIT_FAILURE);
+ 752 : /* LCOV_EXCL_STOP */
+ 753 : }
+ 754 :
+ 755 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 756 41 : if (ret < 0) {
+ 757 : /* LCOV_EXCL_START */
+ 758 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line);
+ 759 : exit(EXIT_FAILURE);
+ 760 : /* LCOV_EXCL_STOP */
+ 761 : }
+ 762 :
+ 763 41 : if (!*buffer) {
+ 764 : /* LCOV_EXCL_START */
+ 765 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line);
+ 766 : exit(EXIT_FAILURE);
+ 767 : /* LCOV_EXCL_STOP */
+ 768 : }
+ 769 :
+ 770 41 : pathimport(state->share, sizeof(state->share), buffer);
+ 771 4666 : } else if (strcmp(tag, "pool") == 0) {
+ 772 : struct stat st;
+ 773 :
+ 774 41 : if (*state->pool) {
+ 775 : /* LCOV_EXCL_START */
+ 776 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line);
+ 777 : exit(EXIT_FAILURE);
+ 778 : /* LCOV_EXCL_STOP */
+ 779 : }
+ 780 :
+ 781 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 782 41 : if (ret < 0) {
+ 783 : /* LCOV_EXCL_START */
+ 784 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line);
+ 785 : exit(EXIT_FAILURE);
+ 786 : /* LCOV_EXCL_STOP */
+ 787 : }
+ 788 :
+ 789 41 : if (!*buffer) {
+ 790 : /* LCOV_EXCL_START */
+ 791 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line);
+ 792 : exit(EXIT_FAILURE);
+ 793 : /* LCOV_EXCL_STOP */
+ 794 : }
795 :
- 796 : /* get the device of the directory containing the pool tree */
- 797 41 : if (stat(buffer, &st) != 0) {
- 798 : /* LCOV_EXCL_START */
- 799 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line);
- 800 : exit(EXIT_FAILURE);
- 801 : /* LCOV_EXCL_STOP */
- 802 : }
- 803 :
- 804 41 : state->pool_device = st.st_dev;
- 805 4625 : } else if (strcmp(tag, "content") == 0) {
- 806 : struct snapraid_content* content;
- 807 : char device[PATH_MAX];
- 808 : char* slash;
- 809 : struct stat st;
- 810 : uint64_t dev;
- 811 :
- 812 1531 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 813 1531 : if (ret < 0) {
- 814 : /* LCOV_EXCL_START */
- 815 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line);
- 816 : exit(EXIT_FAILURE);
- 817 : /* LCOV_EXCL_STOP */
- 818 : }
- 819 :
- 820 1531 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) {
- 821 : /* LCOV_EXCL_START */
- 822 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line);
- 823 : exit(EXIT_FAILURE);
- 824 : /* LCOV_EXCL_STOP */
- 825 : }
- 826 :
- 827 1531 : if (!*buffer) {
- 828 : /* LCOV_EXCL_START */
- 829 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line);
- 830 : exit(EXIT_FAILURE);
- 831 : /* LCOV_EXCL_STOP */
- 832 : }
- 833 :
- 834 : /* check if the content file is already specified */
- 835 5724 : for (i = state->contentlist; i != 0; i = i->next) {
- 836 4193 : content = i->data;
- 837 4193 : if (pathcmp(content->content, buffer) == 0)
- 838 0 : break;
- 839 : }
- 840 1531 : if (i) {
- 841 : /* LCOV_EXCL_START */
- 842 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line);
- 843 : exit(EXIT_FAILURE);
- 844 : /* LCOV_EXCL_STOP */
- 845 : }
- 846 :
- 847 : /* get the device of the directory containing the content file */
- 848 1531 : pathimport(device, sizeof(device), buffer);
- 849 1531 : slash = strrchr(device, '/');
- 850 1531 : if (slash)
- 851 1531 : *slash = 0;
- 852 : else
- 853 0 : pathcpy(device, sizeof(device), ".");
- 854 1531 : if (stat(device, &st) == 0) {
- 855 1530 : dev = st.st_dev;
- 856 : } else {
- 857 1 : if (state->opt.skip_content_access) {
- 858 : /* use a fake device */
- 859 1 : dev = 0;
- 860 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer);
- 861 : } else {
- 862 : /* LCOV_EXCL_START */
- 863 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line);
- 864 : exit(EXIT_FAILURE);
- 865 : /* LCOV_EXCL_STOP */
- 866 : }
- 867 : }
- 868 :
- 869 : /* set the lock file at the first accessible content file */
- 870 1531 : if (state->lockfile[0] == 0 && dev != 0) {
- 871 265 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer);
- 872 265 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock");
- 873 : }
- 874 :
- 875 1531 : content = content_alloc(buffer, dev);
+ 796 41 : pathimport(state->pool, sizeof(state->pool), buffer);
+ 797 :
+ 798 : /* get the device of the directory containing the pool tree */
+ 799 41 : if (stat(buffer, &st) != 0) {
+ 800 : /* LCOV_EXCL_START */
+ 801 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line);
+ 802 : exit(EXIT_FAILURE);
+ 803 : /* LCOV_EXCL_STOP */
+ 804 : }
+ 805 :
+ 806 41 : state->pool_device = st.st_dev;
+ 807 4625 : } else if (strcmp(tag, "content") == 0) {
+ 808 : struct snapraid_content* content;
+ 809 : char device[PATH_MAX];
+ 810 : char* slash;
+ 811 : struct stat st;
+ 812 : uint64_t dev;
+ 813 :
+ 814 1531 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 815 1531 : if (ret < 0) {
+ 816 : /* LCOV_EXCL_START */
+ 817 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line);
+ 818 : exit(EXIT_FAILURE);
+ 819 : /* LCOV_EXCL_STOP */
+ 820 : }
+ 821 :
+ 822 1531 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) {
+ 823 : /* LCOV_EXCL_START */
+ 824 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line);
+ 825 : exit(EXIT_FAILURE);
+ 826 : /* LCOV_EXCL_STOP */
+ 827 : }
+ 828 :
+ 829 1531 : if (!*buffer) {
+ 830 : /* LCOV_EXCL_START */
+ 831 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line);
+ 832 : exit(EXIT_FAILURE);
+ 833 : /* LCOV_EXCL_STOP */
+ 834 : }
+ 835 :
+ 836 : /* check if the content file is already specified */
+ 837 5724 : for (i = state->contentlist; i != 0; i = i->next) {
+ 838 4193 : content = i->data;
+ 839 4193 : if (pathcmp(content->content, buffer) == 0)
+ 840 0 : break;
+ 841 : }
+ 842 1531 : if (i) {
+ 843 : /* LCOV_EXCL_START */
+ 844 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line);
+ 845 : exit(EXIT_FAILURE);
+ 846 : /* LCOV_EXCL_STOP */
+ 847 : }
+ 848 :
+ 849 : /* get the device of the directory containing the content file */
+ 850 1531 : pathimport(device, sizeof(device), buffer);
+ 851 1531 : slash = strrchr(device, '/');
+ 852 1531 : if (slash)
+ 853 1531 : *slash = 0;
+ 854 : else
+ 855 0 : pathcpy(device, sizeof(device), ".");
+ 856 1531 : if (stat(device, &st) == 0) {
+ 857 1530 : dev = st.st_dev;
+ 858 : } else {
+ 859 1 : if (state->opt.skip_content_access) {
+ 860 : /* use a fake device */
+ 861 1 : dev = 0;
+ 862 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer);
+ 863 : } else {
+ 864 : /* LCOV_EXCL_START */
+ 865 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line);
+ 866 : exit(EXIT_FAILURE);
+ 867 : /* LCOV_EXCL_STOP */
+ 868 : }
+ 869 : }
+ 870 :
+ 871 : /* set the lock file at the first accessible content file */
+ 872 1531 : if (state->lockfile[0] == 0 && dev != 0) {
+ 873 265 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer);
+ 874 265 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock");
+ 875 : }
876 :
- 877 1531 : tommy_list_insert_tail(&state->contentlist, &content->node, content);
- 878 4679 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) {
- 879 : /* "disk" is the deprecated name up to SnapRAID 9.x */
- 880 : char dir[PATH_MAX];
- 881 : char device[PATH_MAX];
- 882 : char uuid[UUID_MAX];
- 883 : struct snapraid_disk* disk;
- 884 : uint64_t dev;
- 885 : int skip_access;
- 886 :
- 887 1585 : ret = sgettok(f, buffer, sizeof(buffer));
- 888 1585 : if (ret < 0) {
- 889 : /* LCOV_EXCL_START */
- 890 : log_fatal("Invalid 'data' name specification in '%s' at line %u\n", path, line);
- 891 : exit(EXIT_FAILURE);
- 892 : /* LCOV_EXCL_STOP */
- 893 : }
- 894 :
- 895 1585 : if (!*buffer) {
- 896 : /* LCOV_EXCL_START */
- 897 : log_fatal("Empty 'data' name specification in '%s' at line %u\n", path, line);
- 898 : exit(EXIT_FAILURE);
- 899 : /* LCOV_EXCL_STOP */
- 900 : }
- 901 :
- 902 1585 : sgetspace(f);
+ 877 1531 : content = content_alloc(buffer, dev);
+ 878 :
+ 879 1531 : tommy_list_insert_tail(&state->contentlist, &content->node, content);
+ 880 4679 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) {
+ 881 : /* "disk" is the deprecated name up to SnapRAID 9.x */
+ 882 : char dir[PATH_MAX];
+ 883 : char device[PATH_MAX];
+ 884 : char uuid[UUID_MAX];
+ 885 : struct snapraid_disk* disk;
+ 886 : uint64_t dev;
+ 887 : int skip_access;
+ 888 :
+ 889 1585 : ret = sgettok(f, buffer, sizeof(buffer));
+ 890 1585 : if (ret < 0) {
+ 891 : /* LCOV_EXCL_START */
+ 892 : log_fatal("Invalid 'data' name specification in '%s' at line %u\n", path, line);
+ 893 : exit(EXIT_FAILURE);
+ 894 : /* LCOV_EXCL_STOP */
+ 895 : }
+ 896 :
+ 897 1585 : if (!*buffer) {
+ 898 : /* LCOV_EXCL_START */
+ 899 : log_fatal("Empty 'data' name specification in '%s' at line %u\n", path, line);
+ 900 : exit(EXIT_FAILURE);
+ 901 : /* LCOV_EXCL_STOP */
+ 902 : }
903 :
- 904 1585 : ret = sgetlasttok(f, dir, sizeof(dir));
- 905 1585 : if (ret < 0) {
- 906 : /* LCOV_EXCL_START */
- 907 : log_fatal("Invalid 'data' dir specification in '%s' at line %u\n", path, line);
- 908 : exit(EXIT_FAILURE);
- 909 : /* LCOV_EXCL_STOP */
- 910 : }
- 911 :
- 912 1585 : if (!*dir) {
- 913 : /* LCOV_EXCL_START */
- 914 : log_fatal("Empty 'data' dir specification in '%s' at line %u\n", path, line);
- 915 : exit(EXIT_FAILURE);
- 916 : /* LCOV_EXCL_STOP */
- 917 : }
- 918 :
- 919 : /* get the device of the dir */
- 920 1585 : pathimport(device, sizeof(device), dir);
- 921 :
- 922 : /* check if the disk name already exists */
- 923 5535 : for (i = state->disklist; i != 0; i = i->next) {
- 924 3950 : disk = i->data;
- 925 3950 : if (strcmp(disk->name, buffer) == 0)
- 926 0 : break;
- 927 : }
- 928 1585 : if (i) {
- 929 : /* LCOV_EXCL_START */
- 930 : log_fatal("Duplicate 'data' name '%s' at line %u\n", buffer, line);
- 931 : exit(EXIT_FAILURE);
- 932 : /* LCOV_EXCL_STOP */
- 933 : }
- 934 :
- 935 : /* if the disk has to be present */
- 936 1585 : skip_access = 0;
- 937 1585 : if (!state->opt.skip_disk_access) {
- 938 : struct stat st;
- 939 :
- 940 1423 : if (stat(device, &st) == 0) {
- 941 1422 : dev = st.st_dev;
- 942 :
- 943 : /* read the uuid, if unsupported use an empty one */
- 944 1422 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) {
- 945 0 : *uuid = 0;
- 946 : }
- 947 :
- 948 : /* fake a different UUID when testing */
- 949 1422 : if (state->opt.fake_uuid) {
- 950 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid);
- 951 2 : --state->opt.fake_uuid;
- 952 : }
- 953 : } else {
- 954 : /* if the disk can be skipped */
- 955 1 : if (state->opt.force_device) {
- 956 : /* use a fake device, and mark the disk to be skipped */
- 957 1 : dev = 0;
- 958 1 : *uuid = 0;
- 959 1 : skip_access = 1;
- 960 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer);
- 961 : } else {
- 962 : /* LCOV_EXCL_START */
- 963 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line);
- 964 :
- 965 : /* in "fix" we allow to continue anyway */
- 966 : if (strcmp(state->command, "fix") == 0) {
- 967 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
- 968 : }
- 969 : exit(EXIT_FAILURE);
- 970 : /* LCOV_EXCL_STOP */
- 971 : }
- 972 : }
- 973 : } else {
- 974 : /* use a fake device */
- 975 162 : dev = 0;
- 976 162 : *uuid = 0;
- 977 : }
- 978 :
- 979 1585 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access);
+ 904 1585 : sgetspace(f);
+ 905 :
+ 906 1585 : ret = sgetlasttok(f, dir, sizeof(dir));
+ 907 1585 : if (ret < 0) {
+ 908 : /* LCOV_EXCL_START */
+ 909 : log_fatal("Invalid 'data' dir specification in '%s' at line %u\n", path, line);
+ 910 : exit(EXIT_FAILURE);
+ 911 : /* LCOV_EXCL_STOP */
+ 912 : }
+ 913 :
+ 914 1585 : if (!*dir) {
+ 915 : /* LCOV_EXCL_START */
+ 916 : log_fatal("Empty 'data' dir specification in '%s' at line %u\n", path, line);
+ 917 : exit(EXIT_FAILURE);
+ 918 : /* LCOV_EXCL_STOP */
+ 919 : }
+ 920 :
+ 921 : /* get the device of the dir */
+ 922 1585 : pathimport(device, sizeof(device), dir);
+ 923 :
+ 924 : /* check if the disk name already exists */
+ 925 5535 : for (i = state->disklist; i != 0; i = i->next) {
+ 926 3950 : disk = i->data;
+ 927 3950 : if (strcmp(disk->name, buffer) == 0)
+ 928 0 : break;
+ 929 : }
+ 930 1585 : if (i) {
+ 931 : /* LCOV_EXCL_START */
+ 932 : log_fatal("Duplicate 'data' name '%s' at line %u\n", buffer, line);
+ 933 : exit(EXIT_FAILURE);
+ 934 : /* LCOV_EXCL_STOP */
+ 935 : }
+ 936 :
+ 937 : /* if the disk has to be present */
+ 938 1585 : skip_access = 0;
+ 939 1585 : if (!state->opt.skip_disk_access) {
+ 940 : struct stat st;
+ 941 :
+ 942 1423 : if (stat(device, &st) == 0) {
+ 943 1422 : dev = st.st_dev;
+ 944 :
+ 945 : /* read the uuid, if unsupported use an empty one */
+ 946 1422 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) {
+ 947 0 : *uuid = 0;
+ 948 : }
+ 949 :
+ 950 : /* fake a different UUID when testing */
+ 951 1422 : if (state->opt.fake_uuid) {
+ 952 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid);
+ 953 2 : --state->opt.fake_uuid;
+ 954 : }
+ 955 : } else {
+ 956 : /* if the disk can be skipped */
+ 957 1 : if (state->opt.force_device) {
+ 958 : /* use a fake device, and mark the disk to be skipped */
+ 959 1 : dev = 0;
+ 960 1 : *uuid = 0;
+ 961 1 : skip_access = 1;
+ 962 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer);
+ 963 : } else {
+ 964 : /* LCOV_EXCL_START */
+ 965 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line);
+ 966 :
+ 967 : /* in "fix" we allow to continue anyway */
+ 968 : if (strcmp(state->command, "fix") == 0) {
+ 969 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command);
+ 970 : }
+ 971 : exit(EXIT_FAILURE);
+ 972 : /* LCOV_EXCL_STOP */
+ 973 : }
+ 974 : }
+ 975 : } else {
+ 976 : /* use a fake device */
+ 977 162 : dev = 0;
+ 978 162 : *uuid = 0;
+ 979 : }
980 :
- 981 1585 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
- 982 1509 : } else if (strcmp(tag, "smartctl") == 0) {
- 983 : char custom[PATH_MAX];
- 984 :
- 985 366 : ret = sgettok(f, buffer, sizeof(buffer));
- 986 366 : if (ret < 0) {
- 987 : /* LCOV_EXCL_START */
- 988 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line);
- 989 : exit(EXIT_FAILURE);
- 990 : /* LCOV_EXCL_STOP */
- 991 : }
- 992 :
- 993 366 : if (!*buffer) {
- 994 : /* LCOV_EXCL_START */
- 995 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line);
- 996 : exit(EXIT_FAILURE);
- 997 : /* LCOV_EXCL_STOP */
- 998 : }
- 999 :
- 1000 366 : sgetspace(f);
+ 981 1585 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access);
+ 982 :
+ 983 1585 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
+ 984 1509 : } else if (strcmp(tag, "smartctl") == 0) {
+ 985 : char custom[PATH_MAX];
+ 986 :
+ 987 366 : ret = sgettok(f, buffer, sizeof(buffer));
+ 988 366 : if (ret < 0) {
+ 989 : /* LCOV_EXCL_START */
+ 990 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line);
+ 991 : exit(EXIT_FAILURE);
+ 992 : /* LCOV_EXCL_STOP */
+ 993 : }
+ 994 :
+ 995 366 : if (!*buffer) {
+ 996 : /* LCOV_EXCL_START */
+ 997 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line);
+ 998 : exit(EXIT_FAILURE);
+ 999 : /* LCOV_EXCL_STOP */
+ 1000 : }
1001 :
- 1002 366 : ret = sgetlasttok(f, custom, sizeof(custom));
- 1003 366 : if (ret < 0) {
- 1004 : /* LCOV_EXCL_START */
- 1005 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
- 1006 : exit(EXIT_FAILURE);
- 1007 : /* LCOV_EXCL_STOP */
- 1008 : }
- 1009 :
- 1010 366 : if (!*custom) {
- 1011 : /* LCOV_EXCL_START */
- 1012 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line);
- 1013 : exit(EXIT_FAILURE);
- 1014 : /* LCOV_EXCL_STOP */
- 1015 : }
- 1016 :
- 1017 366 : if (validate_smartctl(custom) != 0) {
- 1018 : /* LCOV_EXCL_START */
- 1019 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
- 1020 : exit(EXIT_FAILURE);
- 1021 : /* LCOV_EXCL_STOP */
- 1022 : }
- 1023 :
- 1024 : /* search for parity */
- 1025 366 : if (lev_config_scan(buffer, &level, 0) == 0) {
- 1026 183 : if (state->parity[level].smartctl[0] != 0) {
- 1027 : /* LCOV_EXCL_START */
- 1028 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line);
- 1029 : exit(EXIT_FAILURE);
- 1030 : /* LCOV_EXCL_STOP */
- 1031 : }
- 1032 :
- 1033 183 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom);
- 1034 : } else {
- 1035 : struct snapraid_disk* disk;
- 1036 :
- 1037 : /* search the disk */
- 1038 183 : disk = 0;
- 1039 183 : for (i = state->disklist; i != 0; i = i->next) {
- 1040 183 : disk = i->data;
- 1041 183 : if (strcmp(disk->name, buffer) == 0)
- 1042 183 : break;
- 1043 : }
- 1044 183 : if (!disk) {
- 1045 : /* LCOV_EXCL_START */
- 1046 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line);
- 1047 : exit(EXIT_FAILURE);
- 1048 : /* LCOV_EXCL_STOP */
- 1049 : }
- 1050 183 : if (disk->smartctl[0] != 0) {
- 1051 : /* LCOV_EXCL_START */
- 1052 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
- 1053 : exit(EXIT_FAILURE);
- 1054 : /* LCOV_EXCL_STOP */
- 1055 : }
- 1056 :
- 1057 183 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom);
- 1058 : }
- 1059 1143 : } else if (strcmp(tag, "nohidden") == 0) {
- 1060 0 : state->filter_hidden = 1;
- 1061 1143 : } else if (strcmp(tag, "exclude") == 0) {
- 1062 : struct snapraid_filter* filter;
- 1063 :
- 1064 265 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 1065 265 : if (ret < 0) {
- 1066 : /* LCOV_EXCL_START */
- 1067 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line);
- 1068 : exit(EXIT_FAILURE);
- 1069 : /* LCOV_EXCL_STOP */
- 1070 : }
- 1071 :
- 1072 265 : if (!*buffer) {
- 1073 : /* LCOV_EXCL_START */
- 1074 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line);
- 1075 : exit(EXIT_FAILURE);
- 1076 : /* LCOV_EXCL_STOP */
- 1077 : }
- 1078 :
- 1079 265 : filter = filter_alloc_file(-1, buffer);
- 1080 265 : if (!filter) {
- 1081 : /* LCOV_EXCL_START */
- 1082 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
- 1083 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
- 1084 : exit(EXIT_FAILURE);
- 1085 : /* LCOV_EXCL_STOP */
- 1086 : }
- 1087 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
- 1088 878 : } else if (strcmp(tag, "include") == 0) {
- 1089 : struct snapraid_filter* filter;
- 1090 :
- 1091 265 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 1092 265 : if (ret < 0) {
- 1093 : /* LCOV_EXCL_START */
- 1094 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line);
- 1095 : exit(EXIT_FAILURE);
- 1096 : /* LCOV_EXCL_STOP */
- 1097 : }
- 1098 :
- 1099 265 : if (!*buffer) {
- 1100 : /* LCOV_EXCL_START */
- 1101 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line);
- 1102 : exit(EXIT_FAILURE);
- 1103 : /* LCOV_EXCL_STOP */
- 1104 : }
- 1105 :
- 1106 265 : filter = filter_alloc_file(1, buffer);
- 1107 265 : if (!filter) {
- 1108 : /* LCOV_EXCL_START */
- 1109 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
- 1110 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
- 1111 : exit(EXIT_FAILURE);
- 1112 : /* LCOV_EXCL_STOP */
- 1113 : }
- 1114 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
- 1115 613 : } else if (strcmp(tag, "autosave") == 0) {
- 1116 : char* e;
- 1117 :
- 1118 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
- 1119 41 : if (ret < 0) {
- 1120 : /* LCOV_EXCL_START */
- 1121 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
- 1122 : exit(EXIT_FAILURE);
- 1123 : /* LCOV_EXCL_STOP */
- 1124 : }
- 1125 :
- 1126 41 : if (!*buffer) {
- 1127 : /* LCOV_EXCL_START */
- 1128 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line);
- 1129 : exit(EXIT_FAILURE);
- 1130 : /* LCOV_EXCL_STOP */
- 1131 : }
- 1132 :
- 1133 41 : state->autosave = strtoul(buffer, &e, 0);
+ 1002 366 : sgetspace(f);
+ 1003 :
+ 1004 366 : ret = sgetlasttok(f, custom, sizeof(custom));
+ 1005 366 : if (ret < 0) {
+ 1006 : /* LCOV_EXCL_START */
+ 1007 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 1008 : exit(EXIT_FAILURE);
+ 1009 : /* LCOV_EXCL_STOP */
+ 1010 : }
+ 1011 :
+ 1012 366 : if (!*custom) {
+ 1013 : /* LCOV_EXCL_START */
+ 1014 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 1015 : exit(EXIT_FAILURE);
+ 1016 : /* LCOV_EXCL_STOP */
+ 1017 : }
+ 1018 :
+ 1019 366 : if (validate_smartctl(custom) != 0) {
+ 1020 : /* LCOV_EXCL_START */
+ 1021 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
+ 1022 : exit(EXIT_FAILURE);
+ 1023 : /* LCOV_EXCL_STOP */
+ 1024 : }
+ 1025 :
+ 1026 : /* search for parity */
+ 1027 366 : if (lev_config_scan(buffer, &level, 0) == 0) {
+ 1028 183 : if (state->parity[level].smartctl[0] != 0) {
+ 1029 : /* LCOV_EXCL_START */
+ 1030 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line);
+ 1031 : exit(EXIT_FAILURE);
+ 1032 : /* LCOV_EXCL_STOP */
+ 1033 : }
+ 1034 :
+ 1035 183 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom);
+ 1036 : } else {
+ 1037 : struct snapraid_disk* disk;
+ 1038 :
+ 1039 : /* search the disk */
+ 1040 183 : disk = 0;
+ 1041 183 : for (i = state->disklist; i != 0; i = i->next) {
+ 1042 183 : disk = i->data;
+ 1043 183 : if (strcmp(disk->name, buffer) == 0)
+ 1044 183 : break;
+ 1045 : }
+ 1046 183 : if (!disk) {
+ 1047 : /* LCOV_EXCL_START */
+ 1048 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line);
+ 1049 : exit(EXIT_FAILURE);
+ 1050 : /* LCOV_EXCL_STOP */
+ 1051 : }
+ 1052 183 : if (disk->smartctl[0] != 0) {
+ 1053 : /* LCOV_EXCL_START */
+ 1054 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line);
+ 1055 : exit(EXIT_FAILURE);
+ 1056 : /* LCOV_EXCL_STOP */
+ 1057 : }
+ 1058 :
+ 1059 183 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom);
+ 1060 : }
+ 1061 1143 : } else if (strcmp(tag, "nohidden") == 0) {
+ 1062 0 : state->filter_hidden = 1;
+ 1063 1143 : } else if (strcmp(tag, "exclude") == 0) {
+ 1064 : struct snapraid_filter* filter;
+ 1065 :
+ 1066 265 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 1067 265 : if (ret < 0) {
+ 1068 : /* LCOV_EXCL_START */
+ 1069 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line);
+ 1070 : exit(EXIT_FAILURE);
+ 1071 : /* LCOV_EXCL_STOP */
+ 1072 : }
+ 1073 :
+ 1074 265 : if (!*buffer) {
+ 1075 : /* LCOV_EXCL_START */
+ 1076 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line);
+ 1077 : exit(EXIT_FAILURE);
+ 1078 : /* LCOV_EXCL_STOP */
+ 1079 : }
+ 1080 :
+ 1081 265 : filter = filter_alloc_file(-1, buffer);
+ 1082 265 : if (!filter) {
+ 1083 : /* LCOV_EXCL_START */
+ 1084 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
+ 1085 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
+ 1086 : exit(EXIT_FAILURE);
+ 1087 : /* LCOV_EXCL_STOP */
+ 1088 : }
+ 1089 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
+ 1090 878 : } else if (strcmp(tag, "include") == 0) {
+ 1091 : struct snapraid_filter* filter;
+ 1092 :
+ 1093 265 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 1094 265 : if (ret < 0) {
+ 1095 : /* LCOV_EXCL_START */
+ 1096 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line);
+ 1097 : exit(EXIT_FAILURE);
+ 1098 : /* LCOV_EXCL_STOP */
+ 1099 : }
+ 1100 :
+ 1101 265 : if (!*buffer) {
+ 1102 : /* LCOV_EXCL_START */
+ 1103 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line);
+ 1104 : exit(EXIT_FAILURE);
+ 1105 : /* LCOV_EXCL_STOP */
+ 1106 : }
+ 1107 :
+ 1108 265 : filter = filter_alloc_file(1, buffer);
+ 1109 265 : if (!filter) {
+ 1110 : /* LCOV_EXCL_START */
+ 1111 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
+ 1112 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
+ 1113 : exit(EXIT_FAILURE);
+ 1114 : /* LCOV_EXCL_STOP */
+ 1115 : }
+ 1116 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
+ 1117 613 : } else if (strcmp(tag, "autosave") == 0) {
+ 1118 : char* e;
+ 1119 :
+ 1120 41 : ret = sgetlasttok(f, buffer, sizeof(buffer));
+ 1121 41 : if (ret < 0) {
+ 1122 : /* LCOV_EXCL_START */
+ 1123 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
+ 1124 : exit(EXIT_FAILURE);
+ 1125 : /* LCOV_EXCL_STOP */
+ 1126 : }
+ 1127 :
+ 1128 41 : if (!*buffer) {
+ 1129 : /* LCOV_EXCL_START */
+ 1130 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line);
+ 1131 : exit(EXIT_FAILURE);
+ 1132 : /* LCOV_EXCL_STOP */
+ 1133 : }
1134 :
- 1135 41 : if (!e || *e) {
- 1136 : /* LCOV_EXCL_START */
- 1137 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
- 1138 : exit(EXIT_FAILURE);
- 1139 : /* LCOV_EXCL_STOP */
- 1140 : }
- 1141 :
- 1142 : /* convert to GB */
- 1143 41 : state->autosave *= GIGA;
- 1144 572 : } else if (tag[0] == 0) {
- 1145 : /* allow empty lines */
- 1146 41 : } else if (tag[0] == '#') {
- 1147 41 : ret = sgetline(f, buffer, sizeof(buffer));
- 1148 41 : if (ret < 0) {
- 1149 : /* LCOV_EXCL_START */
- 1150 : log_fatal("Invalid comment in '%s' at line %u\n", path, line);
- 1151 : exit(EXIT_FAILURE);
- 1152 : /* LCOV_EXCL_STOP */
- 1153 : }
- 1154 : } else {
- 1155 : /* LCOV_EXCL_START */
- 1156 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line);
- 1157 : exit(EXIT_FAILURE);
- 1158 : /* LCOV_EXCL_STOP */
- 1159 : }
- 1160 :
- 1161 : /* skip final spaces */
- 1162 6244 : sgetspace(f);
- 1163 :
- 1164 : /* next line */
- 1165 6244 : c = sgeteol(f);
- 1166 6244 : if (c == EOF) {
- 1167 265 : break;
- 1168 : }
- 1169 5979 : if (c != '\n') {
- 1170 : /* LCOV_EXCL_START */
- 1171 : log_fatal("Extra data in '%s' at line %u\n", path, line);
- 1172 : exit(EXIT_FAILURE);
- 1173 : /* LCOV_EXCL_STOP */
- 1174 : }
- 1175 5979 : ++line;
- 1176 5979 : }
- 1177 :
- 1178 265 : if (serror(f)) {
- 1179 : /* LCOV_EXCL_START */
- 1180 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
- 1181 : exit(EXIT_FAILURE);
- 1182 : /* LCOV_EXCL_STOP */
- 1183 : }
- 1184 :
- 1185 265 : sclose(f);
+ 1135 41 : state->autosave = strtoul(buffer, &e, 0);
+ 1136 :
+ 1137 41 : if (!e || *e) {
+ 1138 : /* LCOV_EXCL_START */
+ 1139 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line);
+ 1140 : exit(EXIT_FAILURE);
+ 1141 : /* LCOV_EXCL_STOP */
+ 1142 : }
+ 1143 :
+ 1144 : /* convert to GB */
+ 1145 41 : state->autosave *= GIGA;
+ 1146 572 : } else if (tag[0] == 0) {
+ 1147 : /* allow empty lines */
+ 1148 41 : } else if (tag[0] == '#') {
+ 1149 41 : ret = sgetline(f, buffer, sizeof(buffer));
+ 1150 41 : if (ret < 0) {
+ 1151 : /* LCOV_EXCL_START */
+ 1152 : log_fatal("Invalid comment in '%s' at line %u\n", path, line);
+ 1153 : exit(EXIT_FAILURE);
+ 1154 : /* LCOV_EXCL_STOP */
+ 1155 : }
+ 1156 : } else {
+ 1157 : /* LCOV_EXCL_START */
+ 1158 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line);
+ 1159 : exit(EXIT_FAILURE);
+ 1160 : /* LCOV_EXCL_STOP */
+ 1161 : }
+ 1162 :
+ 1163 : /* skip final spaces */
+ 1164 6244 : sgetspace(f);
+ 1165 :
+ 1166 : /* next line */
+ 1167 6244 : c = sgeteol(f);
+ 1168 6244 : if (c == EOF) {
+ 1169 265 : break;
+ 1170 : }
+ 1171 5979 : if (c != '\n') {
+ 1172 : /* LCOV_EXCL_START */
+ 1173 : log_fatal("Extra data in '%s' at line %u\n", path, line);
+ 1174 : exit(EXIT_FAILURE);
+ 1175 : /* LCOV_EXCL_STOP */
+ 1176 : }
+ 1177 5979 : ++line;
+ 1178 5979 : }
+ 1179 :
+ 1180 265 : if (serror(f)) {
+ 1181 : /* LCOV_EXCL_START */
+ 1182 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line);
+ 1183 : exit(EXIT_FAILURE);
+ 1184 : /* LCOV_EXCL_STOP */
+ 1185 : }
1186 :
- 1187 265 : state_config_check(state, path, filterlist_disk);
+ 1187 265 : sclose(f);
1188 :
- 1189 : /* select the default hash */
- 1190 265 : if (state->opt.force_murmur3) {
- 1191 1 : state->besthash = HASH_MURMUR3;
- 1192 264 : } else if (state->opt.force_spooky2) {
- 1193 1 : state->besthash = HASH_SPOOKY2;
- 1194 : } else {
- 1195 : #ifdef CONFIG_X86
- 1196 263 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult())
- 1197 263 : state->besthash = HASH_MURMUR3;
- 1198 : else
- 1199 0 : state->besthash = HASH_SPOOKY2;
- 1200 : #else
- 1201 : if (sizeof(void*) == 4)
- 1202 : state->besthash = HASH_MURMUR3;
- 1203 : else
- 1204 : state->besthash = HASH_SPOOKY2;
- 1205 : #endif
- 1206 : }
- 1207 :
- 1208 : /* by default use the best hash */
- 1209 265 : state->hash = state->besthash;
- 1210 :
- 1211 : /* by default use a random hash seed */
- 1212 265 : if (randomize(state->hashseed, HASH_MAX) != 0) {
- 1213 : /* LCOV_EXCL_START */
- 1214 : log_fatal("Failed to get random values.\n");
- 1215 : exit(EXIT_FAILURE);
- 1216 : /* LCOV_EXCL_STOP */
- 1217 : }
- 1218 :
- 1219 : /* no previous hash by default */
- 1220 265 : state->prevhash = HASH_UNDEFINED;
- 1221 :
- 1222 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
+ 1189 265 : state_config_check(state, path, filterlist_disk);
+ 1190 :
+ 1191 : /* select the default hash */
+ 1192 265 : if (state->opt.force_murmur3) {
+ 1193 1 : state->besthash = HASH_MURMUR3;
+ 1194 264 : } else if (state->opt.force_spooky2) {
+ 1195 1 : state->besthash = HASH_SPOOKY2;
+ 1196 : } else {
+ 1197 : #ifdef CONFIG_X86
+ 1198 263 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult())
+ 1199 263 : state->besthash = HASH_MURMUR3;
+ 1200 : else
+ 1201 0 : state->besthash = HASH_SPOOKY2;
+ 1202 : #else
+ 1203 : if (sizeof(void*) == 4)
+ 1204 : state->besthash = HASH_MURMUR3;
+ 1205 : else
+ 1206 : state->besthash = HASH_SPOOKY2;
+ 1207 : #endif
+ 1208 : }
+ 1209 :
+ 1210 : /* by default use the best hash */
+ 1211 265 : state->hash = state->besthash;
+ 1212 :
+ 1213 : /* by default use a random hash seed */
+ 1214 265 : if (randomize(state->hashseed, HASH_MAX) != 0) {
+ 1215 : /* LCOV_EXCL_START */
+ 1216 : log_fatal("Failed to get random values.\n");
+ 1217 : exit(EXIT_FAILURE);
+ 1218 : /* LCOV_EXCL_STOP */
+ 1219 : }
+ 1220 :
+ 1221 : /* no previous hash by default */
+ 1222 265 : state->prevhash = HASH_UNDEFINED;
1223 :
- 1224 265 : log_tag("blocksize:%u\n", state->block_size);
- 1225 1850 : for (i = state->disklist; i != 0; i = i->next) {
- 1226 1585 : struct snapraid_disk* disk = i->data;
- 1227 1585 : log_tag("data:%s:%s\n", disk->name, disk->dir);
- 1228 : }
- 1229 :
- 1230 265 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level));
- 1231 1531 : for (l = 0; l < state->level; ++l)
- 1232 6330 : for (s = 0; s < state->parity[l].split_mac; ++s)
- 1233 5064 : log_tag("%s:%u:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path);
- 1234 265 : if (state->pool[0] != 0)
- 1235 41 : log_tag("pool:%s\n", state->pool);
- 1236 265 : if (state->share[0] != 0)
- 1237 41 : log_tag("share:%s\n", state->share);
- 1238 265 : if (state->autosave != 0)
- 1239 41 : log_tag("autosave:%" PRIu64 "\n", state->autosave);
- 1240 795 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) {
- 1241 : char out[PATH_MAX];
- 1242 530 : struct snapraid_filter* filter = i->data;
- 1243 530 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out)));
- 1244 : }
- 1245 265 : if (state->filter_hidden)
- 1246 0 : log_tag("filter:nohidden:\n");
- 1247 265 : log_flush();
- 1248 : }
- 1249 :
- 1250 : /**
- 1251 : * Find a disk by name.
- 1252 : */
- 1253 7047 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name)
- 1254 : {
- 1255 : tommy_node* i;
- 1256 :
- 1257 24588 : for (i = state->disklist; i != 0; i = i->next) {
- 1258 24580 : struct snapraid_disk* disk = i->data;
- 1259 24580 : if (strcmp(disk->name, name) == 0)
- 1260 7039 : return disk;
- 1261 : }
- 1262 :
- 1263 8 : if (state->no_conf) {
- 1264 : /* without a configuration file, add disks automatically */
- 1265 : struct snapraid_disk* disk;
- 1266 :
- 1267 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0);
+ 1224 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
+ 1225 :
+ 1226 265 : log_tag("blocksize:%u\n", state->block_size);
+ 1227 1850 : for (i = state->disklist; i != 0; i = i->next) {
+ 1228 1585 : struct snapraid_disk* disk = i->data;
+ 1229 1585 : log_tag("data:%s:%s\n", disk->name, disk->dir);
+ 1230 : }
+ 1231 :
+ 1232 265 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level));
+ 1233 1531 : for (l = 0; l < state->level; ++l)
+ 1234 6330 : for (s = 0; s < state->parity[l].split_mac; ++s)
+ 1235 5064 : log_tag("%s:%u:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path);
+ 1236 265 : if (state->pool[0] != 0)
+ 1237 41 : log_tag("pool:%s\n", state->pool);
+ 1238 265 : if (state->share[0] != 0)
+ 1239 41 : log_tag("share:%s\n", state->share);
+ 1240 265 : if (state->autosave != 0)
+ 1241 41 : log_tag("autosave:%" PRIu64 "\n", state->autosave);
+ 1242 795 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) {
+ 1243 : char out[PATH_MAX];
+ 1244 530 : struct snapraid_filter* filter = i->data;
+ 1245 530 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out)));
+ 1246 : }
+ 1247 265 : if (state->filter_hidden)
+ 1248 0 : log_tag("filter:nohidden:\n");
+ 1249 265 : log_flush();
+ 1250 : }
+ 1251 :
+ 1252 : /**
+ 1253 : * Find a disk by name.
+ 1254 : */
+ 1255 7047 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name)
+ 1256 : {
+ 1257 : tommy_node* i;
+ 1258 :
+ 1259 24588 : for (i = state->disklist; i != 0; i = i->next) {
+ 1260 24580 : struct snapraid_disk* disk = i->data;
+ 1261 24580 : if (strcmp(disk->name, name) == 0)
+ 1262 7039 : return disk;
+ 1263 : }
+ 1264 :
+ 1265 8 : if (state->no_conf) {
+ 1266 : /* without a configuration file, add disks automatically */
+ 1267 : struct snapraid_disk* disk;
1268 :
- 1269 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
+ 1269 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0);
1270 :
- 1271 6 : return disk;
- 1272 : }
- 1273 :
- 1274 2 : return 0;
- 1275 : }
- 1276 :
- 1277 : /**
- 1278 : * Find a disk by UUID.
- 1279 : */
- 1280 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid)
- 1281 : {
- 1282 : tommy_node* i;
- 1283 2 : struct snapraid_disk* found = 0;
- 1284 :
- 1285 : /* special test case to find the first matching UUID */
- 1286 : /* when testing UUID are all equal or not supported */
- 1287 : /* and we should handle this case specifically */
- 1288 2 : if (state->opt.match_first_uuid)
- 1289 2 : return state->disklist->data;
- 1290 :
- 1291 : /* LCOV_EXCL_START */
- 1292 : /* never find an empty uuid */
- 1293 : if (!*uuid)
- 1294 : return 0;
- 1295 :
- 1296 : for (i = state->disklist; i != 0; i = i->next) {
- 1297 : struct snapraid_disk* disk = i->data;
- 1298 : if (strcmp(disk->uuid, uuid) == 0) {
- 1299 : /* never match duplicate UUID */
- 1300 : if (found)
- 1301 : return 0;
- 1302 : found = disk;
- 1303 : }
- 1304 : }
- 1305 :
- 1306 : return found;
- 1307 : /* LCOV_EXCL_STOP */
- 1308 : }
- 1309 :
- 1310 : /**
- 1311 : * Update the disk mapping if required.
- 1312 : */
- 1313 260 : static void state_map(struct snapraid_state* state)
- 1314 : {
- 1315 : unsigned hole;
- 1316 : tommy_node* i;
- 1317 : unsigned uuid_mismatch;
- 1318 : unsigned diskcount;
- 1319 : unsigned l, s;
- 1320 :
- 1321 : /* remove all the mapping without a disk */
- 1322 : /* this happens when a disk is removed from the configuration file */
- 1323 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */
- 1324 : /* when saving the content file, but we keep this code to import older content files. */
- 1325 1917 : for (i = state->maplist; i != 0; ) {
- 1326 1397 : struct snapraid_map* map = i->data;
- 1327 : struct snapraid_disk* disk;
- 1328 :
- 1329 1397 : disk = find_disk_by_name(state, map->name);
+ 1271 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk);
+ 1272 :
+ 1273 6 : return disk;
+ 1274 : }
+ 1275 :
+ 1276 2 : return 0;
+ 1277 : }
+ 1278 :
+ 1279 : /**
+ 1280 : * Find a disk by UUID.
+ 1281 : */
+ 1282 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid)
+ 1283 : {
+ 1284 : tommy_node* i;
+ 1285 2 : struct snapraid_disk* found = 0;
+ 1286 :
+ 1287 : /* special test case to find the first matching UUID */
+ 1288 : /* when testing UUID are all equal or not supported */
+ 1289 : /* and we should handle this case specifically */
+ 1290 2 : if (state->opt.match_first_uuid)
+ 1291 2 : return state->disklist->data;
+ 1292 :
+ 1293 : /* LCOV_EXCL_START */
+ 1294 : /* never find an empty uuid */
+ 1295 : if (!*uuid)
+ 1296 : return 0;
+ 1297 :
+ 1298 : for (i = state->disklist; i != 0; i = i->next) {
+ 1299 : struct snapraid_disk* disk = i->data;
+ 1300 : if (strcmp(disk->uuid, uuid) == 0) {
+ 1301 : /* never match duplicate UUID */
+ 1302 : if (found)
+ 1303 : return 0;
+ 1304 : found = disk;
+ 1305 : }
+ 1306 : }
+ 1307 :
+ 1308 : return found;
+ 1309 : /* LCOV_EXCL_STOP */
+ 1310 : }
+ 1311 :
+ 1312 : /**
+ 1313 : * Update the disk mapping if required.
+ 1314 : */
+ 1315 260 : static void state_map(struct snapraid_state* state)
+ 1316 : {
+ 1317 : unsigned hole;
+ 1318 : tommy_node* i;
+ 1319 : unsigned uuid_mismatch;
+ 1320 : unsigned diskcount;
+ 1321 : unsigned l, s;
+ 1322 :
+ 1323 : /* remove all the mapping without a disk */
+ 1324 : /* this happens when a disk is removed from the configuration file */
+ 1325 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */
+ 1326 : /* when saving the content file, but we keep this code to import older content files. */
+ 1327 1917 : for (i = state->maplist; i != 0; ) {
+ 1328 1397 : struct snapraid_map* map = i->data;
+ 1329 : struct snapraid_disk* disk;
1330 :
- 1331 : /* go to the next mapping before removing */
- 1332 1397 : i = i->next;
- 1333 :
- 1334 1397 : if (disk == 0) {
- 1335 : /* disk not found, remove the mapping */
- 1336 0 : tommy_list_remove_existing(&state->maplist, &map->node);
- 1337 0 : map_free(map);
- 1338 : }
- 1339 : }
- 1340 :
- 1341 : /* maps each unmapped disk present in the configuration file in the first available hole */
- 1342 : /* this happens when you add disks for the first time in the configuration file */
- 1343 260 : hole = 0; /* first position to try */
- 1344 1815 : for (i = state->disklist; i != 0; i = i->next) {
- 1345 1555 : struct snapraid_disk* disk = i->data;
- 1346 : struct snapraid_map* map;
- 1347 : tommy_node* j;
- 1348 :
- 1349 : /* check if the disk is already mapped */
- 1350 5430 : for (j = state->maplist; j != 0; j = j->next) {
- 1351 5272 : map = j->data;
- 1352 5272 : if (strcmp(disk->name, map->name) == 0) {
- 1353 : /* mapping found */
- 1354 1397 : break;
- 1355 : }
- 1356 : }
- 1357 1555 : if (j != 0) {
- 1358 : /* mapping is present, then copy the free blocks into to disk */
- 1359 1397 : disk->total_blocks = map->total_blocks;
- 1360 1397 : disk->free_blocks = map->free_blocks;
- 1361 1397 : continue;
- 1362 : }
- 1363 :
- 1364 : /* mapping not found, search for an hole */
- 1365 : while (1) {
- 1366 1100 : for (j = state->maplist; j != 0; j = j->next) {
- 1367 942 : map = j->data;
- 1368 942 : if (map->position == hole) {
- 1369 : /* position already used */
- 1370 158 : break;
- 1371 : }
- 1372 : }
- 1373 316 : if (j == 0) {
- 1374 : /* hole found */
- 1375 158 : break;
- 1376 : }
- 1377 :
- 1378 : /* try with the next one */
- 1379 158 : ++hole;
- 1380 158 : }
- 1381 :
- 1382 : /* insert the new mapping */
- 1383 158 : map = map_alloc(disk->name, hole, 0, 0, "");
- 1384 :
- 1385 158 : tommy_list_insert_tail(&state->maplist, &map->node, map);
- 1386 : }
- 1387 :
- 1388 : /* without configuration don't check for number of data disks or uuid changes */
- 1389 260 : if (state->no_conf)
- 1390 261 : return;
- 1391 :
- 1392 : /* counter for the number of UUID mismatches */
- 1393 259 : uuid_mismatch = 0;
- 1394 :
- 1395 : /* check if mapping match the disk uuid */
- 1396 259 : if (!state->opt.skip_disk_access) {
- 1397 1626 : for (i = state->maplist; i != 0; i = i->next) {
- 1398 1393 : struct snapraid_map* map = i->data;
- 1399 : struct snapraid_disk* disk;
- 1400 :
- 1401 1393 : disk = find_disk_by_name(state, map->name);
- 1402 1393 : if (disk == 0) {
- 1403 : /* LCOV_EXCL_START */
- 1404 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
- 1405 : os_abort();
- 1406 : /* LCOV_EXCL_STOP */
- 1407 : }
- 1408 :
- 1409 1393 : if (disk->has_unsupported_uuid) {
- 1410 : /* if uuid is not available, skip this one */
- 1411 1 : continue;
- 1412 : }
- 1413 :
- 1414 : /* if the uuid is changed */
- 1415 1392 : if (strcmp(disk->uuid, map->uuid) != 0) {
- 1416 : /* mark the disk as with an UUID change */
- 1417 113 : disk->has_different_uuid = 1;
- 1418 :
- 1419 : /* if the previous uuid is available */
- 1420 113 : if (map->uuid[0] != 0) {
- 1421 : /* count the number of uuid change */
- 1422 4 : ++uuid_mismatch;
- 1423 4 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid);
- 1424 : } else {
- 1425 : /* no message here, because having a disk without */
- 1426 : /* UUID is the normal state of an empty disk */
- 1427 109 : disk->had_empty_uuid = 1;
- 1428 : }
- 1429 :
- 1430 : /* update the uuid in the mapping, */
- 1431 113 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid);
- 1432 :
- 1433 : /* write the new state with the new uuid */
- 1434 113 : state->need_write = 1;
- 1435 : }
- 1436 : }
- 1437 : }
- 1438 :
- 1439 : /* check the parity uuid */
- 1440 259 : if (!state->opt.skip_parity_access) {
- 1441 1273 : for (l = 0; l < state->level; ++l) {
- 1442 5260 : for (s = 0; s < state->parity[l].split_mac; ++s) {
- 1443 : char uuid[UUID_MAX];
- 1444 : int ret;
- 1445 :
- 1446 4208 : ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid));
- 1447 4208 : if (ret != 0) {
- 1448 : /* uuid not available, just ignore */
- 1449 4 : continue;
- 1450 : }
- 1451 :
- 1452 : /* if the uuid is changed */
- 1453 4204 : if (strcmp(uuid, state->parity[l].split_map[s].uuid) != 0) {
- 1454 : /* if the previous uuid is available */
- 1455 184 : if (state->parity[l].split_map[s].uuid[0] != 0) {
- 1456 : /* count the number of uuid change */
- 1457 0 : ++uuid_mismatch;
- 1458 0 : log_fatal("UUID change for parity '%s[%u]' from '%s' to '%s'\n", lev_config_name(l), s, state->parity[l].split_map[s].uuid, uuid);
- 1459 : }
- 1460 :
- 1461 : /* update the uuid */
- 1462 184 : pathcpy(state->parity[l].split_map[s].uuid, sizeof(state->parity[l].split_map[s].uuid), uuid);
- 1463 :
- 1464 : /* write the new state with the new uuid */
- 1465 184 : state->need_write = 1;
- 1466 : }
- 1467 : }
- 1468 : }
- 1469 : }
- 1470 :
- 1471 259 : if (!state->opt.force_uuid && uuid_mismatch > state->level) {
- 1472 : /* LCOV_EXCL_START */
- 1473 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n");
- 1474 : log_fatal("If this happens because you really replaced them,\n");
- 1475 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command);
- 1476 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n");
- 1477 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n");
- 1478 : exit(EXIT_FAILURE);
- 1479 : /* LCOV_EXCL_STOP */
- 1480 : }
- 1481 :
- 1482 : /* count the number of data disks, including holes left after removing some */
- 1483 259 : diskcount = 0;
- 1484 1808 : for (i = state->maplist; i != 0; i = i->next) {
- 1485 1549 : struct snapraid_map* map = i->data;
- 1486 :
- 1487 1549 : if (map->position + 1 > diskcount)
- 1488 1367 : diskcount = map->position + 1;
- 1489 : }
- 1490 :
- 1491 : /* ensure to don't go over the limit of the RAID engine */
- 1492 259 : if (diskcount > RAID_DATA_MAX) {
- 1493 : /* LCOV_EXCL_START */
- 1494 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX);
- 1495 : exit(EXIT_FAILURE);
- 1496 : /* LCOV_EXCL_STOP */
- 1497 : }
- 1498 :
- 1499 : /* now count the real number of data disks, excluding holes left after removing some */
- 1500 259 : diskcount = tommy_list_count(&state->maplist);
- 1501 :
- 1502 : /* recommend number of parities */
- 1503 259 : if (!state->opt.no_warnings) {
- 1504 1 : if (diskcount >= 36 && state->level < 6) {
- 1505 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
- 1506 1 : } else if (diskcount >= 29 && state->level < 5) {
- 1507 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
- 1508 1 : } else if (diskcount >= 22 && state->level < 4) {
- 1509 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount);
- 1510 1 : } else if (diskcount >= 15 && state->level < 3) {
- 1511 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
- 1512 1 : } else if (diskcount >= 5 && state->level < 2) {
- 1513 0 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
- 1514 : }
- 1515 : }
- 1516 : }
- 1517 :
- 1518 173 : void state_refresh(struct snapraid_state* state)
- 1519 : {
- 1520 : tommy_node* i;
- 1521 : unsigned l, s;
- 1522 :
- 1523 : /* for all disks */
- 1524 1209 : for (i = state->maplist; i != 0; i = i->next) {
- 1525 1036 : struct snapraid_map* map = i->data;
- 1526 : struct snapraid_disk* disk;
- 1527 : uint64_t total_space;
- 1528 : uint64_t free_space;
- 1529 : int ret;
- 1530 :
- 1531 1036 : disk = find_disk_by_name(state, map->name);
- 1532 1036 : if (disk == 0) {
- 1533 : /* LCOV_EXCL_START */
- 1534 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
- 1535 : os_abort();
- 1536 : /* LCOV_EXCL_STOP */
- 1537 : }
- 1538 :
- 1539 1036 : ret = fsinfo(disk->dir, 0, &total_space, &free_space);
- 1540 1036 : if (ret != 0) {
- 1541 : /* LCOV_EXCL_START */
- 1542 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
- 1543 : exit(EXIT_FAILURE);
- 1544 : /* LCOV_EXCL_STOP */
- 1545 : }
- 1546 :
- 1547 : /* set the new free blocks */
- 1548 1036 : map->total_blocks = total_space / state->block_size;
- 1549 1036 : map->free_blocks = free_space / state->block_size;
- 1550 :
- 1551 : /* also update the disk info */
- 1552 1036 : disk->total_blocks = map->total_blocks;
- 1553 1036 : disk->free_blocks = map->free_blocks;
- 1554 : }
- 1555 :
- 1556 : /* for all parities */
- 1557 1141 : for (l = 0; l < state->level; ++l) {
- 1558 : /* set the new free blocks */
- 1559 968 : state->parity[l].total_blocks = 0;
- 1560 968 : state->parity[l].free_blocks = 0;
- 1561 :
- 1562 4840 : for (s = 0; s < state->parity[l].split_mac; ++s) {
- 1563 : uint64_t total_space;
- 1564 : uint64_t free_space;
- 1565 : int ret;
- 1566 :
- 1567 3872 : ret = fsinfo(state->parity[l].split_map[s].path, 0, &total_space, &free_space);
- 1568 3872 : if (ret != 0) {
- 1569 : /* LCOV_EXCL_START */
- 1570 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno));
- 1571 : exit(EXIT_FAILURE);
- 1572 : /* LCOV_EXCL_STOP */
- 1573 : }
- 1574 :
- 1575 : /* add the new free blocks */
- 1576 3872 : state->parity[l].total_blocks += total_space / state->block_size;
- 1577 3872 : state->parity[l].free_blocks += free_space / state->block_size;
- 1578 : }
- 1579 : }
- 1580 :
- 1581 : /* note what we don't set need_write = 1, because we don't want */
- 1582 : /* to update the content file only for the free space info. */
- 1583 173 : }
- 1584 :
- 1585 : /**
- 1586 : * Check the content.
- 1587 : */
- 1588 253 : static void state_content_check(struct snapraid_state* state, const char* path)
- 1589 : {
- 1590 : tommy_node* i;
- 1591 :
- 1592 : /* check that any map has different name and position */
- 1593 1766 : for (i = state->maplist; i != 0; i = i->next) {
- 1594 1513 : struct snapraid_map* map = i->data;
- 1595 : tommy_node* j;
- 1596 5283 : for (j = i->next; j != 0; j = j->next) {
- 1597 3770 : struct snapraid_map* other = j->data;
- 1598 3770 : if (strcmp(map->name, other->name) == 0) {
- 1599 : /* LCOV_EXCL_START */
- 1600 : log_fatal("Colliding 'map' disk specification in '%s'\n", path);
- 1601 : exit(EXIT_FAILURE);
- 1602 : /* LCOV_EXCL_STOP */
- 1603 : }
- 1604 3770 : if (map->position == other->position) {
- 1605 : /* LCOV_EXCL_START */
- 1606 : log_fatal("Colliding 'map' index specification in '%s'\n", path);
- 1607 : exit(EXIT_FAILURE);
- 1608 : /* LCOV_EXCL_STOP */
- 1609 : }
- 1610 : }
- 1611 : }
- 1612 253 : }
- 1613 :
- 1614 : /**
- 1615 : * Check if the position is REQUIRED, or we can completely clear it from the state.
- 1616 : *
- 1617 : * Note that position with only DELETED blocks are discarged.
- 1618 : */
- 1619 756099 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos)
- 1620 : {
- 1621 : tommy_node* i;
- 1622 :
- 1623 : /* check for each disk */
- 1624 802725 : for (i = state->disklist; i != 0; i = i->next) {
- 1625 802725 : struct snapraid_disk* disk = i->data;
- 1626 802725 : struct snapraid_block* block = fs_par2block_find(disk, pos);
- 1627 :
- 1628 : /* if we have at least one file, the position is needed */
- 1629 802725 : if (block_has_file(block))
- 1630 756099 : return 1;
- 1631 : }
- 1632 :
- 1633 0 : return 0;
- 1634 : }
+ 1331 1397 : disk = find_disk_by_name(state, map->name);
+ 1332 :
+ 1333 : /* go to the next mapping before removing */
+ 1334 1397 : i = i->next;
+ 1335 :
+ 1336 1397 : if (disk == 0) {
+ 1337 : /* disk not found, remove the mapping */
+ 1338 0 : tommy_list_remove_existing(&state->maplist, &map->node);
+ 1339 0 : map_free(map);
+ 1340 : }
+ 1341 : }
+ 1342 :
+ 1343 : /* maps each unmapped disk present in the configuration file in the first available hole */
+ 1344 : /* this happens when you add disks for the first time in the configuration file */
+ 1345 260 : hole = 0; /* first position to try */
+ 1346 1815 : for (i = state->disklist; i != 0; i = i->next) {
+ 1347 1555 : struct snapraid_disk* disk = i->data;
+ 1348 : struct snapraid_map* map;
+ 1349 : tommy_node* j;
+ 1350 :
+ 1351 : /* check if the disk is already mapped */
+ 1352 5430 : for (j = state->maplist; j != 0; j = j->next) {
+ 1353 5272 : map = j->data;
+ 1354 5272 : if (strcmp(disk->name, map->name) == 0) {
+ 1355 : /* mapping found */
+ 1356 1397 : break;
+ 1357 : }
+ 1358 : }
+ 1359 1555 : if (j != 0) {
+ 1360 : /* mapping is present, then copy the free blocks into to disk */
+ 1361 1397 : disk->total_blocks = map->total_blocks;
+ 1362 1397 : disk->free_blocks = map->free_blocks;
+ 1363 1397 : continue;
+ 1364 : }
+ 1365 :
+ 1366 : /* mapping not found, search for an hole */
+ 1367 : while (1) {
+ 1368 1100 : for (j = state->maplist; j != 0; j = j->next) {
+ 1369 942 : map = j->data;
+ 1370 942 : if (map->position == hole) {
+ 1371 : /* position already used */
+ 1372 158 : break;
+ 1373 : }
+ 1374 : }
+ 1375 316 : if (j == 0) {
+ 1376 : /* hole found */
+ 1377 158 : break;
+ 1378 : }
+ 1379 :
+ 1380 : /* try with the next one */
+ 1381 158 : ++hole;
+ 1382 158 : }
+ 1383 :
+ 1384 : /* insert the new mapping */
+ 1385 158 : map = map_alloc(disk->name, hole, 0, 0, "");
+ 1386 :
+ 1387 158 : tommy_list_insert_tail(&state->maplist, &map->node, map);
+ 1388 : }
+ 1389 :
+ 1390 : /* without configuration don't check for number of data disks or uuid changes */
+ 1391 260 : if (state->no_conf)
+ 1392 261 : return;
+ 1393 :
+ 1394 : /* counter for the number of UUID mismatches */
+ 1395 259 : uuid_mismatch = 0;
+ 1396 :
+ 1397 : /* check if mapping match the disk uuid */
+ 1398 259 : if (!state->opt.skip_disk_access) {
+ 1399 1626 : for (i = state->maplist; i != 0; i = i->next) {
+ 1400 1393 : struct snapraid_map* map = i->data;
+ 1401 : struct snapraid_disk* disk;
+ 1402 :
+ 1403 1393 : disk = find_disk_by_name(state, map->name);
+ 1404 1393 : if (disk == 0) {
+ 1405 : /* LCOV_EXCL_START */
+ 1406 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
+ 1407 : os_abort();
+ 1408 : /* LCOV_EXCL_STOP */
+ 1409 : }
+ 1410 :
+ 1411 1393 : if (disk->has_unsupported_uuid) {
+ 1412 : /* if uuid is not available, skip this one */
+ 1413 1 : continue;
+ 1414 : }
+ 1415 :
+ 1416 : /* if the uuid is changed */
+ 1417 1392 : if (strcmp(disk->uuid, map->uuid) != 0) {
+ 1418 : /* mark the disk as with an UUID change */
+ 1419 113 : disk->has_different_uuid = 1;
+ 1420 :
+ 1421 : /* if the previous uuid is available */
+ 1422 113 : if (map->uuid[0] != 0) {
+ 1423 : /* count the number of uuid change */
+ 1424 4 : ++uuid_mismatch;
+ 1425 4 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid);
+ 1426 : } else {
+ 1427 : /* no message here, because having a disk without */
+ 1428 : /* UUID is the normal state of an empty disk */
+ 1429 109 : disk->had_empty_uuid = 1;
+ 1430 : }
+ 1431 :
+ 1432 : /* update the uuid in the mapping, */
+ 1433 113 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid);
+ 1434 :
+ 1435 : /* write the new state with the new uuid */
+ 1436 113 : state->need_write = 1;
+ 1437 : }
+ 1438 : }
+ 1439 : }
+ 1440 :
+ 1441 : /* check the parity uuid */
+ 1442 259 : if (!state->opt.skip_parity_access) {
+ 1443 1273 : for (l = 0; l < state->level; ++l) {
+ 1444 5260 : for (s = 0; s < state->parity[l].split_mac; ++s) {
+ 1445 : char uuid[UUID_MAX];
+ 1446 : int ret;
+ 1447 :
+ 1448 4208 : ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid));
+ 1449 4208 : if (ret != 0) {
+ 1450 : /* uuid not available, just ignore */
+ 1451 4 : continue;
+ 1452 : }
+ 1453 :
+ 1454 : /* if the uuid is changed */
+ 1455 4204 : if (strcmp(uuid, state->parity[l].split_map[s].uuid) != 0) {
+ 1456 : /* if the previous uuid is available */
+ 1457 184 : if (state->parity[l].split_map[s].uuid[0] != 0) {
+ 1458 : /* count the number of uuid change */
+ 1459 0 : ++uuid_mismatch;
+ 1460 0 : log_fatal("UUID change for parity '%s[%u]' from '%s' to '%s'\n", lev_config_name(l), s, state->parity[l].split_map[s].uuid, uuid);
+ 1461 : }
+ 1462 :
+ 1463 : /* update the uuid */
+ 1464 184 : pathcpy(state->parity[l].split_map[s].uuid, sizeof(state->parity[l].split_map[s].uuid), uuid);
+ 1465 :
+ 1466 : /* write the new state with the new uuid */
+ 1467 184 : state->need_write = 1;
+ 1468 : }
+ 1469 : }
+ 1470 : }
+ 1471 : }
+ 1472 :
+ 1473 259 : if (!state->opt.force_uuid && uuid_mismatch > state->level) {
+ 1474 : /* LCOV_EXCL_START */
+ 1475 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n");
+ 1476 : log_fatal("If this happens because you really replaced them,\n");
+ 1477 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command);
+ 1478 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n");
+ 1479 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n");
+ 1480 : exit(EXIT_FAILURE);
+ 1481 : /* LCOV_EXCL_STOP */
+ 1482 : }
+ 1483 :
+ 1484 : /* count the number of data disks, including holes left after removing some */
+ 1485 259 : diskcount = 0;
+ 1486 1808 : for (i = state->maplist; i != 0; i = i->next) {
+ 1487 1549 : struct snapraid_map* map = i->data;
+ 1488 :
+ 1489 1549 : if (map->position + 1 > diskcount)
+ 1490 1367 : diskcount = map->position + 1;
+ 1491 : }
+ 1492 :
+ 1493 : /* ensure to don't go over the limit of the RAID engine */
+ 1494 259 : if (diskcount > RAID_DATA_MAX) {
+ 1495 : /* LCOV_EXCL_START */
+ 1496 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX);
+ 1497 : exit(EXIT_FAILURE);
+ 1498 : /* LCOV_EXCL_STOP */
+ 1499 : }
+ 1500 :
+ 1501 : /* now count the real number of data disks, excluding holes left after removing some */
+ 1502 259 : diskcount = tommy_list_count(&state->maplist);
+ 1503 :
+ 1504 : /* recommend number of parities */
+ 1505 259 : if (!state->opt.no_warnings) {
+ 1506 : /* intentionally use log_fatal() instead of log_error() to give more visibility at the warning */
+ 1507 1 : if (diskcount >= 36 && state->level < 6) {
+ 1508 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
+ 1509 1 : } else if (diskcount >= 29 && state->level < 5) {
+ 1510 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
+ 1511 1 : } else if (diskcount >= 22 && state->level < 4) {
+ 1512 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount);
+ 1513 1 : } else if (diskcount >= 15 && state->level < 3) {
+ 1514 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
+ 1515 1 : } else if (diskcount >= 5 && state->level < 2) {
+ 1516 0 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
+ 1517 : }
+ 1518 : }
+ 1519 : }
+ 1520 :
+ 1521 173 : void state_refresh(struct snapraid_state* state)
+ 1522 : {
+ 1523 : tommy_node* i;
+ 1524 : unsigned l, s;
+ 1525 :
+ 1526 : /* for all disks */
+ 1527 1209 : for (i = state->maplist; i != 0; i = i->next) {
+ 1528 1036 : struct snapraid_map* map = i->data;
+ 1529 : struct snapraid_disk* disk;
+ 1530 : uint64_t total_space;
+ 1531 : uint64_t free_space;
+ 1532 : int ret;
+ 1533 :
+ 1534 1036 : disk = find_disk_by_name(state, map->name);
+ 1535 1036 : if (disk == 0) {
+ 1536 : /* LCOV_EXCL_START */
+ 1537 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
+ 1538 : os_abort();
+ 1539 : /* LCOV_EXCL_STOP */
+ 1540 : }
+ 1541 :
+ 1542 1036 : ret = fsinfo(disk->dir, 0, &total_space, &free_space);
+ 1543 1036 : if (ret != 0) {
+ 1544 : /* LCOV_EXCL_START */
+ 1545 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
+ 1546 : exit(EXIT_FAILURE);
+ 1547 : /* LCOV_EXCL_STOP */
+ 1548 : }
+ 1549 :
+ 1550 : /* set the new free blocks */
+ 1551 1036 : map->total_blocks = total_space / state->block_size;
+ 1552 1036 : map->free_blocks = free_space / state->block_size;
+ 1553 :
+ 1554 : /* also update the disk info */
+ 1555 1036 : disk->total_blocks = map->total_blocks;
+ 1556 1036 : disk->free_blocks = map->free_blocks;
+ 1557 : }
+ 1558 :
+ 1559 : /* for all parities */
+ 1560 1141 : for (l = 0; l < state->level; ++l) {
+ 1561 : /* set the new free blocks */
+ 1562 968 : state->parity[l].total_blocks = 0;
+ 1563 968 : state->parity[l].free_blocks = 0;
+ 1564 :
+ 1565 4840 : for (s = 0; s < state->parity[l].split_mac; ++s) {
+ 1566 : uint64_t total_space;
+ 1567 : uint64_t free_space;
+ 1568 : int ret;
+ 1569 :
+ 1570 3872 : ret = fsinfo(state->parity[l].split_map[s].path, 0, &total_space, &free_space);
+ 1571 3872 : if (ret != 0) {
+ 1572 : /* LCOV_EXCL_START */
+ 1573 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno));
+ 1574 : exit(EXIT_FAILURE);
+ 1575 : /* LCOV_EXCL_STOP */
+ 1576 : }
+ 1577 :
+ 1578 : /* add the new free blocks */
+ 1579 3872 : state->parity[l].total_blocks += total_space / state->block_size;
+ 1580 3872 : state->parity[l].free_blocks += free_space / state->block_size;
+ 1581 : }
+ 1582 : }
+ 1583 :
+ 1584 : /* note what we don't set need_write = 1, because we don't want */
+ 1585 : /* to update the content file only for the free space info. */
+ 1586 173 : }
+ 1587 :
+ 1588 : /**
+ 1589 : * Check the content.
+ 1590 : */
+ 1591 253 : static void state_content_check(struct snapraid_state* state, const char* path)
+ 1592 : {
+ 1593 : tommy_node* i;
+ 1594 :
+ 1595 : /* check that any map has different name and position */
+ 1596 1766 : for (i = state->maplist; i != 0; i = i->next) {
+ 1597 1513 : struct snapraid_map* map = i->data;
+ 1598 : tommy_node* j;
+ 1599 5283 : for (j = i->next; j != 0; j = j->next) {
+ 1600 3770 : struct snapraid_map* other = j->data;
+ 1601 3770 : if (strcmp(map->name, other->name) == 0) {
+ 1602 : /* LCOV_EXCL_START */
+ 1603 : log_fatal("Colliding 'map' disk specification in '%s'\n", path);
+ 1604 : exit(EXIT_FAILURE);
+ 1605 : /* LCOV_EXCL_STOP */
+ 1606 : }
+ 1607 3770 : if (map->position == other->position) {
+ 1608 : /* LCOV_EXCL_START */
+ 1609 : log_fatal("Colliding 'map' index specification in '%s'\n", path);
+ 1610 : exit(EXIT_FAILURE);
+ 1611 : /* LCOV_EXCL_STOP */
+ 1612 : }
+ 1613 : }
+ 1614 : }
+ 1615 253 : }
+ 1616 :
+ 1617 : /**
+ 1618 : * Check if the position is REQUIRED, or we can completely clear it from the state.
+ 1619 : *
+ 1620 : * Note that position with only DELETED blocks are discarged.
+ 1621 : */
+ 1622 756099 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos)
+ 1623 : {
+ 1624 : tommy_node* i;
+ 1625 :
+ 1626 : /* check for each disk */
+ 1627 802725 : for (i = state->disklist; i != 0; i = i->next) {
+ 1628 802725 : struct snapraid_disk* disk = i->data;
+ 1629 802725 : struct snapraid_block* block = fs_par2block_find(disk, pos);
+ 1630 :
+ 1631 : /* if we have at least one file, the position is needed */
+ 1632 802725 : if (block_has_file(block))
+ 1633 756099 : return 1;
+ 1634 : }
1635 :
- 1636 : /**
- 1637 : * Check if the info block is REQUIREQ.
- 1638 : *
- 1639 : * This is used to ensure that we keep the last check used for scrubbing.
- 1640 : * and that we add it when importing old context files.
+ 1636 0 : return 0;
+ 1637 : }
+ 1638 :
+ 1639 : /**
+ 1640 : * Check if the info block is REQUIREQ.
1641 : *
- 1642 : * Note that you can have position without info blocks, for example
- 1643 : * if all the blocks are not synced.
+ 1642 : * This is used to ensure that we keep the last check used for scrubbing.
+ 1643 : * and that we add it when importing old context files.
1644 : *
- 1645 : * Note also that not requiring an info block, doesn't mean that if present it
- 1646 : * can be discarded.
- 1647 : */
- 1648 1547923 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos)
- 1649 : {
- 1650 : tommy_node* i;
- 1651 :
- 1652 : /* check for each disk */
- 1653 2048488 : for (i = state->disklist; i != 0; i = i->next) {
- 1654 1989723 : struct snapraid_disk* disk = i->data;
- 1655 1989723 : struct snapraid_block* block = fs_par2block_find(disk, pos);
- 1656 :
- 1657 : /* if we have at least one synced file, the info is required */
- 1658 1989723 : if (block_state_get(block) == BLOCK_STATE_BLK)
- 1659 1489158 : return 1;
- 1660 : }
- 1661 :
- 1662 58765 : return 0;
- 1663 : }
+ 1645 : * Note that you can have position without info blocks, for example
+ 1646 : * if all the blocks are not synced.
+ 1647 : *
+ 1648 : * Note also that not requiring an info block, doesn't mean that if present it
+ 1649 : * can be discarded.
+ 1650 : */
+ 1651 1547923 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos)
+ 1652 : {
+ 1653 : tommy_node* i;
+ 1654 :
+ 1655 : /* check for each disk */
+ 1656 2048488 : for (i = state->disklist; i != 0; i = i->next) {
+ 1657 1989723 : struct snapraid_disk* disk = i->data;
+ 1658 1989723 : struct snapraid_block* block = fs_par2block_find(disk, pos);
+ 1659 :
+ 1660 : /* if we have at least one synced file, the info is required */
+ 1661 1989723 : if (block_state_get(block) == BLOCK_STATE_BLK)
+ 1662 1489158 : return 1;
+ 1663 : }
1664 :
- 1665 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos)
- 1666 : {
- 1667 : tommy_node* i;
- 1668 :
- 1669 : /* check for each disk if block is really used */
- 1670 0 : for (i = state->disklist; i != 0; i = i->next) {
- 1671 0 : struct snapraid_disk* disk = i->data;
- 1672 0 : struct snapraid_block* block = fs_par2block_find(disk, pos);
- 1673 :
- 1674 : /* if the block is deleted */
- 1675 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
- 1676 : /* set it to empty */
- 1677 0 : fs_deallocate(disk, pos);
- 1678 : }
- 1679 : }
- 1680 0 : }
- 1681 :
- 1682 : /**
- 1683 : * Check if a block position in a disk is deleted.
- 1684 : */
- 1685 4529621 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos)
- 1686 : {
- 1687 4529621 : struct snapraid_block* block = fs_par2block_find(disk, pos);
- 1688 :
- 1689 4529621 : return block_state_get(block) == BLOCK_STATE_DELETED;
- 1690 : }
+ 1665 58765 : return 0;
+ 1666 : }
+ 1667 :
+ 1668 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos)
+ 1669 : {
+ 1670 : tommy_node* i;
+ 1671 :
+ 1672 : /* check for each disk if block is really used */
+ 1673 0 : for (i = state->disklist; i != 0; i = i->next) {
+ 1674 0 : struct snapraid_disk* disk = i->data;
+ 1675 0 : struct snapraid_block* block = fs_par2block_find(disk, pos);
+ 1676 :
+ 1677 : /* if the block is deleted */
+ 1678 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
+ 1679 : /* set it to empty */
+ 1680 0 : fs_deallocate(disk, pos);
+ 1681 : }
+ 1682 : }
+ 1683 0 : }
+ 1684 :
+ 1685 : /**
+ 1686 : * Check if a block position in a disk is deleted.
+ 1687 : */
+ 1688 4529621 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos)
+ 1689 : {
+ 1690 4529621 : struct snapraid_block* block = fs_par2block_find(disk, pos);
1691 :
- 1692 : /**
- 1693 : * Flush the file checking the final CRC.
- 1694 : * We exploit the fact that the CRC is always stored in the last 4 bytes.
- 1695 : */
- 1696 1 : static void decoding_error(const char* path, STREAM* f)
- 1697 : {
- 1698 : unsigned char buf[4];
- 1699 : uint32_t crc_stored;
- 1700 : uint32_t crc_computed;
- 1701 :
- 1702 1 : if (seof(f)) {
- 1703 : /* LCOV_EXCL_START */
- 1704 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1705 : log_fatal("This content file is truncated. Use an alternate copy.\n");
- 1706 : exit(EXIT_FAILURE);
- 1707 : /* LCOV_EXCL_STOP */
- 1708 : }
- 1709 :
- 1710 1 : if (serror(f)) {
- 1711 : /* LCOV_EXCL_START */
- 1712 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1713 : exit(EXIT_FAILURE);
- 1714 : /* LCOV_EXCL_STOP */
- 1715 : }
- 1716 :
- 1717 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1718 :
- 1719 1 : if (sdeplete(f, buf) != 0) {
- 1720 : /* LCOV_EXCL_START */
- 1721 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 1722 : exit(EXIT_FAILURE);
- 1723 : /* LCOV_EXCL_STOP */
- 1724 : }
- 1725 :
- 1726 : /* get the stored crc from the last four bytes */
- 1727 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
+ 1692 4529621 : return block_state_get(block) == BLOCK_STATE_DELETED;
+ 1693 : }
+ 1694 :
+ 1695 : /**
+ 1696 : * Flush the file checking the final CRC.
+ 1697 : * We exploit the fact that the CRC is always stored in the last 4 bytes.
+ 1698 : */
+ 1699 1 : static void decoding_error(const char* path, STREAM* f)
+ 1700 : {
+ 1701 : unsigned char buf[4];
+ 1702 : uint32_t crc_stored;
+ 1703 : uint32_t crc_computed;
+ 1704 :
+ 1705 1 : if (seof(f)) {
+ 1706 : /* LCOV_EXCL_START */
+ 1707 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1708 : log_fatal("This content file is truncated. Use an alternate copy.\n");
+ 1709 : exit(EXIT_FAILURE);
+ 1710 : /* LCOV_EXCL_STOP */
+ 1711 : }
+ 1712 :
+ 1713 1 : if (serror(f)) {
+ 1714 : /* LCOV_EXCL_START */
+ 1715 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1716 : exit(EXIT_FAILURE);
+ 1717 : /* LCOV_EXCL_STOP */
+ 1718 : }
+ 1719 :
+ 1720 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1721 :
+ 1722 1 : if (sdeplete(f, buf) != 0) {
+ 1723 : /* LCOV_EXCL_START */
+ 1724 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 1725 : exit(EXIT_FAILURE);
+ 1726 : /* LCOV_EXCL_STOP */
+ 1727 : }
1728 :
- 1729 : /* get the computed crc */
- 1730 1 : crc_computed = scrc(f);
+ 1729 : /* get the stored crc from the last four bytes */
+ 1730 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
1731 :
- 1732 : /* adjust the stored crc to include itself */
- 1733 1 : crc_stored = crc32c(crc_stored, buf, 4);
+ 1732 : /* get the computed crc */
+ 1733 1 : crc_computed = scrc(f);
1734 :
- 1735 1 : if (crc_computed != crc_stored) {
- 1736 1 : log_fatal("Mismatching CRC in '%s'\n", path);
- 1737 1 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 1738 1 : exit(EXIT_FAILURE);
- 1739 : } else {
- 1740 0 : log_fatal("The file CRC is correct!\n");
- 1741 : }
- 1742 0 : }
- 1743 :
- 1744 254 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f)
- 1745 : {
- 1746 : block_off_t blockmax;
- 1747 : unsigned count_file;
- 1748 : unsigned count_hardlink;
- 1749 : unsigned count_symlink;
- 1750 : unsigned count_dir;
- 1751 : int crc_checked;
- 1752 : char buffer[PATH_MAX];
- 1753 : int ret;
- 1754 : tommy_array disk_mapping;
- 1755 : uint32_t mapping_max;
- 1756 :
- 1757 254 : blockmax = 0;
- 1758 254 : count_file = 0;
- 1759 254 : count_hardlink = 0;
- 1760 254 : count_symlink = 0;
- 1761 254 : count_dir = 0;
- 1762 254 : crc_checked = 0;
- 1763 254 : mapping_max = 0;
- 1764 254 : tommy_array_init(&disk_mapping);
- 1765 :
- 1766 254 : ret = sread(f, buffer, 12);
- 1767 254 : if (ret < 0) {
- 1768 : /* LCOV_EXCL_START */
- 1769 : decoding_error(path, f);
- 1770 : log_fatal("Invalid header!\n");
- 1771 : os_abort();
- 1772 : /* LCOV_EXCL_STOP */
- 1773 : }
- 1774 :
- 1775 : /*
- 1776 : * File format versions:
- 1777 : * - SNAPCNT1/SnapRAID 4.0 First version.
- 1778 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support.
- 1779 : * The previous 'm' entry is now deprecated, but supported for importing.
- 1780 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'.
- 1781 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'y' for hash size.
- 1782 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'Q' for multi parity file.
- 1783 : * The previous 'P' entry is now deprecated, but supported for importing.
- 1784 : */
- 1785 254 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0
- 1786 254 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0
- 1787 254 : && memcmp(buffer, "SNAPCNT3\n\3\0\0", 12) != 0
- 1788 : ) {
- 1789 : /* LCOV_EXCL_START */
- 1790 : if (memcmp(buffer, "SNAPCNT", 7) != 0) {
- 1791 : decoding_error(path, f);
- 1792 : log_fatal("Invalid header!\n");
- 1793 : os_abort();
- 1794 : } else {
- 1795 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path);
- 1796 : exit(EXIT_FAILURE);
- 1797 : }
- 1798 : /* LCOV_EXCL_STOP */
- 1799 : }
- 1800 :
- 1801 : while (1) {
- 1802 : int c;
+ 1735 : /* adjust the stored crc to include itself */
+ 1736 1 : crc_stored = crc32c(crc_stored, buf, 4);
+ 1737 :
+ 1738 1 : if (crc_computed != crc_stored) {
+ 1739 1 : log_fatal("Mismatching CRC in '%s'\n", path);
+ 1740 1 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 1741 1 : exit(EXIT_FAILURE);
+ 1742 : } else {
+ 1743 0 : log_fatal("The file CRC is correct!\n");
+ 1744 : }
+ 1745 0 : }
+ 1746 :
+ 1747 254 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f)
+ 1748 : {
+ 1749 : block_off_t blockmax;
+ 1750 : unsigned count_file;
+ 1751 : unsigned count_hardlink;
+ 1752 : unsigned count_symlink;
+ 1753 : unsigned count_dir;
+ 1754 : int crc_checked;
+ 1755 : char buffer[PATH_MAX];
+ 1756 : int ret;
+ 1757 : tommy_array disk_mapping;
+ 1758 : uint32_t mapping_max;
+ 1759 :
+ 1760 254 : blockmax = 0;
+ 1761 254 : count_file = 0;
+ 1762 254 : count_hardlink = 0;
+ 1763 254 : count_symlink = 0;
+ 1764 254 : count_dir = 0;
+ 1765 254 : crc_checked = 0;
+ 1766 254 : mapping_max = 0;
+ 1767 254 : tommy_array_init(&disk_mapping);
+ 1768 :
+ 1769 254 : ret = sread(f, buffer, 12);
+ 1770 254 : if (ret < 0) {
+ 1771 : /* LCOV_EXCL_START */
+ 1772 : decoding_error(path, f);
+ 1773 : log_fatal("Invalid header!\n");
+ 1774 : os_abort();
+ 1775 : /* LCOV_EXCL_STOP */
+ 1776 : }
+ 1777 :
+ 1778 : /*
+ 1779 : * File format versions:
+ 1780 : * - SNAPCNT1/SnapRAID 4.0 First version.
+ 1781 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support.
+ 1782 : * The previous 'm' entry is now deprecated, but supported for importing.
+ 1783 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'.
+ 1784 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'y' for hash size.
+ 1785 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'Q' for multi parity file.
+ 1786 : * The previous 'P' entry is now deprecated, but supported for importing.
+ 1787 : */
+ 1788 254 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0
+ 1789 254 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0
+ 1790 254 : && memcmp(buffer, "SNAPCNT3\n\3\0\0", 12) != 0
+ 1791 : ) {
+ 1792 : /* LCOV_EXCL_START */
+ 1793 : if (memcmp(buffer, "SNAPCNT", 7) != 0) {
+ 1794 : decoding_error(path, f);
+ 1795 : log_fatal("Invalid header!\n");
+ 1796 : os_abort();
+ 1797 : } else {
+ 1798 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path);
+ 1799 : exit(EXIT_FAILURE);
+ 1800 : }
+ 1801 : /* LCOV_EXCL_STOP */
+ 1802 : }
1803 :
- 1804 : /* read the command */
- 1805 3735612 : c = sgetc(f);
- 1806 3735612 : if (c == EOF) {
- 1807 253 : break;
- 1808 : }
- 1809 :
- 1810 3735359 : if (c == 'f') {
- 1811 : /* file */
- 1812 : char sub[PATH_MAX];
- 1813 : uint64_t v_size;
- 1814 : uint64_t v_mtime_sec;
- 1815 : uint32_t v_mtime_nsec;
- 1816 : uint64_t v_inode;
- 1817 : uint32_t v_idx;
- 1818 : struct snapraid_file* file;
- 1819 : struct snapraid_disk* disk;
- 1820 : uint32_t mapping;
- 1821 :
- 1822 3611762 : ret = sgetb32(f, &mapping);
- 1823 3611762 : if (ret < 0 || mapping >= mapping_max) {
- 1824 : /* LCOV_EXCL_START */
- 1825 : decoding_error(path, f);
- 1826 : log_fatal("Internal inconsistency in mapping index!\n");
- 1827 : os_abort();
- 1828 : /* LCOV_EXCL_STOP */
- 1829 : }
- 1830 3611762 : disk = tommy_array_get(&disk_mapping, mapping);
- 1831 :
- 1832 3611762 : ret = sgetb64(f, &v_size);
- 1833 3611762 : if (ret < 0) {
- 1834 : /* LCOV_EXCL_START */
- 1835 : decoding_error(path, f);
- 1836 : os_abort();
- 1837 : /* LCOV_EXCL_STOP */
- 1838 : }
- 1839 :
- 1840 3611762 : if (state->block_size == 0) {
- 1841 : /* LCOV_EXCL_START */
- 1842 : decoding_error(path, f);
- 1843 : log_fatal("Internal incosistency due zero blocksize!\n");
- 1844 : exit(EXIT_FAILURE);
- 1845 : /* LCOV_EXCL_STOP */
- 1846 : }
- 1847 :
- 1848 : /* check for impossible file size to avoid to crash for a too big allocation */
- 1849 3611762 : if (v_size / state->block_size > blockmax) {
- 1850 : /* LCOV_EXCL_START */
- 1851 : decoding_error(path, f);
- 1852 : log_fatal("Internal inconsistency in file size too big!\n");
- 1853 : os_abort();
- 1854 : /* LCOV_EXCL_STOP */
- 1855 : }
- 1856 :
- 1857 3611762 : ret = sgetb64(f, &v_mtime_sec);
- 1858 3611762 : if (ret < 0) {
- 1859 : /* LCOV_EXCL_START */
- 1860 : decoding_error(path, f);
- 1861 : os_abort();
- 1862 : /* LCOV_EXCL_STOP */
- 1863 : }
- 1864 :
- 1865 3611762 : ret = sgetb32(f, &v_mtime_nsec);
- 1866 3611762 : if (ret < 0) {
- 1867 : /* LCOV_EXCL_START */
- 1868 : decoding_error(path, f);
- 1869 : os_abort();
- 1870 : /* LCOV_EXCL_STOP */
- 1871 : }
- 1872 :
- 1873 : /* STAT_NSEC_INVALID is encoded as 0 */
- 1874 3611762 : if (v_mtime_nsec == 0)
- 1875 0 : v_mtime_nsec = STAT_NSEC_INVALID;
- 1876 : else
- 1877 3611762 : --v_mtime_nsec;
- 1878 :
- 1879 3611762 : ret = sgetb64(f, &v_inode);
- 1880 3611762 : if (ret < 0) {
- 1881 : /* LCOV_EXCL_START */
- 1882 : decoding_error(path, f);
- 1883 : os_abort();
- 1884 : /* LCOV_EXCL_STOP */
- 1885 : }
- 1886 :
- 1887 3611762 : ret = sgetbs(f, sub, sizeof(sub));
- 1888 3611762 : if (ret < 0) {
- 1889 : /* LCOV_EXCL_START */
- 1890 : decoding_error(path, f);
- 1891 : os_abort();
- 1892 : /* LCOV_EXCL_STOP */
- 1893 : }
- 1894 3611762 : if (!*sub) {
- 1895 : /* LCOV_EXCL_START */
- 1896 : decoding_error(path, f);
- 1897 : log_fatal("Internal inconsistency for null file!\n");
- 1898 : os_abort();
- 1899 : /* LCOV_EXCL_STOP */
- 1900 : }
- 1901 :
- 1902 : /* allocate the file */
- 1903 3611762 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0);
+ 1804 : while (1) {
+ 1805 : int c;
+ 1806 :
+ 1807 : /* read the command */
+ 1808 3735613 : c = sgetc(f);
+ 1809 3735613 : if (c == EOF) {
+ 1810 253 : break;
+ 1811 : }
+ 1812 :
+ 1813 3735360 : if (c == 'f') {
+ 1814 : /* file */
+ 1815 : char sub[PATH_MAX];
+ 1816 : uint64_t v_size;
+ 1817 : uint64_t v_mtime_sec;
+ 1818 : uint32_t v_mtime_nsec;
+ 1819 : uint64_t v_inode;
+ 1820 : uint32_t v_idx;
+ 1821 : struct snapraid_file* file;
+ 1822 : struct snapraid_disk* disk;
+ 1823 : uint32_t mapping;
+ 1824 :
+ 1825 3611762 : ret = sgetb32(f, &mapping);
+ 1826 3611762 : if (ret < 0 || mapping >= mapping_max) {
+ 1827 : /* LCOV_EXCL_START */
+ 1828 : decoding_error(path, f);
+ 1829 : log_fatal("Internal inconsistency in mapping index!\n");
+ 1830 : os_abort();
+ 1831 : /* LCOV_EXCL_STOP */
+ 1832 : }
+ 1833 3611762 : disk = tommy_array_get(&disk_mapping, mapping);
+ 1834 :
+ 1835 3611762 : ret = sgetb64(f, &v_size);
+ 1836 3611762 : if (ret < 0) {
+ 1837 : /* LCOV_EXCL_START */
+ 1838 : decoding_error(path, f);
+ 1839 : os_abort();
+ 1840 : /* LCOV_EXCL_STOP */
+ 1841 : }
+ 1842 :
+ 1843 3611762 : if (state->block_size == 0) {
+ 1844 : /* LCOV_EXCL_START */
+ 1845 : decoding_error(path, f);
+ 1846 : log_fatal("Internal incosistency due zero blocksize!\n");
+ 1847 : exit(EXIT_FAILURE);
+ 1848 : /* LCOV_EXCL_STOP */
+ 1849 : }
+ 1850 :
+ 1851 : /* check for impossible file size to avoid to crash for a too big allocation */
+ 1852 3611762 : if (v_size / state->block_size > blockmax) {
+ 1853 : /* LCOV_EXCL_START */
+ 1854 : decoding_error(path, f);
+ 1855 : log_fatal("Internal inconsistency in file size too big!\n");
+ 1856 : os_abort();
+ 1857 : /* LCOV_EXCL_STOP */
+ 1858 : }
+ 1859 :
+ 1860 3611762 : ret = sgetb64(f, &v_mtime_sec);
+ 1861 3611762 : if (ret < 0) {
+ 1862 : /* LCOV_EXCL_START */
+ 1863 : decoding_error(path, f);
+ 1864 : os_abort();
+ 1865 : /* LCOV_EXCL_STOP */
+ 1866 : }
+ 1867 :
+ 1868 3611762 : ret = sgetb32(f, &v_mtime_nsec);
+ 1869 3611762 : if (ret < 0) {
+ 1870 : /* LCOV_EXCL_START */
+ 1871 : decoding_error(path, f);
+ 1872 : os_abort();
+ 1873 : /* LCOV_EXCL_STOP */
+ 1874 : }
+ 1875 :
+ 1876 : /* STAT_NSEC_INVALID is encoded as 0 */
+ 1877 3611762 : if (v_mtime_nsec == 0)
+ 1878 0 : v_mtime_nsec = STAT_NSEC_INVALID;
+ 1879 : else
+ 1880 3611762 : --v_mtime_nsec;
+ 1881 :
+ 1882 3611762 : ret = sgetb64(f, &v_inode);
+ 1883 3611762 : if (ret < 0) {
+ 1884 : /* LCOV_EXCL_START */
+ 1885 : decoding_error(path, f);
+ 1886 : os_abort();
+ 1887 : /* LCOV_EXCL_STOP */
+ 1888 : }
+ 1889 :
+ 1890 3611762 : ret = sgetbs(f, sub, sizeof(sub));
+ 1891 3611762 : if (ret < 0) {
+ 1892 : /* LCOV_EXCL_START */
+ 1893 : decoding_error(path, f);
+ 1894 : os_abort();
+ 1895 : /* LCOV_EXCL_STOP */
+ 1896 : }
+ 1897 3611762 : if (!*sub) {
+ 1898 : /* LCOV_EXCL_START */
+ 1899 : decoding_error(path, f);
+ 1900 : log_fatal("Internal inconsistency for null file!\n");
+ 1901 : os_abort();
+ 1902 : /* LCOV_EXCL_STOP */
+ 1903 : }
1904 :
- 1905 : /* insert the file in the file containers */
- 1906 3611762 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
- 1907 3611762 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
- 1908 3611762 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
- 1909 3611762 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
- 1910 :
- 1911 : /* read all the blocks */
- 1912 3611762 : v_idx = 0;
- 1913 10855962 : while (v_idx < file->blockmax) {
- 1914 : block_off_t v_pos;
- 1915 : uint32_t v_count;
- 1916 :
- 1917 : /* get the "subcommand */
- 1918 3632438 : c = sgetc(f);
+ 1905 : /* allocate the file */
+ 1906 3611762 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0);
+ 1907 :
+ 1908 : /* insert the file in the file containers */
+ 1909 3611762 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
+ 1910 3611762 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
+ 1911 3611762 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
+ 1912 3611762 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);
+ 1913 :
+ 1914 : /* read all the blocks */
+ 1915 3611762 : v_idx = 0;
+ 1916 10855984 : while (v_idx < file->blockmax) {
+ 1917 : block_off_t v_pos;
+ 1918 : uint32_t v_count;
1919 :
- 1920 3632438 : ret = sgetb32(f, &v_pos);
- 1921 3632438 : if (ret < 0) {
- 1922 : /* LCOV_EXCL_START */
- 1923 : decoding_error(path, f);
- 1924 : os_abort();
- 1925 : /* LCOV_EXCL_STOP */
- 1926 : }
- 1927 :
- 1928 3632438 : ret = sgetb32(f, &v_count);
- 1929 3632438 : if (ret < 0) {
- 1930 : /* LCOV_EXCL_START */
- 1931 : decoding_error(path, f);
- 1932 : os_abort();
- 1933 : /* LCOV_EXCL_STOP */
- 1934 : }
- 1935 :
- 1936 3632438 : if (v_idx + v_count > file->blockmax) {
- 1937 : /* LCOV_EXCL_START */
- 1938 : decoding_error(path, f);
- 1939 : log_fatal("Internal inconsistency in block number!\n");
- 1940 : os_abort();
- 1941 : /* LCOV_EXCL_STOP */
- 1942 : }
- 1943 :
- 1944 3632438 : if (v_pos + v_count > blockmax) {
- 1945 : /* LCOV_EXCL_START */
- 1946 : decoding_error(path, f);
- 1947 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count);
- 1948 : os_abort();
- 1949 : /* LCOV_EXCL_START */
- 1950 : }
- 1951 :
- 1952 : /* fill the blocks in the run */
- 1953 : while (v_count) {
- 1954 : struct snapraid_block* block = fs_file2block_get(file, v_idx);
- 1955 :
- 1956 : switch (c) {
- 1957 : case 'b' :
- 1958 : block_state_set(block, BLOCK_STATE_BLK);
- 1959 : break;
- 1960 : case 'n' :
- 1961 : /* deprecated NEW blocks are converted to CHG ones */
- 1962 : block_state_set(block, BLOCK_STATE_CHG);
- 1963 : break;
- 1964 : case 'g' :
+ 1920 : /* get the "subcommand */
+ 1921 3632460 : c = sgetc(f);
+ 1922 :
+ 1923 3632460 : ret = sgetb32(f, &v_pos);
+ 1924 3632460 : if (ret < 0) {
+ 1925 : /* LCOV_EXCL_START */
+ 1926 : decoding_error(path, f);
+ 1927 : os_abort();
+ 1928 : /* LCOV_EXCL_STOP */
+ 1929 : }
+ 1930 :
+ 1931 3632460 : ret = sgetb32(f, &v_count);
+ 1932 3632460 : if (ret < 0) {
+ 1933 : /* LCOV_EXCL_START */
+ 1934 : decoding_error(path, f);
+ 1935 : os_abort();
+ 1936 : /* LCOV_EXCL_STOP */
+ 1937 : }
+ 1938 :
+ 1939 3632460 : if (v_idx + v_count > file->blockmax) {
+ 1940 : /* LCOV_EXCL_START */
+ 1941 : decoding_error(path, f);
+ 1942 : log_fatal("Internal inconsistency in block number!\n");
+ 1943 : os_abort();
+ 1944 : /* LCOV_EXCL_STOP */
+ 1945 : }
+ 1946 :
+ 1947 3632460 : if (v_pos + v_count > blockmax) {
+ 1948 : /* LCOV_EXCL_START */
+ 1949 : decoding_error(path, f);
+ 1950 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count);
+ 1951 : os_abort();
+ 1952 : /* LCOV_EXCL_START */
+ 1953 : }
+ 1954 :
+ 1955 : /* fill the blocks in the run */
+ 1956 : while (v_count) {
+ 1957 : struct snapraid_block* block = fs_file2block_get(file, v_idx);
+ 1958 :
+ 1959 : switch (c) {
+ 1960 : case 'b' :
+ 1961 : block_state_set(block, BLOCK_STATE_BLK);
+ 1962 : break;
+ 1963 : case 'n' :
+ 1964 : /* deprecated NEW blocks are converted to CHG ones */
1965 : block_state_set(block, BLOCK_STATE_CHG);
1966 : break;
- 1967 : case 'p' :
- 1968 : block_state_set(block, BLOCK_STATE_REP);
+ 1967 : case 'g' :
+ 1968 : block_state_set(block, BLOCK_STATE_CHG);
1969 : break;
- 1970 : default :
- 1971 : /* LCOV_EXCL_START */
- 1972 : decoding_error(path, f);
- 1973 : log_fatal("Invalid block type!\n");
- 1974 : os_abort();
- 1975 : /* LCOV_EXCL_STOP */
- 1976 : }
- 1977 :
- 1978 : /* read the hash only for 'blk/chg/rep', and not for 'new' */
- 1979 8896100 : if (c != 'n') {
- 1980 8896100 : ret = sread(f, block->hash, BLOCK_HASH_SIZE);
- 1981 8896100 : if (ret < 0) {
- 1982 : /* LCOV_EXCL_START */
- 1983 : decoding_error(path, f);
- 1984 : os_abort();
- 1985 : /* LCOV_EXCL_STOP */
- 1986 : }
- 1987 : } else {
- 1988 : /* set the ZERO hash for deprecated NEW blocks */
- 1989 0 : hash_zero_set(block->hash);
- 1990 : }
- 1991 :
- 1992 : /* if the block contains a hash of past data */
- 1993 : /* and we are clearing such indeterminate hashes */
- 1994 8896100 : if (state->clear_past_hash
- 1995 2542004 : && block_has_past_hash(block)
- 1996 : ) {
- 1997 : /* set the hash value to INVALID */
- 1998 28006 : hash_invalid_set(block->hash);
- 1999 : }
- 2000 :
- 2001 : /* if we are disabling the copy optimization */
- 2002 : /* we want also to clear any already previously stored information */
- 2003 : /* in other sync commands */
- 2004 : /* note that this is required only in sync, and we detect */
- 2005 : /* this using the clear_past_hash flag */
- 2006 8896100 : if (state->clear_past_hash
- 2007 2542004 : && state->opt.force_nocopy
- 2008 14195 : && block_state_get(block) == BLOCK_STATE_REP
- 2009 : ) {
- 2010 : /* set the hash value to INVALID */
- 2011 1 : hash_invalid_set(block->hash);
- 2012 : /* convert from REP to CHG block */
- 2013 1 : block_state_set(block, BLOCK_STATE_CHG);
- 2014 : }
- 2015 :
- 2016 : /* if we want a full reallocation, marks block as invalid parity */
- 2017 : /* note that we do this after the force_nocopy option */
- 2018 : /* to avoid to mixup the two things */
- 2019 8896100 : if (state->opt.force_realloc
- 2020 27826 : && block_state_get(block) == BLOCK_STATE_BLK) {
- 2021 : /* convert from BLK to REP */
- 2022 27826 : block_state_set(block, BLOCK_STATE_REP);
- 2023 : }
- 2024 :
- 2025 : /* set the parity association */
- 2026 8896100 : fs_allocate(disk, v_pos, file, v_idx);
+ 1970 : case 'p' :
+ 1971 : block_state_set(block, BLOCK_STATE_REP);
+ 1972 : break;
+ 1973 : default :
+ 1974 : /* LCOV_EXCL_START */
+ 1975 : decoding_error(path, f);
+ 1976 : log_fatal("Invalid block type!\n");
+ 1977 : os_abort();
+ 1978 : /* LCOV_EXCL_STOP */
+ 1979 : }
+ 1980 :
+ 1981 : /* read the hash only for 'blk/chg/rep', and not for 'new' */
+ 1982 8896100 : if (c != 'n') {
+ 1983 8896100 : ret = sread(f, block->hash, BLOCK_HASH_SIZE);
+ 1984 8896100 : if (ret < 0) {
+ 1985 : /* LCOV_EXCL_START */
+ 1986 : decoding_error(path, f);
+ 1987 : os_abort();
+ 1988 : /* LCOV_EXCL_STOP */
+ 1989 : }
+ 1990 : } else {
+ 1991 : /* set the ZERO hash for deprecated NEW blocks */
+ 1992 0 : hash_zero_set(block->hash);
+ 1993 : }
+ 1994 :
+ 1995 : /* if the block contains a hash of past data */
+ 1996 : /* and we are clearing such indeterminate hashes */
+ 1997 8896100 : if (state->clear_past_hash
+ 1998 2542004 : && block_has_past_hash(block)
+ 1999 : ) {
+ 2000 : /* set the hash value to INVALID */
+ 2001 28006 : hash_invalid_set(block->hash);
+ 2002 : }
+ 2003 :
+ 2004 : /* if we are disabling the copy optimization */
+ 2005 : /* we want also to clear any already previously stored information */
+ 2006 : /* in other sync commands */
+ 2007 : /* note that this is required only in sync, and we detect */
+ 2008 : /* this using the clear_past_hash flag */
+ 2009 8896100 : if (state->clear_past_hash
+ 2010 2542004 : && state->opt.force_nocopy
+ 2011 14195 : && block_state_get(block) == BLOCK_STATE_REP
+ 2012 : ) {
+ 2013 : /* set the hash value to INVALID */
+ 2014 1 : hash_invalid_set(block->hash);
+ 2015 : /* convert from REP to CHG block */
+ 2016 1 : block_state_set(block, BLOCK_STATE_CHG);
+ 2017 : }
+ 2018 :
+ 2019 : /* if we want a full reallocation, marks block as invalid parity */
+ 2020 : /* note that we do this after the force_nocopy option */
+ 2021 : /* to avoid to mixup the two things */
+ 2022 8896100 : if (state->opt.force_realloc
+ 2023 27826 : && block_state_get(block) == BLOCK_STATE_BLK) {
+ 2024 : /* convert from BLK to REP */
+ 2025 27826 : block_state_set(block, BLOCK_STATE_REP);
+ 2026 : }
2027 :
- 2028 : /* go to the next block */
- 2029 8896100 : ++v_idx;
- 2030 8896100 : ++v_pos;
- 2031 8896100 : --v_count;
- 2032 : }
- 2033 : }
- 2034 :
- 2035 : /* stat */
- 2036 3611762 : ++count_file;
- 2037 123597 : } else if (c == 'i') {
- 2038 : /* "inf" command */
- 2039 : snapraid_info info;
- 2040 : uint32_t v_pos;
- 2041 : uint32_t v_oldest;
- 2042 :
- 2043 253 : ret = sgetb32(f, &v_oldest);
- 2044 253 : if (ret < 0) {
- 2045 : /* LCOV_EXCL_START */
- 2046 : decoding_error(path, f);
- 2047 : os_abort();
- 2048 : /* LCOV_EXCL_STOP */
- 2049 : }
- 2050 :
- 2051 253 : v_pos = 0;
- 2052 55893 : while (v_pos < blockmax) {
- 2053 : int bad;
- 2054 : int rehash;
- 2055 : int justsynced;
- 2056 : uint32_t t;
- 2057 : uint32_t flag;
- 2058 : uint32_t v_count;
- 2059 :
- 2060 55387 : ret = sgetb32(f, &v_count);
- 2061 55387 : if (ret < 0) {
- 2062 : /* LCOV_EXCL_START */
- 2063 : decoding_error(path, f);
- 2064 : os_abort();
- 2065 : /* LCOV_EXCL_STOP */
- 2066 : }
- 2067 :
- 2068 55387 : if (v_pos + v_count > blockmax) {
- 2069 : /* LCOV_EXCL_START */
- 2070 : decoding_error(path, f);
- 2071 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count);
- 2072 : os_abort();
- 2073 : /* LCOV_EXCL_STOP */
- 2074 : }
- 2075 :
- 2076 55387 : ret = sgetb32(f, &flag);
- 2077 55387 : if (ret < 0) {
- 2078 : /* LCOV_EXCL_START */
- 2079 : decoding_error(path, f);
- 2080 : os_abort();
- 2081 : /* LCOV_EXCL_STOP */
- 2082 : }
- 2083 :
- 2084 : /* if there is an info */
- 2085 55387 : if ((flag & 1) != 0) {
- 2086 : /* read the time */
- 2087 55372 : ret = sgetb32(f, &t);
- 2088 55372 : if (ret < 0) {
- 2089 : /* LCOV_EXCL_START */
- 2090 : decoding_error(path, f);
- 2091 : os_abort();
- 2092 : /* LCOV_EXCL_STOP */
- 2093 : }
- 2094 :
- 2095 : /* analyze the flags */
- 2096 55372 : bad = (flag & 2) != 0;
- 2097 55372 : rehash = (flag & 4) != 0;
- 2098 55372 : justsynced = (flag & 8) != 0;
- 2099 :
- 2100 55372 : if (rehash && state->prevhash == HASH_UNDEFINED) {
- 2101 : /* LCOV_EXCL_START */
- 2102 : decoding_error(path, f);
- 2103 : log_fatal("Internal inconsistency for missing previous checksum!\n");
- 2104 : os_abort();
- 2105 : /* LCOV_EXCL_STOP */
- 2106 : }
- 2107 :
- 2108 55372 : info = info_make(t + v_oldest, bad, rehash, justsynced);
- 2109 : } else {
- 2110 15 : info = 0;
- 2111 : }
- 2112 :
- 2113 1658697 : while (v_count) {
- 2114 : /* insert the info in the array */
- 2115 1547923 : info_set(&state->infoarr, v_pos, info);
- 2116 :
- 2117 : /* ensure that an info is present only for used positions */
- 2118 1547923 : if (fs_info_is_required(state, v_pos)) {
- 2119 1489158 : if (!info) {
- 2120 : /* LCOV_EXCL_START */
- 2121 : decoding_error(path, f);
- 2122 : log_fatal("Internal inconsistency for missing info!\n");
- 2123 : os_abort();
- 2124 : /* LCOV_EXCL_STOP */
- 2125 : }
- 2126 : } else {
- 2127 : /* extra info are accepted for backward compatibility */
- 2128 : /* they are discarded at the first write */
- 2129 : }
- 2130 :
- 2131 : /* go to next block */
- 2132 1547923 : ++v_pos;
- 2133 1547923 : --v_count;
- 2134 : }
- 2135 : }
- 2136 123344 : } else if (c == 'h') {
- 2137 : /* hole */
- 2138 : uint32_t v_pos;
- 2139 : struct snapraid_disk* disk;
- 2140 : uint32_t mapping;
- 2141 :
- 2142 1397 : ret = sgetb32(f, &mapping);
- 2143 1397 : if (ret < 0 || mapping >= mapping_max) {
- 2144 : /* LCOV_EXCL_START */
- 2145 : decoding_error(path, f);
- 2146 : log_fatal("Internal inconsistency in mapping index!\n");
- 2147 : os_abort();
- 2148 : /* LCOV_EXCL_STOP */
- 2149 : }
- 2150 1397 : disk = tommy_array_get(&disk_mapping, mapping);
- 2151 :
- 2152 1397 : v_pos = 0;
- 2153 4257 : while (v_pos < blockmax) {
- 2154 : uint32_t v_idx;
- 2155 : uint32_t v_count;
- 2156 : struct snapraid_file* deleted;
- 2157 :
- 2158 1463 : ret = sgetb32(f, &v_count);
- 2159 1463 : if (ret < 0) {
- 2160 : /* LCOV_EXCL_START */
- 2161 : decoding_error(path, f);
- 2162 : os_abort();
- 2163 : /* LCOV_EXCL_STOP */
- 2164 : }
- 2165 :
- 2166 1463 : if (v_pos + v_count > blockmax) {
- 2167 : /* LCOV_EXCL_START */
- 2168 : decoding_error(path, f);
- 2169 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count);
- 2170 : os_abort();
- 2171 : /* LCOV_EXCL_STOP */
- 2172 : }
- 2173 :
- 2174 : /* get the sub-command */
- 2175 1463 : c = sgetc(f);
+ 2028 : /* set the parity association */
+ 2029 8896100 : fs_allocate(disk, v_pos, file, v_idx);
+ 2030 :
+ 2031 : /* go to the next block */
+ 2032 8896100 : ++v_idx;
+ 2033 8896100 : ++v_pos;
+ 2034 8896100 : --v_count;
+ 2035 : }
+ 2036 : }
+ 2037 :
+ 2038 : /* stat */
+ 2039 3611762 : ++count_file;
+ 2040 123598 : } else if (c == 'i') {
+ 2041 : /* "inf" command */
+ 2042 : snapraid_info info;
+ 2043 : uint32_t v_pos;
+ 2044 : uint32_t v_oldest;
+ 2045 :
+ 2046 253 : ret = sgetb32(f, &v_oldest);
+ 2047 253 : if (ret < 0) {
+ 2048 : /* LCOV_EXCL_START */
+ 2049 : decoding_error(path, f);
+ 2050 : os_abort();
+ 2051 : /* LCOV_EXCL_STOP */
+ 2052 : }
+ 2053 :
+ 2054 253 : v_pos = 0;
+ 2055 55856 : while (v_pos < blockmax) {
+ 2056 : int bad;
+ 2057 : int rehash;
+ 2058 : int justsynced;
+ 2059 : uint32_t t;
+ 2060 : uint32_t flag;
+ 2061 : uint32_t v_count;
+ 2062 :
+ 2063 55350 : ret = sgetb32(f, &v_count);
+ 2064 55350 : if (ret < 0) {
+ 2065 : /* LCOV_EXCL_START */
+ 2066 : decoding_error(path, f);
+ 2067 : os_abort();
+ 2068 : /* LCOV_EXCL_STOP */
+ 2069 : }
+ 2070 :
+ 2071 55350 : if (v_pos + v_count > blockmax) {
+ 2072 : /* LCOV_EXCL_START */
+ 2073 : decoding_error(path, f);
+ 2074 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count);
+ 2075 : os_abort();
+ 2076 : /* LCOV_EXCL_STOP */
+ 2077 : }
+ 2078 :
+ 2079 55350 : ret = sgetb32(f, &flag);
+ 2080 55350 : if (ret < 0) {
+ 2081 : /* LCOV_EXCL_START */
+ 2082 : decoding_error(path, f);
+ 2083 : os_abort();
+ 2084 : /* LCOV_EXCL_STOP */
+ 2085 : }
+ 2086 :
+ 2087 : /* if there is an info */
+ 2088 55350 : if ((flag & 1) != 0) {
+ 2089 : /* read the time */
+ 2090 55335 : ret = sgetb32(f, &t);
+ 2091 55335 : if (ret < 0) {
+ 2092 : /* LCOV_EXCL_START */
+ 2093 : decoding_error(path, f);
+ 2094 : os_abort();
+ 2095 : /* LCOV_EXCL_STOP */
+ 2096 : }
+ 2097 :
+ 2098 : /* analyze the flags */
+ 2099 55335 : bad = (flag & 2) != 0;
+ 2100 55335 : rehash = (flag & 4) != 0;
+ 2101 55335 : justsynced = (flag & 8) != 0;
+ 2102 :
+ 2103 55335 : if (rehash && state->prevhash == HASH_UNDEFINED) {
+ 2104 : /* LCOV_EXCL_START */
+ 2105 : decoding_error(path, f);
+ 2106 : log_fatal("Internal inconsistency for missing previous checksum!\n");
+ 2107 : os_abort();
+ 2108 : /* LCOV_EXCL_STOP */
+ 2109 : }
+ 2110 :
+ 2111 55335 : info = info_make(t + v_oldest, bad, rehash, justsynced);
+ 2112 : } else {
+ 2113 15 : info = 0;
+ 2114 : }
+ 2115 :
+ 2116 1658623 : while (v_count) {
+ 2117 : /* insert the info in the array */
+ 2118 1547923 : info_set(&state->infoarr, v_pos, info);
+ 2119 :
+ 2120 : /* ensure that an info is present only for used positions */
+ 2121 1547923 : if (fs_info_is_required(state, v_pos)) {
+ 2122 1489158 : if (!info) {
+ 2123 : /* LCOV_EXCL_START */
+ 2124 : decoding_error(path, f);
+ 2125 : log_fatal("Internal inconsistency for missing info!\n");
+ 2126 : os_abort();
+ 2127 : /* LCOV_EXCL_STOP */
+ 2128 : }
+ 2129 : } else {
+ 2130 : /* extra info are accepted for backward compatibility */
+ 2131 : /* they are discarded at the first write */
+ 2132 : }
+ 2133 :
+ 2134 : /* go to next block */
+ 2135 1547923 : ++v_pos;
+ 2136 1547923 : --v_count;
+ 2137 : }
+ 2138 : }
+ 2139 123345 : } else if (c == 'h') {
+ 2140 : /* hole */
+ 2141 : uint32_t v_pos;
+ 2142 : struct snapraid_disk* disk;
+ 2143 : uint32_t mapping;
+ 2144 :
+ 2145 1397 : ret = sgetb32(f, &mapping);
+ 2146 1397 : if (ret < 0 || mapping >= mapping_max) {
+ 2147 : /* LCOV_EXCL_START */
+ 2148 : decoding_error(path, f);
+ 2149 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2150 : os_abort();
+ 2151 : /* LCOV_EXCL_STOP */
+ 2152 : }
+ 2153 1397 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2154 :
+ 2155 1397 : v_pos = 0;
+ 2156 4257 : while (v_pos < blockmax) {
+ 2157 : uint32_t v_idx;
+ 2158 : uint32_t v_count;
+ 2159 : struct snapraid_file* deleted;
+ 2160 :
+ 2161 1463 : ret = sgetb32(f, &v_count);
+ 2162 1463 : if (ret < 0) {
+ 2163 : /* LCOV_EXCL_START */
+ 2164 : decoding_error(path, f);
+ 2165 : os_abort();
+ 2166 : /* LCOV_EXCL_STOP */
+ 2167 : }
+ 2168 :
+ 2169 1463 : if (v_pos + v_count > blockmax) {
+ 2170 : /* LCOV_EXCL_START */
+ 2171 : decoding_error(path, f);
+ 2172 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count);
+ 2173 : os_abort();
+ 2174 : /* LCOV_EXCL_STOP */
+ 2175 : }
2176 :
- 2177 1463 : switch (c) {
- 2178 : case 'o' :
- 2179 : /* if it's a run of deleted blocks */
- 2180 :
- 2181 : /* allocate a fake deleted file */
- 2182 35 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0);
+ 2177 : /* get the sub-command */
+ 2178 1463 : c = sgetc(f);
+ 2179 :
+ 2180 1463 : switch (c) {
+ 2181 : case 'o' :
+ 2182 : /* if it's a run of deleted blocks */
2183 :
- 2184 : /* mark the file as deleted */
- 2185 35 : file_flag_set(deleted, FILE_IS_DELETED);
+ 2184 : /* allocate a fake deleted file */
+ 2185 35 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0);
2186 :
- 2187 : /* insert it in the list of deleted files */
- 2188 35 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted);
+ 2187 : /* mark the file as deleted */
+ 2188 35 : file_flag_set(deleted, FILE_IS_DELETED);
2189 :
- 2190 : /* process all blocks */
- 2191 35 : v_idx = 0;
- 2192 27956 : while (v_count) {
- 2193 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx);
- 2194 :
- 2195 : /* set the block as deleted */
- 2196 27886 : block_state_set(block, BLOCK_STATE_DELETED);
+ 2190 : /* insert it in the list of deleted files */
+ 2191 35 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted);
+ 2192 :
+ 2193 : /* process all blocks */
+ 2194 35 : v_idx = 0;
+ 2195 27956 : while (v_count) {
+ 2196 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx);
2197 :
- 2198 : /* read the hash */
- 2199 27886 : ret = sread(f, block->hash, BLOCK_HASH_SIZE);
- 2200 27886 : if (ret < 0) {
- 2201 : /* LCOV_EXCL_START */
- 2202 : decoding_error(path, f);
- 2203 : os_abort();
- 2204 : /* LCOV_EXCL_STOP */
- 2205 : }
- 2206 :
- 2207 : /* if we are clearing indeterminate hashes */
- 2208 27886 : if (state->clear_past_hash) {
- 2209 : /* set the hash value to INVALID */
- 2210 9432 : hash_invalid_set(block->hash);
- 2211 : }
- 2212 :
- 2213 : /* insert the block in the block array */
- 2214 27886 : fs_allocate(disk, v_pos, deleted, v_idx);
+ 2198 : /* set the block as deleted */
+ 2199 27886 : block_state_set(block, BLOCK_STATE_DELETED);
+ 2200 :
+ 2201 : /* read the hash */
+ 2202 27886 : ret = sread(f, block->hash, BLOCK_HASH_SIZE);
+ 2203 27886 : if (ret < 0) {
+ 2204 : /* LCOV_EXCL_START */
+ 2205 : decoding_error(path, f);
+ 2206 : os_abort();
+ 2207 : /* LCOV_EXCL_STOP */
+ 2208 : }
+ 2209 :
+ 2210 : /* if we are clearing indeterminate hashes */
+ 2211 27886 : if (state->clear_past_hash) {
+ 2212 : /* set the hash value to INVALID */
+ 2213 9432 : hash_invalid_set(block->hash);
+ 2214 : }
2215 :
- 2216 : /* go to next block */
- 2217 27886 : ++v_pos;
- 2218 27886 : ++v_idx;
- 2219 27886 : --v_count;
- 2220 : }
- 2221 35 : break;
- 2222 : case 'O' :
- 2223 : /* go to the next run */
- 2224 1428 : v_pos += v_count;
- 2225 1428 : break;
- 2226 : default :
- 2227 : /* LCOV_EXCL_START */
- 2228 : decoding_error(path, f);
- 2229 : log_fatal("Invalid hole type!\n");
- 2230 : os_abort();
- 2231 : /* LCOV_EXCL_STOP */
- 2232 : }
- 2233 : }
- 2234 121947 : } else if (c == 's') {
- 2235 : /* symlink */
- 2236 : char sub[PATH_MAX];
- 2237 : char linkto[PATH_MAX];
- 2238 : struct snapraid_link* slink;
- 2239 : struct snapraid_disk* disk;
- 2240 : uint32_t mapping;
- 2241 :
- 2242 116468 : ret = sgetb32(f, &mapping);
- 2243 116468 : if (ret < 0 || mapping >= mapping_max) {
- 2244 : /* LCOV_EXCL_START */
- 2245 : decoding_error(path, f);
- 2246 : log_fatal("Internal inconsistency in mapping index!\n");
- 2247 : os_abort();
- 2248 : /* LCOV_EXCL_STOP */
- 2249 : }
- 2250 116468 : disk = tommy_array_get(&disk_mapping, mapping);
- 2251 :
- 2252 116468 : ret = sgetbs(f, sub, sizeof(sub));
- 2253 116468 : if (ret < 0) {
- 2254 : /* LCOV_EXCL_START */
- 2255 : decoding_error(path, f);
- 2256 : os_abort();
- 2257 : /* LCOV_EXCL_STOP */
- 2258 : }
- 2259 :
- 2260 116468 : if (!*sub) {
- 2261 : /* LCOV_EXCL_START */
- 2262 : decoding_error(path, f);
- 2263 : log_fatal("Internal inconsistency for null symlink!\n");
- 2264 : os_abort();
- 2265 : /* LCOV_EXCL_STOP */
- 2266 : }
- 2267 :
- 2268 116468 : ret = sgetbs(f, linkto, sizeof(linkto));
- 2269 116468 : if (ret < 0) {
- 2270 : /* LCOV_EXCL_START */
- 2271 : decoding_error(path, f);
- 2272 : os_abort();
- 2273 : /* LCOV_EXCL_STOP */
- 2274 : }
- 2275 :
- 2276 : /* allocate the link as symbolic link */
- 2277 116468 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK);
+ 2216 : /* insert the block in the block array */
+ 2217 27886 : fs_allocate(disk, v_pos, deleted, v_idx);
+ 2218 :
+ 2219 : /* go to next block */
+ 2220 27886 : ++v_pos;
+ 2221 27886 : ++v_idx;
+ 2222 27886 : --v_count;
+ 2223 : }
+ 2224 35 : break;
+ 2225 : case 'O' :
+ 2226 : /* go to the next run */
+ 2227 1428 : v_pos += v_count;
+ 2228 1428 : break;
+ 2229 : default :
+ 2230 : /* LCOV_EXCL_START */
+ 2231 : decoding_error(path, f);
+ 2232 : log_fatal("Invalid hole type!\n");
+ 2233 : os_abort();
+ 2234 : /* LCOV_EXCL_STOP */
+ 2235 : }
+ 2236 : }
+ 2237 121948 : } else if (c == 's') {
+ 2238 : /* symlink */
+ 2239 : char sub[PATH_MAX];
+ 2240 : char linkto[PATH_MAX];
+ 2241 : struct snapraid_link* slink;
+ 2242 : struct snapraid_disk* disk;
+ 2243 : uint32_t mapping;
+ 2244 :
+ 2245 116468 : ret = sgetb32(f, &mapping);
+ 2246 116468 : if (ret < 0 || mapping >= mapping_max) {
+ 2247 : /* LCOV_EXCL_START */
+ 2248 : decoding_error(path, f);
+ 2249 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2250 : os_abort();
+ 2251 : /* LCOV_EXCL_STOP */
+ 2252 : }
+ 2253 116468 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2254 :
+ 2255 116468 : ret = sgetbs(f, sub, sizeof(sub));
+ 2256 116468 : if (ret < 0) {
+ 2257 : /* LCOV_EXCL_START */
+ 2258 : decoding_error(path, f);
+ 2259 : os_abort();
+ 2260 : /* LCOV_EXCL_STOP */
+ 2261 : }
+ 2262 :
+ 2263 116468 : if (!*sub) {
+ 2264 : /* LCOV_EXCL_START */
+ 2265 : decoding_error(path, f);
+ 2266 : log_fatal("Internal inconsistency for null symlink!\n");
+ 2267 : os_abort();
+ 2268 : /* LCOV_EXCL_STOP */
+ 2269 : }
+ 2270 :
+ 2271 116468 : ret = sgetbs(f, linkto, sizeof(linkto));
+ 2272 116468 : if (ret < 0) {
+ 2273 : /* LCOV_EXCL_START */
+ 2274 : decoding_error(path, f);
+ 2275 : os_abort();
+ 2276 : /* LCOV_EXCL_STOP */
+ 2277 : }
2278 :
- 2279 : /* insert the link in the link containers */
- 2280 116468 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
- 2281 116468 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
- 2282 :
- 2283 : /* stat */
- 2284 116468 : ++count_symlink;
- 2285 5479 : } else if (c == 'a') {
- 2286 : /* hardlink */
- 2287 : char sub[PATH_MAX];
- 2288 : char linkto[PATH_MAX];
- 2289 : struct snapraid_link* slink;
- 2290 : struct snapraid_disk* disk;
- 2291 : uint32_t mapping;
- 2292 :
- 2293 597 : ret = sgetb32(f, &mapping);
- 2294 597 : if (ret < 0 || mapping >= mapping_max) {
- 2295 : /* LCOV_EXCL_START */
- 2296 : decoding_error(path, f);
- 2297 : log_fatal("Internal inconsistency in mapping index!\n");
- 2298 : os_abort();
- 2299 : /* LCOV_EXCL_STOP */
- 2300 : }
- 2301 597 : disk = tommy_array_get(&disk_mapping, mapping);
- 2302 :
- 2303 597 : ret = sgetbs(f, sub, sizeof(sub));
- 2304 597 : if (ret < 0) {
- 2305 : /* LCOV_EXCL_START */
- 2306 : decoding_error(path, f);
- 2307 : os_abort();
- 2308 : /* LCOV_EXCL_STOP */
- 2309 : }
- 2310 :
- 2311 597 : if (!*sub) {
- 2312 : /* LCOV_EXCL_START */
- 2313 : decoding_error(path, f);
- 2314 : log_fatal("Internal inconsistency for null hardlink!\n");
- 2315 : os_abort();
- 2316 : /* LCOV_EXCL_STOP */
- 2317 : }
- 2318 :
- 2319 597 : ret = sgetbs(f, linkto, sizeof(linkto));
- 2320 597 : if (ret < 0) {
- 2321 : /* LCOV_EXCL_START */
- 2322 : decoding_error(path, f);
- 2323 : os_abort();
- 2324 : /* LCOV_EXCL_STOP */
- 2325 : }
- 2326 :
- 2327 597 : if (!*linkto) {
- 2328 : /* LCOV_EXCL_START */
- 2329 : decoding_error(path, f);
- 2330 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub);
- 2331 : os_abort();
- 2332 : /* LCOV_EXCL_STOP */
- 2333 : }
- 2334 :
- 2335 : /* allocate the link as hard link */
- 2336 597 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK);
+ 2279 : /* allocate the link as symbolic link */
+ 2280 116468 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK);
+ 2281 :
+ 2282 : /* insert the link in the link containers */
+ 2283 116468 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
+ 2284 116468 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
+ 2285 :
+ 2286 : /* stat */
+ 2287 116468 : ++count_symlink;
+ 2288 5480 : } else if (c == 'a') {
+ 2289 : /* hardlink */
+ 2290 : char sub[PATH_MAX];
+ 2291 : char linkto[PATH_MAX];
+ 2292 : struct snapraid_link* slink;
+ 2293 : struct snapraid_disk* disk;
+ 2294 : uint32_t mapping;
+ 2295 :
+ 2296 597 : ret = sgetb32(f, &mapping);
+ 2297 597 : if (ret < 0 || mapping >= mapping_max) {
+ 2298 : /* LCOV_EXCL_START */
+ 2299 : decoding_error(path, f);
+ 2300 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2301 : os_abort();
+ 2302 : /* LCOV_EXCL_STOP */
+ 2303 : }
+ 2304 597 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2305 :
+ 2306 597 : ret = sgetbs(f, sub, sizeof(sub));
+ 2307 597 : if (ret < 0) {
+ 2308 : /* LCOV_EXCL_START */
+ 2309 : decoding_error(path, f);
+ 2310 : os_abort();
+ 2311 : /* LCOV_EXCL_STOP */
+ 2312 : }
+ 2313 :
+ 2314 597 : if (!*sub) {
+ 2315 : /* LCOV_EXCL_START */
+ 2316 : decoding_error(path, f);
+ 2317 : log_fatal("Internal inconsistency for null hardlink!\n");
+ 2318 : os_abort();
+ 2319 : /* LCOV_EXCL_STOP */
+ 2320 : }
+ 2321 :
+ 2322 597 : ret = sgetbs(f, linkto, sizeof(linkto));
+ 2323 597 : if (ret < 0) {
+ 2324 : /* LCOV_EXCL_START */
+ 2325 : decoding_error(path, f);
+ 2326 : os_abort();
+ 2327 : /* LCOV_EXCL_STOP */
+ 2328 : }
+ 2329 :
+ 2330 597 : if (!*linkto) {
+ 2331 : /* LCOV_EXCL_START */
+ 2332 : decoding_error(path, f);
+ 2333 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub);
+ 2334 : os_abort();
+ 2335 : /* LCOV_EXCL_STOP */
+ 2336 : }
2337 :
- 2338 : /* insert the link in the link containers */
- 2339 597 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
- 2340 597 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
- 2341 :
- 2342 : /* stat */
- 2343 597 : ++count_hardlink;
- 2344 4882 : } else if (c == 'r') {
- 2345 : /* dir */
- 2346 : char sub[PATH_MAX];
- 2347 : struct snapraid_dir* dir;
- 2348 : struct snapraid_disk* disk;
- 2349 : uint32_t mapping;
- 2350 :
- 2351 790 : ret = sgetb32(f, &mapping);
- 2352 790 : if (ret < 0 || mapping >= mapping_max) {
- 2353 : /* LCOV_EXCL_START */
- 2354 : decoding_error(path, f);
- 2355 : log_fatal("Internal inconsistency in mapping index!\n");
- 2356 : os_abort();
- 2357 : /* LCOV_EXCL_STOP */
- 2358 : }
- 2359 790 : disk = tommy_array_get(&disk_mapping, mapping);
- 2360 :
- 2361 790 : ret = sgetbs(f, sub, sizeof(sub));
- 2362 790 : if (ret < 0) {
- 2363 : /* LCOV_EXCL_START */
- 2364 : decoding_error(path, f);
- 2365 : os_abort();
- 2366 : /* LCOV_EXCL_STOP */
- 2367 : }
- 2368 :
- 2369 790 : if (!*sub) {
- 2370 : /* LCOV_EXCL_START */
- 2371 : decoding_error(path, f);
- 2372 : log_fatal("Internal inconsistency for null dir!\n");
- 2373 : os_abort();
- 2374 : /* LCOV_EXCL_STOP */
- 2375 : }
- 2376 :
- 2377 : /* allocate the dir */
- 2378 790 : dir = dir_alloc(sub);
+ 2338 : /* allocate the link as hard link */
+ 2339 597 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK);
+ 2340 :
+ 2341 : /* insert the link in the link containers */
+ 2342 597 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
+ 2343 597 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);
+ 2344 :
+ 2345 : /* stat */
+ 2346 597 : ++count_hardlink;
+ 2347 4883 : } else if (c == 'r') {
+ 2348 : /* dir */
+ 2349 : char sub[PATH_MAX];
+ 2350 : struct snapraid_dir* dir;
+ 2351 : struct snapraid_disk* disk;
+ 2352 : uint32_t mapping;
+ 2353 :
+ 2354 790 : ret = sgetb32(f, &mapping);
+ 2355 790 : if (ret < 0 || mapping >= mapping_max) {
+ 2356 : /* LCOV_EXCL_START */
+ 2357 : decoding_error(path, f);
+ 2358 : log_fatal("Internal inconsistency in mapping index!\n");
+ 2359 : os_abort();
+ 2360 : /* LCOV_EXCL_STOP */
+ 2361 : }
+ 2362 790 : disk = tommy_array_get(&disk_mapping, mapping);
+ 2363 :
+ 2364 790 : ret = sgetbs(f, sub, sizeof(sub));
+ 2365 790 : if (ret < 0) {
+ 2366 : /* LCOV_EXCL_START */
+ 2367 : decoding_error(path, f);
+ 2368 : os_abort();
+ 2369 : /* LCOV_EXCL_STOP */
+ 2370 : }
+ 2371 :
+ 2372 790 : if (!*sub) {
+ 2373 : /* LCOV_EXCL_START */
+ 2374 : decoding_error(path, f);
+ 2375 : log_fatal("Internal inconsistency for null dir!\n");
+ 2376 : os_abort();
+ 2377 : /* LCOV_EXCL_STOP */
+ 2378 : }
2379 :
- 2380 : /* insert the dir in the dir containers */
- 2381 790 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
- 2382 790 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir);
- 2383 :
- 2384 : /* stat */
- 2385 790 : ++count_dir;
- 2386 4092 : } else if (c == 'c') {
- 2387 : /* get the subcommand */
- 2388 254 : c = sgetc(f);
- 2389 :
- 2390 254 : switch (c) {
- 2391 : case 'u' :
- 2392 166 : state->hash = HASH_MURMUR3;
- 2393 166 : break;
- 2394 : case 'k' :
- 2395 88 : state->hash = HASH_SPOOKY2;
- 2396 88 : break;
- 2397 : default :
- 2398 : /* LCOV_EXCL_START */
- 2399 : decoding_error(path, f);
- 2400 : log_fatal("Invalid checksum!\n");
- 2401 : os_abort();
- 2402 : /* LCOV_EXCL_STOP */
- 2403 : }
- 2404 :
- 2405 : /* read the seed */
- 2406 254 : ret = sread(f, state->hashseed, HASH_MAX);
- 2407 254 : if (ret < 0) {
- 2408 : /* LCOV_EXCL_START */
- 2409 : decoding_error(path, f);
- 2410 : os_abort();
- 2411 : /* LCOV_EXCL_STOP */
- 2412 : }
- 2413 3838 : } else if (c == 'C') {
- 2414 : /* get the sub-command */
- 2415 4 : c = sgetc(f);
- 2416 :
- 2417 4 : switch (c) {
- 2418 : case 'u' :
- 2419 4 : state->prevhash = HASH_MURMUR3;
- 2420 4 : break;
- 2421 : case 'k' :
- 2422 0 : state->prevhash = HASH_SPOOKY2;
- 2423 0 : break;
- 2424 : default :
- 2425 : /* LCOV_EXCL_START */
- 2426 : decoding_error(path, f);
- 2427 : log_fatal("Invalid checksum!\n");
- 2428 : os_abort();
- 2429 : /* LCOV_EXCL_STOP */
- 2430 : }
- 2431 :
- 2432 : /* read the seed */
- 2433 4 : ret = sread(f, state->prevhashseed, HASH_MAX);
- 2434 4 : if (ret < 0) {
- 2435 : /* LCOV_EXCL_START */
- 2436 : decoding_error(path, f);
- 2437 : os_abort();
- 2438 : /* LCOV_EXCL_STOP */
- 2439 : }
- 2440 3834 : } else if (c == 'z') {
- 2441 : uint32_t block_size;
- 2442 :
- 2443 254 : ret = sgetb32(f, &block_size);
- 2444 254 : if (ret < 0) {
- 2445 : /* LCOV_EXCL_START */
- 2446 : decoding_error(path, f);
- 2447 : os_abort();
- 2448 : /* LCOV_EXCL_STOP */
- 2449 : }
- 2450 :
- 2451 254 : if (block_size == 0) {
- 2452 : /* LCOV_EXCL_START */
- 2453 : decoding_error(path, f);
- 2454 : log_fatal("Zero 'blocksize' specification in the content file!\n");
- 2455 : exit(EXIT_FAILURE);
- 2456 : /* LCOV_EXCL_STOP */
- 2457 : }
- 2458 :
- 2459 : /* without configuration, auto assign the block size */
- 2460 254 : if (state->no_conf) {
- 2461 1 : state->block_size = block_size;
- 2462 : }
- 2463 :
- 2464 254 : if (block_size != state->block_size) {
- 2465 : /* LCOV_EXCL_START */
- 2466 : decoding_error(path, f);
- 2467 : log_fatal("Mismatching 'blocksize' specification in the content file!\n");
- 2468 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", block_size / KIBI);
- 2469 : exit(EXIT_FAILURE);
- 2470 : /* LCOV_EXCL_STOP */
- 2471 : }
- 2472 3580 : } else if (c == 'y') {
- 2473 : uint32_t hash_size;
- 2474 :
- 2475 254 : ret = sgetb32(f, &hash_size);
- 2476 254 : if (ret < 0) {
- 2477 : /* LCOV_EXCL_START */
- 2478 : decoding_error(path, f);
- 2479 : os_abort();
- 2480 : /* LCOV_EXCL_STOP */
- 2481 : }
- 2482 :
- 2483 254 : if (hash_size < 2 || hash_size > HASH_MAX) {
- 2484 : /* LCOV_EXCL_START */
- 2485 : decoding_error(path, f);
- 2486 : log_fatal("Invalid 'hashsize' specification in the content file!\n");
- 2487 : exit(EXIT_FAILURE);
- 2488 : /* LCOV_EXCL_STOP */
- 2489 : }
- 2490 :
- 2491 : /* without configuration, auto assign the block size */
- 2492 254 : if (state->no_conf) {
- 2493 1 : BLOCK_HASH_SIZE = hash_size;
- 2494 : }
- 2495 :
- 2496 254 : if ((int)hash_size != BLOCK_HASH_SIZE) {
- 2497 : /* LCOV_EXCL_START */
- 2498 : decoding_error(path, f);
- 2499 : log_fatal("Mismatching 'hashsize' specification in the content file!\n");
- 2500 : log_fatal("Please restore the 'hashsize' value in the configuration file to '%u'\n", hash_size);
- 2501 : exit(EXIT_FAILURE);
- 2502 : /* LCOV_EXCL_STOP */
- 2503 : }
- 2504 3326 : } else if (c == 'x') {
- 2505 254 : ret = sgetb32(f, &blockmax);
- 2506 254 : if (ret < 0) {
- 2507 : /* LCOV_EXCL_START */
- 2508 : decoding_error(path, f);
- 2509 : os_abort();
- 2510 : /* LCOV_EXCL_STOP */
- 2511 : }
- 2512 4475 : } else if (c == 'm' || c == 'M') {
- 2513 : struct snapraid_map* map;
- 2514 : char uuid[UUID_MAX];
- 2515 : uint32_t v_pos;
- 2516 : uint32_t v_total_blocks;
- 2517 : uint32_t v_free_blocks;
- 2518 : struct snapraid_disk* disk;
- 2519 :
- 2520 1403 : ret = sgetbs(f, buffer, sizeof(buffer));
- 2521 1403 : if (ret < 0) {
- 2522 : /* LCOV_EXCL_START */
- 2523 : decoding_error(path, f);
- 2524 : os_abort();
- 2525 : /* LCOV_EXCL_STOP */
- 2526 : }
- 2527 :
- 2528 1403 : ret = sgetb32(f, &v_pos);
- 2529 1403 : if (ret < 0) {
- 2530 : /* LCOV_EXCL_START */
- 2531 : decoding_error(path, f);
- 2532 : os_abort();
- 2533 : /* LCOV_EXCL_STOP */
- 2534 : }
- 2535 :
- 2536 : /* from SnapRAID 7.0 the 'M' command includes the free space */
- 2537 1403 : if (c == 'M') {
- 2538 1403 : ret = sgetb32(f, &v_total_blocks);
- 2539 1403 : if (ret < 0) {
- 2540 : /* LCOV_EXCL_START */
- 2541 : decoding_error(path, f);
- 2542 : os_abort();
- 2543 : /* LCOV_EXCL_STOP */
- 2544 : }
- 2545 :
- 2546 1403 : ret = sgetb32(f, &v_free_blocks);
- 2547 1403 : if (ret < 0) {
- 2548 : /* LCOV_EXCL_START */
- 2549 : decoding_error(path, f);
- 2550 : os_abort();
- 2551 : /* LCOV_EXCL_STOP */
- 2552 : }
- 2553 : } else {
- 2554 0 : v_total_blocks = 0;
- 2555 0 : v_free_blocks = 0;
- 2556 : }
- 2557 :
- 2558 : /* read the uuid */
- 2559 1403 : ret = sgetbs(f, uuid, sizeof(uuid));
- 2560 1403 : if (ret < 0) {
- 2561 : /* LCOV_EXCL_START */
- 2562 : decoding_error(path, f);
- 2563 : os_abort();
- 2564 : /* LCOV_EXCL_STOP */
- 2565 : }
- 2566 :
- 2567 : /* find the disk */
- 2568 1403 : disk = find_disk_by_name(state, buffer);
- 2569 1403 : if (!disk) {
- 2570 : /* search by UUID if renamed */
- 2571 2 : disk = find_disk_by_uuid(state, uuid);
- 2572 2 : if (disk) {
- 2573 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name);
- 2574 :
- 2575 : /* write the new state with the new name */
- 2576 2 : state->need_write = 1;
- 2577 : }
- 2578 : }
- 2579 1403 : if (!disk) {
- 2580 : /* LCOV_EXCL_START */
- 2581 : decoding_error(path, f);
- 2582 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid);
- 2583 : log_fatal("If you have removed it from the configuration file, please restore it\n");
- 2584 : /* if it's a command without UUID, it cannot autorename using UUID */
- 2585 : if (state->opt.skip_disk_access)
- 2586 : log_fatal("If you have renamed it, run 'sync' to update the new name\n");
- 2587 : exit(EXIT_FAILURE);
- 2588 : /* LCOV_EXCL_STOP */
- 2589 : }
- 2590 :
- 2591 1403 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid);
- 2592 :
- 2593 1403 : tommy_list_insert_tail(&state->maplist, &map->node, map);
- 2594 :
- 2595 : /* insert in the mapping vector */
- 2596 1403 : tommy_array_grow(&disk_mapping, mapping_max + 1);
- 2597 1403 : tommy_array_set(&disk_mapping, mapping_max, disk);
- 2598 1403 : ++mapping_max;
- 2599 1669 : } else if (c == 'P') {
- 2600 : /* from SnapRAID 7.0 the 'P' command includes the free space */
- 2601 : /* from SnapRAID 11.0 the 'P' command is deprecated by 'Q' */
- 2602 : char v_uuid[UUID_MAX];
- 2603 : uint32_t v_level;
- 2604 : uint32_t v_total_blocks;
- 2605 : uint32_t v_free_blocks;
- 2606 :
- 2607 0 : ret = sgetb32(f, &v_level);
- 2608 0 : if (ret < 0) {
- 2609 : /* LCOV_EXCL_START */
- 2610 : decoding_error(path, f);
- 2611 : os_abort();
- 2612 : /* LCOV_EXCL_STOP */
- 2613 : }
- 2614 :
- 2615 0 : ret = sgetb32(f, &v_total_blocks);
- 2616 0 : if (ret < 0) {
- 2617 : /* LCOV_EXCL_START */
- 2618 : decoding_error(path, f);
- 2619 : os_abort();
- 2620 : /* LCOV_EXCL_STOP */
- 2621 : }
- 2622 :
- 2623 0 : ret = sgetb32(f, &v_free_blocks);
- 2624 0 : if (ret < 0) {
- 2625 : /* LCOV_EXCL_START */
- 2626 : decoding_error(path, f);
- 2627 : os_abort();
- 2628 : /* LCOV_EXCL_STOP */
- 2629 : }
- 2630 :
- 2631 0 : ret = sgetbs(f, v_uuid, sizeof(v_uuid));
- 2632 0 : if (ret < 0) {
- 2633 : /* LCOV_EXCL_START */
- 2634 : decoding_error(path, f);
- 2635 : os_abort();
- 2636 : /* LCOV_EXCL_STOP */
- 2637 : }
- 2638 :
- 2639 0 : if (v_level >= LEV_MAX) {
- 2640 : /* LCOV_EXCL_START */
- 2641 : decoding_error(path, f);
- 2642 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level);
- 2643 : exit(EXIT_FAILURE);
- 2644 : /* LCOV_EXCL_STOP */
- 2645 : }
- 2646 :
- 2647 : /* auto configure if configuration is missing */
- 2648 0 : if (state->no_conf) {
- 2649 0 : if (v_level >= state->level)
- 2650 0 : state->level = v_level + 1;
- 2651 : }
- 2652 :
- 2653 : /* if we use this parity entry */
- 2654 0 : if (v_level < state->level) {
- 2655 : /* set the parity info */
- 2656 0 : state->parity[v_level].split_mac = 1;
- 2657 0 : pathcpy(state->parity[v_level].split_map[0].uuid, sizeof(state->parity[v_level].split_map[0].uuid), v_uuid);
- 2658 0 : state->parity[v_level].total_blocks = v_total_blocks;
- 2659 0 : state->parity[v_level].free_blocks = v_free_blocks;
- 2660 : }
- 2661 1669 : } else if (c == 'Q') {
- 2662 : /* from SnapRAID 11.0 the 'Q' command include size info and multi file support */
- 2663 : uint32_t v_level;
- 2664 : uint32_t v_total_blocks;
- 2665 : uint32_t v_free_blocks;
- 2666 : uint32_t v_split_mac;
- 2667 : unsigned s;
- 2668 :
- 2669 1415 : ret = sgetb32(f, &v_level);
- 2670 1415 : if (ret < 0) {
- 2671 : /* LCOV_EXCL_START */
- 2672 : decoding_error(path, f);
- 2673 : os_abort();
- 2674 : /* LCOV_EXCL_STOP */
- 2675 : }
- 2676 :
- 2677 1415 : ret = sgetb32(f, &v_total_blocks);
- 2678 1415 : if (ret < 0) {
- 2679 : /* LCOV_EXCL_START */
- 2680 : decoding_error(path, f);
- 2681 : os_abort();
- 2682 : /* LCOV_EXCL_STOP */
- 2683 : }
- 2684 :
- 2685 1415 : ret = sgetb32(f, &v_free_blocks);
- 2686 1415 : if (ret < 0) {
- 2687 : /* LCOV_EXCL_START */
- 2688 : decoding_error(path, f);
- 2689 : os_abort();
- 2690 : /* LCOV_EXCL_STOP */
- 2691 : }
- 2692 :
- 2693 1415 : ret = sgetb32(f, &v_split_mac);
- 2694 1415 : if (ret < 0) {
- 2695 : /* LCOV_EXCL_START */
- 2696 : decoding_error(path, f);
- 2697 : os_abort();
- 2698 : /* LCOV_EXCL_STOP */
- 2699 : }
- 2700 :
- 2701 1415 : if (v_level >= LEV_MAX) {
- 2702 : /* LCOV_EXCL_START */
- 2703 : decoding_error(path, f);
- 2704 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level);
- 2705 : exit(EXIT_FAILURE);
- 2706 : /* LCOV_EXCL_STOP */
- 2707 : }
- 2708 :
- 2709 : /* auto configure if configuration is missing */
- 2710 1415 : if (state->no_conf) {
- 2711 6 : if (v_level >= state->level)
- 2712 5 : state->level = v_level + 1;
- 2713 6 : if (state->parity[v_level].split_mac < v_split_mac)
- 2714 6 : state->parity[v_level].split_mac = v_split_mac;
- 2715 : }
- 2716 :
- 2717 : /* if we use this parity entry */
- 2718 1415 : if (v_level < state->level) {
- 2719 : /* set the parity info */
- 2720 1156 : state->parity[v_level].total_blocks = v_total_blocks;
- 2721 1156 : state->parity[v_level].free_blocks = v_free_blocks;
- 2722 : }
- 2723 :
- 2724 7075 : for (s = 0; s < v_split_mac; ++s) {
- 2725 : char v_path[PATH_MAX];
- 2726 : char v_uuid[UUID_MAX];
- 2727 : uint64_t v_size;
+ 2380 : /* allocate the dir */
+ 2381 790 : dir = dir_alloc(sub);
+ 2382 :
+ 2383 : /* insert the dir in the dir containers */
+ 2384 790 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
+ 2385 790 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir);
+ 2386 :
+ 2387 : /* stat */
+ 2388 790 : ++count_dir;
+ 2389 4093 : } else if (c == 'c') {
+ 2390 : /* get the subcommand */
+ 2391 254 : c = sgetc(f);
+ 2392 :
+ 2393 254 : switch (c) {
+ 2394 : case 'u' :
+ 2395 166 : state->hash = HASH_MURMUR3;
+ 2396 166 : break;
+ 2397 : case 'k' :
+ 2398 88 : state->hash = HASH_SPOOKY2;
+ 2399 88 : break;
+ 2400 : default :
+ 2401 : /* LCOV_EXCL_START */
+ 2402 : decoding_error(path, f);
+ 2403 : log_fatal("Invalid checksum!\n");
+ 2404 : os_abort();
+ 2405 : /* LCOV_EXCL_STOP */
+ 2406 : }
+ 2407 :
+ 2408 : /* read the seed */
+ 2409 254 : ret = sread(f, state->hashseed, HASH_MAX);
+ 2410 254 : if (ret < 0) {
+ 2411 : /* LCOV_EXCL_START */
+ 2412 : decoding_error(path, f);
+ 2413 : os_abort();
+ 2414 : /* LCOV_EXCL_STOP */
+ 2415 : }
+ 2416 3839 : } else if (c == 'C') {
+ 2417 : /* get the sub-command */
+ 2418 4 : c = sgetc(f);
+ 2419 :
+ 2420 4 : switch (c) {
+ 2421 : case 'u' :
+ 2422 4 : state->prevhash = HASH_MURMUR3;
+ 2423 4 : break;
+ 2424 : case 'k' :
+ 2425 0 : state->prevhash = HASH_SPOOKY2;
+ 2426 0 : break;
+ 2427 : default :
+ 2428 : /* LCOV_EXCL_START */
+ 2429 : decoding_error(path, f);
+ 2430 : log_fatal("Invalid checksum!\n");
+ 2431 : os_abort();
+ 2432 : /* LCOV_EXCL_STOP */
+ 2433 : }
+ 2434 :
+ 2435 : /* read the seed */
+ 2436 4 : ret = sread(f, state->prevhashseed, HASH_MAX);
+ 2437 4 : if (ret < 0) {
+ 2438 : /* LCOV_EXCL_START */
+ 2439 : decoding_error(path, f);
+ 2440 : os_abort();
+ 2441 : /* LCOV_EXCL_STOP */
+ 2442 : }
+ 2443 3835 : } else if (c == 'z') {
+ 2444 : uint32_t block_size;
+ 2445 :
+ 2446 254 : ret = sgetb32(f, &block_size);
+ 2447 254 : if (ret < 0) {
+ 2448 : /* LCOV_EXCL_START */
+ 2449 : decoding_error(path, f);
+ 2450 : os_abort();
+ 2451 : /* LCOV_EXCL_STOP */
+ 2452 : }
+ 2453 :
+ 2454 254 : if (block_size == 0) {
+ 2455 : /* LCOV_EXCL_START */
+ 2456 : decoding_error(path, f);
+ 2457 : log_fatal("Zero 'blocksize' specification in the content file!\n");
+ 2458 : exit(EXIT_FAILURE);
+ 2459 : /* LCOV_EXCL_STOP */
+ 2460 : }
+ 2461 :
+ 2462 : /* without configuration, auto assign the block size */
+ 2463 254 : if (state->no_conf) {
+ 2464 1 : state->block_size = block_size;
+ 2465 : }
+ 2466 :
+ 2467 254 : if (block_size != state->block_size) {
+ 2468 : /* LCOV_EXCL_START */
+ 2469 : decoding_error(path, f);
+ 2470 : log_fatal("Mismatching 'blocksize' specification in the content file!\n");
+ 2471 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", block_size / KIBI);
+ 2472 : exit(EXIT_FAILURE);
+ 2473 : /* LCOV_EXCL_STOP */
+ 2474 : }
+ 2475 3581 : } else if (c == 'y') {
+ 2476 : uint32_t hash_size;
+ 2477 :
+ 2478 254 : ret = sgetb32(f, &hash_size);
+ 2479 254 : if (ret < 0) {
+ 2480 : /* LCOV_EXCL_START */
+ 2481 : decoding_error(path, f);
+ 2482 : os_abort();
+ 2483 : /* LCOV_EXCL_STOP */
+ 2484 : }
+ 2485 :
+ 2486 254 : if (hash_size < 2 || hash_size > HASH_MAX) {
+ 2487 : /* LCOV_EXCL_START */
+ 2488 : decoding_error(path, f);
+ 2489 : log_fatal("Invalid 'hashsize' specification in the content file!\n");
+ 2490 : exit(EXIT_FAILURE);
+ 2491 : /* LCOV_EXCL_STOP */
+ 2492 : }
+ 2493 :
+ 2494 : /* without configuration, auto assign the block size */
+ 2495 254 : if (state->no_conf) {
+ 2496 1 : BLOCK_HASH_SIZE = hash_size;
+ 2497 : }
+ 2498 :
+ 2499 254 : if ((int)hash_size != BLOCK_HASH_SIZE) {
+ 2500 : /* LCOV_EXCL_START */
+ 2501 : decoding_error(path, f);
+ 2502 : log_fatal("Mismatching 'hashsize' specification in the content file!\n");
+ 2503 : log_fatal("Please restore the 'hashsize' value in the configuration file to '%u'\n", hash_size);
+ 2504 : exit(EXIT_FAILURE);
+ 2505 : /* LCOV_EXCL_STOP */
+ 2506 : }
+ 2507 3327 : } else if (c == 'x') {
+ 2508 254 : ret = sgetb32(f, &blockmax);
+ 2509 254 : if (ret < 0) {
+ 2510 : /* LCOV_EXCL_START */
+ 2511 : decoding_error(path, f);
+ 2512 : os_abort();
+ 2513 : /* LCOV_EXCL_STOP */
+ 2514 : }
+ 2515 4476 : } else if (c == 'm' || c == 'M') {
+ 2516 : struct snapraid_map* map;
+ 2517 : char uuid[UUID_MAX];
+ 2518 : uint32_t v_pos;
+ 2519 : uint32_t v_total_blocks;
+ 2520 : uint32_t v_free_blocks;
+ 2521 : struct snapraid_disk* disk;
+ 2522 :
+ 2523 1403 : ret = sgetbs(f, buffer, sizeof(buffer));
+ 2524 1403 : if (ret < 0) {
+ 2525 : /* LCOV_EXCL_START */
+ 2526 : decoding_error(path, f);
+ 2527 : os_abort();
+ 2528 : /* LCOV_EXCL_STOP */
+ 2529 : }
+ 2530 :
+ 2531 1403 : ret = sgetb32(f, &v_pos);
+ 2532 1403 : if (ret < 0) {
+ 2533 : /* LCOV_EXCL_START */
+ 2534 : decoding_error(path, f);
+ 2535 : os_abort();
+ 2536 : /* LCOV_EXCL_STOP */
+ 2537 : }
+ 2538 :
+ 2539 : /* from SnapRAID 7.0 the 'M' command includes the free space */
+ 2540 1403 : if (c == 'M') {
+ 2541 1403 : ret = sgetb32(f, &v_total_blocks);
+ 2542 1403 : if (ret < 0) {
+ 2543 : /* LCOV_EXCL_START */
+ 2544 : decoding_error(path, f);
+ 2545 : os_abort();
+ 2546 : /* LCOV_EXCL_STOP */
+ 2547 : }
+ 2548 :
+ 2549 1403 : ret = sgetb32(f, &v_free_blocks);
+ 2550 1403 : if (ret < 0) {
+ 2551 : /* LCOV_EXCL_START */
+ 2552 : decoding_error(path, f);
+ 2553 : os_abort();
+ 2554 : /* LCOV_EXCL_STOP */
+ 2555 : }
+ 2556 : } else {
+ 2557 0 : v_total_blocks = 0;
+ 2558 0 : v_free_blocks = 0;
+ 2559 : }
+ 2560 :
+ 2561 : /* read the uuid */
+ 2562 1403 : ret = sgetbs(f, uuid, sizeof(uuid));
+ 2563 1403 : if (ret < 0) {
+ 2564 : /* LCOV_EXCL_START */
+ 2565 : decoding_error(path, f);
+ 2566 : os_abort();
+ 2567 : /* LCOV_EXCL_STOP */
+ 2568 : }
+ 2569 :
+ 2570 : /* find the disk */
+ 2571 1403 : disk = find_disk_by_name(state, buffer);
+ 2572 1403 : if (!disk) {
+ 2573 : /* search by UUID if renamed */
+ 2574 2 : disk = find_disk_by_uuid(state, uuid);
+ 2575 2 : if (disk) {
+ 2576 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name);
+ 2577 :
+ 2578 : /* write the new state with the new name */
+ 2579 2 : state->need_write = 1;
+ 2580 : }
+ 2581 : }
+ 2582 1403 : if (!disk) {
+ 2583 : /* LCOV_EXCL_START */
+ 2584 : decoding_error(path, f);
+ 2585 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid);
+ 2586 : log_fatal("If you have removed it from the configuration file, please restore it\n");
+ 2587 : /* if it's a command without UUID, it cannot autorename using UUID */
+ 2588 : if (state->opt.skip_disk_access)
+ 2589 : log_fatal("If you have renamed it, run 'sync' to update the new name\n");
+ 2590 : exit(EXIT_FAILURE);
+ 2591 : /* LCOV_EXCL_STOP */
+ 2592 : }
+ 2593 :
+ 2594 1403 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid);
+ 2595 :
+ 2596 1403 : tommy_list_insert_tail(&state->maplist, &map->node, map);
+ 2597 :
+ 2598 : /* insert in the mapping vector */
+ 2599 1403 : tommy_array_grow(&disk_mapping, mapping_max + 1);
+ 2600 1403 : tommy_array_set(&disk_mapping, mapping_max, disk);
+ 2601 1403 : ++mapping_max;
+ 2602 1670 : } else if (c == 'P') {
+ 2603 : /* from SnapRAID 7.0 the 'P' command includes the free space */
+ 2604 : /* from SnapRAID 11.0 the 'P' command is deprecated by 'Q' */
+ 2605 : char v_uuid[UUID_MAX];
+ 2606 : uint32_t v_level;
+ 2607 : uint32_t v_total_blocks;
+ 2608 : uint32_t v_free_blocks;
+ 2609 :
+ 2610 0 : ret = sgetb32(f, &v_level);
+ 2611 0 : if (ret < 0) {
+ 2612 : /* LCOV_EXCL_START */
+ 2613 : decoding_error(path, f);
+ 2614 : os_abort();
+ 2615 : /* LCOV_EXCL_STOP */
+ 2616 : }
+ 2617 :
+ 2618 0 : ret = sgetb32(f, &v_total_blocks);
+ 2619 0 : if (ret < 0) {
+ 2620 : /* LCOV_EXCL_START */
+ 2621 : decoding_error(path, f);
+ 2622 : os_abort();
+ 2623 : /* LCOV_EXCL_STOP */
+ 2624 : }
+ 2625 :
+ 2626 0 : ret = sgetb32(f, &v_free_blocks);
+ 2627 0 : if (ret < 0) {
+ 2628 : /* LCOV_EXCL_START */
+ 2629 : decoding_error(path, f);
+ 2630 : os_abort();
+ 2631 : /* LCOV_EXCL_STOP */
+ 2632 : }
+ 2633 :
+ 2634 0 : ret = sgetbs(f, v_uuid, sizeof(v_uuid));
+ 2635 0 : if (ret < 0) {
+ 2636 : /* LCOV_EXCL_START */
+ 2637 : decoding_error(path, f);
+ 2638 : os_abort();
+ 2639 : /* LCOV_EXCL_STOP */
+ 2640 : }
+ 2641 :
+ 2642 0 : if (v_level >= LEV_MAX) {
+ 2643 : /* LCOV_EXCL_START */
+ 2644 : decoding_error(path, f);
+ 2645 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level);
+ 2646 : exit(EXIT_FAILURE);
+ 2647 : /* LCOV_EXCL_STOP */
+ 2648 : }
+ 2649 :
+ 2650 : /* auto configure if configuration is missing */
+ 2651 0 : if (state->no_conf) {
+ 2652 0 : if (v_level >= state->level)
+ 2653 0 : state->level = v_level + 1;
+ 2654 : }
+ 2655 :
+ 2656 : /* if we use this parity entry */
+ 2657 0 : if (v_level < state->level) {
+ 2658 : /* if the configuration has more splits, keep them */
+ 2659 0 : if (state->parity[v_level].split_mac < 1)
+ 2660 0 : state->parity[v_level].split_mac = 1;
+ 2661 : /* set the parity info */
+ 2662 0 : pathcpy(state->parity[v_level].split_map[0].uuid, sizeof(state->parity[v_level].split_map[0].uuid), v_uuid);
+ 2663 0 : state->parity[v_level].total_blocks = v_total_blocks;
+ 2664 0 : state->parity[v_level].free_blocks = v_free_blocks;
+ 2665 : }
+ 2666 1670 : } else if (c == 'Q') {
+ 2667 : /* from SnapRAID 11.0 the 'Q' command include size info and multi file support */
+ 2668 : uint32_t v_level;
+ 2669 : uint32_t v_total_blocks;
+ 2670 : uint32_t v_free_blocks;
+ 2671 : uint32_t v_split_mac;
+ 2672 : unsigned s;
+ 2673 :
+ 2674 1417 : ret = sgetb32(f, &v_level);
+ 2675 1417 : if (ret < 0) {
+ 2676 : /* LCOV_EXCL_START */
+ 2677 : decoding_error(path, f);
+ 2678 : os_abort();
+ 2679 : /* LCOV_EXCL_STOP */
+ 2680 : }
+ 2681 :
+ 2682 1417 : ret = sgetb32(f, &v_total_blocks);
+ 2683 1417 : if (ret < 0) {
+ 2684 : /* LCOV_EXCL_START */
+ 2685 : decoding_error(path, f);
+ 2686 : os_abort();
+ 2687 : /* LCOV_EXCL_STOP */
+ 2688 : }
+ 2689 :
+ 2690 1417 : ret = sgetb32(f, &v_free_blocks);
+ 2691 1417 : if (ret < 0) {
+ 2692 : /* LCOV_EXCL_START */
+ 2693 : decoding_error(path, f);
+ 2694 : os_abort();
+ 2695 : /* LCOV_EXCL_STOP */
+ 2696 : }
+ 2697 :
+ 2698 1417 : ret = sgetb32(f, &v_split_mac);
+ 2699 1417 : if (ret < 0) {
+ 2700 : /* LCOV_EXCL_START */
+ 2701 : decoding_error(path, f);
+ 2702 : os_abort();
+ 2703 : /* LCOV_EXCL_STOP */
+ 2704 : }
+ 2705 :
+ 2706 1417 : if (v_level >= LEV_MAX) {
+ 2707 : /* LCOV_EXCL_START */
+ 2708 : decoding_error(path, f);
+ 2709 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level);
+ 2710 : exit(EXIT_FAILURE);
+ 2711 : /* LCOV_EXCL_STOP */
+ 2712 : }
+ 2713 :
+ 2714 : /* auto configure if configuration is missing */
+ 2715 1417 : if (state->no_conf) {
+ 2716 6 : if (v_level >= state->level)
+ 2717 5 : state->level = v_level + 1;
+ 2718 6 : if (state->parity[v_level].split_mac < v_split_mac)
+ 2719 6 : state->parity[v_level].split_mac = v_split_mac;
+ 2720 : }
+ 2721 :
+ 2722 : /* if we use this parity entry */
+ 2723 1417 : if (v_level < state->level) {
+ 2724 : /* set the parity info */
+ 2725 1158 : state->parity[v_level].total_blocks = v_total_blocks;
+ 2726 1158 : state->parity[v_level].free_blocks = v_free_blocks;
+ 2727 : }
2728 :
- 2729 5660 : ret = sgetbs(f, v_path, sizeof(v_path));
- 2730 5660 : if (ret < 0) {
- 2731 : /* LCOV_EXCL_START */
- 2732 : decoding_error(path, f);
- 2733 : os_abort();
- 2734 : /* LCOV_EXCL_STOP */
- 2735 : }
- 2736 :
- 2737 5660 : ret = sgetbs(f, v_uuid, sizeof(v_uuid));
- 2738 5660 : if (ret < 0) {
- 2739 : /* LCOV_EXCL_START */
- 2740 : decoding_error(path, f);
- 2741 : os_abort();
- 2742 : /* LCOV_EXCL_STOP */
- 2743 : }
- 2744 :
- 2745 5660 : ret = sgetb64(f, &v_size);
- 2746 5660 : if (ret < 0) {
- 2747 : /* LCOV_EXCL_START */
- 2748 : decoding_error(path, f);
- 2749 : os_abort();
- 2750 : /* LCOV_EXCL_STOP */
- 2751 : }
- 2752 :
- 2753 : /* if we use this parity entry */
- 2754 5660 : if (v_level < state->level) {
- 2755 : /* if this split was removed from the configuration */
- 2756 4624 : if (s >= state->parity[v_level].split_mac) {
- 2757 : /* if the file is used, we really need it */
- 2758 0 : if (v_size != 0) {
- 2759 : /* LCOV_EXCL_START */
- 2760 : decoding_error(path, f);
- 2761 : log_fatal("Parity '%s' misses used file '%u'!\n", lev_config_name(v_level), s);
- 2762 : log_fatal("If you have removed it from the configuration file, please restore it\n");
- 2763 : exit(EXIT_FAILURE);
- 2764 : /* LCOV_EXCL_STOP */
- 2765 : }
- 2766 :
- 2767 : /* otherwise we can drop it */
- 2768 0 : log_fatal("WARNING! Dropping from '%s' unused split '%u'\n", lev_config_name(v_level), s);
- 2769 : } else {
- 2770 : /* we copy the path only if without configuration file */
- 2771 4624 : if (state->no_conf)
- 2772 24 : pathcpy(state->parity[v_level].split_map[s].path, sizeof(state->parity[v_level].split_map[s].path), v_path);
- 2773 :
- 2774 : /* set the split info */
- 2775 4624 : pathcpy(state->parity[v_level].split_map[s].uuid, sizeof(state->parity[v_level].split_map[s].uuid), v_uuid);
- 2776 4624 : state->parity[v_level].split_map[s].size = v_size;
- 2777 :
- 2778 : /* log the info read from the content file */
- 2779 9248 : log_tag("content:%s:%u:%s:%s:%" PRIi64 "\n", lev_config_name(v_level), s,
- 2780 4624 : state->parity[v_level].split_map[s].path,
- 2781 4624 : state->parity[v_level].split_map[s].uuid,
- 2782 : state->parity[v_level].split_map[s].size);
- 2783 : }
- 2784 : }
- 2785 : }
- 2786 254 : } else if (c == 'N') {
- 2787 : uint32_t crc_stored;
- 2788 : uint32_t crc_computed;
- 2789 :
- 2790 : /* get the crc before reading it from the file */
- 2791 253 : crc_computed = scrc(f);
- 2792 :
- 2793 253 : ret = sgetble32(f, &crc_stored);
- 2794 253 : if (ret < 0) {
- 2795 : /* LCOV_EXCL_START */
- 2796 : /* here don't call decoding_error() because it's too late to get the crc */
- 2797 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f));
- 2798 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 2799 : exit(EXIT_FAILURE);
- 2800 : /* LCOV_EXCL_STOP */
- 2801 : }
- 2802 :
- 2803 253 : if (crc_stored != crc_computed) {
- 2804 : /* LCOV_EXCL_START */
- 2805 : /* here don't call decoding_error() because it's too late to get the crc */
- 2806 : log_fatal("Mismatching CRC in '%s'\n", path);
- 2807 : log_fatal("This content file is damaged! Use an alternate copy.\n");
- 2808 : exit(EXIT_FAILURE);
- 2809 : /* LCOV_EXCL_STOP */
- 2810 : }
- 2811 :
- 2812 253 : crc_checked = 1;
- 2813 : } else {
- 2814 : /* LCOV_EXCL_START */
- 2815 : decoding_error(path, f);
- 2816 : log_fatal("Invalid command '%c'!\n", (char)c);
- 2817 : os_abort();
- 2818 : /* LCOV_EXCL_STOP */
- 2819 : }
- 2820 3735358 : }
- 2821 :
- 2822 253 : tommy_array_done(&disk_mapping);
- 2823 :
- 2824 253 : if (serror(f)) {
- 2825 : /* LCOV_EXCL_START */
- 2826 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
- 2827 : exit(EXIT_FAILURE);
- 2828 : /* LCOV_EXCL_STOP */
- 2829 : }
- 2830 :
- 2831 253 : if (!crc_checked) {
- 2832 : /* LCOV_EXCL_START */
- 2833 : log_fatal("Finished reading '%s' without finding the CRC\n", path);
- 2834 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n");
- 2835 : exit(EXIT_FAILURE);
- 2836 : /* LCOV_EXCL_STOP */
- 2837 : }
- 2838 :
- 2839 : /* check the file-system on all disks */
- 2840 253 : state_fscheck(state, "after read");
- 2841 :
- 2842 : /* check that the stored parity size matches the loaded state */
- 2843 253 : if (blockmax != parity_allocated_size(state)) {
- 2844 : /* LCOV_EXCL_START */
- 2845 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
- 2846 : if (state->opt.skip_content_check) {
- 2847 : log_fatal("Overriding.\n");
- 2848 : blockmax = parity_allocated_size(state);
- 2849 : } else {
- 2850 : exit(EXIT_FAILURE);
- 2851 : }
- 2852 : /* LCOV_EXCL_STOP */
- 2853 : }
- 2854 :
- 2855 253 : msg_verbose("%8u files\n", count_file);
- 2856 253 : msg_verbose("%8u hardlinks\n", count_hardlink);
- 2857 253 : msg_verbose("%8u symlinks\n", count_symlink);
- 2858 253 : msg_verbose("%8u empty dirs\n", count_dir);
- 2859 253 : }
- 2860 :
- 2861 : struct state_write_thread_context {
- 2862 : struct snapraid_state* state;
- 2863 : #if HAVE_MT_WRITE
- 2864 : pthread_t thread;
- 2865 : #endif
- 2866 : /* input */
- 2867 : block_off_t blockmax;
- 2868 : time_t info_oldest;
- 2869 : int info_has_rehash;
- 2870 : STREAM* f;
- 2871 : /* output */
- 2872 : uint32_t crc;
- 2873 : unsigned count_file;
- 2874 : unsigned count_hardlink;
- 2875 : unsigned count_symlink;
- 2876 : unsigned count_dir;
- 2877 : };
- 2878 :
- 2879 151 : static void* state_write_thread(void* arg)
- 2880 : {
- 2881 151 : struct state_write_thread_context* context = arg;
- 2882 151 : struct snapraid_state* state = context->state;
- 2883 151 : block_off_t blockmax = context->blockmax;
- 2884 151 : time_t info_oldest = context->info_oldest;
- 2885 151 : int info_has_rehash = context->info_has_rehash;
- 2886 151 : STREAM* f = context->f;
- 2887 : uint32_t crc;
- 2888 : unsigned count_file;
- 2889 : unsigned count_hardlink;
- 2890 : unsigned count_symlink;
- 2891 : unsigned count_dir;
- 2892 : tommy_node* i;
- 2893 : block_off_t idx;
- 2894 : block_off_t begin;
- 2895 : unsigned l, s;
- 2896 : int version;
- 2897 :
- 2898 151 : count_file = 0;
- 2899 151 : count_hardlink = 0;
- 2900 151 : count_symlink = 0;
- 2901 151 : count_dir = 0;
+ 2729 7083 : for (s = 0; s < v_split_mac; ++s) {
+ 2730 : char v_path[PATH_MAX];
+ 2731 : char v_uuid[UUID_MAX];
+ 2732 : uint64_t v_size;
+ 2733 :
+ 2734 5667 : ret = sgetbs(f, v_path, sizeof(v_path));
+ 2735 5667 : if (ret < 0) {
+ 2736 : /* LCOV_EXCL_START */
+ 2737 : decoding_error(path, f);
+ 2738 : os_abort();
+ 2739 : /* LCOV_EXCL_STOP */
+ 2740 : }
+ 2741 :
+ 2742 5666 : ret = sgetbs(f, v_uuid, sizeof(v_uuid));
+ 2743 5666 : if (ret < 0) {
+ 2744 : /* LCOV_EXCL_START */
+ 2745 : decoding_error(path, f);
+ 2746 : os_abort();
+ 2747 : /* LCOV_EXCL_STOP */
+ 2748 : }
+ 2749 :
+ 2750 5666 : ret = sgetb64(f, &v_size);
+ 2751 5666 : if (ret < 0) {
+ 2752 : /* LCOV_EXCL_START */
+ 2753 : decoding_error(path, f);
+ 2754 : os_abort();
+ 2755 : /* LCOV_EXCL_STOP */
+ 2756 : }
+ 2757 :
+ 2758 : /* if we use this parity entry */
+ 2759 5666 : if (v_level < state->level) {
+ 2760 : /* if this split was removed from the configuration */
+ 2761 4630 : if (s >= state->parity[v_level].split_mac) {
+ 2762 : /* if the file is used, we really need it */
+ 2763 0 : if (v_size != 0) {
+ 2764 : /* LCOV_EXCL_START */
+ 2765 : decoding_error(path, f);
+ 2766 : log_fatal("Parity '%s' misses used file '%u'!\n", lev_config_name(v_level), s);
+ 2767 : log_fatal("If you have removed it from the configuration file, please restore it\n");
+ 2768 : exit(EXIT_FAILURE);
+ 2769 : /* LCOV_EXCL_STOP */
+ 2770 : }
+ 2771 :
+ 2772 : /* otherwise we can drop it */
+ 2773 0 : log_fatal("WARNING! Dropping from '%s' unused split '%u'\n", lev_config_name(v_level), s);
+ 2774 : } else {
+ 2775 : /* we copy the path only if without configuration file */
+ 2776 4630 : if (state->no_conf)
+ 2777 24 : pathcpy(state->parity[v_level].split_map[s].path, sizeof(state->parity[v_level].split_map[s].path), v_path);
+ 2778 :
+ 2779 : /* set the split info */
+ 2780 4630 : pathcpy(state->parity[v_level].split_map[s].uuid, sizeof(state->parity[v_level].split_map[s].uuid), v_uuid);
+ 2781 4630 : state->parity[v_level].split_map[s].size = v_size;
+ 2782 :
+ 2783 : /* log the info read from the content file */
+ 2784 9260 : log_tag("content:%s:%u:%s:%s:%" PRIi64 "\n", lev_config_name(v_level), s,
+ 2785 4630 : state->parity[v_level].split_map[s].path,
+ 2786 4630 : state->parity[v_level].split_map[s].uuid,
+ 2787 : state->parity[v_level].split_map[s].size);
+ 2788 : }
+ 2789 : }
+ 2790 : }
+ 2791 253 : } else if (c == 'N') {
+ 2792 : uint32_t crc_stored;
+ 2793 : uint32_t crc_computed;
+ 2794 :
+ 2795 : /* get the crc before reading it from the file */
+ 2796 253 : crc_computed = scrc(f);
+ 2797 :
+ 2798 253 : ret = sgetble32(f, &crc_stored);
+ 2799 253 : if (ret < 0) {
+ 2800 : /* LCOV_EXCL_START */
+ 2801 : /* here don't call decoding_error() because it's too late to get the crc */
+ 2802 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 2803 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 2804 : exit(EXIT_FAILURE);
+ 2805 : /* LCOV_EXCL_STOP */
+ 2806 : }
+ 2807 :
+ 2808 253 : if (crc_stored != crc_computed) {
+ 2809 : /* LCOV_EXCL_START */
+ 2810 : /* here don't call decoding_error() because it's too late to get the crc */
+ 2811 : log_fatal("Mismatching CRC in '%s'\n", path);
+ 2812 : log_fatal("This content file is damaged! Use an alternate copy.\n");
+ 2813 : exit(EXIT_FAILURE);
+ 2814 : /* LCOV_EXCL_STOP */
+ 2815 : }
+ 2816 :
+ 2817 253 : crc_checked = 1;
+ 2818 : } else {
+ 2819 : /* LCOV_EXCL_START */
+ 2820 : decoding_error(path, f);
+ 2821 : log_fatal("Invalid command '%c'!\n", (char)c);
+ 2822 : os_abort();
+ 2823 : /* LCOV_EXCL_STOP */
+ 2824 : }
+ 2825 3735359 : }
+ 2826 :
+ 2827 253 : tommy_array_done(&disk_mapping);
+ 2828 :
+ 2829 253 : if (serror(f)) {
+ 2830 : /* LCOV_EXCL_START */
+ 2831 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
+ 2832 : exit(EXIT_FAILURE);
+ 2833 : /* LCOV_EXCL_STOP */
+ 2834 : }
+ 2835 :
+ 2836 253 : if (!crc_checked) {
+ 2837 : /* LCOV_EXCL_START */
+ 2838 : log_fatal("Finished reading '%s' without finding the CRC\n", path);
+ 2839 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n");
+ 2840 : exit(EXIT_FAILURE);
+ 2841 : /* LCOV_EXCL_STOP */
+ 2842 : }
+ 2843 :
+ 2844 : /* check the file-system on all disks */
+ 2845 253 : state_fscheck(state, "after read");
+ 2846 :
+ 2847 : /* check that the stored parity size matches the loaded state */
+ 2848 253 : if (blockmax != parity_allocated_size(state)) {
+ 2849 : /* LCOV_EXCL_START */
+ 2850 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
+ 2851 : if (state->opt.skip_content_check) {
+ 2852 : log_fatal("Overriding.\n");
+ 2853 : blockmax = parity_allocated_size(state);
+ 2854 : } else {
+ 2855 : exit(EXIT_FAILURE);
+ 2856 : }
+ 2857 : /* LCOV_EXCL_STOP */
+ 2858 : }
+ 2859 :
+ 2860 253 : msg_verbose("%8u files\n", count_file);
+ 2861 253 : msg_verbose("%8u hardlinks\n", count_hardlink);
+ 2862 253 : msg_verbose("%8u symlinks\n", count_symlink);
+ 2863 253 : msg_verbose("%8u empty dirs\n", count_dir);
+ 2864 253 : }
+ 2865 :
+ 2866 : struct state_write_thread_context {
+ 2867 : struct snapraid_state* state;
+ 2868 : #if HAVE_MT_WRITE
+ 2869 : pthread_t thread;
+ 2870 : #endif
+ 2871 : /* input */
+ 2872 : block_off_t blockmax;
+ 2873 : time_t info_oldest;
+ 2874 : int info_has_rehash;
+ 2875 : STREAM* f;
+ 2876 : /* output */
+ 2877 : uint32_t crc;
+ 2878 : unsigned count_file;
+ 2879 : unsigned count_hardlink;
+ 2880 : unsigned count_symlink;
+ 2881 : unsigned count_dir;
+ 2882 : };
+ 2883 :
+ 2884 151 : static void* state_write_thread(void* arg)
+ 2885 : {
+ 2886 151 : struct state_write_thread_context* context = arg;
+ 2887 151 : struct snapraid_state* state = context->state;
+ 2888 151 : block_off_t blockmax = context->blockmax;
+ 2889 151 : time_t info_oldest = context->info_oldest;
+ 2890 151 : int info_has_rehash = context->info_has_rehash;
+ 2891 151 : STREAM* f = context->f;
+ 2892 : uint32_t crc;
+ 2893 : unsigned count_file;
+ 2894 : unsigned count_hardlink;
+ 2895 : unsigned count_symlink;
+ 2896 : unsigned count_dir;
+ 2897 : tommy_node* i;
+ 2898 : block_off_t idx;
+ 2899 : block_off_t begin;
+ 2900 : unsigned l, s;
+ 2901 : int version;
2902 :
- 2903 : /* check what version to use */
- 2904 151 : version = 2;
- 2905 1012 : for (l = 0; l < state->level; ++l) {
- 2906 861 : if (state->parity[l].split_mac > 1)
- 2907 861 : version = 3;
- 2908 : }
- 2909 151 : if (BLOCK_HASH_SIZE != 16)
- 2910 0 : version = 3;
- 2911 :
- 2912 : /* write header */
- 2913 151 : if (version == 3)
- 2914 151 : swrite("SNAPCNT3\n\3\0\0", 12, f);
- 2915 : else
- 2916 0 : swrite("SNAPCNT2\n\3\0\0", 12, f);
- 2917 :
- 2918 : /* write block size and block max */
- 2919 151 : sputc('z', f);
- 2920 151 : sputb32(state->block_size, f);
- 2921 151 : sputc('x', f);
- 2922 151 : sputb32(blockmax, f);
- 2923 :
- 2924 : /* hash size */
- 2925 151 : if (version == 3) {
- 2926 151 : sputc('y', f);
- 2927 151 : sputb32(BLOCK_HASH_SIZE, f);
- 2928 : }
- 2929 :
- 2930 151 : if (serror(f)) {
- 2931 : /* LCOV_EXCL_START */
- 2932 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2933 : return context;
- 2934 : /* LCOV_EXCL_STOP */
- 2935 : }
- 2936 :
- 2937 151 : sputc('c', f);
- 2938 151 : if (state->hash == HASH_MURMUR3) {
- 2939 122 : sputc('u', f);
- 2940 29 : } else if (state->hash == HASH_SPOOKY2) {
- 2941 29 : sputc('k', f);
- 2942 : } else {
- 2943 : /* LCOV_EXCL_START */
- 2944 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f));
- 2945 : return context;
- 2946 : /* LCOV_EXCL_STOP */
- 2947 : }
- 2948 151 : swrite(state->hashseed, HASH_MAX, f);
- 2949 151 : if (serror(f)) {
- 2950 : /* LCOV_EXCL_START */
- 2951 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2952 : return context;
- 2953 : /* LCOV_EXCL_STOP */
- 2954 : }
- 2955 :
- 2956 : /* previous hash only present */
- 2957 151 : if (state->prevhash != HASH_UNDEFINED) {
- 2958 : /* if at least one rehash tag found, we have to save the previous hash */
- 2959 3 : if (info_has_rehash) {
- 2960 2 : sputc('C', f);
- 2961 2 : if (state->prevhash == HASH_MURMUR3) {
- 2962 2 : sputc('u', f);
- 2963 0 : } else if (state->prevhash == HASH_SPOOKY2) {
- 2964 0 : sputc('k', f);
- 2965 : } else {
- 2966 : /* LCOV_EXCL_START */
- 2967 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f));
- 2968 : return context;
- 2969 : /* LCOV_EXCL_STOP */
- 2970 : }
- 2971 2 : swrite(state->prevhashseed, HASH_MAX, f);
- 2972 2 : if (serror(f)) {
- 2973 : /* LCOV_EXCL_START */
- 2974 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 2975 : return context;
- 2976 : /* LCOV_EXCL_STOP */
- 2977 : }
- 2978 : }
- 2979 : }
- 2980 :
- 2981 : /* for each map */
- 2982 1057 : for (i = state->maplist; i != 0; i = i->next) {
- 2983 906 : struct snapraid_map* map = i->data;
- 2984 : struct snapraid_disk* disk;
+ 2903 151 : count_file = 0;
+ 2904 151 : count_hardlink = 0;
+ 2905 151 : count_symlink = 0;
+ 2906 151 : count_dir = 0;
+ 2907 :
+ 2908 : /* check what version to use */
+ 2909 151 : version = 2;
+ 2910 1012 : for (l = 0; l < state->level; ++l) {
+ 2911 861 : if (state->parity[l].split_mac > 1)
+ 2912 861 : version = 3;
+ 2913 : }
+ 2914 151 : if (BLOCK_HASH_SIZE != 16)
+ 2915 0 : version = 3;
+ 2916 :
+ 2917 : /* write header */
+ 2918 151 : if (version == 3)
+ 2919 151 : swrite("SNAPCNT3\n\3\0\0", 12, f);
+ 2920 : else
+ 2921 0 : swrite("SNAPCNT2\n\3\0\0", 12, f);
+ 2922 :
+ 2923 : /* write block size and block max */
+ 2924 151 : sputc('z', f);
+ 2925 151 : sputb32(state->block_size, f);
+ 2926 151 : sputc('x', f);
+ 2927 151 : sputb32(blockmax, f);
+ 2928 :
+ 2929 : /* hash size */
+ 2930 151 : if (version == 3) {
+ 2931 151 : sputc('y', f);
+ 2932 151 : sputb32(BLOCK_HASH_SIZE, f);
+ 2933 : }
+ 2934 :
+ 2935 151 : if (serror(f)) {
+ 2936 : /* LCOV_EXCL_START */
+ 2937 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2938 : return context;
+ 2939 : /* LCOV_EXCL_STOP */
+ 2940 : }
+ 2941 :
+ 2942 151 : sputc('c', f);
+ 2943 151 : if (state->hash == HASH_MURMUR3) {
+ 2944 122 : sputc('u', f);
+ 2945 29 : } else if (state->hash == HASH_SPOOKY2) {
+ 2946 29 : sputc('k', f);
+ 2947 : } else {
+ 2948 : /* LCOV_EXCL_START */
+ 2949 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f));
+ 2950 : return context;
+ 2951 : /* LCOV_EXCL_STOP */
+ 2952 : }
+ 2953 151 : swrite(state->hashseed, HASH_MAX, f);
+ 2954 151 : if (serror(f)) {
+ 2955 : /* LCOV_EXCL_START */
+ 2956 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2957 : return context;
+ 2958 : /* LCOV_EXCL_STOP */
+ 2959 : }
+ 2960 :
+ 2961 : /* previous hash only present */
+ 2962 151 : if (state->prevhash != HASH_UNDEFINED) {
+ 2963 : /* if at least one rehash tag found, we have to save the previous hash */
+ 2964 3 : if (info_has_rehash) {
+ 2965 2 : sputc('C', f);
+ 2966 2 : if (state->prevhash == HASH_MURMUR3) {
+ 2967 2 : sputc('u', f);
+ 2968 0 : } else if (state->prevhash == HASH_SPOOKY2) {
+ 2969 0 : sputc('k', f);
+ 2970 : } else {
+ 2971 : /* LCOV_EXCL_START */
+ 2972 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f));
+ 2973 : return context;
+ 2974 : /* LCOV_EXCL_STOP */
+ 2975 : }
+ 2976 2 : swrite(state->prevhashseed, HASH_MAX, f);
+ 2977 2 : if (serror(f)) {
+ 2978 : /* LCOV_EXCL_START */
+ 2979 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 2980 : return context;
+ 2981 : /* LCOV_EXCL_STOP */
+ 2982 : }
+ 2983 : }
+ 2984 : }
2985 :
- 2986 : /* find the disk for this mapping */
- 2987 906 : disk = find_disk_by_name(state, map->name);
- 2988 906 : if (!disk) {
- 2989 : /* LCOV_EXCL_START */
- 2990 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
- 2991 : return context;
- 2992 : /* LCOV_EXCL_STOP */
- 2993 : }
- 2994 :
- 2995 : /* save the mapping only if disk is mapped */
- 2996 906 : if (disk->mapping_idx != -1) {
- 2997 814 : sputc('M', f);
- 2998 814 : sputbs(map->name, f);
- 2999 814 : sputb32(map->position, f);
- 3000 814 : sputb32(map->total_blocks, f);
- 3001 814 : sputb32(map->free_blocks, f);
- 3002 814 : sputbs(map->uuid, f);
- 3003 814 : if (serror(f)) {
- 3004 : /* LCOV_EXCL_START */
- 3005 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3006 : return context;
- 3007 : /* LCOV_EXCL_STOP */
- 3008 : }
- 3009 : }
- 3010 : }
- 3011 :
- 3012 : /* for each parity */
- 3013 1012 : for (l = 0; l < state->level; ++l) {
- 3014 861 : if (version == 3) {
- 3015 861 : sputc('Q', f);
- 3016 861 : sputb32(l, f);
- 3017 861 : sputb32(state->parity[l].total_blocks, f);
- 3018 861 : sputb32(state->parity[l].free_blocks, f);
- 3019 861 : sputb32(state->parity[l].split_mac, f);
- 3020 4305 : for (s = 0; s < state->parity[l].split_mac; ++s) {
- 3021 3444 : sputbs(state->parity[l].split_map[s].path, f);
- 3022 3444 : sputbs(state->parity[l].split_map[s].uuid, f);
- 3023 3444 : sputb64(state->parity[l].split_map[s].size, f);
- 3024 : }
- 3025 : } else {
- 3026 0 : sputc('P', f);
- 3027 0 : sputb32(l, f);
- 3028 0 : sputb32(state->parity[l].total_blocks, f);
- 3029 0 : sputb32(state->parity[l].free_blocks, f);
- 3030 0 : sputbs(state->parity[l].split_map[0].uuid, f);
- 3031 : }
- 3032 861 : if (serror(f)) {
- 3033 : /* LCOV_EXCL_START */
- 3034 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3035 : return context;
- 3036 : /* LCOV_EXCL_STOP */
- 3037 : }
- 3038 : }
- 3039 :
- 3040 : /* for each disk */
- 3041 1057 : for (i = state->disklist; i != 0; i = i->next) {
- 3042 : tommy_node* j;
- 3043 906 : struct snapraid_disk* disk = i->data;
+ 2986 : /* for each map */
+ 2987 1057 : for (i = state->maplist; i != 0; i = i->next) {
+ 2988 906 : struct snapraid_map* map = i->data;
+ 2989 : struct snapraid_disk* disk;
+ 2990 :
+ 2991 : /* find the disk for this mapping */
+ 2992 906 : disk = find_disk_by_name(state, map->name);
+ 2993 906 : if (!disk) {
+ 2994 : /* LCOV_EXCL_START */
+ 2995 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
+ 2996 : return context;
+ 2997 : /* LCOV_EXCL_STOP */
+ 2998 : }
+ 2999 :
+ 3000 : /* save the mapping only if disk is mapped */
+ 3001 906 : if (disk->mapping_idx != -1) {
+ 3002 814 : sputc('M', f);
+ 3003 814 : sputbs(map->name, f);
+ 3004 814 : sputb32(map->position, f);
+ 3005 814 : sputb32(map->total_blocks, f);
+ 3006 814 : sputb32(map->free_blocks, f);
+ 3007 814 : sputbs(map->uuid, f);
+ 3008 814 : if (serror(f)) {
+ 3009 : /* LCOV_EXCL_START */
+ 3010 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3011 : return context;
+ 3012 : /* LCOV_EXCL_STOP */
+ 3013 : }
+ 3014 : }
+ 3015 : }
+ 3016 :
+ 3017 : /* for each parity */
+ 3018 1012 : for (l = 0; l < state->level; ++l) {
+ 3019 861 : if (version == 3) {
+ 3020 861 : sputc('Q', f);
+ 3021 861 : sputb32(l, f);
+ 3022 861 : sputb32(state->parity[l].total_blocks, f);
+ 3023 861 : sputb32(state->parity[l].free_blocks, f);
+ 3024 861 : sputb32(state->parity[l].split_mac, f);
+ 3025 4305 : for (s = 0; s < state->parity[l].split_mac; ++s) {
+ 3026 3444 : sputbs(state->parity[l].split_map[s].path, f);
+ 3027 3444 : sputbs(state->parity[l].split_map[s].uuid, f);
+ 3028 3444 : sputb64(state->parity[l].split_map[s].size, f);
+ 3029 : }
+ 3030 : } else {
+ 3031 0 : sputc('P', f);
+ 3032 0 : sputb32(l, f);
+ 3033 0 : sputb32(state->parity[l].total_blocks, f);
+ 3034 0 : sputb32(state->parity[l].free_blocks, f);
+ 3035 0 : sputbs(state->parity[l].split_map[0].uuid, f);
+ 3036 : }
+ 3037 861 : if (serror(f)) {
+ 3038 : /* LCOV_EXCL_START */
+ 3039 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3040 : return context;
+ 3041 : /* LCOV_EXCL_STOP */
+ 3042 : }
+ 3043 : }
3044 :
- 3045 : /* if the disk is not mapped, skip it */
- 3046 906 : if (disk->mapping_idx < 0)
- 3047 92 : continue;
- 3048 :
- 3049 : /* for each file */
- 3050 1771698 : for (j = disk->filelist; j != 0; j = j->next) {
- 3051 1770884 : struct snapraid_file* file = j->data;
- 3052 : uint64_t size;
- 3053 : uint64_t mtime_sec;
- 3054 : int32_t mtime_nsec;
- 3055 : uint64_t inode;
- 3056 :
- 3057 1770884 : size = file->size;
- 3058 1770884 : mtime_sec = file->mtime_sec;
- 3059 1770884 : mtime_nsec = file->mtime_nsec;
- 3060 1770884 : inode = file->inode;
+ 3045 : /* for each disk */
+ 3046 1057 : for (i = state->disklist; i != 0; i = i->next) {
+ 3047 : tommy_node* j;
+ 3048 906 : struct snapraid_disk* disk = i->data;
+ 3049 :
+ 3050 : /* if the disk is not mapped, skip it */
+ 3051 906 : if (disk->mapping_idx < 0)
+ 3052 92 : continue;
+ 3053 :
+ 3054 : /* for each file */
+ 3055 1771698 : for (j = disk->filelist; j != 0; j = j->next) {
+ 3056 1770884 : struct snapraid_file* file = j->data;
+ 3057 : uint64_t size;
+ 3058 : uint64_t mtime_sec;
+ 3059 : int32_t mtime_nsec;
+ 3060 : uint64_t inode;
3061 :
- 3062 1770884 : sputc('f', f);
- 3063 1770884 : sputb32(disk->mapping_idx, f);
- 3064 1770884 : sputb64(size, f);
- 3065 1770884 : sputb64(mtime_sec, f);
- 3066 : /* encode STAT_NSEC_INVALID as 0 */
- 3067 1770884 : if (mtime_nsec == STAT_NSEC_INVALID)
- 3068 0 : sputb32(0, f);
- 3069 : else
- 3070 1770884 : sputb32(mtime_nsec + 1, f);
- 3071 1770884 : sputb64(inode, f);
- 3072 1770884 : sputbs(file->sub, f);
- 3073 1770884 : if (serror(f)) {
- 3074 : /* LCOV_EXCL_START */
- 3075 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3076 : return context;
- 3077 : /* LCOV_EXCL_STOP */
- 3078 : }
- 3079 :
- 3080 : /* for all the blocks of the file */
- 3081 1770884 : begin = 0;
- 3082 5322967 : while (begin < file->blockmax) {
- 3083 1781199 : unsigned v_state = block_state_get(fs_file2block_get(file, begin));
- 3084 1781199 : block_off_t v_pos = fs_file2par_get(disk, file, begin);
- 3085 : uint32_t v_count;
- 3086 :
- 3087 : block_off_t end;
- 3088 :
- 3089 : /* find the end of run of blocks */
- 3090 1781199 : end = begin + 1;
- 3091 6146339 : while (end < file->blockmax) {
- 3092 2596728 : if (v_state != block_state_get(fs_file2block_get(file, end)))
- 3093 12 : break;
- 3094 2596716 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end))
- 3095 12775 : break;
- 3096 2583941 : ++end;
- 3097 : }
- 3098 :
- 3099 1781199 : switch (v_state) {
- 3100 : case BLOCK_STATE_BLK :
- 3101 1678540 : sputc('b', f);
- 3102 1678540 : break;
- 3103 : case BLOCK_STATE_CHG :
- 3104 67741 : sputc('g', f);
- 3105 67741 : break;
- 3106 : case BLOCK_STATE_REP :
- 3107 34918 : sputc('p', f);
- 3108 34918 : break;
- 3109 : default :
- 3110 : /* LCOV_EXCL_START */
- 3111 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state);
- 3112 : return context;
- 3113 : /* LCOV_EXCL_STOP */
- 3114 : }
- 3115 :
- 3116 1781199 : sputb32(v_pos, f);
- 3117 :
- 3118 1781199 : v_count = end - begin;
- 3119 1781199 : sputb32(v_count, f);
+ 3062 1770884 : size = file->size;
+ 3063 1770884 : mtime_sec = file->mtime_sec;
+ 3064 1770884 : mtime_nsec = file->mtime_nsec;
+ 3065 1770884 : inode = file->inode;
+ 3066 :
+ 3067 1770884 : sputc('f', f);
+ 3068 1770884 : sputb32(disk->mapping_idx, f);
+ 3069 1770884 : sputb64(size, f);
+ 3070 1770884 : sputb64(mtime_sec, f);
+ 3071 : /* encode STAT_NSEC_INVALID as 0 */
+ 3072 1770884 : if (mtime_nsec == STAT_NSEC_INVALID)
+ 3073 0 : sputb32(0, f);
+ 3074 : else
+ 3075 1770884 : sputb32(mtime_nsec + 1, f);
+ 3076 1770884 : sputb64(inode, f);
+ 3077 1770884 : sputbs(file->sub, f);
+ 3078 1770884 : if (serror(f)) {
+ 3079 : /* LCOV_EXCL_START */
+ 3080 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3081 : return context;
+ 3082 : /* LCOV_EXCL_STOP */
+ 3083 : }
+ 3084 :
+ 3085 : /* for all the blocks of the file */
+ 3086 1770884 : begin = 0;
+ 3087 5323011 : while (begin < file->blockmax) {
+ 3088 1781243 : unsigned v_state = block_state_get(fs_file2block_get(file, begin));
+ 3089 1781243 : block_off_t v_pos = fs_file2par_get(disk, file, begin);
+ 3090 : uint32_t v_count;
+ 3091 :
+ 3092 : block_off_t end;
+ 3093 :
+ 3094 : /* find the end of run of blocks */
+ 3095 1781243 : end = begin + 1;
+ 3096 6146383 : while (end < file->blockmax) {
+ 3097 2596728 : if (v_state != block_state_get(fs_file2block_get(file, end)))
+ 3098 12 : break;
+ 3099 2596716 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end))
+ 3100 12819 : break;
+ 3101 2583897 : ++end;
+ 3102 : }
+ 3103 :
+ 3104 1781243 : switch (v_state) {
+ 3105 : case BLOCK_STATE_BLK :
+ 3106 1678566 : sputc('b', f);
+ 3107 1678566 : break;
+ 3108 : case BLOCK_STATE_CHG :
+ 3109 67759 : sputc('g', f);
+ 3110 67759 : break;
+ 3111 : case BLOCK_STATE_REP :
+ 3112 34918 : sputc('p', f);
+ 3113 34918 : break;
+ 3114 : default :
+ 3115 : /* LCOV_EXCL_START */
+ 3116 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state);
+ 3117 : return context;
+ 3118 : /* LCOV_EXCL_STOP */
+ 3119 : }
3120 :
- 3121 : /* write hashes */
- 3122 6146339 : for (idx = begin; idx < end; ++idx) {
- 3123 4365140 : struct snapraid_block* block = fs_file2block_get(file, idx);
- 3124 :
- 3125 4365140 : swrite(block->hash, BLOCK_HASH_SIZE, f);
- 3126 : }
- 3127 :
- 3128 1781199 : if (serror(f)) {
- 3129 : /* LCOV_EXCL_START */
- 3130 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3131 : return context;
- 3132 : /* LCOV_EXCL_STOP */
- 3133 : }
- 3134 :
- 3135 : /* next begin position */
- 3136 1781199 : begin = end;
- 3137 : }
- 3138 :
- 3139 1770884 : ++count_file;
- 3140 : }
- 3141 :
- 3142 : /* for each link */
- 3143 58887 : for (j = disk->linklist; j != 0; j = j->next) {
- 3144 58073 : struct snapraid_link* slink = j->data;
- 3145 :
- 3146 58073 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) {
- 3147 : case FILE_IS_HARDLINK :
- 3148 321 : sputc('a', f);
- 3149 321 : ++count_hardlink;
- 3150 321 : break;
- 3151 : case FILE_IS_SYMLINK :
- 3152 57752 : sputc('s', f);
- 3153 57752 : ++count_symlink;
- 3154 57752 : break;
- 3155 : }
- 3156 :
- 3157 58073 : sputb32(disk->mapping_idx, f);
- 3158 58073 : sputbs(slink->sub, f);
- 3159 58073 : sputbs(slink->linkto, f);
- 3160 58073 : if (serror(f)) {
- 3161 : /* LCOV_EXCL_START */
- 3162 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3163 : return context;
- 3164 : /* LCOV_EXCL_STOP */
- 3165 : }
- 3166 : }
- 3167 :
- 3168 : /* for each dir */
- 3169 1241 : for (j = disk->dirlist; j != 0; j = j->next) {
- 3170 427 : struct snapraid_dir* dir = j->data;
- 3171 :
- 3172 427 : sputc('r', f);
- 3173 427 : sputb32(disk->mapping_idx, f);
- 3174 427 : sputbs(dir->sub, f);
- 3175 427 : if (serror(f)) {
- 3176 : /* LCOV_EXCL_START */
- 3177 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3178 : return context;
- 3179 : /* LCOV_EXCL_STOP */
- 3180 : }
- 3181 :
- 3182 427 : ++count_dir;
- 3183 : }
- 3184 :
- 3185 : /* deleted blocks of the disk */
- 3186 814 : sputc('h', f);
- 3187 814 : sputb32(disk->mapping_idx, f);
- 3188 814 : if (serror(f)) {
- 3189 : /* LCOV_EXCL_START */
- 3190 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3191 : return context;
- 3192 : /* LCOV_EXCL_STOP */
- 3193 : }
- 3194 814 : begin = 0;
- 3195 2516 : while (begin < blockmax) {
- 3196 : int is_deleted;
- 3197 : block_off_t end;
- 3198 :
- 3199 888 : is_deleted = fs_is_block_deleted(disk, begin);
- 3200 :
- 3201 : /* find the end of run of blocks */
- 3202 888 : end = begin + 1;
- 3203 4530435 : while (end < blockmax
- 3204 4528733 : && is_deleted == fs_is_block_deleted(disk, end)
- 3205 : ) {
- 3206 4528659 : ++end;
- 3207 : }
- 3208 :
- 3209 888 : sputb32(end - begin, f);
- 3210 :
- 3211 888 : if (is_deleted) {
- 3212 : /* write the run of deleted blocks with hash */
- 3213 47 : sputc('o', f);
- 3214 :
- 3215 : /* write all the hash */
- 3216 15961 : while (begin < end) {
- 3217 15867 : struct snapraid_block* block = fs_par2block_get(disk, begin);
- 3218 :
- 3219 15867 : swrite(block->hash, BLOCK_HASH_SIZE, f);
- 3220 :
- 3221 15867 : ++begin;
- 3222 : }
- 3223 : } else {
- 3224 : /* write the run of blocks without hash */
- 3225 : /* they can be either used or empty blocks */
- 3226 841 : sputc('O', f);
- 3227 :
- 3228 : /* next begin position */
- 3229 841 : begin = end;
- 3230 : }
- 3231 :
- 3232 888 : if (serror(f)) {
- 3233 : /* LCOV_EXCL_START */
- 3234 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3235 : return context;
- 3236 : /* LCOV_EXCL_STOP */
- 3237 : }
- 3238 : }
- 3239 : }
- 3240 :
- 3241 : /* write the info for each block */
- 3242 151 : sputc('i', f);
- 3243 151 : sputb32(info_oldest, f);
- 3244 151 : begin = 0;
- 3245 19777 : while (begin < blockmax) {
- 3246 : snapraid_info info;
- 3247 : block_off_t end;
- 3248 : time_t t;
- 3249 : unsigned flag;
- 3250 :
- 3251 19475 : info = info_get(&state->infoarr, begin);
- 3252 :
- 3253 : /* find the end of run of blocks */
- 3254 19475 : end = begin + 1;
- 3255 775574 : while (end < blockmax
- 3256 755951 : && info == info_get(&state->infoarr, end)
- 3257 : ) {
- 3258 736624 : ++end;
- 3259 : }
- 3260 :
- 3261 19475 : sputb32(end - begin, f);
- 3262 :
- 3263 : /* if there is info */
- 3264 19475 : if (info) {
- 3265 : /* other flags */
- 3266 19452 : flag = 1; /* info is present */
- 3267 19452 : if (info_get_bad(info))
- 3268 1330 : flag |= 2;
- 3269 19452 : if (info_get_rehash(info))
- 3270 5212 : flag |= 4;
- 3271 19452 : if (info_get_justsynced(info))
- 3272 12082 : flag |= 8;
- 3273 19452 : sputb32(flag, f);
- 3274 :
- 3275 19452 : t = info_get_time(info) - info_oldest;
- 3276 19452 : sputb32(t, f);
- 3277 : } else {
- 3278 : /* write a special 0 flag to mark missing info */
- 3279 23 : sputb32(0, f);
- 3280 : }
- 3281 :
- 3282 19475 : if (serror(f)) {
- 3283 : /* LCOV_EXCL_START */
- 3284 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3285 : return context;
- 3286 : /* LCOV_EXCL_STOP */
- 3287 : }
- 3288 :
- 3289 : /* next begin position */
- 3290 19475 : begin = end;
- 3291 : }
- 3292 :
- 3293 151 : sputc('N', f);
- 3294 :
- 3295 : /* flush data written to the disk */
- 3296 151 : if (sflush(f)) {
- 3297 : /* LCOV_EXCL_START */
- 3298 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno));
- 3299 : return context;
- 3300 : /* LCOV_EXCL_STOP */
- 3301 : }
- 3302 :
- 3303 : /* get the file crc */
- 3304 151 : crc = scrc(f);
- 3305 :
- 3306 : /* compare the crc of the data written to file */
- 3307 : /* with the one of the data written to the stream */
- 3308 151 : if (crc != scrc_stream(f)) {
- 3309 : /* LCOV_EXCL_START */
- 3310 : log_fatal("CRC mismatch writing the content stream.\n");
- 3311 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
- 3312 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
- 3313 : return context;
- 3314 : /* LCOV_EXCL_STOP */
- 3315 : }
- 3316 :
- 3317 151 : sputble32(crc, f);
- 3318 151 : if (serror(f)) {
- 3319 : /* LCOV_EXCL_START */
- 3320 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3321 : return context;
- 3322 : /* LCOV_EXCL_STOP */
- 3323 : }
- 3324 :
- 3325 : /* set output variables */
- 3326 151 : context->crc = crc;
- 3327 151 : context->count_file = count_file;
- 3328 151 : context->count_hardlink = count_hardlink;
- 3329 151 : context->count_symlink = count_symlink;
- 3330 151 : context->count_dir = count_dir;
- 3331 :
- 3332 151 : return 0;
- 3333 : }
- 3334 :
- 3335 151 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
- 3336 : {
- 3337 : #if HAVE_MT_WRITE
- 3338 : int fail;
- 3339 : int first;
- 3340 : #else
- 3341 : STREAM* f;
- 3342 : unsigned count_content;
- 3343 : unsigned k;
- 3344 : struct state_write_thread_context* context;
- 3345 : void* retval;
- 3346 : #endif
- 3347 : tommy_node* i;
- 3348 : block_off_t blockmax;
- 3349 : time_t info_oldest;
- 3350 : int info_has_rehash;
- 3351 : int mapping_idx;
- 3352 : block_off_t idx;
- 3353 : uint32_t crc;
- 3354 : unsigned count_file;
- 3355 : unsigned count_hardlink;
- 3356 : unsigned count_symlink;
- 3357 : unsigned count_dir;
- 3358 :
- 3359 : /* blocks of all array */
- 3360 151 : blockmax = parity_allocated_size(state);
- 3361 :
- 3362 : /* check the file-system on all disks */
- 3363 151 : state_fscheck(state, "before write");
- 3364 :
- 3365 : /* clear the info for unused blocks */
- 3366 : /* and get some other info */
- 3367 151 : info_oldest = 0; /* oldest time in info */
- 3368 151 : info_has_rehash = 0; /* if there is a rehash info */
- 3369 756250 : for (idx = 0; idx < blockmax; ++idx) {
- 3370 : /* if the position is used */
- 3371 756099 : if (fs_position_is_required(state, idx)) {
- 3372 756099 : snapraid_info info = info_get(&state->infoarr, idx);
- 3373 :
- 3374 : /* only if there is some info to store */
- 3375 756099 : if (info) {
- 3376 711614 : time_t info_time = info_get_time(info);
- 3377 :
- 3378 711614 : if (!info_oldest || info_time < info_oldest)
- 3379 154 : info_oldest = info_time;
- 3380 :
- 3381 711614 : if (info_get_rehash(info))
- 3382 13822 : info_has_rehash = 1;
- 3383 : }
- 3384 : } else {
- 3385 : /* clear any previous info */
- 3386 0 : info_set(&state->infoarr, idx, 0);
- 3387 :
- 3388 : /* and clear any deleted blocks */
- 3389 0 : fs_position_clear_deleted(state, idx);
- 3390 : }
- 3391 : }
+ 3121 1781243 : sputb32(v_pos, f);
+ 3122 :
+ 3123 1781243 : v_count = end - begin;
+ 3124 1781243 : sputb32(v_count, f);
+ 3125 :
+ 3126 : /* write hashes */
+ 3127 6146383 : for (idx = begin; idx < end; ++idx) {
+ 3128 4365140 : struct snapraid_block* block = fs_file2block_get(file, idx);
+ 3129 :
+ 3130 4365140 : swrite(block->hash, BLOCK_HASH_SIZE, f);
+ 3131 : }
+ 3132 :
+ 3133 1781243 : if (serror(f)) {
+ 3134 : /* LCOV_EXCL_START */
+ 3135 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3136 : return context;
+ 3137 : /* LCOV_EXCL_STOP */
+ 3138 : }
+ 3139 :
+ 3140 : /* next begin position */
+ 3141 1781243 : begin = end;
+ 3142 : }
+ 3143 :
+ 3144 1770884 : ++count_file;
+ 3145 : }
+ 3146 :
+ 3147 : /* for each link */
+ 3148 58887 : for (j = disk->linklist; j != 0; j = j->next) {
+ 3149 58073 : struct snapraid_link* slink = j->data;
+ 3150 :
+ 3151 58073 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) {
+ 3152 : case FILE_IS_HARDLINK :
+ 3153 321 : sputc('a', f);
+ 3154 321 : ++count_hardlink;
+ 3155 321 : break;
+ 3156 : case FILE_IS_SYMLINK :
+ 3157 57752 : sputc('s', f);
+ 3158 57752 : ++count_symlink;
+ 3159 57752 : break;
+ 3160 : }
+ 3161 :
+ 3162 58073 : sputb32(disk->mapping_idx, f);
+ 3163 58073 : sputbs(slink->sub, f);
+ 3164 58073 : sputbs(slink->linkto, f);
+ 3165 58073 : if (serror(f)) {
+ 3166 : /* LCOV_EXCL_START */
+ 3167 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3168 : return context;
+ 3169 : /* LCOV_EXCL_STOP */
+ 3170 : }
+ 3171 : }
+ 3172 :
+ 3173 : /* for each dir */
+ 3174 1241 : for (j = disk->dirlist; j != 0; j = j->next) {
+ 3175 427 : struct snapraid_dir* dir = j->data;
+ 3176 :
+ 3177 427 : sputc('r', f);
+ 3178 427 : sputb32(disk->mapping_idx, f);
+ 3179 427 : sputbs(dir->sub, f);
+ 3180 427 : if (serror(f)) {
+ 3181 : /* LCOV_EXCL_START */
+ 3182 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3183 : return context;
+ 3184 : /* LCOV_EXCL_STOP */
+ 3185 : }
+ 3186 :
+ 3187 427 : ++count_dir;
+ 3188 : }
+ 3189 :
+ 3190 : /* deleted blocks of the disk */
+ 3191 814 : sputc('h', f);
+ 3192 814 : sputb32(disk->mapping_idx, f);
+ 3193 814 : if (serror(f)) {
+ 3194 : /* LCOV_EXCL_START */
+ 3195 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3196 : return context;
+ 3197 : /* LCOV_EXCL_STOP */
+ 3198 : }
+ 3199 814 : begin = 0;
+ 3200 2516 : while (begin < blockmax) {
+ 3201 : int is_deleted;
+ 3202 : block_off_t end;
+ 3203 :
+ 3204 888 : is_deleted = fs_is_block_deleted(disk, begin);
+ 3205 :
+ 3206 : /* find the end of run of blocks */
+ 3207 888 : end = begin + 1;
+ 3208 4530435 : while (end < blockmax
+ 3209 4528733 : && is_deleted == fs_is_block_deleted(disk, end)
+ 3210 : ) {
+ 3211 4528659 : ++end;
+ 3212 : }
+ 3213 :
+ 3214 888 : sputb32(end - begin, f);
+ 3215 :
+ 3216 888 : if (is_deleted) {
+ 3217 : /* write the run of deleted blocks with hash */
+ 3218 47 : sputc('o', f);
+ 3219 :
+ 3220 : /* write all the hash */
+ 3221 15961 : while (begin < end) {
+ 3222 15867 : struct snapraid_block* block = fs_par2block_get(disk, begin);
+ 3223 :
+ 3224 15867 : swrite(block->hash, BLOCK_HASH_SIZE, f);
+ 3225 :
+ 3226 15867 : ++begin;
+ 3227 : }
+ 3228 : } else {
+ 3229 : /* write the run of blocks without hash */
+ 3230 : /* they can be either used or empty blocks */
+ 3231 841 : sputc('O', f);
+ 3232 :
+ 3233 : /* next begin position */
+ 3234 841 : begin = end;
+ 3235 : }
+ 3236 :
+ 3237 888 : if (serror(f)) {
+ 3238 : /* LCOV_EXCL_START */
+ 3239 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3240 : return context;
+ 3241 : /* LCOV_EXCL_STOP */
+ 3242 : }
+ 3243 : }
+ 3244 : }
+ 3245 :
+ 3246 : /* write the info for each block */
+ 3247 151 : sputc('i', f);
+ 3248 151 : sputb32(info_oldest, f);
+ 3249 151 : begin = 0;
+ 3250 19719 : while (begin < blockmax) {
+ 3251 : snapraid_info info;
+ 3252 : block_off_t end;
+ 3253 : time_t t;
+ 3254 : unsigned flag;
+ 3255 :
+ 3256 19417 : info = info_get(&state->infoarr, begin);
+ 3257 :
+ 3258 : /* find the end of run of blocks */
+ 3259 19417 : end = begin + 1;
+ 3260 775516 : while (end < blockmax
+ 3261 755951 : && info == info_get(&state->infoarr, end)
+ 3262 : ) {
+ 3263 736682 : ++end;
+ 3264 : }
+ 3265 :
+ 3266 19417 : sputb32(end - begin, f);
+ 3267 :
+ 3268 : /* if there is info */
+ 3269 19417 : if (info) {
+ 3270 : /* other flags */
+ 3271 19394 : flag = 1; /* info is present */
+ 3272 19394 : if (info_get_bad(info))
+ 3273 1348 : flag |= 2;
+ 3274 19394 : if (info_get_rehash(info))
+ 3275 5212 : flag |= 4;
+ 3276 19394 : if (info_get_justsynced(info))
+ 3277 12059 : flag |= 8;
+ 3278 19394 : sputb32(flag, f);
+ 3279 :
+ 3280 19394 : t = info_get_time(info) - info_oldest;
+ 3281 19394 : sputb32(t, f);
+ 3282 : } else {
+ 3283 : /* write a special 0 flag to mark missing info */
+ 3284 23 : sputb32(0, f);
+ 3285 : }
+ 3286 :
+ 3287 19417 : if (serror(f)) {
+ 3288 : /* LCOV_EXCL_START */
+ 3289 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3290 : return context;
+ 3291 : /* LCOV_EXCL_STOP */
+ 3292 : }
+ 3293 :
+ 3294 : /* next begin position */
+ 3295 19417 : begin = end;
+ 3296 : }
+ 3297 :
+ 3298 151 : sputc('N', f);
+ 3299 :
+ 3300 : /* flush data written to the disk */
+ 3301 151 : if (sflush(f)) {
+ 3302 : /* LCOV_EXCL_START */
+ 3303 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno));
+ 3304 : return context;
+ 3305 : /* LCOV_EXCL_STOP */
+ 3306 : }
+ 3307 :
+ 3308 : /* get the file crc */
+ 3309 151 : crc = scrc(f);
+ 3310 :
+ 3311 : /* compare the crc of the data written to file */
+ 3312 : /* with the one of the data written to the stream */
+ 3313 151 : if (crc != scrc_stream(f)) {
+ 3314 : /* LCOV_EXCL_START */
+ 3315 : log_fatal("CRC mismatch writing the content stream.\n");
+ 3316 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
+ 3317 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
+ 3318 : return context;
+ 3319 : /* LCOV_EXCL_STOP */
+ 3320 : }
+ 3321 :
+ 3322 151 : sputble32(crc, f);
+ 3323 151 : if (serror(f)) {
+ 3324 : /* LCOV_EXCL_START */
+ 3325 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3326 : return context;
+ 3327 : /* LCOV_EXCL_STOP */
+ 3328 : }
+ 3329 :
+ 3330 : /* set output variables */
+ 3331 151 : context->crc = crc;
+ 3332 151 : context->count_file = count_file;
+ 3333 151 : context->count_hardlink = count_hardlink;
+ 3334 151 : context->count_symlink = count_symlink;
+ 3335 151 : context->count_dir = count_dir;
+ 3336 :
+ 3337 151 : return 0;
+ 3338 : }
+ 3339 :
+ 3340 151 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
+ 3341 : {
+ 3342 : #if HAVE_MT_WRITE
+ 3343 : int fail;
+ 3344 : int first;
+ 3345 : #else
+ 3346 : STREAM* f;
+ 3347 : unsigned count_content;
+ 3348 : unsigned k;
+ 3349 : struct state_write_thread_context* context;
+ 3350 : void* retval;
+ 3351 : #endif
+ 3352 : tommy_node* i;
+ 3353 : block_off_t blockmax;
+ 3354 : time_t info_oldest;
+ 3355 : int info_has_rehash;
+ 3356 : int mapping_idx;
+ 3357 : block_off_t idx;
+ 3358 : uint32_t crc;
+ 3359 : unsigned count_file;
+ 3360 : unsigned count_hardlink;
+ 3361 : unsigned count_symlink;
+ 3362 : unsigned count_dir;
+ 3363 :
+ 3364 : /* blocks of all array */
+ 3365 151 : blockmax = parity_allocated_size(state);
+ 3366 :
+ 3367 : /* check the file-system on all disks */
+ 3368 151 : state_fscheck(state, "before write");
+ 3369 :
+ 3370 : /* clear the info for unused blocks */
+ 3371 : /* and get some other info */
+ 3372 151 : info_oldest = 0; /* oldest time in info */
+ 3373 151 : info_has_rehash = 0; /* if there is a rehash info */
+ 3374 756250 : for (idx = 0; idx < blockmax; ++idx) {
+ 3375 : /* if the position is used */
+ 3376 756099 : if (fs_position_is_required(state, idx)) {
+ 3377 756099 : snapraid_info info = info_get(&state->infoarr, idx);
+ 3378 :
+ 3379 : /* only if there is some info to store */
+ 3380 756099 : if (info) {
+ 3381 711614 : time_t info_time = info_get_time(info);
+ 3382 :
+ 3383 711614 : if (!info_oldest || info_time < info_oldest)
+ 3384 151 : info_oldest = info_time;
+ 3385 :
+ 3386 711614 : if (info_get_rehash(info))
+ 3387 13822 : info_has_rehash = 1;
+ 3388 : }
+ 3389 : } else {
+ 3390 : /* clear any previous info */
+ 3391 0 : info_set(&state->infoarr, idx, 0);
3392 :
- 3393 : /* map disks */
- 3394 151 : mapping_idx = 0;
- 3395 1057 : for (i = state->maplist; i != 0; i = i->next) {
- 3396 906 : struct snapraid_map* map = i->data;
- 3397 : struct snapraid_disk* disk;
- 3398 :
- 3399 : /* find the disk for this mapping */
- 3400 906 : disk = find_disk_by_name(state, map->name);
- 3401 906 : if (!disk) {
- 3402 : /* LCOV_EXCL_START */
- 3403 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
- 3404 : os_abort();
- 3405 : /* LCOV_EXCL_STOP */
- 3406 : }
- 3407 :
- 3408 : /* save the mapping only for not empty disks */
- 3409 906 : if (!fs_is_empty(disk, blockmax)) {
- 3410 : /* assign the mapping index used to identify disks */
- 3411 814 : disk->mapping_idx = mapping_idx;
- 3412 814 : ++mapping_idx;
- 3413 : } else {
- 3414 : /* mark the disk as without mapping */
- 3415 92 : disk->mapping_idx = -1;
- 3416 : }
- 3417 : }
- 3418 :
- 3419 : #if HAVE_MT_WRITE
- 3420 : /* start all writing threads */
- 3421 : i = tommy_list_head(&state->contentlist);
- 3422 : while (i) {
- 3423 : struct snapraid_content* content = i->data;
- 3424 : struct state_write_thread_context* context;
- 3425 : char tmp[PATH_MAX];
- 3426 : STREAM* f;
- 3427 :
- 3428 : msg_progress("Saving state to %s...\n", content->content);
- 3429 :
- 3430 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3431 : f = sopen_write(tmp);
- 3432 : if (f == 0) {
- 3433 : /* LCOV_EXCL_START */
- 3434 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
- 3435 : exit(EXIT_FAILURE);
- 3436 : /* LCOV_EXCL_STOP */
- 3437 : }
- 3438 :
- 3439 : /* allocate the thread context */
- 3440 : context = malloc_nofail(sizeof(struct state_write_thread_context));
- 3441 : content->context = context;
- 3442 :
- 3443 : /* initialize */
- 3444 : context->state = state;
- 3445 : context->blockmax = blockmax;
- 3446 : context->info_oldest = info_oldest;
- 3447 : context->info_has_rehash = info_has_rehash;
- 3448 : context->f = f;
- 3449 :
- 3450 : thread_create(&context->thread, 0, state_write_thread, context);
- 3451 :
- 3452 : i = i->next;
- 3453 : }
+ 3393 : /* and clear any deleted blocks */
+ 3394 0 : fs_position_clear_deleted(state, idx);
+ 3395 : }
+ 3396 : }
+ 3397 :
+ 3398 : /* map disks */
+ 3399 151 : mapping_idx = 0;
+ 3400 1057 : for (i = state->maplist; i != 0; i = i->next) {
+ 3401 906 : struct snapraid_map* map = i->data;
+ 3402 : struct snapraid_disk* disk;
+ 3403 :
+ 3404 : /* find the disk for this mapping */
+ 3405 906 : disk = find_disk_by_name(state, map->name);
+ 3406 906 : if (!disk) {
+ 3407 : /* LCOV_EXCL_START */
+ 3408 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
+ 3409 : os_abort();
+ 3410 : /* LCOV_EXCL_STOP */
+ 3411 : }
+ 3412 :
+ 3413 : /* save the mapping only for not empty disks */
+ 3414 906 : if (!fs_is_empty(disk, blockmax)) {
+ 3415 : /* assign the mapping index used to identify disks */
+ 3416 814 : disk->mapping_idx = mapping_idx;
+ 3417 814 : ++mapping_idx;
+ 3418 : } else {
+ 3419 : /* mark the disk as without mapping */
+ 3420 92 : disk->mapping_idx = -1;
+ 3421 : }
+ 3422 : }
+ 3423 :
+ 3424 : #if HAVE_MT_WRITE
+ 3425 : /* start all writing threads */
+ 3426 : i = tommy_list_head(&state->contentlist);
+ 3427 : while (i) {
+ 3428 : struct snapraid_content* content = i->data;
+ 3429 : struct state_write_thread_context* context;
+ 3430 : char tmp[PATH_MAX];
+ 3431 : STREAM* f;
+ 3432 :
+ 3433 : msg_progress("Saving state to %s...\n", content->content);
+ 3434 :
+ 3435 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3436 : f = sopen_write(tmp);
+ 3437 : if (f == 0) {
+ 3438 : /* LCOV_EXCL_START */
+ 3439 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3440 : exit(EXIT_FAILURE);
+ 3441 : /* LCOV_EXCL_STOP */
+ 3442 : }
+ 3443 :
+ 3444 : /* allocate the thread context */
+ 3445 : context = malloc_nofail(sizeof(struct state_write_thread_context));
+ 3446 : content->context = context;
+ 3447 :
+ 3448 : /* initialize */
+ 3449 : context->state = state;
+ 3450 : context->blockmax = blockmax;
+ 3451 : context->info_oldest = info_oldest;
+ 3452 : context->info_has_rehash = info_has_rehash;
+ 3453 : context->f = f;
3454 :
- 3455 : /* join all thread */
- 3456 : fail = 0;
- 3457 : first = 1;
- 3458 : crc = 0;
- 3459 : count_file = 0;
- 3460 : count_hardlink = 0;
- 3461 : count_symlink = 0;
- 3462 : count_dir = 0;
- 3463 : i = tommy_list_head(&state->contentlist);
- 3464 : while (i) {
- 3465 : struct snapraid_content* content = i->data;
- 3466 : struct state_write_thread_context* context = content->context;
- 3467 : void* retval;
- 3468 :
- 3469 : thread_join(context->thread, &retval);
- 3470 :
- 3471 : if (retval) {
- 3472 : /* LCOV_EXCL_START */
- 3473 : fail = 1;
- 3474 : /* LCOV_EXCL_STOP */
- 3475 : } else {
- 3476 : STREAM* f = context->f;
- 3477 :
- 3478 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
- 3479 : /* than even in a system crash event we have one valid copy of the file. */
- 3480 : if (sflush(f) != 0) {
- 3481 : /* LCOV_EXCL_START */
- 3482 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
- 3483 : exit(EXIT_FAILURE);
- 3484 : /* LCOV_EXCL_STOP */
- 3485 : }
- 3486 :
- 3487 : #if HAVE_FSYNC
- 3488 : if (ssync(f) != 0) {
- 3489 : /* LCOV_EXCL_START */
- 3490 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
- 3491 : exit(EXIT_FAILURE);
- 3492 : /* LCOV_EXCL_STOP */
- 3493 : }
- 3494 : #endif
- 3495 :
- 3496 : if (sclose(f) != 0) {
- 3497 : /* LCOV_EXCL_START */
- 3498 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
- 3499 : exit(EXIT_FAILURE);
- 3500 : /* LCOV_EXCL_STOP */
- 3501 : }
- 3502 :
- 3503 : if (first) {
- 3504 : first = 0;
- 3505 : crc = context->crc;
- 3506 : count_file = context->count_file;
- 3507 : count_hardlink = context->count_hardlink;
- 3508 : count_symlink = context->count_symlink;
- 3509 : count_dir = context->count_dir;
- 3510 : } else {
- 3511 : if (crc != context->crc) {
- 3512 : /* LCOV_EXCL_START */
- 3513 : log_fatal("Different CRCs writing content streams.\n");
- 3514 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
- 3515 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
- 3516 : exit(EXIT_FAILURE);
- 3517 : /* LCOV_EXCL_STOP */
- 3518 : }
- 3519 : }
- 3520 : }
- 3521 :
- 3522 : free(context);
- 3523 :
- 3524 : i = i->next;
- 3525 : }
+ 3455 : thread_create(&context->thread, 0, state_write_thread, context);
+ 3456 :
+ 3457 : i = i->next;
+ 3458 : }
+ 3459 :
+ 3460 : /* join all thread */
+ 3461 : fail = 0;
+ 3462 : first = 1;
+ 3463 : crc = 0;
+ 3464 : count_file = 0;
+ 3465 : count_hardlink = 0;
+ 3466 : count_symlink = 0;
+ 3467 : count_dir = 0;
+ 3468 : i = tommy_list_head(&state->contentlist);
+ 3469 : while (i) {
+ 3470 : struct snapraid_content* content = i->data;
+ 3471 : struct state_write_thread_context* context = content->context;
+ 3472 : void* retval;
+ 3473 :
+ 3474 : thread_join(context->thread, &retval);
+ 3475 :
+ 3476 : if (retval) {
+ 3477 : /* LCOV_EXCL_START */
+ 3478 : fail = 1;
+ 3479 : /* LCOV_EXCL_STOP */
+ 3480 : } else {
+ 3481 : STREAM* f = context->f;
+ 3482 :
+ 3483 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
+ 3484 : /* than even in a system crash event we have one valid copy of the file. */
+ 3485 : if (sflush(f) != 0) {
+ 3486 : /* LCOV_EXCL_START */
+ 3487 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
+ 3488 : exit(EXIT_FAILURE);
+ 3489 : /* LCOV_EXCL_STOP */
+ 3490 : }
+ 3491 :
+ 3492 : #if HAVE_FSYNC
+ 3493 : if (ssync(f) != 0) {
+ 3494 : /* LCOV_EXCL_START */
+ 3495 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
+ 3496 : exit(EXIT_FAILURE);
+ 3497 : /* LCOV_EXCL_STOP */
+ 3498 : }
+ 3499 : #endif
+ 3500 :
+ 3501 : if (sclose(f) != 0) {
+ 3502 : /* LCOV_EXCL_START */
+ 3503 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3504 : exit(EXIT_FAILURE);
+ 3505 : /* LCOV_EXCL_STOP */
+ 3506 : }
+ 3507 :
+ 3508 : if (first) {
+ 3509 : first = 0;
+ 3510 : crc = context->crc;
+ 3511 : count_file = context->count_file;
+ 3512 : count_hardlink = context->count_hardlink;
+ 3513 : count_symlink = context->count_symlink;
+ 3514 : count_dir = context->count_dir;
+ 3515 : } else {
+ 3516 : if (crc != context->crc) {
+ 3517 : /* LCOV_EXCL_START */
+ 3518 : log_fatal("Different CRCs writing content streams.\n");
+ 3519 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
+ 3520 : log_fatal("Try running a memory test like http://www.memtest86.com/\n");
+ 3521 : exit(EXIT_FAILURE);
+ 3522 : /* LCOV_EXCL_STOP */
+ 3523 : }
+ 3524 : }
+ 3525 : }
3526 :
- 3527 : /* abort on failure */
- 3528 : if (fail) {
- 3529 : /* LCOV_EXCL_START */
- 3530 : exit(EXIT_FAILURE);
- 3531 : /* LCOV_EXCL_STOP */
- 3532 : }
- 3533 : #else
- 3534 : /* count the content files */
- 3535 151 : count_content = 0;
- 3536 151 : i = tommy_list_head(&state->contentlist);
- 3537 1314 : while (i) {
- 3538 1012 : struct snapraid_content* content = i->data;
- 3539 1012 : msg_progress("Saving state to %s...\n", content->content);
- 3540 1012 : ++count_content;
- 3541 1012 : i = i->next;
- 3542 : }
- 3543 :
- 3544 : /* open all the content files */
- 3545 151 : f = sopen_multi_write(count_content);
- 3546 151 : if (!f) {
- 3547 : /* LCOV_EXCL_START */
- 3548 : log_fatal("Error opening the content files.\n");
- 3549 : exit(EXIT_FAILURE);
- 3550 : /* LCOV_EXCL_STOP */
- 3551 : }
- 3552 :
- 3553 151 : k = 0;
- 3554 151 : i = tommy_list_head(&state->contentlist);
- 3555 1314 : while (i) {
- 3556 1012 : struct snapraid_content* content = i->data;
- 3557 : char tmp[PATH_MAX];
- 3558 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3559 1012 : if (sopen_multi_file(f, k, tmp) != 0) {
- 3560 : /* LCOV_EXCL_START */
- 3561 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
- 3562 : exit(EXIT_FAILURE);
- 3563 : /* LCOV_EXCL_STOP */
- 3564 : }
- 3565 1012 : ++k;
- 3566 1012 : i = i->next;
- 3567 : }
- 3568 :
- 3569 : /* allocate the thread context */
- 3570 151 : context = malloc_nofail(sizeof(struct state_write_thread_context));
- 3571 :
- 3572 : /* initialize */
- 3573 151 : context->state = state;
- 3574 151 : context->blockmax = blockmax;
- 3575 151 : context->info_oldest = info_oldest;
- 3576 151 : context->info_has_rehash = info_has_rehash;
- 3577 151 : context->f = f;
- 3578 :
- 3579 151 : retval = state_write_thread(context);
- 3580 :
- 3581 : /* abort on failure */
- 3582 151 : if (retval) {
- 3583 : /* LCOV_EXCL_START */
- 3584 : exit(EXIT_FAILURE);
- 3585 : /* LCOV_EXCL_STOP */
- 3586 : }
- 3587 :
- 3588 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
- 3589 : /* than even in a system crash event we have one valid copy of the file. */
- 3590 151 : if (sflush(f) != 0) {
- 3591 : /* LCOV_EXCL_START */
- 3592 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
- 3593 : exit(EXIT_FAILURE);
- 3594 : /* LCOV_EXCL_STOP */
- 3595 : }
- 3596 :
- 3597 : #if HAVE_FSYNC
- 3598 151 : if (ssync(f) != 0) {
- 3599 : /* LCOV_EXCL_START */
- 3600 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
- 3601 : exit(EXIT_FAILURE);
- 3602 : /* LCOV_EXCL_STOP */
- 3603 : }
- 3604 : #endif
- 3605 :
- 3606 151 : if (sclose(f) != 0) {
- 3607 : /* LCOV_EXCL_START */
- 3608 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
- 3609 : exit(EXIT_FAILURE);
- 3610 : /* LCOV_EXCL_STOP */
- 3611 : }
- 3612 :
- 3613 151 : crc = context->crc;
- 3614 151 : count_file = context->count_file;
- 3615 151 : count_hardlink = context->count_hardlink;
- 3616 151 : count_symlink = context->count_symlink;
- 3617 151 : count_dir = context->count_dir;
- 3618 :
- 3619 151 : free(context);
- 3620 : #endif
- 3621 :
- 3622 151 : msg_verbose("%8u files\n", count_file);
- 3623 151 : msg_verbose("%8u hardlinks\n", count_hardlink);
- 3624 151 : msg_verbose("%8u symlinks\n", count_symlink);
- 3625 151 : msg_verbose("%8u empty dirs\n", count_dir);
+ 3527 : free(context);
+ 3528 :
+ 3529 : i = i->next;
+ 3530 : }
+ 3531 :
+ 3532 : /* abort on failure */
+ 3533 : if (fail) {
+ 3534 : /* LCOV_EXCL_START */
+ 3535 : exit(EXIT_FAILURE);
+ 3536 : /* LCOV_EXCL_STOP */
+ 3537 : }
+ 3538 : #else
+ 3539 : /* count the content files */
+ 3540 151 : count_content = 0;
+ 3541 151 : i = tommy_list_head(&state->contentlist);
+ 3542 1314 : while (i) {
+ 3543 1012 : struct snapraid_content* content = i->data;
+ 3544 1012 : msg_progress("Saving state to %s...\n", content->content);
+ 3545 1012 : ++count_content;
+ 3546 1012 : i = i->next;
+ 3547 : }
+ 3548 :
+ 3549 : /* open all the content files */
+ 3550 151 : f = sopen_multi_write(count_content);
+ 3551 151 : if (!f) {
+ 3552 : /* LCOV_EXCL_START */
+ 3553 : log_fatal("Error opening the content files.\n");
+ 3554 : exit(EXIT_FAILURE);
+ 3555 : /* LCOV_EXCL_STOP */
+ 3556 : }
+ 3557 :
+ 3558 151 : k = 0;
+ 3559 151 : i = tommy_list_head(&state->contentlist);
+ 3560 1314 : while (i) {
+ 3561 1012 : struct snapraid_content* content = i->data;
+ 3562 : char tmp[PATH_MAX];
+ 3563 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3564 1012 : if (sopen_multi_file(f, k, tmp) != 0) {
+ 3565 : /* LCOV_EXCL_START */
+ 3566 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3567 : exit(EXIT_FAILURE);
+ 3568 : /* LCOV_EXCL_STOP */
+ 3569 : }
+ 3570 1012 : ++k;
+ 3571 1012 : i = i->next;
+ 3572 : }
+ 3573 :
+ 3574 : /* allocate the thread context */
+ 3575 151 : context = malloc_nofail(sizeof(struct state_write_thread_context));
+ 3576 :
+ 3577 : /* initialize */
+ 3578 151 : context->state = state;
+ 3579 151 : context->blockmax = blockmax;
+ 3580 151 : context->info_oldest = info_oldest;
+ 3581 151 : context->info_has_rehash = info_has_rehash;
+ 3582 151 : context->f = f;
+ 3583 :
+ 3584 151 : retval = state_write_thread(context);
+ 3585 :
+ 3586 : /* abort on failure */
+ 3587 151 : if (retval) {
+ 3588 : /* LCOV_EXCL_START */
+ 3589 : exit(EXIT_FAILURE);
+ 3590 : /* LCOV_EXCL_STOP */
+ 3591 : }
+ 3592 :
+ 3593 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */
+ 3594 : /* than even in a system crash event we have one valid copy of the file. */
+ 3595 151 : if (sflush(f) != 0) {
+ 3596 : /* LCOV_EXCL_START */
+ 3597 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno));
+ 3598 : exit(EXIT_FAILURE);
+ 3599 : /* LCOV_EXCL_STOP */
+ 3600 : }
+ 3601 :
+ 3602 : #if HAVE_FSYNC
+ 3603 151 : if (ssync(f) != 0) {
+ 3604 : /* LCOV_EXCL_START */
+ 3605 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno));
+ 3606 : exit(EXIT_FAILURE);
+ 3607 : /* LCOV_EXCL_STOP */
+ 3608 : }
+ 3609 : #endif
+ 3610 :
+ 3611 151 : if (sclose(f) != 0) {
+ 3612 : /* LCOV_EXCL_START */
+ 3613 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3614 : exit(EXIT_FAILURE);
+ 3615 : /* LCOV_EXCL_STOP */
+ 3616 : }
+ 3617 :
+ 3618 151 : crc = context->crc;
+ 3619 151 : count_file = context->count_file;
+ 3620 151 : count_hardlink = context->count_hardlink;
+ 3621 151 : count_symlink = context->count_symlink;
+ 3622 151 : count_dir = context->count_dir;
+ 3623 :
+ 3624 151 : free(context);
+ 3625 : #endif
3626 :
- 3627 151 : *out_crc = crc;
- 3628 151 : }
- 3629 :
- 3630 261 : void state_read(struct snapraid_state* state)
- 3631 : {
- 3632 : STREAM* f;
- 3633 : char path[PATH_MAX];
- 3634 : struct stat st;
- 3635 : tommy_node* node;
- 3636 : int ret;
- 3637 : int c;
- 3638 :
- 3639 : /* iterate over all the available content files and load the first one present */
- 3640 261 : f = 0;
- 3641 261 : node = tommy_list_head(&state->contentlist);
- 3642 572 : while (node) {
- 3643 304 : struct snapraid_content* content = node->data;
- 3644 304 : pathcpy(path, sizeof(path), content->content);
- 3645 :
- 3646 304 : if (!state->no_conf) {
- 3647 303 : log_tag("content:%s\n", path);
- 3648 303 : log_flush();
- 3649 : }
- 3650 304 : msg_progress("Loading state from %s...\n", path);
- 3651 :
- 3652 304 : f = sopen_read(path);
- 3653 304 : if (f != 0) {
- 3654 : /* if opened stop the search */
- 3655 254 : break;
- 3656 : } else {
- 3657 : /* if it's real error of an existing file, abort */
- 3658 50 : if (errno != ENOENT) {
- 3659 : /* LCOV_EXCL_START */
- 3660 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno));
- 3661 : exit(EXIT_FAILURE);
- 3662 : /* LCOV_EXCL_STOP */
- 3663 : }
- 3664 :
- 3665 : /* otherwise continue */
- 3666 50 : if (node->next) {
- 3667 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path);
- 3668 :
- 3669 : /* ensure to rewrite all the content files */
- 3670 43 : state->need_write = 1;
- 3671 : }
- 3672 : }
+ 3627 151 : msg_verbose("%8u files\n", count_file);
+ 3628 151 : msg_verbose("%8u hardlinks\n", count_hardlink);
+ 3629 151 : msg_verbose("%8u symlinks\n", count_symlink);
+ 3630 151 : msg_verbose("%8u empty dirs\n", count_dir);
+ 3631 :
+ 3632 151 : *out_crc = crc;
+ 3633 151 : }
+ 3634 :
+ 3635 261 : void state_read(struct snapraid_state* state)
+ 3636 : {
+ 3637 : STREAM* f;
+ 3638 : char path[PATH_MAX];
+ 3639 : struct stat st;
+ 3640 : tommy_node* node;
+ 3641 : int ret;
+ 3642 : int c;
+ 3643 :
+ 3644 : /* iterate over all the available content files and load the first one present */
+ 3645 261 : f = 0;
+ 3646 261 : node = tommy_list_head(&state->contentlist);
+ 3647 572 : while (node) {
+ 3648 304 : struct snapraid_content* content = node->data;
+ 3649 304 : pathcpy(path, sizeof(path), content->content);
+ 3650 :
+ 3651 304 : if (!state->no_conf) {
+ 3652 303 : log_tag("content:%s\n", path);
+ 3653 303 : log_flush();
+ 3654 : }
+ 3655 304 : msg_progress("Loading state from %s...\n", path);
+ 3656 :
+ 3657 304 : f = sopen_read(path);
+ 3658 304 : if (f != 0) {
+ 3659 : /* if opened stop the search */
+ 3660 254 : break;
+ 3661 : } else {
+ 3662 : /* if it's real error of an existing file, abort */
+ 3663 50 : if (errno != ENOENT) {
+ 3664 : /* LCOV_EXCL_START */
+ 3665 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno));
+ 3666 : exit(EXIT_FAILURE);
+ 3667 : /* LCOV_EXCL_STOP */
+ 3668 : }
+ 3669 :
+ 3670 : /* otherwise continue */
+ 3671 50 : if (node->next) {
+ 3672 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path);
3673 :
- 3674 : /* next content file */
- 3675 50 : node = node->next;
- 3676 : }
- 3677 :
- 3678 : /* if not found, assume empty */
- 3679 261 : if (!f) {
- 3680 7 : log_fatal("No content file found. Assuming empty.\n");
- 3681 :
- 3682 : /* create the initial mapping */
- 3683 7 : state_map(state);
- 3684 267 : return;
- 3685 : }
+ 3674 : /* ensure to rewrite all the content files */
+ 3675 43 : state->need_write = 1;
+ 3676 : }
+ 3677 : }
+ 3678 :
+ 3679 : /* next content file */
+ 3680 50 : node = node->next;
+ 3681 : }
+ 3682 :
+ 3683 : /* if not found, assume empty */
+ 3684 261 : if (!f) {
+ 3685 7 : log_fatal("No content file found. Assuming empty.\n");
3686 :
- 3687 : /* get the stat of the content file */
- 3688 254 : ret = fstat(shandle(f), &st);
- 3689 254 : if (ret != 0) {
- 3690 : /* LCOV_EXCL_START */
- 3691 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno));
- 3692 : exit(EXIT_FAILURE);
- 3693 : /* LCOV_EXCL_STOP */
- 3694 : }
- 3695 :
- 3696 : /* go further to check other content files */
- 3697 1955 : while (node) {
- 3698 : char other_path[PATH_MAX];
- 3699 : struct stat other_st;
- 3700 1447 : struct snapraid_content* content = node->data;
- 3701 1447 : pathcpy(other_path, sizeof(other_path), content->content);
- 3702 :
- 3703 1447 : ret = stat(other_path, &other_st);
- 3704 1447 : if (ret != 0) {
- 3705 : /* allow missing content files, but not any other kind of error */
- 3706 1 : if (errno != ENOENT) {
- 3707 : /* LCOV_EXCL_START */
- 3708 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno));
- 3709 : exit(EXIT_FAILURE);
- 3710 : /* LCOV_EXCL_STOP */
- 3711 : }
- 3712 :
- 3713 : /* ensure to rewrite all the content files */
- 3714 1 : state->need_write = 1;
- 3715 : } else {
- 3716 : /* if the size is different */
- 3717 1446 : if (other_st.st_size != st.st_size) {
- 3718 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path);
- 3719 39 : log_fatal("Likely one of the two is broken!\n");
- 3720 :
- 3721 : /* ensure to rewrite all the content files */
- 3722 39 : state->need_write = 1;
- 3723 : }
- 3724 : }
+ 3687 : /* create the initial mapping */
+ 3688 7 : state_map(state);
+ 3689 267 : return;
+ 3690 : }
+ 3691 :
+ 3692 : /* get the stat of the content file */
+ 3693 254 : ret = fstat(shandle(f), &st);
+ 3694 254 : if (ret != 0) {
+ 3695 : /* LCOV_EXCL_START */
+ 3696 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno));
+ 3697 : exit(EXIT_FAILURE);
+ 3698 : /* LCOV_EXCL_STOP */
+ 3699 : }
+ 3700 :
+ 3701 : /* go further to check other content files */
+ 3702 1955 : while (node) {
+ 3703 : char other_path[PATH_MAX];
+ 3704 : struct stat other_st;
+ 3705 1447 : struct snapraid_content* content = node->data;
+ 3706 1447 : pathcpy(other_path, sizeof(other_path), content->content);
+ 3707 :
+ 3708 1447 : ret = stat(other_path, &other_st);
+ 3709 1447 : if (ret != 0) {
+ 3710 : /* allow missing content files, but not any other kind of error */
+ 3711 1 : if (errno != ENOENT) {
+ 3712 : /* LCOV_EXCL_START */
+ 3713 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno));
+ 3714 : exit(EXIT_FAILURE);
+ 3715 : /* LCOV_EXCL_STOP */
+ 3716 : }
+ 3717 :
+ 3718 : /* ensure to rewrite all the content files */
+ 3719 1 : state->need_write = 1;
+ 3720 : } else {
+ 3721 : /* if the size is different */
+ 3722 1446 : if (other_st.st_size != st.st_size) {
+ 3723 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path);
+ 3724 39 : log_fatal("Likely one of the two is broken!\n");
3725 :
- 3726 : /* next content file */
- 3727 1447 : node = node->next;
- 3728 : }
- 3729 :
- 3730 : /* start with a undefined default. */
- 3731 : /* it's for compatibility with version 1.0 where MD5 was implicit. */
- 3732 254 : state->hash = HASH_UNDEFINED;
- 3733 :
- 3734 : /* start with a zero seed, it was the default in old versions */
- 3735 254 : memset(state->hashseed, 0, HASH_MAX);
- 3736 :
- 3737 : /* previous hash, start with an undefined value */
- 3738 254 : state->prevhash = HASH_UNDEFINED;
- 3739 :
- 3740 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
+ 3726 : /* ensure to rewrite all the content files */
+ 3727 39 : state->need_write = 1;
+ 3728 : }
+ 3729 : }
+ 3730 :
+ 3731 : /* next content file */
+ 3732 1447 : node = node->next;
+ 3733 : }
+ 3734 :
+ 3735 : /* start with a undefined default. */
+ 3736 : /* it's for compatibility with version 1.0 where MD5 was implicit. */
+ 3737 254 : state->hash = HASH_UNDEFINED;
+ 3738 :
+ 3739 : /* start with a zero seed, it was the default in old versions */
+ 3740 254 : memset(state->hashseed, 0, HASH_MAX);
3741 :
- 3742 : /* get the first char to detect the file type */
- 3743 254 : c = sgetc(f);
- 3744 254 : sungetc(c, f);
- 3745 :
- 3746 : /* guess the file type from the first char */
- 3747 254 : if (c == 'S') {
- 3748 254 : state_read_content(state, path, f);
- 3749 : } else {
- 3750 : /* LCOV_EXCL_START */
- 3751 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n");
- 3752 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n");
- 3753 : exit(EXIT_FAILURE);
- 3754 : /* LCOV_EXCL_STOP */
- 3755 : }
- 3756 :
- 3757 253 : sclose(f);
- 3758 :
- 3759 253 : if (state->hash == HASH_UNDEFINED) {
- 3760 : /* LCOV_EXCL_START */
- 3761 : log_fatal("The checksum to use is not specified.\n");
- 3762 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n");
- 3763 : log_fatal("To use a new SnapRAID you must restart from scratch,\n");
- 3764 : log_fatal("deleting all the content and parity files.\n");
- 3765 : exit(EXIT_FAILURE);
- 3766 : /* LCOV_EXCL_STOP */
- 3767 : }
- 3768 :
- 3769 : /* update the mapping */
- 3770 253 : state_map(state);
- 3771 :
- 3772 253 : state_content_check(state, path);
+ 3742 : /* previous hash, start with an undefined value */
+ 3743 254 : state->prevhash = HASH_UNDEFINED;
+ 3744 :
+ 3745 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */
+ 3746 :
+ 3747 : /* get the first char to detect the file type */
+ 3748 254 : c = sgetc(f);
+ 3749 254 : sungetc(c, f);
+ 3750 :
+ 3751 : /* guess the file type from the first char */
+ 3752 254 : if (c == 'S') {
+ 3753 254 : state_read_content(state, path, f);
+ 3754 : } else {
+ 3755 : /* LCOV_EXCL_START */
+ 3756 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n");
+ 3757 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n");
+ 3758 : exit(EXIT_FAILURE);
+ 3759 : /* LCOV_EXCL_STOP */
+ 3760 : }
+ 3761 :
+ 3762 253 : sclose(f);
+ 3763 :
+ 3764 253 : if (state->hash == HASH_UNDEFINED) {
+ 3765 : /* LCOV_EXCL_START */
+ 3766 : log_fatal("The checksum to use is not specified.\n");
+ 3767 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n");
+ 3768 : log_fatal("To use a new SnapRAID you must restart from scratch,\n");
+ 3769 : log_fatal("deleting all the content and parity files.\n");
+ 3770 : exit(EXIT_FAILURE);
+ 3771 : /* LCOV_EXCL_STOP */
+ 3772 : }
3773 :
- 3774 : /* mark that we read the content file, and it passed all the checks */
- 3775 253 : state->checked_read = 1;
- 3776 : }
- 3777 :
- 3778 : struct state_verify_thread_context {
- 3779 : struct snapraid_state* state;
- 3780 : struct snapraid_content* content;
- 3781 : #if HAVE_MT_VERIFY
- 3782 : pthread_t thread;
- 3783 : #else
- 3784 : void* retval;
- 3785 : #endif
- 3786 : /* input */
- 3787 : uint32_t crc;
- 3788 : STREAM* f;
- 3789 : };
- 3790 :
- 3791 1012 : static void* state_verify_thread(void* arg)
- 3792 : {
- 3793 1012 : struct state_verify_thread_context* context = arg;
- 3794 1012 : STREAM* f = context->f;
- 3795 : unsigned char buf[4];
- 3796 : uint32_t crc_stored;
- 3797 : uint32_t crc_computed;
- 3798 :
- 3799 1012 : if (sdeplete(f, buf) != 0) {
- 3800 : /* LCOV_EXCL_START */
- 3801 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
- 3802 : return context;
- 3803 : /* LCOV_EXCL_STOP */
- 3804 : }
- 3805 :
- 3806 : /* get the stored crc from the last four bytes */
- 3807 1012 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
- 3808 :
- 3809 1012 : if (crc_stored != context->crc) {
- 3810 : /* LCOV_EXCL_START */
- 3811 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f));
- 3812 : return context;
- 3813 : /* LCOV_EXCL_STOP */
- 3814 : }
- 3815 :
- 3816 : /* get the computed crc */
- 3817 1012 : crc_computed = scrc(f);
- 3818 :
- 3819 : /* adjust the stored crc to include itself */
- 3820 1012 : crc_stored = crc32c(crc_stored, buf, 4);
- 3821 :
- 3822 1012 : if (crc_computed != crc_stored) {
- 3823 : /* LCOV_EXCL_START */
- 3824 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f));
- 3825 : return context;
- 3826 : /* LCOV_EXCL_STOP */
- 3827 : }
- 3828 :
- 3829 1012 : return 0;
- 3830 : }
- 3831 :
- 3832 151 : static void state_verify_content(struct snapraid_state* state, uint32_t crc)
- 3833 : {
- 3834 : tommy_node* i;
- 3835 : int fail;
+ 3774 : /* update the mapping */
+ 3775 253 : state_map(state);
+ 3776 :
+ 3777 253 : state_content_check(state, path);
+ 3778 :
+ 3779 : /* mark that we read the content file, and it passed all the checks */
+ 3780 253 : state->checked_read = 1;
+ 3781 : }
+ 3782 :
+ 3783 : struct state_verify_thread_context {
+ 3784 : struct snapraid_state* state;
+ 3785 : struct snapraid_content* content;
+ 3786 : #if HAVE_MT_VERIFY
+ 3787 : pthread_t thread;
+ 3788 : #else
+ 3789 : void* retval;
+ 3790 : #endif
+ 3791 : /* input */
+ 3792 : uint32_t crc;
+ 3793 : STREAM* f;
+ 3794 : };
+ 3795 :
+ 3796 1009 : static void* state_verify_thread(void* arg)
+ 3797 : {
+ 3798 1009 : struct state_verify_thread_context* context = arg;
+ 3799 1009 : STREAM* f = context->f;
+ 3800 : unsigned char buf[4];
+ 3801 : uint32_t crc_stored;
+ 3802 : uint32_t crc_computed;
+ 3803 :
+ 3804 1009 : if (sdeplete(f, buf) != 0) {
+ 3805 : /* LCOV_EXCL_START */
+ 3806 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
+ 3807 : return context;
+ 3808 : /* LCOV_EXCL_STOP */
+ 3809 : }
+ 3810 :
+ 3811 : /* get the stored crc from the last four bytes */
+ 3812 1012 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
+ 3813 :
+ 3814 1012 : if (crc_stored != context->crc) {
+ 3815 : /* LCOV_EXCL_START */
+ 3816 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f));
+ 3817 : return context;
+ 3818 : /* LCOV_EXCL_STOP */
+ 3819 : }
+ 3820 :
+ 3821 : /* get the computed crc */
+ 3822 1012 : crc_computed = scrc(f);
+ 3823 :
+ 3824 : /* adjust the stored crc to include itself */
+ 3825 1012 : crc_stored = crc32c(crc_stored, buf, 4);
+ 3826 :
+ 3827 1012 : if (crc_computed != crc_stored) {
+ 3828 : /* LCOV_EXCL_START */
+ 3829 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f));
+ 3830 : return context;
+ 3831 : /* LCOV_EXCL_STOP */
+ 3832 : }
+ 3833 :
+ 3834 1012 : return 0;
+ 3835 : }
3836 :
- 3837 : /* start all reading threads */
- 3838 151 : i = tommy_list_head(&state->contentlist);
- 3839 1314 : while (i) {
- 3840 1012 : struct snapraid_content* content = i->data;
- 3841 : struct state_verify_thread_context* context;
- 3842 : char tmp[PATH_MAX];
- 3843 : STREAM* f;
- 3844 :
- 3845 1012 : msg_progress("Verifying %s...\n", content->content);
- 3846 :
- 3847 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3848 :
- 3849 1012 : f = sopen_read(tmp);
- 3850 1012 : if (f == 0) {
- 3851 : /* LCOV_EXCL_START */
- 3852 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno));
- 3853 : exit(EXIT_FAILURE);
- 3854 : /* LCOV_EXCL_STOP */
- 3855 : }
- 3856 :
- 3857 : /* allocate the thread context */
- 3858 1012 : context = malloc_nofail(sizeof(struct state_verify_thread_context));
- 3859 1012 : content->context = context;
- 3860 :
- 3861 : /* initialize */
- 3862 1012 : context->state = state;
- 3863 1012 : context->content = content;
- 3864 1012 : context->crc = crc;
- 3865 1012 : context->f = f;
- 3866 :
- 3867 : #if HAVE_MT_VERIFY
- 3868 1012 : thread_create(&context->thread, 0, state_verify_thread, context);
- 3869 : #else
- 3870 : context->retval = state_verify_thread(context);
- 3871 : #endif
- 3872 :
- 3873 1012 : i = i->next;
- 3874 : }
- 3875 :
- 3876 : /* join all thread */
- 3877 151 : fail = 0;
- 3878 151 : i = tommy_list_head(&state->contentlist);
- 3879 1314 : while (i) {
- 3880 1012 : struct snapraid_content* content = i->data;
- 3881 1012 : struct state_verify_thread_context* context = content->context;
- 3882 : void* retval;
- 3883 :
- 3884 : #if HAVE_MT_VERIFY
- 3885 1012 : thread_join(context->thread, &retval);
- 3886 : #else
- 3887 : retval = context->retval;
- 3888 : #endif
- 3889 1012 : if (retval) {
- 3890 : /* LCOV_EXCL_START */
- 3891 : fail = 1;
- 3892 : /* LCOV_EXCL_STOP */
- 3893 : } else {
- 3894 1012 : STREAM* f = context->f;
- 3895 :
- 3896 1012 : if (sclose(f) != 0) {
- 3897 : /* LCOV_EXCL_START */
- 3898 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
- 3899 : exit(EXIT_FAILURE);
- 3900 : /* LCOV_EXCL_STOP */
- 3901 : }
- 3902 : }
- 3903 :
- 3904 1012 : free(context);
- 3905 :
- 3906 1012 : i = i->next;
- 3907 : }
+ 3837 151 : static void state_verify_content(struct snapraid_state* state, uint32_t crc)
+ 3838 : {
+ 3839 : tommy_node* i;
+ 3840 : int fail;
+ 3841 :
+ 3842 : /* start all reading threads */
+ 3843 151 : i = tommy_list_head(&state->contentlist);
+ 3844 1314 : while (i) {
+ 3845 1012 : struct snapraid_content* content = i->data;
+ 3846 : struct state_verify_thread_context* context;
+ 3847 : char tmp[PATH_MAX];
+ 3848 : STREAM* f;
+ 3849 :
+ 3850 1012 : msg_progress("Verifying %s...\n", content->content);
+ 3851 :
+ 3852 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3853 :
+ 3854 1012 : f = sopen_read(tmp);
+ 3855 1012 : if (f == 0) {
+ 3856 : /* LCOV_EXCL_START */
+ 3857 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno));
+ 3858 : exit(EXIT_FAILURE);
+ 3859 : /* LCOV_EXCL_STOP */
+ 3860 : }
+ 3861 :
+ 3862 : /* allocate the thread context */
+ 3863 1012 : context = malloc_nofail(sizeof(struct state_verify_thread_context));
+ 3864 1012 : content->context = context;
+ 3865 :
+ 3866 : /* initialize */
+ 3867 1012 : context->state = state;
+ 3868 1012 : context->content = content;
+ 3869 1012 : context->crc = crc;
+ 3870 1012 : context->f = f;
+ 3871 :
+ 3872 : #if HAVE_MT_VERIFY
+ 3873 1012 : thread_create(&context->thread, 0, state_verify_thread, context);
+ 3874 : #else
+ 3875 : context->retval = state_verify_thread(context);
+ 3876 : #endif
+ 3877 :
+ 3878 1012 : i = i->next;
+ 3879 : }
+ 3880 :
+ 3881 : /* join all thread */
+ 3882 151 : fail = 0;
+ 3883 151 : i = tommy_list_head(&state->contentlist);
+ 3884 1314 : while (i) {
+ 3885 1012 : struct snapraid_content* content = i->data;
+ 3886 1012 : struct state_verify_thread_context* context = content->context;
+ 3887 : void* retval;
+ 3888 :
+ 3889 : #if HAVE_MT_VERIFY
+ 3890 1012 : thread_join(context->thread, &retval);
+ 3891 : #else
+ 3892 : retval = context->retval;
+ 3893 : #endif
+ 3894 1012 : if (retval) {
+ 3895 : /* LCOV_EXCL_START */
+ 3896 : fail = 1;
+ 3897 : /* LCOV_EXCL_STOP */
+ 3898 : } else {
+ 3899 1012 : STREAM* f = context->f;
+ 3900 :
+ 3901 1012 : if (sclose(f) != 0) {
+ 3902 : /* LCOV_EXCL_START */
+ 3903 : log_fatal("Error closing the content file. %s.\n", strerror(errno));
+ 3904 : exit(EXIT_FAILURE);
+ 3905 : /* LCOV_EXCL_STOP */
+ 3906 : }
+ 3907 : }
3908 :
- 3909 : /* abort on failure */
- 3910 151 : if (fail) {
- 3911 : /* LCOV_EXCL_START */
- 3912 : exit(EXIT_FAILURE);
- 3913 : /* LCOV_EXCL_STOP */
- 3914 : }
- 3915 151 : }
- 3916 :
- 3917 151 : static void state_rename_content(struct snapraid_state* state)
- 3918 : {
- 3919 : tommy_node* i;
- 3920 :
- 3921 151 : i = tommy_list_head(&state->contentlist);
- 3922 1314 : while (i) {
- 3923 1012 : struct snapraid_content* content = i->data;
- 3924 : char tmp[PATH_MAX];
+ 3909 1012 : free(context);
+ 3910 :
+ 3911 1012 : i = i->next;
+ 3912 : }
+ 3913 :
+ 3914 : /* abort on failure */
+ 3915 151 : if (fail) {
+ 3916 : /* LCOV_EXCL_START */
+ 3917 : exit(EXIT_FAILURE);
+ 3918 : /* LCOV_EXCL_STOP */
+ 3919 : }
+ 3920 151 : }
+ 3921 :
+ 3922 151 : static void state_rename_content(struct snapraid_state* state)
+ 3923 : {
+ 3924 : tommy_node* i;
3925 :
- 3926 : /* now renames the just written copy with the correct name */
- 3927 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
- 3928 1012 : if (rename(tmp, content->content) != 0) {
- 3929 : /* LCOV_EXCL_START */
- 3930 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno));
- 3931 : exit(EXIT_FAILURE);
- 3932 : /* LCOV_EXCL_STOP */
- 3933 : }
- 3934 :
- 3935 1012 : i = i->next;
- 3936 : }
- 3937 151 : }
- 3938 :
- 3939 151 : void state_write(struct snapraid_state* state)
- 3940 : {
- 3941 : uint32_t crc;
- 3942 :
- 3943 : /* write all the content files */
- 3944 151 : state_write_content(state, &crc);
- 3945 :
- 3946 : /* verify the just written files */
- 3947 151 : state_verify_content(state, crc);
- 3948 :
- 3949 : /* rename the new files, over the old ones */
- 3950 151 : state_rename_content(state);
- 3951 :
- 3952 151 : state->need_write = 0; /* no write needed anymore */
- 3953 151 : state->checked_read = 0; /* what we wrote is not checked in read */
- 3954 151 : }
- 3955 :
- 3956 122 : void state_skip(struct snapraid_state* state)
- 3957 : {
- 3958 : tommy_node* i;
- 3959 :
- 3960 : /* for each disk */
- 3961 850 : for (i = state->disklist; i != 0; i = i->next) {
- 3962 : tommy_node* j;
- 3963 728 : struct snapraid_disk* disk = i->data;
+ 3926 151 : i = tommy_list_head(&state->contentlist);
+ 3927 1314 : while (i) {
+ 3928 1012 : struct snapraid_content* content = i->data;
+ 3929 : char tmp[PATH_MAX];
+ 3930 :
+ 3931 : /* now renames the just written copy with the correct name */
+ 3932 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
+ 3933 1012 : if (rename(tmp, content->content) != 0) {
+ 3934 : /* LCOV_EXCL_START */
+ 3935 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno));
+ 3936 : exit(EXIT_FAILURE);
+ 3937 : /* LCOV_EXCL_STOP */
+ 3938 : }
+ 3939 :
+ 3940 1012 : i = i->next;
+ 3941 : }
+ 3942 151 : }
+ 3943 :
+ 3944 151 : void state_write(struct snapraid_state* state)
+ 3945 : {
+ 3946 : uint32_t crc;
+ 3947 :
+ 3948 : /* write all the content files */
+ 3949 151 : state_write_content(state, &crc);
+ 3950 :
+ 3951 : /* verify the just written files */
+ 3952 151 : state_verify_content(state, crc);
+ 3953 :
+ 3954 : /* rename the new files, over the old ones */
+ 3955 151 : state_rename_content(state);
+ 3956 :
+ 3957 151 : state->need_write = 0; /* no write needed anymore */
+ 3958 151 : state->checked_read = 0; /* what we wrote is not checked in read */
+ 3959 151 : }
+ 3960 :
+ 3961 122 : void state_skip(struct snapraid_state* state)
+ 3962 : {
+ 3963 : tommy_node* i;
3964 :
- 3965 728 : if (!disk->skip_access)
- 3966 727 : continue;
- 3967 :
- 3968 : /* for each file */
- 3969 1885 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
- 3970 1884 : struct snapraid_file* file = j->data;
- 3971 1884 : file_flag_set(file, FILE_IS_EXCLUDED);
- 3972 : }
- 3973 :
- 3974 : /* for each link */
- 3975 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
- 3976 56 : struct snapraid_link* slink = j->data;
- 3977 56 : link_flag_set(slink, FILE_IS_EXCLUDED);
- 3978 : }
- 3979 :
- 3980 : /* for each dir */
- 3981 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
- 3982 0 : struct snapraid_dir* dir = j->data;
- 3983 0 : dir_flag_set(dir, FILE_IS_EXCLUDED);
- 3984 : }
- 3985 : }
- 3986 122 : }
- 3987 :
- 3988 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error)
- 3989 : {
- 3990 : tommy_node* i;
- 3991 : unsigned l;
+ 3965 : /* for each disk */
+ 3966 850 : for (i = state->disklist; i != 0; i = i->next) {
+ 3967 : tommy_node* j;
+ 3968 728 : struct snapraid_disk* disk = i->data;
+ 3969 :
+ 3970 728 : if (!disk->skip_access)
+ 3971 727 : continue;
+ 3972 :
+ 3973 : /* for each file */
+ 3974 1885 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
+ 3975 1884 : struct snapraid_file* file = j->data;
+ 3976 1884 : file_flag_set(file, FILE_IS_EXCLUDED);
+ 3977 : }
+ 3978 :
+ 3979 : /* for each link */
+ 3980 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
+ 3981 56 : struct snapraid_link* slink = j->data;
+ 3982 56 : link_flag_set(slink, FILE_IS_EXCLUDED);
+ 3983 : }
+ 3984 :
+ 3985 : /* for each dir */
+ 3986 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
+ 3987 0 : struct snapraid_dir* dir = j->data;
+ 3988 0 : dir_flag_set(dir, FILE_IS_EXCLUDED);
+ 3989 : }
+ 3990 : }
+ 3991 122 : }
3992 :
- 3993 : /* if no filter, include all */
- 3994 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk))
- 3995 235 : return;
- 3996 :
- 3997 9 : msg_progress("Filtering...\n");
- 3998 :
- 3999 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
- 4000 8 : struct snapraid_filter* filter = i->data;
- 4001 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : "");
- 4002 : }
- 4003 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) {
- 4004 3 : struct snapraid_filter* filter = i->data;
- 4005 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : "");
- 4006 : }
- 4007 9 : if (filter_missing)
- 4008 2 : msg_verbose("\t<missing>\n");
- 4009 9 : if (filter_error)
- 4010 2 : msg_verbose("\t<error>\n");
- 4011 :
- 4012 : /* for each disk */
- 4013 63 : for (i = state->disklist; i != 0; i = i->next) {
- 4014 : tommy_node* j;
- 4015 54 : struct snapraid_disk* disk = i->data;
+ 3993 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error)
+ 3994 : {
+ 3995 : tommy_node* i;
+ 3996 : unsigned l;
+ 3997 :
+ 3998 : /* if no filter, include all */
+ 3999 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk))
+ 4000 235 : return;
+ 4001 :
+ 4002 9 : msg_progress("Filtering...\n");
+ 4003 :
+ 4004 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
+ 4005 8 : struct snapraid_filter* filter = i->data;
+ 4006 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : "");
+ 4007 : }
+ 4008 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) {
+ 4009 3 : struct snapraid_filter* filter = i->data;
+ 4010 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : "");
+ 4011 : }
+ 4012 9 : if (filter_missing)
+ 4013 2 : msg_verbose("\t<missing>\n");
+ 4014 9 : if (filter_error)
+ 4015 2 : msg_verbose("\t<error>\n");
4016 :
- 4017 : /* if we filter for presence, we have to access the disk, so better to print something */
- 4018 54 : if (filter_missing)
- 4019 12 : msg_progress("Scanning disk %s...\n", disk->name);
- 4020 :
- 4021 : /* for each file */
- 4022 133944 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
- 4023 133890 : struct snapraid_file* file = j->data;
- 4024 :
- 4025 133890 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0
- 4026 80982 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0
- 4027 78138 : || filter_existence(filter_missing, disk->dir, file->sub) != 0
- 4028 38646 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0
- 4029 : ) {
- 4030 109490 : file_flag_set(file, FILE_IS_EXCLUDED);
- 4031 : }
- 4032 : }
- 4033 :
- 4034 : /* for each link */
- 4035 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
- 4036 4360 : struct snapraid_link* slink = j->data;
- 4037 :
- 4038 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0
- 4039 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0
- 4040 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0
- 4041 : ) {
- 4042 3221 : link_flag_set(slink, FILE_IS_EXCLUDED);
- 4043 : }
- 4044 : }
- 4045 :
- 4046 : /* for each empty dir */
- 4047 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
- 4048 28 : struct snapraid_dir* dir = j->data;
- 4049 :
- 4050 28 : if (filter_emptydir(filterlist_disk, 0, disk->name, dir->sub) != 0
- 4051 17 : || filter_emptydir(filterlist_file, 0, disk->name, dir->sub) != 0
- 4052 17 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0
- 4053 : ) {
- 4054 19 : dir_flag_set(dir, FILE_IS_EXCLUDED);
- 4055 : }
- 4056 : }
- 4057 : }
- 4058 :
- 4059 : /* if we are filtering by disk */
- 4060 9 : if (!tommy_list_empty(filterlist_disk)) {
- 4061 : /* for each parity disk */
- 4062 20 : for (l = 0; l < state->level; ++l) {
- 4063 : /* check if the parity is excluded by name */
- 4064 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) {
- 4065 : /* excluded the parity from further operation */
- 4066 11 : state->parity[l].is_excluded = 1;
- 4067 : }
- 4068 : }
- 4069 : } else {
- 4070 : /* if we are filtering by file, exclude all parity */
- 4071 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) {
- 4072 : /* for each parity disk */
- 4073 16 : for (l = 0; l < state->level; ++l) {
- 4074 13 : state->parity[l].is_excluded = 1;
- 4075 : }
- 4076 : }
- 4077 : }
- 4078 : }
- 4079 :
- 4080 221 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax)
- 4081 : {
- 4082 : time_t now;
- 4083 :
- 4084 221 : if (state->opt.gui) {
- 4085 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax);
- 4086 5 : log_flush();
- 4087 : }
+ 4017 : /* for each disk */
+ 4018 63 : for (i = state->disklist; i != 0; i = i->next) {
+ 4019 : tommy_node* j;
+ 4020 54 : struct snapraid_disk* disk = i->data;
+ 4021 :
+ 4022 : /* if we filter for presence, we have to access the disk, so better to print something */
+ 4023 54 : if (filter_missing)
+ 4024 12 : msg_progress("Scanning disk %s...\n", disk->name);
+ 4025 :
+ 4026 : /* for each file */
+ 4027 133944 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) {
+ 4028 133890 : struct snapraid_file* file = j->data;
+ 4029 :
+ 4030 133890 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0
+ 4031 80982 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0
+ 4032 78138 : || filter_existence(filter_missing, disk->dir, file->sub) != 0
+ 4033 38646 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0
+ 4034 : ) {
+ 4035 109458 : file_flag_set(file, FILE_IS_EXCLUDED);
+ 4036 : }
+ 4037 : }
+ 4038 :
+ 4039 : /* for each link */
+ 4040 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) {
+ 4041 4360 : struct snapraid_link* slink = j->data;
+ 4042 :
+ 4043 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0
+ 4044 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0
+ 4045 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0
+ 4046 : ) {
+ 4047 3221 : link_flag_set(slink, FILE_IS_EXCLUDED);
+ 4048 : }
+ 4049 : }
+ 4050 :
+ 4051 : /* for each empty dir */
+ 4052 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) {
+ 4053 28 : struct snapraid_dir* dir = j->data;
+ 4054 :
+ 4055 28 : if (filter_emptydir(filterlist_disk, 0, disk->name, dir->sub) != 0
+ 4056 17 : || filter_emptydir(filterlist_file, 0, disk->name, dir->sub) != 0
+ 4057 17 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0
+ 4058 : ) {
+ 4059 19 : dir_flag_set(dir, FILE_IS_EXCLUDED);
+ 4060 : }
+ 4061 : }
+ 4062 : }
+ 4063 :
+ 4064 : /* if we are filtering by disk, exclude any parity not explicitely included */
+ 4065 9 : if (!tommy_list_empty(filterlist_disk)) {
+ 4066 : /* for each parity disk */
+ 4067 20 : for (l = 0; l < state->level; ++l) {
+ 4068 : /* check if the parity is excluded by name */
+ 4069 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) {
+ 4070 : /* excluded the parity from further operation */
+ 4071 11 : state->parity[l].is_excluded_by_filter = 1;
+ 4072 : }
+ 4073 : }
+ 4074 : } else {
+ 4075 : /* if we are filtering by file, exclude all parity */
+ 4076 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) {
+ 4077 : /* for each parity disk */
+ 4078 16 : for (l = 0; l < state->level; ++l) {
+ 4079 13 : state->parity[l].is_excluded_by_filter = 1;
+ 4080 : }
+ 4081 : }
+ 4082 : }
+ 4083 : }
+ 4084 :
+ 4085 221 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax)
+ 4086 : {
+ 4087 : time_t now;
4088 :
- 4089 221 : now = time(0);
- 4090 :
- 4091 221 : state->progress_whole_start = now;
- 4092 :
- 4093 221 : state->progress_tick = 0;
- 4094 221 : state->progress_ptr = 0;
- 4095 221 : state->progress_wasted = 0;
- 4096 :
- 4097 : /* stop if requested */
- 4098 221 : if (global_interrupt) {
- 4099 : /* LCOV_EXCL_START */
- 4100 : if (!state->opt.gui) {
- 4101 : msg_status("Not starting for interruption\n");
- 4102 : }
- 4103 : log_tag("sigint:0: SIGINT received\n");
- 4104 : log_flush();
- 4105 : return 0;
- 4106 : /* LCOV_EXCL_STOP */
- 4107 : }
- 4108 :
- 4109 221 : return 1;
- 4110 : }
- 4111 :
- 4112 221 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize)
- 4113 : {
- 4114 221 : if (state->opt.gui) {
- 4115 5 : log_tag("run:end\n");
- 4116 5 : log_flush();
- 4117 216 : } else if (countmax == 0) {
- 4118 19 : msg_status("Nothing to do\n");
- 4119 : } else {
- 4120 : time_t now;
- 4121 : time_t elapsed;
- 4122 :
- 4123 197 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA;
- 4124 :
- 4125 197 : now = time(0);
- 4126 :
- 4127 197 : elapsed = now - state->progress_whole_start - state->progress_wasted;
- 4128 :
- 4129 197 : msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB);
- 4130 197 : if (elapsed >= 60)
- 4131 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
- 4132 197 : msg_bar("\n");
- 4133 197 : msg_flush();
- 4134 : }
- 4135 221 : }
- 4136 :
- 4137 1 : void state_progress_stop(struct snapraid_state* state)
- 4138 : {
- 4139 : time_t now;
+ 4089 221 : if (state->opt.gui) {
+ 4090 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax);
+ 4091 5 : log_flush();
+ 4092 : }
+ 4093 :
+ 4094 221 : now = time(0);
+ 4095 :
+ 4096 221 : state->progress_whole_start = now;
+ 4097 :
+ 4098 221 : state->progress_tick = 0;
+ 4099 221 : state->progress_ptr = 0;
+ 4100 221 : state->progress_wasted = 0;
+ 4101 :
+ 4102 : /* stop if requested */
+ 4103 221 : if (global_interrupt) {
+ 4104 : /* LCOV_EXCL_START */
+ 4105 : if (!state->opt.gui) {
+ 4106 : msg_status("Not starting for interruption\n");
+ 4107 : }
+ 4108 : log_tag("sigint:0: SIGINT received\n");
+ 4109 : log_flush();
+ 4110 : return 0;
+ 4111 : /* LCOV_EXCL_STOP */
+ 4112 : }
+ 4113 :
+ 4114 221 : return 1;
+ 4115 : }
+ 4116 :
+ 4117 221 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize)
+ 4118 : {
+ 4119 221 : if (state->opt.gui) {
+ 4120 5 : log_tag("run:end\n");
+ 4121 5 : log_flush();
+ 4122 216 : } else if (countmax == 0) {
+ 4123 19 : msg_status("Nothing to do\n");
+ 4124 : } else {
+ 4125 : time_t now;
+ 4126 : time_t elapsed;
+ 4127 :
+ 4128 197 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA;
+ 4129 :
+ 4130 197 : now = time(0);
+ 4131 :
+ 4132 197 : elapsed = now - state->progress_whole_start - state->progress_wasted;
+ 4133 :
+ 4134 197 : msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB);
+ 4135 :
+ 4136 197 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
+ 4137 :
+ 4138 : /* some extra spaces to ensure to overwrite the latest status line */
+ 4139 197 : msg_bar(" ");
4140 :
- 4141 1 : now = time(0);
- 4142 :
- 4143 1 : if (!state->opt.gui) {
- 4144 1 : msg_bar("\n");
- 4145 1 : msg_flush();
- 4146 : }
- 4147 :
- 4148 1 : state->progress_interruption = now;
- 4149 1 : }
- 4150 :
- 4151 1 : void state_progress_restart(struct snapraid_state* state)
- 4152 : {
- 4153 : time_t now;
- 4154 :
- 4155 1 : now = time(0);
+ 4141 197 : msg_bar("\n");
+ 4142 197 : msg_flush();
+ 4143 : }
+ 4144 221 : }
+ 4145 :
+ 4146 1 : void state_progress_stop(struct snapraid_state* state)
+ 4147 : {
+ 4148 : time_t now;
+ 4149 :
+ 4150 1 : now = time(0);
+ 4151 :
+ 4152 1 : if (!state->opt.gui) {
+ 4153 1 : msg_bar("\n");
+ 4154 1 : msg_flush();
+ 4155 : }
4156 :
- 4157 : /* reset the progress counter */
- 4158 1 : state->progress_tick = 0;
- 4159 1 : state->progress_ptr = 0;
- 4160 :
- 4161 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */
- 4162 1 : state->progress_wasted += now - state->progress_interruption;
- 4163 1 : }
- 4164 :
- 4165 : #define PROGRESS_CLEAR " "
- 4166 :
- 4167 : /**
- 4168 : * Set the latest tick data in the progress vector.
- 4169 : */
- 4170 532 : static void state_progress_latest(struct snapraid_state* state)
- 4171 : {
- 4172 : tommy_node* i;
- 4173 : unsigned l;
- 4174 :
- 4175 532 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc;
- 4176 532 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched;
- 4177 532 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid;
- 4178 532 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash;
- 4179 532 : state->progress_tick_io[state->progress_ptr] = state->tick_io;
- 4180 3716 : for (i = state->disklist; i != 0; i = i->next) {
- 4181 3184 : struct snapraid_disk* disk = i->data;
- 4182 3184 : disk->progress_tick[state->progress_ptr] = disk->tick;
- 4183 : }
- 4184 2946 : for (l = 0; l < state->level; ++l)
- 4185 2414 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick;
- 4186 532 : }
- 4187 :
- 4188 : /**
- 4189 : * Number of columns
- 4190 : */
- 4191 : #define GRAPH_COLUMN 68
- 4192 :
- 4193 : /**
- 4194 : * Get the reference value, 0 if index is PROGRESS_MAX
- 4195 : */
- 4196 : #define ref(map, index) (index < PROGRESS_MAX ? map[index] : 0)
- 4197 :
- 4198 2 : static void state_progress_graph(struct snapraid_state* state, struct snapraid_io* io, unsigned current, unsigned oldest)
- 4199 : {
- 4200 : uint64_t v;
- 4201 : uint64_t tick_total;
- 4202 : unsigned bar;
- 4203 : tommy_node* i;
- 4204 : unsigned l;
- 4205 : size_t pad;
+ 4157 1 : state->progress_interruption = now;
+ 4158 1 : }
+ 4159 :
+ 4160 1 : void state_progress_restart(struct snapraid_state* state)
+ 4161 : {
+ 4162 : time_t now;
+ 4163 :
+ 4164 1 : now = time(0);
+ 4165 :
+ 4166 : /* reset the progress counter */
+ 4167 1 : state->progress_tick = 0;
+ 4168 1 : state->progress_ptr = 0;
+ 4169 :
+ 4170 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */
+ 4171 1 : state->progress_wasted += now - state->progress_interruption;
+ 4172 1 : }
+ 4173 :
+ 4174 : #define PROGRESS_CLEAR " "
+ 4175 :
+ 4176 : /**
+ 4177 : * Set the latest tick data in the progress vector.
+ 4178 : */
+ 4179 478 : static void state_progress_latest(struct snapraid_state* state)
+ 4180 : {
+ 4181 : tommy_node* i;
+ 4182 : unsigned l;
+ 4183 :
+ 4184 478 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc;
+ 4185 478 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched;
+ 4186 478 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid;
+ 4187 478 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash;
+ 4188 478 : state->progress_tick_io[state->progress_ptr] = state->tick_io;
+ 4189 3338 : for (i = state->disklist; i != 0; i = i->next) {
+ 4190 2860 : struct snapraid_disk* disk = i->data;
+ 4191 2860 : disk->progress_tick[state->progress_ptr] = disk->tick;
+ 4192 : }
+ 4193 2711 : for (l = 0; l < state->level; ++l)
+ 4194 2233 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick;
+ 4195 478 : }
+ 4196 :
+ 4197 : /**
+ 4198 : * Number of columns
+ 4199 : */
+ 4200 : #define GRAPH_COLUMN 68
+ 4201 :
+ 4202 : /**
+ 4203 : * Get the reference value, 0 if index is PROGRESS_MAX
+ 4204 : */
+ 4205 : #define ref(map, index) (index < PROGRESS_MAX ? map[index] : 0)
4206 :
- 4207 2 : tick_total = 0;
- 4208 :
- 4209 2 : tick_total += state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest);
- 4210 2 : tick_total += state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest);
- 4211 2 : tick_total += state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest);
- 4212 2 : tick_total += state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest);
- 4213 2 : tick_total += state->progress_tick_io[current] - ref(state->progress_tick_io, oldest);
- 4214 2 : if (!tick_total)
- 4215 2 : return;
- 4216 :
- 4217 2 : pad = 4;
- 4218 14 : for (i = state->disklist; i != 0; i = i->next) {
- 4219 12 : struct snapraid_disk* disk = i->data;
- 4220 12 : size_t len = strlen(disk->name);
- 4221 12 : if (pad < len)
- 4222 2 : pad = len;
- 4223 : }
- 4224 9 : for (l = 0; l < state->level; ++l) {
- 4225 7 : size_t len = strlen(lev_config_name(l));
- 4226 7 : if (pad < len)
- 4227 3 : pad = len;
- 4228 : }
- 4229 :
- 4230 : /* extra space */
- 4231 2 : pad += 1;
- 4232 :
- 4233 2 : if (pad + 30 < GRAPH_COLUMN)
- 4234 2 : bar = GRAPH_COLUMN - pad;
- 4235 : else
- 4236 0 : bar = 30;
- 4237 :
- 4238 2 : if (io) {
- 4239 1 : const char* legend = "cached blocks (instant, more is better)";
- 4240 :
- 4241 : /* refresh the cached blocks info */
- 4242 1 : io_refresh(io);
- 4243 :
- 4244 1 : printf("\n");
- 4245 :
- 4246 7 : for (i = state->disklist; i != 0; i = i->next) {
- 4247 6 : struct snapraid_disk* disk = i->data;
- 4248 6 : v = disk->cached;
- 4249 6 : printr(disk->name, pad);
- 4250 6 : printf("%4" PRIu64 " | ", v);
- 4251 6 : printc('o', v * bar / io->io_max);
- 4252 6 : printf("\n");
- 4253 : }
+ 4207 1 : static void state_progress_graph(struct snapraid_state* state, struct snapraid_io* io, unsigned current, unsigned oldest)
+ 4208 : {
+ 4209 : uint64_t v;
+ 4210 : uint64_t tick_total;
+ 4211 : unsigned bar;
+ 4212 : tommy_node* i;
+ 4213 : unsigned l;
+ 4214 : size_t pad;
+ 4215 :
+ 4216 1 : tick_total = 0;
+ 4217 :
+ 4218 1 : tick_total += state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest);
+ 4219 1 : tick_total += state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest);
+ 4220 1 : tick_total += state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest);
+ 4221 1 : tick_total += state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest);
+ 4222 1 : tick_total += state->progress_tick_io[current] - ref(state->progress_tick_io, oldest);
+ 4223 1 : if (!tick_total)
+ 4224 1 : return;
+ 4225 :
+ 4226 1 : pad = 4;
+ 4227 7 : for (i = state->disklist; i != 0; i = i->next) {
+ 4228 6 : struct snapraid_disk* disk = i->data;
+ 4229 6 : size_t len = strlen(disk->name);
+ 4230 6 : if (pad < len)
+ 4231 1 : pad = len;
+ 4232 : }
+ 4233 7 : for (l = 0; l < state->level; ++l) {
+ 4234 6 : size_t len = strlen(lev_config_name(l));
+ 4235 6 : if (pad < len)
+ 4236 2 : pad = len;
+ 4237 : }
+ 4238 :
+ 4239 : /* extra space */
+ 4240 1 : pad += 1;
+ 4241 :
+ 4242 1 : if (pad + 30 < GRAPH_COLUMN)
+ 4243 1 : bar = GRAPH_COLUMN - pad;
+ 4244 : else
+ 4245 0 : bar = 30;
+ 4246 :
+ 4247 1 : if (io) {
+ 4248 0 : const char* legend = "cached blocks (instant, more is better)";
+ 4249 :
+ 4250 : /* refresh the cached blocks info */
+ 4251 0 : io_refresh(io);
+ 4252 :
+ 4253 0 : printf("\n");
4254 :
- 4255 2 : for (l = 0; l < state->level; ++l) {
- 4256 1 : v = state->parity[l].cached;
- 4257 1 : printr(lev_config_name(l), pad);
- 4258 1 : printf("%4" PRIu64 " | ", v);
- 4259 1 : printc('o', v * bar / io->io_max);
- 4260 1 : printf("\n");
- 4261 : }
- 4262 :
- 4263 1 : printc(' ', pad);
- 4264 1 : printf(" |_");
- 4265 1 : printc('_', bar);
- 4266 1 : printf("\n");
- 4267 :
- 4268 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2);
- 4269 1 : printf("%s", legend);
- 4270 1 : printf("\n");
- 4271 : }
- 4272 :
- 4273 2 : printf("\n");
- 4274 :
- 4275 14 : for (i = state->disklist; i != 0; i = i->next) {
- 4276 12 : struct snapraid_disk* disk = i->data;
- 4277 12 : v = disk->progress_tick[current] - ref(disk->progress_tick, oldest);
- 4278 12 : printr(disk->name, pad);
- 4279 12 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4280 12 : printc('*', v * bar / tick_total);
- 4281 12 : printf("\n");
- 4282 : }
+ 4255 0 : for (i = state->disklist; i != 0; i = i->next) {
+ 4256 0 : struct snapraid_disk* disk = i->data;
+ 4257 0 : v = disk->cached;
+ 4258 0 : printr(disk->name, pad);
+ 4259 0 : printf("%4" PRIu64 " | ", v);
+ 4260 0 : printc('o', v * bar / io->io_max);
+ 4261 0 : printf("\n");
+ 4262 : }
+ 4263 :
+ 4264 0 : for (l = 0; l < state->level; ++l) {
+ 4265 0 : v = state->parity[l].cached;
+ 4266 0 : printr(lev_config_name(l), pad);
+ 4267 0 : printf("%4" PRIu64 " | ", v);
+ 4268 0 : printc('o', v * bar / io->io_max);
+ 4269 0 : printf("\n");
+ 4270 : }
+ 4271 :
+ 4272 0 : printc(' ', pad);
+ 4273 0 : printf(" |_");
+ 4274 0 : printc('_', bar);
+ 4275 0 : printf("\n");
+ 4276 :
+ 4277 0 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2);
+ 4278 0 : printf("%s", legend);
+ 4279 0 : printf("\n");
+ 4280 : }
+ 4281 :
+ 4282 1 : printf("\n");
4283 :
- 4284 9 : for (l = 0; l < state->level; ++l) {
- 4285 7 : v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest);
- 4286 7 : printr(lev_config_name(l), pad);
- 4287 7 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4288 7 : printc('*', v * bar / tick_total);
- 4289 7 : printf("\n");
- 4290 : }
- 4291 :
- 4292 2 : v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest);
- 4293 2 : printr("raid", pad);
- 4294 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4295 2 : printc('*', v * bar / tick_total);
- 4296 2 : printf("\n");
- 4297 :
- 4298 2 : v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest);
- 4299 2 : printr("hash", pad);
- 4300 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4301 2 : printc('*', v * bar / tick_total);
- 4302 2 : printf("\n");
- 4303 :
- 4304 2 : v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest);
- 4305 2 : printr("sched", pad);
- 4306 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4307 2 : printc('*', v * bar / tick_total);
- 4308 2 : printf("\n");
- 4309 :
- 4310 2 : v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest);
- 4311 2 : printr("misc", pad);
- 4312 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
- 4313 2 : printc('*', v * bar / tick_total);
- 4314 2 : printf("\n");
- 4315 :
- 4316 2 : printc(' ', pad);
- 4317 2 : printf(" |_");
- 4318 2 : printc('_', bar);
- 4319 2 : printf("\n");
- 4320 :
- 4321 2 : if (oldest == PROGRESS_MAX) {
- 4322 1 : const char* legend = "wait time (total, less is better)";
- 4323 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2);
- 4324 1 : printf("%s", legend);
- 4325 1 : printf("\n");
- 4326 : } else {
- 4327 1 : const char* legend_d = "wait time (last %d secs, less is better)";
- 4328 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend_d) / 2);
- 4329 1 : printf(legend_d, PROGRESS_MAX);
- 4330 1 : printf("\n");
- 4331 : }
- 4332 :
- 4333 2 : printf("\n");
- 4334 : }
- 4335 :
- 4336 1073436 : int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize)
- 4337 : {
- 4338 : time_t now;
- 4339 : int pred;
- 4340 :
- 4341 1073436 : now = time(0);
- 4342 :
- 4343 : /* previous position */
- 4344 1073436 : pred = state->progress_ptr + PROGRESS_MAX - 1;
- 4345 1073436 : if (pred >= PROGRESS_MAX)
- 4346 1073237 : pred -= PROGRESS_MAX;
- 4347 :
- 4348 : /* if the previous measure is different */
- 4349 1073436 : if (state->progress_tick == 0
- 4350 1073237 : || state->progress_time[pred] != now
- 4351 : ) {
- 4352 : time_t elapsed;
- 4353 436 : unsigned out_perc = 0;
- 4354 436 : unsigned out_speed = 0;
- 4355 436 : unsigned out_cpu = 0;
- 4356 436 : unsigned out_eta = 0;
- 4357 436 : int out_computed = 0;
- 4358 :
- 4359 : /* store the new measure */
- 4360 436 : state->progress_time[state->progress_ptr] = now;
- 4361 436 : state->progress_pos[state->progress_ptr] = countpos;
- 4362 436 : state->progress_size[state->progress_ptr] = countsize;
- 4363 436 : state_progress_latest(state);
- 4364 :
- 4365 436 : elapsed = now - state->progress_whole_start - state->progress_wasted;
- 4366 :
- 4367 : /* completion percentage */
- 4368 436 : if (countmax)
- 4369 436 : out_perc = countpos * 100 / countmax;
- 4370 :
- 4371 : /* if we have at least 5 measures */
- 4372 436 : if (state->progress_tick >= 5
- 4373 : /* or if we are running in test mode, with at least one measure */
- 4374 397 : || (state->opt.force_progress && state->progress_tick >= 1)
- 4375 : ) {
- 4376 : int oldest;
- 4377 : int past;
- 4378 : time_t delta_time;
- 4379 : block_off_t delta_pos;
- 4380 : data_off_t delta_size;
- 4381 : uint64_t tick_cpu;
- 4382 : uint64_t tick_total;
- 4383 : uint64_t delta_tick_cpu;
- 4384 : uint64_t delta_tick_total;
- 4385 : uint64_t oldest_tick_cpu;
- 4386 : uint64_t oldest_tick_total;
- 4387 :
- 4388 : /* number of past measures */
- 4389 237 : past = state->progress_tick;
- 4390 :
- 4391 : /* drop the oldest ones, to promptly */
- 4392 : /* skip the startup phase */
- 4393 237 : past -= past / 5;
- 4394 :
- 4395 : /* check how much we can go in the past */
- 4396 237 : if (past >= PROGRESS_MAX - 1) {
- 4397 : /* the vector is filled, so we are already in position */
- 4398 : /* to get the possible oldest one */
- 4399 0 : oldest = state->progress_ptr + 1;
- 4400 : } else {
- 4401 : /* go backward the number of positions selected */
- 4402 237 : oldest = state->progress_ptr + PROGRESS_MAX - past;
- 4403 : }
- 4404 237 : if (oldest >= PROGRESS_MAX)
- 4405 237 : oldest -= PROGRESS_MAX;
- 4406 :
- 4407 474 : tick_cpu = state->progress_tick_misc[state->progress_ptr]
- 4408 237 : + state->progress_tick_sched[state->progress_ptr]
- 4409 237 : + state->progress_tick_raid[state->progress_ptr]
- 4410 237 : + state->progress_tick_hash[state->progress_ptr];
- 4411 237 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr];
- 4412 :
- 4413 474 : oldest_tick_cpu = state->progress_tick_misc[oldest]
- 4414 237 : + state->progress_tick_sched[oldest]
- 4415 237 : + state->progress_tick_raid[oldest]
- 4416 237 : + state->progress_tick_hash[oldest];
- 4417 237 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest];
- 4418 :
- 4419 237 : delta_time = now - state->progress_time[oldest];
- 4420 237 : delta_pos = countpos - state->progress_pos[oldest];
- 4421 237 : delta_size = countsize - state->progress_size[oldest];
- 4422 237 : delta_tick_cpu = tick_cpu - oldest_tick_cpu;
- 4423 237 : delta_tick_total = tick_total - oldest_tick_total;
- 4424 :
- 4425 : /* estimate the speed in MB/s */
- 4426 237 : if (delta_time != 0)
- 4427 237 : out_speed = (unsigned)(delta_size / MEGA / delta_time);
- 4428 :
- 4429 : /* estimate the cpu usage percentage */
- 4430 237 : if (delta_tick_total != 0)
- 4431 95 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total);
- 4432 :
- 4433 : /* estimate the remaining time in minutes */
- 4434 237 : if (delta_pos != 0)
- 4435 237 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos);
- 4436 :
- 4437 237 : if (state->opt.force_stats) {
- 4438 1 : os_clear();
- 4439 1 : state_progress_graph(state, io, state->progress_ptr, oldest);
- 4440 : }
+ 4284 7 : for (i = state->disklist; i != 0; i = i->next) {
+ 4285 6 : struct snapraid_disk* disk = i->data;
+ 4286 6 : v = disk->progress_tick[current] - ref(disk->progress_tick, oldest);
+ 4287 6 : printr(disk->name, pad);
+ 4288 6 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4289 6 : printc('*', v * bar / tick_total);
+ 4290 6 : printf("\n");
+ 4291 : }
+ 4292 :
+ 4293 7 : for (l = 0; l < state->level; ++l) {
+ 4294 6 : v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest);
+ 4295 6 : printr(lev_config_name(l), pad);
+ 4296 6 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4297 6 : printc('*', v * bar / tick_total);
+ 4298 6 : printf("\n");
+ 4299 : }
+ 4300 :
+ 4301 1 : v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest);
+ 4302 1 : printr("raid", pad);
+ 4303 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4304 1 : printc('*', v * bar / tick_total);
+ 4305 1 : printf("\n");
+ 4306 :
+ 4307 1 : v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest);
+ 4308 1 : printr("hash", pad);
+ 4309 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4310 1 : printc('*', v * bar / tick_total);
+ 4311 1 : printf("\n");
+ 4312 :
+ 4313 1 : v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest);
+ 4314 1 : printr("sched", pad);
+ 4315 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4316 1 : printc('*', v * bar / tick_total);
+ 4317 1 : printf("\n");
+ 4318 :
+ 4319 1 : v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest);
+ 4320 1 : printr("misc", pad);
+ 4321 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
+ 4322 1 : printc('*', v * bar / tick_total);
+ 4323 1 : printf("\n");
+ 4324 :
+ 4325 1 : printc(' ', pad);
+ 4326 1 : printf(" |_");
+ 4327 1 : printc('_', bar);
+ 4328 1 : printf("\n");
+ 4329 :
+ 4330 1 : if (oldest == PROGRESS_MAX) {
+ 4331 1 : const char* legend = "wait time (total, less is better)";
+ 4332 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2);
+ 4333 1 : printf("%s", legend);
+ 4334 1 : printf("\n");
+ 4335 : } else {
+ 4336 0 : const char* legend_d = "wait time (last %d secs, less is better)";
+ 4337 0 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend_d) / 2);
+ 4338 0 : printf(legend_d, PROGRESS_MAX);
+ 4339 0 : printf("\n");
+ 4340 : }
+ 4341 :
+ 4342 1 : printf("\n");
+ 4343 : }
+ 4344 :
+ 4345 1073492 : int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize)
+ 4346 : {
+ 4347 : time_t now;
+ 4348 : int pred;
+ 4349 :
+ 4350 1073492 : now = time(0);
+ 4351 :
+ 4352 : /* previous position */
+ 4353 1073492 : pred = state->progress_ptr + PROGRESS_MAX - 1;
+ 4354 1073492 : if (pred >= PROGRESS_MAX)
+ 4355 1073293 : pred -= PROGRESS_MAX;
+ 4356 :
+ 4357 : /* if the previous measure is different */
+ 4358 1073492 : if (state->progress_tick == 0
+ 4359 1073293 : || state->progress_time[pred] != now
+ 4360 : ) {
+ 4361 : time_t elapsed;
+ 4362 382 : unsigned out_perc = 0;
+ 4363 382 : unsigned out_speed = 0;
+ 4364 382 : unsigned out_cpu = 0;
+ 4365 382 : unsigned out_eta = 0;
+ 4366 382 : int out_computed = 0;
+ 4367 :
+ 4368 : /* store the new measure */
+ 4369 382 : state->progress_time[state->progress_ptr] = now;
+ 4370 382 : state->progress_pos[state->progress_ptr] = countpos;
+ 4371 382 : state->progress_size[state->progress_ptr] = countsize;
+ 4372 382 : state_progress_latest(state);
+ 4373 :
+ 4374 382 : elapsed = now - state->progress_whole_start - state->progress_wasted;
+ 4375 :
+ 4376 : /* completion percentage */
+ 4377 382 : if (countmax)
+ 4378 382 : out_perc = countpos * 100 / countmax;
+ 4379 :
+ 4380 : /* if we have at least 5 measures */
+ 4381 382 : if (state->progress_tick >= 5
+ 4382 : /* or if we are running in test mode, with at least one measure */
+ 4383 365 : || (state->opt.force_progress && state->progress_tick >= 1)
+ 4384 : ) {
+ 4385 : int oldest;
+ 4386 : int past;
+ 4387 : time_t delta_time;
+ 4388 : block_off_t delta_pos;
+ 4389 : data_off_t delta_size;
+ 4390 : uint64_t tick_cpu;
+ 4391 : uint64_t tick_total;
+ 4392 : uint64_t delta_tick_cpu;
+ 4393 : uint64_t delta_tick_total;
+ 4394 : uint64_t oldest_tick_cpu;
+ 4395 : uint64_t oldest_tick_total;
+ 4396 :
+ 4397 : /* number of past measures */
+ 4398 183 : past = state->progress_tick;
+ 4399 :
+ 4400 : /* drop the oldest ones, to promptly */
+ 4401 : /* skip the startup phase */
+ 4402 183 : past -= past / 5;
+ 4403 :
+ 4404 : /* check how much we can go in the past */
+ 4405 183 : if (past >= PROGRESS_MAX - 1) {
+ 4406 : /* the vector is filled, so we are already in position */
+ 4407 : /* to get the possible oldest one */
+ 4408 0 : oldest = state->progress_ptr + 1;
+ 4409 : } else {
+ 4410 : /* go backward the number of positions selected */
+ 4411 183 : oldest = state->progress_ptr + PROGRESS_MAX - past;
+ 4412 : }
+ 4413 183 : if (oldest >= PROGRESS_MAX)
+ 4414 183 : oldest -= PROGRESS_MAX;
+ 4415 :
+ 4416 366 : tick_cpu = state->progress_tick_misc[state->progress_ptr]
+ 4417 183 : + state->progress_tick_sched[state->progress_ptr]
+ 4418 183 : + state->progress_tick_raid[state->progress_ptr]
+ 4419 183 : + state->progress_tick_hash[state->progress_ptr];
+ 4420 183 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr];
+ 4421 :
+ 4422 366 : oldest_tick_cpu = state->progress_tick_misc[oldest]
+ 4423 183 : + state->progress_tick_sched[oldest]
+ 4424 183 : + state->progress_tick_raid[oldest]
+ 4425 183 : + state->progress_tick_hash[oldest];
+ 4426 183 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest];
+ 4427 :
+ 4428 183 : delta_time = now - state->progress_time[oldest];
+ 4429 183 : delta_pos = countpos - state->progress_pos[oldest];
+ 4430 183 : delta_size = countsize - state->progress_size[oldest];
+ 4431 183 : delta_tick_cpu = tick_cpu - oldest_tick_cpu;
+ 4432 183 : delta_tick_total = tick_total - oldest_tick_total;
+ 4433 :
+ 4434 : /* estimate the speed in MB/s */
+ 4435 183 : if (delta_time != 0)
+ 4436 183 : out_speed = (unsigned)(delta_size / MEGA / delta_time);
+ 4437 :
+ 4438 : /* estimate the cpu usage percentage */
+ 4439 183 : if (delta_tick_total != 0)
+ 4440 77 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total);
4441 :
- 4442 : /* we have the output value */
- 4443 237 : out_computed = 1;
- 4444 : }
+ 4442 : /* estimate the remaining time in minutes */
+ 4443 183 : if (delta_pos != 0)
+ 4444 183 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos);
4445 :
- 4446 436 : if (state->opt.gui) {
- 4447 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);
- 4448 7 : log_flush();
- 4449 : } else {
- 4450 429 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA));
- 4451 429 : if (out_computed) {
- 4452 235 : msg_bar(", %u MB/s", out_speed);
- 4453 235 : msg_bar(", CPU %u%%", out_cpu);
- 4454 235 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
- 4455 : }
- 4456 429 : msg_bar("%s\r", PROGRESS_CLEAR);
- 4457 429 : msg_flush();
- 4458 : }
- 4459 :
- 4460 : /* next position to fill */
- 4461 436 : ++state->progress_ptr;
- 4462 436 : if (state->progress_ptr >= PROGRESS_MAX)
- 4463 0 : state->progress_ptr -= PROGRESS_MAX;
- 4464 :
- 4465 : /* one more measure */
- 4466 436 : ++state->progress_tick;
- 4467 : }
+ 4446 183 : if (state->opt.force_stats) {
+ 4447 0 : os_clear();
+ 4448 0 : state_progress_graph(state, io, state->progress_ptr, oldest);
+ 4449 : }
+ 4450 :
+ 4451 : /* we have the output value */
+ 4452 183 : out_computed = 1;
+ 4453 : }
+ 4454 :
+ 4455 382 : if (state->opt.gui) {
+ 4456 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);
+ 4457 7 : log_flush();
+ 4458 : } else {
+ 4459 375 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA));
+ 4460 375 : if (out_computed) {
+ 4461 181 : msg_bar(", %u MB/s", out_speed);
+ 4462 181 : msg_bar(", CPU %u%%", out_cpu);
+ 4463 181 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
+ 4464 : }
+ 4465 375 : msg_bar("%s\r", PROGRESS_CLEAR);
+ 4466 375 : msg_flush();
+ 4467 : }
4468 :
- 4469 : /* stop if requested */
- 4470 1073436 : if (global_interrupt) {
- 4471 : /* LCOV_EXCL_START */
- 4472 : if (!state->opt.gui) {
- 4473 : log_fatal("\n");
- 4474 : log_fatal("Stopping for interruption at block %u\n", blockpos);
- 4475 : }
- 4476 : log_tag("sigint:%u: SIGINT received\n", blockpos);
- 4477 : log_flush();
- 4478 : return 1;
- 4479 : /* LCOV_EXCL_STOP */
- 4480 : }
- 4481 :
- 4482 1073436 : return 0;
- 4483 : }
- 4484 :
- 4485 104 : void state_usage_waste(struct snapraid_state* state)
- 4486 : {
- 4487 104 : uint64_t now = tick();
- 4488 :
- 4489 104 : state->tick_last = now;
- 4490 104 : }
- 4491 :
- 4492 1063244 : void state_usage_misc(struct snapraid_state* state)
- 4493 : {
- 4494 1063244 : uint64_t now = tick();
- 4495 1063244 : uint64_t delta = now - state->tick_last;
- 4496 :
- 4497 : /* increment the time spent in computations */
- 4498 1063244 : state->tick_misc += delta;
- 4499 :
- 4500 1063244 : state->tick_last = now;
- 4501 1063244 : }
- 4502 :
- 4503 149863 : void state_usage_sched(struct snapraid_state* state)
- 4504 : {
- 4505 149863 : uint64_t now = tick();
- 4506 149863 : uint64_t delta = now - state->tick_last;
- 4507 :
- 4508 : /* increment the time spent in computations */
- 4509 149863 : state->tick_sched += delta;
- 4510 :
- 4511 149863 : state->tick_last = now;
- 4512 149863 : }
- 4513 :
- 4514 140402 : void state_usage_raid(struct snapraid_state* state)
- 4515 : {
- 4516 140402 : uint64_t now = tick();
- 4517 140402 : uint64_t delta = now - state->tick_last;
- 4518 :
- 4519 : /* increment the time spent in computations */
- 4520 140402 : state->tick_raid += delta;
- 4521 :
- 4522 140402 : state->tick_last = now;
- 4523 140402 : }
- 4524 :
- 4525 776953 : void state_usage_hash(struct snapraid_state* state)
- 4526 : {
- 4527 776953 : uint64_t now = tick();
- 4528 776953 : uint64_t delta = now - state->tick_last;
- 4529 :
- 4530 : /* increment the time spent in computations */
- 4531 776953 : state->tick_hash += delta;
- 4532 :
- 4533 776953 : state->tick_last = now;
- 4534 776953 : }
- 4535 :
- 4536 912519 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac)
- 4537 : {
- 4538 912519 : uint64_t now = tick();
- 4539 912519 : uint64_t delta = now - state->tick_last;
- 4540 : unsigned i;
+ 4469 : /* next position to fill */
+ 4470 382 : ++state->progress_ptr;
+ 4471 382 : if (state->progress_ptr >= PROGRESS_MAX)
+ 4472 0 : state->progress_ptr -= PROGRESS_MAX;
+ 4473 :
+ 4474 : /* one more measure */
+ 4475 382 : ++state->progress_tick;
+ 4476 : }
+ 4477 :
+ 4478 : /* stop if requested */
+ 4479 1073492 : if (global_interrupt) {
+ 4480 : /* LCOV_EXCL_START */
+ 4481 : if (!state->opt.gui) {
+ 4482 : log_fatal("\n");
+ 4483 : log_fatal("Stopping for interruption at block %u\n", blockpos);
+ 4484 : }
+ 4485 : log_tag("sigint:%u: SIGINT received\n", blockpos);
+ 4486 : log_flush();
+ 4487 : return 1;
+ 4488 : /* LCOV_EXCL_STOP */
+ 4489 : }
+ 4490 :
+ 4491 1073492 : return 0;
+ 4492 : }
+ 4493 :
+ 4494 104 : void state_usage_waste(struct snapraid_state* state)
+ 4495 : {
+ 4496 104 : uint64_t now = tick();
+ 4497 :
+ 4498 104 : state->tick_last = now;
+ 4499 104 : }
+ 4500 :
+ 4501 1063636 : void state_usage_misc(struct snapraid_state* state)
+ 4502 : {
+ 4503 1063636 : uint64_t now = tick();
+ 4504 1063636 : uint64_t delta = now - state->tick_last;
+ 4505 :
+ 4506 : /* increment the time spent in computations */
+ 4507 1063636 : state->tick_misc += delta;
+ 4508 :
+ 4509 1063636 : state->tick_last = now;
+ 4510 1063636 : }
+ 4511 :
+ 4512 149919 : void state_usage_sched(struct snapraid_state* state)
+ 4513 : {
+ 4514 149919 : uint64_t now = tick();
+ 4515 149919 : uint64_t delta = now - state->tick_last;
+ 4516 :
+ 4517 : /* increment the time spent in computations */
+ 4518 149919 : state->tick_sched += delta;
+ 4519 :
+ 4520 149919 : state->tick_last = now;
+ 4521 149919 : }
+ 4522 :
+ 4523 140474 : void state_usage_raid(struct snapraid_state* state)
+ 4524 : {
+ 4525 140474 : uint64_t now = tick();
+ 4526 140474 : uint64_t delta = now - state->tick_last;
+ 4527 :
+ 4528 : /* increment the time spent in computations */
+ 4529 140474 : state->tick_raid += delta;
+ 4530 :
+ 4531 140474 : state->tick_last = now;
+ 4532 140474 : }
+ 4533 :
+ 4534 777321 : void state_usage_hash(struct snapraid_state* state)
+ 4535 : {
+ 4536 777321 : uint64_t now = tick();
+ 4537 777321 : uint64_t delta = now - state->tick_last;
+ 4538 :
+ 4539 : /* increment the time spent in computations */
+ 4540 777321 : state->tick_hash += delta;
4541 :
- 4542 : /* increment the time spent in the data disks */
- 4543 957179 : for (i = 0; i < waiting_mac; ++i) {
- 4544 44660 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk;
- 4545 :
- 4546 44660 : if (!disk)
- 4547 10 : continue;
- 4548 :
- 4549 44650 : disk->tick += delta;
- 4550 : }
- 4551 912519 : state->tick_io += delta;
- 4552 :
- 4553 912519 : state->tick_last = now;
- 4554 912519 : }
- 4555 :
- 4556 774185 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac)
- 4557 : {
- 4558 774185 : uint64_t now = tick();
- 4559 774185 : uint64_t delta = now - state->tick_last;
- 4560 : unsigned i;
+ 4542 777321 : state->tick_last = now;
+ 4543 777321 : }
+ 4544 :
+ 4545 912855 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac)
+ 4546 : {
+ 4547 912855 : uint64_t now = tick();
+ 4548 912855 : uint64_t delta = now - state->tick_last;
+ 4549 : unsigned i;
+ 4550 :
+ 4551 : /* increment the time spent in the data disks */
+ 4552 955269 : for (i = 0; i < waiting_mac; ++i) {
+ 4553 42414 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk;
+ 4554 :
+ 4555 42414 : if (!disk)
+ 4556 0 : continue;
+ 4557 :
+ 4558 42414 : disk->tick += delta;
+ 4559 : }
+ 4560 912855 : state->tick_io += delta;
4561 :
- 4562 : /* increment the time spent in the parity disk */
- 4563 854258 : for (i = 0; i < waiting_mac; ++i)
- 4564 80073 : state->parity[waiting_map[i]].tick += delta;
- 4565 774185 : state->tick_io += delta;
- 4566 :
- 4567 774185 : state->tick_last = now;
- 4568 774185 : }
- 4569 :
- 4570 96 : void state_usage_print(struct snapraid_state* state)
- 4571 : {
- 4572 : /* set the latest data */
- 4573 96 : state_progress_latest(state);
- 4574 :
- 4575 96 : if (msg_level < MSG_PROGRESS)
- 4576 191 : return;
- 4577 :
- 4578 : /* print a graph for it */
- 4579 1 : state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX);
- 4580 : }
- 4581 :
- 4582 499 : void state_fscheck(struct snapraid_state* state, const char* ope)
- 4583 : {
- 4584 : tommy_node* i;
- 4585 :
- 4586 : /* check the file-system on all disks */
- 4587 3487 : for (i = state->disklist; i != 0; i = i->next) {
- 4588 2988 : struct snapraid_disk* disk = i->data;
- 4589 :
- 4590 2988 : if (fs_check(disk) != 0) {
- 4591 : /* LCOV_EXCL_START */
- 4592 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope);
- 4593 : os_abort();
- 4594 : /* LCOV_EXCL_STOP */
- 4595 : }
- 4596 : }
- 4597 499 : }
+ 4562 912855 : state->tick_last = now;
+ 4563 912855 : }
+ 4564 :
+ 4565 774521 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac)
+ 4566 : {
+ 4567 774521 : uint64_t now = tick();
+ 4568 774521 : uint64_t delta = now - state->tick_last;
+ 4569 : unsigned i;
+ 4570 :
+ 4571 : /* increment the time spent in the parity disk */
+ 4572 854191 : for (i = 0; i < waiting_mac; ++i)
+ 4573 79670 : state->parity[waiting_map[i]].tick += delta;
+ 4574 774521 : state->tick_io += delta;
+ 4575 :
+ 4576 774521 : state->tick_last = now;
+ 4577 774521 : }
+ 4578 :
+ 4579 96 : void state_usage_print(struct snapraid_state* state)
+ 4580 : {
+ 4581 : /* set the latest data */
+ 4582 96 : state_progress_latest(state);
+ 4583 :
+ 4584 96 : if (msg_level < MSG_PROGRESS)
+ 4585 191 : return;
+ 4586 :
+ 4587 : /* print a graph for it */
+ 4588 1 : state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX);
+ 4589 : }
+ 4590 :
+ 4591 499 : void state_fscheck(struct snapraid_state* state, const char* ope)
+ 4592 : {
+ 4593 : tommy_node* i;
+ 4594 :
+ 4595 : /* check the file-system on all disks */
+ 4596 3487 : for (i = state->disklist; i != 0; i = i->next) {
+ 4597 2988 : struct snapraid_disk* disk = i->data;
4598 :
- 4599 1 : void generate_configuration(const char* path)
- 4600 : {
- 4601 : struct snapraid_state state;
- 4602 : struct snapraid_content* content;
- 4603 : char esc_buffer[ESC_MAX];
- 4604 : unsigned l, s;
- 4605 : tommy_node* j;
- 4606 :
- 4607 1 : state_init(&state);
- 4608 :
- 4609 : /* mark that we are without a configuration file */
- 4610 1 : state.no_conf = 1;
- 4611 :
- 4612 : /* create the dummy content entry */
- 4613 1 : content = content_alloc(path, -1);
- 4614 :
- 4615 : /* adds the content entry */
- 4616 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content);
+ 4599 2988 : if (fs_check(disk) != 0) {
+ 4600 : /* LCOV_EXCL_START */
+ 4601 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope);
+ 4602 : os_abort();
+ 4603 : /* LCOV_EXCL_STOP */
+ 4604 : }
+ 4605 : }
+ 4606 499 : }
+ 4607 :
+ 4608 1 : void generate_configuration(const char* path)
+ 4609 : {
+ 4610 : struct snapraid_state state;
+ 4611 : struct snapraid_content* content;
+ 4612 : char esc_buffer[ESC_MAX];
+ 4613 : unsigned l, s;
+ 4614 : tommy_node* j;
+ 4615 :
+ 4616 1 : state_init(&state);
4617 :
- 4618 : /* read the content file */
- 4619 1 : state_read(&state);
+ 4618 : /* mark that we are without a configuration file */
+ 4619 1 : state.no_conf = 1;
4620 :
- 4621 : /* output a dummy configuration file */
- 4622 1 : printf("# Configuration file generated from %s\n", path);
- 4623 1 : printf("\n");
- 4624 1 : printf("# Use this blocksize\n");
- 4625 1 : printf("blocksize %u\n", state.block_size / KIBI);
- 4626 1 : printf("\n");
- 4627 1 : printf("# Use this hashsize\n");
- 4628 1 : printf("hashsize %u\n", BLOCK_HASH_SIZE);
- 4629 1 : printf("\n");
- 4630 7 : for (l = 0; l < state.level; ++l) {
- 4631 6 : printf("# Set the correct path for the %s files\n", lev_name(l));
- 4632 6 : printf("# You had %u of them:\n", state.parity[l].split_mac);
- 4633 30 : for (s = 0; s < state.parity[l].split_mac; ++s) {
- 4634 24 : printf("# %u:\n", s);
- 4635 24 : printf("# PATH:");
- 4636 24 : if (state.parity[l].split_map[s].path[0])
- 4637 24 : printf("%s", state.parity[l].split_map[s].path);
- 4638 : else
- 4639 0 : printf("?");
- 4640 24 : printf("\n");
- 4641 24 : printf("# SIZE:");
- 4642 24 : if (state.parity[l].split_map[s].size != PARITY_SIZE_INVALID)
- 4643 24 : printf("%" PRIu64, state.parity[l].split_map[s].size);
- 4644 : else
- 4645 0 : printf("?");
- 4646 24 : printf("\n");
- 4647 24 : printf("# UUID:");
- 4648 24 : if (state.parity[l].split_map[s].uuid[0])
- 4649 24 : printf("%s", state.parity[l].split_map[s].uuid);
- 4650 : else
- 4651 0 : printf("?");
- 4652 24 : printf("\n");
- 4653 24 : printf("#\n");
- 4654 : }
- 4655 6 : printf("%s ENTER_HERE_THE_PARITY_FILES_COMMA_SEPARATED\n", lev_config_name(l));
- 4656 6 : printf("\n");
- 4657 : }
- 4658 1 : printf("# Add any other content file\n");
- 4659 1 : printf("content %s\n", path);
- 4660 1 : printf("\n");
- 4661 7 : for (j = state.maplist; j; j = j->next) {
- 4662 6 : struct snapraid_map* map = j->data;
- 4663 : struct snapraid_disk* disk;
- 4664 6 : printf("# Set the correct dir for disk '%s'\n", map->name);
- 4665 6 : if (map->uuid[0])
- 4666 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid);
- 4667 6 : disk = find_disk_by_name(&state, map->name);
- 4668 6 : if (disk && disk->filelist) {
- 4669 6 : struct snapraid_file* file = disk->filelist->data;
- 4670 6 : if (file) {
- 4671 6 : printf("# and containing: %s\n", fmt_poll(disk, file->sub, esc_buffer));
- 4672 : }
- 4673 : }
- 4674 6 : printf("data %s ENTER_HERE_THE_DIR\n", map->name);
- 4675 6 : printf("\n");
- 4676 : }
- 4677 :
- 4678 1 : state_done(&state);
- 4679 1 : }
- 4680 :
+ 4621 : /* create the dummy content entry */
+ 4622 1 : content = content_alloc(path, -1);
+ 4623 :
+ 4624 : /* adds the content entry */
+ 4625 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content);
+ 4626 :
+ 4627 : /* read the content file */
+ 4628 1 : state_read(&state);
+ 4629 :
+ 4630 : /* output a dummy configuration file */
+ 4631 1 : printf("# Configuration file generated from %s\n", path);
+ 4632 1 : printf("\n");
+ 4633 1 : printf("# Use this blocksize\n");
+ 4634 1 : printf("blocksize %u\n", state.block_size / KIBI);
+ 4635 1 : printf("\n");
+ 4636 1 : printf("# Use this hashsize\n");
+ 4637 1 : printf("hashsize %u\n", BLOCK_HASH_SIZE);
+ 4638 1 : printf("\n");
+ 4639 7 : for (l = 0; l < state.level; ++l) {
+ 4640 6 : printf("# Set the correct path for the %s files\n", lev_name(l));
+ 4641 6 : printf("# You had %u of them:\n", state.parity[l].split_mac);
+ 4642 30 : for (s = 0; s < state.parity[l].split_mac; ++s) {
+ 4643 24 : printf("# %u:\n", s);
+ 4644 24 : printf("# PATH:");
+ 4645 24 : if (state.parity[l].split_map[s].path[0])
+ 4646 24 : printf("%s", state.parity[l].split_map[s].path);
+ 4647 : else
+ 4648 0 : printf("?");
+ 4649 24 : printf("\n");
+ 4650 24 : printf("# SIZE:");
+ 4651 24 : if (state.parity[l].split_map[s].size != PARITY_SIZE_INVALID)
+ 4652 24 : printf("%" PRIu64, state.parity[l].split_map[s].size);
+ 4653 : else
+ 4654 0 : printf("?");
+ 4655 24 : printf("\n");
+ 4656 24 : printf("# UUID:");
+ 4657 24 : if (state.parity[l].split_map[s].uuid[0])
+ 4658 24 : printf("%s", state.parity[l].split_map[s].uuid);
+ 4659 : else
+ 4660 0 : printf("?");
+ 4661 24 : printf("\n");
+ 4662 24 : printf("#\n");
+ 4663 : }
+ 4664 6 : printf("%s ENTER_HERE_THE_PARITY_FILES_COMMA_SEPARATED\n", lev_config_name(l));
+ 4665 6 : printf("\n");
+ 4666 : }
+ 4667 1 : printf("# Add any other content file\n");
+ 4668 1 : printf("content %s\n", path);
+ 4669 1 : printf("\n");
+ 4670 7 : for (j = state.maplist; j; j = j->next) {
+ 4671 6 : struct snapraid_map* map = j->data;
+ 4672 : struct snapraid_disk* disk;
+ 4673 6 : printf("# Set the correct dir for disk '%s'\n", map->name);
+ 4674 6 : if (map->uuid[0])
+ 4675 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid);
+ 4676 6 : disk = find_disk_by_name(&state, map->name);
+ 4677 6 : if (disk && disk->filelist) {
+ 4678 6 : struct snapraid_file* file = disk->filelist->data;
+ 4679 6 : if (file) {
+ 4680 6 : printf("# and containing: %s\n", fmt_poll(disk, file->sub, esc_buffer));
+ 4681 : }
+ 4682 : }
+ 4683 6 : printf("data %s ENTER_HERE_THE_DIR\n", map->name);
+ 4684 6 : printf("\n");
+ 4685 : }
+ 4686 :
+ 4687 1 : state_done(&state);
+ 4688 1 : }
+ 4689 :
diff --git a/cov/cmdline/status.c.func-sort-c.html b/cov/cmdline/status.c.func-sort-c.html
index e86aad6d..6f1e8aea 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 7976d962..4efc9d69 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 689bae52..4da3101e 100644
--- a/cov/cmdline/status.c.gcov.html
+++ b/cov/cmdline/status.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -395,10 +395,10 @@
333 39808 : scrub_time = info_get_time(info);
334 :
335 39808 : if (info_get_justsynced(info)) {
- 336 20516 : ++unscrubbed_blocks;
+ 336 20520 : ++unscrubbed_blocks;
337 :
338 : /* mark the time as not scrubbed */
- 339 20516 : scrub_time |= TIME_NEW;
+ 339 20520 : scrub_time |= TIME_NEW;
340 : }
341 :
342 39808 : timemap[count++] = scrub_time;
@@ -430,16 +430,16 @@
368 : /* output the info map */
369 9 : i = 0;
370 9 : log_tag("info_count:%u\n", count);
- 371 40 : while (i < count) {
- 372 22 : unsigned j = i + 1;
- 373 39830 : while (j < count && timemap[i] == timemap[j])
- 374 39786 : ++j;
- 375 22 : if ((timemap[i] & TIME_NEW) == 0) {
- 376 8 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i);
+ 371 39 : while (i < count) {
+ 372 21 : unsigned j = i + 1;
+ 373 39829 : while (j < count && timemap[i] == timemap[j])
+ 374 39787 : ++j;
+ 375 21 : if ((timemap[i] & TIME_NEW) == 0) {
+ 376 7 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i);
377 : } else {
378 14 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i);
379 : }
- 380 22 : i = j;
+ 380 21 : i = j;
381 : }
382 :
383 9 : oldest = timemap[0];
@@ -462,9 +462,9 @@
400 630 : step_new = 0;
401 41068 : while (barpos < count && timemap[barpos] <= limit) {
402 39808 : if ((timemap[barpos] & TIME_NEW) != 0)
- 403 20516 : ++step_new;
+ 403 20520 : ++step_new;
404 : else
- 405 19292 : ++step_scrubbed;
+ 405 19288 : ++step_scrubbed;
406 39808 : ++barpos;
407 : }
408 :
@@ -494,20 +494,20 @@
432 9450 : unsigned scrubbed = bar_scrubbed[x];
433 :
434 9450 : if (both > pivot_upper) {
- 435 162 : if (scrubbed > pivot_lower)
- 436 71 : printf("*");
+ 435 159 : if (scrubbed > pivot_lower)
+ 436 63 : printf("*");
437 : else
- 438 91 : printf("o");
- 439 9288 : } else if (both > pivot_lower) {
+ 438 96 : printf("o");
+ 439 9291 : } else if (both > pivot_lower) {
440 21 : if (scrubbed == both)
441 7 : printf("*");
442 : else
443 14 : printf("o");
444 : } else {
- 445 9267 : if (y == GRAPH_ROW - 1)
+ 445 9270 : if (y == GRAPH_ROW - 1)
446 609 : printf("_");
447 : else
- 448 8658 : printf(" ");
+ 448 8661 : printf(" ");
449 : }
450 : }
451 135 : printf("\n");
diff --git a/cov/cmdline/stream.c.func-sort-c.html b/cov/cmdline/stream.c.func-sort-c.html
index 1cce3c59..f28a34b9 100644
--- a/cov/cmdline/stream.c.func-sort-c.html
+++ b/cov/cmdline/stream.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| swrite |
- 20725404 |
+ 20725318 |
| sgetb32 |
- 18667305 |
+ 18667259 |
| sread |
- 12810007 |
+ 12810019 |
| sgetb64 |
- 10849138 |
+ 10849144 |
| sputb32 |
- 9127777 |
+ 9127691 |
| sputb64 |
@@ -85,7 +85,7 @@
| sgetbs |
- 3877064 |
+ 3877077 |
| sputbs |
diff --git a/cov/cmdline/stream.c.func.html b/cov/cmdline/stream.c.func.html
index c096336a..595ba5db 100644
--- a/cov/cmdline/stream.c.func.html
+++ b/cov/cmdline/stream.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -85,11 +85,11 @@
| sgetb32 |
- 18667305 |
+ 18667259 |
| sgetb64 |
- 10849138 |
+ 10849144 |
| sgetble32 |
@@ -97,7 +97,7 @@
| sgetbs |
- 3877064 |
+ 3877077 |
| sgetc_uncached |
@@ -141,7 +141,7 @@
| sputb32 |
- 9127777 |
+ 9127691 |
| sputb64 |
@@ -157,7 +157,7 @@
| sread |
- 12810007 |
+ 12810019 |
| ssync |
@@ -169,7 +169,7 @@
| swrite |
- 20725404 |
+ 20725318 |
diff --git a/cov/cmdline/stream.c.gcov.html b/cov/cmdline/stream.c.gcov.html
index 8a1438fc..64e49810 100644
--- a/cov/cmdline/stream.c.gcov.html
+++ b/cov/cmdline/stream.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -275,29 +275,29 @@
213 :
214 606069 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE);
215 :
- 216 606069 : if (ret < 0) {
+ 216 606067 : if (ret < 0) {
217 : /* LCOV_EXCL_START */
218 : s->state = STREAM_STATE_ERROR;
219 : return EOF;
220 : /* LCOV_EXCL_STOP */
221 : }
- 222 606069 : if (ret == 0) {
+ 222 606067 : if (ret == 0) {
223 1659 : s->state = STREAM_STATE_EOF;
224 1659 : return EOF;
225 : }
226 :
227 : /* update the crc */
- 228 604410 : s->crc_uncached = s->crc;
- 229 604410 : s->crc = crc32c(s->crc, s->buffer, ret);
+ 228 604408 : s->crc_uncached = s->crc;
+ 229 604408 : s->crc = crc32c(s->crc, s->buffer, ret);
230 :
231 : /* update the offset */
- 232 604409 : s->offset_uncached = s->offset;
- 233 604409 : s->offset += ret;
+ 232 604410 : s->offset_uncached = s->offset;
+ 233 604410 : s->offset += ret;
234 :
- 235 604409 : s->pos = s->buffer;
- 236 604409 : s->end = s->buffer + ret;
+ 235 604410 : s->pos = s->buffer;
+ 236 604410 : s->end = s->buffer + ret;
237 :
- 238 604409 : return 0;
+ 238 604410 : return 0;
239 : }
240 :
241 1142 : int sdeplete(STREAM* s, unsigned char* last)
@@ -314,11 +314,11 @@
252 148389 : s->pos = s->end - 4;
253 :
254 : /* insert the last 4 bytes */
- 255 1469855 : while (s->pos < s->end) {
- 256 853323 : last[0] = last[1];
- 257 853323 : last[1] = last[2];
- 258 853323 : last[2] = last[3];
- 259 853323 : last[3] = *s->pos++;
+ 255 1469857 : while (s->pos < s->end) {
+ 256 853325 : last[0] = last[1];
+ 257 853325 : last[1] = last[2];
+ 258 853325 : last[2] = last[3];
+ 259 853325 : last[3] = *s->pos++;
260 : }
261 :
262 : /* fill again the buffer until the end of the file */
@@ -445,35 +445,35 @@
383 8196 : return i - str;
384 : }
385 :
- 386 12810007 : int sread(STREAM* f, void* void_data, unsigned size)
+ 386 12810019 : int sread(STREAM* f, void* void_data, unsigned size)
387 : {
- 388 12810007 : unsigned char* data = void_data;
+ 388 12810019 : unsigned char* data = void_data;
389 :
390 : /* if there is enough space in memory */
- 391 12810007 : if (sptrlookup(f, size)) {
+ 391 12810019 : if (sptrlookup(f, size)) {
392 : /* optimized version with all the data in memory */
- 393 12783678 : unsigned char* pos = sptrget(f);
+ 393 12783673 : unsigned char* pos = sptrget(f);
394 :
395 : /* copy it */
- 396 217717015 : while (size--)
- 397 192149659 : *data++ = *pos++;
+ 396 217716910 : while (size--)
+ 397 192149564 : *data++ = *pos++;
398 :
- 399 12783678 : sptrset(f, pos);
+ 399 12783673 : sptrset(f, pos);
400 : } else {
401 : /* standard version using sgetc() */
- 402 1378240 : while (size--) {
- 403 1325582 : int c = sgetc(f);
- 404 1325582 : if (c == EOF) {
+ 402 1378641 : while (size--) {
+ 403 1325949 : int c = sgetc(f);
+ 404 1325949 : if (c == EOF) {
405 : /* LCOV_EXCL_START */
406 : return -1;
407 : /* LCOV_EXCL_STOP */
408 : }
409 :
- 410 1325582 : *data++ = c;
+ 410 1325949 : *data++ = c;
411 : }
412 : }
413 :
- 414 12810007 : return 0;
+ 414 12810019 : return 0;
415 : }
416 :
417 5448 : int sgetline(STREAM* f, char* str, int size)
@@ -586,76 +586,76 @@
524 : }
525 : }
526 :
- 527 18667305 : int sgetb32(STREAM* f, uint32_t* value)
+ 527 18667259 : int sgetb32(STREAM* f, uint32_t* value)
528 : {
529 : uint32_t v;
530 : unsigned char b;
531 : unsigned char s;
532 : int c;
533 :
- 534 18667305 : v = 0;
- 535 18667305 : s = 0;
+ 534 18667259 : v = 0;
+ 535 18667259 : s = 0;
536 : loop:
- 537 36513909 : c = sgetc(f);
- 538 36513909 : if (c == EOF) {
+ 537 35261143 : c = sgetc(f);
+ 538 35261143 : if (c == EOF) {
539 : /* LCOV_EXCL_START */
540 : return -1;
541 : /* LCOV_EXCL_STOP */
542 : }
543 :
- 544 36513909 : b = (unsigned char)c;
- 545 36513909 : if ((b & 0x80) == 0) {
- 546 17846604 : v |= (uint32_t)b << s;
- 547 17846604 : s += 7;
- 548 17846604 : if (s >= 32) {
+ 544 35261143 : b = (unsigned char)c;
+ 545 35261143 : if ((b & 0x80) == 0) {
+ 546 16593884 : v |= (uint32_t)b << s;
+ 547 16593884 : s += 7;
+ 548 16593884 : if (s >= 32) {
549 : /* LCOV_EXCL_START */
550 : return -1;
551 : /* LCOV_EXCL_STOP */
552 : }
- 553 17846604 : goto loop;
+ 553 16593884 : goto loop;
554 : }
555 :
- 556 18667305 : v |= (uint32_t)(b & 0x7f) << s;
+ 556 18667259 : v |= (uint32_t)(b & 0x7f) << s;
557 :
- 558 18667305 : *value = v;
+ 558 18667259 : *value = v;
559 :
- 560 18667305 : return 0;
+ 560 18667259 : return 0;
561 : }
562 :
- 563 10849138 : int sgetb64(STREAM* f, uint64_t* value)
+ 563 10849144 : int sgetb64(STREAM* f, uint64_t* value)
564 : {
565 : uint64_t v;
566 : unsigned char b;
567 : unsigned char s;
568 : int c;
569 :
- 570 10849138 : v = 0;
- 571 10849138 : s = 0;
+ 570 10849144 : v = 0;
+ 571 10849144 : s = 0;
572 : loop:
- 573 39665269 : c = sgetc(f);
- 574 39665269 : if (c == EOF) {
+ 573 39665284 : c = sgetc(f);
+ 574 39665284 : if (c == EOF) {
575 : /* LCOV_EXCL_START */
576 : return -1;
577 : /* LCOV_EXCL_STOP */
578 : }
579 :
- 580 39665269 : b = (unsigned char)c;
- 581 39665269 : if ((b & 0x80) == 0) {
- 582 28816131 : v |= (uint64_t)b << s;
- 583 28816131 : s += 7;
- 584 28816131 : if (s >= 64) {
+ 580 39665284 : b = (unsigned char)c;
+ 581 39665284 : if ((b & 0x80) == 0) {
+ 582 28816140 : v |= (uint64_t)b << s;
+ 583 28816140 : s += 7;
+ 584 28816140 : if (s >= 64) {
585 : /* LCOV_EXCL_START */
586 : return -1;
587 : /* LCOV_EXCL_STOP */
588 : }
- 589 28816131 : goto loop;
+ 589 28816140 : goto loop;
590 : }
591 :
- 592 10849138 : v |= (uint64_t)(b & 0x7f) << s;
+ 592 10849144 : v |= (uint64_t)(b & 0x7f) << s;
593 :
- 594 10849138 : *value = v;
+ 594 10849144 : *value = v;
595 :
- 596 10849138 : return 0;
+ 596 10849144 : return 0;
597 : }
598 :
599 381 : int sgetble32(STREAM* f, uint32_t* value)
@@ -673,35 +673,35 @@
611 381 : return 0;
612 : }
613 :
- 614 3877064 : int sgetbs(STREAM* f, char* str, int size)
+ 614 3877077 : int sgetbs(STREAM* f, char* str, int size)
615 : {
616 : uint32_t len;
617 :
- 618 3877064 : if (sgetb32(f, &len) < 0) {
+ 618 3877077 : if (sgetb32(f, &len) < 0) {
619 : /* LCOV_EXCL_START */
620 : return -1;
621 : /* LCOV_EXCL_STOP */
622 : }
623 :
- 624 3877064 : if (len + 1 > (uint32_t)size) {
+ 624 3877077 : if (len + 1 > (uint32_t)size) {
625 : /* LCOV_EXCL_START */
626 : return -1;
627 : /* LCOV_EXCL_STOP */
628 : }
629 :
- 630 3877064 : str[len] = 0;
+ 630 3877076 : str[len] = 0;
631 :
- 632 3877064 : return sread(f, str, (int)len);
+ 632 3877076 : return sread(f, str, (int)len);
633 : }
634 :
- 635 20725404 : int swrite(const void* void_data, unsigned size, STREAM* f)
+ 635 20725318 : int swrite(const void* void_data, unsigned size, STREAM* f)
636 : {
- 637 20725404 : const unsigned char* data = void_data;
+ 637 20725318 : const unsigned char* data = void_data;
638 :
639 : /* if there is enough space in memory */
- 640 20725404 : if (sptrlookup(f, size)) {
+ 640 20725318 : if (sptrlookup(f, size)) {
641 : /* optimized version with all the data in memory */
- 642 20719227 : unsigned char* pos = sptrget(f);
+ 642 20719138 : unsigned char* pos = sptrget(f);
643 :
644 : /**
645 : * Update the crc *before* writing the data in the buffer
@@ -710,17 +710,17 @@
648 : * to be able to detect memory errors on the buffer,
649 : * happening before we write it on the file.
650 : */
- 651 20719227 : f->crc_stream = crc32c_plain(f->crc_stream, data, size);
+ 651 20719138 : f->crc_stream = crc32c_plain(f->crc_stream, data, size);
652 :
653 : /* copy it */
- 654 173052917 : while (size--)
- 655 131614463 : *pos++ = *data++;
+ 654 172416299 : while (size--)
+ 655 130978023 : *pos++ = *data++;
656 :
- 657 20719227 : sptrset(f, pos);
+ 657 20719138 : sptrset(f, pos);
658 : } else {
659 : /* standard version using sputc() */
- 660 201663 : while (size--) {
- 661 189309 : if (sputc(*data++, f) != 0) {
+ 660 201861 : while (size--) {
+ 661 189501 : if (sputc(*data++, f) != 0) {
662 : /* LCOV_EXCL_START */
663 : return -1;
664 : /* LCOV_EXCL_STOP */
@@ -728,28 +728,28 @@
666 : }
667 : }
668 :
- 669 20725404 : return 0;
+ 669 20725318 : return 0;
670 : }
671 :
- 672 9127777 : int sputb32(uint32_t value, STREAM* s)
+ 672 9127691 : int sputb32(uint32_t value, STREAM* s)
673 : {
674 : unsigned char b;
675 : unsigned char buf[16];
676 : unsigned i;
677 :
- 678 9127777 : i = 0;
+ 678 9127691 : i = 0;
679 : loop:
- 680 17895036 : b = value & 0x7f;
- 681 17895036 : value >>= 7;
+ 680 17258788 : b = value & 0x7f;
+ 681 17258788 : value >>= 7;
682 :
- 683 17895036 : if (value) {
- 684 8767259 : buf[i++] = b;
- 685 8767259 : goto loop;
+ 683 17258788 : if (value) {
+ 684 8131097 : buf[i++] = b;
+ 685 8131097 : goto loop;
686 : }
687 :
- 688 9127777 : buf[i++] = b | 0x80;
+ 688 9127691 : buf[i++] = b | 0x80;
689 :
- 690 9127777 : return swrite(buf, i, s);
+ 690 9127691 : return swrite(buf, i, s);
691 : }
692 :
693 5317120 : int sputb64(uint64_t value, STREAM* s)
diff --git a/cov/cmdline/stream.h.func-sort-c.html b/cov/cmdline/stream.h.func-sort-c.html
index 5cdb940a..175f0770 100644
--- a/cov/cmdline/stream.h.func-sort-c.html
+++ b/cov/cmdline/stream.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,27 +61,27 @@
| sgetc |
- 85137242 |
+ 83884881 |
| sptrlookup |
- 33540859 |
+ 33540785 |
| sptrset |
- 33502905 |
+ 33502811 |
| sptrget |
- 33502905 |
+ 33502811 |
| sputc |
- 3808426 |
+ 3808662 |
| serror |
- 3635550 |
+ 3635536 |
| sungetc |
diff --git a/cov/cmdline/stream.h.func.html b/cov/cmdline/stream.h.func.html
index 73c97b0d..93a566f5 100644
--- a/cov/cmdline/stream.h.func.html
+++ b/cov/cmdline/stream.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,7 +65,7 @@
| serror |
- 3635550 |
+ 3635536 |
| serrorfile |
@@ -73,7 +73,7 @@
| sgetc |
- 85137242 |
+ 83884881 |
| sgeteol |
@@ -85,19 +85,19 @@
| sptrget |
- 33502905 |
+ 33502811 |
| sptrlookup |
- 33540859 |
+ 33540785 |
| sptrset |
- 33502905 |
+ 33502811 |
| sputc |
- 3808426 |
+ 3808662 |
| sungetc |
diff --git a/cov/cmdline/stream.h.gcov.html b/cov/cmdline/stream.h.gcov.html
index 0d7947f7..9d4d3fb2 100644
--- a/cov/cmdline/stream.h.gcov.html
+++ b/cov/cmdline/stream.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -221,33 +221,33 @@
159 : /**
160 : * Check if the buffer has enough data loaded.
161 : */
- 162 33540859 : static inline int sptrlookup(STREAM* s, int size)
+ 162 33540785 : static inline int sptrlookup(STREAM* s, int size)
163 : {
- 164 33540859 : return s->pos + size <= s->end;
+ 164 33540785 : return s->pos + size <= s->end;
165 : }
166 :
167 : /**
168 : * Get the current stream ptr.
169 : */
- 170 33502905 : static inline unsigned char* sptrget(STREAM* s)
+ 170 33502811 : static inline unsigned char* sptrget(STREAM* s)
171 : {
- 172 33502905 : return s->pos;
+ 172 33502811 : return s->pos;
173 : }
174 :
175 : /**
176 : * Set the current stream ptr.
177 : */
- 178 33502905 : static inline void sptrset(STREAM* s, unsigned char* ptr)
+ 178 33502811 : static inline void sptrset(STREAM* s, unsigned char* ptr)
179 : {
- 180 33502905 : s->pos = ptr;
- 181 33502905 : }
+ 180 33502811 : s->pos = ptr;
+ 181 33502811 : }
182 :
183 : /**
184 : * Check the error status. Like ferror().
185 : */
- 186 3635550 : static inline int serror(STREAM* s)
+ 186 3635536 : static inline int serror(STREAM* s)
187 : {
- 188 3635550 : return s->state == STREAM_STATE_ERROR;
+ 188 3635536 : return s->state == STREAM_STATE_ERROR;
189 : }
190 :
191 : /**
@@ -291,11 +291,11 @@
229 : /**
230 : * Read a char. Like fgetc().
231 : */
- 232 85137242 : static inline int sgetc(STREAM* s)
+ 232 83884881 : static inline int sgetc(STREAM* s)
233 : {
- 234 85137242 : if (tommy_unlikely(s->pos == s->end))
+ 234 83884881 : if (tommy_unlikely(s->pos == s->end))
235 298863 : return sgetc_uncached(s);
- 236 84838379 : return *s->pos++;
+ 236 83586018 : return *s->pos++;
237 : }
238 :
239 : /**
@@ -407,9 +407,9 @@
345 : * Write a char. Like fputc().
346 : * Return 0 on success or -1 on error.
347 : */
- 348 3808426 : static inline int sputc(int c, STREAM* s)
+ 348 3808662 : static inline int sputc(int c, STREAM* s)
349 : {
- 350 3808426 : if (s->pos == s->end) {
+ 350 3808662 : if (s->pos == s->end) {
351 38580 : if (sflush(s) != 0)
352 0 : return -1;
353 : }
@@ -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 3808426 : s->crc_stream = crc32c_plain_char(s->crc_stream, c);
+ 362 3808662 : s->crc_stream = crc32c_plain_char(s->crc_stream, c);
363 :
- 364 3808426 : *s->pos++ = c;
+ 364 3808662 : *s->pos++ = c;
365 :
- 366 3808426 : return 0;
+ 366 3808662 : 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 cf4f03cd..566856c4 100644
--- a/cov/cmdline/support.c.func-sort-c.html
+++ b/cov/cmdline/support.c.func-sort-c.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,131 +60,135 @@
Hit count  |
- | thread_mutex_unlock |
- 80858701 |
+ thread_mutex_unlock |
+ 80868352 |
- | thread_mutex_lock |
- 80857668 |
+ thread_mutex_lock |
+ 80853862 |
- | pathcmp |
- 51890261 |
+ pathcmp |
+ 51889301 |
- | pathprint |
- 51564160 |
+ pathprint |
+ 51562646 |
| unlock_memory |
- 20173887 |
+ 20173439 |
| lock_memory |
- 20173887 |
+ 20173439 |
- | malloc_counter_inc |
- 20173411 |
+ malloc_counter_inc |
+ 20172963 |
- | malloc_nofail |
- 14363921 |
+ malloc_nofail |
+ 14363716 |
- | advise_read |
- 8903631 |
+ advise_read |
+ 8897480 |
- | pathcpy |
- 7892123 |
+ pathcpy |
+ 7884434 |
- | strdup_nofail |
- 5799401 |
-
-
- | lock_msg |
- 3887334 |
+ strdup_nofail |
+ 5799158 |
| unlock_msg |
- 3887334 |
+ 3895151 |
+
+
+ | lock_msg |
+ 3895147 |
| log_tag |
- 2907727 |
+ 2915010 |
- | advise_flags |
- 2494965 |
+ advise_flags |
+ 2494636 |
- | advise_init |
- 2494910 |
+ advise_init |
+ 2494292 |
| esc_tag |
- 2428312 |
+ 2435456 |
- | advise_open |
- 2416366 |
+ advise_open |
+ 2412565 |
- | thread_cond_wait |
- 1037153 |
+ thread_cond_wait |
+ 1125039 |
- | advise_write |
- 900358 |
+ advise_write |
+ 900744 |
- | mkancestor |
- 793073 |
+ mkancestor |
+ 793100 |
| log_error |
- 536048 |
+ 536168 |
| esc_shell_multi |
- 355914 |
+ 356152 |
| msg_info |
- 295689 |
+ 295927 |
- | thread_cond_broadcast |
- 255503 |
+ thread_cond_broadcast |
+ 255615 |
- | thread_cond_broadcast_and_unlock |
- 255313 |
+ thread_cond_broadcast_and_unlock |
+ 255425 |
| msg_verbose |
- 126943 |
+ 127041 |
- | fmtime |
- 119580 |
+ fmtime |
+ 119636 |
- | thread_cond_signal |
- 85887 |
+ thread_cond_signal |
+ 87081 |
- | thread_cond_signal_and_unlock |
- 85887 |
+ thread_cond_signal_and_unlock |
+ 87081 |
- | pathexport |
+ pathexport |
17589 |
- | pathimport |
+ lmtime |
+ 17000 |
+
+
+ | pathimport |
16572 |
@@ -192,11 +196,11 @@
| 11259 |
- | calloc_nofail |
+ calloc_nofail |
10089 |
- | pathslash |
+ pathslash |
7705 |
@@ -204,27 +208,27 @@
| 4449 |
- | thread_mutex_init |
+ thread_mutex_init |
2284 |
- | thread_create |
+ thread_create |
2200 |
- | thread_join |
+ thread_join |
2200 |
- | thread_mutex_destroy |
+ thread_mutex_destroy |
2082 |
| msg_bar |
- 1958 |
+ 2082 |
- | strsplit |
+ strsplit |
1472 |
@@ -236,27 +240,27 @@
| 809 |
- | pathcatc |
+ pathcatc |
788 |
-
- | msg_flush |
- 627 |
-
| msg_status |
- 625 |
+ 622 |
- | malloc_counter_get |
+ msg_flush |
+ 573 |
+
+
+ | malloc_counter_get |
476 |
- | thread_cond_init |
+ thread_cond_init |
380 |
- | thread_cond_destroy |
+ thread_cond_destroy |
380 |
@@ -264,7 +268,7 @@
| 299 |
- | pathcat |
+ pathcat |
267 |
@@ -272,39 +276,39 @@
| 264 |
- | printc |
- 106 |
+ pathcut |
+ 100 |
- | pathcut |
- 100 |
+ printc |
+ 64 |
| printl |
52 |
- | smartctl_attribute |
+ smartctl_attribute |
43 |
-
- | printr |
- 34 |
-
| printp |
18 |
- | smartctl_flush |
+ printr |
+ 16 |
+
+
+ | smartctl_flush |
5 |
- | strpolish |
+ strpolish |
0 |
- | smatch |
+ smatch |
0 |
diff --git a/cov/cmdline/support.c.func.html b/cov/cmdline/support.c.func.html
index 883dd715..117789b2 100644
--- a/cov/cmdline/support.c.func.html
+++ b/cov/cmdline/support.c.func.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -60,40 +60,44 @@
Hit count  |
- | advise_flags |
- 2494965 |
+ advise_flags |
+ 2494636 |
- | advise_init |
- 2494910 |
+ advise_init |
+ 2494292 |
- | advise_open |
- 2416366 |
+ advise_open |
+ 2412565 |
- | advise_read |
- 8903631 |
+ advise_read |
+ 8897480 |
- | advise_write |
- 900358 |
+ advise_write |
+ 900744 |
- | calloc_nofail |
+ calloc_nofail |
10089 |
| esc_shell_multi |
- 355914 |
+ 356152 |
| esc_tag |
- 2428312 |
+ 2435456 |
- | fmtime |
- 119580 |
+ fmtime |
+ 119636 |
+
+
+ | lmtime |
+ 17000 |
| lock_done |
@@ -105,15 +109,15 @@
| lock_memory |
- 20173887 |
+ 20173439 |
| lock_msg |
- 3887334 |
+ 3895147 |
| log_error |
- 536048 |
+ 536168 |
| log_expected |
@@ -129,35 +133,35 @@
| log_tag |
- 2907727 |
+ 2915010 |
- | malloc_counter_get |
+ malloc_counter_get |
476 |
- | malloc_counter_inc |
- 20173411 |
+ malloc_counter_inc |
+ 20172963 |
- | malloc_nofail |
- 14363921 |
+ malloc_nofail |
+ 14363716 |
- | mkancestor |
- 793073 |
+ mkancestor |
+ 793100 |
| msg_bar |
- 1958 |
+ 2082 |
| msg_flush |
- 627 |
+ 573 |
| msg_info |
- 295689 |
+ 295927 |
| msg_progress |
@@ -165,51 +169,51 @@
| msg_status |
- 625 |
+ 622 |
| msg_verbose |
- 126943 |
+ 127041 |
- | pathcat |
+ pathcat |
267 |
- | pathcatc |
+ pathcatc |
788 |
- | pathcmp |
- 51890261 |
+ pathcmp |
+ 51889301 |
- | pathcpy |
- 7892123 |
+ pathcpy |
+ 7884434 |
- | pathcut |
+ pathcut |
100 |
- | pathexport |
+ pathexport |
17589 |
- | pathimport |
+ pathimport |
16572 |
- | pathprint |
- 51564160 |
+ pathprint |
+ 51562646 |
- | pathslash |
+ pathslash |
7705 |
| printc |
- 106 |
+ 64 |
| printl |
@@ -221,91 +225,91 @@
| printr |
- 34 |
+ 16 |
- | smartctl_attribute |
+ smartctl_attribute |
43 |
- | smartctl_flush |
+ smartctl_flush |
5 |
- | smatch |
+ smatch |
0 |
- | strdup_nofail |
- 5799401 |
+ strdup_nofail |
+ 5799158 |
- | strpolish |
+ strpolish |
0 |
- | strsplit |
+ strsplit |
1472 |
- | thread_cond_broadcast |
- 255503 |
+ thread_cond_broadcast |
+ 255615 |
- | thread_cond_broadcast_and_unlock |
- 255313 |
+ thread_cond_broadcast_and_unlock |
+ 255425 |
- | thread_cond_destroy |
+ thread_cond_destroy |
380 |
- | thread_cond_init |
+ thread_cond_init |
380 |
- | thread_cond_signal |
- 85887 |
+ thread_cond_signal |
+ 87081 |
- | thread_cond_signal_and_unlock |
- 85887 |
+ thread_cond_signal_and_unlock |
+ 87081 |
- | thread_cond_wait |
- 1037153 |
+ thread_cond_wait |
+ 1125039 |
- | thread_create |
+ thread_create |
2200 |
- | thread_join |
+ thread_join |
2200 |
- | thread_mutex_destroy |
+ thread_mutex_destroy |
2082 |
- | thread_mutex_init |
+ thread_mutex_init |
2284 |
- | thread_mutex_lock |
- 80857668 |
+ thread_mutex_lock |
+ 80853862 |
- | thread_mutex_unlock |
- 80858701 |
+ thread_mutex_unlock |
+ 80868352 |
| unlock_memory |
- 20173887 |
+ 20173439 |
| unlock_msg |
- 3887334 |
+ 3895151 |
diff --git a/cov/cmdline/support.c.gcov.html b/cov/cmdline/support.c.gcov.html
index d72968c8..bfdab4e2 100644
--- a/cov/cmdline/support.c.gcov.html
+++ b/cov/cmdline/support.c.gcov.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
 |
@@ -92,33 +92,33 @@
30 : static pthread_mutex_t memory_lock;
31 : #endif
32 :
- 33 3887334 : void lock_msg(void)
+ 33 3895147 : void lock_msg(void)
34 : {
35 : #if HAVE_PTHREAD
- 36 3887334 : thread_mutex_lock(&msg_lock);
+ 36 3895147 : thread_mutex_lock(&msg_lock);
37 : #endif
- 38 3887334 : }
+ 38 3895151 : }
39 :
- 40 3887334 : void unlock_msg(void)
+ 40 3895151 : void unlock_msg(void)
41 : {
42 : #if HAVE_PTHREAD
- 43 3887334 : thread_mutex_unlock(&msg_lock);
+ 43 3895151 : thread_mutex_unlock(&msg_lock);
44 : #endif
- 45 3887334 : }
+ 45 3895151 : }
46 :
- 47 20173887 : void lock_memory(void)
+ 47 20173439 : void lock_memory(void)
48 : {
49 : #if HAVE_PTHREAD
- 50 20173887 : thread_mutex_lock(&memory_lock);
+ 50 20173439 : thread_mutex_lock(&memory_lock);
51 : #endif
- 52 20173887 : }
+ 52 20173439 : }
53 :
- 54 20173887 : void unlock_memory(void)
+ 54 20173439 : void unlock_memory(void)
55 : {
56 : #if HAVE_PTHREAD
- 57 20173887 : thread_mutex_unlock(&memory_lock);
+ 57 20173439 : thread_mutex_unlock(&memory_lock);
58 : #endif
- 59 20173887 : }
+ 59 20173439 : }
60 :
61 299 : void lock_init(void)
62 : {
@@ -176,18 +176,18 @@
114 809 : unlock_msg();
115 809 : }
116 :
- 117 536048 : void log_error(const char* format, ...)
+ 117 536168 : void log_error(const char* format, ...)
118 : {
119 : va_list ap;
120 :
- 121 536048 : lock_msg();
+ 121 536168 : lock_msg();
122 :
- 123 536048 : if (stdlog) {
- 124 534168 : va_start(ap, format);
- 125 534168 : fprintf(stdlog, "msg:error: ");
- 126 534168 : vfprintf(stdlog, format, ap);
- 127 534168 : fflush(stdlog);
- 128 534168 : va_end(ap);
+ 123 536168 : if (stdlog) {
+ 124 534288 : va_start(ap, format);
+ 125 534288 : fprintf(stdlog, "msg:error: ");
+ 126 534288 : vfprintf(stdlog, format, ap);
+ 127 534288 : fflush(stdlog);
+ 128 534288 : va_end(ap);
129 : } else {
130 1880 : va_start(ap, format);
131 1880 : vfprintf(stderr, format, ap);
@@ -195,8 +195,8 @@
133 1880 : va_end(ap);
134 : }
135 :
- 136 536048 : unlock_msg();
- 137 536048 : }
+ 136 536168 : unlock_msg();
+ 137 536168 : }
138 :
139 11259 : void log_expected(const char* format, ...)
140 : {
@@ -215,22 +215,22 @@
153 11259 : unlock_msg();
154 11259 : }
155 :
- 156 2907727 : void log_tag(const char* format, ...)
+ 156 2915010 : void log_tag(const char* format, ...)
157 : {
158 : va_list ap;
159 :
- 160 2907727 : lock_msg();
+ 160 2915010 : lock_msg();
161 :
- 162 2907727 : if (stdlog) {
- 163 2571717 : va_start(ap, format);
- 164 2571717 : vfprintf(stdlog, format, ap);
+ 162 2915018 : if (stdlog) {
+ 163 2573287 : va_start(ap, format);
+ 164 2573287 : vfprintf(stdlog, format, ap);
165 : /* here we intentionally don't flush */
166 : /* to make the output faster */
- 167 2571717 : va_end(ap);
+ 167 2573287 : va_end(ap);
168 : }
169 :
- 170 2907727 : unlock_msg();
- 171 2907727 : }
+ 170 2915018 : unlock_msg();
+ 171 2915018 : }
172 :
173 1200 : void log_flush(void)
174 : {
@@ -244,11 +244,11 @@
182 1200 : unlock_msg();
183 1200 : }
184 :
- 185 625 : void msg_status(const char* format, ...)
+ 185 622 : void msg_status(const char* format, ...)
186 : {
187 : va_list ap;
188 :
- 189 625 : lock_msg();
+ 189 622 : lock_msg();
190 :
191 625 : if (stdlog) {
192 275 : va_start(ap, format);
@@ -268,24 +268,24 @@
206 625 : unlock_msg();
207 625 : }
208 :
- 209 295689 : void msg_info(const char* format, ...)
+ 209 295927 : void msg_info(const char* format, ...)
210 : {
211 : va_list ap;
212 :
- 213 295689 : lock_msg();
+ 213 295927 : lock_msg();
214 :
215 : /* don't output in stdlog as these messages */
216 : /* are always paired with a msg_tag() call */
217 :
- 218 295689 : if (msg_level >= MSG_INFO) {
- 219 28811 : va_start(ap, format);
- 220 28811 : vfprintf(stdout, format, ap);
- 221 28811 : fflush(stdout);
- 222 28811 : va_end(ap);
+ 218 295927 : if (msg_level >= MSG_INFO) {
+ 219 28853 : va_start(ap, format);
+ 220 28853 : vfprintf(stdout, format, ap);
+ 221 28853 : fflush(stdout);
+ 222 28853 : va_end(ap);
223 : }
224 :
- 225 295689 : unlock_msg();
- 226 295689 : }
+ 225 295927 : unlock_msg();
+ 226 295927 : }
227 :
228 4449 : void msg_progress(const char* format, ...)
229 : {
@@ -311,89 +311,89 @@
249 4449 : unlock_msg();
250 4449 : }
251 :
- 252 1958 : void msg_bar(const char* format, ...)
+ 252 2082 : void msg_bar(const char* format, ...)
253 : {
254 : va_list ap;
255 :
- 256 1958 : lock_msg();
+ 256 2082 : lock_msg();
257 :
258 : /* don't output in stdlog as these messages */
259 : /* are intended for screen only */
260 : /* also don't flush stdout as they are intended to be partial messages */
261 :
- 262 1958 : if (msg_level >= MSG_BAR) {
+ 262 2082 : if (msg_level >= MSG_BAR) {
263 0 : va_start(ap, format);
264 0 : vfprintf(stdout, format, ap);
265 0 : va_end(ap);
266 : }
267 :
- 268 1958 : unlock_msg();
- 269 1958 : }
+ 268 2082 : unlock_msg();
+ 269 2082 : }
270 :
- 271 126943 : void msg_verbose(const char* format, ...)
+ 271 127041 : void msg_verbose(const char* format, ...)
272 : {
273 : va_list ap;
274 :
- 275 126943 : lock_msg();
+ 275 127041 : lock_msg();
276 :
- 277 126943 : if (stdlog) {
- 278 125077 : va_start(ap, format);
- 279 125077 : fprintf(stdlog, "msg:verbose: ");
- 280 125077 : vfprintf(stdlog, format, ap);
- 281 125077 : fflush(stdlog);
- 282 125077 : va_end(ap);
+ 277 127041 : if (stdlog) {
+ 278 125175 : va_start(ap, format);
+ 279 125175 : fprintf(stdlog, "msg:verbose: ");
+ 280 125175 : vfprintf(stdlog, format, ap);
+ 281 125175 : fflush(stdlog);
+ 282 125175 : va_end(ap);
283 : }
284 :
- 285 126943 : if (msg_level >= MSG_VERBOSE) {
+ 285 127041 : if (msg_level >= MSG_VERBOSE) {
286 91 : va_start(ap, format);
287 91 : vfprintf(stdout, format, ap);
288 91 : fflush(stdout);
289 91 : va_end(ap);
290 : }
291 :
- 292 126943 : unlock_msg();
- 293 126943 : }
+ 292 127041 : unlock_msg();
+ 293 127041 : }
294 :
- 295 627 : void msg_flush(void)
+ 295 573 : void msg_flush(void)
296 : {
- 297 627 : lock_msg();
+ 297 573 : lock_msg();
298 :
- 299 627 : fflush(stdout);
- 300 627 : fflush(stderr);
+ 299 573 : fflush(stdout);
+ 300 573 : fflush(stderr);
301 :
- 302 627 : unlock_msg();
- 303 627 : }
+ 302 573 : unlock_msg();
+ 303 573 : }
304 :
- 305 106 : void printc(char c, size_t pad)
+ 305 64 : void printc(char c, size_t pad)
306 : {
- 307 304 : while (pad) {
+ 307 180 : while (pad) {
308 : /* group writes in long pieces */
309 : char buf[128];
- 310 92 : size_t len = pad;
+ 310 52 : size_t len = pad;
311 :
- 312 92 : if (len >= sizeof(buf))
+ 312 52 : if (len >= sizeof(buf))
313 0 : len = sizeof(buf) - 1;
314 :
- 315 92 : memset(buf, c, len);
- 316 92 : buf[len] = 0;
+ 315 52 : memset(buf, c, len);
+ 316 52 : buf[len] = 0;
317 :
- 318 92 : fputs(buf, stdout);
+ 318 52 : fputs(buf, stdout);
319 :
- 320 92 : pad -= len;
+ 320 52 : pad -= len;
321 : }
- 322 106 : }
+ 322 64 : }
323 :
- 324 34 : void printr(const char* str, size_t pad)
+ 324 16 : void printr(const char* str, size_t pad)
325 : {
326 : size_t len;
327 :
- 328 34 : len = strlen(str);
+ 328 16 : len = strlen(str);
329 :
- 330 34 : if (len < pad)
- 331 34 : printc(' ', pad - len);
+ 330 16 : if (len < pad)
+ 331 16 : printc(' ', pad - len);
332 :
- 333 34 : fputs(str, stdout);
- 334 34 : }
+ 333 16 : fputs(str, stdout);
+ 334 16 : }
335 :
336 52 : void printl(const char* str, size_t pad)
337 : {
@@ -451,17 +451,17 @@
389 : *p++ = to; \
390 : break
391 :
- 392 2428312 : const char* esc_tag(const char* str, char* buffer)
+ 392 2435456 : const char* esc_tag(const char* str, char* buffer)
393 : {
- 394 2428312 : char* begin = buffer;
- 395 2428312 : char* end = begin + ESC_MAX;
- 396 2428312 : char* p = begin;
+ 394 2435456 : char* begin = buffer;
+ 395 2435456 : char* end = begin + ESC_MAX;
+ 396 2435456 : char* p = begin;
397 :
398 : /* copy string with escaping */
- 399 36387237 : while (*str) {
- 400 31530613 : char c = *str;
+ 399 36481551 : while (*str) {
+ 400 31610639 : char c = *str;
401 :
- 402 31530613 : switch (c) {
+ 402 31610639 : switch (c) {
403 :
404 0 : ESCAPE('\n', '\\', 'n');
405 0 : ESCAPE('\r', '\\', 'r');
@@ -469,21 +469,21 @@
407 0 : ESCAPE('\\', '\\', '\\');
408 :
409 : default:
- 410 31530613 : if (p == end)
+ 410 31610639 : if (p == end)
411 0 : goto bail;
- 412 31530613 : *p++ = c;
- 413 31530613 : break;
+ 412 31610639 : *p++ = c;
+ 413 31610639 : break;
414 : }
415 :
- 416 31530613 : ++str;
+ 416 31610639 : ++str;
417 : }
418 :
419 : /* put final 0 */
- 420 2428312 : if (p == end)
+ 420 2435456 : if (p == end)
421 0 : goto bail;
- 422 2428312 : *p = 0;
+ 422 2435456 : *p = 0;
423 :
- 424 4856624 : return begin;
+ 424 4870912 : return begin;
425 :
426 : bail:
427 : /* LCOV_EXCL_START */
@@ -492,11 +492,11 @@
430 : /* LCOV_EXCL_STOP */
431 : }
432 :
- 433 355914 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer)
+ 433 356152 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer)
434 : {
- 435 355914 : char* begin = buffer;
- 436 355914 : char* end = begin + ESC_MAX;
- 437 355914 : char* p = begin;
+ 435 356152 : char* begin = buffer;
+ 436 356152 : char* end = begin + ESC_MAX;
+ 437 356152 : char* p = begin;
438 : unsigned str_mac;
439 : const char* str;
440 :
@@ -517,24 +517,24 @@
455 : #endif
456 :
457 : /* copy string with escaping */
- 458 355914 : str_mac = 0;
- 459 355914 : str = str_map[str_mac];
+ 458 356152 : str_mac = 0;
+ 459 356152 : str = str_map[str_mac];
460 : while (1) {
461 : /* get the next char */
- 462 5122618 : char c = *str;
+ 462 5124343 : char c = *str;
463 :
464 : /* if one string is finished, go to the next */
- 465 10281326 : while (c == 0 && str_mac + 1 < str_max) {
+ 465 10284776 : while (c == 0 && str_mac + 1 < str_max) {
466 36090 : ++str_mac;
467 36090 : str = str_map[str_mac];
468 36090 : c = *str;
469 : }
470 :
471 : /* if we read all the strings, stop */
- 472 5122618 : if (!c)
- 473 355914 : break;
+ 472 5124343 : if (!c)
+ 473 356152 : break;
474 :
- 475 4766704 : switch (c) {
+ 475 4768191 : switch (c) {
476 : #ifdef _WIN32
477 : /*
478 : * Windows shell escape
@@ -589,1144 +589,1193 @@
527 : *p++ = c;
528 : }
529 : break;
- 530 : default :
- 531 : /* unquoted */
- 532 : if (p == end)
- 533 : goto bail;
- 534 : *p++ = c;
- 535 : break;
- 536 : #else
- 537 : case 'a' ... 'z' :
- 538 : case 'A' ... 'Z' :
- 539 : case '0' ... '9' :
- 540 : case ',' :
- 541 : case '.' :
- 542 : case '_' :
- 543 : case '+' :
- 544 : case ':' :
- 545 : case '@' :
- 546 : case '%' :
- 547 : case '/' :
- 548 : case '-' :
- 549 : /* safe chars for all shells, unquoted */
- 550 4687726 : if (p == end)
- 551 0 : goto bail;
- 552 4687726 : *p++ = c;
- 553 4687726 : break;
- 554 : default :
- 555 : /* all the others are quoted with \ */
- 556 78978 : if (p == end)
+ 530 : #else
+ 531 : /* special chars that need to be quoted */
+ 532 : case ' ' : /* space */
+ 533 : case '~' : /* home */
+ 534 : case '`' : /* command */
+ 535 : case '#' : /* comment */
+ 536 : case '$' : /* variable */
+ 537 : case '&' : /* background job */
+ 538 : case '*' : /* wildcard */
+ 539 : case '(' : /* shell */
+ 540 : case ')' : /* shell */
+ 541 : case '\\': /* quote */
+ 542 : case '|' : /* pipe */
+ 543 : case '[' : /* wildcard */
+ 544 : case ']' : /* wildcard */
+ 545 : case '{' : /* code */
+ 546 : case '}' : /* code */
+ 547 : case ';' : /* separator */
+ 548 : case '\'': /* quote */
+ 549 : case '"' : /* quote */
+ 550 : case '<' : /* redirect */
+ 551 : case '>' : /* redirect */
+ 552 : case '?' : /* wildcard */
+ 553 79129 : if (p == end)
+ 554 0 : goto bail;
+ 555 79129 : *p++ = '\\';
+ 556 79129 : if (p == end)
557 0 : goto bail;
- 558 78978 : *p++ = '\\';
- 559 78978 : if (p == end)
- 560 0 : goto bail;
- 561 78978 : *p++ = c;
- 562 78978 : break;
- 563 : #endif
- 564 : }
- 565 :
- 566 4766704 : ++str;
- 567 4766704 : }
+ 558 79129 : *p++ = c;
+ 559 79129 : break;
+ 560 : #endif
+ 561 : default :
+ 562 : /* unquoted */
+ 563 4689062 : if (p == end)
+ 564 0 : goto bail;
+ 565 4689062 : *p++ = c;
+ 566 4689062 : break;
+ 567 : }
568 :
- 569 : #ifdef _WIN32
- 570 : if (has_quote) {
- 571 : if (p == end)
- 572 : goto bail;
- 573 : *p++ = '"';
- 574 : }
- 575 : #endif
- 576 :
- 577 : /* put final 0 */
- 578 355914 : if (p == end)
- 579 0 : goto bail;
- 580 355914 : *p = 0;
- 581 :
- 582 711828 : return begin;
- 583 :
- 584 : bail:
- 585 : /* LCOV_EXCL_START */
- 586 : log_fatal("Escape for shell too long\n");
- 587 : exit(EXIT_FAILURE);
- 588 : /* LCOV_EXCL_STOP */
- 589 : }
- 590 :
- 591 0 : char* strpolish(char* s)
- 592 : {
- 593 0 : char* i = s;
- 594 :
- 595 0 : while (*i) {
- 596 0 : if (isspace(*i) || !isprint(*i))
- 597 0 : *i = ' ';
- 598 0 : ++i;
- 599 : }
- 600 :
- 601 0 : return s;
- 602 : }
+ 569 4768191 : ++str;
+ 570 4768191 : }
+ 571 :
+ 572 : #ifdef _WIN32
+ 573 : if (has_quote) {
+ 574 : if (p == end)
+ 575 : goto bail;
+ 576 : *p++ = '"';
+ 577 : }
+ 578 : #endif
+ 579 :
+ 580 : /* put final 0 */
+ 581 356152 : if (p == end)
+ 582 0 : goto bail;
+ 583 356152 : *p = 0;
+ 584 :
+ 585 712304 : return begin;
+ 586 :
+ 587 : bail:
+ 588 : /* LCOV_EXCL_START */
+ 589 : log_fatal("Escape for shell too long\n");
+ 590 : exit(EXIT_FAILURE);
+ 591 : /* LCOV_EXCL_STOP */
+ 592 : }
+ 593 :
+ 594 0 : char* strpolish(char* s)
+ 595 : {
+ 596 0 : char* i = s;
+ 597 :
+ 598 0 : while (*i) {
+ 599 0 : if (isspace(*i) || !isprint(*i))
+ 600 0 : *i = ' ';
+ 601 0 : ++i;
+ 602 : }
603 :
- 604 1472 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters)
- 605 : {
- 606 1472 : unsigned mac = 0;
- 607 :
- 608 : /* skip initial delimiters */
- 609 1472 : str += strspn(str, delimiters);
+ 604 0 : return s;
+ 605 : }
+ 606 :
+ 607 1472 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters)
+ 608 : {
+ 609 1472 : unsigned mac = 0;
610 :
- 611 8932 : while (*str != 0 || mac == split_max) {
- 612 : /* start of the token */
- 613 5988 : split_map[mac] = str;
- 614 5988 : ++mac;
- 615 :
- 616 : /* find the first delimiter or the end of the string */
- 617 5988 : str += strcspn(str, delimiters);
+ 611 : /* skip initial delimiters */
+ 612 1472 : str += strspn(str, delimiters);
+ 613 :
+ 614 8932 : while (*str != 0 || mac == split_max) {
+ 615 : /* start of the token */
+ 616 5988 : split_map[mac] = str;
+ 617 5988 : ++mac;
618 :
- 619 : /* put the final terminator if missing */
- 620 5988 : if (*str != 0)
- 621 4616 : *str++ = 0;
- 622 :
- 623 : /* skip trailing delimiters */
- 624 5988 : str += strspn(str, delimiters);
- 625 : }
- 626 :
- 627 1472 : return mac;
- 628 : }
+ 619 : /* find the first delimiter or the end of the string */
+ 620 5988 : str += strcspn(str, delimiters);
+ 621 :
+ 622 : /* put the final terminator if missing */
+ 623 5988 : if (*str != 0)
+ 624 4616 : *str++ = 0;
+ 625 :
+ 626 : /* skip trailing delimiters */
+ 627 5988 : str += strspn(str, delimiters);
+ 628 : }
629 :
- 630 : /****************************************************************************/
- 631 : /* path */
+ 630 1472 : return mac;
+ 631 : }
632 :
- 633 7892123 : void pathcpy(char* dst, size_t size, const char* src)
- 634 : {
- 635 7892123 : size_t len = strlen(src);
- 636 :
- 637 7892123 : if (len + 1 > size) {
- 638 : /* LCOV_EXCL_START */
- 639 : log_fatal("Path too long '%s'\n", src);
- 640 : os_abort();
- 641 : /* LCOV_EXCL_STOP */
- 642 : }
- 643 :
- 644 7892123 : memcpy(dst, src, len + 1);
- 645 7892123 : }
+ 633 : /****************************************************************************/
+ 634 : /* path */
+ 635 :
+ 636 7884434 : void pathcpy(char* dst, size_t size, const char* src)
+ 637 : {
+ 638 7884434 : size_t len = strlen(src);
+ 639 :
+ 640 7884434 : if (len + 1 > size) {
+ 641 : /* LCOV_EXCL_START */
+ 642 : log_fatal("Path too long '%s'\n", src);
+ 643 : os_abort();
+ 644 : /* LCOV_EXCL_STOP */
+ 645 : }
646 :
- 647 267 : void pathcat(char* dst, size_t size, const char* src)
- 648 : {
- 649 267 : size_t dst_len = strlen(dst);
- 650 267 : size_t src_len = strlen(src);
- 651 :
- 652 267 : if (dst_len + src_len + 1 > size) {
- 653 : /* LCOV_EXCL_START */
- 654 : log_fatal("Path too long '%s%s'\n", dst, src);
- 655 : os_abort();
- 656 : /* LCOV_EXCL_STOP */
- 657 : }
- 658 :
- 659 267 : memcpy(dst + dst_len, src, src_len + 1);
- 660 267 : }
+ 647 7884434 : memcpy(dst, src, len + 1);
+ 648 7884434 : }
+ 649 :
+ 650 267 : void pathcat(char* dst, size_t size, const char* src)
+ 651 : {
+ 652 267 : size_t dst_len = strlen(dst);
+ 653 267 : size_t src_len = strlen(src);
+ 654 :
+ 655 267 : if (dst_len + src_len + 1 > size) {
+ 656 : /* LCOV_EXCL_START */
+ 657 : log_fatal("Path too long '%s%s'\n", dst, src);
+ 658 : os_abort();
+ 659 : /* LCOV_EXCL_STOP */
+ 660 : }
661 :
- 662 788 : void pathcatc(char* dst, size_t size, char c)
- 663 : {
- 664 788 : size_t dst_len = strlen(dst);
- 665 :
- 666 788 : if (dst_len + 2 > size) {
- 667 : /* LCOV_EXCL_START */
- 668 : log_fatal("Path too long '%s%c'\n", dst, c);
- 669 : os_abort();
- 670 : /* LCOV_EXCL_STOP */
- 671 : }
- 672 :
- 673 788 : dst[dst_len] = c;
- 674 788 : dst[dst_len + 1] = 0;
- 675 788 : }
- 676 :
- 677 16572 : void pathimport(char* dst, size_t size, const char* src)
- 678 : {
- 679 16572 : pathcpy(dst, size, src);
- 680 :
- 681 : #ifdef _WIN32
- 682 : /* convert the Windows dir separator '\' to C '/', */
- 683 : /* and the Windows escaping char '^' to the fnmatch '\' */
- 684 : while (*dst) {
- 685 : switch (*dst) {
- 686 : case '\\' :
- 687 : *dst = '/';
- 688 : break;
- 689 : case '^' :
- 690 : *dst = '\\';
+ 662 267 : memcpy(dst + dst_len, src, src_len + 1);
+ 663 267 : }
+ 664 :
+ 665 788 : void pathcatc(char* dst, size_t size, char c)
+ 666 : {
+ 667 788 : size_t dst_len = strlen(dst);
+ 668 :
+ 669 788 : if (dst_len + 2 > size) {
+ 670 : /* LCOV_EXCL_START */
+ 671 : log_fatal("Path too long '%s%c'\n", dst, c);
+ 672 : os_abort();
+ 673 : /* LCOV_EXCL_STOP */
+ 674 : }
+ 675 :
+ 676 788 : dst[dst_len] = c;
+ 677 788 : dst[dst_len + 1] = 0;
+ 678 788 : }
+ 679 :
+ 680 16572 : void pathimport(char* dst, size_t size, const char* src)
+ 681 : {
+ 682 16572 : pathcpy(dst, size, src);
+ 683 :
+ 684 : #ifdef _WIN32
+ 685 : /* convert the Windows dir separator '\' to C '/', */
+ 686 : /* and the Windows escaping char '^' to the fnmatch '\' */
+ 687 : while (*dst) {
+ 688 : switch (*dst) {
+ 689 : case '\\' :
+ 690 : *dst = '/';
691 : break;
- 692 : }
- 693 : ++dst;
- 694 : }
- 695 : #endif
- 696 16572 : }
- 697 :
- 698 17589 : void pathexport(char* dst, size_t size, const char* src)
- 699 : {
- 700 17589 : pathcpy(dst, size, src);
- 701 :
- 702 : #ifdef _WIN32
- 703 : /* invert the import */
- 704 : while (*dst) {
- 705 : switch (*dst) {
- 706 : case '/' :
- 707 : *dst = '\\';
- 708 : break;
- 709 : case '\\' :
- 710 : *dst = '^';
+ 692 : case '^' :
+ 693 : *dst = '\\';
+ 694 : break;
+ 695 : }
+ 696 : ++dst;
+ 697 : }
+ 698 : #endif
+ 699 16572 : }
+ 700 :
+ 701 17589 : void pathexport(char* dst, size_t size, const char* src)
+ 702 : {
+ 703 17589 : pathcpy(dst, size, src);
+ 704 :
+ 705 : #ifdef _WIN32
+ 706 : /* invert the import */
+ 707 : while (*dst) {
+ 708 : switch (*dst) {
+ 709 : case '/' :
+ 710 : *dst = '\\';
711 : break;
- 712 : }
- 713 : ++dst;
- 714 : }
- 715 : #endif
- 716 17589 : }
- 717 :
- 718 51564160 : void pathprint(char* dst, size_t size, const char* format, ...)
- 719 : {
- 720 : size_t len;
- 721 : va_list ap;
- 722 :
- 723 51564160 : va_start(ap, format);
- 724 51564160 : len = vsnprintf(dst, size, format, ap);
- 725 51564160 : va_end(ap);
- 726 :
- 727 51564160 : if (len >= size) {
- 728 : /* LCOV_EXCL_START */
- 729 : if (size > 0) {
- 730 : dst[size - 1] = 0;
- 731 : log_fatal("Path too long '%s...'\n", dst);
- 732 : } else {
- 733 : log_fatal("Path too long for empty size'\n");
- 734 : }
- 735 : os_abort();
- 736 : /* LCOV_EXCL_STOP */
- 737 : }
- 738 51564160 : }
- 739 :
- 740 7705 : void pathslash(char* dst, size_t size)
- 741 : {
- 742 7705 : size_t len = strlen(dst);
- 743 :
- 744 7705 : if (len > 0 && dst[len - 1] != '/') {
- 745 6114 : if (len + 2 >= size) {
- 746 : /* LCOV_EXCL_START */
- 747 : log_fatal("Path too long '%s/'\n", dst);
- 748 : os_abort();
- 749 : /* LCOV_EXCL_STOP */
- 750 : }
- 751 :
- 752 6114 : dst[len] = '/';
- 753 6114 : dst[len + 1] = 0;
- 754 : }
- 755 7705 : }
- 756 :
- 757 100 : void pathcut(char* dst)
- 758 : {
- 759 100 : char* slash = strrchr(dst, '/');
- 760 :
- 761 100 : if (slash)
- 762 100 : slash[1] = 0;
- 763 : else
- 764 0 : dst[0] = 0;
- 765 100 : }
- 766 :
- 767 51890261 : int pathcmp(const char* a, const char* b)
- 768 : {
- 769 : #ifdef _WIN32
- 770 : char ai[PATH_MAX];
- 771 : char bi[PATH_MAX];
- 772 :
- 773 : /* import to convert \ to / */
- 774 : pathimport(ai, sizeof(ai), a);
- 775 : pathimport(bi, sizeof(bi), b);
- 776 :
- 777 : /* case insensitive compare in Windows */
- 778 : return stricmp(ai, bi);
- 779 : #else
- 780 51890261 : return strcmp(a, b);
- 781 : #endif
- 782 : }
- 783 :
- 784 : /****************************************************************************/
- 785 : /* file-system */
+ 712 : case '\\' :
+ 713 : *dst = '^';
+ 714 : break;
+ 715 : }
+ 716 : ++dst;
+ 717 : }
+ 718 : #endif
+ 719 17589 : }
+ 720 :
+ 721 51562646 : void pathprint(char* dst, size_t size, const char* format, ...)
+ 722 : {
+ 723 : size_t len;
+ 724 : va_list ap;
+ 725 :
+ 726 51562646 : va_start(ap, format);
+ 727 51562646 : len = vsnprintf(dst, size, format, ap);
+ 728 51562646 : va_end(ap);
+ 729 :
+ 730 51562646 : if (len >= size) {
+ 731 : /* LCOV_EXCL_START */
+ 732 : if (size > 0) {
+ 733 : dst[size - 1] = 0;
+ 734 : log_fatal("Path too long '%s...'\n", dst);
+ 735 : } else {
+ 736 : log_fatal("Path too long for empty size'\n");
+ 737 : }
+ 738 : os_abort();
+ 739 : /* LCOV_EXCL_STOP */
+ 740 : }
+ 741 51562646 : }
+ 742 :
+ 743 7705 : void pathslash(char* dst, size_t size)
+ 744 : {
+ 745 7705 : size_t len = strlen(dst);
+ 746 :
+ 747 7705 : if (len > 0 && dst[len - 1] != '/') {
+ 748 6114 : if (len + 2 >= size) {
+ 749 : /* LCOV_EXCL_START */
+ 750 : log_fatal("Path too long '%s/'\n", dst);
+ 751 : os_abort();
+ 752 : /* LCOV_EXCL_STOP */
+ 753 : }
+ 754 :
+ 755 6114 : dst[len] = '/';
+ 756 6114 : dst[len + 1] = 0;
+ 757 : }
+ 758 7705 : }
+ 759 :
+ 760 100 : void pathcut(char* dst)
+ 761 : {
+ 762 100 : char* slash = strrchr(dst, '/');
+ 763 :
+ 764 100 : if (slash)
+ 765 100 : slash[1] = 0;
+ 766 : else
+ 767 0 : dst[0] = 0;
+ 768 100 : }
+ 769 :
+ 770 51889301 : int pathcmp(const char* a, const char* b)
+ 771 : {
+ 772 : #ifdef _WIN32
+ 773 : char ai[PATH_MAX];
+ 774 : char bi[PATH_MAX];
+ 775 :
+ 776 : /* import to convert \ to / */
+ 777 : pathimport(ai, sizeof(ai), a);
+ 778 : pathimport(bi, sizeof(bi), b);
+ 779 :
+ 780 : /* case insensitive compare in Windows */
+ 781 : return stricmp(ai, bi);
+ 782 : #else
+ 783 51889301 : return strcmp(a, b);
+ 784 : #endif
+ 785 : }
786 :
- 787 793073 : int mkancestor(const char* file)
- 788 : {
- 789 : char dir[PATH_MAX];
- 790 : struct stat st;
- 791 : char* c;
- 792 :
- 793 793073 : pathcpy(dir, sizeof(dir), file);
- 794 :
- 795 793073 : c = strrchr(dir, '/');
- 796 793073 : if (!c) {
- 797 : /* no ancestor */
- 798 0 : return 0;
- 799 : }
- 800 :
- 801 : /* clear the file */
- 802 793073 : *c = 0;
+ 787 : /****************************************************************************/
+ 788 : /* file-system */
+ 789 :
+ 790 793100 : int mkancestor(const char* file)
+ 791 : {
+ 792 : char dir[PATH_MAX];
+ 793 : struct stat st;
+ 794 : char* c;
+ 795 :
+ 796 793100 : pathcpy(dir, sizeof(dir), file);
+ 797 :
+ 798 793100 : c = strrchr(dir, '/');
+ 799 793100 : if (!c) {
+ 800 : /* no ancestor */
+ 801 0 : return 0;
+ 802 : }
803 :
- 804 : /* if it's the root dir */
- 805 793073 : if (*dir == 0) {
- 806 : /* nothing more to do */
- 807 0 : return 0;
- 808 : }
- 809 :
- 810 : #ifdef _WIN32
- 811 : /* if it's a drive specificaion like "C:" */
- 812 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
- 813 : /* nothing more to do */
- 814 : return 0;
- 815 : }
- 816 : #endif
- 817 :
- 818 : /*
- 819 : * Check if the dir already exists using lstat().
- 820 : *
- 821 : * Note that in Windows when dealing with read-only media
- 822 : * you cannot try to create the directory, and expecting
- 823 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
- 824 : *
- 825 : * Also in Windows it's better to use lstat() than stat() because it
- 826 : * doesn't need to open the dir with CreateFile().
- 827 : */
- 828 793073 : if (lstat(dir, &st) == 0) {
- 829 : /* it already exists */
- 830 792993 : return 0;
- 831 : }
- 832 :
- 833 : /* recursively create them all */
- 834 80 : if (mkancestor(dir) != 0) {
- 835 : /* LCOV_EXCL_START */
- 836 : return -1;
- 837 : /* LCOV_EXCL_STOP */
- 838 : }
- 839 :
- 840 : /* create it */
- 841 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
- 842 : /* LCOV_EXCL_START */
- 843 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno));
- 844 : return -1;
- 845 : /* LCOV_EXCL_STOP */
- 846 : }
- 847 :
- 848 80 : return 0;
- 849 : }
+ 804 : /* clear the file */
+ 805 793100 : *c = 0;
+ 806 :
+ 807 : /* if it's the root dir */
+ 808 793100 : if (*dir == 0) {
+ 809 : /* nothing more to do */
+ 810 0 : return 0;
+ 811 : }
+ 812 :
+ 813 : #ifdef _WIN32
+ 814 : /* if it's a drive specificaion like "C:" */
+ 815 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
+ 816 : /* nothing more to do */
+ 817 : return 0;
+ 818 : }
+ 819 : #endif
+ 820 :
+ 821 : /*
+ 822 : * Check if the dir already exists using lstat().
+ 823 : *
+ 824 : * Note that in Windows when dealing with read-only media
+ 825 : * you cannot try to create the directory, and expecting
+ 826 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
+ 827 : *
+ 828 : * Also in Windows it's better to use lstat() than stat() because it
+ 829 : * doesn't need to open the dir with CreateFile().
+ 830 : */
+ 831 793100 : if (lstat(dir, &st) == 0) {
+ 832 : /* it already exists */
+ 833 793020 : return 0;
+ 834 : }
+ 835 :
+ 836 : /* recursively create them all */
+ 837 80 : if (mkancestor(dir) != 0) {
+ 838 : /* LCOV_EXCL_START */
+ 839 : return -1;
+ 840 : /* LCOV_EXCL_STOP */
+ 841 : }
+ 842 :
+ 843 : /* create it */
+ 844 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
+ 845 : /* LCOV_EXCL_START */
+ 846 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno));
+ 847 : return -1;
+ 848 : /* LCOV_EXCL_STOP */
+ 849 : }
850 :
- 851 119580 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
- 852 : {
- 853 : #if HAVE_FUTIMENS
- 854 : struct timespec tv[2];
- 855 : #else
- 856 : struct timeval tv[2];
- 857 : #endif
- 858 : int ret;
- 859 :
- 860 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
- 861 119580 : tv[0].tv_sec = mtime_sec;
- 862 119580 : if (mtime_nsec != STAT_NSEC_INVALID)
- 863 119580 : tv[0].tv_nsec = mtime_nsec;
- 864 : else
- 865 0 : tv[0].tv_nsec = 0;
- 866 119580 : tv[1].tv_sec = tv[0].tv_sec;
- 867 119580 : tv[1].tv_nsec = tv[0].tv_nsec;
- 868 :
- 869 119580 : ret = futimens(f, tv);
- 870 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
- 871 : tv[0].tv_sec = mtime_sec;
- 872 : if (mtime_nsec != STAT_NSEC_INVALID)
- 873 : tv[0].tv_usec = mtime_nsec / 1000;
- 874 : else
- 875 : tv[0].tv_usec = 0;
- 876 : tv[1].tv_sec = tv[0].tv_sec;
- 877 : tv[1].tv_usec = tv[0].tv_usec;
- 878 :
- 879 : ret = futimes(f, tv);
- 880 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
- 881 : tv[0].tv_sec = mtime_sec;
- 882 : if (mtime_nsec != STAT_NSEC_INVALID)
- 883 : tv[0].tv_usec = mtime_nsec / 1000;
- 884 : else
- 885 : tv[0].tv_usec = 0;
- 886 : tv[1].tv_sec = tv[0].tv_sec;
- 887 : tv[1].tv_usec = tv[0].tv_usec;
- 888 :
- 889 : ret = futimesat(f, 0, tv);
- 890 : #else
- 891 : #error No function available to set file timestamps with sub-second precision
- 892 : #endif
- 893 :
- 894 119580 : return ret;
- 895 : }
+ 851 80 : return 0;
+ 852 : }
+ 853 :
+ 854 119636 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
+ 855 : {
+ 856 : #if HAVE_FUTIMENS
+ 857 : struct timespec tv[2];
+ 858 : #else
+ 859 : struct timeval tv[2];
+ 860 : #endif
+ 861 : int ret;
+ 862 :
+ 863 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
+ 864 119636 : tv[0].tv_sec = mtime_sec;
+ 865 119636 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 866 119636 : tv[0].tv_nsec = mtime_nsec;
+ 867 : else
+ 868 0 : tv[0].tv_nsec = 0;
+ 869 119636 : tv[1].tv_sec = tv[0].tv_sec;
+ 870 119636 : tv[1].tv_nsec = tv[0].tv_nsec;
+ 871 :
+ 872 119636 : ret = futimens(f, tv);
+ 873 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
+ 874 : tv[0].tv_sec = mtime_sec;
+ 875 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 876 : tv[0].tv_usec = mtime_nsec / 1000;
+ 877 : else
+ 878 : tv[0].tv_usec = 0;
+ 879 : tv[1].tv_sec = tv[0].tv_sec;
+ 880 : tv[1].tv_usec = tv[0].tv_usec;
+ 881 :
+ 882 : ret = futimes(f, tv);
+ 883 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
+ 884 : tv[0].tv_sec = mtime_sec;
+ 885 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 886 : tv[0].tv_usec = mtime_nsec / 1000;
+ 887 : else
+ 888 : tv[0].tv_usec = 0;
+ 889 : tv[1].tv_sec = tv[0].tv_sec;
+ 890 : tv[1].tv_usec = tv[0].tv_usec;
+ 891 :
+ 892 : ret = futimesat(f, 0, tv);
+ 893 : #else
+ 894 : #error No function available to set file timestamps with sub-second precision
+ 895 : #endif
896 :
- 897 : /****************************************************************************/
- 898 : /* advise */
+ 897 119636 : return ret;
+ 898 : }
899 :
- 900 2494910 : void advise_init(struct advise_struct* advise, int mode)
+ 900 17000 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec)
901 : {
- 902 2494910 : advise->mode = mode;
- 903 2494910 : advise->dirty_begin = 0;
- 904 2494910 : advise->dirty_end = 0;
- 905 2494910 : }
- 906 :
- 907 2494965 : int advise_flags(struct advise_struct* advise)
- 908 : {
- 909 2494965 : int flags = 0;
- 910 :
- 911 2494965 : if (advise->mode == ADVISE_SEQUENTIAL
- 912 2483621 : || advise->mode == ADVISE_FLUSH
- 913 34020 : || advise->mode == ADVISE_FLUSH_WINDOW
- 914 22682 : || advise->mode == ADVISE_DISCARD
- 915 22682 : || advise->mode == ADVISE_DISCARD_WINDOW
- 916 : )
- 917 2483614 : flags |= O_SEQUENTIAL;
- 918 :
- 919 : #if HAVE_DIRECT_IO
- 920 2494965 : if (advise->mode == ADVISE_DIRECT)
- 921 0 : flags |= O_DIRECT;
- 922 : #endif
- 923 :
- 924 2494965 : return flags;
- 925 : }
- 926 :
- 927 2416366 : int advise_open(struct advise_struct* advise, int f)
- 928 : {
- 929 : (void)advise;
- 930 : (void)f;
- 931 :
- 932 : #if HAVE_POSIX_FADVISE
- 933 2416366 : if (advise->mode == ADVISE_SEQUENTIAL
- 934 2405026 : || advise->mode == ADVISE_FLUSH
- 935 34021 : || advise->mode == ADVISE_FLUSH_WINDOW
- 936 22682 : || advise->mode == ADVISE_DISCARD
- 937 22682 : || advise->mode == ADVISE_DISCARD_WINDOW
- 938 : ) {
- 939 : int ret;
- 940 :
- 941 : /* advise sequential access */
- 942 2405029 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
- 943 2405059 : if (ret == ENOSYS) {
- 944 : /* call is not supported, like in armhf, see posix_fadvise manpage */
- 945 0 : ret = 0;
- 946 : }
- 947 2405059 : if (ret != 0) {
- 948 : /* LCOV_EXCL_START */
- 949 : errno = ret; /* posix_fadvise return the error code */
- 950 : return -1;
- 951 : /* LCOV_EXCL_STOP */
- 952 : }
- 953 : }
- 954 : #endif
+ 902 : #if HAVE_UTIMENSAT
+ 903 : struct timespec tv[2];
+ 904 : #else
+ 905 : struct timeval tv[2];
+ 906 : #endif
+ 907 : int ret;
+ 908 :
+ 909 : #if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */
+ 910 17000 : tv[0].tv_sec = mtime_sec;
+ 911 17000 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 912 17000 : tv[0].tv_nsec = mtime_nsec;
+ 913 : else
+ 914 0 : tv[0].tv_nsec = 0;
+ 915 17000 : tv[1].tv_sec = tv[0].tv_sec;
+ 916 17000 : tv[1].tv_nsec = tv[0].tv_nsec;
+ 917 :
+ 918 17000 : ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW);
+ 919 : #elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */
+ 920 : tv[0].tv_sec = mtime_sec;
+ 921 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 922 : tv[0].tv_usec = mtime_nsec / 1000;
+ 923 : else
+ 924 : tv[0].tv_usec = 0;
+ 925 : tv[1].tv_sec = tv[0].tv_sec;
+ 926 : tv[1].tv_usec = tv[0].tv_usec;
+ 927 :
+ 928 : ret = lutimes(path, tv);
+ 929 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
+ 930 : tv[0].tv_sec = mtime_sec;
+ 931 : if (mtime_nsec != STAT_NSEC_INVALID)
+ 932 : tv[0].tv_usec = mtime_nsec / 1000;
+ 933 : else
+ 934 : tv[0].tv_usec = 0;
+ 935 : tv[1].tv_sec = tv[0].tv_sec;
+ 936 : tv[1].tv_usec = tv[0].tv_usec;
+ 937 :
+ 938 : ret = futimesat(AT_FDCWD, path, tv);
+ 939 : #else
+ 940 : #error No function available to set file timestamps with sub-second precision
+ 941 : #endif
+ 942 :
+ 943 17000 : return ret;
+ 944 : }
+ 945 :
+ 946 : /****************************************************************************/
+ 947 : /* advise */
+ 948 :
+ 949 2494292 : void advise_init(struct advise_struct* advise, int mode)
+ 950 : {
+ 951 2494292 : advise->mode = mode;
+ 952 2494292 : advise->dirty_begin = 0;
+ 953 2494292 : advise->dirty_end = 0;
+ 954 2494292 : }
955 :
- 956 2416396 : return 0;
- 957 : }
- 958 :
- 959 900358 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
- 960 : {
- 961 : data_off_t flush_offset;
- 962 : data_off_t flush_size;
- 963 : data_off_t discard_offset;
- 964 : data_off_t discard_size;
- 965 :
- 966 : (void)f;
- 967 : (void)flush_offset;
- 968 : (void)flush_size;
- 969 : (void)discard_offset;
- 970 : (void)discard_size;
- 971 :
- 972 900358 : flush_offset = 0;
- 973 900358 : flush_size = 0;
- 974 900358 : discard_offset = 0;
- 975 900358 : discard_size = 0;
- 976 :
- 977 : /*
- 978 : * Follow Linus recommendations about fast writes.
- 979 : *
- 980 : * Linus "Unexpected splice "always copy" behavior observed"
- 981 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070
- 982 : * ---
- 983 : * I have had _very_ good experiences with even a rather trivial
- 984 : * file writer that basically used (iirc) 8MB windows, and the logic was very
- 985 : * trivial:
- 986 : *
- 987 : * - before writing a new 8M window, do "start writeback"
- 988 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do
- 989 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that.
- 990 : *
- 991 : * in fact, in its simplest form, you can do it like this (this is from my
- 992 : * "overwrite disk images" program that I use on old disks):
- 993 : *
- 994 : * for (index = 0; index < max_index ;index++) {
- 995 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE)
- 996 : * break;
- 997 : * // This won't block, but will start writeout asynchronously
- 998 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE);
- 999 : * // This does a blocking write-and-wait on any old ranges
- 1000 : * if (index)
- 1001 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
- 1002 : * }
- 1003 : *
- 1004 : * and even if you don't actually do a discard (maybe we should add a
- 1005 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate
- 1006 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty
- 1007 : * nice, because the heavy writer gets good IO performance _and_ leaves only
- 1008 : * easy-to-free pages around after itself.
- 1009 : * ---
- 1010 : *
- 1011 : * Linus "Unexpected splice "always copy" behavior observed"
- 1012 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176
- 1013 : * ---
- 1014 : * The behavior for dirty page writeback is _not_ well defined, and
- 1015 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that
- 1016 : * writeback logic, ie you do it only on ranges that you have just waited on.
- 1017 : *
- 1018 : * IOW, in my example, you'd couple the
- 1019 : *
- 1020 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
- 1021 : *
- 1022 : * with a
- 1023 : *
- 1024 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED);
- 1025 : *
- 1026 : * afterwards to throw out the pages that you just waited for.
- 1027 : * ---
- 1028 : */
- 1029 :
- 1030 900358 : switch (advise->mode) {
- 1031 : case ADVISE_FLUSH :
- 1032 881613 : flush_offset = offset;
- 1033 881613 : flush_size = size;
- 1034 881613 : break;
- 1035 : case ADVISE_DISCARD :
- 1036 0 : discard_offset = offset;
- 1037 0 : discard_size = size;
- 1038 0 : break;
- 1039 : case ADVISE_FLUSH_WINDOW :
- 1040 : /* if the dirty range can be extended */
- 1041 4687 : if (advise->dirty_end == offset) {
- 1042 : /* extent the dirty range */
- 1043 4687 : advise->dirty_end += size;
- 1044 :
- 1045 : /* if we reached the window size */
- 1046 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) {
- 1047 : /* flush the window */
- 1048 0 : flush_offset = advise->dirty_begin;
- 1049 0 : flush_size = ADVISE_WINDOW_SIZE;
- 1050 :
- 1051 : /* remove it from the dirty range */
- 1052 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE;
- 1053 : }
- 1054 : } else {
- 1055 : /* otherwise flush the existing dirty */
- 1056 0 : flush_offset = advise->dirty_begin;
- 1057 0 : flush_size = advise->dirty_end - advise->dirty_begin;
- 1058 :
- 1059 : /* and set the new range as dirty */
- 1060 0 : advise->dirty_begin = offset;
- 1061 0 : advise->dirty_end = offset + size;
- 1062 : }
- 1063 4687 : break;
- 1064 : case ADVISE_DISCARD_WINDOW :
- 1065 : /* if the dirty range can be extended */
- 1066 4687 : if (advise->dirty_end == offset) {
- 1067 : /* extent the dirty range */
- 1068 4687 : advise->dirty_end += size;
- 1069 :
- 1070 : /* if we reached the double window size */
- 1071 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) {
- 1072 : /* discard the first window */
- 1073 0 : discard_offset = advise->dirty_begin;
- 1074 0 : discard_size = ADVISE_WINDOW_SIZE;
- 1075 :
- 1076 : /* remove it from the dirty range */
- 1077 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE;
+ 956 2494636 : int advise_flags(struct advise_struct* advise)
+ 957 : {
+ 958 2494636 : int flags = 0;
+ 959 :
+ 960 2494636 : if (advise->mode == ADVISE_SEQUENTIAL
+ 961 2482812 : || advise->mode == ADVISE_FLUSH
+ 962 33993 : || advise->mode == ADVISE_FLUSH_WINDOW
+ 963 22671 : || advise->mode == ADVISE_DISCARD
+ 964 22680 : || advise->mode == ADVISE_DISCARD_WINDOW
+ 965 : )
+ 966 2482844 : flags |= O_SEQUENTIAL;
+ 967 :
+ 968 : #if HAVE_DIRECT_IO
+ 969 2494636 : if (advise->mode == ADVISE_DIRECT)
+ 970 0 : flags |= O_DIRECT;
+ 971 : #endif
+ 972 :
+ 973 2494636 : return flags;
+ 974 : }
+ 975 :
+ 976 2412565 : int advise_open(struct advise_struct* advise, int f)
+ 977 : {
+ 978 : (void)advise;
+ 979 : (void)f;
+ 980 :
+ 981 : #if HAVE_POSIX_FADVISE
+ 982 2412565 : if (advise->mode == ADVISE_SEQUENTIAL
+ 983 2402846 : || advise->mode == ADVISE_FLUSH
+ 984 33966 : || advise->mode == ADVISE_FLUSH_WINDOW
+ 985 22656 : || advise->mode == ADVISE_DISCARD
+ 986 22664 : || advise->mode == ADVISE_DISCARD_WINDOW
+ 987 : ) {
+ 988 : int ret;
+ 989 :
+ 990 : /* advise sequential access */
+ 991 2403737 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
+ 992 2403635 : if (ret == ENOSYS) {
+ 993 : /* call is not supported, like in armhf, see posix_fadvise manpage */
+ 994 0 : ret = 0;
+ 995 : }
+ 996 2403635 : if (ret != 0) {
+ 997 : /* LCOV_EXCL_START */
+ 998 : errno = ret; /* posix_fadvise return the error code */
+ 999 : return -1;
+ 1000 : /* LCOV_EXCL_STOP */
+ 1001 : }
+ 1002 : }
+ 1003 : #endif
+ 1004 :
+ 1005 2412463 : return 0;
+ 1006 : }
+ 1007 :
+ 1008 900744 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
+ 1009 : {
+ 1010 : data_off_t flush_offset;
+ 1011 : data_off_t flush_size;
+ 1012 : data_off_t discard_offset;
+ 1013 : data_off_t discard_size;
+ 1014 :
+ 1015 : (void)f;
+ 1016 : (void)flush_offset;
+ 1017 : (void)flush_size;
+ 1018 : (void)discard_offset;
+ 1019 : (void)discard_size;
+ 1020 :
+ 1021 900744 : flush_offset = 0;
+ 1022 900744 : flush_size = 0;
+ 1023 900744 : discard_offset = 0;
+ 1024 900744 : discard_size = 0;
+ 1025 :
+ 1026 : /*
+ 1027 : * Follow Linus recommendations about fast writes.
+ 1028 : *
+ 1029 : * Linus "Unexpected splice "always copy" behavior observed"
+ 1030 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070
+ 1031 : * ---
+ 1032 : * I have had _very_ good experiences with even a rather trivial
+ 1033 : * file writer that basically used (iirc) 8MB windows, and the logic was very
+ 1034 : * trivial:
+ 1035 : *
+ 1036 : * - before writing a new 8M window, do "start writeback"
+ 1037 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do
+ 1038 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that.
+ 1039 : *
+ 1040 : * in fact, in its simplest form, you can do it like this (this is from my
+ 1041 : * "overwrite disk images" program that I use on old disks):
+ 1042 : *
+ 1043 : * for (index = 0; index < max_index ;index++) {
+ 1044 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE)
+ 1045 : * break;
+ 1046 : * // This won't block, but will start writeout asynchronously
+ 1047 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE);
+ 1048 : * // This does a blocking write-and-wait on any old ranges
+ 1049 : * if (index)
+ 1050 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
+ 1051 : * }
+ 1052 : *
+ 1053 : * and even if you don't actually do a discard (maybe we should add a
+ 1054 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate
+ 1055 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty
+ 1056 : * nice, because the heavy writer gets good IO performance _and_ leaves only
+ 1057 : * easy-to-free pages around after itself.
+ 1058 : * ---
+ 1059 : *
+ 1060 : * Linus "Unexpected splice "always copy" behavior observed"
+ 1061 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176
+ 1062 : * ---
+ 1063 : * The behavior for dirty page writeback is _not_ well defined, and
+ 1064 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that
+ 1065 : * writeback logic, ie you do it only on ranges that you have just waited on.
+ 1066 : *
+ 1067 : * IOW, in my example, you'd couple the
+ 1068 : *
+ 1069 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
+ 1070 : *
+ 1071 : * with a
+ 1072 : *
+ 1073 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED);
+ 1074 : *
+ 1075 : * afterwards to throw out the pages that you just waited for.
+ 1076 : * ---
+ 1077 : */
1078 :
- 1079 : /* flush the second window */
- 1080 0 : flush_offset = advise->dirty_begin;
- 1081 0 : flush_size = ADVISE_WINDOW_SIZE;
- 1082 : }
- 1083 : } else {
- 1084 : /* otherwise discard the existing dirty */
- 1085 0 : discard_offset = advise->dirty_begin;
- 1086 0 : discard_size = advise->dirty_end - advise->dirty_begin;
- 1087 :
- 1088 : /* and set the new range as dirty */
- 1089 0 : advise->dirty_begin = offset;
- 1090 0 : advise->dirty_end = offset + size;
- 1091 : }
- 1092 4687 : break;
- 1093 : }
- 1094 :
- 1095 : #if HAVE_SYNC_FILE_RANGE
- 1096 900358 : if (flush_size != 0) {
- 1097 : int ret;
- 1098 :
- 1099 : /* start writing immediately */
- 1100 881612 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE);
- 1101 881612 : if (ret != 0) {
- 1102 : /* LCOV_EXCL_START */
- 1103 : return -1;
- 1104 : /* LCOV_EXCL_STOP */
- 1105 : }
- 1106 : }
- 1107 : #endif
- 1108 :
- 1109 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
- 1110 900358 : if (discard_size != 0) {
- 1111 : int ret;
- 1112 :
- 1113 : /* send the data to the disk and wait until it's written */
- 1114 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
- 1115 0 : if (ret != 0) {
- 1116 : /* LCOV_EXCL_START */
- 1117 : return -1;
- 1118 : /* LCOV_EXCL_STOP */
- 1119 : }
- 1120 :
- 1121 : /* flush the data from the cache */
- 1122 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
- 1123 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
- 1124 0 : if (ret != 0) {
- 1125 : /* LCOV_EXCL_START */
- 1126 : errno = ret; /* posix_fadvise return the error code */
- 1127 : return -1;
- 1128 : /* LCOV_EXCL_STOP */
- 1129 : }
- 1130 : }
- 1131 : #endif
- 1132 :
- 1133 900358 : return 0;
- 1134 : }
- 1135 :
- 1136 8903631 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
- 1137 : {
- 1138 : (void)advise;
- 1139 : (void)f;
- 1140 : (void)offset;
- 1141 : (void)size;
- 1142 :
- 1143 : #if HAVE_POSIX_FADVISE
- 1144 8903631 : if (advise->mode == ADVISE_DISCARD
- 1145 8903983 : || advise->mode == ADVISE_DISCARD_WINDOW
- 1146 : ) {
- 1147 : int ret;
- 1148 :
- 1149 : /* flush the data from the cache */
- 1150 27482 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED);
- 1151 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
- 1152 27825 : if (ret != 0) {
- 1153 : /* LCOV_EXCL_START */
- 1154 : errno = ret; /* posix_fadvise return the error code */
- 1155 : return -1;
- 1156 : /* LCOV_EXCL_STOP */
- 1157 : }
- 1158 : }
- 1159 : #endif
- 1160 :
- 1161 : /*
- 1162 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block
- 1163 : * because it may be blocking.
- 1164 : *
- 1165 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?"
- 1166 : * https://lkml.org/lkml/2010/12/6/122
- 1167 : * ---
- 1168 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same
- 1169 : * way, and in fact share mostly the same code path (see
- 1170 : * force_page_cache_readahead() in mm/readahead.c).
- 1171 : *
- 1172 : * They are asynchronous in that there is no guarantee the pages will be
- 1173 : * in the page cache by the time they return. But at the same time, they
- 1174 : * are not guaranteed to be non-blocking. That is, the work of doing the
- 1175 : * readahead does not take place in a kernel thread. So if you try to
- 1176 : * request I/O than will fit in the request queue, the system call will
- 1177 : * block until some I/O is completed so that more I/O requested cam be
- 1178 : * loaded onto the request queue.
- 1179 : *
- 1180 : * The only way to fix this would be to either put the work on a kernel
- 1181 : * thread (i.e., some kind of workqueue) or in a userspace thread. For
- 1182 : * ion programmer wondering what to do today, I'd suggest the
- 1183 : * latter since it will be more portable across various kernel versions.
- 1184 : *
- 1185 : * This does leave the question about whether we should change the kernel
- 1186 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be
- 1187 : * non-blocking and do this work in a workqueue (or via some kind of
- 1188 : * callback/continuation scheme). My worry is just doing this if a user
- 1189 : * application does something crazy, like request gigabytes and gigabytes
- 1190 : * of readahead, and then repents of their craziness, there should be a
- 1191 : * way of cancelling the readahead request. Today, the user can just
- 1192 : * kill the application. But if we simply shove the work to a kernel
- 1193 : * thread, it becomes a lot harder to cancel the readahead request. We'd
- 1194 : * have to invent a new API, and then have a way to know whether the user
- 1195 : * has access to kill a particular readahead request, etc.
- 1196 : * ---
- 1197 : */
- 1198 :
- 1199 8903974 : return 0;
- 1200 : }
- 1201 :
- 1202 : /****************************************************************************/
- 1203 : /* memory */
- 1204 :
- 1205 : /**
- 1206 : * Total amount of memory allocated.
- 1207 : */
- 1208 : static size_t mcounter;
+ 1079 900744 : switch (advise->mode) {
+ 1080 : case ADVISE_FLUSH :
+ 1081 882011 : flush_offset = offset;
+ 1082 882011 : flush_size = size;
+ 1083 882011 : break;
+ 1084 : case ADVISE_DISCARD :
+ 1085 0 : discard_offset = offset;
+ 1086 0 : discard_size = size;
+ 1087 0 : break;
+ 1088 : case ADVISE_FLUSH_WINDOW :
+ 1089 : /* if the dirty range can be extended */
+ 1090 4687 : if (advise->dirty_end == offset) {
+ 1091 : /* extent the dirty range */
+ 1092 4687 : advise->dirty_end += size;
+ 1093 :
+ 1094 : /* if we reached the window size */
+ 1095 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) {
+ 1096 : /* flush the window */
+ 1097 0 : flush_offset = advise->dirty_begin;
+ 1098 0 : flush_size = ADVISE_WINDOW_SIZE;
+ 1099 :
+ 1100 : /* remove it from the dirty range */
+ 1101 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE;
+ 1102 : }
+ 1103 : } else {
+ 1104 : /* otherwise flush the existing dirty */
+ 1105 0 : flush_offset = advise->dirty_begin;
+ 1106 0 : flush_size = advise->dirty_end - advise->dirty_begin;
+ 1107 :
+ 1108 : /* and set the new range as dirty */
+ 1109 0 : advise->dirty_begin = offset;
+ 1110 0 : advise->dirty_end = offset + size;
+ 1111 : }
+ 1112 4687 : break;
+ 1113 : case ADVISE_DISCARD_WINDOW :
+ 1114 : /* if the dirty range can be extended */
+ 1115 4687 : if (advise->dirty_end == offset) {
+ 1116 : /* extent the dirty range */
+ 1117 4687 : advise->dirty_end += size;
+ 1118 :
+ 1119 : /* if we reached the double window size */
+ 1120 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) {
+ 1121 : /* discard the first window */
+ 1122 0 : discard_offset = advise->dirty_begin;
+ 1123 0 : discard_size = ADVISE_WINDOW_SIZE;
+ 1124 :
+ 1125 : /* remove it from the dirty range */
+ 1126 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE;
+ 1127 :
+ 1128 : /* flush the second window */
+ 1129 0 : flush_offset = advise->dirty_begin;
+ 1130 0 : flush_size = ADVISE_WINDOW_SIZE;
+ 1131 : }
+ 1132 : } else {
+ 1133 : /* otherwise discard the existing dirty */
+ 1134 0 : discard_offset = advise->dirty_begin;
+ 1135 0 : discard_size = advise->dirty_end - advise->dirty_begin;
+ 1136 :
+ 1137 : /* and set the new range as dirty */
+ 1138 0 : advise->dirty_begin = offset;
+ 1139 0 : advise->dirty_end = offset + size;
+ 1140 : }
+ 1141 4687 : break;
+ 1142 : }
+ 1143 :
+ 1144 : #if HAVE_SYNC_FILE_RANGE
+ 1145 900744 : if (flush_size != 0) {
+ 1146 : int ret;
+ 1147 :
+ 1148 : /* start writing immediately */
+ 1149 882058 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE);
+ 1150 881885 : if (ret != 0) {
+ 1151 : /* LCOV_EXCL_START */
+ 1152 : return -1;
+ 1153 : /* LCOV_EXCL_STOP */
+ 1154 : }
+ 1155 : }
+ 1156 : #endif
+ 1157 :
+ 1158 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
+ 1159 900571 : if (discard_size != 0) {
+ 1160 : int ret;
+ 1161 :
+ 1162 : /* send the data to the disk and wait until it's written */
+ 1163 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
+ 1164 0 : if (ret != 0) {
+ 1165 : /* LCOV_EXCL_START */
+ 1166 : return -1;
+ 1167 : /* LCOV_EXCL_STOP */
+ 1168 : }
+ 1169 :
+ 1170 : /* flush the data from the cache */
+ 1171 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
+ 1172 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
+ 1173 0 : if (ret != 0) {
+ 1174 : /* LCOV_EXCL_START */
+ 1175 : errno = ret; /* posix_fadvise return the error code */
+ 1176 : return -1;
+ 1177 : /* LCOV_EXCL_STOP */
+ 1178 : }
+ 1179 : }
+ 1180 : #endif
+ 1181 :
+ 1182 900571 : return 0;
+ 1183 : }
+ 1184 :
+ 1185 8897480 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
+ 1186 : {
+ 1187 : (void)advise;
+ 1188 : (void)f;
+ 1189 : (void)offset;
+ 1190 : (void)size;
+ 1191 :
+ 1192 : #if HAVE_POSIX_FADVISE
+ 1193 8897480 : if (advise->mode == ADVISE_DISCARD
+ 1194 8901398 : || advise->mode == ADVISE_DISCARD_WINDOW
+ 1195 : ) {
+ 1196 : int ret;
+ 1197 :
+ 1198 : /* flush the data from the cache */
+ 1199 23941 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED);
+ 1200 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
+ 1201 27801 : if (ret != 0) {
+ 1202 : /* LCOV_EXCL_START */
+ 1203 : errno = ret; /* posix_fadvise return the error code */
+ 1204 : return -1;
+ 1205 : /* LCOV_EXCL_STOP */
+ 1206 : }
+ 1207 : }
+ 1208 : #endif
1209 :
- 1210 476 : size_t malloc_counter_get(void)
- 1211 : {
- 1212 : size_t ret;
- 1213 :
- 1214 476 : lock_memory();
- 1215 :
- 1216 476 : ret = mcounter;
- 1217 :
- 1218 476 : unlock_memory();
- 1219 :
- 1220 476 : return ret;
- 1221 : }
- 1222 :
- 1223 20173411 : void malloc_counter_inc(size_t inc)
- 1224 : {
- 1225 20173411 : lock_memory();
- 1226 :
- 1227 20173411 : mcounter += inc;
- 1228 :
- 1229 20173411 : unlock_memory();
- 1230 20173411 : }
- 1231 :
- 1232 : /* LCOV_EXCL_START */
- 1233 : static ssize_t malloc_print(int f, const char* str)
- 1234 : {
- 1235 : ssize_t len = 0;
- 1236 :
- 1237 : while (str[len])
- 1238 : ++len;
- 1239 : return write(f, str, len);
- 1240 : }
- 1241 : /* LCOV_EXCL_STOP */
- 1242 :
- 1243 : /* LCOV_EXCL_START */
- 1244 : static ssize_t malloc_printn(int f, size_t value)
- 1245 : {
- 1246 : char buf[32];
- 1247 : int i;
- 1248 :
- 1249 : if (!value)
- 1250 : return write(f, "0", 1);
- 1251 :
- 1252 : i = sizeof(buf);
- 1253 : while (value) {
- 1254 : buf[--i] = (value % 10) + '0';
- 1255 : value /= 10;
- 1256 : }
- 1257 :
- 1258 : return write(f, buf + i, sizeof(buf) - i);
- 1259 : }
- 1260 : /* LCOV_EXCL_STOP */
- 1261 :
- 1262 : /* LCOV_EXCL_START */
- 1263 : void malloc_fail(size_t size)
- 1264 : {
- 1265 : /* don't use printf to avoid any possible extra allocation */
- 1266 : int f = 2; /* stderr */
- 1267 :
- 1268 : malloc_print(f, "Failed for Low Memory!\n");
- 1269 : malloc_print(f, "Allocating ");
- 1270 : malloc_printn(f, size);
- 1271 : malloc_print(f, " bytes.\n");
- 1272 : malloc_print(f, "Already allocated ");
- 1273 : malloc_printn(f, malloc_counter_get());
- 1274 : malloc_print(f, " bytes.\n");
- 1275 : if (sizeof(void*) == 4) {
- 1276 : malloc_print(f, "You are currently using a 32 bits executable.\n");
- 1277 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
- 1278 : }
- 1279 : }
- 1280 : /* LCOV_EXCL_STOP */
- 1281 :
- 1282 14363921 : void* malloc_nofail(size_t size)
+ 1210 : /*
+ 1211 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block
+ 1212 : * because it may be blocking.
+ 1213 : *
+ 1214 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?"
+ 1215 : * https://lkml.org/lkml/2010/12/6/122
+ 1216 : * ---
+ 1217 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same
+ 1218 : * way, and in fact share mostly the same code path (see
+ 1219 : * force_page_cache_readahead() in mm/readahead.c).
+ 1220 : *
+ 1221 : * They are asynchronous in that there is no guarantee the pages will be
+ 1222 : * in the page cache by the time they return. But at the same time, they
+ 1223 : * are not guaranteed to be non-blocking. That is, the work of doing the
+ 1224 : * readahead does not take place in a kernel thread. So if you try to
+ 1225 : * request I/O than will fit in the request queue, the system call will
+ 1226 : * block until some I/O is completed so that more I/O requested cam be
+ 1227 : * loaded onto the request queue.
+ 1228 : *
+ 1229 : * The only way to fix this would be to either put the work on a kernel
+ 1230 : * thread (i.e., some kind of workqueue) or in a userspace thread. For
+ 1231 : * ion programmer wondering what to do today, I'd suggest the
+ 1232 : * latter since it will be more portable across various kernel versions.
+ 1233 : *
+ 1234 : * This does leave the question about whether we should change the kernel
+ 1235 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be
+ 1236 : * non-blocking and do this work in a workqueue (or via some kind of
+ 1237 : * callback/continuation scheme). My worry is just doing this if a user
+ 1238 : * application does something crazy, like request gigabytes and gigabytes
+ 1239 : * of readahead, and then repents of their craziness, there should be a
+ 1240 : * way of cancelling the readahead request. Today, the user can just
+ 1241 : * kill the application. But if we simply shove the work to a kernel
+ 1242 : * thread, it becomes a lot harder to cancel the readahead request. We'd
+ 1243 : * have to invent a new API, and then have a way to know whether the user
+ 1244 : * has access to kill a particular readahead request, etc.
+ 1245 : * ---
+ 1246 : */
+ 1247 :
+ 1248 8901340 : return 0;
+ 1249 : }
+ 1250 :
+ 1251 : /****************************************************************************/
+ 1252 : /* memory */
+ 1253 :
+ 1254 : /**
+ 1255 : * Total amount of memory allocated.
+ 1256 : */
+ 1257 : static size_t mcounter;
+ 1258 :
+ 1259 476 : size_t malloc_counter_get(void)
+ 1260 : {
+ 1261 : size_t ret;
+ 1262 :
+ 1263 476 : lock_memory();
+ 1264 :
+ 1265 476 : ret = mcounter;
+ 1266 :
+ 1267 476 : unlock_memory();
+ 1268 :
+ 1269 476 : return ret;
+ 1270 : }
+ 1271 :
+ 1272 20172963 : void malloc_counter_inc(size_t inc)
+ 1273 : {
+ 1274 20172963 : lock_memory();
+ 1275 :
+ 1276 20172963 : mcounter += inc;
+ 1277 :
+ 1278 20172963 : unlock_memory();
+ 1279 20172963 : }
+ 1280 :
+ 1281 : /* LCOV_EXCL_START */
+ 1282 : static ssize_t malloc_print(int f, const char* str)
1283 : {
- 1284 14363921 : void* ptr = malloc(size);
+ 1284 : ssize_t len = 0;
1285 :
- 1286 14363921 : if (!ptr) {
- 1287 : /* LCOV_EXCL_START */
- 1288 : malloc_fail(size);
- 1289 : exit(EXIT_FAILURE);
- 1290 : /* LCOV_EXCL_STOP */
- 1291 : }
- 1292 :
- 1293 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */
- 1294 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */
- 1295 : /* and not only reserving the addressable space. */
- 1296 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
- 1297 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
- 1298 : /* get a real error from malloc() instead than a process killed. */
- 1299 : /* Note that calloc() doesn't have the same effect. */
- 1300 14363921 : memset(ptr, 0xA5, size);
- 1301 : #endif
- 1302 :
- 1303 14363921 : malloc_counter_inc(size);
- 1304 :
- 1305 14363921 : return ptr;
- 1306 : }
- 1307 :
- 1308 10089 : void* calloc_nofail(size_t count, size_t size)
- 1309 : {
- 1310 : void* ptr;
- 1311 :
- 1312 10089 : size *= count;
- 1313 :
- 1314 : /* see the note in malloc_nofail() of why we don't use calloc() */
- 1315 10089 : ptr = malloc(size);
+ 1286 : while (str[len])
+ 1287 : ++len;
+ 1288 : return write(f, str, len);
+ 1289 : }
+ 1290 : /* LCOV_EXCL_STOP */
+ 1291 :
+ 1292 : /* LCOV_EXCL_START */
+ 1293 : static ssize_t malloc_printn(int f, size_t value)
+ 1294 : {
+ 1295 : char buf[32];
+ 1296 : int i;
+ 1297 :
+ 1298 : if (!value)
+ 1299 : return write(f, "0", 1);
+ 1300 :
+ 1301 : i = sizeof(buf);
+ 1302 : while (value) {
+ 1303 : buf[--i] = (value % 10) + '0';
+ 1304 : value /= 10;
+ 1305 : }
+ 1306 :
+ 1307 : return write(f, buf + i, sizeof(buf) - i);
+ 1308 : }
+ 1309 : /* LCOV_EXCL_STOP */
+ 1310 :
+ 1311 : /* LCOV_EXCL_START */
+ 1312 : void malloc_fail(size_t size)
+ 1313 : {
+ 1314 : /* don't use printf to avoid any possible extra allocation */
+ 1315 : int f = 2; /* stderr */
1316 :
- 1317 10089 : if (!ptr) {
- 1318 : /* LCOV_EXCL_START */
- 1319 : malloc_fail(size);
- 1320 : exit(EXIT_FAILURE);
- 1321 : /* LCOV_EXCL_STOP */
- 1322 : }
- 1323 :
- 1324 10089 : memset(ptr, 0, size);
- 1325 :
- 1326 10089 : malloc_counter_inc(size);
- 1327 :
- 1328 10089 : return ptr;
- 1329 : }
+ 1317 : malloc_print(f, "Failed for Low Memory!\n");
+ 1318 : malloc_print(f, "Allocating ");
+ 1319 : malloc_printn(f, size);
+ 1320 : malloc_print(f, " bytes.\n");
+ 1321 : malloc_print(f, "Already allocated ");
+ 1322 : malloc_printn(f, malloc_counter_get());
+ 1323 : malloc_print(f, " bytes.\n");
+ 1324 : if (sizeof(void*) == 4) {
+ 1325 : malloc_print(f, "You are currently using a 32 bits executable.\n");
+ 1326 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
+ 1327 : }
+ 1328 : }
+ 1329 : /* LCOV_EXCL_STOP */
1330 :
- 1331 5799401 : char* strdup_nofail(const char* str)
+ 1331 14363716 : void* malloc_nofail(size_t size)
1332 : {
- 1333 : size_t size;
- 1334 : char* ptr;
- 1335 :
- 1336 5799401 : size = strlen(str) + 1;
- 1337 :
- 1338 5799401 : ptr = malloc(size);
- 1339 :
- 1340 5799401 : if (!ptr) {
- 1341 : /* LCOV_EXCL_START */
- 1342 : malloc_fail(size);
- 1343 : exit(EXIT_FAILURE);
- 1344 : /* LCOV_EXCL_STOP */
- 1345 : }
- 1346 :
- 1347 5799401 : memcpy(ptr, str, size);
- 1348 :
- 1349 5799401 : malloc_counter_inc(size);
- 1350 :
- 1351 5799401 : return ptr;
- 1352 : }
+ 1333 14363716 : void* ptr = malloc(size);
+ 1334 :
+ 1335 14363716 : if (!ptr) {
+ 1336 : /* LCOV_EXCL_START */
+ 1337 : malloc_fail(size);
+ 1338 : exit(EXIT_FAILURE);
+ 1339 : /* LCOV_EXCL_STOP */
+ 1340 : }
+ 1341 :
+ 1342 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */
+ 1343 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */
+ 1344 : /* and not only reserving the addressable space. */
+ 1345 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
+ 1346 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
+ 1347 : /* get a real error from malloc() instead than a process killed. */
+ 1348 : /* Note that calloc() doesn't have the same effect. */
+ 1349 14363716 : memset(ptr, 0xA5, size);
+ 1350 : #endif
+ 1351 :
+ 1352 14363716 : malloc_counter_inc(size);
1353 :
- 1354 : /****************************************************************************/
- 1355 : /* smartctl */
+ 1354 14363716 : return ptr;
+ 1355 : }
1356 :
- 1357 : /**
- 1358 : * Match a string with the specified pattern.
- 1359 : * Like sscanf() a space match any sequence of spaces.
- 1360 : * Return 0 if it matches.
- 1361 : */
- 1362 0 : static int smatch(const char* str, const char* pattern)
- 1363 : {
- 1364 0 : while (*pattern) {
- 1365 0 : if (isspace(*pattern)) {
- 1366 0 : ++pattern;
- 1367 0 : while (isspace(*str))
- 1368 0 : ++str;
- 1369 0 : } else if (*pattern == *str) {
- 1370 0 : ++pattern;
- 1371 0 : ++str;
- 1372 : } else
- 1373 0 : return -1;
- 1374 : }
- 1375 :
- 1376 0 : return 0;
- 1377 : }
- 1378 :
- 1379 43 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model)
- 1380 : {
- 1381 : unsigned i;
- 1382 : int inside;
- 1383 :
- 1384 : /* preclear attribute */
- 1385 43 : *serial = 0;
- 1386 11223 : for (i = 0; i < SMART_COUNT; ++i)
- 1387 11180 : smart[i] = SMART_UNASSIGNED;
+ 1357 10089 : void* calloc_nofail(size_t count, size_t size)
+ 1358 : {
+ 1359 : void* ptr;
+ 1360 :
+ 1361 10089 : size *= count;
+ 1362 :
+ 1363 : /* see the note in malloc_nofail() of why we don't use calloc() */
+ 1364 10089 : ptr = malloc(size);
+ 1365 :
+ 1366 10089 : if (!ptr) {
+ 1367 : /* LCOV_EXCL_START */
+ 1368 : malloc_fail(size);
+ 1369 : exit(EXIT_FAILURE);
+ 1370 : /* LCOV_EXCL_STOP */
+ 1371 : }
+ 1372 :
+ 1373 10089 : memset(ptr, 0, size);
+ 1374 :
+ 1375 10089 : malloc_counter_inc(size);
+ 1376 :
+ 1377 10089 : return ptr;
+ 1378 : }
+ 1379 :
+ 1380 5799158 : char* strdup_nofail(const char* str)
+ 1381 : {
+ 1382 : size_t size;
+ 1383 : char* ptr;
+ 1384 :
+ 1385 5799158 : size = strlen(str) + 1;
+ 1386 :
+ 1387 5799158 : ptr = malloc(size);
1388 :
- 1389 : /* read the file */
- 1390 43 : inside = 0;
- 1391 : while (1) {
- 1392 : char buf[256];
- 1393 : unsigned id;
- 1394 : uint64_t raw;
- 1395 : char* s;
- 1396 :
- 1397 43 : s = fgets(buf, sizeof(buf), f);
- 1398 43 : if (s == 0)
- 1399 43 : break;
- 1400 :
- 1401 : /* remove extraneous chars */
- 1402 0 : s = strpolish(buf);
- 1403 :
- 1404 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
+ 1389 5799158 : if (!ptr) {
+ 1390 : /* LCOV_EXCL_START */
+ 1391 : malloc_fail(size);
+ 1392 : exit(EXIT_FAILURE);
+ 1393 : /* LCOV_EXCL_STOP */
+ 1394 : }
+ 1395 :
+ 1396 5799158 : memcpy(ptr, str, size);
+ 1397 :
+ 1398 5799158 : malloc_counter_inc(size);
+ 1399 :
+ 1400 5799158 : return ptr;
+ 1401 : }
+ 1402 :
+ 1403 : /****************************************************************************/
+ 1404 : /* smartctl */
1405 :
- 1406 : /* skip initial spaces */
- 1407 0 : while (isspace(*s))
- 1408 0 : ++s;
- 1409 :
- 1410 0 : if (*s == 0) {
- 1411 0 : inside = 0;
- 1412 : /* common */
- 1413 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) {
- 1414 0 : smart[SMART_ROTATION_RATE] = 0;
- 1415 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) {
- 1416 0 : } else if (smatch(s, "User Capacity:") == 0) {
- 1417 0 : char* begin = strchr(s, ':');
- 1418 0 : char* end = strstr(s, "bytes");
- 1419 0 : if (begin != 0 && end != 0 && begin < end) {
- 1420 : char* p;
- 1421 0 : smart[SMART_SIZE] = 0;
- 1422 0 : for (p = begin; p != end; ++p) {
- 1423 0 : if (isdigit(*p)) {
- 1424 0 : smart[SMART_SIZE] *= 10;
- 1425 0 : smart[SMART_SIZE] += *p - '0';
- 1426 : }
- 1427 : }
- 1428 : }
- 1429 0 : } else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) {
- 1430 0 : } else if (sscanf(s, "Device Model: %63s", model) == 1) {
- 1431 : /* SCSI */
- 1432 0 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */
- 1433 0 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) {
- 1434 0 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) {
- 1435 0 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) {
- 1436 0 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) {
- 1437 0 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) {
- 1438 0 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) {
- 1439 : /* ATA */
- 1440 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
- 1441 0 : } else if (smatch(s, "ID#") == 0) {
- 1442 0 : inside = 1;
- 1443 0 : } else if (smatch(s, "No Errors Logged") == 0) {
- 1444 0 : smart[SMART_ERROR] = 0;
- 1445 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
- 1446 0 : smart[SMART_ERROR] = raw;
- 1447 0 : } else if (inside) {
- 1448 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
- 1449 : /* LCOV_EXCL_START */
- 1450 : log_fatal("Invalid smartctl line '%s'.\n", s);
- 1451 : return -1;
- 1452 : /* LCOV_EXCL_STOP */
- 1453 : }
+ 1406 : /**
+ 1407 : * Match a string with the specified pattern.
+ 1408 : * Like sscanf() a space match any sequence of spaces.
+ 1409 : * Return 0 if it matches.
+ 1410 : */
+ 1411 0 : static int smatch(const char* str, const char* pattern)
+ 1412 : {
+ 1413 0 : while (*pattern) {
+ 1414 0 : if (isspace(*pattern)) {
+ 1415 0 : ++pattern;
+ 1416 0 : while (isspace(*str))
+ 1417 0 : ++str;
+ 1418 0 : } else if (*pattern == *str) {
+ 1419 0 : ++pattern;
+ 1420 0 : ++str;
+ 1421 : } else
+ 1422 0 : return -1;
+ 1423 : }
+ 1424 :
+ 1425 0 : return 0;
+ 1426 : }
+ 1427 :
+ 1428 43 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model)
+ 1429 : {
+ 1430 : unsigned i;
+ 1431 : int inside;
+ 1432 :
+ 1433 : /* preclear attribute */
+ 1434 43 : *serial = 0;
+ 1435 11223 : for (i = 0; i < SMART_COUNT; ++i)
+ 1436 11180 : smart[i] = SMART_UNASSIGNED;
+ 1437 :
+ 1438 : /* read the file */
+ 1439 43 : inside = 0;
+ 1440 : while (1) {
+ 1441 : char buf[256];
+ 1442 : unsigned id;
+ 1443 : uint64_t raw;
+ 1444 : char* s;
+ 1445 :
+ 1446 43 : s = fgets(buf, sizeof(buf), f);
+ 1447 42 : if (s == 0)
+ 1448 42 : break;
+ 1449 :
+ 1450 : /* remove extraneous chars */
+ 1451 0 : s = strpolish(buf);
+ 1452 :
+ 1453 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
1454 :
- 1455 0 : if (id >= 256) {
- 1456 : /* LCOV_EXCL_START */
- 1457 : log_fatal("Invalid SMART id '%u'.\n", id);
- 1458 : return -1;
- 1459 : /* LCOV_EXCL_STOP */
- 1460 : }
- 1461 :
- 1462 0 : smart[id] = raw;
- 1463 : }
- 1464 0 : }
- 1465 :
- 1466 43 : return 0;
- 1467 : }
- 1468 :
- 1469 5 : int smartctl_flush(FILE* f, const char* file, const char* name)
- 1470 : {
- 1471 : /* read the file */
- 1472 : while (1) {
- 1473 : char buf[256];
- 1474 : char* s;
- 1475 :
- 1476 5 : s = fgets(buf, sizeof(buf), f);
- 1477 5 : if (s == 0)
- 1478 5 : break;
- 1479 :
- 1480 : /* remove extraneous chars */
- 1481 0 : s = strpolish(buf);
- 1482 :
- 1483 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
- 1484 0 : }
- 1485 :
- 1486 10 : return 0;
- 1487 : }
- 1488 :
- 1489 : /****************************************************************************/
- 1490 : /* thread */
- 1491 :
- 1492 : #if HAVE_PTHREAD
- 1493 2284 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr)
- 1494 : {
- 1495 2284 : if (pthread_mutex_init(mutex, attr) != 0) {
- 1496 : /* LCOV_EXCL_START */
- 1497 : log_fatal("Failed call to pthread_mutex_init().\n");
- 1498 : os_abort();
- 1499 : /* LCOV_EXCL_STOP */
- 1500 : }
- 1501 2284 : }
- 1502 :
- 1503 2082 : void thread_mutex_destroy(pthread_mutex_t* mutex)
- 1504 : {
- 1505 2082 : if (pthread_mutex_destroy(mutex) != 0) {
- 1506 : /* LCOV_EXCL_START */
- 1507 : log_fatal("Failed call to pthread_mutex_destroy().\n");
- 1508 : os_abort();
- 1509 : /* LCOV_EXCL_STOP */
- 1510 : }
- 1511 2082 : }
- 1512 :
- 1513 80857668 : void thread_mutex_lock(pthread_mutex_t* mutex)
- 1514 : {
- 1515 80857668 : if (pthread_mutex_lock(mutex) != 0) {
- 1516 : /* LCOV_EXCL_START */
- 1517 : log_fatal("Failed call to pthread_mutex_lock().\n");
- 1518 : os_abort();
- 1519 : /* LCOV_EXCL_STOP */
- 1520 : }
- 1521 80860507 : }
- 1522 :
- 1523 80858701 : void thread_mutex_unlock(pthread_mutex_t* mutex)
- 1524 : {
- 1525 80858701 : if (pthread_mutex_unlock(mutex) != 0) {
- 1526 : /* LCOV_EXCL_START */
- 1527 : log_fatal("Failed call to pthread_mutex_unlock().\n");
- 1528 : os_abort();
- 1529 : /* LCOV_EXCL_STOP */
- 1530 : }
- 1531 80861909 : }
- 1532 :
- 1533 380 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr)
- 1534 : {
- 1535 380 : if (pthread_cond_init(cond, attr) != 0) {
- 1536 : /* LCOV_EXCL_START */
- 1537 : log_fatal("Failed call to pthread_cond_init().\n");
- 1538 : os_abort();
- 1539 : /* LCOV_EXCL_STOP */
- 1540 : }
- 1541 380 : }
- 1542 :
- 1543 380 : void thread_cond_destroy(pthread_cond_t* cond)
- 1544 : {
- 1545 380 : if (pthread_cond_destroy(cond) != 0) {
- 1546 : /* LCOV_EXCL_START */
- 1547 : log_fatal("Failed call to pthread_cond_destroy().\n");
- 1548 : os_abort();
- 1549 : /* LCOV_EXCL_STOP */
- 1550 : }
- 1551 380 : }
- 1552 :
- 1553 85887 : void thread_cond_signal(pthread_cond_t* cond)
- 1554 : {
- 1555 85887 : if (pthread_cond_signal(cond) != 0) {
- 1556 : /* LCOV_EXCL_START */
- 1557 : log_fatal("Failed call to pthread_cond_signal().\n");
- 1558 : os_abort();
- 1559 : /* LCOV_EXCL_STOP */
- 1560 : }
- 1561 85887 : }
- 1562 :
- 1563 255503 : void thread_cond_broadcast(pthread_cond_t* cond)
- 1564 : {
- 1565 255503 : if (pthread_cond_broadcast(cond) != 0) {
- 1566 : /* LCOV_EXCL_START */
- 1567 : log_fatal("Failed call to pthread_cond_broadcast().\n");
- 1568 : os_abort();
- 1569 : /* LCOV_EXCL_STOP */
- 1570 : }
- 1571 255503 : }
- 1572 :
- 1573 1037153 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
- 1574 : {
- 1575 1037153 : if (pthread_cond_wait(cond, mutex) != 0) {
- 1576 : /* LCOV_EXCL_START */
- 1577 : log_fatal("Failed call to pthread_cond_wait().\n");
- 1578 : os_abort();
- 1579 : /* LCOV_EXCL_STOP */
- 1580 : }
- 1581 1037153 : }
- 1582 :
- 1583 : /**
- 1584 : * Implementation note about conditional variables.
- 1585 : *
- 1586 : * The conditional variables can be signaled inside or ouside the mutex,
- 1587 : * what is better it's debatable but in general doing that ouside the mutex,
- 1588 : * reduces the number of context switches.
- 1589 : *
- 1590 : * But when when testing with helgrind and drd, this disallows such tools to
- 1591 : * to see the dependency between the signal and the wait.
- 1592 : *
- 1593 : * To avoid it we signal everything inside the mutex. And we do this in both
- 1594 : * test mode (with CHERCKER defined) and release mode (CHECKER not defined),
- 1595 : * to be on the safe side and avoid any difference in beaviour between test and
- 1596 : * release.
- 1597 : *
- 1598 : * Here some interesting discussion:
- 1599 : *
- 1600 : * Condvars: signal with mutex locked or not?
- 1601 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/
- 1602 : *
- 1603 : * Calling pthread_cond_signal without locking mutex
- 1604 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494
- 1605 : */
- 1606 :
- 1607 : /**
- 1608 : * Control when to signal the condition variables.
- 1609 : */
- 1610 : int thread_cond_signal_outside = 0;
+ 1455 : /* skip initial spaces */
+ 1456 0 : while (isspace(*s))
+ 1457 0 : ++s;
+ 1458 :
+ 1459 0 : if (*s == 0) {
+ 1460 0 : inside = 0;
+ 1461 : /* common */
+ 1462 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) {
+ 1463 0 : smart[SMART_ROTATION_RATE] = 0;
+ 1464 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) {
+ 1465 0 : } else if (smatch(s, "User Capacity:") == 0) {
+ 1466 0 : char* begin = strchr(s, ':');
+ 1467 0 : char* end = strstr(s, "bytes");
+ 1468 0 : if (begin != 0 && end != 0 && begin < end) {
+ 1469 : char* p;
+ 1470 0 : smart[SMART_SIZE] = 0;
+ 1471 0 : for (p = begin; p != end; ++p) {
+ 1472 0 : if (isdigit(*p)) {
+ 1473 0 : smart[SMART_SIZE] *= 10;
+ 1474 0 : smart[SMART_SIZE] += *p - '0';
+ 1475 : }
+ 1476 : }
+ 1477 : }
+ 1478 0 : } else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) {
+ 1479 0 : } else if (sscanf(s, "Device Model: %63s", model) == 1) {
+ 1480 : /* SCSI */
+ 1481 0 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */
+ 1482 0 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) {
+ 1483 0 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) {
+ 1484 0 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) {
+ 1485 0 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) {
+ 1486 0 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) {
+ 1487 0 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) {
+ 1488 : /* ATA */
+ 1489 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
+ 1490 0 : } else if (smatch(s, "ID#") == 0) {
+ 1491 0 : inside = 1;
+ 1492 0 : } else if (smatch(s, "No Errors Logged") == 0) {
+ 1493 0 : smart[SMART_ERROR] = 0;
+ 1494 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
+ 1495 0 : smart[SMART_ERROR] = raw;
+ 1496 0 : } else if (inside) {
+ 1497 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
+ 1498 : /* LCOV_EXCL_START */
+ 1499 : log_fatal("Invalid smartctl line '%s'.\n", s);
+ 1500 : return -1;
+ 1501 : /* LCOV_EXCL_STOP */
+ 1502 : }
+ 1503 :
+ 1504 0 : if (id >= 256) {
+ 1505 : /* LCOV_EXCL_START */
+ 1506 : log_fatal("Invalid SMART id '%u'.\n", id);
+ 1507 : return -1;
+ 1508 : /* LCOV_EXCL_STOP */
+ 1509 : }
+ 1510 :
+ 1511 0 : smart[id] = raw;
+ 1512 : }
+ 1513 0 : }
+ 1514 :
+ 1515 42 : return 0;
+ 1516 : }
+ 1517 :
+ 1518 5 : int smartctl_flush(FILE* f, const char* file, const char* name)
+ 1519 : {
+ 1520 : /* read the file */
+ 1521 : while (1) {
+ 1522 : char buf[256];
+ 1523 : char* s;
+ 1524 :
+ 1525 5 : s = fgets(buf, sizeof(buf), f);
+ 1526 5 : if (s == 0)
+ 1527 5 : break;
+ 1528 :
+ 1529 : /* remove extraneous chars */
+ 1530 0 : s = strpolish(buf);
+ 1531 :
+ 1532 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
+ 1533 0 : }
+ 1534 :
+ 1535 10 : return 0;
+ 1536 : }
+ 1537 :
+ 1538 : /****************************************************************************/
+ 1539 : /* thread */
+ 1540 :
+ 1541 : #if HAVE_PTHREAD
+ 1542 2284 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr)
+ 1543 : {
+ 1544 2284 : if (pthread_mutex_init(mutex, attr) != 0) {
+ 1545 : /* LCOV_EXCL_START */
+ 1546 : log_fatal("Failed call to pthread_mutex_init().\n");
+ 1547 : os_abort();
+ 1548 : /* LCOV_EXCL_STOP */
+ 1549 : }
+ 1550 2284 : }
+ 1551 :
+ 1552 2082 : void thread_mutex_destroy(pthread_mutex_t* mutex)
+ 1553 : {
+ 1554 2082 : if (pthread_mutex_destroy(mutex) != 0) {
+ 1555 : /* LCOV_EXCL_START */
+ 1556 : log_fatal("Failed call to pthread_mutex_destroy().\n");
+ 1557 : os_abort();
+ 1558 : /* LCOV_EXCL_STOP */
+ 1559 : }
+ 1560 2082 : }
+ 1561 :
+ 1562 80853862 : void thread_mutex_lock(pthread_mutex_t* mutex)
+ 1563 : {
+ 1564 80853862 : if (pthread_mutex_lock(mutex) != 0) {
+ 1565 : /* LCOV_EXCL_START */
+ 1566 : log_fatal("Failed call to pthread_mutex_lock().\n");
+ 1567 : os_abort();
+ 1568 : /* LCOV_EXCL_STOP */
+ 1569 : }
+ 1570 80869808 : }
+ 1571 :
+ 1572 80868352 : void thread_mutex_unlock(pthread_mutex_t* mutex)
+ 1573 : {
+ 1574 80868352 : if (pthread_mutex_unlock(mutex) != 0) {
+ 1575 : /* LCOV_EXCL_START */
+ 1576 : log_fatal("Failed call to pthread_mutex_unlock().\n");
+ 1577 : os_abort();
+ 1578 : /* LCOV_EXCL_STOP */
+ 1579 : }
+ 1580 80867931 : }
+ 1581 :
+ 1582 380 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr)
+ 1583 : {
+ 1584 380 : if (pthread_cond_init(cond, attr) != 0) {
+ 1585 : /* LCOV_EXCL_START */
+ 1586 : log_fatal("Failed call to pthread_cond_init().\n");
+ 1587 : os_abort();
+ 1588 : /* LCOV_EXCL_STOP */
+ 1589 : }
+ 1590 380 : }
+ 1591 :
+ 1592 380 : void thread_cond_destroy(pthread_cond_t* cond)
+ 1593 : {
+ 1594 380 : if (pthread_cond_destroy(cond) != 0) {
+ 1595 : /* LCOV_EXCL_START */
+ 1596 : log_fatal("Failed call to pthread_cond_destroy().\n");
+ 1597 : os_abort();
+ 1598 : /* LCOV_EXCL_STOP */
+ 1599 : }
+ 1600 380 : }
+ 1601 :
+ 1602 87081 : void thread_cond_signal(pthread_cond_t* cond)
+ 1603 : {
+ 1604 87081 : if (pthread_cond_signal(cond) != 0) {
+ 1605 : /* LCOV_EXCL_START */
+ 1606 : log_fatal("Failed call to pthread_cond_signal().\n");
+ 1607 : os_abort();
+ 1608 : /* LCOV_EXCL_STOP */
+ 1609 : }
+ 1610 87081 : }
1611 :
- 1612 85887 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
+ 1612 255615 : void thread_cond_broadcast(pthread_cond_t* cond)
1613 : {
- 1614 85887 : if (thread_cond_signal_outside) {
- 1615 : /* without the thread checker unlock before signaling, */
- 1616 : /* this reduces the number of context switches */
- 1617 0 : thread_mutex_unlock(mutex);
- 1618 : }
- 1619 :
- 1620 85887 : thread_cond_signal(cond);
+ 1614 255615 : if (pthread_cond_broadcast(cond) != 0) {
+ 1615 : /* LCOV_EXCL_START */
+ 1616 : log_fatal("Failed call to pthread_cond_broadcast().\n");
+ 1617 : os_abort();
+ 1618 : /* LCOV_EXCL_STOP */
+ 1619 : }
+ 1620 255615 : }
1621 :
- 1622 85887 : if (!thread_cond_signal_outside) {
- 1623 : /* with the thread checker unlock after signaling */
- 1624 : /* to make explicit the condition and mutex relation */
- 1625 85887 : thread_mutex_unlock(mutex);
- 1626 : }
- 1627 85887 : }
- 1628 :
- 1629 255313 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
- 1630 : {
- 1631 255313 : if (thread_cond_signal_outside) {
- 1632 : /* without the thread checker unlock before signaling, */
- 1633 : /* this reduces the number of context switches */
- 1634 0 : thread_mutex_unlock(mutex);
- 1635 : }
- 1636 :
- 1637 255313 : thread_cond_broadcast(cond);
- 1638 :
- 1639 255313 : if (!thread_cond_signal_outside) {
- 1640 : /* with the thread checker unlock after signaling */
- 1641 : /* to make explicit the condition and mutex relation */
- 1642 255313 : thread_mutex_unlock(mutex);
- 1643 : }
- 1644 255313 : }
- 1645 :
- 1646 2200 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg)
- 1647 : {
- 1648 2200 : if (pthread_create(thread, attr, func, arg) != 0) {
- 1649 : /* LCOV_EXCL_START */
- 1650 : log_fatal("Failed call to pthread_create().\n");
- 1651 : os_abort();
- 1652 : /* LCOV_EXCL_STOP */
- 1653 : }
- 1654 2200 : }
+ 1622 1125039 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
+ 1623 : {
+ 1624 1125039 : if (pthread_cond_wait(cond, mutex) != 0) {
+ 1625 : /* LCOV_EXCL_START */
+ 1626 : log_fatal("Failed call to pthread_cond_wait().\n");
+ 1627 : os_abort();
+ 1628 : /* LCOV_EXCL_STOP */
+ 1629 : }
+ 1630 1125039 : }
+ 1631 :
+ 1632 : /**
+ 1633 : * Implementation note about conditional variables.
+ 1634 : *
+ 1635 : * The conditional variables can be signaled inside or ouside the mutex,
+ 1636 : * what is better it's debatable but in general doing that ouside the mutex,
+ 1637 : * reduces the number of context switches.
+ 1638 : *
+ 1639 : * But when when testing with helgrind and drd, this disallows such tools to
+ 1640 : * to see the dependency between the signal and the wait.
+ 1641 : *
+ 1642 : * To avoid it we signal everything inside the mutex. And we do this in both
+ 1643 : * test mode (with CHERCKER defined) and release mode (CHECKER not defined),
+ 1644 : * to be on the safe side and avoid any difference in beaviour between test and
+ 1645 : * release.
+ 1646 : *
+ 1647 : * Here some interesting discussion:
+ 1648 : *
+ 1649 : * Condvars: signal with mutex locked or not?
+ 1650 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/
+ 1651 : *
+ 1652 : * Calling pthread_cond_signal without locking mutex
+ 1653 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494
+ 1654 : */
1655 :
- 1656 2200 : void thread_join(pthread_t thread, void** retval)
- 1657 : {
- 1658 2200 : if (pthread_join(thread, retval) != 0) {
- 1659 : /* LCOV_EXCL_START */
- 1660 : log_fatal("Failed call to pthread_join().\n");
- 1661 : os_abort();
- 1662 : /* LCOV_EXCL_STOP */
- 1663 : }
- 1664 2200 : }
- 1665 :
- 1666 : #endif
- 1667 :
+ 1656 : /**
+ 1657 : * Control when to signal the condition variables.
+ 1658 : */
+ 1659 : int thread_cond_signal_outside = 0;
+ 1660 :
+ 1661 87081 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
+ 1662 : {
+ 1663 87081 : if (thread_cond_signal_outside) {
+ 1664 : /* without the thread checker unlock before signaling, */
+ 1665 : /* this reduces the number of context switches */
+ 1666 0 : thread_mutex_unlock(mutex);
+ 1667 : }
+ 1668 :
+ 1669 87081 : thread_cond_signal(cond);
+ 1670 :
+ 1671 87081 : if (!thread_cond_signal_outside) {
+ 1672 : /* with the thread checker unlock after signaling */
+ 1673 : /* to make explicit the condition and mutex relation */
+ 1674 87081 : thread_mutex_unlock(mutex);
+ 1675 : }
+ 1676 87081 : }
+ 1677 :
+ 1678 255425 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
+ 1679 : {
+ 1680 255425 : if (thread_cond_signal_outside) {
+ 1681 : /* without the thread checker unlock before signaling, */
+ 1682 : /* this reduces the number of context switches */
+ 1683 0 : thread_mutex_unlock(mutex);
+ 1684 : }
+ 1685 :
+ 1686 255425 : thread_cond_broadcast(cond);
+ 1687 :
+ 1688 255425 : if (!thread_cond_signal_outside) {
+ 1689 : /* with the thread checker unlock after signaling */
+ 1690 : /* to make explicit the condition and mutex relation */
+ 1691 255425 : thread_mutex_unlock(mutex);
+ 1692 : }
+ 1693 255425 : }
+ 1694 :
+ 1695 2200 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg)
+ 1696 : {
+ 1697 2200 : if (pthread_create(thread, attr, func, arg) != 0) {
+ 1698 : /* LCOV_EXCL_START */
+ 1699 : log_fatal("Failed call to pthread_create().\n");
+ 1700 : os_abort();
+ 1701 : /* LCOV_EXCL_STOP */
+ 1702 : }
+ 1703 2200 : }
+ 1704 :
+ 1705 2200 : void thread_join(pthread_t thread, void** retval)
+ 1706 : {
+ 1707 2200 : if (pthread_join(thread, retval) != 0) {
+ 1708 : /* LCOV_EXCL_START */
+ 1709 : log_fatal("Failed call to pthread_join().\n");
+ 1710 : os_abort();
+ 1711 : /* LCOV_EXCL_STOP */
+ 1712 : }
+ 1713 2200 : }
+ 1714 :
+ 1715 : #endif
+ 1716 :
diff --git a/cov/cmdline/support.h.func-sort-c.html b/cov/cmdline/support.h.func-sort-c.html
index 72186336..6a3d8670 100644
--- a/cov/cmdline/support.h.func-sort-c.html
+++ b/cov/cmdline/support.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| esc_shell |
- 331854 |
+ 332092 |
diff --git a/cov/cmdline/support.h.func.html b/cov/cmdline/support.h.func.html
index 4d39d629..5d667b6c 100644
--- a/cov/cmdline/support.h.func.html
+++ b/cov/cmdline/support.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| esc_shell |
- 331854 |
+ 332092 |
diff --git a/cov/cmdline/support.h.gcov.html b/cov/cmdline/support.h.gcov.html
index 48fbc42d..2951cbc8 100644
--- a/cov/cmdline/support.h.gcov.html
+++ b/cov/cmdline/support.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -291,9 +291,9 @@
229 : * \param buffer Preallocated buffer of ESC_MAX size.
230 : */
231 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer);
- 232 331854 : static inline const char* esc_shell(const char* str, char* buffer)
+ 232 332092 : static inline const char* esc_shell(const char* str, char* buffer)
233 : {
- 234 331854 : return esc_shell_multi(&str, 1, buffer);
+ 234 332092 : return esc_shell_multi(&str, 1, buffer);
235 : }
236 :
237 : /**
@@ -384,113 +384,119 @@
322 : */
323 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
324 :
- 325 : /****************************************************************************/
- 326 : /* advise */
- 327 :
- 328 : /**
- 329 : * Advise modes.
- 330 : */
- 331 : #define ADVISE_DEFAULT 0 /**< Default mode. */
- 332 : #define ADVISE_NONE 1 /**< Bare read/write mode. */
- 333 : #define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */
- 334 : #define ADVISE_FLUSH 3 /**< Flush mode. */
- 335 : #define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */
- 336 : #define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */
- 337 : #define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */
- 338 : #define ADVISE_DIRECT 7 /**< Direct mode. */
- 339 :
- 340 : #define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */
- 341 :
- 342 : struct advise_struct {
- 343 : int mode;
- 344 : data_off_t dirty_begin;
- 345 : data_off_t dirty_end;
- 346 : };
+ 325 : /**
+ 326 : * Change the modification time of a file or link.
+ 327 : * Note that links are NOT deferenced.
+ 328 : */
+ 329 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec);
+ 330 :
+ 331 : /****************************************************************************/
+ 332 : /* advise */
+ 333 :
+ 334 : /**
+ 335 : * Advise modes.
+ 336 : */
+ 337 : #define ADVISE_DEFAULT 0 /**< Default mode. */
+ 338 : #define ADVISE_NONE 1 /**< Bare read/write mode. */
+ 339 : #define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */
+ 340 : #define ADVISE_FLUSH 3 /**< Flush mode. */
+ 341 : #define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */
+ 342 : #define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */
+ 343 : #define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */
+ 344 : #define ADVISE_DIRECT 7 /**< Direct mode. */
+ 345 :
+ 346 : #define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */
347 :
- 348 : void advise_init(struct advise_struct* advise, int mode);
- 349 : int advise_flags(struct advise_struct* advise);
- 350 : int advise_open(struct advise_struct* advise, int f);
- 351 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size);
- 352 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size);
+ 348 : struct advise_struct {
+ 349 : int mode;
+ 350 : data_off_t dirty_begin;
+ 351 : data_off_t dirty_end;
+ 352 : };
353 :
- 354 : /****************************************************************************/
- 355 : /* memory */
- 356 :
- 357 : /**
- 358 : * Return the size of the allocated memory.
- 359 : */
- 360 : size_t malloc_counter_get(void);
- 361 :
- 362 : /**
- 363 : * Safe malloc.
- 364 : * If no memory is available, it aborts.
+ 354 : void advise_init(struct advise_struct* advise, int mode);
+ 355 : int advise_flags(struct advise_struct* advise);
+ 356 : int advise_open(struct advise_struct* advise, int f);
+ 357 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size);
+ 358 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size);
+ 359 :
+ 360 : /****************************************************************************/
+ 361 : /* memory */
+ 362 :
+ 363 : /**
+ 364 : * Return the size of the allocated memory.
365 : */
- 366 : void* malloc_nofail(size_t size);
+ 366 : size_t malloc_counter_get(void);
367 :
368 : /**
- 369 : * Safe cmalloc.
+ 369 : * Safe malloc.
370 : * If no memory is available, it aborts.
371 : */
- 372 : void* calloc_nofail(size_t count, size_t size);
+ 372 : void* malloc_nofail(size_t size);
373 :
374 : /**
- 375 : * Safe strdup.
+ 375 : * Safe cmalloc.
376 : * If no memory is available, it aborts.
377 : */
- 378 : char* strdup_nofail(const char* str);
+ 378 : void* calloc_nofail(size_t count, size_t size);
379 :
380 : /**
- 381 : * Helper for printing an error about a failed allocation.
- 382 : */
- 383 : void malloc_fail(size_t size);
- 384 :
- 385 : /****************************************************************************/
- 386 : /* smartctl */
- 387 :
- 388 : /**
- 389 : * Read smartctl attributes from a stream.
- 390 : * Return 0 on success.
- 391 : */
- 392 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model);
+ 381 : * Safe strdup.
+ 382 : * If no memory is available, it aborts.
+ 383 : */
+ 384 : char* strdup_nofail(const char* str);
+ 385 :
+ 386 : /**
+ 387 : * Helper for printing an error about a failed allocation.
+ 388 : */
+ 389 : void malloc_fail(size_t size);
+ 390 :
+ 391 : /****************************************************************************/
+ 392 : /* smartctl */
393 :
394 : /**
- 395 : * Flush smartctl output from a stream.
- 396 : */
- 397 : int smartctl_flush(FILE* f, const char* file, const char* name);
- 398 :
- 399 : /****************************************************************************/
- 400 : /* thread */
- 401 :
- 402 : #if HAVE_PTHREAD
- 403 : /**
- 404 : * Control when to signal the condition variables.
- 405 : *
- 406 : * Default is inside the mutex.
- 407 : *
- 408 : * Ensure to change that before starting any thread.
- 409 : */
- 410 : int thread_cond_signal_outside;
- 411 :
- 412 : /**
- 413 : * Thread wrappers to handle error conditions.
- 414 : */
- 415 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr);
- 416 : void thread_mutex_destroy(pthread_mutex_t* mutex);
- 417 : void thread_mutex_lock(pthread_mutex_t* mutex);
- 418 : void thread_mutex_unlock(pthread_mutex_t* mutex);
- 419 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr);
- 420 : void thread_cond_destroy(pthread_cond_t* cond);
- 421 : void thread_cond_signal(pthread_cond_t* cond);
- 422 : void thread_cond_broadcast(pthread_cond_t* cond);
- 423 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
- 424 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
- 425 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
- 426 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg);
- 427 : void thread_join(pthread_t thread, void** retval);
- 428 : #endif
- 429 :
- 430 : #endif
- 431 :
+ 395 : * Read smartctl attributes from a stream.
+ 396 : * Return 0 on success.
+ 397 : */
+ 398 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model);
+ 399 :
+ 400 : /**
+ 401 : * Flush smartctl output from a stream.
+ 402 : */
+ 403 : int smartctl_flush(FILE* f, const char* file, const char* name);
+ 404 :
+ 405 : /****************************************************************************/
+ 406 : /* thread */
+ 407 :
+ 408 : #if HAVE_PTHREAD
+ 409 : /**
+ 410 : * Control when to signal the condition variables.
+ 411 : *
+ 412 : * Default is inside the mutex.
+ 413 : *
+ 414 : * Ensure to change that before starting any thread.
+ 415 : */
+ 416 : int thread_cond_signal_outside;
+ 417 :
+ 418 : /**
+ 419 : * Thread wrappers to handle error conditions.
+ 420 : */
+ 421 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr);
+ 422 : void thread_mutex_destroy(pthread_mutex_t* mutex);
+ 423 : void thread_mutex_lock(pthread_mutex_t* mutex);
+ 424 : void thread_mutex_unlock(pthread_mutex_t* mutex);
+ 425 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr);
+ 426 : void thread_cond_destroy(pthread_cond_t* cond);
+ 427 : void thread_cond_signal(pthread_cond_t* cond);
+ 428 : void thread_cond_broadcast(pthread_cond_t* cond);
+ 429 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
+ 430 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
+ 431 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
+ 432 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg);
+ 433 : void thread_join(pthread_t thread, void** retval);
+ 434 : #endif
+ 435 :
+ 436 : #endif
+ 437 :
diff --git a/cov/cmdline/sync.c.func-sort-c.html b/cov/cmdline/sync.c.func-sort-c.html
index ed4b5461..f39e3139 100644
--- a/cov/cmdline/sync.c.func-sort-c.html
+++ b/cov/cmdline/sync.c.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -65,11 +65,11 @@
| sync_data_reader |
- 688232 |
+ 688270 |
| sync_parity_writer |
- 544522 |
+ 544910 |
| failed_compare_by_index |
diff --git a/cov/cmdline/sync.c.func.html b/cov/cmdline/sync.c.func.html
index 0c8a6dfb..c356fd8c 100644
--- a/cov/cmdline/sync.c.func.html
+++ b/cov/cmdline/sync.c.func.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -81,11 +81,11 @@
| sync_data_reader |
- 688232 |
+ 688270 |
| sync_parity_writer |
- 544522 |
+ 544910 |
diff --git a/cov/cmdline/sync.c.gcov.html b/cov/cmdline/sync.c.gcov.html
index 465c441c..56bab884 100644
--- a/cov/cmdline/sync.c.gcov.html
+++ b/cov/cmdline/sync.c.gcov.html
@@ -31,13 +31,13 @@
|
-
+
-
+
-
+
|
@@ -483,9 +483,9 @@
421 852 : const struct failed_struct* b = void_b;
422 :
423 852 : if (a->index < b->index)
- 424 850 : return -1;
- 425 2 : if (a->index > b->index)
- 426 2 : return 1;
+ 424 852 : return -1;
+ 425 0 : if (a->index > b->index)
+ 426 0 : return 1;
427 0 : return 0;
428 : }
429 :
@@ -524,56 +524,56 @@
462 4688742 : one_valid = 1;
463 :
464 4911646 : if (block_has_invalid_parity(block) || plan->force_full)
- 465 753240 : one_invalid = 1;
+ 465 753392 : one_invalid = 1;
466 : }
467 :
468 : /* if none valid or none invalid, we don't need to update */
469 820170 : if (!one_invalid || !one_valid)
- 470 590712 : return 0;
+ 470 590600 : return 0;
471 :
- 472 229458 : return 1;
+ 472 229570 : return 1;
473 : }
474 :
- 475 688232 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
+ 475 688270 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
476 : {
- 477 688232 : struct snapraid_io* io = worker->io;
- 478 688232 : struct snapraid_state* state = io->state;
- 479 688232 : struct snapraid_handle* handle = worker->handle;
- 480 688232 : struct snapraid_disk* disk = handle->disk;
- 481 688232 : block_off_t blockcur = task->position;
- 482 688232 : unsigned char* buffer = task->buffer;
+ 477 688270 : struct snapraid_io* io = worker->io;
+ 478 688270 : struct snapraid_state* state = io->state;
+ 479 688270 : struct snapraid_handle* handle = worker->handle;
+ 480 688270 : struct snapraid_disk* disk = handle->disk;
+ 481 688270 : block_off_t blockcur = task->position;
+ 482 688270 : unsigned char* buffer = task->buffer;
483 : int ret;
484 : char esc_buffer[ESC_MAX];
485 :
486 : /* if the disk position is not used */
- 487 688232 : if (!disk) {
+ 487 688270 : if (!disk) {
488 : /* use an empty block */
489 0 : memset(buffer, 0, state->block_size);
490 0 : task->state = TASK_STATE_DONE;
- 491 92183 : return;
+ 491 92084 : return;
492 : }
493 :
494 : /* get the block */
- 495 688237 : task->block = fs_par2block_find(disk, blockcur);
+ 495 688275 : task->block = fs_par2block_find(disk, blockcur);
496 :
497 : /* if the block has no file, meaning that it's EMPTY or DELETED, */
498 : /* it doesn't participate in the new parity computation */
- 499 688177 : if (!block_has_file(task->block)) {
+ 499 688010 : if (!block_has_file(task->block)) {
500 : /* use an empty block */
- 501 92175 : memset(buffer, 0, state->block_size);
- 502 92175 : task->state = TASK_STATE_DONE;
- 503 92175 : return;
+ 501 92076 : memset(buffer, 0, state->block_size);
+ 502 92076 : task->state = TASK_STATE_DONE;
+ 503 92076 : return;
504 : }
505 :
506 : /* get the file of this block */
- 507 595953 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
+ 507 595621 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos);
508 :
509 : /* if the file is different than the current one, close it */
- 510 596099 : if (handle->file != 0 && handle->file != task->file) {
+ 510 596270 : if (handle->file != 0 && handle->file != task->file) {
511 : /* keep a pointer at the file we are going to close for error reporting */
- 512 246100 : struct snapraid_file* report = handle->file;
- 513 246100 : ret = handle_close(handle);
- 514 246014 : if (ret == -1) {
+ 512 246082 : struct snapraid_file* report = handle->file;
+ 513 246082 : ret = handle_close(handle);
+ 514 245642 : if (ret == -1) {
515 : /* LCOV_EXCL_START */
516 : /* This one is really an unexpected error, because we are only reading */
517 : /* and closing a descriptor should never fail */
@@ -596,8 +596,8 @@
534 : }
535 : }
536 :
- 537 596013 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
- 538 596027 : if (ret == -1) {
+ 537 595830 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
+ 538 591402 : if (ret == -1) {
539 12 : if (errno == EIO) {
540 : /* LCOV_EXCL_START */
541 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
@@ -641,10 +641,10 @@
579 : }
580 :
581 : /* check if the file is changed */
- 582 596015 : if (handle->st.st_size != task->file->size
- 583 596023 : || handle->st.st_mtime != task->file->mtime_sec
- 584 596052 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec
- 585 596047 : || handle->st.st_ino != task->file->inode
+ 582 591390 : if (handle->st.st_size != task->file->size
+ 583 592816 : || handle->st.st_mtime != task->file->mtime_sec
+ 584 594857 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec
+ 585 595324 : || handle->st.st_ino != task->file->inode
586 : ) {
587 0 : log_tag("error:%u:%s:%s: Unexpected attribute change\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer));
588 6 : if (handle->st.st_size != task->file->size) {
@@ -663,8 +663,8 @@
601 6 : return;
602 : }
603 :
- 604 596041 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
- 605 595681 : if (task->read_size == -1) {
+ 604 594859 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
+ 605 592671 : if (task->read_size == -1) {
606 : /* LCOV_EXCL_START */
607 : if (errno == EIO) {
608 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
@@ -683,24 +683,24 @@
621 : }
622 :
623 : /* store the path of the opened file */
- 624 595681 : pathcpy(task->path, sizeof(task->path), handle->path);
+ 624 592671 : pathcpy(task->path, sizeof(task->path), handle->path);
625 :
- 626 595979 : task->state = TASK_STATE_DONE;
+ 626 588699 : task->state = TASK_STATE_DONE;
627 : }
628 :
- 629 544522 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task)
+ 629 544910 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task)
630 : {
- 631 544522 : struct snapraid_io* io = worker->io;
- 632 544522 : struct snapraid_state* state = io->state;
- 633 544522 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
- 634 544522 : unsigned level = parity_handle->level;
- 635 544522 : block_off_t blockcur = task->position;
- 636 544522 : unsigned char* buffer = task->buffer;
+ 631 544910 : struct snapraid_io* io = worker->io;
+ 632 544910 : struct snapraid_state* state = io->state;
+ 633 544910 : struct snapraid_parity_handle* parity_handle = worker->parity_handle;
+ 634 544910 : unsigned level = parity_handle->level;
+ 635 544910 : block_off_t blockcur = task->position;
+ 636 544910 : unsigned char* buffer = task->buffer;
637 : int ret;
638 :
639 : /* write parity */
- 640 544522 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size);
- 641 544519 : if (ret == -1) {
+ 640 544910 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size);
+ 641 544712 : if (ret == -1) {
642 : /* LCOV_EXCL_START */
643 : if (errno == EIO) {
644 : log_tag("parity_error:%u:%s: Write EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
@@ -718,7 +718,7 @@
656 : /* LCOV_EXCL_STOP */
657 : }
658 :
- 659 544519 : task->state = TASK_STATE_DONE;
+ 659 544712 : task->state = TASK_STATE_DONE;
660 : }
661 :
662 83 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax)
@@ -799,8 +799,8 @@
737 83 : plan.force_full = state->opt.force_full;
738 410168 : for (blockcur = blockstart; blockcur < blockmax; ++blockcur) {
739 410085 : if (!block_is_enabled(&plan, blockcur))
- 740 295356 : continue;
- 741 114729 : ++countmax;
+ 740 295300 : continue;
+ 741 114785 : ++countmax;
742 : }
743 :
744 : /* compute the autosave size for all disk, even if not read */
@@ -836,31 +836,31 @@
774 : int writer_error[IO_WRITER_ERROR_MAX];
775 :
776 : /* go to the next block */
- 777 114812 : blockcur = io_read_next(&io, &buffer);
- 778 114812 : if (blockcur >= blockmax)
+ 777 114868 : blockcur = io_read_next(&io, &buffer);
+ 778 114868 : if (blockcur >= blockmax)
779 166 : break;
780 :
781 : /* until now is scheduling */
- 782 114729 : state_usage_sched(state);
+ 782 114785 : state_usage_sched(state);
783 :
784 : /* one more block processed for autosave */
- 785 114729 : ++autosavedone;
- 786 114729 : --autosavemissing;
+ 785 114785 : ++autosavedone;
+ 786 114785 : --autosavemissing;
787 :
788 : /* by default process the block, and skip it if something goes wrong */
- 789 114729 : error_on_this_block = 0;
- 790 114729 : silent_error_on_this_block = 0;
- 791 114729 : io_error_on_this_block = 0;
- 792 114729 : fixed_error_on_this_block = 0;
+ 789 114785 : error_on_this_block = 0;
+ 790 114785 : silent_error_on_this_block = 0;
+ 791 114785 : io_error_on_this_block = 0;
+ 792 114785 : fixed_error_on_this_block = 0;
793 :
794 : /* keep track of the number of failed blocks */
- 795 114729 : failed_count = 0;
+ 795 114785 : failed_count = 0;
796 :
797 : /* get block specific info */
- 798 114729 : info = info_get(&state->infoarr, blockcur);
+ 798 114785 : info = info_get(&state->infoarr, blockcur);
799 :
800 : /* if we have to use the old hash */
- 801 114729 : rehash = info_get_rehash(info);
+ 801 114785 : rehash = info_get_rehash(info);
802 :
803 : /* if the parity requires to be updated */
804 : /* It could happens that all the blocks are EMPTY/BLK and CHG but with the hash */
@@ -869,18 +869,18 @@
807 : /* Note that CHG/DELETED blocks already present in the content file loaded */
808 : /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */
809 : /* We are treating only CHG blocks created at runtime. */
- 810 114729 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update;
+ 810 114785 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update;
811 :
812 : /* if the parity is going to be updated */
- 813 114729 : parity_going_to_be_updated = 0;
+ 813 114785 : parity_going_to_be_updated = 0;
814 :
815 : /* if the block is marked as bad, we force the parity update */
816 : /* because the bad block may be the result of a wrong parity */
- 817 114729 : if (info_get_bad(info))
+ 817 114785 : if (info_get_bad(info))
818 0 : parity_needs_to_be_updated = 1;
819 :
820 : /* for each disk, process the block */
- 821 803103 : for (j = 0; j < diskmax; ++j) {
+ 821 803495 : for (j = 0; j < diskmax; ++j) {
822 : struct snapraid_task* task;
823 : int read_size;
824 : unsigned char hash[HASH_MAX];
@@ -892,45 +892,45 @@
830 : unsigned diskcur;
831 :
832 : /* until now is misc */
- 833 688374 : state_usage_misc(state);
+ 833 688710 : state_usage_misc(state);
834 :
- 835 688374 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
+ 835 688710 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
836 :
837 : /* until now is disk */
- 838 688374 : state_usage_disk(state, handle, waiting_map, waiting_mac);
+ 838 688710 : state_usage_disk(state, handle, waiting_map, waiting_mac);
839 :
840 : /* get the results */
- 841 688374 : disk = task->disk;
- 842 688374 : block = task->block;
- 843 688374 : file = task->file;
- 844 688374 : file_pos = task->file_pos;
- 845 688374 : read_size = task->read_size;
+ 841 688710 : disk = task->disk;
+ 842 688710 : block = task->block;
+ 843 688710 : file = task->file;
+ 844 688710 : file_pos = task->file_pos;
+ 845 688710 : read_size = task->read_size;
846 :
847 : /* by default no rehash in case of "continue" */
- 848 688374 : rehandle[diskcur].block = 0;
+ 848 688710 : rehandle[diskcur].block = 0;
849 :
850 : /* if the disk position is not used */
- 851 688374 : if (!disk)
- 852 93074 : continue;
+ 851 688710 : if (!disk)
+ 852 93042 : continue;
853 :
854 : /* get the state of the block */
- 855 688374 : block_state = block_state_get(block);
+ 855 688710 : block_state = block_state_get(block);
856 :
857 : /* if the block has invalid parity, */
858 : /* we have to take care of it in case of recover */
- 859 688374 : if (block_has_invalid_parity(block)) {
+ 859 688710 : if (block_has_invalid_parity(block)) {
860 : /* store it in the failed set, because */
861 : /* the parity may be still computed with the previous content */
- 862 182822 : failed[failed_count].index = diskcur;
- 863 182822 : failed[failed_count].size = state->block_size;
- 864 182822 : failed[failed_count].block = block;
- 865 182822 : ++failed_count;
+ 862 182898 : failed[failed_count].index = diskcur;
+ 863 182898 : failed[failed_count].size = state->block_size;
+ 864 182898 : failed[failed_count].block = block;
+ 865 182898 : ++failed_count;
866 :
867 : /* if the block has invalid parity, we have to update the parity */
868 : /* to include this block change */
869 : /* This also apply to CHG blocks, but we are going to handle */
870 : /* later this case to do the updates only if really needed */
- 871 182822 : if (block_state != BLOCK_STATE_CHG)
+ 871 182898 : if (block_state != BLOCK_STATE_CHG)
872 88225 : parity_needs_to_be_updated = 1;
873 :
874 : /* note that DELETE blocks are skipped in the next check */
@@ -941,28 +941,28 @@
879 : }
880 :
881 : /* if the block is not used */
- 882 688374 : if (!block_has_file(block))
- 883 92203 : continue;
+ 882 688710 : if (!block_has_file(block))
+ 883 92171 : continue;
884 :
885 : /* handle error conditions */
- 886 596171 : if (task->state == TASK_STATE_IOERROR) {
+ 886 596539 : if (task->state == TASK_STATE_IOERROR) {
887 : /* LCOV_EXCL_START */
888 : ++io_error;
889 : goto bail;
890 : /* LCOV_EXCL_STOP */
891 : }
- 892 596171 : if (task->state == TASK_STATE_ERROR) {
+ 892 596539 : if (task->state == TASK_STATE_ERROR) {
893 : /* LCOV_EXCL_START */
894 : ++error;
895 : goto bail;
896 : /* LCOV_EXCL_STOP */
897 : }
- 898 596171 : if (task->state == TASK_STATE_ERROR_CONTINUE) {
+ 898 596539 : if (task->state == TASK_STATE_ERROR_CONTINUE) {
899 18 : ++error;
900 18 : error_on_this_block = 1;
901 18 : continue;
902 : }
- 903 596153 : if (task->state == TASK_STATE_IOERROR_CONTINUE) {
+ 903 596521 : if (task->state == TASK_STATE_IOERROR_CONTINUE) {
904 0 : ++io_error;
905 0 : if (io_error >= state->opt.io_error_limit) {
906 : /* LCOV_EXCL_START */
@@ -977,32 +977,32 @@
915 0 : io_error_on_this_block = 1;
916 0 : continue;
917 : }
- 918 596153 : if (task->state != TASK_STATE_DONE) {
+ 918 596521 : if (task->state != TASK_STATE_DONE) {
919 : /* LCOV_EXCL_START */
920 : log_fatal("Internal inconsistency in task state\n");
921 : os_abort();
922 : /* LCOV_EXCL_STOP */
923 : }
924 :
- 925 596153 : countsize += read_size;
+ 925 596521 : countsize += read_size;
926 :
927 : /* now compute the hash */
- 928 596153 : if (rehash) {
+ 928 596521 : if (rehash) {
929 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[diskcur], read_size);
930 :
931 : /* compute the new hash, and store it */
932 27243 : rehandle[diskcur].block = block;
933 27243 : memhash(state->hash, state->hashseed, rehandle[diskcur].hash, buffer[diskcur], read_size);
934 : } else {
- 935 568910 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
+ 935 569278 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
936 : }
937 :
938 : /* until now is hash */
- 939 596153 : state_usage_hash(state);
+ 939 596521 : state_usage_hash(state);
940 :
- 941 596153 : if (block_has_updated_hash(block)) {
+ 941 596521 : if (block_has_updated_hash(block)) {
942 : /* compare the hash */
- 943 501574 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
+ 943 501866 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
944 : /* if the file has invalid parity, it's a REP changed during the sync */
945 853 : if (block_has_invalid_parity(block)) {
946 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer));
@@ -1026,8 +1026,8 @@
964 1 : continue;
965 : } else { /* otherwise it's a BLK with silent error */
966 852 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE);
- 967 852 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff);
- 968 852 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", task->path, file_pos, diff);
+ 967 852 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8);
+ 968 852 : log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE*8);
969 :
970 : /* save the failed block for the fix */
971 852 : failed[failed_count].index = diskcur;
@@ -1045,28 +1045,28 @@
983 : }
984 : } else {
985 : /* if until now the parity doesn't need to be updated */
- 986 94579 : if (!parity_needs_to_be_updated) {
+ 986 94655 : if (!parity_needs_to_be_updated) {
987 : /* for sure it's a CHG block, because EMPTY are processed before with "continue" */
988 : /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */
989 : /* have "parity_needs_to_be_updated" already at 1 */
- 990 35226 : assert(block_state_get(block) == BLOCK_STATE_CHG);
+ 990 35282 : assert(block_state_get(block) == BLOCK_STATE_CHG);
991 :
992 : /* if the hash represents the data unequivocally */
- 993 35226 : if (hash_is_unique(block->hash)) {
+ 993 35282 : if (hash_is_unique(block->hash)) {
994 : /* check if the hash is changed */
- 995 8551 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
+ 995 8608 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) {
996 : /* the block is different, and we must update parity */
- 997 6039 : parity_needs_to_be_updated = 1;
+ 997 6111 : parity_needs_to_be_updated = 1;
998 : }
999 : } else {
1000 : /* if the hash is already invalid, we update parity */
- 1001 26675 : parity_needs_to_be_updated = 1;
+ 1001 26674 : parity_needs_to_be_updated = 1;
1002 : }
1003 : }
1004 :
1005 : /* copy the hash in the block, but doesn't mark the block as hashed */
1006 : /* this allow in case of skipped block to do not save the failed computation */
- 1007 94579 : memcpy(block->hash, hash, BLOCK_HASH_SIZE);
+ 1007 94655 : memcpy(block->hash, hash, BLOCK_HASH_SIZE);
1008 :
1009 : /* note that in case of rehash, this is the wrong hash, */
1010 : /* but it will be overwritten later */
@@ -1076,7 +1076,7 @@
1014 : /* if we have only silent errors we can try to fix them on-the-fly */
1015 : /* note the the fix is not written to disk, but used only to */
1016 : /* compute the new parity */
- 1017 114729 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) {
+ 1017 114785 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) {
1018 : unsigned failed_mac;
1019 852 : int something_to_recover = 0;
1020 :
@@ -1213,44 +1213,44 @@
1151 : }
1152 :
1153 : /* if we have read all the data required and it's correct, proceed with the parity */
- 1154 114729 : if (!error_on_this_block && !io_error_on_this_block
- 1155 114710 : && (!silent_error_on_this_block || fixed_error_on_this_block)
+ 1154 114785 : if (!error_on_this_block && !io_error_on_this_block
+ 1155 114766 : && (!silent_error_on_this_block || fixed_error_on_this_block)
1156 : ) {
1157 : /* update the parity only if really needed */
- 1158 114710 : if (parity_needs_to_be_updated) {
+ 1158 114766 : if (parity_needs_to_be_updated) {
1159 : /* compute the parity */
- 1160 112438 : raid_gen(diskmax, state->level, state->block_size, buffer);
+ 1160 112510 : raid_gen(diskmax, state->level, state->block_size, buffer);
1161 :
1162 : /* until now is raid */
- 1163 112438 : state_usage_raid(state);
+ 1163 112510 : state_usage_raid(state);
1164 :
1165 : /* mark that the parity is going to be written */
- 1166 112438 : parity_going_to_be_updated = 1;
+ 1166 112510 : parity_going_to_be_updated = 1;
1167 : }
1168 :
1169 : /* for each disk, mark the blocks as processed */
- 1170 802970 : for (j = 0; j < diskmax; ++j) {
+ 1170 803362 : for (j = 0; j < diskmax; ++j) {
1171 : struct snapraid_block* block;
1172 :
- 1173 688260 : if (!handle[j].disk)
+ 1173 688596 : if (!handle[j].disk)
1174 0 : continue;
1175 :
- 1176 688260 : block = fs_par2block_find(handle[j].disk, blockcur);
+ 1176 688596 : block = fs_par2block_find(handle[j].disk, blockcur);
1177 :
- 1178 688260 : if (block == BLOCK_NULL) {
+ 1178 688596 : if (block == BLOCK_NULL) {
1179 : /* nothing to do */
- 1180 81248 : continue;
+ 1180 81216 : continue;
1181 : }
1182 :
1183 : /* if it's a deleted block */
- 1184 607012 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
+ 1184 607380 : if (block_state_get(block) == BLOCK_STATE_DELETED) {
1185 : /* the parity is now updated without this block, so it's now empty */
1186 10953 : fs_deallocate(handle[j].disk, blockcur);
1187 10953 : continue;
1188 : }
1189 :
1190 : /* now all the blocks have the hash and the parity computed */
- 1191 596059 : block_state_set(block, BLOCK_STATE_BLK);
+ 1191 596427 : block_state_set(block, BLOCK_STATE_BLK);
1192 : }
1193 :
1194 : /* we update the info block only if we really have updated the parity */
@@ -1258,11 +1258,11 @@
1196 : /* wrote the parity at this time */
1197 : /* we also update the info block only if no silent error was found */
1198 : /* because has no sense to refresh the time for data that we know bad */
- 1199 114710 : if (parity_needs_to_be_updated
- 1200 112438 : && !silent_error_on_this_block
+ 1199 114766 : if (parity_needs_to_be_updated
+ 1200 112510 : && !silent_error_on_this_block
1201 : ) {
1202 : /* if rehash is needed */
- 1203 112099 : if (rehash) {
+ 1203 112174 : if (rehash) {
1204 : /* store all the new hash already computed */
1205 32249 : for (j = 0; j < diskmax; ++j) {
1206 27642 : if (rehandle[j].block)
@@ -1272,14 +1272,14 @@
1210 :
1211 : /* update the time info of the block */
1212 : /* we are also clearing any previous bad and rehash flag */
- 1213 112099 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1));
+ 1213 112174 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1));
1214 : }
1215 : }
1216 :
1217 : /* if a silent (even if corrected) or input/output error was found */
1218 : /* mark the block as bad to have check/fix to handle it */
1219 : /* because our correction is in memory only and not yet written */
- 1220 114729 : if (silent_error_on_this_block || io_error_on_this_block) {
+ 1220 114785 : if (silent_error_on_this_block || io_error_on_this_block) {
1221 : /* set the error status keeping the other info */
1222 852 : info_set(&state->infoarr, blockcur, info_set_bad(info));
1223 : }
@@ -1288,27 +1288,27 @@
1226 : /* Note that the calls to io_parity_write() are mandatory */
1227 : /* even if the parity doesn't need to be updated */
1228 : /* This because we want to keep track of the time usage */
- 1229 114729 : state_usage_misc(state);
+ 1229 114785 : state_usage_misc(state);
1230 :
1231 : /* write start */
- 1232 114729 : io_write_preset(&io, blockcur, !parity_going_to_be_updated);
+ 1232 114785 : io_write_preset(&io, blockcur, !parity_going_to_be_updated);
1233 :
1234 : /* write the parity */
- 1235 672998 : for (l = 0; l < state->level; ++l) {
+ 1235 673390 : for (l = 0; l < state->level; ++l) {
1236 : unsigned levcur;
1237 :
- 1238 558269 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac);
+ 1238 558605 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac);
1239 :
1240 : /* until now is parity */
- 1241 558269 : state_usage_parity(state, waiting_map, waiting_mac);
+ 1241 558605 : state_usage_parity(state, waiting_map, waiting_mac);
1242 : }
1243 :
1244 : /* write finished */
- 1245 114729 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error);
+ 1245 114785 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error);
1246 :
1247 : /* handle errors reported */
- 1248 573645 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) {
- 1249 458916 : if (writer_error[j]) {
+ 1248 573925 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) {
+ 1249 459140 : if (writer_error[j]) {
1250 0 : switch (j + IO_WRITER_ERROR_BASE) {
1251 : case TASK_STATE_IOERROR_CONTINUE :
1252 0 : ++io_error;
@@ -1338,24 +1338,24 @@
1276 : }
1277 :
1278 : /* mark the state as needing write */
- 1279 114729 : state->need_write = 1;
+ 1279 114785 : state->need_write = 1;
1280 :
1281 : /* count the number of processed block */
- 1282 114729 : ++countpos;
+ 1282 114785 : ++countpos;
1283 :
1284 : /* progress */
- 1285 114729 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) {
+ 1285 114785 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) {
1286 : /* LCOV_EXCL_START */
1287 : break;
1288 : /* LCOV_EXCL_STOP */
1289 : }
1290 :
1291 : /* autosave */
- 1292 114729 : if ((state->autosave != 0
+ 1292 114785 : if ((state->autosave != 0
1293 26021 : && autosavedone >= autosavelimit /* if we have reached the limit */
1294 0 : && autosavemissing >= autosavelimit) /* if we have at least a full step to do */
1295 : /* or if we have a forced autosave at the specified block */
- 1296 114729 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur)
+ 1296 114785 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur)
1297 : ) {
1298 1 : autosavedone = 0; /* restart the counter */
1299 :
@@ -1390,7 +1390,7 @@
1328 : /* drop until now */
1329 1 : state_usage_waste(state);
1330 : }
- 1331 114729 : }
+ 1331 114785 : }
1332 :
1333 : end:
1334 83 : state_progress_end(state, countpos, countmax, countsize);
diff --git a/cov/cmdline/touch.c.func-sort-c.html b/cov/cmdline/touch.c.func-sort-c.html
index 29e46e34..5c8c1624 100644
--- a/cov/cmdline/touch.c.func-sort-c.html
+++ b/cov/cmdline/touch.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/touch.c.func.html b/cov/cmdline/touch.c.func.html
index 7ca70d61..bc6ad4e6 100644
--- a/cov/cmdline/touch.c.func.html
+++ b/cov/cmdline/touch.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/touch.c.gcov.html b/cov/cmdline/touch.c.gcov.html
index 8d7eeb65..caa75c8d 100644
--- a/cov/cmdline/touch.c.gcov.html
+++ b/cov/cmdline/touch.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/cmdline/unix.c.func-sort-c.html b/cov/cmdline/unix.c.func-sort-c.html
index 470599c4..56a88b91 100644
--- a/cov/cmdline/unix.c.func-sort-c.html
+++ b/cov/cmdline/unix.c.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
+
-
+
 |
@@ -60,91 +60,91 @@
Hit count  |
- | tick |
- 3817537 |
+ tick |
+ 3819097 |
| open_noatime |
- 1719437 |
+ 1718110 |
- | filephy |
+ filephy |
11432 |
- | devuuid |
+ devuuid |
5630 |
- | devuuid_dev |
+ devuuid_dev |
5626 |
- | fsinfo |
+ fsinfo |
5483 |
- | randomize |
+ randomize |
282 |
- | os_init |
+ os_init |
271 |
- | os_done |
+ os_done |
248 |
- | tagread |
+ tagread |
191 |
- | devresolve |
+ devresolve_sys |
191 |
- | devresolve_sys |
- 191 |
+ devresolve |
+ 190 |
- | devread |
+ devread |
144 |
- | devtree |
+ devtree |
130 |
- | tick_ms |
+ tick_ms |
65 |
- | thread_smart |
- 43 |
+ thread_smart |
+ 42 |
- | devsmart |
- 43 |
+ devsmart |
+ 42 |
- | devup |
+ devup |
30 |
- | thread_spinup |
+ thread_spinup |
30 |
- | direct_size |
+ direct_size |
7 |
- | thread_spindown |
+ thread_spindown |
5 |
- | devdown |
+ devdown |
5 |
@@ -152,33 +152,33 @@
| 4 |
- | devdereference |
+ devdereference |
4 |
- | devquery |
+ devquery |
4 |
- | device_thread |
+ device_thread |
3 |
- | devscan |
+ devscan |
1 |
- | os_clear |
- 1 |
-
-
- | devuuid_blkid |
+ devuuid_blkid |
0 |
| dirent_hidden |
0 |
+
+ | os_clear |
+ 0 |
+
| stat_desc |
0 |
diff --git a/cov/cmdline/unix.c.func.html b/cov/cmdline/unix.c.func.html
index e5db4a7b..acc9ff99 100644
--- a/cov/cmdline/unix.c.func.html
+++ b/cov/cmdline/unix.c.func.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
+
-
+
 |
@@ -60,67 +60,67 @@
Hit count  |
- | devdereference |
+ devdereference |
4 |
- | devdown |
+ devdown |
5 |
- | device_thread |
+ device_thread |
3 |
- | devquery |
+ devquery |
4 |
- | devread |
+ devread |
144 |
- | devresolve |
- 191 |
+ devresolve |
+ 190 |
| devresolve_proc |
4 |
- | devresolve_sys |
+ devresolve_sys |
191 |
- | devscan |
+ devscan |
1 |
- | devsmart |
- 43 |
+ devsmart |
+ 42 |
- | devtree |
+ devtree |
130 |
- | devup |
+ devup |
30 |
- | devuuid |
+ devuuid |
5630 |
- | devuuid_blkid |
+ devuuid_blkid |
0 |
- | devuuid_dev |
+ devuuid_dev |
5626 |
- | direct_size |
+ direct_size |
7 |
@@ -128,31 +128,31 @@
| 0 |
- | filephy |
+ filephy |
11432 |
- | fsinfo |
+ fsinfo |
5483 |
| open_noatime |
- 1719437 |
+ 1718110 |
- | os_clear |
- 1 |
+ os_clear |
+ 0 |
- | os_done |
+ os_done |
248 |
- | os_init |
+ os_init |
271 |
- | randomize |
+ randomize |
282 |
@@ -160,27 +160,27 @@
| 0 |
- | tagread |
+ tagread |
191 |
- | thread_smart |
- 43 |
+ thread_smart |
+ 42 |
- | thread_spindown |
+ thread_spindown |
5 |
- | thread_spinup |
+ thread_spinup |
30 |
- | tick |
- 3817537 |
+ tick |
+ 3819097 |
- | tick_ms |
+ tick_ms |
65 |
diff --git a/cov/cmdline/unix.c.gcov.html b/cov/cmdline/unix.c.gcov.html
index 1299a964..cc72535d 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 1719437 : int open_noatime(const char* file, int flags)
+ 31 1718110 : int open_noatime(const char* file, int flags)
32 : {
33 : #ifdef O_NOATIME
- 34 1719437 : int f = open(file, flags | O_NOATIME);
+ 34 1718110 : int f = open(file, flags | O_NOATIME);
35 :
36 : /* only root is allowed to use O_NOATIME, in case retry without it */
- 37 1719500 : if (f == -1 && errno == EPERM)
+ 37 1718988 : if (f == -1 && errno == EPERM)
38 0 : f = open(file, flags);
- 39 1719484 : return f;
+ 39 1717923 : return f;
40 : #else
41 : return open(file, flags);
42 : #endif
@@ -176,1416 +176,1435 @@
114 : char* separator;
115 : char* majorminor;
116 : char* mountpoint;
- 117 : char* mountsource;
- 118 :
- 119 104 : s = fgets(buf, sizeof(buf), f);
- 120 104 : if (s == 0)
- 121 4 : break;
- 122 :
- 123 : /* find the separator position */
- 124 100 : separator = strstr(s, " - ");
- 125 100 : if (!separator)
- 126 32 : continue;
- 127 :
- 128 : /* skip the separator */
- 129 100 : *separator = 0;
- 130 100 : separator += 3;
- 131 :
- 132 : /* split the line */
- 133 100 : first_mac = strsplit(first_map, 8, s, " \t\r\n");
- 134 100 : second_mac = strsplit(second_map, 8, separator, " \t\r\n");
- 135 :
- 136 : /* if too short, it's the wrong line */
- 137 100 : if (first_mac < 5)
- 138 0 : continue;
- 139 100 : if (second_mac < 2)
- 140 0 : continue;
- 141 :
- 142 100 : majorminor = first_map[2];
- 143 100 : mountpoint = first_map[4];
- 144 100 : mountsource = second_map[1];
- 145 :
- 146 : /* accept only /dev/... mountsource */
- 147 : /* this excludes ZFS that has the bare label, like "tank" */
- 148 100 : if (strncmp(mountsource, "/dev/", 5) != 0)
- 149 32 : continue;
- 150 :
- 151 : /* compare major:minor from mountinfo */
- 152 68 : if (strcmp(majorminor, match) == 0) {
- 153 0 : pathcpy(path, path_size, mountsource);
- 154 :
- 155 0 : log_tag("resolve:proc:%u:%u:%s: found mountinfo device %s\n", major(device), minor(device), path, match);
- 156 :
- 157 0 : fclose(f);
- 158 0 : return 0;
- 159 : }
- 160 :
- 161 : /* get the device of the mount point */
- 162 : /* in Btrfs it could be different than the one in mountinfo */
- 163 68 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) {
- 164 0 : pathcpy(path, path_size, mountsource);
- 165 :
- 166 0 : log_tag("resolve:proc:%u:%u:%s: found mountpoint %s\n", major(device), minor(device), path, mountpoint);
- 167 :
- 168 0 : fclose(f);
- 169 0 : return 0;
- 170 : }
- 171 100 : }
- 172 :
- 173 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device));
+ 117 : char* fs;
+ 118 : char* mountsource;
+ 119 :
+ 120 104 : s = fgets(buf, sizeof(buf), f);
+ 121 104 : if (s == 0)
+ 122 4 : break;
+ 123 :
+ 124 : /* find the separator position */
+ 125 100 : separator = strstr(s, " - ");
+ 126 100 : if (!separator)
+ 127 0 : continue;
+ 128 :
+ 129 : /* skip the separator */
+ 130 100 : *separator = 0;
+ 131 100 : separator += 3;
+ 132 :
+ 133 : /* split the line */
+ 134 100 : first_mac = strsplit(first_map, 8, s, " \t\r\n");
+ 135 100 : second_mac = strsplit(second_map, 8, separator, " \t\r\n");
+ 136 :
+ 137 : /* if too short, it's the wrong line */
+ 138 100 : if (first_mac < 5)
+ 139 0 : continue;
+ 140 100 : if (second_mac < 2)
+ 141 0 : continue;
+ 142 :
+ 143 100 : majorminor = first_map[2];
+ 144 100 : mountpoint = first_map[4];
+ 145 100 : fs = second_map[0];
+ 146 100 : mountsource = second_map[1];
+ 147 :
+ 148 : /* compare major:minor from mountinfo */
+ 149 100 : if (strcmp(majorminor, match) == 0) {
+ 150 : /*
+ 151 : * Accept only /dev/... mountsource
+ 152 : *
+ 153 : * This excludes ZFS that uses a bare label for mountsource, like "tank".
+ 154 : *
+ 155 : * 410 408 0:193 / /XXX rw,relatime shared:217 - zfs tank/system/data/var/lib/docker/XXX rw,xattr,noacl
+ 156 : *
+ 157 : * Also excludes AUTOFS unmounted devices that point to a fake filesystem
+ 158 : * used to remount them at the first use.
+ 159 : *
+ 160 : * 97 25 0:42 / /XXX rw,relatime shared:76 - autofs /etc/auto.seed rw,fd=6,pgrp=952,timeout=30,minproto=5,maxproto=5,indirect
+ 161 : */
+ 162 0 : if (strncmp(mountsource, "/dev/", 5) != 0) {
+ 163 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource);
+ 164 0 : continue;
+ 165 : }
+ 166 :
+ 167 0 : pathcpy(path, path_size, mountsource);
+ 168 :
+ 169 0 : log_tag("resolve:proc:%u:%u: found device %s matching device %s\n", major(device), minor(device), path, match);
+ 170 :
+ 171 0 : fclose(f);
+ 172 0 : return 0;
+ 173 : }
174 :
- 175 4 : fclose(f);
- 176 4 : return -1;
- 177 : }
- 178 : #endif
- 179 :
- 180 : /**
- 181 : * Get the device of a virtual superblock.
- 182 : *
- 183 : * This is intended to resolve the case of Btrfs filesystems that
- 184 : * create a virtual superblock (major==0) not backed by any low
- 185 : * level device.
- 186 : *
- 187 : * See:
- 188 : * Bug 711881 - too funny btrfs st_dev numbers
- 189 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881
- 190 : */
- 191 : #if HAVE_LINUX_DEVICE
- 192 4 : static int devdereference(uint64_t device, uint64_t* new_device)
- 193 : {
- 194 : char path[PATH_MAX];
- 195 : struct stat st;
- 196 :
- 197 : /* use the proc interface to get the device containing the filesystem */
- 198 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) {
- 199 : /* LCOV_EXCL_START */
- 200 : return -1;
- 201 : /* LCOV_EXCL_STOP */
- 202 : }
- 203 :
- 204 : /* check the device */
- 205 0 : if (stat(path, &st) != 0) {
- 206 : /* LCOV_EXCL_START */
- 207 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path);
- 208 : return -1;
- 209 : /* LCOV_EXCL_STOP */
- 210 : }
- 211 :
- 212 0 : if (major(st.st_rdev) == 0) {
- 213 : /* LCOV_EXCL_START */
- 214 : log_tag("dereference:%u:%u: still null device %s -> %u:%u\n", major(device), minor(device), path, major(st.st_rdev), minor(st.st_rdev));
- 215 : return -1;
- 216 : /* LCOV_EXCL_STOP */
- 217 : }
- 218 :
- 219 0 : *new_device = st.st_rdev;
- 220 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev));
- 221 0 : return 0;
- 222 : }
- 223 : #endif
- 224 :
- 225 : /**
- 226 : * Read a file extracting the specified tag TAG=VALUE format.
- 227 : * Return !=0 on error.
- 228 : */
- 229 : #if HAVE_LINUX_DEVICE
- 230 191 : static int tagread(const char* path, const char* tag, char* value, size_t value_size)
- 231 : {
- 232 : int f;
- 233 : int ret;
- 234 : int len;
- 235 : char buf[512];
- 236 : size_t tag_len;
- 237 : char* i;
- 238 : char* e;
- 239 :
- 240 191 : f = open(path, O_RDONLY);
- 241 191 : if (f == -1) {
- 242 : /* LCOV_EXCL_START */
- 243 : log_fatal("Failed to open '%s'.\n", path);
- 244 : return 0;
- 245 : /* LCOV_EXCL_STOP */
- 246 : }
- 247 :
- 248 191 : len = read(f, buf, sizeof(buf));
- 249 191 : if (len < 0) {
- 250 : /* LCOV_EXCL_START */
- 251 : close(f);
- 252 : log_fatal("Failed to read '%s'.\n", path);
- 253 : return -1;
- 254 : /* LCOV_EXCL_STOP */
- 255 : }
- 256 191 : if (len == sizeof(buf)) {
- 257 : /* LCOV_EXCL_START */
- 258 : close(f);
- 259 : log_fatal("Too long read '%s'.\n", path);
- 260 : return -1;
- 261 : /* LCOV_EXCL_STOP */
- 262 : }
- 263 :
- 264 191 : ret = close(f);
- 265 191 : if (ret != 0) {
- 266 : /* LCOV_EXCL_START */
- 267 : log_fatal("Failed to close '%s'.\n", path);
- 268 : return -1;
- 269 : /* LCOV_EXCL_STOP */
- 270 : }
- 271 :
- 272 191 : buf[len] = 0;
- 273 191 : tag_len = strlen(tag);
- 274 :
- 275 3324 : for (i = buf; *i; ++i) {
- 276 3324 : char* p = i;
- 277 :
- 278 : /* start with a space */
- 279 3324 : if (p != buf) {
- 280 3133 : if (!isspace(*p))
- 281 2751 : continue;
- 282 382 : ++p;
- 283 : }
- 284 :
- 285 573 : if (strncmp(p, tag, tag_len) != 0)
- 286 382 : continue;
- 287 191 : p += tag_len;
- 288 :
- 289 : /* end with a = */
- 290 191 : if (*p != '=')
- 291 0 : continue;
- 292 191 : ++p;
+ 175 : /* get the device of the mount point */
+ 176 : /* in Btrfs it could be different than the one in mountinfo */
+ 177 100 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) {
+ 178 0 : if (strncmp(mountsource, "/dev/", 5) != 0) {
+ 179 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource);
+ 180 0 : continue;
+ 181 : }
+ 182 :
+ 183 0 : pathcpy(path, path_size, mountsource);
+ 184 :
+ 185 0 : log_tag("resolve:proc:%u:%u: found device %s matching mountpoint %s\n", major(device), minor(device), path, mountpoint);
+ 186 :
+ 187 0 : fclose(f);
+ 188 0 : return 0;
+ 189 : }
+ 190 100 : }
+ 191 :
+ 192 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device));
+ 193 :
+ 194 4 : fclose(f);
+ 195 4 : return -1;
+ 196 : }
+ 197 : #endif
+ 198 :
+ 199 : /**
+ 200 : * Get the device of a virtual superblock.
+ 201 : *
+ 202 : * This is intended to resolve the case of Btrfs filesystems that
+ 203 : * create a virtual superblock (major==0) not backed by any low
+ 204 : * level device.
+ 205 : *
+ 206 : * See:
+ 207 : * Bug 711881 - too funny btrfs st_dev numbers
+ 208 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881
+ 209 : */
+ 210 : #if HAVE_LINUX_DEVICE
+ 211 4 : static int devdereference(uint64_t device, uint64_t* new_device)
+ 212 : {
+ 213 : char path[PATH_MAX];
+ 214 : struct stat st;
+ 215 :
+ 216 : /* use the proc interface to get the device containing the filesystem */
+ 217 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) {
+ 218 : /* LCOV_EXCL_START */
+ 219 : return -1;
+ 220 : /* LCOV_EXCL_STOP */
+ 221 : }
+ 222 :
+ 223 : /* check the device */
+ 224 0 : if (stat(path, &st) != 0) {
+ 225 : /* LCOV_EXCL_START */
+ 226 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path);
+ 227 : return -1;
+ 228 : /* LCOV_EXCL_STOP */
+ 229 : }
+ 230 :
+ 231 0 : if (major(st.st_rdev) == 0) {
+ 232 : /* LCOV_EXCL_START */
+ 233 : log_tag("dereference:%u:%u: still null device %s -> %u:%u\n", major(device), minor(device), path, major(st.st_rdev), minor(st.st_rdev));
+ 234 : return -1;
+ 235 : /* LCOV_EXCL_STOP */
+ 236 : }
+ 237 :
+ 238 0 : *new_device = st.st_rdev;
+ 239 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev));
+ 240 0 : return 0;
+ 241 : }
+ 242 : #endif
+ 243 :
+ 244 : /**
+ 245 : * Read a file extracting the specified tag TAG=VALUE format.
+ 246 : * Return !=0 on error.
+ 247 : */
+ 248 : #if HAVE_LINUX_DEVICE
+ 249 191 : static int tagread(const char* path, const char* tag, char* value, size_t value_size)
+ 250 : {
+ 251 : int f;
+ 252 : int ret;
+ 253 : int len;
+ 254 : char buf[512];
+ 255 : size_t tag_len;
+ 256 : char* i;
+ 257 : char* e;
+ 258 :
+ 259 191 : f = open(path, O_RDONLY);
+ 260 191 : if (f == -1) {
+ 261 : /* LCOV_EXCL_START */
+ 262 : log_fatal("Failed to open '%s'.\n", path);
+ 263 : return 0;
+ 264 : /* LCOV_EXCL_STOP */
+ 265 : }
+ 266 :
+ 267 191 : len = read(f, buf, sizeof(buf));
+ 268 190 : if (len < 0) {
+ 269 : /* LCOV_EXCL_START */
+ 270 : close(f);
+ 271 : log_fatal("Failed to read '%s'.\n", path);
+ 272 : return -1;
+ 273 : /* LCOV_EXCL_STOP */
+ 274 : }
+ 275 190 : if (len == sizeof(buf)) {
+ 276 : /* LCOV_EXCL_START */
+ 277 : close(f);
+ 278 : log_fatal("Too long read '%s'.\n", path);
+ 279 : return -1;
+ 280 : /* LCOV_EXCL_STOP */
+ 281 : }
+ 282 :
+ 283 190 : ret = close(f);
+ 284 195 : if (ret != 0) {
+ 285 : /* LCOV_EXCL_START */
+ 286 : log_fatal("Failed to close '%s'.\n", path);
+ 287 : return -1;
+ 288 : /* LCOV_EXCL_STOP */
+ 289 : }
+ 290 :
+ 291 195 : buf[len] = 0;
+ 292 195 : tag_len = strlen(tag);
293 :
- 294 : /* found */
- 295 191 : i = p;
- 296 191 : break;
- 297 : }
- 298 191 : if (!*i) {
- 299 : /* LCOV_EXCL_START */
- 300 : log_fatal("Missing tag '%s' for '%s'.\n", tag, path);
- 301 : return -1;
- 302 : /* LCOV_EXCL_STOP */
- 303 : }
- 304 :
- 305 : /* terminate at the first space */
- 306 191 : e = i;
- 307 1020 : while (*e != 0 && !isspace(*e))
- 308 638 : ++e;
- 309 191 : *e = 0;
- 310 :
- 311 191 : if (!*i) {
- 312 : /* LCOV_EXCL_START */
- 313 : log_fatal("Empty tag '%s' for '%s'.\n", tag, path);
- 314 : return -1;
- 315 : /* LCOV_EXCL_STOP */
+ 294 3319 : for (i = buf; *i; ++i) {
+ 295 3320 : char* p = i;
+ 296 :
+ 297 : /* start with a space */
+ 298 3320 : if (p != buf) {
+ 299 3129 : if (!isspace(*p))
+ 300 2743 : continue;
+ 301 381 : ++p;
+ 302 : }
+ 303 :
+ 304 572 : if (strncmp(p, tag, tag_len) != 0)
+ 305 381 : continue;
+ 306 191 : p += tag_len;
+ 307 :
+ 308 : /* end with a = */
+ 309 191 : if (*p != '=')
+ 310 0 : continue;
+ 311 191 : ++p;
+ 312 :
+ 313 : /* found */
+ 314 191 : i = p;
+ 315 191 : break;
316 : }
- 317 :
- 318 191 : pathprint(value, value_size, "%s", i);
- 319 :
- 320 191 : return 0;
- 321 : }
- 322 : #endif
+ 317 190 : if (!*i) {
+ 318 : /* LCOV_EXCL_START */
+ 319 : log_fatal("Missing tag '%s' for '%s'.\n", tag, path);
+ 320 : return -1;
+ 321 : /* LCOV_EXCL_STOP */
+ 322 : }
323 :
- 324 : /**
- 325 : * Get the device file from the device number.
- 326 : *
- 327 : * It uses /sys/dev/block/.../uevent.
- 328 : *
- 329 : * For null device (major==0) it fails.
- 330 : */
- 331 : #if HAVE_LINUX_DEVICE
- 332 191 : static int devresolve_sys(dev_t device, char* path, size_t path_size)
- 333 : {
- 334 : struct stat st;
- 335 : char buf[PATH_MAX];
+ 324 : /* terminate at the first space */
+ 325 190 : e = i;
+ 326 1017 : while (*e != 0 && !isspace(*e))
+ 327 637 : ++e;
+ 328 191 : *e = 0;
+ 329 :
+ 330 191 : if (!*i) {
+ 331 : /* LCOV_EXCL_START */
+ 332 : log_fatal("Empty tag '%s' for '%s'.\n", tag, path);
+ 333 : return -1;
+ 334 : /* LCOV_EXCL_STOP */
+ 335 : }
336 :
- 337 : /* default device path from device number */
- 338 191 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device));
- 339 :
- 340 191 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) {
- 341 : /* LCOV_EXCL_START */
- 342 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path);
- 343 : return -1;
- 344 : /* LCOV_EXCL_STOP */
- 345 : }
- 346 :
- 347 : /* set the real device path */
- 348 191 : pathprint(path, path_size, "/dev/%s", buf);
- 349 :
- 350 : /* check the device */
- 351 191 : if (stat(path, &st) != 0) {
- 352 : /* LCOV_EXCL_START */
- 353 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path);
- 354 : return -1;
- 355 : /* LCOV_EXCL_STOP */
- 356 : }
- 357 191 : if (st.st_rdev != device) {
- 358 : /* LCOV_EXCL_START */
- 359 : log_tag("resolve:sys:%u:%u: unexpected device '%u:%u' for '%s'.\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev), path);
- 360 : return -1;
- 361 : /* LCOV_EXCL_STOP */
- 362 : }
- 363 :
- 364 191 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path);
+ 337 191 : pathprint(value, value_size, "%s", i);
+ 338 :
+ 339 190 : return 0;
+ 340 : }
+ 341 : #endif
+ 342 :
+ 343 : /**
+ 344 : * Get the device file from the device number.
+ 345 : *
+ 346 : * It uses /sys/dev/block/.../uevent.
+ 347 : *
+ 348 : * For null device (major==0) it fails.
+ 349 : */
+ 350 : #if HAVE_LINUX_DEVICE
+ 351 191 : static int devresolve_sys(dev_t device, char* path, size_t path_size)
+ 352 : {
+ 353 : struct stat st;
+ 354 : char buf[PATH_MAX];
+ 355 :
+ 356 : /* default device path from device number */
+ 357 191 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device));
+ 358 :
+ 359 191 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) {
+ 360 : /* LCOV_EXCL_START */
+ 361 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path);
+ 362 : return -1;
+ 363 : /* LCOV_EXCL_STOP */
+ 364 : }
365 :
- 366 191 : return 0;
- 367 : }
- 368 : #endif
- 369 :
- 370 : /**
- 371 : * Get the device file from the device number.
- 372 : */
- 373 : #if HAVE_LINUX_DEVICE
- 374 191 : static int devresolve(uint64_t device, char* path, size_t path_size)
- 375 : {
- 376 191 : if (devresolve_sys(device, path, path_size) == 0)
- 377 191 : return 0;
- 378 :
- 379 0 : return -1;
- 380 : }
- 381 : #endif
+ 366 : /* set the real device path */
+ 367 190 : pathprint(path, path_size, "/dev/%s", buf);
+ 368 :
+ 369 : /* check the device */
+ 370 191 : if (stat(path, &st) != 0) {
+ 371 : /* LCOV_EXCL_START */
+ 372 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path);
+ 373 : return -1;
+ 374 : /* LCOV_EXCL_STOP */
+ 375 : }
+ 376 190 : if (st.st_rdev != device) {
+ 377 : /* LCOV_EXCL_START */
+ 378 : log_tag("resolve:sys:%u:%u: unexpected device '%u:%u' for '%s'.\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev), path);
+ 379 : return -1;
+ 380 : /* LCOV_EXCL_STOP */
+ 381 : }
382 :
- 383 : /**
- 384 : * Cache used by blkid.
- 385 : */
- 386 : #if HAVE_BLKID
- 387 : static blkid_cache cache = 0;
- 388 : #endif
- 389 :
- 390 : /**
- 391 : * Get the UUID using the /dev/disk/by-uuid/ links.
- 392 : * It doesn't require root permission, and the uuid are always updated.
- 393 : * It doesn't work with Btrfs file-systems that don't export the main UUID
- 394 : * in /dev/disk/by-uuid/.
- 395 : */
- 396 : #if HAVE_LINUX_DEVICE
- 397 5626 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
- 398 : {
- 399 : int ret;
- 400 : DIR* d;
- 401 : struct dirent* dd;
- 402 : struct stat st;
- 403 :
- 404 : /* scan the UUID directory searching for the device */
- 405 5626 : d = opendir("/dev/disk/by-uuid");
- 406 5626 : if (!d) {
- 407 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno));
- 408 : /* directory missing?, likely we are not in Linux */
- 409 0 : return -1;
- 410 : }
- 411 :
- 412 95642 : while ((dd = readdir(d)) != 0) {
- 413 : /* skip "." and ".." files, UUIDs never start with '.' */
- 414 90016 : if (dd->d_name[0] == '.')
- 415 11252 : continue;
- 416 :
- 417 78764 : ret = fstatat(dirfd(d), dd->d_name, &st, 0);
- 418 78764 : if (ret != 0) {
- 419 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno));
- 420 : /* generic error, ignore and continue the search */
- 421 0 : continue;
- 422 : }
- 423 :
- 424 : /* if it matches, we have the uuid */
- 425 78764 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) {
- 426 : char buf[PATH_MAX];
- 427 : char path[PATH_MAX];
- 428 :
- 429 : /* resolve the link */
- 430 5626 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name);
- 431 5626 : ret = readlink(path, buf, sizeof(buf));
- 432 5626 : if (ret < 0 || ret == sizeof(buf)) {
- 433 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno));
- 434 : /* generic error, ignore and continue the search */
- 435 0 : continue;
- 436 : }
- 437 5626 : buf[ret] = 0;
- 438 :
- 439 : /* found */
- 440 5626 : pathcpy(uuid, uuid_size, dd->d_name);
- 441 :
- 442 5626 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf);
- 443 :
- 444 5626 : closedir(d);
- 445 5626 : return 0;
- 446 : }
- 447 : }
- 448 :
- 449 0 : log_tag("uuid:by-uuidd:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device));
- 450 :
- 451 : /* not found */
- 452 0 : closedir(d);
- 453 0 : return -1;
- 454 : }
- 455 : #endif
- 456 :
- 457 : /**
- 458 : * Get the UUID using liblkid.
- 459 : * It uses a cache to work without root permission, resulting in UUID
- 460 : * not necessarily recent.
- 461 : * We could call blkid_probe_all() to refresh the UUID, but it would
- 462 : * require root permission to read the superblocks, and resulting in
- 463 : * all the disks spinning.
- 464 : */
- 465 : #if HAVE_BLKID
- 466 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size)
- 467 : {
- 468 : char* devname;
- 469 : char* uuidname;
- 470 :
- 471 0 : devname = blkid_devno_to_devname(device);
- 472 0 : if (!devname) {
- 473 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno));
- 474 : /* device mapping failed */
- 475 0 : return -1;
- 476 : }
- 477 :
- 478 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname);
- 479 0 : if (!uuidname) {
- 480 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno));
- 481 : /* uuid mapping failed */
- 482 0 : free(devname);
- 483 0 : return -1;
- 484 : }
- 485 :
- 486 0 : pathcpy(uuid, uuid_size, uuidname);
- 487 :
- 488 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname);
+ 383 190 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path);
+ 384 :
+ 385 191 : return 0;
+ 386 : }
+ 387 : #endif
+ 388 :
+ 389 : /**
+ 390 : * Get the device file from the device number.
+ 391 : */
+ 392 : #if HAVE_LINUX_DEVICE
+ 393 190 : static int devresolve(uint64_t device, char* path, size_t path_size)
+ 394 : {
+ 395 190 : if (devresolve_sys(device, path, path_size) == 0)
+ 396 191 : return 0;
+ 397 :
+ 398 0 : return -1;
+ 399 : }
+ 400 : #endif
+ 401 :
+ 402 : /**
+ 403 : * Cache used by blkid.
+ 404 : */
+ 405 : #if HAVE_BLKID
+ 406 : static blkid_cache cache = 0;
+ 407 : #endif
+ 408 :
+ 409 : /**
+ 410 : * Get the UUID using the /dev/disk/by-uuid/ links.
+ 411 : * It doesn't require root permission, and the uuid are always updated.
+ 412 : * It doesn't work with Btrfs file-systems that don't export the main UUID
+ 413 : * in /dev/disk/by-uuid/.
+ 414 : */
+ 415 : #if HAVE_LINUX_DEVICE
+ 416 5626 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
+ 417 : {
+ 418 : int ret;
+ 419 : DIR* d;
+ 420 : struct dirent* dd;
+ 421 : struct stat st;
+ 422 :
+ 423 : /* scan the UUID directory searching for the device */
+ 424 5626 : d = opendir("/dev/disk/by-uuid");
+ 425 5626 : if (!d) {
+ 426 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno));
+ 427 : /* directory missing?, likely we are not in Linux */
+ 428 0 : return -1;
+ 429 : }
+ 430 :
+ 431 95642 : while ((dd = readdir(d)) != 0) {
+ 432 : /* skip "." and ".." files, UUIDs never start with '.' */
+ 433 90016 : if (dd->d_name[0] == '.')
+ 434 11252 : continue;
+ 435 :
+ 436 78764 : ret = fstatat(dirfd(d), dd->d_name, &st, 0);
+ 437 78764 : if (ret != 0) {
+ 438 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno));
+ 439 : /* generic error, ignore and continue the search */
+ 440 0 : continue;
+ 441 : }
+ 442 :
+ 443 : /* if it matches, we have the uuid */
+ 444 78764 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) {
+ 445 : char buf[PATH_MAX];
+ 446 : char path[PATH_MAX];
+ 447 :
+ 448 : /* resolve the link */
+ 449 5626 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name);
+ 450 5626 : ret = readlink(path, buf, sizeof(buf));
+ 451 5626 : if (ret < 0 || ret == sizeof(buf)) {
+ 452 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno));
+ 453 : /* generic error, ignore and continue the search */
+ 454 0 : continue;
+ 455 : }
+ 456 5626 : buf[ret] = 0;
+ 457 :
+ 458 : /* found */
+ 459 5626 : pathcpy(uuid, uuid_size, dd->d_name);
+ 460 :
+ 461 5626 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf);
+ 462 :
+ 463 5626 : closedir(d);
+ 464 5626 : return 0;
+ 465 : }
+ 466 : }
+ 467 :
+ 468 0 : log_tag("uuid:by-uuidd:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device));
+ 469 :
+ 470 : /* not found */
+ 471 0 : closedir(d);
+ 472 0 : return -1;
+ 473 : }
+ 474 : #endif
+ 475 :
+ 476 : /**
+ 477 : * Get the UUID using liblkid.
+ 478 : * It uses a cache to work without root permission, resulting in UUID
+ 479 : * not necessarily recent.
+ 480 : * We could call blkid_probe_all() to refresh the UUID, but it would
+ 481 : * require root permission to read the superblocks, and resulting in
+ 482 : * all the disks spinning.
+ 483 : */
+ 484 : #if HAVE_BLKID
+ 485 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size)
+ 486 : {
+ 487 : char* devname;
+ 488 : char* uuidname;
489 :
- 490 0 : free(devname);
- 491 0 : free(uuidname);
- 492 0 : return 0;
- 493 : }
- 494 : #endif
- 495 :
- 496 5630 : int devuuid(uint64_t device, char* uuid, size_t uuid_size)
- 497 : {
- 498 : #if HAVE_LINUX_DEVICE
- 499 : /* if the major is the null device */
- 500 5630 : if (major(device) == 0) {
- 501 : /* obtain the real device */
- 502 4 : if (devdereference(device, &device) != 0) {
- 503 : /* LCOV_EXCL_START */
- 504 : return -1;
- 505 : /* LCOV_EXCL_STOP */
- 506 : }
- 507 : }
- 508 : #endif
- 509 :
- 510 : /* first try with the /dev/disk/by-uuid version */
- 511 : #if HAVE_LINUX_DEVICE
- 512 5626 : if (devuuid_dev(device, uuid, uuid_size) == 0)
- 513 5626 : return 0;
- 514 : #else
- 515 : log_tag("uuid:by-uuidd:%u:%u: by-uuid not supported\n", major(device), minor(device));
- 516 : #endif
- 517 :
- 518 : /* fall back to blkid for other cases */
- 519 : #if HAVE_BLKID
- 520 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0)
- 521 0 : return 0;
- 522 : #else
- 523 : log_tag("uuid:blkid:%u:%u: blkid not supported\n", major(device), minor(device));
- 524 : #endif
- 525 :
- 526 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device));
- 527 :
- 528 : /* not supported */
- 529 : (void)uuid;
- 530 : (void)uuid_size;
- 531 0 : return -1;
- 532 : }
- 533 :
- 534 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical)
- 535 : {
- 536 : #if HAVE_LINUX_FIEMAP_H
- 537 : /* In Linux get the real physical address of the file */
- 538 : /* Note that FIEMAP doesn't require root permission */
- 539 : int f;
- 540 : struct {
- 541 : struct fiemap fiemap;
- 542 : struct fiemap_extent extent;
- 543 : } fm;
- 544 : unsigned int blknum;
- 545 :
- 546 11432 : f = open(path, O_RDONLY);
- 547 11432 : if (f == -1) {
- 548 0 : return -1;
- 549 : }
- 550 :
- 551 : /* first try with FIEMAP */
- 552 : /* if works for ext2, ext3, ext4, xfs, btrfs */
- 553 11432 : memset(&fm, 0, sizeof(fm));
- 554 11432 : fm.fiemap.fm_start = 0;
- 555 11432 : fm.fiemap.fm_length = ~0ULL;
- 556 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
- 557 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
- 558 :
- 559 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) {
- 560 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags;
- 561 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical;
- 562 :
- 563 : /* check some condition for validating the offset */
- 564 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) {
- 565 : /* if the data is inline, we don't have an offset to report */
- 566 0 : *physical = FILEPHY_WITHOUT_OFFSET;
- 567 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) {
- 568 : /* if the offset is unknown, we don't have an offset to report */
- 569 0 : *physical = FILEPHY_WITHOUT_OFFSET;
- 570 11432 : } else if (offset == 0) {
- 571 : /* 0 is the general fallback for file-systems when */
- 572 : /* they don't have an offset to report */
- 573 14 : *physical = FILEPHY_WITHOUT_OFFSET;
- 574 : } else {
- 575 : /* finally report the real offset */
- 576 11418 : *physical = offset + FILEPHY_REAL_OFFSET;
- 577 : }
- 578 :
- 579 11432 : if (close(f) == -1)
- 580 0 : return -1;
- 581 11432 : return 0;
- 582 : }
- 583 :
- 584 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */
- 585 0 : if (size == 0) {
- 586 0 : *physical = FILEPHY_WITHOUT_OFFSET;
- 587 0 : if (close(f) == -1)
- 588 0 : return -1;
- 589 0 : return 0;
- 590 : }
- 591 :
- 592 : /* then try with FIBMAP */
- 593 : /* it works for jfs, reiserfs, ntfs-3g */
- 594 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */
- 595 0 : blknum = 0; /* first block */
- 596 0 : if (ioctl(f, FIBMAP, &blknum) != -1) {
- 597 0 : *physical = blknum + FILEPHY_REAL_OFFSET;
- 598 0 : if (close(f) == -1)
+ 490 0 : devname = blkid_devno_to_devname(device);
+ 491 0 : if (!devname) {
+ 492 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno));
+ 493 : /* device mapping failed */
+ 494 0 : return -1;
+ 495 : }
+ 496 :
+ 497 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname);
+ 498 0 : if (!uuidname) {
+ 499 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno));
+ 500 : /* uuid mapping failed */
+ 501 0 : free(devname);
+ 502 0 : return -1;
+ 503 : }
+ 504 :
+ 505 0 : pathcpy(uuid, uuid_size, uuidname);
+ 506 :
+ 507 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname);
+ 508 :
+ 509 0 : free(devname);
+ 510 0 : free(uuidname);
+ 511 0 : return 0;
+ 512 : }
+ 513 : #endif
+ 514 :
+ 515 5630 : int devuuid(uint64_t device, char* uuid, size_t uuid_size)
+ 516 : {
+ 517 : #if HAVE_LINUX_DEVICE
+ 518 : /* if the major is the null device */
+ 519 5630 : if (major(device) == 0) {
+ 520 : /* obtain the real device */
+ 521 4 : if (devdereference(device, &device) != 0) {
+ 522 : /* LCOV_EXCL_START */
+ 523 : return -1;
+ 524 : /* LCOV_EXCL_STOP */
+ 525 : }
+ 526 : }
+ 527 : #endif
+ 528 :
+ 529 : /* first try with the /dev/disk/by-uuid version */
+ 530 : #if HAVE_LINUX_DEVICE
+ 531 5626 : if (devuuid_dev(device, uuid, uuid_size) == 0)
+ 532 5626 : return 0;
+ 533 : #else
+ 534 : log_tag("uuid:by-uuidd:%u:%u: by-uuid not supported\n", major(device), minor(device));
+ 535 : #endif
+ 536 :
+ 537 : /* fall back to blkid for other cases */
+ 538 : #if HAVE_BLKID
+ 539 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0)
+ 540 0 : return 0;
+ 541 : #else
+ 542 : log_tag("uuid:blkid:%u:%u: blkid not supported\n", major(device), minor(device));
+ 543 : #endif
+ 544 :
+ 545 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device));
+ 546 :
+ 547 : /* not supported */
+ 548 : (void)uuid;
+ 549 : (void)uuid_size;
+ 550 0 : return -1;
+ 551 : }
+ 552 :
+ 553 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical)
+ 554 : {
+ 555 : #if HAVE_LINUX_FIEMAP_H
+ 556 : /* In Linux get the real physical address of the file */
+ 557 : /* Note that FIEMAP doesn't require root permission */
+ 558 : int f;
+ 559 : struct {
+ 560 : struct fiemap fiemap;
+ 561 : struct fiemap_extent extent;
+ 562 : } fm;
+ 563 : unsigned int blknum;
+ 564 :
+ 565 11432 : f = open(path, O_RDONLY);
+ 566 11432 : if (f == -1) {
+ 567 0 : return -1;
+ 568 : }
+ 569 :
+ 570 : /* first try with FIEMAP */
+ 571 : /* if works for ext2, ext3, ext4, xfs, btrfs */
+ 572 11432 : memset(&fm, 0, sizeof(fm));
+ 573 11432 : fm.fiemap.fm_start = 0;
+ 574 11432 : fm.fiemap.fm_length = ~0ULL;
+ 575 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
+ 576 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
+ 577 :
+ 578 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) {
+ 579 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags;
+ 580 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical;
+ 581 :
+ 582 : /* check some condition for validating the offset */
+ 583 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) {
+ 584 : /* if the data is inline, we don't have an offset to report */
+ 585 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 586 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) {
+ 587 : /* if the offset is unknown, we don't have an offset to report */
+ 588 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 589 11432 : } else if (offset == 0) {
+ 590 : /* 0 is the general fallback for file-systems when */
+ 591 : /* they don't have an offset to report */
+ 592 14 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 593 : } else {
+ 594 : /* finally report the real offset */
+ 595 11418 : *physical = offset + FILEPHY_REAL_OFFSET;
+ 596 : }
+ 597 :
+ 598 11432 : if (close(f) == -1)
599 0 : return -1;
- 600 0 : return 0;
+ 600 11432 : return 0;
601 : }
602 :
- 603 : /* otherwise don't use anything, and keep the directory traversal order */
- 604 : /* at now this should happen only for vfat */
- 605 : /* and it's surely better than using fake inodes */
- 606 0 : *physical = FILEPHY_UNREPORTED_OFFSET;
- 607 0 : if (close(f) == -1)
- 608 0 : return -1;
- 609 : #else
- 610 : /* In a generic Unix use a dummy value for all the files */
- 611 : /* We don't want to risk to use the inode without knowing */
- 612 : /* if it really improves performance. */
- 613 : /* In this way we keep them in the directory traversal order */
- 614 : /* that at least keeps files in the same directory together. */
- 615 : /* Note also that in newer file-system with snapshot, like ZFS, */
- 616 : /* the inode doesn't represent evenmore the disk position, because files */
- 617 : /* are not overwritten in place, but rewritten in another location */
- 618 : /* of the disk. */
- 619 : *physical = FILEPHY_UNREPORTED_OFFSET;
- 620 :
- 621 : (void)path; /* not used here */
- 622 : (void)size;
- 623 : #endif
- 624 :
- 625 0 : return 0;
- 626 : }
- 627 :
- 628 5483 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space)
- 629 : {
- 630 : char type[64];
- 631 : const char* ptype;
- 632 :
- 633 : #if HAVE_STATFS
- 634 : struct statfs st;
- 635 :
- 636 5483 : if (statfs(path, &st) != 0) {
- 637 : char dir[PATH_MAX];
- 638 : char* slash;
+ 603 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */
+ 604 0 : if (size == 0) {
+ 605 0 : *physical = FILEPHY_WITHOUT_OFFSET;
+ 606 0 : if (close(f) == -1)
+ 607 0 : return -1;
+ 608 0 : return 0;
+ 609 : }
+ 610 :
+ 611 : /* then try with FIBMAP */
+ 612 : /* it works for jfs, reiserfs, ntfs-3g */
+ 613 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */
+ 614 0 : blknum = 0; /* first block */
+ 615 0 : if (ioctl(f, FIBMAP, &blknum) != -1) {
+ 616 0 : *physical = blknum + FILEPHY_REAL_OFFSET;
+ 617 0 : if (close(f) == -1)
+ 618 0 : return -1;
+ 619 0 : return 0;
+ 620 : }
+ 621 :
+ 622 : /* otherwise don't use anything, and keep the directory traversal order */
+ 623 : /* at now this should happen only for vfat */
+ 624 : /* and it's surely better than using fake inodes */
+ 625 0 : *physical = FILEPHY_UNREPORTED_OFFSET;
+ 626 0 : if (close(f) == -1)
+ 627 0 : return -1;
+ 628 : #else
+ 629 : /* In a generic Unix use a dummy value for all the files */
+ 630 : /* We don't want to risk to use the inode without knowing */
+ 631 : /* if it really improves performance. */
+ 632 : /* In this way we keep them in the directory traversal order */
+ 633 : /* that at least keeps files in the same directory together. */
+ 634 : /* Note also that in newer file-system with snapshot, like ZFS, */
+ 635 : /* the inode doesn't represent evenmore the disk position, because files */
+ 636 : /* are not overwritten in place, but rewritten in another location */
+ 637 : /* of the disk. */
+ 638 : *physical = FILEPHY_UNREPORTED_OFFSET;
639 :
- 640 24 : if (errno != ENOENT) {
- 641 0 : return -1;
- 642 : }
+ 640 : (void)path; /* not used here */
+ 641 : (void)size;
+ 642 : #endif
643 :
- 644 : /* if it doesn't exist, we assume a file */
- 645 : /* and we check for the containing dir */
- 646 24 : if (strlen(path) + 1 > sizeof(dir)) {
- 647 0 : errno = ENAMETOOLONG;
- 648 0 : return -1;
- 649 : }
- 650 :
- 651 24 : strcpy(dir, path);
- 652 :
- 653 24 : slash = strrchr(dir, '/');
- 654 24 : if (!slash)
- 655 0 : return -1;
- 656 :
- 657 24 : *slash = 0;
- 658 24 : if (statfs(dir, &st) != 0)
- 659 0 : return -1;
- 660 : }
- 661 : #endif
+ 644 0 : return 0;
+ 645 : }
+ 646 :
+ 647 5483 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space)
+ 648 : {
+ 649 : char type[64];
+ 650 : const char* ptype;
+ 651 :
+ 652 : #if HAVE_STATFS
+ 653 : struct statfs st;
+ 654 :
+ 655 5483 : if (statfs(path, &st) != 0) {
+ 656 : char dir[PATH_MAX];
+ 657 : char* slash;
+ 658 :
+ 659 24 : if (errno != ENOENT) {
+ 660 0 : return -1;
+ 661 : }
662 :
- 663 : /* to get the fs type check "man stat" or "stat -f -t FILE" */
- 664 5483 : if (has_persistent_inode) {
- 665 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
- 666 575 : switch (st.f_type) {
- 667 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */
- 668 : case 0x4d44 : /* VFAT, "msdos" in the stat command */
- 669 0 : *has_persistent_inode = 0;
- 670 0 : break;
- 671 : default :
- 672 : /* by default assume yes */
- 673 575 : *has_persistent_inode = 1;
- 674 575 : break;
- 675 : }
- 676 : #else
- 677 : /* by default assume yes */
- 678 : *has_persistent_inode = 1;
- 679 : #endif
- 680 : }
+ 663 : /* if it doesn't exist, we assume a file */
+ 664 : /* and we check for the containing dir */
+ 665 24 : if (strlen(path) + 1 > sizeof(dir)) {
+ 666 0 : errno = ENAMETOOLONG;
+ 667 0 : return -1;
+ 668 : }
+ 669 :
+ 670 24 : strcpy(dir, path);
+ 671 :
+ 672 24 : slash = strrchr(dir, '/');
+ 673 24 : if (!slash)
+ 674 0 : return -1;
+ 675 :
+ 676 24 : *slash = 0;
+ 677 24 : if (statfs(dir, &st) != 0)
+ 678 0 : return -1;
+ 679 : }
+ 680 : #endif
681 :
- 682 5483 : if (total_space) {
- 683 : #if HAVE_STATFS
- 684 4908 : *total_space = st.f_bsize * (uint64_t)st.f_blocks;
- 685 : #else
- 686 : *total_space = 0;
- 687 : #endif
- 688 : }
- 689 :
- 690 5483 : if (free_space) {
- 691 : #if HAVE_STATFS
- 692 4908 : *free_space = st.f_bsize * (uint64_t)st.f_bfree;
- 693 : #else
- 694 : *free_space = 0;
- 695 : #endif
- 696 : }
- 697 :
- 698 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME
- 699 : /* get the filesystem type directly from the struct (Mac OS X) */
- 700 : (void)type;
- 701 : ptype = st.f_fstypename;
- 702 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
- 703 : /* get the filesystem type from f_type (Linux) */
- 704 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */
- 705 5483 : switch (st.f_type) {
- 706 0 : case 0x65735546 : ptype = "fuseblk"; break;
- 707 0 : case 0x4D44 : ptype = "vfat/msdos"; break;
- 708 5483 : case 0xEF53 : ptype = "ext2/3/4"; break;
- 709 0 : case 0x6969 : ptype = "nfs"; break; /* remote */
- 710 0 : case 0x6E667364 : ptype = "nfsd"; break; /* remote */
- 711 0 : case 0x517B : ptype = "smb"; break; /* remote */
- 712 0 : case 0x5346544E : ptype = "ntfs"; break;
- 713 0 : case 0x52654973 : ptype = "reiserfs"; break;
- 714 0 : case 0x3153464A : ptype = "jfs"; break;
- 715 0 : case 0x58465342 : ptype = "xfs"; break;
- 716 0 : case 0x9123683E : ptype = "btrfs"; break;
- 717 0 : case 0x2FC12FC1 : ptype = "zfs"; break;
- 718 : default :
- 719 0 : snprintf(type, sizeof(type), "0x%X", (unsigned)st.f_type);
- 720 0 : ptype = type;
- 721 : }
- 722 : #else
- 723 : (void)type;
- 724 : ptype = "unknown";
- 725 : #endif
- 726 :
- 727 5483 : log_tag("statfs:%s: %s \n", ptype, path);
- 728 :
- 729 5483 : return 0;
- 730 : }
- 731 :
- 732 3817537 : uint64_t tick(void)
- 733 : {
- 734 : #if HAVE_MACH_ABSOLUTE_TIME
- 735 : /* for Mac OS X */
- 736 : return mach_absolute_time();
- 737 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW))
- 738 : /* for Linux */
- 739 : struct timespec tv;
- 740 :
- 741 : /* nanosecond precision with clock_gettime() */
- 742 : #if defined(CLOCK_MONOTONIC_RAW)
- 743 3817537 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) {
- 744 : #else
- 745 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) {
- 746 : #endif
- 747 0 : return 0;
- 748 : }
- 749 :
- 750 3817537 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec;
- 751 : #else
- 752 : /* other platforms */
- 753 : struct timeval tv;
- 754 :
- 755 : /* microsecond precision with gettimeofday() */
- 756 : if (gettimeofday(&tv, 0) != 0) {
- 757 : return 0;
- 758 : }
+ 682 : /* to get the fs type check "man stat" or "stat -f -t FILE" */
+ 683 5483 : if (has_persistent_inode) {
+ 684 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
+ 685 575 : switch (st.f_type) {
+ 686 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */
+ 687 : case 0x4d44 : /* VFAT, "msdos" in the stat command */
+ 688 0 : *has_persistent_inode = 0;
+ 689 0 : break;
+ 690 : default :
+ 691 : /* by default assume yes */
+ 692 575 : *has_persistent_inode = 1;
+ 693 575 : break;
+ 694 : }
+ 695 : #else
+ 696 : /* by default assume yes */
+ 697 : *has_persistent_inode = 1;
+ 698 : #endif
+ 699 : }
+ 700 :
+ 701 5483 : if (total_space) {
+ 702 : #if HAVE_STATFS
+ 703 4908 : *total_space = st.f_bsize * (uint64_t)st.f_blocks;
+ 704 : #else
+ 705 : *total_space = 0;
+ 706 : #endif
+ 707 : }
+ 708 :
+ 709 5483 : if (free_space) {
+ 710 : #if HAVE_STATFS
+ 711 4908 : *free_space = st.f_bsize * (uint64_t)st.f_bfree;
+ 712 : #else
+ 713 : *free_space = 0;
+ 714 : #endif
+ 715 : }
+ 716 :
+ 717 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME
+ 718 : /* get the filesystem type directly from the struct (Mac OS X) */
+ 719 : (void)type;
+ 720 : ptype = st.f_fstypename;
+ 721 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE
+ 722 : /* get the filesystem type from f_type (Linux) */
+ 723 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */
+ 724 5483 : switch (st.f_type) {
+ 725 0 : case 0x65735546 : ptype = "fuseblk"; break;
+ 726 0 : case 0x4D44 : ptype = "vfat/msdos"; break;
+ 727 5483 : case 0xEF53 : ptype = "ext2/3/4"; break;
+ 728 0 : case 0x6969 : ptype = "nfs"; break; /* remote */
+ 729 0 : case 0x6E667364 : ptype = "nfsd"; break; /* remote */
+ 730 0 : case 0x517B : ptype = "smb"; break; /* remote */
+ 731 0 : case 0x5346544E : ptype = "ntfs"; break;
+ 732 0 : case 0x52654973 : ptype = "reiserfs"; break;
+ 733 0 : case 0x3153464A : ptype = "jfs"; break;
+ 734 0 : case 0x58465342 : ptype = "xfs"; break;
+ 735 0 : case 0x9123683E : ptype = "btrfs"; break;
+ 736 0 : case 0x2FC12FC1 : ptype = "zfs"; break;
+ 737 : default :
+ 738 0 : snprintf(type, sizeof(type), "0x%X", (unsigned)st.f_type);
+ 739 0 : ptype = type;
+ 740 : }
+ 741 : #else
+ 742 : (void)type;
+ 743 : ptype = "unknown";
+ 744 : #endif
+ 745 :
+ 746 5483 : log_tag("statfs:%s: %s \n", ptype, path);
+ 747 :
+ 748 5483 : return 0;
+ 749 : }
+ 750 :
+ 751 3819097 : uint64_t tick(void)
+ 752 : {
+ 753 : #if HAVE_MACH_ABSOLUTE_TIME
+ 754 : /* for Mac OS X */
+ 755 : return mach_absolute_time();
+ 756 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW))
+ 757 : /* for Linux */
+ 758 : struct timespec tv;
759 :
- 760 : return tv.tv_sec * 1000000ULL + tv.tv_usec;
- 761 : #endif
- 762 : }
- 763 :
- 764 65 : uint64_t tick_ms(void)
- 765 : {
- 766 : struct timeval tv;
- 767 :
- 768 65 : if (gettimeofday(&tv, 0) != 0)
- 769 0 : return 0;
- 770 :
- 771 65 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
- 772 : }
+ 760 : /* nanosecond precision with clock_gettime() */
+ 761 : #if defined(CLOCK_MONOTONIC_RAW)
+ 762 3819097 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) {
+ 763 : #else
+ 764 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) {
+ 765 : #endif
+ 766 0 : return 0;
+ 767 : }
+ 768 :
+ 769 3819097 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec;
+ 770 : #else
+ 771 : /* other platforms */
+ 772 : struct timeval tv;
773 :
- 774 282 : int randomize(void* ptr, size_t size)
- 775 : {
- 776 : int f;
- 777 : ssize_t ret;
+ 774 : /* microsecond precision with gettimeofday() */
+ 775 : if (gettimeofday(&tv, 0) != 0) {
+ 776 : return 0;
+ 777 : }
778 :
- 779 282 : f = open("/dev/urandom", O_RDONLY);
- 780 282 : if (f == -1)
- 781 0 : return -1;
+ 779 : return tv.tv_sec * 1000000ULL + tv.tv_usec;
+ 780 : #endif
+ 781 : }
782 :
- 783 282 : ret = read(f, ptr, size);
- 784 282 : if (ret < 0 || (size_t)ret != size) {
- 785 0 : close(f);
- 786 0 : return -1;
- 787 : }
- 788 :
- 789 282 : if (close(f) != 0)
- 790 0 : return -1;
- 791 :
- 792 282 : return 0;
- 793 : }
- 794 :
- 795 : /**
- 796 : * Read a file extracting the contained device number in %u:%u format.
- 797 : * Return 0 on error.
- 798 : */
- 799 : #if HAVE_LINUX_DEVICE
- 800 144 : static dev_t devread(const char* path)
- 801 : {
- 802 : int f;
- 803 : int ret;
- 804 : int len;
- 805 : char buf[64];
- 806 : char* e;
- 807 : unsigned ma;
- 808 : unsigned mi;
- 809 :
- 810 144 : f = open(path, O_RDONLY);
- 811 144 : if (f == -1) {
- 812 : /* LCOV_EXCL_START */
- 813 : log_fatal("Failed to open '%s'.\n", path);
- 814 : return 0;
- 815 : /* LCOV_EXCL_STOP */
- 816 : }
- 817 :
- 818 144 : len = read(f, buf, sizeof(buf));
- 819 144 : if (len < 0) {
- 820 : /* LCOV_EXCL_START */
- 821 : close(f);
- 822 : log_fatal("Failed to read '%s'.\n", path);
- 823 : return 0;
- 824 : /* LCOV_EXCL_STOP */
- 825 : }
- 826 144 : if (len == sizeof(buf)) {
- 827 : /* LCOV_EXCL_START */
- 828 : close(f);
- 829 : log_fatal("Too long read '%s'.\n", path);
- 830 : return 0;
- 831 : /* LCOV_EXCL_STOP */
- 832 : }
- 833 :
- 834 144 : ret = close(f);
- 835 144 : if (ret != 0) {
- 836 : /* LCOV_EXCL_START */
- 837 : log_fatal("Failed to close '%s'.\n", path);
- 838 : return 0;
- 839 : /* LCOV_EXCL_STOP */
- 840 : }
- 841 :
- 842 144 : buf[len] = 0;
- 843 :
- 844 144 : ma = strtoul(buf, &e, 10);
- 845 144 : if (*e != ':') {
+ 783 65 : uint64_t tick_ms(void)
+ 784 : {
+ 785 : struct timeval tv;
+ 786 :
+ 787 65 : if (gettimeofday(&tv, 0) != 0)
+ 788 0 : return 0;
+ 789 :
+ 790 63 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
+ 791 : }
+ 792 :
+ 793 282 : int randomize(void* ptr, size_t size)
+ 794 : {
+ 795 : int f;
+ 796 : ssize_t ret;
+ 797 :
+ 798 282 : f = open("/dev/urandom", O_RDONLY);
+ 799 282 : if (f == -1)
+ 800 0 : return -1;
+ 801 :
+ 802 282 : ret = read(f, ptr, size);
+ 803 282 : if (ret < 0 || (size_t)ret != size) {
+ 804 0 : close(f);
+ 805 0 : return -1;
+ 806 : }
+ 807 :
+ 808 282 : if (close(f) != 0)
+ 809 0 : return -1;
+ 810 :
+ 811 282 : return 0;
+ 812 : }
+ 813 :
+ 814 : /**
+ 815 : * Read a file extracting the contained device number in %u:%u format.
+ 816 : * Return 0 on error.
+ 817 : */
+ 818 : #if HAVE_LINUX_DEVICE
+ 819 144 : static dev_t devread(const char* path)
+ 820 : {
+ 821 : int f;
+ 822 : int ret;
+ 823 : int len;
+ 824 : char buf[64];
+ 825 : char* e;
+ 826 : unsigned ma;
+ 827 : unsigned mi;
+ 828 :
+ 829 144 : f = open(path, O_RDONLY);
+ 830 144 : if (f == -1) {
+ 831 : /* LCOV_EXCL_START */
+ 832 : log_fatal("Failed to open '%s'.\n", path);
+ 833 : return 0;
+ 834 : /* LCOV_EXCL_STOP */
+ 835 : }
+ 836 :
+ 837 144 : len = read(f, buf, sizeof(buf));
+ 838 144 : if (len < 0) {
+ 839 : /* LCOV_EXCL_START */
+ 840 : close(f);
+ 841 : log_fatal("Failed to read '%s'.\n", path);
+ 842 : return 0;
+ 843 : /* LCOV_EXCL_STOP */
+ 844 : }
+ 845 144 : if (len == sizeof(buf)) {
846 : /* LCOV_EXCL_START */
- 847 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
- 848 : return 0;
- 849 : /* LCOV_EXCL_STOP */
- 850 : }
- 851 :
- 852 144 : mi = strtoul(e + 1, &e, 10);
- 853 144 : if (*e != 0 && !isspace(*e)) {
- 854 : /* LCOV_EXCL_START */
- 855 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
- 856 : return 0;
- 857 : /* LCOV_EXCL_STOP */
- 858 : }
- 859 :
- 860 144 : return makedev(ma, mi);
- 861 : }
- 862 : #endif
- 863 :
- 864 : /**
- 865 : * Read a device tree filling the specified list of disk_t entries.
- 866 : */
- 867 : #if HAVE_LINUX_DEVICE
- 868 130 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list)
- 869 : {
- 870 : char path[PATH_MAX];
- 871 : DIR* d;
- 872 130 : int slaves = 0;
- 873 :
- 874 130 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device));
- 875 :
- 876 : /* check if there is a slaves list */
- 877 130 : d = opendir(path);
- 878 130 : if (d != 0) {
- 879 : struct dirent* dd;
- 880 :
- 881 325 : while ((dd = readdir(d)) != 0) {
- 882 195 : if (dd->d_name[0] != '.') {
- 883 : /* for each slave, expand the full potential tree */
- 884 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name);
- 885 :
- 886 65 : device = devread(path);
- 887 65 : if (!device) {
- 888 : /* LCOV_EXCL_START */
- 889 : closedir(d);
- 890 : return -1;
- 891 : /* LCOV_EXCL_STOP */
- 892 : }
- 893 :
- 894 65 : if (devtree(name, custom, device, parent, list) != 0) {
- 895 : /* LCOV_EXCL_START */
- 896 : closedir(d);
- 897 : return -1;
- 898 : /* LCOV_EXCL_STOP */
- 899 : }
- 900 :
- 901 65 : ++slaves;
- 902 : }
- 903 : }
+ 847 : close(f);
+ 848 : log_fatal("Too long read '%s'.\n", path);
+ 849 : return 0;
+ 850 : /* LCOV_EXCL_STOP */
+ 851 : }
+ 852 :
+ 853 144 : ret = close(f);
+ 854 144 : if (ret != 0) {
+ 855 : /* LCOV_EXCL_START */
+ 856 : log_fatal("Failed to close '%s'.\n", path);
+ 857 : return 0;
+ 858 : /* LCOV_EXCL_STOP */
+ 859 : }
+ 860 :
+ 861 144 : buf[len] = 0;
+ 862 :
+ 863 144 : ma = strtoul(buf, &e, 10);
+ 864 144 : if (*e != ':') {
+ 865 : /* LCOV_EXCL_START */
+ 866 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
+ 867 : return 0;
+ 868 : /* LCOV_EXCL_STOP */
+ 869 : }
+ 870 :
+ 871 144 : mi = strtoul(e + 1, &e, 10);
+ 872 144 : if (*e != 0 && !isspace(*e)) {
+ 873 : /* LCOV_EXCL_START */
+ 874 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf);
+ 875 : return 0;
+ 876 : /* LCOV_EXCL_STOP */
+ 877 : }
+ 878 :
+ 879 144 : return makedev(ma, mi);
+ 880 : }
+ 881 : #endif
+ 882 :
+ 883 : /**
+ 884 : * Read a device tree filling the specified list of disk_t entries.
+ 885 : */
+ 886 : #if HAVE_LINUX_DEVICE
+ 887 130 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list)
+ 888 : {
+ 889 : char path[PATH_MAX];
+ 890 : DIR* d;
+ 891 130 : int slaves = 0;
+ 892 :
+ 893 130 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device));
+ 894 :
+ 895 : /* check if there is a slaves list */
+ 896 130 : d = opendir(path);
+ 897 130 : if (d != 0) {
+ 898 : struct dirent* dd;
+ 899 :
+ 900 325 : while ((dd = readdir(d)) != 0) {
+ 901 195 : if (dd->d_name[0] != '.') {
+ 902 : /* for each slave, expand the full potential tree */
+ 903 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name);
904 :
- 905 65 : closedir(d);
- 906 : }
- 907 :
- 908 : /* if no slaves found */
- 909 130 : if (!slaves) {
- 910 : /* this is a raw device */
- 911 : devinfo_t* devinfo;
+ 905 65 : device = devread(path);
+ 906 65 : if (!device) {
+ 907 : /* LCOV_EXCL_START */
+ 908 : closedir(d);
+ 909 : return -1;
+ 910 : /* LCOV_EXCL_STOP */
+ 911 : }
912 :
- 913 : /* check if it's a real device */
- 914 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device));
- 915 65 : if (access(path, F_OK) != 0) {
- 916 : /* get the parent device */
- 917 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device));
- 918 :
- 919 65 : device = devread(path);
- 920 65 : if (!device) {
- 921 : /* LCOV_EXCL_START */
- 922 : return -1;
- 923 : /* LCOV_EXCL_STOP */
- 924 : }
- 925 : }
+ 913 65 : if (devtree(name, custom, device, parent, list) != 0) {
+ 914 : /* LCOV_EXCL_START */
+ 915 : closedir(d);
+ 916 : return -1;
+ 917 : /* LCOV_EXCL_STOP */
+ 918 : }
+ 919 :
+ 920 65 : ++slaves;
+ 921 : }
+ 922 : }
+ 923 :
+ 924 65 : closedir(d);
+ 925 : }
926 :
- 927 : /* get the device file */
- 928 65 : if (devresolve(device, path, sizeof(path)) != 0) {
- 929 : /* LCOV_EXCL_START */
- 930 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
- 931 : return -1;
- 932 : /* LCOV_EXCL_STOP */
- 933 : }
- 934 :
- 935 65 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
- 936 :
- 937 65 : devinfo->device = device;
- 938 65 : pathcpy(devinfo->name, sizeof(devinfo->name), name);
- 939 65 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom);
- 940 65 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
- 941 65 : devinfo->parent = parent;
- 942 :
- 943 : /* insert in the list */
- 944 65 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
- 945 : }
- 946 :
- 947 130 : return 0;
- 948 : }
- 949 : #endif
- 950 :
- 951 : /**
- 952 : * Scan all the devices.
- 953 : *
- 954 : * If a device is already in, it's not added again.
- 955 : */
- 956 : #if HAVE_LINUX_DEVICE
- 957 1 : static int devscan(tommy_list* list)
- 958 : {
- 959 : char dir[PATH_MAX];
- 960 : DIR* d;
- 961 : struct dirent* dd;
- 962 :
- 963 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/");
- 964 :
- 965 : /* check if there is a slaves list */
- 966 1 : d = opendir(dir);
- 967 1 : if (d == 0) {
- 968 : /* LCOV_EXCL_START */
- 969 : log_fatal("Failed to open dir '%s'.\n", dir);
- 970 : return -1;
- 971 : /* LCOV_EXCL_STOP */
- 972 : }
- 973 :
- 974 74 : while ((dd = readdir(d)) != 0) {
- 975 : char path[PATH_MAX];
- 976 : tommy_node* i;
- 977 : dev_t device;
- 978 : devinfo_t* devinfo;
- 979 :
- 980 72 : if (dd->d_name[0] == '.')
- 981 61 : continue;
- 982 :
- 983 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name);
- 984 :
- 985 : /* check if it's a real device */
- 986 70 : if (access(path, F_OK) != 0)
- 987 56 : continue;
- 988 :
- 989 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name);
- 990 :
- 991 14 : device = devread(path);
- 992 14 : if (!device) {
- 993 : /* LCOV_EXCL_START */
- 994 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name);
- 995 : continue;
- 996 : /* LCOV_EXCL_STOP */
- 997 : }
+ 927 : /* if no slaves found */
+ 928 130 : if (!slaves) {
+ 929 : /* this is a raw device */
+ 930 : devinfo_t* devinfo;
+ 931 :
+ 932 : /* check if it's a real device */
+ 933 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device));
+ 934 65 : if (access(path, F_OK) != 0) {
+ 935 : /* get the parent device */
+ 936 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device));
+ 937 :
+ 938 65 : device = devread(path);
+ 939 65 : if (!device) {
+ 940 : /* LCOV_EXCL_START */
+ 941 : return -1;
+ 942 : /* LCOV_EXCL_STOP */
+ 943 : }
+ 944 : }
+ 945 :
+ 946 : /* get the device file */
+ 947 65 : if (devresolve(device, path, sizeof(path)) != 0) {
+ 948 : /* LCOV_EXCL_START */
+ 949 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
+ 950 : return -1;
+ 951 : /* LCOV_EXCL_STOP */
+ 952 : }
+ 953 :
+ 954 65 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
+ 955 :
+ 956 65 : devinfo->device = device;
+ 957 65 : pathcpy(devinfo->name, sizeof(devinfo->name), name);
+ 958 65 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom);
+ 959 65 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
+ 960 65 : devinfo->parent = parent;
+ 961 :
+ 962 : /* insert in the list */
+ 963 65 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
+ 964 : }
+ 965 :
+ 966 130 : return 0;
+ 967 : }
+ 968 : #endif
+ 969 :
+ 970 : /**
+ 971 : * Scan all the devices.
+ 972 : *
+ 973 : * If a device is already in, it's not added again.
+ 974 : */
+ 975 : #if HAVE_LINUX_DEVICE
+ 976 1 : static int devscan(tommy_list* list)
+ 977 : {
+ 978 : char dir[PATH_MAX];
+ 979 : DIR* d;
+ 980 : struct dirent* dd;
+ 981 :
+ 982 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/");
+ 983 :
+ 984 : /* check if there is a slaves list */
+ 985 1 : d = opendir(dir);
+ 986 1 : if (d == 0) {
+ 987 : /* LCOV_EXCL_START */
+ 988 : log_fatal("Failed to open dir '%s'.\n", dir);
+ 989 : return -1;
+ 990 : /* LCOV_EXCL_STOP */
+ 991 : }
+ 992 :
+ 993 74 : while ((dd = readdir(d)) != 0) {
+ 994 : char path[PATH_MAX];
+ 995 : tommy_node* i;
+ 996 : dev_t device;
+ 997 : devinfo_t* devinfo;
998 :
- 999 : /* check if already present */
- 1000 482 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 1001 469 : devinfo = i->data;
- 1002 469 : if (devinfo->device == device)
- 1003 1 : break;
- 1004 : }
- 1005 :
- 1006 : /* if already present */
- 1007 14 : if (i != 0)
- 1008 1 : continue;
+ 999 72 : if (dd->d_name[0] == '.')
+ 1000 61 : continue;
+ 1001 :
+ 1002 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name);
+ 1003 :
+ 1004 : /* check if it's a real device */
+ 1005 70 : if (access(path, F_OK) != 0)
+ 1006 56 : continue;
+ 1007 :
+ 1008 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name);
1009 :
- 1010 : /* get the device file */
- 1011 13 : if (devresolve(device, path, sizeof(path)) != 0) {
+ 1010 14 : device = devread(path);
+ 1011 14 : if (!device) {
1012 : /* LCOV_EXCL_START */
- 1013 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device));
+ 1013 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name);
1014 : continue;
1015 : /* LCOV_EXCL_STOP */
1016 : }
1017 :
- 1018 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
- 1019 :
- 1020 13 : devinfo->device = device;
- 1021 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
- 1022 :
- 1023 : /* insert in the list */
- 1024 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
- 1025 : }
- 1026 :
- 1027 1 : closedir(d);
- 1028 1 : return 0;
- 1029 : }
- 1030 : #endif
- 1031 :
- 1032 : /**
- 1033 : * Get SMART attributes.
- 1034 : */
- 1035 : #if HAVE_LINUX_DEVICE
- 1036 43 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model)
- 1037 : {
- 1038 : char cmd[128];
- 1039 : char file[128];
- 1040 : FILE* f;
- 1041 : int ret;
- 1042 :
- 1043 43 : if (devresolve(device, file, sizeof(file)) != 0) {
- 1044 : /* LCOV_EXCL_START */
- 1045 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
- 1046 : return -1;
- 1047 : /* LCOV_EXCL_STOP */
- 1048 : }
- 1049 :
- 1050 : /* if there is a custom command */
- 1051 43 : if (custom[0]) {
- 1052 : char option[128];
- 1053 5 : snprintf(option, sizeof(option), custom, file);
- 1054 5 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option);
- 1055 : } else {
- 1056 38 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file);
- 1057 : }
- 1058 :
- 1059 43 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
- 1060 :
- 1061 43 : f = popen(cmd, "r");
- 1062 43 : if (!f) {
+ 1018 : /* check if already present */
+ 1019 482 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 1020 469 : devinfo = i->data;
+ 1021 469 : if (devinfo->device == device)
+ 1022 1 : break;
+ 1023 : }
+ 1024 :
+ 1025 : /* if already present */
+ 1026 14 : if (i != 0)
+ 1027 1 : continue;
+ 1028 :
+ 1029 : /* get the device file */
+ 1030 13 : if (devresolve(device, path, sizeof(path)) != 0) {
+ 1031 : /* LCOV_EXCL_START */
+ 1032 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device));
+ 1033 : continue;
+ 1034 : /* LCOV_EXCL_STOP */
+ 1035 : }
+ 1036 :
+ 1037 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t));
+ 1038 :
+ 1039 13 : devinfo->device = device;
+ 1040 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path);
+ 1041 :
+ 1042 : /* insert in the list */
+ 1043 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo);
+ 1044 : }
+ 1045 :
+ 1046 1 : closedir(d);
+ 1047 1 : return 0;
+ 1048 : }
+ 1049 : #endif
+ 1050 :
+ 1051 : /**
+ 1052 : * Get SMART attributes.
+ 1053 : */
+ 1054 : #if HAVE_LINUX_DEVICE
+ 1055 42 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model)
+ 1056 : {
+ 1057 : char cmd[128];
+ 1058 : char file[128];
+ 1059 : FILE* f;
+ 1060 : int ret;
+ 1061 :
+ 1062 42 : if (devresolve(device, file, sizeof(file)) != 0) {
1063 : /* LCOV_EXCL_START */
- 1064 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 1064 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
1065 : return -1;
1066 : /* LCOV_EXCL_STOP */
1067 : }
1068 :
- 1069 43 : if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) {
- 1070 : /* LCOV_EXCL_START */
- 1071 : pclose(f);
- 1072 : return -1;
- 1073 : /* LCOV_EXCL_STOP */
- 1074 : }
- 1075 :
- 1076 43 : ret = pclose(f);
+ 1069 : /* if there is a custom command */
+ 1070 43 : if (custom[0]) {
+ 1071 : char option[128];
+ 1072 5 : snprintf(option, sizeof(option), custom, file);
+ 1073 5 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option);
+ 1074 : } else {
+ 1075 38 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file);
+ 1076 : }
1077 :
- 1078 43 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
+ 1078 43 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
1079 :
- 1080 43 : if (!WIFEXITED(ret)) {
- 1081 : /* LCOV_EXCL_START */
- 1082 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
- 1083 : return -1;
- 1084 : /* LCOV_EXCL_STOP */
- 1085 : }
- 1086 43 : if (WEXITSTATUS(ret) == 127) {
- 1087 : /* LCOV_EXCL_START */
- 1088 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
- 1089 : return -1;
- 1090 : /* LCOV_EXCL_STOP */
- 1091 : }
- 1092 :
- 1093 : /* store the return smartctl return value */
- 1094 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret);
- 1095 :
- 1096 0 : return 0;
- 1097 : }
- 1098 : #endif
- 1099 :
- 1100 : /**
- 1101 : * Spin down a specific device.
- 1102 : */
- 1103 : #if HAVE_LINUX_DEVICE
- 1104 5 : static int devdown(dev_t device, const char* name, const char* custom)
- 1105 : {
- 1106 : char cmd[128];
- 1107 : char file[128];
- 1108 : FILE* f;
- 1109 : int ret;
- 1110 :
- 1111 5 : if (devresolve(device, file, sizeof(file)) != 0) {
- 1112 : /* LCOV_EXCL_START */
- 1113 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
- 1114 : return -1;
- 1115 : /* LCOV_EXCL_STOP */
- 1116 : }
- 1117 :
- 1118 : /* if there is a custom command */
- 1119 5 : if (custom[0]) {
- 1120 : char option[128];
- 1121 5 : snprintf(option, sizeof(option), custom, file);
- 1122 5 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option);
- 1123 : } else {
- 1124 0 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file);
- 1125 : }
- 1126 :
- 1127 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
- 1128 :
- 1129 5 : f = popen(cmd, "r");
- 1130 5 : if (!f) {
+ 1080 43 : f = popen(cmd, "r");
+ 1081 42 : if (!f) {
+ 1082 : /* LCOV_EXCL_START */
+ 1083 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 1084 : return -1;
+ 1085 : /* LCOV_EXCL_STOP */
+ 1086 : }
+ 1087 :
+ 1088 42 : if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) {
+ 1089 : /* LCOV_EXCL_START */
+ 1090 : pclose(f);
+ 1091 : return -1;
+ 1092 : /* LCOV_EXCL_STOP */
+ 1093 : }
+ 1094 :
+ 1095 42 : ret = pclose(f);
+ 1096 :
+ 1097 43 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
+ 1098 :
+ 1099 43 : if (!WIFEXITED(ret)) {
+ 1100 : /* LCOV_EXCL_START */
+ 1101 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
+ 1102 : return -1;
+ 1103 : /* LCOV_EXCL_STOP */
+ 1104 : }
+ 1105 43 : if (WEXITSTATUS(ret) == 127) {
+ 1106 : /* LCOV_EXCL_START */
+ 1107 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
+ 1108 : return -1;
+ 1109 : /* LCOV_EXCL_STOP */
+ 1110 : }
+ 1111 :
+ 1112 : /* store the return smartctl return value */
+ 1113 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret);
+ 1114 :
+ 1115 0 : return 0;
+ 1116 : }
+ 1117 : #endif
+ 1118 :
+ 1119 : /**
+ 1120 : * Spin down a specific device.
+ 1121 : */
+ 1122 : #if HAVE_LINUX_DEVICE
+ 1123 5 : static int devdown(dev_t device, const char* name, const char* custom)
+ 1124 : {
+ 1125 : char cmd[128];
+ 1126 : char file[128];
+ 1127 : FILE* f;
+ 1128 : int ret;
+ 1129 :
+ 1130 5 : if (devresolve(device, file, sizeof(file)) != 0) {
1131 : /* LCOV_EXCL_START */
- 1132 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 1132 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
1133 : return -1;
1134 : /* LCOV_EXCL_STOP */
1135 : }
1136 :
- 1137 5 : if (smartctl_flush(f, file, name) != 0) {
- 1138 : /* LCOV_EXCL_START */
- 1139 : pclose(f);
- 1140 : return -1;
- 1141 : /* LCOV_EXCL_STOP */
- 1142 : }
- 1143 :
- 1144 5 : ret = pclose(f);
+ 1137 : /* if there is a custom command */
+ 1138 5 : if (custom[0]) {
+ 1139 : char option[128];
+ 1140 5 : snprintf(option, sizeof(option), custom, file);
+ 1141 5 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option);
+ 1142 : } else {
+ 1143 0 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file);
+ 1144 : }
1145 :
- 1146 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
+ 1146 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd);
1147 :
- 1148 5 : if (!WIFEXITED(ret)) {
- 1149 : /* LCOV_EXCL_START */
- 1150 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
- 1151 : return -1;
- 1152 : /* LCOV_EXCL_STOP */
- 1153 : }
- 1154 5 : if (WEXITSTATUS(ret) == 127) {
- 1155 : /* LCOV_EXCL_START */
- 1156 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
- 1157 : return -1;
- 1158 : /* LCOV_EXCL_STOP */
- 1159 : }
- 1160 0 : if (WEXITSTATUS(ret) != 0) {
- 1161 : /* LCOV_EXCL_START */
- 1162 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret));
- 1163 : return -1;
- 1164 : /* LCOV_EXCL_STOP */
- 1165 : }
+ 1148 5 : f = popen(cmd, "r");
+ 1149 5 : if (!f) {
+ 1150 : /* LCOV_EXCL_START */
+ 1151 : log_fatal("Failed to run '%s' (from popen).\n", cmd);
+ 1152 : return -1;
+ 1153 : /* LCOV_EXCL_STOP */
+ 1154 : }
+ 1155 :
+ 1156 5 : if (smartctl_flush(f, file, name) != 0) {
+ 1157 : /* LCOV_EXCL_START */
+ 1158 : pclose(f);
+ 1159 : return -1;
+ 1160 : /* LCOV_EXCL_STOP */
+ 1161 : }
+ 1162 :
+ 1163 5 : ret = pclose(f);
+ 1164 :
+ 1165 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret);
1166 :
- 1167 0 : return 0;
- 1168 : }
- 1169 : #endif
- 1170 :
- 1171 : /**
- 1172 : * Spin up a device.
- 1173 : *
- 1174 : * There isn't a defined way to spin up a device,
- 1175 : * so we just do a generic write.
- 1176 : */
- 1177 30 : static int devup(const char* mountpoint)
- 1178 : {
- 1179 : int ret;
- 1180 : char path[PATH_MAX];
- 1181 :
- 1182 : /* add a temporary name used for writing */
- 1183 30 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint);
- 1184 :
- 1185 : /* do a generic write, and immediately undo it */
- 1186 30 : ret = mkdir(path, 0);
- 1187 30 : if (ret != 0 && errno != EEXIST) {
- 1188 : /* LCOV_EXCL_START */
- 1189 : log_fatal("Failed to create dir '%s'.\n", path);
- 1190 : return -1;
- 1191 : /* LCOV_EXCL_STOP */
- 1192 : }
- 1193 :
- 1194 : /* remove the just created dir */
- 1195 30 : rmdir(path);
- 1196 :
- 1197 30 : return 0;
- 1198 : }
- 1199 :
- 1200 : /**
- 1201 : * Thread for spinning up.
- 1202 : *
- 1203 : * Note that filling up the devinfo object is done inside this thread,
- 1204 : * to avoid to block the main thread if the device need to be spin up
- 1205 : * to handle stat/resolve requests.
- 1206 : */
- 1207 30 : static void* thread_spinup(void* arg)
- 1208 : {
- 1209 30 : devinfo_t* devinfo = arg;
- 1210 : struct stat st;
- 1211 : uint64_t start;
+ 1167 5 : if (!WIFEXITED(ret)) {
+ 1168 : /* LCOV_EXCL_START */
+ 1169 : log_fatal("Failed to run '%s' (not exited).\n", cmd);
+ 1170 : return -1;
+ 1171 : /* LCOV_EXCL_STOP */
+ 1172 : }
+ 1173 5 : if (WEXITSTATUS(ret) == 127) {
+ 1174 : /* LCOV_EXCL_START */
+ 1175 : log_fatal("Failed to run '%s' (from sh).\n", cmd);
+ 1176 : return -1;
+ 1177 : /* LCOV_EXCL_STOP */
+ 1178 : }
+ 1179 0 : if (WEXITSTATUS(ret) != 0) {
+ 1180 : /* LCOV_EXCL_START */
+ 1181 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret));
+ 1182 : return -1;
+ 1183 : /* LCOV_EXCL_STOP */
+ 1184 : }
+ 1185 :
+ 1186 0 : return 0;
+ 1187 : }
+ 1188 : #endif
+ 1189 :
+ 1190 : /**
+ 1191 : * Spin up a device.
+ 1192 : *
+ 1193 : * There isn't a defined way to spin up a device,
+ 1194 : * so we just do a generic write.
+ 1195 : */
+ 1196 30 : static int devup(const char* mountpoint)
+ 1197 : {
+ 1198 : int ret;
+ 1199 : char path[PATH_MAX];
+ 1200 :
+ 1201 : /* add a temporary name used for writing */
+ 1202 30 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint);
+ 1203 :
+ 1204 : /* do a generic write, and immediately undo it */
+ 1205 30 : ret = mkdir(path, 0);
+ 1206 30 : if (ret != 0 && errno != EEXIST) {
+ 1207 : /* LCOV_EXCL_START */
+ 1208 : log_fatal("Failed to create dir '%s'.\n", path);
+ 1209 : return -1;
+ 1210 : /* LCOV_EXCL_STOP */
+ 1211 : }
1212 :
- 1213 30 : start = tick_ms();
- 1214 :
- 1215 : /* first get the device number, this usually doesn't trigger a thread_spinup */
- 1216 30 : if (stat(devinfo->mount, &st) != 0) {
- 1217 : /* LCOV_EXCL_START */
- 1218 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount);
- 1219 : return (void*)-1;
- 1220 : /* LCOV_EXCL_STOP */
- 1221 : }
- 1222 :
- 1223 : /* set the device number for printing */
- 1224 30 : devinfo->device = st.st_dev;
- 1225 :
- 1226 30 : if (devup(devinfo->mount) != 0) {
- 1227 : /* LCOV_EXCL_START */
- 1228 : return (void*)-1;
- 1229 : /* LCOV_EXCL_STOP */
- 1230 : }
+ 1213 : /* remove the just created dir */
+ 1214 30 : rmdir(path);
+ 1215 :
+ 1216 30 : return 0;
+ 1217 : }
+ 1218 :
+ 1219 : /**
+ 1220 : * Thread for spinning up.
+ 1221 : *
+ 1222 : * Note that filling up the devinfo object is done inside this thread,
+ 1223 : * to avoid to block the main thread if the device need to be spin up
+ 1224 : * to handle stat/resolve requests.
+ 1225 : */
+ 1226 30 : static void* thread_spinup(void* arg)
+ 1227 : {
+ 1228 30 : devinfo_t* devinfo = arg;
+ 1229 : struct stat st;
+ 1230 : uint64_t start;
1231 :
- 1232 30 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start);
+ 1232 30 : start = tick_ms();
1233 :
- 1234 30 : return 0;
- 1235 : }
- 1236 :
- 1237 : /**
- 1238 : * Thread for spinning down.
- 1239 : */
- 1240 5 : static void* thread_spindown(void* arg)
- 1241 : {
- 1242 : #if HAVE_LINUX_DEVICE
- 1243 5 : devinfo_t* devinfo = arg;
- 1244 : uint64_t start;
- 1245 :
- 1246 5 : start = tick_ms();
- 1247 :
- 1248 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
- 1249 : /* LCOV_EXCL_START */
- 1250 : return (void*)-1;
- 1251 : /* LCOV_EXCL_STOP */
- 1252 : }
- 1253 :
- 1254 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
+ 1234 : /* first get the device number, this usually doesn't trigger a thread_spinup */
+ 1235 30 : if (stat(devinfo->mount, &st) != 0) {
+ 1236 : /* LCOV_EXCL_START */
+ 1237 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount);
+ 1238 : return (void*)-1;
+ 1239 : /* LCOV_EXCL_STOP */
+ 1240 : }
+ 1241 :
+ 1242 : /* set the device number for printing */
+ 1243 30 : devinfo->device = st.st_dev;
+ 1244 :
+ 1245 30 : if (devup(devinfo->mount) != 0) {
+ 1246 : /* LCOV_EXCL_START */
+ 1247 : return (void*)-1;
+ 1248 : /* LCOV_EXCL_STOP */
+ 1249 : }
+ 1250 :
+ 1251 30 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start);
+ 1252 :
+ 1253 30 : return 0;
+ 1254 : }
1255 :
- 1256 0 : return 0;
- 1257 : #else
- 1258 : (void)arg;
- 1259 : return (void*)-1;
- 1260 : #endif
- 1261 : }
- 1262 :
- 1263 : /**
- 1264 : * Thread for getting smart info.
- 1265 : */
- 1266 43 : static void* thread_smart(void* arg)
- 1267 : {
- 1268 : #if HAVE_LINUX_DEVICE
- 1269 43 : devinfo_t* devinfo = arg;
- 1270 :
- 1271 43 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) {
- 1272 : /* LCOV_EXCL_START */
- 1273 : return (void*)-1;
- 1274 : /* LCOV_EXCL_STOP */
- 1275 : }
- 1276 :
- 1277 0 : return 0;
- 1278 : #else
- 1279 : (void)arg;
- 1280 : return (void*)-1;
- 1281 : #endif
- 1282 : }
- 1283 :
- 1284 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg))
- 1285 : {
- 1286 3 : int fail = 0;
- 1287 : tommy_node* i;
- 1288 :
- 1289 : #if HAVE_PTHREAD
- 1290 : /* start all threads */
- 1291 81 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 1292 78 : devinfo_t* devinfo = i->data;
- 1293 :
- 1294 78 : thread_create(&devinfo->thread, 0, func, devinfo);
- 1295 : }
- 1296 :
- 1297 : /* join all threads */
- 1298 81 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 1299 78 : devinfo_t* devinfo = i->data;
- 1300 : void* retval;
- 1301 :
- 1302 78 : thread_join(devinfo->thread, &retval);
- 1303 :
- 1304 78 : if (retval != 0)
- 1305 48 : ++fail;
- 1306 : }
- 1307 : #else
- 1308 : for (i = tommy_list_head(list); i != 0; i = i->next) {
- 1309 : devinfo_t* devinfo = i->data;
- 1310 :
- 1311 : if (func(devinfo) != 0)
- 1312 : ++fail;
- 1313 : }
- 1314 : #endif
- 1315 3 : if (fail != 0) {
- 1316 : /* LCOV_EXCL_START */
- 1317 : return -1;
- 1318 : /* LCOV_EXCL_STOP */
- 1319 : }
+ 1256 : /**
+ 1257 : * Thread for spinning down.
+ 1258 : */
+ 1259 5 : static void* thread_spindown(void* arg)
+ 1260 : {
+ 1261 : #if HAVE_LINUX_DEVICE
+ 1262 5 : devinfo_t* devinfo = arg;
+ 1263 : uint64_t start;
+ 1264 :
+ 1265 5 : start = tick_ms();
+ 1266 :
+ 1267 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
+ 1268 : /* LCOV_EXCL_START */
+ 1269 : return (void*)-1;
+ 1270 : /* LCOV_EXCL_STOP */
+ 1271 : }
+ 1272 :
+ 1273 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
+ 1274 :
+ 1275 0 : return 0;
+ 1276 : #else
+ 1277 : (void)arg;
+ 1278 : return (void*)-1;
+ 1279 : #endif
+ 1280 : }
+ 1281 :
+ 1282 : /**
+ 1283 : * Thread for getting smart info.
+ 1284 : */
+ 1285 42 : static void* thread_smart(void* arg)
+ 1286 : {
+ 1287 : #if HAVE_LINUX_DEVICE
+ 1288 42 : devinfo_t* devinfo = arg;
+ 1289 :
+ 1290 42 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) {
+ 1291 : /* LCOV_EXCL_START */
+ 1292 : return (void*)-1;
+ 1293 : /* LCOV_EXCL_STOP */
+ 1294 : }
+ 1295 :
+ 1296 0 : return 0;
+ 1297 : #else
+ 1298 : (void)arg;
+ 1299 : return (void*)-1;
+ 1300 : #endif
+ 1301 : }
+ 1302 :
+ 1303 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg))
+ 1304 : {
+ 1305 3 : int fail = 0;
+ 1306 : tommy_node* i;
+ 1307 :
+ 1308 : #if HAVE_PTHREAD
+ 1309 : /* start all threads */
+ 1310 81 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 1311 78 : devinfo_t* devinfo = i->data;
+ 1312 :
+ 1313 78 : thread_create(&devinfo->thread, 0, func, devinfo);
+ 1314 : }
+ 1315 :
+ 1316 : /* join all threads */
+ 1317 81 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 1318 78 : devinfo_t* devinfo = i->data;
+ 1319 : void* retval;
1320 :
- 1321 1 : return 0;
- 1322 : }
- 1323 :
- 1324 4 : int devquery(tommy_list* high, tommy_list* low, int operation, int others)
- 1325 : {
- 1326 : tommy_node* i;
- 1327 4 : void* (*func)(void* arg) = 0;
- 1328 :
- 1329 : #if HAVE_LINUX_DEVICE
- 1330 4 : if (operation != DEVICE_UP) {
- 1331 : struct stat st;
- 1332 : /* sysfs interface is required */
- 1333 3 : if (stat("/sys/dev/block", &st) != 0) {
- 1334 : /* LCOV_EXCL_START */
- 1335 : log_fatal("Missing interface /sys/dev/block.\n");
- 1336 : return -1;
- 1337 : /* LCOV_EXCL_STOP */
- 1338 : }
+ 1321 78 : thread_join(devinfo->thread, &retval);
+ 1322 :
+ 1323 78 : if (retval != 0)
+ 1324 48 : ++fail;
+ 1325 : }
+ 1326 : #else
+ 1327 : for (i = tommy_list_head(list); i != 0; i = i->next) {
+ 1328 : devinfo_t* devinfo = i->data;
+ 1329 :
+ 1330 : if (func(devinfo) != 0)
+ 1331 : ++fail;
+ 1332 : }
+ 1333 : #endif
+ 1334 3 : if (fail != 0) {
+ 1335 : /* LCOV_EXCL_START */
+ 1336 : return -1;
+ 1337 : /* LCOV_EXCL_STOP */
+ 1338 : }
1339 :
- 1340 : /* for each device */
- 1341 136 : for (i = tommy_list_head(high); i != 0; i = i->next) {
- 1342 65 : devinfo_t* devinfo = i->data;
- 1343 65 : uint64_t device = devinfo->device;
- 1344 :
- 1345 : /* if the major is the null device, find the real one */
- 1346 65 : if (major(device) == 0) {
- 1347 : /* obtain the real device */
- 1348 0 : if (devdereference(device, &device) != 0) {
- 1349 : /* LCOV_EXCL_START */
- 1350 : log_fatal("Failed to dereference device '%u:%u'.\n", major(device), minor(device));
- 1351 : return -1;
- 1352 : /* LCOV_EXCL_STOP */
- 1353 : }
- 1354 : }
- 1355 :
- 1356 : /* get the device file */
- 1357 65 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) {
- 1358 : /* LCOV_EXCL_START */
- 1359 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
- 1360 : return -1;
- 1361 : /* LCOV_EXCL_STOP */
- 1362 : }
+ 1340 1 : return 0;
+ 1341 : }
+ 1342 :
+ 1343 4 : int devquery(tommy_list* high, tommy_list* low, int operation, int others)
+ 1344 : {
+ 1345 : tommy_node* i;
+ 1346 4 : void* (*func)(void* arg) = 0;
+ 1347 :
+ 1348 : #if HAVE_LINUX_DEVICE
+ 1349 4 : if (operation != DEVICE_UP) {
+ 1350 : struct stat st;
+ 1351 : /* sysfs interface is required */
+ 1352 3 : if (stat("/sys/dev/block", &st) != 0) {
+ 1353 : /* LCOV_EXCL_START */
+ 1354 : log_fatal("Missing interface /sys/dev/block.\n");
+ 1355 : return -1;
+ 1356 : /* LCOV_EXCL_STOP */
+ 1357 : }
+ 1358 :
+ 1359 : /* for each device */
+ 1360 136 : for (i = tommy_list_head(high); i != 0; i = i->next) {
+ 1361 65 : devinfo_t* devinfo = i->data;
+ 1362 65 : uint64_t device = devinfo->device;
1363 :
- 1364 : /* expand the tree of devices */
- 1365 65 : if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) {
- 1366 : /* LCOV_EXCL_START */
- 1367 : log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device));
- 1368 : return -1;
- 1369 : /* LCOV_EXCL_STOP */
- 1370 : }
- 1371 : }
- 1372 : }
- 1373 : #endif
+ 1364 : /* if the major is the null device, find the real one */
+ 1365 65 : if (major(device) == 0) {
+ 1366 : /* obtain the real device */
+ 1367 0 : if (devdereference(device, &device) != 0) {
+ 1368 : /* LCOV_EXCL_START */
+ 1369 : log_fatal("Failed to dereference device '%u:%u'.\n", major(device), minor(device));
+ 1370 : return -1;
+ 1371 : /* LCOV_EXCL_STOP */
+ 1372 : }
+ 1373 : }
1374 :
- 1375 4 : if (operation == DEVICE_UP) {
- 1376 : /* duplicate the high */
- 1377 31 : for (i = tommy_list_head(high); i != 0; i = i->next) {
- 1378 30 : devinfo_t* devinfo = i->data;
- 1379 : devinfo_t* entry;
- 1380 :
- 1381 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
+ 1375 : /* get the device file */
+ 1376 65 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) {
+ 1377 : /* LCOV_EXCL_START */
+ 1378 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device));
+ 1379 : return -1;
+ 1380 : /* LCOV_EXCL_STOP */
+ 1381 : }
1382 :
- 1383 30 : entry->device = devinfo->device;
- 1384 30 : pathcpy(entry->name, sizeof(entry->name), devinfo->name);
- 1385 30 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount);
- 1386 :
- 1387 : /* insert in the high */
- 1388 30 : tommy_list_insert_tail(low, &entry->node, entry);
- 1389 : }
- 1390 : }
- 1391 :
- 1392 : #if HAVE_LINUX_DEVICE
- 1393 : /* add other devices */
- 1394 4 : if (others) {
- 1395 1 : if (devscan(low) != 0) {
- 1396 : /* LCOV_EXCL_START */
- 1397 : log_fatal("Failed to list other devices.\n");
- 1398 : return -1;
- 1399 : /* LCOV_EXCL_STOP */
- 1400 : }
- 1401 : }
- 1402 : #else
- 1403 : (void)others;
- 1404 : #endif
+ 1383 : /* expand the tree of devices */
+ 1384 65 : if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) {
+ 1385 : /* LCOV_EXCL_START */
+ 1386 : log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device));
+ 1387 : return -1;
+ 1388 : /* LCOV_EXCL_STOP */
+ 1389 : }
+ 1390 : }
+ 1391 : }
+ 1392 : #endif
+ 1393 :
+ 1394 4 : if (operation == DEVICE_UP) {
+ 1395 : /* duplicate the high */
+ 1396 31 : for (i = tommy_list_head(high); i != 0; i = i->next) {
+ 1397 30 : devinfo_t* devinfo = i->data;
+ 1398 : devinfo_t* entry;
+ 1399 :
+ 1400 30 : entry = calloc_nofail(1, sizeof(devinfo_t));
+ 1401 :
+ 1402 30 : entry->device = devinfo->device;
+ 1403 30 : pathcpy(entry->name, sizeof(entry->name), devinfo->name);
+ 1404 30 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount);
1405 :
- 1406 4 : switch (operation) {
- 1407 1 : case DEVICE_UP : func = thread_spinup; break;
- 1408 1 : case DEVICE_DOWN : func = thread_spindown; break;
- 1409 1 : case DEVICE_SMART : func = thread_smart; break;
- 1410 : }
- 1411 :
- 1412 4 : if (!func)
- 1413 1 : return 0;
- 1414 :
- 1415 3 : return device_thread(low, func);
- 1416 : }
- 1417 :
- 1418 271 : void os_init(int opt)
- 1419 : {
- 1420 : #if HAVE_BLKID
- 1421 : int ret;
- 1422 271 : ret = blkid_get_cache(&cache, NULL);
- 1423 271 : if (ret != 0) {
- 1424 : /* LCOV_EXCL_START */
- 1425 : log_fatal("WARNING Failed to get blkid cache\n");
- 1426 : /* LCOV_EXCL_STOP */
- 1427 : }
- 1428 : #endif
- 1429 :
- 1430 : (void)opt;
- 1431 271 : }
- 1432 :
- 1433 248 : void os_done(void)
- 1434 : {
- 1435 : #if HAVE_BLKID
- 1436 248 : if (cache != 0)
- 1437 248 : blkid_put_cache(cache);
- 1438 : #endif
- 1439 248 : }
- 1440 :
- 1441 : /* LCOV_EXCL_START */
- 1442 : void os_abort(void)
- 1443 : {
- 1444 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
- 1445 : void* stack[32];
- 1446 : char** messages;
- 1447 : size_t size;
- 1448 : unsigned i;
- 1449 : #endif
- 1450 :
- 1451 : printf("Stacktrace of " PACKAGE " v" VERSION);
- 1452 : #ifdef _linux
- 1453 : printf(", linux");
- 1454 : #endif
- 1455 : #ifdef __GNUC__
- 1456 : printf(", gcc " __VERSION__);
+ 1406 : /* insert in the high */
+ 1407 30 : tommy_list_insert_tail(low, &entry->node, entry);
+ 1408 : }
+ 1409 : }
+ 1410 :
+ 1411 : #if HAVE_LINUX_DEVICE
+ 1412 : /* add other devices */
+ 1413 4 : if (others) {
+ 1414 1 : if (devscan(low) != 0) {
+ 1415 : /* LCOV_EXCL_START */
+ 1416 : log_fatal("Failed to list other devices.\n");
+ 1417 : return -1;
+ 1418 : /* LCOV_EXCL_STOP */
+ 1419 : }
+ 1420 : }
+ 1421 : #else
+ 1422 : (void)others;
+ 1423 : #endif
+ 1424 :
+ 1425 4 : switch (operation) {
+ 1426 1 : case DEVICE_UP : func = thread_spinup; break;
+ 1427 1 : case DEVICE_DOWN : func = thread_spindown; break;
+ 1428 1 : case DEVICE_SMART : func = thread_smart; break;
+ 1429 : }
+ 1430 :
+ 1431 4 : if (!func)
+ 1432 1 : return 0;
+ 1433 :
+ 1434 3 : return device_thread(low, func);
+ 1435 : }
+ 1436 :
+ 1437 271 : void os_init(int opt)
+ 1438 : {
+ 1439 : #if HAVE_BLKID
+ 1440 : int ret;
+ 1441 271 : ret = blkid_get_cache(&cache, NULL);
+ 1442 271 : if (ret != 0) {
+ 1443 : /* LCOV_EXCL_START */
+ 1444 : log_fatal("WARNING Failed to get blkid cache\n");
+ 1445 : /* LCOV_EXCL_STOP */
+ 1446 : }
+ 1447 : #endif
+ 1448 :
+ 1449 : (void)opt;
+ 1450 271 : }
+ 1451 :
+ 1452 248 : void os_done(void)
+ 1453 : {
+ 1454 : #if HAVE_BLKID
+ 1455 248 : if (cache != 0)
+ 1456 248 : blkid_put_cache(cache);
1457 : #endif
- 1458 : printf(", %d-bit", (int)sizeof(void *) * 8);
- 1459 : printf(", PATH_MAX=%d", PATH_MAX);
- 1460 : printf("\n");
- 1461 :
- 1462 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
- 1463 : size = backtrace(stack, 32);
- 1464 :
- 1465 : messages = backtrace_symbols(stack, size);
- 1466 :
- 1467 : for (i = 1; i < size; ++i) {
- 1468 : const char* msg;
+ 1458 248 : }
+ 1459 :
+ 1460 : /* LCOV_EXCL_START */
+ 1461 : void os_abort(void)
+ 1462 : {
+ 1463 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
+ 1464 : void* stack[32];
+ 1465 : char** messages;
+ 1466 : size_t size;
+ 1467 : unsigned i;
+ 1468 : #endif
1469 :
- 1470 : if (messages)
- 1471 : msg = messages[i];
- 1472 : else
- 1473 : msg = "<unknown>";
- 1474 :
- 1475 : printf("[bt] %02u: %s\n", i, msg);
- 1476 :
- 1477 : if (messages) {
- 1478 : int ret;
- 1479 : char addr2line[1024];
- 1480 : size_t j = 0;
- 1481 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0)
- 1482 : ++j;
+ 1470 : printf("Stacktrace of " PACKAGE " v" VERSION);
+ 1471 : #ifdef _linux
+ 1472 : printf(", linux");
+ 1473 : #endif
+ 1474 : #ifdef __GNUC__
+ 1475 : printf(", gcc " __VERSION__);
+ 1476 : #endif
+ 1477 : printf(", %d-bit", (int)sizeof(void *) * 8);
+ 1478 : printf(", PATH_MAX=%d", PATH_MAX);
+ 1479 : printf("\n");
+ 1480 :
+ 1481 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
+ 1482 : size = backtrace(stack, 32);
1483 :
- 1484 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg);
+ 1484 : messages = backtrace_symbols(stack, size);
1485 :
- 1486 : ret = system(addr2line);
- 1487 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)
- 1488 : printf("exit:%d\n", WEXITSTATUS(ret));
- 1489 : if (WIFSIGNALED(ret))
- 1490 : printf("signal:%d\n", WTERMSIG(ret));
- 1491 : }
- 1492 : }
- 1493 : #endif
- 1494 :
- 1495 : printf("Please report this error to the SnapRAID Forum:\n");
- 1496 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n");
- 1497 :
- 1498 : abort();
- 1499 : }
- 1500 : /* LCOV_EXCL_STOP */
- 1501 :
- 1502 1 : void os_clear(void)
- 1503 : {
- 1504 : /* ANSI codes */
- 1505 1 : printf("\033[H"); /* cursor at topleft */
- 1506 1 : printf("\033[2J"); /* clear screen */
- 1507 1 : }
- 1508 :
- 1509 7 : size_t direct_size(void)
- 1510 : {
- 1511 : long size;
- 1512 :
- 1513 7 : size = sysconf(_SC_PAGESIZE);
- 1514 :
- 1515 7 : if (size == -1) {
- 1516 : /* LCOV_EXCL_START */
- 1517 : log_fatal("No page size\n");
- 1518 : exit(EXIT_FAILURE);
- 1519 : /* LCOV_EXCL_STOP */
- 1520 : }
- 1521 :
- 1522 7 : return size;
- 1523 : }
- 1524 :
- 1525 : #endif
- 1526 :
+ 1486 : for (i = 1; i < size; ++i) {
+ 1487 : const char* msg;
+ 1488 :
+ 1489 : if (messages)
+ 1490 : msg = messages[i];
+ 1491 : else
+ 1492 : msg = "<unknown>";
+ 1493 :
+ 1494 : printf("[bt] %02u: %s\n", i, msg);
+ 1495 :
+ 1496 : if (messages) {
+ 1497 : int ret;
+ 1498 : char addr2line[1024];
+ 1499 : size_t j = 0;
+ 1500 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0)
+ 1501 : ++j;
+ 1502 :
+ 1503 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg);
+ 1504 :
+ 1505 : ret = system(addr2line);
+ 1506 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)
+ 1507 : printf("exit:%d\n", WEXITSTATUS(ret));
+ 1508 : if (WIFSIGNALED(ret))
+ 1509 : printf("signal:%d\n", WTERMSIG(ret));
+ 1510 : }
+ 1511 : }
+ 1512 : #endif
+ 1513 :
+ 1514 : printf("Please report this error to the SnapRAID Forum:\n");
+ 1515 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n");
+ 1516 :
+ 1517 : abort();
+ 1518 : }
+ 1519 : /* LCOV_EXCL_STOP */
+ 1520 :
+ 1521 0 : void os_clear(void)
+ 1522 : {
+ 1523 : /* ANSI codes */
+ 1524 0 : printf("\033[H"); /* cursor at topleft */
+ 1525 0 : printf("\033[2J"); /* clear screen */
+ 1526 0 : }
+ 1527 :
+ 1528 7 : size_t direct_size(void)
+ 1529 : {
+ 1530 : long size;
+ 1531 :
+ 1532 7 : size = sysconf(_SC_PAGESIZE);
+ 1533 :
+ 1534 7 : if (size == -1) {
+ 1535 : /* LCOV_EXCL_START */
+ 1536 : log_fatal("No page size\n");
+ 1537 : exit(EXIT_FAILURE);
+ 1538 : /* LCOV_EXCL_STOP */
+ 1539 : }
+ 1540 :
+ 1541 7 : return size;
+ 1542 : }
+ 1543 :
+ 1544 : #endif
+ 1545 :
diff --git a/cov/cmdline/util.c.func-sort-c.html b/cov/cmdline/util.c.func-sort-c.html
index 6587372f..fc4ec072 100644
--- a/cov/cmdline/util.c.func-sort-c.html
+++ b/cov/cmdline/util.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,39 +61,39 @@
| util_rotl32 |
- 854122150 |
+ 854124441 |
| util_rotl64 |
- 510718872 |
+ 511238832 |
| util_read32 |
- 8307408 |
+ 8307428 |
| util_write32 |
- 8307408 |
+ 8307428 |
| util_write64 |
- 7722914 |
+ 7722984 |
| util_read64 |
- 7722914 |
+ 7722984 |
| memhash |
- 5938309 |
+ 5938349 |
| crc32c_x86 |
- 646603 |
+ 646616 |
| memdiff |
- 93220 |
+ 93324 |
| malloc_nofail_vector_align |
diff --git a/cov/cmdline/util.c.func.html b/cov/cmdline/util.c.func.html
index 34c06e88..6c534ef4 100644
--- a/cov/cmdline/util.c.func.html
+++ b/cov/cmdline/util.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -69,7 +69,7 @@
| crc32c_x86 |
- 646603 |
+ 646616 |
| fast_mtest_vector |
@@ -109,11 +109,11 @@
| memdiff |
- 93220 |
+ 93324 |
| memhash |
- 5938309 |
+ 5938349 |
| mtest_vector |
@@ -121,27 +121,27 @@
| util_read32 |
- 8307408 |
+ 8307428 |
| util_read64 |
- 7722914 |
+ 7722984 |
| util_rotl32 |
- 854122150 |
+ 854124441 |
| util_rotl64 |
- 510718872 |
+ 511238832 |
| util_write32 |
- 8307408 |
+ 8307428 |
| util_write64 |
- 7722914 |
+ 7722984 |
diff --git a/cov/cmdline/util.c.gcov.html b/cov/cmdline/util.c.gcov.html
index e731c931..3ff495b0 100644
--- a/cov/cmdline/util.c.gcov.html
+++ b/cov/cmdline/util.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -490,15 +490,15 @@
428 : }
429 :
430 : #if HAVE_SSE42
- 431 646603 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 431 646616 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size)
432 : {
- 433 646603 : crc ^= CRC_IV;
+ 433 646616 : crc ^= CRC_IV;
434 :
- 435 646603 : crc = crc32c_x86_plain(crc, ptr, size);
+ 435 646616 : crc = crc32c_x86_plain(crc, ptr, size);
436 :
- 437 646602 : crc ^= CRC_IV;
+ 437 646618 : crc ^= CRC_IV;
438 :
- 439 646602 : return crc;
+ 439 646618 : return crc;
440 : }
441 : #endif
442 :
@@ -522,14 +522,14 @@
460 : * Rotate left.
461 : * In x86/x64 they are optimized with a single assembler instruction.
462 : */
- 463 854122150 : static inline uint32_t util_rotl32(uint32_t x, int8_t r)
+ 463 854124441 : static inline uint32_t util_rotl32(uint32_t x, int8_t r)
464 : {
- 465 854122150 : return (x << r) | (x >> (32 - r));
+ 465 854124441 : return (x << r) | (x >> (32 - r));
466 : }
467 :
- 468 510718872 : static inline uint64_t util_rotl64(uint64_t x, int8_t r)
+ 468 511238832 : static inline uint64_t util_rotl64(uint64_t x, int8_t r)
469 : {
- 470 510718872 : return (x << r) | (x >> (64 - r));
+ 470 511238832 : return (x << r) | (x >> (64 - r));
471 : }
472 :
473 : /**
@@ -564,41 +564,41 @@
502 : }
503 : #endif
504 :
- 505 8307408 : static inline uint32_t util_read32(const void* ptr)
+ 505 8307428 : static inline uint32_t util_read32(const void* ptr)
506 : {
507 : uint32_t v;
- 508 8307408 : memcpy(&v, ptr, sizeof(v));
+ 508 8307428 : memcpy(&v, ptr, sizeof(v));
509 : #if WORDS_BIGENDIAN
510 : v = util_swap32(v);
511 : #endif
- 512 8307408 : return v;
+ 512 8307428 : return v;
513 : }
514 :
- 515 7722914 : static inline uint64_t util_read64(const void* ptr)
+ 515 7722984 : static inline uint64_t util_read64(const void* ptr)
516 : {
517 : uint64_t v;
- 518 7722914 : memcpy(&v, ptr, sizeof(v));
+ 518 7722984 : memcpy(&v, ptr, sizeof(v));
519 : #if WORDS_BIGENDIAN
520 : v = util_swap64(v);
521 : #endif
- 522 7722914 : return v;
+ 522 7722984 : return v;
523 : }
524 :
- 525 8307408 : static inline void util_write32(void* ptr, uint32_t v)
+ 525 8307428 : static inline void util_write32(void* ptr, uint32_t v)
526 : {
527 : #if WORDS_BIGENDIAN
528 : v = util_swap32(v);
529 : #endif
- 530 8307408 : memcpy(ptr, &v, sizeof(v));
- 531 8307408 : }
+ 530 8307428 : memcpy(ptr, &v, sizeof(v));
+ 531 8307428 : }
532 :
- 533 7722914 : static inline void util_write64(void* ptr, uint64_t v)
+ 533 7722984 : static inline void util_write64(void* ptr, uint64_t v)
534 : {
535 : #if WORDS_BIGENDIAN
536 : v = util_swap64(v);
537 : #endif
- 538 7722914 : memcpy(ptr, &v, sizeof(v));
- 539 7722914 : }
+ 538 7722984 : memcpy(ptr, &v, sizeof(v));
+ 539 7722984 : }
540 :
541 : /****************************************************************************/
542 : /* hash */
@@ -606,15 +606,15 @@
544 : #include "murmur3.c"
545 : #include "spooky2.c"
546 :
- 547 5938309 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size)
+ 547 5938349 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size)
548 : {
- 549 5938309 : switch (kind) {
+ 549 5938349 : switch (kind) {
550 : case HASH_MURMUR3 :
- 551 2076852 : MurmurHash3_x86_128(src, size, seed, digest);
- 552 2076852 : break;
+ 551 2076857 : MurmurHash3_x86_128(src, size, seed, digest);
+ 552 2076857 : break;
553 : case HASH_SPOOKY2 :
- 554 3861457 : SpookyHash128(src, size, seed, digest);
- 555 3861457 : break;
+ 554 3861492 : SpookyHash128(src, size, seed, digest);
+ 555 3861492 : break;
556 : default :
557 : /* LCOV_EXCL_START */
558 : log_fatal("Internal inconsistency in hash function %u\n", kind);
@@ -622,7 +622,7 @@
560 : break;
561 : /* LCOV_EXCL_STOP */
562 : }
- 563 5938309 : }
+ 563 5938349 : }
564 :
565 45 : const char* hash_config_name(unsigned kind)
566 : {
@@ -637,23 +637,23 @@
575 : }
576 : }
577 :
- 578 93220 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size)
+ 578 93324 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size)
579 : {
580 : size_t i;
581 : unsigned count;
582 :
- 583 93220 : count = 0;
- 584 80894180 : for (i = 0; i < size; ++i) {
+ 583 93324 : count = 0;
+ 584 80906028 : for (i = 0; i < size; ++i) {
585 : unsigned j;
- 586 80800960 : unsigned char diff = data1[i] ^ data2[i];
- 587 727208640 : for (j = 0; j < 8; ++j) {
- 588 646407680 : if ((diff & 1) != 0)
- 589 311424980 : ++count;
- 590 646407680 : diff >>= 1;
+ 586 80812704 : unsigned char diff = data1[i] ^ data2[i];
+ 587 727314336 : for (j = 0; j < 8; ++j) {
+ 588 646501632 : if ((diff & 1) != 0)
+ 589 311419223 : ++count;
+ 590 646501632 : diff >>= 1;
591 : }
592 : }
593 :
- 594 93220 : return count;
+ 594 93324 : return count;
595 : }
596 :
597 : /****************************************************************************/
diff --git a/cov/cmdline/util.h.func-sort-c.html b/cov/cmdline/util.h.func-sort-c.html
index be791415..71470ec6 100644
--- a/cov/cmdline/util.h.func-sort-c.html
+++ b/cov/cmdline/util.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| crc32c_x86_plain |
- 21365830 |
+ 21365757 |
| crc32c_plain |
- 20719227 |
+ 20719138 |
| crc32c_plain_char |
- 3808426 |
+ 3808662 |
| crc32c_gen_plain |
diff --git a/cov/cmdline/util.h.func.html b/cov/cmdline/util.h.func.html
index bb76f47b..e22c16ef 100644
--- a/cov/cmdline/util.h.func.html
+++ b/cov/cmdline/util.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,15 +65,15 @@
| crc32c_plain |
- 20719227 |
+ 20719138 |
| crc32c_plain_char |
- 3808426 |
+ 3808662 |
| crc32c_x86_plain |
- 21365830 |
+ 21365757 |
diff --git a/cov/cmdline/util.h.gcov.html b/cov/cmdline/util.h.gcov.html
index 1d87b293..58272aab 100644
--- a/cov/cmdline/util.h.gcov.html
+++ b/cov/cmdline/util.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -144,12 +144,12 @@
82 : /**
83 : * Compute CRC-32 (Castagnoli) for a single byte without the IV.
84 : */
- 85 3808426 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c)
+ 85 3808662 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c)
86 : {
87 : #if HAVE_SSE42
- 88 3808426 : if (tommy_likely(crc_x86)) {
- 89 3808426 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c));
- 90 3808426 : return crc;
+ 88 3808662 : if (tommy_likely(crc_x86)) {
+ 89 3808662 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c));
+ 90 3808662 : return crc;
91 : }
92 : #endif
93 0 : return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8);
@@ -180,7 +180,7 @@
118 : * Compute the CRC-32 (Castagnoli) without the IV.
119 : */
120 : #if HAVE_SSE42
- 121 21365830 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 121 21365757 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
122 : {
123 : #ifdef CONFIG_X86_64
124 : uint64_t crc64 = crc;
@@ -191,30 +191,30 @@
129 : }
130 : crc = crc64;
131 : #else
- 132 392452749 : while (size >= 4) {
- 133 349721089 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr));
- 134 349721089 : ptr += 4;
- 135 349721089 : size -= 4;
+ 132 349127638 : while (size >= 4) {
+ 133 306396124 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr));
+ 134 306396124 : ptr += 4;
+ 135 306396124 : size -= 4;
136 : }
137 : #endif
- 138 62466405 : while (size) {
- 139 19734745 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr));
- 140 19734745 : ++ptr;
- 141 19734745 : --size;
+ 138 61840849 : while (size) {
+ 139 19109335 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr));
+ 140 19109335 : ++ptr;
+ 141 19109335 : --size;
142 : }
143 :
- 144 21365830 : return crc;
+ 144 21365757 : return crc;
145 : }
146 : #endif
147 :
148 : /**
149 : * Compute CRC-32 (Castagnoli) without the IV.
150 : */
- 151 20719227 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
+ 151 20719138 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size)
152 : {
153 : #if HAVE_SSE42
- 154 20719227 : if (tommy_likely(crc_x86)) {
- 155 20719227 : return crc32c_x86_plain(crc, ptr, size);
+ 154 20719138 : if (tommy_likely(crc_x86)) {
+ 155 20719138 : return crc32c_x86_plain(crc, ptr, size);
156 : }
157 : #endif
158 0 : return crc32c_gen_plain(crc, ptr, size);
diff --git a/cov/index-sort-f.html b/cov/index-sort-f.html
index ba99cdd3..d8a55378 100644
--- a/cov/index-sort-f.html
+++ b/cov/index-sort-f.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 90.8 % |
- 8683 / 9562 |
- 97.0 % |
- 488 / 503 |
+ 90.2 % |
+ 8640 / 9584 |
+ 96.6 % |
+ 487 / 504 |
| tommyds |
diff --git a/cov/index-sort-l.html b/cov/index-sort-l.html
index 6732e9e4..d4c07db2 100644
--- a/cov/index-sort-l.html
+++ b/cov/index-sort-l.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 90.8 % |
- 8683 / 9562 |
- 97.0 % |
- 488 / 503 |
+ 90.2 % |
+ 8640 / 9584 |
+ 96.6 % |
+ 487 / 504 |
| raid |
diff --git a/cov/index.html b/cov/index.html
index d8000377..8b39adef 100644
--- a/cov/index.html
+++ b/cov/index.html
@@ -31,18 +31,18 @@
|
-
-
-
+
+
+
-
+
|
-
-
-
+
+
+
 |
@@ -72,12 +72,12 @@
| cmdline |
-
+
|
- 90.8 % |
- 8683 / 9562 |
- 97.0 % |
- 488 / 503 |
+ 90.2 % |
+ 8640 / 9584 |
+ 96.6 % |
+ 487 / 504 |
| raid |
diff --git a/cov/raid/check.c.func-sort-c.html b/cov/raid/check.c.func-sort-c.html
index 359f4f99..a2ddca2f 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 a3e6f425..2f97978e 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 3e42bb82..fc0d4901 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 8f7c071c..62280165 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 e0b37946..be1c4a51 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 c9aec85c..ce38279e 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 207740 : assert(0 < r && r <= n);
+ 111 207883 : assert(0 < r && r <= n);
112 :
- 113 688823 : for (i = 0; i < r; ++i)
- 114 481083 : c[i] = i;
+ 113 689228 : for (i = 0; i < r; ++i)
+ 114 481345 : 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 52213 : int i = r - 1; /* present position */
- 124 52213 : int h = n; /* high limit for this position */
+ 123 52183 : int i = r - 1; /* present position */
+ 124 52183 : int h = n; /* high limit for this position */
125 :
126 : recurse:
127 : /* next element at position i */
- 128 85086 : ++c[i];
+ 128 85056 : ++c[i];
129 :
130 : /* if the position has reached the max */
- 131 85086 : if (c[i] >= h) {
+ 131 85056 : if (c[i] >= h) {
132 :
133 : /* if we are at the first level, we have finished */
- 134 45038 : if (i == 0)
- 135 12165 : return 0;
+ 134 45028 : if (i == 0)
+ 135 12155 : return 0;
136 :
137 : /* increase the previous position */
138 32873 : --i;
@@ -202,16 +202,16 @@
140 : goto recurse;
141 : }
142 :
- 143 40048 : ++i;
+ 143 40028 : ++i;
144 :
145 : /* initialize all the next positions, if any */
- 146 62593 : while (i < r) {
+ 146 62573 : 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 40048 : return 1;
+ 152 40028 : 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 1ff1626d..2ffcbc83 100644
--- a/cov/raid/cpu.h.func-sort-c.html
+++ b/cov/raid/cpu.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/cpu.h.func.html b/cov/raid/cpu.h.func.html
index 72ccd3b3..a3056ec6 100644
--- a/cov/raid/cpu.h.func.html
+++ b/cov/raid/cpu.h.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/cpu.h.gcov.html b/cov/raid/cpu.h.gcov.html
index f5a1e826..5684fca8 100644
--- a/cov/raid/cpu.h.gcov.html
+++ b/cov/raid/cpu.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/gf.h.func-sort-c.html b/cov/raid/gf.h.func-sort-c.html
index 87a1b765..2caf4886 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 fa1b1d4c..9c2e0fae 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 51d692be..c61b4bc0 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 23791770 : return gfmul[a][b];
+ 29 23793674 : return gfmul[a][b];
30 : }
31 :
32 : /*
@@ -97,9 +97,9 @@
35 : */
36 : static __always_inline uint8_t inv(uint8_t v)
37 : {
- 38 635424 : BUG_ON(v == 0); /* division by zero */
+ 38 635642 : BUG_ON(v == 0); /* division by zero */
39 :
- 40 635424 : return gfinv[v];
+ 40 635642 : return gfinv[v];
41 : }
42 :
43 : /*
@@ -125,7 +125,7 @@
63 : */
64 : static __always_inline uint8_t A(int p, int d)
65 : {
- 66 2604422 : return gfgen[p][d];
+ 66 2604878 : return gfgen[p][d];
67 : }
68 :
69 : /*
@@ -148,12 +148,12 @@
86 : */
87 : static __always_inline uint32_t x2_32(uint32_t v)
88 : {
- 89 32577344 : uint32_t mask = v & 0x80808080U;
+ 89 33036096 : uint32_t mask = v & 0x80808080U;
90 :
- 91 32577344 : mask = (mask << 1) - (mask >> 7);
- 92 32577344 : v = (v << 1) & 0xfefefefeU;
- 93 32577344 : v ^= mask & 0x1d1d1d1dU;
- 94 32577344 : return v;
+ 91 33036096 : mask = (mask << 1) - (mask >> 7);
+ 92 33036096 : v = (v << 1) & 0xfefefefeU;
+ 93 33036096 : v ^= mask & 0x1d1d1d1dU;
+ 94 33036096 : return v;
95 : }
96 :
97 : /*
@@ -161,12 +161,12 @@
99 : */
100 : static __always_inline uint64_t x2_64(uint64_t v)
101 : {
- 102 16288672 : uint64_t mask = v & 0x8080808080808080ULL;
+ 102 16518048 : uint64_t mask = v & 0x8080808080808080ULL;
103 :
- 104 16288672 : mask = (mask << 1) - (mask >> 7);
- 105 16288672 : v = (v << 1) & 0xfefefefefefefefeULL;
- 106 16288672 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL;
- 107 16288672 : return v;
+ 104 16518048 : mask = (mask << 1) - (mask >> 7);
+ 105 16518048 : v = (v << 1) & 0xfefefefefefefefeULL;
+ 106 16518048 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL;
+ 107 16518048 : return v;
108 : }
109 :
110 : /*
diff --git a/cov/raid/helper.c.func-sort-c.html b/cov/raid/helper.c.func-sort-c.html
index 5f219c44..7e1a23ed 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 4f2ba325..07048a48 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 7807e32c..638b18f0 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 f76853ec..8b8326d2 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 b0f2e8de..a8835134 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 05eee1e7..c48051ef 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 3f2b190f..2d550ad5 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 |
- 180 |
+ 183 |
| raid_rec1_int8 |
@@ -77,15 +77,15 @@
| raid_gen1_int32 |
- 113 |
+ 118 |
| raid_gen2_int64 |
- 46 |
+ 47 |
| raid_gen2_int32 |
- 46 |
+ 47 |
| raid_gen3_int8 |
@@ -101,7 +101,7 @@
| raid_gen6_int8 |
- 15 |
+ 18 |
diff --git a/cov/raid/int.c.func.html b/cov/raid/int.c.func.html
index 9510bc38..39f17525 100644
--- a/cov/raid/int.c.func.html
+++ b/cov/raid/int.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| raid_gen1_int32 |
- 113 |
+ 118 |
| raid_gen1_int64 |
- 180 |
+ 183 |
| raid_gen2_int32 |
- 46 |
+ 47 |
| raid_gen2_int64 |
- 46 |
+ 47 |
| raid_gen3_int8 |
@@ -89,7 +89,7 @@
| raid_gen6_int8 |
- 15 |
+ 18 |
| raid_rec1_int8 |
diff --git a/cov/raid/int.c.gcov.html b/cov/raid/int.c.gcov.html
index 3ef0c5f6..42a08e4c 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 113 : void raid_gen1_int32(int nd, size_t size, void **vv)
+ 21 118 : void raid_gen1_int32(int nd, size_t size, void **vv)
22 : {
- 23 113 : uint8_t **v = (uint8_t **)vv;
+ 23 118 : 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 113 : l = nd - 1;
- 32 113 : p = v[nd];
+ 31 118 : l = nd - 1;
+ 32 118 : p = v[nd];
33 :
- 34 3604689 : for (i = 0; i < size; i += 8) {
- 35 3604576 : p0 = v_32(v[l][i]);
- 36 3604576 : p1 = v_32(v[l][i + 4]);
- 37 28837920 : for (d = l - 1; d >= 0; --d) {
- 38 25233344 : p0 ^= v_32(v[d][i]);
- 39 25233344 : p1 ^= v_32(v[d][i + 4]);
+ 34 3768534 : for (i = 0; i < size; i += 8) {
+ 35 3768416 : p0 = v_32(v[l][i]);
+ 36 3768416 : p1 = v_32(v[l][i + 4]);
+ 37 30148640 : for (d = l - 1; d >= 0; --d) {
+ 38 26380224 : p0 ^= v_32(v[d][i]);
+ 39 26380224 : p1 ^= v_32(v[d][i + 4]);
40 : }
- 41 3604576 : v_32(p[i]) = p0;
- 42 3604576 : v_32(p[i + 4]) = p1;
+ 41 3768416 : v_32(p[i]) = p0;
+ 42 3768416 : v_32(p[i + 4]) = p1;
43 : }
- 44 113 : }
+ 44 118 : }
45 :
46 : /*
47 : * GEN1 (RAID5 with xor) 64bit C implementation
48 : */
- 49 180 : void raid_gen1_int64(int nd, size_t size, void **vv)
+ 49 183 : void raid_gen1_int64(int nd, size_t size, void **vv)
50 : {
- 51 180 : uint8_t **v = (uint8_t **)vv;
+ 51 183 : uint8_t **v = (uint8_t **)vv;
52 : uint8_t *p;
53 : int d, l;
54 : size_t i;
@@ -118,27 +118,27 @@
56 : uint64_t p0;
57 : uint64_t p1;
58 :
- 59 180 : l = nd - 1;
- 60 180 : p = v[nd];
+ 59 183 : l = nd - 1;
+ 60 183 : p = v[nd];
61 :
- 62 2900196 : for (i = 0; i < size; i += 16) {
- 63 2900016 : p0 = v_64(v[l][i]);
- 64 2900016 : p1 = v_64(v[l][i + 8]);
- 65 23200784 : for (d = l - 1; d >= 0; --d) {
- 66 20300768 : p0 ^= v_64(v[d][i]);
- 67 20300768 : p1 ^= v_64(v[d][i + 8]);
+ 62 2949351 : for (i = 0; i < size; i += 16) {
+ 63 2949168 : p0 = v_64(v[l][i]);
+ 64 2949168 : p1 = v_64(v[l][i + 8]);
+ 65 23594000 : for (d = l - 1; d >= 0; --d) {
+ 66 20644832 : p0 ^= v_64(v[d][i]);
+ 67 20644832 : p1 ^= v_64(v[d][i + 8]);
68 : }
- 69 2900016 : v_64(p[i]) = p0;
- 70 2900016 : v_64(p[i + 8]) = p1;
+ 69 2949168 : v_64(p[i]) = p0;
+ 70 2949168 : v_64(p[i + 8]) = p1;
71 : }
- 72 180 : }
+ 72 183 : }
73 :
74 : /*
75 : * GEN2 (RAID6 with powers of 2) 32bit C implementation
76 : */
- 77 46 : void raid_gen2_int32(int nd, size_t size, void **vv)
+ 77 47 : void raid_gen2_int32(int nd, size_t size, void **vv)
78 : {
- 79 46 : uint8_t **v = (uint8_t **)vv;
+ 79 47 : uint8_t **v = (uint8_t **)vv;
80 : uint8_t *p;
81 : uint8_t *q;
82 : int d, l;
@@ -147,39 +147,39 @@
85 : uint32_t d0, q0, p0;
86 : uint32_t d1, q1, p1;
87 :
- 88 46 : l = nd - 1;
- 89 46 : p = v[nd];
- 90 46 : q = v[nd + 1];
+ 88 47 : l = nd - 1;
+ 89 47 : p = v[nd];
+ 90 47 : q = v[nd + 1];
91 :
- 92 1409166 : for (i = 0; i < size; i += 8) {
- 93 1409120 : q0 = p0 = v_32(v[l][i]);
- 94 1409120 : q1 = p1 = v_32(v[l][i + 4]);
- 95 11274272 : for (d = l - 1; d >= 0; --d) {
- 96 9865152 : d0 = v_32(v[d][i]);
- 97 9865152 : d1 = v_32(v[d][i + 4]);
+ 92 1441935 : for (i = 0; i < size; i += 8) {
+ 93 1441888 : q0 = p0 = v_32(v[l][i]);
+ 94 1441888 : q1 = p1 = v_32(v[l][i + 4]);
+ 95 11536416 : for (d = l - 1; d >= 0; --d) {
+ 96 10094528 : d0 = v_32(v[d][i]);
+ 97 10094528 : d1 = v_32(v[d][i + 4]);
98 :
- 99 9865152 : p0 ^= d0;
- 100 9865152 : p1 ^= d1;
+ 99 10094528 : p0 ^= d0;
+ 100 10094528 : p1 ^= d1;
101 :
- 102 9865152 : q0 = x2_32(q0);
- 103 9865152 : q1 = x2_32(q1);
+ 102 10094528 : q0 = x2_32(q0);
+ 103 10094528 : q1 = x2_32(q1);
104 :
- 105 9865152 : q0 ^= d0;
- 106 9865152 : q1 ^= d1;
+ 105 10094528 : q0 ^= d0;
+ 106 10094528 : q1 ^= d1;
107 : }
- 108 1409120 : v_32(p[i]) = p0;
- 109 1409120 : v_32(p[i + 4]) = p1;
- 110 1409120 : v_32(q[i]) = q0;
- 111 1409120 : v_32(q[i + 4]) = q1;
+ 108 1441888 : v_32(p[i]) = p0;
+ 109 1441888 : v_32(p[i + 4]) = p1;
+ 110 1441888 : v_32(q[i]) = q0;
+ 111 1441888 : v_32(q[i + 4]) = q1;
112 : }
- 113 46 : }
+ 113 47 : }
114 :
115 : /*
116 : * GEN2 (RAID6 with powers of 2) 64bit C implementation
117 : */
- 118 46 : void raid_gen2_int64(int nd, size_t size, void **vv)
+ 118 47 : void raid_gen2_int64(int nd, size_t size, void **vv)
119 : {
- 120 46 : uint8_t **v = (uint8_t **)vv;
+ 120 47 : uint8_t **v = (uint8_t **)vv;
121 : uint8_t *p;
122 : uint8_t *q;
123 : int d, l;
@@ -188,32 +188,32 @@
126 : uint64_t d0, q0, p0;
127 : uint64_t d1, q1, p1;
128 :
- 129 46 : l = nd - 1;
- 130 46 : p = v[nd];
- 131 46 : q = v[nd + 1];
+ 129 47 : l = nd - 1;
+ 130 47 : p = v[nd];
+ 131 47 : q = v[nd + 1];
132 :
- 133 704606 : for (i = 0; i < size; i += 16) {
- 134 704560 : q0 = p0 = v_64(v[l][i]);
- 135 704560 : q1 = p1 = v_64(v[l][i + 8]);
- 136 5637136 : for (d = l - 1; d >= 0; --d) {
- 137 4932576 : d0 = v_64(v[d][i]);
- 138 4932576 : d1 = v_64(v[d][i + 8]);
+ 133 720991 : for (i = 0; i < size; i += 16) {
+ 134 720944 : q0 = p0 = v_64(v[l][i]);
+ 135 720944 : q1 = p1 = v_64(v[l][i + 8]);
+ 136 5768208 : for (d = l - 1; d >= 0; --d) {
+ 137 5047264 : d0 = v_64(v[d][i]);
+ 138 5047264 : d1 = v_64(v[d][i + 8]);
139 :
- 140 4932576 : p0 ^= d0;
- 141 4932576 : p1 ^= d1;
+ 140 5047264 : p0 ^= d0;
+ 141 5047264 : p1 ^= d1;
142 :
- 143 4932576 : q0 = x2_64(q0);
- 144 4932576 : q1 = x2_64(q1);
+ 143 5047264 : q0 = x2_64(q0);
+ 144 5047264 : q1 = x2_64(q1);
145 :
- 146 4932576 : q0 ^= d0;
- 147 4932576 : q1 ^= d1;
+ 146 5047264 : q0 ^= d0;
+ 147 5047264 : q1 ^= d1;
148 : }
- 149 704560 : v_64(p[i]) = p0;
- 150 704560 : v_64(p[i + 8]) = p1;
- 151 704560 : v_64(q[i]) = q0;
- 152 704560 : v_64(q[i + 8]) = q1;
+ 149 720944 : v_64(p[i]) = p0;
+ 150 720944 : v_64(p[i + 8]) = p1;
+ 151 720944 : v_64(q[i]) = q0;
+ 152 720944 : v_64(q[i + 8]) = q1;
153 : }
- 154 46 : }
+ 154 47 : }
155 :
156 : /*
157 : * GEN3 (triple parity with Cauchy matrix) 8bit 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 15 : 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 15 : 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 15 : l = nd - 1;
- 335 15 : p = v[nd];
- 336 15 : q = v[nd + 1];
- 337 15 : r = v[nd + 2];
- 338 15 : s = v[nd + 3];
- 339 15 : t = v[nd + 4];
- 340 15 : 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 3408399 : for (i = 0; i < size; i += 1) {
- 343 3408384 : p0 = q0 = r0 = s0 = t0 = u0 = 0;
- 344 27271424 : for (d = l; d > 0; --d) {
- 345 23863040 : 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 23863040 : p0 ^= d0;
- 348 23863040 : q0 ^= gfmul[d0][gfgen[1][d]];
- 349 23863040 : r0 ^= gfmul[d0][gfgen[2][d]];
- 350 23863040 : s0 ^= gfmul[d0][gfgen[3][d]];
- 351 23863040 : t0 ^= gfmul[d0][gfgen[4][d]];
- 352 23863040 : 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 3408384 : d0 = v_8(v[0][i]);
+ 356 4194816 : d0 = v_8(v[0][i]);
357 :
- 358 3408384 : p0 ^= d0;
- 359 3408384 : q0 ^= d0;
- 360 3408384 : r0 ^= d0;
- 361 3408384 : s0 ^= d0;
- 362 3408384 : t0 ^= d0;
- 363 3408384 : 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 3408384 : v_8(p[i]) = p0;
- 366 3408384 : v_8(q[i]) = q0;
- 367 3408384 : v_8(r[i]) = r0;
- 368 3408384 : v_8(s[i]) = s0;
- 369 3408384 : v_8(t[i]) = t0;
- 370 3408384 : 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 15 : }
+ 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 52c3bb25..df4ad79b 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 45ac5440..e8311124 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 8958d14c..c3981909 100644
--- a/cov/raid/internal.h.gcov.html
+++ b/cov/raid/internal.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -169,11 +169,11 @@
107 : */
108 : static __always_inline void *__align_ptr(void *ptr, uintptr_t size)
109 : {
- 110 711884 : uintptr_t offset = (uintptr_t)ptr;
+ 110 711958 : uintptr_t offset = (uintptr_t)ptr;
111 :
- 112 711884 : offset = (offset + size - 1U) & ~(size - 1U);
+ 112 711958 : offset = (offset + size - 1U) & ~(size - 1U);
113 :
- 114 711884 : return (void *)offset;
+ 114 711958 : return (void *)offset;
115 : }
116 :
117 : /*
@@ -294,7 +294,7 @@
232 : /* that use a weak memory model. To ensure that other processors */
233 : /* see correctly the data written, we use a store-store memory */
234 : /* barrier at the end of the asm code */
- 235 1388567 : asm volatile ("sfence" : : : "memory");
+ 235 1388797 : asm volatile ("sfence" : : : "memory");
236 :
237 : /* clobbers registers used in the asm code */
238 : /* this is required because in the Windows ABI, */
@@ -327,7 +327,7 @@
265 : /* reset the upper part of the ymm registers */
266 : /* to avoid the 70 clocks penality on the next */
267 : /* xmm register use */
- 268 19674 : asm volatile ("vzeroupper" : : : "memory");
+ 268 19675 : asm volatile ("vzeroupper" : : : "memory");
269 : }
270 : #endif
271 : #endif /* CONFIG_X86 */
diff --git a/cov/raid/intz.c.func-sort-c.html b/cov/raid/intz.c.func-sort-c.html
index 18ef6699..80d5021d 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 55de5b7d..b2ed069a 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 cde048b4..0a8d7573 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 e5414239..0ece055a 100644
--- a/cov/raid/memory.c.func-sort-c.html
+++ b/cov/raid/memory.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/memory.c.func.html b/cov/raid/memory.c.func.html
index c41407b0..43bb1d27 100644
--- a/cov/raid/memory.c.func.html
+++ b/cov/raid/memory.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/memory.c.gcov.html b/cov/raid/memory.c.gcov.html
index f256592a..51354524 100644
--- a/cov/raid/memory.c.gcov.html
+++ b/cov/raid/memory.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,7 +94,7 @@
32 12558 : offset = ((uintptr_t)ptr) % align_size;
33 :
34 12558 : if (offset != 0)
- 35 12172 : ptr += align_size - offset;
+ 35 12173 : ptr += align_size - offset;
36 :
37 12558 : return ptr;
38 : }
diff --git a/cov/raid/module.c.func-sort-c.html b/cov/raid/module.c.func-sort-c.html
index ec79fad3..9dc89c58 100644
--- a/cov/raid/module.c.func-sort-c.html
+++ b/cov/raid/module.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/module.c.func.html b/cov/raid/module.c.func.html
index dea2069a..e8155122 100644
--- a/cov/raid/module.c.func.html
+++ b/cov/raid/module.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/module.c.gcov.html b/cov/raid/module.c.gcov.html
index 5da7dd67..5c10a8e3 100644
--- a/cov/raid/module.c.gcov.html
+++ b/cov/raid/module.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/raid/raid.c.func-sort-c.html b/cov/raid/raid.c.func-sort-c.html
index 05da72d1..9b412bbd 100644
--- a/cov/raid/raid.c.func-sort-c.html
+++ b/cov/raid/raid.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| raid_gen |
- 1235650 |
+ 1235764 |
| raid_data |
- 214670 |
+ 214793 |
| raid_invert |
- 172489 |
+ 172608 |
| raid_delta_gen |
- 171491 |
+ 171590 |
| raid_rec1of1 |
- 101560 |
+ 101584 |
| raid_rec |
diff --git a/cov/raid/raid.c.func.html b/cov/raid/raid.c.func.html
index 217f6747..ce892751 100644
--- a/cov/raid/raid.c.func.html
+++ b/cov/raid/raid.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| raid_data |
- 214670 |
+ 214793 |
| raid_delta_gen |
- 171491 |
+ 171590 |
| raid_gen |
- 1235650 |
+ 1235764 |
| raid_invert |
- 172489 |
+ 172608 |
| raid_mode |
@@ -85,7 +85,7 @@
| raid_rec1of1 |
- 101560 |
+ 101584 |
| raid_rec2of2_int8 |
diff --git a/cov/raid/raid.c.gcov.html b/cov/raid/raid.c.gcov.html
index 918df0e1..35498747 100644
--- a/cov/raid/raid.c.gcov.html
+++ b/cov/raid/raid.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -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 1235650 : void raid_gen(int nd, int np, size_t size, void **v)
+ 223 1235764 : void raid_gen(int nd, int np, size_t size, void **v)
224 : {
225 : /* enforce limit on size */
- 226 1235650 : BUG_ON(size % 64 != 0);
+ 226 1235764 : BUG_ON(size % 64 != 0);
227 :
228 : /* enforce limit on number of failures */
- 229 1235650 : BUG_ON(np < 1);
- 230 1235650 : BUG_ON(np > RAID_PARITY_MAX);
+ 229 1235764 : BUG_ON(np < 1);
+ 230 1235764 : BUG_ON(np > RAID_PARITY_MAX);
231 :
- 232 1235650 : raid_gen_ptr[np - 1](nd, size, v);
- 233 1235650 : }
+ 232 1235764 : raid_gen_ptr[np - 1](nd, size, v);
+ 233 1235764 : }
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 172489 : void raid_invert(uint8_t *M, uint8_t *V, int n)
+ 246 172608 : 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 797524 : for (i = 0; i < n; ++i)
- 252 3219332 : for (j = 0; j < n; ++j)
- 253 2594297 : V[i * n + j] = i == j;
+ 251 797881 : for (i = 0; i < n; ++i)
+ 252 3220046 : for (j = 0; j < n; ++j)
+ 253 2594773 : V[i * n + j] = i == j;
254 :
255 : /* for each element in the diagonal */
- 256 797524 : for (k = 0; k < n; ++k) {
+ 256 797881 : 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 625035 : BUG_ON(M[k * n + k] == 0);
+ 262 625273 : BUG_ON(M[k * n + k] == 0);
263 :
264 : /* make the diagonal element to be 1 */
- 265 1250070 : f = inv(M[k * n + k]);
- 266 3219332 : for (j = 0; j < n; ++j) {
- 267 5188594 : M[k * n + j] = mul(f, M[k * n + j]);
- 268 5188594 : V[k * n + j] = mul(f, V[k * n + j]);
+ 265 1250546 : f = inv(M[k * n + k]);
+ 266 3220046 : for (j = 0; j < n; ++j) {
+ 267 5189546 : M[k * n + j] = mul(f, M[k * n + j]);
+ 268 5189546 : 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 3219332 : for (i = 0; i < n; ++i) {
- 274 2594297 : if (i == k)
- 275 625035 : continue;
- 276 1969262 : f = M[i * n + k];
- 277 11270850 : for (j = 0; j < n; ++j) {
- 278 18603176 : M[i * n + j] ^= mul(f, M[k * n + j]);
- 279 18603176 : V[i * n + j] ^= mul(f, V[k * n + j]);
+ 273 3220046 : for (i = 0; i < n; ++i) {
+ 274 2594773 : if (i == k)
+ 275 625273 : continue;
+ 276 1969500 : f = M[i * n + k];
+ 277 11271564 : for (j = 0; j < n; ++j) {
+ 278 18604128 : M[i * n + j] ^= mul(f, M[k * n + j]);
+ 279 18604128 : V[i * n + j] ^= mul(f, V[k * n + j]);
280 : }
281 : }
282 : }
- 283 172489 : }
+ 283 172608 : }
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 171491 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v)
+ 291 171590 : 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 171491 : np = ip[nr - 1] + 1;
+ 301 171590 : np = ip[nr - 1] + 1;
302 :
303 : /* latest missing data block */
- 304 171491 : latest = v[id[nr - 1]];
+ 304 171590 : latest = v[id[nr - 1]];
305 :
306 : /* setup pointers for delta computation */
- 307 873017 : for (i = 0, j = 0; i < np; ++i) {
+ 307 873314 : for (i = 0, j = 0; i < np; ++i) {
308 : /* keep a copy of the original parity vector */
- 309 701526 : p[i] = v[nd + i];
+ 309 701724 : p[i] = v[nd + i];
310 :
- 311 701526 : if (ip[j] == i) {
+ 311 701724 : 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 605363 : BUG_ON(j >= nr);
+ 322 605581 : BUG_ON(j >= nr);
323 :
324 : /* buffer for missing data blocks */
- 325 605363 : pa[j] = v[id[j]];
+ 325 605581 : pa[j] = v[id[j]];
326 :
327 : /* set at zero the missing data blocks */
- 328 605363 : v[id[j]] = raid_zero_block;
+ 328 605581 : v[id[j]] = raid_zero_block;
329 :
330 : /* compute the parity over the missing data blocks */
- 331 605363 : v[nd + i] = pa[j];
+ 331 605581 : v[nd + i] = pa[j];
332 :
333 : /* check for the next used entry */
- 334 605363 : ++j;
+ 334 605581 : ++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 96163 : v[nd + i] = latest;
+ 354 96143 : v[nd + i] = latest;
355 : }
356 : }
357 :
358 : /* all the parities have to be processed */
- 359 171491 : BUG_ON(j != nr);
+ 359 171590 : BUG_ON(j != nr);
360 :
361 : /* recompute the parity, note that np may be smaller than the */
362 : /* total number of parities available */
- 363 171491 : raid_gen(nd, np, size, v);
+ 363 171590 : raid_gen(nd, np, size, v);
364 :
365 : /* restore data buffers as before */
- 366 776854 : for (j = 0; j < nr; ++j)
- 367 605363 : v[id[j]] = pa[j];
+ 366 777171 : for (j = 0; j < nr; ++j)
+ 367 605581 : v[id[j]] = pa[j];
368 :
369 : /* restore parity buffers as before */
- 370 873017 : for (i = 0; i < np; ++i)
- 371 701526 : v[nd + i] = p[i];
- 372 171491 : }
+ 370 873314 : for (i = 0; i < np; ++i)
+ 371 701724 : v[nd + i] = p[i];
+ 372 171590 : }
373 :
374 : /**
375 : * Recover failure of one data block for PAR1.
@@ -444,29 +444,29 @@
382 : *
383 : * Dx = Pd
384 : */
- 385 101560 : void raid_rec1of1(int *id, int nd, size_t size, void **v)
+ 385 101584 : 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 101560 : p = v[nd];
- 393 101560 : pa = v[id[0]];
+ 392 101584 : p = v[nd];
+ 393 101584 : pa = v[id[0]];
394 :
395 : /* use the parity as missing data block */
- 396 101560 : v[id[0]] = p;
+ 396 101584 : v[id[0]] = p;
397 :
398 : /* compute the parity over the missing data block */
- 399 101560 : v[nd] = pa;
+ 399 101584 : v[nd] = pa;
400 :
401 : /* compute */
- 402 101560 : raid_gen(nd, 1, size, v);
+ 402 101584 : raid_gen(nd, 1, size, v);
403 :
404 : /* restore as before */
- 405 101560 : v[id[0]] = pa;
- 406 101560 : v[nd] = p;
- 407 101560 : }
+ 405 101584 : v[id[0]] = pa;
+ 406 101584 : v[nd] = p;
+ 407 101584 : }
408 :
409 : /**
410 : * Recover failure of two data blocks for PAR2.
@@ -615,36 +615,36 @@
553 12 : raid_gen(nd, ir[nr - 1] - nd + 1, size, v);
554 870 : }
555 :
- 556 214670 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
+ 556 214793 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v)
557 : {
558 : /* enforce limit on size */
- 559 214670 : BUG_ON(size % 64 != 0);
+ 559 214793 : BUG_ON(size % 64 != 0);
560 :
561 : /* enforce limit on number of failures */
- 562 214670 : BUG_ON(nr > nd);
- 563 214670 : BUG_ON(nr > RAID_PARITY_MAX);
+ 562 214793 : BUG_ON(nr > nd);
+ 563 214793 : BUG_ON(nr > RAID_PARITY_MAX);
564 :
565 : /* enforce order in index vector for data */
- 566 214670 : BUG_ON(nr >= 2 && id[0] >= id[1]);
- 567 214670 : BUG_ON(nr >= 3 && id[1] >= id[2]);
- 568 214670 : BUG_ON(nr >= 4 && id[2] >= id[3]);
- 569 214670 : BUG_ON(nr >= 5 && id[3] >= id[4]);
- 570 214670 : BUG_ON(nr >= 6 && id[4] >= id[5]);
+ 566 214793 : BUG_ON(nr >= 2 && id[0] >= id[1]);
+ 567 214793 : BUG_ON(nr >= 3 && id[1] >= id[2]);
+ 568 214793 : BUG_ON(nr >= 4 && id[2] >= id[3]);
+ 569 214793 : BUG_ON(nr >= 5 && id[3] >= id[4]);
+ 570 214793 : BUG_ON(nr >= 6 && id[4] >= id[5]);
571 :
572 : /* enforce limit on index vector for data */
- 573 214670 : BUG_ON(nr > 0 && id[nr-1] >= nd);
+ 573 214793 : BUG_ON(nr > 0 && id[nr-1] >= nd);
574 :
575 : /* enforce order in index vector for parity */
- 576 214670 : BUG_ON(nr >= 2 && ip[0] >= ip[1]);
- 577 214670 : BUG_ON(nr >= 3 && ip[1] >= ip[2]);
- 578 214670 : BUG_ON(nr >= 4 && ip[2] >= ip[3]);
- 579 214670 : BUG_ON(nr >= 5 && ip[3] >= ip[4]);
- 580 214670 : BUG_ON(nr >= 6 && ip[4] >= ip[5]);
+ 576 214793 : BUG_ON(nr >= 2 && ip[0] >= ip[1]);
+ 577 214793 : BUG_ON(nr >= 3 && ip[1] >= ip[2]);
+ 578 214793 : BUG_ON(nr >= 4 && ip[2] >= ip[3]);
+ 579 214793 : BUG_ON(nr >= 5 && ip[3] >= ip[4]);
+ 580 214793 : BUG_ON(nr >= 6 && ip[4] >= ip[5]);
581 :
582 : /* if failed data is present */
- 583 214670 : if (nr != 0)
- 584 214668 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
- 585 214670 : }
+ 583 214793 : if (nr != 0)
+ 584 214791 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
+ 585 214793 : }
586 :
diff --git a/cov/raid/tag.c.func-sort-c.html b/cov/raid/tag.c.func-sort-c.html
index 1f9b9cc9..5886f163 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 ed516e06..ac6d52b3 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 c32dfdec..5fc80304 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 f0ff52fe..c06e625f 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 f1adbb5b..b49cc7a1 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 f06db169..bf8c0609 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 d8bd9c3e..9c4f11bc 100644
--- a/cov/raid/x86.c.func-sort-c.html
+++ b/cov/raid/x86.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| raid_gen6_ssse3 |
- 564177 |
+ 564249 |
| raid_gen1_sse2 |
- 288948 |
+ 288895 |
| raid_gen2_sse2 |
- 268716 |
+ 268822 |
| raid_rec1_ssse3 |
- 111395 |
+ 111399 |
| raid_recX_ssse3 |
@@ -81,11 +81,11 @@
| raid_gen5_ssse3 |
- 50654 |
+ 50656 |
| raid_rec2_ssse3 |
- 44038 |
+ 44157 |
| raid_gen4_ssse3 |
@@ -93,7 +93,7 @@
| raid_gen3_ssse3 |
- 29542 |
+ 29541 |
| raid_recX_avx2 |
@@ -113,7 +113,7 @@
| raid_gen1_avx2 |
- 97 |
+ 98 |
diff --git a/cov/raid/x86.c.func.html b/cov/raid/x86.c.func.html
index 80a9bfea..4b7e9dd9 100644
--- a/cov/raid/x86.c.func.html
+++ b/cov/raid/x86.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| raid_gen1_avx2 |
- 97 |
+ 98 |
| raid_gen1_sse2 |
- 288948 |
+ 288895 |
| raid_gen2_avx2 |
@@ -73,11 +73,11 @@
| raid_gen2_sse2 |
- 268716 |
+ 268822 |
| raid_gen3_ssse3 |
- 29542 |
+ 29541 |
| raid_gen4_ssse3 |
@@ -85,11 +85,11 @@
| raid_gen5_ssse3 |
- 50654 |
+ 50656 |
| raid_gen6_ssse3 |
- 564177 |
+ 564249 |
| raid_rec1_avx2 |
@@ -97,7 +97,7 @@
| raid_rec1_ssse3 |
- 111395 |
+ 111399 |
| raid_rec2_avx2 |
@@ -105,7 +105,7 @@
| raid_rec2_ssse3 |
- 44038 |
+ 44157 |
| raid_recX_avx2 |
diff --git a/cov/raid/x86.c.gcov.html b/cov/raid/x86.c.gcov.html
index 7c8a2e85..35b792da 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 288948 : void raid_gen1_sse2(int nd, size_t size, void **vv)
+ 36 288895 : void raid_gen1_sse2(int nd, size_t size, void **vv)
37 : {
- 38 288948 : uint8_t **v = (uint8_t **)vv;
+ 38 288895 : uint8_t **v = (uint8_t **)vv;
39 : uint8_t *p;
40 : int d, l;
41 : size_t i;
42 :
- 43 288948 : l = nd - 1;
- 44 288948 : p = v[nd];
+ 43 288895 : l = nd - 1;
+ 44 288895 : p = v[nd];
45 :
46 : raid_sse_begin();
47 :
- 48 6140160 : for (i = 0; i < size; i += 64) {
- 49 5851212 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 50 5851212 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
- 51 5851212 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32]));
- 52 5851212 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48]));
- 53 37573252 : for (d = l - 1; d >= 0; --d) {
- 54 31722040 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i]));
- 55 31722040 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16]));
- 56 31722040 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32]));
- 57 31722040 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48]));
+ 48 6155579 : for (i = 0; i < size; i += 64) {
+ 49 5866684 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 50 5866684 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
+ 51 5866684 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32]));
+ 52 5866684 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48]));
+ 53 37698852 : for (d = l - 1; d >= 0; --d) {
+ 54 31832168 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i]));
+ 55 31832168 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16]));
+ 56 31832168 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32]));
+ 57 31832168 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48]));
58 : }
- 59 5851212 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 60 5851212 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
- 61 5851212 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32]));
- 62 5851212 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48]));
+ 59 5866684 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 60 5866684 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
+ 61 5866684 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32]));
+ 62 5866684 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48]));
63 : }
64 :
65 : raid_sse_end();
- 66 288948 : }
+ 66 288895 : }
67 : #endif
68 :
69 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2)
@@ -136,31 +136,31 @@
74 : * cache block, and processing 128 bytes doesn't increase performance, and in
75 : * some cases it even decreases it.
76 : */
- 77 97 : void raid_gen1_avx2(int nd, size_t size, void **vv)
+ 77 98 : void raid_gen1_avx2(int nd, size_t size, void **vv)
78 : {
- 79 97 : uint8_t **v = (uint8_t **)vv;
+ 79 98 : uint8_t **v = (uint8_t **)vv;
80 : uint8_t *p;
81 : int d, l;
82 : size_t i;
83 :
- 84 97 : l = nd - 1;
- 85 97 : p = v[nd];
+ 84 98 : l = nd - 1;
+ 85 98 : p = v[nd];
86 :
87 : raid_avx_begin();
88 :
- 89 50189 : for (i = 0; i < size; i += 64) {
- 90 50092 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i]));
- 91 50092 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32]));
- 92 407172 : for (d = l - 1; d >= 0; --d) {
- 93 357080 : asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i]));
- 94 357080 : asm volatile ("vpxor %0,%%ymm1,%%ymm1" : : "m" (v[d][i + 32]));
+ 89 54286 : for (i = 0; i < size; i += 64) {
+ 90 54188 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i]));
+ 91 54188 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32]));
+ 92 439940 : for (d = l - 1; d >= 0; --d) {
+ 93 385752 : asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i]));
+ 94 385752 : asm volatile ("vpxor %0,%%ymm1,%%ymm1" : : "m" (v[d][i + 32]));
95 : }
- 96 50092 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i]));
- 97 50092 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32]));
+ 96 54188 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i]));
+ 97 54188 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32]));
98 : }
99 :
100 : raid_avx_end();
- 101 97 : }
+ 101 98 : }
102 : #endif
103 :
104 : #if defined(CONFIG_X86) && defined(CONFIG_SSE2)
@@ -183,54 +183,54 @@
121 : /*
122 : * GEN2 (RAID6 with powers of 2) SSE2 implementation
123 : */
- 124 268716 : void raid_gen2_sse2(int nd, size_t size, void **vv)
+ 124 268822 : void raid_gen2_sse2(int nd, size_t size, void **vv)
125 : {
- 126 268716 : uint8_t **v = (uint8_t **)vv;
+ 126 268822 : uint8_t **v = (uint8_t **)vv;
127 : uint8_t *p;
128 : uint8_t *q;
129 : int d, l;
130 : size_t i;
131 :
- 132 268716 : l = nd - 1;
- 133 268716 : p = v[nd];
- 134 268716 : q = v[nd + 1];
+ 132 268822 : l = nd - 1;
+ 133 268822 : p = v[nd];
+ 134 268822 : q = v[nd + 1];
135 :
136 : raid_sse_begin();
137 :
- 138 268716 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 138 268822 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
139 :
- 140 10785156 : for (i = 0; i < size; i += 32) {
- 141 10516440 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 142 10516440 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
- 143 10516440 : asm volatile ("movdqa %xmm0,%xmm2");
- 144 10516440 : asm volatile ("movdqa %xmm1,%xmm3");
- 145 66949256 : for (d = l - 1; d >= 0; --d) {
- 146 56432816 : asm volatile ("pxor %xmm4,%xmm4");
- 147 56432816 : asm volatile ("pxor %xmm5,%xmm5");
- 148 56432816 : asm volatile ("pcmpgtb %xmm2,%xmm4");
- 149 56432816 : asm volatile ("pcmpgtb %xmm3,%xmm5");
- 150 56432816 : asm volatile ("paddb %xmm2,%xmm2");
- 151 56432816 : asm volatile ("paddb %xmm3,%xmm3");
- 152 56432816 : asm volatile ("pand %xmm7,%xmm4");
- 153 56432816 : asm volatile ("pand %xmm7,%xmm5");
- 154 56432816 : asm volatile ("pxor %xmm4,%xmm2");
- 155 56432816 : asm volatile ("pxor %xmm5,%xmm3");
+ 140 10845774 : for (i = 0; i < size; i += 32) {
+ 141 10576952 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 142 10576952 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16]));
+ 143 10576952 : asm volatile ("movdqa %xmm0,%xmm2");
+ 144 10576952 : asm volatile ("movdqa %xmm1,%xmm3");
+ 145 67427016 : for (d = l - 1; d >= 0; --d) {
+ 146 56850064 : asm volatile ("pxor %xmm4,%xmm4");
+ 147 56850064 : asm volatile ("pxor %xmm5,%xmm5");
+ 148 56850064 : asm volatile ("pcmpgtb %xmm2,%xmm4");
+ 149 56850064 : asm volatile ("pcmpgtb %xmm3,%xmm5");
+ 150 56850064 : asm volatile ("paddb %xmm2,%xmm2");
+ 151 56850064 : asm volatile ("paddb %xmm3,%xmm3");
+ 152 56850064 : asm volatile ("pand %xmm7,%xmm4");
+ 153 56850064 : asm volatile ("pand %xmm7,%xmm5");
+ 154 56850064 : asm volatile ("pxor %xmm4,%xmm2");
+ 155 56850064 : asm volatile ("pxor %xmm5,%xmm3");
156 :
- 157 56432816 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 158 56432816 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16]));
- 159 56432816 : asm volatile ("pxor %xmm4,%xmm0");
- 160 56432816 : asm volatile ("pxor %xmm5,%xmm1");
- 161 56432816 : asm volatile ("pxor %xmm4,%xmm2");
- 162 56432816 : asm volatile ("pxor %xmm5,%xmm3");
+ 157 56850064 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 158 56850064 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16]));
+ 159 56850064 : asm volatile ("pxor %xmm4,%xmm0");
+ 160 56850064 : asm volatile ("pxor %xmm5,%xmm1");
+ 161 56850064 : asm volatile ("pxor %xmm4,%xmm2");
+ 162 56850064 : asm volatile ("pxor %xmm5,%xmm3");
163 : }
- 164 10516440 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 165 10516440 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
- 166 10516440 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i]));
- 167 10516440 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16]));
+ 164 10576952 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 165 10576952 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16]));
+ 166 10576952 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i]));
+ 167 10576952 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16]));
168 : }
169 :
170 : raid_sse_end();
- 171 268716 : }
+ 171 268822 : }
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 29542 : void raid_gen3_ssse3(int nd, size_t size, void **vv)
+ 311 29541 : void raid_gen3_ssse3(int nd, size_t size, void **vv)
312 : {
- 313 29542 : uint8_t **v = (uint8_t **)vv;
+ 313 29541 : 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 29542 : l = nd - 1;
- 321 29542 : p = v[nd];
- 322 29542 : q = v[nd + 1];
- 323 29542 : r = v[nd + 2];
+ 320 29541 : l = nd - 1;
+ 321 29541 : p = v[nd];
+ 322 29541 : q = v[nd + 1];
+ 323 29541 : r = v[nd + 2];
324 :
325 : /* special case with only one data disk */
- 326 29542 : if (l == 0) {
+ 326 29541 : if (l == 0) {
327 4 : for (i = 0; i < 3; ++i)
328 3 : memcpy(v[1 + i], v[0], size);
- 329 29543 : return;
+ 329 29542 : return;
330 : }
331 :
332 : raid_sse_begin();
333 :
334 : /* generic case with at least two data disks */
- 335 29541 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
- 336 29541 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 335 29540 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
+ 336 29540 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
337 :
- 338 4888821 : for (i = 0; i < size; i += 16) {
+ 338 4872436 : for (i = 0; i < size; i += 16) {
339 : /* last disk without the by two multiplication */
- 340 4859280 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 340 4842896 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
341 :
- 342 4859280 : asm volatile ("movdqa %xmm4,%xmm0");
- 343 4859280 : asm volatile ("movdqa %xmm4,%xmm1");
+ 342 4842896 : asm volatile ("movdqa %xmm4,%xmm0");
+ 343 4842896 : asm volatile ("movdqa %xmm4,%xmm1");
344 :
- 345 4859280 : asm volatile ("movdqa %xmm4,%xmm5");
- 346 4859280 : asm volatile ("psrlw $4,%xmm5");
- 347 4859280 : asm volatile ("pand %xmm7,%xmm4");
- 348 4859280 : asm volatile ("pand %xmm7,%xmm5");
+ 345 4842896 : asm volatile ("movdqa %xmm4,%xmm5");
+ 346 4842896 : asm volatile ("psrlw $4,%xmm5");
+ 347 4842896 : asm volatile ("pand %xmm7,%xmm4");
+ 348 4842896 : asm volatile ("pand %xmm7,%xmm5");
349 :
- 350 4859280 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
- 351 4859280 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0]));
- 352 4859280 : asm volatile ("pshufb %xmm4,%xmm2");
- 353 4859280 : asm volatile ("pshufb %xmm5,%xmm6");
- 354 4859280 : asm volatile ("pxor %xmm6,%xmm2");
+ 350 4842896 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0]));
+ 351 4842896 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0]));
+ 352 4842896 : asm volatile ("pshufb %xmm4,%xmm2");
+ 353 4842896 : asm volatile ("pshufb %xmm5,%xmm6");
+ 354 4842896 : asm volatile ("pxor %xmm6,%xmm2");
355 :
356 : /* intermediate disks */
- 357 30489328 : for (d = l - 1; d > 0; --d) {
- 358 25630048 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 357 30374640 : for (d = l - 1; d > 0; --d) {
+ 358 25531744 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
359 :
- 360 25630048 : asm volatile ("pxor %xmm5,%xmm5");
- 361 25630048 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 362 25630048 : asm volatile ("paddb %xmm1,%xmm1");
- 363 25630048 : asm volatile ("pand %xmm3,%xmm5");
- 364 25630048 : asm volatile ("pxor %xmm5,%xmm1");
+ 360 25531744 : asm volatile ("pxor %xmm5,%xmm5");
+ 361 25531744 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 362 25531744 : asm volatile ("paddb %xmm1,%xmm1");
+ 363 25531744 : asm volatile ("pand %xmm3,%xmm5");
+ 364 25531744 : asm volatile ("pxor %xmm5,%xmm1");
365 :
- 366 25630048 : asm volatile ("pxor %xmm4,%xmm0");
- 367 25630048 : asm volatile ("pxor %xmm4,%xmm1");
+ 366 25531744 : asm volatile ("pxor %xmm4,%xmm0");
+ 367 25531744 : asm volatile ("pxor %xmm4,%xmm1");
368 :
- 369 25630048 : asm volatile ("movdqa %xmm4,%xmm5");
- 370 25630048 : asm volatile ("psrlw $4,%xmm5");
- 371 25630048 : asm volatile ("pand %xmm7,%xmm4");
- 372 25630048 : asm volatile ("pand %xmm7,%xmm5");
+ 369 25531744 : asm volatile ("movdqa %xmm4,%xmm5");
+ 370 25531744 : asm volatile ("psrlw $4,%xmm5");
+ 371 25531744 : asm volatile ("pand %xmm7,%xmm4");
+ 372 25531744 : asm volatile ("pand %xmm7,%xmm5");
373 :
- 374 25630048 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 375 25630048 : asm volatile ("pshufb %xmm4,%xmm6");
- 376 25630048 : asm volatile ("pxor %xmm6,%xmm2");
- 377 25630048 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0]));
- 378 25630048 : asm volatile ("pshufb %xmm5,%xmm6");
- 379 25630048 : asm volatile ("pxor %xmm6,%xmm2");
+ 374 25531744 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 375 25531744 : asm volatile ("pshufb %xmm4,%xmm6");
+ 376 25531744 : asm volatile ("pxor %xmm6,%xmm2");
+ 377 25531744 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0]));
+ 378 25531744 : asm volatile ("pshufb %xmm5,%xmm6");
+ 379 25531744 : asm volatile ("pxor %xmm6,%xmm2");
380 : }
381 :
382 : /* first disk with all coefficients at 1 */
- 383 4859280 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 383 4842896 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
384 :
- 385 4859280 : asm volatile ("pxor %xmm5,%xmm5");
- 386 4859280 : asm volatile ("pcmpgtb %xmm1,%xmm5");
- 387 4859280 : asm volatile ("paddb %xmm1,%xmm1");
- 388 4859280 : asm volatile ("pand %xmm3,%xmm5");
- 389 4859280 : asm volatile ("pxor %xmm5,%xmm1");
+ 385 4842896 : asm volatile ("pxor %xmm5,%xmm5");
+ 386 4842896 : asm volatile ("pcmpgtb %xmm1,%xmm5");
+ 387 4842896 : asm volatile ("paddb %xmm1,%xmm1");
+ 388 4842896 : asm volatile ("pand %xmm3,%xmm5");
+ 389 4842896 : asm volatile ("pxor %xmm5,%xmm1");
390 :
- 391 4859280 : asm volatile ("pxor %xmm4,%xmm0");
- 392 4859280 : asm volatile ("pxor %xmm4,%xmm1");
- 393 4859280 : asm volatile ("pxor %xmm4,%xmm2");
+ 391 4842896 : asm volatile ("pxor %xmm4,%xmm0");
+ 392 4842896 : asm volatile ("pxor %xmm4,%xmm1");
+ 393 4842896 : asm volatile ("pxor %xmm4,%xmm2");
394 :
- 395 4859280 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 396 4859280 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
- 397 4859280 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
+ 395 4842896 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 396 4842896 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
+ 397 4842896 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
398 : }
399 :
400 : raid_sse_end();
@@ -1191,9 +1191,9 @@
1129 : /*
1130 : * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation
1131 : */
- 1132 50654 : void raid_gen5_ssse3(int nd, size_t size, void **vv)
+ 1132 50656 : void raid_gen5_ssse3(int nd, size_t size, void **vv)
1133 : {
- 1134 50654 : uint8_t **v = (uint8_t **)vv;
+ 1134 50656 : 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 50654 : uint8_t *pd = __align_ptr(buffer, 16);
+ 1143 50656 : uint8_t *pd = __align_ptr(buffer, 16);
1144 :
- 1145 50654 : l = nd - 1;
- 1146 50654 : p = v[nd];
- 1147 50654 : q = v[nd + 1];
- 1148 50654 : r = v[nd + 2];
- 1149 50654 : s = v[nd + 3];
- 1150 50654 : t = v[nd + 4];
+ 1145 50656 : l = nd - 1;
+ 1146 50656 : p = v[nd];
+ 1147 50656 : q = v[nd + 1];
+ 1148 50656 : r = v[nd + 2];
+ 1149 50656 : s = v[nd + 3];
+ 1150 50656 : t = v[nd + 4];
1151 :
1152 : /* special case with only one data disk */
- 1153 50654 : if (l == 0) {
+ 1153 50656 : if (l == 0) {
1154 6 : for (i = 0; i < 5; ++i)
1155 5 : memcpy(v[1 + i], v[0], size);
- 1156 50655 : return;
+ 1156 50657 : return;
1157 : }
1158 :
1159 : raid_sse_begin();
1160 :
1161 : /* generic case with at least two data disks */
- 1162 3937517 : for (i = 0; i < size; i += 16) {
+ 1162 3970287 : for (i = 0; i < size; i += 16) {
1163 : /* last disk without the by two multiplication */
- 1164 3886864 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 1164 3919632 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
1165 :
- 1166 3886864 : asm volatile ("movdqa %xmm4,%xmm0");
- 1167 3886864 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
+ 1166 3919632 : asm volatile ("movdqa %xmm4,%xmm0");
+ 1167 3919632 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
1168 :
- 1169 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1170 3886864 : asm volatile ("movdqa %xmm4,%xmm5");
- 1171 3886864 : asm volatile ("psrlw $4,%xmm5");
- 1172 3886864 : asm volatile ("pand %xmm7,%xmm4");
- 1173 3886864 : asm volatile ("pand %xmm7,%xmm5");
+ 1169 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1170 3919632 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1171 3919632 : asm volatile ("psrlw $4,%xmm5");
+ 1172 3919632 : asm volatile ("pand %xmm7,%xmm4");
+ 1173 3919632 : asm volatile ("pand %xmm7,%xmm5");
1174 :
- 1175 3886864 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0]));
- 1176 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
- 1177 3886864 : asm volatile ("pshufb %xmm4,%xmm1");
- 1178 3886864 : asm volatile ("pshufb %xmm5,%xmm7");
- 1179 3886864 : asm volatile ("pxor %xmm7,%xmm1");
+ 1175 3919632 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0]));
+ 1176 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
+ 1177 3919632 : asm volatile ("pshufb %xmm4,%xmm1");
+ 1178 3919632 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1179 3919632 : asm volatile ("pxor %xmm7,%xmm1");
1180 :
- 1181 3886864 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0]));
- 1182 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
- 1183 3886864 : asm volatile ("pshufb %xmm4,%xmm2");
- 1184 3886864 : asm volatile ("pshufb %xmm5,%xmm7");
- 1185 3886864 : asm volatile ("pxor %xmm7,%xmm2");
+ 1181 3919632 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0]));
+ 1182 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
+ 1183 3919632 : asm volatile ("pshufb %xmm4,%xmm2");
+ 1184 3919632 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1185 3919632 : asm volatile ("pxor %xmm7,%xmm2");
1186 :
- 1187 3886864 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0]));
- 1188 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
- 1189 3886864 : asm volatile ("pshufb %xmm4,%xmm3");
- 1190 3886864 : asm volatile ("pshufb %xmm5,%xmm7");
- 1191 3886864 : asm volatile ("pxor %xmm7,%xmm3");
+ 1187 3919632 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0]));
+ 1188 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
+ 1189 3919632 : asm volatile ("pshufb %xmm4,%xmm3");
+ 1190 3919632 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1191 3919632 : asm volatile ("pxor %xmm7,%xmm3");
1192 :
1193 : /* intermediate disks */
- 1194 23263984 : for (d = l - 1; d > 0; --d) {
- 1195 19377120 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 1196 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
- 1197 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1194 23493360 : for (d = l - 1; d > 0; --d) {
+ 1195 19573728 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 1196 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
+ 1197 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1198 :
- 1199 19377120 : asm volatile ("pxor %xmm5,%xmm5");
- 1200 19377120 : asm volatile ("pcmpgtb %xmm0,%xmm5");
- 1201 19377120 : asm volatile ("paddb %xmm0,%xmm0");
- 1202 19377120 : asm volatile ("pand %xmm7,%xmm5");
- 1203 19377120 : asm volatile ("pxor %xmm5,%xmm0");
+ 1199 19573728 : asm volatile ("pxor %xmm5,%xmm5");
+ 1200 19573728 : asm volatile ("pcmpgtb %xmm0,%xmm5");
+ 1201 19573728 : asm volatile ("paddb %xmm0,%xmm0");
+ 1202 19573728 : asm volatile ("pand %xmm7,%xmm5");
+ 1203 19573728 : asm volatile ("pxor %xmm5,%xmm0");
1204 :
- 1205 19377120 : asm volatile ("pxor %xmm4,%xmm0");
- 1206 19377120 : asm volatile ("pxor %xmm4,%xmm6");
- 1207 19377120 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0]));
+ 1205 19573728 : asm volatile ("pxor %xmm4,%xmm0");
+ 1206 19573728 : asm volatile ("pxor %xmm4,%xmm6");
+ 1207 19573728 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0]));
1208 :
- 1209 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1210 19377120 : asm volatile ("movdqa %xmm4,%xmm5");
- 1211 19377120 : asm volatile ("psrlw $4,%xmm5");
- 1212 19377120 : asm volatile ("pand %xmm7,%xmm4");
- 1213 19377120 : asm volatile ("pand %xmm7,%xmm5");
+ 1209 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1210 19573728 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1211 19573728 : asm volatile ("psrlw $4,%xmm5");
+ 1212 19573728 : asm volatile ("pand %xmm7,%xmm4");
+ 1213 19573728 : asm volatile ("pand %xmm7,%xmm5");
1214 :
- 1215 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 1216 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
- 1217 19377120 : asm volatile ("pshufb %xmm4,%xmm6");
- 1218 19377120 : asm volatile ("pshufb %xmm5,%xmm7");
- 1219 19377120 : asm volatile ("pxor %xmm6,%xmm1");
- 1220 19377120 : asm volatile ("pxor %xmm7,%xmm1");
+ 1215 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 1216 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
+ 1217 19573728 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1218 19573728 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1219 19573728 : asm volatile ("pxor %xmm6,%xmm1");
+ 1220 19573728 : asm volatile ("pxor %xmm7,%xmm1");
1221 :
- 1222 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
- 1223 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
- 1224 19377120 : asm volatile ("pshufb %xmm4,%xmm6");
- 1225 19377120 : asm volatile ("pshufb %xmm5,%xmm7");
- 1226 19377120 : asm volatile ("pxor %xmm6,%xmm2");
- 1227 19377120 : asm volatile ("pxor %xmm7,%xmm2");
+ 1222 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
+ 1223 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
+ 1224 19573728 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1225 19573728 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1226 19573728 : asm volatile ("pxor %xmm6,%xmm2");
+ 1227 19573728 : asm volatile ("pxor %xmm7,%xmm2");
1228 :
- 1229 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
- 1230 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
- 1231 19377120 : asm volatile ("pshufb %xmm4,%xmm6");
- 1232 19377120 : asm volatile ("pshufb %xmm5,%xmm7");
- 1233 19377120 : asm volatile ("pxor %xmm6,%xmm3");
- 1234 19377120 : asm volatile ("pxor %xmm7,%xmm3");
+ 1229 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
+ 1230 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
+ 1231 19573728 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1232 19573728 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1233 19573728 : asm volatile ("pxor %xmm6,%xmm3");
+ 1234 19573728 : asm volatile ("pxor %xmm7,%xmm3");
1235 : }
1236 :
1237 : /* first disk with all coefficients at 1 */
- 1238 3886864 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
- 1239 3886864 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
- 1240 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1238 3919632 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 1239 3919632 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0]));
+ 1240 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1241 :
- 1242 3886864 : asm volatile ("pxor %xmm5,%xmm5");
- 1243 3886864 : asm volatile ("pcmpgtb %xmm0,%xmm5");
- 1244 3886864 : asm volatile ("paddb %xmm0,%xmm0");
- 1245 3886864 : asm volatile ("pand %xmm7,%xmm5");
- 1246 3886864 : asm volatile ("pxor %xmm5,%xmm0");
+ 1242 3919632 : asm volatile ("pxor %xmm5,%xmm5");
+ 1243 3919632 : asm volatile ("pcmpgtb %xmm0,%xmm5");
+ 1244 3919632 : asm volatile ("paddb %xmm0,%xmm0");
+ 1245 3919632 : asm volatile ("pand %xmm7,%xmm5");
+ 1246 3919632 : asm volatile ("pxor %xmm5,%xmm0");
1247 :
- 1248 3886864 : asm volatile ("pxor %xmm4,%xmm0");
- 1249 3886864 : asm volatile ("pxor %xmm4,%xmm1");
- 1250 3886864 : asm volatile ("pxor %xmm4,%xmm2");
- 1251 3886864 : asm volatile ("pxor %xmm4,%xmm3");
- 1252 3886864 : asm volatile ("pxor %xmm4,%xmm6");
+ 1248 3919632 : asm volatile ("pxor %xmm4,%xmm0");
+ 1249 3919632 : asm volatile ("pxor %xmm4,%xmm1");
+ 1250 3919632 : asm volatile ("pxor %xmm4,%xmm2");
+ 1251 3919632 : asm volatile ("pxor %xmm4,%xmm3");
+ 1252 3919632 : asm volatile ("pxor %xmm4,%xmm6");
1253 :
- 1254 3886864 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i]));
- 1255 3886864 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i]));
- 1256 3886864 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i]));
- 1257 3886864 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i]));
- 1258 3886864 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i]));
+ 1254 3919632 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i]));
+ 1255 3919632 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i]));
+ 1256 3919632 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i]));
+ 1257 3919632 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i]));
+ 1258 3919632 : 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 564177 : void raid_gen6_ssse3(int nd, size_t size, void **vv)
+ 1532 564249 : void raid_gen6_ssse3(int nd, size_t size, void **vv)
1533 : {
- 1534 564177 : uint8_t **v = (uint8_t **)vv;
+ 1534 564249 : 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 564177 : uint8_t *pd = __align_ptr(buffer, 16);
+ 1544 564249 : uint8_t *pd = __align_ptr(buffer, 16);
1545 :
- 1546 564177 : l = nd - 1;
- 1547 564177 : p = v[nd];
- 1548 564177 : q = v[nd + 1];
- 1549 564177 : r = v[nd + 2];
- 1550 564177 : s = v[nd + 3];
- 1551 564177 : t = v[nd + 4];
- 1552 564177 : u = v[nd + 5];
+ 1546 564249 : l = nd - 1;
+ 1547 564249 : p = v[nd];
+ 1548 564249 : q = v[nd + 1];
+ 1549 564249 : r = v[nd + 2];
+ 1550 564249 : s = v[nd + 3];
+ 1551 564249 : t = v[nd + 4];
+ 1552 564249 : u = v[nd + 5];
1553 :
1554 : /* special case with only one data disk */
- 1555 564177 : if (l == 0) {
+ 1555 564249 : if (l == 0) {
1556 7 : for (i = 0; i < 6; ++i)
1557 6 : memcpy(v[1 + i], v[0], size);
- 1558 564178 : return;
+ 1558 564250 : return;
1559 : }
1560 :
1561 : raid_sse_begin();
1562 :
1563 : /* generic case with at least two data disks */
- 1564 36098080 : for (i = 0; i < size; i += 16) {
+ 1564 36102760 : for (i = 0; i < size; i += 16) {
1565 : /* last disk without the by two multiplication */
- 1566 35533904 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
+ 1566 35538512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i]));
1567 :
- 1568 35533904 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
- 1569 35533904 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16]));
+ 1568 35538512 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0]));
+ 1569 35538512 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16]));
1570 :
- 1571 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1572 35533904 : asm volatile ("movdqa %xmm4,%xmm5");
- 1573 35533904 : asm volatile ("psrlw $4,%xmm5");
- 1574 35533904 : asm volatile ("pand %xmm7,%xmm4");
- 1575 35533904 : asm volatile ("pand %xmm7,%xmm5");
+ 1571 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1572 35538512 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1573 35538512 : asm volatile ("psrlw $4,%xmm5");
+ 1574 35538512 : asm volatile ("pand %xmm7,%xmm4");
+ 1575 35538512 : asm volatile ("pand %xmm7,%xmm5");
1576 :
- 1577 35533904 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0]));
- 1578 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
- 1579 35533904 : asm volatile ("pshufb %xmm4,%xmm0");
- 1580 35533904 : asm volatile ("pshufb %xmm5,%xmm7");
- 1581 35533904 : asm volatile ("pxor %xmm7,%xmm0");
+ 1577 35538512 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0]));
+ 1578 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0]));
+ 1579 35538512 : asm volatile ("pshufb %xmm4,%xmm0");
+ 1580 35538512 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1581 35538512 : asm volatile ("pxor %xmm7,%xmm0");
1582 :
- 1583 35533904 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0]));
- 1584 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
- 1585 35533904 : asm volatile ("pshufb %xmm4,%xmm1");
- 1586 35533904 : asm volatile ("pshufb %xmm5,%xmm7");
- 1587 35533904 : asm volatile ("pxor %xmm7,%xmm1");
+ 1583 35538512 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0]));
+ 1584 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0]));
+ 1585 35538512 : asm volatile ("pshufb %xmm4,%xmm1");
+ 1586 35538512 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1587 35538512 : asm volatile ("pxor %xmm7,%xmm1");
1588 :
- 1589 35533904 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0]));
- 1590 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
- 1591 35533904 : asm volatile ("pshufb %xmm4,%xmm2");
- 1592 35533904 : asm volatile ("pshufb %xmm5,%xmm7");
- 1593 35533904 : asm volatile ("pxor %xmm7,%xmm2");
+ 1589 35538512 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0]));
+ 1590 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0]));
+ 1591 35538512 : asm volatile ("pshufb %xmm4,%xmm2");
+ 1592 35538512 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1593 35538512 : asm volatile ("pxor %xmm7,%xmm2");
1594 :
- 1595 35533904 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0]));
- 1596 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0]));
- 1597 35533904 : asm volatile ("pshufb %xmm4,%xmm3");
- 1598 35533904 : asm volatile ("pshufb %xmm5,%xmm7");
- 1599 35533904 : asm volatile ("pxor %xmm7,%xmm3");
+ 1595 35538512 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0]));
+ 1596 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0]));
+ 1597 35538512 : asm volatile ("pshufb %xmm4,%xmm3");
+ 1598 35538512 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1599 35538512 : asm volatile ("pxor %xmm7,%xmm3");
1600 :
1601 : /* intermediate disks */
- 1602 183674416 : for (d = l - 1; d > 0; --d) {
- 1603 148140512 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
- 1604 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
- 1605 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1602 183697456 : for (d = l - 1; d > 0; --d) {
+ 1603 148158944 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
+ 1604 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
+ 1605 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1606 :
- 1607 148140512 : asm volatile ("pxor %xmm4,%xmm4");
- 1608 148140512 : asm volatile ("pcmpgtb %xmm6,%xmm4");
- 1609 148140512 : asm volatile ("paddb %xmm6,%xmm6");
- 1610 148140512 : asm volatile ("pand %xmm7,%xmm4");
- 1611 148140512 : asm volatile ("pxor %xmm4,%xmm6");
+ 1607 148158944 : asm volatile ("pxor %xmm4,%xmm4");
+ 1608 148158944 : asm volatile ("pcmpgtb %xmm6,%xmm4");
+ 1609 148158944 : asm volatile ("paddb %xmm6,%xmm6");
+ 1610 148158944 : asm volatile ("pand %xmm7,%xmm4");
+ 1611 148158944 : asm volatile ("pxor %xmm4,%xmm6");
1612 :
- 1613 148140512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 1613 148158944 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
1614 :
- 1615 148140512 : asm volatile ("pxor %xmm4,%xmm5");
- 1616 148140512 : asm volatile ("pxor %xmm4,%xmm6");
- 1617 148140512 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0]));
- 1618 148140512 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16]));
+ 1615 148158944 : asm volatile ("pxor %xmm4,%xmm5");
+ 1616 148158944 : asm volatile ("pxor %xmm4,%xmm6");
+ 1617 148158944 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0]));
+ 1618 148158944 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16]));
1619 :
- 1620 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 1621 148140512 : asm volatile ("movdqa %xmm4,%xmm5");
- 1622 148140512 : asm volatile ("psrlw $4,%xmm5");
- 1623 148140512 : asm volatile ("pand %xmm7,%xmm4");
- 1624 148140512 : asm volatile ("pand %xmm7,%xmm5");
+ 1620 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 1621 148158944 : asm volatile ("movdqa %xmm4,%xmm5");
+ 1622 148158944 : asm volatile ("psrlw $4,%xmm5");
+ 1623 148158944 : asm volatile ("pand %xmm7,%xmm4");
+ 1624 148158944 : asm volatile ("pand %xmm7,%xmm5");
1625 :
- 1626 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
- 1627 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
- 1628 148140512 : asm volatile ("pshufb %xmm4,%xmm6");
- 1629 148140512 : asm volatile ("pshufb %xmm5,%xmm7");
- 1630 148140512 : asm volatile ("pxor %xmm6,%xmm0");
- 1631 148140512 : asm volatile ("pxor %xmm7,%xmm0");
+ 1626 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0]));
+ 1627 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0]));
+ 1628 148158944 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1629 148158944 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1630 148158944 : asm volatile ("pxor %xmm6,%xmm0");
+ 1631 148158944 : asm volatile ("pxor %xmm7,%xmm0");
1632 :
- 1633 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
- 1634 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
- 1635 148140512 : asm volatile ("pshufb %xmm4,%xmm6");
- 1636 148140512 : asm volatile ("pshufb %xmm5,%xmm7");
- 1637 148140512 : asm volatile ("pxor %xmm6,%xmm1");
- 1638 148140512 : asm volatile ("pxor %xmm7,%xmm1");
+ 1633 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0]));
+ 1634 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0]));
+ 1635 148158944 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1636 148158944 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1637 148158944 : asm volatile ("pxor %xmm6,%xmm1");
+ 1638 148158944 : asm volatile ("pxor %xmm7,%xmm1");
1639 :
- 1640 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
- 1641 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
- 1642 148140512 : asm volatile ("pshufb %xmm4,%xmm6");
- 1643 148140512 : asm volatile ("pshufb %xmm5,%xmm7");
- 1644 148140512 : asm volatile ("pxor %xmm6,%xmm2");
- 1645 148140512 : asm volatile ("pxor %xmm7,%xmm2");
+ 1640 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0]));
+ 1641 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0]));
+ 1642 148158944 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1643 148158944 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1644 148158944 : asm volatile ("pxor %xmm6,%xmm2");
+ 1645 148158944 : asm volatile ("pxor %xmm7,%xmm2");
1646 :
- 1647 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0]));
- 1648 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0]));
- 1649 148140512 : asm volatile ("pshufb %xmm4,%xmm6");
- 1650 148140512 : asm volatile ("pshufb %xmm5,%xmm7");
- 1651 148140512 : asm volatile ("pxor %xmm6,%xmm3");
- 1652 148140512 : asm volatile ("pxor %xmm7,%xmm3");
+ 1647 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0]));
+ 1648 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0]));
+ 1649 148158944 : asm volatile ("pshufb %xmm4,%xmm6");
+ 1650 148158944 : asm volatile ("pshufb %xmm5,%xmm7");
+ 1651 148158944 : asm volatile ("pxor %xmm6,%xmm3");
+ 1652 148158944 : asm volatile ("pxor %xmm7,%xmm3");
1653 : }
1654 :
1655 : /* first disk with all coefficients at 1 */
- 1656 35533904 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
- 1657 35533904 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
- 1658 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
+ 1656 35538512 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0]));
+ 1657 35538512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16]));
+ 1658 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
1659 :
- 1660 35533904 : asm volatile ("pxor %xmm4,%xmm4");
- 1661 35533904 : asm volatile ("pcmpgtb %xmm6,%xmm4");
- 1662 35533904 : asm volatile ("paddb %xmm6,%xmm6");
- 1663 35533904 : asm volatile ("pand %xmm7,%xmm4");
- 1664 35533904 : asm volatile ("pxor %xmm4,%xmm6");
+ 1660 35538512 : asm volatile ("pxor %xmm4,%xmm4");
+ 1661 35538512 : asm volatile ("pcmpgtb %xmm6,%xmm4");
+ 1662 35538512 : asm volatile ("paddb %xmm6,%xmm6");
+ 1663 35538512 : asm volatile ("pand %xmm7,%xmm4");
+ 1664 35538512 : asm volatile ("pxor %xmm4,%xmm6");
1665 :
- 1666 35533904 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
- 1667 35533904 : asm volatile ("pxor %xmm4,%xmm0");
- 1668 35533904 : asm volatile ("pxor %xmm4,%xmm1");
- 1669 35533904 : asm volatile ("pxor %xmm4,%xmm2");
- 1670 35533904 : asm volatile ("pxor %xmm4,%xmm3");
- 1671 35533904 : asm volatile ("pxor %xmm4,%xmm5");
- 1672 35533904 : asm volatile ("pxor %xmm4,%xmm6");
+ 1666 35538512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i]));
+ 1667 35538512 : asm volatile ("pxor %xmm4,%xmm0");
+ 1668 35538512 : asm volatile ("pxor %xmm4,%xmm1");
+ 1669 35538512 : asm volatile ("pxor %xmm4,%xmm2");
+ 1670 35538512 : asm volatile ("pxor %xmm4,%xmm3");
+ 1671 35538512 : asm volatile ("pxor %xmm4,%xmm5");
+ 1672 35538512 : asm volatile ("pxor %xmm4,%xmm6");
1673 :
- 1674 35533904 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i]));
- 1675 35533904 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i]));
- 1676 35533904 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i]));
- 1677 35533904 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i]));
- 1678 35533904 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i]));
- 1679 35533904 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i]));
+ 1674 35538512 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i]));
+ 1675 35538512 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i]));
+ 1676 35538512 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i]));
+ 1677 35538512 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i]));
+ 1678 35538512 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i]));
+ 1679 35538512 : 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 111395 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
+ 1987 111399 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
1988 : {
- 1989 111395 : uint8_t **v = (uint8_t **)vv;
+ 1989 111399 : 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 111395 : if (ip[0] == 0) {
- 2000 101506 : raid_rec1of1(id, nd, size, vv);
- 2001 212901 : return;
+ 1999 111399 : if (ip[0] == 0) {
+ 2000 101530 : raid_rec1of1(id, nd, size, vv);
+ 2001 212929 : return;
2002 : }
2003 :
2004 : /* setup the coefficients matrix */
- 2005 19778 : G = A(ip[0], id[0]);
+ 2005 19738 : G = A(ip[0], id[0]);
2006 :
2007 : /* invert it to solve the system of linear equations */
- 2008 19778 : V = inv(G);
+ 2008 19738 : V = inv(G);
2009 :
2010 : /* compute delta parity */
- 2011 9889 : raid_delta_gen(1, id, ip, nd, size, vv);
+ 2011 9869 : raid_delta_gen(1, id, ip, nd, size, vv);
2012 :
- 2013 9889 : p = v[nd + ip[0]];
- 2014 9889 : pa = v[id[0]];
+ 2013 9869 : p = v[nd + ip[0]];
+ 2014 9869 : pa = v[id[0]];
2015 :
2016 : raid_sse_begin();
2017 :
- 2018 9889 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
- 2019 9889 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
- 2020 9889 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
+ 2018 9869 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 2019 9869 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
+ 2020 9869 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
2021 :
- 2022 1552673 : for (i = 0; i < size; i += 16) {
- 2023 1542784 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i]));
- 2024 1542784 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i]));
- 2025 1542784 : asm volatile ("movdqa %xmm4,%xmm2");
- 2026 1542784 : asm volatile ("movdqa %xmm5,%xmm3");
- 2027 1542784 : asm volatile ("pxor %xmm0,%xmm1");
- 2028 1542784 : asm volatile ("movdqa %xmm1,%xmm0");
- 2029 1542784 : asm volatile ("psrlw $4,%xmm1");
- 2030 1542784 : asm volatile ("pand %xmm7,%xmm0");
- 2031 1542784 : asm volatile ("pand %xmm7,%xmm1");
- 2032 1542784 : asm volatile ("pshufb %xmm0,%xmm2");
- 2033 1542784 : asm volatile ("pshufb %xmm1,%xmm3");
- 2034 1542784 : asm volatile ("pxor %xmm3,%xmm2");
- 2035 1542784 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i]));
+ 2022 1551373 : for (i = 0; i < size; i += 16) {
+ 2023 1541504 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i]));
+ 2024 1541504 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i]));
+ 2025 1541504 : asm volatile ("movdqa %xmm4,%xmm2");
+ 2026 1541504 : asm volatile ("movdqa %xmm5,%xmm3");
+ 2027 1541504 : asm volatile ("pxor %xmm0,%xmm1");
+ 2028 1541504 : asm volatile ("movdqa %xmm1,%xmm0");
+ 2029 1541504 : asm volatile ("psrlw $4,%xmm1");
+ 2030 1541504 : asm volatile ("pand %xmm7,%xmm0");
+ 2031 1541504 : asm volatile ("pand %xmm7,%xmm1");
+ 2032 1541504 : asm volatile ("pshufb %xmm0,%xmm2");
+ 2033 1541504 : asm volatile ("pshufb %xmm1,%xmm3");
+ 2034 1541504 : asm volatile ("pxor %xmm3,%xmm2");
+ 2035 1541504 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i]));
2036 : }
2037 :
2038 : raid_sse_end();
@@ -2105,106 +2105,106 @@
2043 : /*
2044 : * RAID recovering for two disks SSSE3 implementation
2045 : */
- 2046 44038 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
+ 2046 44157 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
2047 : {
- 2048 44038 : uint8_t **v = (uint8_t **)vv;
- 2049 44038 : const int N = 2;
- 2050 44038 : uint8_t *p[N];
- 2051 44038 : uint8_t *pa[N];
- 2052 44038 : uint8_t G[N * N];
- 2053 44038 : uint8_t V[N * N];
+ 2048 44157 : uint8_t **v = (uint8_t **)vv;
+ 2049 44157 : const int N = 2;
+ 2050 44157 : uint8_t *p[N];
+ 2051 44157 : uint8_t *pa[N];
+ 2052 44157 : uint8_t G[N * N];
+ 2053 44157 : 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 132114 : for (j = 0; j < N; ++j)
- 2061 264228 : for (k = 0; k < N; ++k)
- 2062 352304 : G[j * N + k] = A(ip[j], id[k]);
+ 2060 132471 : for (j = 0; j < N; ++j)
+ 2061 264942 : for (k = 0; k < N; ++k)
+ 2062 353256 : G[j * N + k] = A(ip[j], id[k]);
2063 :
2064 : /* invert it to solve the system of linear equations */
- 2065 44038 : raid_invert(G, V, N);
+ 2065 44157 : raid_invert(G, V, N);
2066 :
2067 : /* compute delta parity */
- 2068 44038 : raid_delta_gen(N, id, ip, nd, size, vv);
+ 2068 44157 : raid_delta_gen(N, id, ip, nd, size, vv);
2069 :
- 2070 132114 : for (j = 0; j < N; ++j) {
- 2071 88076 : p[j] = v[nd + ip[j]];
- 2072 88076 : pa[j] = v[id[j]];
+ 2070 132471 : for (j = 0; j < N; ++j) {
+ 2071 88314 : p[j] = v[nd + ip[j]];
+ 2072 88314 : pa[j] = v[id[j]];
2073 : }
2074 :
2075 : raid_sse_begin();
2076 :
- 2077 44038 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
+ 2077 44157 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
2078 :
- 2079 3588806 : for (i = 0; i < size; i += 16) {
- 2080 3544768 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i]));
- 2081 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i]));
- 2082 3544768 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i]));
- 2083 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i]));
- 2084 3544768 : asm volatile ("pxor %xmm2,%xmm0");
- 2085 3544768 : asm volatile ("pxor %xmm3,%xmm1");
+ 2079 3596541 : for (i = 0; i < size; i += 16) {
+ 2080 3552384 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i]));
+ 2081 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i]));
+ 2082 3552384 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i]));
+ 2083 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i]));
+ 2084 3552384 : asm volatile ("pxor %xmm2,%xmm0");
+ 2085 3552384 : asm volatile ("pxor %xmm3,%xmm1");
2086 :
- 2087 3544768 : asm volatile ("pxor %xmm6,%xmm6");
+ 2087 3552384 : asm volatile ("pxor %xmm6,%xmm6");
2088 :
- 2089 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0]));
- 2090 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0]));
- 2091 3544768 : asm volatile ("movdqa %xmm0,%xmm4");
- 2092 3544768 : asm volatile ("movdqa %xmm0,%xmm5");
- 2093 3544768 : asm volatile ("psrlw $4,%xmm5");
- 2094 3544768 : asm volatile ("pand %xmm7,%xmm4");
- 2095 3544768 : asm volatile ("pand %xmm7,%xmm5");
- 2096 3544768 : asm volatile ("pshufb %xmm4,%xmm2");
- 2097 3544768 : asm volatile ("pshufb %xmm5,%xmm3");
- 2098 3544768 : asm volatile ("pxor %xmm2,%xmm6");
- 2099 3544768 : asm volatile ("pxor %xmm3,%xmm6");
+ 2089 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0]));
+ 2090 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0]));
+ 2091 3552384 : asm volatile ("movdqa %xmm0,%xmm4");
+ 2092 3552384 : asm volatile ("movdqa %xmm0,%xmm5");
+ 2093 3552384 : asm volatile ("psrlw $4,%xmm5");
+ 2094 3552384 : asm volatile ("pand %xmm7,%xmm4");
+ 2095 3552384 : asm volatile ("pand %xmm7,%xmm5");
+ 2096 3552384 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2097 3552384 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2098 3552384 : asm volatile ("pxor %xmm2,%xmm6");
+ 2099 3552384 : asm volatile ("pxor %xmm3,%xmm6");
2100 :
- 2101 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0]));
- 2102 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0]));
- 2103 3544768 : asm volatile ("movdqa %xmm1,%xmm4");
- 2104 3544768 : asm volatile ("movdqa %xmm1,%xmm5");
- 2105 3544768 : asm volatile ("psrlw $4,%xmm5");
- 2106 3544768 : asm volatile ("pand %xmm7,%xmm4");
- 2107 3544768 : asm volatile ("pand %xmm7,%xmm5");
- 2108 3544768 : asm volatile ("pshufb %xmm4,%xmm2");
- 2109 3544768 : asm volatile ("pshufb %xmm5,%xmm3");
- 2110 3544768 : asm volatile ("pxor %xmm2,%xmm6");
- 2111 3544768 : asm volatile ("pxor %xmm3,%xmm6");
+ 2101 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0]));
+ 2102 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0]));
+ 2103 3552384 : asm volatile ("movdqa %xmm1,%xmm4");
+ 2104 3552384 : asm volatile ("movdqa %xmm1,%xmm5");
+ 2105 3552384 : asm volatile ("psrlw $4,%xmm5");
+ 2106 3552384 : asm volatile ("pand %xmm7,%xmm4");
+ 2107 3552384 : asm volatile ("pand %xmm7,%xmm5");
+ 2108 3552384 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2109 3552384 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2110 3552384 : asm volatile ("pxor %xmm2,%xmm6");
+ 2111 3552384 : asm volatile ("pxor %xmm3,%xmm6");
2112 :
- 2113 3544768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i]));
+ 2113 3552384 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i]));
2114 :
- 2115 3544768 : asm volatile ("pxor %xmm6,%xmm6");
+ 2115 3552384 : asm volatile ("pxor %xmm6,%xmm6");
2116 :
- 2117 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0]));
- 2118 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0]));
- 2119 3544768 : asm volatile ("movdqa %xmm0,%xmm4");
- 2120 3544768 : asm volatile ("movdqa %xmm0,%xmm5");
- 2121 3544768 : asm volatile ("psrlw $4,%xmm5");
- 2122 3544768 : asm volatile ("pand %xmm7,%xmm4");
- 2123 3544768 : asm volatile ("pand %xmm7,%xmm5");
- 2124 3544768 : asm volatile ("pshufb %xmm4,%xmm2");
- 2125 3544768 : asm volatile ("pshufb %xmm5,%xmm3");
- 2126 3544768 : asm volatile ("pxor %xmm2,%xmm6");
- 2127 3544768 : asm volatile ("pxor %xmm3,%xmm6");
+ 2117 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0]));
+ 2118 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0]));
+ 2119 3552384 : asm volatile ("movdqa %xmm0,%xmm4");
+ 2120 3552384 : asm volatile ("movdqa %xmm0,%xmm5");
+ 2121 3552384 : asm volatile ("psrlw $4,%xmm5");
+ 2122 3552384 : asm volatile ("pand %xmm7,%xmm4");
+ 2123 3552384 : asm volatile ("pand %xmm7,%xmm5");
+ 2124 3552384 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2125 3552384 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2126 3552384 : asm volatile ("pxor %xmm2,%xmm6");
+ 2127 3552384 : asm volatile ("pxor %xmm3,%xmm6");
2128 :
- 2129 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0]));
- 2130 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0]));
- 2131 3544768 : asm volatile ("movdqa %xmm1,%xmm4");
- 2132 3544768 : asm volatile ("movdqa %xmm1,%xmm5");
- 2133 3544768 : asm volatile ("psrlw $4,%xmm5");
- 2134 3544768 : asm volatile ("pand %xmm7,%xmm4");
- 2135 3544768 : asm volatile ("pand %xmm7,%xmm5");
- 2136 3544768 : asm volatile ("pshufb %xmm4,%xmm2");
- 2137 3544768 : asm volatile ("pshufb %xmm5,%xmm3");
- 2138 3544768 : asm volatile ("pxor %xmm2,%xmm6");
- 2139 3544768 : asm volatile ("pxor %xmm3,%xmm6");
+ 2129 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0]));
+ 2130 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0]));
+ 2131 3552384 : asm volatile ("movdqa %xmm1,%xmm4");
+ 2132 3552384 : asm volatile ("movdqa %xmm1,%xmm5");
+ 2133 3552384 : asm volatile ("psrlw $4,%xmm5");
+ 2134 3552384 : asm volatile ("pand %xmm7,%xmm4");
+ 2135 3552384 : asm volatile ("pand %xmm7,%xmm5");
+ 2136 3552384 : asm volatile ("pshufb %xmm4,%xmm2");
+ 2137 3552384 : asm volatile ("pshufb %xmm5,%xmm3");
+ 2138 3552384 : asm volatile ("pxor %xmm2,%xmm6");
+ 2139 3552384 : asm volatile ("pxor %xmm3,%xmm6");
2140 :
- 2141 3544768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i]));
+ 2141 3552384 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i]));
2142 : }
2143 :
2144 : raid_sse_end();
- 2145 44038 : }
+ 2145 44157 : }
2146 : #endif
2147 :
2148 : #if defined(CONFIG_X86) && defined(CONFIG_SSSE3)
diff --git a/cov/raid/x86z.c.func-sort-c.html b/cov/raid/x86z.c.func-sort-c.html
index 4b3634ae..f1021661 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 |
- 1176 |
+ 1180 |
diff --git a/cov/raid/x86z.c.func.html b/cov/raid/x86z.c.func.html
index b6fdb7c1..a4138197 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 |
- 1176 |
+ 1180 |
diff --git a/cov/raid/x86z.c.gcov.html b/cov/raid/x86z.c.gcov.html
index 6a1f08a2..c32bcabf 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 1176 : void raid_genz_sse2(int nd, size_t size, void **vv)
+ 43 1180 : void raid_genz_sse2(int nd, size_t size, void **vv)
44 : {
- 45 1176 : uint8_t **v = (uint8_t**)vv;
+ 45 1180 : 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 1176 : l = nd - 1;
- 53 1176 : p = v[nd];
- 54 1176 : q = v[nd + 1];
- 55 1176 : r = v[nd + 2];
+ 52 1180 : l = nd - 1;
+ 53 1180 : p = v[nd];
+ 54 1180 : q = v[nd + 1];
+ 55 1180 : r = v[nd + 2];
56 :
57 : raid_sse_begin();
58 :
- 59 1176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0]));
- 60 1176 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0]));
- 61 1176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0]));
+ 59 1180 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0]));
+ 60 1180 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0]));
+ 61 1180 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0]));
62 :
- 63 1378536 : for (i = 0; i < size; i += 16) {
- 64 1377360 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
- 65 1377360 : asm volatile ("movdqa %xmm0,%xmm1");
- 66 1377360 : asm volatile ("movdqa %xmm0,%xmm2");
- 67 11089152 : for (d = l - 1; d >= 0; --d) {
- 68 9711792 : asm volatile ("pxor %xmm4,%xmm4");
- 69 9711792 : asm volatile ("pcmpgtb %xmm1,%xmm4");
- 70 9711792 : asm volatile ("paddb %xmm1,%xmm1");
- 71 9711792 : asm volatile ("pand %xmm7,%xmm4");
- 72 9711792 : asm volatile ("pxor %xmm4,%xmm1");
+ 63 1444076 : for (i = 0; i < size; i += 16) {
+ 64 1442896 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i]));
+ 65 1442896 : asm volatile ("movdqa %xmm0,%xmm1");
+ 66 1442896 : asm volatile ("movdqa %xmm0,%xmm2");
+ 67 11613440 : for (d = l - 1; d >= 0; --d) {
+ 68 10170544 : asm volatile ("pxor %xmm4,%xmm4");
+ 69 10170544 : asm volatile ("pcmpgtb %xmm1,%xmm4");
+ 70 10170544 : asm volatile ("paddb %xmm1,%xmm1");
+ 71 10170544 : asm volatile ("pand %xmm7,%xmm4");
+ 72 10170544 : asm volatile ("pxor %xmm4,%xmm1");
73 :
- 74 9711792 : asm volatile ("movdqa %xmm2,%xmm4");
- 75 9711792 : asm volatile ("pxor %xmm5,%xmm5");
- 76 9711792 : asm volatile ("psllw $7,%xmm4");
- 77 9711792 : asm volatile ("psrlw $1,%xmm2");
- 78 9711792 : asm volatile ("pcmpgtb %xmm4,%xmm5");
- 79 9711792 : asm volatile ("pand %xmm6,%xmm2");
- 80 9711792 : asm volatile ("pand %xmm3,%xmm5");
- 81 9711792 : asm volatile ("pxor %xmm5,%xmm2");
+ 74 10170544 : asm volatile ("movdqa %xmm2,%xmm4");
+ 75 10170544 : asm volatile ("pxor %xmm5,%xmm5");
+ 76 10170544 : asm volatile ("psllw $7,%xmm4");
+ 77 10170544 : asm volatile ("psrlw $1,%xmm2");
+ 78 10170544 : asm volatile ("pcmpgtb %xmm4,%xmm5");
+ 79 10170544 : asm volatile ("pand %xmm6,%xmm2");
+ 80 10170544 : asm volatile ("pand %xmm3,%xmm5");
+ 81 10170544 : asm volatile ("pxor %xmm5,%xmm2");
82 :
- 83 9711792 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
- 84 9711792 : asm volatile ("pxor %xmm4,%xmm0");
- 85 9711792 : asm volatile ("pxor %xmm4,%xmm1");
- 86 9711792 : asm volatile ("pxor %xmm4,%xmm2");
+ 83 10170544 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i]));
+ 84 10170544 : asm volatile ("pxor %xmm4,%xmm0");
+ 85 10170544 : asm volatile ("pxor %xmm4,%xmm1");
+ 86 10170544 : asm volatile ("pxor %xmm4,%xmm2");
87 : }
- 88 1377360 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
- 89 1377360 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
- 90 1377360 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
+ 88 1442896 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i]));
+ 89 1442896 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i]));
+ 90 1442896 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i]));
91 : }
92 :
93 : raid_sse_end();
- 94 1176 : }
+ 94 1180 : }
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 1aac10bb..c57172c1 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 85809ff9..c06f93f9 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 ad75eb65..7aa8cb14 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 5a3f8371..f0719a77 100644
--- a/cov/tommyds/tommyarray.c.func-sort-c.html
+++ b/cov/tommyds/tommyarray.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarray.c.func.html b/cov/tommyds/tommyarray.c.func.html
index 945e89e6..dce97b64 100644
--- a/cov/tommyds/tommyarray.c.func.html
+++ b/cov/tommyds/tommyarray.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarray.c.gcov.html b/cov/tommyds/tommyarray.c.gcov.html
index 19d8f82f..965bc4aa 100644
--- a/cov/tommyds/tommyarray.c.gcov.html
+++ b/cov/tommyds/tommyarray.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommyarray.h.func-sort-c.html b/cov/tommyds/tommyarray.h.func-sort-c.html
index 1969ed9c..5a7f3eba 100644
--- a/cov/tommyds/tommyarray.h.func-sort-c.html
+++ b/cov/tommyds/tommyarray.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_array_ref |
- 10268668 |
+ 10268805 |
| tommy_array_get |
- 10266454 |
+ 10266591 |
| tommy_array_size |
diff --git a/cov/tommyds/tommyarray.h.func.html b/cov/tommyds/tommyarray.h.func.html
index 4b216f81..fdcaddab 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 |
- 10266454 |
+ 10266591 |
| tommy_array_insert |
@@ -69,7 +69,7 @@
| tommy_array_ref |
- 10268668 |
+ 10268805 |
| tommy_array_set |
diff --git a/cov/tommyds/tommyarray.h.gcov.html b/cov/tommyds/tommyarray.h.gcov.html
index 41939361..200e23cc 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 10268668 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
+ 93 10268805 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
94 : {
95 : tommy_uint_t bsr;
96 :
- 97 10268668 : assert(pos < array->count);
+ 97 10268805 : assert(pos < array->count);
98 :
99 : /* get the highest bit set, in case of all 0, return 0 */
- 100 10268668 : bsr = tommy_ilog2_u32(pos | 1);
+ 100 10268805 : bsr = tommy_ilog2_u32(pos | 1);
101 :
- 102 10268668 : return &array->bucket[bsr][pos];
+ 102 10268805 : return &array->bucket[bsr][pos];
103 : }
104 :
105 : /**
@@ -179,9 +179,9 @@
117 : * You must be sure that space for this position is already
118 : * allocated calling tommy_array_grow().
119 : */
- 120 10266454 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
+ 120 10266591 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
121 : {
- 122 10266454 : return *tommy_array_ref(array, pos);
+ 122 10266591 : return *tommy_array_ref(array, pos);
123 : }
124 :
125 : /**
diff --git a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
index ca7ec51f..12188e51 100644
--- a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
+++ b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| tommy_arrayblkof_grow |
- 1698377 |
+ 1698452 |
| tommy_arrayblkof_init |
diff --git a/cov/tommyds/tommyarrayblkof.c.func.html b/cov/tommyds/tommyarrayblkof.c.func.html
index a2043ce2..11789fbc 100644
--- a/cov/tommyds/tommyarrayblkof.c.func.html
+++ b/cov/tommyds/tommyarrayblkof.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -65,7 +65,7 @@
| tommy_arrayblkof_grow |
- 1698377 |
+ 1698452 |
| tommy_arrayblkof_init |
diff --git a/cov/tommyds/tommyarrayblkof.c.gcov.html b/cov/tommyds/tommyarrayblkof.c.gcov.html
index 7c6784d6..52aae83d 100644
--- a/cov/tommyds/tommyarrayblkof.c.gcov.html
+++ b/cov/tommyds/tommyarrayblkof.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -110,13 +110,13 @@
48 245 : tommy_array_done(&array->block);
49 245 : }
50 :
- 51 1698377 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count)
+ 51 1698452 : 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 1698377 : if (array->count >= count)
- 57 1821747 : return;
+ 56 1698452 : if (array->count >= count)
+ 57 1821897 : return;
58 1575007 : array->count = count;
59 :
60 1575007 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE;
diff --git a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html
index f0445720..0d9c497b 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 |
- 6534659 |
+ 6534796 |
| tommy_arrayblkof_size |
- 5098669 |
+ 5098731 |
diff --git a/cov/tommyds/tommyarrayblkof.h.func.html b/cov/tommyds/tommyarrayblkof.h.func.html
index 63d16647..ba44229b 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 |
- 6534659 |
+ 6534796 |
| tommy_arrayblkof_size |
- 5098669 |
+ 5098731 |
diff --git a/cov/tommyds/tommyarrayblkof.h.gcov.html b/cov/tommyds/tommyarrayblkof.h.gcov.html
index 93bf2682..3349dc0c 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 6534659 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
+ 89 6534796 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
90 : {
91 : unsigned char* base;
92 :
- 93 6534659 : assert(pos < array->count);
+ 93 6534796 : assert(pos < array->count);
94 :
- 95 6534659 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE));
+ 95 6534796 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE));
96 :
- 97 6534659 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size;
+ 97 6534796 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size;
98 : }
99 :
100 : /**
101 : * Gets the initialized size of the array.
102 : */
- 103 5098669 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
+ 103 5098731 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
104 : {
- 105 5098669 : return array->count;
+ 105 5098731 : 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 e2cfdd86..ecb8e710 100644
--- a/cov/tommyds/tommychain.h.func-sort-c.html
+++ b/cov/tommyds/tommychain.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| tommy_chain_splice |
- 4491318 |
+ 4493802 |
| tommy_chain_merge_degenerated |
- 1283280 |
+ 1283278 |
| tommy_chain_concat |
- 1276623 |
+ 1276615 |
| tommy_chain_merge |
- 470639 |
+ 471147 |
| tommy_chain_mergesort |
diff --git a/cov/tommyds/tommychain.h.func.html b/cov/tommyds/tommychain.h.func.html
index 094728af..c92eb3c5 100644
--- a/cov/tommyds/tommychain.h.func.html
+++ b/cov/tommyds/tommychain.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,15 +61,15 @@
| tommy_chain_concat |
- 1276623 |
+ 1276615 |
| tommy_chain_merge |
- 470639 |
+ 471147 |
| tommy_chain_merge_degenerated |
- 1283280 |
+ 1283278 |
| tommy_chain_mergesort |
@@ -77,7 +77,7 @@
| tommy_chain_splice |
- 4491318 |
+ 4493802 |
diff --git a/cov/tommyds/tommychain.h.gcov.html b/cov/tommyds/tommychain.h.gcov.html
index 0438c98f..a9b05b5c 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 4491318 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail)
+ 60 4493802 : 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 4491318 : first_after->prev = second_tail;
- 64 4491318 : second_head->prev = first_before;
+ 63 4493802 : first_after->prev = second_tail;
+ 64 4493802 : second_head->prev = first_before;
65 :
66 : /* set the next list */
- 67 4491318 : first_before->next = second_head;
- 68 4491318 : second_tail->next = first_after;
- 69 4491318 : }
+ 67 4493802 : first_before->next = second_head;
+ 68 4493802 : second_tail->next = first_after;
+ 69 4493802 : }
70 :
71 : /**
72 : * Concats two chains.
73 : */
- 74 1276623 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head)
+ 74 1276615 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head)
75 : {
76 : /* set the prev list */
- 77 1276623 : second_head->prev = first_tail;
+ 77 1276615 : second_head->prev = first_tail;
78 :
79 : /* set the next list */
- 80 1276623 : first_tail->next = second_head;
- 81 1276623 : }
+ 80 1276615 : first_tail->next = second_head;
+ 81 1276615 : }
82 :
83 : /**
84 : * Merges two chains.
85 : */
- 86 470639 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
+ 86 471147 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
87 : {
- 88 470639 : tommy_node* first_i = first->head;
- 89 470639 : tommy_node* second_i = second->head;
+ 88 471147 : tommy_node* first_i = first->head;
+ 89 471147 : tommy_node* second_i = second->head;
90 :
91 : /* merge */
92 : while (1) {
- 93 9777914 : if (cmp(first_i->data, second_i->data) > 0) {
- 94 4723551 : tommy_node* next = second_i->next;
- 95 4723551 : if (first_i == first->head) {
- 96 232233 : tommy_chain_concat(second_i, first_i);
- 97 232233 : first->head = second_i;
+ 93 9786940 : if (cmp(first_i->data, second_i->data) > 0) {
+ 94 4726143 : tommy_node* next = second_i->next;
+ 95 4726143 : if (first_i == first->head) {
+ 96 232341 : tommy_chain_concat(second_i, first_i);
+ 97 232341 : first->head = second_i;
98 : } else {
- 99 4491318 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i);
+ 99 4493802 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i);
100 : }
- 101 4723551 : if (second_i == second->tail)
- 102 238890 : break;
- 103 4484661 : second_i = next;
+ 101 4726143 : if (second_i == second->tail)
+ 102 239004 : break;
+ 103 4487139 : second_i = next;
104 : } else {
- 105 5054363 : if (first_i == first->tail) {
- 106 231749 : tommy_chain_concat(first_i, second_i);
- 107 231749 : first->tail = second->tail;
- 108 231749 : break;
+ 105 5060797 : if (first_i == first->tail) {
+ 106 232143 : tommy_chain_concat(first_i, second_i);
+ 107 232143 : first->tail = second->tail;
+ 108 232143 : break;
109 : }
- 110 4822614 : first_i = first_i->next;
+ 110 4828654 : first_i = first_i->next;
111 : }
- 112 9307275 : }
- 113 470639 : }
+ 112 9315793 : }
+ 113 471147 : }
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 1283280 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp)
+ 119 1283278 : 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 1283280 : if (cmp(first->tail->data, second->head->data) <= 0) {
- 123 477942 : tommy_chain_concat(first->tail, second->head);
- 124 477942 : first->tail = second->tail;
- 125 477942 : return;
+ 122 1283278 : if (cmp(first->tail->data, second->head->data) <= 0) {
+ 123 477266 : tommy_chain_concat(first->tail, second->head);
+ 124 477266 : first->tail = second->tail;
+ 125 477266 : return;
126 : }
127 :
128 : /* identify the condition second < first */
129 : /* here we must be strict on comparison to keep the sort stable */
- 130 805338 : if (cmp(second->tail->data, first->head->data) < 0) {
- 131 334699 : tommy_chain_concat(second->tail, first->head);
- 132 334699 : first->head = second->head;
- 133 334699 : return;
+ 130 806012 : if (cmp(second->tail->data, first->head->data) < 0) {
+ 131 334865 : tommy_chain_concat(second->tail, first->head);
+ 132 334865 : first->head = second->head;
+ 133 334865 : return;
134 : }
135 :
- 136 470639 : tommy_chain_merge(first, second, cmp);
+ 136 471147 : tommy_chain_merge(first, second, cmp);
137 : }
138 :
139 : /**
@@ -241,42 +241,42 @@
179 : tommy_chain* last;
180 :
181 : /* carry bit to add */
- 182 1284973 : last = &bit[TOMMY_CHAIN_BIT_MAX];
- 183 1284973 : bit[TOMMY_CHAIN_BIT_MAX].head = node;
- 184 1284973 : bit[TOMMY_CHAIN_BIT_MAX].tail = node;
- 185 1284973 : next = node->next;
+ 182 1284971 : last = &bit[TOMMY_CHAIN_BIT_MAX];
+ 183 1284971 : bit[TOMMY_CHAIN_BIT_MAX].head = node;
+ 184 1284971 : bit[TOMMY_CHAIN_BIT_MAX].tail = node;
+ 185 1284971 : next = node->next;
186 :
187 : /* add the bit, propagating the carry */
- 188 1284973 : i = 0;
- 189 1284973 : mask = counter;
- 190 3847173 : while ((mask & 1) != 0) {
- 191 1277227 : tommy_chain_merge_degenerated(&bit[i], last, cmp);
- 192 1277227 : mask >>= 1;
- 193 1277227 : last = &bit[i];
- 194 1277227 : ++i;
+ 188 1284971 : i = 0;
+ 189 1284971 : mask = counter;
+ 190 3847168 : while ((mask & 1) != 0) {
+ 191 1277226 : tommy_chain_merge_degenerated(&bit[i], last, cmp);
+ 192 1277226 : mask >>= 1;
+ 193 1277226 : last = &bit[i];
+ 194 1277226 : ++i;
195 : }
196 :
197 : /* copy the carry in the first empty bit */
- 198 1284973 : bit[i] = *last;
+ 198 1284971 : bit[i] = *last;
199 :
200 : /* add the carry in the counter */
- 201 1284973 : ++counter;
+ 201 1284971 : ++counter;
202 :
- 203 1284973 : if (node == tail)
+ 203 1284971 : if (node == tail)
204 1693 : break;
- 205 1283280 : node = next;
- 206 1283280 : }
+ 205 1283278 : node = next;
+ 206 1283278 : }
207 :
208 : /* merge the buckets */
209 1693 : i = tommy_ctz_u32(counter);
210 1693 : mask = counter >> i;
- 211 12416 : while (mask != 1) {
- 212 9030 : mask >>= 1;
- 213 9030 : if (mask & 1)
- 214 6053 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp);
+ 211 12415 : while (mask != 1) {
+ 212 9029 : mask >>= 1;
+ 213 9029 : if (mask & 1)
+ 214 6052 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp);
215 : else
216 2977 : bit[i + 1] = bit[i];
- 217 9030 : ++i;
+ 217 9029 : ++i;
218 : }
219 :
220 1693 : *chain = bit[i];
diff --git a/cov/tommyds/tommyhash.c.func-sort-c.html b/cov/tommyds/tommyhash.c.func-sort-c.html
index df6507f4..1b2f6d83 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 |
- 11588009 |
+ 11604375 |
| tommy_hash_u32 |
- 4059942 |
+ 4065657 |
| tommy_strhash_u32 |
diff --git a/cov/tommyds/tommyhash.c.func.html b/cov/tommyds/tommyhash.c.func.html
index 54128f24..a8f382e5 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 |
- 4059942 |
+ 4065657 |
| tommy_hash_u64 |
@@ -69,7 +69,7 @@
| tommy_le_uint32_read |
- 11588009 |
+ 11604375 |
| tommy_strhash_u32 |
diff --git a/cov/tommyds/tommyhash.c.gcov.html b/cov/tommyds/tommyhash.c.gcov.html
index 68119537..16bf6da2 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 11588009 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr)
+ 33 11604375 : 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 11588009 : return *(const tommy_uint32_t*)ptr;
+ 38 11604375 : 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 4059942 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len)
+ 69 4065657 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len)
70 : {
- 71 4059942 : const unsigned char* key = tommy_cast(const unsigned char*, void_key);
+ 71 4065657 : const unsigned char* key = tommy_cast(const unsigned char*, void_key);
72 : tommy_uint32_t a, b, c;
73 :
- 74 4059942 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val;
+ 74 4065657 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val;
75 :
- 76 10240213 : while (key_len > 12) {
- 77 2120329 : a += tommy_le_uint32_read(key + 0);
- 78 2120329 : b += tommy_le_uint32_read(key + 4);
- 79 2120329 : c += tommy_le_uint32_read(key + 8);
+ 76 10254604 : while (key_len > 12) {
+ 77 2123290 : a += tommy_le_uint32_read(key + 0);
+ 78 2123290 : b += tommy_le_uint32_read(key + 4);
+ 79 2123290 : c += tommy_le_uint32_read(key + 8);
80 :
- 81 2120329 : tommy_mix(a, b, c);
+ 81 2123290 : tommy_mix(a, b, c);
82 :
- 83 2120329 : key_len -= 12;
- 84 2120329 : key += 12;
+ 83 2123290 : key_len -= 12;
+ 84 2123290 : key += 12;
85 : }
86 :
- 87 4059942 : switch (key_len) {
+ 87 4065657 : switch (key_len) {
88 : case 0 :
89 1 : return c; /* used only when called with a zero length */
90 : case 12 :
- 91 207744 : c += tommy_le_uint32_read(key + 8);
- 92 207744 : b += tommy_le_uint32_read(key + 4);
- 93 207744 : a += tommy_le_uint32_read(key + 0);
- 94 207744 : break;
- 95 217371 : case 11 : c += ((tommy_uint32_t)key[10]) << 16;
- 96 640231 : case 10 : c += ((tommy_uint32_t)key[9]) << 8;
- 97 1059969 : case 9 : c += key[8];
+ 91 208009 : c += tommy_le_uint32_read(key + 8);
+ 92 208009 : b += tommy_le_uint32_read(key + 4);
+ 93 208009 : a += tommy_le_uint32_read(key + 0);
+ 94 208009 : break;
+ 95 217656 : case 11 : c += ((tommy_uint32_t)key[10]) << 16;
+ 96 641102 : case 10 : c += ((tommy_uint32_t)key[9]) << 8;
+ 97 1061522 : case 9 : c += key[8];
98 : case 8 :
- 99 1470946 : b += tommy_le_uint32_read(key + 4);
- 100 1470946 : a += tommy_le_uint32_read(key + 0);
- 101 1470946 : break;
- 102 413133 : case 7 : b += ((tommy_uint32_t)key[6]) << 16;
- 103 812960 : case 6 : b += ((tommy_uint32_t)key[5]) << 8;
- 104 1229671 : case 5 : b += key[4];
+ 99 1473120 : b += tommy_le_uint32_read(key + 4);
+ 100 1473120 : a += tommy_le_uint32_read(key + 0);
+ 101 1473120 : break;
+ 102 413650 : case 7 : b += ((tommy_uint32_t)key[6]) << 16;
+ 103 814028 : case 6 : b += ((tommy_uint32_t)key[5]) << 8;
+ 104 1231376 : case 5 : b += key[4];
105 : case 4 :
- 106 1661764 : a += tommy_le_uint32_read(key + 0);
- 107 1661764 : break;
- 108 301721 : case 3 : a += ((tommy_uint32_t)key[2]) << 16;
- 109 509505 : case 2 : a += ((tommy_uint32_t)key[1]) << 8;
- 110 719487 : case 1 : a += key[0];
+ 106 1664104 : a += tommy_le_uint32_read(key + 0);
+ 107 1664104 : break;
+ 108 302114 : case 3 : a += ((tommy_uint32_t)key[2]) << 16;
+ 109 510191 : case 2 : a += ((tommy_uint32_t)key[1]) << 8;
+ 110 720423 : case 1 : a += key[0];
111 : }
112 :
- 113 4059941 : tommy_final(a, b, c);
+ 113 4065656 : tommy_final(a, b, c);
114 :
- 115 4059941 : return c;
+ 115 4065656 : 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 e16f4c74..16d6d836 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 |
- 18826263 |
+ 18826860 |
| tommy_inthash_u64 |
- 5042449 |
+ 5055357 |
diff --git a/cov/tommyds/tommyhash.h.func.html b/cov/tommyds/tommyhash.h.func.html
index c3f3a49c..efa2bd47 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 |
- 18826263 |
+ 18826860 |
| tommy_inthash_u64 |
- 5042449 |
+ 5055357 |
diff --git a/cov/tommyds/tommyhash.h.gcov.html b/cov/tommyds/tommyhash.h.gcov.html
index 86c2762a..6ea87a53 100644
--- a/cov/tommyds/tommyhash.h.gcov.html
+++ b/cov/tommyds/tommyhash.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -167,17 +167,17 @@
105 : * Implementation of the Robert Jenkins "4-byte Integer Hashing",
106 : * from http://burtleburtle.net/bob/hash/integer.html
107 : */
- 108 18826263 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key)
+ 108 18826860 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key)
109 : {
- 110 18826263 : key -= key << 6;
- 111 18826263 : key ^= key >> 17;
- 112 18826263 : key -= key << 9;
- 113 18826263 : key ^= key << 4;
- 114 18826263 : key -= key << 3;
- 115 18826263 : key ^= key << 10;
- 116 18826263 : key ^= key >> 15;
+ 110 18826860 : key -= key << 6;
+ 111 18826860 : key ^= key >> 17;
+ 112 18826860 : key -= key << 9;
+ 113 18826860 : key ^= key << 4;
+ 114 18826860 : key -= key << 3;
+ 115 18826860 : key ^= key << 10;
+ 116 18826860 : key ^= key >> 15;
117 :
- 118 18826263 : return key;
+ 118 18826860 : return key;
119 : }
120 :
121 : /**
@@ -185,17 +185,17 @@
123 : * Implementation of the Thomas Wang "Integer Hash Function",
124 : * from http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm
125 : */
- 126 5042449 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key)
+ 126 5055357 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key)
127 : {
- 128 5042449 : key = ~key + (key << 21);
- 129 5042449 : key = key ^ (key >> 24);
- 130 5042449 : key = key + (key << 3) + (key << 8);
- 131 5042449 : key = key ^ (key >> 14);
- 132 5042449 : key = key + (key << 2) + (key << 4);
- 133 5042449 : key = key ^ (key >> 28);
- 134 5042449 : key = key + (key << 31);
+ 128 5055357 : key = ~key + (key << 21);
+ 129 5055357 : key = key ^ (key >> 24);
+ 130 5055357 : key = key + (key << 3) + (key << 8);
+ 131 5055357 : key = key ^ (key >> 14);
+ 132 5055357 : key = key + (key << 2) + (key << 4);
+ 133 5055357 : key = key ^ (key >> 28);
+ 134 5055357 : key = key + (key << 31);
135 :
- 136 5042449 : return key;
+ 136 5055357 : return key;
137 : }
138 :
139 : #endif
diff --git a/cov/tommyds/tommyhashdyn.c.func-sort-c.html b/cov/tommyds/tommyhashdyn.c.func-sort-c.html
index 9c360eb3..24828b7c 100644
--- a/cov/tommyds/tommyhashdyn.c.func-sort-c.html
+++ b/cov/tommyds/tommyhashdyn.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,19 +61,19 @@
| hashdyn_grow_step |
- 13231522 |
+ 13244128 |
| tommy_hashdyn_insert |
- 13231522 |
+ 13244128 |
| hashdyn_shrink_step |
- 276876 |
+ 289723 |
| tommy_hashdyn_remove_existing |
- 276748 |
+ 289595 |
| tommy_hashdyn_resize |
diff --git a/cov/tommyds/tommyhashdyn.c.func.html b/cov/tommyds/tommyhashdyn.c.func.html
index f2525885..93a5b706 100644
--- a/cov/tommyds/tommyhashdyn.c.func.html
+++ b/cov/tommyds/tommyhashdyn.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| hashdyn_grow_step |
- 13231522 |
+ 13244128 |
| hashdyn_shrink_step |
- 276876 |
+ 289723 |
| tommy_hashdyn_done |
@@ -85,7 +85,7 @@
| tommy_hashdyn_insert |
- 13231522 |
+ 13244128 |
| tommy_hashdyn_memory_usage |
@@ -97,7 +97,7 @@
| tommy_hashdyn_remove_existing |
- 276748 |
+ 289595 |
| tommy_hashdyn_resize |
diff --git a/cov/tommyds/tommyhashdyn.c.gcov.html b/cov/tommyds/tommyhashdyn.c.gcov.html
index f6e08f05..c2738e4a 100644
--- a/cov/tommyds/tommyhashdyn.c.gcov.html
+++ b/cov/tommyds/tommyhashdyn.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -148,9 +148,9 @@
86 16077016 : tommy_hashdyn_node* j_next = j->next;
87 16077016 : tommy_count_t pos = j->key & new_bucket_mask;
88 16077016 : if (new_bucket[pos])
- 89 1915511 : tommy_list_insert_tail_not_empty(new_bucket[pos], j);
+ 89 1895759 : tommy_list_insert_tail_not_empty(new_bucket[pos], j);
90 : else
- 91 14161505 : tommy_list_insert_first(&new_bucket[pos], j);
+ 91 14181257 : tommy_list_insert_first(&new_bucket[pos], j);
92 16077016 : j = j_next;
93 : }
94 : }
@@ -179,47 +179,47 @@
117 : /**
118 : * Grow.
119 : */
- 120 13231522 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn)
+ 120 13244128 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn)
121 : {
122 : /* grow if more than 50% full */
- 123 13231522 : if (hashdyn->count >= hashdyn->bucket_max / 2)
+ 123 13244128 : if (hashdyn->count >= hashdyn->bucket_max / 2)
124 41474 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1);
- 125 13231522 : }
+ 125 13244128 : }
126 :
127 : /**
128 : * Shrink.
129 : */
- 130 276876 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
+ 130 289723 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
131 : {
132 : /* shrink if less than 12.5% full */
- 133 276876 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT)
+ 133 289723 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT)
134 49 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1);
- 135 276876 : }
+ 135 289723 : }
136 :
- 137 13231522 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
+ 137 13244128 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
138 : {
- 139 13231522 : tommy_count_t pos = hash & hashdyn->bucket_mask;
+ 139 13244128 : tommy_count_t pos = hash & hashdyn->bucket_mask;
140 :
- 141 13231522 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
+ 141 13244128 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
142 :
- 143 13231522 : node->key = hash;
+ 143 13244128 : node->key = hash;
144 :
- 145 13231522 : ++hashdyn->count;
+ 145 13244128 : ++hashdyn->count;
146 :
- 147 13231522 : hashdyn_grow_step(hashdyn);
- 148 13231522 : }
+ 147 13244128 : hashdyn_grow_step(hashdyn);
+ 148 13244128 : }
149 :
- 150 276748 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
+ 150 289595 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
151 : {
- 152 276748 : tommy_count_t pos = node->key & hashdyn->bucket_mask;
+ 152 289595 : tommy_count_t pos = node->key & hashdyn->bucket_mask;
153 :
- 154 276748 : tommy_list_remove_existing(&hashdyn->bucket[pos], node);
+ 154 289595 : tommy_list_remove_existing(&hashdyn->bucket[pos], node);
155 :
- 156 276748 : --hashdyn->count;
+ 156 289595 : --hashdyn->count;
157 :
- 158 276748 : hashdyn_shrink_step(hashdyn);
+ 158 289595 : hashdyn_shrink_step(hashdyn);
159 :
- 160 276748 : return node->data;
+ 160 289595 : 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)
@@ -253,10 +253,10 @@
191 5812552 : for (pos = 0; pos < bucket_max; ++pos) {
192 5812304 : tommy_hashdyn_node* node = bucket[pos];
193 :
- 194 13485790 : while (node) {
- 195 1861182 : void* data = node->data;
- 196 1861182 : node = node->next;
- 197 1861182 : func(data);
+ 194 13485549 : while (node) {
+ 195 1860941 : void* data = node->data;
+ 196 1860941 : node = node->next;
+ 197 1860941 : func(data);
198 : }
199 : }
200 248 : }
diff --git a/cov/tommyds/tommyhashdyn.h.func-sort-c.html b/cov/tommyds/tommyhashdyn.h.func-sort-c.html
index 6937e5cf..a26eea91 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 |
- 3108747 |
+ 3115397 |
| tommy_hashdyn_search |
- 3108747 |
+ 3115397 |
| tommy_hashdyn_count |
diff --git a/cov/tommyds/tommyhashdyn.h.func.html b/cov/tommyds/tommyhashdyn.h.func.html
index 60527ed5..c815da55 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 |
- 3108747 |
+ 3115397 |
| tommy_hashdyn_count |
@@ -69,7 +69,7 @@
| tommy_hashdyn_search |
- 3108747 |
+ 3115397 |
diff --git a/cov/tommyds/tommyhashdyn.h.gcov.html b/cov/tommyds/tommyhashdyn.h.gcov.html
index b5142826..9fc9fbf8 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 3108747 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash)
+ 208 3115397 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash)
209 : {
- 210 3108747 : return hashdyn->bucket[hash & hashdyn->bucket_mask];
+ 210 3115397 : 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 3108747 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
+ 223 3115397 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
224 : {
- 225 3108747 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash);
+ 225 3115397 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash);
226 :
- 227 6892825 : while (i) {
+ 227 6906900 : while (i) {
228 : /* we first check if the hash matches, as in the same bucket we may have multiples hash values */
- 229 1828483 : if (i->key == hash && cmp(cmp_arg, i->data) == 0)
- 230 1153152 : return i->data;
- 231 675331 : i = i->next;
+ 229 1847113 : if (i->key == hash && cmp(cmp_arg, i->data) == 0)
+ 230 1171007 : return i->data;
+ 231 676106 : i = i->next;
232 : }
- 233 1955595 : return 0;
+ 233 1944390 : 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 0839d722..7805d5dc 100644
--- a/cov/tommyds/tommylist.c.func-sort-c.html
+++ b/cov/tommyds/tommylist.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommylist.c.func.html b/cov/tommyds/tommylist.c.func.html
index 1dfa43e9..78e520bf 100644
--- a/cov/tommyds/tommylist.c.func.html
+++ b/cov/tommyds/tommylist.c.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommylist.c.gcov.html b/cov/tommyds/tommylist.c.gcov.html
index ff470829..15db502b 100644
--- a/cov/tommyds/tommylist.c.gcov.html
+++ b/cov/tommyds/tommylist.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/cov/tommyds/tommylist.h.func-sort-c.html b/cov/tommyds/tommylist.h.func-sort-c.html
index 59514e63..2a1dad02 100644
--- a/cov/tommyds/tommylist.h.func-sort-c.html
+++ b/cov/tommyds/tommylist.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,23 +61,23 @@
| tommy_list_head |
- 25304133 |
+ 25329368 |
| tommy_list_insert_first |
- 23374774 |
+ 23404491 |
| tommy_list_insert_tail |
- 18376886 |
+ 18389486 |
| tommy_list_insert_tail_not_empty |
- 11079128 |
+ 11062011 |
| tommy_list_remove_existing |
- 334849 |
+ 347694 |
| tommy_list_concat |
diff --git a/cov/tommyds/tommylist.h.func.html b/cov/tommyds/tommylist.h.func.html
index 665f8a95..3ededb05 100644
--- a/cov/tommyds/tommylist.h.func.html
+++ b/cov/tommyds/tommylist.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -77,7 +77,7 @@
| tommy_list_head |
- 25304133 |
+ 25329368 |
| tommy_list_init |
@@ -85,19 +85,19 @@
| tommy_list_insert_first |
- 23374774 |
+ 23404491 |
| tommy_list_insert_tail |
- 18376886 |
+ 18389486 |
| tommy_list_insert_tail_not_empty |
- 11079128 |
+ 11062011 |
| tommy_list_remove_existing |
- 334849 |
+ 347694 |
| tommy_list_tail |
diff --git a/cov/tommyds/tommylist.h.gcov.html b/cov/tommyds/tommylist.h.gcov.html
index 600cc1c4..097181a6 100644
--- a/cov/tommyds/tommylist.h.gcov.html
+++ b/cov/tommyds/tommylist.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -182,9 +182,9 @@
120 : * Gets the head of the list.
121 : * \return The head node. For empty lists 0 is returned.
122 : */
- 123 25304133 : tommy_inline tommy_node* tommy_list_head(tommy_list* list)
+ 123 25329368 : tommy_inline tommy_node* tommy_list_head(tommy_list* list)
124 : {
- 125 25304133 : return *list;
+ 125 25329368 : return *list;
126 : }
127 :
128 : /**
@@ -206,16 +206,16 @@
144 : * \param list The list to initialize.
145 : * \param node The node to insert.
146 : */
- 147 23374774 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node)
+ 147 23404491 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node)
148 : {
149 : /* one element "circular" prev list */
- 150 23374774 : node->prev = node;
+ 150 23404491 : node->prev = node;
151 :
152 : /* one element "0 terminated" next list */
- 153 23374774 : node->next = 0;
+ 153 23404491 : node->next = 0;
154 :
- 155 23374774 : *list = node;
- 156 23374774 : }
+ 155 23404491 : *list = node;
+ 156 23404491 : }
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 11079128 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node)
+ 184 11062011 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node)
185 : {
186 : /* insert in the "circular" prev list */
- 187 11079128 : node->prev = head->prev;
- 188 11079128 : head->prev = node;
+ 187 11062011 : node->prev = head->prev;
+ 188 11062011 : head->prev = node;
189 :
190 : /* insert in the "0 terminated" next list */
- 191 11079128 : node->next = 0;
- 192 11079128 : node->prev->next = node;
- 193 11079128 : }
+ 191 11062011 : node->next = 0;
+ 192 11062011 : node->prev->next = node;
+ 193 11062011 : }
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 18376886 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data)
+ 217 18389486 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data)
218 : {
- 219 18376886 : tommy_node* head = tommy_list_head(list);
+ 219 18389486 : tommy_node* head = tommy_list_head(list);
220 :
- 221 18376886 : if (head)
- 222 9163617 : tommy_list_insert_tail_not_empty(head, node);
+ 221 18389486 : if (head)
+ 222 9166252 : tommy_list_insert_tail_not_empty(head, node);
223 : else
- 224 9213269 : tommy_list_insert_first(list, node);
+ 224 9223234 : tommy_list_insert_first(list, node);
225 :
- 226 18376886 : node->data = data;
- 227 18376886 : }
+ 226 18389486 : node->data = data;
+ 227 18389486 : }
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 334849 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node)
+ 255 347694 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node)
256 : {
- 257 334849 : tommy_node* head = tommy_list_head(list);
+ 257 347694 : tommy_node* head = tommy_list_head(list);
258 :
259 : /* remove from the "circular" prev list */
- 260 334849 : if (node->next)
- 261 116893 : node->next->prev = node->prev;
+ 260 347694 : if (node->next)
+ 261 117955 : node->next->prev = node->prev;
262 : else
- 263 217956 : head->prev = node->prev; /* the last */
+ 263 229739 : head->prev = node->prev; /* the last */
264 :
265 : /* remove from the "0 terminated" next list */
- 266 334849 : if (head == node)
- 267 234397 : *list = node->next; /* the new head, in case 0 */
+ 266 347694 : if (head == node)
+ 267 244534 : *list = node->next; /* the new head, in case 0 */
268 : else
- 269 100452 : node->prev->next = node->next;
+ 269 103160 : node->prev->next = node->next;
270 :
- 271 334849 : return node->data;
+ 271 347694 : return node->data;
272 : }
273 :
274 : /**
@@ -349,24 +349,24 @@
287 : /* if the second is empty, nothing to do */
288 63152 : second_head = tommy_list_head(second);
289 63152 : if (second_head == 0)
- 290 55882 : return;
+ 290 55787 : return;
291 :
292 : /* if the first is empty, copy the second */
- 293 7270 : first_head = tommy_list_head(first);
- 294 7270 : if (first_head == 0) {
- 295 6382 : *first = *second;
- 296 6382 : return;
+ 293 7365 : first_head = tommy_list_head(first);
+ 294 7365 : if (first_head == 0) {
+ 295 6478 : *first = *second;
+ 296 6478 : return;
297 : }
298 :
299 : /* tail of the first list */
- 300 888 : first_tail = first_head->prev;
+ 300 887 : first_tail = first_head->prev;
301 :
302 : /* set the "circular" prev list */
- 303 888 : first_head->prev = second_head->prev;
- 304 888 : second_head->prev = first_tail;
+ 303 887 : first_head->prev = second_head->prev;
+ 304 887 : second_head->prev = first_tail;
305 :
306 : /* set the "0 terminated" next list */
- 307 888 : first_tail->next = second_head;
+ 307 887 : first_tail->next = second_head;
308 : }
309 :
310 : /**
@@ -436,10 +436,10 @@
374 : {
375 7645 : tommy_node* node = tommy_list_head(list);
376 :
- 377 3679931 : while (node) {
- 378 3664641 : void* data = node->data;
- 379 3664641 : node = node->next;
- 380 3664641 : func(data);
+ 377 3679929 : while (node) {
+ 378 3664639 : void* data = node->data;
+ 379 3664639 : node = node->next;
+ 380 3664639 : func(data);
381 : }
382 7645 : }
383 :
diff --git a/cov/tommyds/tommytree.c.func-sort-c.html b/cov/tommyds/tommytree.c.func-sort-c.html
index 82ebea9a..0a34d3a4 100644
--- a/cov/tommyds/tommytree.c.func-sort-c.html
+++ b/cov/tommyds/tommytree.c.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,55 +61,55 @@
| tommy_tree_search_node |
- 137516004 |
+ 136358907 |
| tommy_tree_delta |
- 112385081 |
+ 112386346 |
| tommy_tree_balance |
- 104878675 |
+ 104880543 |
| tommy_tree_insert_node |
- 96198722 |
+ 96201724 |
| tommy_tree_foreach_arg_node |
- 26344381 |
+ 26344733 |
| tommy_tree_search_compare |
- 12374066 |
+ 12265513 |
| tommy_tree_rotate_left |
- 7494967 |
+ 7494292 |
| tommy_tree_insert |
- 7470835 |
+ 7470915 |
| tommy_tree_foreach_node |
- 7052386 |
+ 7052474 |
| tommy_tree_remove_node |
- 791513 |
+ 791997 |
| tommy_tree_move_right |
- 187087 |
+ 186993 |
| tommy_tree_rotate_right |
- 170763 |
+ 170708 |
| tommy_tree_remove |
- 79700 |
+ 79692 |
| tommy_tree_foreach_arg |
diff --git a/cov/tommyds/tommytree.c.func.html b/cov/tommyds/tommytree.c.func.html
index d5863abc..4fbf0ecc 100644
--- a/cov/tommyds/tommytree.c.func.html
+++ b/cov/tommyds/tommytree.c.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,11 +61,11 @@
| tommy_tree_balance |
- 104878675 |
+ 104880543 |
| tommy_tree_delta |
- 112385081 |
+ 112386346 |
| tommy_tree_foreach |
@@ -77,11 +77,11 @@
| tommy_tree_foreach_arg_node |
- 26344381 |
+ 26344733 |
| tommy_tree_foreach_node |
- 7052386 |
+ 7052474 |
| tommy_tree_init |
@@ -89,11 +89,11 @@
| tommy_tree_insert |
- 7470835 |
+ 7470915 |
| tommy_tree_insert_node |
- 96198722 |
+ 96201724 |
| tommy_tree_memory_usage |
@@ -101,11 +101,11 @@
| tommy_tree_move_right |
- 187087 |
+ 186993 |
| tommy_tree_remove |
- 79700 |
+ 79692 |
| tommy_tree_remove_existing |
@@ -113,15 +113,15 @@
| tommy_tree_remove_node |
- 791513 |
+ 791997 |
| tommy_tree_rotate_left |
- 7494967 |
+ 7494292 |
| tommy_tree_rotate_right |
- 170763 |
+ 170708 |
| tommy_tree_search |
@@ -129,11 +129,11 @@
| tommy_tree_search_compare |
- 12374066 |
+ 12265513 |
| tommy_tree_search_node |
- 137516004 |
+ 136358907 |
diff --git a/cov/tommyds/tommytree.c.gcov.html b/cov/tommyds/tommytree.c.gcov.html
index cf93057e..2ff1395c 100644
--- a/cov/tommyds/tommytree.c.gcov.html
+++ b/cov/tommyds/tommytree.c.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -101,97 +101,97 @@
39 3183 : tree->cmp = cmp;
40 3183 : }
41 :
- 42 112385081 : static int tommy_tree_delta(tommy_tree_node* root)
+ 42 112386346 : static int tommy_tree_delta(tommy_tree_node* root)
43 : {
- 44 112385081 : int left_height = root->prev ? root->prev->key : 0;
- 45 112385081 : int right_height = root->next ? root->next->key : 0;
+ 44 112386346 : int left_height = root->prev ? root->prev->key : 0;
+ 45 112386346 : int right_height = root->next ? root->next->key : 0;
46 :
- 47 112385081 : return left_height - right_height;
+ 47 112386346 : return left_height - right_height;
48 : }
49 :
50 : /* AVL tree operations */
51 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*);
52 :
- 53 7494967 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root)
+ 53 7494292 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root)
54 : {
- 55 7494967 : tommy_tree_node* next = root->next;
+ 55 7494292 : tommy_tree_node* next = root->next;
56 :
- 57 7494967 : root->next = next->prev;
+ 57 7494292 : root->next = next->prev;
58 :
- 59 7494967 : next->prev = tommy_tree_balance(root);
+ 59 7494292 : next->prev = tommy_tree_balance(root);
60 :
- 61 7494967 : return tommy_tree_balance(next);
+ 61 7494292 : return tommy_tree_balance(next);
62 : }
63 :
- 64 170763 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root)
+ 64 170708 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root)
65 : {
- 66 170763 : tommy_tree_node* prev = root->prev;
+ 66 170708 : tommy_tree_node* prev = root->prev;
67 :
- 68 170763 : root->prev = prev->next;
+ 68 170708 : root->prev = prev->next;
69 :
- 70 170763 : prev->next = tommy_tree_balance(root);
+ 70 170708 : prev->next = tommy_tree_balance(root);
71 :
- 72 170763 : return tommy_tree_balance(prev);
+ 72 170708 : return tommy_tree_balance(prev);
73 : }
74 :
- 75 187087 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node)
+ 75 186993 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node)
76 : {
- 77 187087 : if (!root)
- 78 79572 : return node;
+ 77 186993 : if (!root)
+ 78 79564 : return node;
79 :
- 80 107515 : root->next = tommy_tree_move_right(root->next, node);
+ 80 107429 : root->next = tommy_tree_move_right(root->next, node);
81 :
- 82 107515 : return tommy_tree_balance(root);
+ 82 107429 : return tommy_tree_balance(root);
83 : }
84 :
- 85 104878675 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
+ 85 104880543 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
86 : {
- 87 104878675 : int delta = tommy_tree_delta(root);
+ 87 104880543 : int delta = tommy_tree_delta(root);
88 :
- 89 104878675 : if (delta < -1) {
- 90 7378499 : if (tommy_tree_delta(root->next) > 0)
- 91 42856 : root->next = tommy_tree_rotate_right(root->next);
- 92 7378499 : return tommy_tree_rotate_left(root);
+ 89 104880543 : if (delta < -1) {
+ 90 7378061 : if (tommy_tree_delta(root->next) > 0)
+ 91 42966 : root->next = tommy_tree_rotate_right(root->next);
+ 92 7378061 : return tommy_tree_rotate_left(root);
93 : }
94 :
- 95 97500176 : if (delta > 1) {
- 96 127907 : if (tommy_tree_delta(root->prev) < 0)
- 97 116468 : root->prev = tommy_tree_rotate_left(root->prev);
- 98 127907 : return tommy_tree_rotate_right(root);
+ 95 97502482 : if (delta > 1) {
+ 96 127742 : if (tommy_tree_delta(root->prev) < 0)
+ 97 116231 : root->prev = tommy_tree_rotate_left(root->prev);
+ 98 127742 : return tommy_tree_rotate_right(root);
99 : }
100 :
101 : /* recompute key */
- 102 97372269 : root->key = 0;
+ 102 97374740 : root->key = 0;
103 :
- 104 97372269 : if (root->prev && root->prev->key > root->key)
- 105 78769557 : root->key = root->prev->key;
+ 104 97374740 : if (root->prev && root->prev->key > root->key)
+ 105 78772370 : root->key = root->prev->key;
106 :
- 107 97372269 : if (root->next && root->next->key > root->key)
- 108 44908478 : root->key = root->next->key;
+ 107 97374740 : if (root->next && root->next->key > root->key)
+ 108 44910466 : root->key = root->next->key;
109 :
110 : /* count itself */
- 111 97372269 : root->key += 1;
+ 111 97374740 : root->key += 1;
112 :
- 113 97372269 : return root;
+ 113 97374740 : return root;
114 : }
115 :
- 116 96198722 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let)
+ 116 96201724 : 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 96198722 : if (!root)
- 121 7470834 : return *let;
+ 120 96201724 : if (!root)
+ 121 7470914 : return *let;
122 :
- 123 88727888 : c = cmp((*let)->data, root->data);
+ 123 88730810 : c = cmp((*let)->data, root->data);
124 :
- 125 88727888 : if (c < 0) {
- 126 1533765 : root->prev = tommy_tree_insert_node(cmp, root->prev, let);
- 127 1533765 : return tommy_tree_balance(root);
+ 125 88730810 : if (c < 0) {
+ 126 1533509 : root->prev = tommy_tree_insert_node(cmp, root->prev, let);
+ 127 1533509 : return tommy_tree_balance(root);
128 : }
129 :
- 130 87194123 : if (c > 0) {
- 131 87194122 : root->next = tommy_tree_insert_node(cmp, root->next, let);
- 132 87194122 : return tommy_tree_balance(root);
+ 130 87197301 : if (c > 0) {
+ 131 87197300 : root->next = tommy_tree_insert_node(cmp, root->next, let);
+ 132 87197300 : 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 7470835 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
+ 141 7470915 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
142 : {
- 143 7470835 : tommy_tree_node* insert = node;
+ 143 7470915 : tommy_tree_node* insert = node;
144 :
- 145 7470835 : insert->data = data;
- 146 7470835 : insert->prev = 0;
- 147 7470835 : insert->next = 0;
- 148 7470835 : insert->key = 0;
+ 145 7470915 : insert->data = data;
+ 146 7470915 : insert->prev = 0;
+ 147 7470915 : insert->next = 0;
+ 148 7470915 : insert->key = 0;
149 :
- 150 7470835 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
+ 150 7470915 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
151 :
- 152 7470835 : if (insert == node)
- 153 7470834 : ++tree->count;
+ 152 7470915 : if (insert == node)
+ 153 7470914 : ++tree->count;
154 :
- 155 7470835 : return insert->data;
+ 155 7470915 : return insert->data;
156 : }
157 :
- 158 791513 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let)
+ 158 791997 : 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 791513 : if (!root)
+ 162 791997 : if (!root)
163 128 : return 0;
164 :
- 165 791385 : c = cmp(data, root->data);
+ 165 791869 : c = cmp(data, root->data);
166 :
- 167 791385 : if (c < 0) {
- 168 304173 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let);
- 169 304173 : return tommy_tree_balance(root);
+ 167 791869 : if (c < 0) {
+ 168 304676 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let);
+ 169 304676 : return tommy_tree_balance(root);
170 : }
171 :
- 172 487212 : if (c > 0) {
- 173 407640 : root->next = tommy_tree_remove_node(cmp, root->next, data, let);
- 174 407640 : return tommy_tree_balance(root);
+ 172 487193 : if (c > 0) {
+ 173 407629 : root->next = tommy_tree_remove_node(cmp, root->next, data, let);
+ 174 407629 : return tommy_tree_balance(root);
175 : }
176 :
177 : /* found */
- 178 79572 : *let = root;
+ 178 79564 : *let = root;
179 :
- 180 79572 : return tommy_tree_move_right(root->prev, root->next);
+ 180 79564 : return tommy_tree_move_right(root->prev, root->next);
181 : }
182 :
- 183 79700 : void* tommy_tree_remove(tommy_tree* tree, void* data)
+ 183 79692 : void* tommy_tree_remove(tommy_tree* tree, void* data)
184 : {
- 185 79700 : tommy_tree_node* node = 0;
+ 185 79692 : tommy_tree_node* node = 0;
186 :
- 187 79700 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node);
+ 187 79692 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node);
188 :
- 189 79700 : if (!node)
+ 189 79692 : if (!node)
190 128 : return 0;
191 :
- 192 79572 : --tree->count;
+ 192 79564 : --tree->count;
193 :
- 194 79572 : return node->data;
+ 194 79564 : return node->data;
195 : }
196 :
- 197 137516004 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data)
+ 197 136358907 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data)
198 : {
199 : int c;
200 :
- 201 137516004 : if (!root)
- 202 1589078 : return 0;
+ 201 136358907 : if (!root)
+ 202 1589052 : return 0;
203 :
- 204 135926926 : c = cmp(data, root->data);
+ 204 134769855 : c = cmp(data, root->data);
205 :
- 206 135935261 : if (c < 0)
- 207 49441744 : return tommy_tree_search_node(cmp, root->prev, data);
+ 206 134778932 : if (c < 0)
+ 207 48960881 : return tommy_tree_search_node(cmp, root->prev, data);
208 :
- 209 86493517 : if (c > 0)
- 210 75708858 : return tommy_tree_search_node(cmp, root->next, data);
+ 209 85818051 : if (c > 0)
+ 210 75141540 : return tommy_tree_search_node(cmp, root->next, data);
211 :
- 212 10784659 : return root;
+ 212 10676511 : 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 12374066 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg)
+ 225 12265513 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg)
226 : {
- 227 12374066 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg);
+ 227 12265513 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg);
228 :
- 229 12373755 : if (!node)
- 230 1589128 : return 0;
+ 229 12265527 : if (!node)
+ 230 1589090 : return 0;
231 :
- 232 10784627 : return node->data;
+ 232 10676437 : return node->data;
233 : }
234 :
235 128 : void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node)
@@ -303,21 +303,21 @@
241 128 : return data;
242 : }
243 :
- 244 7052386 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func)
+ 244 7052474 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func)
245 : {
246 : tommy_tree_node* next;
247 :
- 248 7052386 : if (!root)
- 249 10579309 : return;
+ 248 7052474 : if (!root)
+ 249 10579441 : return;
250 :
- 251 3525463 : tommy_tree_foreach_node(root->prev, func);
+ 251 3525507 : tommy_tree_foreach_node(root->prev, func);
252 :
253 : /* make a copy in case func is free() */
- 254 3525463 : next = root->next;
+ 254 3525507 : next = root->next;
255 :
- 256 3525463 : func(root->data);
+ 256 3525507 : func(root->data);
257 :
- 258 3525463 : tommy_tree_foreach_node(next, func);
+ 258 3525507 : tommy_tree_foreach_node(next, func);
259 : }
260 :
261 1460 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func)
@@ -325,21 +325,21 @@
263 1460 : tommy_tree_foreach_node(tree->root, func);
264 1460 : }
265 :
- 266 26344381 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg)
+ 266 26344733 : 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 26344381 : if (!root)
- 271 39519560 : return;
+ 270 26344733 : if (!root)
+ 271 39520088 : return;
272 :
- 273 13169202 : tommy_tree_foreach_arg_node(root->prev, func, arg);
+ 273 13169378 : tommy_tree_foreach_arg_node(root->prev, func, arg);
274 :
275 : /* make a copy in case func is free() */
- 276 13169202 : next = root->next;
+ 276 13169378 : next = root->next;
277 :
- 278 13169202 : func(arg, root->data);
+ 278 13169378 : func(arg, root->data);
279 :
- 280 13169202 : tommy_tree_foreach_arg_node(next, func, arg);
+ 280 13169378 : tommy_tree_foreach_arg_node(next, func, arg);
281 : }
282 :
283 5977 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg)
diff --git a/cov/tommyds/tommytree.h.func-sort-c.html b/cov/tommyds/tommytree.h.func-sort-c.html
index ff624258..0baf7714 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 1d42fad9..a637aeda 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 d11ce0f8..840efecf 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 a9485641..5fe44624 100644
--- a/cov/tommyds/tommytypes.h.func-sort-c.html
+++ b/cov/tommyds/tommytypes.h.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -61,7 +61,7 @@
| tommy_ilog2_u32 |
- 10268668 |
+ 10268805 |
| tommy_ctz_u32 |
diff --git a/cov/tommyds/tommytypes.h.func.html b/cov/tommyds/tommytypes.h.func.html
index b4d67947..06c03883 100644
--- a/cov/tommyds/tommytypes.h.func.html
+++ b/cov/tommyds/tommytypes.h.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -69,7 +69,7 @@
| tommy_ilog2_u32 |
- 10268668 |
+ 10268805 |
diff --git a/cov/tommyds/tommytypes.h.gcov.html b/cov/tommyds/tommytypes.h.gcov.html
index feca1864..8dfc33bc 100644
--- a/cov/tommyds/tommytypes.h.gcov.html
+++ b/cov/tommyds/tommytypes.h.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -390,7 +390,7 @@
328 : * \param value Value to scan. 0 is not allowed.
329 : * \return The index of the most significant bit set.
330 : */
- 331 10268668 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
+ 331 10268805 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
332 : {
333 : #if defined(_MSC_VER)
334 : unsigned long count;
@@ -406,7 +406,7 @@
344 : * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)",
345 : * to allow the double xor to be optimized out.
346 : */
- 347 10268668 : return __builtin_clz(value) ^ 31;
+ 347 10268805 : return __builtin_clz(value) ^ 31;
348 : #else
349 : /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */
350 : /* from http://graphics.stanford.edu/~seander/bithacks.html */