diff --git a/cov/cmdline/bw.c.func-sort-c.html b/cov/cmdline/bw.c.func-sort-c.html index 158c5d47..2d01b03a 100644 --- a/cov/cmdline/bw.c.func-sort-c.html +++ b/cov/cmdline/bw.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ bw_limit - 9766068 + 9765411
diff --git a/cov/cmdline/bw.c.func.html b/cov/cmdline/bw.c.func.html index c4056475..c67434d5 100644 --- a/cov/cmdline/bw.c.func.html +++ b/cov/cmdline/bw.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ bw_limit - 9766068 + 9765411
diff --git a/cov/cmdline/bw.c.gcov.html b/cov/cmdline/bw.c.gcov.html index a3173a17..19865db2 100644 --- a/cov/cmdline/bw.c.gcov.html +++ b/cov/cmdline/bw.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -88,10 +88,10 @@ 26 220 : bw->start = tick_ms(); 27 220 : } 28 : - 29 9766068 : void bw_limit(struct snapraid_bw* bw, uint64_t bytes) + 29 9765411 : void bw_limit(struct snapraid_bw* bw, uint64_t bytes) 30 : { - 31 9766068 : if (!bw || bw->limit == 0) - 32 9766012 : return; + 31 9765411 : if (!bw || bw->limit == 0) + 32 9765355 : return; 33 : 34 56 : uint64_t elapsed = tick_ms() - bw->start; 35 : uint64_t done; diff --git a/cov/cmdline/check.c.func-sort-c.html b/cov/cmdline/check.c.func-sort-c.html index 31bacb5b..de06c869 100644 --- a/cov/cmdline/check.c.func-sort-c.html +++ b/cov/cmdline/check.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 766 + 765 862 - 88.9 % + 88.7 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -73,19 +73,19 @@ is_hash_matching - 210036 + 210236 repair_step - 252597 + 252818 blockcmp - 468600 + 468795 es - 731365 + 731403 repair diff --git a/cov/cmdline/check.c.func.html b/cov/cmdline/check.c.func.html index 5979533f..41f82be8 100644 --- a/cov/cmdline/check.c.func.html +++ b/cov/cmdline/check.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 766 + 765 862 - 88.9 % + 88.7 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -65,11 +65,11 @@ blockcmp - 468600 + 468795 es - 731365 + 731403 file_post @@ -77,7 +77,7 @@ is_hash_matching - 210036 + 210236 is_parity_matching @@ -89,7 +89,7 @@ repair_step - 252597 + 252818 state_check diff --git a/cov/cmdline/check.c.gcov.html b/cov/cmdline/check.c.gcov.html index b848cf93..f5f15d66 100644 --- a/cov/cmdline/check.c.gcov.html +++ b/cov/cmdline/check.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 766 + 765 862 - 88.9 % + 88.7 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -93,12 +93,12 @@ 31 : /****************************************************************************/ 32 : /* check */ 33 : - 34 731365 : static const char* es(int err) + 34 731403 : static const char* es(int err) 35 : { - 36 731365 : if (is_hw(err)) + 36 731403 : if (is_hw(err)) 37 0 : return "error_io"; 38 : else - 39 731365 : return "error"; + 39 731403 : return "error"; 40 : } 41 : 42 : /** @@ -137,64 +137,64 @@ 75 : * Check if a block hash matches the specified buffer. 76 : * Return ==0 if equal 77 : */ - 78 468600 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) + 78 468795 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) 79 : { 80 : unsigned char hash[HASH_MAX]; 81 : 82 : /* now compute the hash of the valid part */ - 83 468600 : if (rehash) { + 83 468795 : if (rehash) { 84 0 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size); 85 : } else { - 86 468600 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); + 86 468795 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); 87 : } 88 : 89 : /* compare the hash */ - 90 468600 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { - 91 14376 : return -1; + 90 468795 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 91 14403 : return -1; 92 : } 93 : 94 : /* compare to the end of the block */ - 95 454224 : if (pos_size < state->block_size) { - 96 187417 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { - 97 42 : return -1; + 95 454392 : if (pos_size < state->block_size) { + 96 187544 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { + 97 45 : return -1; 98 : } 99 : } 100 : - 101 454182 : return 0; + 101 454347 : return 0; 102 : } 103 : 104 : /** 105 : * Check if the hash of all the failed blocks we are expecting to recover are now matching. 106 : */ - 107 210036 : 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) + 107 210236 : 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) 108 : { 109 : unsigned j; 110 : int hash_checked; 111 : - 112 210036 : hash_checked = 0; /* keep track if we check at least one block */ + 112 210236 : hash_checked = 0; /* keep track if we check at least one block */ 113 : 114 : /* check if the recovered blocks are OK */ - 115 668740 : for (j = 0; j < failed_count; ++j) { + 115 669105 : for (j = 0; j < failed_count; ++j) { 116 : /* if we are expected to recover this block */ - 117 473122 : if (!failed[failed_map[j]].is_outofdate + 117 473317 : if (!failed[failed_map[j]].is_outofdate 118 : /* if the block has a hash to check */ - 119 468600 : && block_has_updated_hash(failed[failed_map[j]].block) + 119 468795 : && block_has_updated_hash(failed[failed_map[j]].block) 120 : ) { 121 : /* if a hash doesn't match, fail the check */ - 122 468600 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); - 123 468600 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { - 124 14418 : log_tag("repair_hash_error:%u: Hash mismatch\n", failed_map[j]); - 125 14418 : return 0; + 122 468795 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); + 123 468795 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { + 124 14448 : log_tag("repair_hash_error:%u: Hash mismatch\n", failed_map[j]); + 125 14448 : return 0; 126 : } 127 : - 128 454182 : hash_checked = 1; + 128 454347 : hash_checked = 1; 129 : } 130 : } 131 : 132 : /* if nothing checked, we reject it */ 133 : /* note that we are excluding this case at upper level */ 134 : /* but checking again doesn't hurt */ - 135 195618 : if (!hash_checked) { + 135 195788 : if (!hash_checked) { 136 : /* LCOV_EXCL_START */ 137 : return 0; 138 : /* LCOV_EXCL_STOP */ @@ -202,8 +202,8 @@ 140 : 141 : /* if we checked something, and no block failed the check */ 142 : /* recompute all the redundancy information */ - 143 195618 : raid_gen(diskmax, state->level, state->block_size, buffer); - 144 195618 : return 1; + 143 195788 : raid_gen(diskmax, state->level, state->block_size, buffer); + 144 195788 : return 1; 145 : } 146 : 147 : /** @@ -229,7 +229,7 @@ 167 : * Return <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. 168 : * If success, the parity is computed in the buffer variable. 169 : */ - 170 252597 : 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) + 170 252818 : 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) 171 : { 172 : unsigned i, n; 173 : int error; @@ -238,7 +238,7 @@ 176 : int ip[LEV_MAX]; 177 : 178 : /* no fix required, already checked at higher level, but just to be sure */ - 179 252597 : if (failed_count == 0) { + 179 252818 : if (failed_count == 0) { 180 : /* LCOV_EXCL_START */ 181 : /* recompute only the parity */ 182 : raid_gen(diskmax, state->level, state->block_size, buffer); @@ -246,28 +246,28 @@ 184 : /* LCOV_EXCL_STOP */ 185 : } 186 : - 187 252597 : n = state->level; - 188 252597 : error = 0; + 187 252818 : n = state->level; + 188 252818 : error = 0; 189 : 190 : /* setup vector of failed disk indexes */ - 191 891533 : for (i = 0; i < failed_count; ++i) - 192 638936 : id[i] = failed[failed_map[i]].index; + 191 892011 : for (i = 0; i < failed_count; ++i) + 192 639193 : id[i] = failed[failed_map[i]].index; 193 : 194 : /* check if there is at least a failed block that can be checked for correctness using the hash */ 195 : /* if there isn't, we have to sacrifice a parity block to check that the result is correct */ - 196 252597 : has_hash = 0; - 197 891533 : for (i = 0; i < failed_count; ++i) { + 196 252818 : has_hash = 0; + 197 892011 : for (i = 0; i < failed_count; ++i) { 198 : /* if we are expected to recover this block */ - 199 638936 : if (!failed[failed_map[i]].is_outofdate + 199 639193 : if (!failed[failed_map[i]].is_outofdate 200 : /* if the block has a hash to check */ - 201 629892 : && block_has_updated_hash(failed[failed_map[i]].block) + 201 630149 : && block_has_updated_hash(failed[failed_map[i]].block) 202 : ) - 203 629884 : has_hash = 1; + 203 630141 : has_hash = 1; 204 : } 205 : 206 : /* if we don't have a hash, but we have an extra parity */ 207 : /* (strictly-less failures than number of parities) */ - 208 252597 : if (!has_hash && failed_count < n) { + 208 252818 : if (!has_hash && failed_count < n) { 209 : /* number of parity to use, one more to check the recovering */ 210 8 : unsigned r = failed_count + 1; 211 : @@ -307,51 +307,51 @@ 245 : 246 : /* if we have a hash, and enough parities */ 247 : /* (less-or-equal failures than number of parities) */ - 248 252589 : if (has_hash && failed_count <= n) { + 248 252810 : if (has_hash && failed_count <= n) { 249 : /* number of parities to use equal to the number of failures */ - 250 204946 : unsigned r = failed_count; + 250 205126 : unsigned r = failed_count; 251 : 252 : /* all combinations (r of n) parities */ - 253 204946 : combination_first(r, n, ip); + 253 205126 : combination_first(r, n, ip); 254 : do { 255 : /* if a parity is missing, do nothing */ - 256 687807 : for (i = 0; i < r; ++i) { - 257 477771 : if (buffer_recov[ip[i]] == 0) + 256 688202 : for (i = 0; i < r; ++i) { + 257 477966 : if (buffer_recov[ip[i]] == 0) 258 4649 : break; 259 : } - 260 214685 : if (i != r) + 260 214885 : if (i != r) 261 4649 : continue; 262 : 263 : /* copy the parities to use */ - 264 683158 : for (i = 0; i < r; ++i) - 265 473122 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + 264 683553 : for (i = 0; i < r; ++i) + 265 473317 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); 266 : 267 : /* recover */ - 268 210036 : raid_data(r, id, ip, diskmax, state->block_size, buffer); + 268 210236 : raid_data(r, id, ip, diskmax, state->block_size, buffer); 269 : 270 : /* use the hash to check the result */ - 271 210036 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) - 272 195618 : return 0; + 271 210236 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) + 272 195788 : return 0; 273 : 274 : /* log */ - 275 14418 : log_tag("recover_hash_error:%u:", pos); - 276 28836 : for (i = 0; i < r; ++i) { - 277 14418 : if (i != 0) + 275 14448 : log_tag("recover_hash_error:%u:", pos); + 276 28896 : for (i = 0; i < r; ++i) { + 277 14448 : if (i != 0) 278 0 : log_tag("/"); - 279 14418 : log_tag("%s", lev_config_name(ip[i])); + 279 14448 : log_tag("%s", lev_config_name(ip[i])); 280 : } - 281 14418 : log_tag(": Hash mismatch\n"); - 282 14418 : ++error; - 283 38134 : } while (combination_next(r, n, ip)); + 281 14448 : log_tag(": Hash mismatch\n"); + 282 14448 : ++error; + 283 38194 : } while (combination_next(r, n, ip)); 284 : } 285 : 286 : /* return the number of failed attempts, or -1 if no strategy */ - 287 56971 : if (error) - 288 9328 : return error; + 287 57022 : if (error) + 288 9338 : return error; 289 : - 290 47643 : log_tag("recover_strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", + 290 47684 : log_tag("recover_strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", 291 : pos, failed_count, n, has_hash ? "with" : "without"); - 292 47643 : return -1; + 292 47684 : return -1; 293 : } 294 : 295 872338 : 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) @@ -368,47 +368,47 @@ 306 : 307 : /* if nothing failed, just recompute the parity */ 308 872338 : if (failed_count == 0) { - 309 584829 : raid_gen(diskmax, state->level, state->block_size, buffer); - 310 584829 : return 0; + 309 584608 : raid_gen(diskmax, state->level, state->block_size, buffer); + 310 584608 : return 0; 311 : } 312 : 313 : /* logs the status */ - 314 1016464 : for (j = 0; j < failed_count; ++j) { + 314 1016942 : for (j = 0; j < failed_count; ++j) { 315 : const char* desc; 316 : const char* hash; 317 : const char* data; - 318 728955 : struct snapraid_block* block = failed[j].block; - 319 728955 : unsigned block_state = block_state_get(block); + 318 729212 : struct snapraid_block* block = failed[j].block; + 319 729212 : unsigned block_state = block_state_get(block); 320 : - 321 728955 : switch (block_state) { + 321 729212 : switch (block_state) { 322 18454 : case BLOCK_STATE_DELETED : desc = "delete"; break; 323 13851 : case BLOCK_STATE_CHG : desc = "change"; break; 324 62282 : case BLOCK_STATE_REP : desc = "replace"; break; - 325 634368 : case BLOCK_STATE_BLK : desc = "block"; break; + 325 634625 : case BLOCK_STATE_BLK : desc = "block"; break; 326 : /* LCOV_EXCL_START */ 327 : default : desc = "unknown"; break; 328 : /* LCOV_EXCL_STOP */ 329 : } 330 : - 331 728955 : if (hash_is_invalid(block->hash)) { + 331 729212 : if (hash_is_invalid(block->hash)) { 332 13843 : hash = "lost"; - 333 715112 : } else if (hash_is_zero(block->hash)) { + 333 715369 : } else if (hash_is_zero(block->hash)) { 334 8 : hash = "zero"; 335 : } else { - 336 715104 : hash = "known"; + 336 715361 : hash = "known"; 337 : } 338 : - 339 728955 : if (failed[j].is_bad) - 340 643230 : data = "bad"; + 339 729212 : if (failed[j].is_bad) + 340 643487 : data = "bad"; 341 : else 342 85725 : data = "good"; 343 : - 344 728955 : if (failed[j].file) { - 345 710501 : struct snapraid_disk* disk = failed[j].disk; - 346 710501 : struct snapraid_file* file = failed[j].file; - 347 710501 : block_off_t file_pos = failed[j].file_pos; + 344 729212 : if (failed[j].file) { + 345 710758 : struct snapraid_disk* disk = failed[j].disk; + 346 710758 : struct snapraid_file* file = failed[j].file; + 347 710758 : block_off_t file_pos = failed[j].file_pos; 348 : - 349 710501 : log_tag("repair_entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + 349 710758 : log_tag("repair_entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos); 350 : } else { 351 18454 : log_tag("repair_entry:%u:%s:%s:%s:\n", j, desc, hash, data); 352 : } @@ -430,35 +430,35 @@ 368 : /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */ 369 : /* but we are not interested in DELETED ones. */ 370 : - 371 287509 : n = 0; - 372 287509 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 373 1016464 : for (j = 0; j < failed_count; ++j) { - 374 728955 : if (failed[j].is_bad) { - 375 643230 : unsigned block_state = block_state_get(failed[j].block); + 371 287730 : n = 0; + 372 287730 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 373 1016942 : for (j = 0; j < failed_count; ++j) { + 374 729212 : if (failed[j].is_bad) { + 375 643487 : unsigned block_state = block_state_get(failed[j].block); 376 : - 377 643230 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ + 377 643487 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ 378 : 379 : /* if we have the hash for it */ - 380 643230 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) + 380 643487 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) 381 : /* try to fetch the block using the known hash */ - 382 643222 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 - 383 638750 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) + 382 643479 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 + 383 639007 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) 384 : ) { 385 : /* we already have corrected it! */ 386 22382 : log_tag("repair_hash_import:%u: Fixed by import\n", j); 387 : } else { 388 : /* otherwise try to recover it */ - 389 620848 : failed_map[n] = j; - 390 620848 : ++n; + 389 621105 : failed_map[n] = j; + 390 621105 : ++n; 391 : 392 : /* we have something to try to recover */ - 393 620848 : something_to_recover = 1; + 393 621105 : something_to_recover = 1; 394 : } 395 : } 396 : } 397 : 398 : /* if nothing to fix */ - 399 287509 : if (!something_to_recover) { + 399 287730 : if (!something_to_recover) { 400 43956 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n); 401 : 402 : /* recompute only the parity */ @@ -466,22 +466,22 @@ 404 43956 : return 0; 405 : } 406 : - 407 243553 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); - 408 243553 : if (ret == 0) { + 407 243774 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); + 408 243774 : if (ret == 0) { 409 : /* reprocess the CHG blocks, for which we don't have a hash to check */ 410 : /* if they were BAD we have to use some heuristics to ensure that we have recovered */ 411 : /* the state after the sync. If unsure, we assume the worst case */ 412 : - 413 667399 : for (j = 0; j < failed_count; ++j) { + 413 667734 : for (j = 0; j < failed_count; ++j) { 414 : /* we take care only of BAD blocks we have to write back */ - 415 476295 : if (failed[j].is_bad) { - 416 462823 : unsigned block_state = block_state_get(failed[j].block); + 415 476460 : if (failed[j].is_bad) { + 416 462988 : unsigned block_state = block_state_get(failed[j].block); 417 : 418 : /* BLK and REP blocks are always OK, because at this point */ 419 : /* we have already checked their hash */ - 420 462823 : if (block_state != BLOCK_STATE_CHG) { - 421 462815 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); - 422 462815 : continue; + 420 462988 : if (block_state != BLOCK_STATE_CHG) { + 421 462980 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 422 462980 : continue; 423 : } 424 : 425 : /* for CHG blocks we have to 'guess' if they are correct or not */ @@ -523,15 +523,15 @@ 461 : } 462 : } 463 : - 464 191104 : return 0; + 464 191274 : return 0; 465 : } - 466 52449 : if (ret > 0) - 467 9328 : error += ret; + 466 52500 : if (ret > 0) + 467 9338 : error += ret; 468 : - 469 52449 : if (ret < 0) - 470 43121 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); + 469 52500 : if (ret < 0) + 470 43162 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); 471 : else - 472 9328 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); + 472 9338 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); 473 : 474 : /* Now assume that the parity IS NOT updated at the current state, */ 475 : /* but still represent the state before the last 'sync' process. */ @@ -541,15 +541,15 @@ 479 : /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */ 480 : /* even if marked as bad, because we don't have parity for them and it's just impossible, */ 481 : /* and we are not interested to recover DELETED ones. */ - 482 52449 : n = 0; - 483 52449 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 484 52449 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ - 485 232673 : for (j = 0; j < failed_count; ++j) { - 486 180224 : unsigned block_state = block_state_get(failed[j].block); + 482 52500 : n = 0; + 483 52500 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 484 52500 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ + 485 232816 : for (j = 0; j < failed_count; ++j) { + 486 180316 : unsigned block_state = block_state_get(failed[j].block); 487 : - 488 180224 : if (block_state == BLOCK_STATE_DELETED - 489 171180 : || block_state == BLOCK_STATE_CHG - 490 171180 : || block_state == BLOCK_STATE_REP + 488 180316 : if (block_state == BLOCK_STATE_DELETED + 489 171272 : || block_state == BLOCK_STATE_CHG + 490 171272 : || block_state == BLOCK_STATE_REP 491 : ) { 492 : /* If the block is CHG, REP or DELETED, we don't have the original content of block, */ 493 : /* and we must try to recover it. */ @@ -591,24 +591,24 @@ 529 : /* it also applies to CHG and DELETE blocks because we want to have */ 530 : /* a successful recovering only if a BLK one is matching */ 531 9044 : failed[j].is_outofdate = 1; - 532 171180 : } else if (failed[j].is_bad) { + 532 171272 : } else if (failed[j].is_bad) { 533 : /* If the block is bad we don't know its content, and we try to recover it */ 534 : /* At this point, we can have only BLK ones */ 535 : - 536 171180 : assert(block_state == BLOCK_STATE_BLK); + 536 171272 : assert(block_state == BLOCK_STATE_BLK); 537 : 538 : /* we have something we are interested to recover */ - 539 171180 : something_to_recover = 1; + 539 171272 : something_to_recover = 1; 540 : 541 : /* we try to recover it */ - 542 171180 : failed_map[n] = j; - 543 171180 : ++n; + 542 171272 : failed_map[n] = j; + 543 171272 : ++n; 544 : } 545 : } 546 : 547 : /* if nothing to fix, we just don't try */ 548 : /* if nothing unsynced we also don't retry, because it's the same try as before */ - 549 52449 : if (something_to_recover && something_unsynced) { + 549 52500 : if (something_to_recover && something_unsynced) { 550 9044 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); 551 9044 : if (ret == 0) { 552 : /* reprocess the REP and CHG blocks, for which we have recovered an old state */ @@ -642,17 +642,17 @@ 580 : else 581 0 : log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret); 582 : } else { - 583 43405 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, + 583 43456 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, 584 : !something_to_recover ? " nothing to recover" : "", 585 : !something_unsynced ? " nothing unsynced" : "" 586 : ); 587 : } 588 : 589 : /* return the number of failed attempts, or -1 if no strategy */ - 590 47927 : if (error) - 591 4806 : return error; + 590 47978 : if (error) + 591 4816 : return error; 592 : else - 593 43121 : return -1; + 593 43162 : return -1; 594 : } 595 : 596 : /** @@ -686,7 +686,7 @@ 624 5469678 : disk = handle[j].disk; 625 5469678 : if (!disk) { 626 : /* if no disk, nothing to do */ - 627 3341616 : continue; + 627 3341619 : continue; 628 : } 629 : 630 5455617 : block = fs_par2block_find(disk, i); @@ -700,35 +700,35 @@ 638 : /* if it isn't the last block in the file */ 639 5245100 : if (!file_block_is_last(file, file_pos)) { 640 : /* nothing to do */ - 641 3117038 : continue; + 641 3117041 : continue; 642 : } 643 : 644 : /* if the file is excluded, we have nothing to adjust as the file is never written */ - 645 2128062 : if (file_flag_has(file, FILE_IS_EXCLUDED) - 646 2070660 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) { + 645 2128059 : if (file_flag_has(file, FILE_IS_EXCLUDED) + 646 2070705 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) { 647 : /* nothing to do, but close the file */ - 648 57402 : goto close_and_continue; + 648 57354 : goto close_and_continue; 649 : } 650 : 651 : /* finish the fix process if it's the last block of the files */ - 652 2070660 : if (fix) { + 652 2070705 : if (fix) { 653 : /* mark that we finished with this file */ 654 : /* to identify later any NOT finished ones */ - 655 765508 : file_flag_set(file, FILE_IS_FINISHED); + 655 765553 : file_flag_set(file, FILE_IS_FINISHED); 656 : 657 : /* if the file is damaged, meaning that a fix failed */ - 658 765508 : if (file_flag_has(file, FILE_IS_DAMAGED)) { + 658 765553 : if (file_flag_has(file, FILE_IS_DAMAGED)) { 659 : /* rename it to .unrecoverable */ 660 : char path[PATH_MAX]; 661 : char path_to[PATH_MAX]; 662 : - 663 63262 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); - 664 63262 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); + 663 63301 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + 664 63301 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); 665 : 666 : /* ensure to close the file before renaming */ - 667 63262 : if (handle[j].file == file) { - 668 63262 : ret = handle_close(&handle[j]); - 669 63262 : if (ret != 0) { + 667 63301 : if (handle[j].file == file) { + 668 63301 : ret = handle_close(&handle[j]); + 669 63301 : if (ret != 0) { 670 : /* LCOV_EXCL_START */ 671 : log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 672 : log_fatal_errno(errno, disk->name); @@ -737,8 +737,8 @@ 675 : } 676 : } 677 : - 678 63262 : ret = rename(path, path_to); - 679 63262 : if (ret != 0) { + 678 63301 : ret = rename(path, path_to); + 679 63301 : if (ret != 0) { 680 : /* LCOV_EXCL_START */ 681 : log_fatal(errno, "Error renaming '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno)); 682 : log_tag("%s:%u:%s:%s: Rename error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); @@ -747,22 +747,22 @@ 685 : /* LCOV_EXCL_STOP */ 686 : } 687 : - 688 63262 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 689 63262 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 688 63301 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 689 63301 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); 690 : 691 : /* and do not set the time if damaged */ - 692 63262 : goto close_and_continue; + 692 63301 : goto close_and_continue; 693 : } 694 : 695 : /* if the file is not fixed, meaning that it is untouched */ - 696 702246 : if (!file_flag_has(file, FILE_IS_FIXED)) { + 696 702252 : if (!file_flag_has(file, FILE_IS_FIXED)) { 697 : /* nothing to do, but close the file */ - 698 581072 : goto close_and_continue; + 698 581048 : goto close_and_continue; 699 : } 700 : 701 : /* if the file is closed or different than the one expected, reopen it */ 702 : /* a different open file could happen when filtering for bad blocks */ - 703 121174 : if (handle[j].file != file) { + 703 121204 : if (handle[j].file != file) { 704 : /* keep a pointer at the file we are going to close for error reporting */ 705 0 : struct snapraid_file* report = handle[j].file; 706 0 : ret = handle_close(&handle[j]); @@ -786,13 +786,13 @@ 724 : } 725 : } 726 : - 727 121174 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 728 121174 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); + 727 121204 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 728 121204 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); 729 : - 730 121174 : inode = handle[j].st.st_ino; + 730 121204 : inode = handle[j].st.st_ino; 731 : 732 : /* search for the corresponding inode */ - 733 121174 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + 733 121204 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); 734 : 735 : /* if the inode is already in the database and it refers to a different file name, */ 736 : /* we can fix the file time ONLY if the time and size allow to differentiate */ @@ -802,15 +802,15 @@ 740 : /* when recreating them the inodes may be reused in a different order, */ 741 : /* and at the next sync some files may have matching inode/size/time even if different name */ 742 : /* not allowing sync to detect that the file is changed and not renamed */ - 743 121174 : if (!collide_file /* if not in the database, there is no collision */ - 744 42214 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ - 745 33405 : || collide_file->size != file->size /* if the size is different, the collision is identified */ + 743 121204 : if (!collide_file /* if not in the database, there is no collision */ + 744 44180 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ + 745 35319 : || collide_file->size != file->size /* if the size is different, the collision is identified */ 746 9 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ - 747 5 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ + 747 8 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ 748 : ) { 749 : /* set the original modification time */ - 750 121173 : ret = handle_utime(&handle[j]); - 751 121173 : if (ret == -1) { + 750 121204 : ret = handle_utime(&handle[j]); + 751 121204 : if (ret == -1) { 752 : /* LCOV_EXCL_START */ 753 : log_tag("%s:%u:%s:%s: Time error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 754 : log_fatal_errno(errno, disk->name); @@ -821,35 +821,35 @@ 759 : /* LCOV_EXCL_STOP */ 760 : } 761 : } else { - 762 1 : log_tag("collision:%s:%s:%s: Not setting modification time to avoid inode collision\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(collide_file->sub, esc_buffer_alt)); + 762 0 : log_tag("collision:%s:%s:%s: Not setting modification time to avoid inode collision\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(collide_file->sub, esc_buffer_alt)); 763 : } 764 : } else { 765 : /* we are not fixing, but only checking */ 766 : /* print just the final status */ 767 1305152 : if (file_flag_has(file, FILE_IS_DAMAGED)) { - 768 9430 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 769 9430 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); - 770 1295722 : } else if (file_flag_has(file, FILE_IS_FIXED)) { - 771 76206 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 772 76206 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 768 9483 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 769 9483 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 770 1295669 : } else if (file_flag_has(file, FILE_IS_FIXED)) { + 771 76272 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 772 76272 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); 773 : } else { 774 : /* we don't use msg_verbose() because it also goes into the log */ - 775 1219516 : if (msg_level >= MSG_VERBOSE) { - 776 20373 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 777 20373 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer)); + 775 1219397 : if (msg_level >= MSG_VERBOSE) { + 776 20355 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 777 20355 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer)); 778 : } 779 : } 780 : } 781 : - 782 1199143 : close_and_continue: + 782 1199042 : close_and_continue: 783 : /* if the opened file is the correct one, close it */ 784 : /* in case of excluded and fragmented files it's possible */ 785 : /* that the opened file is not the current one */ - 786 2128062 : if (handle[j].file == file) { + 786 2128059 : if (handle[j].file == file) { 787 : /* ensure to close the file just after finishing with it */ 788 : /* to avoid keeping it open without any possible use */ - 789 1986088 : ret = handle_close(&handle[j]); - 790 1986088 : if (ret != 0) { + 789 1986081 : ret = handle_close(&handle[j]); + 790 1986081 : if (ret != 0) { 791 : /* LCOV_EXCL_START */ 792 : log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 793 : log_fatal_errno(errno, disk->name); @@ -902,7 +902,7 @@ 840 : * the bad blocks. 841 : */ 842 9374 : if (info_get_bad(info)) - 843 1771 : return 1; + 843 1772 : return 1; 844 : } else { 845 : /* if a parity is not excluded, include all blocks, even unused ones */ 846 1061137 : for (l = 0; l < state->level; ++l) { @@ -913,21 +913,21 @@ 851 : } 852 : 853 : /* filter for the files */ - 854 238634 : for (j = 0; j < diskmax; ++j) { + 854 238648 : for (j = 0; j < diskmax; ++j) { 855 : struct snapraid_block* block; 856 : 857 : /* if no disk, nothing to check */ - 858 214768 : if (!handle[j].disk) + 858 214782 : if (!handle[j].disk) 859 0 : continue; 860 : - 861 214768 : block = fs_par2block_find(handle[j].disk, i); + 861 214782 : block = fs_par2block_find(handle[j].disk, i); 862 : 863 : /* try to recover all files, even the ones without hash */ 864 : /* because in some cases we can recover also them */ - 865 214768 : if (block_has_file(block)) { - 866 210845 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); - 867 210845 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ - 868 25427 : return 1; + 865 214782 : if (block_has_file(block)) { + 866 210859 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); + 867 210859 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ + 868 25426 : return 1; 869 : } 870 : } 871 : } @@ -1068,7 +1068,7 @@ 1006 5469678 : if (!disk) { 1007 : /* use an empty block */ 1008 14061 : memset(buffer[j], 0, state->block_size); - 1009 940909 : continue; + 1009 941260 : continue; 1010 : } 1011 : 1012 : /* if the disk block is not used */ @@ -1127,9 +1127,9 @@ 1065 : /* if the file is closed or different than the current one */ 1066 5245100 : if (handle[j].file == 0 || handle[j].file != file) { 1067 : /* keep a pointer at the file we are going to close for error reporting */ - 1068 2259176 : struct snapraid_file* report = handle[j].file; - 1069 2259176 : ret = handle_close(&handle[j]); - 1070 2259176 : if (ret == -1) { + 1068 2259318 : struct snapraid_file* report = handle[j].file; + 1069 2259318 : ret = handle_close(&handle[j]); + 1070 2259318 : if (ret == -1) { 1071 : /* LCOV_EXCL_START */ 1072 : log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); 1073 : log_fatal_errno(errno, disk->name); @@ -1141,10 +1141,10 @@ 1079 : } 1080 : 1081 : /* if fixing, and the file is not excluded, we must open for writing */ - 1082 2259176 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1082 2259318 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { 1083 : /* if fixing, create the file, open for writing and resize if required */ - 1084 771292 : ret = handle_create(&handle[j], file, state->file_mode); - 1085 771292 : if (ret == -1) { + 1084 771350 : ret = handle_create(&handle[j], file, state->file_mode); + 1085 771350 : if (ret == -1) { 1086 : /* LCOV_EXCL_START */ 1087 : log_tag("%s:%u:%s:%s: Create error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 1088 : log_fatal_errno(errno, disk->name); @@ -1156,75 +1156,75 @@ 1094 : } 1095 : 1096 : /* check if the file was just created */ - 1097 771292 : if (handle[j].created != 0) { + 1097 771350 : if (handle[j].created != 0) { 1098 : /* if fragmented, it may be reopened, so remember that the file */ 1099 : /* was originally missing */ - 1100 113113 : file_flag_set(file, FILE_IS_CREATED); + 1100 113069 : file_flag_set(file, FILE_IS_CREATED); 1101 : } 1102 : } else { 1103 : /* open the file only for reading */ - 1104 1487884 : if (!file_flag_has(file, FILE_IS_MISSING)) { - 1105 1372280 : ret = handle_open(&handle[j], file, state->file_mode, log_error, state->opt.expected_missing ? log_expected : 0); + 1104 1487968 : if (!file_flag_has(file, FILE_IS_MISSING)) { + 1105 1372199 : ret = handle_open(&handle[j], file, state->file_mode, log_error, state->opt.expected_missing ? log_expected : 0); 1106 : } else { - 1107 115604 : errno = ENOENT; - 1108 115604 : ret = -1; /* if the file is missing, we cannot open it */ + 1107 115769 : errno = ENOENT; + 1108 115769 : ret = -1; /* if the file is missing, we cannot open it */ 1109 : } - 1110 1487884 : if (ret == -1) { + 1110 1487968 : if (ret == -1) { 1111 : /* save the failed block for the check/fix */ - 1112 194317 : failed[failed_count].is_bad = 1; - 1113 194317 : failed[failed_count].is_outofdate = 0; - 1114 194317 : failed[failed_count].index = j; - 1115 194317 : failed[failed_count].block = block; - 1116 194317 : failed[failed_count].disk = disk; - 1117 194317 : failed[failed_count].file = file; - 1118 194317 : failed[failed_count].file_pos = file_pos; - 1119 194317 : failed[failed_count].handle = &handle[j]; - 1120 194317 : ++failed_count; + 1112 194447 : failed[failed_count].is_bad = 1; + 1113 194447 : failed[failed_count].is_outofdate = 0; + 1114 194447 : failed[failed_count].index = j; + 1115 194447 : failed[failed_count].block = block; + 1116 194447 : failed[failed_count].disk = disk; + 1117 194447 : failed[failed_count].file = file; + 1118 194447 : failed[failed_count].file_pos = file_pos; + 1119 194447 : failed[failed_count].handle = &handle[j]; + 1120 194447 : ++failed_count; 1121 : - 1122 194317 : log_tag("%s:%u:%s:%s: Open error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); + 1122 194447 : log_tag("%s:%u:%s:%s: Open error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); 1123 : - 1124 194317 : if (is_hw(errno)) { + 1124 194447 : if (is_hw(errno)) { 1125 0 : ++io_error; 1126 : } else { - 1127 194317 : ++soft_error; + 1127 194447 : ++soft_error; 1128 : } 1129 : 1130 : /* mark the file as missing, to avoid to retry to open it again */ 1131 : /* note that this can be done only if we are not fixing it */ 1132 : /* otherwise, it could be recreated */ - 1133 194317 : file_flag_set(file, FILE_IS_MISSING); - 1134 194317 : continue; + 1133 194447 : file_flag_set(file, FILE_IS_MISSING); + 1134 194447 : continue; 1135 : } 1136 : } 1137 : 1138 : /* if it's the first open, and not excluded */ - 1139 2064859 : if (!file_flag_has(file, FILE_IS_OPENED) - 1140 2049425 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1139 2064871 : if (!file_flag_has(file, FILE_IS_OPENED) + 1140 2049466 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { 1141 : 1142 : /* check if the file is changed */ - 1143 1995721 : if (handle[j].st.st_size != file->size - 1144 1802900 : || handle[j].st.st_mtime != file->mtime_sec - 1145 1779966 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec + 1143 1995801 : if (handle[j].st.st_size != file->size + 1144 1803079 : || handle[j].st.st_mtime != file->mtime_sec + 1145 1780127 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec 1146 : /* don't check the inode to support file-system without persistent inodes */ 1147 : ) { 1148 : /* report that the file is not synced */ - 1149 215755 : file_flag_set(file, FILE_IS_UNSYNCED); + 1149 215674 : file_flag_set(file, FILE_IS_UNSYNCED); 1150 : } 1151 : } 1152 : 1153 : /* if it's the first open, and not excluded and larger */ - 1154 2064859 : if (!file_flag_has(file, FILE_IS_OPENED) - 1155 2049425 : && !file_flag_has(file, FILE_IS_EXCLUDED) - 1156 1995721 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) - 1157 1995721 : && handle[j].st.st_size > file->size + 1154 2064871 : if (!file_flag_has(file, FILE_IS_OPENED) + 1155 2049466 : && !file_flag_has(file, FILE_IS_EXCLUDED) + 1156 1995801 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) + 1157 1995801 : && handle[j].st.st_size > file->size 1158 : ) { - 1159 8795 : log_error(ESOFT, "File '%s' is larger than expected.\n", handle[j].path); - 1160 8795 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); - 1161 8795 : ++soft_error; + 1159 8695 : log_error(ESOFT, "File '%s' is larger than expected.\n", handle[j].path); + 1160 8695 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + 1161 8695 : ++soft_error; 1162 : - 1163 8795 : if (fix) { - 1164 3256 : ret = handle_truncate(&handle[j], file); - 1165 3256 : if (ret == -1) { + 1163 8695 : if (fix) { + 1164 3213 : ret = handle_truncate(&handle[j], file); + 1165 3213 : if (ret == -1) { 1166 : /* LCOV_EXCL_START */ 1167 : log_tag("%s:%u:%s:%s: Truncate error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 1168 : log_fatal_errno(errno, disk->name); @@ -1235,58 +1235,58 @@ 1173 : /* LCOV_EXCL_STOP */ 1174 : } 1175 : - 1176 3256 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer)); - 1177 3256 : ++recovered_error; + 1176 3213 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + 1177 3213 : ++recovered_error; 1178 : } 1179 : } 1180 : 1181 : /* mark the file as opened at least one time */ 1182 : /* this is used to avoid to check the unsynced and size */ 1183 : /* more than one time, in case the file is reopened later */ - 1184 2064859 : file_flag_set(file, FILE_IS_OPENED); + 1184 2064871 : file_flag_set(file, FILE_IS_OPENED); 1185 : } 1186 : 1187 : /* read from the file */ - 1188 5050783 : if (file_flag_has(file, FILE_IS_MISSING)) { + 1188 5050653 : if (file_flag_has(file, FILE_IS_MISSING)) { 1189 : /* if the file is reported missing, don't even try to read it */ - 1190 256474 : errno = ENOENT; - 1191 256474 : read_size = -1; + 1190 256551 : errno = ENOENT; + 1191 256551 : read_size = -1; 1192 : } else { - 1193 4794309 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, state->opt.expected_missing ? log_expected : 0); + 1193 4794102 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, state->opt.expected_missing ? log_expected : 0); 1194 : } - 1195 5050783 : if (read_size == -1) { + 1195 5050653 : if (read_size == -1) { 1196 : /* save the failed block for the check/fix */ - 1197 442171 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ - 1198 442171 : failed[failed_count].is_outofdate = 0; - 1199 442171 : failed[failed_count].index = j; - 1200 442171 : failed[failed_count].block = block; - 1201 442171 : failed[failed_count].disk = disk; - 1202 442171 : failed[failed_count].file = file; - 1203 442171 : failed[failed_count].file_pos = file_pos; - 1204 442171 : failed[failed_count].handle = &handle[j]; - 1205 442171 : ++failed_count; + 1197 442068 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ + 1198 442068 : failed[failed_count].is_outofdate = 0; + 1199 442068 : failed[failed_count].index = j; + 1200 442068 : failed[failed_count].block = block; + 1201 442068 : failed[failed_count].disk = disk; + 1202 442068 : failed[failed_count].file = file; + 1203 442068 : failed[failed_count].file_pos = file_pos; + 1204 442068 : failed[failed_count].handle = &handle[j]; + 1205 442068 : ++failed_count; 1206 : - 1207 442171 : log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); + 1207 442068 : log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); 1208 : - 1209 442171 : if (is_hw(errno)) { + 1209 442068 : if (is_hw(errno)) { 1210 0 : ++io_error; 1211 : } else { - 1212 442171 : ++soft_error; + 1212 442068 : ++soft_error; 1213 : } 1214 : 1215 : /* if we are reading at the end, mark the file as missing to avoid to try to read it again at the next block */ - 1216 442171 : if (errno == ENOENT) { - 1217 432266 : file_flag_set(file, FILE_IS_MISSING); + 1216 442068 : if (errno == ENOENT) { + 1217 432259 : file_flag_set(file, FILE_IS_MISSING); 1218 : } - 1219 442171 : continue; + 1219 442068 : continue; 1220 : } 1221 : - 1222 4608612 : countsize += read_size; + 1222 4608585 : countsize += read_size; 1223 : 1224 : /* always insert CHG blocks, the repair functions needs all of them */ 1225 : /* because the parity may be still referring at the old state */ 1226 : /* and the repair must be aware of it */ - 1227 4608612 : if (block_state == BLOCK_STATE_CHG) { + 1227 4608585 : if (block_state == BLOCK_STATE_CHG) { 1228 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */ 1229 : /* if we don't have a hash, we always assume the first read of the block correct. */ 1230 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ @@ -1301,39 +1301,39 @@ 1239 13843 : continue; 1240 : } 1241 : - 1242 4594769 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 1242 4594742 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); 1243 : 1244 : /* compute the hash of the block just read */ - 1245 4594769 : if (rehash) { + 1245 4594742 : if (rehash) { 1246 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); 1247 : } else { - 1248 4567526 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 1248 4567499 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); 1249 : } 1250 : 1251 : /* compare the hash */ - 1252 4594769 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { - 1253 12572 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + 1252 4594742 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 1253 12896 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); 1254 : 1255 : /* save the failed block for the check/fix */ - 1256 12572 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ - 1257 12572 : failed[failed_count].is_outofdate = 0; - 1258 12572 : failed[failed_count].index = j; - 1259 12572 : failed[failed_count].block = block; - 1260 12572 : failed[failed_count].disk = disk; - 1261 12572 : failed[failed_count].file = file; - 1262 12572 : failed[failed_count].file_pos = file_pos; - 1263 12572 : failed[failed_count].handle = &handle[j]; - 1264 12572 : ++failed_count; + 1256 12896 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ + 1257 12896 : failed[failed_count].is_outofdate = 0; + 1258 12896 : failed[failed_count].index = j; + 1259 12896 : failed[failed_count].block = block; + 1260 12896 : failed[failed_count].disk = disk; + 1261 12896 : failed[failed_count].file = file; + 1262 12896 : failed[failed_count].file_pos = file_pos; + 1263 12896 : failed[failed_count].handle = &handle[j]; + 1264 12896 : ++failed_count; 1265 : - 1266 12572 : log_tag("error:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); - 1267 12572 : ++silent_error; - 1268 12572 : continue; + 1266 12896 : log_tag("error:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + 1267 12896 : ++silent_error; + 1268 12896 : continue; 1269 : } 1270 : 1271 : /* always insert REP blocks, the repair functions needs all of them */ 1272 : /* because the parity may be still referring at the old state */ 1273 : /* and the repair must be aware of it */ - 1274 4582197 : if (block_state == BLOCK_STATE_REP) { + 1274 4581846 : if (block_state == BLOCK_STATE_REP) { 1275 53428 : failed[failed_count].is_bad = 0; /* it's not bad */ 1276 53428 : failed[failed_count].is_outofdate = 0; 1277 53428 : failed[failed_count].index = j; @@ -1385,35 +1385,35 @@ 1323 872338 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); 1324 872338 : if (ret != 0) { 1325 : /* increment the number of errors */ - 1326 47927 : if (ret > 0) - 1327 4806 : silent_error += ret; - 1328 47927 : ++unrecoverable_error; + 1326 47978 : if (ret > 0) + 1327 4816 : silent_error += ret; + 1328 47978 : ++unrecoverable_error; 1329 : 1330 : /* print a list of all the errors in files */ - 1331 219107 : for (j = 0; j < failed_count; ++j) { - 1332 171180 : if (failed[j].is_bad) - 1333 166658 : 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); + 1331 219250 : for (j = 0; j < failed_count; ++j) { + 1332 171272 : if (failed[j].is_bad) + 1333 166750 : 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); 1334 : } 1335 : 1336 : /* keep track of damaged files */ - 1337 219107 : for (j = 0; j < failed_count; ++j) { - 1338 171180 : if (failed[j].is_bad) - 1339 166658 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1337 219250 : for (j = 0; j < failed_count; ++j) { + 1338 171272 : if (failed[j].is_bad) + 1339 166750 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); 1340 : } 1341 : } else { 1342 : /* now counts partial recovers */ 1343 : /* note that this could happen only when we have an incomplete 'sync' */ 1344 : /* and that we have recovered is the state before the 'sync' */ - 1345 824411 : int partial_recover_error = 0; + 1345 824360 : int partial_recover_error = 0; 1346 : 1347 : /* print a list of all the errors in files */ - 1348 1382186 : for (j = 0; j < failed_count; ++j) { - 1349 557775 : if (failed[j].is_bad && failed[j].is_outofdate) { + 1348 1382300 : for (j = 0; j < failed_count; ++j) { + 1349 557940 : if (failed[j].is_bad && failed[j].is_outofdate) { 1350 8 : ++partial_recover_error; 1351 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); 1352 : } 1353 : } - 1354 824411 : if (partial_recover_error != 0) { + 1354 824360 : if (partial_recover_error != 0) { 1355 8 : silent_error += partial_recover_error; 1356 8 : ++unrecoverable_error; 1357 : } @@ -1427,36 +1427,36 @@ 1365 : * It's also OK to have data errors on unused parity, because sync doesn't 1366 : * update it. 1367 : */ - 1368 824411 : if (used_parity && valid_parity) { + 1368 824360 : if (used_parity && valid_parity) { 1369 : /* check the parity */ - 1370 3738622 : for (l = 0; l < state->level; ++l) { - 1371 2975796 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { - 1372 21250 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); + 1370 3738520 : for (l = 0; l < state->level; ++l) { + 1371 2975745 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { + 1372 21240 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); 1373 : 1374 : /* mark that the read parity is wrong, setting ptr to 0 */ - 1375 21250 : buffer_recov[l] = 0; + 1375 21240 : buffer_recov[l] = 0; 1376 : - 1377 21250 : log_tag("parity_error:%u:%s: Data error, diff parity bits %u/%u\n", i, lev_config_name(l), diff, state->block_size * 8); - 1378 21250 : ++silent_error; + 1377 21240 : log_tag("parity_error:%u:%s: Data error, diff parity bits %u/%u\n", i, lev_config_name(l), diff, state->block_size * 8); + 1378 21240 : ++silent_error; 1379 : } 1380 : } 1381 : } 1382 : 1383 : /* now write recovered files */ - 1384 824411 : if (fix) { + 1384 824360 : if (fix) { 1385 : /* update the fixed files */ - 1386 655355 : for (j = 0; j < failed_count; ++j) { + 1386 655347 : for (j = 0; j < failed_count; ++j) { 1387 : /* nothing to do if it doesn't need recovering */ - 1388 338027 : if (!failed[j].is_bad) + 1388 338061 : if (!failed[j].is_bad) 1389 40318 : continue; 1390 : 1391 : /* do not fix if the file is excluded */ - 1392 297709 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) - 1393 288429 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) + 1392 297743 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) + 1393 288463 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) 1394 9280 : continue; 1395 : - 1396 288429 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); - 1397 288429 : if (ret == -1) { + 1396 288463 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); + 1397 288463 : if (ret == -1) { 1398 : /* LCOV_EXCL_START */ 1399 : log_tag("%s:%u:%s:%s: Write error. %s.\n", es(errno), i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), strerror(errno)); 1400 : log_fatal_errno(errno, failed[j].disk->name); @@ -1471,7 +1471,7 @@ 1409 : } 1410 : 1411 : /* if we are not sure that the recovered content is uptodate */ - 1412 288429 : if (failed[j].is_outofdate) { + 1412 288463 : if (failed[j].is_outofdate) { 1413 : /* mark the file as damaged */ 1414 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); 1415 8 : continue; @@ -1479,10 +1479,10 @@ 1417 : 1418 : /* mark the file as containing some fixes */ 1419 : /* note that it could be also marked as damaged in other iterations */ - 1420 288421 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1420 288455 : file_flag_set(failed[j].file, FILE_IS_FIXED); 1421 : - 1422 288421 : 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); - 1423 288421 : ++recovered_error; + 1422 288455 : 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); + 1423 288455 : ++recovered_error; 1424 : } 1425 : 1426 : /* @@ -1495,11 +1495,11 @@ 1433 : * we already have allocated space for it on parity file creation, 1434 : * and its content doesn't matter. 1435 : */ - 1436 317328 : if (used_parity && valid_parity) { + 1436 317286 : if (used_parity && valid_parity) { 1437 : /* update the parity */ - 1438 982581 : for (l = 0; l < state->level; ++l) { + 1438 982497 : for (l = 0; l < state->level; ++l) { 1439 : /* if the parity on disk is wrong */ - 1440 714433 : if (buffer_recov[l] == 0 + 1440 714391 : if (buffer_recov[l] == 0 1441 : /* and we have access at the parity */ 1442 72150 : && parity[l] != 0 1443 : /* and the parity is not excluded */ @@ -1525,9 +1525,9 @@ 1463 : } else { 1464 : /* if we are not fixing, we just set the FIXED flag */ 1465 : /* meaning that we could fix this file if we try */ - 1466 726831 : for (j = 0; j < failed_count; ++j) { - 1467 219748 : if (failed[j].is_bad) { - 1468 178863 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1466 726953 : for (j = 0; j < failed_count; ++j) { + 1467 219879 : if (failed[j].is_bad) { + 1468 178994 : file_flag_set(failed[j].file, FILE_IS_FIXED); 1469 : } 1470 : } 1471 : } @@ -1535,9 +1535,9 @@ 1473 : } else { 1474 : /* if we are not checking, we just set the DAMAGED flag */ 1475 : /* to report that the file is damaged, and we don't know if we can fix it */ - 1476 45105 : for (j = 0; j < failed_count; ++j) { - 1477 5830 : if (failed[j].is_bad) { - 1478 5830 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1476 45199 : for (j = 0; j < failed_count; ++j) { + 1477 5924 : if (failed[j].is_bad) { + 1478 5924 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); 1479 : } 1480 : } 1481 : } @@ -1613,23 +1613,23 @@ 1551 2779 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); 1552 2779 : ret = stat(path, &st); 1553 2779 : if (ret == -1) { - 1554 179 : unsuccessful = 1; + 1554 176 : unsuccessful = 1; 1555 : - 1556 179 : log_error(errno, "Error stating empty file '%s'. %s.\n", path, strerror(errno)); - 1557 179 : log_tag("empty_%s:%s:%s: Empty file stat error\n", es(errno), disk->name, esc_tag(file->sub, esc_buffer)); + 1556 176 : log_error(errno, "Error stating empty file '%s'. %s.\n", path, strerror(errno)); + 1557 176 : log_tag("empty_%s:%s:%s: Empty file stat error\n", es(errno), disk->name, esc_tag(file->sub, esc_buffer)); 1558 : - 1559 179 : if (is_hw(errno)) { + 1559 176 : if (is_hw(errno)) { 1560 0 : ++io_error; 1561 : } else { - 1562 179 : ++soft_error; + 1562 176 : ++soft_error; 1563 : } - 1564 2600 : } else if (!S_ISREG(st.st_mode)) { + 1564 2603 : } else if (!S_ISREG(st.st_mode)) { 1565 0 : unsuccessful = 1; 1566 : 1567 0 : log_error(ESOFT, "Error stating empty file '%s' for not regular file.\n", path); 1568 0 : log_tag("empty_error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer)); 1569 0 : ++soft_error; - 1570 2600 : } else if (st.st_size != 0) { + 1570 2603 : } else if (st.st_size != 0) { 1571 5 : unsuccessful = 1; 1572 : 1573 5 : log_error(ESOFT, "Error stating empty file '%s' for not empty file.\n", path); @@ -1641,8 +1641,8 @@ 1579 : int f; 1580 : 1581 : /* create the ancestor directories */ - 1582 159 : ret = mkancestor(path); - 1583 159 : if (ret != 0) { + 1582 158 : ret = mkancestor(path); + 1583 158 : if (ret != 0) { 1584 : /* LCOV_EXCL_START */ 1585 : log_fatal(errno, "Error creating ancestor '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno)); 1586 : log_tag("empty_%s:%u:%s:%s: Create ancestor error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); @@ -1656,8 +1656,8 @@ 1594 : 1595 : /* create it */ 1596 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ - 1597 159 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); - 1598 159 : if (f == -1) { + 1597 158 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); + 1598 158 : if (f == -1) { 1599 : /* LCOV_EXCL_START */ 1600 : log_fatal(errno, "Error creating '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno)); 1601 : log_tag("empty_%s:%u:%s:%s: Create error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); @@ -1670,8 +1670,8 @@ 1608 : } 1609 : 1610 : /* set the original modification time */ - 1611 159 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec); - 1612 159 : if (ret != 0) { + 1611 158 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec); + 1612 158 : if (ret != 0) { 1613 : /* LCOV_EXCL_START */ 1614 : log_fatal(errno, "Error timing '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno)); 1615 : log_tag("empty_%s:%u:%s:%s: Time error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); @@ -1686,8 +1686,8 @@ 1624 : } 1625 : 1626 : /* close it */ - 1627 159 : ret = close(f); - 1628 159 : if (ret != 0) { + 1627 158 : ret = close(f); + 1628 158 : if (ret != 0) { 1629 : /* LCOV_EXCL_START */ 1630 : log_fatal(errno, "Error closing '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno)); 1631 : log_tag("empty_%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); @@ -1699,11 +1699,11 @@ 1637 : /* LCOV_EXCL_STOP */ 1638 : } 1639 : - 1640 159 : log_tag("empty_fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1641 159 : ++recovered_error; + 1640 158 : log_tag("empty_fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1641 158 : ++recovered_error; 1642 : - 1643 159 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1644 159 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); + 1643 158 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1644 158 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); 1645 : } 1646 : } 1647 : @@ -1795,30 +1795,30 @@ 1733 66426 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); 1734 66426 : ret = readlink(path, linkto, sizeof(linkto)); 1735 66426 : if (ret < 0) { - 1736 4279 : unsuccessful = 1; + 1736 4293 : unsuccessful = 1; 1737 : - 1738 4279 : log_error(errno, "Error reading symlink '%s'. %s.\n", path, strerror(errno)); - 1739 4279 : log_tag("symlink_%s:%s:%s: Symlink read error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno)); + 1738 4293 : log_error(errno, "Error reading symlink '%s'. %s.\n", path, strerror(errno)); + 1739 4293 : log_tag("symlink_%s:%s:%s: Symlink read error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno)); 1740 : - 1741 4279 : if (is_hw(errno)) { + 1741 4293 : if (is_hw(errno)) { 1742 0 : ++io_error; 1743 : } else { - 1744 4279 : ++soft_error; + 1744 4293 : ++soft_error; 1745 : } - 1746 62147 : } else if (ret >= PATH_MAX) { + 1746 62133 : } else if (ret >= PATH_MAX) { 1747 0 : unsuccessful = 1; 1748 : 1749 0 : log_error(ESOFT, "Error reading symlink '%s'. Symlink too long.\n", path); 1750 0 : log_tag("symlink_error:%s:%s: Symlink too long\n", disk->name, esc_tag(slink->sub, esc_buffer)); 1751 0 : ++soft_error; 1752 : } else { - 1753 62147 : linkto[ret] = 0; + 1753 62133 : linkto[ret] = 0; 1754 : - 1755 62147 : if (strcmp(linkto, slink->linkto) != 0) { - 1756 557 : unsuccessful = 1; + 1755 62133 : if (strcmp(linkto, slink->linkto) != 0) { + 1756 543 : unsuccessful = 1; 1757 : - 1758 557 : 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); - 1759 557 : ++soft_error; + 1758 543 : 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); + 1759 543 : ++soft_error; 1760 : } 1761 : } 1762 : } @@ -2018,9 +2018,9 @@ 1956 : } 1957 : 1958 : /* if processing was finished */ - 1959 113113 : if (file_flag_has(file, FILE_IS_FINISHED)) { + 1959 113069 : if (file_flag_has(file, FILE_IS_FINISHED)) { 1960 : /* nothing to do */ - 1961 113113 : continue; + 1961 113069 : continue; 1962 : } 1963 : 1964 : /* if the file was originally missing, and processing not yet finished */ diff --git a/cov/cmdline/device.c.func-sort-c.html b/cov/cmdline/device.c.func-sort-c.html index 31512a0d..27cd899a 100644 --- a/cov/cmdline/device.c.func-sort-c.html +++ b/cov/cmdline/device.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 345 + 363 409 - 84.4 % + 88.8 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 13 14 - 92.9 % + 14 + 100.0 % @@ -59,29 +59,29 @@ Function Name Sort by function name Hit count Sort by hit count - - smart_afr_value - 0 - - - poisson_prob_at_least_one_failure - 1 - state_smart 1 - state_probe + poisson_prob_at_least_one_failure 2 + + smart_afr_value + 2 + + + state_probe + 3 + state_stat - 4 + 5 state_device - 6 + 7 raid_prob_of_one_or_more_failures @@ -97,23 +97,23 @@ smart_afr - 72568 + 72582 state_info_log - 72570 + 72584 state_smart_ignore - 72570 + 72584 state_smart_log - 72570 + 72584 device_name_set - 72635 + 72647
diff --git a/cov/cmdline/device.c.func.html b/cov/cmdline/device.c.func.html index 5a10b9c1..f8820d32 100644 --- a/cov/cmdline/device.c.func.html +++ b/cov/cmdline/device.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 345 + 363 409 - 84.4 % + 88.8 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 13 14 - 92.9 % + 14 + 100.0 % @@ -61,7 +61,7 @@ device_name_set - 72635 + 72647 devtest @@ -69,7 +69,7 @@ poisson_prob_at_least_one_failure - 1 + 2 raid_prob_of_one_or_more_failures @@ -77,11 +77,11 @@ smart_afr - 72568 + 72582 smart_afr_value - 0 + 2 state_attr @@ -89,15 +89,15 @@ state_device - 6 + 7 state_info_log - 72570 + 72584 state_probe - 2 + 3 state_smart @@ -105,15 +105,15 @@ state_smart_ignore - 72570 + 72584 state_smart_log - 72570 + 72584 state_stat - 4 + 5
diff --git a/cov/cmdline/device.c.gcov.html b/cov/cmdline/device.c.gcov.html index 0ebe20f8..39031fe8 100644 --- a/cov/cmdline/device.c.gcov.html +++ b/cov/cmdline/device.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 345 + 363 409 - 84.4 % + 88.8 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 13 14 - 92.9 % + 14 + 100.0 % @@ -83,13 +83,13 @@ 21 : #include "state.h" 22 : #include "raid/raid.h" 23 : - 24 72635 : void device_name_set(devinfo_t* dev, const char* name, int index) + 24 72647 : void device_name_set(devinfo_t* dev, const char* name, int index) 25 : { - 26 72635 : if (index == 0) - 27 29054 : pathcpy(dev->name, sizeof(dev->name), name); + 26 72647 : if (index == 0) + 27 29066 : pathcpy(dev->name, sizeof(dev->name), name); 28 : else 29 43581 : pathprint(dev->name, sizeof(dev->name), "%s/%d", name, index); - 30 72635 : } + 30 72647 : } 31 : 32 : /** 33 : * The following are Failure Rate tables computed from the data that @@ -442,15 +442,15 @@ 380 : /** 381 : * Computes the estimated Annual Failure Rate from the specified table. 382 : */ - 383 0 : static double smart_afr_value(double* tab, unsigned step, uint64_t value) + 383 2 : static double smart_afr_value(double* tab, unsigned step, uint64_t value) 384 : { - 385 0 : value /= step; + 385 2 : value /= step; 386 : - 387 0 : if (value >= SMART_MEASURES) + 387 2 : if (value >= SMART_MEASURES) 388 0 : value = SMART_MEASURES - 1; 389 : 390 : /* table rates are for a month, so we scale to a year */ - 391 0 : return 365.0 / 30.0 * tab[value]; + 391 2 : return 365.0 / 30.0 * tab[value]; 392 : } 393 : 394 : /** @@ -470,31 +470,31 @@ 408 : * we use the maximum rate reported, and we do not sum them, 409 : * because the attributes are not independent. 410 : */ - 411 72568 : static double smart_afr(struct smart_attr* smart, const char* model) + 411 72582 : static double smart_afr(struct smart_attr* smart, const char* model) 412 : { - 413 72568 : double afr = 0; - 414 72568 : uint64_t mask32 = 0xffffffffU; - 415 72568 : uint64_t mask16 = 0xffffU; + 413 72582 : double afr = 0; + 414 72582 : uint64_t mask32 = 0xffffffffU; + 415 72582 : uint64_t mask16 = 0xffffU; 416 : 417 : /* do not estimate for not rotational */ - 418 72568 : if (smart[INFO_ROTATION_RATE].raw == 0) - 419 70149 : return 0; + 418 72582 : if (smart[INFO_ROTATION_RATE].raw == 0) + 419 70150 : return 0; 420 : - 421 2419 : if (smart[5].raw != SMART_UNASSIGNED) { - 422 0 : double r = smart_afr_value(SMART_5_R, SMART_5_STEP, smart[5].raw & mask32); - 423 0 : if (afr < r) - 424 0 : afr = r; + 421 2432 : if (smart[5].raw != SMART_UNASSIGNED) { + 422 1 : double r = smart_afr_value(SMART_5_R, SMART_5_STEP, smart[5].raw & mask32); + 423 1 : if (afr < r) + 424 1 : afr = r; 425 : } 426 : - 427 2419 : if (smart[187].raw != SMART_UNASSIGNED) { + 427 2432 : if (smart[187].raw != SMART_UNASSIGNED) { 428 : /* with some disks, only the lower 16 bits are significant */ 429 : /* See: http://web.archive.org/web/20130507072056/http://media.kingston.com/support/downloads/MKP_306_SMART_attribute.pdf */ - 430 0 : double r = smart_afr_value(SMART_187_R, SMART_187_STEP, smart[187].raw & mask16); - 431 0 : if (afr < r) - 432 0 : afr = r; + 430 1 : double r = smart_afr_value(SMART_187_R, SMART_187_STEP, smart[187].raw & mask16); + 431 1 : if (afr < r) + 432 1 : afr = r; 433 : } 434 : - 435 2419 : if ( + 435 2432 : if ( 436 : /** 437 : * Don't check Command_Timeout (188) for Seagate disks. 438 : * @@ -502,7 +502,7 @@ 440 : * and IronWolf disks to be a not significant test as 441 : * this value increases too often also on sane disks. 442 : */ - 443 2419 : strncmp(model, "ST", 2) != 0 && smart[188].raw != SMART_UNASSIGNED + 443 2432 : strncmp(model, "ST", 2) != 0 && smart[188].raw != SMART_UNASSIGNED 444 : ) { 445 : /* with Seagate disks, there are three different 16 bits value reported */ 446 : /* the lowest one is the most significant */ @@ -511,19 +511,19 @@ 449 0 : afr = r; 450 : } 451 : - 452 2419 : if (smart[197].raw != SMART_UNASSIGNED) { + 452 2432 : if (smart[197].raw != SMART_UNASSIGNED) { 453 0 : double r = smart_afr_value(SMART_197_R, SMART_197_STEP, smart[197].raw & mask32); 454 0 : if (afr < r) 455 0 : afr = r; 456 : } 457 : - 458 2419 : if (smart[198].raw != SMART_UNASSIGNED) { + 458 2432 : if (smart[198].raw != SMART_UNASSIGNED) { 459 0 : double r = smart_afr_value(SMART_198_R, SMART_198_STEP, smart[198].raw & mask32); 460 0 : if (afr < r) 461 0 : afr = r; 462 : } 463 : - 464 2419 : return afr; + 464 2432 : return afr; 465 : } 466 : 467 : /** @@ -533,9 +533,9 @@ 471 : * @param afr The aggregate Annual Failure Rate (lambda). 472 : * @return The probability as a double between 0 and 1. 473 : */ - 474 1 : static double poisson_prob_at_least_one_failure(double rate) + 474 2 : static double poisson_prob_at_least_one_failure(double rate) 475 : { - 476 1 : return 1.0 - exp(-rate); + 476 2 : return 1.0 - exp(-rate); 477 : } 478 : 479 : /** @@ -582,81 +582,81 @@ 520 0 : return poisson_prob_at_least_one_failure(raid_failure_rate); 521 : } 522 : - 523 72570 : static void state_info_log(devinfo_t* devinfo) + 523 72584 : static void state_info_log(devinfo_t* devinfo) 524 : { 525 : char esc_buffer[ESC_MAX]; 526 : - 527 72570 : log_tag("info:%s:%s\n", devinfo->file, devinfo->name); - 528 72570 : if (devinfo->serial[0]) - 529 72570 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->serial, esc_buffer)); - 530 72570 : if (devinfo->family[0]) - 531 72570 : log_tag("attr:%s:%s:family:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->family, esc_buffer)); - 532 72570 : if (devinfo->model[0]) - 533 72570 : log_tag("attr:%s:%s:model:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->model, esc_buffer)); - 534 72570 : if (devinfo->interf[0]) - 535 72570 : log_tag("attr:%s:%s:interface:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->interf, esc_buffer)); - 536 72570 : if (devinfo->info[INFO_SIZE] != SMART_UNASSIGNED) - 537 72570 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_SIZE]); - 538 72570 : if (devinfo->info[INFO_ROTATION_RATE] != SMART_UNASSIGNED) - 539 72570 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_ROTATION_RATE]); - 540 72570 : } + 527 72584 : log_tag("info:%s:%s\n", devinfo->file, devinfo->name); + 528 72584 : if (devinfo->serial[0]) + 529 72584 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->serial, esc_buffer)); + 530 72584 : if (devinfo->family[0]) + 531 72572 : log_tag("attr:%s:%s:family:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->family, esc_buffer)); + 532 72584 : if (devinfo->model[0]) + 533 72584 : log_tag("attr:%s:%s:model:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->model, esc_buffer)); + 534 72584 : if (devinfo->interf[0]) + 535 72572 : log_tag("attr:%s:%s:interface:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->interf, esc_buffer)); + 536 72584 : if (devinfo->info[INFO_SIZE] != SMART_UNASSIGNED) + 537 72584 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_SIZE]); + 538 72584 : if (devinfo->info[INFO_ROTATION_RATE] != SMART_UNASSIGNED) + 539 72584 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_ROTATION_RATE]); + 540 72584 : } 541 : - 542 72570 : static void state_smart_ignore(struct snapraid_state* state, devinfo_t* devinfo) + 542 72584 : static void state_smart_ignore(struct snapraid_state* state, devinfo_t* devinfo) 543 : { 544 : /* clear attributes to ignore */ - 545 362850 : for (int i = 0; i < SMART_IGNORE_MAX; ++i) { - 546 290280 : devinfo->smart[state->smartignore[i]].raw = SMART_UNASSIGNED; - 547 290280 : devinfo->smart[devinfo->smartignore[i]].raw = SMART_UNASSIGNED; + 545 362920 : for (int i = 0; i < SMART_IGNORE_MAX; ++i) { + 546 290336 : devinfo->smart[state->smartignore[i]].raw = SMART_UNASSIGNED; + 547 290336 : devinfo->smart[devinfo->smartignore[i]].raw = SMART_UNASSIGNED; 548 : } - 549 72570 : } + 549 72584 : } 550 : - 551 72570 : static void state_smart_log(devinfo_t* devinfo, double afr) + 551 72584 : static void state_smart_log(devinfo_t* devinfo, double afr) 552 : { 553 : unsigned j; 554 : - 555 72570 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); - 556 72570 : if (devinfo->smart[SMART_ERROR_PROTOCOL].raw != SMART_UNASSIGNED) - 557 72570 : log_tag("attr:%s:%s:error_protocol:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_PROTOCOL].raw); - 558 72570 : if (devinfo->smart[SMART_ERROR_MEDIUM].raw != SMART_UNASSIGNED) + 555 72584 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); + 556 72584 : if (devinfo->smart[SMART_ERROR_PROTOCOL].raw != SMART_UNASSIGNED) + 557 72572 : log_tag("attr:%s:%s:error_protocol:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_PROTOCOL].raw); + 558 72584 : if (devinfo->smart[SMART_ERROR_MEDIUM].raw != SMART_UNASSIGNED) 559 72570 : log_tag("attr:%s:%s:error_medium:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_MEDIUM].raw); - 560 72570 : if (devinfo->smart[SMART_WEAR_LEVEL].raw != SMART_UNASSIGNED) - 561 72570 : log_tag("attr:%s:%s:wear_level:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_WEAR_LEVEL].raw); - 562 72570 : if (devinfo->smart[SMART_FLAGS].raw != SMART_UNASSIGNED) - 563 19352 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS].raw, devinfo->smart[SMART_FLAGS].raw); + 560 72584 : if (devinfo->smart[SMART_WEAR_LEVEL].raw != SMART_UNASSIGNED) + 561 72571 : log_tag("attr:%s:%s:wear_level:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_WEAR_LEVEL].raw); + 562 72584 : if (devinfo->smart[SMART_FLAGS].raw != SMART_UNASSIGNED) + 563 19354 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS].raw, devinfo->smart[SMART_FLAGS].raw); 564 : - 565 72570 : if (afr != 0) - 566 0 : log_tag("attr:%s:%s:afr:%g:%g\n", devinfo->file, devinfo->name, afr, poisson_prob_at_least_one_failure(afr)); + 565 72584 : if (afr != 0) + 566 1 : log_tag("attr:%s:%s:afr:%g:%g\n", devinfo->file, devinfo->name, afr, poisson_prob_at_least_one_failure(afr)); 567 : - 568 18650490 : for (j = 0; j < 256; ++j) { - 569 18577920 : struct smart_attr* attr = &devinfo->smart[j]; - 570 18577920 : if (attr->raw != SMART_UNASSIGNED) { - 571 17890837 : const char* type = "";; - 572 17890837 : const char* updated = ""; - 573 17890837 : const char* when_failed = ""; + 568 18654088 : for (j = 0; j < 256; ++j) { + 569 18581504 : struct smart_attr* attr = &devinfo->smart[j]; + 570 18581504 : if (attr->raw != SMART_UNASSIGNED) { + 571 17890868 : const char* type = "";; + 572 17890868 : const char* updated = ""; + 573 17890868 : const char* when_failed = ""; 574 : - 575 17890837 : if (attr->flags & SMART_ATTR_TYPE_PREFAIL) - 576 0 : type = "prefail"; - 577 17890837 : else if (attr->flags & SMART_ATTR_TYPE_OLDAGE) - 578 0 : type = "oldage"; - 579 17890837 : if (attr->flags & SMART_ATTR_UPDATE_ALWAYS) - 580 0 : updated = "always"; - 581 17890837 : else if (attr->flags & SMART_ATTR_UPDATE_OFFLINE) - 582 0 : updated = "offline"; - 583 17890837 : if (attr->flags & SMART_ATTR_WHEN_FAILED_NOW) + 575 17890868 : if (attr->flags & SMART_ATTR_TYPE_PREFAIL) + 576 11 : type = "prefail"; + 577 17890857 : else if (attr->flags & SMART_ATTR_TYPE_OLDAGE) + 578 20 : type = "oldage"; + 579 17890868 : if (attr->flags & SMART_ATTR_UPDATE_ALWAYS) + 580 28 : updated = "always"; + 581 17890840 : else if (attr->flags & SMART_ATTR_UPDATE_OFFLINE) + 582 3 : updated = "offline"; + 583 17890868 : if (attr->flags & SMART_ATTR_WHEN_FAILED_NOW) 584 0 : when_failed = "now"; - 585 17890837 : else if (attr->flags & SMART_ATTR_WHEN_FAILED_PAST) + 585 17890868 : else if (attr->flags & SMART_ATTR_WHEN_FAILED_PAST) 586 0 : when_failed = "past"; - 587 17890837 : else if (attr->flags & SMART_ATTR_WHEN_FAILED_NEVER) - 588 0 : when_failed = "never"; + 587 17890868 : else if (attr->flags & SMART_ATTR_WHEN_FAILED_NEVER) + 588 31 : when_failed = "never"; 589 : - 590 17890837 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%s:%s:%s:%s\n", devinfo->file, devinfo->name, j, attr->raw, attr->raw, attr->norm, attr->worst, attr->thresh, attr->name, type, updated, when_failed); + 590 17890868 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%s:%s:%s:%s\n", devinfo->file, devinfo->name, j, attr->raw, attr->raw, attr->norm, attr->worst, attr->thresh, attr->name, type, updated, when_failed); 591 : } 592 : } 593 : - 594 72570 : int temp = smart_temp(devinfo); - 595 72570 : if (temp >= 0) - 596 72570 : log_tag("attr:%s:%s:temperature:%d\n", devinfo->file, devinfo->name, temp); - 597 72570 : } + 594 72584 : int temp = smart_temp(devinfo); + 595 72584 : if (temp >= 0) + 596 72572 : log_tag("attr:%s:%s:temperature:%d\n", devinfo->file, devinfo->name, temp); + 597 72584 : } 598 : 599 1 : static void state_smart(struct snapraid_state* state, unsigned n, tommy_list* low) 600 : { @@ -894,7 +894,7 @@ 832 : } 833 2416 : } 834 : - 835 2 : static void state_probe(struct snapraid_state* state, tommy_list* low) + 835 3 : static void state_probe(struct snapraid_state* state, tommy_list* low) 836 : { 837 : tommy_node* i; 838 : size_t device_pad; @@ -902,80 +902,80 @@ 840 : (void)state; 841 : 842 : /* compute lengths for padding */ - 843 2 : device_pad = 0; - 844 62 : for (i = tommy_list_head(low); i != 0; i = i->next) { + 843 3 : device_pad = 0; + 844 77 : for (i = tommy_list_head(low); i != 0; i = i->next) { 845 : size_t len; - 846 60 : devinfo_t* devinfo = i->data; + 846 74 : devinfo_t* devinfo = i->data; 847 : - 848 60 : state_smart_ignore(state, devinfo); + 848 74 : state_smart_ignore(state, devinfo); 849 : - 850 60 : len = strlen(devinfo->file); - 851 60 : if (len > device_pad) - 852 2 : device_pad = len; + 850 74 : len = strlen(devinfo->file); + 851 74 : if (len > device_pad) + 852 3 : device_pad = len; 853 : - 854 60 : double afr = smart_afr(devinfo->smart, devinfo->model); + 854 74 : double afr = smart_afr(devinfo->smart, devinfo->model); 855 : - 856 60 : state_info_log(devinfo); - 857 60 : state_smart_log(devinfo, afr); + 856 74 : state_info_log(devinfo); + 857 74 : state_smart_log(devinfo, afr); 858 : } 859 : - 860 2 : printf("SnapRAID PROBE report:\n"); - 861 2 : printf("\n"); - 862 2 : printf(" State "); - 863 2 : printf(" "); - 864 2 : printl("Device", device_pad); - 865 2 : printf(" Disk"); - 866 2 : printf("\n"); + 860 3 : printf("SnapRAID PROBE report:\n"); + 861 3 : printf("\n"); + 862 3 : printf(" State "); + 863 3 : printf(" "); + 864 3 : printl("Device", device_pad); + 865 3 : printf(" Disk"); + 866 3 : printf("\n"); 867 : /* |<##################################################################72>|####80>| */ - 868 2 : printf(" -----------------------------------------------------------------------\n"); + 868 3 : printf(" -----------------------------------------------------------------------\n"); 869 : - 870 62 : for (i = tommy_list_head(low); i != 0; i = i->next) { - 871 60 : devinfo_t* devinfo = i->data; + 870 77 : for (i = tommy_list_head(low); i != 0; i = i->next) { + 871 74 : devinfo_t* devinfo = i->data; 872 : - 873 60 : printf(" "); + 873 74 : printf(" "); 874 : - 875 60 : switch (devinfo->power) { - 876 0 : case POWER_STANDBY : printf("StandBy"); break; - 877 60 : case POWER_ACTIVE : printf(" Active"); break; + 875 74 : switch (devinfo->power) { + 876 12 : case POWER_STANDBY : printf("StandBy"); break; + 877 62 : case POWER_ACTIVE : printf(" Active"); break; 878 0 : default : printf("Unknown"); break; 879 : } 880 : - 881 60 : printf(" "); - 882 60 : if (*devinfo->file) - 883 60 : printl(devinfo->file, device_pad); + 881 74 : printf(" "); + 882 74 : if (*devinfo->file) + 883 74 : printl(devinfo->file, device_pad); 884 : else 885 0 : printl("-", device_pad); 886 : - 887 60 : printf(" "); - 888 60 : if (*devinfo->name) - 889 60 : printf("%s", devinfo->name); + 887 74 : printf(" "); + 888 74 : if (*devinfo->name) + 889 72 : printf("%s", devinfo->name); 890 : else - 891 0 : printf("-"); + 891 2 : printf("-"); 892 : - 893 60 : printf("\n"); + 893 74 : printf("\n"); 894 : - 895 60 : log_tag("probe:%s:%s:%d\n", devinfo->file, devinfo->name, devinfo->power); + 895 74 : log_tag("probe:%s:%s:%d\n", devinfo->file, devinfo->name, devinfo->power); 896 : } 897 : - 898 2 : printf("\n"); - 899 2 : } + 898 3 : printf("\n"); + 899 3 : } 900 : - 901 4 : static void state_stat(struct snapraid_state* state, tommy_list* high) + 901 5 : static void state_stat(struct snapraid_state* state, tommy_list* high) 902 : { 903 : tommy_node* i; 904 : 905 : (void)state; 906 : 907 : /* compute lengths for padding */ - 908 124 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 909 120 : devinfo_t* devinfo = i->data; + 908 137 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 909 132 : devinfo_t* devinfo = i->data; 910 : 911 : /* print disk access_stat (not split) */ - 912 120 : if (devinfo->split == 0 && devinfo->access_stat != 0) { - 913 12 : log_tag("stat:%s:%" PRIu64 "\n", devinfo->name, devinfo->access_stat); + 912 132 : if (devinfo->split == 0 && devinfo->access_stat != 0) { + 913 24 : log_tag("stat:%s:%" PRIu64 "\n", devinfo->name, devinfo->access_stat); 914 : } 915 : } - 916 4 : } + 916 5 : } 917 : 918 2419 : int devtest(tommy_list* high, tommy_list* low, int operation) 919 : { @@ -1046,88 +1046,88 @@ 984 2419 : return 0; 985 : } 986 : - 987 6 : void state_device(struct snapraid_state* state, int operation, tommy_list* filterlist_disk) + 987 7 : void state_device(struct snapraid_state* state, int operation, tommy_list* filterlist_disk) 988 : { 989 : tommy_node* i; 990 : unsigned j; 991 : tommy_list high; 992 : tommy_list low; 993 : int ret; - 994 6 : time_t now = time(0); + 994 7 : time_t now = time(0); 995 : - 996 6 : switch (operation) { + 996 7 : switch (operation) { 997 1 : case DEVICE_UP : msg_progress("Spinup...\n"); break; 998 1 : case DEVICE_DOWN : msg_progress("Spindown...\n"); break; 999 : } 1000 : - 1001 6 : tommy_list_init(&high); - 1002 6 : tommy_list_init(&low); + 1001 7 : tommy_list_init(&high); + 1002 7 : tommy_list_init(&low); 1003 : 1004 : /* for all disks */ - 1005 42 : for (i = state->disklist; i != 0; i = i->next) { - 1006 36 : struct snapraid_disk* disk = i->data; + 1005 53 : for (i = state->disklist; i != 0; i = i->next) { + 1006 46 : struct snapraid_disk* disk = i->data; 1007 : devinfo_t* entry; 1008 : - 1009 36 : if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, disk->name, 0) != 0) + 1009 46 : if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, disk->name, 0) != 0) 1010 5 : continue; 1011 : - 1012 31 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 1012 41 : entry = calloc_nofail(1, sizeof(devinfo_t)); 1013 : - 1014 31 : entry->device = disk->device; - 1015 31 : device_name_set(entry, disk->name, 0); - 1016 31 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir); - 1017 31 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); - 1018 31 : memcpy(entry->smartignore, disk->smartignore, sizeof(entry->smartignore)); + 1014 41 : entry->device = disk->device; + 1015 41 : device_name_set(entry, disk->name, 0); + 1016 41 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir); + 1017 41 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); + 1018 41 : memcpy(entry->smartignore, disk->smartignore, sizeof(entry->smartignore)); 1019 : - 1020 31 : tommy_list_insert_tail(&high, &entry->node, entry); + 1020 41 : tommy_list_insert_tail(&high, &entry->node, entry); 1021 : } 1022 : 1023 : /* for all parities */ - 1024 42 : for (j = 0; j < state->level; ++j) { + 1024 45 : for (j = 0; j < state->level; ++j) { 1025 : devinfo_t* entry; 1026 : devinfo_t* split; 1027 : unsigned s; 1028 : - 1029 36 : if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, lev_config_name(j), 0) != 0) + 1029 38 : if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, lev_config_name(j), 0) != 0) 1030 5 : continue; 1031 : - 1032 155 : for (s = 0; s < state->parity[j].split_mac; ++s) { - 1033 124 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 1032 159 : for (s = 0; s < state->parity[j].split_mac; ++s) { + 1033 126 : entry = calloc_nofail(1, sizeof(devinfo_t)); 1034 : 1035 : /* keep track of the first split */ - 1036 124 : if (s == 0) - 1037 31 : split = entry; + 1036 126 : if (s == 0) + 1037 33 : split = entry; 1038 : else 1039 93 : entry->split = split; 1040 : - 1041 124 : entry->device = state->parity[j].split_map[s].device; - 1042 124 : device_name_set(entry, lev_config_name(j), s); - 1043 124 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].split_map[s].path); - 1044 124 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); - 1045 124 : memcpy(entry->smartignore, state->parity[j].smartignore, sizeof(entry->smartignore)); - 1046 124 : pathcut(entry->mount); /* remove the parity file */ + 1041 126 : entry->device = state->parity[j].split_map[s].device; + 1042 126 : device_name_set(entry, lev_config_name(j), s); + 1043 126 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].split_map[s].path); + 1044 126 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); + 1045 126 : memcpy(entry->smartignore, state->parity[j].smartignore, sizeof(entry->smartignore)); + 1046 126 : pathcut(entry->mount); /* remove the parity file */ 1047 : - 1048 124 : tommy_list_insert_tail(&high, &entry->node, entry); + 1048 126 : tommy_list_insert_tail(&high, &entry->node, entry); 1049 : } 1050 : } 1051 : 1052 : /* with a GUI always gives time reference */ - 1053 6 : if (state->opt.gui) + 1053 7 : if (state->opt.gui) 1054 3 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)now); 1055 : - 1056 6 : if (state->opt.fake_device) { + 1056 7 : if (state->opt.fake_device) { 1057 3 : ret = devtest(&high, &low, operation); 1058 : } else { - 1059 3 : int others = operation == DEVICE_SMART || operation == DEVICE_PROBE; + 1059 4 : int others = operation == DEVICE_SMART || operation == DEVICE_PROBE; 1060 : - 1061 3 : ret = devquery(&high, &low, operation, others); + 1061 4 : ret = devquery(&high, &low, operation, others); 1062 : } 1063 : 1064 : /* if the list is empty, it's not supported in this platform */ - 1065 6 : if (ret == 0 && tommy_list_empty(&low)) + 1065 7 : if (ret == 0 && tommy_list_empty(&low)) 1066 0 : ret = -1; 1067 : - 1068 6 : if (ret != 0) { + 1068 7 : if (ret != 0) { 1069 2 : const char* ope = 0; 1070 2 : switch (operation) { 1071 1 : case DEVICE_UP : ope = "Spinup"; break; @@ -1139,7 +1139,7 @@ 1077 : } 1078 2 : log_fatal(ESOFT, "%s is unsupported in this platform.\n", ope); 1079 : } else { - 1080 4 : if (operation == DEVICE_LIST) { + 1080 5 : if (operation == DEVICE_LIST) { 1081 31 : for (i = tommy_list_head(&low); i != 0; i = i->next) { 1082 30 : devinfo_t* devinfo = i->data; 1083 30 : devinfo_t* parent = devinfo->parent; @@ -1151,21 +1151,21 @@ 1089 : } 1090 : } 1091 : - 1092 4 : state_stat(state, &high); + 1092 5 : state_stat(state, &high); 1093 : - 1094 4 : if (operation == DEVICE_SMART) + 1094 5 : if (operation == DEVICE_SMART) 1095 1 : state_smart(state, state->level + tommy_list_count(&state->disklist), &low); 1096 : - 1097 3 : if (operation == DEVICE_PROBE) - 1098 2 : state_probe(state, &low); + 1097 4 : if (operation == DEVICE_PROBE) + 1098 3 : state_probe(state, &low); 1099 : - 1100 3 : if (operation == DEVICE_UP) + 1100 4 : if (operation == DEVICE_UP) 1101 0 : state_attr(state, &low); 1102 : } 1103 : - 1104 5 : tommy_list_foreach(&high, free); - 1105 5 : tommy_list_foreach(&low, free); - 1106 5 : } + 1104 6 : tommy_list_foreach(&high, free); + 1105 6 : tommy_list_foreach(&low, free); + 1106 6 : } 1107 : diff --git a/cov/cmdline/dry.c.func-sort-c.html b/cov/cmdline/dry.c.func-sort-c.html index f252ce7a..569846cb 100644 --- a/cov/cmdline/dry.c.func-sort-c.html +++ b/cov/cmdline/dry.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 diff --git a/cov/cmdline/dry.c.func.html b/cov/cmdline/dry.c.func.html index 8bc46275..887c3efb 100644 --- a/cov/cmdline/dry.c.func.html +++ b/cov/cmdline/dry.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 diff --git a/cov/cmdline/dry.c.gcov.html b/cov/cmdline/dry.c.gcov.html index dfe1cb38..36dad312 100644 --- a/cov/cmdline/dry.c.gcov.html +++ b/cov/cmdline/dry.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 diff --git a/cov/cmdline/dup.c.func-sort-c.html b/cov/cmdline/dup.c.func-sort-c.html index 1f553993..39fa51cc 100644 --- a/cov/cmdline/dup.c.func-sort-c.html +++ b/cov/cmdline/dup.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -65,7 +65,7 @@ hash_compare - 20 + 18 hash_alloc diff --git a/cov/cmdline/dup.c.func.html b/cov/cmdline/dup.c.func.html index 8b81da74..c3ab35fb 100644 --- a/cov/cmdline/dup.c.func.html +++ b/cov/cmdline/dup.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -65,7 +65,7 @@ hash_compare - 20 + 18 hash_free diff --git a/cov/cmdline/dup.c.gcov.html b/cov/cmdline/dup.c.gcov.html index fb238dff..259212b4 100644 --- a/cov/cmdline/dup.c.gcov.html +++ b/cov/cmdline/dup.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -141,12 +141,12 @@ 79 16976 : free(hash); 80 16976 : } 81 : - 82 20 : int hash_compare(const void* void_arg, const void* void_data) + 82 18 : int hash_compare(const void* void_arg, const void* void_data) 83 : { - 84 20 : const char* arg = void_arg; - 85 20 : const struct snapraid_hash* hash = void_data; + 84 18 : const char* arg = void_arg; + 85 18 : const struct snapraid_hash* hash = void_data; 86 : - 87 20 : return memcmp(arg, hash->hash, HASH_MAX); + 87 18 : return memcmp(arg, hash->hash, HASH_MAX); 88 : } 89 : 90 3 : void state_dup(struct snapraid_state* state) diff --git a/cov/cmdline/elem.c.func-sort-c.html b/cov/cmdline/elem.c.func-sort-c.html index 42d47b7e..67a5f3de 100644 --- a/cov/cmdline/elem.c.func-sort-c.html +++ b/cov/cmdline/elem.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 70 @@ -97,23 +97,23 @@ bucket_to_list - 421 - - - filter_free - 547 - - - filter_alloc_file - 559 + 420 bucket_cmp - 711 + 521 + + + filter_free + 552 + + + filter_alloc_file + 564 bucket_free - 746 + 705 dir_free @@ -125,23 +125,23 @@ fs_is_empty - 942 + 936 content_free - 1551 + 1555 map_free 1573 - disk_free - 1603 + content_alloc + 1610 - content_alloc - 1606 + disk_free + 1613 map_alloc @@ -149,11 +149,11 @@ disk_alloc - 1663 + 1673 fs_check - 3120 + 3114 link_alpha_compare @@ -165,7 +165,7 @@ fs_size - 4549 + 4543 file_dup @@ -177,15 +177,15 @@ file_stamp_compare - 23671 + 23670 file_name_compare - 23856 + 23865 file_namestamp_compare - 23856 + 23865 link_name_compare_to_arg @@ -197,31 +197,31 @@ file_name - 47712 + 47730 extent_disk_size_compare_unlock - 52890 + 52796 bucket_insert - 72052 + 55958 filter_existence 77701 - file_path_compare_to_arg - 97862 + file_physical_compare + 96760 - file_physical_compare - 99756 + file_path_compare_to_arg + 97805 fs_deallocate - 102986 + 102931 link_free @@ -233,47 +233,47 @@ filter_type - 125231 + 125314 file_path_compare - 187689 + 187677 fmt_term - 366067 + 366236 file_inode_compare_to_arg - 1043743 + 1046316 filter_content - 3231524 + 3231650 file_free - 3784741 + 3784728 extent_free - 3806435 + 3806358 file_alloc - 3807696 + 3807720 extent_alloc - 3852016 + 3851976 filter_path - 4587023 + 4587158 filter_element - 4591561 + 4591696 file_block_is_last @@ -281,71 +281,71 @@ fs_file2par_find - 5301463 + 5260119 filter_apply - 6355925 + 6356195 file_block_size - 6817779 + 6817866 extent_file_check_foreach_unlock - 6837675 + 6820724 extent_parity_check_foreach_unlock - 6837675 + 6820724 fs_allocate - 9473576 + 9473620 fs_file2extent_get_unlock - 10949888 + 10908566 extent_file_inside_compare_unlock - 22976989 + 22802303 fs_par2block_find - 38360216 + 38266700 extent_parity_compare - 45768745 + 45767042 extent_file_compare - 46158505 + 46157545 fs_par2file_find - 49865865 + 49771977 fs_par2extent_get_unlock - 49968851 + 49874908 fs_file2block_get - 56447214 + 56273071 fs_lock - 64751658 + 64616403 fs_unlock - 64751658 + 64616403 extent_parity_inside_compare_unlock - 158551658 + 158133634
diff --git a/cov/cmdline/elem.c.func.html b/cov/cmdline/elem.c.func.html index 3e47a0a9..2e65d1fc 100644 --- a/cov/cmdline/elem.c.func.html +++ b/cov/cmdline/elem.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 70 @@ -61,27 +61,27 @@ bucket_cmp - 711 + 521 bucket_free - 746 + 705 bucket_insert - 72052 + 55958 bucket_to_list - 421 + 420 content_alloc - 1606 + 1610 content_free - 1551 + 1555 dir_alloc @@ -97,15 +97,15 @@ disk_alloc - 1663 + 1673 disk_free - 1603 + 1613 extent_alloc - 3852016 + 3851976 extent_disk_empty_compare_unlock @@ -113,39 +113,39 @@ extent_disk_size_compare_unlock - 52890 + 52796 extent_file_check_foreach_unlock - 6837675 + 6820724 extent_file_compare - 46158505 + 46157545 extent_file_inside_compare_unlock - 22976989 + 22802303 extent_free - 3806435 + 3806358 extent_parity_check_foreach_unlock - 6837675 + 6820724 extent_parity_compare - 45768745 + 45767042 extent_parity_inside_compare_unlock - 158551658 + 158133634 file_alloc - 3807696 + 3807720 file_block_is_last @@ -153,7 +153,7 @@ file_block_size - 6817779 + 6817866 file_copy @@ -165,7 +165,7 @@ file_free - 3784741 + 3784728 file_inode_compare @@ -173,27 +173,27 @@ file_inode_compare_to_arg - 1043743 + 1046316 file_name - 47712 + 47730 file_name_compare - 23856 + 23865 file_namestamp_compare - 23856 + 23865 file_path_compare - 187689 + 187677 file_path_compare_to_arg - 97862 + 97805 file_pathstamp_compare @@ -201,7 +201,7 @@ file_physical_compare - 99756 + 96760 file_rename @@ -209,7 +209,7 @@ file_stamp_compare - 23671 + 23670 filter_alloc_disk @@ -217,15 +217,15 @@ filter_alloc_file - 559 + 564 filter_apply - 6355925 + 6356195 filter_content - 3231524 + 3231650 filter_correctness @@ -233,7 +233,7 @@ filter_element - 4591561 + 4591696 filter_emptydir @@ -245,11 +245,11 @@ filter_free - 547 + 552 filter_path - 4587023 + 4587158 filter_subdir @@ -257,7 +257,7 @@ filter_type - 125231 + 125314 fmt_poll @@ -269,59 +269,59 @@ fmt_term - 366067 + 366236 fs_allocate - 9473576 + 9473620 fs_check - 3120 + 3114 fs_deallocate - 102986 + 102931 fs_file2block_get - 56447214 + 56273071 fs_file2extent_get_unlock - 10949888 + 10908566 fs_file2par_find - 5301463 + 5260119 fs_is_empty - 942 + 936 fs_lock - 64751658 + 64616403 fs_par2block_find - 38360216 + 38266700 fs_par2extent_get_unlock - 49968851 + 49874908 fs_par2file_find - 49865865 + 49771977 fs_size - 4549 + 4543 fs_unlock - 64751658 + 64616403 link_alloc diff --git a/cov/cmdline/elem.c.gcov.html b/cov/cmdline/elem.c.gcov.html index 5b3a0c0c..238b5d8e 100644 --- a/cov/cmdline/elem.c.gcov.html +++ b/cov/cmdline/elem.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 70 @@ -89,23 +89,23 @@ 27 : 28 : int BLOCK_HASH_SIZE = HASH_MAX; 29 : - 30 1606 : struct snapraid_content* content_alloc(const char* path, uint64_t dev) + 30 1610 : struct snapraid_content* content_alloc(const char* path, uint64_t dev) 31 : { 32 : struct snapraid_content* content; 33 : - 34 1606 : content = malloc_nofail(sizeof(struct snapraid_content)); - 35 1606 : pathimport(content->content, sizeof(content->content), path); - 36 1606 : content->device = dev; + 34 1610 : content = malloc_nofail(sizeof(struct snapraid_content)); + 35 1610 : pathimport(content->content, sizeof(content->content), path); + 36 1610 : content->device = dev; 37 : - 38 1606 : return content; + 38 1610 : return content; 39 : } 40 : - 41 1551 : void content_free(struct snapraid_content* content) + 41 1555 : void content_free(struct snapraid_content* content) 42 : { - 43 1551 : free(content); - 44 1551 : } + 43 1555 : free(content); + 44 1555 : } 45 : - 46 559 : struct snapraid_filter* filter_alloc_file(int direction, const char* root, const char* pattern) + 46 564 : struct snapraid_filter* filter_alloc_file(int direction, const char* root, const char* pattern) 47 : { 48 : struct snapraid_filter* filter; 49 : char* i; @@ -114,72 +114,72 @@ 52 : int token_is_valid; 53 : int token_is_filled; 54 : - 55 559 : filter = malloc_nofail(sizeof(struct snapraid_filter)); - 56 559 : pathimport(filter->pattern, sizeof(filter->pattern), pattern); - 57 559 : pathimport(filter->root, sizeof(filter->root), root); - 58 559 : filter->direction = direction; + 55 564 : filter = malloc_nofail(sizeof(struct snapraid_filter)); + 56 564 : pathimport(filter->pattern, sizeof(filter->pattern), pattern); + 57 564 : pathimport(filter->root, sizeof(filter->root), root); + 58 564 : filter->direction = direction; 59 : 60 : /* find first and last slash */ - 61 559 : first = 0; - 62 559 : last = 0; + 61 564 : first = 0; + 62 564 : last = 0; 63 : 64 : /* reject invalid tokens, like "<empty>", ".", ".." and more dots */ - 65 559 : token_is_valid = 0; - 66 559 : token_is_filled = 0; - 67 6943 : for (i = filter->pattern; *i; ++i) { - 68 6385 : if (*i == '/') { + 65 564 : token_is_valid = 0; + 66 564 : token_is_filled = 0; + 67 6984 : for (i = filter->pattern; *i; ++i) { + 68 6421 : if (*i == '/') { 69 : /* reject invalid tokens, but accept an empty one as first */ - 70 4 : if (!token_is_valid && (first != 0 || token_is_filled)) { + 70 8 : if (!token_is_valid && (first != 0 || token_is_filled)) { 71 1 : free(filter); 72 1 : return 0; 73 : } - 74 3 : token_is_valid = 0; - 75 3 : token_is_filled = 0; + 74 7 : token_is_valid = 0; + 75 7 : token_is_filled = 0; 76 : 77 : /* update slash position */ - 78 3 : if (!first) - 79 2 : first = i; - 80 3 : last = i; - 81 6381 : } else if (*i != '.') { - 82 5825 : token_is_valid = 1; - 83 5825 : token_is_filled = 1; + 78 7 : if (!first) + 79 5 : first = i; + 80 7 : last = i; + 81 6413 : } else if (*i != '.') { + 82 5855 : token_is_valid = 1; + 83 5855 : token_is_filled = 1; 84 : } else { - 85 556 : token_is_filled = 1; + 85 558 : token_is_filled = 1; 86 : } 87 : } 88 : 89 : /* reject invalid tokens, but accept an empty one as last, but not if it's the only one */ - 90 558 : if (!token_is_valid && (first == 0 || token_is_filled)) { + 90 563 : if (!token_is_valid && (first == 0 || token_is_filled)) { 91 1 : free(filter); 92 1 : return 0; 93 : } 94 : 95 : /* it's a file filter */ - 96 557 : filter->is_disk = 0; + 96 562 : filter->is_disk = 0; 97 : - 98 557 : if (first == 0) { + 98 562 : if (first == 0) { 99 : /* no slash */ - 100 555 : filter->is_abs = 0; - 101 555 : filter->is_dir = 0; + 100 557 : filter->is_abs = 0; + 101 557 : filter->is_dir = 0; 102 : } else { - 103 2 : if (first == filter->pattern) { + 103 5 : if (first == filter->pattern) { 104 : /* slash at the start */ - 105 1 : filter->is_abs = 1; + 105 2 : filter->is_abs = 1; 106 : } else { 107 : /* no slash at the start */ - 108 1 : filter->is_abs = 0; + 108 3 : filter->is_abs = 0; 109 : } - 110 2 : if (last[1] == 0) { + 110 5 : if (last[1] == 0) { 111 : /* slash at the end */ - 112 1 : filter->is_dir = 1; - 113 1 : last[0] = 0; /* clear the slash */ + 112 4 : filter->is_dir = 1; + 113 4 : last[0] = 0; /* clear the slash */ 114 : } else { 115 : /* no slash at the end */ 116 1 : filter->is_dir = 0; 117 : } 118 : } 119 : - 120 557 : return filter; + 120 562 : return filter; 121 : } 122 : 123 10 : struct snapraid_filter* filter_alloc_disk(int direction, const char* pattern) @@ -206,28 +206,28 @@ 144 10 : return filter; 145 : } 146 : - 147 547 : void filter_free(void* filter) + 147 552 : void filter_free(void* filter) 148 : { - 149 547 : free(filter); - 150 547 : } + 149 552 : free(filter); + 150 552 : } 151 : - 152 125231 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) + 152 125314 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) 153 : { 154 : const char* direction; 155 : - 156 125231 : if (filter->direction < 0) - 157 124954 : direction = "exclude"; + 156 125314 : if (filter->direction < 0) + 157 125037 : direction = "exclude"; 158 : else 159 277 : direction = "include"; 160 : - 161 125231 : if (filter->is_disk) + 161 125314 : if (filter->is_disk) 162 0 : pathprint(out, out_size, "%s %s:", direction, filter->pattern); - 163 125231 : else if (filter->is_dir) - 164 0 : pathprint(out, out_size, "%s %s/", direction, filter->pattern); + 163 125314 : else if (filter->is_dir) + 164 3 : pathprint(out, out_size, "%s %s/", direction, filter->pattern); 165 : else - 166 125231 : pathprint(out, out_size, "%s %s", direction, filter->pattern); + 166 125311 : pathprint(out, out_size, "%s %s", direction, filter->pattern); 167 : - 168 125231 : return out; + 168 125314 : return out; 169 : } 170 : 171 : /** @@ -239,9 +239,9 @@ 177 : * @param is_dir if the path refers to a directory, otherwise to a file. 178 : * @return < 0 if the path is excluded, > 0 if the path is included, 0 if the filter doesn't apply. 179 : */ - 180 6355925 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, int is_dir) + 180 6356195 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, int is_dir) 181 : { - 182 6355925 : if (filter->root[0] != 0) { /* if it's a local filter */ + 182 6356195 : if (filter->root[0] != 0) { /* if it's a local filter */ 183 0 : if (!path_is_root_of(filter->root, path)) /* applies it only if it matches the root */ 184 0 : return 0; 185 : /* advance the path to compare to make it local */ @@ -249,39 +249,39 @@ 187 : } 188 : 189 : /* match dirs with dirs and files with files */ - 190 6355925 : if (filter->is_dir && !is_dir) + 190 6356195 : if (filter->is_dir && !is_dir) 191 5939 : return 0; - 192 6349986 : if (!filter->is_dir && is_dir) + 192 6350256 : if (!filter->is_dir && is_dir) 193 6274 : return 0; 194 : - 195 6343712 : int ret = 0; + 195 6343982 : int ret = 0; 196 : - 197 6343712 : if (filter->is_abs) { + 197 6343982 : if (filter->is_abs) { 198 : /* skip initial slash, as always missing in the path */ 199 5939 : if (wnmatch(filter->pattern + 1, path) == 0) 200 0 : ret = filter->direction; 201 : } else { 202 : /* the path is relative, first try to match from the root */ - 203 6337773 : if (wnmatch(filter->pattern, path) == 0) { + 203 6338043 : if (wnmatch(filter->pattern, path) == 0) { 204 92 : ret = filter->direction; 205 : } else { 206 : /* then try to match after all the / presents */ - 207 6337681 : char* slash = strchr(path, '/'); - 208 12543215 : while (slash) { - 209 6330119 : if (wnmatch(filter->pattern, slash + 1) == 0) { - 210 124585 : ret = filter->direction; - 211 124585 : break; + 207 6337951 : char* slash = strchr(path, '/'); + 208 12543677 : while (slash) { + 209 6330389 : if (wnmatch(filter->pattern, slash + 1) == 0) { + 210 124663 : ret = filter->direction; + 211 124663 : break; 212 : } 213 : - 214 6205534 : slash = strchr(slash + 1, '/'); + 214 6205726 : slash = strchr(slash + 1, '/'); 215 : } 216 : } 217 : } 218 : - 219 6343712 : if (reason != 0 && ret < 0) - 220 124677 : *reason = filter; + 219 6343982 : if (reason != 0 && ret < 0) + 220 124755 : *reason = filter; 221 : - 222 6343712 : return ret; + 222 6343982 : return ret; 223 : } 224 : 225 : /** @@ -296,7 +296,7 @@ 234 : * @return < 0 if the path is excluded, == 0 if the path is included. 235 : */ 236 : - 237 4591561 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include) + 237 4591696 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include) 238 : { 239 : tommy_node* i; 240 : @@ -308,14 +308,14 @@ 246 : * If the latest filter is an 'inclusion' filter, the default is to exclude. 247 : * If there are no filter, the default is to include. 248 : */ - 249 4591561 : int default_direction = 1; + 249 4591696 : int default_direction = 1; 250 : 251 : /* for each filter */ - 252 10924117 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { + 252 10924444 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { 253 : int ret; - 254 6465913 : struct snapraid_filter* filter = i->data; + 254 6466183 : struct snapraid_filter* filter = i->data; 255 : - 256 6465913 : if (filter->is_disk) { + 256 6466183 : if (filter->is_disk) { 257 109988 : if (wnmatch(filter->pattern, disk) == 0) { 258 8680 : ret = filter->direction; 259 : } else { @@ -324,39 +324,39 @@ 262 109988 : if (reason != 0 && ret < 0) 263 0 : *reason = filter; 264 : } else { - 265 6355925 : ret = filter_apply(filter, reason, sub, is_dir); + 265 6356195 : ret = filter_apply(filter, reason, sub, is_dir); 266 : } 267 : - 268 6465913 : if (ret > 0) { + 268 6466183 : if (ret > 0) { 269 : /* include the file */ 270 8680 : return 0; - 271 6457233 : } else if (ret < 0) { + 271 6457503 : } else if (ret < 0) { 272 : /* exclude the file */ - 273 124677 : return -1; + 273 124755 : return -1; 274 : } else { 275 : /* default is opposite of the last filter */ - 276 6332556 : default_direction = -filter->direction; - 277 6332556 : if (reason != 0 && default_direction < 0) - 278 3169054 : *reason = filter; + 276 6332748 : default_direction = -filter->direction; + 277 6332748 : if (reason != 0 && default_direction < 0) + 278 3169189 : *reason = filter; 279 : /* continue with the next one */ 280 : } 281 : } 282 : 283 : /* directories are always included by default, otherwise we cannot apply rules */ 284 : /* to the contained files */ - 285 4458204 : if (is_def_include) + 285 4458261 : if (is_def_include) 286 4493 : return 0; 287 : 288 : /* files are excluded/included depending of the last rule processed */ - 289 4453711 : if (default_direction < 0) + 289 4453768 : if (default_direction < 0) 290 60598 : return -1; 291 : - 292 4393113 : return 0; + 292 4393170 : return 0; 293 : } 294 : - 295 4587023 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) + 295 4587158 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) 296 : { - 297 4587023 : return filter_element(filterlist, reason, disk, sub, 0, 0); + 297 4587158 : return filter_element(filterlist, reason, disk, sub, 0, 0); 298 : } 299 : 300 4493 : int filter_subdir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) @@ -402,67 +402,67 @@ 340 13214 : return 0; 341 : 342 : /* check each block of the file */ - 343 60662 : for (i = 0; i < file->blockmax; ++i) { - 344 46388 : block_off_t parity_pos = fs_file2par_get(disk, file, i); - 345 46388 : snapraid_info info = info_get(infoarr, parity_pos); + 343 60694 : for (i = 0; i < file->blockmax; ++i) { + 344 46465 : block_off_t parity_pos = fs_file2par_get(disk, file, i); + 345 46465 : snapraid_info info = info_get(infoarr, parity_pos); 346 : 347 : /* if the file has a bad block, don't exclude it */ - 348 46388 : if (info_get_bad(info)) - 349 8274 : return 0; + 348 46465 : if (info_get_bad(info)) + 349 8319 : return 0; 350 : } 351 : 352 : /* the file is correct, so we filter it out */ - 353 14274 : return 1; + 353 14229 : return 1; 354 : } 355 : - 356 3231524 : int filter_content(tommy_list* contentlist, const char* path) + 356 3231650 : int filter_content(tommy_list* contentlist, const char* path) 357 : { 358 : tommy_node* i; 359 : - 360 20922616 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { - 361 17691092 : struct snapraid_content* content = i->data; + 360 20923098 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { + 361 17691448 : struct snapraid_content* content = i->data; 362 : char tmp[PATH_MAX]; 363 : - 364 17691092 : if (pathcmp(content->content, path) == 0) + 364 17691448 : if (pathcmp(content->content, path) == 0) 365 0 : return -1; 366 : 367 : /* exclude also the ".tmp" copy used to save it */ - 368 17691092 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 369 17691092 : if (pathcmp(tmp, path) == 0) + 368 17691448 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 369 17691448 : if (pathcmp(tmp, path) == 0) 370 0 : return -1; 371 : 372 : /* exclude also the ".lock" file */ - 373 17691092 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); - 374 17691092 : if (pathcmp(tmp, path) == 0) + 373 17691448 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); + 374 17691448 : if (pathcmp(tmp, path) == 0) 375 0 : return -1; 376 : } 377 : - 378 3231524 : return 0; + 378 3231650 : return 0; 379 : } 380 : - 381 3807696 : 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) + 381 3807720 : 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) 382 : { 383 : struct snapraid_file* file; 384 : block_off_t i; 385 : - 386 3807696 : file = malloc_nofail(sizeof(struct snapraid_file)); - 387 3807696 : file->sub = strdup_nofail(sub); - 388 3807696 : file->size = size; - 389 3807696 : file->blockmax = (size + block_size - 1) / block_size; - 390 3807696 : file->mtime_sec = mtime_sec; - 391 3807696 : file->mtime_nsec = mtime_nsec; - 392 3807696 : file->inode = inode; - 393 3807696 : file->physical = physical; - 394 3807696 : file->flag = 0; - 395 3807696 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); + 386 3807720 : file = malloc_nofail(sizeof(struct snapraid_file)); + 387 3807720 : file->sub = strdup_nofail(sub); + 388 3807720 : file->size = size; + 389 3807720 : file->blockmax = (size + block_size - 1) / block_size; + 390 3807720 : file->mtime_sec = mtime_sec; + 391 3807720 : file->mtime_nsec = mtime_nsec; + 392 3807720 : file->inode = inode; + 393 3807720 : file->physical = physical; + 394 3807720 : file->flag = 0; + 395 3807720 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); 396 : - 397 13224281 : for (i = 0; i < file->blockmax; ++i) { - 398 9416585 : struct snapraid_block* block = file_block(file, i); - 399 9416585 : block_state_set(block, BLOCK_STATE_CHG); - 400 9416585 : hash_invalid_set(block->hash); + 397 13224349 : for (i = 0; i < file->blockmax; ++i) { + 398 9416629 : struct snapraid_block* block = file_block(file, i); + 399 9416629 : block_state_set(block, BLOCK_STATE_CHG); + 400 9416629 : hash_invalid_set(block->hash); 401 : } 402 : - 403 3807696 : return file; + 403 3807720 : return file; 404 : } 405 : 406 22687 : struct snapraid_file* file_dup(struct snapraid_file* copy) @@ -491,14 +491,14 @@ 429 22687 : return file; 430 : } 431 : - 432 3784741 : void file_free(struct snapraid_file* file) + 432 3784728 : void file_free(struct snapraid_file* file) 433 : { - 434 3784741 : free(file->sub); - 435 3784741 : file->sub = 0; - 436 3784741 : free(file->blockvec); - 437 3784741 : file->blockvec = 0; - 438 3784741 : free(file); - 439 3784741 : } + 434 3784728 : free(file->sub); + 435 3784728 : file->sub = 0; + 436 3784728 : free(file->blockvec); + 437 3784728 : file->blockvec = 0; + 438 3784728 : free(file); + 439 3784728 : } 440 : 441 155 : void file_rename(struct snapraid_file* file, const char* sub) 442 : { @@ -542,31 +542,31 @@ 480 23637 : file_flag_set(dst_file, FILE_IS_COPY); 481 23637 : } 482 : - 483 47712 : const char* file_name(const struct snapraid_file* file) + 483 47730 : const char* file_name(const struct snapraid_file* file) 484 : { - 485 47712 : const char* r = strrchr(file->sub, '/'); + 485 47730 : const char* r = strrchr(file->sub, '/'); 486 : - 487 47712 : if (!r) - 488 80 : r = file->sub; + 487 47730 : if (!r) + 488 78 : r = file->sub; 489 : else - 490 47632 : ++r; - 491 47712 : return r; + 490 47652 : ++r; + 491 47730 : return r; 492 : } 493 : - 494 6817779 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) + 494 6817866 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) 495 : { 496 : /* if it's the last block */ - 497 6817779 : if (file_pos + 1 == file->blockmax) { + 497 6817866 : if (file_pos + 1 == file->blockmax) { 498 : unsigned block_remainder; - 499 2771709 : if (file->size == 0) + 499 2772053 : if (file->size == 0) 500 0 : return 0; - 501 2771709 : block_remainder = file->size % block_size; - 502 2771709 : if (block_remainder == 0) - 503 3046 : block_remainder = block_size; - 504 2771709 : return block_remainder; + 501 2772053 : block_remainder = file->size % block_size; + 502 2772053 : if (block_remainder == 0) + 503 3053 : block_remainder = block_size; + 504 2772053 : return block_remainder; 505 : } 506 : - 507 4046070 : return block_size; + 507 4045813 : return block_size; 508 : } 509 : 510 5245100 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) @@ -584,16 +584,16 @@ 522 5245100 : return file_pos == file->blockmax - 1; 523 : } 524 : - 525 1043743 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) + 525 1046316 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) 526 : { - 527 1043743 : const uint64_t* arg = void_arg; - 528 1043743 : const struct snapraid_file* file = void_data; + 527 1046316 : const uint64_t* arg = void_arg; + 528 1046316 : const struct snapraid_file* file = void_data; 529 : - 530 1043743 : if (*arg < file->inode) + 530 1046316 : if (*arg < file->inode) 531 0 : return -1; - 532 1043743 : if (*arg > file->inode) + 532 1046316 : if (*arg > file->inode) 533 0 : return 1; - 534 1043743 : return 0; + 534 1046316 : return 0; 535 : } 536 : 537 0 : int file_inode_compare(const void* void_a, const void* void_b) @@ -608,76 +608,76 @@ 546 0 : return 0; 547 : } 548 : - 549 187689 : int file_path_compare(const void* void_a, const void* void_b) + 549 187677 : int file_path_compare(const void* void_a, const void* void_b) 550 : { - 551 187689 : const struct snapraid_file* file_a = void_a; - 552 187689 : const struct snapraid_file* file_b = void_b; + 551 187677 : const struct snapraid_file* file_a = void_a; + 552 187677 : const struct snapraid_file* file_b = void_b; 553 : - 554 187689 : return strcmp(file_a->sub, file_b->sub); + 554 187677 : return strcmp(file_a->sub, file_b->sub); 555 : } 556 : - 557 99756 : int file_physical_compare(const void* void_a, const void* void_b) + 557 96760 : int file_physical_compare(const void* void_a, const void* void_b) 558 : { - 559 99756 : const struct snapraid_file* file_a = void_a; - 560 99756 : const struct snapraid_file* file_b = void_b; + 559 96760 : const struct snapraid_file* file_a = void_a; + 560 96760 : const struct snapraid_file* file_b = void_b; 561 : - 562 99756 : if (file_a->physical < file_b->physical) - 563 52632 : return -1; - 564 47124 : if (file_a->physical > file_b->physical) - 565 47122 : return 1; + 562 96760 : if (file_a->physical < file_b->physical) + 563 52606 : return -1; + 564 44154 : if (file_a->physical > file_b->physical) + 565 44152 : return 1; 566 2 : return 0; 567 : } 568 : - 569 97862 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) + 569 97805 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) 570 : { - 571 97862 : const char* arg = void_arg; - 572 97862 : const struct snapraid_file* file = void_data; + 571 97805 : const char* arg = void_arg; + 572 97805 : const struct snapraid_file* file = void_data; 573 : - 574 97862 : return strcmp(arg, file->sub); + 574 97805 : return strcmp(arg, file->sub); 575 : } 576 : - 577 23856 : int file_name_compare(const void* void_a, const void* void_b) + 577 23865 : int file_name_compare(const void* void_a, const void* void_b) 578 : { - 579 23856 : const struct snapraid_file* file_a = void_a; - 580 23856 : const struct snapraid_file* file_b = void_b; - 581 23856 : const char* name_a = file_name(file_a); - 582 23856 : const char* name_b = file_name(file_b); + 579 23865 : const struct snapraid_file* file_a = void_a; + 580 23865 : const struct snapraid_file* file_b = void_b; + 581 23865 : const char* name_a = file_name(file_a); + 582 23865 : const char* name_b = file_name(file_b); 583 : - 584 23856 : return strcmp(name_a, name_b); + 584 23865 : return strcmp(name_a, name_b); 585 : } 586 : - 587 23671 : int file_stamp_compare(const void* void_a, const void* void_b) + 587 23670 : int file_stamp_compare(const void* void_a, const void* void_b) 588 : { - 589 23671 : const struct snapraid_file* file_a = void_a; - 590 23671 : const struct snapraid_file* file_b = void_b; + 589 23670 : const struct snapraid_file* file_a = void_a; + 590 23670 : const struct snapraid_file* file_b = void_b; 591 : - 592 23671 : if (file_a->size < file_b->size) + 592 23670 : if (file_a->size < file_b->size) 593 0 : return -1; - 594 23671 : if (file_a->size > file_b->size) + 594 23670 : if (file_a->size > file_b->size) 595 0 : return 1; 596 : - 597 23671 : if (file_a->mtime_sec < file_b->mtime_sec) + 597 23670 : if (file_a->mtime_sec < file_b->mtime_sec) 598 0 : return -1; - 599 23671 : if (file_a->mtime_sec > file_b->mtime_sec) + 599 23670 : if (file_a->mtime_sec > file_b->mtime_sec) 600 0 : return 1; 601 : - 602 23671 : if (file_a->mtime_nsec < file_b->mtime_nsec) + 602 23670 : if (file_a->mtime_nsec < file_b->mtime_nsec) 603 0 : return -1; - 604 23671 : if (file_a->mtime_nsec > file_b->mtime_nsec) + 604 23670 : if (file_a->mtime_nsec > file_b->mtime_nsec) 605 0 : return 1; 606 : - 607 23671 : return 0; + 607 23670 : return 0; 608 : } 609 : - 610 23856 : int file_namestamp_compare(const void* void_a, const void* void_b) + 610 23865 : int file_namestamp_compare(const void* void_a, const void* void_b) 611 : { 612 : int ret; 613 : - 614 23856 : ret = file_name_compare(void_a, void_b); - 615 23856 : if (ret != 0) - 616 185 : return ret; + 614 23865 : ret = file_name_compare(void_a, void_b); + 615 23865 : if (ret != 0) + 616 195 : return ret; 617 : - 618 23671 : return file_stamp_compare(void_a, void_b); + 618 23670 : return file_stamp_compare(void_a, void_b); 619 : } 620 : 621 0 : int file_pathstamp_compare(const void* void_a, const void* void_b) @@ -691,66 +691,66 @@ 629 0 : return file_stamp_compare(void_a, void_b); 630 : } 631 : - 632 3852016 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) + 632 3851976 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) 633 : { 634 : struct snapraid_extent* extent; 635 : - 636 3852016 : if (count == 0) { + 636 3851976 : if (count == 0) { 637 : /* LCOV_EXCL_START */ 638 : log_fatal(EINTERNAL, "Internal inconsistency: Allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); 639 : os_abort(); 640 : /* LCOV_EXCL_STOP */ 641 : } - 642 3852016 : if (file_pos + count > file->blockmax) { + 642 3851976 : if (file_pos + count > file->blockmax) { 643 : /* LCOV_EXCL_START */ 644 : log_fatal(EINTERNAL, "Internal inconsistency: Allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax); 645 : os_abort(); 646 : /* LCOV_EXCL_STOP */ 647 : } 648 : - 649 3852016 : extent = malloc_nofail(sizeof(struct snapraid_extent)); - 650 3852016 : extent->parity_pos = parity_pos; - 651 3852016 : extent->file = file; - 652 3852016 : extent->file_pos = file_pos; - 653 3852016 : extent->count = count; + 649 3851976 : extent = malloc_nofail(sizeof(struct snapraid_extent)); + 650 3851976 : extent->parity_pos = parity_pos; + 651 3851976 : extent->file = file; + 652 3851976 : extent->file_pos = file_pos; + 653 3851976 : extent->count = count; 654 : - 655 3852016 : return extent; + 655 3851976 : return extent; 656 : } 657 : - 658 3806435 : void extent_free(struct snapraid_extent* extent) + 658 3806358 : void extent_free(struct snapraid_extent* extent) 659 : { - 660 3806435 : free(extent); - 661 3806435 : } + 660 3806358 : free(extent); + 661 3806358 : } 662 : - 663 45768745 : int extent_parity_compare(const void* void_a, const void* void_b) + 663 45767042 : int extent_parity_compare(const void* void_a, const void* void_b) 664 : { - 665 45768745 : const struct snapraid_extent* arg_a = void_a; - 666 45768745 : const struct snapraid_extent* arg_b = void_b; + 665 45767042 : const struct snapraid_extent* arg_a = void_a; + 666 45767042 : const struct snapraid_extent* arg_b = void_b; 667 : - 668 45768745 : if (arg_a->parity_pos < arg_b->parity_pos) - 669 939508 : return -1; - 670 44829237 : if (arg_a->parity_pos > arg_b->parity_pos) - 671 44791372 : return 1; + 668 45767042 : if (arg_a->parity_pos < arg_b->parity_pos) + 669 940645 : return -1; + 670 44826397 : if (arg_a->parity_pos > arg_b->parity_pos) + 671 44788547 : return 1; 672 : - 673 37865 : return 0; + 673 37850 : return 0; 674 : } 675 : - 676 46158505 : int extent_file_compare(const void* void_a, const void* void_b) + 676 46157545 : int extent_file_compare(const void* void_a, const void* void_b) 677 : { - 678 46158505 : const struct snapraid_extent* arg_a = void_a; - 679 46158505 : const struct snapraid_extent* arg_b = void_b; + 678 46157545 : const struct snapraid_extent* arg_a = void_a; + 679 46157545 : const struct snapraid_extent* arg_b = void_b; 680 : - 681 46158505 : if (arg_a->file < arg_b->file) - 682 1049004 : return -1; - 683 45109501 : if (arg_a->file > arg_b->file) - 684 45040264 : return 1; + 681 46157545 : if (arg_a->file < arg_b->file) + 682 1039297 : return -1; + 683 45118248 : if (arg_a->file > arg_b->file) + 684 45049105 : return 1; 685 : - 686 69237 : if (arg_a->file_pos < arg_b->file_pos) - 687 183 : return -1; - 688 69054 : if (arg_a->file_pos > arg_b->file_pos) - 689 31189 : return 1; + 686 69143 : if (arg_a->file_pos < arg_b->file_pos) + 687 186 : return -1; + 688 68957 : if (arg_a->file_pos > arg_b->file_pos) + 689 31107 : return 1; 690 : - 691 37865 : return 0; + 691 37850 : return 0; 692 : } 693 : 694 123513 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag) @@ -813,96 +813,96 @@ 751 269 : return strcmp(arg, dir->sub); 752 : } 753 : - 754 1663 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip_access) + 754 1673 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip_access) 755 : { 756 : struct snapraid_disk* disk; 757 : unsigned i; 758 : - 759 1663 : disk = malloc_nofail(sizeof(struct snapraid_disk)); - 760 1663 : pathcpy(disk->name, sizeof(disk->name), name); - 761 1663 : pathimport(disk->dir, sizeof(disk->dir), dir); - 762 1663 : pathcpy(disk->uuid, sizeof(disk->uuid), uuid); + 759 1673 : disk = malloc_nofail(sizeof(struct snapraid_disk)); + 760 1673 : pathcpy(disk->name, sizeof(disk->name), name); + 761 1673 : pathimport(disk->dir, sizeof(disk->dir), dir); + 762 1673 : pathcpy(disk->uuid, sizeof(disk->uuid), uuid); 763 : 764 : /* ensure that the dir terminate with "/" if it isn't empty */ - 765 1663 : pathslash(disk->dir, sizeof(disk->dir)); + 765 1673 : pathslash(disk->dir, sizeof(disk->dir)); 766 : 767 : #if HAVE_THREAD - 768 1663 : thread_mutex_init(&disk->fs_mutex); + 768 1673 : thread_mutex_init(&disk->fs_mutex); 769 : #endif 770 : - 771 1663 : disk->smartctl[0] = 0; - 772 8315 : for (i = 0; i < SMART_IGNORE_MAX; ++i) - 773 6652 : disk->smartignore[i] = 0; - 774 1663 : disk->fstype[0] = 0; - 775 1663 : disk->fslabel[0] = 0; - 776 1663 : disk->device = dev; - 777 1663 : disk->tick = 0; - 778 1663 : disk->cached_blocks = 0; - 779 1663 : disk->progress_file = 0; - 780 1663 : disk->total_blocks = 0; - 781 1663 : disk->free_blocks = 0; - 782 1663 : disk->first_free_block = 0; - 783 1663 : disk->has_volatile_inodes = 0; - 784 1663 : disk->has_volatile_hardlinks = 0; - 785 1663 : disk->has_unreliable_physical = 0; - 786 1663 : disk->has_different_uuid = 0; - 787 1663 : disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */ - 788 1663 : disk->had_empty_uuid = 0; - 789 1663 : disk->mapping_idx = -1; - 790 1663 : disk->skip_access = skip_access; - 791 1663 : tommy_list_init(&disk->filelist); - 792 1663 : tommy_list_init(&disk->deletedlist); - 793 1663 : tommy_hashdyn_init(&disk->inodeset); - 794 1663 : tommy_hashdyn_init(&disk->pathset); - 795 1663 : tommy_hashdyn_init(&disk->stampset); - 796 1663 : tommy_list_init(&disk->linklist); - 797 1663 : tommy_hashdyn_init(&disk->linkset); - 798 1663 : tommy_list_init(&disk->dirlist); - 799 1663 : tommy_hashdyn_init(&disk->dirset); - 800 1663 : tommy_tree_init(&disk->fs_parity, extent_parity_compare); - 801 1663 : tommy_tree_init(&disk->fs_file, extent_file_compare); - 802 1663 : disk->fs_last = 0; + 771 1673 : disk->smartctl[0] = 0; + 772 8365 : for (i = 0; i < SMART_IGNORE_MAX; ++i) + 773 6692 : disk->smartignore[i] = 0; + 774 1673 : disk->fstype[0] = 0; + 775 1673 : disk->fslabel[0] = 0; + 776 1673 : disk->device = dev; + 777 1673 : disk->tick = 0; + 778 1673 : disk->cached_blocks = 0; + 779 1673 : disk->progress_file = 0; + 780 1673 : disk->total_blocks = 0; + 781 1673 : disk->free_blocks = 0; + 782 1673 : disk->first_free_block = 0; + 783 1673 : disk->has_volatile_inodes = 0; + 784 1673 : disk->has_volatile_hardlinks = 0; + 785 1673 : disk->has_unreliable_physical = 0; + 786 1673 : disk->has_different_uuid = 0; + 787 1673 : disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */ + 788 1673 : disk->had_empty_uuid = 0; + 789 1673 : disk->mapping_idx = -1; + 790 1673 : disk->skip_access = skip_access; + 791 1673 : tommy_list_init(&disk->filelist); + 792 1673 : tommy_list_init(&disk->deletedlist); + 793 1673 : tommy_hashdyn_init(&disk->inodeset); + 794 1673 : tommy_hashdyn_init(&disk->pathset); + 795 1673 : tommy_hashdyn_init(&disk->stampset); + 796 1673 : tommy_list_init(&disk->linklist); + 797 1673 : tommy_hashdyn_init(&disk->linkset); + 798 1673 : tommy_list_init(&disk->dirlist); + 799 1673 : tommy_hashdyn_init(&disk->dirset); + 800 1673 : tommy_tree_init(&disk->fs_parity, extent_parity_compare); + 801 1673 : tommy_tree_init(&disk->fs_file, extent_file_compare); + 802 1673 : disk->fs_last = 0; 803 : - 804 1663 : return disk; + 804 1673 : return disk; 805 : } 806 : - 807 1603 : void disk_free(struct snapraid_disk* disk) + 807 1613 : void disk_free(struct snapraid_disk* disk) 808 : { - 809 1603 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free); - 810 1603 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free); - 811 1603 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)extent_free); - 812 1603 : tommy_hashdyn_done(&disk->inodeset); - 813 1603 : tommy_hashdyn_done(&disk->pathset); - 814 1603 : tommy_hashdyn_done(&disk->stampset); - 815 1603 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free); - 816 1603 : tommy_hashdyn_done(&disk->linkset); - 817 1603 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); - 818 1603 : tommy_hashdyn_done(&disk->dirset); + 809 1613 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free); + 810 1613 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free); + 811 1613 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)extent_free); + 812 1613 : tommy_hashdyn_done(&disk->inodeset); + 813 1613 : tommy_hashdyn_done(&disk->pathset); + 814 1613 : tommy_hashdyn_done(&disk->stampset); + 815 1613 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free); + 816 1613 : tommy_hashdyn_done(&disk->linkset); + 817 1613 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); + 818 1613 : tommy_hashdyn_done(&disk->dirset); 819 : 820 : #if HAVE_THREAD - 821 1603 : thread_mutex_destroy(&disk->fs_mutex); + 821 1613 : thread_mutex_destroy(&disk->fs_mutex); 822 : #endif 823 : - 824 1603 : free(disk); - 825 1603 : } + 824 1613 : free(disk); + 825 1613 : } 826 : - 827 64751658 : static inline void fs_lock(struct snapraid_disk* disk) + 827 64616403 : static inline void fs_lock(struct snapraid_disk* disk) 828 : { 829 : #if HAVE_THREAD - 830 64751658 : thread_mutex_lock(&disk->fs_mutex); + 830 64616403 : thread_mutex_lock(&disk->fs_mutex); 831 : #else 832 : (void)disk; 833 : #endif - 834 64751658 : } + 834 64616403 : } 835 : - 836 64751658 : static inline void fs_unlock(struct snapraid_disk* disk) + 836 64616403 : static inline void fs_unlock(struct snapraid_disk* disk) 837 : { 838 : #if HAVE_THREAD - 839 64751658 : thread_mutex_unlock(&disk->fs_mutex); + 839 64616403 : thread_mutex_unlock(&disk->fs_mutex); 840 : #else 841 : (void)disk; 842 : #endif - 843 64751658 : } + 843 64616403 : } 844 : 845 : struct extent_disk_empty { 846 : block_off_t blockmax; @@ -924,14 +924,14 @@ 862 5 : return -1; 863 : } 864 : - 865 942 : int fs_is_empty(struct snapraid_disk* disk, block_off_t blockmax) + 865 936 : int fs_is_empty(struct snapraid_disk* disk, block_off_t blockmax) 866 : { - 867 942 : struct extent_disk_empty arg = { blockmax }; + 867 936 : struct extent_disk_empty arg = { blockmax }; 868 : 869 : /* if there is an element, it's not empty */ 870 : /* even if links and dirs have no block allocation */ - 871 942 : if (!tommy_list_empty(&disk->filelist)) - 872 843 : return 0; + 871 936 : if (!tommy_list_empty(&disk->filelist)) + 872 837 : return 0; 873 99 : if (!tommy_list_empty(&disk->linklist)) 874 0 : return 0; 875 99 : if (!tommy_list_empty(&disk->dirlist)) @@ -959,30 +959,30 @@ 897 : * 898 : * The maximum parity position is stored as size. 899 : */ - 900 52890 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b) + 900 52796 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b) 901 : { - 902 52890 : struct extent_disk_size* arg_a = (void*)void_a; - 903 52890 : const struct snapraid_extent* arg_b = void_b; + 902 52796 : struct extent_disk_size* arg_a = (void*)void_a; + 903 52796 : const struct snapraid_extent* arg_b = void_b; 904 : 905 : /* get the maximum size */ - 906 52890 : if (arg_a->size < arg_b->parity_pos + arg_b->count) - 907 52890 : arg_a->size = arg_b->parity_pos + arg_b->count; + 906 52796 : if (arg_a->size < arg_b->parity_pos + arg_b->count) + 907 52796 : arg_a->size = arg_b->parity_pos + arg_b->count; 908 : 909 : /* search always for a bigger one */ - 910 52890 : return 1; + 910 52796 : return 1; 911 : } 912 : - 913 4549 : block_off_t fs_size(struct snapraid_disk* disk) + 913 4543 : block_off_t fs_size(struct snapraid_disk* disk) 914 : { - 915 4549 : struct extent_disk_size arg = { 0 }; + 915 4543 : struct extent_disk_size arg = { 0 }; 916 : - 917 4549 : fs_lock(disk); + 917 4543 : fs_lock(disk); 918 : - 919 4549 : tommy_tree_search_compare(&disk->fs_parity, extent_disk_size_compare_unlock, &arg); + 919 4543 : tommy_tree_search_compare(&disk->fs_parity, extent_disk_size_compare_unlock, &arg); 920 : - 921 4549 : fs_unlock(disk); + 921 4543 : fs_unlock(disk); 922 : - 923 4549 : return arg.size; + 923 4543 : return arg.size; 924 : } 925 : 926 : struct extent_check { @@ -990,23 +990,23 @@ 928 : int result; 929 : }; 930 : - 931 6837675 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj) + 931 6820724 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj) 932 : { - 933 6837675 : struct extent_check* arg = void_arg; - 934 6837675 : const struct snapraid_extent* obj = void_obj; - 935 6837675 : const struct snapraid_extent* prev = arg->prev; + 933 6820724 : struct extent_check* arg = void_arg; + 934 6820724 : const struct snapraid_extent* obj = void_obj; + 935 6820724 : const struct snapraid_extent* prev = arg->prev; 936 : 937 : /* set the next previous block */ - 938 6837675 : arg->prev = obj; + 938 6820724 : arg->prev = obj; 939 : 940 : /* stop reporting if too many errors */ - 941 6837675 : if (arg->result > 100) { + 941 6820724 : if (arg->result > 100) { 942 : /* LCOV_EXCL_START */ 943 : return; 944 : /* LCOV_EXCL_STOP */ 945 : } 946 : - 947 6837675 : if (obj->count == 0) { + 947 6820724 : if (obj->count == 0) { 948 : /* LCOV_EXCL_START */ 949 : log_fatal(EINTERNAL, "Internal inconsistency: Parity count zero for file '%s' at '%u'\n", 950 : obj->file->sub, obj->parity_pos); @@ -1016,11 +1016,11 @@ 954 : } 955 : 956 : /* check only if there is a previous block */ - 957 6837675 : if (!prev) - 958 2855 : return; + 957 6820724 : if (!prev) + 958 2849 : return; 959 : 960 : /* check the order */ - 961 6834820 : if (prev->parity_pos >= obj->parity_pos) { + 961 6817875 : if (prev->parity_pos >= obj->parity_pos) { 962 : /* LCOV_EXCL_START */ 963 : log_fatal(EINTERNAL, "Internal inconsistency: Parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", 964 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); @@ -1030,7 +1030,7 @@ 968 : } 969 : 970 : /* check that the extents don't overlap */ - 971 6834820 : if (prev->parity_pos + prev->count > obj->parity_pos) { + 971 6817875 : if (prev->parity_pos + prev->count > obj->parity_pos) { 972 : /* LCOV_EXCL_START */ 973 : log_fatal(EINTERNAL, "Internal inconsistency: Parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", 974 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); @@ -1040,23 +1040,23 @@ 978 : } 979 : } 980 : - 981 6837675 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj) + 981 6820724 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj) 982 : { - 983 6837675 : struct extent_check* arg = void_arg; - 984 6837675 : const struct snapraid_extent* obj = void_obj; - 985 6837675 : const struct snapraid_extent* prev = arg->prev; + 983 6820724 : struct extent_check* arg = void_arg; + 984 6820724 : const struct snapraid_extent* obj = void_obj; + 985 6820724 : const struct snapraid_extent* prev = arg->prev; 986 : 987 : /* set the next previous block */ - 988 6837675 : arg->prev = obj; + 988 6820724 : arg->prev = obj; 989 : 990 : /* stop reporting if too many errors */ - 991 6837675 : if (arg->result > 100) { + 991 6820724 : if (arg->result > 100) { 992 : /* LCOV_EXCL_START */ 993 : return; 994 : /* LCOV_EXCL_STOP */ 995 : } 996 : - 997 6837675 : if (obj->count == 0) { + 997 6820724 : if (obj->count == 0) { 998 : /* LCOV_EXCL_START */ 999 : log_fatal(EINTERNAL, "Internal inconsistency: File count zero for file '%s' at '%u'\n", 1000 : obj->file->sub, obj->file_pos); @@ -1068,9 +1068,9 @@ 1006 : /* note that for deleted files, some extents may be missing */ 1007 : 1008 : /* if the files are different */ - 1009 6837675 : if (!prev || prev->file != obj->file) { - 1010 6791430 : if (prev != 0) { - 1011 6788575 : if (file_flag_has(prev->file, FILE_IS_DELETED)) { + 1009 6820724 : if (!prev || prev->file != obj->file) { + 1010 6774697 : if (prev != 0) { + 1011 6771848 : if (file_flag_has(prev->file, FILE_IS_DELETED)) { 1012 : /* check that the extent doesn't overflow the file */ 1013 59775 : if (prev->file_pos + prev->count > prev->file->blockmax) { 1014 : /* LCOV_EXCL_START */ @@ -1082,7 +1082,7 @@ 1020 : } 1021 : } else { 1022 : /* check that the extent ends the file */ - 1023 6728800 : if (prev->file_pos + prev->count != prev->file->blockmax) { + 1023 6712073 : if (prev->file_pos + prev->count != prev->file->blockmax) { 1024 : /* LCOV_EXCL_START */ 1025 : log_fatal(EINTERNAL, "Internal inconsistency: File end for file '%s' at '%u:%u' instead of size '%u'\n", 1026 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); @@ -1093,7 +1093,7 @@ 1031 : } 1032 : } 1033 : - 1034 6791430 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { + 1034 6774697 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { 1035 : /* check that the extent doesn't overflow the file */ 1036 59852 : if (obj->file_pos + obj->count > obj->file->blockmax) { 1037 : /* LCOV_EXCL_START */ @@ -1105,7 +1105,7 @@ 1043 : } 1044 : } else { 1045 : /* check that the extent starts the file */ - 1046 6731578 : if (obj->file_pos != 0) { + 1046 6714845 : if (obj->file_pos != 0) { 1047 : /* LCOV_EXCL_START */ 1048 : log_fatal(EINTERNAL, "Internal inconsistency: File start for file '%s' at '%u:%u'\n", 1049 : obj->file->sub, obj->file_pos, obj->count); @@ -1116,7 +1116,7 @@ 1054 : } 1055 : } else { 1056 : /* check the order */ - 1057 46245 : if (prev->file_pos >= obj->file_pos) { + 1057 46027 : if (prev->file_pos >= obj->file_pos) { 1058 : /* LCOV_EXCL_START */ 1059 : log_fatal(EINTERNAL, "Internal inconsistency: File order for file '%s' at '%u:%u' and at '%u:%u'\n", 1060 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); @@ -1125,7 +1125,7 @@ 1063 : /* LCOV_EXCL_STOP */ 1064 : } 1065 : - 1066 46245 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { + 1066 46027 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { 1067 : /* check that the extents don't overlap */ 1068 27 : if (prev->file_pos + prev->count > obj->file_pos) { 1069 : /* LCOV_EXCL_START */ @@ -1137,7 +1137,7 @@ 1075 : } 1076 : } else { 1077 : /* check that the extents are sequential */ - 1078 46218 : if (prev->file_pos + prev->count != obj->file_pos) { + 1078 46000 : if (prev->file_pos + prev->count != obj->file_pos) { 1079 : /* LCOV_EXCL_START */ 1080 : log_fatal(EINTERNAL, "Internal inconsistency: File sequence for file '%s' at '%u:%u' and at '%u:%u'\n", 1081 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); @@ -1149,29 +1149,29 @@ 1087 : } 1088 : } 1089 : - 1090 3120 : int fs_check(struct snapraid_disk* disk) + 1090 3114 : int fs_check(struct snapraid_disk* disk) 1091 : { 1092 : struct extent_check arg; 1093 : 1094 : /* error count starts from 0 */ - 1095 3120 : arg.result = 0; + 1095 3114 : arg.result = 0; 1096 : - 1097 3120 : fs_lock(disk); + 1097 3114 : fs_lock(disk); 1098 : 1099 : /* check parity sequence */ - 1100 3120 : arg.prev = 0; - 1101 3120 : tommy_tree_foreach_arg(&disk->fs_parity, extent_parity_check_foreach_unlock, &arg); + 1100 3114 : arg.prev = 0; + 1101 3114 : tommy_tree_foreach_arg(&disk->fs_parity, extent_parity_check_foreach_unlock, &arg); 1102 : 1103 : /* check file sequence */ - 1104 3120 : arg.prev = 0; - 1105 3120 : tommy_tree_foreach_arg(&disk->fs_file, extent_file_check_foreach_unlock, &arg); + 1104 3114 : arg.prev = 0; + 1105 3114 : tommy_tree_foreach_arg(&disk->fs_file, extent_file_check_foreach_unlock, &arg); 1106 : - 1107 3120 : fs_unlock(disk); + 1107 3114 : fs_unlock(disk); 1108 : - 1109 3120 : if (arg.result != 0) + 1109 3114 : if (arg.result != 0) 1110 0 : return -1; 1111 : - 1112 3120 : return 0; + 1112 3114 : return 0; 1113 : } 1114 : 1115 : struct extent_parity_inside { @@ -1181,17 +1181,17 @@ 1119 : /** 1120 : * Compare the extent if containing the specified parity position. 1121 : */ - 1122 158551658 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b) + 1122 158133634 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b) 1123 : { - 1124 158551658 : const struct extent_parity_inside* arg_a = void_a; - 1125 158551658 : const struct snapraid_extent* arg_b = void_b; + 1124 158133634 : const struct extent_parity_inside* arg_a = void_a; + 1125 158133634 : const struct snapraid_extent* arg_b = void_b; 1126 : - 1127 158551658 : if (arg_a->parity_pos < arg_b->parity_pos) - 1128 58193079 : return -1; - 1129 100358579 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) - 1130 87784588 : return 1; + 1127 158133634 : if (arg_a->parity_pos < arg_b->parity_pos) + 1128 58032399 : return -1; + 1129 100101235 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) + 1130 87563112 : return 1; 1131 : - 1132 12573991 : return 0; + 1132 12538123 : return 0; 1133 : } 1134 : 1135 : /** @@ -1199,28 +1199,28 @@ 1137 : * The search is optimized for sequential accesses. 1138 : * \return If not found return 0 1139 : */ - 1140 49968851 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos) + 1140 49874908 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos) 1141 : { 1142 : struct snapraid_extent* extent; 1143 : 1144 : /* check if the last accessed extent matches */ - 1145 49968851 : if (*fs_last - 1146 49934657 : && parity_pos >= (*fs_last)->parity_pos - 1147 49256770 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count + 1145 49874908 : if (*fs_last + 1146 49840714 : && parity_pos >= (*fs_last)->parity_pos + 1147 49161414 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count 1148 : ) { - 1149 35471955 : extent = *fs_last; + 1149 35415936 : extent = *fs_last; 1150 : } else { - 1151 14496896 : struct extent_parity_inside arg = { parity_pos }; - 1152 14496896 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg); + 1151 14458972 : struct extent_parity_inside arg = { parity_pos }; + 1152 14458972 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg); 1153 : } 1154 : - 1155 49968851 : if (!extent) - 1156 1922905 : return 0; + 1155 49874908 : if (!extent) + 1156 1920849 : return 0; 1157 : 1158 : /* store the last accessed extent */ - 1159 48045946 : *fs_last = extent; + 1159 47954059 : *fs_last = extent; 1160 : - 1161 48045946 : return extent; + 1161 47954059 : return extent; 1162 : } 1163 : 1164 : struct extent_file_inside { @@ -1231,22 +1231,22 @@ 1169 : /** 1170 : * Compare the extent if containing the specified file position. 1171 : */ - 1172 22976989 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b) + 1172 22802303 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b) 1173 : { - 1174 22976989 : const struct extent_file_inside* arg_a = void_a; - 1175 22976989 : const struct snapraid_extent* arg_b = void_b; + 1174 22802303 : const struct extent_file_inside* arg_a = void_a; + 1175 22802303 : const struct snapraid_extent* arg_b = void_b; 1176 : - 1177 22976989 : if (arg_a->file < arg_b->file) - 1178 9660370 : return -1; - 1179 13316619 : if (arg_a->file > arg_b->file) - 1180 11130615 : return 1; + 1177 22802303 : if (arg_a->file < arg_b->file) + 1178 9581099 : return -1; + 1179 13221204 : if (arg_a->file > arg_b->file) + 1180 11052341 : return 1; 1181 : - 1182 2186004 : if (arg_a->file_pos < arg_b->file_pos) - 1183 7579 : return -1; - 1184 2178425 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) - 1185 8807 : return 1; + 1182 2168863 : if (arg_a->file_pos < arg_b->file_pos) + 1183 7628 : return -1; + 1184 2161235 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) + 1185 8545 : return 1; 1186 : - 1187 2169618 : return 0; + 1187 2152690 : return 0; 1188 : } 1189 : 1190 : /** @@ -1254,88 +1254,88 @@ 1192 : * The search is optimized for sequential accesses. 1193 : * \return If not found return 0 1194 : */ - 1195 10949888 : 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) + 1195 10908566 : 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) 1196 : { 1197 : struct snapraid_extent* extent; 1198 : 1199 : /* check if the last accessed extent matches */ - 1200 10949888 : if (*fs_last - 1201 10927396 : && file == (*fs_last)->file - 1202 8794650 : && file_pos >= (*fs_last)->file_pos - 1203 8794650 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count + 1200 10908566 : if (*fs_last + 1201 10886120 : && file == (*fs_last)->file + 1202 8770101 : && file_pos >= (*fs_last)->file_pos + 1203 8770101 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count 1204 : ) { - 1205 8780262 : extent = *fs_last; + 1205 8755868 : extent = *fs_last; 1206 : } else { - 1207 2169626 : struct extent_file_inside arg = { file, file_pos }; - 1208 2169626 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg); + 1207 2152698 : struct extent_file_inside arg = { file, file_pos }; + 1208 2152698 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg); 1209 : } 1210 : - 1211 10949888 : if (!extent) + 1211 10908566 : if (!extent) 1212 8 : return 0; 1213 : 1214 : /* store the last accessed extent */ - 1215 10949880 : *fs_last = extent; + 1215 10908558 : *fs_last = extent; 1216 : - 1217 10949880 : return extent; + 1217 10908558 : return extent; 1218 : } 1219 : - 1220 49865865 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) + 1220 49771977 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) 1221 : { 1222 : struct snapraid_extent* extent; 1223 : struct snapraid_file* file; 1224 : - 1225 49865865 : fs_lock(disk); + 1225 49771977 : fs_lock(disk); 1226 : - 1227 49865865 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + 1227 49771977 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); 1228 : - 1229 49865865 : if (!extent) { - 1230 1922905 : fs_unlock(disk); - 1231 1922905 : return 0; + 1229 49771977 : if (!extent) { + 1230 1920849 : fs_unlock(disk); + 1231 1920849 : return 0; 1232 : } 1233 : - 1234 47942960 : if (file_pos) - 1235 47732115 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos); + 1234 47851128 : if (file_pos) + 1235 47640269 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos); 1236 : - 1237 47942960 : file = extent->file; + 1237 47851128 : file = extent->file; 1238 : - 1239 47942960 : fs_unlock(disk); - 1240 47942960 : return file; + 1239 47851128 : fs_unlock(disk); + 1240 47851128 : return file; 1241 : } 1242 : - 1243 5301463 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) + 1243 5260119 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) 1244 : { 1245 : struct snapraid_extent* extent; 1246 : block_off_t ret; 1247 : - 1248 5301463 : fs_lock(disk); + 1248 5260119 : fs_lock(disk); 1249 : - 1250 5301463 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos); - 1251 5301463 : if (!extent) { + 1250 5260119 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos); + 1251 5260119 : if (!extent) { 1252 8 : fs_unlock(disk); 1253 8 : return POS_NULL; 1254 : } 1255 : - 1256 5301455 : ret = extent->parity_pos + (file_pos - extent->file_pos); + 1256 5260111 : ret = extent->parity_pos + (file_pos - extent->file_pos); 1257 : - 1258 5301455 : fs_unlock(disk); - 1259 5301455 : return ret; + 1258 5260111 : fs_unlock(disk); + 1259 5260111 : return ret; 1260 : } 1261 : - 1262 9473576 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) + 1262 9473620 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) 1263 : { 1264 : struct snapraid_extent* extent; 1265 : struct snapraid_extent* parity_extent; 1266 : struct snapraid_extent* file_extent; 1267 : - 1268 9473576 : fs_lock(disk); + 1268 9473620 : fs_lock(disk); 1269 : - 1270 9473576 : if (file_pos > 0) { + 1270 9473620 : if (file_pos > 0) { 1271 : /* search an existing extent for the previous file_pos */ - 1272 5648425 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1); + 1272 5648447 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1); 1273 : - 1274 5648425 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) { + 1274 5648447 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) { 1275 : /* ensure that we are extending the extent at the end */ - 1276 5621562 : if (file_pos != extent->file_pos + extent->count) { + 1276 5621646 : if (file_pos != extent->file_pos + extent->count) { 1277 : /* LCOV_EXCL_START */ 1278 : log_fatal(EINTERNAL, "Internal inconsistency: 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); 1279 : os_abort(); @@ -1343,21 +1343,21 @@ 1281 : } 1282 : 1283 : /* extend the existing extent */ - 1284 5621562 : ++extent->count; + 1284 5621646 : ++extent->count; 1285 : - 1286 5621562 : fs_unlock(disk); - 1287 5621562 : return; + 1286 5621646 : fs_unlock(disk); + 1287 5621646 : return; 1288 : } 1289 : } 1290 : 1291 : /* a extent doesn't exist, and we have to create a new one */ - 1292 3852014 : extent = extent_alloc(parity_pos, file, file_pos, 1); + 1292 3851974 : extent = extent_alloc(parity_pos, file, file_pos, 1); 1293 : 1294 : /* insert the extent in the trees */ - 1295 3852014 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent); - 1296 3852014 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent); + 1295 3851974 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent); + 1296 3851974 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent); 1297 : - 1298 3852014 : if (parity_extent != extent || file_extent != extent) { + 1298 3851974 : if (parity_extent != extent || file_extent != extent) { 1299 : /* LCOV_EXCL_START */ 1300 : log_fatal(EINTERNAL, "Internal inconsistency: 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); 1301 : os_abort(); @@ -1365,12 +1365,12 @@ 1303 : } 1304 : 1305 : /* store the last accessed extent */ - 1306 3852014 : disk->fs_last = extent; + 1306 3851974 : disk->fs_last = extent; 1307 : - 1308 3852014 : fs_unlock(disk); + 1308 3851974 : fs_unlock(disk); 1309 : } 1310 : - 1311 102986 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) + 1311 102931 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) 1312 : { 1313 : struct snapraid_extent* extent; 1314 : struct snapraid_extent* second_extent; @@ -1378,10 +1378,10 @@ 1316 : struct snapraid_extent* file_extent; 1317 : block_off_t first_count, second_count; 1318 : - 1319 102986 : fs_lock(disk); + 1319 102931 : fs_lock(disk); 1320 : - 1321 102986 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); - 1322 102986 : if (!extent) { + 1321 102931 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + 1322 102931 : if (!extent) { 1323 : /* LCOV_EXCL_START */ 1324 : log_fatal(EINTERNAL, "Internal inconsistency: Deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name); 1325 : os_abort(); @@ -1389,29 +1389,29 @@ 1327 : } 1328 : 1329 : /* if it's the only block of the extent, delete it */ - 1330 102986 : if (extent->count == 1) { + 1330 102931 : if (extent->count == 1) { 1331 : /* remove from the trees */ - 1332 37865 : tommy_tree_remove(&disk->fs_parity, extent); - 1333 37865 : tommy_tree_remove(&disk->fs_file, extent); + 1332 37850 : tommy_tree_remove(&disk->fs_parity, extent); + 1333 37850 : tommy_tree_remove(&disk->fs_file, extent); 1334 : 1335 : /* deallocate */ - 1336 37865 : extent_free(extent); + 1336 37850 : extent_free(extent); 1337 : 1338 : /* clear the last accessed extent */ - 1339 37865 : disk->fs_last = 0; + 1339 37850 : disk->fs_last = 0; 1340 : - 1341 37865 : fs_unlock(disk); - 1342 37865 : return; + 1341 37850 : fs_unlock(disk); + 1342 37850 : return; 1343 : } 1344 : 1345 : /* if it's at the start of the extent, shrink the extent */ - 1346 65121 : if (parity_pos == extent->parity_pos) { - 1347 65118 : ++extent->parity_pos; - 1348 65118 : ++extent->file_pos; - 1349 65118 : --extent->count; + 1346 65081 : if (parity_pos == extent->parity_pos) { + 1347 65078 : ++extent->parity_pos; + 1348 65078 : ++extent->file_pos; + 1349 65078 : --extent->count; 1350 : - 1351 65118 : fs_unlock(disk); - 1352 65118 : return; + 1351 65078 : fs_unlock(disk); + 1352 65078 : return; 1353 : } 1354 : 1355 : /* if it's at the end of the extent, shrink the extent */ @@ -1449,28 +1449,28 @@ 1387 2 : fs_unlock(disk); 1388 : } 1389 : - 1390 56447214 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) + 1390 56273071 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) 1391 : { - 1392 56447214 : if (file_pos >= file->blockmax) { + 1392 56273071 : if (file_pos >= file->blockmax) { 1393 : /* LCOV_EXCL_START */ 1394 : log_fatal(EINTERNAL, "Internal inconsistency: Dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); 1395 : os_abort(); 1396 : /* LCOV_EXCL_STOP */ 1397 : } 1398 : - 1399 56447214 : return file_block(file, file_pos); + 1399 56273071 : return file_block(file, file_pos); 1400 : } 1401 : - 1402 38360216 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos) + 1402 38266700 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos) 1403 : { 1404 : struct snapraid_file* file; 1405 : block_off_t file_pos; 1406 : - 1407 38360216 : file = fs_par2file_find(disk, parity_pos, &file_pos); - 1408 38360216 : if (file == 0) - 1409 1922905 : return BLOCK_NULL; + 1407 38266700 : file = fs_par2file_find(disk, parity_pos, &file_pos); + 1408 38266700 : if (file == 0) + 1409 1920849 : return BLOCK_NULL; 1410 : - 1411 36437311 : return fs_file2block_get(file, file_pos); + 1411 36345851 : return fs_file2block_get(file, file_pos); 1412 : } 1413 : 1414 1627 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid) @@ -1495,78 +1495,78 @@ 1433 : /****************************************************************************/ 1434 : /* bucket */ 1435 : - 1436 711 : static int bucket_cmp(const void* void_a, const void* void_b) + 1436 521 : static int bucket_cmp(const void* void_a, const void* void_b) 1437 : { - 1438 711 : const struct snapraid_bucket* a = void_a; - 1439 711 : const struct snapraid_bucket* b = void_b; - 1440 711 : if (a->time_at < b->time_at) - 1441 355 : return -1; - 1442 356 : if (a->time_at > b->time_at) - 1443 356 : return 1; + 1438 521 : const struct snapraid_bucket* a = void_a; + 1439 521 : const struct snapraid_bucket* b = void_b; + 1440 521 : if (a->time_at < b->time_at) + 1441 314 : return -1; + 1442 207 : if (a->time_at > b->time_at) + 1443 207 : return 1; 1444 0 : return 0; 1445 : } 1446 : - 1447 746 : void bucket_free(struct snapraid_bucket* bucket) + 1447 705 : void bucket_free(struct snapraid_bucket* bucket) 1448 : { - 1449 746 : free(bucket); - 1450 746 : } + 1449 705 : free(bucket); + 1450 705 : } 1451 : - 1452 72052 : void bucket_insert(tommy_hashdyn* bucket_hash, time_t time_at, block_off_t count, int justsynced) + 1452 55958 : void bucket_insert(tommy_hashdyn* bucket_hash, time_t time_at, block_off_t count, int justsynced) 1453 : { - 1454 72052 : tommy_hash_t hash = tommy_inthash_u64(time_at); - 1455 72052 : tommy_node* i = tommy_hashdyn_bucket(bucket_hash, hash); - 1456 72078 : while (i) { - 1457 71322 : struct snapraid_bucket* entry = i->data; - 1458 71322 : if (entry->time_at == time_at) { - 1459 71296 : if (justsynced) - 1460 43455 : entry->count_justsynced += count; + 1454 55958 : tommy_hash_t hash = tommy_inthash_u64(time_at); + 1455 55958 : tommy_node* i = tommy_hashdyn_bucket(bucket_hash, hash); + 1456 55958 : while (i) { + 1457 55242 : struct snapraid_bucket* entry = i->data; + 1458 55242 : if (entry->time_at == time_at) { + 1459 55242 : if (justsynced) + 1460 27409 : entry->count_justsynced += count; 1461 : else - 1462 27841 : entry->count_scrubbed += count; - 1463 71296 : return; + 1462 27833 : entry->count_scrubbed += count; + 1463 55242 : return; 1464 : } - 1465 26 : i = i->next; + 1465 0 : i = i->next; 1466 : } 1467 : - 1468 756 : struct snapraid_bucket* entry = malloc_nofail(sizeof(struct snapraid_bucket)); - 1469 756 : entry->time_at = time_at; - 1470 756 : if (justsynced) { - 1471 683 : entry->count_justsynced = count; - 1472 683 : entry->count_scrubbed = 0; + 1468 716 : struct snapraid_bucket* entry = malloc_nofail(sizeof(struct snapraid_bucket)); + 1469 716 : entry->time_at = time_at; + 1470 716 : if (justsynced) { + 1471 643 : entry->count_justsynced = count; + 1472 643 : entry->count_scrubbed = 0; 1473 : } else { 1474 73 : entry->count_justsynced = 0; 1475 73 : entry->count_scrubbed = count; 1476 : } 1477 : - 1478 756 : tommy_hashdyn_insert(bucket_hash, &entry->node, entry, hash); + 1478 716 : tommy_hashdyn_insert(bucket_hash, &entry->node, entry, hash); 1479 : } 1480 : - 1481 421 : void bucket_to_list(tommy_hashdyn* bucket_hash, tommy_list* bucket_list, block_off_t* bucketcount) + 1481 420 : void bucket_to_list(tommy_hashdyn* bucket_hash, tommy_list* bucket_list, block_off_t* bucketcount) 1482 : { 1483 : /* clear previous list */ - 1484 421 : tommy_list_foreach(bucket_list, (tommy_foreach_func*)bucket_free); - 1485 421 : tommy_list_init(bucket_list); + 1484 420 : tommy_list_foreach(bucket_list, (tommy_foreach_func*)bucket_free); + 1485 420 : tommy_list_init(bucket_list); 1486 : - 1487 421 : log_tag("list:bucket_begin\n"); + 1487 420 : log_tag("list:bucket_begin\n"); 1488 : - 1489 421 : log_tag("bucket:count:%" PRIu64 "\n", (uint64_t)tommy_hashdyn_count(bucket_hash)); + 1489 420 : log_tag("bucket:count:%" PRIu64 "\n", (uint64_t)tommy_hashdyn_count(bucket_hash)); 1490 : - 1491 421 : tommy_hashdyn_to_list(bucket_hash, bucket_list); + 1491 420 : tommy_hashdyn_to_list(bucket_hash, bucket_list); 1492 : - 1493 421 : tommy_list_sort(bucket_list, bucket_cmp); + 1493 420 : tommy_list_sort(bucket_list, bucket_cmp); 1494 : - 1495 421 : block_off_t count = 0; - 1496 1177 : for (tommy_node* i = tommy_list_head(bucket_list); i != 0; i = i->next) { - 1497 756 : struct snapraid_bucket* entry = i->data; - 1498 756 : count += entry->count_scrubbed + entry->count_justsynced; - 1499 756 : log_tag("bucket:entry:%" PRIu64 ":%u:%u\n", (uint64_t)entry->time_at, entry->count_scrubbed, entry->count_justsynced); + 1495 420 : block_off_t count = 0; + 1496 1136 : for (tommy_node* i = tommy_list_head(bucket_list); i != 0; i = i->next) { + 1497 716 : struct snapraid_bucket* entry = i->data; + 1498 716 : count += entry->count_scrubbed + entry->count_justsynced; + 1499 716 : log_tag("bucket:entry:%" PRIu64 ":%u:%u\n", (uint64_t)entry->time_at, entry->count_scrubbed, entry->count_justsynced); 1500 : } 1501 : - 1502 421 : log_tag("bucket:block_count:%u\n", count); + 1502 420 : log_tag("bucket:block_count:%u\n", count); 1503 : - 1504 421 : log_tag("list:bucket_end\n"); + 1504 420 : log_tag("list:bucket_end\n"); 1505 : - 1506 421 : *bucketcount = count; - 1507 421 : } + 1506 420 : *bucketcount = count; + 1507 420 : } 1508 : 1509 : /****************************************************************************/ 1510 : /* format */ @@ -1585,14 +1585,14 @@ 1523 : /** 1524 : * Format a path name for terminal reference 1525 : */ - 1526 366067 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer) + 1526 366236 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer) 1527 : { 1528 : const char* out[3]; 1529 : - 1530 366067 : switch (FMT_MODE) { - 1531 342002 : case FMT_FILE : + 1530 366236 : switch (FMT_MODE) { + 1531 342171 : case FMT_FILE : 1532 : default : - 1533 342002 : return esc_shell(str, buffer); + 1533 342171 : return esc_shell(str, buffer); 1534 12030 : case FMT_DISK : 1535 12030 : out[0] = disk->name; 1536 12030 : out[1] = ":"; diff --git a/cov/cmdline/elem.h.func-sort-c.html b/cov/cmdline/elem.h.func-sort-c.html index a7fb7cd8..038b35bf 100644 --- a/cov/cmdline/elem.h.func-sort-c.html +++ b/cov/cmdline/elem.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 41 @@ -77,7 +77,7 @@ info_set_bad - 1771 + 1772 info_set_rehash @@ -85,7 +85,7 @@ file_flag_clear - 12545 + 13077 fs_par2block_get @@ -93,7 +93,7 @@ info_get_justsynced - 23836 + 18930 link_flag_set @@ -101,11 +101,11 @@ hash_is_unique - 44043 + 43988 link_flag_get - 96285 + 95741 hash_zero_set @@ -117,7 +117,7 @@ info_make - 191697 + 180457 link_flag_has @@ -125,103 +125,103 @@ block_has_file_and_valid_parity - 226094 + 226098 info_get_bad - 247612 + 242727 hash_is_invalid - 756505 + 756707 hash_is_zero - 760014 + 760217 info_get_time - 798417 + 786514 info_set - 1757573 + 1757522 info_get_rehash - 2048435 + 2036469 block_has_updated_hash - 2188335 + 2188345 block_has_past_hash - 2686312 + 2686411 info_get - 3171512 + 3152579 filter_hidden - 3231524 + 3231650 file_path_hash - 4002881 + 4002848 fs_file2par_get - 4959524 + 4918180 file_inode_hash - 5220350 + 5220892 file_flag_set - 5792498 + 5793396 file_stamp_hash - 6390305 + 6390630 hash_invalid_set - 9532465 + 9532509 fs_par2file_get - 11505649 + 11505277 block_state_set - 19703104 + 19702751 block_has_invalid_parity - 23228801 + 23186776 block_has_file - 25304571 + 25253088 file_flag_has - 39608750 + 39575710 file_block - 66152513 + 65978414 block_sizeof - 69982896 + 69808821 block_state_get - 74577257 + 74400305
diff --git a/cov/cmdline/elem.h.func.html b/cov/cmdline/elem.h.func.html index bf49b1bf..3a131467 100644 --- a/cov/cmdline/elem.h.func.html +++ b/cov/cmdline/elem.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 41 @@ -61,35 +61,35 @@ block_has_file - 25304571 + 25253088 block_has_file_and_valid_parity - 226094 + 226098 block_has_invalid_parity - 23228801 + 23186776 block_has_past_hash - 2686312 + 2686411 block_has_updated_hash - 2188335 + 2188345 block_sizeof - 69982896 + 69808821 block_state_get - 74577257 + 74400305 block_state_set - 19703104 + 19702751 dir_flag_has @@ -105,39 +105,39 @@ file_block - 66152513 + 65978414 file_flag_clear - 12545 + 13077 file_flag_has - 39608750 + 39575710 file_flag_set - 5792498 + 5793396 file_inode_hash - 5220350 + 5220892 file_path_hash - 4002881 + 4002848 file_stamp_hash - 6390305 + 6390630 filter_hidden - 3231524 + 3231650 fs_file2par_get - 4959524 + 4918180 fs_par2block_get @@ -145,23 +145,23 @@ fs_par2file_get - 11505649 + 11505277 hash_invalid_set - 9532465 + 9532509 hash_is_invalid - 756505 + 756707 hash_is_unique - 44043 + 43988 hash_is_zero - 760014 + 760217 hash_zero_set @@ -169,35 +169,35 @@ info_get - 3171512 + 3152579 info_get_bad - 247612 + 242727 info_get_justsynced - 23836 + 18930 info_get_rehash - 2048435 + 2036469 info_get_time - 798417 + 786514 info_make - 191697 + 180457 info_set - 1757573 + 1757522 info_set_bad - 1771 + 1772 info_set_rehash @@ -205,7 +205,7 @@ link_flag_get - 96285 + 95741 link_flag_has diff --git a/cov/cmdline/elem.h.gcov.html b/cov/cmdline/elem.h.gcov.html index 39ac75c1..7fbcc909 100644 --- a/cov/cmdline/elem.h.gcov.html +++ b/cov/cmdline/elem.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 41 @@ -594,13 +594,13 @@ 532 : * Filter hidden files. 533 : * Return !=0 if it matches and it should be excluded. 534 : */ - 535 3231524 : static inline int filter_hidden(int enable, struct dirent* dd) + 535 3231650 : static inline int filter_hidden(int enable, struct dirent* dd) 536 : { - 537 3231524 : if (enable && dirent_hidden(dd)) { + 537 3231650 : if (enable && dirent_hidden(dd)) { 538 0 : return 1; /* filter out */ 539 : } 540 : - 541 3231524 : return 0; + 541 3231650 : return 0; 542 : } 543 : 544 : /** @@ -651,17 +651,17 @@ 589 : * 590 : * If working with reduced hash lengths, this function always return 0. 591 : */ - 592 756505 : static inline int hash_is_invalid(const unsigned char* hash) + 592 756707 : static inline int hash_is_invalid(const unsigned char* hash) 593 : { 594 : int i; 595 : 596 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 597 756505 : if (BLOCK_HASH_SIZE != HASH_MAX) + 597 756707 : if (BLOCK_HASH_SIZE != HASH_MAX) 598 0 : return 0; 599 : - 600 1176105 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) - 601 1150041 : if (hash[i] != 0x00) - 602 730441 : return 0; + 600 1176704 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) + 601 1150640 : if (hash[i] != 0x00) + 602 730643 : return 0; 603 : 604 26064 : return 1; 605 : } @@ -673,17 +673,17 @@ 611 : * 612 : * If working with reduced hash lengths, this function always return 0. 613 : */ - 614 760014 : static inline int hash_is_zero(const unsigned char* hash) + 614 760217 : static inline int hash_is_zero(const unsigned char* hash) 615 : { 616 : int i; 617 : 618 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 619 760014 : if (BLOCK_HASH_SIZE != HASH_MAX) + 619 760217 : if (BLOCK_HASH_SIZE != HASH_MAX) 620 0 : return 0; 621 : - 622 1027474 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) - 623 1010957 : if (hash[i] != 0xFF) - 624 743497 : return 0; + 622 1027299 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) + 623 1010782 : if (hash[i] != 0xFF) + 624 743700 : return 0; 625 : 626 16517 : return 1; 627 : } @@ -693,22 +693,22 @@ 631 : * 632 : * If working with reduced hash lengths, this function always return 0. 633 : */ - 634 44043 : static inline int hash_is_unique(const unsigned char* hash) + 634 43988 : static inline int hash_is_unique(const unsigned char* hash) 635 : { 636 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 637 44043 : if (BLOCK_HASH_SIZE != HASH_MAX) + 637 43988 : if (BLOCK_HASH_SIZE != HASH_MAX) 638 0 : return 0; 639 : - 640 44043 : return !hash_is_zero(hash) && !hash_is_invalid(hash); + 640 43988 : return !hash_is_zero(hash) && !hash_is_invalid(hash); 641 : } 642 : 643 : /** 644 : * Set the hash to the special INVALID value. 645 : */ - 646 9532465 : static inline void hash_invalid_set(unsigned char* hash) + 646 9532509 : static inline void hash_invalid_set(unsigned char* hash) 647 : { - 648 9532465 : memset(hash, 0x00, BLOCK_HASH_SIZE); - 649 9532465 : } + 648 9532509 : memset(hash, 0x00, BLOCK_HASH_SIZE); + 649 9532509 : } 650 : 651 : /** 652 : * Set the hash to the special ZERO value. @@ -721,9 +721,9 @@ 659 : /** 660 : * Allocated space for block. 661 : */ - 662 69982896 : static inline size_t block_sizeof(void) + 662 69808821 : static inline size_t block_sizeof(void) 663 : { - 664 69982896 : return 1 + BLOCK_HASH_SIZE; + 664 69808821 : return 1 + BLOCK_HASH_SIZE; 665 : } 666 : 667 : /** @@ -732,32 +732,32 @@ 670 : * For this function, it's allowed to pass a NULL block 671 : * pointer than results in the BLOCK_STATE_EMPTY state. 672 : */ - 673 74577257 : static inline unsigned block_state_get(const struct snapraid_block* block) + 673 74400305 : static inline unsigned block_state_get(const struct snapraid_block* block) 674 : { - 675 74577257 : if (block == BLOCK_NULL) - 676 2302380 : return BLOCK_STATE_EMPTY; + 675 74400305 : if (block == BLOCK_NULL) + 676 2299617 : return BLOCK_STATE_EMPTY; 677 : - 678 72274877 : return block->state; + 678 72100688 : return block->state; 679 : } 680 : 681 : /** 682 : * Set the state of the block. 683 : */ - 684 19703104 : static inline void block_state_set(struct snapraid_block* block, unsigned state) + 684 19702751 : static inline void block_state_set(struct snapraid_block* block, unsigned state) 685 : { - 686 19703104 : block->state = state; - 687 19703104 : } + 686 19702751 : block->state = state; + 687 19702751 : } 688 : 689 : /** 690 : * Check if the specified block has an updated hash. 691 : * 692 : * Note that EMPTY / CHG / DELETED return 0. 693 : */ - 694 2188335 : static inline int block_has_updated_hash(const struct snapraid_block* block) + 694 2188345 : static inline int block_has_updated_hash(const struct snapraid_block* block) 695 : { - 696 2188335 : unsigned state = block_state_get(block); + 696 2188345 : unsigned state = block_state_get(block); 697 : - 698 2188335 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; + 698 2188345 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; 699 : } 700 : 701 : /** @@ -766,11 +766,11 @@ 704 : * 705 : * Note that EMPTY / BLK / REP return 0. 706 : */ - 707 2686312 : static inline int block_has_past_hash(const struct snapraid_block* block) + 707 2686411 : static inline int block_has_past_hash(const struct snapraid_block* block) 708 : { - 709 2686312 : unsigned state = block_state_get(block); + 709 2686411 : unsigned state = block_state_get(block); 710 : - 711 2686312 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED; + 711 2686411 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED; 712 : } 713 : 714 : /** @@ -778,12 +778,12 @@ 716 : * 717 : * Note that EMPTY / DELETED return 0. 718 : */ - 719 25304571 : static inline int block_has_file(const struct snapraid_block* block) + 719 25253088 : static inline int block_has_file(const struct snapraid_block* block) 720 : { - 721 25304571 : unsigned state = block_state_get(block); + 721 25253088 : unsigned state = block_state_get(block); 722 : 723 : return state == BLOCK_STATE_BLK - 724 25304571 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 724 25253088 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; 725 : } 726 : 727 : /** @@ -791,12 +791,12 @@ 729 : * 730 : * Note that EMPTY / BLK return 0. 731 : */ - 732 23228801 : static inline int block_has_invalid_parity(const struct snapraid_block* block) + 732 23186776 : static inline int block_has_invalid_parity(const struct snapraid_block* block) 733 : { - 734 23228801 : unsigned state = block_state_get(block); + 734 23186776 : unsigned state = block_state_get(block); 735 : 736 : return state == BLOCK_STATE_DELETED - 737 23228801 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 737 23186776 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; 738 : } 739 : 740 : /** @@ -804,27 +804,27 @@ 742 : * 743 : * Note that anything different than BLK return 0. 744 : */ - 745 226094 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) + 745 226098 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) 746 : { - 747 226094 : unsigned state = block_state_get(block); + 747 226098 : unsigned state = block_state_get(block); 748 : - 749 226094 : return state == BLOCK_STATE_BLK; + 749 226098 : return state == BLOCK_STATE_BLK; 750 : } 751 : - 752 39608750 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) + 752 39575710 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) 753 : { - 754 39608750 : return (file->flag & mask) == mask; + 754 39575710 : return (file->flag & mask) == mask; 755 : } 756 : - 757 5792498 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) + 757 5793396 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) 758 : { - 759 5792498 : file->flag |= mask; - 760 5792498 : } + 759 5793396 : file->flag |= mask; + 760 5793396 : } 761 : - 762 12545 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) + 762 13077 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) 763 : { - 764 12545 : file->flag &= ~mask; - 765 12545 : } + 764 13077 : file->flag &= ~mask; + 765 13077 : } 766 : 767 : /** 768 : * Allocate a file. @@ -856,11 +856,11 @@ 794 : * 795 : * Note that the block size if a runtime value. 796 : */ - 797 66152513 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos) + 797 65978414 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos) 798 : { - 799 66152513 : unsigned char* ptr = (unsigned char*)file->blockvec; + 799 65978414 : unsigned char* ptr = (unsigned char*)file->blockvec; 800 : - 801 66152513 : return (struct snapraid_block*)(ptr + pos * block_sizeof()); + 801 65978414 : return (struct snapraid_block*)(ptr + pos * block_sizeof()); 802 : } 803 : 804 : /** @@ -902,9 +902,9 @@ 840 : /** 841 : * Compute the hash of a file inode. 842 : */ - 843 5220350 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) + 843 5220892 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) 844 : { - 845 5220350 : return (tommy_uint32_t)tommy_inthash_u64(inode); + 845 5220892 : return (tommy_uint32_t)tommy_inthash_u64(inode); 846 : } 847 : 848 : /** @@ -923,17 +923,17 @@ 861 : /** 862 : * Compute the hash of a file path. 863 : */ - 864 4002881 : static inline tommy_uint32_t file_path_hash(const char* sub) + 864 4002848 : static inline tommy_uint32_t file_path_hash(const char* sub) 865 : { - 866 4002881 : return tommy_hash_u32(0, sub, strlen(sub)); + 866 4002848 : return tommy_hash_u32(0, sub, strlen(sub)); 867 : } 868 : 869 : /** 870 : * Compute the hash of a file stamp. 871 : */ - 872 6390305 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) + 872 6390630 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) 873 : { - 874 6390305 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); + 874 6390630 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); 875 : } 876 : 877 : /** @@ -977,9 +977,9 @@ 915 6 : slink->flag |= flag & mask; 916 6 : } 917 : - 918 96285 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask) + 918 95741 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask) 919 : { - 920 96285 : return slink->flag & mask; + 920 95741 : return slink->flag & mask; 921 : } 922 : 923 : /** @@ -1111,19 +1111,19 @@ 1049 : /** 1050 : * Get the file position from the parity position. 1051 : */ - 1052 11505649 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) + 1052 11505277 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) 1053 : { 1054 : struct snapraid_file* ret; 1055 : - 1056 11505649 : ret = fs_par2file_find(disk, parity_pos, file_pos); - 1057 11505649 : if (ret == 0) { + 1056 11505277 : ret = fs_par2file_find(disk, parity_pos, file_pos); + 1057 11505277 : if (ret == 0) { 1058 : /* LCOV_EXCL_START */ 1059 : log_fatal(EINTERNAL, "Internal inconsistency: Deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name); 1060 : os_abort(); 1061 : /* LCOV_EXCL_STOP */ 1062 : } 1063 : - 1064 11505649 : return ret; + 1064 11505277 : return ret; 1065 : } 1066 : 1067 : /** @@ -1135,19 +1135,19 @@ 1073 : /** 1074 : * Get the parity position from the file position. 1075 : */ - 1076 4959524 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) + 1076 4918180 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) 1077 : { 1078 : block_off_t ret; 1079 : - 1080 4959524 : ret = fs_file2par_find(disk, file, file_pos); - 1081 4959524 : if (ret == POS_NULL) { + 1080 4918180 : ret = fs_file2par_find(disk, file, file_pos); + 1081 4918180 : if (ret == POS_NULL) { 1082 : /* LCOV_EXCL_START */ 1083 : log_fatal(EINTERNAL, "Internal inconsistency: Resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); 1084 : os_abort(); 1085 : /* LCOV_EXCL_STOP */ 1086 : } 1087 : - 1088 4959524 : return ret; + 1088 4918180 : return ret; 1089 : } 1090 : 1091 : /** @@ -1195,18 +1195,18 @@ 1133 : /** 1134 : * Make an info. 1135 : */ - 1136 191697 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) + 1136 180457 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) 1137 : { 1138 : /* clear the lowest bits as reserved for other information */ - 1139 191697 : snapraid_info info = last_access & ~INFO_MASK; + 1139 180457 : snapraid_info info = last_access & ~INFO_MASK; 1140 : - 1141 191697 : if (error != 0) - 1142 5274 : info |= 0x1; - 1143 191697 : if (rehash != 0) - 1144 14426 : info |= 0x2; - 1145 191697 : if (justsynced != 0) - 1146 145610 : info |= 0x4; - 1147 191697 : return info; + 1141 180457 : if (error != 0) + 1142 5276 : info |= 0x1; + 1143 180457 : if (rehash != 0) + 1144 14181 : info |= 0x2; + 1145 180457 : if (justsynced != 0) + 1146 134376 : info |= 0x4; + 1147 180457 : return info; 1148 : } 1149 : 1150 : /** @@ -1214,44 +1214,44 @@ 1152 : * This is the last time when the block was know to be correct. 1153 : * The "scrubbed" info tells if the time is referring at the latest sync or scrub. 1154 : */ - 1155 798417 : static inline time_t info_get_time(snapraid_info info) + 1155 786514 : static inline time_t info_get_time(snapraid_info info) 1156 : { - 1157 798417 : return info & ~INFO_MASK; + 1157 786514 : return info & ~INFO_MASK; 1158 : } 1159 : 1160 : /** 1161 : * Extract the error information. 1162 : * Report if the block address had some problem. 1163 : */ - 1164 247612 : static inline int info_get_bad(snapraid_info info) + 1164 242727 : static inline int info_get_bad(snapraid_info info) 1165 : { - 1166 247612 : return (info & 0x1) != 0; + 1166 242727 : return (info & 0x1) != 0; 1167 : } 1168 : 1169 : /** 1170 : * Extract the rehash information. 1171 : * Report if the block address is using the old hash and needs to be rehashed. 1172 : */ - 1173 2048435 : static inline int info_get_rehash(snapraid_info info) + 1173 2036469 : static inline int info_get_rehash(snapraid_info info) 1174 : { - 1175 2048435 : return (info & 0x2) != 0; + 1175 2036469 : return (info & 0x2) != 0; 1176 : } 1177 : 1178 : /** 1179 : * Extract the scrubbed information. 1180 : * Report if the block address was never scrubbed. 1181 : */ - 1182 23836 : static inline int info_get_justsynced(snapraid_info info) + 1182 18930 : static inline int info_get_justsynced(snapraid_info info) 1183 : { - 1184 23836 : return (info & 0x4) != 0; + 1184 18930 : return (info & 0x4) != 0; 1185 : } 1186 : 1187 : /** 1188 : * Mark the block address as with error. 1189 : */ - 1190 1771 : static inline snapraid_info info_set_bad(snapraid_info info) + 1190 1772 : static inline snapraid_info info_set_bad(snapraid_info info) 1191 : { - 1192 1771 : return info | 0x1; + 1192 1772 : return info | 0x1; 1193 : } 1194 : 1195 : /** @@ -1266,27 +1266,27 @@ 1204 : * Set the info at the specified position. 1205 : * The position is allocated if not yet done. 1206 : */ - 1207 1757573 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info) + 1207 1757522 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info) 1208 : { - 1209 1757573 : tommy_arrayblkof_grow(array, pos + 1); + 1209 1757522 : tommy_arrayblkof_grow(array, pos + 1); 1210 : - 1211 1757573 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); - 1212 1757573 : } + 1211 1757522 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); + 1212 1757522 : } 1213 : 1214 : /** 1215 : * Get the info at the specified position. 1216 : * For not allocated position, 0 is returned. 1217 : */ - 1218 3171512 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos) + 1218 3152579 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos) 1219 : { 1220 : snapraid_info info; 1221 : - 1222 3171512 : if (pos >= tommy_arrayblkof_size(array)) + 1222 3152579 : if (pos >= tommy_arrayblkof_size(array)) 1223 270497 : return 0; 1224 : - 1225 2901015 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); + 1225 2882082 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); 1226 : - 1227 2901015 : return info; + 1227 2882082 : return info; 1228 : } 1229 : 1230 : /****************************************************************************/ diff --git a/cov/cmdline/handle.c.func-sort-c.html b/cov/cmdline/handle.c.func-sort-c.html index 68af7fbe..81e68a67 100644 --- a/cov/cmdline/handle.c.func-sort-c.html +++ b/cov/cmdline/handle.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -65,31 +65,31 @@ handle_truncate - 3256 + 3213 handle_utime - 121173 + 121204 handle_write - 288429 + 288463 handle_create - 771292 + 771350 handle_open - 2176884 + 2176417 handle_close - 4649470 + 4649540 handle_read - 5598886 + 5598293
diff --git a/cov/cmdline/handle.c.func.html b/cov/cmdline/handle.c.func.html index b027534b..104333b0 100644 --- a/cov/cmdline/handle.c.func.html +++ b/cov/cmdline/handle.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -61,11 +61,11 @@ handle_close - 4649470 + 4649540 handle_create - 771292 + 771350 handle_mapping @@ -73,23 +73,23 @@ handle_open - 2176884 + 2176417 handle_read - 5598886 + 5598293 handle_truncate - 3256 + 3213 handle_utime - 121173 + 121204 handle_write - 288429 + 288463
diff --git a/cov/cmdline/handle.c.gcov.html b/cov/cmdline/handle.c.gcov.html index b80dbaca..57f018e4 100644 --- a/cov/cmdline/handle.c.gcov.html +++ b/cov/cmdline/handle.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -86,64 +86,64 @@ 24 : /****************************************************************************/ 25 : /* handle */ 26 : - 27 771292 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) + 27 771350 : 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 771292 : if (handle->file == file && handle->f != -1) { + 33 771350 : if (handle->file == file && handle->f != -1) { 34 0 : return 0; 35 : } 36 : - 37 771292 : advise_init(&handle->advise, mode); - 38 771292 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 37 771350 : advise_init(&handle->advise, mode); + 38 771350 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 39 : - 40 771292 : ret = mkancestor(handle->path); - 41 771292 : if (ret != 0) { + 40 771350 : ret = mkancestor(handle->path); + 41 771350 : if (ret != 0) { 42 : /* LCOV_EXCL_START */ 43 : return -1; 44 : /* LCOV_EXCL_STOP */ 45 : } 46 : 47 : /* initial values, changed later if required */ - 48 771292 : handle->created = 0; + 48 771350 : 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 771292 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + 53 771350 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); 54 : 55 : /* open for read write */ - 56 771292 : handle->f = open(handle->path, flags | O_RDWR); + 56 771350 : handle->f = open(handle->path, flags | O_RDWR); 57 : 58 : /* if failed for missing write permission */ - 59 771292 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { + 59 771350 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { 60 : /* open for read-only */ 61 0 : handle->f = open(handle->path, flags | O_RDONLY); 62 : } 63 : 64 : /* if failed for missing file */ - 65 771292 : if (handle->f == -1 && errno == ENOENT) { + 65 771350 : 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 176374 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); + 69 176369 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); 70 : - 71 176374 : if (rename(path_from, handle->path) == 0) { + 71 176369 : if (rename(path_from, handle->path) == 0) { 72 : /* open for read write */ - 73 63261 : handle->f = open(handle->path, flags | O_RDWR); + 73 63300 : handle->f = open(handle->path, flags | O_RDWR); 74 : } else { 75 : /* create it */ - 76 113113 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); - 77 113113 : if (handle->f != -1) { + 76 113069 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); + 77 113069 : if (handle->f != -1) { 78 : /* mark it as created if really done */ - 79 113113 : handle->created = 1; + 79 113069 : handle->created = 1; 80 : } 81 : } 82 : } 83 : - 84 771292 : if (handle->f == -1) { + 84 771350 : 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 771292 : handle->file = file; + 97 771350 : handle->file = file; 98 : 99 : /* get the stat info */ - 100 771292 : ret = fstat(handle->f, &handle->st); - 101 771292 : if (ret != 0) { + 100 771350 : ret = fstat(handle->f, &handle->st); + 101 771350 : if (ret != 0) { 102 : /* LCOV_EXCL_START */ 103 : log_fatal(errno, "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 771292 : handle->valid_size = handle->st.st_size; + 109 771350 : handle->valid_size = handle->st.st_size; 110 : - 111 771292 : ret = advise_open(&handle->advise, handle->f); - 112 771292 : if (ret != 0) { + 111 771350 : ret = advise_open(&handle->advise, handle->f); + 112 771350 : if (ret != 0) { 113 : /* LCOV_EXCL_START */ 114 : log_fatal(errno, "Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 115 : return -1; 116 : /* LCOV_EXCL_STOP */ 117 : } 118 : - 119 771292 : return 0; + 119 771350 : return 0; 120 : } 121 : - 122 3256 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) + 122 3213 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) 123 : { 124 : int ret; 125 : - 126 3256 : ret = ftruncate(handle->f, file->size); - 127 3256 : if (ret != 0) { + 126 3213 : ret = ftruncate(handle->f, file->size); + 127 3213 : if (ret != 0) { 128 : /* LCOV_EXCL_START */ 129 : if (errno == EACCES) { 130 : log_fatal(errno, "Failed to truncate file '%s' for missing write permission.\n", handle->path); @@ -198,58 +198,58 @@ 136 : } 137 : 138 : /* adjust the size to the truncated size */ - 139 3256 : handle->valid_size = file->size; + 139 3213 : handle->valid_size = file->size; 140 : - 141 3256 : return 0; + 141 3213 : return 0; 142 : } 143 : - 144 2176884 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, log_ptr* out, log_ptr* out_missing) + 144 2176417 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, log_ptr* out, log_ptr* out_missing) 145 : { 146 : int ret; 147 : int flags; 148 : - 149 2176884 : if (!out_missing) - 150 1576375 : out_missing = out; + 149 2176417 : if (!out_missing) + 150 1576294 : out_missing = out; 151 : 152 : /* if already opened, nothing to do */ - 153 2176884 : if (handle->file == file && handle->file != 0 && handle->f != -1) { - 154 464548 : return 0; + 153 2176417 : if (handle->file == file && handle->file != 0 && handle->f != -1) { + 154 464272 : return 0; 155 : } 156 : - 157 1712336 : advise_init(&handle->advise, mode); - 158 1712336 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 157 1712145 : advise_init(&handle->advise, mode); + 158 1712145 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 159 : 160 : /* for sure not created */ - 161 1712336 : handle->created = 0; + 161 1712145 : 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 1712336 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + 166 1712145 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); 167 : 168 : /* open for read */ - 169 1712336 : handle->f = open_noatime(handle->path, flags | O_RDONLY); - 170 1712336 : if (handle->f == -1) { + 169 1712145 : handle->f = open_noatime(handle->path, flags | O_RDONLY); + 170 1712145 : if (handle->f == -1) { 171 : /* invalidate for error */ - 172 78731 : handle->file = 0; - 173 78731 : handle->f = -1; - 174 78731 : handle->valid_size = 0; + 172 78696 : handle->file = 0; + 173 78696 : handle->f = -1; + 174 78696 : handle->valid_size = 0; 175 : - 176 78731 : if (errno == ENOENT) - 177 78719 : out_missing(errno, "Missing file '%s'.\n", handle->path); + 176 78696 : if (errno == ENOENT) + 177 78684 : out_missing(errno, "Missing file '%s'.\n", handle->path); 178 12 : else if (errno == EACCES) 179 12 : out(errno, "Permission denied for file '%s'.\n", handle->path); 180 : else 181 0 : out(errno, "Error opening file '%s'. %s.\n", handle->path, strerror(errno)); - 182 78731 : return -1; + 182 78696 : return -1; 183 : } 184 : 185 : /* just opened */ - 186 1633605 : handle->file = file; + 186 1633449 : handle->file = file; 187 : 188 : /* get the stat info */ - 189 1633605 : ret = fstat(handle->f, &handle->st); - 190 1633605 : if (ret != 0) { + 189 1633449 : ret = fstat(handle->f, &handle->st); + 190 1633449 : if (ret != 0) { 191 : /* LCOV_EXCL_START */ 192 : out(errno, "Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); 193 : return -1; @@ -257,27 +257,27 @@ 195 : } 196 : 197 : /* get the size of the existing data */ - 198 1633605 : handle->valid_size = handle->st.st_size; + 198 1633449 : handle->valid_size = handle->st.st_size; 199 : - 200 1633605 : ret = advise_open(&handle->advise, handle->f); - 201 1633605 : if (ret != 0) { + 200 1633449 : ret = advise_open(&handle->advise, handle->f); + 201 1633449 : if (ret != 0) { 202 : /* LCOV_EXCL_START */ 203 : out(errno, "Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 204 : return -1; 205 : /* LCOV_EXCL_STOP */ 206 : } 207 : - 208 1633605 : return 0; + 208 1633449 : return 0; 209 : } 210 : - 211 4649470 : int handle_close(struct snapraid_handle* handle) + 211 4649540 : int handle_close(struct snapraid_handle* handle) 212 : { 213 : int ret; 214 : 215 : /* close if open */ - 216 4649470 : if (handle->f != -1) { - 217 2404897 : ret = close(handle->f); - 218 2404897 : if (ret != 0) { + 216 4649540 : if (handle->f != -1) { + 217 2404799 : ret = close(handle->f); + 218 2404799 : if (ret != 0) { 219 : /* LCOV_EXCL_START */ 220 : log_fatal(errno, "Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 221 : @@ -291,14 +291,14 @@ 229 : } 230 : 231 : /* reset the descriptor */ - 232 4649470 : handle->file = 0; - 233 4649470 : handle->f = -1; - 234 4649470 : handle->valid_size = 0; + 232 4649540 : handle->file = 0; + 233 4649540 : handle->f = -1; + 234 4649540 : handle->valid_size = 0; 235 : - 236 4649470 : return 0; + 236 4649540 : return 0; 237 : } 238 : - 239 5598886 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, log_ptr* out, log_ptr* out_missing) + 239 5598293 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, log_ptr* out, log_ptr* out_missing) 240 : { 241 : ssize_t read_ret; 242 : data_off_t offset; @@ -306,43 +306,43 @@ 244 : unsigned count; 245 : int ret; 246 : - 247 5598886 : offset = file_pos * (data_off_t)block_size; + 247 5598293 : offset = file_pos * (data_off_t)block_size; 248 : - 249 5598886 : if (!out_missing) - 250 5592557 : out_missing = out; + 249 5598293 : if (!out_missing) + 250 5591964 : out_missing = out; 251 : 252 : /* check if we are going to read only not initialized data */ - 253 5598886 : if (offset >= handle->valid_size) { + 253 5598293 : if (offset >= handle->valid_size) { 254 : /* if the file is missing, it's at 0 size, or it's rebuilt while reading */ - 255 176886 : if (offset == handle->valid_size || handle->valid_size == 0) { - 256 175792 : errno = ENOENT; - 257 175792 : if (offset == 0) { - 258 174839 : out_missing(errno, "Missing file '%s'.\n", handle->path); + 255 176692 : if (offset == handle->valid_size || handle->valid_size == 0) { + 256 175708 : errno = ENOENT; + 257 175708 : if (offset == 0) { + 258 174804 : out_missing(errno, "Missing file '%s'.\n", handle->path); 259 : } else { - 260 953 : out_missing(errno, "Missing data in file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 260 904 : out_missing(errno, "Missing data in file '%s' at offset %" PRIu64 ".\n", handle->path, offset); 261 : } 262 : } else { - 263 1094 : errno = ENXIO; - 264 1094 : out(errno, "Reading over the end from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 263 984 : errno = ENXIO; + 264 984 : out(errno, "Reading over the end from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); 265 : } - 266 176886 : return -1; + 266 176692 : return -1; 267 : } 268 : - 269 5422000 : read_size = file_block_size(handle->file, file_pos, block_size); + 269 5421601 : read_size = file_block_size(handle->file, file_pos, block_size); 270 : - 271 5422000 : count = 0; - 272 5422000 : errno = 0; + 271 5421601 : count = 0; + 272 5421601 : errno = 0; 273 : do { - 274 5430811 : bw_limit(handle->bw, block_size - count); + 274 5430426 : bw_limit(handle->bw, block_size - count); 275 : - 276 5430811 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count); - 277 5430811 : if (read_ret == -1) { + 276 5430426 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count); + 277 5430426 : if (read_ret == -1) { 278 : /* LCOV_EXCL_START */ 279 : out(errno, "Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, block_size - count, strerror(errno)); 280 : return -1; 281 : /* LCOV_EXCL_STOP */ 282 : } - 283 5430811 : if (read_ret == 0) { + 283 5430426 : if (read_ret == 0) { 284 : /* LCOV_EXCL_START */ 285 : if (errno == 0) 286 : errno = ENXIO; @@ -351,26 +351,26 @@ 289 : /* LCOV_EXCL_STOP */ 290 : } 291 : - 292 5422000 : count += read_ret; - 293 5422000 : } while (count < read_size); + 292 5421601 : count += read_ret; + 293 5421601 : } while (count < read_size); 294 : 295 : /* pad with 0 */ - 296 5413189 : if (read_size < block_size) { - 297 2187257 : memset(block_buffer + read_size, 0, block_size - read_size); + 296 5412776 : if (read_size < block_size) { + 297 2187169 : memset(block_buffer + read_size, 0, block_size - read_size); 298 : } 299 : - 300 5413189 : ret = advise_read(&handle->advise, handle->f, offset, block_size); - 301 5413189 : if (ret != 0) { + 300 5412776 : ret = advise_read(&handle->advise, handle->f, offset, block_size); + 301 5412776 : if (ret != 0) { 302 : /* LCOV_EXCL_START */ 303 : out(errno, "Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 304 : return -1; 305 : /* LCOV_EXCL_STOP */ 306 : } 307 : - 308 5413189 : return read_size; + 308 5412776 : return read_size; 309 : } 310 : - 311 288429 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) + 311 288463 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) 312 : { 313 : ssize_t write_ret; 314 : data_off_t offset; @@ -378,22 +378,22 @@ 316 : unsigned count; 317 : int ret; 318 : - 319 288429 : offset = file_pos * (data_off_t)block_size; + 319 288463 : offset = file_pos * (data_off_t)block_size; 320 : - 321 288429 : write_size = file_block_size(handle->file, file_pos, block_size); + 321 288463 : write_size = file_block_size(handle->file, file_pos, block_size); 322 : - 323 288429 : count = 0; + 323 288463 : count = 0; 324 : do { - 325 288429 : bw_limit(handle->bw, write_size - count); + 325 288463 : bw_limit(handle->bw, write_size - count); 326 : - 327 288429 : write_ret = pwrite(handle->f, block_buffer + count, write_size - count, offset + count); - 328 288429 : if (write_ret == -1) { + 327 288463 : write_ret = pwrite(handle->f, block_buffer + count, write_size - count, offset + count); + 328 288463 : if (write_ret == -1) { 329 : /* LCOV_EXCL_START */ 330 : log_fatal(errno, "Error writing file '%s'. %s.\n", handle->path, strerror(errno)); 331 : return -1; 332 : /* LCOV_EXCL_STOP */ 333 : } - 334 288429 : if (write_ret == 0) { + 334 288463 : if (write_ret == 0) { 335 : /* LCOV_EXCL_START */ 336 : errno = ENXIO; 337 : log_fatal(errno, "Unexpected 0 write to file '%s'. %s.\n", handle->path, strerror(errno)); @@ -401,43 +401,43 @@ 339 : /* LCOV_EXCL_STOP */ 340 : } 341 : - 342 288429 : count += write_ret; - 343 288429 : } while (count < write_size); + 342 288463 : count += write_ret; + 343 288463 : } while (count < write_size); 344 : 345 : /* adjust the size of the valid data */ - 346 288429 : if (handle->valid_size < offset + write_size) { - 347 282456 : handle->valid_size = offset + write_size; + 346 288463 : if (handle->valid_size < offset + write_size) { + 347 282376 : handle->valid_size = offset + write_size; 348 : } 349 : - 350 288429 : ret = advise_write(&handle->advise, handle->f, offset, block_size); - 351 288429 : if (ret != 0) { + 350 288463 : ret = advise_write(&handle->advise, handle->f, offset, block_size); + 351 288463 : if (ret != 0) { 352 : /* LCOV_EXCL_START */ 353 : log_fatal(errno, "Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 354 : return -1; 355 : /* LCOV_EXCL_STOP */ 356 : } 357 : - 358 288429 : return 0; + 358 288463 : return 0; 359 : } 360 : - 361 121173 : int handle_utime(struct snapraid_handle* handle) + 361 121204 : int handle_utime(struct snapraid_handle* handle) 362 : { 363 : int ret; 364 : 365 : /* do nothing if not opened */ - 366 121173 : if (handle->f == -1) + 366 121204 : if (handle->f == -1) 367 0 : return 0; 368 : - 369 121173 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); + 369 121204 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); 370 : - 371 121173 : if (ret != 0) { + 371 121204 : if (ret != 0) { 372 : /* LCOV_EXCL_START */ 373 : log_fatal(errno, "Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 374 : return -1; 375 : /* LCOV_EXCL_STOP */ 376 : } 377 : - 378 121173 : return 0; + 378 121204 : return 0; 379 : } 380 : 381 227 : 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 d528c811..93da1ca4 100644 --- a/cov/cmdline/import.c.func-sort-c.html +++ b/cov/cmdline/import.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -85,11 +85,11 @@ state_import_fetch - 652266 + 652523 import_block_hash - 656738 + 656995
diff --git a/cov/cmdline/import.c.func.html b/cov/cmdline/import.c.func.html index 207bcbe6..0739502b 100644 --- a/cov/cmdline/import.c.func.html +++ b/cov/cmdline/import.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -61,7 +61,7 @@ import_block_hash - 656738 + 656995 import_block_hash_compare @@ -89,7 +89,7 @@ state_import_fetch - 652266 + 652523
diff --git a/cov/cmdline/import.c.gcov.html b/cov/cmdline/import.c.gcov.html index 1aca67ec..804a8f6a 100644 --- a/cov/cmdline/import.c.gcov.html +++ b/cov/cmdline/import.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 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 656738 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash) + 49 656995 : 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 656738 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24); + 52 656995 : 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 652266 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) + 148 652523 : 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 652266 : const unsigned char* hash = missing_block->hash; - 154 652266 : unsigned block_size = state->block_size; + 153 652523 : const unsigned char* hash = missing_block->hash; + 154 652523 : unsigned block_size = state->block_size; 155 : unsigned read_size; 156 : unsigned char buffer_hash[HASH_MAX]; 157 : const char* path; 158 : - 159 652266 : if (rehash) { + 159 652523 : if (rehash) { 160 0 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash)); 161 : } else { - 162 652266 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); + 162 652523 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); 163 : } - 164 652266 : if (!block) - 165 647794 : return -1; + 164 652523 : if (!block) + 165 648051 : 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 dbaa53cc..453e36a3 100644 --- a/cov/cmdline/index-sort-f.html +++ b/cov/cmdline/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 10504 - 12155 - 86.4 % + 10781 + 12115 + 89.0 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 565 + 573 600 - 94.2 % + 95.5 % @@ -69,16 +69,6 @@ Line Coverage Sort by line coverage Functions Sort by function coverage - - unix.c - -
56.2%56.2%
- - 56.2 % - 381 / 678 - 73.8 % - 31 / 42 - dry.c @@ -90,14 +80,14 @@ 4 / 5 - scrub.c + unix.c -
79.3%79.3%
+
70.6%70.6%
- 79.3 % - 303 / 382 - 85.7 % - 6 / 7 + 70.6 % + 475 / 673 + 83.3 % + 35 / 42 thermal.c @@ -109,6 +99,16 @@ 85.7 % 6 / 7 + + scrub.c + +
79.3%79.3%
+ + 79.3 % + 303 / 382 + 85.7 % + 6 / 7 + import.c @@ -119,16 +119,6 @@ 87.5 % 7 / 8 - - support.c - -
63.9%63.9%
- - 63.9 % - 633 / 991 - 89.3 % - 75 / 84 - stream.h @@ -140,14 +130,14 @@ 10 / 11 - device.c + support.c -
84.4%84.4%
+
80.4%80.4%
- 84.4 % - 345 / 409 + 80.4 % + 769 / 956 92.9 % - 13 / 14 + 78 / 84 io.c @@ -172,10 +162,10 @@ state.c -
88.9%88.9%
+
90.3%90.3%
- 88.9 % - 1737 / 1954 + 90.3 % + 1765 / 1954 96.1 % 49 / 51 @@ -209,26 +199,6 @@ 97.2 % 70 / 72 - - spooky2.c - -
100.0%
- - 100.0 % - 20 / 20 - 100.0 % - 1 / 1 - - - portable.h - -
100.0%
- - 100.0 % - 2 / 2 - 100.0 % - 1 / 1 - list.c @@ -239,26 +209,6 @@ 100.0 % 1 / 1 - - rehash.c - -
95.2%95.2%
- - 95.2 % - 20 / 21 - 100.0 % - 1 / 1 - - - touch.c - -
100.0%
- - 100.0 % - 28 / 28 - 100.0 % - 1 / 1 - museair.c @@ -279,6 +229,36 @@ 100.0 % 1 / 1 + + portable.h + +
100.0%
+ + 100.0 % + 2 / 2 + 100.0 % + 1 / 1 + + + touch.c + +
100.0%
+ + 100.0 % + 28 / 28 + 100.0 % + 1 / 1 + + + rehash.c + +
95.2%95.2%
+ + 95.2 % + 20 / 21 + 100.0 % + 1 / 1 + metro.c @@ -290,12 +270,22 @@ 1 / 1 - main.c + spooky2.c -
83.6%83.6%
+
100.0%
- 83.6 % - 51 / 61 + 100.0 % + 20 / 20 + 100.0 % + 1 / 1 + + + speed.c + +
99.6%99.6%
+ + 99.6 % + 490 / 492 100.0 % 2 / 2 @@ -310,32 +300,12 @@ 2 / 2 - mkstream.c + main.c -
100.0%
+
83.6%83.6%
- 100.0 % - 69 / 69 - 100.0 % - 2 / 2 - - - status.c - -
96.2%96.2%
- - 96.2 % - 256 / 266 - 100.0 % - 2 / 2 - - - speed.c - -
99.6%99.6%
- - 99.6 % - 490 / 492 + 83.6 % + 51 / 61 100.0 % 2 / 2 @@ -349,6 +319,26 @@ 100.0 % 2 / 2 + + status.c + +
96.2%96.2%
+ + 96.2 % + 256 / 266 + 100.0 % + 2 / 2 + + + mkstream.c + +
100.0%
+ + 100.0 % + 69 / 69 + 100.0 % + 2 / 2 + dup.c @@ -359,16 +349,6 @@ 100.0 % 5 / 5 - - locate.c - -
94.4%94.4%
- - 94.4 % - 119 / 126 - 100.0 % - 7 / 7 - util.h @@ -382,10 +362,20 @@ search.c -
90.9%90.9%
+
91.9%91.9%
- 90.9 % - 90 / 99 + 91.9 % + 91 / 99 + 100.0 % + 7 / 7 + + + locate.c + +
94.4%94.4%
+ + 94.4 % + 119 / 126 100.0 % 7 / 7 @@ -429,16 +419,6 @@ 100.0 % 9 / 9 - - check.c - -
88.9%88.9%
- - 88.9 % - 766 / 862 - 100.0 % - 10 / 10 - snapraid.c @@ -449,13 +429,33 @@ 100.0 % 10 / 10 + + check.c + +
88.7%88.7%
+ + 88.7 % + 765 / 862 + 100.0 % + 10 / 10 + + + device.c + +
88.8%88.8%
+ + 88.8 % + 363 / 409 + 100.0 % + 14 / 14 + mktest.c -
92.8%92.8%
+
93.2%93.2%
- 92.8 % - 220 / 237 + 93.2 % + 221 / 237 100.0 % 18 / 18 diff --git a/cov/cmdline/index-sort-l.html b/cov/cmdline/index-sort-l.html index be52e4cc..c91a2d2f 100644 --- a/cov/cmdline/index-sort-l.html +++ b/cov/cmdline/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 10504 - 12155 - 86.4 % + 10781 + 12115 + 89.0 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 565 + 573 600 - 94.2 % + 95.5 % @@ -72,22 +72,12 @@ unix.c -
56.2%56.2%
+
70.6%70.6%
- 56.2 % - 381 / 678 - 73.8 % - 31 / 42 - - - support.c - -
63.9%63.9%
- - 63.9 % - 633 / 991 - 89.3 % - 75 / 84 + 70.6 % + 475 / 673 + 83.3 % + 35 / 42 dry.c @@ -109,6 +99,16 @@ 85.7 % 6 / 7 + + support.c + +
80.4%80.4%
+ + 80.4 % + 769 / 956 + 92.9 % + 78 / 84 + thermal.c @@ -129,16 +129,6 @@ 100.0 % 2 / 2 - - device.c - -
84.4%84.4%
- - 84.4 % - 345 / 409 - 92.9 % - 13 / 14 - snapraid.c @@ -150,24 +140,24 @@ 10 / 10 - check.c + device.c -
88.9%88.9%
+
88.8%88.8%
- 88.9 % - 766 / 862 + 88.8 % + 363 / 409 100.0 % - 10 / 10 + 14 / 14 - state.c + check.c -
88.9%88.9%
+
88.7%88.7%
- 88.9 % - 1737 / 1954 - 96.1 % - 49 / 51 + 88.7 % + 765 / 862 + 100.0 % + 10 / 10 scan.c @@ -199,6 +189,16 @@ 87.5 % 7 / 8 + + state.c + +
90.3%90.3%
+ + 90.3 % + 1765 / 1954 + 96.1 % + 49 / 51 + stream.h @@ -219,16 +219,6 @@ 96.4 % 27 / 28 - - search.c - -
90.9%90.9%
- - 90.9 % - 90 / 99 - 100.0 % - 7 / 7 - parity.c @@ -249,6 +239,16 @@ 100.0 % 1 / 1 + + search.c + +
91.9%91.9%
+ + 91.9 % + 91 / 99 + 100.0 % + 7 / 7 + util.c @@ -262,10 +262,10 @@ mktest.c -
92.8%92.8%
+
93.2%93.2%
- 92.8 % - 220 / 237 + 93.2 % + 221 / 237 100.0 % 18 / 18 @@ -390,7 +390,7 @@ 2 / 2 - portable.h + support.h
100.0%
@@ -400,7 +400,7 @@ 1 / 1 - support.h + portable.h
100.0%
diff --git a/cov/cmdline/index.html b/cov/cmdline/index.html index d9ff2cc8..8ee7a2f1 100644 --- a/cov/cmdline/index.html +++ b/cov/cmdline/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 10504 - 12155 - 86.4 % + 10781 + 12115 + 89.0 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 565 + 573 600 - 94.2 % + 95.5 % @@ -82,22 +82,22 @@ check.c -
88.9%88.9%
+
88.7%88.7%
- 88.9 % - 766 / 862 + 88.7 % + 765 / 862 100.0 % 10 / 10 device.c -
84.4%84.4%
+
88.8%88.8%
- 84.4 % - 345 / 409 - 92.9 % - 13 / 14 + 88.8 % + 363 / 409 + 100.0 % + 14 / 14 dry.c @@ -222,10 +222,10 @@ mktest.c -
92.8%92.8%
+
93.2%93.2%
- 92.8 % - 220 / 237 + 93.2 % + 221 / 237 100.0 % 18 / 18 @@ -312,10 +312,10 @@ search.c -
90.9%90.9%
+
91.9%91.9%
- 90.9 % - 90 / 99 + 91.9 % + 91 / 99 100.0 % 7 / 7 @@ -362,10 +362,10 @@ state.c -
88.9%88.9%
+
90.3%90.3%
- 88.9 % - 1737 / 1954 + 90.3 % + 1765 / 1954 96.1 % 49 / 51 @@ -402,12 +402,12 @@ support.c -
63.9%63.9%
+
80.4%80.4%
- 63.9 % - 633 / 991 - 89.3 % - 75 / 84 + 80.4 % + 769 / 956 + 92.9 % + 78 / 84 support.h @@ -452,12 +452,12 @@ unix.c -
56.2%56.2%
+
70.6%70.6%
- 56.2 % - 381 / 678 - 73.8 % - 31 / 42 + 70.6 % + 475 / 673 + 83.3 % + 35 / 42 util.c diff --git a/cov/cmdline/io.c.func-sort-c.html b/cov/cmdline/io.c.func-sort-c.html index 3f6abcaf..87f7601d 100644 --- a/cov/cmdline/io.c.func-sort-c.html +++ b/cov/cmdline/io.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 31 @@ -113,7 +113,7 @@ io_writer_sched_empty - 931 + 920 io_parity_write_mono @@ -141,27 +141,27 @@ io_write_next_thread - 111042 + 110979 io_write_preset_thread - 111042 + 110979 io_writer_sched - 114798 + 114746 io_read_next_thread - 146427 + 146364 io_position_next - 163942 + 163879 io_reader_sched - 163942 + 163879 io_parity_read_thread @@ -169,27 +169,27 @@ io_parity_write_thread - 559582 + 559204 io_writer_step - 560074 + 559696 io_data_read_thread - 877956 + 877578 io_task_read_thread - 1089660 + 1089282 io_reader_worker - 1089792 + 1089420 io_reader_step - 1177886 + 1177263
diff --git a/cov/cmdline/io.c.func.html b/cov/cmdline/io.c.func.html index 7aada686..fc6ac5db 100644 --- a/cov/cmdline/io.c.func.html +++ b/cov/cmdline/io.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 31 @@ -65,7 +65,7 @@ io_data_read_thread - 877956 + 877578 io_done @@ -97,11 +97,11 @@ io_parity_write_thread - 559582 + 559204 io_position_next - 163942 + 163879 io_read_next_mono @@ -109,15 +109,15 @@ io_read_next_thread - 146427 + 146364 io_reader_sched - 163942 + 163879 io_reader_step - 1177886 + 1177263 io_reader_thread @@ -125,7 +125,7 @@ io_reader_worker - 1089792 + 1089420 io_refresh_mono @@ -157,7 +157,7 @@ io_task_read_thread - 1089660 + 1089282 io_write_next_mono @@ -165,7 +165,7 @@ io_write_next_thread - 111042 + 110979 io_write_preset_mono @@ -173,19 +173,19 @@ io_write_preset_thread - 111042 + 110979 io_writer_sched - 114798 + 114746 io_writer_sched_empty - 931 + 920 io_writer_step - 560074 + 559696 io_writer_thread diff --git a/cov/cmdline/io.c.gcov.html b/cov/cmdline/io.c.gcov.html index 25ad9bba..652a74b8 100644 --- a/cov/cmdline/io.c.gcov.html +++ b/cov/cmdline/io.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 31 @@ -97,108 +97,108 @@ 35 : /** 36 : * Get the next block position to process. 37 : */ - 38 163942 : static block_off_t io_position_next(struct snapraid_io* io) + 38 163879 : static block_off_t io_position_next(struct snapraid_io* io) 39 : { 40 : block_off_t blockcur; 41 : 42 : /* get the next position */ - 43 163942 : if (io->block_enabled) { + 43 163879 : if (io->block_enabled) { 44 507954 : while (io->block_next < io->block_max && !bit_vect_test(io->block_enabled, io->block_next)) - 45 353913 : ++io->block_next; + 45 353976 : ++io->block_next; 46 : } 47 : - 48 163942 : blockcur = io->block_next; + 48 163879 : blockcur = io->block_next; 49 : 50 : /* next block for the next call */ - 51 163942 : ++io->block_next; + 51 163879 : ++io->block_next; 52 : - 53 163942 : return blockcur; + 53 163879 : return blockcur; 54 : } 55 : 56 : /** 57 : * Setup the next pending task for all readers. 58 : */ - 59 163942 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) + 59 163879 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) 60 : { 61 : unsigned i; 62 : - 63 1370050 : for (i = 0; i < io->reader_max; ++i) { - 64 1206108 : struct snapraid_worker* worker = &io->reader_map[i]; - 65 1206108 : struct snapraid_task* task = &worker->task_map[task_index]; + 63 1369609 : for (i = 0; i < io->reader_max; ++i) { + 64 1205730 : struct snapraid_worker* worker = &io->reader_map[i]; + 65 1205730 : struct snapraid_task* task = &worker->task_map[task_index]; 66 : 67 : /* setup the new pending task */ - 68 1206108 : if (blockcur < io->block_max) - 69 1117782 : task->state = TASK_STATE_READY; + 68 1205730 : if (blockcur < io->block_max) + 69 1117404 : task->state = TASK_STATE_READY; 70 : else 71 88326 : task->state = TASK_STATE_EMPTY; 72 : - 73 1206108 : task->path[0] = 0; - 74 1206108 : if (worker->handle) - 75 983652 : task->disk = worker->handle->disk; + 73 1205730 : task->path[0] = 0; + 74 1205730 : if (worker->handle) + 75 983274 : task->disk = worker->handle->disk; 76 : else 77 222456 : task->disk = 0; 78 : - 79 1206108 : assert(worker->buffer_skew + i < io->buffer_max); + 79 1205730 : assert(worker->buffer_skew + i < io->buffer_max); 80 : - 81 1206108 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; - 82 1206108 : task->position = blockcur; - 83 1206108 : task->block = 0; - 84 1206108 : task->file = 0; - 85 1206108 : task->file_pos = 0; - 86 1206108 : task->read_size = 0; - 87 1206108 : task->is_timestamp_different = 0; + 81 1205730 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + 82 1205730 : task->position = blockcur; + 83 1205730 : task->block = 0; + 84 1205730 : task->file = 0; + 85 1205730 : task->file_pos = 0; + 86 1205730 : task->read_size = 0; + 87 1205730 : task->is_timestamp_different = 0; 88 : } - 89 163942 : } + 89 163879 : } 90 : 91 : /** 92 : * Setup the next pending task for all writers. 93 : */ - 94 114798 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) + 94 114746 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) 95 : { 96 : unsigned i; 97 : - 98 673481 : for (i = 0; i < io->writer_max; ++i) { - 99 558683 : struct snapraid_worker* worker = &io->writer_map[i]; - 100 558683 : struct snapraid_task* task = &worker->task_map[task_index]; + 98 673117 : for (i = 0; i < io->writer_max; ++i) { + 99 558371 : struct snapraid_worker* worker = &io->writer_map[i]; + 100 558371 : struct snapraid_task* task = &worker->task_map[task_index]; 101 : 102 : /* setup the new pending task */ - 103 558683 : task->state = TASK_STATE_READY; - 104 558683 : task->path[0] = 0; - 105 558683 : task->disk = 0; - 106 558683 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; - 107 558683 : task->position = blockcur; - 108 558683 : task->block = 0; - 109 558683 : task->file = 0; - 110 558683 : task->file_pos = 0; - 111 558683 : task->read_size = 0; - 112 558683 : task->is_timestamp_different = 0; + 103 558371 : task->state = TASK_STATE_READY; + 104 558371 : task->path[0] = 0; + 105 558371 : task->disk = 0; + 106 558371 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + 107 558371 : task->position = blockcur; + 108 558371 : task->block = 0; + 109 558371 : task->file = 0; + 110 558371 : task->file_pos = 0; + 111 558371 : task->read_size = 0; + 112 558371 : task->is_timestamp_different = 0; 113 : } - 114 114798 : } + 114 114746 : } 115 : 116 : /** 117 : * Setup an empty next pending task for all writers. 118 : */ - 119 931 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur) + 119 920 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur) 120 : { 121 : unsigned i; 122 : - 123 6517 : for (i = 0; i < io->writer_max; ++i) { - 124 5586 : struct snapraid_worker* worker = &io->writer_map[i]; - 125 5586 : struct snapraid_task* task = &worker->task_map[task_index]; + 123 6440 : for (i = 0; i < io->writer_max; ++i) { + 124 5520 : struct snapraid_worker* worker = &io->writer_map[i]; + 125 5520 : struct snapraid_task* task = &worker->task_map[task_index]; 126 : 127 : /* setup the new pending task */ - 128 5586 : task->state = TASK_STATE_EMPTY; - 129 5586 : task->path[0] = 0; - 130 5586 : task->disk = 0; - 131 5586 : task->buffer = 0; - 132 5586 : task->position = blockcur; - 133 5586 : task->block = 0; - 134 5586 : task->file = 0; - 135 5586 : task->file_pos = 0; - 136 5586 : task->read_size = 0; - 137 5586 : task->is_timestamp_different = 0; + 128 5520 : task->state = TASK_STATE_EMPTY; + 129 5520 : task->path[0] = 0; + 130 5520 : task->disk = 0; + 131 5520 : task->buffer = 0; + 132 5520 : task->position = blockcur; + 133 5520 : task->block = 0; + 134 5520 : task->file = 0; + 135 5520 : task->file_pos = 0; + 136 5520 : task->read_size = 0; + 137 5520 : task->is_timestamp_different = 0; 138 : } - 139 931 : } + 139 920 : } 140 : 141 : /*****************************************************************************/ 142 : /* mono thread */ @@ -353,54 +353,54 @@ 291 : * 292 : * This is the synchronization point for workers with the io. 293 : */ - 294 1177886 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) + 294 1177263 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) 295 : { - 296 1177886 : struct snapraid_io* io = worker->io; + 296 1177263 : struct snapraid_io* io = worker->io; 297 : 298 : /* the synchronization is protected by the io mutex */ - 299 1177886 : thread_mutex_lock(&io->io_mutex); + 299 1177263 : thread_mutex_lock(&io->io_mutex); 300 : - 301 1004268 : while (1) { + 301 1002477 : while (1) { 302 : unsigned next_index; 303 : 304 : /* check if the worker has to exit */ 305 : /* even if there is work to do */ - 306 2182154 : if (io->done) { + 306 2179740 : if (io->done) { 307 690 : thread_mutex_unlock(&io->io_mutex); 308 690 : return 0; 309 : } 310 : 311 : /* get the next pending task */ - 312 2181464 : next_index = (worker->index + 1) % io->io_max; + 312 2179050 : next_index = (worker->index + 1) % io->io_max; 313 : 314 : /* if the queue of pending tasks is not empty */ - 315 2181464 : if (next_index != io->reader_index) { + 315 2179050 : if (next_index != io->reader_index) { 316 : struct snapraid_task* task; 317 : 318 : /* the index that the IO may be waiting for */ - 319 1177196 : unsigned waiting_index = io->reader_index; + 319 1176573 : unsigned waiting_index = io->reader_index; 320 : 321 : /* the index that worker just completed */ - 322 1177196 : unsigned done_index = worker->index; + 322 1176573 : unsigned done_index = worker->index; 323 : 324 : /* get the new working task */ - 325 1177196 : worker->index = next_index; - 326 1177196 : task = &worker->task_map[worker->index]; + 325 1176573 : worker->index = next_index; + 326 1176573 : task = &worker->task_map[worker->index]; 327 : 328 : /* if the just completed task is at this index */ - 329 1177196 : if (done_index == waiting_index) { + 329 1176573 : if (done_index == waiting_index) { 330 : /* notify the IO that a new read is complete */ - 331 668 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex); + 331 827 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex); 332 : } else { - 333 1176528 : thread_mutex_unlock(&io->io_mutex); + 333 1175746 : thread_mutex_unlock(&io->io_mutex); 334 : } 335 : 336 : /* return the new task */ - 337 1177196 : return task; + 337 1176573 : return task; 338 : } 339 : 340 : /* otherwise wait for a read_sched event */ - 341 1004268 : thread_cond_wait(&io->read_sched, &io->io_mutex); + 341 1002477 : thread_cond_wait(&io->read_sched, &io->io_mutex); 342 : } 343 : } 344 : @@ -409,60 +409,60 @@ 347 : * 348 : * This is the synchronization point for workers with the io. 349 : */ - 350 560074 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state) + 350 559696 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state) 351 : { - 352 560074 : struct snapraid_io* io = worker->io; + 352 559696 : struct snapraid_io* io = worker->io; 353 : int error_index; 354 : 355 : /* the synchronization is protected by the io mutex */ - 356 560074 : thread_mutex_lock(&io->io_mutex); + 356 559696 : thread_mutex_lock(&io->io_mutex); 357 : 358 : /* counts the number of errors in the global state */ - 359 560074 : error_index = state - IO_WRITER_ERROR_BASE; - 360 560074 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX) + 359 559696 : error_index = state - IO_WRITER_ERROR_BASE; + 360 559696 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX) 361 0 : ++io->writer_error[error_index]; 362 : - 363 549486 : while (1) { + 363 551113 : while (1) { 364 : unsigned next_index; 365 : 366 : /* get the next pending task */ - 367 1109560 : next_index = (worker->index + 1) % io->io_max; + 367 1110809 : next_index = (worker->index + 1) % io->io_max; 368 : 369 : /* if the queue of pending tasks is not empty */ - 370 1109560 : if (next_index != io->writer_index) { + 370 1110809 : if (next_index != io->writer_index) { 371 : struct snapraid_task* task; 372 : 373 : /* the index that the IO may be waiting for */ - 374 559582 : unsigned waiting_index = (io->writer_index + 1) % io->io_max; + 374 559204 : unsigned waiting_index = (io->writer_index + 1) % io->io_max; 375 : 376 : /* the index that worker just completed */ - 377 559582 : unsigned done_index = worker->index; + 377 559204 : unsigned done_index = worker->index; 378 : 379 : /* get the new working task */ - 380 559582 : worker->index = next_index; - 381 559582 : task = &worker->task_map[worker->index]; + 380 559204 : worker->index = next_index; + 381 559204 : task = &worker->task_map[worker->index]; 382 : 383 : /* if the just completed task is at this index */ - 384 559582 : if (done_index == waiting_index) { + 384 559204 : if (done_index == waiting_index) { 385 : /* notify the IO that a new write is complete */ 386 0 : thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex); 387 : } else { - 388 559582 : thread_mutex_unlock(&io->io_mutex); + 388 559204 : thread_mutex_unlock(&io->io_mutex); 389 : } 390 : 391 : /* return the new task */ - 392 559582 : return task; + 392 559204 : return task; 393 : } 394 : 395 : /* check if the worker has to exit */ 396 : /* but only if there is no work to do */ - 397 549978 : if (io->done) { + 397 551605 : if (io->done) { 398 492 : thread_mutex_unlock(&io->io_mutex); 399 492 : return 0; 400 : } 401 : 402 : /* otherwise wait for a write_sched event */ - 403 549486 : thread_cond_wait(&io->write_sched, &io->io_mutex); + 403 551113 : thread_cond_wait(&io->write_sched, &io->io_mutex); 404 : } 405 : } 406 : @@ -471,87 +471,87 @@ 409 : * 410 : * This is the synchronization point for workers with the io. 411 : */ - 412 146427 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer) + 412 146364 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer) 413 : { 414 : block_off_t blockcur_schedule; 415 : block_off_t blockcur_caller; 416 : unsigned i; 417 : 418 : /* get the next parity position to process */ - 419 146427 : blockcur_schedule = io_position_next(io); + 419 146364 : blockcur_schedule = io_position_next(io); 420 : 421 : /* ensure that all data/parity was read */ - 422 146427 : assert(io->reader_list[0] == io->reader_max); + 422 146364 : assert(io->reader_list[0] == io->reader_max); 423 : 424 : /* setup the list of workers to process */ - 425 1383204 : for (i = 0; i <= io->reader_max; ++i) - 426 1236777 : io->reader_list[i] = i; + 425 1382700 : for (i = 0; i <= io->reader_max; ++i) + 426 1236336 : io->reader_list[i] = i; 427 : 428 : /* the synchronization is protected by the io mutex */ - 429 146427 : thread_mutex_lock(&io->io_mutex); + 429 146364 : thread_mutex_lock(&io->io_mutex); 430 : 431 : /* schedule the next read */ - 432 146427 : io_reader_sched(io, io->reader_index, blockcur_schedule); + 432 146364 : io_reader_sched(io, io->reader_index, blockcur_schedule); 433 : 434 : /* set the index for the tasks to return to the caller */ - 435 146427 : io->reader_index = (io->reader_index + 1) % io->io_max; + 435 146364 : io->reader_index = (io->reader_index + 1) % io->io_max; 436 : 437 : /* get the position to operate at high level from one task */ - 438 146427 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position; + 438 146364 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position; 439 : 440 : /* set the buffer to use */ - 441 146427 : *buffer = io->buffer_map[io->reader_index]; + 441 146364 : *buffer = io->buffer_map[io->reader_index]; 442 : 443 : /* signal all the workers that there is a new pending task */ - 444 146427 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex); + 444 146364 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex); 445 : - 446 146427 : return blockcur_caller; + 446 146364 : return blockcur_caller; 447 : } 448 : - 449 111042 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip) + 449 110979 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip) 450 : { 451 : (void)io; 452 : (void)blockcur; 453 : (void)skip; - 454 111042 : } + 454 110979 : } 455 : - 456 111042 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) + 456 110979 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) 457 : { 458 : unsigned i; 459 : 460 : /* ensure that all parity was written */ - 461 111042 : assert(io->writer_list[0] == io->writer_max); + 461 110979 : assert(io->writer_list[0] == io->writer_max); 462 : 463 : /* setup the list of workers to process */ - 464 781666 : for (i = 0; i <= io->writer_max; ++i) - 465 670624 : io->writer_list[i] = i; + 464 781162 : for (i = 0; i <= io->writer_max; ++i) + 465 670183 : io->writer_list[i] = i; 466 : 467 : /* the synchronization is protected by the io mutex */ - 468 111042 : thread_mutex_lock(&io->io_mutex); + 468 110979 : thread_mutex_lock(&io->io_mutex); 469 : 470 : /* report errors */ - 471 555210 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { - 472 444168 : writer_error[i] = io->writer_error[i]; - 473 444168 : io->writer_error[i] = 0; + 471 554895 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { + 472 443916 : writer_error[i] = io->writer_error[i]; + 473 443916 : io->writer_error[i] = 0; 474 : } 475 : - 476 111042 : if (skip) { + 476 110979 : if (skip) { 477 : /* skip the next write */ - 478 931 : io_writer_sched_empty(io, io->writer_index, blockcur); + 478 920 : io_writer_sched_empty(io, io->writer_index, blockcur); 479 : } else { 480 : /* schedule the next write */ - 481 110111 : io_writer_sched(io, io->writer_index, blockcur); + 481 110059 : io_writer_sched(io, io->writer_index, blockcur); 482 : } 483 : 484 : /* at this point the writers must be in sync with the readers */ - 485 111042 : assert(io->writer_index == io->reader_index); + 485 110979 : assert(io->writer_index == io->reader_index); 486 : 487 : /* set the index to be used for the next write */ - 488 111042 : io->writer_index = (io->writer_index + 1) % io->io_max; + 488 110979 : io->writer_index = (io->writer_index + 1) % io->io_max; 489 : 490 : /* signal all the workers that there is a new pending task */ - 491 111042 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex); - 492 111042 : } + 491 110979 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex); + 492 110979 : } 493 : 494 1 : static void io_refresh_thread(struct snapraid_io* io) 495 : { @@ -599,120 +599,120 @@ 537 1 : thread_mutex_unlock(&io->io_mutex); 538 1 : } 539 : - 540 105587 : static void io_flush_thread(struct snapraid_io* io) + 540 108200 : static void io_flush_thread(struct snapraid_io* io) 541 : { 542 : unsigned i; 543 : - 544 105499 : while (1) { - 545 105587 : int all_done = 1; + 544 108112 : while (1) { + 545 108200 : int all_done = 1; 546 : 547 : /* the synchronization is protected by the io mutex */ - 548 105587 : thread_mutex_lock(&io->io_mutex); + 548 108200 : thread_mutex_lock(&io->io_mutex); 549 : - 550 161400 : for (i = 0; i < io->writer_max; ++i) { - 551 161312 : struct snapraid_worker* worker = &io->writer_map[i]; + 550 194281 : for (i = 0; i < io->writer_max; ++i) { + 551 194193 : struct snapraid_worker* worker = &io->writer_map[i]; 552 : 553 : /* get the next pending task */ - 554 161312 : unsigned next_index = (worker->index + 1) % io->io_max; + 554 194193 : unsigned next_index = (worker->index + 1) % io->io_max; 555 : 556 : /* if the queue of pending tasks is not empty */ - 557 161312 : if (next_index != io->writer_index) { - 558 105499 : all_done = 0; - 559 105499 : break; + 557 194193 : if (next_index != io->writer_index) { + 558 108112 : all_done = 0; + 559 108112 : break; 560 : } 561 : } 562 : - 563 105587 : thread_mutex_unlock(&io->io_mutex); + 563 108200 : thread_mutex_unlock(&io->io_mutex); 564 : - 565 105587 : if (all_done) + 565 108200 : if (all_done) 566 88 : break; 567 : 568 : /* wait for something to complete */ - 569 105499 : thread_yield(); + 569 108112 : thread_yield(); 570 : } 571 88 : } 572 : - 573 1089660 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 573 1089282 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 574 : { 575 : unsigned waiting_cycle; 576 : 577 : /* count the waiting cycle */ - 578 1089660 : waiting_cycle = 0; + 578 1089282 : waiting_cycle = 0; 579 : 580 : /* clear the waiting indexes */ - 581 1089660 : *waiting_mac = 0; + 581 1089282 : *waiting_mac = 0; 582 : 583 : /* the synchronization is protected by the io mutex */ - 584 1089660 : thread_mutex_lock(&io->io_mutex); + 584 1089282 : thread_mutex_lock(&io->io_mutex); 585 : - 586 576 : while (1) { + 586 700 : while (1) { 587 : unsigned char* let; 588 : unsigned busy_index; 589 : 590 : /* get the index the IO is using */ 591 : /* we must ensure that this index has not a read in progress */ 592 : /* to avoid a concurrent access */ - 593 1090236 : busy_index = io->reader_index; + 593 1089982 : busy_index = io->reader_index; 594 : 595 : /* search for a worker that has already finished */ - 596 1090236 : let = &io->reader_list[0]; - 597 4632 : while (1) { - 598 1094868 : unsigned i = *let; + 596 1089982 : let = &io->reader_list[0]; + 597 5383 : while (1) { + 598 1095365 : unsigned i = *let; 599 : 600 : /* if we are at the end */ - 601 1094868 : if (i == io->reader_max) - 602 576 : break; + 601 1095365 : if (i == io->reader_max) + 602 700 : break; 603 : 604 : /* if it's in range */ - 605 1094292 : if (base <= i && i < base + count) { + 605 1094665 : if (base <= i && i < base + count) { 606 : struct snapraid_worker* worker; 607 : 608 : /* if it's the first cycle */ - 609 1091472 : if (waiting_cycle == 0) { + 609 1091581 : if (waiting_cycle == 0) { 610 : /* store the waiting indexes */ - 611 1090868 : waiting_map[(*waiting_mac)++] = i - base; + 611 1090833 : waiting_map[(*waiting_mac)++] = i - base; 612 : } 613 : - 614 1091472 : worker = &io->reader_map[i]; + 614 1091581 : worker = &io->reader_map[i]; 615 : 616 : /* if the worker has finished this index */ - 617 1091472 : if (busy_index != worker->index) { + 617 1091581 : if (busy_index != worker->index) { 618 : struct snapraid_task* task; 619 : - 620 1089660 : task = &worker->task_map[io->reader_index]; + 620 1089282 : task = &worker->task_map[io->reader_index]; 621 : - 622 1089660 : thread_mutex_unlock(&io->io_mutex); + 622 1089282 : thread_mutex_unlock(&io->io_mutex); 623 : 624 : /* mark the worker as processed */ 625 : /* setting the previous one to point at the next one */ - 626 1089660 : *let = io->reader_list[i + 1]; + 626 1089282 : *let = io->reader_list[i + 1]; 627 : 628 : /* return the position */ - 629 1089660 : *pos = i - base; + 629 1089282 : *pos = i - base; 630 : 631 : /* on the first cycle, no one is waiting */ - 632 1089660 : if (waiting_cycle == 0) - 633 1089084 : *waiting_mac = 0; + 632 1089282 : if (waiting_cycle == 0) + 633 1088587 : *waiting_mac = 0; 634 : - 635 1089660 : return task; + 635 1089282 : return task; 636 : } 637 : } 638 : 639 : /* next position to check */ - 640 4632 : let = &io->reader_list[i + 1]; + 640 5383 : let = &io->reader_list[i + 1]; 641 : } 642 : 643 : /* if no worker is ready, wait for an event */ - 644 576 : thread_cond_wait(&io->read_done, &io->io_mutex); + 644 700 : thread_cond_wait(&io->read_done, &io->io_mutex); 645 : 646 : /* count the cycles */ - 647 576 : ++waiting_cycle; + 647 700 : ++waiting_cycle; 648 : } 649 : } 650 : - 651 877956 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 651 877578 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 652 : { - 653 877956 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); + 653 877578 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); 654 : } 655 : 656 211704 : static struct snapraid_task* io_parity_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) @@ -720,18 +720,18 @@ 658 211704 : return io_task_read_thread(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac); 659 : } 660 : - 661 559582 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 661 559204 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 662 : { 663 : unsigned waiting_cycle; 664 : 665 : /* count the waiting cycle */ - 666 559582 : waiting_cycle = 0; + 666 559204 : waiting_cycle = 0; 667 : 668 : /* clear the waiting indexes */ - 669 559582 : *waiting_mac = 0; + 669 559204 : *waiting_mac = 0; 670 : 671 : /* the synchronization is protected by the io mutex */ - 672 559582 : thread_mutex_lock(&io->io_mutex); + 672 559204 : thread_mutex_lock(&io->io_mutex); 673 : 674 0 : while (1) { 675 : unsigned char* let; @@ -742,45 +742,45 @@ 680 : /* to avoid a concurrent access */ 681 : /* note that we are already sure that a write is not in progress */ 682 : /* at the index the IO is using at now */ - 683 559582 : busy_index = (io->writer_index + 1) % io->io_max; + 683 559204 : busy_index = (io->writer_index + 1) % io->io_max; 684 : 685 : /* search for a worker that has already finished */ - 686 559582 : let = &io->writer_list[0]; + 686 559204 : let = &io->writer_list[0]; 687 0 : while (1) { - 688 559582 : unsigned i = *let; + 688 559204 : unsigned i = *let; 689 : struct snapraid_worker* worker; 690 : 691 : /* if we are at the end */ - 692 559582 : if (i == io->writer_max) + 692 559204 : if (i == io->writer_max) 693 0 : break; 694 : 695 : /* if it's the first cycle */ - 696 559582 : if (waiting_cycle == 0) { + 696 559204 : if (waiting_cycle == 0) { 697 : /* store the waiting indexes */ - 698 559582 : waiting_map[(*waiting_mac)++] = i; + 698 559204 : waiting_map[(*waiting_mac)++] = i; 699 : } 700 : - 701 559582 : worker = &io->writer_map[i]; + 701 559204 : worker = &io->writer_map[i]; 702 : 703 : /* the two indexes cannot be equal */ - 704 559582 : assert(io->writer_index != worker->index); + 704 559204 : assert(io->writer_index != worker->index); 705 : 706 : /* if the worker has finished this index */ - 707 559582 : if (busy_index != worker->index) { - 708 559582 : thread_mutex_unlock(&io->io_mutex); + 707 559204 : if (busy_index != worker->index) { + 708 559204 : thread_mutex_unlock(&io->io_mutex); 709 : 710 : /* mark the worker as processed */ 711 : /* setting the previous one to point at the next one */ - 712 559582 : *let = io->writer_list[i + 1]; + 712 559204 : *let = io->writer_list[i + 1]; 713 : 714 : /* return the position */ - 715 559582 : *pos = i; + 715 559204 : *pos = i; 716 : 717 : /* on the first cycle, no one is waiting */ - 718 559582 : if (waiting_cycle == 0) - 719 559582 : *waiting_mac = 0; + 718 559204 : if (waiting_cycle == 0) + 719 559204 : *waiting_mac = 0; 720 : - 721 559582 : return; + 721 559204 : return; 722 : } 723 : 724 : /* next position to check */ @@ -795,16 +795,16 @@ 733 : } 734 : } 735 : - 736 1089792 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task) + 736 1089420 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task) 737 : { 738 : /* if we reached the end */ - 739 1089792 : if (task->position >= worker->io->block_max) { + 739 1089420 : if (task->position >= worker->io->block_max) { 740 : /* complete a dummy task */ - 741 132 : task->state = TASK_STATE_EMPTY; + 741 138 : task->state = TASK_STATE_EMPTY; 742 : } else { - 743 1089660 : worker->func(worker, task); + 743 1089282 : worker->func(worker, task); 744 : } - 745 1089792 : } + 745 1089420 : } 746 : 747 690 : static void* io_reader_thread(void* arg) 748 : { @@ -813,24 +813,24 @@ 751 : /* force completion of the first task */ 752 690 : io_reader_worker(worker, &worker->task_map[0]); 753 : - 754 1177196 : while (1) { + 754 1176573 : while (1) { 755 : struct snapraid_task* task; 756 : 757 : /* get the new task */ - 758 1177886 : task = io_reader_step(worker); + 758 1177263 : task = io_reader_step(worker); 759 : 760 : /* if no task, it means to exit */ - 761 1177886 : if (!task) + 761 1177263 : if (!task) 762 690 : break; 763 : 764 : /* nothing more to do */ - 765 1177196 : if (task->state == TASK_STATE_EMPTY) - 766 88094 : continue; + 765 1176573 : if (task->state == TASK_STATE_EMPTY) + 766 87843 : continue; 767 : - 768 1089102 : assert(task->state == TASK_STATE_READY); + 768 1088730 : assert(task->state == TASK_STATE_READY); 769 : 770 : /* work on the assigned task */ - 771 1089102 : io_reader_worker(worker, task); + 771 1088730 : io_reader_worker(worker, task); 772 : } 773 : 774 690 : return 0; @@ -841,29 +841,29 @@ 779 492 : struct snapraid_worker* worker = arg; 780 492 : int latest_state = TASK_STATE_DONE; 781 : - 782 559582 : while (1) { + 782 559204 : while (1) { 783 : struct snapraid_task* task; 784 : 785 : /* get the new task */ - 786 560074 : task = io_writer_step(worker, latest_state); + 786 559696 : task = io_writer_step(worker, latest_state); 787 : 788 : /* if no task, it means to exit */ - 789 560074 : if (!task) + 789 559696 : if (!task) 790 492 : break; 791 : 792 : /* nothing more to do */ - 793 559582 : if (task->state == TASK_STATE_EMPTY) { - 794 5586 : latest_state = TASK_STATE_DONE; - 795 5586 : continue; + 793 559204 : if (task->state == TASK_STATE_EMPTY) { + 794 5520 : latest_state = TASK_STATE_DONE; + 795 5520 : continue; 796 : } 797 : - 798 553996 : assert(task->state == TASK_STATE_READY); + 798 553684 : assert(task->state == TASK_STATE_READY); 799 : 800 : /* work on the assigned task */ - 801 553996 : worker->func(worker, task); + 801 553684 : worker->func(worker, task); 802 : 803 : /* save the resulting state */ - 804 553996 : latest_state = task->state; + 804 553684 : latest_state = task->state; 805 : } 806 : 807 492 : return 0; diff --git a/cov/cmdline/list.c.func-sort-c.html b/cov/cmdline/list.c.func-sort-c.html index 6160af18..b8ed0eb3 100644 --- a/cov/cmdline/list.c.func-sort-c.html +++ b/cov/cmdline/list.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/list.c.func.html b/cov/cmdline/list.c.func.html index 74144636..c8ff02a0 100644 --- a/cov/cmdline/list.c.func.html +++ b/cov/cmdline/list.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/list.c.gcov.html b/cov/cmdline/list.c.gcov.html index d365932e..c7963829 100644 --- a/cov/cmdline/list.c.gcov.html +++ b/cov/cmdline/list.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/main.c.func-sort-c.html b/cov/cmdline/main.c.func-sort-c.html index 04900a31..948dc1f3 100644 --- a/cov/cmdline/main.c.func-sort-c.html +++ b/cov/cmdline/main.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ main - 289 + 290
diff --git a/cov/cmdline/main.c.func.html b/cov/cmdline/main.c.func.html index 9e64c6f8..e705c789 100644 --- a/cov/cmdline/main.c.func.html +++ b/cov/cmdline/main.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ main - 289 + 290
diff --git a/cov/cmdline/main.c.gcov.html b/cov/cmdline/main.c.gcov.html index 06014c51..3a071ce0 100644 --- a/cov/cmdline/main.c.gcov.html +++ b/cov/cmdline/main.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -381,27 +381,27 @@ 319 : } 320 : /* LCOV_EXCL_STOP */ 321 : - 322 289 : int main(int argc, char* argv[]) + 322 290 : int main(int argc, char* argv[]) 323 : { 324 : int mode; 325 : int i, j; 326 : int ret; 327 : - 328 289 : mode = MODE_DEFAULT; - 329 289 : j = 1; - 330 4328 : for (i = 1; i < argc; ++i) { - 331 4039 : if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--spin-down-on-error") == 0) { + 328 290 : mode = MODE_DEFAULT; + 329 290 : j = 1; + 330 4330 : for (i = 1; i < argc; ++i) { + 331 4040 : if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--spin-down-on-error") == 0) { 332 1 : mode = MODE_SPINDOWN; 333 : } else { - 334 4038 : argv[j] = argv[i]; - 335 4038 : ++j; + 334 4039 : argv[j] = argv[i]; + 335 4039 : ++j; 336 : } 337 : } - 338 289 : argc = j; - 339 289 : argv[argc] = 0; + 338 290 : argc = j; + 339 290 : argv[argc] = 0; 340 : - 341 289 : if (mode == MODE_DEFAULT) { - 342 288 : ret = snapraid_main(argc, argv); + 341 290 : if (mode == MODE_DEFAULT) { + 342 289 : ret = snapraid_main(argc, argv); 343 : } else { 344 : struct sigaction sa; 345 : @@ -499,7 +499,7 @@ 437 : } 438 : } 439 : - 440 256 : return ret; + 440 257 : return ret; 441 : } 442 : #endif 443 : diff --git a/cov/cmdline/metro.c.func-sort-c.html b/cov/cmdline/metro.c.func-sort-c.html index b66d3e97..1a4c21ca 100644 --- a/cov/cmdline/metro.c.func-sort-c.html +++ b/cov/cmdline/metro.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ MetroHash128 - 369 + 393
diff --git a/cov/cmdline/metro.c.func.html b/cov/cmdline/metro.c.func.html index 5e61b75e..e219fd9b 100644 --- a/cov/cmdline/metro.c.func.html +++ b/cov/cmdline/metro.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ MetroHash128 - 369 + 393
diff --git a/cov/cmdline/metro.c.gcov.html b/cov/cmdline/metro.c.gcov.html index 817ebc45..436f25b5 100644 --- a/cov/cmdline/metro.c.gcov.html +++ b/cov/cmdline/metro.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -107,9 +107,9 @@ 45 : static const uint64_t k2 = 0x7BDEC03B; 46 : static const uint64_t k3 = 0x2F5870A5; 47 : - 48 369 : void MetroHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) + 48 393 : void MetroHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) 49 : { - 50 369 : const uint8_t* ptr = data; + 50 393 : const uint8_t* ptr = data; 51 : uint64_t v[4]; 52 : 53 : /* @@ -120,10 +120,10 @@ 58 : * v[0] = (static_cast<uint64_t>(seed) - k0) * k3; 59 : * v[1] = (static_cast<uint64_t>(seed) + k1) * k2; 60 : */ - 61 369 : v[0] = (util_read64(seed) - k0) * k3; - 62 369 : v[1] = (util_read64(seed + 8) + k1) * k2; + 61 393 : v[0] = (util_read64(seed) - k0) * k3; + 62 393 : v[1] = (util_read64(seed + 8) + k1) * k2; 63 : - 64 369 : if (size >= 32) { + 64 393 : if (size >= 32) { 65 : /* 66 : * EXTENSION: Initialize secondary state using both halves of the 128-bit seed 67 : * @@ -131,24 +131,24 @@ 69 : * v[2] = (static_cast<uint64_t>(seed) + k0) * k2; 70 : * v[3] = (static_cast<uint64_t>(seed) - k1) * k3; 71 : */ - 72 333 : v[2] = (util_read64(seed) + k0) * k2; - 73 333 : v[3] = (util_read64(seed + 8) - k1) * k3; + 72 357 : v[2] = (util_read64(seed) + k0) * k2; + 73 357 : v[3] = (util_read64(seed + 8) - k1) * k3; 74 : 75 : do { - 76 852876 : v[0] += util_read64(ptr) * k0; ptr += 8; v[0] = util_rotr64(v[0], 29) + v[2]; - 77 852876 : v[1] += util_read64(ptr) * k1; ptr += 8; v[1] = util_rotr64(v[1], 29) + v[3]; - 78 852876 : v[2] += util_read64(ptr) * k2; ptr += 8; v[2] = util_rotr64(v[2], 29) + v[0]; - 79 852876 : v[3] += util_read64(ptr) * k3; ptr += 8; v[3] = util_rotr64(v[3], 29) + v[1]; - 80 852876 : size -= 32; - 81 852876 : } while (size >= 32); + 76 1049484 : v[0] += util_read64(ptr) * k0; ptr += 8; v[0] = util_rotr64(v[0], 29) + v[2]; + 77 1049484 : v[1] += util_read64(ptr) * k1; ptr += 8; v[1] = util_rotr64(v[1], 29) + v[3]; + 78 1049484 : v[2] += util_read64(ptr) * k2; ptr += 8; v[2] = util_rotr64(v[2], 29) + v[0]; + 79 1049484 : v[3] += util_read64(ptr) * k3; ptr += 8; v[3] = util_rotr64(v[3], 29) + v[1]; + 80 1049484 : size -= 32; + 81 1049484 : } while (size >= 32); 82 : - 83 333 : v[2] ^= util_rotr64(((v[0] + v[3]) * k0) + v[1], 21) * k1; - 84 333 : v[3] ^= util_rotr64(((v[1] + v[2]) * k1) + v[0], 21) * k0; - 85 333 : v[0] ^= util_rotr64(((v[0] + v[2]) * k0) + v[3], 21) * k1; - 86 333 : v[1] ^= util_rotr64(((v[1] + v[3]) * k1) + v[2], 21) * k0; + 83 357 : v[2] ^= util_rotr64(((v[0] + v[3]) * k0) + v[1], 21) * k1; + 84 357 : v[3] ^= util_rotr64(((v[1] + v[2]) * k1) + v[0], 21) * k0; + 85 357 : v[0] ^= util_rotr64(((v[0] + v[2]) * k0) + v[3], 21) * k1; + 86 357 : v[1] ^= util_rotr64(((v[1] + v[3]) * k1) + v[2], 21) * k0; 87 : } 88 : - 89 369 : if (size >= 16) { + 89 393 : if (size >= 16) { 90 132 : v[0] += util_read64(ptr) * k2; ptr += 8; v[0] = util_rotr64(v[0], 33) * k3; 91 132 : v[1] += util_read64(ptr) * k2; ptr += 8; v[1] = util_rotr64(v[1], 33) * k3; 92 132 : v[0] ^= util_rotr64((v[0] * k2) + v[1], 45) * k1; @@ -156,37 +156,37 @@ 94 132 : size -= 16; 95 : } 96 : - 97 369 : if (size >= 8) { + 97 393 : if (size >= 8) { 98 134 : v[0] += util_read64(ptr) * k2; ptr += 8; v[0] = util_rotr64(v[0], 33) * k3; 99 134 : v[0] ^= util_rotr64((v[0] * k2) + v[1], 27) * k1; 100 134 : size -= 8; 101 : } 102 : - 103 369 : if (size >= 4) { + 103 393 : if (size >= 4) { 104 132 : v[1] += util_read32(ptr) * k2; ptr += 4; v[1] = util_rotr64(v[1], 33) * k3; 105 132 : v[1] ^= util_rotr64((v[1] * k3) + v[0], 46) * k0; 106 132 : size -= 4; 107 : } 108 : - 109 369 : if (size >= 2) { + 109 393 : if (size >= 2) { 110 135 : v[0] += util_read16(ptr) * k2; ptr += 2; v[0] = util_rotr64(v[0], 33) * k3; 111 135 : v[0] ^= util_rotr64((v[0] * k2) + v[1], 22) * k1; 112 135 : size -= 2; 113 : } 114 : - 115 369 : if (size >= 1) { + 115 393 : if (size >= 1) { 116 133 : v[1] += util_read8(ptr) * k2; v[1] = util_rotr64(v[1], 33) * k3; 117 133 : v[1] ^= util_rotr64((v[1] * k3) + v[0], 58) * k0; 118 : } 119 : - 120 369 : v[0] += util_rotr64((v[0] * k0) + v[1], 13); - 121 369 : v[1] += util_rotr64((v[1] * k1) + v[0], 37); - 122 369 : v[0] += util_rotr64((v[0] * k2) + v[1], 13); - 123 369 : v[1] += util_rotr64((v[1] * k3) + v[0], 37); + 120 393 : v[0] += util_rotr64((v[0] * k0) + v[1], 13); + 121 393 : v[1] += util_rotr64((v[1] * k1) + v[0], 37); + 122 393 : v[0] += util_rotr64((v[0] * k2) + v[1], 13); + 123 393 : v[1] += util_rotr64((v[1] * k3) + v[0], 37); 124 : - 125 369 : util_write64(digest, v[0]); - 126 369 : util_write64(digest + 8, v[1]); - 127 369 : } + 125 393 : util_write64(digest, v[0]); + 126 393 : util_write64(digest + 8, v[1]); + 127 393 : } 128 : diff --git a/cov/cmdline/mkstream.c.func-sort-c.html b/cov/cmdline/mkstream.c.func-sort-c.html index 9f99c180..5c259716 100644 --- a/cov/cmdline/mkstream.c.func-sort-c.html +++ b/cov/cmdline/mkstream.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/cmdline/mkstream.c.func.html b/cov/cmdline/mkstream.c.func.html index 18ef917b..31f6e1d2 100644 --- a/cov/cmdline/mkstream.c.func.html +++ b/cov/cmdline/mkstream.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/cmdline/mkstream.c.gcov.html b/cov/cmdline/mkstream.c.gcov.html index 0e3663c9..d58651cd 100644 --- a/cov/cmdline/mkstream.c.gcov.html +++ b/cov/cmdline/mkstream.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/cmdline/mktest.c.func-sort-c.html b/cov/cmdline/mktest.c.func-sort-c.html index ddc4e72b..d7479dd2 100644 --- a/cov/cmdline/mktest.c.func-sort-c.html +++ b/cov/cmdline/mktest.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 220 + 221 237 - 92.8 % + 93.2 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -69,7 +69,7 @@ cmd_generate_symlink - 940 + 932 fallback @@ -85,19 +85,19 @@ cmd_truncate - 3121 + 3136 cmd_delete - 3205 + 3160 cmd_append - 3258 + 3215 cmd_write - 6176 + 6236 cmd_change @@ -113,23 +113,23 @@ rnd_name - 26849 + 26841 rndnz_range - 32674 + 32691 file_cmp - 146738 + 146742 rndnz - 55633505 + 55624443 rnd - 56044755 + 56035837
diff --git a/cov/cmdline/mktest.c.func.html b/cov/cmdline/mktest.c.func.html index 63678c03..526da4d8 100644 --- a/cov/cmdline/mktest.c.func.html +++ b/cov/cmdline/mktest.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 220 + 221 237 - 92.8 % + 93.2 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -61,7 +61,7 @@ cmd_append - 3258 + 3215 cmd_change @@ -73,7 +73,7 @@ cmd_delete - 3205 + 3160 cmd_generate @@ -85,15 +85,15 @@ cmd_generate_symlink - 940 + 932 cmd_truncate - 3121 + 3136 cmd_write - 6176 + 6236 fallback @@ -101,7 +101,7 @@ file_cmp - 146738 + 146742 help @@ -113,15 +113,15 @@ rnd - 56044755 + 56035837 rnd_name - 26849 + 26841 rndnz - 55633505 + 55624443 rndnz_damage @@ -129,7 +129,7 @@ rndnz_range - 32674 + 32691
diff --git a/cov/cmdline/mktest.c.gcov.html b/cov/cmdline/mktest.c.gcov.html index fcec551c..ee7112ef 100644 --- a/cov/cmdline/mktest.c.gcov.html +++ b/cov/cmdline/mktest.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 220 + 221 237 - 92.8 % + 93.2 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -91,28 +91,28 @@ 29 : */ 30 : unsigned long long seed = 0; 31 : - 32 56044755 : unsigned rnd(unsigned max) + 32 56035837 : unsigned rnd(unsigned max) 33 : { - 34 56044755 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; + 34 56035837 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; 35 : - 36 56044755 : return (seed >> 32) % max; + 36 56035837 : return (seed >> 32) % max; 37 : } 38 : - 39 55633505 : unsigned rndnz(unsigned max) + 39 55624443 : unsigned rndnz(unsigned max) 40 : { - 41 55633505 : if (max <= 1) + 41 55624443 : if (max <= 1) 42 2831 : return 1; 43 : else - 44 55630674 : return rnd(max - 1) + 1; + 44 55621612 : return rnd(max - 1) + 1; 45 : } 46 : - 47 32674 : void rndnz_range(unsigned char* data, int size) + 47 32691 : void rndnz_range(unsigned char* data, int size) 48 : { 49 : int i; 50 : - 51 55659420 : for (i = 0; i < size; ++i) - 52 55626746 : data[i] = rndnz(256); - 53 32674 : } + 51 55650371 : for (i = 0; i < size; ++i) + 52 55617680 : data[i] = rndnz(256); + 53 32691 : } 54 : 55 1821 : void rndnz_damage(unsigned char* data, int size) 56 : { @@ -123,8 +123,8 @@ 61 : unsigned char c; 62 : 63 : do { - 64 1828 : c = rndnz(256); - 65 1828 : } while (c == data[i]); + 64 1832 : c = rndnz(256); + 65 1832 : } while (c == data[i]); 66 : 67 1821 : data[i] = c; 68 : } @@ -133,23 +133,23 @@ 71 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+"; 72 : #define CHARSET_LEN (sizeof(CHARSET) - 1) 73 : - 74 26849 : void rnd_name(char* file) + 74 26841 : void rnd_name(char* file) 75 : { - 76 26849 : int l = 1 + rnd(20); + 76 26841 : int l = 1 + rnd(20); 77 : - 78 308613 : while (l) { - 79 281764 : *file++ = CHARSET[rnd(CHARSET_LEN)]; - 80 281764 : --l; + 78 308703 : while (l) { + 79 281862 : *file++ = CHARSET[rnd(CHARSET_LEN)]; + 80 281862 : --l; 81 : } - 82 26849 : *file = 0; - 83 26849 : } + 82 26841 : *file = 0; + 83 26841 : } 84 : 85 : /****************************************************************************/ 86 : /* file */ 87 : - 88 146738 : int file_cmp(const void* a, const void* b) + 88 146742 : int file_cmp(const void* a, const void* b) 89 : { - 90 146738 : return strcmp(a, b); + 90 146742 : return strcmp(a, b); 91 : } 92 : 93 1821 : int fallback(int f, struct stat* st) @@ -261,11 +261,11 @@ 199 : * Create a symlink. 200 : * - If the file already exists, it's removed. 201 : */ - 202 940 : void cmd_generate_symlink(const char* path, const char* linkto) + 202 932 : void cmd_generate_symlink(const char* path, const char* linkto) 203 : { 204 : /* remove the existing file/symlink if any */ - 205 940 : if (remove(path) != 0) { - 206 919 : if (errno != ENOENT) { + 205 932 : if (remove(path) != 0) { + 206 911 : if (errno != ENOENT) { 207 : /* LCOV_EXCL_START */ 208 : log_fatal(errno, "Error removing file %s\n", path); 209 : exit(EXIT_FAILURE); @@ -273,13 +273,13 @@ 211 : } 212 : } 213 : - 214 940 : if (symlink(linkto, path) != 0) { + 214 932 : if (symlink(linkto, path) != 0) { 215 : /* LCOV_EXCL_START */ 216 : log_fatal(errno, "Error writing symlink %s\n", path); 217 : exit(EXIT_FAILURE); 218 : /* LCOV_EXCL_STOP */ 219 : } - 220 940 : } + 220 932 : } 221 : 222 : /** 223 : * Create a file or a symlink with a random name. @@ -352,68 +352,68 @@ 290 : * - The written data may be equal or not at the already existing one. 291 : * - If it's a symlink nothing is done. 292 : */ - 293 6176 : void cmd_write(const char* path, int size) + 293 6236 : void cmd_write(const char* path, int size) 294 : { 295 : struct stat st; 296 : - 297 6176 : if (lstat(path, &st) != 0) { + 297 6236 : if (lstat(path, &st) != 0) { 298 : /* LCOV_EXCL_START */ 299 : log_fatal(errno, "Error accessing %s\n", path); 300 : exit(EXIT_FAILURE); 301 : /* LCOV_EXCL_STOP */ 302 : } 303 : - 304 6176 : if (S_ISREG(st.st_mode)) { + 304 6236 : if (S_ISREG(st.st_mode)) { 305 : unsigned char* data; 306 : off_t off; 307 : int f; 308 : 309 : /* not over the end */ - 310 6149 : if (size > st.st_size) - 311 686 : size = st.st_size; + 310 6209 : if (size > st.st_size) + 311 677 : size = st.st_size; 312 : 313 : /* start at random position inside the file */ - 314 6149 : if (size < st.st_size) - 315 5463 : off = rnd(st.st_size - size); + 314 6209 : if (size < st.st_size) + 315 5530 : off = rnd(st.st_size - size); 316 : else - 317 686 : off = 0; + 317 679 : off = 0; 318 : - 319 6149 : data = malloc(size); + 319 6209 : data = malloc(size); 320 : - 321 6149 : rndnz_range(data, size); + 321 6209 : rndnz_range(data, size); 322 : - 323 6149 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 324 6149 : if (f < 0) { + 323 6209 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 324 6209 : if (f < 0) { 325 : /* LCOV_EXCL_START */ 326 : log_fatal(errno, "Error creating file %s\n", path); 327 : exit(EXIT_FAILURE); 328 : /* LCOV_EXCL_STOP */ 329 : } 330 : - 331 6149 : if (lseek(f, off, SEEK_SET) != off) { + 331 6209 : if (lseek(f, off, SEEK_SET) != off) { 332 : /* LCOV_EXCL_START */ 333 : log_fatal(errno, "Error seeking file %s\n", path); 334 : exit(EXIT_FAILURE); 335 : /* LCOV_EXCL_STOP */ 336 : } 337 : - 338 6149 : if (write(f, data, size) != size) { + 338 6209 : if (write(f, data, size) != size) { 339 : /* LCOV_EXCL_START */ 340 : log_fatal(errno, "Error writing file %s\n", path); 341 : exit(EXIT_FAILURE); 342 : /* LCOV_EXCL_STOP */ 343 : } 344 : - 345 6149 : if (close(f) != 0) { + 345 6209 : if (close(f) != 0) { 346 : /* LCOV_EXCL_START */ 347 : log_fatal(errno, "Error closing file %s\n", path); 348 : exit(EXIT_FAILURE); 349 : /* LCOV_EXCL_STOP */ 350 : } 351 : - 352 6149 : free(data); + 352 6209 : free(data); 353 : } - 354 6176 : } + 354 6236 : } 355 : 356 : /** 357 : * Damage a file. @@ -520,50 +520,50 @@ 458 : * - The file must exist. 459 : * - If it's a symlink nothing is done. 460 : */ - 461 3258 : void cmd_append(const char* path, int size) + 461 3215 : void cmd_append(const char* path, int size) 462 : { 463 : struct stat st; 464 : - 465 3258 : if (lstat(path, &st) != 0) { + 465 3215 : if (lstat(path, &st) != 0) { 466 : /* LCOV_EXCL_START */ 467 : log_fatal(errno, "Error accessing %s\n", path); 468 : exit(EXIT_FAILURE); 469 : /* LCOV_EXCL_STOP */ 470 : } 471 : - 472 3258 : if (S_ISREG(st.st_mode)) { + 472 3215 : if (S_ISREG(st.st_mode)) { 473 : unsigned char* data; 474 : int f; 475 : - 476 3258 : data = malloc(size); + 476 3215 : data = malloc(size); 477 : - 478 3258 : rndnz_range(data, size); + 478 3215 : rndnz_range(data, size); 479 : - 480 3258 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); - 481 3258 : if (f < 0) { + 480 3215 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); + 481 3215 : if (f < 0) { 482 : /* LCOV_EXCL_START */ 483 : log_fatal(errno, "Error opening file %s\n", path); 484 : exit(EXIT_FAILURE); 485 : /* LCOV_EXCL_STOP */ 486 : } 487 : - 488 3258 : if (write(f, data, size) != size) { + 488 3215 : if (write(f, data, size) != size) { 489 : /* LCOV_EXCL_START */ 490 : log_fatal(errno, "Error writing file %s\n", path); 491 : exit(EXIT_FAILURE); 492 : /* LCOV_EXCL_STOP */ 493 : } 494 : - 495 3258 : if (close(f) != 0) { + 495 3215 : if (close(f) != 0) { 496 : /* LCOV_EXCL_START */ 497 : log_fatal(errno, "Error closing file %s\n", path); 498 : exit(EXIT_FAILURE); 499 : /* LCOV_EXCL_STOP */ 500 : } 501 : - 502 3258 : free(data); + 502 3215 : free(data); 503 : } - 504 3258 : } + 504 3215 : } 505 : 506 : /** 507 : * Truncate a file. @@ -571,69 +571,69 @@ 509 : * - The file is NEVER truncated to 0. 510 : * - If it's a symlink nothing is done. 511 : */ - 512 3121 : void cmd_truncate(const char* path, int size) + 512 3136 : void cmd_truncate(const char* path, int size) 513 : { 514 : struct stat st; 515 : - 516 3121 : if (lstat(path, &st) != 0) { + 516 3136 : if (lstat(path, &st) != 0) { 517 : /* LCOV_EXCL_START */ 518 : log_fatal(errno, "Error accessing %s\n", path); 519 : exit(EXIT_FAILURE); 520 : /* LCOV_EXCL_STOP */ 521 : } 522 : - 523 3121 : if (S_ISREG(st.st_mode)) { + 523 3136 : if (S_ISREG(st.st_mode)) { 524 : off_t off; 525 : int f; 526 : 527 : /* if file is empty, just rewrite it */ - 528 3121 : if (st.st_size == 0) { - 529 0 : size = 0; + 528 3136 : if (st.st_size == 0) { + 529 4 : size = 0; 530 : } else { 531 : /* don't truncate files to 0 size to avoid ZERO file size protection */ - 532 3121 : if (size >= st.st_size) - 533 196 : size = st.st_size - 1; + 532 3132 : if (size >= st.st_size) + 533 182 : size = st.st_size - 1; 534 : } 535 : - 536 3121 : off = st.st_size - size; + 536 3136 : off = st.st_size - size; 537 : - 538 3121 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 539 3121 : if (f < 0) { + 538 3136 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 539 3136 : if (f < 0) { 540 : /* LCOV_EXCL_START */ 541 : log_fatal(errno, "Error opening file %s\n", path); 542 : exit(EXIT_FAILURE); 543 : /* LCOV_EXCL_STOP */ 544 : } 545 : - 546 3121 : if (ftruncate(f, off) != 0) { + 546 3136 : if (ftruncate(f, off) != 0) { 547 : /* LCOV_EXCL_START */ 548 : log_fatal(errno, "Error truncating file %s\n", path); 549 : exit(EXIT_FAILURE); 550 : /* LCOV_EXCL_STOP */ 551 : } 552 : - 553 3121 : if (close(f) != 0) { + 553 3136 : if (close(f) != 0) { 554 : /* LCOV_EXCL_START */ 555 : log_fatal(errno, "Error closing file %s\n", path); 556 : exit(EXIT_FAILURE); 557 : /* LCOV_EXCL_STOP */ 558 : } 559 : } - 560 3121 : } + 560 3136 : } 561 : 562 : /** 563 : * Delete a file. 564 : * - The file must exist. 565 : */ - 566 3205 : void cmd_delete(const char* path) + 566 3160 : void cmd_delete(const char* path) 567 : { - 568 3205 : if (remove(path) != 0) { + 568 3160 : if (remove(path) != 0) { 569 : /* LCOV_EXCL_START */ 570 : log_fatal(errno, "Error removing %s\n", path); 571 : exit(EXIT_FAILURE); 572 : /* LCOV_EXCL_STOP */ 573 : } - 574 3205 : } + 574 3160 : } 575 : 576 : /** 577 : * Change a file. Or deleted/truncated/append/created. @@ -644,20 +644,20 @@ 582 : struct stat st; 583 : 584 13128 : if (!size) - 585 23 : return; + 585 36 : return; 586 : - 587 13105 : if (lstat(path, &st) != 0) { + 587 13092 : if (lstat(path, &st) != 0) { 588 : /* LCOV_EXCL_START */ 589 : log_fatal(errno, "Error accessing %s\n", path); 590 : exit(EXIT_FAILURE); 591 : /* LCOV_EXCL_STOP */ 592 : } 593 : - 594 13105 : if (S_ISLNK(st.st_mode)) { + 594 13092 : if (S_ISLNK(st.st_mode)) { 595 : /* symlink */ 596 394 : if (rnd(2) == 0) { 597 : /* delete */ - 598 187 : if (remove(path) != 0) { + 598 195 : if (remove(path) != 0) { 599 : /* LCOV_EXCL_START */ 600 : log_fatal(errno, "Error removing %s\n", path); 601 : exit(EXIT_FAILURE); @@ -667,30 +667,30 @@ 605 : /* recreate */ 606 : char linkto[PATH_MAX]; 607 : - 608 207 : if (remove(path) != 0) { + 608 199 : if (remove(path) != 0) { 609 : /* LCOV_EXCL_START */ 610 : log_fatal(errno, "Error removing %s\n", path); 611 : exit(EXIT_FAILURE); 612 : /* LCOV_EXCL_STOP */ 613 : } 614 : - 615 207 : rnd_name(linkto); + 615 199 : rnd_name(linkto); 616 : - 617 207 : cmd_generate_symlink(path, linkto); + 617 199 : cmd_generate_symlink(path, linkto); 618 : } - 619 12711 : } else if (S_ISREG(st.st_mode)) { + 619 12698 : } else if (S_ISREG(st.st_mode)) { 620 : int r; 621 : - 622 12711 : r = rnd(4); + 622 12698 : r = rnd(4); 623 : - 624 12711 : if (r == 0) { - 625 3127 : cmd_write(path, size); - 626 9584 : } else if (r == 1) { - 627 3258 : cmd_append(path, size); - 628 6326 : } else if (r == 2) { - 629 3121 : cmd_truncate(path, size); + 624 12698 : if (r == 0) { + 625 3187 : cmd_write(path, size); + 626 9511 : } else if (r == 1) { + 627 3215 : cmd_append(path, size); + 628 6296 : } else if (r == 2) { + 629 3136 : cmd_truncate(path, size); 630 : } else { - 631 3205 : cmd_delete(path); + 631 3160 : cmd_delete(path); 632 : } 633 : } 634 : } diff --git a/cov/cmdline/murmur3.c.func-sort-c.html b/cov/cmdline/murmur3.c.func-sort-c.html index 7e43ceaa..7a3d6086 100644 --- a/cov/cmdline/murmur3.c.func-sort-c.html +++ b/cov/cmdline/murmur3.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ MurmurHash3_x86_128 - 2030257 + 2030240 fmix32 - 8121028 + 8120960
diff --git a/cov/cmdline/murmur3.c.func.html b/cov/cmdline/murmur3.c.func.html index 513f9246..88612806 100644 --- a/cov/cmdline/murmur3.c.func.html +++ b/cov/cmdline/murmur3.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ MurmurHash3_x86_128 - 2030257 + 2030240 fmix32 - 8121028 + 8120960
diff --git a/cov/cmdline/murmur3.c.gcov.html b/cov/cmdline/murmur3.c.gcov.html index ac27494b..ab19a90a 100644 --- a/cov/cmdline/murmur3.c.gcov.html +++ b/cov/cmdline/murmur3.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -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 8121028 : static inline uint32_t fmix32(uint32_t h) + 32 8120960 : static inline uint32_t fmix32(uint32_t h) 33 : { - 34 8121028 : h ^= h >> 16; - 35 8121028 : h *= 0x85ebca6b; - 36 8121028 : h ^= h >> 13; - 37 8121028 : h *= 0xc2b2ae35; - 38 8121028 : h ^= h >> 16; - 39 8121028 : return h; + 34 8120960 : h ^= h >> 16; + 35 8120960 : h *= 0x85ebca6b; + 36 8120960 : h ^= h >> 13; + 37 8120960 : h *= 0xc2b2ae35; + 38 8120960 : h ^= h >> 16; + 39 8120960 : return h; 40 : } 41 : 42 : /* @@ -137,7 +137,7 @@ 75 : uint32_t c3 = 0x38b34ae5; 76 : uint32_t c4 = 0xa1e38b93; 77 : - 78 2030257 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) + 78 2030240 : 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 2030257 : h1 = util_read32(seed + 0); - 87 2030257 : h2 = util_read32(seed + 4); - 88 2030257 : h3 = util_read32(seed + 8); - 89 2030257 : h4 = util_read32(seed + 12); + 86 2030240 : h1 = util_read32(seed + 0); + 87 2030240 : h2 = util_read32(seed + 4); + 88 2030240 : h3 = util_read32(seed + 8); + 89 2030240 : h4 = util_read32(seed + 12); 90 : - 91 2030257 : nblocks = size / 16; - 92 2030257 : blocks = data; - 93 2030257 : end = blocks + nblocks * 4; + 91 2030240 : nblocks = size / 16; + 92 2030240 : blocks = data; + 93 2030240 : end = blocks + nblocks * 4; 94 : 95 : /* body */ - 96 105999566 : while (blocks < end) { - 97 103969309 : uint32_t k1 = blocks[0]; - 98 103969309 : uint32_t k2 = blocks[1]; - 99 103969309 : uint32_t k3 = blocks[2]; - 100 103969309 : uint32_t k4 = blocks[3]; + 96 106001256 : while (blocks < end) { + 97 103971016 : uint32_t k1 = blocks[0]; + 98 103971016 : uint32_t k2 = blocks[1]; + 99 103971016 : uint32_t k3 = blocks[2]; + 100 103971016 : uint32_t k4 = blocks[3]; 101 : 102 : #if WORDS_BIGENDIAN 103 : k1 = util_swap32(k1); @@ -168,81 +168,81 @@ 106 : k4 = util_swap32(k4); 107 : #endif 108 : - 109 103969309 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 109 103971016 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 110 : - 111 103969309 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; + 111 103971016 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; 112 : - 113 103969309 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 113 103971016 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; 114 : - 115 103969309 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; + 115 103971016 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; 116 : - 117 103969309 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 117 103971016 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; 118 : - 119 103969309 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; + 119 103971016 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; 120 : - 121 103969309 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 121 103971016 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; 122 : - 123 103969309 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; + 123 103971016 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; 124 : - 125 103969309 : blocks += 4; + 125 103971016 : blocks += 4; 126 : } 127 : 128 : /* tail */ - 129 2030257 : size_remainder = size & 15; - 130 2030257 : if (size_remainder != 0) { - 131 767192 : const uint8_t* tail = (const uint8_t*)blocks; + 129 2030240 : size_remainder = size & 15; + 130 2030240 : if (size_remainder != 0) { + 131 767156 : const uint8_t* tail = (const uint8_t*)blocks; 132 : - 133 767192 : uint32_t k1 = 0; - 134 767192 : uint32_t k2 = 0; - 135 767192 : uint32_t k3 = 0; - 136 767192 : uint32_t k4 = 0; + 133 767156 : uint32_t k1 = 0; + 134 767156 : uint32_t k2 = 0; + 135 767156 : uint32_t k3 = 0; + 136 767156 : uint32_t k4 = 0; 137 : - 138 767192 : switch (size_remainder) { - 139 50471 : case 15 : k4 ^= (uint32_t)tail[14] << 16; /* fallthrough */ - 140 102429 : case 14 : k4 ^= (uint32_t)tail[13] << 8; /* fallthrough */ - 141 153813 : case 13 : k4 ^= (uint32_t)tail[12] << 0; /* fallthrough */ - 142 153813 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 138 767156 : switch (size_remainder) { + 139 50451 : case 15 : k4 ^= (uint32_t)tail[14] << 16; /* fallthrough */ + 140 102402 : case 14 : k4 ^= (uint32_t)tail[13] << 8; /* fallthrough */ + 141 153791 : case 13 : k4 ^= (uint32_t)tail[12] << 0; /* fallthrough */ + 142 153791 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; 143 : /* fallthrough */ - 144 205844 : case 12 : k3 ^= (uint32_t)tail[11] << 24; /* fallthrough */ - 145 257558 : case 11 : k3 ^= (uint32_t)tail[10] << 16; /* fallthrough */ - 146 308901 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8; /* fallthrough */ - 147 361309 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0; /* fallthrough */ - 148 361309 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 144 205797 : case 12 : k3 ^= (uint32_t)tail[11] << 24; /* fallthrough */ + 145 257494 : case 11 : k3 ^= (uint32_t)tail[10] << 16; /* fallthrough */ + 146 308851 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8; /* fallthrough */ + 147 361271 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0; /* fallthrough */ + 148 361271 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; 149 : /* fallthrough */ - 150 414370 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24; /* fallthrough */ - 151 463089 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16; /* fallthrough */ - 152 514935 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8; /* fallthrough */ - 153 564647 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0; /* fallthrough */ - 154 564647 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 150 414299 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24; /* fallthrough */ + 151 463009 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16; /* fallthrough */ + 152 514868 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8; /* fallthrough */ + 153 564597 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0; /* fallthrough */ + 154 564597 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; 155 : /* fallthrough */ - 156 615781 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24; /* fallthrough */ - 157 665404 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16; /* fallthrough */ - 158 715694 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8; /* fallthrough */ - 159 767192 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0; /* fallthrough */ - 160 767192 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 156 615741 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24; /* fallthrough */ + 157 665352 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16; /* fallthrough */ + 158 715670 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8; /* fallthrough */ + 159 767156 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0; /* fallthrough */ + 160 767156 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 161 : /* fallthrough */ 162 : } 163 : } 164 : 165 : /* finalization */ - 166 2030257 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; + 166 2030240 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; 167 : - 168 2030257 : h1 += h2; h1 += h3; h1 += h4; - 169 2030257 : h2 += h1; h3 += h1; h4 += h1; + 168 2030240 : h1 += h2; h1 += h3; h1 += h4; + 169 2030240 : h2 += h1; h3 += h1; h4 += h1; 170 : - 171 2030257 : h1 = fmix32(h1); - 172 2030257 : h2 = fmix32(h2); - 173 2030257 : h3 = fmix32(h3); - 174 2030257 : h4 = fmix32(h4); + 171 2030240 : h1 = fmix32(h1); + 172 2030240 : h2 = fmix32(h2); + 173 2030240 : h3 = fmix32(h3); + 174 2030240 : h4 = fmix32(h4); 175 : - 176 2030257 : h1 += h2; h1 += h3; h1 += h4; - 177 2030257 : h2 += h1; h3 += h1; h4 += h1; + 176 2030240 : h1 += h2; h1 += h3; h1 += h4; + 177 2030240 : h2 += h1; h3 += h1; h4 += h1; 178 : - 179 2030257 : util_write32(digest + 0, h1); - 180 2030257 : util_write32(digest + 4, h2); - 181 2030257 : util_write32(digest + 8, h3); - 182 2030257 : util_write32(digest + 12, h4); - 183 2030257 : } + 179 2030240 : util_write32(digest + 0, h1); + 180 2030240 : util_write32(digest + 4, h2); + 181 2030240 : util_write32(digest + 8, h3); + 182 2030240 : util_write32(digest + 12, h4); + 183 2030240 : } 184 : diff --git a/cov/cmdline/parity.c.func-sort-c.html b/cov/cmdline/parity.c.func-sort-c.html index 889e3488..fc232c83 100644 --- a/cov/cmdline/parity.c.func-sort-c.html +++ b/cov/cmdline/parity.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -101,7 +101,7 @@ parity_allocated_size - 668 + 667 hbit_u64 @@ -125,15 +125,15 @@ parity_write - 626146 + 625834 parity_read - 3511017 + 3511023 parity_split_find - 4137163 + 4136857
diff --git a/cov/cmdline/parity.c.func.html b/cov/cmdline/parity.c.func.html index 7ae69d2d..88f29a3c 100644 --- a/cov/cmdline/parity.c.func.html +++ b/cov/cmdline/parity.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -65,7 +65,7 @@ parity_allocated_size - 668 + 667 parity_chsize @@ -105,7 +105,7 @@ parity_read - 3511017 + 3511023 parity_size @@ -113,7 +113,7 @@ parity_split_find - 4137163 + 4136857 parity_split_is_fixed @@ -133,7 +133,7 @@ parity_write - 626146 + 625834
diff --git a/cov/cmdline/parity.c.gcov.html b/cov/cmdline/parity.c.gcov.html index 4977beba..2e2b96f5 100644 --- a/cov/cmdline/parity.c.gcov.html +++ b/cov/cmdline/parity.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 18 @@ -94,31 +94,31 @@ 32 : /****************************************************************************/ 33 : /* parity */ 34 : - 35 668 : block_off_t parity_allocated_size(struct snapraid_state* state) + 35 667 : block_off_t parity_allocated_size(struct snapraid_state* state) 36 : { 37 : block_off_t parity_block; 38 : tommy_node* i; 39 : 40 : /* compute the size of the parity file */ - 41 668 : parity_block = 0; - 42 4666 : for (i = state->disklist; i != 0; i = i->next) { - 43 3998 : struct snapraid_disk* disk = i->data; + 41 667 : parity_block = 0; + 42 4659 : for (i = state->disklist; i != 0; i = i->next) { + 43 3992 : struct snapraid_disk* disk = i->data; 44 : 45 : /* start from the declared size */ - 46 3998 : block_off_t block = fs_size(disk); + 46 3992 : block_off_t block = fs_size(disk); 47 : 48 : /* decrease the block until an allocated one, but part of a file */ 49 : /* we don't stop at deleted blocks, because we want to have them cleared */ 50 : /* if they are at the end of the parity */ - 51 192692 : while (block > parity_block && !block_has_file(fs_par2block_find(disk, block - 1))) + 51 192686 : while (block > parity_block && !block_has_file(fs_par2block_find(disk, block - 1))) 52 188694 : --block; 53 : 54 : /* get the highest value */ - 55 3998 : if (block > parity_block) - 56 2313 : parity_block = block; + 55 3992 : if (block > parity_block) + 56 2308 : parity_block = block; 57 : } 58 : - 59 668 : return parity_block; + 59 667 : return parity_block; 60 : } 61 : 62 92 : block_off_t parity_used_size(struct snapraid_state* state) @@ -135,8 +135,8 @@ 73 551 : block_off_t block = fs_size(disk); 74 : 75 : /* decrease the block until an used one */ - 76 226345 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1))) - 77 225794 : --block; + 76 226349 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1))) + 77 225798 : --block; 78 : 79 : /* get the highest value */ 80 551 : if (block > parity_block) @@ -859,26 +859,26 @@ 797 1058 : return f_ret; 798 : } 799 : - 800 4137163 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset) + 800 4136857 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset) 801 : { 802 : unsigned s; 803 : - 804 4137163 : if (*offset < 0) + 804 4136857 : if (*offset < 0) 805 0 : return 0; 806 : - 807 6542594 : for (s = 0; s < handle->split_mac; ++s) { - 808 6531234 : struct snapraid_split_handle* split = &handle->split_map[s]; + 807 6542370 : for (s = 0; s < handle->split_mac; ++s) { + 808 6531010 : struct snapraid_split_handle* split = &handle->split_map[s]; 809 : - 810 6531234 : if (*offset < split->size) - 811 4125803 : return split; + 810 6531010 : if (*offset < split->size) + 811 4125497 : return split; 812 : - 813 2405431 : *offset -= split->size; + 813 2405513 : *offset -= split->size; 814 : } 815 : 816 11360 : return 0; 817 : } 818 : - 819 626146 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size) + 819 625834 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size) 820 : { 821 : ssize_t write_ret; 822 : data_off_t offset; @@ -886,10 +886,10 @@ 824 : unsigned count; 825 : int ret; 826 : - 827 626146 : offset = pos * (data_off_t)block_size; + 827 625834 : offset = pos * (data_off_t)block_size; 828 : - 829 626146 : split = parity_split_find(handle, &offset); - 830 626146 : if (!split) { + 829 625834 : split = parity_split_find(handle, &offset); + 830 625834 : if (!split) { 831 : /* LCOV_EXCL_START */ 832 : errno = ENXIO; 833 : log_fatal(errno, "Writing parity data outside range at extra offset %" PRIu64 ".\n", offset); @@ -898,15 +898,15 @@ 836 : } 837 : 838 : /* update the valid range */ - 839 626146 : if (split->valid_size < offset + block_size) + 839 625834 : if (split->valid_size < offset + block_size) 840 182791 : split->valid_size = offset + block_size; 841 : - 842 626146 : count = 0; + 842 625834 : count = 0; 843 : do { - 844 626146 : bw_limit(handle->bw, block_size - count); + 844 625834 : bw_limit(handle->bw, block_size - count); 845 : - 846 626146 : write_ret = pwrite(split->f, block_buffer + count, block_size - count, offset + count); - 847 626146 : if (write_ret == -1) { + 846 625834 : write_ret = pwrite(split->f, block_buffer + count, block_size - count, offset + count); + 847 625834 : if (write_ret == -1) { 848 : /* LCOV_EXCL_START */ 849 : if (errno == ENOSPC) { 850 : log_fatal(errno, "Failed to grow parity file '%s' using write due lack of space.\n", split->path); @@ -916,7 +916,7 @@ 854 : return -1; 855 : /* LCOV_EXCL_STOP */ 856 : } - 857 626146 : if (write_ret == 0) { + 857 625834 : if (write_ret == 0) { 858 : /* LCOV_EXCL_START */ 859 : errno = ENXIO; 860 : log_fatal(errno, "Unexpected 0 write to file '%s'. %s.\n", split->path, strerror(errno)); @@ -924,21 +924,21 @@ 862 : /* LCOV_EXCL_STOP */ 863 : } 864 : - 865 626146 : count += write_ret; - 866 626146 : } while (count < block_size); + 865 625834 : count += write_ret; + 866 625834 : } while (count < block_size); 867 : - 868 626146 : ret = advise_write(&split->advise, split->f, offset, block_size); - 869 626146 : if (ret != 0) { + 868 625834 : ret = advise_write(&split->advise, split->f, offset, block_size); + 869 625834 : if (ret != 0) { 870 : /* LCOV_EXCL_START */ 871 : log_fatal(errno, "Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); 872 : return -1; 873 : /* LCOV_EXCL_STOP */ 874 : } 875 : - 876 626146 : return 0; + 876 625834 : return 0; 877 : } 878 : - 879 3511017 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, log_ptr* out) + 879 3511023 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, log_ptr* out) 880 : { 881 : ssize_t read_ret; 882 : data_off_t offset; @@ -946,10 +946,10 @@ 884 : struct snapraid_split_handle* split; 885 : int ret; 886 : - 887 3511017 : offset = pos * (data_off_t)block_size; + 887 3511023 : offset = pos * (data_off_t)block_size; 888 : - 889 3511017 : split = parity_split_find(handle, &offset); - 890 3511017 : if (!split) { + 889 3511023 : split = parity_split_find(handle, &offset); + 890 3511023 : if (!split) { 891 : /* LCOV_EXCL_START */ 892 : errno = ENXIO; 893 : out(errno, "Reading parity data outside range at extra offset %" PRIu64 ".\n", offset); @@ -958,7 +958,7 @@ 896 : } 897 : 898 : /* if read is completely out of the valid range */ - 899 3499657 : if (offset >= split->valid_size) { + 899 3499663 : if (offset >= split->valid_size) { 900 : /* LCOV_EXCL_START */ 901 : errno = ENXIO; 902 : out(errno, "Reading over the end from parity file '%s' at offset %" PRIu64 " for size %u.\n", split->path, offset, block_size); @@ -966,19 +966,19 @@ 904 : /* LCOV_EXCL_STOP */ 905 : } 906 : - 907 3420682 : count = 0; - 908 3420682 : errno = 0; + 907 3420688 : count = 0; + 908 3420688 : errno = 0; 909 : do { - 910 3420682 : bw_limit(handle->bw, block_size - count); + 910 3420688 : bw_limit(handle->bw, block_size - count); 911 : - 912 3420682 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count); - 913 3420682 : if (read_ret == -1) { + 912 3420688 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count); + 913 3420688 : if (read_ret == -1) { 914 : /* LCOV_EXCL_START */ 915 : out(errno, "Error reading parity file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno)); 916 : return -1; 917 : /* LCOV_EXCL_STOP */ 918 : } - 919 3420682 : if (read_ret == 0) { + 919 3420688 : if (read_ret == 0) { 920 : /* LCOV_EXCL_START */ 921 : if (errno == 0) 922 : errno = ENXIO; @@ -987,18 +987,18 @@ 925 : /* LCOV_EXCL_STOP */ 926 : } 927 : - 928 3420682 : count += read_ret; - 929 3420682 : } while (count < block_size); + 928 3420688 : count += read_ret; + 929 3420688 : } while (count < block_size); 930 : - 931 3420682 : ret = advise_read(&split->advise, split->f, offset, block_size); - 932 3420682 : if (ret != 0) { + 931 3420688 : ret = advise_read(&split->advise, split->f, offset, block_size); + 932 3420688 : if (ret != 0) { 933 : /* LCOV_EXCL_START */ 934 : out(errno, "Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); 935 : return -1; 936 : /* LCOV_EXCL_STOP */ 937 : } 938 : - 939 3420682 : return block_size; + 939 3420688 : return block_size; 940 : } 941 : diff --git a/cov/cmdline/pool.c.func-sort-c.html b/cov/cmdline/pool.c.func-sort-c.html index 5d27197f..1ddb6947 100644 --- a/cov/cmdline/pool.c.func-sort-c.html +++ b/cov/cmdline/pool.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 diff --git a/cov/cmdline/pool.c.func.html b/cov/cmdline/pool.c.func.html index 411287e8..a37a2b51 100644 --- a/cov/cmdline/pool.c.func.html +++ b/cov/cmdline/pool.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 diff --git a/cov/cmdline/pool.c.gcov.html b/cov/cmdline/pool.c.gcov.html index de4a6006..05536db4 100644 --- a/cov/cmdline/pool.c.gcov.html +++ b/cov/cmdline/pool.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 @@ -392,7 +392,7 @@ 330 : 331 : /* check if the info match */ 332 5690 : if (found->mtime_sec == mtime_sec - 333 5399 : && found->mtime_nsec == mtime_nsec + 333 5406 : && found->mtime_nsec == mtime_nsec 334 5385 : && strcmp(found->linkto, linkto) == 0 335 : ) { 336 : /* nothing to do */ diff --git a/cov/cmdline/portable.h.func-sort-c.html b/cov/cmdline/portable.h.func-sort-c.html index 2d001c82..ce670742 100644 --- a/cov/cmdline/portable.h.func-sort-c.html +++ b/cov/cmdline/portable.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/portable.h.func.html b/cov/cmdline/portable.h.func.html index 178ea9e0..c09b0f5c 100644 --- a/cov/cmdline/portable.h.func.html +++ b/cov/cmdline/portable.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/portable.h.gcov.html b/cov/cmdline/portable.h.gcov.html index 01522dd0..330dd262 100644 --- a/cov/cmdline/portable.h.gcov.html +++ b/cov/cmdline/portable.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/rehash.c.func-sort-c.html b/cov/cmdline/rehash.c.func-sort-c.html index 7182d3c8..9efd3408 100644 --- a/cov/cmdline/rehash.c.func-sort-c.html +++ b/cov/cmdline/rehash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/rehash.c.func.html b/cov/cmdline/rehash.c.func.html index d5f81867..fefc25ea 100644 --- a/cov/cmdline/rehash.c.func.html +++ b/cov/cmdline/rehash.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/rehash.c.gcov.html b/cov/cmdline/rehash.c.gcov.html index 07606a7d..32f3df23 100644 --- a/cov/cmdline/rehash.c.gcov.html +++ b/cov/cmdline/rehash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/scan.c.func-sort-c.html b/cov/cmdline/scan.c.func-sort-c.html index 2478ee8e..5910e578 100644 --- a/cov/cmdline/scan.c.func-sort-c.html +++ b/cov/cmdline/scan.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 29 @@ -113,7 +113,7 @@ file_is_full_hashed_and_stable - 23671 + 23670 scan_link @@ -121,27 +121,27 @@ scan_file_deallocate - 55231 + 55218 scan_file_remove - 55231 + 55218 scan_file_refresh - 77410 + 77397 scan_file_allocate - 100097 + 100084 scan_file_delayed_allocate - 100097 + 100084 scan_file_insert - 100097 + 100084 dd_ino_compare @@ -149,19 +149,19 @@ stamp_lock - 512471 + 512368 stamp_unlock - 512471 + 512368 file_is_full_invalid_parity_and_stable - 1083709 + 1083722 scan_file_keep - 1083709 + 1083722 scan_file diff --git a/cov/cmdline/scan.c.func.html b/cov/cmdline/scan.c.func.html index 87041753..8ed9eb89 100644 --- a/cov/cmdline/scan.c.func.html +++ b/cov/cmdline/scan.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 29 @@ -73,11 +73,11 @@ file_is_full_hashed_and_stable - 23671 + 23670 file_is_full_invalid_parity_and_stable - 1083709 + 1083722 scan_alloc @@ -109,31 +109,31 @@ scan_file_allocate - 100097 + 100084 scan_file_deallocate - 55231 + 55218 scan_file_delayed_allocate - 100097 + 100084 scan_file_insert - 100097 + 100084 scan_file_keep - 1083709 + 1083722 scan_file_refresh - 77410 + 77397 scan_file_remove - 55231 + 55218 scan_free @@ -157,11 +157,11 @@ stamp_lock - 512471 + 512368 stamp_unlock - 512471 + 512368 state_diff diff --git a/cov/cmdline/scan.c.gcov.html b/cov/cmdline/scan.c.gcov.html index 76c4b158..1297c5e1 100644 --- a/cov/cmdline/scan.c.gcov.html +++ b/cov/cmdline/scan.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 29 @@ -156,23 +156,23 @@ 94 599 : free(scan); 95 599 : } 96 : - 97 512471 : static void stamp_lock(struct snapraid_disk* disk) + 97 512368 : static void stamp_lock(struct snapraid_disk* disk) 98 : { 99 : #if HAVE_THREAD - 100 512471 : thread_mutex_lock(&disk->stamp_mutex); + 100 512368 : thread_mutex_lock(&disk->stamp_mutex); 101 : #else 102 : (void)disk; 103 : #endif - 104 512471 : } + 104 512368 : } 105 : - 106 512471 : static void stamp_unlock(struct snapraid_disk* disk) + 106 512368 : static void stamp_unlock(struct snapraid_disk* disk) 107 : { 108 : #if HAVE_THREAD - 109 512471 : thread_mutex_unlock(&disk->stamp_mutex); + 109 512368 : thread_mutex_unlock(&disk->stamp_mutex); 110 : #else 111 : (void)disk; 112 : #endif - 113 512471 : } + 113 512368 : } 114 : 115 : /** 116 : * Remove the specified link from the data set. @@ -285,42 +285,42 @@ 223 : /** 224 : * Insert the specified file in the parity. 225 : */ - 226 100097 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 226 100084 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 227 : { - 228 100097 : struct snapraid_state* state = scan->state; - 229 100097 : struct snapraid_disk* disk = scan->disk; + 228 100084 : struct snapraid_state* state = scan->state; + 229 100084 : struct snapraid_disk* disk = scan->disk; 230 : block_off_t i; 231 : block_off_t parity_pos; 232 : 233 : /* state changed */ - 234 100097 : scan->need_write = 1; + 234 100084 : scan->need_write = 1; 235 : 236 : /* allocate the blocks of the file */ - 237 100097 : parity_pos = disk->first_free_block; - 238 350007 : for (i = 0; i < file->blockmax; ++i) { + 237 100084 : parity_pos = disk->first_free_block; + 238 349939 : for (i = 0; i < file->blockmax; ++i) { 239 : struct snapraid_block* block; 240 : struct snapraid_block* over_block; 241 : snapraid_info info; 242 : 243 : /* increment the position until the first really free block */ - 244 784407 : while (block_has_file(fs_par2block_find(disk, parity_pos))) - 245 534497 : ++parity_pos; + 244 782963 : while (block_has_file(fs_par2block_find(disk, parity_pos))) + 245 533108 : ++parity_pos; 246 : 247 : /* get block we are going to overwrite, if any */ - 248 249910 : over_block = fs_par2block_find(disk, parity_pos); + 248 249855 : over_block = fs_par2block_find(disk, parity_pos); 249 : 250 : /* deallocate it */ - 251 249910 : if (over_block != BLOCK_NULL) - 252 90924 : fs_deallocate(disk, parity_pos); + 251 249855 : if (over_block != BLOCK_NULL) + 252 90869 : fs_deallocate(disk, parity_pos); 253 : 254 : /* get block specific info */ - 255 249910 : info = info_get(&state->infoarr, parity_pos); + 255 249855 : info = info_get(&state->infoarr, parity_pos); 256 : 257 : /* get the new block we are going to write */ - 258 249910 : block = fs_file2block_get(file, i); + 258 249855 : block = fs_file2block_get(file, i); 259 : 260 : /* if the file block already has an updated hash without rehash */ - 261 249910 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { + 261 249855 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { 262 : /* the only possible case is for REP blocks */ 263 87239 : assert(block_state_get(block) == BLOCK_STATE_REP); 264 : @@ -332,25 +332,25 @@ 270 : unsigned over_state; 271 : 272 : /* convert to a CHG block */ - 273 162671 : block_state_set(block, BLOCK_STATE_CHG); + 273 162616 : block_state_set(block, BLOCK_STATE_CHG); 274 : 275 : /* state of the block we are going to overwrite */ - 276 162671 : over_state = block_state_get(over_block); + 276 162616 : over_state = block_state_get(over_block); 277 : 278 : /* if the block is an empty one */ - 279 162671 : if (over_state == BLOCK_STATE_EMPTY) { + 279 162616 : if (over_state == BLOCK_STATE_EMPTY) { 280 : /* the block was empty and filled with zeros */ 281 : /* set the hash to the special ZERO value */ 282 117591 : hash_zero_set(block->hash); 283 : } else { 284 : /* otherwise it's a DELETED one */ - 285 45080 : assert(over_state == BLOCK_STATE_DELETED); + 285 45025 : assert(over_state == BLOCK_STATE_DELETED); 286 : 287 : /* copy the past hash of the block */ - 288 45080 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE); + 288 45025 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE); 289 : 290 : /* if we have not already cleared the past hash */ - 291 45080 : if (!state->clear_past_hash) { + 291 45025 : if (!state->clear_past_hash) { 292 : /* in this case we don't know if the old state is still the one */ 293 : /* stored inside the parity, because after an aborted sync, the parity */ 294 : /* may be or may be not have been updated with the new data */ @@ -367,15 +367,15 @@ 305 : } 306 : 307 : /* store in the disk map, after invalidating all the other blocks */ - 308 249910 : fs_allocate(disk, parity_pos, file, i); + 308 249855 : fs_allocate(disk, parity_pos, file, i); 309 : 310 : /* set the new free position */ - 311 249910 : disk->first_free_block = parity_pos + 1; + 311 249855 : disk->first_free_block = parity_pos + 1; 312 : } 313 : 314 : /* insert in the list of contained files */ - 315 100097 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); - 316 100097 : } + 315 100084 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 316 100084 : } 317 : 318 : /** 319 : * Delete the specified file from the parity. @@ -384,23 +384,23 @@ 322 : * The file is then inserted in the deleted set, and it should not be deallocated, 323 : * as the parity still references it. 324 : */ - 325 55231 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) + 325 55218 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) 326 : { - 327 55231 : struct snapraid_state* state = scan->state; - 328 55231 : struct snapraid_disk* disk = scan->disk; + 327 55218 : struct snapraid_state* state = scan->state; + 328 55218 : struct snapraid_disk* disk = scan->disk; 329 : block_off_t i; 330 : 331 : /* remove from the list of contained files */ - 332 55231 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); + 332 55218 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); 333 : 334 : /* state changed */ - 335 55231 : scan->need_write = 1; + 335 55218 : scan->need_write = 1; 336 : 337 : /* here we are supposed to adjust the ::first_free_block position */ 338 : /* with the parity position we are deleting */ 339 : /* but we also know that we do only delayed insert, after all the deletion, */ 340 : /* so at this point ::first_free_block is always at 0, and we don't need to update it */ - 341 55231 : if (disk->first_free_block != 0) { + 341 55218 : if (disk->first_free_block != 0) { 342 : /* LCOV_EXCL_START */ 343 : log_fatal(EINTERNAL, "Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub); 344 : os_abort(); @@ -408,17 +408,17 @@ 346 : } 347 : 348 : /* free all the blocks of the file */ - 349 194526 : for (i = 0; i < file->blockmax; ++i) { - 350 139295 : struct snapraid_block* block = fs_file2block_get(file, i); + 349 194458 : for (i = 0; i < file->blockmax; ++i) { + 350 139240 : struct snapraid_block* block = fs_file2block_get(file, i); 351 : unsigned block_state; 352 : 353 : /* in case we scan after an aborted sync, */ 354 : /* we could get also intermediate states */ - 355 139295 : block_state = block_state_get(block); - 356 139295 : switch (block_state) { - 357 33275 : case BLOCK_STATE_BLK : + 355 139240 : block_state = block_state_get(block); + 356 139240 : switch (block_state) { + 357 33220 : case BLOCK_STATE_BLK : 358 : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */ - 359 33275 : break; + 359 33220 : break; 360 28040 : case BLOCK_STATE_CHG : 361 : /* if we have not already cleared the past hash */ 362 28040 : if (!state->clear_past_hash) { @@ -448,23 +448,23 @@ 386 : } 387 : 388 : /* set the block as deleted */ - 389 139295 : block_state_set(block, BLOCK_STATE_DELETED); + 389 139240 : block_state_set(block, BLOCK_STATE_DELETED); 390 : } 391 : 392 : /* mark the file as deleted */ - 393 55231 : file_flag_set(file, FILE_IS_DELETED); + 393 55218 : file_flag_set(file, FILE_IS_DELETED); 394 : 395 : /* insert it in the list of deleted blocks */ - 396 55231 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); - 397 55231 : } + 396 55218 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); + 397 55218 : } 398 : - 399 100097 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 399 100084 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 400 : { - 401 100097 : struct snapraid_state* state = scan->state; - 402 100097 : struct snapraid_disk* disk = scan->disk; + 401 100084 : struct snapraid_state* state = scan->state; + 402 100084 : struct snapraid_disk* disk = scan->disk; 403 : 404 : /* if we sort for physical offsets we have to read them for new files */ - 405 100097 : if (state->opt.force_order == SORT_PHYSICAL + 405 100084 : if (state->opt.force_order == SORT_PHYSICAL 406 11432 : && file->physical == FILEPHY_UNREAD_OFFSET 407 : ) { 408 : char path_next[PATH_MAX]; @@ -480,30 +480,30 @@ 418 : } 419 : 420 : /* insert in the delayed list */ - 421 100097 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); - 422 100097 : } + 421 100084 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); + 422 100084 : } 423 : 424 : /** 425 : * Check if a file is completely formed of blocks with invalid parity, 426 : * and no rehash is tagged, and if it has at least one block. 427 : */ - 428 1083709 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 428 1083722 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 429 : { 430 : block_off_t i; 431 : 432 : /* with no block, it never has an invalid parity */ - 433 1083709 : if (file->blockmax == 0) - 434 1525 : return 0; + 433 1083722 : if (file->blockmax == 0) + 434 1523 : return 0; 435 : 436 : /* check all blocks */ - 437 1139175 : for (i = 0; i < file->blockmax; ++i) { + 437 1139190 : for (i = 0; i < file->blockmax; ++i) { 438 : snapraid_info info; - 439 1116488 : struct snapraid_block* block = fs_file2block_get(file, i); + 439 1116503 : struct snapraid_block* block = fs_file2block_get(file, i); 440 : block_off_t parity_pos; 441 : 442 : /* exclude blocks with parity */ - 443 1116488 : if (!block_has_invalid_parity(block)) - 444 1059497 : return 0; + 443 1116503 : if (!block_has_invalid_parity(block)) + 444 1059512 : return 0; 445 : 446 : /* 447 : * Get the parity position. @@ -533,23 +533,23 @@ 471 : * Check if a file is completely formed of blocks with an updated hash, 472 : * and no rehash is tagged, and if it has at least one block. 473 : */ - 474 23671 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 474 23670 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 475 : { 476 : block_off_t i; 477 : 478 : /* with no block, it never has a hash */ - 479 23671 : if (file->blockmax == 0) + 479 23670 : if (file->blockmax == 0) 480 27 : return 0; 481 : 482 : /* check all blocks */ - 483 81888 : for (i = 0; i < file->blockmax; ++i) { + 483 81887 : for (i = 0; i < file->blockmax; ++i) { 484 : snapraid_info info; - 485 58251 : struct snapraid_block* block = fs_file2block_get(file, i); + 485 58250 : struct snapraid_block* block = fs_file2block_get(file, i); 486 : block_off_t parity_pos; 487 : 488 : /* exclude blocks without hash */ - 489 58251 : if (!block_has_updated_hash(block)) - 490 7 : return 0; + 489 58250 : if (!block_has_updated_hash(block)) + 490 6 : return 0; 491 : 492 : /* 493 : * Get the parity position. @@ -590,7 +590,7 @@ 528 : * 529 : * If this happens, we read also the physical offset, to avoid to read it later. 530 : */ - 531 77410 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) + 531 77397 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) 532 : { 533 : #if HAVE_LSTAT_SYNC 534 : struct snapraid_state* state = scan->state; @@ -678,49 +678,49 @@ 616 : (void)st; 617 : (void)physical; 618 : #endif - 619 77410 : } + 619 77397 : } 620 : 621 : /** 622 : * Insert the file in the data set. 623 : */ - 624 100097 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) + 624 100084 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) 625 : { - 626 100097 : struct snapraid_disk* disk = scan->disk; + 626 100084 : struct snapraid_disk* disk = scan->disk; 627 : 628 : /* insert the file in the containers */ - 629 100097 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 630 100097 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 629 100084 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 630 100084 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 631 : - 632 100097 : stamp_lock(disk); - 633 100097 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 634 100097 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); - 635 100097 : stamp_unlock(disk); + 632 100084 : stamp_lock(disk); + 633 100084 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 634 100084 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 635 100084 : stamp_unlock(disk); 636 : 637 : /* delayed allocation of the parity */ - 638 100097 : scan_file_delayed_allocate(scan, file); - 639 100097 : } + 638 100084 : scan_file_delayed_allocate(scan, file); + 639 100084 : } 640 : 641 : /** 642 : * Remove the file from the data set. 643 : * 644 : * File is then deleted. 645 : */ - 646 55231 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) + 646 55218 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) 647 : { - 648 55231 : struct snapraid_disk* disk = scan->disk; + 648 55218 : struct snapraid_disk* disk = scan->disk; 649 : 650 : /* remove the file from the containers */ - 651 55231 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 652 55184 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); - 653 55231 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + 651 55218 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 652 55153 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 653 55218 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); 654 : - 655 55231 : stamp_lock(disk); - 656 55231 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); - 657 55231 : stamp_unlock(disk); + 655 55218 : stamp_lock(disk); + 656 55218 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); + 657 55218 : stamp_unlock(disk); 658 : 659 : /* deallocate the file from the parity */ - 660 55231 : scan_file_deallocate(scan, file); - 661 55231 : } + 660 55218 : scan_file_deallocate(scan, file); + 661 55218 : } 662 : 663 : /** 664 : * Keep the file as it's (or with only a name/inode modification). @@ -733,12 +733,12 @@ 671 : * This could happen after a failed sync, when some other files are deleted, 672 : * and then new ones can be moved backward to fill the hole created. 673 : */ - 674 1083709 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) + 674 1083722 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) 675 : { - 676 1083709 : struct snapraid_disk* disk = scan->disk; + 676 1083722 : struct snapraid_disk* disk = scan->disk; 677 : 678 : /* if the file is full invalid, schedule a reinsert at later stage */ - 679 1083709 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { + 679 1083722 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { 680 22687 : struct snapraid_file* copy = file_dup(file); 681 : 682 : /* remove the file */ @@ -747,7 +747,7 @@ 685 : /* reinsert the copy in the delayed list */ 686 22687 : scan_file_insert(scan, copy); 687 : } - 688 1083709 : } + 688 1083722 : } 689 : 690 : /** 691 : * Process a file. @@ -804,17 +804,17 @@ 742 : /* identify moved files with past inodes and hardlinks with the new inodes */ 743 1161329 : if (file) { 744 : /* check if the file is not changed */ - 745 1001529 : if (file->size == st->st_size - 746 990214 : && file->mtime_sec == st->st_mtime - 747 988959 : && (file->mtime_nsec == STAT_NSEC(st) + 745 1002136 : if (file->size == st->st_size + 746 990273 : && file->mtime_sec == st->st_mtime + 747 989015 : && (file->mtime_nsec == STAT_NSEC(st) 748 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 749 : /* it happens when upgrading from an old version of SnapRAID */ 750 : /* not yet supporting the nanosecond field */ - 751 8 : || file->mtime_nsec == STAT_NSEC_INVALID + 751 7 : || file->mtime_nsec == STAT_NSEC_INVALID 752 : ) 753 : ) { 754 : /* check if multiple files have the same inode */ - 755 988951 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 755 989008 : if (file_flag_has(file, FILE_IS_PRESENT)) { 756 : /* if has_volatile_hardlinks is true, the nlink value is not reliable */ 757 210 : if (!disk->has_volatile_hardlinks && st->st_nlink == 1) { 758 : /* LCOV_EXCL_START */ @@ -825,15 +825,15 @@ 763 : 764 : /* it's a hardlink */ 765 210 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK); - 766 1083919 : return; + 766 1083932 : return; 767 : } 768 : 769 : /* mark as present */ - 770 988741 : file_flag_set(file, FILE_IS_PRESENT); + 770 988798 : file_flag_set(file, FILE_IS_PRESENT); 771 : 772 : /* update the nanoseconds mtime only if different */ 773 : /* to avoid unneeded updates */ - 774 988741 : if (file->mtime_nsec == STAT_NSEC_INVALID + 774 988798 : if (file->mtime_nsec == STAT_NSEC_INVALID 775 0 : && STAT_NSEC(st) != file->mtime_nsec 776 : ) { 777 0 : file->mtime_nsec = STAT_NSEC(st); @@ -842,7 +842,7 @@ 780 0 : scan->need_write = 1; 781 : } 782 : - 783 988741 : if (strcmp(file->sub, sub) != 0) { + 783 988798 : if (strcmp(file->sub, sub) != 0) { 784 : /* if the path is different, it means a moved file with the same inode */ 785 155 : ++scan->count_move; 786 : @@ -864,18 +864,18 @@ 802 155 : scan->need_write = 1; 803 : } else { 804 : /* otherwise it's equal */ - 805 988586 : ++scan->count_equal; + 805 988643 : ++scan->count_equal; 806 : - 807 988586 : if (state->opt.gui_verbose) { + 807 988643 : if (state->opt.gui_verbose) { 808 0 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); 809 : } 810 : } 811 : 812 : /* mark the file as kept */ - 813 988741 : scan_file_keep(scan, file); + 813 988798 : scan_file_keep(scan, file); 814 : 815 : /* nothing more to do */ - 816 988741 : return; + 816 988798 : return; 817 : } 818 : 819 : /* @@ -897,7 +897,7 @@ 835 : * C:> dir 836 : * ...both time and size of A and B don't match! 837 : */ - 838 12578 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 838 13128 : if (file_flag_has(file, FILE_IS_PRESENT)) { 839 : /* if has_volatile_hardlinks is true, the nlink value is not reliable */ 840 0 : if (!disk->has_volatile_hardlinks && st->st_nlink == 1) { 841 : /* LCOV_EXCL_START */ @@ -923,44 +923,44 @@ 861 : /* otherwise, it will get removed */ 862 : 863 : /* remove from the inode set */ - 864 12578 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 864 13128 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 865 : 866 : /* clear the inode */ 867 : /* this is not really needed for correct functionality */ 868 : /* because we are going to set FILE_IS_WITHOUT_INODE */ 869 : /* but it's easier for debugging to have invalid inodes set to 0 */ - 870 12578 : file->inode = 0; + 870 13128 : file->inode = 0; 871 : 872 : /* mark as missing inode */ - 873 12578 : file_flag_set(file, FILE_IS_WITHOUT_INODE); + 873 13128 : file_flag_set(file, FILE_IS_WITHOUT_INODE); 874 : 875 : /* go further to find it by name */ 876 : } 877 : 878 : /* initialize for later overwrite */ - 879 172378 : is_file_reported = 0; - 880 172378 : is_original_file_size_different_than_zero = 0; + 879 172321 : is_file_reported = 0; + 880 172321 : is_original_file_size_different_than_zero = 0; 881 : 882 : /* then try finding it by name */ - 883 172378 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); + 883 172321 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); 884 : 885 : /* keep track if the file already exists */ - 886 172378 : is_file_already_present = file != 0; + 886 172321 : is_file_already_present = file != 0; 887 : - 888 172378 : if (is_file_already_present) { + 888 172321 : if (is_file_already_present) { 889 : /* if the file is without an inode */ - 890 97862 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { + 890 97805 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { 891 : /* set it now */ - 892 12545 : file->inode = st->st_ino; + 892 13077 : file->inode = st->st_ino; 893 : 894 : /* insert in the set */ - 895 12545 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 895 13077 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 896 : 897 : /* unmark as missing inode */ - 898 12545 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); + 898 13077 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); 899 : } else { 900 : /* here the inode has to be different, otherwise we would have found it before */ - 901 85317 : if (file->inode == st->st_ino) { + 901 84728 : if (file->inode == st->st_ino) { 902 : /* LCOV_EXCL_START */ 903 : log_fatal(EINTERNAL, "Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub); 904 : os_abort(); @@ -969,7 +969,7 @@ 907 : } 908 : 909 : /* for sure it cannot be already present */ - 910 97862 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 910 97805 : if (file_flag_has(file, FILE_IS_PRESENT)) { 911 : /* LCOV_EXCL_START */ 912 : log_fatal(EINTERNAL, "Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub); 913 : os_abort(); @@ -977,9 +977,9 @@ 915 : } 916 : 917 : /* check if the file is not changed */ - 918 97862 : if (file->size == st->st_size - 919 97266 : && file->mtime_sec == st->st_mtime - 920 94970 : && (file->mtime_nsec == STAT_NSEC(st) + 918 97805 : if (file->size == st->st_size + 919 97209 : && file->mtime_sec == st->st_mtime + 920 94926 : && (file->mtime_nsec == STAT_NSEC(st) 921 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 922 : /* it happens when upgrading from an old version of SnapRAID */ 923 : /* not yet supporting the nanosecond field */ @@ -987,11 +987,11 @@ 925 : ) 926 : ) { 927 : /* mark as present */ - 928 94968 : file_flag_set(file, FILE_IS_PRESENT); + 928 94924 : file_flag_set(file, FILE_IS_PRESENT); 929 : 930 : /* update the nano seconds mtime only if different */ 931 : /* to avoid unneeded updates */ - 932 94968 : if (file->mtime_nsec == STAT_NSEC_INVALID + 932 94924 : if (file->mtime_nsec == STAT_NSEC_INVALID 933 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID 934 : ) { 935 0 : file->mtime_nsec = STAT_NSEC(st); @@ -1001,30 +1001,30 @@ 939 : } 940 : 941 : /* if when processing the disk we used the past inodes values */ - 942 94968 : if (has_past_inodes) { + 942 94924 : if (has_past_inodes) { 943 : /* if persistent inodes are supported, we are sure that the inode number */ 944 : /* is now different, because otherwise the file would have been found */ 945 : /* when searching by inode. */ 946 : /* if the inode is different, it means a rewritten file with the same path */ 947 : /* like when restoring a backup that restores also the timestamp */ - 948 94954 : ++scan->count_restore; + 948 94910 : ++scan->count_restore; 949 : - 950 94954 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); - 951 94954 : if (is_diff) { + 950 94910 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); + 951 94910 : if (is_diff) { 952 0 : msg_info("restore %s\n", fmt_term(disk, sub, esc_buffer)); 953 : } 954 : 955 : /* remove from the inode set */ - 956 94954 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 956 94910 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 957 : 958 : /* save the new inode */ - 959 94954 : file->inode = st->st_ino; + 959 94910 : file->inode = st->st_ino; 960 : 961 : /* reinsert in the inode set */ - 962 94954 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 962 94910 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 963 : 964 : /* we have to save the new inode */ - 965 94954 : scan->need_write = 1; + 965 94910 : scan->need_write = 1; 966 : } else { 967 : /* otherwise it's the case of not persistent inode, where doesn't */ 968 : /* matter if the inode is different or equal, because they have no */ @@ -1037,24 +1037,24 @@ 975 : } 976 : 977 : /* mark the file as kept */ - 978 94968 : scan_file_keep(scan, file); + 978 94924 : scan_file_keep(scan, file); 979 : 980 : /* nothing more to do */ - 981 94968 : return; + 981 94924 : return; 982 : } 983 : 984 : /* here if the file is changed but with the correct name */ 985 : 986 : /* save the info for later printout */ - 987 2894 : file_already_present_size = file->size; - 988 2894 : file_already_present_mtime_sec = file->mtime_sec; - 989 2894 : file_already_present_mtime_nsec = file->mtime_nsec; + 987 2881 : file_already_present_size = file->size; + 988 2881 : file_already_present_mtime_sec = file->mtime_sec; + 989 2881 : file_already_present_mtime_nsec = file->mtime_nsec; 990 : 991 : /* keep track if the original file was not of zero size */ - 992 2894 : is_original_file_size_different_than_zero = file->size != 0; + 992 2881 : is_original_file_size_different_than_zero = file->size != 0; 993 : 994 : /* remove it, and continue to insert it again */ - 995 2894 : scan_file_remove(scan, file); + 995 2881 : scan_file_remove(scan, file); 996 : 997 : /* and continue to insert it again */ 998 : } else { @@ -1066,13 +1066,13 @@ 1004 : /* refresh the info, to ensure that they are synced, */ 1005 : /* note that we refresh only the info of the new or modified files */ 1006 : /* because this is slow operation */ - 1007 77410 : scan_file_refresh(scan, sub, st, &physical); + 1007 77397 : scan_file_refresh(scan, sub, st, &physical); 1008 : 1009 : #ifndef _WIN32 1010 : /* do a safety check to ensure that the common ext4 case of zeroing */ 1011 : /* the size of a file after a crash doesn't propagate to the backup */ 1012 : /* this check is specific for Linux, so we disable it on Windows */ - 1013 77410 : if (is_original_file_size_different_than_zero && st->st_size == 0) { + 1013 77397 : if (is_original_file_size_different_than_zero && st->st_size == 0) { 1014 0 : if (!state->opt.force_zero) { 1015 : /* LCOV_EXCL_START */ 1016 : log_fatal(ESOFT, "The file '%s%s' has unexpected zero size!\n", disk->dir, sub); @@ -1091,35 +1091,35 @@ 1029 : #endif 1030 : 1031 : /* insert it */ - 1032 77410 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); + 1032 77397 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); 1033 : 1034 : /* mark it as present */ - 1035 77410 : file_flag_set(file, FILE_IS_PRESENT); + 1035 77397 : file_flag_set(file, FILE_IS_PRESENT); 1036 : 1037 : /* if copy detection is enabled */ 1038 : /* note that the copy detection is tried also for updated files */ 1039 : /* this makes sense because it may happen to have two different copies */ 1040 : /* of the same file, and we move the right one over the wrong one */ 1041 : /* in such case we have a "copy" over an "update" */ - 1042 77410 : if (!state->opt.force_nocopy) { - 1043 77410 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 1042 77397 : if (!state->opt.force_nocopy) { + 1043 77397 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 1044 : 1045 : /* search for a file with the same name and stamp in all the disks */ - 1046 410916 : for (i = state->disklist; i != 0; i = i->next) { - 1047 357143 : struct snapraid_disk* other_disk = i->data; + 1046 410826 : for (i = state->disklist; i != 0; i = i->next) { + 1047 357066 : struct snapraid_disk* other_disk = i->data; 1048 : struct snapraid_file* other_file; 1049 : - 1050 357143 : stamp_lock(other_disk); + 1050 357066 : stamp_lock(other_disk); 1051 : /* if the nanosecond part of the time stamp is valid, search */ 1052 : /* for name and stamp, otherwise for path and stamp */ - 1053 357143 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) - 1054 357035 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); + 1053 357066 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) + 1054 356958 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); 1055 : else 1056 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); - 1057 357143 : stamp_unlock(other_disk); + 1057 357066 : stamp_unlock(other_disk); 1058 : 1059 : /* if found, and it's a fully hashed file */ - 1060 357143 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { + 1060 357066 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { 1061 : /* assume that the file is a copy, and reuse the hash */ 1062 23637 : file_copy(other_file, file); 1063 : @@ -1142,16 +1142,16 @@ 1080 : 1081 : /* if not yet reported, do it now */ 1082 : /* we postpone this to avoid to print two times the copied files */ - 1083 77410 : if (!is_file_reported) { - 1084 53773 : if (is_file_already_present) { - 1085 2894 : ++scan->count_change; + 1083 77397 : if (!is_file_reported) { + 1084 53760 : if (is_file_already_present) { + 1085 2881 : ++scan->count_change; 1086 : - 1087 2894 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer), + 1087 2881 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer), 1088 : file_already_present_size, file_already_present_mtime_sec, file_already_present_mtime_nsec, 1089 : file->size, file->mtime_sec, file->mtime_nsec 1090 : ); 1091 : - 1092 2894 : if (is_diff) { + 1092 2881 : if (is_diff) { 1093 118 : msg_info("update %s\n", fmt_term(disk, sub, esc_buffer)); 1094 : } 1095 : } else { @@ -1165,7 +1165,7 @@ 1103 : } 1104 : 1105 : /* insert the file in the delayed list */ - 1106 77410 : scan_file_insert(scan, file); + 1106 77397 : scan_file_insert(scan, file); 1107 : } 1108 : 1109 : /** @@ -1754,14 +1754,14 @@ 1692 : 1693 : /* check for removed files */ 1694 605 : node = disk->filelist; - 1695 1091277 : while (node) { - 1696 1090672 : struct snapraid_file* file = node->data; + 1695 1091290 : while (node) { + 1696 1090685 : struct snapraid_file* file = node->data; 1697 : 1698 : /* next node */ - 1699 1090672 : node = node->next; + 1699 1090685 : node = node->next; 1700 : 1701 : /* remove if not present */ - 1702 1090672 : if (!file_flag_has(file, FILE_IS_PRESENT)) { + 1702 1090685 : if (!file_flag_has(file, FILE_IS_PRESENT)) { 1703 29650 : ++scan->count_remove; 1704 : 1705 29650 : log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); @@ -1833,11 +1833,11 @@ 1771 605 : phy_dup = 0; 1772 605 : phy_last = FILEPHY_UNREAD_OFFSET; 1773 605 : phy_file_last = 0; - 1774 100702 : while (node) { - 1775 100097 : struct snapraid_file* file = node->data; + 1774 100689 : while (node) { + 1775 100084 : struct snapraid_file* file = node->data; 1776 : 1777 : /* if the file is not empty, count duplicate physical offsets */ - 1778 100097 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { + 1778 100084 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { 1779 11418 : if (phy_file_last != 0 && file->physical == phy_last 1780 : /* files without offset are expected to have duplicates */ 1781 0 : && phy_last != FILEPHY_WITHOUT_OFFSET @@ -1854,10 +1854,10 @@ 1792 : } 1793 : 1794 : /* next node */ - 1795 100097 : node = node->next; + 1795 100084 : node = node->next; 1796 : 1797 : /* insert in the parity */ - 1798 100097 : scan_file_allocate(scan, file); + 1798 100084 : scan_file_allocate(scan, file); 1799 : } 1800 : 1801 : /* 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 a3c92b38..2939451b 100644 --- a/cov/cmdline/scrub.c.func-sort-c.html +++ b/cov/cmdline/scrub.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 diff --git a/cov/cmdline/scrub.c.func.html b/cov/cmdline/scrub.c.func.html index c8189fcc..1ee8f66b 100644 --- a/cov/cmdline/scrub.c.func.html +++ b/cov/cmdline/scrub.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 diff --git a/cov/cmdline/scrub.c.gcov.html b/cov/cmdline/scrub.c.gcov.html index a93ec933..0d0e8b93 100644 --- a/cov/cmdline/scrub.c.gcov.html +++ b/cov/cmdline/scrub.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 @@ -131,12 +131,12 @@ 69 : 70 : /* bad blocks are always scrubbed in all plans */ 71 56085 : if (info_get_bad(info)) - 72 1771 : return 1; + 72 1772 : return 1; 73 : - 74 54314 : switch (plan->plan) { - 75 8523 : case SCRUB_FULL : + 74 54313 : switch (plan->plan) { + 75 8522 : case SCRUB_FULL : 76 : /* in 'full' plan everything is scrubbed */ - 77 8523 : return 1; + 77 8522 : return 1; 78 9215 : case SCRUB_EVEN : 79 : /* in 'even' plan, scrub only even blocks */ 80 9215 : return i % 2 == 0; @@ -206,9 +206,9 @@ 144 : /* if the file is different than the current one, close it */ 145 153017 : if (handle->file != 0 && handle->file != task->file) { 146 : /* keep a pointer at the file we are going to close for error reporting */ - 147 72541 : struct snapraid_file* report = handle->file; - 148 72541 : ret = handle_close(handle); - 149 72541 : if (ret == -1) { + 147 72572 : struct snapraid_file* report = handle->file; + 148 72572 : ret = handle_close(handle); + 149 72572 : if (ret == -1) { 150 : /* LCOV_EXCL_START */ 151 : /* This one is really an unexpected error, because we are only reading */ 152 : /* and closing a descriptor should never fail */ @@ -907,9 +907,9 @@ 845 : } 846 : 847 11 : count = 0; - 848 29 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { - 849 18 : struct snapraid_bucket* bucket = j->data; - 850 18 : count += bucket->count_scrubbed + bucket->count_justsynced; + 848 27 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { + 849 16 : struct snapraid_bucket* bucket = j->data; + 850 16 : count += bucket->count_scrubbed + bucket->count_justsynced; 851 : } 852 : 853 11 : if (!count) { diff --git a/cov/cmdline/search.c.func-sort-c.html b/cov/cmdline/search.c.func-sort-c.html index 5972d4f2..8710bd57 100644 --- a/cov/cmdline/search.c.func-sort-c.html +++ b/cov/cmdline/search.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 90 + 91 99 - 90.9 % + 91.9 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -73,19 +73,19 @@ search_file_compare - 20005 + 20083 state_search_fetch - 638750 + 639007 search_file - 1843797 + 1843854 search_file_free - 1843797 + 1843854
diff --git a/cov/cmdline/search.c.func.html b/cov/cmdline/search.c.func.html index 32bfdb02..3dd332ef 100644 --- a/cov/cmdline/search.c.func.html +++ b/cov/cmdline/search.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 90 + 91 99 - 90.9 % + 91.9 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -65,15 +65,15 @@ search_file - 1843797 + 1843854 search_file_compare - 20005 + 20083 search_file_free - 1843797 + 1843854 state_search @@ -85,7 +85,7 @@ state_search_fetch - 638750 + 639007
diff --git a/cov/cmdline/search.c.gcov.html b/cov/cmdline/search.c.gcov.html index 1a782acd..5218e3d8 100644 --- a/cov/cmdline/search.c.gcov.html +++ b/cov/cmdline/search.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 90 + 91 99 - 90.9 % + 91.9 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -85,27 +85,27 @@ 23 : /****************************************************************************/ 24 : /* search */ 25 : - 26 1843797 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) + 26 1843854 : 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 1843797 : file = malloc_nofail(sizeof(struct snapraid_search_file)); - 32 1843797 : file->path = strdup_nofail(path); - 33 1843797 : file->size = size; - 34 1843797 : file->mtime_sec = mtime_sec; - 35 1843797 : file->mtime_nsec = mtime_nsec; + 31 1843854 : file = malloc_nofail(sizeof(struct snapraid_search_file)); + 32 1843854 : file->path = strdup_nofail(path); + 33 1843854 : file->size = size; + 34 1843854 : file->mtime_sec = mtime_sec; + 35 1843854 : file->mtime_nsec = mtime_nsec; 36 : - 37 1843797 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 37 1843854 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 38 : - 39 1843797 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); - 40 1843797 : } + 39 1843854 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); + 40 1843854 : } 41 : - 42 1843797 : void search_file_free(struct snapraid_search_file* file) + 42 1843854 : void search_file_free(struct snapraid_search_file* file) 43 : { - 44 1843797 : free(file->path); - 45 1843797 : free(file); - 46 1843797 : } + 44 1843854 : free(file->path); + 45 1843854 : free(file); + 46 1843854 : } 47 : 48 : struct search_file_compare_arg { 49 : const struct snapraid_state* state; @@ -117,29 +117,29 @@ 55 : int prevhash; 56 : }; 57 : - 58 20005 : int search_file_compare(const void* void_arg, const void* void_data) + 58 20083 : int search_file_compare(const void* void_arg, const void* void_data) 59 : { - 60 20005 : const struct search_file_compare_arg* arg = void_arg; - 61 20005 : const struct snapraid_search_file* file = void_data; - 62 20005 : const struct snapraid_state* state = arg->state; + 60 20083 : const struct search_file_compare_arg* arg = void_arg; + 61 20083 : const struct snapraid_search_file* file = void_data; + 62 20083 : const struct snapraid_state* state = arg->state; 63 : unsigned char buffer_hash[HASH_MAX]; - 64 20005 : const char* path = file->path; + 64 20083 : const char* path = file->path; 65 : int f; 66 : ssize_t ret; 67 : 68 : /* compare file info */ - 69 20005 : if (arg->file->size != file->size) - 70 0 : return -1; + 69 20083 : if (arg->file->size != file->size) + 70 20 : return -1; 71 : - 72 20005 : if (arg->file->mtime_sec != file->mtime_sec) + 72 20063 : if (arg->file->mtime_sec != file->mtime_sec) 73 0 : return -1; 74 : - 75 20005 : if (arg->file->mtime_nsec != file->mtime_nsec) + 75 20063 : if (arg->file->mtime_nsec != file->mtime_nsec) 76 0 : return -1; 77 : 78 : /* read the block and compare the hash */ - 79 20005 : f = open(path, O_RDONLY | O_BINARY); - 80 20005 : if (f == -1) { + 79 20063 : f = open(path, O_RDONLY | O_BINARY); + 80 20063 : if (f == -1) { 81 : /* LCOV_EXCL_START */ 82 : if (errno == ENOENT) { 83 : log_fatal(EUSER, "DANGER! file '%s' disappeared.\n", path); @@ -151,16 +151,16 @@ 89 : /* LCOV_EXCL_STOP */ 90 : } 91 : - 92 20005 : ret = pread(f, arg->buffer, arg->read_size, arg->offset); - 93 20005 : if (ret < 0 || (unsigned)ret != arg->read_size) { + 92 20063 : ret = pread(f, arg->buffer, arg->read_size, arg->offset); + 93 20063 : if (ret < 0 || (unsigned)ret != arg->read_size) { 94 : /* LCOV_EXCL_START */ 95 : log_fatal(errno, "Error reading file '%s'. %s.\n", path, strerror(errno)); 96 : exit(EXIT_FAILURE); 97 : /* LCOV_EXCL_STOP */ 98 : } 99 : - 100 20005 : ret = close(f); - 101 20005 : if (ret != 0) { + 100 20063 : ret = close(f); + 101 20063 : if (ret != 0) { 102 : /* LCOV_EXCL_START */ 103 : log_fatal(errno, "Error closing file '%s'. %s.\n", path, strerror(errno)); 104 : exit(EXIT_FAILURE); @@ -168,14 +168,14 @@ 106 : } 107 : 108 : /* compute the hash */ - 109 20005 : if (arg->prevhash) + 109 20063 : if (arg->prevhash) 110 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size); 111 : else - 112 20005 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); + 112 20063 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); 113 : 114 : /* check if the hash is matching */ - 115 20005 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0) - 116 2095 : return -1; + 115 20063 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0) + 116 2153 : 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 638750 : 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 639007 : 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 638750 : arg.state = state; - 133 638750 : arg.block = missing_block; - 134 638750 : arg.file = missing_file; - 135 638750 : arg.buffer = buffer; - 136 638750 : arg.offset = state->block_size * (data_off_t)missing_file_pos; - 137 638750 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); - 138 638750 : arg.prevhash = prevhash; + 132 639007 : arg.state = state; + 133 639007 : arg.block = missing_block; + 134 639007 : arg.file = missing_file; + 135 639007 : arg.buffer = buffer; + 136 639007 : arg.offset = state->block_size * (data_off_t)missing_file_pos; + 137 639007 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); + 138 639007 : arg.prevhash = prevhash; 139 : - 140 638750 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); + 140 639007 : 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 638750 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); - 144 638750 : if (!file) - 145 620840 : return -1; + 143 639007 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); + 144 639007 : if (!file) + 145 621097 : return -1; 146 : 147 : /* if found, buffer is already set with data */ 148 17910 : return 0; @@ -222,44 +222,44 @@ 160 : /* LCOV_EXCL_STOP */ 161 : } 162 : - 163 2037708 : while (1) { + 163 2037834 : while (1) { 164 : char path_next[PATH_MAX]; 165 : char sub_next[PATH_MAX]; 166 : char out[PATH_MAX]; - 167 2040170 : struct snapraid_filter* reason = 0; + 167 2040296 : 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 2040170 : errno = 0; - 174 2040170 : dd = readdir(d); - 175 2040170 : if (dd == 0 && errno != 0) { + 173 2040296 : errno = 0; + 174 2040296 : dd = readdir(d); + 175 2040296 : if (dd == 0 && errno != 0) { 176 : /* LCOV_EXCL_START */ 177 : log_fatal(errno, "Error reading directory '%s'. %s.\n", dir, strerror(errno)); 178 : exit(EXIT_FAILURE); 179 : /* LCOV_EXCL_STOP */ 180 : } - 181 2040170 : if (dd == 0) { + 181 2040296 : if (dd == 0) { 182 2462 : break; /* finished */ 183 : } 184 : 185 : /* skip "." and ".." files */ - 186 2037708 : name = dd->d_name; - 187 2037708 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 186 2037834 : name = dd->d_name; + 187 2037834 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 188 4924 : continue; 189 : - 190 2032784 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 191 2032784 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + 190 2032910 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 191 2032910 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); 192 : 193 : /* exclude hidden files even before calling lstat() */ - 194 2032784 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { + 194 2032910 : 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 2032784 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { + 200 2032910 : 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 2032784 : if (lstat(path_next, &st) != 0) { + 224 2032910 : if (lstat(path_next, &st) != 0) { 225 : /* LCOV_EXCL_START */ 226 : log_fatal(errno, "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 2032784 : if (S_ISREG(st.st_mode)) { - 233 1968474 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { - 234 1843797 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); + 232 2032910 : if (S_ISREG(st.st_mode)) { + 233 1968609 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 234 1843854 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); 235 : } else { - 236 124677 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 236 124755 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 237 : } - 238 64310 : } else if (S_ISDIR(st.st_mode)) { + 238 64301 : } 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)); diff --git a/cov/cmdline/selftest.c.func-sort-c.html b/cov/cmdline/selftest.c.func-sort-c.html index d693c961..5b445e68 100644 --- a/cov/cmdline/selftest.c.func-sort-c.html +++ b/cov/cmdline/selftest.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 diff --git a/cov/cmdline/selftest.c.func.html b/cov/cmdline/selftest.c.func.html index 4fdb12a7..0a61b811 100644 --- a/cov/cmdline/selftest.c.func.html +++ b/cov/cmdline/selftest.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 diff --git a/cov/cmdline/selftest.c.gcov.html b/cov/cmdline/selftest.c.gcov.html index 6939bd88..987dc1e0 100644 --- a/cov/cmdline/selftest.c.gcov.html +++ b/cov/cmdline/selftest.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 diff --git a/cov/cmdline/snapraid.c.func-sort-c.html b/cov/cmdline/snapraid.c.func-sort-c.html index 6321b0f0..4ee91916 100644 --- a/cov/cmdline/snapraid.c.func-sort-c.html +++ b/cov/cmdline/snapraid.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -81,23 +81,23 @@ log_close - 267 + 268 log_open - 278 + 279 config - 287 + 288 snapraid_main - 288 + 289 test - 288 + 289
diff --git a/cov/cmdline/snapraid.c.func.html b/cov/cmdline/snapraid.c.func.html index e2c2747d..18d601dc 100644 --- a/cov/cmdline/snapraid.c.func.html +++ b/cov/cmdline/snapraid.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -61,15 +61,15 @@ config - 287 + 288 log_close - 267 + 268 log_open - 278 + 279 memory @@ -85,11 +85,11 @@ snapraid_main - 288 + 289 test - 288 + 289 usage diff --git a/cov/cmdline/snapraid.c.gcov.html b/cov/cmdline/snapraid.c.gcov.html index ab932c2d..30882961 100644 --- a/cov/cmdline/snapraid.c.gcov.html +++ b/cov/cmdline/snapraid.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -158,14 +158,14 @@ 96 244 : msg_progress("Using %u MiB of memory for the file-system.\n", (unsigned)(malloc_counter_get() / MEBI)); 97 244 : } 98 : - 99 288 : void test(int argc, char* argv[]) + 99 289 : void test(int argc, char* argv[]) 100 : { 101 : int i; 102 : char buffer[ESC_MAX]; 103 : 104 : /* special testing code for quoting */ - 105 288 : if (argc < 2 || strcmp(argv[1], "test") != 0) - 106 287 : return; + 105 289 : if (argc < 2 || strcmp(argv[1], "test") != 0) + 106 288 : return; 107 : 108 1 : assert(strcmp(strpolish(strcpy(buffer, "\r \n\xFF")), " ") == 0); 109 1 : assert(strcmp(strtrim(strcpy(buffer, " trim trim \n\r")), "trim trim") == 0); @@ -556,7 +556,7 @@ 494 : /****************************************************************************/ 495 : /* log */ 496 : - 497 278 : void log_open(const char* file) + 497 279 : void log_open(const char* file) 498 : { 499 : char path[PATH_MAX]; 500 : const char* mode; @@ -569,8 +569,8 @@ 507 : #endif 508 : 509 : /* leave stdlog at 0 if not specified */ - 510 278 : if (file == 0) - 511 204 : return; + 510 279 : if (file == 0) + 511 205 : return; 512 : 513 80 : t = time(0); 514 : #if HAVE_LOCALTIME_R @@ -647,9 +647,9 @@ 585 : } 586 : } 587 : - 588 267 : void log_close(const char* file) + 588 268 : void log_close(const char* file) 589 : { - 590 267 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) { + 590 268 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) { 591 74 : if (fclose(stdlog) != 0) { 592 : /* LCOV_EXCL_START */ 593 : log_fatal(errno, "Error closing the log file '%s'. %s.\n", file, strerror(errno)); @@ -658,13 +658,13 @@ 596 : } 597 : } 598 : - 599 267 : stdlog = 0; - 600 267 : } + 599 268 : stdlog = 0; + 600 268 : } 601 : 602 : /****************************************************************************/ 603 : /* config */ 604 : - 605 287 : void config(char* conf, size_t conf_size, const char* argv0) + 605 288 : void config(char* conf, size_t conf_size, const char* argv0) 606 : { 607 : #ifdef _WIN32 608 : char* slash; @@ -683,15 +683,15 @@ 621 : 622 : #ifdef SYSCONFDIR 623 : /* if it exists, give precedence at sysconfdir, usually /usr/local/etc */ - 624 287 : if (access(SYSCONFDIR "/" PACKAGE ".conf", F_OK) == 0) { + 624 288 : if (access(SYSCONFDIR "/" PACKAGE ".conf", F_OK) == 0) { 625 0 : pathcpy(conf, conf_size, SYSCONFDIR "/" PACKAGE ".conf"); 626 : } else /* otherwise fallback to plain /etc */ 627 : #endif 628 : { - 629 287 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf"); + 629 288 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf"); 630 : } 631 : #endif - 632 287 : } + 632 288 : } 633 : 634 : /****************************************************************************/ 635 : /* main */ @@ -1029,7 +1029,7 @@ 967 : #define OPERATION_PROBE 18 968 : #define OPERATION_LOCATE 19 969 : - 970 288 : int snapraid_main(int argc, char* argv[]) + 970 289 : int snapraid_main(int argc, char* argv[]) 971 : { 972 : int c; 973 : struct snapraid_option opt; @@ -1064,41 +1064,41 @@ 1002 : #endif 1003 : int i; 1004 : - 1005 288 : test(argc, argv); + 1005 289 : test(argc, argv); 1006 : - 1007 287 : lock_init(); + 1007 288 : lock_init(); 1008 : 1009 : /* defaults */ - 1010 287 : config(conf, sizeof(conf), argv[0]); - 1011 287 : memset(&opt, 0, sizeof(opt)); - 1012 287 : opt.io_error_limit = 100; - 1013 287 : blockstart = 0; - 1014 287 : blockcount = 0; - 1015 287 : tommy_list_init(&filterlist_file); - 1016 287 : tommy_list_init(&filterlist_disk); - 1017 287 : speed_test_period = -1; - 1018 287 : speed_test_blocks_size = -1; - 1019 287 : speed_test_disks_number = -1; - 1020 287 : filter_missing = 0; - 1021 287 : filter_error = 0; - 1022 287 : plan100 = SCRUB_AUTO; - 1023 287 : olderthan = SCRUB_AUTO; - 1024 287 : import_timestamp = 0; - 1025 287 : import_content = 0; - 1026 287 : log_file = 0; - 1027 287 : lock = 0; - 1028 287 : gen_conf = 0; - 1029 287 : speedtest = 0; - 1030 287 : run = 0; + 1010 288 : config(conf, sizeof(conf), argv[0]); + 1011 288 : memset(&opt, 0, sizeof(opt)); + 1012 288 : opt.io_error_limit = 100; + 1013 288 : blockstart = 0; + 1014 288 : blockcount = 0; + 1015 288 : tommy_list_init(&filterlist_file); + 1016 288 : tommy_list_init(&filterlist_disk); + 1017 288 : speed_test_period = -1; + 1018 288 : speed_test_blocks_size = -1; + 1019 288 : speed_test_disks_number = -1; + 1020 288 : filter_missing = 0; + 1021 288 : filter_error = 0; + 1022 288 : plan100 = SCRUB_AUTO; + 1023 288 : olderthan = SCRUB_AUTO; + 1024 288 : import_timestamp = 0; + 1025 288 : import_content = 0; + 1026 288 : log_file = 0; + 1027 288 : lock = 0; + 1028 288 : gen_conf = 0; + 1029 288 : speedtest = 0; + 1030 288 : run = 0; 1031 : - 1032 287 : opterr = 0; - 1033 287 : while ((c = + 1032 288 : opterr = 0; + 1033 288 : while ((c = 1034 : #if HAVE_GETOPT_LONG - 1035 3607 : getopt_long(argc, argv, OPTIONS, long_options, 0)) + 1035 3608 : getopt_long(argc, argv, OPTIONS, long_options, 0)) 1036 : #else 1037 : getopt(argc, argv, OPTIONS)) 1038 : #endif - 1039 3607 : != EOF) { + 1039 3608 : != EOF) { 1040 3324 : switch (c) { 1041 280 : case 'c' : 1042 280 : pathimport(conf, sizeof(conf), optarg); @@ -1510,69 +1510,69 @@ 1448 : } 1449 : } 1450 : - 1451 283 : os_init(opt.force_scan_winfind); - 1452 283 : raid_init(); - 1453 283 : crc32c_init(); - 1454 283 : random_reseed(); + 1451 284 : os_init(opt.force_scan_winfind); + 1452 284 : raid_init(); + 1453 284 : crc32c_init(); + 1454 284 : random_reseed(); 1455 : - 1456 283 : if (speedtest != 0) { + 1456 284 : if (speedtest != 0) { 1457 4 : speed(speed_test_period, speed_test_disks_number, speed_test_blocks_size); 1458 4 : os_done(); 1459 4 : exit(EXIT_SUCCESS); 1460 : } 1461 : - 1462 279 : if (gen_conf != 0) { + 1462 280 : if (gen_conf != 0) { 1463 1 : generate_configuration(gen_conf); 1464 1 : os_done(); 1465 1 : exit(EXIT_SUCCESS); 1466 : } 1467 : - 1468 278 : if (optind + 1 != argc) { + 1468 279 : if (optind + 1 != argc) { 1469 : /* LCOV_EXCL_START */ 1470 : usage(conf); 1471 : exit(EXIT_FAILURE); 1472 : /* LCOV_EXCL_STOP */ 1473 : } 1474 : - 1475 278 : command = argv[optind]; - 1476 278 : if (strcmp(command, "diff") == 0) { + 1475 279 : command = argv[optind]; + 1476 279 : if (strcmp(command, "diff") == 0) { 1477 8 : operation = OPERATION_DIFF; - 1478 270 : } else if (strcmp(argv[optind], "sync") == 0) { + 1478 271 : } else if (strcmp(argv[optind], "sync") == 0) { 1479 94 : operation = OPERATION_SYNC; - 1480 176 : } else if (strcmp(argv[optind], "check") == 0) { + 1480 177 : } else if (strcmp(argv[optind], "check") == 0) { 1481 75 : operation = OPERATION_CHECK; - 1482 101 : } else if (strcmp(argv[optind], "fix") == 0) { + 1482 102 : } else if (strcmp(argv[optind], "fix") == 0) { 1483 46 : operation = OPERATION_FIX; - 1484 55 : } else if (strcmp(argv[optind], "test-dry") == 0) { + 1484 56 : } else if (strcmp(argv[optind], "test-dry") == 0) { 1485 3 : operation = OPERATION_DRY; - 1486 52 : } else if (strcmp(argv[optind], "dup") == 0) { + 1486 53 : } else if (strcmp(argv[optind], "dup") == 0) { 1487 3 : operation = OPERATION_DUP; - 1488 49 : } else if (strcmp(argv[optind], "list") == 0) { + 1488 50 : } else if (strcmp(argv[optind], "list") == 0) { 1489 5 : operation = OPERATION_LIST; - 1490 44 : } else if (strcmp(argv[optind], "pool") == 0) { + 1490 45 : } else if (strcmp(argv[optind], "pool") == 0) { 1491 3 : operation = OPERATION_POOL; - 1492 41 : } else if (strcmp(argv[optind], "rehash") == 0) { + 1492 42 : } else if (strcmp(argv[optind], "rehash") == 0) { 1493 1 : operation = OPERATION_REHASH; - 1494 40 : } else if (strcmp(argv[optind], "scrub") == 0) { + 1494 41 : } else if (strcmp(argv[optind], "scrub") == 0) { 1495 11 : operation = OPERATION_SCRUB; - 1496 29 : } else if (strcmp(argv[optind], "status") == 0) { + 1496 30 : } else if (strcmp(argv[optind], "status") == 0) { 1497 15 : operation = OPERATION_STATUS; - 1498 14 : } else if (strcmp(argv[optind], "test-rewrite") == 0) { + 1498 15 : } else if (strcmp(argv[optind], "test-rewrite") == 0) { 1499 1 : operation = OPERATION_REWRITE; - 1500 13 : } else if (strcmp(argv[optind], "read") == 0) { + 1500 14 : } else if (strcmp(argv[optind], "read") == 0) { 1501 1 : operation = OPERATION_READ; - 1502 12 : } else if (strcmp(argv[optind], "touch") == 0) { + 1502 13 : } else if (strcmp(argv[optind], "touch") == 0) { 1503 1 : operation = OPERATION_TOUCH; - 1504 11 : } else if (strcmp(argv[optind], "up") == 0) { + 1504 12 : } else if (strcmp(argv[optind], "up") == 0) { 1505 1 : operation = OPERATION_SPINUP; - 1506 10 : } else if (strcmp(argv[optind], "down") == 0) { + 1506 11 : } else if (strcmp(argv[optind], "down") == 0) { 1507 1 : operation = OPERATION_SPINDOWN; - 1508 9 : } else if (strcmp(argv[optind], "devices") == 0) { + 1508 10 : } else if (strcmp(argv[optind], "devices") == 0) { 1509 1 : operation = OPERATION_DEVICES; - 1510 8 : } else if (strcmp(argv[optind], "smart") == 0) { + 1510 9 : } else if (strcmp(argv[optind], "smart") == 0) { 1511 1 : operation = OPERATION_SMART; - 1512 7 : } else if (strcmp(argv[optind], "probe") == 0) { - 1513 2 : operation = OPERATION_PROBE; + 1512 8 : } else if (strcmp(argv[optind], "probe") == 0) { + 1513 3 : operation = OPERATION_PROBE; 1514 5 : } else if (strcmp(argv[optind], "locate") == 0) { 1515 5 : operation = OPERATION_LOCATE; 1516 : } else { @@ -1583,11 +1583,11 @@ 1521 : } 1522 : 1523 : /* check options compatibility */ - 1524 278 : switch (operation) { + 1524 279 : switch (operation) { 1525 75 : case OPERATION_CHECK : 1526 75 : break; - 1527 203 : default : - 1528 203 : if (opt.auditonly) { + 1527 204 : default : + 1528 204 : if (opt.auditonly) { 1529 : /* LCOV_EXCL_START */ 1530 : log_fatal(EUSER, "You cannot use -a, --audit-only with the '%s' command\n", command); 1531 : exit(EXIT_FAILURE); @@ -1595,15 +1595,15 @@ 1533 : } 1534 : } 1535 : - 1536 278 : switch (operation) { - 1537 127 : case OPERATION_FIX : + 1536 279 : switch (operation) { + 1537 128 : case OPERATION_FIX : 1538 : case OPERATION_CHECK : 1539 : case OPERATION_SMART : 1540 : case OPERATION_PROBE : 1541 : case OPERATION_DEVICES : 1542 : case OPERATION_SPINUP : 1543 : case OPERATION_SPINDOWN : - 1544 127 : break; + 1544 128 : break; 1545 151 : default : 1546 151 : if (opt.force_device) { 1547 : /* LCOV_EXCL_START */ @@ -1613,13 +1613,13 @@ 1551 : } 1552 : } 1553 : - 1554 278 : switch (operation) { + 1554 279 : switch (operation) { 1555 215 : case OPERATION_SYNC : 1556 : case OPERATION_CHECK : 1557 : case OPERATION_FIX : 1558 215 : break; - 1559 63 : default : - 1560 63 : if (opt.force_nocopy) { + 1559 64 : default : + 1560 64 : if (opt.force_nocopy) { 1561 : /* LCOV_EXCL_START */ 1562 : log_fatal(EUSER, "You cannot use -N, --force-nocopy with the '%s' command\n", command); 1563 : exit(EXIT_FAILURE); @@ -1627,25 +1627,25 @@ 1565 : } 1566 : } 1567 : - 1568 278 : switch (operation) { + 1568 279 : switch (operation) { 1569 94 : case OPERATION_SYNC : 1570 94 : break; - 1571 184 : default : - 1572 184 : if (opt.prehash) { + 1571 185 : default : + 1572 185 : if (opt.prehash) { 1573 : /* LCOV_EXCL_START */ 1574 : log_fatal(EUSER, "You cannot use -h, --pre-hash with the '%s' command\n", command); 1575 : exit(EXIT_FAILURE); 1576 : /* LCOV_EXCL_STOP */ 1577 : } 1578 : - 1579 184 : if (opt.force_full) { + 1579 185 : if (opt.force_full) { 1580 : /* LCOV_EXCL_START */ 1581 : log_fatal(EUSER, "You cannot use -F, --force-full with the '%s' command\n", command); 1582 : exit(EXIT_FAILURE); 1583 : /* LCOV_EXCL_STOP */ 1584 : } 1585 : - 1586 184 : if (opt.force_realloc) { + 1586 185 : if (opt.force_realloc) { 1587 : /* LCOV_EXCL_START */ 1588 : log_fatal(EUSER, "You cannot use -R, --force-realloc with the '%s' command\n", command); 1589 : exit(EXIT_FAILURE); @@ -1653,41 +1653,41 @@ 1591 : } 1592 : } 1593 : - 1594 278 : if (opt.force_full && opt.force_nocopy) { + 1594 279 : if (opt.force_full && opt.force_nocopy) { 1595 : /* LCOV_EXCL_START */ 1596 : log_fatal(EUSER, "You cannot use the -F, --force-full and -N, --force-nocopy options simultaneously\n"); 1597 : exit(EXIT_FAILURE); 1598 : /* LCOV_EXCL_STOP */ 1599 : } 1600 : - 1601 278 : if (opt.force_realloc && opt.force_nocopy) { + 1601 279 : if (opt.force_realloc && opt.force_nocopy) { 1602 : /* LCOV_EXCL_START */ 1603 : log_fatal(EUSER, "You cannot use the -R, --force-realloc and -N, --force-nocopy options simultaneously\n"); 1604 : exit(EXIT_FAILURE); 1605 : /* LCOV_EXCL_STOP */ 1606 : } 1607 : - 1608 278 : if (opt.force_realloc && opt.force_full) { + 1608 279 : if (opt.force_realloc && opt.force_full) { 1609 : /* LCOV_EXCL_START */ 1610 : log_fatal(EUSER, "You cannot use the -R, --force-realloc and -F, --force-full options simultaneously\n"); 1611 : exit(EXIT_FAILURE); 1612 : /* LCOV_EXCL_STOP */ 1613 : } 1614 : - 1615 278 : if (opt.prehash && opt.force_nocopy) { + 1615 279 : if (opt.prehash && opt.force_nocopy) { 1616 : /* LCOV_EXCL_START */ 1617 : log_fatal(EUSER, "You cannot use the -h, --pre-hash and -N, --force-nocopy options simultaneously\n"); 1618 : exit(EXIT_FAILURE); 1619 : /* LCOV_EXCL_STOP */ 1620 : } 1621 : - 1622 278 : switch (operation) { + 1622 279 : switch (operation) { 1623 124 : case OPERATION_CHECK : 1624 : case OPERATION_FIX : 1625 : case OPERATION_DRY : 1626 124 : break; - 1627 152 : default : - 1628 152 : if (!tommy_list_empty(&filterlist_disk)) { + 1627 153 : default : + 1628 153 : if (!tommy_list_empty(&filterlist_disk)) { 1629 : /* LCOV_EXCL_START */ 1630 : log_fatal(EUSER, "You cannot use -d, --filter-disk with the '%s' command\n", command); 1631 : exit(EXIT_FAILURE); @@ -1696,19 +1696,19 @@ 1634 : /* fallthrough */ 1635 : case OPERATION_SPINUP : 1636 : case OPERATION_SPINDOWN : - 1637 154 : if (!tommy_list_empty(&filterlist_file)) { + 1637 155 : if (!tommy_list_empty(&filterlist_file)) { 1638 : /* LCOV_EXCL_START */ 1639 : log_fatal(EUSER, "You cannot use -f, --filter with the '%s' command\n", command); 1640 : exit(EXIT_FAILURE); 1641 : /* LCOV_EXCL_STOP */ 1642 : } - 1643 154 : if (filter_missing != 0) { + 1643 155 : if (filter_missing != 0) { 1644 : /* LCOV_EXCL_START */ 1645 : log_fatal(EUSER, "You cannot use -m, --filter-missing with the '%s' command\n", command); 1646 : exit(EXIT_FAILURE); 1647 : /* LCOV_EXCL_STOP */ 1648 : } - 1649 154 : if (filter_error != 0) { + 1649 155 : if (filter_error != 0) { 1650 : /* LCOV_EXCL_START */ 1651 : log_fatal(EUSER, "You cannot use -e, --filter-error with the '%s' command\n", command); 1652 : exit(EXIT_FAILURE); @@ -1718,19 +1718,19 @@ 1656 : 1657 : /* errors must be always fixed on all disks */ 1658 : /* because we don't keep the information on what disk is the error */ - 1659 278 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) { + 1659 279 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) { 1660 : /* LCOV_EXCL_START */ 1661 : log_fatal(EUSER, "You cannot use -e, --filter-error and -d, --filter-disk simultaneously\n"); 1662 : exit(EXIT_FAILURE); 1663 : /* LCOV_EXCL_STOP */ 1664 : } 1665 : - 1666 278 : switch (operation) { + 1666 279 : switch (operation) { 1667 121 : case OPERATION_CHECK : 1668 : case OPERATION_FIX : 1669 121 : break; - 1670 157 : default : - 1671 157 : if (import_timestamp != 0 || import_content != 0) { + 1670 158 : default : + 1671 158 : if (import_timestamp != 0 || import_content != 0) { 1672 : /* LCOV_EXCL_START */ 1673 : log_fatal(EUSER, "Import not allowed with the '%s' command\n", command); 1674 : exit(EXIT_FAILURE); @@ -1738,7 +1738,7 @@ 1676 : } 1677 : } 1678 : - 1679 278 : switch (operation) { + 1679 279 : switch (operation) { 1680 26 : case OPERATION_LIST : 1681 : case OPERATION_DUP : 1682 : case OPERATION_STATUS : @@ -1750,7 +1750,7 @@ 1688 26 : break; 1689 : } 1690 : - 1691 278 : switch (operation) { + 1691 279 : switch (operation) { 1692 38 : case OPERATION_DIFF : 1693 : case OPERATION_LIST : 1694 : case OPERATION_DUP : @@ -1765,7 +1765,7 @@ 1703 38 : break; 1704 : } 1705 : - 1706 278 : switch (operation) { + 1706 279 : switch (operation) { 1707 121 : case OPERATION_FIX : 1708 : case OPERATION_CHECK : 1709 : /* avoid to stop processing if a content file is not accessible */ @@ -1773,8 +1773,8 @@ 1711 121 : break; 1712 : } 1713 : - 1714 278 : switch (operation) { - 1715 26 : case OPERATION_DIFF : + 1714 279 : switch (operation) { + 1715 27 : case OPERATION_DIFF : 1716 : case OPERATION_LIST : 1717 : case OPERATION_DUP : 1718 : case OPERATION_POOL : @@ -1784,77 +1784,77 @@ 1722 : case OPERATION_DEVICES : 1723 : case OPERATION_SMART : 1724 : case OPERATION_PROBE : - 1725 26 : opt.skip_self = 1; - 1726 26 : break; + 1725 27 : opt.skip_self = 1; + 1726 27 : break; 1727 : } 1728 : - 1729 278 : switch (operation) { + 1729 279 : switch (operation) { 1730 : #if HAVE_DIRECT_IO 1731 108 : case OPERATION_SYNC : 1732 : case OPERATION_SCRUB : 1733 : case OPERATION_DRY : 1734 108 : break; 1735 : #endif - 1736 170 : default : + 1736 171 : default : 1737 : /* we allow direct IO only on some commands */ - 1738 170 : if (opt.file_mode == ADVISE_DIRECT) + 1738 171 : if (opt.file_mode == ADVISE_DIRECT) 1739 0 : opt.file_mode = ADVISE_SEQUENTIAL; - 1740 170 : break; + 1740 171 : break; 1741 : } 1742 : - 1743 278 : switch (operation) { - 1744 4 : case OPERATION_DEVICES : + 1743 279 : switch (operation) { + 1744 5 : case OPERATION_DEVICES : 1745 : case OPERATION_SMART : 1746 : case OPERATION_PROBE : 1747 : /* we may need to use these commands during operations */ - 1748 4 : opt.skip_lock = 1; - 1749 4 : break; + 1748 5 : opt.skip_lock = 1; + 1749 5 : break; 1750 : } 1751 : - 1752 278 : switch (operation) { - 1753 3 : case OPERATION_SMART : + 1752 279 : switch (operation) { + 1753 4 : case OPERATION_SMART : 1754 : case OPERATION_PROBE : 1755 : /* allow to run without configuration file */ - 1756 3 : opt.auto_conf = 1; - 1757 3 : break; + 1756 4 : opt.auto_conf = 1; + 1757 4 : break; 1758 : } 1759 : 1760 : /* open the log file */ - 1761 278 : log_open(log_file); + 1761 279 : log_open(log_file); 1762 : 1763 : /* print generic info into the log */ - 1764 278 : t = time(0); + 1764 279 : t = time(0); 1765 : #if HAVE_LOCALTIME_R - 1766 278 : tm = localtime_r(&t, &tm_res); + 1766 279 : tm = localtime_r(&t, &tm_res); 1767 : #else 1768 : tm = localtime(&t); 1769 : #endif - 1770 278 : log_tag("version:%s\n", PACKAGE_VERSION); - 1771 278 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t); - 1772 278 : if (tm) { + 1770 279 : log_tag("version:%s\n", PACKAGE_VERSION); + 1771 279 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t); + 1772 279 : if (tm) { 1773 : char datetime[64]; - 1774 278 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm); - 1775 278 : log_tag("time:%s\n", datetime); + 1774 279 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm); + 1775 279 : log_tag("time:%s\n", datetime); 1776 : } - 1777 278 : log_tag("command:%s\n", command); - 1778 4526 : for (i = 0; i < argc; ++i) - 1779 4248 : log_tag("argv:%u:%s\n", i, argv[i]); - 1780 278 : log_flush(); + 1777 279 : log_tag("command:%s\n", command); + 1778 4529 : for (i = 0; i < argc; ++i) + 1779 4250 : log_tag("argv:%u:%s\n", i, argv[i]); + 1780 279 : log_flush(); 1781 : - 1782 278 : if (!opt.skip_self) + 1782 279 : if (!opt.skip_self) 1783 1 : selftest(); 1784 : - 1785 278 : state_init(&state); + 1785 279 : state_init(&state); 1786 : 1787 : /* read the configuration file */ - 1788 278 : state_config(&state, conf, command, &opt, &filterlist_disk); + 1788 279 : state_config(&state, conf, command, &opt, &filterlist_disk); 1789 : 1790 : /* set the raid mode */ - 1791 277 : raid_mode(state.raid_mode); + 1791 278 : raid_mode(state.raid_mode); 1792 : 1793 : #if HAVE_LOCKFILE 1794 : /* create the lock file */ - 1795 277 : if (!opt.skip_lock && state.lockfile[0]) { + 1795 278 : if (!opt.skip_lock && state.lockfile[0]) { 1796 273 : lock = lock_lock(state.lockfile); 1797 273 : if (lock == -1) { 1798 : /* LCOV_EXCL_START */ @@ -1872,8 +1872,8 @@ 1810 : (void)lock; 1811 : #endif 1812 : - 1813 277 : ret = 0; - 1814 277 : if (operation == OPERATION_DIFF) { + 1813 278 : ret = 0; + 1814 278 : if (operation == OPERATION_DIFF) { 1815 8 : state_read(&state); 1816 : 1817 : /* refresh the size info to log correct info */ @@ -1884,7 +1884,7 @@ 1822 : /* abort if sync needed */ 1823 8 : if (ret > 0) 1824 7 : exit(EXIT_SYNC_NEEDED); - 1825 269 : } else if (operation == OPERATION_SYNC) { + 1825 270 : } else if (operation == OPERATION_SYNC) { 1826 : 1827 : /* in the next state read ensures to clear all the past hashes in case */ 1828 : /* we are reading from an incomplete sync */ @@ -1962,7 +1962,7 @@ 1900 0 : sleep(2); 1901 : 1902 92 : ret = state_sync(&state, blockstart, blockcount); - 1903 175 : } else if (operation == OPERATION_DRY) { + 1903 176 : } else if (operation == OPERATION_DRY) { 1904 3 : state_read(&state); 1905 : 1906 : /* refresh the size info to log correct info */ @@ -1978,7 +1978,7 @@ 1916 3 : signal_init(); 1917 : 1918 3 : ret = state_dry(&state, blockstart, blockcount); - 1919 172 : } else if (operation == OPERATION_REHASH) { + 1919 173 : } else if (operation == OPERATION_REHASH) { 1920 1 : state_read(&state); 1921 : 1922 : /* intercept signals while operating */ @@ -1989,7 +1989,7 @@ 1927 : /* save the new state if required */ 1928 1 : if (state.need_write) 1929 1 : state_write(&state); - 1930 171 : } else if (operation == OPERATION_SCRUB) { + 1930 172 : } else if (operation == OPERATION_SCRUB) { 1931 11 : state_read(&state); 1932 : 1933 : /* refresh the size info before the content write */ @@ -2001,7 +2001,7 @@ 1939 11 : signal_init(); 1940 : 1941 11 : ret = state_scrub(&state, plan100, olderthan); - 1942 160 : } else if (operation == OPERATION_REWRITE) { + 1942 161 : } else if (operation == OPERATION_REWRITE) { 1943 1 : state_read(&state); 1944 : 1945 : /* intercept signals while operating */ @@ -2010,11 +2010,11 @@ 1948 1 : state_write(&state); 1949 : 1950 1 : memory(); - 1951 159 : } else if (operation == OPERATION_READ) { + 1951 160 : } else if (operation == OPERATION_READ) { 1952 1 : state_read(&state); 1953 : 1954 1 : memory(); - 1955 158 : } else if (operation == OPERATION_TOUCH) { + 1955 159 : } else if (operation == OPERATION_TOUCH) { 1956 1 : state_read(&state); 1957 : 1958 1 : memory(); @@ -2025,16 +2025,16 @@ 1963 1 : signal_init(); 1964 : 1965 1 : state_write(&state); - 1966 157 : } else if (operation == OPERATION_SPINUP) { + 1966 158 : } else if (operation == OPERATION_SPINUP) { 1967 1 : state_device(&state, DEVICE_UP, &filterlist_disk); - 1968 156 : } else if (operation == OPERATION_SPINDOWN) { + 1968 157 : } else if (operation == OPERATION_SPINDOWN) { 1969 1 : state_device(&state, DEVICE_DOWN, &filterlist_disk); - 1970 155 : } else if (operation == OPERATION_DEVICES) { + 1970 156 : } else if (operation == OPERATION_DEVICES) { 1971 1 : state_device(&state, DEVICE_LIST, 0); - 1972 154 : } else if (operation == OPERATION_SMART) { + 1972 155 : } else if (operation == OPERATION_SMART) { 1973 1 : state_device(&state, DEVICE_SMART, 0); - 1974 153 : } else if (operation == OPERATION_PROBE) { - 1975 2 : state_device(&state, DEVICE_PROBE, 0); + 1974 154 : } else if (operation == OPERATION_PROBE) { + 1975 3 : state_device(&state, DEVICE_PROBE, 0); 1976 151 : } else if (operation == OPERATION_STATUS) { 1977 15 : state_read(&state); 1978 : @@ -2100,10 +2100,10 @@ 2038 : } 2039 : 2040 : /* close log file */ - 2041 267 : log_close(log_file); + 2041 268 : log_close(log_file); 2042 : 2043 : #if HAVE_LOCKFILE - 2044 267 : if (!opt.skip_lock && state.lockfile[0]) { + 2044 268 : if (!opt.skip_lock && state.lockfile[0]) { 2045 264 : if (lock_unlock(lock) == -1) { 2046 : /* LCOV_EXCL_START */ 2047 : log_fatal(errno, "Failed to close the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); @@ -2113,20 +2113,20 @@ 2051 : } 2052 : #endif 2053 : - 2054 267 : state_done(&state); - 2055 267 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free); - 2056 267 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free); + 2054 268 : state_done(&state); + 2055 268 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free); + 2056 268 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free); 2057 : - 2058 267 : os_done(); - 2059 267 : lock_done(); + 2058 268 : os_done(); + 2059 268 : lock_done(); 2060 : 2061 : /* abort if required */ - 2062 267 : if (ret != 0) { + 2062 268 : if (ret != 0) { 2063 : /* LCOV_EXCL_START */ 2064 : exit(EXIT_FAILURE); 2065 : /* LCOV_EXCL_STOP */ 2066 : } - 2067 255 : if (global_interrupt) { + 2067 256 : if (global_interrupt) { 2068 : /* LCOV_EXCL_START */ 2069 : #ifdef _WIN32 2070 : exit(STATUS_CONTROL_C_EXIT); @@ -2143,7 +2143,7 @@ 2081 : /* LCOV_EXCL_STOP */ 2082 : } 2083 : - 2084 255 : return EXIT_SUCCESS; + 2084 256 : return EXIT_SUCCESS; 2085 : } 2086 : diff --git a/cov/cmdline/speed.c.func-sort-c.html b/cov/cmdline/speed.c.func-sort-c.html index 227dbab6..4c45a6ba 100644 --- a/cov/cmdline/speed.c.func-sort-c.html +++ b/cov/cmdline/speed.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ diffgettimeofday - 1643 + 1617
diff --git a/cov/cmdline/speed.c.func.html b/cov/cmdline/speed.c.func.html index 90e32ecd..7299055d 100644 --- a/cov/cmdline/speed.c.func.html +++ b/cov/cmdline/speed.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,7 +61,7 @@ diffgettimeofday - 1643 + 1617 speed diff --git a/cov/cmdline/speed.c.gcov.html b/cov/cmdline/speed.c.gcov.html index 2ed597f7..eb8353ed 100644 --- a/cov/cmdline/speed.c.gcov.html +++ b/cov/cmdline/speed.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -90,14 +90,14 @@ 28 : /** 29 : * Differential us of two timeval. 30 : */ - 31 1643 : static int64_t diffgettimeofday(struct timeval* start, struct timeval* stop) + 31 1617 : static int64_t diffgettimeofday(struct timeval* start, struct timeval* stop) 32 : { 33 : int64_t d; 34 : - 35 1643 : d = 1000000LL * (stop->tv_sec - start->tv_sec); - 36 1643 : d += stop->tv_usec - start->tv_usec; + 35 1617 : d = 1000000LL * (stop->tv_sec - start->tv_sec); + 36 1617 : d += stop->tv_usec - start->tv_usec; 37 : - 38 1643 : return d; + 38 1617 : return d; 39 : } 40 : 41 : /** @@ -233,10 +233,10 @@ 171 4 : printf("%8s", "memset"); 172 4 : fflush(stdout); 173 : - 174 1292 : SPEED_START { - 175 5814 : for (j = 0; j < nd; ++j) - 176 5168 : memset(v[j], j, size); - 177 646 : } SPEED_STOP + 174 1284 : SPEED_START { + 175 5778 : for (j = 0; j < nd; ++j) + 176 5136 : memset(v[j], j, size); + 177 642 : } SPEED_STOP 178 : 179 4 : printf("%8" PRIu64, ds / dt); 180 4 : printf("\n"); @@ -248,10 +248,10 @@ 186 4 : printf("%8s", "table"); 187 4 : fflush(stdout); 188 : - 189 74 : SPEED_START { - 190 333 : for (j = 0; j < nd; ++j) - 191 296 : side_effect += crc32c_gen(0, v[j], size); - 192 37 : } SPEED_STOP + 189 62 : SPEED_START { + 190 279 : for (j = 0; j < nd; ++j) + 191 248 : side_effect += crc32c_gen(0, v[j], size); + 192 31 : } SPEED_STOP 193 : 194 4 : printf("%8" PRIu64, ds / dt); 195 4 : printf("\n"); @@ -261,10 +261,10 @@ 199 : 200 : #if HAVE_SSE42 201 4 : if (raid_cpu_has_crc32()) { - 202 82 : SPEED_START { - 203 369 : for (j = 0; j < nd; ++j) - 204 328 : side_effect += crc32c_x86(0, v[j], size); - 205 41 : } SPEED_STOP + 202 92 : SPEED_START { + 203 414 : for (j = 0; j < nd; ++j) + 204 368 : side_effect += crc32c_x86(0, v[j], size); + 205 46 : } SPEED_STOP 206 : 207 2 : printf("%8" PRIu64, ds / dt); 208 : } @@ -295,26 +295,26 @@ 233 4 : printf("%8" PRIu64, ds / dt); 234 4 : fflush(stdout); 235 : - 236 36 : SPEED_START { - 237 162 : for (j = 0; j < nd; ++j) - 238 144 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); - 239 18 : } SPEED_STOP + 236 42 : SPEED_START { + 237 189 : for (j = 0; j < nd; ++j) + 238 168 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); + 239 21 : } SPEED_STOP 240 : 241 4 : printf("%8" PRIu64, ds / dt); 242 4 : fflush(stdout); 243 : - 244 26 : SPEED_START { - 245 117 : for (j = 0; j < nd; ++j) - 246 104 : memhash(HASH_METRO, seed, digest, v[j], size); - 247 13 : } SPEED_STOP + 244 32 : SPEED_START { + 245 144 : for (j = 0; j < nd; ++j) + 246 128 : memhash(HASH_METRO, seed, digest, v[j], size); + 247 16 : } SPEED_STOP 248 : 249 4 : printf("%8" PRIu64, ds / dt); 250 4 : fflush(stdout); 251 : - 252 32 : SPEED_START { - 253 144 : for (j = 0; j < nd; ++j) - 254 128 : memhash(HASH_MUSEAIR, seed, digest, v[j], size); - 255 16 : } SPEED_STOP + 252 34 : SPEED_START { + 253 153 : for (j = 0; j < nd; ++j) + 254 136 : memhash(HASH_MUSEAIR, seed, digest, v[j], size); + 255 17 : } SPEED_STOP 256 : 257 4 : printf("%8" PRIu64, ds / dt); 258 4 : printf("\n"); @@ -350,16 +350,16 @@ 288 : 289 4 : printf("%8s", ""); 290 : - 291 168 : SPEED_START { - 292 84 : raid_gen1_int32(nd, size, v); - 293 84 : } SPEED_STOP + 291 156 : SPEED_START { + 292 78 : raid_gen1_int32(nd, size, v); + 293 78 : } SPEED_STOP 294 : 295 4 : printf("%8" PRIu64, ds / dt); 296 4 : fflush(stdout); 297 : - 298 334 : SPEED_START { - 299 167 : raid_gen1_int64(nd, size, v); - 300 167 : } SPEED_STOP + 298 312 : SPEED_START { + 299 156 : raid_gen1_int64(nd, size, v); + 300 156 : } SPEED_STOP 301 : 302 4 : printf("%8" PRIu64, ds / dt); 303 4 : fflush(stdout); @@ -367,9 +367,9 @@ 305 : #ifdef CONFIG_X86 306 : #ifdef CONFIG_SSE2 307 4 : if (raid_cpu_has_sse2()) { - 308 100 : SPEED_START { - 309 50 : raid_gen1_sse2(nd, size, v); - 310 50 : } SPEED_STOP + 308 96 : SPEED_START { + 309 48 : raid_gen1_sse2(nd, size, v); + 310 48 : } SPEED_STOP 311 : 312 4 : printf("%8" PRIu64, ds / dt); 313 4 : fflush(stdout); @@ -385,9 +385,9 @@ 323 : #endif 324 : #ifdef CONFIG_AVX2 325 4 : if (raid_cpu_has_avx2()) { - 326 24 : SPEED_START { - 327 12 : raid_gen1_avx2(nd, size, v); - 328 12 : } SPEED_STOP + 326 22 : SPEED_START { + 327 11 : raid_gen1_avx2(nd, size, v); + 328 11 : } SPEED_STOP 329 : 330 1 : printf("%8" PRIu64, ds / dt); 331 1 : fflush(stdout); @@ -403,16 +403,16 @@ 341 : 342 4 : printf("%8s", ""); 343 : - 344 80 : SPEED_START { - 345 40 : raid_gen2_int32(nd, size, v); - 346 40 : } SPEED_STOP + 344 84 : SPEED_START { + 345 42 : raid_gen2_int32(nd, size, v); + 346 42 : } SPEED_STOP 347 : 348 4 : printf("%8" PRIu64, ds / dt); 349 4 : fflush(stdout); 350 : - 351 164 : SPEED_START { - 352 82 : raid_gen2_int64(nd, size, v); - 353 82 : } SPEED_STOP + 351 156 : SPEED_START { + 352 78 : raid_gen2_int64(nd, size, v); + 353 78 : } SPEED_STOP 354 : 355 4 : printf("%8" PRIu64, ds / dt); 356 4 : fflush(stdout); @@ -444,9 +444,9 @@ 382 : #endif 383 : #ifdef CONFIG_AVX2 384 4 : if (raid_cpu_has_avx2()) { - 385 6 : SPEED_START { - 386 3 : raid_gen2_avx2(nd, size, v); - 387 3 : } SPEED_STOP + 385 4 : SPEED_START { + 386 2 : raid_gen2_avx2(nd, size, v); + 387 2 : } SPEED_STOP 388 : 389 1 : printf("%8" PRIu64, ds / dt); 390 1 : fflush(stdout); @@ -469,9 +469,9 @@ 407 4 : printf("%8" PRIu64, ds / dt); 408 4 : fflush(stdout); 409 : - 410 98 : SPEED_START { - 411 49 : raid_genz_int64(nd, size, v); - 412 49 : } SPEED_STOP + 410 102 : SPEED_START { + 411 51 : raid_genz_int64(nd, size, v); + 412 51 : } SPEED_STOP 413 : 414 4 : printf("%8" PRIu64, ds / dt); 415 4 : fflush(stdout); @@ -479,9 +479,9 @@ 417 : #ifdef CONFIG_X86 418 : #ifdef CONFIG_SSE2 419 4 : if (raid_cpu_has_sse2()) { - 420 24 : SPEED_START { - 421 12 : raid_genz_sse2(nd, size, v); - 422 12 : } SPEED_STOP + 420 20 : SPEED_START { + 421 10 : raid_genz_sse2(nd, size, v); + 422 10 : } SPEED_STOP 423 : 424 4 : printf("%8" PRIu64, ds / dt); 425 4 : fflush(stdout); @@ -523,9 +523,9 @@ 461 4 : printf("%8s", raid_gen3_tag()); 462 4 : fflush(stdout); 463 : - 464 20 : SPEED_START { - 465 10 : raid_gen3_int8(nd, size, v); - 466 10 : } SPEED_STOP + 464 18 : SPEED_START { + 465 9 : raid_gen3_int8(nd, size, v); + 466 9 : } SPEED_STOP 467 : 468 4 : printf("%8" PRIu64, ds / dt); 469 4 : fflush(stdout); @@ -546,9 +546,9 @@ 484 : #ifdef CONFIG_X86 485 : #ifdef CONFIG_SSSE3 486 4 : if (raid_cpu_has_ssse3()) { - 487 18 : SPEED_START { - 488 9 : raid_gen3_ssse3(nd, size, v); - 489 9 : } SPEED_STOP + 487 14 : SPEED_START { + 488 7 : raid_gen3_ssse3(nd, size, v); + 489 7 : } SPEED_STOP 490 : 491 3 : printf("%8" PRIu64, ds / dt); 492 3 : fflush(stdout); @@ -716,9 +716,9 @@ 654 4 : printf("%8s", raid_gen6_tag()); 655 4 : fflush(stdout); 656 : - 657 16 : SPEED_START { - 658 8 : raid_gen6_int8(nd, size, v); - 659 8 : } SPEED_STOP + 657 14 : SPEED_START { + 658 7 : raid_gen6_int8(nd, size, v); + 659 7 : } SPEED_STOP 660 : 661 4 : printf("%8" PRIu64, ds / dt); 662 4 : fflush(stdout); @@ -749,9 +749,9 @@ 687 3 : fflush(stdout); 688 : 689 : #ifdef CONFIG_X86_64 - 690 8 : SPEED_START { - 691 4 : raid_gen6_ssse3ext(nd, size, v); - 692 4 : } SPEED_STOP + 690 6 : SPEED_START { + 691 3 : raid_gen6_ssse3ext(nd, size, v); + 692 3 : } SPEED_STOP 693 : 694 3 : printf("%8" PRIu64, ds / dt); 695 3 : fflush(stdout); diff --git a/cov/cmdline/spooky2.c.func-sort-c.html b/cov/cmdline/spooky2.c.func-sort-c.html index 491565a2..759c15c5 100644 --- a/cov/cmdline/spooky2.c.func-sort-c.html +++ b/cov/cmdline/spooky2.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3888115 + 3887997
diff --git a/cov/cmdline/spooky2.c.func.html b/cov/cmdline/spooky2.c.func.html index 691ce22a..0dc90f5f 100644 --- a/cov/cmdline/spooky2.c.func.html +++ b/cov/cmdline/spooky2.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3888115 + 3887997
diff --git a/cov/cmdline/spooky2.c.gcov.html b/cov/cmdline/spooky2.c.gcov.html index 73f1c05d..f3c85dd0 100644 --- a/cov/cmdline/spooky2.c.gcov.html +++ b/cov/cmdline/spooky2.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -170,7 +170,7 @@ 108 : // 109 : #define sc_const 0xdeadbeefdeadbeefLL 110 : - 111 3888115 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) + 111 3887997 : 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 3888115 : h9 = util_read64(seed + 0); - 124 3888115 : h10 = util_read64(seed + 8); + 123 3887997 : h9 = util_read64(seed + 0); + 124 3887997 : h10 = util_read64(seed + 8); 125 : - 126 3888115 : h0 = h3 = h6 = h9; - 127 3888115 : h1 = h4 = h7 = h10; - 128 3888115 : h2 = h5 = h8 = h11 = sc_const; + 126 3887997 : h0 = h3 = h6 = h9; + 127 3887997 : h1 = h4 = h7 = h10; + 128 3887997 : h2 = h5 = h8 = h11 = sc_const; 129 : - 130 3888115 : nblocks = size / sc_blockSize; - 131 3888115 : blocks = data; - 132 3888115 : end = blocks + nblocks * sc_numVars; + 130 3887997 : nblocks = size / sc_blockSize; + 131 3887997 : blocks = data; + 132 3887997 : end = blocks + nblocks * sc_numVars; 133 : 134 : /* body */ - 135 34766493 : while (blocks < end) { + 135 34830303 : 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 30878378 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 141 30942306 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 142 : #endif - 143 30878378 : blocks += sc_numVars; + 143 30942306 : blocks += sc_numVars; 144 : } 145 : 146 : /* tail */ - 147 3888115 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); - 148 3888115 : memcpy(buf, end, size_remainder); - 149 3888115 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); - 150 3888115 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; + 147 3887997 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); + 148 3887997 : memcpy(buf, end, size_remainder); + 149 3887997 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); + 150 3887997 : ((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 3888115 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 157 3887997 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 158 : - 159 3888115 : util_write64(digest + 0, h0); - 160 3888115 : util_write64(digest + 8, h1); - 161 3888115 : } + 159 3887997 : util_write64(digest + 0, h0); + 160 3887997 : util_write64(digest + 8, h1); + 161 3887997 : } 162 : diff --git a/cov/cmdline/state.c.func-sort-c.html b/cov/cmdline/state.c.func-sort-c.html index a13141ff..b282e74b 100644 --- a/cov/cmdline/state.c.func-sort-c.html +++ b/cov/cmdline/state.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1737 + 1765 1954 - 88.9 % + 90.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 49 @@ -117,23 +117,23 @@ state_rename_content - 157 + 156 state_verify_content - 157 + 156 state_write - 157 + 156 state_write_content - 157 + 156 state_write_thread - 157 + 156 state_refresh @@ -157,7 +157,7 @@ state_done - 268 + 269 state_map @@ -169,35 +169,35 @@ lev_raid_name - 277 - - - state_config_check - 277 - - - state_config 278 - state_init + state_config_check + 278 + + + state_config 279 + + state_init + 280 + validate_smartctl 384 state_progress_latest - 493 + 481 state_fscheck - 521 + 520 state_verify_thread - 1054 + 1047 fs_position_clear_deleted @@ -205,51 +205,51 @@ lev_config_scan - 6985 + 7028 find_disk_by_name - 7508 + 7496 state_usage_raid - 140496 + 140445 state_usage_sched - 151013 + 150950 lev_config_name - 273686 + 273680 state_usage_hash - 753854 + 753469 state_usage_parity - 781079 + 780707 fs_position_is_required - 800411 + 793414 state_usage_file - 914732 + 914354 state_usage_disk - 919419 + 919041 state_usage_misc - 1071293 + 1070853 state_progress - 1075966 + 1075903 fs_info_is_required @@ -257,11 +257,11 @@ fs_is_block_unsynced - 2406326 + 2399329 fs_is_block_deleted - 4795496 + 4753514
diff --git a/cov/cmdline/state.c.func.html b/cov/cmdline/state.c.func.html index bb510bac..14e0e84c 100644 --- a/cov/cmdline/state.c.func.html +++ b/cov/cmdline/state.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1737 + 1765 1954 - 88.9 % + 90.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 49 @@ -65,7 +65,7 @@ find_disk_by_name - 7508 + 7496 find_disk_by_uuid @@ -77,11 +77,11 @@ fs_is_block_deleted - 4795496 + 4753514 fs_is_block_unsynced - 2406326 + 2399329 fs_position_clear_deleted @@ -89,7 +89,7 @@ fs_position_is_required - 800411 + 793414 generate_configuration @@ -97,11 +97,11 @@ lev_config_name - 273686 + 273680 lev_config_scan - 6985 + 7028 lev_name @@ -109,15 +109,15 @@ lev_raid_name - 277 - - - state_config 278 + + state_config + 279 + state_config_check - 277 + 278 state_content_check @@ -125,7 +125,7 @@ state_done - 268 + 269 state_filter @@ -137,11 +137,11 @@ state_fscheck - 521 + 520 state_init - 279 + 280 state_load_ignore_file @@ -153,7 +153,7 @@ state_progress - 1075966 + 1075903 state_progress_begin @@ -169,7 +169,7 @@ state_progress_latest - 493 + 481 state_progress_restart @@ -193,7 +193,7 @@ state_rename_content - 157 + 156 state_skip @@ -205,23 +205,23 @@ state_usage_disk - 919419 + 919041 state_usage_file - 914732 + 914354 state_usage_hash - 753854 + 753469 state_usage_misc - 1071293 + 1070853 state_usage_parity - 781079 + 780707 state_usage_print @@ -229,11 +229,11 @@ state_usage_raid - 140496 + 140445 state_usage_sched - 151013 + 150950 state_usage_waste @@ -241,23 +241,23 @@ state_verify_content - 157 + 156 state_verify_thread - 1054 + 1047 state_write - 157 + 156 state_write_content - 157 + 156 state_write_thread - 157 + 156 validate_smartctl diff --git a/cov/cmdline/state.c.gcov.html b/cov/cmdline/state.c.gcov.html index f6d21b9d..488bfc2f 100644 --- a/cov/cmdline/state.c.gcov.html +++ b/cov/cmdline/state.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1737 + 1765 1954 - 88.9 % + 90.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 49 @@ -122,67 +122,67 @@ 60 0 : return "invalid"; 61 : } 62 : - 63 273686 : const char* lev_config_name(unsigned l) + 63 273680 : const char* lev_config_name(unsigned l) 64 : { - 65 273686 : switch (l) { - 66 94064 : case 0 : return "parity"; - 67 76604 : case 1 : return "2-parity"; - 68 25794 : case 2 : return "3-parity"; - 69 25769 : case 3 : return "4-parity"; - 70 25744 : case 4 : return "5-parity"; - 71 25711 : case 5 : return "6-parity"; + 65 273680 : switch (l) { + 66 94081 : case 0 : return "parity"; + 67 76601 : case 1 : return "2-parity"; + 68 25789 : case 2 : return "3-parity"; + 69 25764 : case 3 : return "4-parity"; + 70 25739 : case 4 : return "5-parity"; + 71 25706 : case 5 : return "6-parity"; 72 : } 73 : 74 0 : return "invalid"; 75 : } 76 : - 77 6985 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) + 77 7028 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) 78 : { - 79 6985 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { - 80 661 : *level = 0; - 81 661 : return 0; + 79 7028 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { + 80 662 : *level = 0; + 81 662 : return 0; 82 : } 83 : - 84 6324 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { - 85 235 : *level = 1; - 86 235 : return 0; + 84 6366 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { + 85 236 : *level = 1; + 86 236 : return 0; 87 : } 88 : - 89 6089 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { + 89 6130 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { 90 210 : *level = 2; 91 210 : return 0; 92 : } 93 : - 94 5879 : if (strcmp(s, "4-parity") == 0) { + 94 5920 : if (strcmp(s, "4-parity") == 0) { 95 207 : *level = 3; 96 207 : return 0; 97 : } 98 : - 99 5672 : if (strcmp(s, "5-parity") == 0) { + 99 5713 : if (strcmp(s, "5-parity") == 0) { 100 204 : *level = 4; 101 204 : return 0; 102 : } 103 : - 104 5468 : if (strcmp(s, "6-parity") == 0) { + 104 5509 : if (strcmp(s, "6-parity") == 0) { 105 200 : *level = 5; 106 200 : return 0; 107 : } 108 : - 109 5268 : if (strcmp(s, "z-parity") == 0) { + 109 5309 : if (strcmp(s, "z-parity") == 0) { 110 0 : *level = 2; 111 0 : if (mode) 112 0 : *mode = RAID_MODE_VANDERMONDE; 113 0 : return 0; 114 : } 115 : - 116 5268 : return -1; + 116 5309 : return -1; 117 : } 118 : - 119 277 : const char* lev_raid_name(unsigned mode, unsigned n) + 119 278 : const char* lev_raid_name(unsigned mode, unsigned n) 120 : { - 121 277 : switch (n) { + 121 278 : switch (n) { 122 43 : case 1 : return "par1"; - 123 25 : case 2 : return "par2"; + 123 26 : case 2 : return "par2"; 124 3 : case 3 : if (mode == RAID_MODE_CAUCHY) 125 3 : return "par3"; 126 : else @@ -195,105 +195,105 @@ 133 0 : return 0; 134 : } 135 : - 136 279 : void state_init(struct snapraid_state* state) + 136 280 : void state_init(struct snapraid_state* state) 137 : { 138 : unsigned l, s, i; 139 : - 140 279 : memset(&state->opt, 0, sizeof(state->opt)); - 141 279 : state->filter_hidden = 0; - 142 279 : state->autosave = 0; - 143 279 : state->need_write = 0; - 144 279 : state->written = 0; - 145 279 : state->checked_read = 0; - 146 279 : state->block_size = 256 * KIBI; /* default 256 KiB */ - 147 279 : state->raid_mode = RAID_MODE_CAUCHY; - 148 279 : state->file_mode = ADVISE_DEFAULT; - 149 1953 : for (l = 0; l < LEV_MAX; ++l) { - 150 1674 : state->parity[l].split_mac = 0; - 151 15066 : for (s = 0; s < SPLIT_MAX; ++s) { - 152 13392 : state->parity[l].split_map[s].path[0] = 0; - 153 13392 : state->parity[l].split_map[s].uuid[0] = 0; - 154 13392 : state->parity[l].split_map[s].fstype[0] = 0; - 155 13392 : state->parity[l].split_map[s].fslabel[0] = 0; - 156 13392 : state->parity[l].split_map[s].size = PARITY_SIZE_INVALID; - 157 13392 : state->parity[l].split_map[s].device = 0; + 140 280 : memset(&state->opt, 0, sizeof(state->opt)); + 141 280 : state->filter_hidden = 0; + 142 280 : state->autosave = 0; + 143 280 : state->need_write = 0; + 144 280 : state->written = 0; + 145 280 : state->checked_read = 0; + 146 280 : state->block_size = 256 * KIBI; /* default 256 KiB */ + 147 280 : state->raid_mode = RAID_MODE_CAUCHY; + 148 280 : state->file_mode = ADVISE_DEFAULT; + 149 1960 : for (l = 0; l < LEV_MAX; ++l) { + 150 1680 : state->parity[l].split_mac = 0; + 151 15120 : for (s = 0; s < SPLIT_MAX; ++s) { + 152 13440 : state->parity[l].split_map[s].path[0] = 0; + 153 13440 : state->parity[l].split_map[s].uuid[0] = 0; + 154 13440 : state->parity[l].split_map[s].fstype[0] = 0; + 155 13440 : state->parity[l].split_map[s].fslabel[0] = 0; + 156 13440 : state->parity[l].split_map[s].size = PARITY_SIZE_INVALID; + 157 13440 : state->parity[l].split_map[s].device = 0; 158 : } - 159 1674 : state->parity[l].smartctl[0] = 0; - 160 8370 : for (i = 0; i < SMART_IGNORE_MAX; ++i) - 161 6696 : state->parity[l].smartignore[i] = 0; - 162 1674 : state->parity[l].total_blocks = 0; - 163 1674 : state->parity[l].free_blocks = 0; - 164 1674 : state->parity[l].skip_access = 0; - 165 1674 : state->parity[l].tick = 0; - 166 1674 : state->parity[l].cached_blocks = 0; - 167 1674 : state->parity[l].is_excluded_by_filter = 0; + 159 1680 : state->parity[l].smartctl[0] = 0; + 160 8400 : for (i = 0; i < SMART_IGNORE_MAX; ++i) + 161 6720 : state->parity[l].smartignore[i] = 0; + 162 1680 : state->parity[l].total_blocks = 0; + 163 1680 : state->parity[l].free_blocks = 0; + 164 1680 : state->parity[l].skip_access = 0; + 165 1680 : state->parity[l].tick = 0; + 166 1680 : state->parity[l].cached_blocks = 0; + 167 1680 : state->parity[l].is_excluded_by_filter = 0; 168 : } - 169 279 : state->tick_io = 0; - 170 279 : state->tick_misc = 0; - 171 279 : state->tick_sched = 0; - 172 279 : state->tick_raid = 0; - 173 279 : state->tick_hash = 0; - 174 279 : state->tick_last = tick(); - 175 279 : state->share[0] = 0; - 176 279 : state->pool[0] = 0; - 177 279 : state->pool_device = 0; - 178 279 : state->lockfile[0] = 0; - 179 279 : state->level = 1; /* default is the lowest protection */ - 180 279 : state->clear_past_hash = 0; - 181 279 : state->no_conf = 0; - 182 1395 : for (i = 0; i < SMART_IGNORE_MAX; ++i) - 183 1116 : state->smartignore[i] = 0; - 184 279 : state->rehash_blocks = 0; - 185 279 : state->bad_blocks = 0; - 186 279 : state->unsynced_blocks = 0; - 187 279 : state->unscrubbed_blocks = 0; - 188 279 : state->thermal_stop_gathering = 0; - 189 279 : state->thermal_ambient_temperature = 0; - 190 279 : state->thermal_highest_temperature = 0; - 191 279 : state->thermal_first = 0; - 192 279 : state->thermal_latest = 0; - 193 279 : state->thermal_temperature_limit = 0; - 194 279 : state->thermal_cooldown_time = 0; + 169 280 : state->tick_io = 0; + 170 280 : state->tick_misc = 0; + 171 280 : state->tick_sched = 0; + 172 280 : state->tick_raid = 0; + 173 280 : state->tick_hash = 0; + 174 280 : state->tick_last = tick(); + 175 280 : state->share[0] = 0; + 176 280 : state->pool[0] = 0; + 177 280 : state->pool_device = 0; + 178 280 : state->lockfile[0] = 0; + 179 280 : state->level = 1; /* default is the lowest protection */ + 180 280 : state->clear_past_hash = 0; + 181 280 : state->no_conf = 0; + 182 1400 : for (i = 0; i < SMART_IGNORE_MAX; ++i) + 183 1120 : state->smartignore[i] = 0; + 184 280 : state->rehash_blocks = 0; + 185 280 : state->bad_blocks = 0; + 186 280 : state->unsynced_blocks = 0; + 187 280 : state->unscrubbed_blocks = 0; + 188 280 : state->thermal_stop_gathering = 0; + 189 280 : state->thermal_ambient_temperature = 0; + 190 280 : state->thermal_highest_temperature = 0; + 191 280 : state->thermal_first = 0; + 192 280 : state->thermal_latest = 0; + 193 280 : state->thermal_temperature_limit = 0; + 194 280 : state->thermal_cooldown_time = 0; 195 : - 196 279 : tommy_list_init(&state->disklist); - 197 279 : tommy_list_init(&state->maplist); - 198 279 : tommy_list_init(&state->contentlist); - 199 279 : tommy_list_init(&state->filterlist); - 200 279 : tommy_list_init(&state->importlist); - 201 279 : tommy_list_init(&state->thermallist); - 202 279 : tommy_hashdyn_init(&state->importset); - 203 279 : tommy_hashdyn_init(&state->previmportset); - 204 279 : tommy_hashdyn_init(&state->searchset); - 205 279 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info)); - 206 279 : tommy_list_init(&state->bucketlist); - 207 279 : } + 196 280 : tommy_list_init(&state->disklist); + 197 280 : tommy_list_init(&state->maplist); + 198 280 : tommy_list_init(&state->contentlist); + 199 280 : tommy_list_init(&state->filterlist); + 200 280 : tommy_list_init(&state->importlist); + 201 280 : tommy_list_init(&state->thermallist); + 202 280 : tommy_hashdyn_init(&state->importset); + 203 280 : tommy_hashdyn_init(&state->previmportset); + 204 280 : tommy_hashdyn_init(&state->searchset); + 205 280 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info)); + 206 280 : tommy_list_init(&state->bucketlist); + 207 280 : } 208 : - 209 268 : void state_done(struct snapraid_state* state) + 209 269 : void state_done(struct snapraid_state* state) 210 : { - 211 268 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); - 212 268 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free); - 213 268 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); - 214 268 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); - 215 268 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free); - 216 268 : tommy_list_foreach(&state->thermallist, (tommy_foreach_func*)thermal_free); - 217 268 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free); - 218 268 : tommy_hashdyn_done(&state->importset); - 219 268 : tommy_hashdyn_done(&state->previmportset); - 220 268 : tommy_hashdyn_done(&state->searchset); - 221 268 : tommy_arrayblkof_done(&state->infoarr); - 222 268 : tommy_list_foreach(&state->bucketlist, (tommy_foreach_func*)bucket_free); - 223 268 : } + 211 269 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); + 212 269 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free); + 213 269 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); + 214 269 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); + 215 269 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free); + 216 269 : tommy_list_foreach(&state->thermallist, (tommy_foreach_func*)thermal_free); + 217 269 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free); + 218 269 : tommy_hashdyn_done(&state->importset); + 219 269 : tommy_hashdyn_done(&state->previmportset); + 220 269 : tommy_hashdyn_done(&state->searchset); + 221 269 : tommy_arrayblkof_done(&state->infoarr); + 222 269 : tommy_list_foreach(&state->bucketlist, (tommy_foreach_func*)bucket_free); + 223 269 : } 224 : 225 : /** 226 : * Check the configuration. 227 : */ - 228 277 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk) + 228 278 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk) 229 : { 230 : tommy_node* i; 231 : unsigned l, s; 232 : 233 : /* check for parity level */ - 234 277 : if (state->raid_mode == RAID_MODE_VANDERMONDE) { + 234 278 : if (state->raid_mode == RAID_MODE_VANDERMONDE) { 235 0 : if (state->level > 3) { 236 : /* LCOV_EXCL_START */ 237 : log_fatal(EUSER, "Using z-parity limits you to a maximum of 3 parities.\n"); @@ -311,7 +311,7 @@ 249 : } 250 : } 251 : - 252 277 : if (tommy_list_empty(&state->contentlist)) { + 252 278 : if (tommy_list_empty(&state->contentlist)) { 253 : /* LCOV_EXCL_START */ 254 : log_fatal(EUSER, "Missing 'content' specification in '%s'\n", path); 255 : exit(EXIT_FAILURE); @@ -319,12 +319,12 @@ 257 : } 258 : 259 : /* check for equal paths */ - 260 1882 : for (i = state->contentlist; i != 0; i = i->next) { - 261 1605 : struct snapraid_content* content = i->data; + 260 1887 : for (i = state->contentlist; i != 0; i = i->next) { + 261 1609 : struct snapraid_content* content = i->data; 262 : - 263 10415 : for (l = 0; l < state->level; ++l) { - 264 44050 : for (s = 0; s < state->parity[l].split_mac; ++s) { - 265 35240 : if (pathcmp(state->parity[l].split_map[s].path, content->content) == 0) { + 263 10427 : for (l = 0; l < state->level; ++l) { + 264 44066 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 265 35248 : if (pathcmp(state->parity[l].split_map[s].path, content->content) == 0) { 266 : /* LCOV_EXCL_START */ 267 : log_fatal(EUSER, "Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content); 268 : exit(EXIT_FAILURE); @@ -335,13 +335,13 @@ 273 : } 274 : 275 : /* check device of data disks */ - 276 277 : if (!state->opt.skip_device && !state->opt.skip_disk_access) { - 277 0 : for (i = state->disklist; i != 0; i = i->next) { + 276 278 : if (!state->opt.skip_device && !state->opt.skip_disk_access) { + 277 11 : for (i = state->disklist; i != 0; i = i->next) { 278 : tommy_node* j; - 279 0 : struct snapraid_disk* disk = i->data; + 279 10 : struct snapraid_disk* disk = i->data; 280 : 281 : /* skip data disks that are not accessible */ - 282 0 : if (disk->skip_access) + 282 10 : if (disk->skip_access) 283 0 : continue; 284 : 285 : #ifdef _WIN32 @@ -356,9 +356,9 @@ 294 : } 295 : #endif 296 : - 297 0 : for (j = i->next; j != 0; j = j->next) { - 298 0 : struct snapraid_disk* other = j->data; - 299 0 : if (disk->device == other->device) { + 297 55 : for (j = i->next; j != 0; j = j->next) { + 298 45 : struct snapraid_disk* other = j->data; + 299 45 : if (disk->device == other->device) { 300 0 : if (state->opt.force_device) { 301 : /* note that we just ignore the issue */ 302 : /* and we DON'T mark the disk to be skipped */ @@ -384,13 +384,13 @@ 322 : } 323 : 324 : /* skip data disks that are not accessible */ - 325 0 : if (disk->skip_access) + 325 10 : if (disk->skip_access) 326 0 : continue; 327 : - 328 0 : if (!state->opt.skip_parity_access) { - 329 0 : for (l = 0; l < state->level; ++l) { - 330 0 : for (s = 0; s < state->parity[l].split_mac; ++s) { - 331 0 : if (disk->device == state->parity[l].split_map[s].device) { + 328 10 : if (!state->opt.skip_parity_access) { + 329 30 : for (l = 0; l < state->level; ++l) { + 330 40 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 331 20 : if (disk->device == state->parity[l].split_map[s].device) { 332 0 : if (state->opt.force_device) { 333 : /* note that we just ignore the issue */ 334 : /* and we DON'T mark the disk to be skipped */ @@ -413,7 +413,7 @@ 351 : } 352 : } 353 : - 354 0 : if (state->pool[0] != 0 && disk->device == state->pool_device) { + 354 10 : if (state->pool[0] != 0 && disk->device == state->pool_device) { 355 : /* LCOV_EXCL_START */ 356 : log_fatal(ESOFT, "Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool); 357 : #ifdef _WIN32 @@ -428,13 +428,13 @@ 366 : } 367 : 368 : /* check device of parity disks */ - 369 277 : if (!state->opt.skip_device && !state->opt.skip_parity_access) { - 370 0 : for (l = 0; l < state->level; ++l) { - 371 0 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 369 278 : if (!state->opt.skip_device && !state->opt.skip_parity_access) { + 370 3 : for (l = 0; l < state->level; ++l) { + 371 4 : for (s = 0; s < state->parity[l].split_mac; ++s) { 372 : unsigned j, t; 373 : 374 : /* skip parity disks that are not accessible */ - 375 0 : if (state->parity[l].skip_access) + 375 2 : if (state->parity[l].skip_access) 376 0 : continue; 377 : 378 : #ifdef _WIN32 @@ -449,9 +449,9 @@ 387 : } 388 : #endif 389 : - 390 0 : for (j = l + 1; j < state->level; ++j) { - 391 0 : for (t = 0; t < state->parity[j].split_mac; ++t) { - 392 0 : if (state->parity[l].split_map[s].device == state->parity[j].split_map[t].device) { + 390 3 : for (j = l + 1; j < state->level; ++j) { + 391 2 : for (t = 0; t < state->parity[j].split_mac; ++t) { + 392 1 : if (state->parity[l].split_map[s].device == state->parity[j].split_map[t].device) { 393 0 : if (state->opt.force_device) { 394 : /* note that we just ignore the issue */ 395 : /* and we DON'T mark the disk to be skipped */ @@ -477,7 +477,7 @@ 415 : } 416 : } 417 : - 418 0 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].split_map[s].device) { + 418 2 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].split_map[s].device) { 419 : /* LCOV_EXCL_START */ 420 : log_fatal(ESOFT, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].split_map[s].path); 421 : #ifdef _WIN32 @@ -508,31 +508,31 @@ 446 : #endif 447 : 448 : /* count the content files */ - 449 277 : if (!state->opt.skip_device && !state->opt.skip_content_access) { + 449 278 : if (!state->opt.skip_device && !state->opt.skip_content_access) { 450 : unsigned content_count; 451 : - 452 0 : content_count = 0; - 453 0 : for (i = state->contentlist; i != 0; i = i->next) { + 452 1 : content_count = 0; + 453 5 : for (i = state->contentlist; i != 0; i = i->next) { 454 : tommy_node* j; - 455 0 : struct snapraid_content* content = i->data; + 455 4 : struct snapraid_content* content = i->data; 456 : 457 : /* check if there are others in the same disk */ - 458 0 : for (j = i->next; j != 0; j = j->next) { - 459 0 : struct snapraid_content* other = j->data; - 460 0 : if (content->device == other->device) { + 458 10 : for (j = i->next; j != 0; j = j->next) { + 459 6 : struct snapraid_content* other = j->data; + 460 6 : if (content->device == other->device) { 461 0 : log_fatal(ESOFT, "WARNING! Content files on the same disk: '%s' and '%s'.\n", content->content, other->content); 462 0 : break; 463 : } 464 : } - 465 0 : if (j != 0) { + 465 4 : if (j != 0) { 466 : /* skip it */ 467 0 : continue; 468 : } 469 : - 470 0 : ++content_count; + 470 4 : ++content_count; 471 : } 472 : - 473 0 : if (content_count < state->level + 1) { + 473 1 : if (content_count < state->level + 1) { 474 : /* LCOV_EXCL_START */ 475 : log_fatal(EUSER, "You must have at least %d 'content' files in different disks.\n", state->level + 1); 476 : exit(EXIT_FAILURE); @@ -542,7 +542,7 @@ 480 : 481 : /* check for speed */ 482 : #ifdef CONFIG_X86 - 483 277 : if (!raid_cpu_has_ssse3()) + 483 278 : if (!raid_cpu_has_ssse3()) 484 : #endif 485 0 : if (state->raid_mode == RAID_MODE_CAUCHY && !state->opt.no_warnings) { 486 0 : if (state->level == 3) { @@ -555,7 +555,7 @@ 493 : } 494 : 495 : /* ensure that specified filter disks are valid ones */ - 496 287 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + 496 288 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { 497 : tommy_node* j; 498 10 : struct snapraid_filter* filter = i->data; 499 51 : for (j = state->disklist; j != 0; j = j->next) { @@ -576,7 +576,7 @@ 514 : } 515 : } 516 : } - 517 277 : } + 517 278 : } 518 : 519 : /** 520 : * Validate the smartctl command. @@ -608,7 +608,7 @@ 546 384 : return 0; 547 : } 548 : - 549 278 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk) + 549 279 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk) 550 : { 551 : STREAM* f; 552 : unsigned line; @@ -616,27 +616,27 @@ 554 : unsigned l, s; 555 : 556 : /* copy the options */ - 557 278 : state->opt = *opt; + 557 279 : state->opt = *opt; 558 : 559 : /* if unset, sort by physical order */ - 560 278 : if (!state->opt.force_order) - 561 1 : state->opt.force_order = SORT_PHYSICAL; + 560 279 : if (!state->opt.force_order) + 561 2 : state->opt.force_order = SORT_PHYSICAL; 562 : 563 : /* adjust file mode */ - 564 278 : if (state->opt.file_mode != ADVISE_DEFAULT) { + 564 279 : if (state->opt.file_mode != ADVISE_DEFAULT) { 565 277 : state->file_mode = state->opt.file_mode; 566 : } else { 567 : /* default mode, if nothing is specified */ - 568 1 : state->file_mode = ADVISE_DISCARD; + 568 2 : state->file_mode = ADVISE_DISCARD; 569 : } 570 : 571 : /* store current command */ - 572 278 : state->command = command; + 572 279 : state->command = command; 573 : - 574 278 : log_tag("conf:file:%s\n", path); + 574 279 : log_tag("conf:file:%s\n", path); 575 : - 576 278 : f = sopen_read(path, 0); - 577 278 : if (!f) { + 576 279 : f = sopen_read(path, 0); + 577 279 : if (!f) { 578 : /* LCOV_EXCL_START */ 579 : if (errno == ENOENT) { 580 : if (state->opt.auto_conf) { @@ -657,8 +657,8 @@ 595 : /* LCOV_EXCL_STOP */ 596 : } 597 : - 598 278 : line = 1; - 599 6410 : while (1) { + 598 279 : line = 1; + 599 6453 : while (1) { 600 : char tag[PATH_MAX]; 601 : char buffer[PATH_MAX]; 602 : int ret; @@ -666,11 +666,11 @@ 604 : unsigned level; 605 : 606 : /* skip initial spaces */ - 607 6688 : sgetspace(f); + 607 6732 : sgetspace(f); 608 : 609 : /* read the command */ - 610 6688 : ret = sgettok(f, tag, sizeof(tag)); - 611 6688 : if (ret < 0) { + 610 6732 : ret = sgettok(f, tag, sizeof(tag)); + 611 6732 : if (ret < 0) { 612 : /* LCOV_EXCL_START */ 613 : log_fatal(EUSER, "Error reading the configuration file '%s' at line %u\n", path, line); 614 : exit(EXIT_FAILURE); @@ -678,41 +678,41 @@ 616 : } 617 : 618 : /* skip spaces after the command */ - 619 6688 : sgetspace(f); + 619 6732 : sgetspace(f); 620 : - 621 6688 : if (strcmp(tag, "blocksize") == 0 + 621 6732 : if (strcmp(tag, "blocksize") == 0 622 : /* block_size is the old format of the option */ - 623 6410 : || strcmp(tag, "block_size") == 0) { + 623 6454 : || strcmp(tag, "block_size") == 0) { 624 : - 625 278 : ret = sgetu32(f, &state->block_size); - 626 278 : if (ret < 0) { + 625 279 : ret = sgetu32(f, &state->block_size); + 626 279 : if (ret < 0) { 627 : /* LCOV_EXCL_START */ 628 : log_fatal(EUSER, "Invalid 'blocksize' specification in '%s' at line %u\n", path, line); 629 : exit(EXIT_FAILURE); 630 : /* LCOV_EXCL_STOP */ 631 : } - 632 278 : if (state->block_size < 1) { + 632 279 : if (state->block_size < 1) { 633 : /* LCOV_EXCL_START */ 634 : log_fatal(EUSER, "Too small 'blocksize' specification in '%s' at line %u\n", path, line); 635 : exit(EXIT_FAILURE); 636 : /* LCOV_EXCL_STOP */ 637 : } - 638 278 : if (state->block_size > 16 * KIBI) { + 638 279 : if (state->block_size > 16 * KIBI) { 639 : /* LCOV_EXCL_START */ 640 : log_fatal(EUSER, "Too big 'blocksize' specification in '%s' at line %u\n", path, line); 641 : exit(EXIT_FAILURE); 642 : /* LCOV_EXCL_STOP */ 643 : } 644 : /* check if it's a power of 2 */ - 645 278 : if ((state->block_size & (state->block_size - 1)) != 0) { + 645 279 : if ((state->block_size & (state->block_size - 1)) != 0) { 646 : /* LCOV_EXCL_START */ 647 : log_fatal(EUSER, "Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line); 648 : exit(EXIT_FAILURE); 649 : /* LCOV_EXCL_STOP */ 650 : } - 651 278 : state->block_size *= KIBI; - 652 6410 : } else if (strcmp(tag, "hashsize") == 0 - 653 6410 : || strcmp(tag, "hash_size") == 0 /* v11.0 used incorrectly this one, kept now for backward compatibility */ + 651 279 : state->block_size *= KIBI; + 652 6453 : } else if (strcmp(tag, "hashsize") == 0 + 653 6453 : || strcmp(tag, "hash_size") == 0 /* v11.0 used incorrectly this one, kept now for backward compatibility */ 654 0 : ) { 655 : uint32_t hash_size; 656 : @@ -744,7 +744,7 @@ 682 : } 683 : 684 0 : BLOCK_HASH_SIZE = hash_size; - 685 6410 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { + 685 6453 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { 686 : char device[PATH_MAX]; 687 : char* split_map[SPLIT_MAX + 1]; 688 : unsigned split_mac; @@ -752,59 +752,59 @@ 690 : uint64_t dev; 691 : int skip_access; 692 : - 693 1334 : if (state->parity[level].split_mac != 0) { + 693 1336 : if (state->parity[level].split_mac != 0) { 694 : /* LCOV_EXCL_START */ 695 : log_fatal(EUSER, "Multiple '%s' specification in '%s' at line %u\n", tag, path, line); 696 : exit(EXIT_FAILURE); 697 : /* LCOV_EXCL_STOP */ 698 : } 699 : - 700 1334 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 701 1334 : if (ret < 0) { + 700 1336 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 701 1336 : if (ret < 0) { 702 : /* LCOV_EXCL_START */ 703 : log_fatal(EUSER, "Invalid '%s' specification in '%s' at line %u\n", tag, path, line); 704 : exit(EXIT_FAILURE); 705 : /* LCOV_EXCL_STOP */ 706 : } 707 : - 708 1334 : if (!*buffer) { + 708 1336 : if (!*buffer) { 709 : /* LCOV_EXCL_START */ 710 : log_fatal(EUSER, "Empty '%s' specification in '%s' at line %u\n", tag, path, line); 711 : exit(EXIT_FAILURE); 712 : /* LCOV_EXCL_STOP */ 713 : } 714 : - 715 1334 : split_mac = strsplit(split_map, SPLIT_MAX + 1, buffer, ","); + 715 1336 : split_mac = strsplit(split_map, SPLIT_MAX + 1, buffer, ","); 716 : - 717 1334 : if (split_mac > SPLIT_MAX) { + 717 1336 : if (split_mac > SPLIT_MAX) { 718 : /* LCOV_EXCL_START */ 719 : log_fatal(EUSER, "Too many files in '%s' specification in '%s' at line %u\n", tag, path, line); 720 : exit(EXIT_FAILURE); 721 : /* LCOV_EXCL_STOP */ 722 : } 723 : - 724 1334 : skip_access = 0; - 725 1334 : state->parity[level].split_mac = split_mac; - 726 6666 : for (s = 0; s < split_mac; ++s) { + 724 1336 : skip_access = 0; + 725 1336 : state->parity[level].split_mac = split_mac; + 726 6670 : for (s = 0; s < split_mac; ++s) { 727 : char uuid[UUID_MAX]; - 728 5333 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]); + 728 5335 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]); 729 : - 730 5333 : if (!state->opt.skip_parity_access) { + 730 5335 : if (!state->opt.skip_parity_access) { 731 : struct stat st; 732 : 733 : /* get the device of the directory containing the parity file */ - 734 4621 : pathimport(device, sizeof(device), split_map[s]); - 735 4621 : slash = strrchr(device, '/'); - 736 4621 : if (slash) - 737 4621 : *slash = 0; + 734 4623 : pathimport(device, sizeof(device), split_map[s]); + 735 4623 : slash = strrchr(device, '/'); + 736 4623 : if (slash) + 737 4623 : *slash = 0; 738 : else 739 0 : pathcpy(device, sizeof(device), "."); 740 : - 741 4621 : if (stat(device, &st) == 0) { - 742 4616 : dev = st.st_dev; + 741 4623 : if (stat(device, &st) == 0) { + 742 4618 : dev = st.st_dev; 743 : 744 : /* read the uuid, if unsupported use an empty one */ - 745 4616 : if (devuuid(dev, split_map[s], uuid, sizeof(uuid)) != 0) { + 745 4618 : if (devuuid(dev, split_map[s], uuid, sizeof(uuid)) != 0) { 746 0 : *uuid = 0; 747 : } 748 : } else { @@ -833,17 +833,17 @@ 771 712 : *uuid = 0; 772 : } 773 : - 774 5332 : state->parity[level].split_map[s].device = dev; - 775 5332 : pathcpy(state->parity[level].split_map[s].uuid, sizeof(state->parity[level].split_map[s].uuid), uuid); + 774 5334 : state->parity[level].split_map[s].device = dev; + 775 5334 : pathcpy(state->parity[level].split_map[s].uuid, sizeof(state->parity[level].split_map[s].uuid), uuid); 776 : } 777 : 778 : /* store the global parity skip_access */ - 779 1333 : state->parity[level].skip_access = skip_access; + 779 1335 : state->parity[level].skip_access = skip_access; 780 : 781 : /* adjust the level */ - 782 1333 : if (state->level < level + 1) - 783 1055 : state->level = level + 1; - 784 5076 : } else if (strcmp(tag, "share") == 0) { + 782 1335 : if (state->level < level + 1) + 783 1056 : state->level = level + 1; + 784 5117 : } else if (strcmp(tag, "share") == 0) { 785 43 : if (*state->share) { 786 : /* LCOV_EXCL_START */ 787 : log_fatal(EUSER, "Multiple 'share' specification in '%s' at line %u\n", path, line); @@ -867,65 +867,65 @@ 805 : } 806 : 807 43 : pathimport(state->share, sizeof(state->share), buffer); - 808 5033 : } else if (strcmp(tag, "pool") == 0) { + 808 5074 : } else if (strcmp(tag, "pool") == 0) { 809 : struct stat st; 810 : - 811 43 : if (*state->pool) { + 811 44 : if (*state->pool) { 812 : /* LCOV_EXCL_START */ 813 : log_fatal(EUSER, "Multiple 'pool' specification in '%s' at line %u\n", path, line); 814 : exit(EXIT_FAILURE); 815 : /* LCOV_EXCL_STOP */ 816 : } 817 : - 818 43 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 819 43 : if (ret < 0) { + 818 44 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 819 44 : if (ret < 0) { 820 : /* LCOV_EXCL_START */ 821 : log_fatal(EUSER, "Invalid 'pool' specification in '%s' at line %u\n", path, line); 822 : exit(EXIT_FAILURE); 823 : /* LCOV_EXCL_STOP */ 824 : } 825 : - 826 43 : if (!*buffer) { + 826 44 : if (!*buffer) { 827 : /* LCOV_EXCL_START */ 828 : log_fatal(EUSER, "Empty 'pool' specification in '%s' at line %u\n", path, line); 829 : exit(EXIT_FAILURE); 830 : /* LCOV_EXCL_STOP */ 831 : } 832 : - 833 43 : pathimport(state->pool, sizeof(state->pool), buffer); + 833 44 : pathimport(state->pool, sizeof(state->pool), buffer); 834 : 835 : /* get the device of the directory containing the pool tree */ - 836 43 : if (stat(buffer, &st) != 0) { + 836 44 : if (stat(buffer, &st) != 0) { 837 : /* LCOV_EXCL_START */ 838 : log_fatal(errno, "Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); 839 : exit(EXIT_FAILURE); 840 : /* LCOV_EXCL_STOP */ 841 : } 842 : - 843 43 : state->pool_device = st.st_dev; - 844 4990 : } else if (strcmp(tag, "content") == 0) { + 843 44 : state->pool_device = st.st_dev; + 844 5030 : } else if (strcmp(tag, "content") == 0) { 845 : struct snapraid_content* content; 846 : char device[PATH_MAX]; 847 : char* slash; 848 : struct stat st; 849 : uint64_t dev; 850 : - 851 1605 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 852 1605 : if (ret < 0) { + 851 1609 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 852 1609 : if (ret < 0) { 853 : /* LCOV_EXCL_START */ 854 : log_fatal(EUSER, "Invalid 'content' specification in '%s' at line %u\n", path, line); 855 : exit(EXIT_FAILURE); 856 : /* LCOV_EXCL_STOP */ 857 : } 858 : - 859 1605 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { + 859 1609 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { 860 : /* LCOV_EXCL_START */ 861 : log_fatal(EUSER, "You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); 862 : exit(EXIT_FAILURE); 863 : /* LCOV_EXCL_STOP */ 864 : } 865 : - 866 1605 : if (!*buffer) { + 866 1609 : if (!*buffer) { 867 : /* LCOV_EXCL_START */ 868 : log_fatal(EUSER, "Empty 'content' specification in '%s' at line %u\n", path, line); 869 : exit(EXIT_FAILURE); @@ -933,12 +933,12 @@ 871 : } 872 : 873 : /* check if the content file is already specified */ - 874 6010 : for (i = state->contentlist; i != 0; i = i->next) { - 875 4405 : content = i->data; - 876 4405 : if (pathcmp(content->content, buffer) == 0) + 874 6020 : for (i = state->contentlist; i != 0; i = i->next) { + 875 4411 : content = i->data; + 876 4411 : if (pathcmp(content->content, buffer) == 0) 877 0 : break; 878 : } - 879 1605 : if (i) { + 879 1609 : if (i) { 880 : /* LCOV_EXCL_START */ 881 : log_fatal(EUSER, "Duplicate 'content' specification in '%s' at line %u\n", path, line); 882 : exit(EXIT_FAILURE); @@ -946,14 +946,14 @@ 884 : } 885 : 886 : /* get the device of the directory containing the content file */ - 887 1605 : pathimport(device, sizeof(device), buffer); - 888 1605 : slash = strrchr(device, '/'); - 889 1605 : if (slash) - 890 1605 : *(slash + 1) = 0; + 887 1609 : pathimport(device, sizeof(device), buffer); + 888 1609 : slash = strrchr(device, '/'); + 889 1609 : if (slash) + 890 1609 : *(slash + 1) = 0; 891 : else 892 0 : pathcpy(device, sizeof(device), "."); - 893 1605 : if (stat(device, &st) == 0) { - 894 1604 : dev = st.st_dev; + 893 1609 : if (stat(device, &st) == 0) { + 894 1608 : dev = st.st_dev; 895 : } else { 896 1 : if (state->opt.skip_content_access) { 897 : /* use a fake device */ @@ -968,15 +968,15 @@ 906 : } 907 : 908 : /* set the lock file at the first accessible content file */ - 909 1605 : if (state->lockfile[0] == 0 && dev != 0) { - 910 277 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); - 911 277 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); + 909 1609 : if (state->lockfile[0] == 0 && dev != 0) { + 910 278 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); + 911 278 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); 912 : } 913 : - 914 1605 : content = content_alloc(buffer, dev); + 914 1609 : content = content_alloc(buffer, dev); 915 : - 916 1605 : tommy_list_insert_tail(&state->contentlist, &content->node, content); - 917 5042 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) { + 916 1609 : tommy_list_insert_tail(&state->contentlist, &content->node, content); + 917 5088 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) { 918 : /* "disk" is the deprecated name up to SnapRAID 9.x */ 919 : char dir[PATH_MAX]; 920 : char device[PATH_MAX]; @@ -985,32 +985,32 @@ 923 : uint64_t dev; 924 : int skip_access; 925 : - 926 1657 : ret = sgettok(f, buffer, sizeof(buffer)); - 927 1657 : if (ret < 0) { + 926 1667 : ret = sgettok(f, buffer, sizeof(buffer)); + 927 1667 : if (ret < 0) { 928 : /* LCOV_EXCL_START */ 929 : log_fatal(EUSER, "Invalid 'data' name specification in '%s' at line %u\n", path, line); 930 : exit(EXIT_FAILURE); 931 : /* LCOV_EXCL_STOP */ 932 : } 933 : - 934 1657 : if (!*buffer) { + 934 1667 : if (!*buffer) { 935 : /* LCOV_EXCL_START */ 936 : log_fatal(EUSER, "Empty 'data' name specification in '%s' at line %u\n", path, line); 937 : exit(EXIT_FAILURE); 938 : /* LCOV_EXCL_STOP */ 939 : } 940 : - 941 1657 : sgetspace(f); + 941 1667 : sgetspace(f); 942 : - 943 1657 : ret = sgetlasttok(f, dir, sizeof(dir)); - 944 1657 : if (ret < 0) { + 943 1667 : ret = sgetlasttok(f, dir, sizeof(dir)); + 944 1667 : if (ret < 0) { 945 : /* LCOV_EXCL_START */ 946 : log_fatal(EUSER, "Invalid 'data' dir specification in '%s' at line %u\n", path, line); 947 : exit(EXIT_FAILURE); 948 : /* LCOV_EXCL_STOP */ 949 : } 950 : - 951 1657 : if (!*dir) { + 951 1667 : if (!*dir) { 952 : /* LCOV_EXCL_START */ 953 : log_fatal(EUSER, "Empty 'data' dir specification in '%s' at line %u\n", path, line); 954 : exit(EXIT_FAILURE); @@ -1018,15 +1018,15 @@ 956 : } 957 : 958 : /* get the device of the dir */ - 959 1657 : pathimport(device, sizeof(device), dir); + 959 1667 : pathimport(device, sizeof(device), dir); 960 : 961 : /* check if the disk name already exists */ - 962 5787 : for (i = state->disklist; i != 0; i = i->next) { - 963 4130 : disk = i->data; - 964 4130 : if (strcmp(disk->name, buffer) == 0) + 962 5842 : for (i = state->disklist; i != 0; i = i->next) { + 963 4175 : disk = i->data; + 964 4175 : if (strcmp(disk->name, buffer) == 0) 965 0 : break; 966 : } - 967 1657 : if (i) { + 967 1667 : if (i) { 968 : /* LCOV_EXCL_START */ 969 : log_fatal(EUSER, "Duplicate 'data' name '%s' at line %u\n", buffer, line); 970 : exit(EXIT_FAILURE); @@ -1034,20 +1034,20 @@ 972 : } 973 : 974 : /* if the disk has to be present */ - 975 1657 : skip_access = 0; - 976 1657 : if (!state->opt.skip_disk_access) { + 975 1667 : skip_access = 0; + 976 1667 : if (!state->opt.skip_disk_access) { 977 : struct stat st; 978 : - 979 1501 : if (stat(device, &st) == 0) { - 980 1500 : dev = st.st_dev; + 979 1511 : if (stat(device, &st) == 0) { + 980 1510 : dev = st.st_dev; 981 : 982 : /* read the uuid, if unsupported use an empty one */ - 983 1500 : if (devuuid(dev, dir, uuid, sizeof(uuid)) != 0) { + 983 1510 : if (devuuid(dev, dir, uuid, sizeof(uuid)) != 0) { 984 0 : *uuid = 0; 985 : } 986 : 987 : /* fake a different UUID when testing */ - 988 1500 : if (state->opt.fake_uuid) { + 988 1510 : if (state->opt.fake_uuid) { 989 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid); 990 2 : --state->opt.fake_uuid; 991 : } @@ -1077,10 +1077,10 @@ 1015 156 : *uuid = 0; 1016 : } 1017 : - 1018 1657 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access); + 1018 1667 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access); 1019 : - 1020 1657 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); - 1021 1728 : } else if (strcmp(tag, "smartctl") == 0) { + 1020 1667 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 1021 1754 : } else if (strcmp(tag, "smartctl") == 0) { 1022 : char custom[PATH_MAX]; 1023 : 1024 384 : ret = sgettok(f, buffer, sizeof(buffer)); @@ -1157,7 +1157,7 @@ 1095 : 1096 192 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); 1097 : } - 1098 1344 : } else if (strcmp(tag, "smartignore") == 0) { + 1098 1370 : } else if (strcmp(tag, "smartignore") == 0) { 1099 : int* smart; 1100 : 1101 382 : ret = sgettok(f, buffer, sizeof(buffer)); @@ -1244,71 +1244,71 @@ 1182 : exit(EXIT_FAILURE); 1183 : /* LCOV_EXCL_STOP */ 1184 : } - 1185 962 : } else if (strcmp(tag, "temp_limit") == 0) { + 1185 988 : } else if (strcmp(tag, "temp_limit") == 0) { 1186 : unsigned temp; 1187 : - 1188 1 : ret = sgetu32(f, &temp); - 1189 1 : if (ret < 0) { + 1188 2 : ret = sgetu32(f, &temp); + 1189 2 : if (ret < 0) { 1190 : /* LCOV_EXCL_START */ 1191 : log_fatal(EUSER, "Invalid 'temp_limit' specification in '%s' at line %u\n", path, line); 1192 : exit(EXIT_FAILURE); 1193 : /* LCOV_EXCL_STOP */ 1194 : } - 1195 1 : if (temp < 40 || temp > 70) { + 1195 2 : if (temp < 40 || temp > 70) { 1196 : /* LCOV_EXCL_START */ 1197 : log_fatal(EUSER, "Invalid 'temp_limit' temperature specification in '%s' at line %u. It must be between 40 and 70\n", path, line); 1198 : exit(EXIT_FAILURE); 1199 : /* LCOV_EXCL_STOP */ 1200 : } 1201 : - 1202 1 : state->thermal_temperature_limit = temp; - 1203 961 : } else if (strcmp(tag, "temp_sleep") == 0) { + 1202 2 : state->thermal_temperature_limit = temp; + 1203 986 : } else if (strcmp(tag, "temp_sleep") == 0) { 1204 : unsigned time; 1205 : - 1206 1 : ret = sgetu32(f, &time); - 1207 1 : if (ret < 0) { + 1206 2 : ret = sgetu32(f, &time); + 1207 2 : if (ret < 0) { 1208 : /* LCOV_EXCL_START */ 1209 : log_fatal(EUSER, "Invalid 'temp_sleep' specification in '%s' at line %u\n", path, line); 1210 : exit(EXIT_FAILURE); 1211 : /* LCOV_EXCL_STOP */ 1212 : } - 1213 1 : if (time < 3 || time > 120) { + 1213 2 : if (time < 3 || time > 120) { 1214 : /* LCOV_EXCL_START */ 1215 : log_fatal(EUSER, "Invalid 'temp_sleep' temperature specification in '%s' at line %u. It must be between 3 and 120\n", path, line); 1216 : exit(EXIT_FAILURE); 1217 : /* LCOV_EXCL_STOP */ 1218 : } 1219 : - 1220 1 : state->thermal_cooldown_time = time * 60; - 1221 960 : } else if (strcmp(tag, "nohidden") == 0) { + 1220 2 : state->thermal_cooldown_time = time * 60; + 1221 984 : } else if (strcmp(tag, "nohidden") == 0) { 1222 0 : state->filter_hidden = 1; - 1223 960 : } else if (strcmp(tag, "exclude") == 0) { + 1223 984 : } else if (strcmp(tag, "exclude") == 0) { 1224 : struct snapraid_filter* filter; 1225 : - 1226 277 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1227 277 : if (ret < 0) { + 1226 282 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1227 282 : if (ret < 0) { 1228 : /* LCOV_EXCL_START */ 1229 : log_fatal(EUSER, "Invalid 'exclude' specification in '%s' at line %u\n", path, line); 1230 : exit(EXIT_FAILURE); 1231 : /* LCOV_EXCL_STOP */ 1232 : } 1233 : - 1234 277 : if (!*buffer) { + 1234 282 : if (!*buffer) { 1235 : /* LCOV_EXCL_START */ 1236 : log_fatal(EUSER, "Empty 'exclude' specification in '%s' at line %u\n", path, line); 1237 : exit(EXIT_FAILURE); 1238 : /* LCOV_EXCL_STOP */ 1239 : } 1240 : - 1241 277 : filter = filter_alloc_file(-1, "", buffer); - 1242 277 : if (!filter) { + 1241 282 : filter = filter_alloc_file(-1, "", buffer); + 1242 282 : if (!filter) { 1243 : /* LCOV_EXCL_START */ 1244 : log_fatal(EUSER, "Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); 1245 : exit(EXIT_FAILURE); 1246 : /* LCOV_EXCL_STOP */ 1247 : } - 1248 277 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 1249 683 : } else if (strcmp(tag, "include") == 0) { + 1248 282 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + 1249 702 : } else if (strcmp(tag, "include") == 0) { 1250 : struct snapraid_filter* filter; 1251 : 1252 277 : ret = sgetlasttok(f, buffer, sizeof(buffer)); @@ -1334,27 +1334,27 @@ 1272 : /* LCOV_EXCL_STOP */ 1273 : } 1274 277 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 1275 406 : } else if (strcmp(tag, "autosave") == 0) { + 1275 425 : } else if (strcmp(tag, "autosave") == 0) { 1276 : char* e; 1277 : - 1278 43 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1279 43 : if (ret < 0) { + 1278 44 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1279 44 : if (ret < 0) { 1280 : /* LCOV_EXCL_START */ 1281 : log_fatal(EUSER, "Invalid 'autosave' specification in '%s' at line %u\n", path, line); 1282 : exit(EXIT_FAILURE); 1283 : /* LCOV_EXCL_STOP */ 1284 : } 1285 : - 1286 43 : if (!*buffer) { + 1286 44 : if (!*buffer) { 1287 : /* LCOV_EXCL_START */ 1288 : log_fatal(EUSER, "Empty 'autosave' specification in '%s' at line %u\n", path, line); 1289 : exit(EXIT_FAILURE); 1290 : /* LCOV_EXCL_STOP */ 1291 : } 1292 : - 1293 43 : state->autosave = strtoul(buffer, &e, 0); + 1293 44 : state->autosave = strtoul(buffer, &e, 0); 1294 : - 1295 43 : if (!e || *e) { + 1295 44 : if (!e || *e) { 1296 : /* LCOV_EXCL_START */ 1297 : log_fatal(EUSER, "Invalid 'autosave' specification in '%s' at line %u\n", path, line); 1298 : exit(EXIT_FAILURE); @@ -1362,12 +1362,12 @@ 1300 : } 1301 : 1302 : /* convert to GB */ - 1303 43 : state->autosave *= GIGA; - 1304 363 : } else if (tag[0] == 0) { + 1303 44 : state->autosave *= GIGA; + 1304 381 : } else if (tag[0] == 0) { 1305 : /* allow empty lines */ - 1306 43 : } else if (tag[0] == '#') { - 1307 43 : ret = sgetline(f, buffer, sizeof(buffer)); - 1308 43 : if (ret < 0) { + 1306 52 : } else if (tag[0] == '#') { + 1307 52 : ret = sgetline(f, buffer, sizeof(buffer)); + 1308 52 : if (ret < 0) { 1309 : /* LCOV_EXCL_START */ 1310 : log_fatal(EUSER, "Invalid comment in '%s' at line %u\n", path, line); 1311 : exit(EXIT_FAILURE); @@ -1381,47 +1381,47 @@ 1319 : } 1320 : 1321 : /* skip final spaces */ - 1322 6687 : sgetspace(f); + 1322 6731 : sgetspace(f); 1323 : 1324 : /* next line */ - 1325 6687 : c = sgeteol(f); - 1326 6687 : if (c == EOF) { - 1327 277 : break; + 1325 6731 : c = sgeteol(f); + 1326 6731 : if (c == EOF) { + 1327 278 : break; 1328 : } - 1329 6410 : if (c != '\n') { + 1329 6453 : if (c != '\n') { 1330 : /* LCOV_EXCL_START */ 1331 : log_fatal(EUSER, "Extra data in '%s' at line %u\n", path, line); 1332 : exit(EXIT_FAILURE); 1333 : /* LCOV_EXCL_STOP */ 1334 : } - 1335 6410 : ++line; + 1335 6453 : ++line; 1336 : } 1337 : - 1338 277 : if (serror(f)) { + 1338 278 : if (serror(f)) { 1339 : /* LCOV_EXCL_START */ 1340 : log_fatal(errno, "Error reading the configuration file '%s' at line %u\n", path, line); 1341 : exit(EXIT_FAILURE); 1342 : /* LCOV_EXCL_STOP */ 1343 : } 1344 : - 1345 277 : sclose(f); + 1345 278 : sclose(f); 1346 : - 1347 277 : state_config_check(state, path, filterlist_disk); + 1347 278 : state_config_check(state, path, filterlist_disk); 1348 : 1349 : /* select the default hash */ - 1350 277 : if (state->opt.force_murmur3) { + 1350 278 : if (state->opt.force_murmur3) { 1351 1 : state->besthash = HASH_MURMUR3; - 1352 276 : } else if (state->opt.force_spooky2) { + 1352 277 : } else if (state->opt.force_spooky2) { 1353 1 : state->besthash = HASH_SPOOKY2; 1354 : } else { - 1355 275 : state->besthash = membesthash(); + 1355 276 : state->besthash = membesthash(); 1356 : } 1357 : 1358 : /* by default use the best hash */ - 1359 277 : state->hash = state->besthash; + 1359 278 : state->hash = state->besthash; 1360 : 1361 : /* by default use a random hash seed */ - 1362 277 : if (randomize(state->hashseed, HASH_MAX) != 0) { + 1362 278 : if (randomize(state->hashseed, HASH_MAX) != 0) { 1363 : /* LCOV_EXCL_START */ 1364 : log_fatal(errno, "Failed to retrieve random values.\n"); 1365 : exit(EXIT_FAILURE); @@ -1429,50 +1429,50 @@ 1367 : } 1368 : 1369 : /* no previous hash by default */ - 1370 277 : state->prevhash = HASH_UNDEFINED; + 1370 278 : state->prevhash = HASH_UNDEFINED; 1371 : 1372 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ 1373 : - 1374 277 : log_tag("blocksize:%u\n", state->block_size); - 1375 1934 : for (i = state->disklist; i != 0; i = i->next) { - 1376 1657 : struct snapraid_disk* disk = i->data; - 1377 1657 : log_tag("data:%s:%s:%s\n", disk->name, disk->dir, disk->uuid); + 1374 278 : log_tag("blocksize:%u\n", state->block_size); + 1375 1945 : for (i = state->disklist; i != 0; i = i->next) { + 1376 1667 : struct snapraid_disk* disk = i->data; + 1377 1667 : log_tag("data:%s:%s:%s\n", disk->name, disk->dir, disk->uuid); 1378 : } 1379 : - 1380 277 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); - 1381 1605 : for (l = 0; l < state->level; ++l) { - 1382 1328 : log_tag("%s:%s:%s\n", lev_config_name(l), state->parity[l].split_map[0].path, state->parity[l].split_map[0].uuid); - 1383 5312 : for (s = 1; s < state->parity[l].split_mac; ++s) { + 1380 278 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); + 1381 1608 : for (l = 0; l < state->level; ++l) { + 1382 1330 : log_tag("%s:%s:%s\n", lev_config_name(l), state->parity[l].split_map[0].path, state->parity[l].split_map[0].uuid); + 1383 5314 : for (s = 1; s < state->parity[l].split_mac; ++s) { 1384 3984 : log_tag("%s/%u:%s:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path, state->parity[l].split_map[s].uuid); 1385 : } 1386 : } - 1387 277 : if (state->pool[0] != 0) - 1388 43 : log_tag("pool:%s\n", state->pool); - 1389 277 : if (state->share[0] != 0) + 1387 278 : if (state->pool[0] != 0) + 1388 44 : log_tag("pool:%s\n", state->pool); + 1389 278 : if (state->share[0] != 0) 1390 43 : log_tag("share:%s\n", state->share); - 1391 277 : if (state->autosave != 0) - 1392 43 : log_tag("autosave:%" PRIu64 "\n", state->autosave); - 1393 831 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { + 1391 278 : if (state->autosave != 0) + 1392 44 : log_tag("autosave:%" PRIu64 "\n", state->autosave); + 1393 837 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { 1394 : char out[PATH_MAX]; - 1395 554 : struct snapraid_filter* filter = i->data; - 1396 554 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); + 1395 559 : struct snapraid_filter* filter = i->data; + 1396 559 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); 1397 : } - 1398 277 : if (state->filter_hidden) + 1398 278 : if (state->filter_hidden) 1399 0 : log_tag("filter:nohidden:\n"); - 1400 277 : log_flush(); + 1400 278 : log_flush(); 1401 : } 1402 : 1403 : /** 1404 : * Find a disk by name. 1405 : */ - 1406 7508 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) + 1406 7496 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) 1407 : { 1408 : tommy_node* i; 1409 : - 1410 26199 : for (i = state->disklist; i != 0; i = i->next) { - 1411 26191 : struct snapraid_disk* disk = i->data; - 1412 26191 : if (strcmp(disk->name, name) == 0) - 1413 7500 : return disk; + 1410 26157 : for (i = state->disklist; i != 0; i = i->next) { + 1411 26149 : struct snapraid_disk* disk = i->data; + 1412 26149 : if (strcmp(disk->name, name) == 0) + 1413 7488 : return disk; 1414 : } 1415 : 1416 8 : if (state->no_conf) { @@ -1859,18 +1859,18 @@ 1797 : * 1798 : * Note that position with only DELETED blocks are discharged. 1799 : */ - 1800 800411 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) + 1800 793414 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) 1801 : { 1802 : tommy_node* i; 1803 : 1804 : /* check for each disk */ - 1805 858937 : for (i = state->disklist; i != 0; i = i->next) { - 1806 857059 : struct snapraid_disk* disk = i->data; - 1807 857059 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1805 851308 : for (i = state->disklist; i != 0; i = i->next) { + 1806 849430 : struct snapraid_disk* disk = i->data; + 1807 849430 : struct snapraid_block* block = fs_par2block_find(disk, pos); 1808 : 1809 : /* if we have at least one file, the position is needed */ - 1810 857059 : if (block_has_file(block)) - 1811 798533 : return 1; + 1810 849430 : if (block_has_file(block)) + 1811 791536 : return 1; 1812 : } 1813 : 1814 1878 : return 0; @@ -1925,11 +1925,11 @@ 1863 : /** 1864 : * Check if a block position in a disk is deleted. 1865 : */ - 1866 4795496 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) + 1866 4753514 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) 1867 : { - 1868 4795496 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1868 4753514 : struct snapraid_block* block = fs_par2block_find(disk, pos); 1869 : - 1870 4795496 : return block_state_get(block) == BLOCK_STATE_DELETED; + 1870 4753514 : return block_state_get(block) == BLOCK_STATE_DELETED; 1871 : } 1872 : 1873 : /** @@ -1940,24 +1940,24 @@ 1878 : * 1879 : * This means that DELETED blocks won't necessarily imply an invalid parity. 1880 : */ - 1881 2406326 : static int fs_is_block_unsynced(struct snapraid_state* state, block_off_t pos) + 1881 2399329 : static int fs_is_block_unsynced(struct snapraid_state* state, block_off_t pos) 1882 : { - 1883 2406326 : int one_invalid = 0; - 1884 2406326 : int one_valid = 0; - 1885 15549374 : for (tommy_node* i = state->disklist; i != 0; i = i->next) { - 1886 13367674 : struct snapraid_disk* disk = i->data; - 1887 13367674 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1883 2399329 : int one_invalid = 0; + 1884 2399329 : int one_valid = 0; + 1885 15500777 : for (tommy_node* i = state->disklist; i != 0; i = i->next) { + 1886 13326011 : struct snapraid_disk* disk = i->data; + 1887 13326011 : struct snapraid_block* block = fs_par2block_find(disk, pos); 1888 : - 1889 13367674 : if (block_has_file(block)) - 1890 13039655 : one_valid = 1; - 1891 13367674 : if (block_has_invalid_parity(block)) - 1892 225298 : one_invalid = 1; + 1889 13326011 : if (block_has_file(block)) + 1890 12998715 : one_valid = 1; + 1891 13326011 : if (block_has_invalid_parity(block)) + 1892 225235 : one_invalid = 1; 1893 : - 1894 13367674 : if (one_invalid && one_valid) - 1895 224626 : return 1; + 1894 13326011 : if (one_invalid && one_valid) + 1895 224563 : return 1; 1896 : } 1897 : - 1898 2181700 : return 0; + 1898 2174766 : return 0; 1899 : } 1900 : 1901 : /** @@ -2079,16 +2079,16 @@ 2017 : /* LCOV_EXCL_STOP */ 2018 : } 2019 : - 2020 3858136 : while (1) { + 2020 3858173 : while (1) { 2021 : int c; 2022 : 2023 : /* read the command */ - 2024 3858401 : c = sgetc(f); - 2025 3858401 : if (c == EOF) { + 2024 3858438 : c = sgetc(f); + 2025 3858438 : if (c == EOF) { 2026 264 : break; 2027 : } 2028 : - 2029 3858137 : if (c == 'f') { + 2029 3858174 : if (c == 'f') { 2030 : /* file */ 2031 : char sub[PATH_MAX]; 2032 : uint64_t v_size; @@ -2100,25 +2100,25 @@ 2038 : struct snapraid_disk* disk; 2039 : uint32_t mapping; 2040 : - 2041 3730251 : ret = sgetb32(f, &mapping); - 2042 3730251 : if (ret < 0 || mapping >= mapping_max) { + 2041 3730288 : ret = sgetb32(f, &mapping); + 2042 3730288 : if (ret < 0 || mapping >= mapping_max) { 2043 : /* LCOV_EXCL_START */ 2044 : decoding_error(path, f); 2045 : log_fatal(EINTERNAL, "Internal inconsistency: File mapping index out of range\n"); 2046 : os_abort(); 2047 : /* LCOV_EXCL_STOP */ 2048 : } - 2049 3730251 : disk = tommy_array_get(&disk_mapping, mapping); + 2049 3730288 : disk = tommy_array_get(&disk_mapping, mapping); 2050 : - 2051 3730251 : ret = sgetb64(f, &v_size); - 2052 3730251 : if (ret < 0) { + 2051 3730288 : ret = sgetb64(f, &v_size); + 2052 3730288 : if (ret < 0) { 2053 : /* LCOV_EXCL_START */ 2054 : decoding_error(path, f); 2055 : os_abort(); 2056 : /* LCOV_EXCL_STOP */ 2057 : } 2058 : - 2059 3730251 : if (state->block_size == 0) { + 2059 3730288 : if (state->block_size == 0) { 2060 : /* LCOV_EXCL_START */ 2061 : decoding_error(path, f); 2062 : log_fatal(EINTERNAL, "Internal inconsistency: Zero blocksize\n"); @@ -2127,7 +2127,7 @@ 2065 : } 2066 : 2067 : /* check for impossible file size to avoid to crash for a too big allocation */ - 2068 3730251 : if (v_size / state->block_size > blockmax) { + 2068 3730288 : if (v_size / state->block_size > blockmax) { 2069 : /* LCOV_EXCL_START */ 2070 : decoding_error(path, f); 2071 : log_fatal(EINTERNAL, "Internal inconsistency: File size too big!\n"); @@ -2135,16 +2135,16 @@ 2073 : /* LCOV_EXCL_STOP */ 2074 : } 2075 : - 2076 3730251 : ret = sgetb64(f, &v_mtime_sec); - 2077 3730251 : if (ret < 0) { + 2076 3730288 : ret = sgetb64(f, &v_mtime_sec); + 2077 3730288 : if (ret < 0) { 2078 : /* LCOV_EXCL_START */ 2079 : decoding_error(path, f); 2080 : os_abort(); 2081 : /* LCOV_EXCL_STOP */ 2082 : } 2083 : - 2084 3730251 : ret = sgetb32(f, &v_mtime_nsec); - 2085 3730251 : if (ret < 0) { + 2084 3730288 : ret = sgetb32(f, &v_mtime_nsec); + 2085 3730288 : if (ret < 0) { 2086 : /* LCOV_EXCL_START */ 2087 : decoding_error(path, f); 2088 : os_abort(); @@ -2152,27 +2152,27 @@ 2090 : } 2091 : 2092 : /* STAT_NSEC_INVALID is encoded as 0 */ - 2093 3730251 : if (v_mtime_nsec == 0) + 2093 3730288 : if (v_mtime_nsec == 0) 2094 0 : v_mtime_nsec = STAT_NSEC_INVALID; 2095 : else - 2096 3730251 : --v_mtime_nsec; + 2096 3730288 : --v_mtime_nsec; 2097 : - 2098 3730251 : ret = sgetb64(f, &v_inode); - 2099 3730251 : if (ret < 0) { + 2098 3730288 : ret = sgetb64(f, &v_inode); + 2099 3730288 : if (ret < 0) { 2100 : /* LCOV_EXCL_START */ 2101 : decoding_error(path, f); 2102 : os_abort(); 2103 : /* LCOV_EXCL_STOP */ 2104 : } 2105 : - 2106 3730251 : ret = sgetbs(f, sub, sizeof(sub)); - 2107 3730251 : if (ret < 0) { + 2106 3730288 : ret = sgetbs(f, sub, sizeof(sub)); + 2107 3730288 : if (ret < 0) { 2108 : /* LCOV_EXCL_START */ 2109 : decoding_error(path, f); 2110 : os_abort(); 2111 : /* LCOV_EXCL_STOP */ 2112 : } - 2113 3730251 : if (!*sub) { + 2113 3730288 : if (!*sub) { 2114 : /* LCOV_EXCL_START */ 2115 : decoding_error(path, f); 2116 : log_fatal(EINTERNAL, "Internal inconsistency: Null file!\n"); @@ -2181,40 +2181,40 @@ 2119 : } 2120 : 2121 : /* allocate the file */ - 2122 3730251 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); + 2122 3730288 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); 2123 : 2124 : /* insert the file in the file containers */ - 2125 3730251 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - 2126 3730251 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 2127 3730251 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); - 2128 3730251 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 2125 3730288 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 2126 3730288 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 2127 3730288 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 2128 3730288 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); 2129 : 2130 : /* read all the blocks */ - 2131 3730251 : v_idx = 0; - 2132 7481190 : while (v_idx < file->blockmax) { + 2131 3730288 : v_idx = 0; + 2132 7481233 : while (v_idx < file->blockmax) { 2133 : block_off_t v_pos; 2134 : uint32_t v_count; 2135 : 2136 : /* get the "subcommand */ - 2137 3750939 : c = sgetc(f); + 2137 3750945 : c = sgetc(f); 2138 : - 2139 3750939 : ret = sgetb32(f, &v_pos); - 2140 3750939 : if (ret < 0) { + 2139 3750945 : ret = sgetb32(f, &v_pos); + 2140 3750945 : if (ret < 0) { 2141 : /* LCOV_EXCL_START */ 2142 : decoding_error(path, f); 2143 : os_abort(); 2144 : /* LCOV_EXCL_STOP */ 2145 : } 2146 : - 2147 3750939 : ret = sgetb32(f, &v_count); - 2148 3750939 : if (ret < 0) { + 2147 3750945 : ret = sgetb32(f, &v_count); + 2148 3750945 : if (ret < 0) { 2149 : /* LCOV_EXCL_START */ 2150 : decoding_error(path, f); 2151 : os_abort(); 2152 : /* LCOV_EXCL_STOP */ 2153 : } 2154 : - 2155 3750939 : if (v_idx + v_count > file->blockmax) { + 2155 3750945 : if (v_idx + v_count > file->blockmax) { 2156 : /* LCOV_EXCL_START */ 2157 : decoding_error(path, f); 2158 : log_fatal(EINTERNAL, "Internal inconsistency: Block number out of range\n"); @@ -2222,7 +2222,7 @@ 2160 : /* LCOV_EXCL_STOP */ 2161 : } 2162 : - 2163 3750939 : if (v_pos + v_count > blockmax) { + 2163 3750945 : if (v_pos + v_count > blockmax) { 2164 : /* LCOV_EXCL_START */ 2165 : decoding_error(path, f); 2166 : log_fatal(EINTERNAL, "Internal inconsistency: Block size %u/%u!\n", blockmax, v_pos + v_count); @@ -2257,9 +2257,9 @@ 2195 : } 2196 : 2197 : /* read the hash only for 'blk/chg/rep', and not for 'new' */ - 2198 9195780 : if (c != 'n') { - 2199 9195780 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); - 2200 9195780 : if (ret < 0) { + 2198 9195879 : if (c != 'n') { + 2199 9195879 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); + 2200 9195879 : if (ret < 0) { 2201 : /* LCOV_EXCL_START */ 2202 : decoding_error(path, f); 2203 : os_abort(); @@ -2272,8 +2272,8 @@ 2210 : 2211 : /* if the block contains a hash of past data */ 2212 : /* and we are clearing such indeterminate hashes */ - 2213 9195780 : if (state->clear_past_hash - 2214 2686312 : && block_has_past_hash(block) + 2213 9195879 : if (state->clear_past_hash + 2214 2686411 : && block_has_past_hash(block) 2215 : ) { 2216 : /* set the hash value to INVALID */ 2217 28006 : hash_invalid_set(block->hash); @@ -2284,8 +2284,8 @@ 2222 : /* in other sync commands */ 2223 : /* note that this is required only in sync, and we detect */ 2224 : /* this using the clear_past_hash flag */ - 2225 9195780 : if (state->clear_past_hash - 2226 2686312 : && state->opt.force_nocopy + 2225 9195879 : if (state->clear_past_hash + 2226 2686411 : && state->opt.force_nocopy 2227 14195 : && block_state_get(block) == BLOCK_STATE_REP 2228 : ) { 2229 : /* set the hash value to INVALID */ @@ -2295,17 +2295,17 @@ 2233 : } 2234 : 2235 : /* set the parity association */ - 2236 9195780 : fs_allocate(disk, v_pos, file, v_idx); + 2236 9195879 : fs_allocate(disk, v_pos, file, v_idx); 2237 : 2238 : /* go to the next block */ - 2239 9195780 : ++v_idx; - 2240 9195780 : ++v_pos; - 2241 9195780 : --v_count; + 2239 9195879 : ++v_idx; + 2240 9195879 : ++v_pos; + 2241 9195879 : --v_count; 2242 : } 2243 : } 2244 : 2245 : /* stat */ - 2246 3730251 : ++count_file; + 2246 3730288 : ++count_file; 2247 127886 : } else if (c == 'i') { 2248 : /* "inf" command */ 2249 : snapraid_info info; @@ -2321,7 +2321,7 @@ 2259 : } 2260 : 2261 264 : v_pos = 0; - 2262 53184 : while (v_pos < blockmax) { + 2262 41996 : while (v_pos < blockmax) { 2263 : int bad; 2264 : int rehash; 2265 : int justsynced; @@ -2329,15 +2329,15 @@ 2267 : uint32_t flag; 2268 : uint32_t v_count; 2269 : - 2270 52920 : ret = sgetb32(f, &v_count); - 2271 52920 : if (ret < 0) { + 2270 41732 : ret = sgetb32(f, &v_count); + 2271 41732 : if (ret < 0) { 2272 : /* LCOV_EXCL_START */ 2273 : decoding_error(path, f); 2274 : os_abort(); 2275 : /* LCOV_EXCL_STOP */ 2276 : } 2277 : - 2278 52920 : if (v_pos + v_count > blockmax) { + 2278 41732 : if (v_pos + v_count > blockmax) { 2279 : /* LCOV_EXCL_START */ 2280 : decoding_error(path, f); 2281 : log_fatal(EINTERNAL, "Internal inconsistency: Info size %u/%u!\n", blockmax, v_pos + v_count); @@ -2345,8 +2345,8 @@ 2283 : /* LCOV_EXCL_STOP */ 2284 : } 2285 : - 2286 52920 : ret = sgetb32(f, &flag); - 2287 52920 : if (ret < 0) { + 2286 41732 : ret = sgetb32(f, &flag); + 2287 41732 : if (ret < 0) { 2288 : /* LCOV_EXCL_START */ 2289 : decoding_error(path, f); 2290 : os_abort(); @@ -2354,10 +2354,10 @@ 2292 : } 2293 : 2294 : /* if there is an info */ - 2295 52920 : if ((flag & 1) != 0) { + 2295 41732 : if ((flag & 1) != 0) { 2296 : /* read the time */ - 2297 52903 : ret = sgetb64(f, &t64); - 2298 52903 : if (ret < 0) { + 2297 41715 : ret = sgetb64(f, &t64); + 2298 41715 : if (ret < 0) { 2299 : /* LCOV_EXCL_START */ 2300 : decoding_error(path, f); 2301 : os_abort(); @@ -2365,18 +2365,18 @@ 2303 : } 2304 : 2305 : /* analyze the flags */ - 2306 52903 : bad = (flag & 2) != 0; - 2307 52903 : rehash = (flag & 4) != 0; - 2308 52903 : justsynced = (flag & 8) != 0; + 2306 41715 : bad = (flag & 2) != 0; + 2307 41715 : rehash = (flag & 4) != 0; + 2308 41715 : justsynced = (flag & 8) != 0; 2309 : - 2310 52903 : if (bad) - 2311 5274 : count_bad += v_count; - 2312 52903 : if (rehash) - 2313 14426 : count_rehash += v_count; - 2314 52903 : if (justsynced) - 2315 31663 : count_unscrubbed += v_count; + 2310 41715 : if (bad) + 2311 5276 : count_bad += v_count; + 2312 41715 : if (rehash) + 2313 14181 : count_rehash += v_count; + 2314 41715 : if (justsynced) + 2315 20481 : count_unscrubbed += v_count; 2316 : - 2317 52903 : if (rehash && state->prevhash == HASH_UNDEFINED) { + 2317 41715 : if (rehash && state->prevhash == HASH_UNDEFINED) { 2318 : /* LCOV_EXCL_START */ 2319 : decoding_error(path, f); 2320 : log_fatal(EINTERNAL, "Internal inconsistency: Missing previous checksum!\n"); @@ -2384,14 +2384,14 @@ 2322 : /* LCOV_EXCL_STOP */ 2323 : } 2324 : - 2325 52903 : info = info_make(t64 + v_oldest, bad, rehash, justsynced); + 2325 41715 : info = info_make(t64 + v_oldest, bad, rehash, justsynced); 2326 : - 2327 52903 : bucket_insert(&bucket_hash, t64 + v_oldest, v_count, justsynced); + 2327 41715 : bucket_insert(&bucket_hash, t64 + v_oldest, v_count, justsynced); 2328 : } else { 2329 17 : info = 0; 2330 : } 2331 : - 2332 1658835 : while (v_count) { + 2332 1647647 : while (v_count) { 2333 : /* insert the info in the array */ 2334 1605915 : info_set(&state->infoarr, v_pos, info); 2335 : @@ -3227,15 +3227,15 @@ 3165 : unsigned count_unscrubbed; 3166 : }; 3167 : - 3168 157 : static void* state_write_thread(void* arg) + 3168 156 : static void* state_write_thread(void* arg) 3169 : { - 3170 157 : struct state_write_thread_context* context = arg; - 3171 157 : struct snapraid_state* state = context->state; - 3172 157 : block_off_t blockmax = context->blockmax; - 3173 157 : time_t info_oldest = context->info_oldest; - 3174 157 : time_t info_now = context->info_now; - 3175 157 : int info_has_rehash = context->info_has_rehash; - 3176 157 : STREAM* f = context->f; + 3170 156 : struct state_write_thread_context* context = arg; + 3171 156 : struct snapraid_state* state = context->state; + 3172 156 : block_off_t blockmax = context->blockmax; + 3173 156 : time_t info_oldest = context->info_oldest; + 3174 156 : time_t info_now = context->info_now; + 3175 156 : int info_has_rehash = context->info_has_rehash; + 3176 156 : STREAM* f = context->f; 3177 : uint32_t crc; 3178 : uint64_t t64; 3179 : unsigned count_file; @@ -3252,40 +3252,40 @@ 3190 : unsigned l, s; 3191 : tommy_hashdyn bucket_hash; 3192 : - 3193 157 : count_file = 0; - 3194 157 : count_hardlink = 0; - 3195 157 : count_symlink = 0; - 3196 157 : count_dir = 0; - 3197 157 : count_bad = 0; - 3198 157 : count_rehash = 0; - 3199 157 : count_unsynced = 0; - 3200 157 : count_unscrubbed = 0; - 3201 157 : tommy_hashdyn_init(&bucket_hash); + 3193 156 : count_file = 0; + 3194 156 : count_hardlink = 0; + 3195 156 : count_symlink = 0; + 3196 156 : count_dir = 0; + 3197 156 : count_bad = 0; + 3198 156 : count_rehash = 0; + 3199 156 : count_unsynced = 0; + 3200 156 : count_unscrubbed = 0; + 3201 156 : tommy_hashdyn_init(&bucket_hash); 3202 : 3203 : /* force version 3 a we want to always store the parity size */ 3204 : /* write header */ - 3205 157 : swrite("SNAPCNT3\n\3\0\0", 12, f); + 3205 156 : swrite("SNAPCNT3\n\3\0\0", 12, f); 3206 : 3207 : /* write block size and block max */ - 3208 157 : sputc('z', f); - 3209 157 : sputb32(state->block_size, f); - 3210 157 : sputc('x', f); - 3211 157 : sputb32(blockmax, f); + 3208 156 : sputc('z', f); + 3209 156 : sputb32(state->block_size, f); + 3210 156 : sputc('x', f); + 3211 156 : sputb32(blockmax, f); 3212 : 3213 : /* hash size */ - 3214 157 : sputc('y', f); - 3215 157 : sputb32(BLOCK_HASH_SIZE, f); + 3214 156 : sputc('y', f); + 3215 156 : sputb32(BLOCK_HASH_SIZE, f); 3216 : - 3217 157 : if (serror(f)) { + 3217 156 : if (serror(f)) { 3218 : /* LCOV_EXCL_START */ 3219 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3220 : goto bail; 3221 : /* LCOV_EXCL_STOP */ 3222 : } 3223 : - 3224 157 : sputc('c', f); - 3225 157 : if (state->hash == HASH_MURMUR3) { - 3226 102 : sputc('u', f); + 3224 156 : sputc('c', f); + 3225 156 : if (state->hash == HASH_MURMUR3) { + 3226 101 : sputc('u', f); 3227 55 : } else if (state->hash == HASH_SPOOKY2) { 3228 55 : sputc('k', f); 3229 0 : } else if (state->hash == HASH_METRO) { @@ -3296,8 +3296,8 @@ 3234 : goto bail; 3235 : /* LCOV_EXCL_STOP */ 3236 : } - 3237 157 : swrite(state->hashseed, HASH_MAX, f); - 3238 157 : if (serror(f)) { + 3237 156 : swrite(state->hashseed, HASH_MAX, f); + 3238 156 : if (serror(f)) { 3239 : /* LCOV_EXCL_START */ 3240 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3241 : goto bail; @@ -3305,7 +3305,7 @@ 3243 : } 3244 : 3245 : /* previous hash only present */ - 3246 157 : if (state->prevhash != HASH_UNDEFINED) { + 3246 156 : if (state->prevhash != HASH_UNDEFINED) { 3247 : /* if at least one rehash tag found, we have to save the previous hash */ 3248 3 : if (info_has_rehash) { 3249 2 : sputc('C', f); @@ -3332,13 +3332,13 @@ 3270 : } 3271 : 3272 : /* for each map */ - 3273 1099 : for (i = state->maplist; i != 0; i = i->next) { - 3274 942 : struct snapraid_map* map = i->data; + 3273 1092 : for (i = state->maplist; i != 0; i = i->next) { + 3274 936 : struct snapraid_map* map = i->data; 3275 : struct snapraid_disk* disk; 3276 : 3277 : /* find the disk for this mapping */ - 3278 942 : disk = find_disk_by_name(state, map->name); - 3279 942 : if (!disk) { + 3278 936 : disk = find_disk_by_name(state, map->name); + 3279 936 : if (!disk) { 3280 : /* LCOV_EXCL_START */ 3281 : log_fatal(EINTERNAL, "Internal inconsistency: Unmapped disk '%s'\n", map->name); 3282 : goto bail; @@ -3346,23 +3346,23 @@ 3284 : } 3285 : 3286 : /* save the mapping only if disk is mapped */ - 3287 942 : if (disk->mapping_idx != -1) { - 3288 850 : sputc('M', f); - 3289 850 : sputbs(map->name, f); - 3290 850 : sputb32(map->position, f); - 3291 850 : sputb32(map->total_blocks, f); - 3292 850 : sputb32(map->free_blocks, f); - 3293 850 : sputbs(map->uuid, f); - 3294 850 : if (context->first) { - 3295 850 : log_tag("content_data:%s:%" PRIi64 ":%" PRIi64 "\n", - 3296 850 : map->name, - 3297 850 : map->total_blocks * (uint64_t)state->block_size, - 3298 850 : map->free_blocks * (uint64_t)state->block_size); - 3299 850 : log_tag("content_data_split:%s:%s\n", - 3300 850 : map->name, - 3301 850 : map->uuid); + 3287 936 : if (disk->mapping_idx != -1) { + 3288 844 : sputc('M', f); + 3289 844 : sputbs(map->name, f); + 3290 844 : sputb32(map->position, f); + 3291 844 : sputb32(map->total_blocks, f); + 3292 844 : sputb32(map->free_blocks, f); + 3293 844 : sputbs(map->uuid, f); + 3294 844 : if (context->first) { + 3295 844 : log_tag("content_data:%s:%" PRIi64 ":%" PRIi64 "\n", + 3296 844 : map->name, + 3297 844 : map->total_blocks * (uint64_t)state->block_size, + 3298 844 : map->free_blocks * (uint64_t)state->block_size); + 3299 844 : log_tag("content_data_split:%s:%s\n", + 3300 844 : map->name, + 3301 844 : map->uuid); 3302 : } - 3303 850 : if (serror(f)) { + 3303 844 : if (serror(f)) { 3304 : /* LCOV_EXCL_START */ 3305 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3306 : goto bail; @@ -3372,36 +3372,36 @@ 3310 : } 3311 : 3312 : /* for each parity */ - 3313 1054 : for (l = 0; l < state->level; ++l) { - 3314 897 : sputc('Q', f); - 3315 897 : sputb32(l, f); - 3316 897 : sputb32(state->parity[l].total_blocks, f); - 3317 897 : sputb32(state->parity[l].free_blocks, f); - 3318 897 : if (context->first) { - 3319 897 : log_tag("content_parity:%s:%" PRIi64 ":%" PRIi64 "\n", + 3313 1047 : for (l = 0; l < state->level; ++l) { + 3314 891 : sputc('Q', f); + 3315 891 : sputb32(l, f); + 3316 891 : sputb32(state->parity[l].total_blocks, f); + 3317 891 : sputb32(state->parity[l].free_blocks, f); + 3318 891 : if (context->first) { + 3319 891 : log_tag("content_parity:%s:%" PRIi64 ":%" PRIi64 "\n", 3320 : lev_config_name(l), - 3321 897 : state->parity[l].total_blocks * (uint64_t)state->block_size, - 3322 897 : state->parity[l].free_blocks * (uint64_t)state->block_size); + 3321 891 : state->parity[l].total_blocks * (uint64_t)state->block_size, + 3322 891 : state->parity[l].free_blocks * (uint64_t)state->block_size); 3323 : } - 3324 897 : sputb32(state->parity[l].split_mac, f); - 3325 4485 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 3324 891 : sputb32(state->parity[l].split_mac, f); + 3325 4455 : for (s = 0; s < state->parity[l].split_mac; ++s) { 3326 : char parity_name[64]; - 3327 3588 : sputbs(state->parity[l].split_map[s].path, f); - 3328 3588 : sputbs(state->parity[l].split_map[s].uuid, f); - 3329 3588 : sputb64(state->parity[l].split_map[s].size, f); - 3330 3588 : if (s == 0) - 3331 897 : pathcpy(parity_name, sizeof(parity_name), lev_config_name(l)); + 3327 3564 : sputbs(state->parity[l].split_map[s].path, f); + 3328 3564 : sputbs(state->parity[l].split_map[s].uuid, f); + 3329 3564 : sputb64(state->parity[l].split_map[s].size, f); + 3330 3564 : if (s == 0) + 3331 891 : pathcpy(parity_name, sizeof(parity_name), lev_config_name(l)); 3332 : else - 3333 2691 : pathprint(parity_name, sizeof(parity_name), "%s/%u", lev_config_name(l), s); - 3334 3588 : if (context->first) { - 3335 3588 : log_tag("content_parity_split:%s:%s:%s:%" PRIi64 "\n", + 3333 2673 : pathprint(parity_name, sizeof(parity_name), "%s/%u", lev_config_name(l), s); + 3334 3564 : if (context->first) { + 3335 3564 : log_tag("content_parity_split:%s:%s:%s:%" PRIi64 "\n", 3336 : parity_name, - 3337 3588 : state->parity[l].split_map[s].uuid, - 3338 3588 : state->parity[l].split_map[s].path, + 3337 3564 : state->parity[l].split_map[s].uuid, + 3338 3564 : state->parity[l].split_map[s].path, 3339 : state->parity[l].split_map[s].size); 3340 : } 3341 : } - 3342 897 : if (serror(f)) { + 3342 891 : if (serror(f)) { 3343 : /* LCOV_EXCL_START */ 3344 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3345 : goto bail; @@ -3410,39 +3410,39 @@ 3348 : } 3349 : 3350 : /* for each disk */ - 3351 1099 : for (i = state->disklist; i != 0; i = i->next) { + 3351 1092 : for (i = state->disklist; i != 0; i = i->next) { 3352 : tommy_node* j; - 3353 942 : struct snapraid_disk* disk = i->data; + 3353 936 : struct snapraid_disk* disk = i->data; 3354 : 3355 : /* if the disk is not mapped, skip it */ - 3356 942 : if (disk->mapping_idx < 0) + 3356 936 : if (disk->mapping_idx < 0) 3357 92 : continue; 3358 : 3359 : /* for each file */ - 3360 1850418 : for (j = disk->filelist; j != 0; j = j->next) { - 3361 1849568 : struct snapraid_file* file = j->data; + 3360 1833655 : for (j = disk->filelist; j != 0; j = j->next) { + 3361 1832811 : struct snapraid_file* file = j->data; 3362 : uint64_t size; 3363 : uint64_t mtime_sec; 3364 : int32_t mtime_nsec; 3365 : uint64_t inode; 3366 : - 3367 1849568 : size = file->size; - 3368 1849568 : mtime_sec = file->mtime_sec; - 3369 1849568 : mtime_nsec = file->mtime_nsec; - 3370 1849568 : inode = file->inode; + 3367 1832811 : size = file->size; + 3368 1832811 : mtime_sec = file->mtime_sec; + 3369 1832811 : mtime_nsec = file->mtime_nsec; + 3370 1832811 : inode = file->inode; 3371 : - 3372 1849568 : sputc('f', f); - 3373 1849568 : sputb32(disk->mapping_idx, f); - 3374 1849568 : sputb64(size, f); - 3375 1849568 : sputb64(mtime_sec, f); + 3372 1832811 : sputc('f', f); + 3373 1832811 : sputb32(disk->mapping_idx, f); + 3374 1832811 : sputb64(size, f); + 3375 1832811 : sputb64(mtime_sec, f); 3376 : /* encode STAT_NSEC_INVALID as 0 */ - 3377 1849568 : if (mtime_nsec == STAT_NSEC_INVALID) + 3377 1832811 : if (mtime_nsec == STAT_NSEC_INVALID) 3378 0 : sputb32(0, f); 3379 : else - 3380 1849568 : sputb32(mtime_nsec + 1, f); - 3381 1849568 : sputb64(inode, f); - 3382 1849568 : sputbs(file->sub, f); - 3383 1849568 : if (serror(f)) { + 3380 1832811 : sputb32(mtime_nsec + 1, f); + 3381 1832811 : sputb64(inode, f); + 3382 1832811 : sputbs(file->sub, f); + 3383 1832811 : if (serror(f)) { 3384 : /* LCOV_EXCL_START */ 3385 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3386 : goto bail; @@ -3450,31 +3450,31 @@ 3388 : } 3389 : 3390 : /* for all the blocks of the file */ - 3391 1849568 : begin = 0; - 3392 3709156 : while (begin < file->blockmax) { - 3393 1859588 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); - 3394 1859588 : block_off_t v_pos = fs_file2par_get(disk, file, begin); + 3391 1832811 : begin = 0; + 3392 3675510 : while (begin < file->blockmax) { + 3393 1842699 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); + 3394 1842699 : block_off_t v_pos = fs_file2par_get(disk, file, begin); 3395 : uint32_t v_count; 3396 : 3397 : block_off_t end; 3398 : 3399 : /* find the end of run of blocks */ - 3400 1859588 : end = begin + 1; - 3401 4569406 : while (end < file->blockmax) { - 3402 2722429 : if (v_state != block_state_get(fs_file2block_get(file, end))) + 3400 1842699 : end = begin + 1; + 3401 4528141 : while (end < file->blockmax) { + 3402 2697897 : if (v_state != block_state_get(fs_file2block_get(file, end))) 3403 12 : break; - 3404 2722417 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end)) - 3405 12599 : break; - 3406 2709818 : ++end; + 3404 2697885 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end)) + 3405 12443 : break; + 3406 2685442 : ++end; 3407 : } 3408 : - 3409 1859588 : switch (v_state) { - 3410 1758705 : case BLOCK_STATE_BLK : - 3411 1758705 : sputc('b', f); - 3412 1758705 : break; - 3413 65965 : case BLOCK_STATE_CHG : - 3414 65965 : sputc('g', f); - 3415 65965 : break; + 3409 1842699 : switch (v_state) { + 3410 1741862 : case BLOCK_STATE_BLK : + 3411 1741862 : sputc('b', f); + 3412 1741862 : break; + 3413 65919 : case BLOCK_STATE_CHG : + 3414 65919 : sputc('g', f); + 3415 65919 : break; 3416 34918 : case BLOCK_STATE_REP : 3417 34918 : sputc('p', f); 3418 34918 : break; @@ -3485,19 +3485,19 @@ 3423 : /* LCOV_EXCL_STOP */ 3424 : } 3425 : - 3426 1859588 : sputb32(v_pos, f); + 3426 1842699 : sputb32(v_pos, f); 3427 : - 3428 1859588 : v_count = end - begin; - 3429 1859588 : sputb32(v_count, f); + 3428 1842699 : v_count = end - begin; + 3429 1842699 : sputb32(v_count, f); 3430 : 3431 : /* write hashes */ - 3432 6428994 : for (idx = begin; idx < end; ++idx) { - 3433 4569406 : struct snapraid_block* block = fs_file2block_get(file, idx); + 3432 6370840 : for (idx = begin; idx < end; ++idx) { + 3433 4528141 : struct snapraid_block* block = fs_file2block_get(file, idx); 3434 : - 3435 4569406 : swrite(block->hash, BLOCK_HASH_SIZE, f); + 3435 4528141 : swrite(block->hash, BLOCK_HASH_SIZE, f); 3436 : } 3437 : - 3438 1859588 : if (serror(f)) { + 3438 1842699 : if (serror(f)) { 3439 : /* LCOV_EXCL_START */ 3440 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3441 : goto bail; @@ -3505,31 +3505,31 @@ 3443 : } 3444 : 3445 : /* next begin position */ - 3446 1859588 : begin = end; + 3446 1842699 : begin = end; 3447 : } 3448 : - 3449 1849568 : ++count_file; + 3449 1832811 : ++count_file; 3450 : } 3451 : 3452 : /* for each link */ - 3453 61524 : for (j = disk->linklist; j != 0; j = j->next) { - 3454 60674 : struct snapraid_link* slink = j->data; + 3453 60974 : for (j = disk->linklist; j != 0; j = j->next) { + 3454 60130 : struct snapraid_link* slink = j->data; 3455 : - 3456 60674 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { - 3457 342 : case FILE_IS_HARDLINK : - 3458 342 : sputc('a', f); - 3459 342 : ++count_hardlink; - 3460 342 : break; - 3461 60332 : case FILE_IS_SYMLINK : - 3462 60332 : sputc('s', f); - 3463 60332 : ++count_symlink; - 3464 60332 : break; + 3456 60130 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { + 3457 339 : case FILE_IS_HARDLINK : + 3458 339 : sputc('a', f); + 3459 339 : ++count_hardlink; + 3460 339 : break; + 3461 59791 : case FILE_IS_SYMLINK : + 3462 59791 : sputc('s', f); + 3463 59791 : ++count_symlink; + 3464 59791 : break; 3465 : } 3466 : - 3467 60674 : sputb32(disk->mapping_idx, f); - 3468 60674 : sputbs(slink->sub, f); - 3469 60674 : sputbs(slink->linkto, f); - 3470 60674 : if (serror(f)) { + 3467 60130 : sputb32(disk->mapping_idx, f); + 3468 60130 : sputbs(slink->sub, f); + 3469 60130 : sputbs(slink->linkto, f); + 3470 60130 : if (serror(f)) { 3471 : /* LCOV_EXCL_START */ 3472 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3473 : goto bail; @@ -3538,49 +3538,49 @@ 3476 : } 3477 : 3478 : /* for each dir */ - 3479 1305 : for (j = disk->dirlist; j != 0; j = j->next) { - 3480 455 : struct snapraid_dir* dir = j->data; + 3479 1295 : for (j = disk->dirlist; j != 0; j = j->next) { + 3480 451 : struct snapraid_dir* dir = j->data; 3481 : - 3482 455 : sputc('r', f); - 3483 455 : sputb32(disk->mapping_idx, f); - 3484 455 : sputbs(dir->sub, f); - 3485 455 : if (serror(f)) { + 3482 451 : sputc('r', f); + 3483 451 : sputb32(disk->mapping_idx, f); + 3484 451 : sputbs(dir->sub, f); + 3485 451 : if (serror(f)) { 3486 : /* LCOV_EXCL_START */ 3487 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3488 : goto bail; 3489 : /* LCOV_EXCL_STOP */ 3490 : } 3491 : - 3492 455 : ++count_dir; + 3492 451 : ++count_dir; 3493 : } 3494 : 3495 : /* deleted blocks of the disk */ - 3496 850 : sputc('h', f); - 3497 850 : sputb32(disk->mapping_idx, f); - 3498 850 : if (serror(f)) { + 3496 844 : sputc('h', f); + 3497 844 : sputb32(disk->mapping_idx, f); + 3498 844 : if (serror(f)) { 3499 : /* LCOV_EXCL_START */ 3500 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3501 : goto bail; 3502 : /* LCOV_EXCL_STOP */ 3503 : } - 3504 850 : begin = 0; - 3505 1777 : while (begin < blockmax) { + 3504 844 : begin = 0; + 3505 1765 : while (begin < blockmax) { 3506 : int is_deleted; 3507 : block_off_t end; 3508 : - 3509 927 : is_deleted = fs_is_block_deleted(disk, begin); + 3509 921 : is_deleted = fs_is_block_deleted(disk, begin); 3510 : 3511 : /* find the end of run of blocks */ - 3512 927 : end = begin + 1; - 3513 927 : while (end < blockmax - 3514 4795419 : && is_deleted == fs_is_block_deleted(disk, end) + 3512 921 : end = begin + 1; + 3513 921 : while (end < blockmax + 3514 4753437 : && is_deleted == fs_is_block_deleted(disk, end) 3515 : ) { - 3516 4794492 : ++end; + 3516 4752516 : ++end; 3517 : } 3518 : - 3519 927 : sputb32(end - begin, f); + 3519 921 : sputb32(end - begin, f); 3520 : - 3521 927 : if (is_deleted) { + 3521 921 : if (is_deleted) { 3522 : /* write the run of deleted blocks with hash */ 3523 49 : sputc('o', f); 3524 : @@ -3595,13 +3595,13 @@ 3533 : } else { 3534 : /* write the run of blocks without hash */ 3535 : /* they can be either used or empty blocks */ - 3536 878 : sputc('O', f); + 3536 872 : sputc('O', f); 3537 : 3538 : /* next begin position */ - 3539 878 : begin = end; + 3539 872 : begin = end; 3540 : } 3541 : - 3542 927 : if (serror(f)) { + 3542 921 : if (serror(f)) { 3543 : /* LCOV_EXCL_START */ 3544 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3545 : goto bail; @@ -3611,82 +3611,82 @@ 3549 : } 3550 : 3551 : /* write the info for each block */ - 3552 157 : sputc('i', f); + 3552 156 : sputc('i', f); 3553 : /* ensure to write a 64 bit time */ - 3554 157 : t64 = info_oldest; - 3555 157 : sputb64(t64, f); - 3556 157 : begin = 0; - 3557 19334 : while (begin < blockmax) { + 3554 156 : t64 = info_oldest; + 3555 156 : sputb64(t64, f); + 3556 156 : begin = 0; + 3557 14427 : while (begin < blockmax) { 3558 : snapraid_info info; 3559 : block_off_t end; 3560 : block_off_t count; 3561 : time_t t; 3562 : unsigned flag; 3563 : - 3564 19177 : info = info_get(&state->infoarr, begin); + 3564 14271 : info = info_get(&state->infoarr, begin); 3565 : 3566 : /* avoid this slow operation if not needed */ - 3567 19177 : if (context->first && fs_is_block_unsynced(state, begin)) - 3568 197 : ++count_unsynced; + 3567 14271 : if (context->first && fs_is_block_unsynced(state, begin)) + 3568 105 : ++count_unsynced; 3569 : 3570 : /* find the end of run of blocks */ - 3571 19177 : end = begin + 1; - 3572 19177 : while (end < blockmax - 3573 800411 : && info == info_get(&state->infoarr, end) + 3571 14271 : end = begin + 1; + 3572 14271 : while (end < blockmax + 3573 793414 : && info == info_get(&state->infoarr, end) 3574 : ) { - 3575 781234 : if (context->first && fs_is_block_unsynced(state, end)) - 3576 111131 : ++count_unsynced; - 3577 781234 : ++end; + 3575 779143 : if (context->first && fs_is_block_unsynced(state, end)) + 3576 111160 : ++count_unsynced; + 3577 779143 : ++end; 3578 : } 3579 : - 3580 19177 : count = end - begin; - 3581 19177 : sputb32(count, f); + 3580 14271 : count = end - begin; + 3581 14271 : sputb32(count, f); 3582 : 3583 : /* if there is info */ - 3584 19177 : if (info) { + 3584 14271 : if (info) { 3585 : /* other flags */ - 3586 19149 : flag = 1; /* info is present */ - 3587 19149 : if (info_get_bad(info)) { + 3586 14243 : flag = 1; /* info is present */ + 3587 14243 : if (info_get_bad(info)) { 3588 1326 : flag |= 2; 3589 1326 : if (context->first) 3590 1326 : count_bad += count; 3591 : } - 3592 19149 : if (info_get_rehash(info)) { - 3593 5212 : flag |= 4; - 3594 5212 : if (context->first) - 3595 5212 : count_rehash += count; + 3592 14243 : if (info_get_rehash(info)) { + 3593 4967 : flag |= 4; + 3594 4967 : if (context->first) + 3595 4967 : count_rehash += count; 3596 : } - 3597 19149 : if (info_get_justsynced(info)) { - 3598 12475 : flag |= 8; - 3599 12475 : if (context->first) - 3600 12475 : count_unscrubbed += count; + 3597 14243 : if (info_get_justsynced(info)) { + 3598 7571 : flag |= 8; + 3599 7571 : if (context->first) + 3600 7571 : count_unscrubbed += count; 3601 : } - 3602 19149 : sputb32(flag, f); + 3602 14243 : sputb32(flag, f); 3603 : - 3604 19149 : t = info_get_time(info); + 3604 14243 : t = info_get_time(info); 3605 : - 3606 19149 : if (context->first) - 3607 19149 : bucket_insert(&bucket_hash, t, count, flag & 8); + 3606 14243 : if (context->first) + 3607 14243 : bucket_insert(&bucket_hash, t, count, flag & 8); 3608 : 3609 : /* truncate any time that is in the future */ - 3610 19149 : if (t > info_now) + 3610 14243 : if (t > info_now) 3611 0 : t = info_now; 3612 : 3613 : /* the oldest info is computed only on required blocks, so it may not be the absolute oldest */ - 3614 19149 : if (t < info_oldest) + 3614 14243 : if (t < info_oldest) 3615 0 : t = 0; 3616 : else - 3617 19149 : t -= info_oldest; + 3617 14243 : t -= info_oldest; 3618 : 3619 : /* ensure to write a 64 bit time */ - 3620 19149 : t64 = t; - 3621 19149 : sputb64(t64, f); + 3620 14243 : t64 = t; + 3621 14243 : sputb64(t64, f); 3622 : } else { 3623 : /* write a special 0 flag to mark missing info */ 3624 28 : sputb32(0, f); 3625 : } 3626 : - 3627 19177 : if (serror(f)) { + 3627 14271 : if (serror(f)) { 3628 : /* LCOV_EXCL_START */ 3629 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3630 : goto bail; @@ -3694,13 +3694,13 @@ 3632 : } 3633 : 3634 : /* next begin position */ - 3635 19177 : begin = end; + 3635 14271 : begin = end; 3636 : } 3637 : - 3638 157 : sputc('N', f); + 3638 156 : sputc('N', f); 3639 : 3640 : /* flush data written to the disk */ - 3641 157 : if (sflush(f)) { + 3641 156 : if (sflush(f)) { 3642 : /* LCOV_EXCL_START */ 3643 : log_fatal(errno, "Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); 3644 : goto bail; @@ -3708,11 +3708,11 @@ 3646 : } 3647 : 3648 : /* get the file crc */ - 3649 157 : crc = scrc(f); + 3649 156 : crc = scrc(f); 3650 : 3651 : /* compare the crc of the data written to file */ 3652 : /* with the one of the data written to the stream */ - 3653 157 : if (crc != scrc_stream(f)) { + 3653 156 : if (crc != scrc_stream(f)) { 3654 : /* LCOV_EXCL_START */ 3655 : log_fatal(ECONTENT, "CRC mismatch while writing the content stream.\n"); 3656 : log_fatal(ECONTENT, "DANGER! Your RAM memory is faulty! DO NOT PROCEED UNTIL FIXED!\n"); @@ -3721,8 +3721,8 @@ 3659 : /* LCOV_EXCL_STOP */ 3660 : } 3661 : - 3662 157 : sputble32(crc, f); - 3663 157 : if (serror(f)) { + 3662 156 : sputble32(crc, f); + 3663 156 : if (serror(f)) { 3664 : /* LCOV_EXCL_START */ 3665 : log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 3666 : goto bail; @@ -3730,29 +3730,29 @@ 3668 : } 3669 : 3670 : /* set output variables */ - 3671 157 : context->crc = crc; - 3672 157 : context->count_file = count_file; - 3673 157 : context->count_hardlink = count_hardlink; - 3674 157 : context->count_symlink = count_symlink; - 3675 157 : context->count_dir = count_dir; - 3676 157 : context->count_bad = count_bad; - 3677 157 : context->count_rehash = count_rehash; - 3678 157 : context->count_unsynced = count_unsynced; - 3679 157 : context->count_unscrubbed = count_unscrubbed; + 3671 156 : context->crc = crc; + 3672 156 : context->count_file = count_file; + 3673 156 : context->count_hardlink = count_hardlink; + 3674 156 : context->count_symlink = count_symlink; + 3675 156 : context->count_dir = count_dir; + 3676 156 : context->count_bad = count_bad; + 3677 156 : context->count_rehash = count_rehash; + 3678 156 : context->count_unsynced = count_unsynced; + 3679 156 : context->count_unscrubbed = count_unscrubbed; 3680 : 3681 : /* store the bucket info list */ - 3682 157 : if (context->first) - 3683 157 : bucket_to_list(&bucket_hash, &state->bucketlist, &state->bucketcount); + 3682 156 : if (context->first) + 3683 156 : bucket_to_list(&bucket_hash, &state->bucketlist, &state->bucketcount); 3684 : - 3685 157 : tommy_hashdyn_done(&bucket_hash); - 3686 157 : return 0; + 3685 156 : tommy_hashdyn_done(&bucket_hash); + 3686 156 : return 0; 3687 : 3688 0 : bail: 3689 0 : tommy_hashdyn_done(&bucket_hash); 3690 0 : return context; 3691 : } 3692 : - 3693 157 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) + 3693 156 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) 3694 : { 3695 : #if HAVE_MT_WRITE 3696 : int fail; @@ -3782,29 +3782,29 @@ 3720 : unsigned count_unscrubbed; 3721 : 3722 : /* blocks of all array */ - 3723 157 : blockmax = parity_allocated_size(state); + 3723 156 : blockmax = parity_allocated_size(state); 3724 : 3725 : /* check the file-system on all disks */ - 3726 157 : state_fscheck(state, "before write"); + 3726 156 : state_fscheck(state, "before write"); 3727 : 3728 : /* clear the info for unused blocks */ 3729 : /* and get some other info */ - 3730 157 : info_oldest = 0; /* oldest time in info */ - 3731 157 : info_now = time(0); /* get the present time */ - 3732 157 : info_has_rehash = 0; /* if there is a rehash info */ - 3733 800568 : for (idx = 0; idx < blockmax; ++idx) { + 3730 156 : info_oldest = 0; /* oldest time in info */ + 3731 156 : info_now = time(0); /* get the present time */ + 3732 156 : info_has_rehash = 0; /* if there is a rehash info */ + 3733 793570 : for (idx = 0; idx < blockmax; ++idx) { 3734 : /* if the position is used */ - 3735 800411 : if (fs_position_is_required(state, idx)) { - 3736 798533 : snapraid_info info = info_get(&state->infoarr, idx); + 3735 793414 : if (fs_position_is_required(state, idx)) { + 3736 791536 : snapraid_info info = info_get(&state->infoarr, idx); 3737 : 3738 : /* only if there is some info to store */ - 3739 798533 : if (info) { - 3740 751146 : time_t info_time = info_get_time(info); + 3739 791536 : if (info) { + 3740 744149 : time_t info_time = info_get_time(info); 3741 : - 3742 751146 : if (!info_oldest || info_time < info_oldest) - 3743 156 : info_oldest = info_time; + 3742 744149 : if (!info_oldest || info_time < info_oldest) + 3743 155 : info_oldest = info_time; 3744 : - 3745 751146 : if (info_get_rehash(info)) + 3745 744149 : if (info_get_rehash(info)) 3746 13822 : info_has_rehash = 1; 3747 : } 3748 : } else { @@ -3817,14 +3817,14 @@ 3755 : } 3756 : 3757 : /* map disks */ - 3758 157 : mapping_idx = 0; - 3759 1099 : for (i = state->maplist; i != 0; i = i->next) { - 3760 942 : struct snapraid_map* map = i->data; + 3758 156 : mapping_idx = 0; + 3759 1092 : for (i = state->maplist; i != 0; i = i->next) { + 3760 936 : struct snapraid_map* map = i->data; 3761 : struct snapraid_disk* disk; 3762 : 3763 : /* find the disk for this mapping */ - 3764 942 : disk = find_disk_by_name(state, map->name); - 3765 942 : if (!disk) { + 3764 936 : disk = find_disk_by_name(state, map->name); + 3765 936 : if (!disk) { 3766 : /* LCOV_EXCL_START */ 3767 : log_fatal(EINTERNAL, "Internal inconsistency: Unmapped disk '%s'\n", map->name); 3768 : os_abort(); @@ -3832,10 +3832,10 @@ 3770 : } 3771 : 3772 : /* save the mapping only for not empty disks */ - 3773 942 : if (!fs_is_empty(disk, blockmax)) { + 3773 936 : if (!fs_is_empty(disk, blockmax)) { 3774 : /* assign the mapping index used to identify disks */ - 3775 850 : disk->mapping_idx = mapping_idx; - 3776 850 : ++mapping_idx; + 3775 844 : disk->mapping_idx = mapping_idx; + 3776 844 : ++mapping_idx; 3777 : } else { 3778 : /* mark the disk as without mapping */ 3779 92 : disk->mapping_idx = -1; @@ -3983,34 +3983,34 @@ 3921 : } 3922 : #else 3923 : /* count the content files */ - 3924 157 : count_content = 0; - 3925 157 : i = tommy_list_head(&state->contentlist); - 3926 1211 : while (i) { - 3927 1054 : struct snapraid_content* content = i->data; - 3928 1054 : msg_progress("Saving state to %s...\n", content->content); - 3929 1054 : ++count_content; - 3930 1054 : i = i->next; + 3924 156 : count_content = 0; + 3925 156 : i = tommy_list_head(&state->contentlist); + 3926 1203 : while (i) { + 3927 1047 : struct snapraid_content* content = i->data; + 3928 1047 : msg_progress("Saving state to %s...\n", content->content); + 3929 1047 : ++count_content; + 3930 1047 : i = i->next; 3931 : } 3932 : 3933 : /* open all the content files */ - 3934 157 : f = sopen_multi_write(count_content, STREAM_FLAGS_SEQUENTIAL | STREAM_FLAGS_CRC); - 3935 157 : if (!f) { + 3934 156 : f = sopen_multi_write(count_content, STREAM_FLAGS_SEQUENTIAL | STREAM_FLAGS_CRC); + 3935 156 : if (!f) { 3936 : /* LCOV_EXCL_START */ 3937 : log_fatal(errno, "Error opening the content files.\n"); 3938 : exit(EXIT_FAILURE); 3939 : /* LCOV_EXCL_STOP */ 3940 : } 3941 : - 3942 157 : k = 0; - 3943 157 : i = tommy_list_head(&state->contentlist); - 3944 1211 : while (i) { - 3945 1054 : struct snapraid_content* content = i->data; + 3942 156 : k = 0; + 3943 156 : i = tommy_list_head(&state->contentlist); + 3944 1203 : while (i) { + 3945 1047 : struct snapraid_content* content = i->data; 3946 : char tmp[PATH_MAX]; - 3947 1054 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3947 1047 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); 3948 : 3949 : /* ensure to delete a previous stale file */ - 3950 1054 : if (remove(tmp) != 0) { - 3951 1054 : if (errno != ENOENT) { + 3950 1047 : if (remove(tmp) != 0) { + 3951 1047 : if (errno != ENOENT) { 3952 : /* LCOV_EXCL_START */ 3953 : log_fatal(errno, "Error removing the stale content file '%s'. %s.\n", tmp, strerror(errno)); 3954 : exit(EXIT_FAILURE); @@ -4018,33 +4018,33 @@ 3956 : } 3957 : } 3958 : - 3959 1054 : if (sopen_multi_file(f, k, tmp) != 0) { + 3959 1047 : if (sopen_multi_file(f, k, tmp) != 0) { 3960 : /* LCOV_EXCL_START */ 3961 : log_fatal(errno, "Error opening the temporary content file '%s'. %s.\n", tmp, strerror(errno)); 3962 : exit(EXIT_FAILURE); 3963 : /* LCOV_EXCL_STOP */ 3964 : } 3965 : - 3966 1054 : ++k; - 3967 1054 : i = i->next; + 3966 1047 : ++k; + 3967 1047 : i = i->next; 3968 : } 3969 : 3970 : /* allocate the thread context */ - 3971 157 : context = malloc_nofail(sizeof(struct state_write_thread_context)); + 3971 156 : context = malloc_nofail(sizeof(struct state_write_thread_context)); 3972 : 3973 : /* initialize */ - 3974 157 : context->state = state; - 3975 157 : context->blockmax = blockmax; - 3976 157 : context->info_oldest = info_oldest; - 3977 157 : context->info_now = info_now; - 3978 157 : context->info_has_rehash = info_has_rehash; - 3979 157 : context->f = f; - 3980 157 : context->first = 1; + 3974 156 : context->state = state; + 3975 156 : context->blockmax = blockmax; + 3976 156 : context->info_oldest = info_oldest; + 3977 156 : context->info_now = info_now; + 3978 156 : context->info_has_rehash = info_has_rehash; + 3979 156 : context->f = f; + 3980 156 : context->first = 1; 3981 : - 3982 157 : retval = state_write_thread(context); + 3982 156 : retval = state_write_thread(context); 3983 : 3984 : /* abort on failure */ - 3985 157 : if (retval) { + 3985 156 : if (retval) { 3986 : /* LCOV_EXCL_START */ 3987 : exit(EXIT_FAILURE); 3988 : /* LCOV_EXCL_STOP */ @@ -4052,7 +4052,7 @@ 3990 : 3991 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ 3992 : /* than even in a system crash event we have one valid copy of the file. */ - 3993 157 : if (sflush(f) != 0) { + 3993 156 : if (sflush(f) != 0) { 3994 : /* LCOV_EXCL_START */ 3995 : log_fatal(errno, "Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); 3996 : exit(EXIT_FAILURE); @@ -4060,7 +4060,7 @@ 3998 : } 3999 : 4000 : #if HAVE_FSYNC - 4001 157 : if (ssync(f) != 0) { + 4001 156 : if (ssync(f) != 0) { 4002 : /* LCOV_EXCL_START */ 4003 : log_fatal(errno, "Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); 4004 : exit(EXIT_FAILURE); @@ -4068,50 +4068,50 @@ 4006 : } 4007 : #endif 4008 : - 4009 157 : if (sclose(f) != 0) { + 4009 156 : if (sclose(f) != 0) { 4010 : /* LCOV_EXCL_START */ 4011 : log_fatal(errno, "Error closing the content file. %s.\n", strerror(errno)); 4012 : exit(EXIT_FAILURE); 4013 : /* LCOV_EXCL_STOP */ 4014 : } 4015 : - 4016 157 : crc = context->crc; - 4017 157 : count_file = context->count_file; - 4018 157 : count_hardlink = context->count_hardlink; - 4019 157 : count_symlink = context->count_symlink; - 4020 157 : count_dir = context->count_dir; - 4021 157 : count_bad = context->count_bad; - 4022 157 : count_rehash = context->count_rehash; - 4023 157 : count_unsynced = context->count_unsynced; - 4024 157 : count_unscrubbed = context->count_unscrubbed; + 4016 156 : crc = context->crc; + 4017 156 : count_file = context->count_file; + 4018 156 : count_hardlink = context->count_hardlink; + 4019 156 : count_symlink = context->count_symlink; + 4020 156 : count_dir = context->count_dir; + 4021 156 : count_bad = context->count_bad; + 4022 156 : count_rehash = context->count_rehash; + 4023 156 : count_unsynced = context->count_unsynced; + 4024 156 : count_unscrubbed = context->count_unscrubbed; 4025 : - 4026 157 : free(context); + 4026 156 : free(context); 4027 : #endif 4028 : - 4029 157 : msg_verbose("%8u files\n", count_file); - 4030 157 : msg_verbose("%8u hardlinks\n", count_hardlink); - 4031 157 : msg_verbose("%8u symlinks\n", count_symlink); - 4032 157 : msg_verbose("%8u empty dirs\n", count_dir); + 4029 156 : msg_verbose("%8u files\n", count_file); + 4030 156 : msg_verbose("%8u hardlinks\n", count_hardlink); + 4031 156 : msg_verbose("%8u symlinks\n", count_symlink); + 4032 156 : msg_verbose("%8u empty dirs\n", count_dir); 4033 : - 4034 157 : log_tag("content_info:file:%u\n", count_file); - 4035 157 : log_tag("content_info:hardlink:%u\n", count_hardlink); - 4036 157 : log_tag("content_info:symlink:%u\n", count_symlink); - 4037 157 : log_tag("content_info:dir_empty:%u\n", count_dir); + 4034 156 : log_tag("content_info:file:%u\n", count_file); + 4035 156 : log_tag("content_info:hardlink:%u\n", count_hardlink); + 4036 156 : log_tag("content_info:symlink:%u\n", count_symlink); + 4037 156 : log_tag("content_info:dir_empty:%u\n", count_dir); 4038 : - 4039 157 : log_tag("content_info:block:%u\n", blockmax); - 4040 157 : log_tag("content_info:block_bad:%u\n", count_bad); - 4041 157 : log_tag("content_info:block_rehash:%u\n", count_rehash); - 4042 157 : log_tag("content_info:block_unsynced:%u\n", count_unsynced); - 4043 157 : log_tag("content_info:block_unscrubbed:%u\n", count_unscrubbed); + 4039 156 : log_tag("content_info:block:%u\n", blockmax); + 4040 156 : log_tag("content_info:block_bad:%u\n", count_bad); + 4041 156 : log_tag("content_info:block_rehash:%u\n", count_rehash); + 4042 156 : log_tag("content_info:block_unsynced:%u\n", count_unsynced); + 4043 156 : log_tag("content_info:block_unscrubbed:%u\n", count_unscrubbed); 4044 : 4045 : /* store the blocks counters */ - 4046 157 : state->rehash_blocks = count_rehash; - 4047 157 : state->bad_blocks = count_bad; - 4048 157 : state->unsynced_blocks = count_unsynced; - 4049 157 : state->unscrubbed_blocks = count_unscrubbed; + 4046 156 : state->rehash_blocks = count_rehash; + 4047 156 : state->bad_blocks = count_bad; + 4048 156 : state->unsynced_blocks = count_unsynced; + 4049 156 : state->unscrubbed_blocks = count_unscrubbed; 4050 : - 4051 157 : *out_crc = crc; - 4052 157 : } + 4051 156 : *out_crc = crc; + 4052 156 : } 4053 : 4054 272 : void state_read(struct snapraid_state* state) 4055 : { @@ -4275,19 +4275,19 @@ 4213 : STREAM* f; 4214 : }; 4215 : - 4216 1054 : static void* state_verify_thread(void* arg) + 4216 1047 : static void* state_verify_thread(void* arg) 4217 : { - 4218 1054 : struct state_verify_thread_context* context = arg; - 4219 1054 : struct snapraid_content* content = context->content; - 4220 1054 : STREAM* f = context->f; + 4218 1047 : struct state_verify_thread_context* context = arg; + 4219 1047 : struct snapraid_content* content = context->content; + 4220 1047 : STREAM* f = context->f; 4221 : unsigned char buf[4]; 4222 : uint32_t crc_stored; 4223 : uint32_t crc_computed; 4224 : uint64_t start; 4225 : - 4226 1054 : start = tick_ms(); + 4226 1047 : start = tick_ms(); 4227 : - 4228 1054 : if (sdeplete(f, buf) != 0) { + 4228 1047 : if (sdeplete(f, buf) != 0) { 4229 : /* LCOV_EXCL_START */ 4230 : log_fatal(errno, "Failed to flush content file '%s'. %s.\n", serrorfile(f), strerror(errno)); 4231 : return context; @@ -4295,9 +4295,9 @@ 4233 : } 4234 : 4235 : /* get the stored crc from the last four bytes */ - 4236 1054 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + 4236 1047 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; 4237 : - 4238 1054 : if (crc_stored != context->crc) { + 4238 1047 : if (crc_stored != context->crc) { 4239 : /* LCOV_EXCL_START */ 4240 : log_fatal(ECONTENT, "DANGER! Wrong stored CRC in '%s'\n", serrorfile(f)); 4241 : return context; @@ -4305,41 +4305,41 @@ 4243 : } 4244 : 4245 : /* get the computed crc */ - 4246 1054 : crc_computed = scrc(f); + 4246 1047 : crc_computed = scrc(f); 4247 : 4248 : /* adjust the stored crc to include itself */ - 4249 1054 : crc_stored = crc32c(crc_stored, buf, 4); + 4249 1047 : crc_stored = crc32c(crc_stored, buf, 4); 4250 : - 4251 1054 : if (crc_computed != crc_stored) { + 4251 1047 : if (crc_computed != crc_stored) { 4252 : /* LCOV_EXCL_START */ 4253 : log_fatal(ECONTENT, "DANGER! Wrong file CRC in '%s'\n", serrorfile(f)); 4254 : return context; 4255 : /* LCOV_EXCL_STOP */ 4256 : } 4257 : - 4258 1054 : msg_progress("Verified %s in %" PRIu64 " seconds\n", content->content, (tick_ms() - start) / 1000); + 4258 1047 : msg_progress("Verified %s in %" PRIu64 " seconds\n", content->content, (tick_ms() - start) / 1000); 4259 : - 4260 1054 : return 0; + 4260 1047 : return 0; 4261 : } 4262 : - 4263 157 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) + 4263 156 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) 4264 : { 4265 : tommy_node* i; 4266 : int fail; 4267 : - 4268 157 : msg_progress("Verifying...\n"); + 4268 156 : msg_progress("Verifying...\n"); 4269 : 4270 : /* start all reading threads */ - 4271 157 : i = tommy_list_head(&state->contentlist); - 4272 1211 : while (i) { - 4273 1054 : struct snapraid_content* content = i->data; + 4271 156 : i = tommy_list_head(&state->contentlist); + 4272 1203 : while (i) { + 4273 1047 : struct snapraid_content* content = i->data; 4274 : struct state_verify_thread_context* context; 4275 : char tmp[PATH_MAX]; 4276 : STREAM* f; 4277 : - 4278 1054 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 4279 1054 : f = sopen_read(tmp, STREAM_FLAGS_SEQUENTIAL | STREAM_FLAGS_CRC); - 4280 1054 : if (f == 0) { + 4278 1047 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 4279 1047 : f = sopen_read(tmp, STREAM_FLAGS_SEQUENTIAL | STREAM_FLAGS_CRC); + 4280 1047 : if (f == 0) { 4281 : /* LCOV_EXCL_START */ 4282 : log_fatal(errno, "Error reopening the temporary content file '%s'. %s.\n", tmp, strerror(errno)); 4283 : exit(EXIT_FAILURE); @@ -4347,45 +4347,45 @@ 4285 : } 4286 : 4287 : /* allocate the thread context */ - 4288 1054 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); - 4289 1054 : content->context = context; + 4288 1047 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); + 4289 1047 : content->context = context; 4290 : 4291 : /* initialize */ - 4292 1054 : context->state = state; - 4293 1054 : context->content = content; - 4294 1054 : context->crc = crc; - 4295 1054 : context->f = f; + 4292 1047 : context->state = state; + 4293 1047 : context->content = content; + 4294 1047 : context->crc = crc; + 4295 1047 : context->f = f; 4296 : 4297 : #if HAVE_MT_VERIFY - 4298 1054 : thread_create(&context->thread, state_verify_thread, context); + 4298 1047 : thread_create(&context->thread, state_verify_thread, context); 4299 : #else 4300 : context->retval = state_verify_thread(context); 4301 : #endif 4302 : - 4303 1054 : i = i->next; + 4303 1047 : i = i->next; 4304 : } 4305 : 4306 : /* join all thread */ - 4307 157 : fail = 0; - 4308 157 : i = tommy_list_head(&state->contentlist); - 4309 1211 : while (i) { - 4310 1054 : struct snapraid_content* content = i->data; - 4311 1054 : struct state_verify_thread_context* context = content->context; + 4307 156 : fail = 0; + 4308 156 : i = tommy_list_head(&state->contentlist); + 4309 1203 : while (i) { + 4310 1047 : struct snapraid_content* content = i->data; + 4311 1047 : struct state_verify_thread_context* context = content->context; 4312 : void* retval; 4313 : 4314 : #if HAVE_MT_VERIFY - 4315 1054 : thread_join(context->thread, &retval); + 4315 1047 : thread_join(context->thread, &retval); 4316 : #else 4317 : retval = context->retval; 4318 : #endif - 4319 1054 : if (retval) { + 4319 1047 : if (retval) { 4320 : /* LCOV_EXCL_START */ 4321 : fail = 1; 4322 : /* LCOV_EXCL_STOP */ 4323 : } else { - 4324 1054 : STREAM* f = context->f; + 4324 1047 : STREAM* f = context->f; 4325 : - 4326 1054 : if (sclose(f) != 0) { + 4326 1047 : if (sclose(f) != 0) { 4327 : /* LCOV_EXCL_START */ 4328 : log_fatal(errno, "Error closing the content file. %s.\n", strerror(errno)); 4329 : exit(EXIT_FAILURE); @@ -4393,20 +4393,20 @@ 4331 : } 4332 : } 4333 : - 4334 1054 : free(context); + 4334 1047 : free(context); 4335 : - 4336 1054 : i = i->next; + 4336 1047 : i = i->next; 4337 : } 4338 : 4339 : /* abort on failure */ - 4340 157 : if (fail) { + 4340 156 : if (fail) { 4341 : /* LCOV_EXCL_START */ 4342 : exit(EXIT_FAILURE); 4343 : /* LCOV_EXCL_STOP */ 4344 : } - 4345 157 : } + 4345 156 : } 4346 : - 4347 157 : static void state_rename_content(struct snapraid_state* state) + 4347 156 : static void state_rename_content(struct snapraid_state* state) 4348 : { 4349 : tommy_node* i; 4350 : @@ -4463,42 +4463,42 @@ 4401 : i = i->next; 4402 : } 4403 : #else - 4404 157 : i = tommy_list_head(&state->contentlist); - 4405 1211 : while (i) { - 4406 1054 : struct snapraid_content* content = i->data; + 4404 156 : i = tommy_list_head(&state->contentlist); + 4405 1203 : while (i) { + 4406 1047 : struct snapraid_content* content = i->data; 4407 : char tmp[PATH_MAX]; 4408 : 4409 : /* now renames the just written copy with the correct name */ - 4410 1054 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 4411 1054 : if (rename(tmp, content->content) != 0) { + 4410 1047 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 4411 1047 : if (rename(tmp, content->content) != 0) { 4412 : /* LCOV_EXCL_START */ 4413 : log_fatal(errno, "Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); 4414 : exit(EXIT_FAILURE); 4415 : /* LCOV_EXCL_STOP */ 4416 : } 4417 : - 4418 1054 : i = i->next; + 4418 1047 : i = i->next; 4419 : } 4420 : #endif - 4421 157 : } + 4421 156 : } 4422 : - 4423 157 : void state_write(struct snapraid_state* state) + 4423 156 : void state_write(struct snapraid_state* state) 4424 : { 4425 : uint32_t crc; 4426 : 4427 : /* write all the content files */ - 4428 157 : state_write_content(state, &crc); + 4428 156 : state_write_content(state, &crc); 4429 : 4430 : /* verify the just written files */ - 4431 157 : state_verify_content(state, crc); + 4431 156 : state_verify_content(state, crc); 4432 : 4433 : /* rename the new files, over the old ones */ - 4434 157 : state_rename_content(state); + 4434 156 : state_rename_content(state); 4435 : - 4436 157 : state->need_write = 0; /* no write needed anymore */ - 4437 157 : state->checked_read = 0; /* what we wrote is not checked in read */ - 4438 157 : state->written = 1; - 4439 157 : } + 4436 156 : state->need_write = 0; /* no write needed anymore */ + 4437 156 : state->checked_read = 0; /* what we wrote is not checked in read */ + 4438 156 : state->written = 1; + 4439 156 : } 4440 : 4441 123 : void state_skip(struct snapraid_state* state) 4442 : { @@ -4574,7 +4574,7 @@ 4512 75254 : || filter_existence(filter_missing, disk->dir, file->sub) != 0 4513 35762 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 4514 : ) { - 4515 112402 : file_flag_set(file, FILE_IS_EXCLUDED); + 4515 112357 : file_flag_set(file, FILE_IS_EXCLUDED); 4516 : } 4517 : } 4518 : @@ -4665,8 +4665,8 @@ 4603 5 : log_tag("run:end\n"); 4604 5 : log_flush(); 4605 222 : } else if (countmax == 0) { - 4606 20 : if (state->need_write || state->written) { - 4607 15 : msg_status("100%% completed\n"); + 4606 21 : if (state->need_write || state->written) { + 4607 16 : msg_status("100%% completed\n"); 4608 : } else { 4609 5 : msg_status("%s", msg); 4610 : } @@ -4674,18 +4674,18 @@ 4612 : time_t now; 4613 : time_t elapsed; 4614 : - 4615 202 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; + 4615 201 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; 4616 : - 4617 202 : now = time(0); + 4617 201 : now = time(0); 4618 : - 4619 202 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 4619 201 : elapsed = now - state->progress_whole_start - state->progress_wasted; 4620 : - 4621 202 : msg_bar("%u%% completed, %u MB accessed", muldiv(countpos, 100, countmax), countsize_MB); + 4621 201 : msg_bar("%u%% completed, %u MB accessed", muldiv(countpos, 100, countmax), countsize_MB); 4622 : - 4623 202 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); + 4623 201 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); 4624 : - 4625 202 : msg_bar("\n"); - 4626 202 : msg_flush(); + 4625 201 : msg_bar("\n"); + 4626 201 : msg_flush(); 4627 : } 4628 227 : } 4629 : @@ -4715,23 +4715,23 @@ 4653 : /** 4654 : * Set the latest tick data in the progress vector. 4655 : */ - 4656 493 : static void state_progress_latest(struct snapraid_state* state) + 4656 481 : static void state_progress_latest(struct snapraid_state* state) 4657 : { 4658 : tommy_node* i; 4659 : unsigned l; 4660 : - 4661 493 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc; - 4662 493 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched; - 4663 493 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid; - 4664 493 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash; - 4665 493 : state->progress_tick_io[state->progress_ptr] = state->tick_io; - 4666 3442 : for (i = state->disklist; i != 0; i = i->next) { - 4667 2949 : struct snapraid_disk* disk = i->data; - 4668 2949 : disk->progress_tick[state->progress_ptr] = disk->tick; + 4661 481 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc; + 4662 481 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched; + 4663 481 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid; + 4664 481 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash; + 4665 481 : state->progress_tick_io[state->progress_ptr] = state->tick_io; + 4666 3358 : for (i = state->disklist; i != 0; i = i->next) { + 4667 2877 : struct snapraid_disk* disk = i->data; + 4668 2877 : disk->progress_tick[state->progress_ptr] = disk->tick; 4669 : } - 4670 2881 : for (l = 0; l < state->level; ++l) - 4671 2388 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick; - 4672 493 : } + 4670 2837 : for (l = 0; l < state->level; ++l) + 4671 2356 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick; + 4672 481 : } 4673 : 4674 : /** 4675 : * Number of columns @@ -4964,54 +4964,54 @@ 4902 2 : printf("\n"); 4903 : } 4904 : - 4905 1075966 : 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) + 4905 1075903 : 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) 4906 : { 4907 : time_t now; 4908 : int pred; 4909 : - 4910 1075966 : now = time(0); + 4910 1075903 : now = time(0); 4911 : 4912 : /* thermal measure */ - 4913 1075966 : if (now > state->thermal_latest + THERMAL_PERIOD_SECONDS || state->opt.fake_device) { - 4914 2613 : state->thermal_latest = now; - 4915 2613 : state_thermal(state, now); + 4913 1075903 : if (now > state->thermal_latest + THERMAL_PERIOD_SECONDS || state->opt.fake_device) { + 4914 2612 : state->thermal_latest = now; + 4915 2612 : state_thermal(state, now); 4916 : } 4917 : 4918 : /* previous position */ - 4919 1075966 : pred = state->progress_ptr + PROGRESS_MAX - 1; - 4920 1075966 : if (pred >= PROGRESS_MAX) - 4921 1075763 : pred -= PROGRESS_MAX; + 4919 1075903 : pred = state->progress_ptr + PROGRESS_MAX - 1; + 4920 1075903 : if (pred >= PROGRESS_MAX) + 4921 1075701 : pred -= PROGRESS_MAX; 4922 : 4923 : /* if the previous measure is different */ - 4924 1075966 : if (state->progress_tick == 0 - 4925 1075763 : || state->progress_time[pred] != now + 4924 1075903 : if (state->progress_tick == 0 + 4925 1075701 : || state->progress_time[pred] != now 4926 : ) { 4927 : time_t elapsed; - 4928 391 : unsigned out_perc = 0; - 4929 391 : unsigned out_size_speed = 0; - 4930 391 : unsigned out_block_speed = 0; - 4931 391 : unsigned out_cpu = 0; - 4932 391 : unsigned out_eta = 0; - 4933 391 : int out_temperature = 0; - 4934 391 : int out_steady = 0; - 4935 391 : int out_computed = 0; + 4928 379 : unsigned out_perc = 0; + 4929 379 : unsigned out_size_speed = 0; + 4930 379 : unsigned out_block_speed = 0; + 4931 379 : unsigned out_cpu = 0; + 4932 379 : unsigned out_eta = 0; + 4933 379 : int out_temperature = 0; + 4934 379 : int out_steady = 0; + 4935 379 : int out_computed = 0; 4936 : 4937 : /* store the new measure */ - 4938 391 : state->progress_time[state->progress_ptr] = now; - 4939 391 : state->progress_pos[state->progress_ptr] = countpos; - 4940 391 : state->progress_size[state->progress_ptr] = countsize; - 4941 391 : state_progress_latest(state); + 4938 379 : state->progress_time[state->progress_ptr] = now; + 4939 379 : state->progress_pos[state->progress_ptr] = countpos; + 4940 379 : state->progress_size[state->progress_ptr] = countsize; + 4941 379 : state_progress_latest(state); 4942 : - 4943 391 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 4943 379 : elapsed = now - state->progress_whole_start - state->progress_wasted; 4944 : 4945 : /* completion percentage */ - 4946 391 : if (countmax) - 4947 391 : out_perc = muldiv(countpos, 100, countmax); + 4946 379 : if (countmax) + 4947 379 : out_perc = muldiv(countpos, 100, countmax); 4948 : 4949 : /* if we have at least 5 measures */ - 4950 391 : if (state->progress_tick >= 5 + 4950 379 : if (state->progress_tick >= 5 4951 : /* or if we are running in test mode, with at least one measure */ - 4952 390 : || (state->opt.force_progress && state->progress_tick >= 1) + 4952 377 : || (state->opt.force_progress && state->progress_tick >= 1) 4953 : ) { 4954 : int oldest; 4955 : int past; @@ -5027,142 +5027,142 @@ 4965 : tommy_node* i; 4966 : 4967 : /* number of past measures */ - 4968 188 : past = state->progress_tick; + 4968 177 : past = state->progress_tick; 4969 : 4970 : /* drop the oldest ones, to promptly */ 4971 : /* skip the startup phase */ - 4972 188 : past -= past / 5; + 4972 177 : past -= past / 5; 4973 : 4974 : /* check how much we can go in the past */ - 4975 188 : if (past >= PROGRESS_MAX - 1) { + 4975 177 : if (past >= PROGRESS_MAX - 1) { 4976 : /* the vector is filled, so we are already in position */ 4977 : /* to get the possible oldest one */ 4978 0 : oldest = state->progress_ptr + 1; 4979 : } else { 4980 : /* go backward the number of positions selected */ - 4981 188 : oldest = state->progress_ptr + PROGRESS_MAX - past; + 4981 177 : oldest = state->progress_ptr + PROGRESS_MAX - past; 4982 : } - 4983 188 : if (oldest >= PROGRESS_MAX) - 4984 188 : oldest -= PROGRESS_MAX; + 4983 177 : if (oldest >= PROGRESS_MAX) + 4984 177 : oldest -= PROGRESS_MAX; 4985 : - 4986 188 : tick_cpu = state->progress_tick_misc[state->progress_ptr] - 4987 188 : + state->progress_tick_sched[state->progress_ptr] - 4988 188 : + state->progress_tick_raid[state->progress_ptr] - 4989 188 : + state->progress_tick_hash[state->progress_ptr]; - 4990 188 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr]; + 4986 177 : tick_cpu = state->progress_tick_misc[state->progress_ptr] + 4987 177 : + state->progress_tick_sched[state->progress_ptr] + 4988 177 : + state->progress_tick_raid[state->progress_ptr] + 4989 177 : + state->progress_tick_hash[state->progress_ptr]; + 4990 177 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr]; 4991 : - 4992 188 : oldest_tick_cpu = state->progress_tick_misc[oldest] - 4993 188 : + state->progress_tick_sched[oldest] - 4994 188 : + state->progress_tick_raid[oldest] - 4995 188 : + state->progress_tick_hash[oldest]; - 4996 188 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest]; + 4992 177 : oldest_tick_cpu = state->progress_tick_misc[oldest] + 4993 177 : + state->progress_tick_sched[oldest] + 4994 177 : + state->progress_tick_raid[oldest] + 4995 177 : + state->progress_tick_hash[oldest]; + 4996 177 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest]; 4997 : - 4998 188 : delta_time = now - state->progress_time[oldest]; - 4999 188 : delta_pos = countpos - state->progress_pos[oldest]; - 5000 188 : delta_size = countsize - state->progress_size[oldest]; - 5001 188 : delta_tick_cpu = tick_cpu - oldest_tick_cpu; - 5002 188 : delta_tick_total = tick_total - oldest_tick_total; + 4998 177 : delta_time = now - state->progress_time[oldest]; + 4999 177 : delta_pos = countpos - state->progress_pos[oldest]; + 5000 177 : delta_size = countsize - state->progress_size[oldest]; + 5001 177 : delta_tick_cpu = tick_cpu - oldest_tick_cpu; + 5002 177 : delta_tick_total = tick_total - oldest_tick_total; 5003 : 5004 : /* estimate the speed in MB/s */ - 5005 188 : if (delta_time != 0) - 5006 188 : out_size_speed = (unsigned)(delta_size / MEGA / delta_time); + 5005 177 : if (delta_time != 0) + 5006 177 : out_size_speed = (unsigned)(delta_size / MEGA / delta_time); 5007 : 5008 : /* estimate the speed in block/s */ - 5009 188 : if (delta_time != 0) - 5010 188 : out_block_speed = (unsigned)(delta_pos / delta_time); + 5009 177 : if (delta_time != 0) + 5010 177 : out_block_speed = (unsigned)(delta_pos / delta_time); 5011 : 5012 : /* estimate the cpu usage percentage */ - 5013 188 : if (delta_tick_total != 0) - 5014 33 : out_cpu = muldiv(delta_tick_cpu, 100, delta_tick_total); + 5013 177 : if (delta_tick_total != 0) + 5014 34 : out_cpu = muldiv(delta_tick_cpu, 100, delta_tick_total); 5015 : 5016 : /* estimate the remaining time in minutes */ - 5017 188 : if (delta_pos != 0) - 5018 188 : out_eta = muldiv(countmax - countpos, delta_time, delta_pos); + 5017 177 : if (delta_pos != 0) + 5018 177 : out_eta = muldiv(countmax - countpos, delta_time, delta_pos); 5019 : - 5020 188 : if (state->opt.force_stats) { + 5020 177 : if (state->opt.force_stats) { 5021 1 : os_clear(); 5022 1 : state_progress_graph(state, io, state->progress_ptr, oldest); 5023 : } 5024 : - 5025 188 : if (state->thermal_temperature_limit != 0) { + 5025 177 : if (state->thermal_temperature_limit != 0) { 5026 : /* get the max temperature */ - 5027 4 : out_temperature = 0; - 5028 124 : for (i = tommy_list_head(&state->thermallist); i != 0; i = i->next) { - 5029 120 : struct snapraid_thermal* thermal = i->data; - 5030 120 : if (out_temperature < thermal->latest_temperature) { - 5031 4 : out_temperature = thermal->latest_temperature; - 5032 4 : if (thermal->params.r_squared >= THERMAL_R_SQUARED_LIMIT) - 5033 4 : out_steady = thermal->params.t_steady; + 5027 5 : out_temperature = 0; + 5028 155 : for (i = tommy_list_head(&state->thermallist); i != 0; i = i->next) { + 5029 150 : struct snapraid_thermal* thermal = i->data; + 5030 150 : if (out_temperature < thermal->latest_temperature) { + 5031 5 : out_temperature = thermal->latest_temperature; + 5032 5 : if (thermal->params.r_squared >= THERMAL_R_SQUARED_LIMIT) + 5033 5 : out_steady = thermal->params.t_steady; 5034 : else 5035 0 : out_steady = 0; 5036 : } 5037 : } 5038 : } else { - 5039 184 : out_temperature = 0; - 5040 184 : out_steady = 0; + 5039 172 : out_temperature = 0; + 5040 172 : out_steady = 0; 5041 : } 5042 : 5043 : /* we have the output value */ - 5044 188 : out_computed = 1; + 5044 177 : out_computed = 1; 5045 : } 5046 : - 5047 391 : if (state->opt.gui) { + 5047 379 : if (state->opt.gui) { 5048 : char str_eta[32]; 5049 : char str_size_speed[32]; 5050 : char str_cpu[32]; 5051 : char str_temp[32]; 5052 : char str_steady[32]; - 5053 7 : if (out_computed) { - 5054 3 : snprintf(str_eta, sizeof(str_eta), "%u", out_eta); - 5055 3 : snprintf(str_size_speed, sizeof(str_size_speed), "%u", out_size_speed); - 5056 3 : snprintf(str_cpu, sizeof(str_cpu), "%u", out_cpu); + 5053 8 : if (out_computed) { + 5054 4 : snprintf(str_eta, sizeof(str_eta), "%u", out_eta); + 5055 4 : snprintf(str_size_speed, sizeof(str_size_speed), "%u", out_size_speed); + 5056 4 : snprintf(str_cpu, sizeof(str_cpu), "%u", out_cpu); 5057 : } else { 5058 4 : str_eta[0] = 0; 5059 4 : str_size_speed[0] = 0; 5060 4 : str_cpu[0] = 0; 5061 : } - 5062 7 : if (out_temperature) { + 5062 8 : if (out_temperature) { 5063 0 : snprintf(str_temp, sizeof(str_eta), "%u", out_temperature); 5064 : } else { - 5065 7 : str_temp[0] = 0; + 5065 8 : str_temp[0] = 0; 5066 : } - 5067 7 : if (out_steady) { + 5067 8 : if (out_steady) { 5068 0 : snprintf(str_steady, sizeof(str_steady), "%u", out_steady); 5069 : } else { - 5070 7 : str_steady[0] = 0; + 5070 8 : str_steady[0] = 0; 5071 : } - 5072 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%s:%s:%s:%" PRIu64 ":%s:%s\n", blockpos, countpos, countsize, out_perc, str_eta, str_size_speed, str_cpu, (uint64_t)elapsed, str_temp, str_steady); - 5073 7 : log_flush(); + 5072 8 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%s:%s:%s:%" PRIu64 ":%s:%s\n", blockpos, countpos, countsize, out_perc, str_eta, str_size_speed, str_cpu, (uint64_t)elapsed, str_temp, str_steady); + 5073 8 : log_flush(); 5074 : } else { - 5075 384 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA)); - 5076 384 : if (out_computed) { - 5077 185 : msg_bar(", %u MB/s", out_size_speed); - 5078 185 : msg_bar(", %u stripe/s", out_block_speed); - 5079 185 : msg_bar(", CPU %u%%", out_cpu); - 5080 185 : if (out_temperature != 0) { - 5081 4 : if (out_steady != 0) - 5082 4 : msg_bar(", Tmax %u (%u)", out_temperature, out_steady); + 5075 371 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA)); + 5076 371 : if (out_computed) { + 5077 173 : msg_bar(", %u MB/s", out_size_speed); + 5078 173 : msg_bar(", %u stripe/s", out_block_speed); + 5079 173 : msg_bar(", CPU %u%%", out_cpu); + 5080 173 : if (out_temperature != 0) { + 5081 5 : if (out_steady != 0) + 5082 5 : msg_bar(", Tmax %u (%u)", out_temperature, out_steady); 5083 : else 5084 0 : msg_bar(", Tmax %u", out_temperature); 5085 : } - 5086 185 : unsigned out_eta_minutes = out_eta / 60; /* minutes */ - 5087 185 : msg_bar(", %u:%02u ETA", out_eta_minutes / 60, out_eta_minutes % 60); + 5086 173 : unsigned out_eta_minutes = out_eta / 60; /* minutes */ + 5087 173 : msg_bar(", %u:%02u ETA", out_eta_minutes / 60, out_eta_minutes % 60); 5088 : } - 5089 384 : msg_bar("\r"); - 5090 384 : msg_flush(); + 5089 371 : msg_bar("\r"); + 5090 371 : msg_flush(); 5091 : } 5092 : 5093 : /* next position to fill */ - 5094 391 : ++state->progress_ptr; - 5095 391 : if (state->progress_ptr >= PROGRESS_MAX) + 5094 379 : ++state->progress_ptr; + 5095 379 : if (state->progress_ptr >= PROGRESS_MAX) 5096 0 : state->progress_ptr -= PROGRESS_MAX; 5097 : 5098 : /* one more measure */ - 5099 391 : ++state->progress_tick; + 5099 379 : ++state->progress_tick; 5100 : } 5101 : 5102 : /* stop if requested */ - 5103 1075966 : if (global_interrupt) { + 5103 1075903 : if (global_interrupt) { 5104 : /* LCOV_EXCL_START */ 5105 : if (!state->opt.gui) { 5106 : log_fatal(EUSER, "\n"); @@ -5174,7 +5174,7 @@ 5112 : /* LCOV_EXCL_STOP */ 5113 : } 5114 : - 5115 1075966 : return 0; + 5115 1075903 : return 0; 5116 : } 5117 : 5118 110 : void state_usage_waste(struct snapraid_state* state) @@ -5184,90 +5184,90 @@ 5122 110 : state->tick_last = now; 5123 110 : } 5124 : - 5125 1071293 : void state_usage_misc(struct snapraid_state* state) + 5125 1070853 : void state_usage_misc(struct snapraid_state* state) 5126 : { - 5127 1071293 : uint64_t now = tick(); - 5128 1071293 : uint64_t delta = now - state->tick_last; + 5127 1070853 : uint64_t now = tick(); + 5128 1070853 : uint64_t delta = now - state->tick_last; 5129 : 5130 : /* increment the time spent in computations */ - 5131 1071293 : state->tick_misc += delta; + 5131 1070853 : state->tick_misc += delta; 5132 : - 5133 1071293 : state->tick_last = now; - 5134 1071293 : } + 5133 1070853 : state->tick_last = now; + 5134 1070853 : } 5135 : - 5136 151013 : void state_usage_sched(struct snapraid_state* state) + 5136 150950 : void state_usage_sched(struct snapraid_state* state) 5137 : { - 5138 151013 : uint64_t now = tick(); - 5139 151013 : uint64_t delta = now - state->tick_last; + 5138 150950 : uint64_t now = tick(); + 5139 150950 : uint64_t delta = now - state->tick_last; 5140 : 5141 : /* increment the time spent in computations */ - 5142 151013 : state->tick_sched += delta; + 5142 150950 : state->tick_sched += delta; 5143 : - 5144 151013 : state->tick_last = now; - 5145 151013 : } + 5144 150950 : state->tick_last = now; + 5145 150950 : } 5146 : - 5147 140496 : void state_usage_raid(struct snapraid_state* state) + 5147 140445 : void state_usage_raid(struct snapraid_state* state) 5148 : { - 5149 140496 : uint64_t now = tick(); - 5150 140496 : uint64_t delta = now - state->tick_last; + 5149 140445 : uint64_t now = tick(); + 5150 140445 : uint64_t delta = now - state->tick_last; 5151 : 5152 : /* increment the time spent in computations */ - 5153 140496 : state->tick_raid += delta; + 5153 140445 : state->tick_raid += delta; 5154 : - 5155 140496 : state->tick_last = now; - 5156 140496 : } + 5155 140445 : state->tick_last = now; + 5156 140445 : } 5157 : - 5158 753854 : void state_usage_hash(struct snapraid_state* state) + 5158 753469 : void state_usage_hash(struct snapraid_state* state) 5159 : { - 5160 753854 : uint64_t now = tick(); - 5161 753854 : uint64_t delta = now - state->tick_last; + 5160 753469 : uint64_t now = tick(); + 5161 753469 : uint64_t delta = now - state->tick_last; 5162 : 5163 : /* increment the time spent in computations */ - 5164 753854 : state->tick_hash += delta; + 5164 753469 : state->tick_hash += delta; 5165 : - 5166 753854 : state->tick_last = now; - 5167 753854 : } + 5166 753469 : state->tick_last = now; + 5167 753469 : } 5168 : - 5169 914732 : void state_usage_file(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 5169 914354 : void state_usage_file(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 5170 : { 5171 : (void)state; 5172 : - 5173 914732 : disk->progress_file = file; - 5174 914732 : } + 5173 914354 : disk->progress_file = file; + 5174 914354 : } 5175 : - 5176 919419 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac) + 5176 919041 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac) 5177 : { - 5178 919419 : uint64_t now = tick(); - 5179 919419 : uint64_t delta = now - state->tick_last; + 5178 919041 : uint64_t now = tick(); + 5179 919041 : uint64_t delta = now - state->tick_last; 5180 : unsigned i; 5181 : 5182 : /* increment the time spent in the data disks */ - 5183 961474 : for (i = 0; i < waiting_mac; ++i) { - 5184 42055 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk; + 5183 961157 : for (i = 0; i < waiting_mac; ++i) { + 5184 42116 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk; 5185 : - 5186 42055 : if (!disk) + 5186 42116 : if (!disk) 5187 0 : continue; 5188 : - 5189 42055 : disk->tick += delta; + 5189 42116 : disk->tick += delta; 5190 : } - 5191 919419 : state->tick_io += delta; + 5191 919041 : state->tick_io += delta; 5192 : - 5193 919419 : state->tick_last = now; - 5194 919419 : } + 5193 919041 : state->tick_last = now; + 5194 919041 : } 5195 : - 5196 781079 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac) + 5196 780707 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac) 5197 : { - 5198 781079 : uint64_t now = tick(); - 5199 781079 : uint64_t delta = now - state->tick_last; + 5198 780707 : uint64_t now = tick(); + 5199 780707 : uint64_t delta = now - state->tick_last; 5200 : unsigned i; 5201 : 5202 : /* increment the time spent in the parity disk */ - 5203 790921 : for (i = 0; i < waiting_mac; ++i) - 5204 9842 : state->parity[waiting_map[i]].tick += delta; - 5205 781079 : state->tick_io += delta; + 5203 790636 : for (i = 0; i < waiting_mac; ++i) + 5204 9929 : state->parity[waiting_map[i]].tick += delta; + 5205 780707 : state->tick_io += delta; 5206 : - 5207 781079 : state->tick_last = now; - 5208 781079 : } + 5207 780707 : state->tick_last = now; + 5208 780707 : } 5209 : 5210 102 : void state_usage_print(struct snapraid_state* state) 5211 : { @@ -5281,22 +5281,22 @@ 5219 1 : state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX); 5220 : } 5221 : - 5222 521 : void state_fscheck(struct snapraid_state* state, const char* ope) + 5222 520 : void state_fscheck(struct snapraid_state* state, const char* ope) 5223 : { 5224 : tommy_node* i; 5225 : 5226 : /* check the file-system on all disks */ - 5227 3641 : for (i = state->disklist; i != 0; i = i->next) { - 5228 3120 : struct snapraid_disk* disk = i->data; + 5227 3634 : for (i = state->disklist; i != 0; i = i->next) { + 5228 3114 : struct snapraid_disk* disk = i->data; 5229 : - 5230 3120 : if (fs_check(disk) != 0) { + 5230 3114 : if (fs_check(disk) != 0) { 5231 : /* LCOV_EXCL_START */ 5232 : log_fatal(EINTERNAL, "Internal inconsistency: File-system check for disk '%s' %s\n", disk->name, ope); 5233 : os_abort(); 5234 : /* LCOV_EXCL_STOP */ 5235 : } 5236 : } - 5237 521 : } + 5237 520 : } 5238 : 5239 1 : void generate_configuration(const char* path) 5240 : { diff --git a/cov/cmdline/status.c.func-sort-c.html b/cov/cmdline/status.c.func-sort-c.html index 98428a8a..bbff8974 100644 --- a/cov/cmdline/status.c.func-sort-c.html +++ b/cov/cmdline/status.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/cmdline/status.c.func.html b/cov/cmdline/status.c.func.html index a6973a39..e8c15562 100644 --- a/cov/cmdline/status.c.func.html +++ b/cov/cmdline/status.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/cmdline/status.c.gcov.html b/cov/cmdline/status.c.gcov.html index 458a4da3..c5fcd73b 100644 --- a/cov/cmdline/status.c.gcov.html +++ b/cov/cmdline/status.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -148,7 +148,7 @@ 86 90 : log_tag("summary:parity_block_total:%s:%u\n", lev_config_name(l), state->parity[l].total_blocks); 87 90 : log_tag("summary:parity_block_free:%s:%u\n", lev_config_name(l), state->parity[l].free_blocks); 88 90 : if (state->parity[l].free_blocks < parity_block_free) - 89 4 : parity_block_free = state->parity[l].free_blocks; + 89 1 : parity_block_free = state->parity[l].free_blocks; 90 90 : if (state->parity[l].free_blocks != 0) 91 79 : free_not_zero = 1; 92 : } @@ -226,7 +226,7 @@ 164 : /* keep track of latest block used */ 165 95396 : last_pos = fs_file2par_get(disk, file, file->blockmax - 1); 166 95396 : if (last_pos > disk_block_latest_used) { - 167 92536 : disk_block_latest_used = last_pos; + 167 92537 : disk_block_latest_used = last_pos; 168 : } 169 : 170 95396 : if (fragmented) { @@ -348,17 +348,17 @@ 286 15 : median = 0; 287 15 : newest = 0; 288 15 : count = 0; - 289 32 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { - 290 17 : struct snapraid_bucket* bucket = j->data; - 291 17 : block_off_t bucket_count = bucket->count_scrubbed + bucket->count_justsynced; + 289 30 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { + 290 15 : struct snapraid_bucket* bucket = j->data; + 291 15 : block_off_t bucket_count = bucket->count_scrubbed + bucket->count_justsynced; 292 : - 293 17 : if (count == 0) + 293 15 : if (count == 0) 294 9 : oldest = bucket->time_at; - 295 17 : if (count < state->bucketcount / 2) - 296 14 : median = bucket->time_at; - 297 17 : newest = bucket->time_at; + 295 15 : if (count < state->bucketcount / 2) + 296 12 : median = bucket->time_at; + 297 15 : newest = bucket->time_at; 298 : - 299 17 : count += bucket_count; + 299 15 : count += bucket_count; 300 : } 301 : 302 15 : if (!count) { @@ -378,15 +378,15 @@ 316 9 : barmax = 0; 317 9 : memset(bar_scrubbed, 0, sizeof(bar_scrubbed)); 318 9 : memset(bar_new, 0, sizeof(bar_new)); - 319 26 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { - 320 17 : struct snapraid_bucket* bucket = j->data; + 319 24 : for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) { + 320 15 : struct snapraid_bucket* bucket = j->data; 321 : - 322 17 : unsigned column = muldiv(bucket->time_at - oldest, GRAPH_COLUMN, newest - oldest + 1); + 322 15 : unsigned column = muldiv(bucket->time_at - oldest, GRAPH_COLUMN, newest - oldest + 1); 323 : - 324 17 : bar_scrubbed[column] += bucket->count_scrubbed; - 325 17 : bar_new[column] += bucket->count_justsynced; + 324 15 : bar_scrubbed[column] += bucket->count_scrubbed; + 325 15 : bar_new[column] += bucket->count_justsynced; 326 : - 327 17 : if (bar_scrubbed[column] + bar_new[column] > barmax) + 327 15 : if (bar_scrubbed[column] + bar_new[column] > barmax) 328 12 : barmax = bar_scrubbed[column] + bar_new[column]; 329 : } 330 : @@ -416,20 +416,20 @@ 354 9450 : unsigned scrubbed = bar_scrubbed[x]; 355 : 356 9450 : if (both > pivot_upper) { - 357 156 : if (scrubbed > pivot_lower) + 357 157 : if (scrubbed > pivot_lower) 358 60 : printf("*"); 359 : else - 360 96 : printf("o"); - 361 9294 : } else if (both > pivot_lower) { - 362 17 : if (scrubbed == both) + 360 97 : printf("o"); + 361 9293 : } else if (both > pivot_lower) { + 362 15 : if (scrubbed == both) 363 6 : printf("*"); 364 : else - 365 11 : printf("o"); + 365 9 : printf("o"); 366 : } else { - 367 9277 : if (y == GRAPH_ROW - 1) - 368 613 : printf("_"); + 367 9278 : if (y == GRAPH_ROW - 1) + 368 615 : printf("_"); 369 : else - 370 8664 : printf(" "); + 370 8663 : printf(" "); 371 : } 372 : } 373 135 : printf("\n"); @@ -491,27 +491,27 @@ 429 2 : bad_count = 0; 430 2 : range_start = 0; 431 2 : range_count = 0; - 432 887 : for (i = 0; i <= blockmax; ++i) { /* one extra iteration to print the final range */ - 433 887 : snapraid_info info = 0; - 434 887 : int is_bad = 0; + 432 894 : for (i = 0; i <= blockmax; ++i) { /* one extra iteration to print the final range */ + 433 894 : snapraid_info info = 0; + 434 894 : int is_bad = 0; 435 : - 436 887 : if (i < blockmax) { - 437 887 : info = info_get(&state->infoarr, i); - 438 887 : if (info != 0) /* unused blocks are never bad */ - 439 887 : is_bad = info_get_bad(info); + 436 894 : if (i < blockmax) { + 437 894 : info = info_get(&state->infoarr, i); + 438 894 : if (info != 0) /* unused blocks are never bad */ + 439 894 : is_bad = info_get_bad(info); 440 : } - 441 887 : if (is_bad) { + 441 894 : if (is_bad) { 442 : /* create or extend the range */ - 443 259 : if (!range_count) + 443 263 : if (!range_count) 444 202 : range_start = i; - 445 259 : ++range_count; + 445 263 : ++range_count; 446 : } else { 447 : /* break the range */ - 448 628 : if (range_count) { + 448 631 : if (range_count) { 449 202 : if (range_count == 1) { - 450 153 : printf(" %u", range_start); + 450 155 : printf(" %u", range_start); 451 : } else { - 452 49 : printf(" %u-%u", range_start, range_start + range_count - 1); + 452 47 : printf(" %u-%u", range_start, range_start + range_count - 1); 453 : } 454 202 : bad_count += range_count; 455 202 : ++bad_range; @@ -519,7 +519,7 @@ 457 : } 458 : } 459 : - 460 887 : if (bad_range > 100) { + 460 894 : if (bad_range > 100) { 461 2 : printf(" and %u more...", state->bad_blocks - bad_count); 462 2 : break; 463 : } diff --git a/cov/cmdline/stream.c.func-sort-c.html b/cov/cmdline/stream.c.func-sort-c.html index fa9c6041..740c4771 100644 --- a/cov/cmdline/stream.c.func-sort-c.html +++ b/cov/cmdline/stream.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 27 @@ -69,19 +69,19 @@ ssync - 157 + 156 scrc_stream - 173 + 172 sopen_multi_write - 173 + 172 sputble32 - 173 + 172 shandle @@ -89,7 +89,7 @@ sgetu32 - 280 + 283 sgetble32 @@ -97,79 +97,79 @@ sopen_multi_file - 1182 + 1175 sdeplete - 1183 + 1176 scrc - 1748 + 1740 sopen_read - 1903 + 1897 sclose - 2024 + 2017 sgetlasttok - 5663 + 5686 sgetline - 5706 + 5738 sgettok - 9875 + 9929 sflush - 39158 + 39136 sgetc_uncached - 299093 + 299099 sfill - 608081 + 607940 sputbs - 1982279 + 1964370 sgetbs - 4004187 + 4004224 sputb64 - 5572622 + 5517420 sputb32 - 9508972 + 9413354 sgetb64 - 11258012 + 11246935 sread - 13236843 + 13236979 sgetb32 - 19212483 + 19190230 swrite - 21650829 + 21440832
diff --git a/cov/cmdline/stream.c.func.html b/cov/cmdline/stream.c.func.html index e4e635a3..81e17132 100644 --- a/cov/cmdline/stream.c.func.html +++ b/cov/cmdline/stream.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 27 @@ -61,35 +61,35 @@ sclose - 2024 + 2017 scrc - 1748 + 1740 scrc_stream - 173 + 172 sdeplete - 1183 + 1176 sfill - 608081 + 607940 sflush - 39158 + 39136 sgetb32 - 19212483 + 19190230 sgetb64 - 11258012 + 11246935 sgetble32 @@ -97,27 +97,27 @@ sgetbs - 4004187 + 4004224 sgetc_uncached - 299093 + 299099 sgetlasttok - 5663 + 5686 sgetline - 5706 + 5738 sgettok - 9875 + 9929 sgetu32 - 280 + 283 shandle @@ -125,15 +125,15 @@ sopen_multi_file - 1182 + 1175 sopen_multi_write - 173 + 172 sopen_read - 1903 + 1897 sopen_write @@ -141,27 +141,27 @@ sputb32 - 9508972 + 9413354 sputb64 - 5572622 + 5517420 sputble32 - 173 + 172 sputbs - 1982279 + 1964370 sread - 13236843 + 13236979 ssync - 157 + 156 stell @@ -169,7 +169,7 @@ swrite - 21650829 + 21440832
diff --git a/cov/cmdline/stream.c.gcov.html b/cov/cmdline/stream.c.gcov.html index 6b451924..7db6643f 100644 --- a/cov/cmdline/stream.c.gcov.html +++ b/cov/cmdline/stream.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 27 @@ -88,50 +88,50 @@ 26 : 27 : unsigned STREAM_SIZE = 64 * 1024; 28 : - 29 1903 : STREAM* sopen_read(const char* file, int flags) + 29 1897 : STREAM* sopen_read(const char* file, int flags) 30 : { 31 : #if HAVE_POSIX_FADVISE 32 : int ret; 33 : #endif - 34 1903 : STREAM* s = malloc_nofail(sizeof(STREAM)); + 34 1897 : STREAM* s = malloc_nofail(sizeof(STREAM)); 35 : struct stat st; 36 : - 37 1903 : s->handle_size = 1; - 38 1903 : s->handle = malloc_nofail(sizeof(struct stream_handle)); - 39 1903 : s->flags = flags; + 37 1897 : s->handle_size = 1; + 38 1897 : s->handle = malloc_nofail(sizeof(struct stream_handle)); + 39 1897 : s->flags = flags; 40 : - 41 1903 : int open_flags = O_RDONLY | O_BINARY; - 42 1903 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) - 43 1369 : open_flags |= O_SEQUENTIAL; + 41 1897 : int open_flags = O_RDONLY | O_BINARY; + 42 1897 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) + 43 1362 : open_flags |= O_SEQUENTIAL; 44 : - 45 1903 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); - 46 1903 : s->handle[0].f = open(file, open_flags); - 47 1903 : if (s->handle[0].f == -1) { + 45 1897 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); + 46 1897 : s->handle[0].f = open(file, open_flags); + 47 1897 : if (s->handle[0].f == -1) { 48 50 : free(s->handle); 49 50 : free(s); 50 50 : return 0; 51 : } 52 : 53 : /* get file info */ - 54 1853 : if (fstat(s->handle[0].f, &st) != 0) { + 54 1847 : if (fstat(s->handle[0].f, &st) != 0) { 55 0 : close(s->handle[0].f); 56 0 : free(s->handle); 57 0 : free(s); 58 0 : return 0; 59 : } 60 : - 61 1853 : s->size = st.st_size; + 61 1847 : s->size = st.st_size; 62 : 63 : #if HAVE_POSIX_FADVISE - 64 1853 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) { + 64 1847 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) { 65 : /* advise sequential access */ - 66 1319 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL); - 67 1319 : if (ret == ENOSYS) { + 66 1312 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL); + 67 1312 : if (ret == ENOSYS) { 68 0 : log_fatal(errno, "WARNING! fadvise() is not supported in this platform. Performance may not be optimal!\n"); 69 : /* call is not supported, like in armhf, see posix_fadvise manpage */ 70 0 : ret = 0; 71 : } - 72 1319 : if (ret != 0) { + 72 1312 : if (ret != 0) { 73 : /* LCOV_EXCL_START */ 74 : close(s->handle[0].f); 75 : free(s->handle); @@ -143,82 +143,82 @@ 81 : } 82 : #endif 83 : - 84 1853 : s->buffer_size = STREAM_SIZE; - 85 1853 : if (s->buffer_size > s->size) - 86 473 : s->buffer_size = s->size; /* allocate only what is necessary */ - 87 1853 : s->buffer = malloc_nofail_test(s->buffer_size); - 88 1853 : s->pos = s->buffer; - 89 1853 : s->end = s->buffer; - 90 1853 : s->state = STREAM_STATE_READ; - 91 1853 : s->state_index = 0; - 92 1853 : s->offset = 0; - 93 1853 : s->offset_uncached = 0; - 94 1853 : s->crc = 0; - 95 1853 : s->crc_uncached = 0; - 96 1853 : s->crc_stream = CRC_IV; + 84 1847 : s->buffer_size = STREAM_SIZE; + 85 1847 : if (s->buffer_size > s->size) + 86 474 : s->buffer_size = s->size; /* allocate only what is necessary */ + 87 1847 : s->buffer = malloc_nofail_test(s->buffer_size); + 88 1847 : s->pos = s->buffer; + 89 1847 : s->end = s->buffer; + 90 1847 : s->state = STREAM_STATE_READ; + 91 1847 : s->state_index = 0; + 92 1847 : s->offset = 0; + 93 1847 : s->offset_uncached = 0; + 94 1847 : s->crc = 0; + 95 1847 : s->crc_uncached = 0; + 96 1847 : s->crc_stream = CRC_IV; 97 : - 98 1853 : return s; + 98 1847 : return s; 99 : } 100 : - 101 173 : STREAM* sopen_multi_write(unsigned count, int flags) + 101 172 : STREAM* sopen_multi_write(unsigned count, int flags) 102 : { 103 : unsigned i; 104 : - 105 173 : STREAM* s = malloc_nofail(sizeof(STREAM)); + 105 172 : STREAM* s = malloc_nofail(sizeof(STREAM)); 106 : - 107 173 : s->handle_size = count; - 108 173 : s->handle = malloc_nofail(count * sizeof(struct stream_handle)); - 109 173 : s->flags = flags; + 107 172 : s->handle_size = count; + 108 172 : s->handle = malloc_nofail(count * sizeof(struct stream_handle)); + 109 172 : s->flags = flags; 110 : - 111 1355 : for (i = 0; i < count; ++i) - 112 1182 : s->handle[i].f = -1; + 111 1347 : for (i = 0; i < count; ++i) + 112 1175 : s->handle[i].f = -1; 113 : - 114 173 : s->buffer_size = STREAM_SIZE; - 115 173 : s->buffer = malloc_nofail_test(s->buffer_size); - 116 173 : s->pos = s->buffer; - 117 173 : s->end = s->buffer + s->buffer_size; - 118 173 : s->state = STREAM_STATE_WRITE; - 119 173 : s->state_index = 0; - 120 173 : s->size = 0; - 121 173 : s->offset = 0; - 122 173 : s->offset_uncached = 0; - 123 173 : s->crc = 0; - 124 173 : s->crc_uncached = 0; - 125 173 : s->crc_stream = CRC_IV; + 114 172 : s->buffer_size = STREAM_SIZE; + 115 172 : s->buffer = malloc_nofail_test(s->buffer_size); + 116 172 : s->pos = s->buffer; + 117 172 : s->end = s->buffer + s->buffer_size; + 118 172 : s->state = STREAM_STATE_WRITE; + 119 172 : s->state_index = 0; + 120 172 : s->size = 0; + 121 172 : s->offset = 0; + 122 172 : s->offset_uncached = 0; + 123 172 : s->crc = 0; + 124 172 : s->crc_uncached = 0; + 125 172 : s->crc_stream = CRC_IV; 126 : - 127 173 : return s; + 127 172 : return s; 128 : } 129 : - 130 1182 : int sopen_multi_file(STREAM* s, unsigned i, const char* file) + 130 1175 : int sopen_multi_file(STREAM* s, unsigned i, const char* file) 131 : { 132 : #if HAVE_POSIX_FADVISE 133 : int ret; 134 : #endif 135 : int f; 136 : - 137 1182 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file); + 137 1175 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file); 138 : - 139 1182 : int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY; - 140 1182 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) - 141 1054 : open_flags |= O_SEQUENTIAL; ; + 139 1175 : int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY; + 140 1175 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) + 141 1047 : open_flags |= O_SEQUENTIAL; ; 142 : 143 : /* O_EXCL to be resilient ensure to always create a new file and not use a stale link to the original file */ - 144 1182 : f = open(file, open_flags, 0600); - 145 1182 : if (f == -1) { + 144 1175 : f = open(file, open_flags, 0600); + 145 1175 : if (f == -1) { 146 : /* LCOV_EXCL_START */ 147 : return -1; 148 : /* LCOV_EXCL_STOP */ 149 : } 150 : 151 : #if HAVE_POSIX_FADVISE - 152 1182 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) { + 152 1175 : if (s->flags & STREAM_FLAGS_SEQUENTIAL) { 153 : /* advise sequential access */ - 154 1054 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); - 155 1054 : if (ret == ENOSYS) { + 154 1047 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + 155 1047 : if (ret == ENOSYS) { 156 : /* call is not supported, like in armhf, see posix_fadvise manpage */ 157 0 : ret = 0; 158 : } - 159 1054 : if (ret != 0) { + 159 1047 : if (ret != 0) { 160 : /* LCOV_EXCL_START */ 161 : close(f); 162 : errno = ret; /* posix_fadvise return the error code */ @@ -228,9 +228,9 @@ 166 : } 167 : #endif 168 : - 169 1182 : s->handle[i].f = f; + 169 1175 : s->handle[i].f = f; 170 : - 171 1182 : return 0; + 171 1175 : return 0; 172 : } 173 : 174 0 : STREAM* sopen_write(const char* file, int flags) @@ -245,38 +245,38 @@ 183 0 : return s; 184 : } 185 : - 186 2024 : int sclose(STREAM* s) + 186 2017 : int sclose(STREAM* s) 187 : { - 188 2024 : int fail = 0; + 188 2017 : int fail = 0; 189 : unsigned i; 190 : - 191 2024 : if (s->state == STREAM_STATE_WRITE) { - 192 173 : if (sflush(s) != 0) { + 191 2017 : if (s->state == STREAM_STATE_WRITE) { + 192 172 : if (sflush(s) != 0) { 193 : /* LCOV_EXCL_START */ 194 : fail = 1; 195 : /* LCOV_EXCL_STOP */ 196 : } 197 : } 198 : - 199 5057 : for (i = 0; i < s->handle_size; ++i) { - 200 3033 : if (close(s->handle[i].f) != 0) { + 199 5037 : for (i = 0; i < s->handle_size; ++i) { + 200 3020 : if (close(s->handle[i].f) != 0) { 201 : /* LCOV_EXCL_START */ 202 : fail = 1; 203 : /* LCOV_EXCL_STOP */ 204 : } 205 : } 206 : - 207 2024 : free(s->handle); - 208 2024 : free(s->buffer); - 209 2024 : free(s); + 207 2017 : free(s->handle); + 208 2017 : free(s->buffer); + 209 2017 : free(s); 210 : - 211 2024 : if (fail) { + 211 2017 : if (fail) { 212 : /* LCOV_EXCL_START */ 213 : return -1; 214 : /* LCOV_EXCL_STOP */ 215 : } 216 : - 217 2024 : return 0; + 217 2017 : return 0; 218 : } 219 : 220 265 : int shandle(STREAM* s) @@ -294,30 +294,30 @@ 232 : * Fill the read stream buffer. 233 : * \return 0 if at least on char is read, or EOF on error. 234 : */ - 235 608081 : static int sfill(STREAM* s) + 235 607940 : static int sfill(STREAM* s) 236 : { 237 : ssize_t ret; 238 : - 239 608081 : if (s->state != STREAM_STATE_READ) { + 239 607940 : if (s->state != STREAM_STATE_READ) { 240 : /* LCOV_EXCL_START */ 241 : return EOF; 242 : /* LCOV_EXCL_STOP */ 243 : } 244 : 245 : /* if we reached the end, doesn't try to read */ - 246 608081 : if (s->offset >= s->size) { - 247 2832 : return EOF; + 246 607940 : if (s->offset >= s->size) { + 247 2830 : return EOF; 248 : } 249 : - 250 605249 : ret = read(s->handle[0].f, s->buffer, s->buffer_size); + 250 605110 : ret = read(s->handle[0].f, s->buffer, s->buffer_size); 251 : - 252 605249 : if (ret < 0) { + 252 605110 : if (ret < 0) { 253 : /* LCOV_EXCL_START */ 254 : s->state = STREAM_STATE_ERROR; 255 : return EOF; 256 : /* LCOV_EXCL_STOP */ 257 : } - 258 605249 : if (ret == 0) { + 258 605110 : if (ret == 0) { 259 : /* nothing mode to read */ 260 0 : s->state = STREAM_STATE_EOF; 261 0 : return EOF; @@ -325,79 +325,79 @@ 263 : /* assume that it can be a shorter read, so ret < s->buffer_size doesn't mean that we reached EOF */ 264 : 265 : /* update the crc */ - 266 605249 : if (s->flags & STREAM_FLAGS_CRC) { - 267 604971 : s->crc_uncached = s->crc; - 268 604971 : s->crc = crc32c(s->crc, s->buffer, ret); + 266 605110 : if (s->flags & STREAM_FLAGS_CRC) { + 267 604831 : s->crc_uncached = s->crc; + 268 604831 : s->crc = crc32c(s->crc, s->buffer, ret); 269 : } 270 : 271 : /* update the offset */ - 272 605249 : s->offset_uncached = s->offset; - 273 605249 : s->offset += ret; + 272 605110 : s->offset_uncached = s->offset; + 273 605110 : s->offset += ret; 274 : - 275 605249 : s->pos = s->buffer; - 276 605249 : s->end = s->buffer + ret; + 275 605110 : s->pos = s->buffer; + 276 605110 : s->end = s->buffer + ret; 277 : - 278 605249 : return 0; + 278 605110 : return 0; 279 : } 280 : - 281 1183 : int sdeplete(STREAM* s, unsigned char* last) + 281 1176 : int sdeplete(STREAM* s, unsigned char* last) 282 : { 283 : /* last four bytes */ - 284 1183 : last[0] = 0; - 285 1183 : last[1] = 0; - 286 1183 : last[2] = 0; - 287 1183 : last[3] = 0; + 284 1176 : last[0] = 0; + 285 1176 : last[1] = 0; + 286 1176 : last[2] = 0; + 287 1176 : last[3] = 0; 288 : 289 : while (1) { 290 : /* increase the position up to 4 bytes before the end */ - 291 308988 : if (s->pos + 4 <= s->end) - 292 149070 : s->pos = s->end - 4; + 291 308841 : if (s->pos + 4 <= s->end) + 292 148930 : s->pos = s->end - 4; 293 : 294 : /* insert the last 4 bytes */ - 295 1165036 : while (s->pos < s->end) { - 296 856048 : last[0] = last[1]; - 297 856048 : last[1] = last[2]; - 298 856048 : last[2] = last[3]; - 299 856048 : last[3] = *s->pos++; + 295 1164329 : while (s->pos < s->end) { + 296 855488 : last[0] = last[1]; + 297 855488 : last[1] = last[2]; + 298 855488 : last[2] = last[3]; + 299 855488 : last[3] = *s->pos++; 300 : } 301 : 302 : /* fill again the buffer until the end of the file */ - 303 308988 : if (sfill(s) != 0) { + 303 308841 : if (sfill(s) != 0) { 304 : /* on error fail */ - 305 1183 : if (serror(s)) { + 305 1176 : if (serror(s)) { 306 : /* LCOV_EXCL_START */ 307 : return EOF; 308 : /* LCOV_EXCL_STOP */ 309 : } 310 : 311 : /* on EOF terminate */ - 312 1183 : break; + 312 1176 : break; 313 : } 314 : } 315 : - 316 1183 : return 0; + 316 1176 : return 0; 317 : } 318 : - 319 39158 : int sflush(STREAM* s) + 319 39136 : int sflush(STREAM* s) 320 : { 321 : ssize_t ret; 322 : ssize_t size; 323 : unsigned i; 324 : - 325 39158 : if (s->state != STREAM_STATE_WRITE) { + 325 39136 : if (s->state != STREAM_STATE_WRITE) { 326 : /* LCOV_EXCL_START */ 327 : return EOF; 328 : /* LCOV_EXCL_STOP */ 329 : } 330 : - 331 39158 : size = s->pos - s->buffer; - 332 39158 : if (!size) - 333 157 : return 0; + 331 39136 : size = s->pos - s->buffer; + 332 39136 : if (!size) + 333 156 : return 0; 334 : - 335 347847 : for (i = 0; i < s->handle_size; ++i) { - 336 308846 : ret = write(s->handle[i].f, s->buffer, size); + 335 347679 : for (i = 0; i < s->handle_size; ++i) { + 336 308699 : ret = write(s->handle[i].f, s->buffer, size); 337 : - 338 308846 : if (ret != size) { + 338 308699 : if (ret != size) { 339 : /* LCOV_EXCL_START */ 340 : s->state = STREAM_STATE_ERROR; 341 : s->state_index = i; @@ -413,18 +413,18 @@ 351 : * to be able to detect memory errors on the buffer, 352 : * happening during the write. 353 : */ - 354 39001 : if (s->flags & STREAM_FLAGS_CRC) { - 355 39001 : s->crc = crc32c(s->crc, s->buffer, size); - 356 39001 : s->crc_uncached = s->crc; + 354 38980 : if (s->flags & STREAM_FLAGS_CRC) { + 355 38980 : s->crc = crc32c(s->crc, s->buffer, size); + 356 38980 : s->crc_uncached = s->crc; 357 : } 358 : 359 : /* update the offset */ - 360 39001 : s->offset += size; - 361 39001 : s->offset_uncached = s->offset; + 360 38980 : s->offset += size; + 361 38980 : s->offset_uncached = s->offset; 362 : - 363 39001 : s->pos = s->buffer; + 363 38980 : s->pos = s->buffer; 364 : - 365 39001 : return 0; + 365 38980 : return 0; 366 : } 367 : 368 1 : int64_t stell(STREAM* s) @@ -432,102 +432,102 @@ 370 1 : return s->offset_uncached + (s->pos - s->buffer); 371 : } 372 : - 373 1748 : uint32_t scrc(STREAM* s) + 373 1740 : uint32_t scrc(STREAM* s) 374 : { - 375 1748 : assert(s->flags & STREAM_FLAGS_CRC); - 376 1748 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer); + 375 1740 : assert(s->flags & STREAM_FLAGS_CRC); + 376 1740 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer); 377 : } 378 : - 379 173 : uint32_t scrc_stream(STREAM* s) + 379 172 : uint32_t scrc_stream(STREAM* s) 380 : { - 381 173 : assert(s->flags & STREAM_FLAGS_CRC); - 382 173 : return s->crc_stream ^ CRC_IV; + 381 172 : assert(s->flags & STREAM_FLAGS_CRC); + 382 172 : return s->crc_stream ^ CRC_IV; 383 : } 384 : - 385 299093 : int sgetc_uncached(STREAM* s) + 385 299099 : int sgetc_uncached(STREAM* s) 386 : { 387 : /* if at the end of the buffer, fill it */ - 388 299093 : if (s->pos == s->end && sfill(s) != 0) - 389 1649 : return EOF; - 390 297444 : return *s->pos++; + 388 299099 : if (s->pos == s->end && sfill(s) != 0) + 389 1654 : return EOF; + 390 297445 : return *s->pos++; 391 : } 392 : - 393 9875 : int sgettok(STREAM* f, char* str, int size) + 393 9929 : int sgettok(STREAM* f, char* str, int size) 394 : { - 395 9875 : char* i = str; - 396 9875 : char* send = str + size; + 395 9929 : char* i = str; + 396 9929 : char* send = str + size; 397 : int c; 398 : 399 : while (1) { - 400 65189 : c = sgetc(f); - 401 65189 : if (c == EOF) { - 402 277 : break; + 400 65431 : c = sgetc(f); + 401 65431 : if (c == EOF) { + 402 278 : break; 403 : } - 404 64912 : if (c == ' ' || c == '\t') { - 405 8791 : sungetc(c, f); - 406 8791 : break; + 404 65153 : if (c == ' ' || c == '\t') { + 405 8836 : sungetc(c, f); + 406 8836 : break; 407 : } - 408 56121 : if (c == '\n') { + 408 56317 : if (c == '\n') { 409 : /* remove ending carriage return to support the Windows CR+LF format */ - 410 807 : if (i != str && i[-1] == '\r') + 410 815 : if (i != str && i[-1] == '\r') 411 0 : --i; - 412 807 : sungetc(c, f); - 413 807 : break; + 412 815 : sungetc(c, f); + 413 815 : break; 414 : } 415 : - 416 55314 : *i++ = c; + 416 55502 : *i++ = c; 417 : - 418 55314 : if (i == send) { + 418 55502 : if (i == send) { 419 : /* LCOV_EXCL_START */ 420 : return -1; 421 : /* LCOV_EXCL_STOP */ 422 : } 423 : } 424 : - 425 9875 : *i = 0; + 425 9929 : *i = 0; 426 : - 427 9875 : return i - str; + 427 9929 : return i - str; 428 : } 429 : - 430 13236843 : int sread(STREAM* f, void* void_data, unsigned size) + 430 13236979 : int sread(STREAM* f, void* void_data, unsigned size) 431 : { - 432 13236843 : unsigned char* data = void_data; + 432 13236979 : unsigned char* data = void_data; 433 : 434 : /* if there is enough space in memory */ - 435 13236843 : if (sptrlookup(f, size)) { + 435 13236979 : if (sptrlookup(f, size)) { 436 : /* optimized version with all the data in memory */ - 437 13210539 : unsigned char* pos = sptrget(f); + 437 13210923 : unsigned char* pos = sptrget(f); 438 : 439 : /* copy it */ - 440 211762965 : while (size--) - 441 198552426 : *data++ = *pos++; + 440 211770491 : while (size--) + 441 198559568 : *data++ = *pos++; 442 : - 443 13210539 : sptrset(f, pos); + 443 13210923 : sptrset(f, pos); 444 : } else { 445 : /* standard version using sgetc() */ - 446 1352124 : while (size--) { - 447 1325820 : int c = sgetc(f); - 448 1325820 : if (c == EOF) { + 446 1346793 : while (size--) { + 447 1320737 : int c = sgetc(f); + 448 1320737 : if (c == EOF) { 449 : /* LCOV_EXCL_START */ 450 : return -1; 451 : /* LCOV_EXCL_STOP */ 452 : } 453 : - 454 1325820 : *data++ = c; + 454 1320737 : *data++ = c; 455 : } 456 : } 457 : - 458 13236843 : return 0; + 458 13236979 : return 0; 459 : } 460 : - 461 5706 : int sgetline(STREAM* f, char* str, int size) + 461 5738 : int sgetline(STREAM* f, char* str, int size) 462 : { - 463 5706 : char* i = str; - 464 5706 : char* send = str + size; + 463 5738 : char* i = str; + 464 5738 : char* send = str + size; 465 : int c; 466 : 467 : /* if there is enough data in memory */ - 468 5706 : if (sptrlookup(f, size)) { + 468 5738 : if (sptrlookup(f, size)) { 469 : /* optimized version with all the data in memory */ 470 0 : unsigned char* pos = sptrget(f); 471 : @@ -556,22 +556,22 @@ 494 0 : sptrset(f, pos); 495 : } else { 496 : while (1) { - 497 146677 : c = sgetc(f); - 498 146677 : if (c == EOF) { + 497 147172 : c = sgetc(f); + 498 147172 : if (c == EOF) { 499 : /* LCOV_EXCL_START */ 500 : break; 501 : /* LCOV_EXCL_STOP */ 502 : } 503 : - 504 146677 : if (c == '\n') { + 504 147172 : if (c == '\n') { 505 : /* remove ending carriage return to support the Windows CR+LF format */ - 506 5706 : if (i != str && i[-1] == '\r') + 506 5738 : if (i != str && i[-1] == '\r') 507 0 : --i; - 508 5706 : sungetc(c, f); - 509 5706 : break; + 508 5738 : sungetc(c, f); + 509 5738 : break; 510 : } 511 : - 512 140971 : if (i + 1 >= send) { + 512 141434 : if (i + 1 >= send) { 513 : /* LCOV_EXCL_START */ 514 : *i = 0; 515 : sungetc(c, f); @@ -579,74 +579,74 @@ 517 : /* LCOV_EXCL_STOP */ 518 : } 519 : - 520 140971 : *i++ = c; + 520 141434 : *i++ = c; 521 : } 522 : } 523 : - 524 5706 : *i = 0; + 524 5738 : *i = 0; 525 : - 526 5706 : return i - str; + 526 5738 : return i - str; 527 : } 528 : - 529 5663 : int sgetlasttok(STREAM* f, char* str, int size) + 529 5686 : int sgetlasttok(STREAM* f, char* str, int size) 530 : { 531 : int ret; 532 : - 533 5663 : ret = sgetline(f, str, size); - 534 5663 : if (ret < 0) { + 533 5686 : ret = sgetline(f, str, size); + 534 5686 : if (ret < 0) { 535 : /* LCOV_EXCL_START */ 536 : return ret; 537 : /* LCOV_EXCL_STOP */ 538 : } 539 : - 540 5663 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t')) + 540 5686 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t')) 541 0 : --ret; 542 : - 543 5663 : str[ret] = 0; + 543 5686 : str[ret] = 0; 544 : - 545 5663 : return ret; + 545 5686 : return ret; 546 : } 547 : - 548 280 : int sgetu32(STREAM* f, uint32_t* value) + 548 283 : int sgetu32(STREAM* f, uint32_t* value) 549 : { 550 : int c; 551 : - 552 280 : c = sgetc(f); - 553 280 : if (c == '0') { + 552 283 : c = sgetc(f); + 553 283 : if (c == '0') { 554 0 : *value = 0; 555 0 : return 0; - 556 280 : } else if (c >= '1' && c <= '9') { + 556 283 : } else if (c >= '1' && c <= '9') { 557 : uint32_t v; 558 : - 559 280 : v = c - '0'; + 559 283 : v = c - '0'; 560 : - 561 280 : c = sgetc(f); - 562 281 : while (c >= '0' && c <= '9') { + 561 283 : c = sgetc(f); + 562 287 : while (c >= '0' && c <= '9') { 563 : uint32_t digit; - 564 1 : if (v > 0xFFFFFFFFU / 10) { + 564 4 : if (v > 0xFFFFFFFFU / 10) { 565 : /* LCOV_EXCL_START */ 566 : /* overflow */ 567 : return -1; 568 : /* LCOV_EXCL_STOP */ 569 : } - 570 1 : v *= 10; + 570 4 : v *= 10; 571 : - 572 1 : digit = c - '0'; - 573 1 : if (v > 0xFFFFFFFFU - digit) { + 572 4 : digit = c - '0'; + 573 4 : if (v > 0xFFFFFFFFU - digit) { 574 : /* LCOV_EXCL_START */ 575 : /* overflow */ 576 : return -1; 577 : /* LCOV_EXCL_STOP */ 578 : } - 579 1 : v += digit; + 579 4 : v += digit; 580 : - 581 1 : c = sgetc(f); + 581 4 : c = sgetc(f); 582 : } 583 : - 584 280 : *value = v; + 584 283 : *value = v; 585 : - 586 280 : sungetc(c, f); - 587 280 : return 0; + 586 283 : sungetc(c, f); + 587 283 : return 0; 588 : } else { 589 : /* LCOV_EXCL_START */ 590 : /* nothing read */ @@ -655,76 +655,76 @@ 593 : } 594 : } 595 : - 596 19212483 : int sgetb32(STREAM* f, uint32_t* value) + 596 19190230 : int sgetb32(STREAM* f, uint32_t* value) 597 : { 598 : uint32_t v; 599 : unsigned char b; 600 : unsigned char s; 601 : int c; 602 : - 603 19212483 : v = 0; - 604 19212483 : s = 0; - 605 36660649 : loop: - 606 36660649 : c = sgetc(f); - 607 36660649 : if (c == EOF) { + 603 19190230 : v = 0; + 604 19190230 : s = 0; + 605 36975859 : loop: + 606 36975859 : c = sgetc(f); + 607 36975859 : if (c == EOF) { 608 : /* LCOV_EXCL_START */ 609 : return -1; 610 : /* LCOV_EXCL_STOP */ 611 : } 612 : - 613 36660649 : b = (unsigned char)c; - 614 36660649 : if ((b & 0x80) == 0) { - 615 17448166 : v |= (uint32_t)b << s; - 616 17448166 : s += 7; - 617 17448166 : if (s >= 32) { + 613 36975859 : b = (unsigned char)c; + 614 36975859 : if ((b & 0x80) == 0) { + 615 17785629 : v |= (uint32_t)b << s; + 616 17785629 : s += 7; + 617 17785629 : if (s >= 32) { 618 : /* LCOV_EXCL_START */ 619 : return -1; 620 : /* LCOV_EXCL_STOP */ 621 : } - 622 17448166 : goto loop; + 622 17785629 : goto loop; 623 : } 624 : - 625 19212483 : v |= (uint32_t)(b & 0x7f) << s; + 625 19190230 : v |= (uint32_t)(b & 0x7f) << s; 626 : - 627 19212483 : *value = v; + 627 19190230 : *value = v; 628 : - 629 19212483 : return 0; + 629 19190230 : return 0; 630 : } 631 : - 632 11258012 : int sgetb64(STREAM* f, uint64_t* value) + 632 11246935 : int sgetb64(STREAM* f, uint64_t* value) 633 : { 634 : uint64_t v; 635 : unsigned char b; 636 : unsigned char s; 637 : int c; 638 : - 639 11258012 : v = 0; - 640 11258012 : s = 0; - 641 41020058 : loop: - 642 41020058 : c = sgetc(f); - 643 41020058 : if (c == EOF) { + 639 11246935 : v = 0; + 640 11246935 : s = 0; + 641 41009253 : loop: + 642 41009253 : c = sgetc(f); + 643 41009253 : if (c == EOF) { 644 : /* LCOV_EXCL_START */ 645 : return -1; 646 : /* LCOV_EXCL_STOP */ 647 : } 648 : - 649 41020058 : b = (unsigned char)c; - 650 41020058 : if ((b & 0x80) == 0) { - 651 29762046 : v |= (uint64_t)b << s; - 652 29762046 : s += 7; - 653 29762046 : if (s >= 64) { + 649 41009253 : b = (unsigned char)c; + 650 41009253 : if ((b & 0x80) == 0) { + 651 29762318 : v |= (uint64_t)b << s; + 652 29762318 : s += 7; + 653 29762318 : if (s >= 64) { 654 : /* LCOV_EXCL_START */ 655 : return -1; 656 : /* LCOV_EXCL_STOP */ 657 : } - 658 29762046 : goto loop; + 658 29762318 : goto loop; 659 : } 660 : - 661 11258012 : v |= (uint64_t)(b & 0x7f) << s; + 661 11246935 : v |= (uint64_t)(b & 0x7f) << s; 662 : - 663 11258012 : *value = v; + 663 11246935 : *value = v; 664 : - 665 11258012 : return 0; + 665 11246935 : return 0; 666 : } 667 : 668 392 : int sgetble32(STREAM* f, uint32_t* value) @@ -742,35 +742,35 @@ 680 392 : return 0; 681 : } 682 : - 683 4004187 : int sgetbs(STREAM* f, char* str, int size) + 683 4004224 : int sgetbs(STREAM* f, char* str, int size) 684 : { 685 : uint32_t len; 686 : - 687 4004187 : if (sgetb32(f, &len) < 0) { + 687 4004224 : if (sgetb32(f, &len) < 0) { 688 : /* LCOV_EXCL_START */ 689 : return -1; 690 : /* LCOV_EXCL_STOP */ 691 : } 692 : - 693 4004187 : if (len + 1 > (uint32_t)size) { + 693 4004224 : if (len + 1 > (uint32_t)size) { 694 : /* LCOV_EXCL_START */ 695 : return -1; 696 : /* LCOV_EXCL_STOP */ 697 : } 698 : - 699 4004187 : str[len] = 0; + 699 4004224 : str[len] = 0; 700 : - 701 4004187 : return sread(f, str, (int)len); + 701 4004224 : return sread(f, str, (int)len); 702 : } 703 : - 704 21650829 : int swrite(const void* void_data, unsigned size, STREAM* f) + 704 21440832 : int swrite(const void* void_data, unsigned size, STREAM* f) 705 : { - 706 21650829 : const unsigned char* data = void_data; + 706 21440832 : const unsigned char* data = void_data; 707 : 708 : /* if there is enough space in memory */ - 709 21650829 : if (sptrlookup(f, size)) { + 709 21440832 : if (sptrlookup(f, size)) { 710 : /* optimized version with all the data in memory */ - 711 21644594 : unsigned char* pos = sptrget(f); + 711 21434636 : unsigned char* pos = sptrget(f); 712 : 713 : /** 714 : * Update the crc *before* writing the data in the buffer @@ -779,19 +779,19 @@ 717 : * to be able to detect memory errors on the buffer, 718 : * happening before we write it on the file. 719 : */ - 720 21644594 : if (f->flags & STREAM_FLAGS_CRC) { - 721 21644594 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); + 720 21434636 : if (f->flags & STREAM_FLAGS_CRC) { + 721 21434636 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); 722 : } 723 : 724 : /* copy it */ - 725 158733264 : while (size--) - 726 137088670 : *pos++ = *data++; + 725 157447190 : while (size--) + 726 136012554 : *pos++ = *data++; 727 : - 728 21644594 : sptrset(f, pos); + 728 21434636 : sptrset(f, pos); 729 : } else { 730 : /* standard version using sputc() */ - 731 196188 : while (size--) { - 732 189953 : if (sputc(*data++, f) != 0) { + 731 194484 : while (size--) { + 732 188288 : if (sputc(*data++, f) != 0) { 733 : /* LCOV_EXCL_START */ 734 : return -1; 735 : /* LCOV_EXCL_STOP */ @@ -799,83 +799,83 @@ 737 : } 738 : } 739 : - 740 21650829 : return 0; + 740 21440832 : return 0; 741 : } 742 : - 743 9508972 : int sputb32(uint32_t value, STREAM* s) + 743 9413354 : int sputb32(uint32_t value, STREAM* s) 744 : { 745 : unsigned char b; 746 : unsigned char buf[16]; 747 : unsigned i; 748 : - 749 9508972 : i = 0; - 750 18146612 : loop: - 751 18146612 : b = value & 0x7f; - 752 18146612 : value >>= 7; + 749 9413354 : i = 0; + 750 18145593 : loop: + 751 18145593 : b = value & 0x7f; + 752 18145593 : value >>= 7; 753 : - 754 18146612 : if (value) { - 755 8637640 : buf[i++] = b; - 756 8637640 : goto loop; + 754 18145593 : if (value) { + 755 8732239 : buf[i++] = b; + 756 8732239 : goto loop; 757 : } 758 : - 759 9508972 : buf[i++] = b | 0x80; + 759 9413354 : buf[i++] = b | 0x80; 760 : - 761 9508972 : return swrite(buf, i, s); + 761 9413354 : return swrite(buf, i, s); 762 : } 763 : - 764 5572622 : int sputb64(uint64_t value, STREAM* s) + 764 5517420 : int sputb64(uint64_t value, STREAM* s) 765 : { 766 : unsigned char b; 767 : unsigned char buf[16]; 768 : unsigned i; 769 : - 770 5572622 : i = 0; - 771 20318073 : loop: - 772 20318073 : b = value & 0x7f; - 773 20318073 : value >>= 7; + 770 5517420 : i = 0; + 771 20129323 : loop: + 772 20129323 : b = value & 0x7f; + 773 20129323 : value >>= 7; 774 : - 775 20318073 : if (value) { - 776 14745451 : buf[i++] = b; - 777 14745451 : goto loop; + 775 20129323 : if (value) { + 776 14611903 : buf[i++] = b; + 777 14611903 : goto loop; 778 : } 779 : - 780 5572622 : buf[i++] = b | 0x80; + 780 5517420 : buf[i++] = b | 0x80; 781 : - 782 5572622 : return swrite(buf, i, s); + 782 5517420 : return swrite(buf, i, s); 783 : } 784 : - 785 173 : int sputble32(uint32_t value, STREAM* s) + 785 172 : int sputble32(uint32_t value, STREAM* s) 786 : { 787 : unsigned char buf[4]; 788 : - 789 173 : buf[0] = value & 0xFF; - 790 173 : buf[1] = (value >> 8) & 0xFF; - 791 173 : buf[2] = (value >> 16) & 0xFF; - 792 173 : buf[3] = (value >> 24) & 0xFF; + 789 172 : buf[0] = value & 0xFF; + 790 172 : buf[1] = (value >> 8) & 0xFF; + 791 172 : buf[2] = (value >> 16) & 0xFF; + 792 172 : buf[3] = (value >> 24) & 0xFF; 793 : - 794 173 : return swrite(buf, 4, s); + 794 172 : return swrite(buf, 4, s); 795 : } 796 : - 797 1982279 : int sputbs(const char* str, STREAM* f) + 797 1964370 : int sputbs(const char* str, STREAM* f) 798 : { - 799 1982279 : size_t len = strlen(str); + 799 1964370 : size_t len = strlen(str); 800 : - 801 1982279 : if (sputb32(len, f) != 0) { + 801 1964370 : if (sputb32(len, f) != 0) { 802 : /* LCOV_EXCL_START */ 803 : return -1; 804 : /* LCOV_EXCL_STOP */ 805 : } 806 : - 807 1982279 : return swrite(str, len, f); + 807 1964370 : return swrite(str, len, f); 808 : } 809 : 810 : #if HAVE_FSYNC - 811 157 : int ssync(STREAM* s) + 811 156 : int ssync(STREAM* s) 812 : { 813 : unsigned i; 814 : - 815 1211 : for (i = 0; i < s->handle_size; ++i) { - 816 1054 : if (fsync(s->handle[i].f) != 0) { + 815 1203 : for (i = 0; i < s->handle_size; ++i) { + 816 1047 : if (fsync(s->handle[i].f) != 0) { 817 : /* LCOV_EXCL_START */ 818 : s->state = STREAM_STATE_ERROR; 819 : s->state_index = i; @@ -884,7 +884,7 @@ 822 : } 823 : } 824 : - 825 157 : return 0; + 825 156 : return 0; 826 : } 827 : #endif 828 : diff --git a/cov/cmdline/stream.h.func-sort-c.html b/cov/cmdline/stream.h.func-sort-c.html index 795eccde..5ea9bb08 100644 --- a/cov/cmdline/stream.h.func-sort-c.html +++ b/cov/cmdline/stream.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -69,39 +69,39 @@ sgeteol - 6687 + 6731 sgetspace - 22868 + 23010 sungetc - 38717 + 38947 serror - 3795184 + 3756051 sputc - 3968961 + 3933071 sptrget - 34855133 + 34645559 sptrset - 34855133 + 34645559 sptrlookup - 34893378 + 34683549 sgetc - 86901471 + 87201813
diff --git a/cov/cmdline/stream.h.func.html b/cov/cmdline/stream.h.func.html index d6052605..cc1a51e4 100644 --- a/cov/cmdline/stream.h.func.html +++ b/cov/cmdline/stream.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -65,7 +65,7 @@ serror - 3795184 + 3756051 serrorfile @@ -73,35 +73,35 @@ sgetc - 86901471 + 87201813 sgeteol - 6687 + 6731 sgetspace - 22868 + 23010 sptrget - 34855133 + 34645559 sptrlookup - 34893378 + 34683549 sptrset - 34855133 + 34645559 sputc - 3968961 + 3933071 sungetc - 38717 + 38947
diff --git a/cov/cmdline/stream.h.gcov.html b/cov/cmdline/stream.h.gcov.html index e22695d2..87eca41e 100644 --- a/cov/cmdline/stream.h.gcov.html +++ b/cov/cmdline/stream.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 10 @@ -228,33 +228,33 @@ 166 : /** 167 : * Check if the buffer has enough data loaded. 168 : */ - 169 34893378 : static inline int sptrlookup(STREAM* s, int size) + 169 34683549 : static inline int sptrlookup(STREAM* s, int size) 170 : { - 171 34893378 : return s->pos + size <= s->end; + 171 34683549 : return s->pos + size <= s->end; 172 : } 173 : 174 : /** 175 : * Get the current stream ptr. 176 : */ - 177 34855133 : static inline unsigned char* sptrget(STREAM* s) + 177 34645559 : static inline unsigned char* sptrget(STREAM* s) 178 : { - 179 34855133 : return s->pos; + 179 34645559 : return s->pos; 180 : } 181 : 182 : /** 183 : * Set the current stream ptr. 184 : */ - 185 34855133 : static inline void sptrset(STREAM* s, unsigned char* ptr) + 185 34645559 : static inline void sptrset(STREAM* s, unsigned char* ptr) 186 : { - 187 34855133 : s->pos = ptr; - 188 34855133 : } + 187 34645559 : s->pos = ptr; + 188 34645559 : } 189 : 190 : /** 191 : * Check the error status. Like ferror(). 192 : */ - 193 3795184 : static inline int serror(STREAM* s) + 193 3756051 : static inline int serror(STREAM* s) 194 : { - 195 3795184 : return s->state == STREAM_STATE_ERROR; + 195 3756051 : return s->state == STREAM_STATE_ERROR; 196 : } 197 : 198 : /** @@ -298,22 +298,22 @@ 236 : /** 237 : * Read a char. Like fgetc(). 238 : */ - 239 86901471 : static inline int sgetc(STREAM* s) + 239 87201813 : static inline int sgetc(STREAM* s) 240 : { - 241 86901471 : if (tommy_unlikely(s->pos == s->end)) - 242 299093 : return sgetc_uncached(s); - 243 86602378 : return *s->pos++; + 241 87201813 : if (tommy_unlikely(s->pos == s->end)) + 242 299099 : return sgetc_uncached(s); + 243 86902714 : return *s->pos++; 244 : } 245 : 246 : /** 247 : * Unread a char. 248 : * Like ungetc() but you have to unget the same char read. 249 : */ - 250 38717 : static inline void sungetc(int c, STREAM* s) + 250 38947 : static inline void sungetc(int c, STREAM* s) 251 : { - 252 38717 : if (c != EOF) - 253 37886 : --s->pos; - 254 38717 : } + 252 38947 : if (c != EOF) + 253 38113 : --s->pos; + 254 38947 : } 255 : 256 : /** 257 : * Read a fixed amount of chars. @@ -324,34 +324,34 @@ 262 : /** 263 : * Get a char from a stream, ignoring one '\r'. 264 : */ - 265 6687 : static inline int sgeteol(STREAM* f) + 265 6731 : static inline int sgeteol(STREAM* f) 266 : { 267 : int c; 268 : - 269 6687 : c = sgetc(f); - 270 6687 : if (c == '\r') + 269 6731 : c = sgetc(f); + 270 6731 : if (c == '\r') 271 0 : c = sgetc(f); 272 : - 273 6687 : return c; + 273 6731 : return c; 274 : } 275 : 276 : /** 277 : * Read all the spaces and tabs. 278 : * Return the number of spaces and tabs read. 279 : */ - 280 22868 : static inline int sgetspace(STREAM* f) + 280 23010 : static inline int sgetspace(STREAM* f) 281 : { - 282 22868 : int count = 0; + 282 23010 : int count = 0; 283 : int c; 284 : - 285 22868 : c = sgetc(f); - 286 31659 : while (c == ' ' || c == '\t') { - 287 8791 : ++count; - 288 8791 : c = sgetc(f); + 285 23010 : c = sgetc(f); + 286 31846 : while (c == ' ' || c == '\t') { + 287 8836 : ++count; + 288 8836 : c = sgetc(f); 289 : } 290 : - 291 22868 : sungetc(c, f); - 292 22868 : return count; + 291 23010 : sungetc(c, f); + 292 23010 : return count; 293 : } 294 : 295 : /** @@ -414,10 +414,10 @@ 352 : * Write a char. Like fputc(). 353 : * Return 0 on success or -1 on error. 354 : */ - 355 3968961 : static inline int sputc(int c, STREAM* s) + 355 3933071 : static inline int sputc(int c, STREAM* s) 356 : { - 357 3968961 : if (s->pos == s->end) { - 358 38671 : if (sflush(s) != 0) + 357 3933071 : if (s->pos == s->end) { + 358 38652 : if (sflush(s) != 0) 359 0 : return -1; 360 : } 361 : @@ -428,12 +428,12 @@ 366 : * to be able to detect memory errors on the buffer, 367 : * happening before we write it on the file. 368 : */ - 369 3968961 : if (s->flags & STREAM_FLAGS_CRC) - 370 3968961 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); + 369 3933071 : if (s->flags & STREAM_FLAGS_CRC) + 370 3933071 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); 371 : - 372 3968961 : *s->pos++ = c; + 372 3933071 : *s->pos++ = c; 373 : - 374 3968961 : return 0; + 374 3933071 : return 0; 375 : } 376 : 377 : /** diff --git a/cov/cmdline/support.c.func-sort-c.html b/cov/cmdline/support.c.func-sort-c.html index dd03490b..a44989a5 100644 --- a/cov/cmdline/support.c.func-sort-c.html +++ b/cov/cmdline/support.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 633 - 991 - 63.9 % + 769 + 956 + 80.4 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 75 + 78 84 - 89.3 % + 92.9 % @@ -64,11 +64,11 @@ 0 - log_fatal_errno + log_fatal_errno 0 - path_is_root_of + path_is_root_of 0 @@ -79,321 +79,321 @@ random_u8 0 - - scomma - 0 - - - smartctl_attribute - 0 - - - smatch - 0 - unlock_random 0 - strlwr + strlwr 2 - smartctl_flush + smartctl_flush 5 - worddigitstr + worddigitstr 11 - strtrim - 13 + smartctl_attribute + 14 - printp + printp 18 - strpolish - 21 - - - log_error_errno + log_error_errno 27 - match_class + match_class 28 - printr + printr 34 - printc - 77 + strtrim + 67 - printl - 142 + printc + 78 - pathcat - 279 + printl + 157 + + + strpolish + 256 + + + pathcat + 280 random_reseed - 283 + 284 lock_done - 288 + 289 lock_init - 310 + 311 - thread_cond_destroy + thread_cond_destroy 404 - thread_cond_init + thread_cond_init 404 - malloc_counter_get + malloc_counter_get 488 - msg_flush - 586 + msg_flush + 572 - thread_cond_signal - 668 - - - thread_cond_signal_and_unlock - 668 - - - msg_status + msg_status 743 - pathcatc + pathcatc 788 - log_fatal + log_fatal 803 - strsplit - 1718 + thread_cond_signal + 827 - msg_bar - 2118 + thread_cond_signal_and_unlock + 827 - thread_create - 2876 + strsplit + 1720 - thread_join - 2876 + smatch + 1779 - thread_mutex_destroy - 3167 + msg_bar + 2042 - thread_mutex_init - 3299 + scomma + 2316 - log_flush - 3649 + thread_create + 2883 - log_expected + thread_join + 2883 + + + thread_mutex_destroy + 3180 + + + thread_mutex_init + 3312 + + + log_flush + 3652 + + + log_expected 4697 - msg_progress - 5081 + msg_progress + 5066 - pathslash - 7949 + pathslash + 7959 - lmtime + lmtime 11645 - pathexport + pathexport 12234 - pathimport - 17981 + pathimport + 18024 - vmsg - 41543 + vmsg + 41562 - pathcut - 58108 + pathcut + 58110 - thread_yield - 105499 + thread_yield + 108112 - fmtime - 121348 + fmtime + 121378 - msg_verbose - 127020 + msg_verbose + 127094 - smart_temp - 145110 + smart_temp + 145124 - calloc_nofail - 156192 + calloc_nofail + 156271 - thread_cond_broadcast_and_unlock - 257469 + thread_cond_broadcast_and_unlock + 257343 - thread_cond_broadcast - 257671 + thread_cond_broadcast + 257545 - msg_info - 312495 + msg_info + 312664 - log_error - 365227 + log_error + 364924 - esc_shell_multi - 366218 + esc_shell_multi + 366387 - mkancestor - 787726 + mkancestor + 787783 - advise_write - 914575 + advise_write + 914297 - thread_cond_wait - 1554330 + thread_cond_wait + 1554290 is_hw - 1830939 + 1830711 - pathcpy - 1902922 + pathcpy + 1902784 - advise_open - 2410879 + advise_open + 2410781 - advise_flags - 2489611 + advise_flags + 2489478 - advise_init - 2489611 + advise_init + 2489478 - esc_tag - 2652388 + esc_tag + 2653118 - pathcatl + pathcatl 3601926 - ssget - 5261663 + ssget + 5265543 - strdup_nofail - 5965500 + strdup_nofail + 5965600 - advise_read - 8833871 + advise_read + 8833464 - malloc_nofail - 14819123 + malloc_nofail + 14819141 - malloc_counter_inc - 20940815 + malloc_counter_inc + 20941012 lock_memory - 20941303 + 20941500 unlock_memory - 20941303 + 20941500 - log_tag - 21732148 + log_tag + 21733516 lock_msg - 22554567 + 22555773 unlock_msg - 22554567 + 22555773 - pathprint - 42979947 + pathprint + 42981264 - pathcmp - 53116131 + pathcmp + 53117221 - char_match - 86982601 + char_match + 86985273 - wnmatch - 102260599 + wnmatch + 102263029 - thread_mutex_lock - 112510359 + thread_mutex_lock + 112377134 - thread_mutex_unlock - 112510359 + thread_mutex_unlock + 112377134
diff --git a/cov/cmdline/support.c.func.html b/cov/cmdline/support.c.func.html index 7de0aca5..b5f7b1cc 100644 --- a/cov/cmdline/support.c.func.html +++ b/cov/cmdline/support.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 633 - 991 - 63.9 % + 769 + 956 + 80.4 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 75 + 78 84 - 89.3 % + 92.9 % @@ -60,208 +60,208 @@ Hit count Sort by hit count - advise_flags - 2489611 + advise_flags + 2489478 - advise_init - 2489611 + advise_init + 2489478 - advise_open - 2410879 + advise_open + 2410781 - advise_read - 8833871 + advise_read + 8833464 - advise_write - 914575 + advise_write + 914297 - calloc_nofail - 156192 + calloc_nofail + 156271 - char_match - 86982601 + char_match + 86985273 - esc_shell_multi - 366218 + esc_shell_multi + 366387 - esc_tag - 2652388 + esc_tag + 2653118 - fmtime - 121348 + fmtime + 121378 is_hw - 1830939 + 1830711 - lmtime + lmtime 11645 lock_done - 288 + 289 lock_init - 310 + 311 lock_memory - 20941303 + 20941500 lock_msg - 22554567 + 22555773 lock_random 0 - log_error - 365227 + log_error + 364924 - log_error_errno + log_error_errno 27 - log_expected + log_expected 4697 - log_fatal + log_fatal 803 - log_fatal_errno + log_fatal_errno 0 - log_flush - 3649 + log_flush + 3652 - log_tag - 21732148 + log_tag + 21733516 - malloc_counter_get + malloc_counter_get 488 - malloc_counter_inc - 20940815 + malloc_counter_inc + 20941012 - malloc_nofail - 14819123 + malloc_nofail + 14819141 - match_class + match_class 28 - mkancestor - 787726 + mkancestor + 787783 - msg_bar - 2118 + msg_bar + 2042 - msg_flush - 586 + msg_flush + 572 - msg_info - 312495 + msg_info + 312664 - msg_progress - 5081 + msg_progress + 5066 - msg_status + msg_status 743 - msg_verbose - 127020 + msg_verbose + 127094 - path_is_root_of + path_is_root_of 0 - pathcat - 279 + pathcat + 280 - pathcatc + pathcatc 788 - pathcatl + pathcatl 3601926 - pathcmp - 53116131 + pathcmp + 53117221 - pathcpy - 1902922 + pathcpy + 1902784 - pathcut - 58108 + pathcut + 58110 - pathexport + pathexport 12234 - pathimport - 17981 + pathimport + 18024 - pathprint - 42979947 + pathprint + 42981264 - pathslash - 7949 + pathslash + 7959 - printc - 77 + printc + 78 - printl - 142 + printl + 157 - printp + printp 18 - printr + printr 34 random_reseed - 283 + 284 random_u64 @@ -272,127 +272,127 @@ 0 - scomma - 0 + scomma + 2316 - smart_temp - 145110 + smart_temp + 145124 - smartctl_attribute - 0 + smartctl_attribute + 14 - smartctl_flush + smartctl_flush 5 - smatch - 0 + smatch + 1779 - ssget - 5261663 + ssget + 5265543 - strdup_nofail - 5965500 + strdup_nofail + 5965600 - strlwr + strlwr 2 - strpolish - 21 + strpolish + 256 - strsplit - 1718 + strsplit + 1720 - strtrim - 13 + strtrim + 67 - thread_cond_broadcast - 257671 + thread_cond_broadcast + 257545 - thread_cond_broadcast_and_unlock - 257469 + thread_cond_broadcast_and_unlock + 257343 - thread_cond_destroy + thread_cond_destroy 404 - thread_cond_init + thread_cond_init 404 - thread_cond_signal - 668 + thread_cond_signal + 827 - thread_cond_signal_and_unlock - 668 + thread_cond_signal_and_unlock + 827 - thread_cond_wait - 1554330 + thread_cond_wait + 1554290 - thread_create - 2876 + thread_create + 2883 - thread_join - 2876 + thread_join + 2883 - thread_mutex_destroy - 3167 + thread_mutex_destroy + 3180 - thread_mutex_init - 3299 + thread_mutex_init + 3312 - thread_mutex_lock - 112510359 + thread_mutex_lock + 112377134 - thread_mutex_unlock - 112510359 + thread_mutex_unlock + 112377134 - thread_yield - 105499 + thread_yield + 108112 unlock_memory - 20941303 + 20941500 unlock_msg - 22554567 + 22555773 unlock_random 0 - vmsg - 41543 + vmsg + 41562 - wnmatch - 102260599 + wnmatch + 102263029 - worddigitstr + worddigitstr 11 diff --git a/cov/cmdline/support.c.gcov.html b/cov/cmdline/support.c.gcov.html index a91b3552..17ab328d 100644 --- a/cov/cmdline/support.c.gcov.html +++ b/cov/cmdline/support.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 633 - 991 - 63.9 % + 769 + 956 + 80.4 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 75 + 78 84 - 89.3 % + 92.9 % @@ -93,33 +93,33 @@ 31 : static thread_mutex_t random_lock; 32 : #endif 33 : - 34 22554567 : void lock_msg(void) + 34 22555773 : void lock_msg(void) 35 : { 36 : #if HAVE_THREAD - 37 22554567 : thread_mutex_lock(&msg_lock); + 37 22555773 : thread_mutex_lock(&msg_lock); 38 : #endif - 39 22554567 : } + 39 22555773 : } 40 : - 41 22554567 : void unlock_msg(void) + 41 22555773 : void unlock_msg(void) 42 : { 43 : #if HAVE_THREAD - 44 22554567 : thread_mutex_unlock(&msg_lock); + 44 22555773 : thread_mutex_unlock(&msg_lock); 45 : #endif - 46 22554567 : } + 46 22555773 : } 47 : - 48 20941303 : void lock_memory(void) + 48 20941500 : void lock_memory(void) 49 : { 50 : #if HAVE_THREAD - 51 20941303 : thread_mutex_lock(&memory_lock); + 51 20941500 : thread_mutex_lock(&memory_lock); 52 : #endif - 53 20941303 : } + 53 20941500 : } 54 : - 55 20941303 : void unlock_memory(void) + 55 20941500 : void unlock_memory(void) 56 : { 57 : #if HAVE_THREAD - 58 20941303 : thread_mutex_unlock(&memory_lock); + 58 20941500 : thread_mutex_unlock(&memory_lock); 59 : #endif - 60 20941303 : } + 60 20941500 : } 61 : 62 0 : void lock_random(void) 63 : { @@ -136,34 +136,34 @@ 74 0 : } 75 : 76 : - 77 310 : void lock_init(void) + 77 311 : void lock_init(void) 78 : { 79 : #if HAVE_THREAD 80 : /* initialize the locks as first operation as log_fatal depends on them */ - 81 310 : thread_mutex_init(&msg_lock); - 82 310 : thread_mutex_init(&memory_lock); - 83 310 : thread_mutex_init(&random_lock); + 81 311 : thread_mutex_init(&msg_lock); + 82 311 : thread_mutex_init(&memory_lock); + 83 311 : thread_mutex_init(&random_lock); 84 : #endif - 85 310 : } + 85 311 : } 86 : - 87 288 : void lock_done(void) + 87 289 : void lock_done(void) 88 : { 89 : #if HAVE_THREAD - 90 288 : thread_mutex_destroy(&msg_lock); - 91 288 : thread_mutex_destroy(&memory_lock); - 92 288 : thread_mutex_destroy(&random_lock); + 90 289 : thread_mutex_destroy(&msg_lock); + 91 289 : thread_mutex_destroy(&memory_lock); + 92 289 : thread_mutex_destroy(&random_lock); 93 : #endif - 94 288 : } + 94 289 : } 95 : 96 : /****************************************************************************/ 97 : /* random */ 98 : 99 : static uint64_t random_state = 1; 100 : - 101 283 : void random_reseed(void) + 101 284 : void random_reseed(void) 102 : { - 103 283 : random_state = tick(); - 104 283 : } + 103 284 : random_state = tick(); + 104 284 : } 105 : 106 0 : unsigned char random_u8(void) 107 : { @@ -198,2494 +198,2500 @@ 136 : /****************************************************************************/ 137 : /* error */ 138 : - 139 1830939 : int is_hw(int err) + 139 1830711 : int is_hw(int err) 140 : { - 141 1830939 : if (err == EIO) - 142 12 : return 1; - 143 : #ifdef EFSCORRUPTED - 144 : if (err == EFSCORRUPTED) /* used by XFS inside the kernel - never expected in user mode as converted to EUCLEAN */ - 145 : return 1; - 146 : #endif - 147 : #ifdef EUCLEAN - 148 1830927 : if (err == EUCLEAN) /* used by XFS at user level instead of EFSCORRUPTED */ - 149 0 : return 1; - 150 : #endif - 151 : #ifdef EBADCRC - 152 : if (err == EBADCRC) /* used by BTRFS - never expected in user mode as converted to EIO */ - 153 : return 1; - 154 : #endif - 155 : #ifdef EBADMSG - 156 1830927 : if (err == EBADMSG) /* used by BTRFS - never expected in user mode as converted to EIO */ - 157 0 : return 1; - 158 : #endif - 159 : #ifdef ENOMEDIUM - 160 1830927 : if (err == ENOMEDIUM) /* medium removed */ - 161 0 : return 1; - 162 : #endif - 163 : #ifdef EHWPOISON - 164 1830927 : if (err == EHWPOISON) /* hardware memory error */ - 165 0 : return 1; - 166 : #endif - 167 1830927 : return 0; - 168 : } - 169 : - 170 0 : void log_fatal_errno(int err, const char* name) - 171 : { - 172 0 : if (err == EIO) { - 173 0 : log_fatal(err, "DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name); - 174 : #ifdef EFSCORRUPTED - 175 : } else if (err == EFSCORRUPTED) { - 176 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s. It isn't possible to continue.\n", name); - 177 : #endif - 178 : #ifdef EUCLEAN - 179 0 : } else if (err == EUCLEAN) { - 180 0 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s. It isn't possible to continue.\n", name); - 181 : #endif - 182 : #ifdef EBADCRC - 183 : } else if (err == EBADCRC) { - 184 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s. It isn't possible to continue.\n", name); - 185 : #endif - 186 : #ifdef EBADMSG - 187 0 : } else if (err == EBADMSG) { - 188 0 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s. It isn't possible to continue.\n", name); - 189 : #endif - 190 : #ifdef ENOMEDIUM - 191 0 : } else if (err == ENOMEDIUM) { - 192 0 : log_fatal(err, "DANGER! Unexpected medium removed in disk %s. It isn't possible to continue.\n", name); - 193 : #endif - 194 : #ifdef EHWPOISON - 195 0 : } else if (err == EHWPOISON) { - 196 0 : log_fatal(err, "DANGER! Unexpected memory error in disk %s. It isn't possible to continue.\n", name); - 197 : #endif - 198 0 : } else if (err == EACCES) { - 199 0 : log_fatal(err, "WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name); - 200 0 : } else if (err == ENOSPC) { - 201 0 : log_fatal(err, "WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name); - 202 : } else { - 203 0 : log_fatal(err, "WARNING! Without a working %s disk, it isn't possible to continue.\n", name); - 204 : } - 205 0 : } - 206 : - 207 27 : void log_error_errno(int err, const char* name) - 208 : { - 209 27 : if (err == EIO) { - 210 0 : log_fatal(err, "DANGER! Unexpected input/output error in disk %s.\n", name); - 211 : #ifdef EFSCORRUPTED - 212 : } else if (err == EFSCORRUPTED) { - 213 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s.\n", name); - 214 : #endif - 215 : #ifdef EUCLEAN - 216 27 : } else if (err == EUCLEAN) { - 217 0 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s.\n", name); - 218 : #endif - 219 : #ifdef EBADCRC - 220 : } else if (err == EBADCRC) { - 221 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s.\n", name); - 222 : #endif - 223 : #ifdef EBADMSG - 224 27 : } else if (err == EBADMSG) { - 225 0 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s.\n", name); - 226 : #endif - 227 : #ifdef ENOMEDIUM - 228 27 : } else if (err == ENOMEDIUM) { - 229 0 : log_fatal(err, "DANGER! Unexpected medium removed in disk %s.\n", name); - 230 : #endif - 231 : #ifdef EHWPOISON - 232 27 : } else if (err == EHWPOISON) { - 233 0 : log_fatal(err, "DANGER! Unexpected memory error in disk %s.\n", name); - 234 : #endif - 235 27 : } else if (err == EACCES) { - 236 12 : log_error(err, "WARNING! Grant permission in the disk %s.\n", name); - 237 15 : } else if (err == ENOSPC) { - 238 0 : log_error(err, "WARNING! Ensure there is free space on the disk %s.\n", name); - 239 15 : } else if (err == ENOENT) { - 240 15 : log_error(err, "WARNING! You cannot modify files while running.\n"); - 241 : } - 242 27 : } - 243 : - 244 : /****************************************************************************/ - 245 : /* print */ - 246 : - 247 : int msg_level = 0; - 248 : FILE* stdlog = 0; - 249 : int msg_line_prev = 0; /**< Previous line width on stdout */ - 250 : int msg_line_curr = 0; /**< Current line width on stdout */ - 251 : - 252 : /* - 253 : * Note that in the following functions we always flush both - 254 : * stdout and stderr, because we want to ensure that they mixes - 255 : * well when redirected to files - 256 : * - 257 : * The buffering is similar at the "line buffered" one, that - 258 : * is not available on Windows, so we emulate it in this way. - 259 : * - 260 : * For stdlog flushing is limited. To ensure flushing the - 261 : * caller should use log_flush(). - 262 : */ - 263 : - 264 41543 : static void vmsg(FILE* out, const char* format, va_list ap) - 265 : { - 266 41543 : char* dup = strdup_nofail(format); - 267 41543 : int len = strlen(dup); - 268 41543 : int written = 0; - 269 41543 : char control = 0; - 270 : - 271 41543 : if (len > 0) { - 272 41543 : if (dup[len - 1] == '\n') { - 273 41533 : dup[len - 1] = 0; - 274 41533 : control = '\n'; - 275 10 : } else if (dup[len - 1] == '\r') { - 276 0 : dup[len - 1] = 0; - 277 0 : control = '\r'; - 278 : } - 279 : } - 280 : - 281 41543 : if (dup[0]) { - 282 41440 : written = vfprintf(out, dup, ap); - 283 : } - 284 : - 285 41543 : switch (control) { - 286 10 : case 0 : - 287 10 : msg_line_curr += written; - 288 10 : break; - 289 41533 : case '\n' : - 290 41533 : msg_line_curr += written; - 291 : /* writes spaces to overwrite any previous char */ - 292 41533 : while (msg_line_curr < msg_line_prev) { - 293 0 : fprintf(out, " "); - 294 0 : --msg_line_prev; - 295 : } - 296 41533 : msg_line_prev = 0; - 297 41533 : msg_line_curr = 0; - 298 41533 : fprintf(out, "\n"); - 299 41533 : break; - 300 0 : case '\r' : - 301 0 : msg_line_curr += written; - 302 : /* writes spaces to overwrite any previous char */ - 303 0 : while (msg_line_curr < msg_line_prev) { - 304 0 : fprintf(out, " "); - 305 0 : --msg_line_prev; - 306 : } - 307 0 : msg_line_prev = msg_line_curr; - 308 0 : msg_line_curr = 0; - 309 0 : fprintf(out, "\r"); - 310 : } - 311 : - 312 41543 : free(dup); - 313 41543 : } - 314 : - 315 803 : void log_fatal(int err, const char* format, ...) - 316 : { - 317 : va_list ap; - 318 : - 319 803 : lock_msg(); + 141 : /* LCOV_EXCL_START */ + 142 : if (err == EIO) + 143 : return 1; + 144 : #ifdef EFSCORRUPTED + 145 : if (err == EFSCORRUPTED) /* used by XFS inside the kernel - never expected in user mode as converted to EUCLEAN */ + 146 : return 1; + 147 : #endif + 148 : #ifdef EUCLEAN + 149 : if (err == EUCLEAN) /* used by XFS at user level instead of EFSCORRUPTED */ + 150 : return 1; + 151 : #endif + 152 : #ifdef EBADCRC + 153 : if (err == EBADCRC) /* used by BTRFS - never expected in user mode as converted to EIO */ + 154 : return 1; + 155 : #endif + 156 : #ifdef EBADMSG + 157 : if (err == EBADMSG) /* used by BTRFS - never expected in user mode as converted to EIO */ + 158 : return 1; + 159 : #endif + 160 : #ifdef ENOMEDIUM + 161 : if (err == ENOMEDIUM) /* medium removed */ + 162 : return 1; + 163 : #endif + 164 : #ifdef EHWPOISON + 165 : if (err == EHWPOISON) /* hardware memory error */ + 166 : return 1; + 167 : #endif + 168 : /* LCOV_EXCL_STOP */ + 169 1830699 : return 0; + 170 : } + 171 : + 172 0 : void log_fatal_errno(int err, const char* name) + 173 : { + 174 : /* LCOV_EXCL_START */ + 175 : if (err == EIO) { + 176 : log_fatal(err, "DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name); + 177 : #ifdef EFSCORRUPTED + 178 : } else if (err == EFSCORRUPTED) { + 179 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s. It isn't possible to continue.\n", name); + 180 : #endif + 181 : #ifdef EUCLEAN + 182 : } else if (err == EUCLEAN) { + 183 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s. It isn't possible to continue.\n", name); + 184 : #endif + 185 : #ifdef EBADCRC + 186 : } else if (err == EBADCRC) { + 187 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s. It isn't possible to continue.\n", name); + 188 : #endif + 189 : #ifdef EBADMSG + 190 : } else if (err == EBADMSG) { + 191 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s. It isn't possible to continue.\n", name); + 192 : #endif + 193 : #ifdef ENOMEDIUM + 194 : } else if (err == ENOMEDIUM) { + 195 : log_fatal(err, "DANGER! Unexpected medium removed in disk %s. It isn't possible to continue.\n", name); + 196 : #endif + 197 : #ifdef EHWPOISON + 198 : } else if (err == EHWPOISON) { + 199 : log_fatal(err, "DANGER! Unexpected memory error in disk %s. It isn't possible to continue.\n", name); + 200 : #endif + 201 : } else if (err == EACCES) { + 202 : log_fatal(err, "WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name); + 203 : } else if (err == ENOSPC) { + 204 : log_fatal(err, "WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name); + 205 : } else { + 206 : log_fatal(err, "WARNING! Without a working %s disk, it isn't possible to continue.\n", name); + 207 : } + 208 : /* LCOV_EXCL_STOP */ + 209 0 : } + 210 : + 211 27 : void log_error_errno(int err, const char* name) + 212 : { + 213 : /* LCOV_EXCL_START */ + 214 : if (err == EIO) { + 215 : log_fatal(err, "DANGER! Unexpected input/output error in disk %s.\n", name); + 216 : #ifdef EFSCORRUPTED + 217 : } else if (err == EFSCORRUPTED) { + 218 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s.\n", name); + 219 : #endif + 220 : #ifdef EUCLEAN + 221 : } else if (err == EUCLEAN) { + 222 : log_fatal(err, "DANGER! Unexpected corrupted error in disk %s.\n", name); + 223 : #endif + 224 : #ifdef EBADCRC + 225 : } else if (err == EBADCRC) { + 226 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s.\n", name); + 227 : #endif + 228 : #ifdef EBADMSG + 229 : } else if (err == EBADMSG) { + 230 : log_fatal(err, "DANGER! Unexpected bad crc error in disk %s.\n", name); + 231 : #endif + 232 : #ifdef ENOMEDIUM + 233 : } else if (err == ENOMEDIUM) { + 234 : log_fatal(err, "DANGER! Unexpected medium removed in disk %s.\n", name); + 235 : #endif + 236 : #ifdef EHWPOISON + 237 : } else if (err == EHWPOISON) { + 238 : log_fatal(err, "DANGER! Unexpected memory error in disk %s.\n", name); + 239 : #endif + 240 : /* LCOV_EXCL_STOP */ + 241 27 : } else if (err == EACCES) { + 242 12 : log_error(err, "WARNING! Grant permission in the disk %s.\n", name); + 243 15 : } else if (err == ENOSPC) { + 244 0 : log_error(err, "WARNING! Ensure there is free space on the disk %s.\n", name); + 245 15 : } else if (err == ENOENT) { + 246 15 : log_error(err, "WARNING! You cannot modify files while running.\n"); + 247 : } + 248 27 : } + 249 : + 250 : /****************************************************************************/ + 251 : /* print */ + 252 : + 253 : int msg_level = 0; + 254 : FILE* stdlog = 0; + 255 : int msg_line_prev = 0; /**< Previous line width on stdout */ + 256 : int msg_line_curr = 0; /**< Current line width on stdout */ + 257 : + 258 : /* + 259 : * Note that in the following functions we always flush both + 260 : * stdout and stderr, because we want to ensure that they mixes + 261 : * well when redirected to files + 262 : * + 263 : * The buffering is similar at the "line buffered" one, that + 264 : * is not available on Windows, so we emulate it in this way. + 265 : * + 266 : * For stdlog flushing is limited. To ensure flushing the + 267 : * caller should use log_flush(). + 268 : */ + 269 : + 270 41562 : static void vmsg(FILE* out, const char* format, va_list ap) + 271 : { + 272 41562 : char* dup = strdup_nofail(format); + 273 41562 : int len = strlen(dup); + 274 41562 : int written = 0; + 275 41562 : char control = 0; + 276 : + 277 41562 : if (len > 0) { + 278 41562 : if (dup[len - 1] == '\n') { + 279 41552 : dup[len - 1] = 0; + 280 41552 : control = '\n'; + 281 10 : } else if (dup[len - 1] == '\r') { + 282 0 : dup[len - 1] = 0; + 283 0 : control = '\r'; + 284 : } + 285 : } + 286 : + 287 41562 : if (dup[0]) { + 288 41459 : written = vfprintf(out, dup, ap); + 289 : } + 290 : + 291 41562 : switch (control) { + 292 10 : case 0 : + 293 10 : msg_line_curr += written; + 294 10 : break; + 295 41552 : case '\n' : + 296 41552 : msg_line_curr += written; + 297 : /* writes spaces to overwrite any previous char */ + 298 41552 : while (msg_line_curr < msg_line_prev) { + 299 0 : fprintf(out, " "); + 300 0 : --msg_line_prev; + 301 : } + 302 41552 : msg_line_prev = 0; + 303 41552 : msg_line_curr = 0; + 304 41552 : fprintf(out, "\n"); + 305 41552 : break; + 306 0 : case '\r' : + 307 0 : msg_line_curr += written; + 308 : /* writes spaces to overwrite any previous char */ + 309 0 : while (msg_line_curr < msg_line_prev) { + 310 0 : fprintf(out, " "); + 311 0 : --msg_line_prev; + 312 : } + 313 0 : msg_line_prev = msg_line_curr; + 314 0 : msg_line_curr = 0; + 315 0 : fprintf(out, "\r"); + 316 : } + 317 : + 318 41562 : free(dup); + 319 41562 : } 320 : - 321 803 : if (stdlog) { - 322 105 : if (is_hw(err)) - 323 12 : fprintf(stdlog, "msg:fatal_hardware: "); - 324 : else - 325 93 : fprintf(stdlog, "msg:fatal: "); + 321 803 : void log_fatal(int err, const char* format, ...) + 322 : { + 323 : va_list ap; + 324 : + 325 803 : lock_msg(); 326 : - 327 105 : va_start(ap, format); - 328 105 : vfprintf(stdlog, format, ap); - 329 105 : va_end(ap); - 330 : - 331 105 : fflush(stdlog); - 332 : } - 333 : - 334 803 : va_start(ap, format); - 335 803 : vmsg(stderr, format, ap); - 336 803 : va_end(ap); - 337 : - 338 803 : fflush(stderr); + 327 803 : if (stdlog) { + 328 105 : if (is_hw(err)) + 329 12 : fprintf(stdlog, "msg:fatal_hardware: "); + 330 : else + 331 93 : fprintf(stdlog, "msg:fatal: "); + 332 : + 333 105 : va_start(ap, format); + 334 105 : vfprintf(stdlog, format, ap); + 335 105 : va_end(ap); + 336 : + 337 105 : fflush(stdlog); + 338 : } 339 : - 340 803 : unlock_msg(); - 341 803 : } - 342 : - 343 365227 : void log_error(int err, const char* format, ...) - 344 : { - 345 : va_list ap; - 346 : - 347 365227 : lock_msg(); + 340 803 : va_start(ap, format); + 341 803 : vmsg(stderr, format, ap); + 342 803 : va_end(ap); + 343 : + 344 803 : fflush(stderr); + 345 : + 346 803 : unlock_msg(); + 347 803 : } 348 : - 349 365227 : if (stdlog) { - 350 363389 : if (is_hw(err)) - 351 0 : fprintf(stdlog, "msg:error_hardware: "); - 352 : else - 353 363389 : fprintf(stdlog, "msg:error: "); + 349 364924 : void log_error(int err, const char* format, ...) + 350 : { + 351 : va_list ap; + 352 : + 353 364924 : lock_msg(); 354 : - 355 363389 : va_start(ap, format); - 356 363389 : vfprintf(stdlog, format, ap); - 357 363389 : va_end(ap); - 358 : - 359 363389 : fflush(stdlog); - 360 : } else { - 361 1838 : va_start(ap, format); - 362 1838 : vmsg(stderr, format, ap); - 363 1838 : va_end(ap); + 355 364924 : if (stdlog) { + 356 363085 : if (is_hw(err)) + 357 0 : fprintf(stdlog, "msg:error_hardware: "); + 358 : else + 359 363085 : fprintf(stdlog, "msg:error: "); + 360 : + 361 363085 : va_start(ap, format); + 362 363085 : vfprintf(stdlog, format, ap); + 363 363085 : va_end(ap); 364 : - 365 1838 : fflush(stderr); - 366 : } - 367 : - 368 365227 : unlock_msg(); - 369 365227 : } + 365 363085 : fflush(stdlog); + 366 : } else { + 367 1839 : va_start(ap, format); + 368 1839 : vmsg(stderr, format, ap); + 369 1839 : va_end(ap); 370 : - 371 4697 : void log_expected(int err, const char* format, ...) - 372 : { - 373 : va_list ap; - 374 : - 375 4697 : lock_msg(); + 371 1839 : fflush(stderr); + 372 : } + 373 : + 374 364924 : unlock_msg(); + 375 364924 : } 376 : - 377 4697 : if (stdlog) { - 378 4697 : if (is_hw(err)) - 379 0 : fprintf(stdlog, "msg:error_hardware: "); /* we never expect an hardware error */ - 380 : else - 381 4697 : fprintf(stdlog, "msg:expected: "); + 377 4697 : void log_expected(int err, const char* format, ...) + 378 : { + 379 : va_list ap; + 380 : + 381 4697 : lock_msg(); 382 : - 383 4697 : va_start(ap, format); - 384 4697 : vfprintf(stdlog, format, ap); - 385 4697 : va_end(ap); - 386 : - 387 4697 : fflush(stdlog); - 388 : } - 389 : - 390 4697 : unlock_msg(); - 391 4697 : } + 383 4697 : if (stdlog) { + 384 4697 : if (is_hw(err)) + 385 0 : fprintf(stdlog, "msg:error_hardware: "); /* we never expect an hardware error */ + 386 : else + 387 4697 : fprintf(stdlog, "msg:expected: "); + 388 : + 389 4697 : va_start(ap, format); + 390 4697 : vfprintf(stdlog, format, ap); + 391 4697 : va_end(ap); 392 : - 393 21732148 : void log_tag(const char* format, ...) - 394 : { - 395 : va_list ap; - 396 : - 397 21732148 : lock_msg(); + 393 4697 : fflush(stdlog); + 394 : } + 395 : + 396 4697 : unlock_msg(); + 397 4697 : } 398 : - 399 21732148 : if (stdlog) { - 400 2567733 : va_start(ap, format); - 401 2567733 : vfprintf(stdlog, format, ap); - 402 2567733 : va_end(ap); - 403 : - 404 : /* here we intentionally don't flush to make the output faster */ - 405 : } - 406 : - 407 21732148 : unlock_msg(); - 408 21732148 : } + 399 21733516 : void log_tag(const char* format, ...) + 400 : { + 401 : va_list ap; + 402 : + 403 21733516 : lock_msg(); + 404 : + 405 21733516 : if (stdlog) { + 406 2568745 : va_start(ap, format); + 407 2568745 : vfprintf(stdlog, format, ap); + 408 2568745 : va_end(ap); 409 : - 410 3649 : void log_flush(void) - 411 : { - 412 3649 : lock_msg(); - 413 : - 414 3649 : if (stdlog) - 415 334 : fflush(stdlog); - 416 3649 : fflush(stdout); - 417 3649 : fflush(stderr); - 418 : - 419 3649 : unlock_msg(); - 420 3649 : } - 421 : - 422 743 : void msg_status(const char* format, ...) - 423 : { - 424 : va_list ap; - 425 : - 426 743 : lock_msg(); + 410 : /* here we intentionally don't flush to make the output faster */ + 411 : } + 412 : + 413 21733516 : unlock_msg(); + 414 21733516 : } + 415 : + 416 3652 : void log_flush(void) + 417 : { + 418 3652 : lock_msg(); + 419 : + 420 3652 : if (stdlog) + 421 335 : fflush(stdlog); + 422 3652 : fflush(stdout); + 423 3652 : fflush(stderr); + 424 : + 425 3652 : unlock_msg(); + 426 3652 : } 427 : - 428 743 : if (stdlog) { - 429 407 : fprintf(stdlog, "msg:status: "); - 430 : - 431 407 : va_start(ap, format); - 432 407 : vfprintf(stdlog, format, ap); - 433 407 : va_end(ap); - 434 : - 435 407 : fflush(stdlog); - 436 : } - 437 : - 438 743 : if (msg_level >= MSG_STATUS) { - 439 743 : va_start(ap, format); - 440 743 : vmsg(stdout, format, ap); - 441 743 : va_end(ap); + 428 743 : void msg_status(const char* format, ...) + 429 : { + 430 : va_list ap; + 431 : + 432 743 : lock_msg(); + 433 : + 434 743 : if (stdlog) { + 435 407 : fprintf(stdlog, "msg:status: "); + 436 : + 437 407 : va_start(ap, format); + 438 407 : vfprintf(stdlog, format, ap); + 439 407 : va_end(ap); + 440 : + 441 407 : fflush(stdlog); 442 : } 443 : - 444 743 : unlock_msg(); - 445 743 : } - 446 : - 447 312495 : void msg_info(const char* format, ...) - 448 : { - 449 : va_list ap; - 450 : - 451 312495 : lock_msg(); + 444 743 : if (msg_level >= MSG_STATUS) { + 445 743 : va_start(ap, format); + 446 743 : vmsg(stdout, format, ap); + 447 743 : va_end(ap); + 448 : } + 449 : + 450 743 : unlock_msg(); + 451 743 : } 452 : - 453 : /* don't output in stdlog as these messages */ - 454 : /* are always paired with a msg_tag() call */ - 455 : - 456 312495 : if (msg_level >= MSG_INFO) { - 457 37886 : va_start(ap, format); - 458 37886 : vmsg(stdout, format, ap); - 459 37886 : va_end(ap); - 460 : - 461 37886 : fflush(stdout); - 462 : } - 463 : - 464 312495 : unlock_msg(); - 465 312495 : } + 453 312664 : void msg_info(const char* format, ...) + 454 : { + 455 : va_list ap; + 456 : + 457 312664 : lock_msg(); + 458 : + 459 : /* don't output in stdlog as these messages */ + 460 : /* are always paired with a msg_tag() call */ + 461 : + 462 312664 : if (msg_level >= MSG_INFO) { + 463 37904 : va_start(ap, format); + 464 37904 : vmsg(stdout, format, ap); + 465 37904 : va_end(ap); 466 : - 467 5081 : void msg_progress(const char* format, ...) - 468 : { - 469 : va_list ap; - 470 : - 471 5081 : lock_msg(); + 467 37904 : fflush(stdout); + 468 : } + 469 : + 470 312664 : unlock_msg(); + 471 312664 : } 472 : - 473 5081 : if (stdlog) { - 474 901 : fprintf(stdlog, "msg:progress: "); - 475 : - 476 901 : va_start(ap, format); - 477 901 : vfprintf(stdlog, format, ap); - 478 901 : va_end(ap); - 479 : - 480 901 : fflush(stdlog); - 481 : } - 482 : - 483 5081 : if (msg_level >= MSG_PROGRESS) { - 484 174 : va_start(ap, format); - 485 174 : vmsg(stdout, format, ap); - 486 174 : va_end(ap); - 487 : - 488 174 : fflush(stdout); - 489 : } - 490 : - 491 5081 : unlock_msg(); - 492 5081 : } + 473 5066 : void msg_progress(const char* format, ...) + 474 : { + 475 : va_list ap; + 476 : + 477 5066 : lock_msg(); + 478 : + 479 5066 : if (stdlog) { + 480 901 : fprintf(stdlog, "msg:progress: "); + 481 : + 482 901 : va_start(ap, format); + 483 901 : vfprintf(stdlog, format, ap); + 484 901 : va_end(ap); + 485 : + 486 901 : fflush(stdlog); + 487 : } + 488 : + 489 5066 : if (msg_level >= MSG_PROGRESS) { + 490 174 : va_start(ap, format); + 491 174 : vmsg(stdout, format, ap); + 492 174 : va_end(ap); 493 : - 494 2118 : void msg_bar(const char* format, ...) - 495 : { - 496 : va_list ap; - 497 : - 498 2118 : lock_msg(); + 494 174 : fflush(stdout); + 495 : } + 496 : + 497 5066 : unlock_msg(); + 498 5066 : } 499 : - 500 : /* don't output in stdlog as these messages */ - 501 : /* are intended for screen only */ - 502 : /* also don't flush stdout as they are intended to be partial messages */ + 500 2042 : void msg_bar(const char* format, ...) + 501 : { + 502 : va_list ap; 503 : - 504 2118 : if (msg_level >= MSG_BAR) { - 505 0 : va_start(ap, format); - 506 0 : vmsg(stdout, format, ap); - 507 0 : va_end(ap); - 508 : } + 504 2042 : lock_msg(); + 505 : + 506 : /* don't output in stdlog as these messages */ + 507 : /* are intended for screen only */ + 508 : /* also don't flush stdout as they are intended to be partial messages */ 509 : - 510 2118 : unlock_msg(); - 511 2118 : } - 512 : - 513 127020 : void msg_verbose(const char* format, ...) - 514 : { - 515 : va_list ap; - 516 : - 517 127020 : lock_msg(); + 510 2042 : if (msg_level >= MSG_BAR) { + 511 0 : va_start(ap, format); + 512 0 : vmsg(stdout, format, ap); + 513 0 : va_end(ap); + 514 : } + 515 : + 516 2042 : unlock_msg(); + 517 2042 : } 518 : - 519 127020 : if (stdlog) { - 520 125051 : fprintf(stdlog, "msg:verbose: "); - 521 : - 522 125051 : va_start(ap, format); - 523 125051 : vfprintf(stdlog, format, ap); - 524 125051 : va_end(ap); - 525 : - 526 125051 : fflush(stdlog); - 527 : } - 528 : - 529 127020 : if (msg_level >= MSG_VERBOSE) { - 530 99 : va_start(ap, format); - 531 99 : vmsg(stdout, format, ap); - 532 99 : va_end(ap); - 533 : - 534 99 : fflush(stdout); - 535 : } - 536 : - 537 127020 : unlock_msg(); - 538 127020 : } + 519 127094 : void msg_verbose(const char* format, ...) + 520 : { + 521 : va_list ap; + 522 : + 523 127094 : lock_msg(); + 524 : + 525 127094 : if (stdlog) { + 526 125129 : fprintf(stdlog, "msg:verbose: "); + 527 : + 528 125129 : va_start(ap, format); + 529 125129 : vfprintf(stdlog, format, ap); + 530 125129 : va_end(ap); + 531 : + 532 125129 : fflush(stdlog); + 533 : } + 534 : + 535 127094 : if (msg_level >= MSG_VERBOSE) { + 536 99 : va_start(ap, format); + 537 99 : vmsg(stdout, format, ap); + 538 99 : va_end(ap); 539 : - 540 586 : void msg_flush(void) - 541 : { - 542 586 : lock_msg(); - 543 : - 544 586 : fflush(stdout); - 545 586 : fflush(stderr); - 546 : - 547 586 : unlock_msg(); - 548 586 : } + 540 99 : fflush(stdout); + 541 : } + 542 : + 543 127094 : unlock_msg(); + 544 127094 : } + 545 : + 546 572 : void msg_flush(void) + 547 : { + 548 572 : lock_msg(); 549 : - 550 77 : void printc(char c, size_t pad) - 551 : { - 552 135 : while (pad) { - 553 : /* group writes in long pieces */ - 554 : char buf[128]; - 555 58 : size_t len = pad; - 556 : - 557 58 : if (len >= sizeof(buf)) - 558 0 : len = sizeof(buf) - 1; - 559 : - 560 58 : memset(buf, c, len); - 561 58 : buf[len] = 0; + 550 572 : fflush(stdout); + 551 572 : fflush(stderr); + 552 : + 553 572 : unlock_msg(); + 554 572 : } + 555 : + 556 78 : void printc(char c, size_t pad) + 557 : { + 558 137 : while (pad) { + 559 : /* group writes in long pieces */ + 560 : char buf[128]; + 561 59 : size_t len = pad; 562 : - 563 58 : fputs(buf, stdout); - 564 : - 565 58 : pad -= len; - 566 : } - 567 77 : } + 563 59 : if (len >= sizeof(buf)) + 564 0 : len = sizeof(buf) - 1; + 565 : + 566 59 : memset(buf, c, len); + 567 59 : buf[len] = 0; 568 : - 569 34 : void printr(const char* str, size_t pad) - 570 : { - 571 : size_t len; - 572 : - 573 34 : len = strlen(str); + 569 59 : fputs(buf, stdout); + 570 : + 571 59 : pad -= len; + 572 : } + 573 78 : } 574 : - 575 34 : if (len < pad) - 576 34 : printc(' ', pad - len); - 577 : - 578 34 : fputs(str, stdout); - 579 34 : } + 575 34 : void printr(const char* str, size_t pad) + 576 : { + 577 : size_t len; + 578 : + 579 34 : len = strlen(str); 580 : - 581 142 : void printl(const char* str, size_t pad) - 582 : { - 583 : size_t len; - 584 : - 585 142 : fputs(str, stdout); + 581 34 : if (len < pad) + 582 34 : printc(' ', pad - len); + 583 : + 584 34 : fputs(str, stdout); + 585 34 : } 586 : - 587 142 : len = strlen(str); - 588 : - 589 142 : if (len < pad) - 590 6 : printc(' ', pad - len); - 591 142 : } + 587 157 : void printl(const char* str, size_t pad) + 588 : { + 589 : size_t len; + 590 : + 591 157 : fputs(str, stdout); 592 : - 593 18 : void printp(double v, size_t pad) - 594 : { - 595 : char buf[64]; - 596 18 : const char* s = "%"; - 597 : - 598 18 : if (v > 0.1) - 599 0 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s); - 600 18 : else if (v > 0.01) - 601 0 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s); - 602 18 : else if (v > 0.001) - 603 0 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s); - 604 18 : else if (v > 0.0001) - 605 0 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s); - 606 18 : else if (v > 0.00001) - 607 0 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s); - 608 18 : else if (v > 0.000001) - 609 0 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s); - 610 18 : else if (v > 0.0000001) - 611 0 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s); - 612 18 : else if (v > 0.00000001) - 613 0 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s); - 614 18 : else if (v > 0.000000001) - 615 0 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s); - 616 18 : else if (v > 0.0000000001) - 617 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s); - 618 18 : else if (v > 0.00000000001) - 619 0 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s); - 620 18 : else if (v > 0.000000000001) - 621 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s); - 622 : else - 623 18 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s); - 624 18 : printl(buf, pad); - 625 18 : } - 626 : - 627 : #define charcat(c) \ - 628 : do { \ - 629 : if (p == end) { \ - 630 : goto bail; \ - 631 : } \ - 632 : *p++ = (c); \ - 633 : } while (0) - 634 : - 635 2652388 : const char* esc_tag(const char* str, char* buffer) - 636 : { - 637 2652388 : char* begin = buffer; - 638 2652388 : char* end = begin + ESC_MAX; - 639 2652388 : char* p = begin; + 593 157 : len = strlen(str); + 594 : + 595 157 : if (len < pad) + 596 7 : printc(' ', pad - len); + 597 157 : } + 598 : + 599 18 : void printp(double v, size_t pad) + 600 : { + 601 : char buf[64]; + 602 18 : const char* s = "%"; + 603 : + 604 18 : if (v > 0.1) + 605 0 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s); + 606 18 : else if (v > 0.01) + 607 0 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s); + 608 18 : else if (v > 0.001) + 609 0 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s); + 610 18 : else if (v > 0.0001) + 611 0 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s); + 612 18 : else if (v > 0.00001) + 613 0 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s); + 614 18 : else if (v > 0.000001) + 615 0 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s); + 616 18 : else if (v > 0.0000001) + 617 0 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s); + 618 18 : else if (v > 0.00000001) + 619 0 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s); + 620 18 : else if (v > 0.000000001) + 621 0 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s); + 622 18 : else if (v > 0.0000000001) + 623 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s); + 624 18 : else if (v > 0.00000000001) + 625 0 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s); + 626 18 : else if (v > 0.000000000001) + 627 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s); + 628 : else + 629 18 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s); + 630 18 : printl(buf, pad); + 631 18 : } + 632 : + 633 : #define charcat(c) \ + 634 : do { \ + 635 : if (p == end) { \ + 636 : goto bail; \ + 637 : } \ + 638 : *p++ = (c); \ + 639 : } while (0) 640 : - 641 : /* copy string with escaping */ - 642 34792293 : while (*str) { - 643 32139905 : char c = *str++; - 644 : - 645 32139905 : switch (c) { - 646 3 : case '\n' : - 647 3 : charcat('\\'); - 648 3 : charcat('n'); - 649 3 : break; - 650 3 : case '\r' : - 651 3 : charcat('\\'); - 652 3 : charcat('r'); - 653 3 : break; - 654 4 : case ':' : - 655 4 : charcat('\\'); - 656 4 : charcat('d'); - 657 4 : break; - 658 6 : case '\\' : - 659 6 : charcat('\\'); - 660 6 : charcat('\\'); - 661 6 : break; - 662 32139889 : default : - 663 32139889 : charcat(c); - 664 32139889 : break; - 665 : } - 666 : } - 667 : - 668 : /* put final 0 */ - 669 2652388 : if (p == end) - 670 0 : goto bail; - 671 2652388 : *p = 0; - 672 : - 673 2652388 : return begin; - 674 : - 675 0 : bail: - 676 : /* LCOV_EXCL_START */ - 677 : log_fatal(EINTERNAL, "Escape for log is too long\n"); - 678 : exit(EXIT_FAILURE); - 679 : /* LCOV_EXCL_STOP */ - 680 : } - 681 : - 682 : #ifdef _WIN32 - 683 : static int needs_quote(const char* arg) - 684 : { - 685 : while (*arg) { - 686 : char c = *arg; - 687 : if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || - 688 : c == '&' || c == '|' || c == '(' || c == ')' || - 689 : c == '<' || c == '>' || c == '^' || c == '"' || - 690 : c == '%' || c == '!' || c == '=' || c == ';' || - 691 : (unsigned char)c < 32 || c == 127) - 692 : return 1; - 693 : ++arg; - 694 : } - 695 : - 696 : return 0; - 697 : } - 698 : #endif - 699 : - 700 : struct stream { - 701 : const char* str; - 702 : unsigned idx; - 703 : const char** map; - 704 : unsigned max; - 705 : }; - 706 : - 707 5261663 : static inline char ssget(struct stream* ss) - 708 : { - 709 : /* get the next char */ - 710 5261663 : char c = *ss->str++; - 711 : - 712 : /* if one string is finished, go to the next */ - 713 5297758 : while (c == 0 && ss->idx + 1 < ss->max) { - 714 36095 : ss->str = ss->map[++ss->idx]; - 715 36095 : c = *ss->str++; - 716 : } + 641 2653118 : const char* esc_tag(const char* str, char* buffer) + 642 : { + 643 2653118 : char* begin = buffer; + 644 2653118 : char* end = begin + ESC_MAX; + 645 2653118 : char* p = begin; + 646 : + 647 : /* copy string with escaping */ + 648 34809715 : while (*str) { + 649 32156597 : char c = *str++; + 650 : + 651 32156597 : switch (c) { + 652 3 : case '\n' : + 653 3 : charcat('\\'); + 654 3 : charcat('n'); + 655 3 : break; + 656 3 : case '\r' : + 657 3 : charcat('\\'); + 658 3 : charcat('r'); + 659 3 : break; + 660 4 : case ':' : + 661 4 : charcat('\\'); + 662 4 : charcat('d'); + 663 4 : break; + 664 6 : case '\\' : + 665 6 : charcat('\\'); + 666 6 : charcat('\\'); + 667 6 : break; + 668 32156581 : default : + 669 32156581 : charcat(c); + 670 32156581 : break; + 671 : } + 672 : } + 673 : + 674 : /* put final 0 */ + 675 2653118 : if (p == end) + 676 0 : goto bail; + 677 2653118 : *p = 0; + 678 : + 679 2653118 : return begin; + 680 : + 681 0 : bail: + 682 : /* LCOV_EXCL_START */ + 683 : log_fatal(EINTERNAL, "Escape for log is too long\n"); + 684 : exit(EXIT_FAILURE); + 685 : /* LCOV_EXCL_STOP */ + 686 : } + 687 : + 688 : #ifdef _WIN32 + 689 : static int needs_quote(const char* arg) + 690 : { + 691 : while (*arg) { + 692 : char c = *arg; + 693 : if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || + 694 : c == '&' || c == '|' || c == '(' || c == ')' || + 695 : c == '<' || c == '>' || c == '^' || c == '"' || + 696 : c == '%' || c == '!' || c == '=' || c == ';' || + 697 : (unsigned char)c < 32 || c == 127) + 698 : return 1; + 699 : ++arg; + 700 : } + 701 : + 702 : return 0; + 703 : } + 704 : #endif + 705 : + 706 : struct stream { + 707 : const char* str; + 708 : unsigned idx; + 709 : const char** map; + 710 : unsigned max; + 711 : }; + 712 : + 713 5265543 : static inline char ssget(struct stream* ss) + 714 : { + 715 : /* get the next char */ + 716 5265543 : char c = *ss->str++; 717 : - 718 5261663 : return c; - 719 : } - 720 : - 721 : #ifdef _WIN32 - 722 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) - 723 : { - 724 : char* begin = buffer; - 725 : char* end = begin + ESC_MAX; - 726 : char* p = begin; - 727 : struct stream ss; - 728 : char c; - 729 : unsigned i; - 730 : int has_quote; - 731 : - 732 : has_quote = 0; - 733 : for (i = 0; i < str_max; ++i) { - 734 : if (needs_quote(str_map[i])) - 735 : has_quote = 1; - 736 : } + 718 : /* if one string is finished, go to the next */ + 719 5301638 : while (c == 0 && ss->idx + 1 < ss->max) { + 720 36095 : ss->str = ss->map[++ss->idx]; + 721 36095 : c = *ss->str++; + 722 : } + 723 : + 724 5265543 : return c; + 725 : } + 726 : + 727 : #ifdef _WIN32 + 728 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) + 729 : { + 730 : char* begin = buffer; + 731 : char* end = begin + ESC_MAX; + 732 : char* p = begin; + 733 : struct stream ss; + 734 : char c; + 735 : unsigned i; + 736 : int has_quote; 737 : - 738 : ss.idx = 0; - 739 : ss.str = str_map[0]; - 740 : ss.map = str_map; - 741 : ss.max = str_max; - 742 : - 743 : if (!has_quote) { - 744 : c = ssget(&ss); - 745 : while (c) { - 746 : charcat(c); - 747 : c = ssget(&ss); - 748 : } - 749 : } else { - 750 : /* starting quote */ - 751 : charcat('"'); - 752 : - 753 : c = ssget(&ss); - 754 : while (c) { - 755 : int bl = 0; - 756 : while (c == '\\') { - 757 : ++bl; - 758 : c = ssget(&ss); - 759 : } - 760 : - 761 : if (c == 0) { - 762 : /* double backslashes before closing quote */ - 763 : bl = bl * 2; - 764 : while (bl--) - 765 : charcat('\\'); - 766 : break; - 767 : } else if (c == '"') { - 768 : /* double backslashes + escape the quote */ - 769 : bl = bl * 2 + 1; + 738 : has_quote = 0; + 739 : for (i = 0; i < str_max; ++i) { + 740 : if (needs_quote(str_map[i])) + 741 : has_quote = 1; + 742 : } + 743 : + 744 : ss.idx = 0; + 745 : ss.str = str_map[0]; + 746 : ss.map = str_map; + 747 : ss.max = str_max; + 748 : + 749 : if (!has_quote) { + 750 : c = ssget(&ss); + 751 : while (c) { + 752 : charcat(c); + 753 : c = ssget(&ss); + 754 : } + 755 : } else { + 756 : /* starting quote */ + 757 : charcat('"'); + 758 : + 759 : c = ssget(&ss); + 760 : while (c) { + 761 : int bl = 0; + 762 : while (c == '\\') { + 763 : ++bl; + 764 : c = ssget(&ss); + 765 : } + 766 : + 767 : if (c == 0) { + 768 : /* double backslashes before closing quote */ + 769 : bl = bl * 2; 770 : while (bl--) 771 : charcat('\\'); - 772 : charcat('"'); - 773 : } else { - 774 : /* normal backslashes */ - 775 : while (bl--) - 776 : charcat('\\'); - 777 : charcat(c); - 778 : } - 779 : - 780 : c = ssget(&ss); - 781 : } - 782 : - 783 : /* ending quote */ - 784 : charcat('"'); - 785 : } - 786 : - 787 : /* put final 0 */ - 788 : charcat(0); - 789 : - 790 : return begin; - 791 : - 792 : bail: - 793 : /* LCOV_EXCL_START */ - 794 : log_fatal(EINTERNAL, "Escape for shell is too long\n"); - 795 : exit(EXIT_FAILURE); - 796 : /* LCOV_EXCL_STOP */ - 797 : } - 798 : #else - 799 366218 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) - 800 : { - 801 366218 : char* begin = buffer; - 802 366218 : char* end = begin + ESC_MAX; - 803 366218 : char* p = begin; - 804 : struct stream ss; - 805 : char c; - 806 : - 807 366218 : ss.idx = 0; - 808 366218 : ss.str = str_map[0]; - 809 366218 : ss.map = str_map; - 810 366218 : ss.max = str_max; - 811 : - 812 366218 : c = ssget(&ss); - 813 5261663 : while (c) { - 814 4895445 : switch (c) { - 815 : /* special chars that need to be quoted */ - 816 81442 : case ' ' : /* space */ - 817 : case '\t' : /* tab */ - 818 : case '\n' : /* newline */ - 819 : case '\r' : /* carriage return */ - 820 : case '~' : /* home */ - 821 : case '`' : /* command */ - 822 : case '#' : /* comment */ - 823 : case '$' : /* variable */ - 824 : case '&' : /* background job */ - 825 : case '*' : /* wildcard */ - 826 : case '(' : /* shell */ - 827 : case ')' : /* shell */ - 828 : case '\\' : /* quote */ - 829 : case '|' : /* pipe */ - 830 : case '[' : /* wildcard */ - 831 : case ']' : /* wildcard */ - 832 : case '{' : /* code */ - 833 : case '}' : /* code */ - 834 : case ';' : /* separator */ - 835 : case '\'' : /* quote */ - 836 : case '"' : /* quote */ - 837 : case '<' : /* redirect */ - 838 : case '>' : /* redirect */ - 839 : case '?' : /* wildcard */ - 840 : case '=' : /* assignment */ - 841 : case '!' : /* history expansion */ - 842 81442 : charcat('\\'); - 843 81442 : charcat(c); - 844 81442 : break; - 845 4814003 : default : - 846 : /* check for control characters */ - 847 4814003 : if ((unsigned char)c < 32 || c == 127) { - 848 6 : charcat('\\'); - 849 6 : charcat(c); - 850 : } else { - 851 4813997 : charcat(c); - 852 : } - 853 4814003 : break; - 854 : } - 855 : - 856 4895445 : c = ssget(&ss); - 857 : } - 858 : - 859 : /* put final 0 */ - 860 366218 : charcat(0); + 772 : break; + 773 : } else if (c == '"') { + 774 : /* double backslashes + escape the quote */ + 775 : bl = bl * 2 + 1; + 776 : while (bl--) + 777 : charcat('\\'); + 778 : charcat('"'); + 779 : } else { + 780 : /* normal backslashes */ + 781 : while (bl--) + 782 : charcat('\\'); + 783 : charcat(c); + 784 : } + 785 : + 786 : c = ssget(&ss); + 787 : } + 788 : + 789 : /* ending quote */ + 790 : charcat('"'); + 791 : } + 792 : + 793 : /* put final 0 */ + 794 : charcat(0); + 795 : + 796 : return begin; + 797 : + 798 : bail: + 799 : /* LCOV_EXCL_START */ + 800 : log_fatal(EINTERNAL, "Escape for shell is too long\n"); + 801 : exit(EXIT_FAILURE); + 802 : /* LCOV_EXCL_STOP */ + 803 : } + 804 : #else + 805 366387 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) + 806 : { + 807 366387 : char* begin = buffer; + 808 366387 : char* end = begin + ESC_MAX; + 809 366387 : char* p = begin; + 810 : struct stream ss; + 811 : char c; + 812 : + 813 366387 : ss.idx = 0; + 814 366387 : ss.str = str_map[0]; + 815 366387 : ss.map = str_map; + 816 366387 : ss.max = str_max; + 817 : + 818 366387 : c = ssget(&ss); + 819 5265543 : while (c) { + 820 4899156 : switch (c) { + 821 : /* special chars that need to be quoted */ + 822 81659 : case ' ' : /* space */ + 823 : case '\t' : /* tab */ + 824 : case '\n' : /* newline */ + 825 : case '\r' : /* carriage return */ + 826 : case '~' : /* home */ + 827 : case '`' : /* command */ + 828 : case '#' : /* comment */ + 829 : case '$' : /* variable */ + 830 : case '&' : /* background job */ + 831 : case '*' : /* wildcard */ + 832 : case '(' : /* shell */ + 833 : case ')' : /* shell */ + 834 : case '\\' : /* quote */ + 835 : case '|' : /* pipe */ + 836 : case '[' : /* wildcard */ + 837 : case ']' : /* wildcard */ + 838 : case '{' : /* code */ + 839 : case '}' : /* code */ + 840 : case ';' : /* separator */ + 841 : case '\'' : /* quote */ + 842 : case '"' : /* quote */ + 843 : case '<' : /* redirect */ + 844 : case '>' : /* redirect */ + 845 : case '?' : /* wildcard */ + 846 : case '=' : /* assignment */ + 847 : case '!' : /* history expansion */ + 848 81659 : charcat('\\'); + 849 81659 : charcat(c); + 850 81659 : break; + 851 4817497 : default : + 852 : /* check for control characters */ + 853 4817497 : if ((unsigned char)c < 32 || c == 127) { + 854 6 : charcat('\\'); + 855 6 : charcat(c); + 856 : } else { + 857 4817491 : charcat(c); + 858 : } + 859 4817497 : break; + 860 : } 861 : - 862 366218 : return begin; - 863 : - 864 0 : bail: - 865 : /* LCOV_EXCL_START */ - 866 : log_fatal(EINTERNAL, "Escape for shell is too long\n"); - 867 : exit(EXIT_FAILURE); - 868 : /* LCOV_EXCL_STOP */ - 869 : } - 870 : #endif - 871 : - 872 21 : char* strpolish(char* s) - 873 : { - 874 21 : char* i = s; - 875 : - 876 1030 : while (*i) { - 877 1009 : if (isspace(*i) || !isprint(*i)) - 878 119 : *i = ' '; - 879 1009 : ++i; - 880 : } + 862 4899156 : c = ssget(&ss); + 863 : } + 864 : + 865 : /* put final 0 */ + 866 366387 : charcat(0); + 867 : + 868 366387 : return begin; + 869 : + 870 0 : bail: + 871 : /* LCOV_EXCL_START */ + 872 : log_fatal(EINTERNAL, "Escape for shell is too long\n"); + 873 : exit(EXIT_FAILURE); + 874 : /* LCOV_EXCL_STOP */ + 875 : } + 876 : #endif + 877 : + 878 256 : char* strpolish(char* s) + 879 : { + 880 256 : char* i = s; 881 : - 882 21 : return s; - 883 : } - 884 : - 885 1718 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters) - 886 : { - 887 1718 : unsigned mac = 0; - 888 : - 889 : /* skip initial delimiters */ - 890 1718 : str += strspn(str, delimiters); - 891 : - 892 8782 : while (*str != 0 || mac == split_max) { - 893 : /* start of the token */ - 894 7064 : split_map[mac] = str; - 895 7064 : ++mac; - 896 : - 897 : /* find the first delimiter or the end of the string */ - 898 7064 : str += strcspn(str, delimiters); - 899 : - 900 : /* put the final terminator if missing */ - 901 7064 : if (*str != 0) - 902 5538 : *str++ = 0; - 903 : - 904 : /* skip trailing delimiters */ - 905 7064 : str += strspn(str, delimiters); - 906 : } - 907 : - 908 1718 : return mac; - 909 : } - 910 : - 911 13 : char* strtrim(char* str) - 912 : { - 913 : char* begin; - 914 : char* end; - 915 : - 916 13 : begin = str; - 917 14 : while (begin[0] && isspace((unsigned char)begin[0])) - 918 1 : ++begin; - 919 : - 920 13 : end = begin + strlen(begin); - 921 28 : while (end > begin && isspace((unsigned char)end[-1])) - 922 15 : --end; - 923 : - 924 13 : end[0] = 0; + 882 12430 : while (*i) { + 883 12174 : if (isspace(*i) || !isprint(*i)) + 884 2975 : *i = ' '; + 885 12174 : ++i; + 886 : } + 887 : + 888 256 : return s; + 889 : } + 890 : + 891 1720 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters) + 892 : { + 893 1720 : unsigned mac = 0; + 894 : + 895 : /* skip initial delimiters */ + 896 1720 : str += strspn(str, delimiters); + 897 : + 898 8786 : while (*str != 0 || mac == split_max) { + 899 : /* start of the token */ + 900 7066 : split_map[mac] = str; + 901 7066 : ++mac; + 902 : + 903 : /* find the first delimiter or the end of the string */ + 904 7066 : str += strcspn(str, delimiters); + 905 : + 906 : /* put the final terminator if missing */ + 907 7066 : if (*str != 0) + 908 5538 : *str++ = 0; + 909 : + 910 : /* skip trailing delimiters */ + 911 7066 : str += strspn(str, delimiters); + 912 : } + 913 : + 914 1720 : return mac; + 915 : } + 916 : + 917 67 : char* strtrim(char* str) + 918 : { + 919 : char* begin; + 920 : char* end; + 921 : + 922 67 : begin = str; + 923 97 : while (begin[0] && isspace((unsigned char)begin[0])) + 924 30 : ++begin; 925 : - 926 13 : if (begin != end) - 927 13 : memmove(str, begin, end - begin + 1); - 928 : - 929 13 : return str; - 930 : } + 926 67 : end = begin + strlen(begin); + 927 247 : while (end > begin && isspace((unsigned char)end[-1])) + 928 180 : --end; + 929 : + 930 67 : end[0] = 0; 931 : - 932 2 : char* strlwr(char* str) - 933 : { - 934 2 : char* s = str; - 935 : - 936 24 : while (*s) { - 937 22 : *s = tolower((unsigned char)*s); - 938 22 : ++s; - 939 : } - 940 : - 941 2 : return str; - 942 : } - 943 : - 944 11 : char* worddigitstr(const char* haystack, const char* needle) - 945 : { - 946 11 : size_t len = strlen(needle); - 947 : const char* s; - 948 : - 949 11 : if (len == 0) - 950 1 : return NULL; - 951 : - 952 11 : for (s = haystack; (s = strstr(s, needle)) != NULL; ++s) { - 953 : - 954 : /* left boundary */ - 955 8 : if (s == haystack || isspace((unsigned char)s[-1]) || isdigit((unsigned char)s[-1])) { - 956 : /* right boundary */ - 957 7 : if (s[len] == '\0' || isspace((unsigned char)s[len]) || isdigit((unsigned char)s[len])) { - 958 7 : return (char*)s; - 959 : } - 960 : } - 961 : } - 962 : - 963 3 : return NULL; - 964 : } - 965 : - 966 : /****************************************************************************/ - 967 : /* path */ + 932 67 : if (begin != end) + 933 67 : memmove(str, begin, end - begin + 1); + 934 : + 935 67 : return str; + 936 : } + 937 : + 938 2 : char* strlwr(char* str) + 939 : { + 940 2 : char* s = str; + 941 : + 942 24 : while (*s) { + 943 22 : *s = tolower((unsigned char)*s); + 944 22 : ++s; + 945 : } + 946 : + 947 2 : return str; + 948 : } + 949 : + 950 11 : char* worddigitstr(const char* haystack, const char* needle) + 951 : { + 952 11 : size_t len = strlen(needle); + 953 : const char* s; + 954 : + 955 11 : if (len == 0) + 956 1 : return NULL; + 957 : + 958 11 : for (s = haystack; (s = strstr(s, needle)) != NULL; ++s) { + 959 : + 960 : /* left boundary */ + 961 8 : if (s == haystack || isspace((unsigned char)s[-1]) || isdigit((unsigned char)s[-1])) { + 962 : /* right boundary */ + 963 7 : if (s[len] == '\0' || isspace((unsigned char)s[len]) || isdigit((unsigned char)s[len])) { + 964 7 : return (char*)s; + 965 : } + 966 : } + 967 : } 968 : - 969 1902922 : void pathcpy(char* dst, size_t size, const char* src) - 970 : { - 971 1902922 : size_t len = strlen(src); - 972 : - 973 1902922 : if (len + 1 > size) { - 974 : /* LCOV_EXCL_START */ - 975 : log_fatal(EINTERNAL, "Path too long '%s'\n", src); - 976 : os_abort(); - 977 : /* LCOV_EXCL_STOP */ - 978 : } - 979 : - 980 1902922 : memcpy(dst, src, len + 1); - 981 1902922 : } - 982 : - 983 279 : void pathcat(char* dst, size_t size, const char* src) - 984 : { - 985 279 : size_t dst_len = strlen(dst); - 986 279 : size_t src_len = strlen(src); - 987 : - 988 279 : if (dst_len + src_len + 1 > size) { - 989 : /* LCOV_EXCL_START */ - 990 : log_fatal(EINTERNAL, "Path too long '%s%s'\n", dst, src); - 991 : os_abort(); - 992 : /* LCOV_EXCL_STOP */ - 993 : } - 994 : - 995 279 : memcpy(dst + dst_len, src, src_len + 1); - 996 279 : } - 997 : - 998 3601926 : void pathcatl(char* dst, size_t dst_len, size_t size, const char* src) - 999 : { - 1000 3601926 : size_t src_len = strlen(src); - 1001 : - 1002 3601926 : if (dst_len + src_len + 1 > size) { - 1003 : /* LCOV_EXCL_START */ - 1004 : log_fatal(EINTERNAL, "Path too long '%s%s'\n", dst, src); - 1005 : os_abort(); - 1006 : /* LCOV_EXCL_STOP */ - 1007 : } - 1008 : - 1009 3601926 : memcpy(dst + dst_len, src, src_len + 1); - 1010 3601926 : } - 1011 : - 1012 788 : void pathcatc(char* dst, size_t size, char c) - 1013 : { - 1014 788 : size_t dst_len = strlen(dst); - 1015 : - 1016 788 : if (dst_len + 2 > size) { - 1017 : /* LCOV_EXCL_START */ - 1018 : log_fatal(EINTERNAL, "Path too long '%s%c'\n", dst, c); - 1019 : os_abort(); - 1020 : /* LCOV_EXCL_STOP */ - 1021 : } - 1022 : - 1023 788 : dst[dst_len] = c; - 1024 788 : dst[dst_len + 1] = 0; - 1025 788 : } - 1026 : - 1027 17981 : void pathimport(char* dst, size_t size, const char* src) - 1028 : { - 1029 17981 : pathcpy(dst, size, src); - 1030 : - 1031 : #ifdef _WIN32 - 1032 : /* convert the Windows dir separator '\' to C '/', */ - 1033 : /* and the Windows escaping char '^' to the fnmatch '\' */ - 1034 : while (*dst) { - 1035 : switch (*dst) { - 1036 : case '\\' : - 1037 : *dst = '/'; - 1038 : break; - 1039 : case '^' : - 1040 : *dst = '\\'; - 1041 : break; - 1042 : } - 1043 : ++dst; - 1044 : } - 1045 : #endif - 1046 17981 : } - 1047 : - 1048 12234 : void pathexport(char* dst, size_t size, const char* src) - 1049 : { - 1050 12234 : pathcpy(dst, size, src); - 1051 : - 1052 : #ifdef _WIN32 - 1053 : /* invert the import */ - 1054 : while (*dst) { - 1055 : switch (*dst) { - 1056 : case '/' : - 1057 : *dst = '\\'; - 1058 : break; - 1059 : case '\\' : - 1060 : *dst = '^'; - 1061 : break; - 1062 : } - 1063 : ++dst; - 1064 : } - 1065 : #endif - 1066 12234 : } - 1067 : - 1068 42979947 : void pathprint(char* dst, size_t size, const char* format, ...) - 1069 : { - 1070 : size_t len; - 1071 : va_list ap; - 1072 : - 1073 42979947 : va_start(ap, format); - 1074 42979947 : len = vsnprintf(dst, size, format, ap); - 1075 42979947 : va_end(ap); - 1076 : - 1077 42979947 : if (len >= size) { - 1078 : /* LCOV_EXCL_START */ - 1079 : if (size > 0) { - 1080 : dst[size - 1] = 0; - 1081 : log_fatal(EINTERNAL, "Path too long '%s...'\n", dst); - 1082 : } else { - 1083 : log_fatal(EINTERNAL, "Path too long for empty size'\n"); - 1084 : } - 1085 : os_abort(); - 1086 : /* LCOV_EXCL_STOP */ - 1087 : } - 1088 42979947 : } - 1089 : - 1090 7949 : void pathslash(char* dst, size_t size) - 1091 : { - 1092 7949 : size_t len = strlen(dst); - 1093 : - 1094 7949 : if (len > 0 && dst[len - 1] != '/') { - 1095 6286 : if (len + 2 >= size) { - 1096 : /* LCOV_EXCL_START */ - 1097 : log_fatal(EINTERNAL, "Path too long '%s/'\n", dst); - 1098 : os_abort(); - 1099 : /* LCOV_EXCL_STOP */ - 1100 : } - 1101 : - 1102 6286 : dst[len] = '/'; - 1103 6286 : dst[len + 1] = 0; - 1104 : } - 1105 7949 : } - 1106 : - 1107 58108 : void pathcut(char* dst) - 1108 : { - 1109 58108 : char* slash = strrchr(dst, '/'); - 1110 : - 1111 58108 : if (slash) - 1112 58108 : slash[1] = 0; - 1113 : else - 1114 0 : dst[0] = 0; - 1115 58108 : } + 969 3 : return NULL; + 970 : } + 971 : + 972 : /****************************************************************************/ + 973 : /* path */ + 974 : + 975 1902784 : void pathcpy(char* dst, size_t size, const char* src) + 976 : { + 977 1902784 : size_t len = strlen(src); + 978 : + 979 1902784 : if (len + 1 > size) { + 980 : /* LCOV_EXCL_START */ + 981 : log_fatal(EINTERNAL, "Path too long '%s'\n", src); + 982 : os_abort(); + 983 : /* LCOV_EXCL_STOP */ + 984 : } + 985 : + 986 1902784 : memcpy(dst, src, len + 1); + 987 1902784 : } + 988 : + 989 280 : void pathcat(char* dst, size_t size, const char* src) + 990 : { + 991 280 : size_t dst_len = strlen(dst); + 992 280 : size_t src_len = strlen(src); + 993 : + 994 280 : if (dst_len + src_len + 1 > size) { + 995 : /* LCOV_EXCL_START */ + 996 : log_fatal(EINTERNAL, "Path too long '%s%s'\n", dst, src); + 997 : os_abort(); + 998 : /* LCOV_EXCL_STOP */ + 999 : } + 1000 : + 1001 280 : memcpy(dst + dst_len, src, src_len + 1); + 1002 280 : } + 1003 : + 1004 3601926 : void pathcatl(char* dst, size_t dst_len, size_t size, const char* src) + 1005 : { + 1006 3601926 : size_t src_len = strlen(src); + 1007 : + 1008 3601926 : if (dst_len + src_len + 1 > size) { + 1009 : /* LCOV_EXCL_START */ + 1010 : log_fatal(EINTERNAL, "Path too long '%s%s'\n", dst, src); + 1011 : os_abort(); + 1012 : /* LCOV_EXCL_STOP */ + 1013 : } + 1014 : + 1015 3601926 : memcpy(dst + dst_len, src, src_len + 1); + 1016 3601926 : } + 1017 : + 1018 788 : void pathcatc(char* dst, size_t size, char c) + 1019 : { + 1020 788 : size_t dst_len = strlen(dst); + 1021 : + 1022 788 : if (dst_len + 2 > size) { + 1023 : /* LCOV_EXCL_START */ + 1024 : log_fatal(EINTERNAL, "Path too long '%s%c'\n", dst, c); + 1025 : os_abort(); + 1026 : /* LCOV_EXCL_STOP */ + 1027 : } + 1028 : + 1029 788 : dst[dst_len] = c; + 1030 788 : dst[dst_len + 1] = 0; + 1031 788 : } + 1032 : + 1033 18024 : void pathimport(char* dst, size_t size, const char* src) + 1034 : { + 1035 18024 : pathcpy(dst, size, src); + 1036 : + 1037 : #ifdef _WIN32 + 1038 : /* convert the Windows dir separator '\' to C '/', */ + 1039 : /* and the Windows escaping char '^' to the fnmatch '\' */ + 1040 : while (*dst) { + 1041 : switch (*dst) { + 1042 : case '\\' : + 1043 : *dst = '/'; + 1044 : break; + 1045 : case '^' : + 1046 : *dst = '\\'; + 1047 : break; + 1048 : } + 1049 : ++dst; + 1050 : } + 1051 : #endif + 1052 18024 : } + 1053 : + 1054 12234 : void pathexport(char* dst, size_t size, const char* src) + 1055 : { + 1056 12234 : pathcpy(dst, size, src); + 1057 : + 1058 : #ifdef _WIN32 + 1059 : /* invert the import */ + 1060 : while (*dst) { + 1061 : switch (*dst) { + 1062 : case '/' : + 1063 : *dst = '\\'; + 1064 : break; + 1065 : case '\\' : + 1066 : *dst = '^'; + 1067 : break; + 1068 : } + 1069 : ++dst; + 1070 : } + 1071 : #endif + 1072 12234 : } + 1073 : + 1074 42981264 : void pathprint(char* dst, size_t size, const char* format, ...) + 1075 : { + 1076 : size_t len; + 1077 : va_list ap; + 1078 : + 1079 42981264 : va_start(ap, format); + 1080 42981264 : len = vsnprintf(dst, size, format, ap); + 1081 42981264 : va_end(ap); + 1082 : + 1083 42981264 : if (len >= size) { + 1084 : /* LCOV_EXCL_START */ + 1085 : if (size > 0) { + 1086 : dst[size - 1] = 0; + 1087 : log_fatal(EINTERNAL, "Path too long '%s...'\n", dst); + 1088 : } else { + 1089 : log_fatal(EINTERNAL, "Path too long for empty size'\n"); + 1090 : } + 1091 : os_abort(); + 1092 : /* LCOV_EXCL_STOP */ + 1093 : } + 1094 42981264 : } + 1095 : + 1096 7959 : void pathslash(char* dst, size_t size) + 1097 : { + 1098 7959 : size_t len = strlen(dst); + 1099 : + 1100 7959 : if (len > 0 && dst[len - 1] != '/') { + 1101 6286 : if (len + 2 >= size) { + 1102 : /* LCOV_EXCL_START */ + 1103 : log_fatal(EINTERNAL, "Path too long '%s/'\n", dst); + 1104 : os_abort(); + 1105 : /* LCOV_EXCL_STOP */ + 1106 : } + 1107 : + 1108 6286 : dst[len] = '/'; + 1109 6286 : dst[len + 1] = 0; + 1110 : } + 1111 7959 : } + 1112 : + 1113 58110 : void pathcut(char* dst) + 1114 : { + 1115 58110 : char* slash = strrchr(dst, '/'); 1116 : - 1117 53116131 : int pathcmp(const char* a, const char* b) - 1118 : { - 1119 : #ifdef _WIN32 - 1120 : char ai[PATH_MAX]; - 1121 : char bi[PATH_MAX]; + 1117 58110 : if (slash) + 1118 58110 : slash[1] = 0; + 1119 : else + 1120 0 : dst[0] = 0; + 1121 58110 : } 1122 : - 1123 : /* import to convert \ to / */ - 1124 : pathimport(ai, sizeof(ai), a); - 1125 : pathimport(bi, sizeof(bi), b); - 1126 : - 1127 : /* case insensitive compare in Windows */ - 1128 : return stricmp(ai, bi); - 1129 : #else - 1130 53116131 : return strcmp(a, b); - 1131 : #endif - 1132 : } - 1133 : - 1134 0 : int path_is_root_of(const char* root, const char* path) - 1135 : { - 1136 0 : while (*root && *path) { - 1137 : #ifdef _WIN32 - 1138 : /* case insensitive compare in Windows */ - 1139 : char r = tolower((unsigned char)*root); - 1140 : char p = tolower((unsigned char)*path); - 1141 : if (r == '\\') - 1142 : r = '/'; - 1143 : if (p == '\\') - 1144 : p = '/'; - 1145 : if (r != p) - 1146 : return 0; - 1147 : #else - 1148 0 : if (*root != *path) - 1149 0 : return 0; - 1150 : #endif - 1151 0 : ++root; - 1152 0 : ++path; - 1153 : } - 1154 : - 1155 0 : return *root == 0 && *path != 0; - 1156 : } - 1157 : - 1158 : /****************************************************************************/ - 1159 : /* file-system */ + 1123 53117221 : int pathcmp(const char* a, const char* b) + 1124 : { + 1125 : #ifdef _WIN32 + 1126 : char ai[PATH_MAX]; + 1127 : char bi[PATH_MAX]; + 1128 : + 1129 : /* import to convert \ to / */ + 1130 : pathimport(ai, sizeof(ai), a); + 1131 : pathimport(bi, sizeof(bi), b); + 1132 : + 1133 : /* case insensitive compare in Windows */ + 1134 : return stricmp(ai, bi); + 1135 : #else + 1136 53117221 : return strcmp(a, b); + 1137 : #endif + 1138 : } + 1139 : + 1140 0 : int path_is_root_of(const char* root, const char* path) + 1141 : { + 1142 0 : while (*root && *path) { + 1143 : #ifdef _WIN32 + 1144 : /* case insensitive compare in Windows */ + 1145 : char r = tolower((unsigned char)*root); + 1146 : char p = tolower((unsigned char)*path); + 1147 : if (r == '\\') + 1148 : r = '/'; + 1149 : if (p == '\\') + 1150 : p = '/'; + 1151 : if (r != p) + 1152 : return 0; + 1153 : #else + 1154 0 : if (*root != *path) + 1155 0 : return 0; + 1156 : #endif + 1157 0 : ++root; + 1158 0 : ++path; + 1159 : } 1160 : - 1161 787726 : int mkancestor(const char* file) - 1162 : { - 1163 : char dir[PATH_MAX]; - 1164 : struct stat st; - 1165 : char* c; + 1161 0 : return *root == 0 && *path != 0; + 1162 : } + 1163 : + 1164 : /****************************************************************************/ + 1165 : /* file-system */ 1166 : - 1167 787726 : pathcpy(dir, sizeof(dir), file); - 1168 : - 1169 787726 : c = strrchr(dir, '/'); - 1170 787726 : if (!c) { - 1171 : /* no ancestor */ - 1172 0 : return 0; - 1173 : } + 1167 787783 : int mkancestor(const char* file) + 1168 : { + 1169 : char dir[PATH_MAX]; + 1170 : struct stat st; + 1171 : char* c; + 1172 : + 1173 787783 : pathcpy(dir, sizeof(dir), file); 1174 : - 1175 : /* clear the file */ - 1176 787726 : *c = 0; - 1177 : - 1178 : /* if it's the root dir */ - 1179 787726 : if (*dir == 0) { - 1180 : /* nothing more to do */ - 1181 0 : return 0; - 1182 : } + 1175 787783 : c = strrchr(dir, '/'); + 1176 787783 : if (!c) { + 1177 : /* no ancestor */ + 1178 0 : return 0; + 1179 : } + 1180 : + 1181 : /* clear the file */ + 1182 787783 : *c = 0; 1183 : - 1184 : #ifdef _WIN32 - 1185 : /* if it's a drive specification like "C:" */ - 1186 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { - 1187 : /* nothing more to do */ - 1188 : return 0; - 1189 : } - 1190 : #endif - 1191 : - 1192 : /* - 1193 : * Check if the dir already exists using lstat(). - 1194 : * - 1195 : * Note that in Windows when dealing with read-only media - 1196 : * you cannot try to create the directory, and expecting - 1197 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. - 1198 : * - 1199 : * Also in Windows it's better to use lstat() than stat() because it - 1200 : * doesn't need to open the dir with CreateFile(). - 1201 : */ - 1202 787726 : if (lstat(dir, &st) == 0) { - 1203 : /* it already exists */ - 1204 787648 : return 0; - 1205 : } - 1206 : - 1207 : /* recursively create them all */ - 1208 78 : if (mkancestor(dir) != 0) { - 1209 : /* LCOV_EXCL_START */ - 1210 : return -1; - 1211 : /* LCOV_EXCL_STOP */ - 1212 : } - 1213 : - 1214 : /* create it */ - 1215 78 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { - 1216 : /* LCOV_EXCL_START */ - 1217 : log_fatal(errno, "Error creating directory '%s'. %s.\n", dir, strerror(errno)); - 1218 : return -1; - 1219 : /* LCOV_EXCL_STOP */ - 1220 : } - 1221 : - 1222 78 : return 0; - 1223 : } - 1224 : - 1225 121348 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) - 1226 : { - 1227 : #if HAVE_FUTIMENS - 1228 : struct timespec tv[2]; - 1229 : #else - 1230 : struct timeval tv[2]; - 1231 : #endif - 1232 : int ret; - 1233 : - 1234 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ - 1235 121348 : tv[0].tv_sec = mtime_sec; - 1236 121348 : if (mtime_nsec != STAT_NSEC_INVALID) - 1237 121348 : tv[0].tv_nsec = mtime_nsec; - 1238 : else - 1239 0 : tv[0].tv_nsec = 0; - 1240 121348 : tv[1].tv_sec = tv[0].tv_sec; - 1241 121348 : tv[1].tv_nsec = tv[0].tv_nsec; - 1242 : - 1243 121348 : ret = futimens(f, tv); - 1244 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ - 1245 : tv[0].tv_sec = mtime_sec; - 1246 : if (mtime_nsec != STAT_NSEC_INVALID) - 1247 : tv[0].tv_usec = mtime_nsec / 1000; - 1248 : else - 1249 : tv[0].tv_usec = 0; - 1250 : tv[1].tv_sec = tv[0].tv_sec; - 1251 : tv[1].tv_usec = tv[0].tv_usec; - 1252 : - 1253 : ret = futimes(f, tv); - 1254 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ - 1255 : tv[0].tv_sec = mtime_sec; - 1256 : if (mtime_nsec != STAT_NSEC_INVALID) - 1257 : tv[0].tv_usec = mtime_nsec / 1000; - 1258 : else - 1259 : tv[0].tv_usec = 0; - 1260 : tv[1].tv_sec = tv[0].tv_sec; - 1261 : tv[1].tv_usec = tv[0].tv_usec; - 1262 : - 1263 : ret = futimesat(f, 0, tv); - 1264 : #else - 1265 : #error No function available to set file timestamps with sub-second precision - 1266 : #endif - 1267 : - 1268 121348 : return ret; - 1269 : } - 1270 : - 1271 11645 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec) - 1272 : { - 1273 : #if HAVE_UTIMENSAT - 1274 : struct timespec tv[2]; - 1275 : #else - 1276 : struct timeval tv[2]; - 1277 : #endif - 1278 : int ret; - 1279 : - 1280 : #if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */ - 1281 11645 : tv[0].tv_sec = mtime_sec; - 1282 11645 : if (mtime_nsec != STAT_NSEC_INVALID) - 1283 11645 : tv[0].tv_nsec = mtime_nsec; - 1284 : else - 1285 0 : tv[0].tv_nsec = 0; - 1286 11645 : tv[1].tv_sec = tv[0].tv_sec; - 1287 11645 : tv[1].tv_nsec = tv[0].tv_nsec; - 1288 : - 1289 11645 : ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW); - 1290 : #elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */ - 1291 : tv[0].tv_sec = mtime_sec; - 1292 : if (mtime_nsec != STAT_NSEC_INVALID) - 1293 : tv[0].tv_usec = mtime_nsec / 1000; - 1294 : else - 1295 : tv[0].tv_usec = 0; - 1296 : tv[1].tv_sec = tv[0].tv_sec; - 1297 : tv[1].tv_usec = tv[0].tv_usec; - 1298 : - 1299 : ret = lutimes(path, tv); - 1300 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ - 1301 : tv[0].tv_sec = mtime_sec; - 1302 : if (mtime_nsec != STAT_NSEC_INVALID) - 1303 : tv[0].tv_usec = mtime_nsec / 1000; - 1304 : else - 1305 : tv[0].tv_usec = 0; - 1306 : tv[1].tv_sec = tv[0].tv_sec; - 1307 : tv[1].tv_usec = tv[0].tv_usec; - 1308 : - 1309 : ret = futimesat(AT_FDCWD, path, tv); - 1310 : #else - 1311 : #error No function available to set file timestamps with sub-second precision - 1312 : #endif - 1313 : - 1314 11645 : return ret; - 1315 : } - 1316 : - 1317 : /****************************************************************************/ - 1318 : /* advise */ + 1184 : /* if it's the root dir */ + 1185 787783 : if (*dir == 0) { + 1186 : /* nothing more to do */ + 1187 0 : return 0; + 1188 : } + 1189 : + 1190 : #ifdef _WIN32 + 1191 : /* if it's a drive specification like "C:" */ + 1192 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { + 1193 : /* nothing more to do */ + 1194 : return 0; + 1195 : } + 1196 : #endif + 1197 : + 1198 : /* + 1199 : * Check if the dir already exists using lstat(). + 1200 : * + 1201 : * Note that in Windows when dealing with read-only media + 1202 : * you cannot try to create the directory, and expecting + 1203 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. + 1204 : * + 1205 : * Also in Windows it's better to use lstat() than stat() because it + 1206 : * doesn't need to open the dir with CreateFile(). + 1207 : */ + 1208 787783 : if (lstat(dir, &st) == 0) { + 1209 : /* it already exists */ + 1210 787705 : return 0; + 1211 : } + 1212 : + 1213 : /* recursively create them all */ + 1214 78 : if (mkancestor(dir) != 0) { + 1215 : /* LCOV_EXCL_START */ + 1216 : return -1; + 1217 : /* LCOV_EXCL_STOP */ + 1218 : } + 1219 : + 1220 : /* create it */ + 1221 78 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + 1222 : /* LCOV_EXCL_START */ + 1223 : log_fatal(errno, "Error creating directory '%s'. %s.\n", dir, strerror(errno)); + 1224 : return -1; + 1225 : /* LCOV_EXCL_STOP */ + 1226 : } + 1227 : + 1228 78 : return 0; + 1229 : } + 1230 : + 1231 121378 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) + 1232 : { + 1233 : #if HAVE_FUTIMENS + 1234 : struct timespec tv[2]; + 1235 : #else + 1236 : struct timeval tv[2]; + 1237 : #endif + 1238 : int ret; + 1239 : + 1240 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ + 1241 121378 : tv[0].tv_sec = mtime_sec; + 1242 121378 : if (mtime_nsec != STAT_NSEC_INVALID) + 1243 121378 : tv[0].tv_nsec = mtime_nsec; + 1244 : else + 1245 0 : tv[0].tv_nsec = 0; + 1246 121378 : tv[1].tv_sec = tv[0].tv_sec; + 1247 121378 : tv[1].tv_nsec = tv[0].tv_nsec; + 1248 : + 1249 121378 : ret = futimens(f, tv); + 1250 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ + 1251 : tv[0].tv_sec = mtime_sec; + 1252 : if (mtime_nsec != STAT_NSEC_INVALID) + 1253 : tv[0].tv_usec = mtime_nsec / 1000; + 1254 : else + 1255 : tv[0].tv_usec = 0; + 1256 : tv[1].tv_sec = tv[0].tv_sec; + 1257 : tv[1].tv_usec = tv[0].tv_usec; + 1258 : + 1259 : ret = futimes(f, tv); + 1260 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + 1261 : tv[0].tv_sec = mtime_sec; + 1262 : if (mtime_nsec != STAT_NSEC_INVALID) + 1263 : tv[0].tv_usec = mtime_nsec / 1000; + 1264 : else + 1265 : tv[0].tv_usec = 0; + 1266 : tv[1].tv_sec = tv[0].tv_sec; + 1267 : tv[1].tv_usec = tv[0].tv_usec; + 1268 : + 1269 : ret = futimesat(f, 0, tv); + 1270 : #else + 1271 : #error No function available to set file timestamps with sub-second precision + 1272 : #endif + 1273 : + 1274 121378 : return ret; + 1275 : } + 1276 : + 1277 11645 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec) + 1278 : { + 1279 : #if HAVE_UTIMENSAT + 1280 : struct timespec tv[2]; + 1281 : #else + 1282 : struct timeval tv[2]; + 1283 : #endif + 1284 : int ret; + 1285 : + 1286 : #if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */ + 1287 11645 : tv[0].tv_sec = mtime_sec; + 1288 11645 : if (mtime_nsec != STAT_NSEC_INVALID) + 1289 11645 : tv[0].tv_nsec = mtime_nsec; + 1290 : else + 1291 0 : tv[0].tv_nsec = 0; + 1292 11645 : tv[1].tv_sec = tv[0].tv_sec; + 1293 11645 : tv[1].tv_nsec = tv[0].tv_nsec; + 1294 : + 1295 11645 : ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW); + 1296 : #elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */ + 1297 : tv[0].tv_sec = mtime_sec; + 1298 : if (mtime_nsec != STAT_NSEC_INVALID) + 1299 : tv[0].tv_usec = mtime_nsec / 1000; + 1300 : else + 1301 : tv[0].tv_usec = 0; + 1302 : tv[1].tv_sec = tv[0].tv_sec; + 1303 : tv[1].tv_usec = tv[0].tv_usec; + 1304 : + 1305 : ret = lutimes(path, tv); + 1306 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + 1307 : tv[0].tv_sec = mtime_sec; + 1308 : if (mtime_nsec != STAT_NSEC_INVALID) + 1309 : tv[0].tv_usec = mtime_nsec / 1000; + 1310 : else + 1311 : tv[0].tv_usec = 0; + 1312 : tv[1].tv_sec = tv[0].tv_sec; + 1313 : tv[1].tv_usec = tv[0].tv_usec; + 1314 : + 1315 : ret = futimesat(AT_FDCWD, path, tv); + 1316 : #else + 1317 : #error No function available to set file timestamps with sub-second precision + 1318 : #endif 1319 : - 1320 2489611 : void advise_init(struct advise_struct* advise, int mode) - 1321 : { - 1322 2489611 : advise->mode = mode; - 1323 2489611 : advise->dirty_begin = 0; - 1324 2489611 : advise->dirty_end = 0; - 1325 2489611 : } - 1326 : - 1327 2489611 : int advise_flags(struct advise_struct* advise) - 1328 : { - 1329 2489611 : int flags = 0; - 1330 : - 1331 2489611 : if (advise->mode == ADVISE_SEQUENTIAL - 1332 2478269 : || advise->mode == ADVISE_FLUSH - 1333 2478269 : || advise->mode == ADVISE_FLUSH_WINDOW - 1334 2466927 : || advise->mode == ADVISE_DISCARD - 1335 2466927 : || advise->mode == ADVISE_DISCARD_WINDOW - 1336 : ) - 1337 34026 : flags |= O_SEQUENTIAL; - 1338 : - 1339 : #if HAVE_DIRECT_IO - 1340 2489611 : if (advise->mode == ADVISE_DIRECT) - 1341 0 : flags |= O_DIRECT; - 1342 : #endif - 1343 : - 1344 2489611 : return flags; - 1345 : } - 1346 : - 1347 2410879 : int advise_open(struct advise_struct* advise, int f) - 1348 : { - 1349 : (void)advise; - 1350 : (void)f; - 1351 : - 1352 : #if HAVE_POSIX_FADVISE - 1353 2410879 : if (advise->mode == ADVISE_SEQUENTIAL - 1354 2399537 : || advise->mode == ADVISE_FLUSH - 1355 2399537 : || advise->mode == ADVISE_FLUSH_WINDOW - 1356 2388195 : || advise->mode == ADVISE_DISCARD - 1357 2388195 : || advise->mode == ADVISE_DISCARD_WINDOW - 1358 : ) { - 1359 : int ret; - 1360 : - 1361 : /* advise noreuse access, this avoids to pollute the page cache */ - 1362 : /* supported from Linux Kernel 6.3 with this commit: https://github.com/torvalds/linux/commit/17e810229cb3068b692fa078bd9b3a6527e0866a */ - 1363 34026 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_NOREUSE); - 1364 34026 : if (ret == ENOSYS) { - 1365 : /* call is not supported */ - 1366 0 : ret = 0; - 1367 : } - 1368 34026 : if (ret != 0) { - 1369 : /* LCOV_EXCL_START */ - 1370 : errno = ret; /* posix_fadvise return the error code */ - 1371 : return -1; - 1372 : /* LCOV_EXCL_STOP */ + 1320 11645 : return ret; + 1321 : } + 1322 : + 1323 : /****************************************************************************/ + 1324 : /* advise */ + 1325 : + 1326 2489478 : void advise_init(struct advise_struct* advise, int mode) + 1327 : { + 1328 2489478 : advise->mode = mode; + 1329 2489478 : advise->dirty_begin = 0; + 1330 2489478 : advise->dirty_end = 0; + 1331 2489478 : } + 1332 : + 1333 2489478 : int advise_flags(struct advise_struct* advise) + 1334 : { + 1335 2489478 : int flags = 0; + 1336 : + 1337 2489478 : if (advise->mode == ADVISE_SEQUENTIAL + 1338 2478136 : || advise->mode == ADVISE_FLUSH + 1339 2478136 : || advise->mode == ADVISE_FLUSH_WINDOW + 1340 2466794 : || advise->mode == ADVISE_DISCARD + 1341 2466794 : || advise->mode == ADVISE_DISCARD_WINDOW + 1342 : ) + 1343 34026 : flags |= O_SEQUENTIAL; + 1344 : + 1345 : #if HAVE_DIRECT_IO + 1346 2489478 : if (advise->mode == ADVISE_DIRECT) + 1347 0 : flags |= O_DIRECT; + 1348 : #endif + 1349 : + 1350 2489478 : return flags; + 1351 : } + 1352 : + 1353 2410781 : int advise_open(struct advise_struct* advise, int f) + 1354 : { + 1355 : (void)advise; + 1356 : (void)f; + 1357 : + 1358 : #if HAVE_POSIX_FADVISE + 1359 2410781 : if (advise->mode == ADVISE_SEQUENTIAL + 1360 2399439 : || advise->mode == ADVISE_FLUSH + 1361 2399439 : || advise->mode == ADVISE_FLUSH_WINDOW + 1362 2388097 : || advise->mode == ADVISE_DISCARD + 1363 2388097 : || advise->mode == ADVISE_DISCARD_WINDOW + 1364 : ) { + 1365 : int ret; + 1366 : + 1367 : /* advise noreuse access, this avoids to pollute the page cache */ + 1368 : /* supported from Linux Kernel 6.3 with this commit: https://github.com/torvalds/linux/commit/17e810229cb3068b692fa078bd9b3a6527e0866a */ + 1369 34026 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_NOREUSE); + 1370 34026 : if (ret == ENOSYS) { + 1371 : /* call is not supported */ + 1372 0 : ret = 0; 1373 : } - 1374 : - 1375 : /* advise sequential access, this doubles the read-ahead window size */ - 1376 34026 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); - 1377 34026 : if (ret == ENOSYS) { - 1378 : /* call is not supported, like in armhf, see posix_fadvise manpage */ - 1379 0 : ret = 0; - 1380 : } - 1381 34026 : if (ret != 0) { - 1382 : /* LCOV_EXCL_START */ - 1383 : errno = ret; /* posix_fadvise return the error code */ - 1384 : return -1; - 1385 : /* LCOV_EXCL_STOP */ + 1374 34026 : if (ret != 0) { + 1375 : /* LCOV_EXCL_START */ + 1376 : errno = ret; /* posix_fadvise return the error code */ + 1377 : return -1; + 1378 : /* LCOV_EXCL_STOP */ + 1379 : } + 1380 : + 1381 : /* advise sequential access, this doubles the read-ahead window size */ + 1382 34026 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + 1383 34026 : if (ret == ENOSYS) { + 1384 : /* call is not supported, like in armhf, see posix_fadvise manpage */ + 1385 0 : ret = 0; 1386 : } - 1387 : } - 1388 : #endif - 1389 : - 1390 2410879 : return 0; - 1391 : } - 1392 : - 1393 914575 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) - 1394 : { - 1395 : data_off_t flush_offset; - 1396 : data_off_t flush_size; - 1397 : data_off_t discard_offset; - 1398 : data_off_t discard_size; - 1399 : - 1400 : (void)f; - 1401 : (void)flush_offset; - 1402 : (void)flush_size; - 1403 : (void)discard_offset; - 1404 : (void)discard_size; + 1387 34026 : if (ret != 0) { + 1388 : /* LCOV_EXCL_START */ + 1389 : errno = ret; /* posix_fadvise return the error code */ + 1390 : return -1; + 1391 : /* LCOV_EXCL_STOP */ + 1392 : } + 1393 : } + 1394 : #endif + 1395 : + 1396 2410781 : return 0; + 1397 : } + 1398 : + 1399 914297 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) + 1400 : { + 1401 : data_off_t flush_offset; + 1402 : data_off_t flush_size; + 1403 : data_off_t discard_offset; + 1404 : data_off_t discard_size; 1405 : - 1406 914575 : flush_offset = 0; - 1407 914575 : flush_size = 0; - 1408 914575 : discard_offset = 0; - 1409 914575 : discard_size = 0; - 1410 : - 1411 : /* - 1412 : * Follow Linus recommendations about fast writes. - 1413 : * - 1414 : * Linus "Unexpected splice "always copy" behavior observed" - 1415 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070 - 1416 : * --- - 1417 : * I have had _very_ good experiences with even a rather trivial - 1418 : * file writer that basically used (iirc) 8MB windows, and the logic was very - 1419 : * trivial: - 1420 : * - 1421 : * - before writing a new 8M window, do "start writeback" - 1422 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do - 1423 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that. - 1424 : * - 1425 : * in fact, in its simplest form, you can do it like this (this is from my - 1426 : * "overwrite disk images" program that I use on old disks): - 1427 : * - 1428 : * for (index = 0; index < max_index ;index++) { - 1429 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE) - 1430 : * break; - 1431 : * // This won't block, but will start writeout asynchronously - 1432 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE); - 1433 : * // This does a blocking write-and-wait on any old ranges - 1434 : * if (index) - 1435 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); - 1436 : * } - 1437 : * - 1438 : * and even if you don't actually do a discard (maybe we should add a - 1439 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate - 1440 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty - 1441 : * nice, because the heavy writer gets good IO performance _and_ leaves only - 1442 : * easy-to-free pages around after itself. - 1443 : * --- - 1444 : * - 1445 : * Linus "Unexpected splice "always copy" behavior observed" - 1446 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176 - 1447 : * --- - 1448 : * The behavior for dirty page writeback is _not_ well defined, and - 1449 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that - 1450 : * writeback logic, ie you do it only on ranges that you have just waited on. - 1451 : * - 1452 : * IOW, in my example, you'd couple the - 1453 : * - 1454 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); - 1455 : * - 1456 : * with a + 1406 : (void)f; + 1407 : (void)flush_offset; + 1408 : (void)flush_size; + 1409 : (void)discard_offset; + 1410 : (void)discard_size; + 1411 : + 1412 914297 : flush_offset = 0; + 1413 914297 : flush_size = 0; + 1414 914297 : discard_offset = 0; + 1415 914297 : discard_size = 0; + 1416 : + 1417 : /* + 1418 : * Follow Linus recommendations about fast writes. + 1419 : * + 1420 : * Linus "Unexpected splice "always copy" behavior observed" + 1421 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070 + 1422 : * --- + 1423 : * I have had _very_ good experiences with even a rather trivial + 1424 : * file writer that basically used (iirc) 8MB windows, and the logic was very + 1425 : * trivial: + 1426 : * + 1427 : * - before writing a new 8M window, do "start writeback" + 1428 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do + 1429 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that. + 1430 : * + 1431 : * in fact, in its simplest form, you can do it like this (this is from my + 1432 : * "overwrite disk images" program that I use on old disks): + 1433 : * + 1434 : * for (index = 0; index < max_index ;index++) { + 1435 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE) + 1436 : * break; + 1437 : * // This won't block, but will start writeout asynchronously + 1438 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE); + 1439 : * // This does a blocking write-and-wait on any old ranges + 1440 : * if (index) + 1441 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + 1442 : * } + 1443 : * + 1444 : * and even if you don't actually do a discard (maybe we should add a + 1445 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate + 1446 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty + 1447 : * nice, because the heavy writer gets good IO performance _and_ leaves only + 1448 : * easy-to-free pages around after itself. + 1449 : * --- + 1450 : * + 1451 : * Linus "Unexpected splice "always copy" behavior observed" + 1452 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176 + 1453 : * --- + 1454 : * The behavior for dirty page writeback is _not_ well defined, and + 1455 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that + 1456 : * writeback logic, ie you do it only on ranges that you have just waited on. 1457 : * - 1458 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED); + 1458 : * IOW, in my example, you'd couple the 1459 : * - 1460 : * afterwards to throw out the pages that you just waited for. - 1461 : * --- - 1462 : */ - 1463 : - 1464 914575 : switch (advise->mode) { - 1465 0 : case ADVISE_FLUSH : - 1466 0 : flush_offset = offset; - 1467 0 : flush_size = size; - 1468 0 : break; - 1469 0 : case ADVISE_DISCARD : - 1470 0 : discard_offset = offset; - 1471 0 : discard_size = size; - 1472 0 : break; - 1473 4687 : case ADVISE_FLUSH_WINDOW : - 1474 : /* if the dirty range can be extended */ - 1475 4687 : if (advise->dirty_end == offset) { - 1476 : /* extent the dirty range */ - 1477 4687 : advise->dirty_end += size; - 1478 : - 1479 : /* if we reached the window size */ - 1480 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) { - 1481 : /* flush the window */ - 1482 0 : flush_offset = advise->dirty_begin; - 1483 0 : flush_size = ADVISE_WINDOW_SIZE; + 1460 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + 1461 : * + 1462 : * with a + 1463 : * + 1464 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED); + 1465 : * + 1466 : * afterwards to throw out the pages that you just waited for. + 1467 : * --- + 1468 : */ + 1469 : + 1470 914297 : switch (advise->mode) { + 1471 0 : case ADVISE_FLUSH : + 1472 0 : flush_offset = offset; + 1473 0 : flush_size = size; + 1474 0 : break; + 1475 0 : case ADVISE_DISCARD : + 1476 0 : discard_offset = offset; + 1477 0 : discard_size = size; + 1478 0 : break; + 1479 4687 : case ADVISE_FLUSH_WINDOW : + 1480 : /* if the dirty range can be extended */ + 1481 4687 : if (advise->dirty_end == offset) { + 1482 : /* extent the dirty range */ + 1483 4687 : advise->dirty_end += size; 1484 : - 1485 : /* remove it from the dirty range */ - 1486 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; - 1487 : } - 1488 : } else { - 1489 : /* otherwise flush the existing dirty */ - 1490 0 : flush_offset = advise->dirty_begin; - 1491 0 : flush_size = advise->dirty_end - advise->dirty_begin; - 1492 : - 1493 : /* and set the new range as dirty */ - 1494 0 : advise->dirty_begin = offset; - 1495 0 : advise->dirty_end = offset + size; - 1496 : } - 1497 4687 : break; - 1498 4687 : case ADVISE_DISCARD_WINDOW : - 1499 : /* if the dirty range can be extended */ - 1500 4687 : if (advise->dirty_end == offset) { - 1501 : /* extent the dirty range */ - 1502 4687 : advise->dirty_end += size; - 1503 : - 1504 : /* if we reached the double window size */ - 1505 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) { - 1506 : /* discard the first window */ - 1507 0 : discard_offset = advise->dirty_begin; - 1508 0 : discard_size = ADVISE_WINDOW_SIZE; + 1485 : /* if we reached the window size */ + 1486 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) { + 1487 : /* flush the window */ + 1488 0 : flush_offset = advise->dirty_begin; + 1489 0 : flush_size = ADVISE_WINDOW_SIZE; + 1490 : + 1491 : /* remove it from the dirty range */ + 1492 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; + 1493 : } + 1494 : } else { + 1495 : /* otherwise flush the existing dirty */ + 1496 0 : flush_offset = advise->dirty_begin; + 1497 0 : flush_size = advise->dirty_end - advise->dirty_begin; + 1498 : + 1499 : /* and set the new range as dirty */ + 1500 0 : advise->dirty_begin = offset; + 1501 0 : advise->dirty_end = offset + size; + 1502 : } + 1503 4687 : break; + 1504 4687 : case ADVISE_DISCARD_WINDOW : + 1505 : /* if the dirty range can be extended */ + 1506 4687 : if (advise->dirty_end == offset) { + 1507 : /* extent the dirty range */ + 1508 4687 : advise->dirty_end += size; 1509 : - 1510 : /* remove it from the dirty range */ - 1511 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; - 1512 : - 1513 : /* flush the second window */ - 1514 0 : flush_offset = advise->dirty_begin; - 1515 0 : flush_size = ADVISE_WINDOW_SIZE; - 1516 : } - 1517 : } else { - 1518 : /* otherwise discard the existing dirty */ - 1519 0 : discard_offset = advise->dirty_begin; - 1520 0 : discard_size = advise->dirty_end - advise->dirty_begin; - 1521 : - 1522 : /* and set the new range as dirty */ - 1523 0 : advise->dirty_begin = offset; - 1524 0 : advise->dirty_end = offset + size; - 1525 : } - 1526 4687 : break; - 1527 : } - 1528 : - 1529 : #if HAVE_SYNC_FILE_RANGE - 1530 914575 : if (flush_size != 0) { - 1531 : int ret; - 1532 : - 1533 : /* start writing immediately */ - 1534 0 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); - 1535 0 : if (ret != 0) { - 1536 : /* LCOV_EXCL_START */ - 1537 : return -1; - 1538 : /* LCOV_EXCL_STOP */ - 1539 : } - 1540 : } - 1541 : #endif - 1542 : - 1543 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE - 1544 914575 : if (discard_size != 0) { - 1545 : int ret; - 1546 : - 1547 : /* send the data to the disk and wait until it's written */ - 1548 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); - 1549 0 : if (ret != 0) { - 1550 : /* LCOV_EXCL_START */ - 1551 : return -1; - 1552 : /* LCOV_EXCL_STOP */ - 1553 : } - 1554 : - 1555 : /* flush the data from the cache */ - 1556 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); - 1557 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ - 1558 0 : if (ret != 0) { - 1559 : /* LCOV_EXCL_START */ - 1560 : errno = ret; /* posix_fadvise return the error code */ - 1561 : return -1; - 1562 : /* LCOV_EXCL_STOP */ - 1563 : } - 1564 : } - 1565 : #endif - 1566 : - 1567 914575 : return 0; - 1568 : } - 1569 : - 1570 8833871 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) - 1571 : { - 1572 : (void)advise; - 1573 : (void)f; - 1574 : (void)offset; - 1575 : (void)size; - 1576 : - 1577 : #if HAVE_POSIX_FADVISE - 1578 8833871 : if (advise->mode == ADVISE_DISCARD - 1579 8833871 : || advise->mode == ADVISE_DISCARD_WINDOW - 1580 : ) { - 1581 : int ret; + 1510 : /* if we reached the double window size */ + 1511 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) { + 1512 : /* discard the first window */ + 1513 0 : discard_offset = advise->dirty_begin; + 1514 0 : discard_size = ADVISE_WINDOW_SIZE; + 1515 : + 1516 : /* remove it from the dirty range */ + 1517 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; + 1518 : + 1519 : /* flush the second window */ + 1520 0 : flush_offset = advise->dirty_begin; + 1521 0 : flush_size = ADVISE_WINDOW_SIZE; + 1522 : } + 1523 : } else { + 1524 : /* otherwise discard the existing dirty */ + 1525 0 : discard_offset = advise->dirty_begin; + 1526 0 : discard_size = advise->dirty_end - advise->dirty_begin; + 1527 : + 1528 : /* and set the new range as dirty */ + 1529 0 : advise->dirty_begin = offset; + 1530 0 : advise->dirty_end = offset + size; + 1531 : } + 1532 4687 : break; + 1533 : } + 1534 : + 1535 : #if HAVE_SYNC_FILE_RANGE + 1536 914297 : if (flush_size != 0) { + 1537 : int ret; + 1538 : + 1539 : /* start writing immediately */ + 1540 0 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); + 1541 0 : if (ret != 0) { + 1542 : /* LCOV_EXCL_START */ + 1543 : return -1; + 1544 : /* LCOV_EXCL_STOP */ + 1545 : } + 1546 : } + 1547 : #endif + 1548 : + 1549 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE + 1550 914297 : if (discard_size != 0) { + 1551 : int ret; + 1552 : + 1553 : /* send the data to the disk and wait until it's written */ + 1554 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); + 1555 0 : if (ret != 0) { + 1556 : /* LCOV_EXCL_START */ + 1557 : return -1; + 1558 : /* LCOV_EXCL_STOP */ + 1559 : } + 1560 : + 1561 : /* flush the data from the cache */ + 1562 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); + 1563 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + 1564 0 : if (ret != 0) { + 1565 : /* LCOV_EXCL_START */ + 1566 : errno = ret; /* posix_fadvise return the error code */ + 1567 : return -1; + 1568 : /* LCOV_EXCL_STOP */ + 1569 : } + 1570 : } + 1571 : #endif + 1572 : + 1573 914297 : return 0; + 1574 : } + 1575 : + 1576 8833464 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) + 1577 : { + 1578 : (void)advise; + 1579 : (void)f; + 1580 : (void)offset; + 1581 : (void)size; 1582 : - 1583 : /* flush the data from the cache */ - 1584 27825 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED); - 1585 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ - 1586 27825 : if (ret != 0) { - 1587 : /* LCOV_EXCL_START */ - 1588 : errno = ret; /* posix_fadvise return the error code */ - 1589 : return -1; - 1590 : /* LCOV_EXCL_STOP */ - 1591 : } - 1592 : } - 1593 : #endif - 1594 : - 1595 : /* - 1596 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block - 1597 : * because it may be blocking. - 1598 : * - 1599 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?" - 1600 : * https://lkml.org/lkml/2010/12/6/122 - 1601 : * --- - 1602 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same - 1603 : * way, and in fact share mostly the same code path (see - 1604 : * force_page_cache_readahead() in mm/readahead.c). - 1605 : * - 1606 : * They are asynchronous in that there is no guarantee the pages will be - 1607 : * in the page cache by the time they return. But at the same time, they - 1608 : * are not guaranteed to be non-blocking. That is, the work of doing the - 1609 : * readahead does not take place in a kernel thread. So if you try to - 1610 : * request I/O than will fit in the request queue, the system call will - 1611 : * block until some I/O is completed so that more I/O requested cam be - 1612 : * loaded onto the request queue. - 1613 : * - 1614 : * The only way to fix this would be to either put the work on a kernel - 1615 : * thread (i.e., some kind of workqueue) or in a userspace thread. For - 1616 : * ion programmer wondering what to do today, I'd suggest the - 1617 : * latter since it will be more portable across various kernel versions. - 1618 : * - 1619 : * This does leave the question about whether we should change the kernel - 1620 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be - 1621 : * non-blocking and do this work in a workqueue (or via some kind of - 1622 : * callback/continuation scheme). My worry is just doing this if a user - 1623 : * application does something crazy, like request gigabytes and gigabytes - 1624 : * of readahead, and then repented of their craziness, there should be a - 1625 : * way of cancelling the readahead request. Today, the user can just - 1626 : * kill the application. But if we simply shove the work to a kernel - 1627 : * thread, it becomes a lot harder to cancel the readahead request. We'd - 1628 : * have to invent a new API, and then have a way to know whether the user - 1629 : * has access to kill a particular readahead request, etc. - 1630 : * --- - 1631 : */ - 1632 : - 1633 8833871 : return 0; - 1634 : } - 1635 : - 1636 : /****************************************************************************/ - 1637 : /* memory */ + 1583 : #if HAVE_POSIX_FADVISE + 1584 8833464 : if (advise->mode == ADVISE_DISCARD + 1585 8833464 : || advise->mode == ADVISE_DISCARD_WINDOW + 1586 : ) { + 1587 : int ret; + 1588 : + 1589 : /* flush the data from the cache */ + 1590 27825 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED); + 1591 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + 1592 27825 : if (ret != 0) { + 1593 : /* LCOV_EXCL_START */ + 1594 : errno = ret; /* posix_fadvise return the error code */ + 1595 : return -1; + 1596 : /* LCOV_EXCL_STOP */ + 1597 : } + 1598 : } + 1599 : #endif + 1600 : + 1601 : /* + 1602 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block + 1603 : * because it may be blocking. + 1604 : * + 1605 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?" + 1606 : * https://lkml.org/lkml/2010/12/6/122 + 1607 : * --- + 1608 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same + 1609 : * way, and in fact share mostly the same code path (see + 1610 : * force_page_cache_readahead() in mm/readahead.c). + 1611 : * + 1612 : * They are asynchronous in that there is no guarantee the pages will be + 1613 : * in the page cache by the time they return. But at the same time, they + 1614 : * are not guaranteed to be non-blocking. That is, the work of doing the + 1615 : * readahead does not take place in a kernel thread. So if you try to + 1616 : * request I/O than will fit in the request queue, the system call will + 1617 : * block until some I/O is completed so that more I/O requested cam be + 1618 : * loaded onto the request queue. + 1619 : * + 1620 : * The only way to fix this would be to either put the work on a kernel + 1621 : * thread (i.e., some kind of workqueue) or in a userspace thread. For + 1622 : * ion programmer wondering what to do today, I'd suggest the + 1623 : * latter since it will be more portable across various kernel versions. + 1624 : * + 1625 : * This does leave the question about whether we should change the kernel + 1626 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be + 1627 : * non-blocking and do this work in a workqueue (or via some kind of + 1628 : * callback/continuation scheme). My worry is just doing this if a user + 1629 : * application does something crazy, like request gigabytes and gigabytes + 1630 : * of readahead, and then repented of their craziness, there should be a + 1631 : * way of cancelling the readahead request. Today, the user can just + 1632 : * kill the application. But if we simply shove the work to a kernel + 1633 : * thread, it becomes a lot harder to cancel the readahead request. We'd + 1634 : * have to invent a new API, and then have a way to know whether the user + 1635 : * has access to kill a particular readahead request, etc. + 1636 : * --- + 1637 : */ 1638 : - 1639 : /** - 1640 : * Total amount of memory allocated. - 1641 : */ - 1642 : static size_t mcounter; - 1643 : - 1644 488 : size_t malloc_counter_get(void) - 1645 : { - 1646 : size_t ret; - 1647 : - 1648 488 : lock_memory(); + 1639 8833464 : return 0; + 1640 : } + 1641 : + 1642 : /****************************************************************************/ + 1643 : /* memory */ + 1644 : + 1645 : /** + 1646 : * Total amount of memory allocated. + 1647 : */ + 1648 : static size_t mcounter; 1649 : - 1650 488 : ret = mcounter; - 1651 : - 1652 488 : unlock_memory(); + 1650 488 : size_t malloc_counter_get(void) + 1651 : { + 1652 : size_t ret; 1653 : - 1654 488 : return ret; - 1655 : } - 1656 : - 1657 20940815 : void malloc_counter_inc(size_t inc) - 1658 : { - 1659 20940815 : lock_memory(); - 1660 : - 1661 20940815 : mcounter += inc; + 1654 488 : lock_memory(); + 1655 : + 1656 488 : ret = mcounter; + 1657 : + 1658 488 : unlock_memory(); + 1659 : + 1660 488 : return ret; + 1661 : } 1662 : - 1663 20940815 : unlock_memory(); - 1664 20940815 : } - 1665 : - 1666 : /* LCOV_EXCL_START */ - 1667 : static ssize_t malloc_print(int f, const char* str) - 1668 : { - 1669 : ssize_t len = 0; - 1670 : - 1671 : while (str[len]) - 1672 : ++len; - 1673 : return write(f, str, len); - 1674 : } - 1675 : /* LCOV_EXCL_STOP */ + 1663 20941012 : void malloc_counter_inc(size_t inc) + 1664 : { + 1665 20941012 : lock_memory(); + 1666 : + 1667 20941012 : mcounter += inc; + 1668 : + 1669 20941012 : unlock_memory(); + 1670 20941012 : } + 1671 : + 1672 : /* LCOV_EXCL_START */ + 1673 : static ssize_t malloc_print(int f, const char* str) + 1674 : { + 1675 : ssize_t len = 0; 1676 : - 1677 : /* LCOV_EXCL_START */ - 1678 : static ssize_t malloc_printn(int f, size_t value) - 1679 : { - 1680 : char buf[32]; - 1681 : int i; + 1677 : while (str[len]) + 1678 : ++len; + 1679 : return write(f, str, len); + 1680 : } + 1681 : /* LCOV_EXCL_STOP */ 1682 : - 1683 : if (!value) - 1684 : return write(f, "0", 1); - 1685 : - 1686 : i = sizeof(buf); - 1687 : while (value) { - 1688 : buf[--i] = (value % 10) + '0'; - 1689 : value /= 10; - 1690 : } + 1683 : /* LCOV_EXCL_START */ + 1684 : static ssize_t malloc_printn(int f, size_t value) + 1685 : { + 1686 : char buf[32]; + 1687 : int i; + 1688 : + 1689 : if (!value) + 1690 : return write(f, "0", 1); 1691 : - 1692 : return write(f, buf + i, sizeof(buf) - i); - 1693 : } - 1694 : /* LCOV_EXCL_STOP */ - 1695 : - 1696 : /* LCOV_EXCL_START */ - 1697 : void malloc_fail(size_t size) - 1698 : { - 1699 : /* don't use printf to avoid any possible extra allocation */ - 1700 : int f = 2; /* stderr */ + 1692 : i = sizeof(buf); + 1693 : while (value) { + 1694 : buf[--i] = (value % 10) + '0'; + 1695 : value /= 10; + 1696 : } + 1697 : + 1698 : return write(f, buf + i, sizeof(buf) - i); + 1699 : } + 1700 : /* LCOV_EXCL_STOP */ 1701 : - 1702 : malloc_print(f, "Failed for Low Memory!\n"); - 1703 : malloc_print(f, "Allocating "); - 1704 : malloc_printn(f, size); - 1705 : malloc_print(f, " bytes.\n"); - 1706 : malloc_print(f, "Already allocated "); - 1707 : malloc_printn(f, malloc_counter_get()); - 1708 : malloc_print(f, " bytes.\n"); - 1709 : if (sizeof(void*) == 4) { - 1710 : malloc_print(f, "You are currently using a 32 bits executable.\n"); - 1711 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); - 1712 : } - 1713 : } - 1714 : /* LCOV_EXCL_STOP */ - 1715 : - 1716 14819123 : void* malloc_nofail(size_t size) - 1717 : { - 1718 14819123 : void* ptr = malloc(size); - 1719 : - 1720 14819123 : if (!ptr) { - 1721 : /* LCOV_EXCL_START */ - 1722 : malloc_fail(size); - 1723 : exit(EXIT_FAILURE); - 1724 : /* LCOV_EXCL_STOP */ - 1725 : } - 1726 : - 1727 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ - 1728 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ - 1729 : /* and not only reserving the addressable space. */ - 1730 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ - 1731 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ - 1732 : /* get a real error from malloc() instead than a process killed. */ - 1733 : /* Note that calloc() doesn't have the same effect. */ - 1734 14819123 : memset(ptr, 0xA5, size); - 1735 : #endif - 1736 : - 1737 14819123 : malloc_counter_inc(size); - 1738 : - 1739 14819123 : return ptr; - 1740 : } - 1741 : - 1742 156192 : void* calloc_nofail(size_t count, size_t size) - 1743 : { - 1744 : void* ptr; - 1745 : - 1746 156192 : size *= count; + 1702 : /* LCOV_EXCL_START */ + 1703 : void malloc_fail(size_t size) + 1704 : { + 1705 : /* don't use printf to avoid any possible extra allocation */ + 1706 : int f = 2; /* stderr */ + 1707 : + 1708 : malloc_print(f, "Failed for Low Memory!\n"); + 1709 : malloc_print(f, "Allocating "); + 1710 : malloc_printn(f, size); + 1711 : malloc_print(f, " bytes.\n"); + 1712 : malloc_print(f, "Already allocated "); + 1713 : malloc_printn(f, malloc_counter_get()); + 1714 : malloc_print(f, " bytes.\n"); + 1715 : if (sizeof(void*) == 4) { + 1716 : malloc_print(f, "You are currently using a 32 bits executable.\n"); + 1717 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); + 1718 : } + 1719 : } + 1720 : /* LCOV_EXCL_STOP */ + 1721 : + 1722 14819141 : void* malloc_nofail(size_t size) + 1723 : { + 1724 14819141 : void* ptr = malloc(size); + 1725 : + 1726 14819141 : if (!ptr) { + 1727 : /* LCOV_EXCL_START */ + 1728 : malloc_fail(size); + 1729 : exit(EXIT_FAILURE); + 1730 : /* LCOV_EXCL_STOP */ + 1731 : } + 1732 : + 1733 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ + 1734 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ + 1735 : /* and not only reserving the addressable space. */ + 1736 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ + 1737 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ + 1738 : /* get a real error from malloc() instead than a process killed. */ + 1739 : /* Note that calloc() doesn't have the same effect. */ + 1740 14819141 : memset(ptr, 0xA5, size); + 1741 : #endif + 1742 : + 1743 14819141 : malloc_counter_inc(size); + 1744 : + 1745 14819141 : return ptr; + 1746 : } 1747 : - 1748 : /* see the note in malloc_nofail() of why we don't use calloc() */ - 1749 156192 : ptr = malloc(size); - 1750 : - 1751 156192 : if (!ptr) { - 1752 : /* LCOV_EXCL_START */ - 1753 : malloc_fail(size); - 1754 : exit(EXIT_FAILURE); - 1755 : /* LCOV_EXCL_STOP */ - 1756 : } - 1757 : - 1758 156192 : memset(ptr, 0, size); - 1759 : - 1760 156192 : malloc_counter_inc(size); - 1761 : - 1762 156192 : return ptr; - 1763 : } - 1764 : - 1765 5965500 : char* strdup_nofail(const char* str) - 1766 : { - 1767 : size_t size; - 1768 : char* ptr; - 1769 : - 1770 5965500 : size = strlen(str) + 1; - 1771 : - 1772 5965500 : ptr = malloc(size); - 1773 : - 1774 5965500 : if (!ptr) { - 1775 : /* LCOV_EXCL_START */ - 1776 : malloc_fail(size); - 1777 : exit(EXIT_FAILURE); - 1778 : /* LCOV_EXCL_STOP */ - 1779 : } - 1780 : - 1781 5965500 : memcpy(ptr, str, size); - 1782 : - 1783 5965500 : malloc_counter_inc(size); - 1784 : - 1785 5965500 : return ptr; - 1786 : } - 1787 : - 1788 : /****************************************************************************/ - 1789 : /* smartctl */ + 1748 156271 : void* calloc_nofail(size_t count, size_t size) + 1749 : { + 1750 : void* ptr; + 1751 : + 1752 156271 : size *= count; + 1753 : + 1754 : /* see the note in malloc_nofail() of why we don't use calloc() */ + 1755 156271 : ptr = malloc(size); + 1756 : + 1757 156271 : if (!ptr) { + 1758 : /* LCOV_EXCL_START */ + 1759 : malloc_fail(size); + 1760 : exit(EXIT_FAILURE); + 1761 : /* LCOV_EXCL_STOP */ + 1762 : } + 1763 : + 1764 156271 : memset(ptr, 0, size); + 1765 : + 1766 156271 : malloc_counter_inc(size); + 1767 : + 1768 156271 : return ptr; + 1769 : } + 1770 : + 1771 5965600 : char* strdup_nofail(const char* str) + 1772 : { + 1773 : size_t size; + 1774 : char* ptr; + 1775 : + 1776 5965600 : size = strlen(str) + 1; + 1777 : + 1778 5965600 : ptr = malloc(size); + 1779 : + 1780 5965600 : if (!ptr) { + 1781 : /* LCOV_EXCL_START */ + 1782 : malloc_fail(size); + 1783 : exit(EXIT_FAILURE); + 1784 : /* LCOV_EXCL_STOP */ + 1785 : } + 1786 : + 1787 5965600 : memcpy(ptr, str, size); + 1788 : + 1789 5965600 : malloc_counter_inc(size); 1790 : - 1791 : /** - 1792 : * Match a string with the specified pattern. - 1793 : * Like sscanf() a space match any sequence of spaces. - 1794 : * Return 0 if it matches. - 1795 : */ - 1796 0 : static int smatch(const char* str, const char* pattern) - 1797 : { - 1798 0 : while (*pattern) { - 1799 0 : if (isspace(*pattern)) { - 1800 0 : ++pattern; - 1801 0 : while (isspace(*str)) - 1802 0 : ++str; - 1803 0 : } else if (*pattern == *str) { - 1804 0 : ++pattern; - 1805 0 : ++str; - 1806 : } else - 1807 0 : return -1; - 1808 : } - 1809 : - 1810 0 : return 0; - 1811 : } - 1812 : - 1813 : /* - 1814 : * scomma() - 1815 : * - 1816 : * Matches a literal prefix (the second argument), then parses the following - 1817 : * unsigned 64-bit integer, allowing comma thousand separators (U.S. style). - 1818 : * - 1819 : * Whitespace is flexible around the prefix and before the number. - 1820 : * Commas are ignored during number parsing but basic validation is applied. + 1791 5965600 : return ptr; + 1792 : } + 1793 : + 1794 : /****************************************************************************/ + 1795 : /* smartctl */ + 1796 : + 1797 : /** + 1798 : * Match a string with the specified pattern. + 1799 : * Like sscanf() a space match any sequence of spaces. + 1800 : * Return 0 if it matches. + 1801 : */ + 1802 1779 : static int smatch(const char* str, const char* pattern) + 1803 : { + 1804 2026 : while (*pattern) { + 1805 2015 : if (isspace(*pattern)) { + 1806 24 : ++pattern; + 1807 54 : while (isspace(*str)) + 1808 30 : ++str; + 1809 1991 : } else if (*pattern == *str) { + 1810 223 : ++pattern; + 1811 223 : ++str; + 1812 : } else + 1813 1768 : return -1; + 1814 : } + 1815 : + 1816 11 : return 0; + 1817 : } + 1818 : + 1819 : /* + 1820 : * scomma() 1821 : * - 1822 : * Returns: - 1823 : * 1 - successfully parsed a valid uint64_t - 1824 : * 0 - prefix mismatch, no digits found, invalid format or overflow - 1825 : */ - 1826 0 : int scomma(const char* str, const char* prefix, uint64_t* value) - 1827 : { - 1828 0 : const char* s = str; - 1829 0 : const char* f = prefix; - 1830 : - 1831 : /* match literal prefix, tolerating whitespace differences */ - 1832 0 : while (*f) { - 1833 : /* skip whitespace in both strings */ - 1834 0 : while (isspace((unsigned char)*f)) - 1835 0 : ++f; - 1836 0 : while (isspace((unsigned char)*s)) - 1837 0 : ++s; - 1838 : - 1839 0 : if (*f == 0) - 1840 0 : break; - 1841 0 : if (*s != *f) - 1842 0 : return 0; /* prefix mismatch */ - 1843 : - 1844 0 : ++s; - 1845 0 : ++f; - 1846 : } - 1847 : - 1848 : /* skip whitespace before the number starts */ - 1849 0 : while (isspace((unsigned char)*s)) - 1850 0 : ++s; - 1851 : - 1852 0 : uint64_t num = 0; - 1853 0 : int digits_seen = 0; - 1854 0 : int comma_seen = 0; - 1855 : - 1856 : /* parse digits, ignoring commas */ - 1857 0 : while (*s) { - 1858 0 : if (*s >= '0' && *s <= '9') { - 1859 0 : unsigned digit = (unsigned)(*s - '0'); - 1860 : - 1861 : /* check for uint64_t overflow before multiplying */ - 1862 0 : if (num > (UINT64_MAX - digit) / 10ULL) - 1863 0 : return 0; - 1864 : - 1865 0 : num = num * 10ULL + digit; - 1866 0 : ++digits_seen; - 1867 0 : comma_seen = 0; - 1868 0 : } else if (*s == ',') { - 1869 : /* disallow leading commas */ - 1870 0 : if (digits_seen == 0) - 1871 0 : return 0; - 1872 : - 1873 : /* if two consecutive commas, stop parsing */ - 1874 0 : if (comma_seen) - 1875 0 : break; - 1876 : - 1877 0 : comma_seen = 1; - 1878 : } else { - 1879 : /* any other character ends the number */ - 1880 0 : break; - 1881 : } + 1822 : * Matches a literal prefix (the second argument), then parses the following + 1823 : * unsigned 64-bit integer, allowing comma thousand separators (U.S. style). + 1824 : * + 1825 : * Whitespace is flexible around the prefix and before the number. + 1826 : * Commas are ignored during number parsing but basic validation is applied. + 1827 : * + 1828 : * Returns: + 1829 : * 1 - successfully parsed a valid uint64_t + 1830 : * 0 - prefix mismatch, no digits found, invalid format or overflow + 1831 : */ + 1832 2316 : int scomma(const char* str, const char* prefix, uint64_t* value) + 1833 : { + 1834 2316 : const char* s = str; + 1835 2316 : const char* f = prefix; + 1836 : + 1837 : /* match literal prefix, tolerating whitespace differences */ + 1838 2418 : while (*f) { + 1839 : /* skip whitespace in both strings */ + 1840 2424 : while (isspace((unsigned char)*f)) + 1841 6 : ++f; + 1842 2424 : while (isspace((unsigned char)*s)) + 1843 6 : ++s; + 1844 : + 1845 2418 : if (*f == 0) + 1846 0 : break; + 1847 2418 : if (*s != *f) + 1848 2316 : return 0; /* prefix mismatch */ + 1849 : + 1850 102 : ++s; + 1851 102 : ++f; + 1852 : } + 1853 : + 1854 : /* skip whitespace before the number starts */ + 1855 0 : while (isspace((unsigned char)*s)) + 1856 0 : ++s; + 1857 : + 1858 0 : uint64_t num = 0; + 1859 0 : int digits_seen = 0; + 1860 0 : int comma_seen = 0; + 1861 : + 1862 : /* parse digits, ignoring commas */ + 1863 0 : while (*s) { + 1864 0 : if (*s >= '0' && *s <= '9') { + 1865 0 : unsigned digit = (unsigned)(*s - '0'); + 1866 : + 1867 : /* check for uint64_t overflow before multiplying */ + 1868 0 : if (num > (UINT64_MAX - digit) / 10ULL) + 1869 0 : return 0; + 1870 : + 1871 0 : num = num * 10ULL + digit; + 1872 0 : ++digits_seen; + 1873 0 : comma_seen = 0; + 1874 0 : } else if (*s == ',') { + 1875 : /* disallow leading commas */ + 1876 0 : if (digits_seen == 0) + 1877 0 : return 0; + 1878 : + 1879 : /* if two consecutive commas, stop parsing */ + 1880 0 : if (comma_seen) + 1881 0 : break; 1882 : - 1883 0 : ++s; - 1884 : } - 1885 : - 1886 : /* require at least one digit */ - 1887 0 : if (digits_seen == 0) - 1888 0 : return 0; - 1889 : - 1890 0 : *value = num; - 1891 0 : return 1; - 1892 : } - 1893 : - 1894 0 : int smartctl_attribute(FILE* f, const char* file, const char* name, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* inter) - 1895 : { - 1896 : unsigned i; - 1897 : int inside; - 1898 : struct smart_attr dummy_smart[SMART_COUNT]; - 1899 : uint64_t dummy_info[INFO_COUNT]; - 1900 : char dummy_serial[SMART_MAX]; - 1901 : char dummy_family[SMART_MAX]; - 1902 : char dummy_model[SMART_MAX]; - 1903 : char dummy_interface[SMART_MAX]; - 1904 : - 1905 : /* dummy attributes */ - 1906 0 : if (!smart) - 1907 0 : smart = dummy_smart; - 1908 0 : if (!info) - 1909 0 : info = dummy_info; - 1910 0 : if (!serial) - 1911 0 : serial = dummy_serial; - 1912 0 : if (!family) - 1913 0 : family = dummy_family; - 1914 0 : if (!model) - 1915 0 : model = dummy_model; - 1916 0 : if (!inter) - 1917 0 : inter = dummy_interface; - 1918 : - 1919 : /* preclear attributes */ - 1920 0 : *serial = 0; - 1921 0 : *family = 0; - 1922 0 : *model = 0; - 1923 0 : *inter = 0; - 1924 0 : memset(smart, 0, sizeof(struct smart_attr) * SMART_COUNT); - 1925 0 : for (i = 0; i < SMART_COUNT; ++i) - 1926 0 : smart[i].raw = SMART_UNASSIGNED; - 1927 0 : for (i = 0; i < INFO_COUNT; ++i) - 1928 0 : info[i] = SMART_UNASSIGNED; - 1929 : - 1930 : /* read the file */ - 1931 0 : inside = 0; - 1932 0 : while (1) { - 1933 : char buf[256]; - 1934 : unsigned id; - 1935 : uint64_t raw; - 1936 : uint64_t norm; - 1937 : uint64_t worst; - 1938 : uint64_t thresh; - 1939 : char* s; - 1940 : - 1941 0 : s = fgets(buf, sizeof(buf), f); - 1942 0 : if (s == 0) - 1943 0 : break; - 1944 : - 1945 : /* remove extraneous chars */ - 1946 0 : s = strpolish(buf); - 1947 : - 1948 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); - 1949 : - 1950 : /* skip initial spaces */ - 1951 0 : while (isspace(*s)) - 1952 0 : ++s; + 1883 0 : comma_seen = 1; + 1884 : } else { + 1885 : /* any other character ends the number */ + 1886 0 : break; + 1887 : } + 1888 : + 1889 0 : ++s; + 1890 : } + 1891 : + 1892 : /* require at least one digit */ + 1893 0 : if (digits_seen == 0) + 1894 0 : return 0; + 1895 : + 1896 0 : *value = num; + 1897 0 : return 1; + 1898 : } + 1899 : + 1900 14 : int smartctl_attribute(FILE* f, const char* file, const char* name, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* inter) + 1901 : { + 1902 : unsigned i; + 1903 : int inside; + 1904 : struct smart_attr dummy_smart[SMART_COUNT]; + 1905 : uint64_t dummy_info[INFO_COUNT]; + 1906 : char dummy_serial[SMART_MAX]; + 1907 : char dummy_family[SMART_MAX]; + 1908 : char dummy_model[SMART_MAX]; + 1909 : char dummy_interface[SMART_MAX]; + 1910 : + 1911 : /* dummy attributes */ + 1912 14 : if (!smart) + 1913 0 : smart = dummy_smart; + 1914 14 : if (!info) + 1915 0 : info = dummy_info; + 1916 14 : if (!serial) + 1917 0 : serial = dummy_serial; + 1918 14 : if (!family) + 1919 0 : family = dummy_family; + 1920 14 : if (!model) + 1921 0 : model = dummy_model; + 1922 14 : if (!inter) + 1923 0 : inter = dummy_interface; + 1924 : + 1925 : /* preclear attributes */ + 1926 14 : *serial = 0; + 1927 14 : *family = 0; + 1928 14 : *model = 0; + 1929 14 : *inter = 0; + 1930 14 : memset(smart, 0, sizeof(struct smart_attr) * SMART_COUNT); + 1931 3654 : for (i = 0; i < SMART_COUNT; ++i) + 1932 3640 : smart[i].raw = SMART_UNASSIGNED; + 1933 42 : for (i = 0; i < INFO_COUNT; ++i) + 1934 28 : info[i] = SMART_UNASSIGNED; + 1935 : + 1936 : /* read the file */ + 1937 14 : inside = 0; + 1938 235 : while (1) { + 1939 : char buf[256]; + 1940 : unsigned id; + 1941 : uint64_t raw; + 1942 : uint64_t norm; + 1943 : uint64_t worst; + 1944 : uint64_t thresh; + 1945 : char* s; + 1946 : + 1947 249 : s = fgets(buf, sizeof(buf), f); + 1948 249 : if (s == 0) + 1949 14 : break; + 1950 : + 1951 : /* remove extraneous chars */ + 1952 235 : s = strpolish(buf); 1953 : - 1954 0 : if (*s == 0) { - 1955 0 : inside = 0; - 1956 : /* common */ - 1957 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { - 1958 0 : info[INFO_ROTATION_RATE] = 0; - 1959 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &info[INFO_ROTATION_RATE]) == 1) { - 1960 0 : } else if (smatch(s, "User Capacity:") == 0) { - 1961 0 : char* begin = strchr(s, ':'); - 1962 0 : char* end = strstr(s, "bytes"); - 1963 0 : if (begin != 0 && end != 0 && begin < end) { - 1964 : char* p; - 1965 0 : info[INFO_SIZE] = 0; - 1966 0 : for (p = begin; p != end; ++p) { - 1967 0 : if (isdigit(*p)) { - 1968 0 : info[INFO_SIZE] *= 10; - 1969 0 : info[INFO_SIZE] += *p - '0'; - 1970 : } - 1971 : } - 1972 : } - 1973 0 : } else if (sscanf(s, "Model Family: %63[^\n]", family) == 1) { - 1974 0 : strtrim(family); - 1975 0 : } else if (sscanf(s, "Device Model: %63[^\n]", model) == 1) { - 1976 0 : strtrim(model); - 1977 0 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { - 1978 0 : strtrim(serial); - 1979 : /* SCSI */ - 1980 : /* - 1981 : Vendor: WD - 1982 : Product: WD4001FYYG-01SL3 - 1983 : Revision: VR08 - 1984 : Compliance: SPC-4 - 1985 : User Capacity: 4,000,787,030,016 bytes [4.00 TB] - 1986 : Logical block size: 512 bytes - 1987 : Rotation Rate: 7200 rpm - 1988 : Form Factor: 3.5 inches - 1989 : Logical Unit id: 0x50000c0f01f55dd0 - 1990 : Serial number: WMC1F0D41KD5 - 1991 : Device type: disk - 1992 : Transport protocol: SAS (SPL-3) - 1993 : Local Time is: Fri Jan 28 14:14:51 2022 CET - 1994 : SMART support is: Available - device has SMART capability. - 1995 : SMART support is: Enabled - 1996 : Temperature Warning: Enabled - 1997 : - 1998 : Current Drive Temperature: 38 C - 1999 : Drive Trip Temperature: 65 C - 2000 : - 2001 : Manufactured in week 25 of year 2012 - 2002 : Specified cycle count over device lifetime: 10000 - 2003 : Accumulated start-stop cycles: 103 - 2004 : Specified load-unload count over device lifetime: 300000 - 2005 : Accumulated load-unload cycles: 103 - 2006 : Elements in grown defect list: 5 - 2007 : - 2008 : Vendor (Seagate) cache information - 2009 : Blocks sent to initiator = 569127595 - 2010 : Blocks received from initiator = 2633690060 - 2011 : Blocks read from cache and sent to initiator = 1881027254 - 2012 : Number of read and write commands whose size <= segment size = 181284019 - 2013 : Number of read and write commands whose size > segment size = 0 - 2014 : - 2015 : Vendor (Seagate/Hitachi) factory information - 2016 : number of hours powered up = 25024.80 - 2017 : number of minutes until next internal SMART test = 42 - 2018 : - 2019 : */ - 2020 0 : } else if (sscanf(s, "Transport protocol: %63[^\n]", inter) == 1) { - 2021 0 : if (strcmp(inter, "Fibre channel (FCP-4)") == 0) - 2022 0 : strcpy(inter, "Fibre"); - 2023 0 : else if (strcmp(inter, "SSA") == 0) - 2024 0 : strcpy(inter, "SSA"); - 2025 0 : else if (strcmp(inter, "IEEE 1394 (SBP-3)") == 0) - 2026 0 : strcpy(inter, "FireWire"); - 2027 0 : else if (strcmp(inter, "RDMA (SRP)") == 0) - 2028 0 : strcpy(inter, "SCSI"); - 2029 0 : else if (strcmp(inter, "iSCSI") == 0) - 2030 0 : strcpy(inter, "iSCSI"); - 2031 0 : else if (strcmp(inter, "SAS (SPL-4)") == 0) - 2032 0 : strcpy(inter, "SAS"); - 2033 0 : else if (strcmp(inter, "ADT") == 0) + 1954 235 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 1955 : + 1956 : /* skip initial spaces */ + 1957 504 : while (isspace(*s)) + 1958 269 : ++s; + 1959 : + 1960 235 : if (*s == 0) { + 1961 28 : inside = 0; + 1962 : /* common */ + 1963 207 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { + 1964 1 : info[INFO_ROTATION_RATE] = 0; + 1965 206 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &info[INFO_ROTATION_RATE]) == 1) { + 1966 205 : } else if (smatch(s, "User Capacity:") == 0) { + 1967 2 : char* begin = strchr(s, ':'); + 1968 2 : char* end = strstr(s, "bytes"); + 1969 2 : if (begin != 0 && end != 0 && begin < end) { + 1970 : char* p; + 1971 2 : info[INFO_SIZE] = 0; + 1972 46 : for (p = begin; p != end; ++p) { + 1973 44 : if (isdigit(*p)) { + 1974 25 : info[INFO_SIZE] *= 10; + 1975 25 : info[INFO_SIZE] += *p - '0'; + 1976 : } + 1977 : } + 1978 : } + 1979 203 : } else if (sscanf(s, "Model Family: %63[^\n]", family) == 1) { + 1980 2 : strtrim(family); + 1981 201 : } else if (sscanf(s, "Device Model: %63[^\n]", model) == 1) { + 1982 2 : strtrim(model); + 1983 199 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { + 1984 0 : strtrim(serial); + 1985 : /* SCSI */ + 1986 : /* + 1987 : Vendor: WD + 1988 : Product: WD4001FYYG-01SL3 + 1989 : Revision: VR08 + 1990 : Compliance: SPC-4 + 1991 : User Capacity: 4,000,787,030,016 bytes [4.00 TB] + 1992 : Logical block size: 512 bytes + 1993 : Rotation Rate: 7200 rpm + 1994 : Form Factor: 3.5 inches + 1995 : Logical Unit id: 0x50000c0f01f55dd0 + 1996 : Serial number: WMC1F0D41KD5 + 1997 : Device type: disk + 1998 : Transport protocol: SAS (SPL-3) + 1999 : Local Time is: Fri Jan 28 14:14:51 2022 CET + 2000 : SMART support is: Available - device has SMART capability. + 2001 : SMART support is: Enabled + 2002 : Temperature Warning: Enabled + 2003 : + 2004 : Current Drive Temperature: 38 C + 2005 : Drive Trip Temperature: 65 C + 2006 : + 2007 : Manufactured in week 25 of year 2012 + 2008 : Specified cycle count over device lifetime: 10000 + 2009 : Accumulated start-stop cycles: 103 + 2010 : Specified load-unload count over device lifetime: 300000 + 2011 : Accumulated load-unload cycles: 103 + 2012 : Elements in grown defect list: 5 + 2013 : + 2014 : Vendor (Seagate) cache information + 2015 : Blocks sent to initiator = 569127595 + 2016 : Blocks received from initiator = 2633690060 + 2017 : Blocks read from cache and sent to initiator = 1881027254 + 2018 : Number of read and write commands whose size <= segment size = 181284019 + 2019 : Number of read and write commands whose size > segment size = 0 + 2020 : + 2021 : Vendor (Seagate/Hitachi) factory information + 2022 : number of hours powered up = 25024.80 + 2023 : number of minutes until next internal SMART test = 42 + 2024 : + 2025 : */ + 2026 199 : } else if (sscanf(s, "Transport protocol: %63[^\n]", inter) == 1) { + 2027 0 : if (strcmp(inter, "Fibre channel (FCP-4)") == 0) + 2028 0 : strcpy(inter, "Fibre"); + 2029 0 : else if (strcmp(inter, "SSA") == 0) + 2030 0 : strcpy(inter, "SSA"); + 2031 0 : else if (strcmp(inter, "IEEE 1394 (SBP-3)") == 0) + 2032 0 : strcpy(inter, "FireWire"); + 2033 0 : else if (strcmp(inter, "RDMA (SRP)") == 0) 2034 0 : strcpy(inter, "SCSI"); - 2035 0 : else if (strcmp(inter, "ATA (ACS-2)") == 0) - 2036 0 : strcpy(inter, "SATA"); - 2037 0 : else if (strcmp(inter, "UAS") == 0) - 2038 0 : strcpy(inter, "USB"); - 2039 0 : else if (strcmp(inter, "SOP") == 0) - 2040 0 : strcpy(inter, "NVMe"); - 2041 0 : else if (strcmp(inter, "PCIe") == 0) - 2042 0 : strcpy(inter, "PCIe"); - 2043 : else - 2044 0 : strcpy(inter, "SCSI"); - 2045 : /* map generic attributes to SMART attr */ - 2046 0 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT].raw) == 1) { - 2047 0 : pathcpy(smart[SMART_REALLOCATED_SECTOR_COUNT].name, sizeof(smart[SMART_REALLOCATED_SECTOR_COUNT].name), "Elements_In_Grown_Defect_List"); - 2048 0 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS].raw) == 1) { - 2049 0 : pathcpy(smart[SMART_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_TEMPERATURE_CELSIUS].name), "Current_Drive_Temperature"); - 2050 0 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw) == 1) { - 2051 0 : pathcpy(smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].name), "Drive_Trip_Temperature"); - 2052 0 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT].raw) == 1) { - 2053 0 : pathcpy(smart[SMART_START_STOP_COUNT].name, sizeof(smart[SMART_START_STOP_COUNT].name), "Accumulated_Start-Stop_Cycles"); - 2054 0 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT].raw) == 1) { - 2055 0 : pathcpy(smart[SMART_LOAD_CYCLE_COUNT].name, sizeof(smart[SMART_LOAD_CYCLE_COUNT].name), "Accumulated_Load-Unload_Cycles"); - 2056 0 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS].raw) == 1) { /* note "n" of "number" lower case */ - 2057 0 : pathcpy(smart[SMART_POWER_ON_HOURS].name, sizeof(smart[SMART_POWER_ON_HOURS].name), "Number_Of_Hours_Powered_Up"); - 2058 : /* special entries */ - 2059 0 : } else if (sscanf(s, "Non-medium error count: %" SCNu64, &raw) == 1) { - 2060 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; - 2061 : /* ATA */ - 2062 : /* - 2063 : ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE - 2064 : 1 Raw_Read_Error_Rate 0x002f 200 200 051 Pre-fail Always - 0 - 2065 : 3 Spin_Up_Time 0x0027 172 169 021 Pre-fail Always - 8383 - 2066 : 4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 24 - 2067 : 5 Reallocated_Sector_Ct 0x0033 200 200 140 Pre-fail Always - 0 - 2068 : 7 Seek_Error_Rate 0x002e 200 200 000 Old_age Always - 0 - 2069 : 9 Power_On_Hours 0x0032 083 083 000 Old_age Always - 12471 - 2070 : 10 Spin_Retry_Count 0x0032 100 253 000 Old_age Always - 0 - 2071 : 11 Calibration_Retry_Count 0x0032 100 253 000 Old_age Always - 0 - 2072 : 12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 24 - 2073 : 192 Power-Off_Retract_Count 0x0032 200 200 000 Old_age Always - 9 - 2074 : 193 Load_Cycle_Count 0x0032 157 157 000 Old_age Always - 131565 - 2075 : 194 Temperature_Celsius 0x0022 127 119 000 Old_age Always - 25 - 2076 : 196 Reallocated_Event_Count 0x0032 200 200 000 Old_age Always - 0 - 2077 : 197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 0 - 2078 : 198 Offline_Uncorrectable 0x0030 100 253 000 Old_age Offline - 0 - 2079 : 199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age Always - 0 - 2080 : 200 Multi_Zone_Error_Rate 0x0008 200 200 000 Old_age Offline - 0 - 2081 : */ - 2082 0 : } else if (smatch(s, "ATA Version is:") == 0) { - 2083 0 : strcpy(inter, "ATA"); - 2084 0 : } else if (smatch(s, "SATA Version is:") == 0) { - 2085 0 : strcpy(inter, "SATA"); - 2086 0 : } else if (smatch(s, "Transport Type: PCIe") == 0) { - 2087 0 : strcpy(inter, "PCIe"); - 2088 0 : } else if (smatch(s, "Transport Type: Parallel") == 0) { - 2089 0 : strcpy(inter, "PATA"); - 2090 : /* special entries */ - 2091 0 : } else if (smatch(s, "No Errors Logged") == 0) { - 2092 0 : smart[SMART_ERROR_PROTOCOL].raw = 0; - 2093 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - 2094 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; - 2095 : /* NVME */ - 2096 : /* - 2097 : Critical Warning: 0x00 - 2098 : Temperature: 55 Celsius - 2099 : Available Spare: 100% - 2100 : Available Spare Threshold: 10% - 2101 : Percentage Used: 8% - 2102 : Data Units Read: 213,006,510 [109 TB] - 2103 : Data Units Written: 549,370,112 [281 TB] - 2104 : Host Read Commands: 11,210,192,197 - 2105 : Host Write Commands: 20,687,602,229 - 2106 : Controller Busy Time: 14,055 - 2107 : Power Cycles: 39 - 2108 : Power On Hours: 4,204 - 2109 : Unsafe Shutdowns: 9 - 2110 : Media and Data Integrity Errors: 0 - 2111 : Error Information Log Entries: 1,479,242 - 2112 : Warning Comp. Temperature Time: 0 - 2113 : Critical Comp. Temperature Time: 0 - 2114 : Temperature Sensor 2: 75 Celsius - 2115 : Thermal Temp. 1 Total Time: 58745 - 2116 : */ - 2117 0 : } else if (smatch(s, "NVMe Version:") == 0) { - 2118 0 : strcpy(inter, "NVMe"); - 2119 : /* special entries */ - 2120 0 : } else if (scomma(s, "Media and Data Integrity Errors:", &raw) == 1) { - 2121 0 : smart[SMART_ERROR_MEDIUM].raw = raw; - 2122 0 : } else if (scomma(s, "Error Information Log Entries:", &raw) == 1) { - 2123 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; - 2124 0 : } else if (sscanf(s, "Percentage Used: %" SCNu64 "%%", &raw) == 1) { - 2125 0 : smart[SMART_WEAR_LEVEL].raw = raw; /* take care that it can be greather than 100%, meaning that it's used over the expected lifetime */ - 2126 : /* map generic attributes to SMART attr */ - 2127 0 : } else if (sscanf(s, "Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS].raw) == 1) { - 2128 0 : pathcpy(smart[SMART_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_TEMPERATURE_CELSIUS].name), "Temperature"); - 2129 0 : } else if (scomma(s, "Power On Hours:", &smart[SMART_POWER_ON_HOURS].raw) == 1) { - 2130 0 : pathcpy(smart[SMART_POWER_ON_HOURS].name, sizeof(smart[SMART_POWER_ON_HOURS].name), "Power_On_Hours"); - 2131 0 : } else if (scomma(s, "Power Cycles:", &smart[SMART_POWER_CYCLE_COUNT].raw) == 1) { - 2132 0 : pathcpy(smart[SMART_POWER_CYCLE_COUNT].name, sizeof(smart[SMART_POWER_CYCLE_COUNT].name), "Power_Cycles"); - 2133 : /* map specific attributes to UNUSED SMART attr */ - 2134 0 : } else if (sscanf(s, "Critical Warning: %" SCNx64, &smart[SMART_NVME_CRITICAL_WARNING].raw) == 1) { - 2135 0 : pathcpy(smart[SMART_NVME_CRITICAL_WARNING].name, sizeof(smart[SMART_NVME_CRITICAL_WARNING].name), "Critical_Warning"); - 2136 0 : } else if (sscanf(s, "Available Spare: %" SCNu64 "%%", &smart[SMART_NVME_AVAILABLE_SPARE].raw) == 1) { - 2137 0 : pathcpy(smart[SMART_NVME_AVAILABLE_SPARE].name, sizeof(smart[SMART_NVME_AVAILABLE_SPARE].name), "Available_Spare"); - 2138 0 : } else if (scomma(s, "Data Units Read:", &smart[SMART_NVME_DATA_UNITS_READ].raw) == 1) { - 2139 0 : pathcpy(smart[SMART_NVME_DATA_UNITS_READ].name, sizeof(smart[SMART_NVME_DATA_UNITS_READ].name), "Data_Units_Read"); - 2140 0 : } else if (scomma(s, "Data Units Written:", &smart[SMART_NVME_DATA_UNITS_WRITTEN].raw) == 1) { - 2141 0 : pathcpy(smart[SMART_NVME_DATA_UNITS_WRITTEN].name, sizeof(smart[SMART_NVME_DATA_UNITS_WRITTEN].name), "Data_Units_Written"); - 2142 0 : } else if (scomma(s, "Host Read Commands:", &smart[SMART_NVME_HOST_READ_COMMANDS].raw) == 1) { - 2143 0 : pathcpy(smart[SMART_NVME_HOST_READ_COMMANDS].name, sizeof(smart[SMART_NVME_HOST_READ_COMMANDS].name), "Host_Read_Commands"); - 2144 0 : } else if (scomma(s, "Host Write Commands:", &smart[SMART_NVME_HOST_WRITE_COMMANDS].raw) == 1) { - 2145 0 : pathcpy(smart[SMART_NVME_HOST_WRITE_COMMANDS].name, sizeof(smart[SMART_NVME_HOST_WRITE_COMMANDS].name), "Host_Write_Commands"); - 2146 0 : } else if (scomma(s, "Controller Busy Time:", &smart[SMART_NVME_CONTROLLER_BUSY_TIME].raw) == 1) { - 2147 0 : pathcpy(smart[SMART_NVME_CONTROLLER_BUSY_TIME].name, sizeof(smart[SMART_NVME_CONTROLLER_BUSY_TIME].name), "Controller_Busy_Time"); - 2148 0 : } else if (scomma(s, "Unsafe Shutdowns:", &smart[SMART_NVME_UNSAFE_SHUTDOWNS].raw) == 1) { - 2149 0 : pathcpy(smart[SMART_NVME_UNSAFE_SHUTDOWNS].name, sizeof(smart[SMART_NVME_UNSAFE_SHUTDOWNS].name), "Unsafe_Shutdowns"); - 2150 : /* smartctl doesn't print this with command, but %d */ - 2151 0 : } else if (scomma(s, "Warning Comp. Temperature Time:", &smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].raw) == 1) { - 2152 0 : pathcpy(smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].name, sizeof(smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].name), "Warning_Comp_Temperature_Time"); - 2153 : /* smartctl doesn't print this with command, but %d */ - 2154 0 : } else if (scomma(s, "Critical Comp. Temperature Time:", &smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].raw) == 1) { - 2155 0 : pathcpy(smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].name, sizeof(smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].name), "Critical_Comp_Temperature_Time"); - 2156 : /* ATA Attributes table */ - 2157 0 : } else if (smatch(s, "ID#") == 0) { - 2158 0 : inside = 1; - 2159 0 : } else if (inside) { - 2160 0 : char id_name[128] = { 0 }; - 2161 0 : char type[64] = { 0 }; - 2162 0 : char updated[64] = { 0 }; - 2163 0 : char when_failed[64] = { 0 }; - 2164 : uint64_t min, max; - 2165 : int minmax; - 2166 : int flags; - 2167 : - 2168 0 : if (sscanf(s, "%u %127s %*s %" SCNu64 " %" SCNu64 " %" SCNu64 " %63s %63s %63s %" SCNu64 " (Min/Max %" SCNu64 "/%" SCNu64 ")", &id, id_name, &norm, &worst, &thresh, type, updated, when_failed, &raw, &min, &max) == 11) { - 2169 0 : minmax = 1; - 2170 0 : } else if (sscanf(s, "%u %127s %*s %" SCNu64 " %" SCNu64 " %" SCNu64 " %63s %63s %63s %" SCNu64, &id, id_name, &norm, &worst, &thresh, type, updated, when_failed, &raw) == 9) { - 2171 0 : minmax = 0; - 2172 : } else { - 2173 0 : log_fatal(EEXTERNAL, "Invalid smartctl line '%s'.\n", s); - 2174 0 : return -1; - 2175 : } - 2176 : - 2177 0 : if (id >= 256) { - 2178 : /* LCOV_EXCL_START */ - 2179 : log_fatal(EEXTERNAL, "Invalid SMART id '%u'.\n", id); - 2180 : return -1; - 2181 : /* LCOV_EXCL_STOP */ - 2182 : } - 2183 : - 2184 0 : flags = 0; - 2185 0 : if (strcmp(type, "Pre-fail") == 0) - 2186 0 : flags |= SMART_ATTR_TYPE_PREFAIL; - 2187 0 : else if (strcmp(type, "Old_age") == 0) - 2188 0 : flags |= SMART_ATTR_TYPE_OLDAGE; - 2189 0 : if (strcmp(updated, "Always") == 0) - 2190 0 : flags |= SMART_ATTR_UPDATE_ALWAYS; - 2191 0 : else if (strcmp(updated, "Offline") == 0) - 2192 0 : flags |= SMART_ATTR_UPDATE_OFFLINE; - 2193 0 : if (strcmp(when_failed, "FAILING_NOW") == 0) - 2194 0 : flags |= SMART_ATTR_WHEN_FAILED_NOW; - 2195 0 : else if (strcmp(when_failed, "In_the_past") == 0) - 2196 0 : flags |= SMART_ATTR_WHEN_FAILED_PAST; - 2197 0 : else if (strcmp(when_failed, "-") == 0) - 2198 0 : flags |= SMART_ATTR_WHEN_FAILED_NEVER; - 2199 : - 2200 : /* revert the min/max decoding done by smartctl */ - 2201 0 : if (minmax - 2202 0 : && raw <= 0xFFFFUL - 2203 0 : && min <= 0xFFFFUL - 2204 0 : && max <= 0xFFFFUL) { - 2205 0 : raw |= min << 16; - 2206 0 : raw |= max << 32; - 2207 : } - 2208 : - 2209 0 : smart[id].raw = raw; - 2210 0 : smart[id].norm = norm; - 2211 0 : smart[id].worst = worst; - 2212 0 : smart[id].thresh = thresh; - 2213 0 : smart[id].flags = flags; - 2214 0 : pathcpy(smart[id].name, sizeof(smart[id].name), id_name); - 2215 : - 2216 : /* - 2217 : * Map normalized health percentage to our unified wear level for SSDs - 2218 : * 177: Wear_Leveling_Count (Samsung/Crucial) - 2219 : * 231: SSD_Life_Left (Kingston/WD) - 2220 : * 233: Media_Wearout_Indicator (Intel) - 2221 : */ - 2222 0 : if (norm <= 100) { - 2223 0 : switch (id) { - 2224 0 : case 177 : - 2225 : case 233 : - 2226 : case 231 : - 2227 0 : smart[SMART_WEAR_LEVEL].raw = 100 - norm; - 2228 0 : break; - 2229 : } - 2230 : } - 2231 : } - 2232 : } - 2233 : - 2234 0 : return 0; - 2235 : } - 2236 : - 2237 25 : int smartctl_flush(FILE* f, const char* file, const char* name) - 2238 : { - 2239 : /* read the file */ - 2240 20 : while (1) { - 2241 : char buf[256]; - 2242 : char* s; - 2243 : - 2244 25 : s = fgets(buf, sizeof(buf), f); - 2245 25 : if (s == 0) - 2246 5 : break; - 2247 : - 2248 : /* remove extraneous chars */ - 2249 20 : s = strpolish(buf); - 2250 : - 2251 20 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); - 2252 : } + 2035 0 : else if (strcmp(inter, "iSCSI") == 0) + 2036 0 : strcpy(inter, "iSCSI"); + 2037 0 : else if (strcmp(inter, "SAS (SPL-4)") == 0) + 2038 0 : strcpy(inter, "SAS"); + 2039 0 : else if (strcmp(inter, "ADT") == 0) + 2040 0 : strcpy(inter, "SCSI"); + 2041 0 : else if (strcmp(inter, "ATA (ACS-2)") == 0) + 2042 0 : strcpy(inter, "SATA"); + 2043 0 : else if (strcmp(inter, "UAS") == 0) + 2044 0 : strcpy(inter, "USB"); + 2045 0 : else if (strcmp(inter, "SOP") == 0) + 2046 0 : strcpy(inter, "NVMe"); + 2047 0 : else if (strcmp(inter, "PCIe") == 0) + 2048 0 : strcpy(inter, "PCIe"); + 2049 : else + 2050 0 : strcpy(inter, "SCSI"); + 2051 : /* map generic attributes to SMART attr */ + 2052 199 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT].raw) == 1) { + 2053 0 : pathcpy(smart[SMART_REALLOCATED_SECTOR_COUNT].name, sizeof(smart[SMART_REALLOCATED_SECTOR_COUNT].name), "Elements_In_Grown_Defect_List"); + 2054 199 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS].raw) == 1) { + 2055 0 : pathcpy(smart[SMART_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_TEMPERATURE_CELSIUS].name), "Current_Drive_Temperature"); + 2056 199 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw) == 1) { + 2057 0 : pathcpy(smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].name), "Drive_Trip_Temperature"); + 2058 199 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT].raw) == 1) { + 2059 0 : pathcpy(smart[SMART_START_STOP_COUNT].name, sizeof(smart[SMART_START_STOP_COUNT].name), "Accumulated_Start-Stop_Cycles"); + 2060 199 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT].raw) == 1) { + 2061 0 : pathcpy(smart[SMART_LOAD_CYCLE_COUNT].name, sizeof(smart[SMART_LOAD_CYCLE_COUNT].name), "Accumulated_Load-Unload_Cycles"); + 2062 199 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS].raw) == 1) { /* note "n" of "number" lower case */ + 2063 0 : pathcpy(smart[SMART_POWER_ON_HOURS].name, sizeof(smart[SMART_POWER_ON_HOURS].name), "Number_Of_Hours_Powered_Up"); + 2064 : /* special entries */ + 2065 199 : } else if (sscanf(s, "Non-medium error count: %" SCNu64, &raw) == 1) { + 2066 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; + 2067 : /* ATA */ + 2068 : /* + 2069 : ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE + 2070 : 1 Raw_Read_Error_Rate 0x002f 200 200 051 Pre-fail Always - 0 + 2071 : 3 Spin_Up_Time 0x0027 172 169 021 Pre-fail Always - 8383 + 2072 : 4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 24 + 2073 : 5 Reallocated_Sector_Ct 0x0033 200 200 140 Pre-fail Always - 0 + 2074 : 7 Seek_Error_Rate 0x002e 200 200 000 Old_age Always - 0 + 2075 : 9 Power_On_Hours 0x0032 083 083 000 Old_age Always - 12471 + 2076 : 10 Spin_Retry_Count 0x0032 100 253 000 Old_age Always - 0 + 2077 : 11 Calibration_Retry_Count 0x0032 100 253 000 Old_age Always - 0 + 2078 : 12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 24 + 2079 : 192 Power-Off_Retract_Count 0x0032 200 200 000 Old_age Always - 9 + 2080 : 193 Load_Cycle_Count 0x0032 157 157 000 Old_age Always - 131565 + 2081 : 194 Temperature_Celsius 0x0022 127 119 000 Old_age Always - 25 + 2082 : 196 Reallocated_Event_Count 0x0032 200 200 000 Old_age Always - 0 + 2083 : 197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 0 + 2084 : 198 Offline_Uncorrectable 0x0030 100 253 000 Old_age Offline - 0 + 2085 : 199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age Always - 0 + 2086 : 200 Multi_Zone_Error_Rate 0x0008 200 200 000 Old_age Offline - 0 + 2087 : */ + 2088 199 : } else if (smatch(s, "ATA Version is:") == 0) { + 2089 2 : strcpy(inter, "ATA"); + 2090 197 : } else if (smatch(s, "SATA Version is:") == 0) { + 2091 2 : strcpy(inter, "SATA"); + 2092 195 : } else if (smatch(s, "Transport Type: PCIe") == 0) { + 2093 0 : strcpy(inter, "PCIe"); + 2094 195 : } else if (smatch(s, "Transport Type: Parallel") == 0) { + 2095 0 : strcpy(inter, "PATA"); + 2096 : /* special entries */ + 2097 195 : } else if (smatch(s, "No Errors Logged") == 0) { + 2098 2 : smart[SMART_ERROR_PROTOCOL].raw = 0; + 2099 193 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { + 2100 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; + 2101 : /* NVME */ + 2102 : /* + 2103 : Critical Warning: 0x00 + 2104 : Temperature: 55 Celsius + 2105 : Available Spare: 100% + 2106 : Available Spare Threshold: 10% + 2107 : Percentage Used: 8% + 2108 : Data Units Read: 213,006,510 [109 TB] + 2109 : Data Units Written: 549,370,112 [281 TB] + 2110 : Host Read Commands: 11,210,192,197 + 2111 : Host Write Commands: 20,687,602,229 + 2112 : Controller Busy Time: 14,055 + 2113 : Power Cycles: 39 + 2114 : Power On Hours: 4,204 + 2115 : Unsafe Shutdowns: 9 + 2116 : Media and Data Integrity Errors: 0 + 2117 : Error Information Log Entries: 1,479,242 + 2118 : Warning Comp. Temperature Time: 0 + 2119 : Critical Comp. Temperature Time: 0 + 2120 : Temperature Sensor 2: 75 Celsius + 2121 : Thermal Temp. 1 Total Time: 58745 + 2122 : */ + 2123 193 : } else if (smatch(s, "NVMe Version:") == 0) { + 2124 0 : strcpy(inter, "NVMe"); + 2125 : /* special entries */ + 2126 193 : } else if (scomma(s, "Media and Data Integrity Errors:", &raw) == 1) { + 2127 0 : smart[SMART_ERROR_MEDIUM].raw = raw; + 2128 193 : } else if (scomma(s, "Error Information Log Entries:", &raw) == 1) { + 2129 0 : smart[SMART_ERROR_PROTOCOL].raw = raw; + 2130 193 : } else if (sscanf(s, "Percentage Used: %" SCNu64 "%%", &raw) == 1) { + 2131 0 : smart[SMART_WEAR_LEVEL].raw = raw; /* take care that it can be greather than 100%, meaning that it's used over the expected lifetime */ + 2132 : /* map generic attributes to SMART attr */ + 2133 193 : } else if (sscanf(s, "Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS].raw) == 1) { + 2134 0 : pathcpy(smart[SMART_TEMPERATURE_CELSIUS].name, sizeof(smart[SMART_TEMPERATURE_CELSIUS].name), "Temperature"); + 2135 193 : } else if (scomma(s, "Power On Hours:", &smart[SMART_POWER_ON_HOURS].raw) == 1) { + 2136 0 : pathcpy(smart[SMART_POWER_ON_HOURS].name, sizeof(smart[SMART_POWER_ON_HOURS].name), "Power_On_Hours"); + 2137 193 : } else if (scomma(s, "Power Cycles:", &smart[SMART_POWER_CYCLE_COUNT].raw) == 1) { + 2138 0 : pathcpy(smart[SMART_POWER_CYCLE_COUNT].name, sizeof(smart[SMART_POWER_CYCLE_COUNT].name), "Power_Cycles"); + 2139 : /* map specific attributes to UNUSED SMART attr */ + 2140 193 : } else if (sscanf(s, "Critical Warning: %" SCNx64, &smart[SMART_NVME_CRITICAL_WARNING].raw) == 1) { + 2141 0 : pathcpy(smart[SMART_NVME_CRITICAL_WARNING].name, sizeof(smart[SMART_NVME_CRITICAL_WARNING].name), "Critical_Warning"); + 2142 193 : } else if (sscanf(s, "Available Spare: %" SCNu64 "%%", &smart[SMART_NVME_AVAILABLE_SPARE].raw) == 1) { + 2143 0 : pathcpy(smart[SMART_NVME_AVAILABLE_SPARE].name, sizeof(smart[SMART_NVME_AVAILABLE_SPARE].name), "Available_Spare"); + 2144 193 : } else if (scomma(s, "Data Units Read:", &smart[SMART_NVME_DATA_UNITS_READ].raw) == 1) { + 2145 0 : pathcpy(smart[SMART_NVME_DATA_UNITS_READ].name, sizeof(smart[SMART_NVME_DATA_UNITS_READ].name), "Data_Units_Read"); + 2146 193 : } else if (scomma(s, "Data Units Written:", &smart[SMART_NVME_DATA_UNITS_WRITTEN].raw) == 1) { + 2147 0 : pathcpy(smart[SMART_NVME_DATA_UNITS_WRITTEN].name, sizeof(smart[SMART_NVME_DATA_UNITS_WRITTEN].name), "Data_Units_Written"); + 2148 193 : } else if (scomma(s, "Host Read Commands:", &smart[SMART_NVME_HOST_READ_COMMANDS].raw) == 1) { + 2149 0 : pathcpy(smart[SMART_NVME_HOST_READ_COMMANDS].name, sizeof(smart[SMART_NVME_HOST_READ_COMMANDS].name), "Host_Read_Commands"); + 2150 193 : } else if (scomma(s, "Host Write Commands:", &smart[SMART_NVME_HOST_WRITE_COMMANDS].raw) == 1) { + 2151 0 : pathcpy(smart[SMART_NVME_HOST_WRITE_COMMANDS].name, sizeof(smart[SMART_NVME_HOST_WRITE_COMMANDS].name), "Host_Write_Commands"); + 2152 193 : } else if (scomma(s, "Controller Busy Time:", &smart[SMART_NVME_CONTROLLER_BUSY_TIME].raw) == 1) { + 2153 0 : pathcpy(smart[SMART_NVME_CONTROLLER_BUSY_TIME].name, sizeof(smart[SMART_NVME_CONTROLLER_BUSY_TIME].name), "Controller_Busy_Time"); + 2154 193 : } else if (scomma(s, "Unsafe Shutdowns:", &smart[SMART_NVME_UNSAFE_SHUTDOWNS].raw) == 1) { + 2155 0 : pathcpy(smart[SMART_NVME_UNSAFE_SHUTDOWNS].name, sizeof(smart[SMART_NVME_UNSAFE_SHUTDOWNS].name), "Unsafe_Shutdowns"); + 2156 : /* smartctl doesn't print this with command, but %d */ + 2157 193 : } else if (scomma(s, "Warning Comp. Temperature Time:", &smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].raw) == 1) { + 2158 0 : pathcpy(smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].name, sizeof(smart[SMART_NVME_WARNING_COMP_TEMPERATURE_TIME].name), "Warning_Comp_Temperature_Time"); + 2159 : /* smartctl doesn't print this with command, but %d */ + 2160 193 : } else if (scomma(s, "Critical Comp. Temperature Time:", &smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].raw) == 1) { + 2161 0 : pathcpy(smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].name, sizeof(smart[SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME].name), "Critical_Comp_Temperature_Time"); + 2162 : /* ATA Attributes table */ + 2163 193 : } else if (smatch(s, "ID#") == 0) { + 2164 2 : inside = 1; + 2165 191 : } else if (inside) { + 2166 31 : char id_name[128] = { 0 }; + 2167 31 : char type[64] = { 0 }; + 2168 31 : char updated[64] = { 0 }; + 2169 31 : char when_failed[64] = { 0 }; + 2170 : uint64_t min, max; + 2171 : int minmax; + 2172 : int flags; + 2173 : + 2174 31 : if (sscanf(s, "%u %127s %*s %" SCNu64 " %" SCNu64 " %" SCNu64 " %63s %63s %63s %" SCNu64 " (Min/Max %" SCNu64 "/%" SCNu64 ")", &id, id_name, &norm, &worst, &thresh, type, updated, when_failed, &raw, &min, &max) == 11) { + 2175 1 : minmax = 1; + 2176 30 : } else if (sscanf(s, "%u %127s %*s %" SCNu64 " %" SCNu64 " %" SCNu64 " %63s %63s %63s %" SCNu64, &id, id_name, &norm, &worst, &thresh, type, updated, when_failed, &raw) == 9) { + 2177 30 : minmax = 0; + 2178 : } else { + 2179 0 : log_fatal(EEXTERNAL, "Invalid smartctl line '%s'.\n", s); + 2180 0 : return -1; + 2181 : } + 2182 : + 2183 31 : if (id >= 256) { + 2184 : /* LCOV_EXCL_START */ + 2185 : log_fatal(EEXTERNAL, "Invalid SMART id '%u'.\n", id); + 2186 : return -1; + 2187 : /* LCOV_EXCL_STOP */ + 2188 : } + 2189 : + 2190 31 : flags = 0; + 2191 31 : if (strcmp(type, "Pre-fail") == 0) + 2192 11 : flags |= SMART_ATTR_TYPE_PREFAIL; + 2193 20 : else if (strcmp(type, "Old_age") == 0) + 2194 20 : flags |= SMART_ATTR_TYPE_OLDAGE; + 2195 31 : if (strcmp(updated, "Always") == 0) + 2196 28 : flags |= SMART_ATTR_UPDATE_ALWAYS; + 2197 3 : else if (strcmp(updated, "Offline") == 0) + 2198 3 : flags |= SMART_ATTR_UPDATE_OFFLINE; + 2199 31 : if (strcmp(when_failed, "FAILING_NOW") == 0) + 2200 0 : flags |= SMART_ATTR_WHEN_FAILED_NOW; + 2201 31 : else if (strcmp(when_failed, "In_the_past") == 0) + 2202 0 : flags |= SMART_ATTR_WHEN_FAILED_PAST; + 2203 31 : else if (strcmp(when_failed, "-") == 0) + 2204 31 : flags |= SMART_ATTR_WHEN_FAILED_NEVER; + 2205 : + 2206 : /* revert the min/max decoding done by smartctl */ + 2207 31 : if (minmax + 2208 1 : && raw <= 0xFFFFUL + 2209 1 : && min <= 0xFFFFUL + 2210 1 : && max <= 0xFFFFUL) { + 2211 1 : raw |= min << 16; + 2212 1 : raw |= max << 32; + 2213 : } + 2214 : + 2215 31 : smart[id].raw = raw; + 2216 31 : smart[id].norm = norm; + 2217 31 : smart[id].worst = worst; + 2218 31 : smart[id].thresh = thresh; + 2219 31 : smart[id].flags = flags; + 2220 31 : pathcpy(smart[id].name, sizeof(smart[id].name), id_name); + 2221 : + 2222 : /* + 2223 : * Map normalized health percentage to our unified wear level for SSDs + 2224 : * 177: Wear_Leveling_Count (Samsung/Crucial) + 2225 : * 231: SSD_Life_Left (Kingston/WD) + 2226 : * 233: Media_Wearout_Indicator (Intel) + 2227 : */ + 2228 31 : if (norm <= 100) { + 2229 25 : switch (id) { + 2230 1 : case 177 : + 2231 : case 233 : + 2232 : case 231 : + 2233 1 : smart[SMART_WEAR_LEVEL].raw = 100 - norm; + 2234 1 : break; + 2235 : } + 2236 : } + 2237 : } + 2238 : } + 2239 : + 2240 14 : return 0; + 2241 : } + 2242 : + 2243 25 : int smartctl_flush(FILE* f, const char* file, const char* name) + 2244 : { + 2245 : /* read the file */ + 2246 20 : while (1) { + 2247 : char buf[256]; + 2248 : char* s; + 2249 : + 2250 25 : s = fgets(buf, sizeof(buf), f); + 2251 25 : if (s == 0) + 2252 5 : break; 2253 : - 2254 5 : return 0; - 2255 : } + 2254 : /* remove extraneous chars */ + 2255 20 : s = strpolish(buf); 2256 : - 2257 145110 : int smart_temp(devinfo_t* devinfo) - 2258 : { - 2259 145110 : uint64_t t = devinfo->smart[SMART_TEMPERATURE_CELSIUS].raw; - 2260 145110 : if (t == SMART_UNASSIGNED) - 2261 0 : t = devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw; - 2262 145110 : if (t == SMART_UNASSIGNED) - 2263 0 : return -1; - 2264 : - 2265 : /* mask out min/max values */ - 2266 145110 : t &= 0xFFFFUL; - 2267 : - 2268 145110 : if (t == 0) - 2269 0 : return -1; - 2270 145110 : if (t > 100) - 2271 0 : return -1; - 2272 : - 2273 145110 : return t; - 2274 : } - 2275 : - 2276 : /****************************************************************************/ - 2277 : /* thread */ + 2257 20 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 2258 : } + 2259 : + 2260 5 : return 0; + 2261 : } + 2262 : + 2263 145124 : int smart_temp(devinfo_t* devinfo) + 2264 : { + 2265 145124 : uint64_t t = devinfo->smart[SMART_TEMPERATURE_CELSIUS].raw; + 2266 145124 : if (t == SMART_UNASSIGNED) + 2267 13 : t = devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw; + 2268 145124 : if (t == SMART_UNASSIGNED) + 2269 12 : return -1; + 2270 : + 2271 : /* mask out min/max values */ + 2272 145112 : t &= 0xFFFFUL; + 2273 : + 2274 145112 : if (t == 0) + 2275 0 : return -1; + 2276 145112 : if (t > 100) + 2277 0 : return -1; 2278 : - 2279 : #if HAVE_THREAD - 2280 3299 : void thread_mutex_init(thread_mutex_t* mutex) - 2281 : { - 2282 3299 : if (pthread_mutex_init(mutex, 0) != 0) { - 2283 : /* LCOV_EXCL_START */ - 2284 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_init().\n"); - 2285 : os_abort(); - 2286 : /* LCOV_EXCL_STOP */ - 2287 : } - 2288 3299 : } - 2289 : - 2290 3167 : void thread_mutex_destroy(thread_mutex_t* mutex) - 2291 : { - 2292 3167 : if (pthread_mutex_destroy(mutex) != 0) { - 2293 : /* LCOV_EXCL_START */ - 2294 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_destroy().\n"); - 2295 : os_abort(); - 2296 : /* LCOV_EXCL_STOP */ - 2297 : } - 2298 3167 : } - 2299 : - 2300 112510359 : void thread_mutex_lock(thread_mutex_t* mutex) - 2301 : { - 2302 112510359 : if (pthread_mutex_lock(mutex) != 0) { - 2303 : /* LCOV_EXCL_START */ - 2304 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_lock().\n"); - 2305 : os_abort(); - 2306 : /* LCOV_EXCL_STOP */ - 2307 : } - 2308 112510359 : } - 2309 : - 2310 112510359 : void thread_mutex_unlock(thread_mutex_t* mutex) - 2311 : { - 2312 112510359 : if (pthread_mutex_unlock(mutex) != 0) { - 2313 : /* LCOV_EXCL_START */ - 2314 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_unlock().\n"); - 2315 : os_abort(); - 2316 : /* LCOV_EXCL_STOP */ - 2317 : } - 2318 112510359 : } - 2319 : - 2320 404 : void thread_cond_init(thread_cond_t* cond) - 2321 : { - 2322 404 : if (pthread_cond_init(cond, 0) != 0) { - 2323 : /* LCOV_EXCL_START */ - 2324 : log_fatal(EINTERNAL, "Failed call to pthread_cond_init().\n"); - 2325 : os_abort(); - 2326 : /* LCOV_EXCL_STOP */ - 2327 : } - 2328 404 : } - 2329 : - 2330 404 : void thread_cond_destroy(thread_cond_t* cond) - 2331 : { - 2332 404 : if (pthread_cond_destroy(cond) != 0) { - 2333 : /* LCOV_EXCL_START */ - 2334 : log_fatal(EINTERNAL, "Failed call to pthread_cond_destroy().\n"); - 2335 : os_abort(); - 2336 : /* LCOV_EXCL_STOP */ - 2337 : } - 2338 404 : } - 2339 : - 2340 668 : void thread_cond_signal(thread_cond_t* cond) - 2341 : { - 2342 668 : if (pthread_cond_signal(cond) != 0) { - 2343 : /* LCOV_EXCL_START */ - 2344 : log_fatal(EINTERNAL, "Failed call to pthread_cond_signal().\n"); - 2345 : os_abort(); - 2346 : /* LCOV_EXCL_STOP */ - 2347 : } - 2348 668 : } - 2349 : - 2350 257671 : void thread_cond_broadcast(thread_cond_t* cond) - 2351 : { - 2352 257671 : if (pthread_cond_broadcast(cond) != 0) { - 2353 : /* LCOV_EXCL_START */ - 2354 : log_fatal(EINTERNAL, "Failed call to pthread_cond_broadcast().\n"); - 2355 : os_abort(); - 2356 : /* LCOV_EXCL_STOP */ - 2357 : } - 2358 257671 : } - 2359 : - 2360 1554330 : void thread_cond_wait(thread_cond_t* cond, thread_mutex_t* mutex) - 2361 : { - 2362 1554330 : if (pthread_cond_wait(cond, mutex) != 0) { - 2363 : /* LCOV_EXCL_START */ - 2364 : log_fatal(EINTERNAL, "Failed call to pthread_cond_wait().\n"); - 2365 : os_abort(); - 2366 : /* LCOV_EXCL_STOP */ - 2367 : } - 2368 1554330 : } - 2369 : - 2370 : /** - 2371 : * Implementation note about conditional variables. - 2372 : * - 2373 : * The conditional variables can be signaled inside or outside the mutex, - 2374 : * what is better it's debatable but in general doing that outside the mutex, - 2375 : * reduces the number of context switches. - 2376 : * - 2377 : * But when testing with helgrind and drd, this disallows such tools to - 2378 : * to see the dependency between the signal and the wait. - 2379 : * - 2380 : * To avoid it we signal everything inside the mutex. And we do this in both - 2381 : * test mode (with CHECKER defined) and release mode (CHECKER not defined), - 2382 : * to be on the safe side and avoid any difference in behaviour between test and - 2383 : * release. - 2384 : * - 2385 : * Here some interesting discussion: - 2386 : * - 2387 : * Condvars: signal with mutex locked or not? - 2388 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ - 2389 : * - 2390 : * Calling pthread_cond_signal without locking mutex - 2391 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494 - 2392 : */ - 2393 : - 2394 : /** - 2395 : * Control when to signal the condition variables. - 2396 : */ - 2397 : int thread_cond_signal_outside = 0; - 2398 : - 2399 668 : void thread_cond_signal_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex) - 2400 : { - 2401 668 : if (thread_cond_signal_outside) { - 2402 : /* without the thread checker unlock before signaling, */ - 2403 : /* this reduces the number of context switches */ - 2404 0 : thread_mutex_unlock(mutex); - 2405 : } - 2406 : - 2407 668 : thread_cond_signal(cond); - 2408 : - 2409 668 : if (!thread_cond_signal_outside) { - 2410 : /* with the thread checker unlock after signaling */ - 2411 : /* to make explicit the condition and mutex relation */ - 2412 668 : thread_mutex_unlock(mutex); - 2413 : } - 2414 668 : } - 2415 : - 2416 257469 : void thread_cond_broadcast_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex) - 2417 : { - 2418 257469 : if (thread_cond_signal_outside) { - 2419 : /* without the thread checker unlock before signaling, */ - 2420 : /* this reduces the number of context switches */ - 2421 0 : thread_mutex_unlock(mutex); - 2422 : } - 2423 : - 2424 257469 : thread_cond_broadcast(cond); - 2425 : - 2426 257469 : if (!thread_cond_signal_outside) { - 2427 : /* with the thread checker unlock after signaling */ - 2428 : /* to make explicit the condition and mutex relation */ - 2429 257469 : thread_mutex_unlock(mutex); - 2430 : } - 2431 257469 : } - 2432 : - 2433 2876 : void thread_create(thread_id_t* thread, void* (*func)(void*), void* arg) - 2434 : { - 2435 2876 : if (pthread_create(thread, 0, func, arg) != 0) { - 2436 : /* LCOV_EXCL_START */ - 2437 : log_fatal(EINTERNAL, "Failed call to pthread_create().\n"); - 2438 : os_abort(); - 2439 : /* LCOV_EXCL_STOP */ - 2440 : } - 2441 2876 : } - 2442 : - 2443 2876 : void thread_join(thread_id_t thread, void** retval) - 2444 : { - 2445 2876 : if (pthread_join(thread, retval) != 0) { - 2446 : /* LCOV_EXCL_START */ - 2447 : log_fatal(EINTERNAL, "Failed call to pthread_join().\n"); - 2448 : os_abort(); - 2449 : /* LCOV_EXCL_STOP */ - 2450 : } - 2451 2876 : } - 2452 : - 2453 105499 : void thread_yield(void) - 2454 : { - 2455 : #ifdef __MINGW32__ - 2456 : Sleep(0); - 2457 : #else - 2458 105499 : sched_yield(); - 2459 : #endif - 2460 105499 : } - 2461 : #endif - 2462 : - 2463 : /****************************************************************************/ - 2464 : /* wnmatch */ - 2465 : - 2466 : /** - 2467 : * Helper function for case-insensitive character comparison - 2468 : */ - 2469 86982601 : static inline int char_match(char p, char t) - 2470 : { - 2471 : #ifdef WIN32 - 2472 : return tolower((unsigned char)p) == tolower((unsigned char)t); - 2473 : #else - 2474 86982601 : return p == t; - 2475 : #endif - 2476 : } - 2477 : - 2478 : /** - 2479 : * Match character class [...] - 2480 : * Return 0 if NOT matched - 2481 : */ - 2482 28 : static const char* match_class(const char* p, char t) - 2483 : { - 2484 28 : int negate = 0; - 2485 28 : int matched = 0; - 2486 : - 2487 28 : if (*p == '!' || *p == '^') { - 2488 9 : negate = 1; - 2489 9 : ++p; - 2490 : } - 2491 : - 2492 77 : while (*p && *p != ']') { - 2493 49 : if (p[1] == '-' && p[2] != ']' && p[2] != 0) { - 2494 : /* range [a-z] */ - 2495 22 : char start = *p; - 2496 22 : char end = p[2]; - 2497 : #ifdef WIN32 - 2498 : start = tolower((unsigned char)start); - 2499 : end = tolower((unsigned char)end); - 2500 : t = tolower((unsigned char)t); - 2501 : #endif - 2502 22 : if (t >= start && t <= end) - 2503 10 : matched = 1; - 2504 22 : p += 3; - 2505 : } else { - 2506 : /* single character */ - 2507 27 : if (char_match(*p, t)) - 2508 5 : matched = 1; - 2509 27 : ++p; - 2510 : } - 2511 : } - 2512 : - 2513 28 : if (*p == ']') - 2514 28 : ++p; - 2515 : - 2516 28 : if (negate) - 2517 9 : matched = !matched; - 2518 28 : if (!matched) - 2519 14 : return 0; - 2520 : - 2521 14 : return p; - 2522 : } - 2523 : - 2524 102260599 : int wnmatch(const char* p, const char* t) - 2525 : { - 2526 102260599 : char p1 = 0; /* previous char */ - 2527 105985464 : while (*p) { - 2528 105852004 : char p0 = *p; - 2529 105852004 : switch (p0) { - 2530 20 : case '?' : - 2531 : /* ? matches any single character except / */ - 2532 20 : if (*t == 0 || *t == '/') - 2533 4 : return 1; - 2534 16 : ++p; - 2535 16 : ++t; - 2536 16 : break; - 2537 12656225 : case '*' : - 2538 : /* check for ** */ - 2539 12656225 : if (p[1] == '*') { - 2540 : /* skip the ** */ - 2541 104 : p += 2; - 2542 : - 2543 : /* munge all * */ - 2544 114 : while (*p == '*') - 2545 10 : ++p; - 2546 : - 2547 : /* if its not near a slash, it's like a single * */ - 2548 104 : if (p1 == '/' || *p == '/') { - 2549 : /* a ** at end matches everything */ - 2550 84 : if (*p == 0) - 2551 10 : return 0; + 2279 145112 : return t; + 2280 : } + 2281 : + 2282 : /****************************************************************************/ + 2283 : /* thread */ + 2284 : + 2285 : #if HAVE_THREAD + 2286 3312 : void thread_mutex_init(thread_mutex_t* mutex) + 2287 : { + 2288 3312 : if (pthread_mutex_init(mutex, 0) != 0) { + 2289 : /* LCOV_EXCL_START */ + 2290 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_init().\n"); + 2291 : os_abort(); + 2292 : /* LCOV_EXCL_STOP */ + 2293 : } + 2294 3312 : } + 2295 : + 2296 3180 : void thread_mutex_destroy(thread_mutex_t* mutex) + 2297 : { + 2298 3180 : if (pthread_mutex_destroy(mutex) != 0) { + 2299 : /* LCOV_EXCL_START */ + 2300 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_destroy().\n"); + 2301 : os_abort(); + 2302 : /* LCOV_EXCL_STOP */ + 2303 : } + 2304 3180 : } + 2305 : + 2306 112377134 : void thread_mutex_lock(thread_mutex_t* mutex) + 2307 : { + 2308 112377134 : if (pthread_mutex_lock(mutex) != 0) { + 2309 : /* LCOV_EXCL_START */ + 2310 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_lock().\n"); + 2311 : os_abort(); + 2312 : /* LCOV_EXCL_STOP */ + 2313 : } + 2314 112377134 : } + 2315 : + 2316 112377134 : void thread_mutex_unlock(thread_mutex_t* mutex) + 2317 : { + 2318 112377134 : if (pthread_mutex_unlock(mutex) != 0) { + 2319 : /* LCOV_EXCL_START */ + 2320 : log_fatal(EINTERNAL, "Failed call to pthread_mutex_unlock().\n"); + 2321 : os_abort(); + 2322 : /* LCOV_EXCL_STOP */ + 2323 : } + 2324 112377134 : } + 2325 : + 2326 404 : void thread_cond_init(thread_cond_t* cond) + 2327 : { + 2328 404 : if (pthread_cond_init(cond, 0) != 0) { + 2329 : /* LCOV_EXCL_START */ + 2330 : log_fatal(EINTERNAL, "Failed call to pthread_cond_init().\n"); + 2331 : os_abort(); + 2332 : /* LCOV_EXCL_STOP */ + 2333 : } + 2334 404 : } + 2335 : + 2336 404 : void thread_cond_destroy(thread_cond_t* cond) + 2337 : { + 2338 404 : if (pthread_cond_destroy(cond) != 0) { + 2339 : /* LCOV_EXCL_START */ + 2340 : log_fatal(EINTERNAL, "Failed call to pthread_cond_destroy().\n"); + 2341 : os_abort(); + 2342 : /* LCOV_EXCL_STOP */ + 2343 : } + 2344 404 : } + 2345 : + 2346 827 : void thread_cond_signal(thread_cond_t* cond) + 2347 : { + 2348 827 : if (pthread_cond_signal(cond) != 0) { + 2349 : /* LCOV_EXCL_START */ + 2350 : log_fatal(EINTERNAL, "Failed call to pthread_cond_signal().\n"); + 2351 : os_abort(); + 2352 : /* LCOV_EXCL_STOP */ + 2353 : } + 2354 827 : } + 2355 : + 2356 257545 : void thread_cond_broadcast(thread_cond_t* cond) + 2357 : { + 2358 257545 : if (pthread_cond_broadcast(cond) != 0) { + 2359 : /* LCOV_EXCL_START */ + 2360 : log_fatal(EINTERNAL, "Failed call to pthread_cond_broadcast().\n"); + 2361 : os_abort(); + 2362 : /* LCOV_EXCL_STOP */ + 2363 : } + 2364 257545 : } + 2365 : + 2366 1554290 : void thread_cond_wait(thread_cond_t* cond, thread_mutex_t* mutex) + 2367 : { + 2368 1554290 : if (pthread_cond_wait(cond, mutex) != 0) { + 2369 : /* LCOV_EXCL_START */ + 2370 : log_fatal(EINTERNAL, "Failed call to pthread_cond_wait().\n"); + 2371 : os_abort(); + 2372 : /* LCOV_EXCL_STOP */ + 2373 : } + 2374 1554290 : } + 2375 : + 2376 : /** + 2377 : * Implementation note about conditional variables. + 2378 : * + 2379 : * The conditional variables can be signaled inside or outside the mutex, + 2380 : * what is better it's debatable but in general doing that outside the mutex, + 2381 : * reduces the number of context switches. + 2382 : * + 2383 : * But when testing with helgrind and drd, this disallows such tools to + 2384 : * to see the dependency between the signal and the wait. + 2385 : * + 2386 : * To avoid it we signal everything inside the mutex. And we do this in both + 2387 : * test mode (with CHECKER defined) and release mode (CHECKER not defined), + 2388 : * to be on the safe side and avoid any difference in behaviour between test and + 2389 : * release. + 2390 : * + 2391 : * Here some interesting discussion: + 2392 : * + 2393 : * Condvars: signal with mutex locked or not? + 2394 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ + 2395 : * + 2396 : * Calling pthread_cond_signal without locking mutex + 2397 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494 + 2398 : */ + 2399 : + 2400 : /** + 2401 : * Control when to signal the condition variables. + 2402 : */ + 2403 : int thread_cond_signal_outside = 0; + 2404 : + 2405 827 : void thread_cond_signal_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex) + 2406 : { + 2407 827 : if (thread_cond_signal_outside) { + 2408 : /* without the thread checker unlock before signaling, */ + 2409 : /* this reduces the number of context switches */ + 2410 0 : thread_mutex_unlock(mutex); + 2411 : } + 2412 : + 2413 827 : thread_cond_signal(cond); + 2414 : + 2415 827 : if (!thread_cond_signal_outside) { + 2416 : /* with the thread checker unlock after signaling */ + 2417 : /* to make explicit the condition and mutex relation */ + 2418 827 : thread_mutex_unlock(mutex); + 2419 : } + 2420 827 : } + 2421 : + 2422 257343 : void thread_cond_broadcast_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex) + 2423 : { + 2424 257343 : if (thread_cond_signal_outside) { + 2425 : /* without the thread checker unlock before signaling, */ + 2426 : /* this reduces the number of context switches */ + 2427 0 : thread_mutex_unlock(mutex); + 2428 : } + 2429 : + 2430 257343 : thread_cond_broadcast(cond); + 2431 : + 2432 257343 : if (!thread_cond_signal_outside) { + 2433 : /* with the thread checker unlock after signaling */ + 2434 : /* to make explicit the condition and mutex relation */ + 2435 257343 : thread_mutex_unlock(mutex); + 2436 : } + 2437 257343 : } + 2438 : + 2439 2883 : void thread_create(thread_id_t* thread, void* (*func)(void*), void* arg) + 2440 : { + 2441 2883 : if (pthread_create(thread, 0, func, arg) != 0) { + 2442 : /* LCOV_EXCL_START */ + 2443 : log_fatal(EINTERNAL, "Failed call to pthread_create().\n"); + 2444 : os_abort(); + 2445 : /* LCOV_EXCL_STOP */ + 2446 : } + 2447 2883 : } + 2448 : + 2449 2883 : void thread_join(thread_id_t thread, void** retval) + 2450 : { + 2451 2883 : if (pthread_join(thread, retval) != 0) { + 2452 : /* LCOV_EXCL_START */ + 2453 : log_fatal(EINTERNAL, "Failed call to pthread_join().\n"); + 2454 : os_abort(); + 2455 : /* LCOV_EXCL_STOP */ + 2456 : } + 2457 2883 : } + 2458 : + 2459 108112 : void thread_yield(void) + 2460 : { + 2461 : #ifdef __MINGW32__ + 2462 : Sleep(0); + 2463 : #else + 2464 108112 : sched_yield(); + 2465 : #endif + 2466 108112 : } + 2467 : #endif + 2468 : + 2469 : /****************************************************************************/ + 2470 : /* wnmatch */ + 2471 : + 2472 : /** + 2473 : * Helper function for case-insensitive character comparison + 2474 : */ + 2475 86985273 : static inline int char_match(char p, char t) + 2476 : { + 2477 : #ifdef WIN32 + 2478 : return tolower((unsigned char)p) == tolower((unsigned char)t); + 2479 : #else + 2480 86985273 : return p == t; + 2481 : #endif + 2482 : } + 2483 : + 2484 : /** + 2485 : * Match character class [...] + 2486 : * Return 0 if NOT matched + 2487 : */ + 2488 28 : static const char* match_class(const char* p, char t) + 2489 : { + 2490 28 : int negate = 0; + 2491 28 : int matched = 0; + 2492 : + 2493 28 : if (*p == '!' || *p == '^') { + 2494 9 : negate = 1; + 2495 9 : ++p; + 2496 : } + 2497 : + 2498 77 : while (*p && *p != ']') { + 2499 49 : if (p[1] == '-' && p[2] != ']' && p[2] != 0) { + 2500 : /* range [a-z] */ + 2501 22 : char start = *p; + 2502 22 : char end = p[2]; + 2503 : #ifdef WIN32 + 2504 : start = tolower((unsigned char)start); + 2505 : end = tolower((unsigned char)end); + 2506 : t = tolower((unsigned char)t); + 2507 : #endif + 2508 22 : if (t >= start && t <= end) + 2509 10 : matched = 1; + 2510 22 : p += 3; + 2511 : } else { + 2512 : /* single character */ + 2513 27 : if (char_match(*p, t)) + 2514 5 : matched = 1; + 2515 27 : ++p; + 2516 : } + 2517 : } + 2518 : + 2519 28 : if (*p == ']') + 2520 28 : ++p; + 2521 : + 2522 28 : if (negate) + 2523 9 : matched = !matched; + 2524 28 : if (!matched) + 2525 14 : return 0; + 2526 : + 2527 14 : return p; + 2528 : } + 2529 : + 2530 102263029 : int wnmatch(const char* p, const char* t) + 2531 : { + 2532 102263029 : char p1 = 0; /* previous char */ + 2533 105988951 : while (*p) { + 2534 105855413 : char p0 = *p; + 2535 105855413 : switch (p0) { + 2536 20 : case '?' : + 2537 : /* ? matches any single character except / */ + 2538 20 : if (*t == 0 || *t == '/') + 2539 4 : return 1; + 2540 16 : ++p; + 2541 16 : ++t; + 2542 16 : break; + 2543 12656765 : case '*' : + 2544 : /* check for ** */ + 2545 12656765 : if (p[1] == '*') { + 2546 : /* skip the ** */ + 2547 104 : p += 2; + 2548 : + 2549 : /* munge all * */ + 2550 114 : while (*p == '*') + 2551 10 : ++p; 2552 : - 2553 : /* - 2554 : * In between slashes matches to nothing - 2555 : * - 2556 : * Check for /##/ or ^##/ (^ start of string) - 2557 : * - 2558 : * This is required for: - 2559 : * "/##/file.txt" matching "/file.txt" - 2560 : * "##/file.txt" matching "file.txt" - 2561 : * "x##/file.txt" NOT matching "xfile.txt" - 2562 : */ - 2563 74 : if (*p == '/' && (p1 == 0 || p1 == '/')) { - 2564 : /* try reducing to nothing */ - 2565 71 : if (wnmatch(p + 1, t) == 0) - 2566 27 : return 0; - 2567 : /* otherwise / should match in the text */ - 2568 : } - 2569 : - 2570 : /* try matching with 0 or more characters */ - 2571 275 : while (*t) { - 2572 263 : if (wnmatch(p, t) == 0) - 2573 35 : return 0; - 2574 228 : ++t; - 2575 : } - 2576 : - 2577 : /* try matching at the end */ - 2578 12 : return wnmatch(p, t); - 2579 : } - 2580 : } else { - 2581 : /* skip the * */ - 2582 12656121 : ++p; - 2583 : } - 2584 : - 2585 : /* a * at end matches rest of segment */ - 2586 12656141 : if (*p == 0) { - 2587 60 : while (*t && *t != '/') - 2588 49 : ++t; - 2589 11 : return *t != 0; - 2590 : } - 2591 : - 2592 : /* try matching with 0 or more characters */ - 2593 89476178 : while (*t && *t != '/') { - 2594 76944779 : if (wnmatch(p, t) == 0) - 2595 124731 : return 0; - 2596 76820048 : ++t; - 2597 : } - 2598 : - 2599 : /* try matching at the end */ - 2600 12531399 : return wnmatch(p, t); - 2601 31 : case '[' : - 2602 : /* character class */ - 2603 31 : if (*t == 0 || *t == '/') - 2604 3 : return 1; - 2605 : - 2606 28 : p = match_class(p + 1, *t); - 2607 28 : if (!p) - 2608 14 : return 1; - 2609 : - 2610 14 : ++t; - 2611 14 : break; - 2612 93195728 : default : - 2613 : /* literal character */ - 2614 93195728 : if (*t == 0 || !char_match(*p, *t)) - 2615 89470893 : return 1; - 2616 3724835 : ++p; - 2617 3724835 : ++t; - 2618 3724835 : break; - 2619 : } - 2620 3724865 : p1 = p0; - 2621 : } - 2622 : - 2623 : /* match successful if we've consumed all text */ - 2624 133460 : return *t != 0; - 2625 : } - 2626 : + 2553 : /* if its not near a slash, it's like a single * */ + 2554 104 : if (p1 == '/' || *p == '/') { + 2555 : /* a ** at end matches everything */ + 2556 84 : if (*p == 0) + 2557 10 : return 0; + 2558 : + 2559 : /* + 2560 : * In between slashes matches to nothing + 2561 : * + 2562 : * Check for /##/ or ^##/ (^ start of string) + 2563 : * + 2564 : * This is required for: + 2565 : * "/##/file.txt" matching "/file.txt" + 2566 : * "##/file.txt" matching "file.txt" + 2567 : * "x##/file.txt" NOT matching "xfile.txt" + 2568 : */ + 2569 74 : if (*p == '/' && (p1 == 0 || p1 == '/')) { + 2570 : /* try reducing to nothing */ + 2571 71 : if (wnmatch(p + 1, t) == 0) + 2572 27 : return 0; + 2573 : /* otherwise / should match in the text */ + 2574 : } + 2575 : + 2576 : /* try matching with 0 or more characters */ + 2577 275 : while (*t) { + 2578 263 : if (wnmatch(p, t) == 0) + 2579 35 : return 0; + 2580 228 : ++t; + 2581 : } + 2582 : + 2583 : /* try matching at the end */ + 2584 12 : return wnmatch(p, t); + 2585 : } + 2586 : } else { + 2587 : /* skip the * */ + 2588 12656661 : ++p; + 2589 : } + 2590 : + 2591 : /* a * at end matches rest of segment */ + 2592 12656681 : if (*p == 0) { + 2593 60 : while (*t && *t != '/') + 2594 49 : ++t; + 2595 11 : return *t != 0; + 2596 : } + 2597 : + 2598 : /* try matching with 0 or more characters */ + 2599 89478068 : while (*t && *t != '/') { + 2600 76946207 : if (wnmatch(p, t) == 0) + 2601 124809 : return 0; + 2602 76821398 : ++t; + 2603 : } + 2604 : + 2605 : /* try matching at the end */ + 2606 12531861 : return wnmatch(p, t); + 2607 31 : case '[' : + 2608 : /* character class */ + 2609 31 : if (*t == 0 || *t == '/') + 2610 3 : return 1; + 2611 : + 2612 28 : p = match_class(p + 1, *t); + 2613 28 : if (!p) + 2614 14 : return 1; + 2615 : + 2616 14 : ++t; + 2617 14 : break; + 2618 93198597 : default : + 2619 : /* literal character */ + 2620 93198597 : if (*t == 0 || !char_match(*p, *t)) + 2621 89472705 : return 1; + 2622 3725892 : ++p; + 2623 3725892 : ++t; + 2624 3725892 : break; + 2625 : } + 2626 3725922 : p1 = p0; + 2627 : } + 2628 : + 2629 : /* match successful if we've consumed all text */ + 2630 133538 : return *t != 0; + 2631 : } + 2632 : diff --git a/cov/cmdline/support.h.func-sort-c.html b/cov/cmdline/support.h.func-sort-c.html index 9991d0bb..6755a63b 100644 --- a/cov/cmdline/support.h.func-sort-c.html +++ b/cov/cmdline/support.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ esc_shell - 342153 + 342322
diff --git a/cov/cmdline/support.h.func.html b/cov/cmdline/support.h.func.html index e1796c7e..1647af1e 100644 --- a/cov/cmdline/support.h.func.html +++ b/cov/cmdline/support.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -61,7 +61,7 @@ esc_shell - 342153 + 342322
diff --git a/cov/cmdline/support.h.gcov.html b/cov/cmdline/support.h.gcov.html index 97b66087..aae9d877 100644 --- a/cov/cmdline/support.h.gcov.html +++ b/cov/cmdline/support.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 @@ -328,9 +328,9 @@ 266 : * \param buffer Preallocated buffer of ESC_MAX size. 267 : */ 268 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer); - 269 342153 : static inline const char* esc_shell(const char* str, char* buffer) + 269 342322 : static inline const char* esc_shell(const char* str, char* buffer) 270 : { - 271 342153 : return esc_shell_multi(&str, 1, buffer); + 271 342322 : return esc_shell_multi(&str, 1, buffer); 272 : } 273 : 274 : /** diff --git a/cov/cmdline/sync.c.func-sort-c.html b/cov/cmdline/sync.c.func-sort-c.html index 3546ca35..8e531515 100644 --- a/cov/cmdline/sync.c.func-sort-c.html +++ b/cov/cmdline/sync.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -77,7 +77,7 @@ failed_compare_by_index - 851 + 852 block_is_enabled @@ -85,11 +85,11 @@ sync_parity_writer - 558683 + 558371 sync_data_reader - 694374 + 693996
diff --git a/cov/cmdline/sync.c.func.html b/cov/cmdline/sync.c.func.html index 9ca34905..33ebfd23 100644 --- a/cov/cmdline/sync.c.func.html +++ b/cov/cmdline/sync.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -69,7 +69,7 @@ failed_compare_by_index - 851 + 852 state_hash_process @@ -85,11 +85,11 @@ sync_data_reader - 694374 + 693996 sync_parity_writer - 558683 + 558371
diff --git a/cov/cmdline/sync.c.gcov.html b/cov/cmdline/sync.c.gcov.html index 28bb9e42..2fa657a9 100644 --- a/cov/cmdline/sync.c.gcov.html +++ b/cov/cmdline/sync.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 8 @@ -480,13 +480,13 @@ 418 : /** 419 : * Comparison function for sorting by index. 420 : */ - 421 851 : int failed_compare_by_index(const void* void_a, const void* void_b) + 421 852 : int failed_compare_by_index(const void* void_a, const void* void_b) 422 : { - 423 851 : const struct failed_struct* a = void_a; - 424 851 : const struct failed_struct* b = void_b; + 423 852 : const struct failed_struct* a = void_a; + 424 852 : const struct failed_struct* b = void_b; 425 : - 426 851 : if (a->index < b->index) - 427 851 : return -1; + 426 852 : if (a->index < b->index) + 427 852 : return -1; 428 0 : if (a->index > b->index) 429 0 : return 1; 430 0 : return 0; @@ -526,56 +526,56 @@ 464 2488621 : one_valid = 1; 465 : 466 2631257 : if (block_has_invalid_parity(block) || plan->force_full) - 467 377610 : one_invalid = 1; + 467 377555 : one_invalid = 1; 468 : } 469 : 470 : /* if none valid or none invalid, we don't need to update */ 471 439324 : if (!one_invalid || !one_valid) - 472 323595 : return 0; + 472 323658 : return 0; 473 : - 474 115729 : return 1; + 474 115666 : return 1; 475 : } 476 : - 477 694374 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 477 693996 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) 478 : { - 479 694374 : struct snapraid_io* io = worker->io; - 480 694374 : struct snapraid_state* state = io->state; - 481 694374 : struct snapraid_handle* handle = worker->handle; - 482 694374 : struct snapraid_disk* disk = handle->disk; - 483 694374 : block_off_t blockcur = task->position; - 484 694374 : unsigned char* buffer = task->buffer; + 479 693996 : struct snapraid_io* io = worker->io; + 480 693996 : struct snapraid_state* state = io->state; + 481 693996 : struct snapraid_handle* handle = worker->handle; + 482 693996 : struct snapraid_disk* disk = handle->disk; + 483 693996 : block_off_t blockcur = task->position; + 484 693996 : unsigned char* buffer = task->buffer; 485 : int ret; 486 : char esc_buffer[ESC_MAX]; 487 : 488 : /* if the disk position is not used */ - 489 694374 : if (!disk) { + 489 693996 : if (!disk) { 490 : /* use an empty block */ 491 0 : memset(buffer, 0, state->block_size); 492 0 : task->state = TASK_STATE_DONE; - 493 107729 : return; + 493 107737 : return; 494 : } 495 : 496 : /* get the block */ - 497 694374 : task->block = fs_par2block_find(disk, blockcur); + 497 693996 : task->block = fs_par2block_find(disk, blockcur); 498 : 499 : /* if the block has no file, meaning that it's EMPTY or DELETED, */ 500 : /* it doesn't participate in the new parity computation */ - 501 694374 : if (!block_has_file(task->block)) { + 501 693996 : if (!block_has_file(task->block)) { 502 : /* use an empty block */ - 503 107711 : memset(buffer, 0, state->block_size); - 504 107711 : task->state = TASK_STATE_DONE; - 505 107711 : return; + 503 107719 : memset(buffer, 0, state->block_size); + 504 107719 : task->state = TASK_STATE_DONE; + 505 107719 : return; 506 : } 507 : 508 : /* get the file of this block */ - 509 586663 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + 509 586277 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); 510 : 511 : /* if the file is different than the current one, close it */ - 512 586663 : if (handle->file != 0 && handle->file != task->file) { + 512 586277 : if (handle->file != 0 && handle->file != task->file) { 513 : /* keep a pointer at the file we are going to close for error reporting */ - 514 240907 : struct snapraid_file* report = handle->file; - 515 240907 : ret = handle_close(handle); - 516 240907 : if (ret == -1) { + 514 240772 : struct snapraid_file* report = handle->file; + 515 240772 : ret = handle_close(handle); + 516 240772 : if (ret == -1) { 517 : /* LCOV_EXCL_START */ 518 : /* This one is really an unexpected error, because we are only reading */ 519 : /* and closing a descriptor should never fail */ @@ -593,8 +593,8 @@ 531 : } 532 : } 533 : - 534 586663 : ret = handle_open(handle, task->file, state->file_mode, log_error, log_error); /* output a message for missing files */ - 535 586663 : if (ret == -1) { + 534 586277 : ret = handle_open(handle, task->file, state->file_mode, log_error, log_error); /* output a message for missing files */ + 535 586277 : if (ret == -1) { 536 12 : log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); 537 12 : if (errno == ENOENT) { 538 4 : log_error_errno(errno, disk->name); @@ -628,10 +628,10 @@ 566 : } 567 : 568 : /* check if the file is changed */ - 569 586651 : if (handle->st.st_size != task->file->size - 570 586649 : || handle->st.st_mtime != task->file->mtime_sec - 571 586647 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec - 572 586647 : || handle->st.st_ino != task->file->inode + 569 586265 : if (handle->st.st_size != task->file->size + 570 586263 : || handle->st.st_mtime != task->file->mtime_sec + 571 586261 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec + 572 586261 : || handle->st.st_ino != task->file->inode 573 : ) { 574 6 : log_tag("error:%u:%s:%s: Unexpected attribute change\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer)); 575 6 : if (handle->st.st_size != task->file->size) { @@ -650,8 +650,8 @@ 588 6 : return; 589 : } 590 : - 591 586645 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); - 592 586645 : if (task->read_size == -1) { + 591 586259 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + 592 586259 : if (task->read_size == -1) { 593 : /* LCOV_EXCL_START */ 594 : log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); 595 : @@ -669,24 +669,24 @@ 607 : } 608 : 609 : /* store the path of the opened file */ - 610 586645 : pathcpy(task->path, sizeof(task->path), handle->path); + 610 586259 : pathcpy(task->path, sizeof(task->path), handle->path); 611 : - 612 586645 : task->state = TASK_STATE_DONE; + 612 586259 : task->state = TASK_STATE_DONE; 613 : } 614 : - 615 558683 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task) + 615 558371 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task) 616 : { - 617 558683 : struct snapraid_io* io = worker->io; - 618 558683 : struct snapraid_state* state = io->state; - 619 558683 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; - 620 558683 : unsigned level = parity_handle->level; - 621 558683 : block_off_t blockcur = task->position; - 622 558683 : unsigned char* buffer = task->buffer; + 617 558371 : struct snapraid_io* io = worker->io; + 618 558371 : struct snapraid_state* state = io->state; + 619 558371 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; + 620 558371 : unsigned level = parity_handle->level; + 621 558371 : block_off_t blockcur = task->position; + 622 558371 : unsigned char* buffer = task->buffer; 623 : int ret; 624 : 625 : /* write parity */ - 626 558683 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size); - 627 558683 : if (ret == -1) { + 626 558371 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size); + 627 558371 : if (ret == -1) { 628 : /* LCOV_EXCL_START */ 629 : log_tag("parity_%s:%u:%s: Write error. %s.\n", es(errno), blockcur, lev_config_name(level), strerror(errno)); 630 : @@ -703,7 +703,7 @@ 641 : /* LCOV_EXCL_STOP */ 642 : } 643 : - 644 558683 : task->state = TASK_STATE_DONE; + 644 558371 : task->state = TASK_STATE_DONE; 645 : } 646 : 647 88 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax) @@ -788,9 +788,9 @@ 726 88 : block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */ 727 439412 : for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { 728 439324 : if (!block_is_enabled(&plan, blockcur)) - 729 323595 : continue; - 730 115729 : bit_vect_set(block_enabled, blockcur); - 731 115729 : ++countmax; + 729 323658 : continue; + 730 115666 : bit_vect_set(block_enabled, blockcur); + 731 115666 : ++countmax; 732 : } 733 : 734 : /* compute the autosave size for all disk, even if not read */ @@ -817,7 +817,7 @@ 755 88 : if (alert < 0) 756 0 : goto bail; 757 : - 758 115729 : while (1) { + 758 115666 : while (1) { 759 : unsigned failed_count; 760 : int error_on_this_block; 761 : int silent_error_on_this_block; @@ -831,31 +831,31 @@ 769 : int writer_error[IO_WRITER_ERROR_MAX]; 770 : 771 : /* go to the next block */ - 772 115817 : blockcur = io_read_next(&io, &buffer); - 773 115817 : if (blockcur >= blockmax) + 772 115754 : blockcur = io_read_next(&io, &buffer); + 773 115754 : if (blockcur >= blockmax) 774 88 : break; 775 : 776 : /* until now is scheduling */ - 777 115729 : state_usage_sched(state); + 777 115666 : state_usage_sched(state); 778 : 779 : /* one more block processed for autosave */ - 780 115729 : ++autosavedone; - 781 115729 : --autosavemissing; + 780 115666 : ++autosavedone; + 781 115666 : --autosavemissing; 782 : 783 : /* by default process the block, and skip it if something goes wrong */ - 784 115729 : error_on_this_block = 0; - 785 115729 : silent_error_on_this_block = 0; - 786 115729 : io_error_on_this_block = 0; - 787 115729 : fixed_error_on_this_block = 0; + 784 115666 : error_on_this_block = 0; + 785 115666 : silent_error_on_this_block = 0; + 786 115666 : io_error_on_this_block = 0; + 787 115666 : fixed_error_on_this_block = 0; 788 : 789 : /* keep track of the number of failed blocks */ - 790 115729 : failed_count = 0; + 790 115666 : failed_count = 0; 791 : 792 : /* get block specific info */ - 793 115729 : info = info_get(&state->infoarr, blockcur); + 793 115666 : info = info_get(&state->infoarr, blockcur); 794 : 795 : /* if we have to use the old hash */ - 796 115729 : rehash = info_get_rehash(info); + 796 115666 : rehash = info_get_rehash(info); 797 : 798 : /* if the parity requires to be updated */ 799 : /* It could happens that all the blocks are EMPTY/BLK and CHG but with the hash */ @@ -864,18 +864,18 @@ 802 : /* Note that CHG/DELETED blocks already present in the content file loaded */ 803 : /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */ 804 : /* We are treating only CHG blocks created at runtime. */ - 805 115729 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update; + 805 115666 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update; 806 : 807 : /* if the parity is going to be updated */ - 808 115729 : parity_going_to_be_updated = 0; + 808 115666 : parity_going_to_be_updated = 0; 809 : 810 : /* if the block is marked as bad, we force the parity update */ 811 : /* because the bad block may be the result of a wrong parity */ - 812 115729 : if (info_get_bad(info)) + 812 115666 : if (info_get_bad(info)) 813 0 : parity_needs_to_be_updated = 1; 814 : 815 : /* for each disk, process the block */ - 816 810103 : for (j = 0; j < diskmax; ++j) { + 816 809662 : for (j = 0; j < diskmax; ++j) { 817 : struct snapraid_task* task; 818 : int read_size; 819 : unsigned char hash[HASH_MAX]; @@ -887,47 +887,47 @@ 825 : unsigned diskcur; 826 : 827 : /* until now is misc */ - 828 694374 : state_usage_misc(state); + 828 693996 : state_usage_misc(state); 829 : - 830 694374 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); + 830 693996 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); 831 : 832 : /* until now is disk */ - 833 694374 : state_usage_disk(state, handle, waiting_map, waiting_mac); + 833 693996 : state_usage_disk(state, handle, waiting_map, waiting_mac); 834 : 835 : /* get the results */ - 836 694374 : disk = task->disk; - 837 694374 : block = task->block; - 838 694374 : file = task->file; - 839 694374 : file_pos = task->file_pos; - 840 694374 : read_size = task->read_size; + 836 693996 : disk = task->disk; + 837 693996 : block = task->block; + 838 693996 : file = task->file; + 839 693996 : file_pos = task->file_pos; + 840 693996 : read_size = task->read_size; 841 : 842 : /* by default no rehash in case of "continue" */ - 843 694374 : rehandle[diskcur].block = 0; + 843 693996 : rehandle[diskcur].block = 0; 844 : 845 : /* if the disk position is not used */ - 846 694374 : if (!disk) - 847 108581 : continue; + 846 693996 : if (!disk) + 847 108590 : continue; 848 : - 849 694374 : state_usage_file(state, disk, file); + 849 693996 : state_usage_file(state, disk, file); 850 : 851 : /* get the state of the block */ - 852 694374 : block_state = block_state_get(block); + 852 693996 : block_state = block_state_get(block); 853 : 854 : /* if the block has invalid parity, */ 855 : /* we have to take care of it in case of recover */ - 856 694374 : if (block_has_invalid_parity(block)) { + 856 693996 : if (block_has_invalid_parity(block)) { 857 : /* store it in the failed set, because */ 858 : /* the parity may be still computed with the previous content */ - 859 181710 : failed[failed_count].index = diskcur; - 860 181710 : failed[failed_count].size = state->block_size; - 861 181710 : failed[failed_count].block = block; - 862 181710 : ++failed_count; + 859 181655 : failed[failed_count].index = diskcur; + 860 181655 : failed[failed_count].size = state->block_size; + 861 181655 : failed[failed_count].block = block; + 862 181655 : ++failed_count; 863 : 864 : /* if the block has invalid parity, we have to update the parity */ 865 : /* to include this block change */ 866 : /* This also apply to CHG blocks, but we are going to handle */ 867 : /* later this case to do the updates only if really needed */ - 868 181710 : if (block_state != BLOCK_STATE_CHG) + 868 181655 : if (block_state != BLOCK_STATE_CHG) 869 89419 : parity_needs_to_be_updated = 1; 870 : 871 : /* note that DELETE blocks are skipped in the next check */ @@ -938,28 +938,28 @@ 876 : } 877 : 878 : /* if the block is not used */ - 879 694374 : if (!block_has_file(block)) - 880 107711 : continue; + 879 693996 : if (!block_has_file(block)) + 880 107719 : continue; 881 : 882 : /* handle error conditions */ - 883 586663 : if (task->state == TASK_STATE_IOERROR) { + 883 586277 : if (task->state == TASK_STATE_IOERROR) { 884 : /* LCOV_EXCL_START */ 885 : ++io_error; 886 : goto bail; 887 : /* LCOV_EXCL_STOP */ 888 : } - 889 586663 : if (task->state == TASK_STATE_ERROR) { + 889 586277 : if (task->state == TASK_STATE_ERROR) { 890 : /* LCOV_EXCL_START */ 891 : ++soft_error; 892 : goto bail; 893 : /* LCOV_EXCL_STOP */ 894 : } - 895 586663 : if (task->state == TASK_STATE_ERROR_CONTINUE) { + 895 586277 : if (task->state == TASK_STATE_ERROR_CONTINUE) { 896 18 : ++soft_error; 897 18 : error_on_this_block = 1; 898 18 : continue; 899 : } - 900 586645 : if (task->state == TASK_STATE_IOERROR_CONTINUE) { + 900 586259 : if (task->state == TASK_STATE_IOERROR_CONTINUE) { 901 0 : ++io_error; 902 0 : if (io_error >= state->opt.io_error_limit) { 903 : /* LCOV_EXCL_START */ @@ -973,34 +973,34 @@ 911 0 : io_error_on_this_block = 1; 912 0 : continue; 913 : } - 914 586645 : if (task->state != TASK_STATE_DONE) { + 914 586259 : if (task->state != TASK_STATE_DONE) { 915 : /* LCOV_EXCL_START */ 916 : log_fatal(EINTERNAL, "Internal inconsistency in task state\n"); 917 : os_abort(); 918 : /* LCOV_EXCL_STOP */ 919 : } 920 : - 921 586645 : countsize += read_size; + 921 586259 : countsize += read_size; 922 : 923 : /* now compute the hash */ - 924 586645 : if (rehash) { + 924 586259 : if (rehash) { 925 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[diskcur], read_size); 926 : 927 : /* compute the new hash, and store it */ 928 27243 : rehandle[diskcur].block = block; 929 27243 : memhash(state->hash, state->hashseed, rehandle[diskcur].hash, buffer[diskcur], read_size); 930 : } else { - 931 559402 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); + 931 559016 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); 932 : } 933 : 934 : /* until now is hash */ - 935 586645 : state_usage_hash(state); + 935 586259 : state_usage_hash(state); 936 : - 937 586645 : if (block_has_updated_hash(block)) { + 937 586259 : if (block_has_updated_hash(block)) { 938 : /* compare the hash */ - 939 494372 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 939 494041 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { 940 : /* if the file has invalid parity, it's a REP changed during the sync */ - 941 852 : if (block_has_invalid_parity(block)) { + 941 853 : if (block_has_invalid_parity(block)) { 942 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer)); 943 1 : log_error(ESOFT, "Data change at file '%s' at position '%u'\n", task->path, file_pos); 944 1 : log_error(ESOFT, "WARNING! Unexpected data modification of a file without parity!\n"); @@ -1020,39 +1020,39 @@ 958 : /* this isn't a serious error, so we skip this block, and continue with others */ 959 1 : error_on_this_block = 1; 960 1 : continue; - 961 851 : } else { /* otherwise it's a BLK with silent error */ - 962 851 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); - 963 851 : log_tag("error_data:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); - 964 851 : log_error(EDATA, "Data error in file '%s' at position '%u', diff hash bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); + 961 852 : } else { /* otherwise it's a BLK with silent error */ + 962 852 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + 963 852 : log_tag("error_data:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + 964 852 : log_error(EDATA, "Data error in file '%s' at position '%u', diff hash bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); 965 : 966 : /* save the failed block for the fix */ - 967 851 : failed[failed_count].index = diskcur; - 968 851 : failed[failed_count].size = read_size; - 969 851 : failed[failed_count].block = block; - 970 851 : ++failed_count; + 967 852 : failed[failed_count].index = diskcur; + 968 852 : failed[failed_count].size = read_size; + 969 852 : failed[failed_count].block = block; + 970 852 : ++failed_count; 971 : 972 : /* silent errors are very rare, and are not a signal that a disk */ 973 : /* is going to fail. So, we just continue marking the block as bad */ 974 : /* just like in scrub */ - 975 851 : ++silent_error; - 976 851 : silent_error_on_this_block = 1; - 977 851 : continue; + 975 852 : ++silent_error; + 976 852 : silent_error_on_this_block = 1; + 977 852 : continue; 978 : } 979 : } 980 : } else { 981 : /* if until now the parity doesn't need to be updated */ - 982 92273 : if (!parity_needs_to_be_updated) { + 982 92218 : if (!parity_needs_to_be_updated) { 983 : /* for sure it's a CHG block, because EMPTY are processed before with "continue" */ 984 : /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */ 985 : /* have "parity_needs_to_be_updated" already at 1 */ - 986 34999 : assert(block_state_get(block) == BLOCK_STATE_CHG); + 986 34944 : assert(block_state_get(block) == BLOCK_STATE_CHG); 987 : 988 : /* if the hash represents the data unequivocally */ - 989 34999 : if (hash_is_unique(block->hash)) { + 989 34944 : if (hash_is_unique(block->hash)) { 990 : /* check if the hash is changed */ - 991 6277 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 991 6222 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { 992 : /* the block is different, and we must update parity */ - 993 5157 : parity_needs_to_be_updated = 1; + 993 5105 : parity_needs_to_be_updated = 1; 994 : } 995 : } else { 996 : /* if the hash is already invalid, we update parity */ @@ -1062,7 +1062,7 @@ 1000 : 1001 : /* copy the hash in the block, but doesn't mark the block as hashed */ 1002 : /* this allow in case of skipped block to do not save the failed computation */ - 1003 92273 : memcpy(block->hash, hash, BLOCK_HASH_SIZE); + 1003 92218 : memcpy(block->hash, hash, BLOCK_HASH_SIZE); 1004 : 1005 : /* note that in case of rehash, this is the wrong hash, */ 1006 : /* but it will be overwritten later */ @@ -1072,57 +1072,57 @@ 1010 : /* if we have only silent errors we can try to fix them on-the-fly */ 1011 : /* note the fix is not written to disk, but used only to */ 1012 : /* compute the new parity */ - 1013 115729 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { + 1013 115666 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { 1014 : unsigned failed_mac; - 1015 851 : int something_to_recover = 0; + 1015 852 : int something_to_recover = 0; 1016 : 1017 : /* sort the failed vector */ 1018 : /* because with threads it may be in any order */ 1019 : /* but RAID requires the indexes to be sorted */ - 1020 851 : qsort(failed, failed_count, sizeof(failed[0]), failed_compare_by_index); + 1020 852 : qsort(failed, failed_count, sizeof(failed[0]), failed_compare_by_index); 1021 : 1022 : /* setup the blocks to recover */ - 1023 851 : failed_mac = 0; - 1024 2553 : for (j = 0; j < failed_count; ++j) { - 1025 1702 : unsigned char* block_buffer = buffer[failed[j].index]; - 1026 1702 : unsigned char* block_copy = copy[failed[j].index]; - 1027 1702 : unsigned block_state = block_state_get(failed[j].block); + 1023 852 : failed_mac = 0; + 1024 2556 : for (j = 0; j < failed_count; ++j) { + 1025 1704 : unsigned char* block_buffer = buffer[failed[j].index]; + 1026 1704 : unsigned char* block_copy = copy[failed[j].index]; + 1027 1704 : unsigned block_state = block_state_get(failed[j].block); 1028 : 1029 : /* we try to recover only if at least one BLK is present */ - 1030 1702 : if (block_state == BLOCK_STATE_BLK) - 1031 851 : something_to_recover = 1; + 1030 1704 : if (block_state == BLOCK_STATE_BLK) + 1031 852 : something_to_recover = 1; 1032 : 1033 : /* save a copy of the content just read */ 1034 : /* that it's going to be overwritten by the recovering function */ - 1035 1702 : memcpy(block_copy, block_buffer, state->block_size); + 1035 1704 : memcpy(block_copy, block_buffer, state->block_size); 1036 : - 1037 1702 : if (block_state == BLOCK_STATE_CHG - 1038 851 : && hash_is_zero(failed[j].block->hash) + 1037 1704 : if (block_state == BLOCK_STATE_CHG + 1038 852 : && hash_is_zero(failed[j].block->hash) 1039 : ) { 1040 : /* if the block was filled with 0, restore this state */ 1041 : /* and avoid to recover it */ 1042 0 : memset(block_buffer, 0, state->block_size); 1043 : } else { 1044 : /* if we have too many failures, we cannot recover */ - 1045 1702 : if (failed_mac >= state->level) + 1045 1704 : if (failed_mac >= state->level) 1046 0 : break; 1047 : 1048 : /* otherwise it has to be recovered */ - 1049 1702 : failed_map[failed_mac++] = failed[j].index; + 1049 1704 : failed_map[failed_mac++] = failed[j].index; 1050 : } 1051 : } 1052 : 1053 : /* if we have something to recover and enough parity */ - 1054 851 : if (something_to_recover && j == failed_count) { + 1054 852 : if (something_to_recover && j == failed_count) { 1055 : /* until now is misc */ - 1056 851 : state_usage_misc(state); + 1056 852 : state_usage_misc(state); 1057 : 1058 : /* read the parity */ 1059 : /* we are sure that parity exists because */ 1060 : /* we have at least one BLK block */ - 1061 5957 : for (l = 0; l < state->level; ++l) { - 1062 5106 : ret = parity_read(&parity_handle[l], blockcur, buffer[diskmax + l], state->block_size, log_error); - 1063 5106 : if (ret == -1) { + 1061 5964 : for (l = 0; l < state->level; ++l) { + 1062 5112 : ret = parity_read(&parity_handle[l], blockcur, buffer[diskmax + l], state->block_size, log_error); + 1063 5112 : if (ret == -1) { 1064 : /* LCOV_EXCL_START */ 1065 : log_tag("parity_%s:%u:%s: Read error. %s.\n", es(errno), blockcur, lev_config_name(l), strerror(errno)); 1066 : if (is_hw(errno)) { @@ -1147,103 +1147,103 @@ 1085 : } 1086 : 1087 : /* until now is parity */ - 1088 5106 : state_usage_parity(state, &l, 1); + 1088 5112 : state_usage_parity(state, &l, 1); 1089 : } 1090 : 1091 : /* if no error in parity read */ - 1092 851 : if (!io_error_on_this_block) { + 1092 852 : if (!io_error_on_this_block) { 1093 : /* try to fix the data */ 1094 : /* note that this is a simple fix algorithm, that doesn't take into */ 1095 : /* account the case of a wrong parity */ 1096 : /* only 'fix' supports the most advanced fixing */ - 1097 851 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer); + 1097 852 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer); 1098 : 1099 : /* until now is raid */ - 1100 851 : state_usage_raid(state); + 1100 852 : state_usage_raid(state); 1101 : 1102 : /* check the result and prepare the data */ - 1103 2553 : for (j = 0; j < failed_count; ++j) { + 1103 2556 : for (j = 0; j < failed_count; ++j) { 1104 : unsigned char hash[HASH_MAX]; - 1105 1702 : unsigned char* block_buffer = buffer[failed[j].index]; - 1106 1702 : unsigned char* block_copy = copy[failed[j].index]; - 1107 1702 : unsigned block_state = block_state_get(failed[j].block); + 1105 1704 : unsigned char* block_buffer = buffer[failed[j].index]; + 1106 1704 : unsigned char* block_copy = copy[failed[j].index]; + 1107 1704 : unsigned block_state = block_state_get(failed[j].block); 1108 : - 1109 1702 : if (block_state == BLOCK_STATE_BLK) { - 1110 851 : unsigned size = failed[j].size; + 1109 1704 : if (block_state == BLOCK_STATE_BLK) { + 1110 852 : unsigned size = failed[j].size; 1111 : 1112 : /* compute the hash of the recovered block */ - 1113 851 : if (rehash) { + 1113 852 : if (rehash) { 1114 0 : memhash(state->prevhash, state->prevhashseed, hash, block_buffer, size); 1115 : } else { - 1116 851 : memhash(state->hash, state->hashseed, hash, block_buffer, size); + 1116 852 : memhash(state->hash, state->hashseed, hash, block_buffer, size); 1117 : } 1118 : 1119 : /* until now is hash */ - 1120 851 : state_usage_hash(state); + 1120 852 : state_usage_hash(state); 1121 : 1122 : /* if the hash doesn't match */ - 1123 851 : if (memcmp(hash, failed[j].block->hash, BLOCK_HASH_SIZE) != 0) { + 1123 852 : if (memcmp(hash, failed[j].block->hash, BLOCK_HASH_SIZE) != 0) { 1124 : /* we have not recovered */ 1125 0 : break; 1126 : } 1127 : 1128 : /* pad with 0 if needed */ - 1129 851 : if (size < state->block_size) - 1130 348 : memset(block_buffer + size, 0, state->block_size - size); + 1129 852 : if (size < state->block_size) + 1130 335 : memset(block_buffer + size, 0, state->block_size - size); 1131 : } else { 1132 : /* otherwise restore the content */ 1133 : /* because we are not interested in the old state */ 1134 : /* that it's recovered for CHG, REP and DELETED blocks */ - 1135 851 : memcpy(block_buffer, block_copy, state->block_size); + 1135 852 : memcpy(block_buffer, block_copy, state->block_size); 1136 : } 1137 : } 1138 : 1139 : /* if all is processed, we have fixed it */ - 1140 851 : if (j == failed_count) - 1141 851 : fixed_error_on_this_block = 1; + 1140 852 : if (j == failed_count) + 1141 852 : fixed_error_on_this_block = 1; 1142 : } 1143 : } 1144 : } 1145 : 1146 : /* if we have read all the data required and it's correct, proceed with the parity */ - 1147 115729 : if (!error_on_this_block && !io_error_on_this_block - 1148 115710 : && (!silent_error_on_this_block || fixed_error_on_this_block) + 1147 115666 : if (!error_on_this_block && !io_error_on_this_block + 1148 115647 : && (!silent_error_on_this_block || fixed_error_on_this_block) 1149 : ) { 1150 : /* update the parity only if really needed */ - 1151 115710 : if (parity_needs_to_be_updated) { + 1151 115647 : if (parity_needs_to_be_updated) { 1152 : /* compute the parity */ - 1153 114798 : raid_gen(diskmax, state->level, state->block_size, buffer); + 1153 114746 : raid_gen(diskmax, state->level, state->block_size, buffer); 1154 : 1155 : /* until now is raid */ - 1156 114798 : state_usage_raid(state); + 1156 114746 : state_usage_raid(state); 1157 : 1158 : /* mark that the parity is going to be written */ - 1159 114798 : parity_going_to_be_updated = 1; + 1159 114746 : parity_going_to_be_updated = 1; 1160 : } 1161 : 1162 : /* for each disk, mark the blocks as processed */ - 1163 809970 : for (j = 0; j < diskmax; ++j) { + 1163 809529 : for (j = 0; j < diskmax; ++j) { 1164 : struct snapraid_block* block; 1165 : - 1166 694260 : if (!handle[j].disk) + 1166 693882 : if (!handle[j].disk) 1167 0 : continue; 1168 : - 1169 694260 : block = fs_par2block_find(handle[j].disk, blockcur); + 1169 693882 : block = fs_par2block_find(handle[j].disk, blockcur); 1170 : - 1171 694260 : if (block == BLOCK_NULL) { + 1171 693882 : if (block == BLOCK_NULL) { 1172 : /* nothing to do */ - 1173 96586 : continue; + 1173 96594 : continue; 1174 : } 1175 : 1176 : /* if it's a deleted block */ - 1177 597674 : if (block_state_get(block) == BLOCK_STATE_DELETED) { + 1177 597288 : if (block_state_get(block) == BLOCK_STATE_DELETED) { 1178 : /* the parity is now updated without this block, so it's now empty */ 1179 11123 : fs_deallocate(handle[j].disk, blockcur); 1180 11123 : continue; 1181 : } 1182 : 1183 : /* now all the blocks have the hash and the parity computed */ - 1184 586551 : block_state_set(block, BLOCK_STATE_BLK); + 1184 586165 : block_state_set(block, BLOCK_STATE_BLK); 1185 : } 1186 : 1187 : /* we update the info block only if we really have updated the parity */ @@ -1251,11 +1251,11 @@ 1189 : /* wrote the parity at this time */ 1190 : /* we also update the info block only if no silent error was found */ 1191 : /* because has no sense to refresh the time for data that we know bad */ - 1192 115710 : if (parity_needs_to_be_updated - 1193 114798 : && !silent_error_on_this_block + 1192 115647 : if (parity_needs_to_be_updated + 1193 114746 : && !silent_error_on_this_block 1194 : ) { 1195 : /* if rehash is needed */ - 1196 113947 : if (rehash) { + 1196 113895 : if (rehash) { 1197 : /* store all the new hash already computed */ 1198 32249 : for (j = 0; j < diskmax; ++j) { 1199 27642 : if (rehandle[j].block) @@ -1265,43 +1265,43 @@ 1203 : 1204 : /* update the time info of the block */ 1205 : /* we are also clearing any previous bad and rehash flag */ - 1206 113947 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1)); + 1206 113895 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1)); 1207 : } 1208 : } 1209 : 1210 : /* if a silent (even if corrected) or input/output error was found */ 1211 : /* mark the block as bad to have check/fix to handle it */ 1212 : /* because our correction is in memory only and not yet written */ - 1213 115729 : if (silent_error_on_this_block || io_error_on_this_block) { + 1213 115666 : if (silent_error_on_this_block || io_error_on_this_block) { 1214 : /* set the error status keeping the other info */ - 1215 851 : info_set(&state->infoarr, blockcur, info_set_bad(info)); + 1215 852 : info_set(&state->infoarr, blockcur, info_set_bad(info)); 1216 : } 1217 : 1218 : /* finally schedule parity write */ 1219 : /* Note that the calls to io_parity_write() are mandatory */ 1220 : /* even if the parity doesn't need to be updated */ 1221 : /* This because we want to keep track of the time usage */ - 1222 115729 : state_usage_misc(state); + 1222 115666 : state_usage_misc(state); 1223 : 1224 : /* write start */ - 1225 115729 : io_write_preset(&io, blockcur, !parity_going_to_be_updated); + 1225 115666 : io_write_preset(&io, blockcur, !parity_going_to_be_updated); 1226 : 1227 : /* write the parity */ - 1228 679998 : for (l = 0; l < state->level; ++l) { + 1228 679557 : for (l = 0; l < state->level; ++l) { 1229 : unsigned levcur; 1230 : - 1231 564269 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac); + 1231 563891 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac); 1232 : 1233 : /* until now is parity */ - 1234 564269 : state_usage_parity(state, waiting_map, waiting_mac); + 1234 563891 : state_usage_parity(state, waiting_map, waiting_mac); 1235 : } 1236 : 1237 : /* write finished */ - 1238 115729 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error); + 1238 115666 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error); 1239 : 1240 : /* handle errors reported */ - 1241 578645 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) { - 1242 462916 : if (writer_error[j]) { + 1241 578330 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) { + 1242 462664 : if (writer_error[j]) { 1243 0 : switch (j + IO_WRITER_ERROR_BASE) { 1244 0 : case TASK_STATE_IOERROR_CONTINUE : 1245 0 : ++io_error; @@ -1331,20 +1331,20 @@ 1269 : } 1270 : 1271 : /* mark the state as needing write */ - 1272 115729 : state->need_write = 1; + 1272 115666 : state->need_write = 1; 1273 : 1274 : /* count the number of processed block */ - 1275 115729 : ++countpos; + 1275 115666 : ++countpos; 1276 : 1277 : /* progress */ - 1278 115729 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { + 1278 115666 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { 1279 : /* LCOV_EXCL_START */ 1280 : break; 1281 : /* LCOV_EXCL_STOP */ 1282 : } 1283 : 1284 : /* thermal control */ - 1285 115729 : if (state_thermal_alarm(state)) { + 1285 115666 : if (state_thermal_alarm(state)) { 1286 : /* until now is misc */ 1287 0 : state_usage_misc(state); 1288 : @@ -1369,11 +1369,11 @@ 1307 : } 1308 : 1309 : /* autosave */ - 1310 115729 : if ((state->autosave != 0 + 1310 115666 : if ((state->autosave != 0 1311 26021 : && autosavedone >= autosavelimit /* if we have reached the limit */ 1312 0 : && autosavemissing >= autosavelimit) /* if we have at least a full step to do */ 1313 : /* or if we have a forced autosave at the specified block */ - 1314 115729 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur) + 1314 115666 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur) 1315 : ) { 1316 1 : autosavedone = 0; /* restart the counter */ 1317 : @@ -1422,7 +1422,7 @@ 1360 : /* save the new state if required */ 1361 88 : if (!state->opt.kill_after_sync) { 1362 78 : if ((state->need_write || state->opt.force_content_write)) - 1363 62 : state_write(state); + 1363 61 : state_write(state); 1364 : } else { 1365 10 : log_fatal(EUSER, "WARNING! Skipped writing state due to --test-kill-after-sync option.\n"); 1366 : } @@ -1437,7 +1437,7 @@ 1375 : } else { 1376 : /* print the result only if processed something */ 1377 76 : if (countpos != 0) - 1378 58 : msg_status("Everything OK\n"); + 1378 57 : msg_status("Everything OK\n"); 1379 : } 1380 : 1381 88 : if (soft_error) diff --git a/cov/cmdline/thermal.c.func-sort-c.html b/cov/cmdline/thermal.c.func-sort-c.html index 73b12a34..d5c8aa27 100644 --- a/cov/cmdline/thermal.c.func-sort-c.html +++ b/cov/cmdline/thermal.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 @@ -81,11 +81,11 @@ state_thermal - 2614 + 2613 state_thermal_alarm - 1062627 + 1062564
diff --git a/cov/cmdline/thermal.c.func.html b/cov/cmdline/thermal.c.func.html index 28995b42..694ec2bb 100644 --- a/cov/cmdline/thermal.c.func.html +++ b/cov/cmdline/thermal.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 @@ -65,11 +65,11 @@ state_thermal - 2614 + 2613 state_thermal_alarm - 1062627 + 1062564 state_thermal_begin diff --git a/cov/cmdline/thermal.c.gcov.html b/cov/cmdline/thermal.c.gcov.html index 845bcca9..f53c4f1d 100644 --- a/cov/cmdline/thermal.c.gcov.html +++ b/cov/cmdline/thermal.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 @@ -184,7 +184,7 @@ 122 30 : return model; 123 : } 124 : - 125 2614 : void state_thermal(struct snapraid_state* state, time_t now) + 125 2613 : void state_thermal(struct snapraid_state* state, time_t now) 126 : { 127 : tommy_node* i; 128 : unsigned j; @@ -192,8 +192,8 @@ 130 : tommy_list low; 131 : int ret; 132 : - 133 2614 : if (state->thermal_temperature_limit == 0) - 134 198 : return; + 133 2613 : if (state->thermal_temperature_limit == 0) + 134 197 : return; 135 : 136 2416 : tommy_list_init(&high); 137 2416 : tommy_list_init(&low); @@ -362,11 +362,11 @@ 300 2416 : tommy_list_foreach(&low, free); 301 : } 302 : - 303 1062627 : int state_thermal_alarm(struct snapraid_state* state) + 303 1062564 : int state_thermal_alarm(struct snapraid_state* state) 304 : { 305 : /* if no limit, there is no thermal support */ - 306 1062627 : if (state->thermal_temperature_limit == 0) - 307 1060211 : return 0; + 306 1062564 : if (state->thermal_temperature_limit == 0) + 307 1060148 : return 0; 308 : 309 2416 : if (state->thermal_highest_temperature <= state->thermal_temperature_limit) 310 2416 : return 0; diff --git a/cov/cmdline/touch.c.func-sort-c.html b/cov/cmdline/touch.c.func-sort-c.html index dbfc39f1..c58b1e91 100644 --- a/cov/cmdline/touch.c.func-sort-c.html +++ b/cov/cmdline/touch.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/touch.c.func.html b/cov/cmdline/touch.c.func.html index fb7a9feb..26a7b3be 100644 --- a/cov/cmdline/touch.c.func.html +++ b/cov/cmdline/touch.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/touch.c.gcov.html b/cov/cmdline/touch.c.gcov.html index 1a7412ad..b724a670 100644 --- a/cov/cmdline/touch.c.gcov.html +++ b/cov/cmdline/touch.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/cmdline/unix.c.func-sort-c.html b/cov/cmdline/unix.c.func-sort-c.html index 3b92bb56..2d0c0a14 100644 --- a/cov/cmdline/unix.c.func-sort-c.html +++ b/cov/cmdline/unix.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 381 - 678 - 56.2 % + 475 + 673 + 70.6 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 31 + 35 42 - 73.8 % + 83.3 % @@ -60,27 +60,15 @@ Hit count Sort by hit count - devattr + devdownifup 0 - devdownifup + devsmart 0 - devprobe - 0 - - - devscan - 0 - - - devsmart - 0 - - - devuuid_blkid + devuuid_blkid 0 @@ -92,140 +80,152 @@ 0 - thread_probe + thread_smart 0 - thread_smart + thread_spindownifup 0 - thread_spindownifup - 0 - - - ambient_temperature + ambient_temperature 1 - os_clear + devscan 1 - device_thread - 2 + os_clear + 1 - devquery + device_thread 3 - devdereference + devdereference 4 - devresolve_proc + devquery 4 - devdown + devresolve_proc + 4 + + + devdown 5 - find_smartctl + thread_spindown 5 - thread_spindown - 5 - - - direct_size + direct_size 7 - sysattr - 12 + devattr + 14 - devup + devprobe + 14 + + + thread_probe + 14 + + + find_smartctl + 19 + + + devup 30 - thread_spinup + thread_spinup 30 - devstat - 65 + sysattr + 62 - devread - 130 + devstat + 77 - devtree - 130 + devtree + 154 - devresolve - 165 + devread + 168 - devresolve_sys - 165 + devresolve + 205 - tagread - 165 + devresolve_sys + 205 + + + tagread + 205 + + + os_done + 273 + + + os_init + 284 + + + randomize + 295 sysread - 242 + 358 - os_done - 272 + tick_ms + 3567 - os_init - 283 - - - randomize - 294 - - - tick_ms - 3581 - - - devuuid_label + devuuid_label 5759 - fsinfo + fsinfo 6412 - devuuid_dev - 10544 + devuuid_dev + 10556 - devuuid - 10548 + devuuid + 10560 - filephy + filephy 11432 open_noatime - 1714013 + 1713822 - tick - 3817826 + tick + 3816139
diff --git a/cov/cmdline/unix.c.func.html b/cov/cmdline/unix.c.func.html index da140618..bf6927b9 100644 --- a/cov/cmdline/unix.c.func.html +++ b/cov/cmdline/unix.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 381 - 678 - 56.2 % + 475 + 673 + 70.6 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 31 + 35 42 - 73.8 % + 83.3 % @@ -60,91 +60,91 @@ Hit count Sort by hit count - ambient_temperature + ambient_temperature 1 - devattr - 0 + devattr + 14 - devdereference + devdereference 4 - devdown + devdown 5 - devdownifup + devdownifup 0 - device_thread - 2 - - - devprobe - 0 - - - devquery + device_thread 3 - devread - 130 + devprobe + 14 - devresolve - 165 - - - devresolve_proc + devquery 4 - devresolve_sys - 165 + devread + 168 - devscan + devresolve + 205 + + + devresolve_proc + 4 + + + devresolve_sys + 205 + + + devscan + 1 + + + devsmart 0 - devsmart - 0 + devstat + 77 - devstat - 65 + devtree + 154 - devtree - 130 - - - devup + devup 30 - devuuid - 10548 + devuuid + 10560 - devuuid_blkid + devuuid_blkid 0 - devuuid_dev - 10544 + devuuid_dev + 10556 - devuuid_label + devuuid_label 5759 - direct_size + direct_size 7 @@ -152,80 +152,80 @@ 0 - filephy + filephy 11432 find_smartctl - 5 + 19 - fsinfo + fsinfo 6412 open_noatime - 1714013 + 1713822 - os_clear + os_clear 1 - os_done - 272 + os_done + 273 - os_init - 283 + os_init + 284 - randomize - 294 + randomize + 295 stat_desc 0 - sysattr - 12 + sysattr + 62 sysread - 242 + 358 - tagread - 165 + tagread + 205 - thread_probe + thread_probe + 14 + + + thread_smart 0 - thread_smart - 0 - - - thread_spindown + thread_spindown 5 - thread_spindownifup + thread_spindownifup 0 - thread_spinup + thread_spinup 30 - tick - 3817826 + tick + 3816139 - tick_ms - 3581 + tick_ms + 3567
diff --git a/cov/cmdline/unix.c.gcov.html b/cov/cmdline/unix.c.gcov.html index 77993dca..374b6972 100644 --- a/cov/cmdline/unix.c.gcov.html +++ b/cov/cmdline/unix.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 381 - 678 - 56.2 % + 475 + 673 + 70.6 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 31 + 35 42 - 73.8 % + 83.3 % @@ -90,15 +90,15 @@ 28 : int exit_failure = 1; 29 : int exit_sync_needed = 2; 30 : - 31 1714013 : int open_noatime(const char* file, int flags) + 31 1713822 : int open_noatime(const char* file, int flags) 32 : { 33 : #ifdef O_NOATIME - 34 1714013 : int f = open(file, flags | O_NOATIME); + 34 1713822 : int f = open(file, flags | O_NOATIME); 35 : 36 : /* only root is allowed to use O_NOATIME, in case retry without it */ - 37 1714013 : if (f == -1 && errno == EPERM) + 37 1713822 : if (f == -1 && errno == EPERM) 38 0 : f = open(file, flags); - 39 1714013 : return f; + 39 1713822 : return f; 40 : #else 41 : return open(file, flags); 42 : #endif @@ -142,13 +142,13 @@ 80 : 0 81 : }; 82 : - 83 5 : const char* find_smartctl(void) + 83 19 : const char* find_smartctl(void) 84 : { 85 : int i; 86 : - 87 5 : for (i = 0; smartctl_paths[i]; ++i) { - 88 5 : if (access(smartctl_paths[i], X_OK) == 0) - 89 5 : return smartctl_paths[i]; + 87 19 : for (i = 0; smartctl_paths[i]; ++i) { + 88 19 : if (access(smartctl_paths[i], X_OK) == 0) + 89 19 : return smartctl_paths[i]; 90 : } 91 : 92 0 : return 0; @@ -160,35 +160,35 @@ 98 : * Return -1 on error, otherwise the size of data read 99 : */ 100 : #if HAVE_LINUX_DEVICE - 101 242 : static int sysread(const char* path, char* buf, size_t buf_size) + 101 358 : static int sysread(const char* path, char* buf, size_t buf_size) 102 : { 103 : int f; 104 : int ret; 105 : int len; 106 : - 107 242 : f = open(path, O_RDONLY); - 108 242 : if (f == -1) { + 107 358 : f = open(path, O_RDONLY); + 108 358 : if (f == -1) { 109 : /* LCOV_EXCL_START */ 110 : return -1; 111 : /* LCOV_EXCL_STOP */ 112 : } 113 : - 114 242 : len = read(f, buf, buf_size); - 115 242 : if (len < 0) { + 114 344 : len = read(f, buf, buf_size); + 115 344 : if (len < 0) { 116 : /* LCOV_EXCL_START */ 117 : close(f); 118 : return -1; 119 : /* LCOV_EXCL_STOP */ 120 : } 121 : - 122 242 : ret = close(f); - 123 242 : if (ret != 0) { + 122 344 : ret = close(f); + 123 344 : if (ret != 0) { 124 : /* LCOV_EXCL_START */ 125 : return -1; 126 : /* LCOV_EXCL_STOP */ 127 : } 128 : - 129 242 : return len; + 129 344 : return len; 130 : } 131 : #endif 132 : @@ -197,2408 +197,2402 @@ 135 : * Trim spaces. 136 : * Always put an ending 0. 137 : * Do not report error on reading. - 138 : * - 139 : * Return 0 on error, otherwise a pointer to buf - 140 : */ - 141 : #if HAVE_LINUX_DEVICE - 142 12 : static char* sysattr(const char* path, char* buf, size_t buf_size) - 143 : { - 144 : int len; - 145 : - 146 12 : len = sysread(path, buf, buf_size); - 147 12 : if (len < 0) { - 148 : /* LCOV_EXCL_START */ - 149 : return 0; - 150 : /* LCOV_EXCL_STOP */ - 151 : } - 152 : - 153 12 : if ((size_t)len + 1 > buf_size) { - 154 : /* LCOV_EXCL_START */ - 155 : return 0; - 156 : /* LCOV_EXCL_STOP */ - 157 : } - 158 : - 159 12 : buf[len] = 0; - 160 : - 161 12 : strtrim(buf); - 162 : - 163 12 : return buf; - 164 : } - 165 : #endif - 166 : - 167 : /** - 168 : * Get the device file from the device number. - 169 : * - 170 : * It uses /proc/self/mountinfo. - 171 : * - 172 : * Null devices (major==0) are resolved to the device indicated in mountinfo. - 173 : */ - 174 : #if HAVE_LINUX_DEVICE - 175 4 : static int devresolve_proc(uint64_t device, char* path, size_t path_size) - 176 : { - 177 : FILE* f; - 178 : char match[32]; - 179 : - 180 : /* generate the matching string */ - 181 4 : snprintf(match, sizeof(match), "%u:%u", major(device), minor(device)); - 182 : - 183 4 : f = fopen("/proc/self/mountinfo", "r"); - 184 4 : if (!f) { - 185 0 : log_tag("resolve:proc:%u:%u: failed to open /proc/self/mountinfo\n", major(device), minor(device)); - 186 0 : return -1; - 187 : } - 188 : - 189 : /* - 190 : * mountinfo format - 191 : * 0 - mount ID - 192 : * 1 - parent ID - 193 : * 2 - major:minor - 194 : * 3 - root - 195 : * 4 - mount point - 196 : * 5 - options - 197 : * 6 - "-" (separator) - 198 : * 7 - fs - 199 : * 8 - mount source - /dev/device - 200 : */ - 201 : - 202 192 : while (1) { - 203 : char buf[256]; - 204 : char* first_map[8]; - 205 : unsigned first_mac; - 206 : char* second_map[8]; - 207 : unsigned second_mac; - 208 : char* s; - 209 : struct stat st; - 210 : char* separator; - 211 : char* majorminor; - 212 : char* mountpoint; - 213 : char* fs; - 214 : char* mountsource; - 215 : - 216 196 : s = fgets(buf, sizeof(buf), f); - 217 196 : if (s == 0) - 218 4 : break; - 219 : - 220 : /* find the separator position */ - 221 192 : separator = strstr(s, " - "); - 222 192 : if (!separator) - 223 0 : continue; - 224 : - 225 : /* skip the separator */ - 226 192 : *separator = 0; - 227 192 : separator += 3; - 228 : - 229 : /* split the line */ - 230 192 : first_mac = strsplit(first_map, 8, s, " \t\r\n"); - 231 192 : second_mac = strsplit(second_map, 8, separator, " \t\r\n"); - 232 : - 233 : /* if too short, it's the wrong line */ - 234 192 : if (first_mac < 5) - 235 0 : continue; - 236 192 : if (second_mac < 2) - 237 0 : continue; - 238 : - 239 192 : majorminor = first_map[2]; - 240 192 : mountpoint = first_map[4]; - 241 192 : fs = second_map[0]; - 242 192 : mountsource = second_map[1]; - 243 : - 244 : /* compare major:minor from mountinfo */ - 245 192 : if (strcmp(majorminor, match) == 0) { - 246 : /* - 247 : * Accept only /dev/... mountsource - 248 : * - 249 : * This excludes ZFS that uses a bare label for mountsource, like "tank". - 250 : * - 251 : * 410 408 0:193 / /XXX rw,relatime shared:217 - zfs tank/system/data/var/lib/docker/XXX rw,xattr,noacl - 252 : * - 253 : * Also excludes AUTOFS unmounted devices that point to a fake filesystem - 254 : * used to remount them at the first use. - 255 : * - 256 : * 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 - 257 : */ - 258 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { - 259 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); - 260 0 : continue; - 261 : } - 262 : - 263 0 : pathcpy(path, path_size, mountsource); - 264 : - 265 0 : log_tag("resolve:proc:%u:%u: found device %s matching device %s\n", major(device), minor(device), path, match); - 266 : - 267 0 : fclose(f); - 268 0 : return 0; - 269 : } - 270 : - 271 : /* get the device of the mount point */ - 272 : /* in Btrfs it could be different than the one in mountinfo */ - 273 192 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) { - 274 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { - 275 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); - 276 0 : continue; - 277 : } - 278 : - 279 0 : pathcpy(path, path_size, mountsource); - 280 : - 281 0 : log_tag("resolve:proc:%u:%u: found device %s matching mountpoint %s\n", major(device), minor(device), path, mountpoint); - 282 : - 283 0 : fclose(f); - 284 0 : return 0; - 285 : } - 286 : } - 287 : - 288 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device)); - 289 : - 290 4 : fclose(f); - 291 4 : return -1; - 292 : } - 293 : #endif - 294 : - 295 : /** - 296 : * Get the device of a virtual superblock. - 297 : * - 298 : * This is intended to resolve the case of Btrfs filesystems that - 299 : * create a virtual superblock (major==0) not backed by any low - 300 : * level device. - 301 : * - 302 : * See: - 303 : * Bug 711881 - too funny btrfs st_dev numbers - 304 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881 - 305 : */ - 306 : #if HAVE_LINUX_DEVICE - 307 4 : static int devdereference(uint64_t device, uint64_t* new_device) - 308 : { - 309 : char path[PATH_MAX]; - 310 : struct stat st; - 311 : - 312 : /* use the proc interface to get the device containing the filesystem */ - 313 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) { - 314 : /* LCOV_EXCL_START */ - 315 : return -1; - 316 : /* LCOV_EXCL_STOP */ - 317 : } - 318 : - 319 : /* check the device */ - 320 0 : if (stat(path, &st) != 0) { - 321 : /* LCOV_EXCL_START */ - 322 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path); - 323 : return -1; - 324 : /* LCOV_EXCL_STOP */ - 325 : } - 326 : - 327 0 : if (major(st.st_rdev) == 0) { - 328 : /* LCOV_EXCL_START */ - 329 : 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)); - 330 : return -1; - 331 : /* LCOV_EXCL_STOP */ - 332 : } - 333 : - 334 0 : *new_device = st.st_rdev; - 335 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev)); - 336 0 : return 0; - 337 : } - 338 : #endif - 339 : - 340 : /** - 341 : * Read a file extracting the specified tag TAG=VALUE format. - 342 : * Return !=0 on error. - 343 : */ - 344 : #if HAVE_LINUX_DEVICE - 345 165 : static int tagread(const char* path, const char* tag, char* value, size_t value_size) - 346 : { - 347 : int ret; - 348 : char buf[512]; - 349 : size_t tag_len; - 350 : char* i; - 351 : char* e; - 352 : - 353 165 : ret = sysread(path, buf, sizeof(buf)); - 354 165 : if (ret < 0) { - 355 : /* LCOV_EXCL_START */ - 356 : log_fatal(errno, "Failed to read '%s'.\n", path); - 357 : return -1; - 358 : /* LCOV_EXCL_STOP */ - 359 : } - 360 165 : if ((size_t)ret + 1 > sizeof(buf)) { - 361 : /* LCOV_EXCL_START */ - 362 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); - 363 : return -1; - 364 : /* LCOV_EXCL_STOP */ - 365 : } - 366 : - 367 : /* ending 0 */ - 368 165 : buf[ret] = 0; - 369 : - 370 165 : tag_len = strlen(tag); - 371 : - 372 2870 : for (i = buf; *i; ++i) { - 373 2870 : char* p = i; - 374 : - 375 : /* start with a space */ - 376 2870 : if (p != buf) { - 377 2705 : if (!isspace(*p)) - 378 2375 : continue; - 379 330 : ++p; - 380 : } - 381 : - 382 495 : if (strncmp(p, tag, tag_len) != 0) - 383 330 : continue; - 384 165 : p += tag_len; - 385 : - 386 : /* end with a = */ - 387 165 : if (*p != '=') - 388 0 : continue; - 389 165 : ++p; - 390 : - 391 : /* found */ - 392 165 : i = p; - 393 165 : break; - 394 : } - 395 165 : if (!*i) { - 396 : /* LCOV_EXCL_START */ - 397 : log_fatal(EEXTERNAL, "Missing tag '%s' for '%s'.\n", tag, path); - 398 : return -1; - 399 : /* LCOV_EXCL_STOP */ - 400 : } - 401 : - 402 : /* terminate at the first space */ - 403 165 : e = i; - 404 725 : while (*e != 0 && !isspace(*e)) - 405 560 : ++e; - 406 165 : *e = 0; - 407 : - 408 165 : if (!*i) { - 409 : /* LCOV_EXCL_START */ - 410 : log_fatal(EEXTERNAL, "Empty tag '%s' for '%s'.\n", tag, path); - 411 : return -1; - 412 : /* LCOV_EXCL_STOP */ - 413 : } - 414 : - 415 165 : pathprint(value, value_size, "%s", i); - 416 : - 417 165 : return 0; - 418 : } - 419 : #endif - 420 : - 421 : /** - 422 : * Get the device file from the device number. - 423 : * - 424 : * It uses /sys/dev/block/.../uevent. - 425 : * - 426 : * For null device (major==0) it fails. - 427 : */ - 428 : #if HAVE_LINUX_DEVICE - 429 165 : static int devresolve_sys(dev_t device, char* path, size_t path_size) - 430 : { - 431 : struct stat st; - 432 : char buf[PATH_MAX]; - 433 : - 434 : /* default device path from device number */ - 435 165 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device)); - 436 : - 437 165 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) { - 438 : /* LCOV_EXCL_START */ - 439 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path); - 440 : return -1; - 441 : /* LCOV_EXCL_STOP */ - 442 : } - 443 : - 444 : /* set the real device path */ - 445 165 : pathprint(path, path_size, "/dev/%s", buf); - 446 : - 447 : /* check the device */ - 448 165 : if (stat(path, &st) != 0) { - 449 : /* LCOV_EXCL_START */ - 450 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path); - 451 : return -1; - 452 : /* LCOV_EXCL_STOP */ - 453 : } - 454 165 : if (st.st_rdev != device) { - 455 : /* LCOV_EXCL_START */ - 456 : 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); - 457 : return -1; - 458 : /* LCOV_EXCL_STOP */ - 459 : } - 460 : - 461 165 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path); - 462 : - 463 165 : return 0; - 464 : } - 465 : #endif - 466 : - 467 : /** - 468 : * Get the device file from the device number. - 469 : */ - 470 : #if HAVE_LINUX_DEVICE - 471 165 : static int devresolve(uint64_t device, char* path, size_t path_size) - 472 : { - 473 165 : if (devresolve_sys(device, path, path_size) == 0) - 474 165 : return 0; - 475 : - 476 0 : return -1; - 477 : } - 478 : #endif - 479 : - 480 : /** - 481 : * Cache used by blkid. - 482 : */ - 483 : #if HAVE_BLKID - 484 : static blkid_cache cache = 0; - 485 : #endif - 486 : - 487 : /** - 488 : * Get the UUID using the /dev/disk/by-uuid/ links. - 489 : * It doesn't require root permission, and the uuid are always updated. - 490 : * It doesn't work with Btrfs file-systems that don't export the main UUID - 491 : * in /dev/disk/by-uuid/. - 492 : */ - 493 : #if HAVE_LINUX_DEVICE - 494 10544 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) - 495 : { - 496 : int ret; - 497 : DIR* d; - 498 : struct dirent* dd; - 499 : struct stat st; - 500 : - 501 : /* scan the UUID directory searching for the device */ - 502 10544 : d = opendir("/dev/disk/by-uuid"); - 503 10544 : if (!d) { - 504 0 : log_tag("uuid:by-uuid:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); - 505 : /* directory missing?, likely we are not in Linux */ - 506 0 : return -1; - 507 : } - 508 : - 509 10544 : int dir_fd = dirfd(d); - 510 10544 : if (dir_fd == -1) { - 511 0 : log_tag("uuid:by-uuid:%u:%u: dirfd(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); - 512 0 : return -1; - 513 : } - 514 : - 515 168704 : while ((dd = readdir(d)) != 0) { - 516 : /* skip "." and ".." files, UUIDs never start with '.' */ - 517 168704 : if (dd->d_name[0] == '.') - 518 21088 : continue; - 519 : - 520 147616 : ret = fstatat(dir_fd, dd->d_name, &st, 0); - 521 147616 : if (ret != 0) { - 522 0 : log_tag("uuid:by-uuid:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); - 523 : /* generic error, ignore and continue the search */ - 524 0 : continue; - 525 : } - 526 : - 527 : /* if it matches, we have the uuid */ - 528 147616 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { - 529 : char buf[PATH_MAX]; - 530 : char path[PATH_MAX]; - 531 : - 532 : /* resolve the link */ - 533 10544 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); - 534 10544 : ret = readlink(path, buf, sizeof(buf)); - 535 10544 : if (ret < 0 || ret >= PATH_MAX) { - 536 0 : log_tag("uuid:by-uuid:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); - 537 : /* generic error, ignore and continue the search */ - 538 0 : continue; - 539 : } - 540 10544 : buf[ret] = 0; - 541 : - 542 : /* found */ - 543 10544 : pathcpy(uuid, uuid_size, dd->d_name); - 544 : - 545 10544 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); - 546 : - 547 10544 : closedir(d); - 548 10544 : return 0; - 549 : } - 550 : } - 551 : - 552 0 : log_tag("uuid:by-uuid:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device)); - 553 : - 554 : /* not found */ - 555 0 : closedir(d); - 556 0 : return -1; - 557 : } - 558 : #endif - 559 : - 560 : /** - 561 : * Get the UUID using libblkid. - 562 : * It uses a cache to work without root permission, resulting in UUID - 563 : * not necessarily recent. - 564 : * We could call blkid_probe_all() to refresh the UUID, but it would - 565 : * require root permission to read the superblocks, and resulting in - 566 : * all the disks spinning. - 567 : */ - 568 : #if HAVE_BLKID - 569 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) - 570 : { - 571 : char* devname; - 572 : char* uuidname; - 573 : - 574 0 : devname = blkid_devno_to_devname(device); - 575 0 : if (!devname) { - 576 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); - 577 : /* device mapping failed */ - 578 0 : return -1; - 579 : } - 580 : - 581 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname); - 582 0 : if (!uuidname) { - 583 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); - 584 : /* uuid mapping failed */ - 585 0 : free(devname); - 586 0 : return -1; - 587 : } - 588 : - 589 0 : pathcpy(uuid, uuid_size, uuidname); - 590 : - 591 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); - 592 : - 593 0 : free(devname); - 594 0 : free(uuidname); - 595 0 : return 0; - 596 : } - 597 : #endif - 598 : + 138 : * Return an error if truncated + 139 : * + 140 : * Return -1 on error, 0 on success + 141 : */ + 142 : #if HAVE_LINUX_DEVICE + 143 62 : static int sysattr(const char* path, char* buf, size_t buf_size) + 144 : { + 145 : int len; + 146 : + 147 62 : len = sysread(path, buf, buf_size); + 148 62 : if (len < 0) { + 149 : /* LCOV_EXCL_START */ + 150 : return -1; + 151 : /* LCOV_EXCL_STOP */ + 152 : } + 153 : + 154 48 : if ((size_t)len + 1 > buf_size) { + 155 : /* LCOV_EXCL_START */ + 156 : return -1; + 157 : /* LCOV_EXCL_STOP */ + 158 : } + 159 : + 160 48 : buf[len] = 0; + 161 : + 162 48 : strtrim(buf); + 163 : + 164 48 : return 0; + 165 : } + 166 : #endif + 167 : + 168 : /** + 169 : * Get the device file from the device number. + 170 : * + 171 : * It uses /proc/self/mountinfo. + 172 : * + 173 : * Null devices (major==0) are resolved to the device indicated in mountinfo. + 174 : */ + 175 : #if HAVE_LINUX_DEVICE + 176 4 : static int devresolve_proc(uint64_t device, char* path, size_t path_size) + 177 : { + 178 : FILE* f; + 179 : char match[32]; + 180 : + 181 : /* generate the matching string */ + 182 4 : snprintf(match, sizeof(match), "%u:%u", major(device), minor(device)); + 183 : + 184 4 : f = fopen("/proc/self/mountinfo", "r"); + 185 4 : if (!f) { + 186 0 : log_tag("resolve:proc:%u:%u: failed to open /proc/self/mountinfo\n", major(device), minor(device)); + 187 0 : return -1; + 188 : } + 189 : + 190 : /* + 191 : * mountinfo format + 192 : * 0 - mount ID + 193 : * 1 - parent ID + 194 : * 2 - major:minor + 195 : * 3 - root + 196 : * 4 - mount point + 197 : * 5 - options + 198 : * 6 - "-" (separator) + 199 : * 7 - fs + 200 : * 8 - mount source - /dev/device + 201 : */ + 202 : + 203 192 : while (1) { + 204 : char buf[256]; + 205 : char* first_map[8]; + 206 : unsigned first_mac; + 207 : char* second_map[8]; + 208 : unsigned second_mac; + 209 : char* s; + 210 : struct stat st; + 211 : char* separator; + 212 : char* majorminor; + 213 : char* mountpoint; + 214 : char* fs; + 215 : char* mountsource; + 216 : + 217 196 : s = fgets(buf, sizeof(buf), f); + 218 196 : if (s == 0) + 219 4 : break; + 220 : + 221 : /* find the separator position */ + 222 192 : separator = strstr(s, " - "); + 223 192 : if (!separator) + 224 0 : continue; + 225 : + 226 : /* skip the separator */ + 227 192 : *separator = 0; + 228 192 : separator += 3; + 229 : + 230 : /* split the line */ + 231 192 : first_mac = strsplit(first_map, 8, s, " \t\r\n"); + 232 192 : second_mac = strsplit(second_map, 8, separator, " \t\r\n"); + 233 : + 234 : /* if too short, it's the wrong line */ + 235 192 : if (first_mac < 5) + 236 0 : continue; + 237 192 : if (second_mac < 2) + 238 0 : continue; + 239 : + 240 192 : majorminor = first_map[2]; + 241 192 : mountpoint = first_map[4]; + 242 192 : fs = second_map[0]; + 243 192 : mountsource = second_map[1]; + 244 : + 245 : /* compare major:minor from mountinfo */ + 246 192 : if (strcmp(majorminor, match) == 0) { + 247 : /* + 248 : * Accept only /dev/... mountsource + 249 : * + 250 : * This excludes ZFS that uses a bare label for mountsource, like "tank". + 251 : * + 252 : * 410 408 0:193 / /XXX rw,relatime shared:217 - zfs tank/system/data/var/lib/docker/XXX rw,xattr,noacl + 253 : * + 254 : * Also excludes AUTOFS unmounted devices that point to a fake filesystem + 255 : * used to remount them at the first use. + 256 : * + 257 : * 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 + 258 : */ + 259 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { + 260 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + 261 0 : continue; + 262 : } + 263 : + 264 0 : pathcpy(path, path_size, mountsource); + 265 : + 266 0 : log_tag("resolve:proc:%u:%u: found device %s matching device %s\n", major(device), minor(device), path, match); + 267 : + 268 0 : fclose(f); + 269 0 : return 0; + 270 : } + 271 : + 272 : /* get the device of the mount point */ + 273 : /* in Btrfs it could be different than the one in mountinfo */ + 274 192 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) { + 275 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { + 276 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + 277 0 : continue; + 278 : } + 279 : + 280 0 : pathcpy(path, path_size, mountsource); + 281 : + 282 0 : log_tag("resolve:proc:%u:%u: found device %s matching mountpoint %s\n", major(device), minor(device), path, mountpoint); + 283 : + 284 0 : fclose(f); + 285 0 : return 0; + 286 : } + 287 : } + 288 : + 289 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device)); + 290 : + 291 4 : fclose(f); + 292 4 : return -1; + 293 : } + 294 : #endif + 295 : + 296 : /** + 297 : * Get the device of a virtual superblock. + 298 : * + 299 : * This is intended to resolve the case of Btrfs filesystems that + 300 : * create a virtual superblock (major==0) not backed by any low + 301 : * level device. + 302 : * + 303 : * See: + 304 : * Bug 711881 - too funny btrfs st_dev numbers + 305 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881 + 306 : */ + 307 : #if HAVE_LINUX_DEVICE + 308 4 : static int devdereference(uint64_t device, uint64_t* new_device) + 309 : { + 310 : char path[PATH_MAX]; + 311 : struct stat st; + 312 : + 313 : /* use the proc interface to get the device containing the filesystem */ + 314 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) { + 315 : /* LCOV_EXCL_START */ + 316 : return -1; + 317 : /* LCOV_EXCL_STOP */ + 318 : } + 319 : + 320 : /* check the device */ + 321 0 : if (stat(path, &st) != 0) { + 322 : /* LCOV_EXCL_START */ + 323 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path); + 324 : return -1; + 325 : /* LCOV_EXCL_STOP */ + 326 : } + 327 : + 328 0 : if (major(st.st_rdev) == 0) { + 329 : /* LCOV_EXCL_START */ + 330 : 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)); + 331 : return -1; + 332 : /* LCOV_EXCL_STOP */ + 333 : } + 334 : + 335 0 : *new_device = st.st_rdev; + 336 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev)); + 337 0 : return 0; + 338 : } + 339 : #endif + 340 : + 341 : /** + 342 : * Read a file extracting the specified tag TAG=VALUE format. + 343 : * Return !=0 on error. + 344 : */ + 345 : #if HAVE_LINUX_DEVICE + 346 205 : static int tagread(const char* path, const char* tag, char* value, size_t value_size) + 347 : { + 348 : int ret; + 349 : char buf[512]; + 350 : size_t tag_len; + 351 : char* i; + 352 : char* e; + 353 : + 354 205 : ret = sysread(path, buf, sizeof(buf)); + 355 205 : if (ret < 0) { + 356 : /* LCOV_EXCL_START */ + 357 : log_fatal(errno, "Failed to read '%s'.\n", path); + 358 : return -1; + 359 : /* LCOV_EXCL_STOP */ + 360 : } + 361 205 : if ((size_t)ret + 1 > sizeof(buf)) { + 362 : /* LCOV_EXCL_START */ + 363 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); + 364 : return -1; + 365 : /* LCOV_EXCL_STOP */ + 366 : } + 367 : + 368 : /* ending 0 */ + 369 205 : buf[ret] = 0; + 370 : + 371 205 : tag_len = strlen(tag); + 372 : + 373 3578 : for (i = buf; *i; ++i) { + 374 3578 : char* p = i; + 375 : + 376 : /* start with a space */ + 377 3578 : if (p != buf) { + 378 3373 : if (!isspace(*p)) + 379 2963 : continue; + 380 410 : ++p; + 381 : } + 382 : + 383 615 : if (strncmp(p, tag, tag_len) != 0) + 384 410 : continue; + 385 205 : p += tag_len; + 386 : + 387 : /* end with a = */ + 388 205 : if (*p != '=') + 389 0 : continue; + 390 205 : ++p; + 391 : + 392 : /* found */ + 393 205 : i = p; + 394 205 : break; + 395 : } + 396 205 : if (!*i) { + 397 : /* LCOV_EXCL_START */ + 398 : log_fatal(EEXTERNAL, "Missing tag '%s' for '%s'.\n", tag, path); + 399 : return -1; + 400 : /* LCOV_EXCL_STOP */ + 401 : } + 402 : + 403 : /* terminate at the first space */ + 404 205 : e = i; + 405 901 : while (*e != 0 && !isspace(*e)) + 406 696 : ++e; + 407 205 : *e = 0; + 408 : + 409 205 : if (!*i) { + 410 : /* LCOV_EXCL_START */ + 411 : log_fatal(EEXTERNAL, "Empty tag '%s' for '%s'.\n", tag, path); + 412 : return -1; + 413 : /* LCOV_EXCL_STOP */ + 414 : } + 415 : + 416 205 : pathprint(value, value_size, "%s", i); + 417 : + 418 205 : return 0; + 419 : } + 420 : #endif + 421 : + 422 : /** + 423 : * Get the device file from the device number. + 424 : * + 425 : * It uses /sys/dev/block/.../uevent. + 426 : * + 427 : * For null device (major==0) it fails. + 428 : */ + 429 : #if HAVE_LINUX_DEVICE + 430 205 : static int devresolve_sys(dev_t device, char* path, size_t path_size) + 431 : { + 432 : struct stat st; + 433 : char buf[PATH_MAX]; + 434 : + 435 : /* default device path from device number */ + 436 205 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device)); + 437 : + 438 205 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) { + 439 : /* LCOV_EXCL_START */ + 440 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path); + 441 : return -1; + 442 : /* LCOV_EXCL_STOP */ + 443 : } + 444 : + 445 : /* set the real device path */ + 446 205 : pathprint(path, path_size, "/dev/%s", buf); + 447 : + 448 : /* check the device */ + 449 205 : if (stat(path, &st) != 0) { + 450 : /* LCOV_EXCL_START */ + 451 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path); + 452 : return -1; + 453 : /* LCOV_EXCL_STOP */ + 454 : } + 455 205 : if (st.st_rdev != device) { + 456 : /* LCOV_EXCL_START */ + 457 : 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); + 458 : return -1; + 459 : /* LCOV_EXCL_STOP */ + 460 : } + 461 : + 462 205 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path); + 463 : + 464 205 : return 0; + 465 : } + 466 : #endif + 467 : + 468 : /** + 469 : * Get the device file from the device number. + 470 : */ + 471 : #if HAVE_LINUX_DEVICE + 472 205 : static int devresolve(uint64_t device, char* path, size_t path_size) + 473 : { + 474 205 : if (devresolve_sys(device, path, path_size) == 0) + 475 205 : return 0; + 476 : + 477 0 : return -1; + 478 : } + 479 : #endif + 480 : + 481 : /** + 482 : * Cache used by blkid. + 483 : */ + 484 : #if HAVE_BLKID + 485 : static blkid_cache cache = 0; + 486 : #endif + 487 : + 488 : /** + 489 : * Get the UUID using the /dev/disk/by-uuid/ links. + 490 : * It doesn't require root permission, and the uuid are always updated. + 491 : * It doesn't work with Btrfs file-systems that don't export the main UUID + 492 : * in /dev/disk/by-uuid/. + 493 : */ + 494 : #if HAVE_LINUX_DEVICE + 495 10556 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) + 496 : { + 497 : int ret; + 498 : DIR* d; + 499 : struct dirent* dd; + 500 : struct stat st; + 501 : + 502 : /* scan the UUID directory searching for the device */ + 503 10556 : d = opendir("/dev/disk/by-uuid"); + 504 10556 : if (!d) { + 505 0 : log_tag("uuid:by-uuid:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); + 506 : /* directory missing?, likely we are not in Linux */ + 507 0 : return -1; + 508 : } + 509 : + 510 10556 : int dir_fd = dirfd(d); + 511 10556 : if (dir_fd == -1) { + 512 0 : log_tag("uuid:by-uuid:%u:%u: dirfd(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); + 513 0 : return -1; + 514 : } + 515 : + 516 168806 : while ((dd = readdir(d)) != 0) { + 517 : /* skip "." and ".." files, UUIDs never start with '.' */ + 518 168806 : if (dd->d_name[0] == '.') + 519 21112 : continue; + 520 : + 521 147694 : ret = fstatat(dir_fd, dd->d_name, &st, 0); + 522 147694 : if (ret != 0) { + 523 0 : log_tag("uuid:by-uuid:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + 524 : /* generic error, ignore and continue the search */ + 525 0 : continue; + 526 : } + 527 : + 528 : /* if it matches, we have the uuid */ + 529 147694 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { + 530 : char buf[PATH_MAX]; + 531 : char path[PATH_MAX]; + 532 : + 533 : /* resolve the link */ + 534 10556 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); + 535 10556 : ret = readlink(path, buf, sizeof(buf)); + 536 10556 : if (ret < 0 || ret >= PATH_MAX) { + 537 0 : log_tag("uuid:by-uuid:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + 538 : /* generic error, ignore and continue the search */ + 539 0 : continue; + 540 : } + 541 10556 : buf[ret] = 0; + 542 : + 543 : /* found */ + 544 10556 : pathcpy(uuid, uuid_size, dd->d_name); + 545 : + 546 10556 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); + 547 : + 548 10556 : closedir(d); + 549 10556 : return 0; + 550 : } + 551 : } + 552 : + 553 0 : log_tag("uuid:by-uuid:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device)); + 554 : + 555 : /* not found */ + 556 0 : closedir(d); + 557 0 : return -1; + 558 : } + 559 : #endif + 560 : + 561 : /** + 562 : * Get the UUID using libblkid. + 563 : * It uses a cache to work without root permission, resulting in UUID + 564 : * not necessarily recent. + 565 : * We could call blkid_probe_all() to refresh the UUID, but it would + 566 : * require root permission to read the superblocks, and resulting in + 567 : * all the disks spinning. + 568 : */ + 569 : #if HAVE_BLKID + 570 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) + 571 : { + 572 : char* devname; + 573 : char* uuidname; + 574 : + 575 0 : devname = blkid_devno_to_devname(device); + 576 0 : if (!devname) { + 577 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); + 578 : /* device mapping failed */ + 579 0 : return -1; + 580 : } + 581 : + 582 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname); + 583 0 : if (!uuidname) { + 584 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); + 585 : /* uuid mapping failed */ + 586 0 : free(devname); + 587 0 : return -1; + 588 : } + 589 : + 590 0 : pathcpy(uuid, uuid_size, uuidname); + 591 : + 592 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); + 593 : + 594 0 : free(devname); + 595 0 : free(uuidname); + 596 0 : return 0; + 597 : } + 598 : #endif 599 : - 600 : /** - 601 : * Get the LABEL using libblkid. - 602 : * It uses a cache to work without root permission, resulting in LABEL - 603 : * not necessarily recent. - 604 : */ - 605 : #if HAVE_BLKID - 606 5759 : static int devuuid_label(uint64_t device, char* label, size_t label_size) - 607 : { - 608 : char* devname; - 609 : char* labelname; - 610 : - 611 5759 : devname = blkid_devno_to_devname(device); - 612 5759 : if (!devname) { - 613 0 : log_tag("label:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); - 614 : /* device mapping failed */ - 615 0 : return -1; - 616 : } - 617 : - 618 5759 : labelname = blkid_get_tag_value(cache, "LABEL", devname); - 619 5759 : if (!labelname) { - 620 5759 : log_tag("label:blkid:%u:%u: blkid_get_tag_value(LABEL,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); - 621 5759 : free(devname); - 622 : /* label mapping failed */ - 623 5759 : return -1; - 624 : } - 625 : - 626 0 : pathcpy(label, label_size, labelname); - 627 : - 628 0 : log_tag("label:blkid:%u:%u:%s: found %s\n", major(device), minor(device), label, devname); - 629 : - 630 0 : free(devname); - 631 0 : free(labelname); - 632 0 : return 0; - 633 : } - 634 : #endif - 635 : + 600 : + 601 : /** + 602 : * Get the LABEL using libblkid. + 603 : * It uses a cache to work without root permission, resulting in LABEL + 604 : * not necessarily recent. + 605 : */ + 606 : #if HAVE_BLKID + 607 5759 : static int devuuid_label(uint64_t device, char* label, size_t label_size) + 608 : { + 609 : char* devname; + 610 : char* labelname; + 611 : + 612 5759 : devname = blkid_devno_to_devname(device); + 613 5759 : if (!devname) { + 614 0 : log_tag("label:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); + 615 : /* device mapping failed */ + 616 0 : return -1; + 617 : } + 618 : + 619 5759 : labelname = blkid_get_tag_value(cache, "LABEL", devname); + 620 5759 : if (!labelname) { + 621 5759 : log_tag("label:blkid:%u:%u: blkid_get_tag_value(LABEL,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); + 622 5759 : free(devname); + 623 : /* label mapping failed */ + 624 5759 : return -1; + 625 : } + 626 : + 627 0 : pathcpy(label, label_size, labelname); + 628 : + 629 0 : log_tag("label:blkid:%u:%u:%s: found %s\n", major(device), minor(device), label, devname); + 630 : + 631 0 : free(devname); + 632 0 : free(labelname); + 633 0 : return 0; + 634 : } + 635 : #endif 636 : - 637 : #ifdef __APPLE__ - 638 : static int devuuid_darwin(const char* path, char* uuid, size_t uuid_size) - 639 : { - 640 : CFStringRef path_apple = 0; - 641 : DASessionRef session = 0; - 642 : CFURLRef path_appler = 0; - 643 : int result = -1; - 644 : - 645 : *uuid = 0; - 646 : - 647 : path_apple = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); - 648 : if (!path_apple) - 649 : goto bail; - 650 : - 651 : session = DASessionCreate(kCFAllocatorDefault); - 652 : if (!session) - 653 : goto bail; - 654 : - 655 : path_appler = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_apple, kCFURLPOSIXPathStyle, false); - 656 : if (!path_appler) - 657 : goto bail; - 658 : - 659 : /* find the mount point */ - 660 : DADiskRef disk = NULL; - 661 : while (path_appler) { - 662 : disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, path_appler); - 663 : if (disk) - 664 : break; - 665 : - 666 : CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, path_appler); - 667 : if (!parent) - 668 : break; - 669 : - 670 : /* check if we hit the root (parent == child) */ - 671 : if (CFEqual(parent, path_appler)) { - 672 : CFRelease(parent); - 673 : break; - 674 : } - 675 : - 676 : CFRelease(path_appler); - 677 : path_appler = parent; - 678 : } - 679 : - 680 : /* safely extract the UUID */ - 681 : if (disk) { - 682 : CFDictionaryRef description = DADiskCopyDescription(disk); - 683 : if (description) { - 684 : /* key might not exist for NTFS/ExFAT on some drivers */ - 685 : const void* value = (CFUUIDRef)CFDictionaryGetValue(description, kDADiskDescriptionVolumeUUIDKey); - 686 : CFStringRef uuid_string = NULL; - 687 : - 688 : if (value) { - 689 : if (CFGetTypeID(value) == CFUUIDGetTypeID()) { - 690 : uuid_string = CFUUIDCreateString(kCFAllocatorDefault, (CFUUIDRef)value); - 691 : } else if (CFGetTypeID(value) == CFStringGetTypeID()) { - 692 : /* if it's already a string, retain it so we can release it later consistently */ - 693 : uuid_string = (CFStringRef)CFRetain(value); - 694 : } - 695 : } - 696 : - 697 : if (uuid_string) { - 698 : if (CFStringGetCString(uuid_string, uuid, uuid_size, kCFStringEncodingUTF8)) { - 699 : result = 0; /* success */ - 700 : } - 701 : CFRelease(uuid_string); - 702 : } - 703 : - 704 : CFRelease(description); - 705 : } - 706 : CFRelease(disk); - 707 : } - 708 : - 709 : bail: - 710 : /* clean up */ - 711 : if (path_appler) CFRelease(path_appler); - 712 : if (session) CFRelease(session); - 713 : if (path_apple) CFRelease(path_apple); - 714 : - 715 : return result; - 716 : } - 717 : #endif - 718 : - 719 10548 : int devuuid(uint64_t device, const char* path, char* uuid, size_t uuid_size) - 720 : { - 721 : (void)path; - 722 : (void)device; - 723 : - 724 : #ifdef __APPLE__ - 725 : if (devuuid_darwin(path, uuid, uuid_size) == 0) - 726 : return 0; - 727 : #endif - 728 : - 729 : #if HAVE_LINUX_DEVICE - 730 : /* if the major is the null device */ - 731 10548 : if (major(device) == 0) { - 732 : /* obtain the real device */ - 733 4 : if (devdereference(device, &device) != 0) { - 734 : /* LCOV_EXCL_START */ - 735 : return -1; - 736 : /* LCOV_EXCL_STOP */ - 737 : } - 738 : } - 739 : #endif - 740 : - 741 : /* first try with the /dev/disk/by-uuid version */ - 742 : #if HAVE_LINUX_DEVICE - 743 10544 : if (devuuid_dev(device, uuid, uuid_size) == 0) - 744 10544 : return 0; - 745 : #else - 746 : log_tag("uuid:by-uuid:%u:%u: by-uuid not supported\n", major(device), minor(device)); - 747 : #endif - 748 : - 749 : /* fall back to blkid for other cases */ - 750 : #if HAVE_BLKID - 751 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0) - 752 0 : return 0; - 753 : #else - 754 : log_tag("uuid:blkid:%u:%u: blkid support not compiled in\n", major(device), minor(device)); - 755 : #endif - 756 : - 757 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); - 758 : - 759 : /* not supported */ - 760 : (void)uuid; - 761 : (void)uuid_size; - 762 0 : return -1; - 763 : } - 764 : - 765 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) - 766 : { - 767 : #if HAVE_LINUX_FIEMAP_H - 768 : /* In Linux get the real physical address of the file */ - 769 : /* Note that FIEMAP doesn't require root permission */ - 770 : int f; - 771 : struct fiemap* fiemap; - 772 : size_t fiemap_size; - 773 : unsigned int blknum; - 774 : - 775 11432 : f = open(path, O_RDONLY); - 776 11432 : if (f == -1) { - 777 0 : return -1; - 778 : } - 779 : - 780 : /* first try with FIEMAP */ - 781 : /* if works for ext2, ext3, ext4, xfs, btrfs */ - 782 11432 : fiemap_size = sizeof(struct fiemap) + sizeof(struct fiemap_extent); - 783 11432 : fiemap = malloc_nofail(fiemap_size); - 784 11432 : memset(fiemap, 0, fiemap_size); - 785 11432 : fiemap->fm_start = 0; - 786 11432 : fiemap->fm_length = ~0ULL; - 787 11432 : fiemap->fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ - 788 11432 : fiemap->fm_extent_count = 1; /* we are interested only at the first block */ - 789 : - 790 11432 : if (ioctl(f, FS_IOC_FIEMAP, fiemap) != -1) { - 791 11432 : uint32_t flags = fiemap->fm_extents[0].fe_flags; - 792 11432 : uint64_t offset = fiemap->fm_extents[0].fe_physical; - 793 : - 794 : /* check some condition for validating the offset */ - 795 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) { - 796 : /* if the data is inline, we don't have an offset to report */ - 797 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 798 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) { - 799 : /* if the offset is unknown, we don't have an offset to report */ - 800 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 801 11432 : } else if (offset == 0) { - 802 : /* 0 is the general fallback for file-systems when */ - 803 : /* they don't have an offset to report */ - 804 14 : *physical = FILEPHY_WITHOUT_OFFSET; - 805 : } else { - 806 : /* finally report the real offset */ - 807 11418 : *physical = offset + FILEPHY_REAL_OFFSET; - 808 : } - 809 : - 810 11432 : if (close(f) == -1) - 811 0 : return -1; - 812 11432 : return 0; - 813 : } - 814 : - 815 0 : free(fiemap); - 816 : - 817 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ - 818 0 : if (size == 0) { - 819 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 820 0 : if (close(f) == -1) - 821 0 : return -1; - 822 0 : return 0; - 823 : } - 824 : - 825 : /* then try with FIBMAP */ - 826 : /* it works for jfs, reiserfs, ntfs-3g */ - 827 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ - 828 0 : blknum = 0; /* first block */ - 829 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { - 830 0 : *physical = blknum + FILEPHY_REAL_OFFSET; - 831 0 : if (close(f) == -1) - 832 0 : return -1; - 833 0 : return 0; - 834 : } - 835 : - 836 : /* otherwise don't use anything, and keep the directory traversal order */ - 837 : /* at now this should happen only for vfat */ - 838 : /* and it's surely better than using fake inodes */ - 839 0 : *physical = FILEPHY_UNREPORTED_OFFSET; - 840 0 : if (close(f) == -1) - 841 0 : return -1; - 842 : #else - 843 : /* In a generic Unix use a dummy value for all the files */ - 844 : /* We don't want to risk to use the inode without knowing */ - 845 : /* if it really improves performance. */ - 846 : /* In this way we keep them in the directory traversal order */ - 847 : /* that at least keeps files in the same directory together. */ - 848 : /* Note also that in newer file-system with snapshot, like ZFS, */ - 849 : /* the inode doesn't represent even more the disk position, because files */ - 850 : /* are not overwritten in place, but rewritten in another location */ - 851 : /* of the disk. */ - 852 : *physical = FILEPHY_UNREPORTED_OFFSET; - 853 : - 854 : (void)path; /* not used here */ - 855 : (void)size; - 856 : #endif - 857 : - 858 0 : return 0; - 859 : } - 860 : - 861 : /* from man statfs */ - 862 : #define ADFS_SUPER_MAGIC 0xadf5 - 863 : #define AFFS_SUPER_MAGIC 0xADFF - 864 : #define BDEVFS_MAGIC 0x62646576 - 865 : #define BEFS_SUPER_MAGIC 0x42465331 - 866 : #define BFS_MAGIC 0x1BADFACE - 867 : #define BINFMTFS_MAGIC 0x42494e4d - 868 : #define BTRFS_SUPER_MAGIC 0x9123683E - 869 : #define CGROUP_SUPER_MAGIC 0x27e0eb - 870 : #define CIFS_MAGIC_NUMBER 0xFF534D42 - 871 : #define CODA_SUPER_MAGIC 0x73757245 - 872 : #define COH_SUPER_MAGIC 0x012FF7B7 - 873 : #define CRAMFS_MAGIC 0x28cd3d45 - 874 : #define DEBUGFS_MAGIC 0x64626720 - 875 : #define DEVFS_SUPER_MAGIC 0x1373 - 876 : #define DEVPTS_SUPER_MAGIC 0x1cd1 - 877 : #define EFIVARFS_MAGIC 0xde5e81e4 - 878 : #define EFS_SUPER_MAGIC 0x00414A53 - 879 : #define EXT_SUPER_MAGIC 0x137D - 880 : #define EXT2_OLD_SUPER_MAGIC 0xEF51 - 881 : #define EXT4_SUPER_MAGIC 0xEF53 /* also ext2/ext3 */ - 882 : #define FUSE_SUPER_MAGIC 0x65735546 - 883 : #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA - 884 : #define HFS_SUPER_MAGIC 0x4244 - 885 : #define HFSPLUS_SUPER_MAGIC 0x482b - 886 : #define HOSTFS_SUPER_MAGIC 0x00c0ffee - 887 : #define HPFS_SUPER_MAGIC 0xF995E849 - 888 : #define HUGETLBFS_MAGIC 0x958458f6 - 889 : #define ISOFS_SUPER_MAGIC 0x9660 - 890 : #define JFFS2_SUPER_MAGIC 0x72b6 - 891 : #define JFS_SUPER_MAGIC 0x3153464a - 892 : #define MINIX_SUPER_MAGIC 0x137F - 893 : #define MINIX_SUPER_MAGIC2 0x138F - 894 : #define MINIX2_SUPER_MAGIC 0x2468 - 895 : #define MINIX2_SUPER_MAGIC2 0x2478 - 896 : #define MINIX3_SUPER_MAGIC 0x4d5a - 897 : #define MQUEUE_MAGIC 0x19800202 - 898 : #define MSDOS_SUPER_MAGIC 0x4d44 - 899 : #define NCP_SUPER_MAGIC 0x564c - 900 : #define NFS_SUPER_MAGIC 0x6969 - 901 : #define NILFS_SUPER_MAGIC 0x3434 - 902 : #define NTFS_SB_MAGIC 0x5346544e - 903 : #define OCFS2_SUPER_MAGIC 0x7461636f - 904 : #define OPENPROM_SUPER_MAGIC 0x9fa1 - 905 : #define PIPEFS_MAGIC 0x50495045 - 906 : #define PROC_SUPER_MAGIC 0x9fa0 - 907 : #define PSTOREFS_MAGIC 0x6165676C - 908 : #define QNX4_SUPER_MAGIC 0x002f - 909 : #define QNX6_SUPER_MAGIC 0x68191122 - 910 : #define RAMFS_MAGIC 0x858458f6 - 911 : #define REISERFS_SUPER_MAGIC 0x52654973 - 912 : #define ROMFS_MAGIC 0x7275 - 913 : #define SELINUX_MAGIC 0xf97cff8c - 914 : #define SMACK_MAGIC 0x43415d53 - 915 : #define SMB_SUPER_MAGIC 0x517B - 916 : #define SOCKFS_MAGIC 0x534F434B - 917 : #define SQUASHFS_MAGIC 0x73717368 - 918 : #define SYSFS_MAGIC 0x62656572 - 919 : #define SYSV2_SUPER_MAGIC 0x012FF7B6 - 920 : #define SYSV4_SUPER_MAGIC 0x012FF7B5 - 921 : #define TMPFS_MAGIC 0x01021994 - 922 : #define UDF_SUPER_MAGIC 0x15013346 - 923 : #define UFS_MAGIC 0x00011954 - 924 : #define USBDEVICE_SUPER_MAGIC 0x9fa2 - 925 : #define V9FS_MAGIC 0x01021997 - 926 : #define VXFS_SUPER_MAGIC 0xa501FCF5 - 927 : #define XENFS_SUPER_MAGIC 0xabba1974 - 928 : #define XENIX_SUPER_MAGIC 0x012FF7B4 - 929 : #define XFS_SUPER_MAGIC 0x58465342 - 930 : #define _XIAFS_SUPER_MAGIC 0x012FD16D - 931 : #define AFS_SUPER_MAGIC 0x5346414F - 932 : #define AUFS_SUPER_MAGIC 0x61756673 - 933 : #define ANON_INODE_FS_SUPER_MAGIC 0x09041934 - 934 : #define CEPH_SUPER_MAGIC 0x00C36400 - 935 : #define ECRYPTFS_SUPER_MAGIC 0xF15F - 936 : #define FAT_SUPER_MAGIC 0x4006 - 937 : #define FHGFS_SUPER_MAGIC 0x19830326 - 938 : #define FUSEBLK_SUPER_MAGIC 0x65735546 - 939 : #define FUSECTL_SUPER_MAGIC 0x65735543 - 940 : #define GFS_SUPER_MAGIC 0x1161970 - 941 : #define GPFS_SUPER_MAGIC 0x47504653 - 942 : #define MTD_INODE_FS_SUPER_MAGIC 0x11307854 - 943 : #define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA - 944 : #define ISOFS_R_WIN_SUPER_MAGIC 0x4004 - 945 : #define ISOFS_WIN_SUPER_MAGIC 0x4000 - 946 : #define JFFS_SUPER_MAGIC 0x07C0 - 947 : #define KAFS_SUPER_MAGIC 0x6B414653 - 948 : #define LUSTRE_SUPER_MAGIC 0x0BD00BD0 - 949 : #define NFSD_SUPER_MAGIC 0x6E667364 - 950 : #define PANFS_SUPER_MAGIC 0xAAD7AAEA - 951 : #define RPC_PIPEFS_SUPER_MAGIC 0x67596969 - 952 : #define SECURITYFS_SUPER_MAGIC 0x73636673 - 953 : #define UFS_BYTESWAPPED_SUPER_MAGIC 0x54190100 - 954 : #define VMHGFS_SUPER_MAGIC 0xBACBACBC - 955 : #define VZFS_SUPER_MAGIC 0x565A4653 - 956 : #define ZFS_SUPER_MAGIC 0x2FC12FC1 - 957 : - 958 : struct filesystem_entry { - 959 : unsigned id; - 960 : const char* name; - 961 : int remote; - 962 : } FILESYSTEMS[] = { - 963 : { ADFS_SUPER_MAGIC, "adfs", 0 }, - 964 : { AFFS_SUPER_MAGIC, "affs", 0 }, - 965 : { AFS_SUPER_MAGIC, "afs", 1 }, - 966 : { AUFS_SUPER_MAGIC, "aufs", 1 }, - 967 : { BEFS_SUPER_MAGIC, "befs", 0 }, - 968 : { BDEVFS_MAGIC, "bdevfs", 0 }, - 969 : { BFS_MAGIC, "bfs", 0 }, - 970 : { BINFMTFS_MAGIC, "binfmt_misc", 0 }, - 971 : { BTRFS_SUPER_MAGIC, "btrfs", 0 }, - 972 : { CEPH_SUPER_MAGIC, "ceph", 1 }, - 973 : { CGROUP_SUPER_MAGIC, "cgroupfs", 0 }, - 974 : { CIFS_MAGIC_NUMBER, "cifs", 1 }, - 975 : { CODA_SUPER_MAGIC, "coda", 1 }, - 976 : { COH_SUPER_MAGIC, "coh", 0 }, - 977 : { CRAMFS_MAGIC, "cramfs", 0 }, - 978 : { DEBUGFS_MAGIC, "debugfs", 0 }, - 979 : { DEVFS_SUPER_MAGIC, "devfs", 0 }, - 980 : { DEVPTS_SUPER_MAGIC, "devpts", 0 }, - 981 : { ECRYPTFS_SUPER_MAGIC, "ecryptfs", 0 }, - 982 : { EFS_SUPER_MAGIC, "efs", 0 }, - 983 : { EXT_SUPER_MAGIC, "ext", 0 }, - 984 : { EXT4_SUPER_MAGIC, "ext4", 0 }, - 985 : { EXT2_OLD_SUPER_MAGIC, "ext2", 0 }, - 986 : { FAT_SUPER_MAGIC, "fat", 0 }, - 987 : { FHGFS_SUPER_MAGIC, "fhgfs", 1 }, - 988 : { FUSEBLK_SUPER_MAGIC, "fuseblk", 1 }, - 989 : { FUSECTL_SUPER_MAGIC, "fusectl", 1 }, - 990 : { FUTEXFS_SUPER_MAGIC, "futexfs", 0 }, - 991 : { GFS_SUPER_MAGIC, "gfs/gfs2", 1 }, - 992 : { GPFS_SUPER_MAGIC, "gpfs", 1 }, - 993 : { HFS_SUPER_MAGIC, "hfs", 0 }, - 994 : { HFSPLUS_SUPER_MAGIC, "hfsplus", 0 }, - 995 : { HPFS_SUPER_MAGIC, "hpfs", 0 }, - 996 : { HUGETLBFS_MAGIC, "hugetlbfs", 0 }, - 997 : { MTD_INODE_FS_SUPER_MAGIC, "inodefs", 0 }, - 998 : { INOTIFYFS_SUPER_MAGIC, "inotifyfs", 0 }, - 999 : { ISOFS_SUPER_MAGIC, "isofs", 0 }, - 1000 : { ISOFS_R_WIN_SUPER_MAGIC, "isofs", 0 }, - 1001 : { ISOFS_WIN_SUPER_MAGIC, "isofs", 0 }, - 1002 : { JFFS_SUPER_MAGIC, "jffs", 0 }, - 1003 : { JFFS2_SUPER_MAGIC, "jffs2", 0 }, - 1004 : { JFS_SUPER_MAGIC, "jfs", 0 }, - 1005 : { KAFS_SUPER_MAGIC, "k-afs", 1 }, - 1006 : { LUSTRE_SUPER_MAGIC, "lustre", 1 }, - 1007 : { MINIX_SUPER_MAGIC, "minix", 0 }, - 1008 : { MINIX_SUPER_MAGIC2, "minix", 0 }, - 1009 : { MINIX2_SUPER_MAGIC, "minix2", 0 }, - 1010 : { MINIX2_SUPER_MAGIC2, "minix2", 0 }, - 1011 : { MINIX3_SUPER_MAGIC, "minix3", 0 }, - 1012 : { MQUEUE_MAGIC, "mqueue", 0 }, - 1013 : { MSDOS_SUPER_MAGIC, "msdos", 0 }, - 1014 : { NCP_SUPER_MAGIC, "novell", 1 }, - 1015 : { NFS_SUPER_MAGIC, "nfs", 1 }, - 1016 : { NFSD_SUPER_MAGIC, "nfsd", 1 }, - 1017 : { NILFS_SUPER_MAGIC, "nilfs", 0 }, - 1018 : { NTFS_SB_MAGIC, "ntfs", 0 }, - 1019 : { OPENPROM_SUPER_MAGIC, "openprom", 0 }, - 1020 : { OCFS2_SUPER_MAGIC, "ocfs2", 1 }, - 1021 : { PANFS_SUPER_MAGIC, "panfs", 1 }, - 1022 : { PIPEFS_MAGIC, "pipefs", 1 }, - 1023 : { PROC_SUPER_MAGIC, "proc", 0 }, - 1024 : { PSTOREFS_MAGIC, "pstorefs", 0 }, - 1025 : { QNX4_SUPER_MAGIC, "qnx4", 0 }, - 1026 : { QNX6_SUPER_MAGIC, "qnx6", 0 }, - 1027 : { RAMFS_MAGIC, "ramfs", 0 }, - 1028 : { REISERFS_SUPER_MAGIC, "reiserfs", 0 }, - 1029 : { ROMFS_MAGIC, "romfs", 0 }, - 1030 : { RPC_PIPEFS_SUPER_MAGIC, "rpc_pipefs", 0 }, - 1031 : { SECURITYFS_SUPER_MAGIC, "securityfs", 0 }, - 1032 : { SELINUX_MAGIC, "selinux", 0 }, - 1033 : { SMB_SUPER_MAGIC, "smb", 1 }, - 1034 : { SOCKFS_MAGIC, "sockfs", 0 }, - 1035 : { SQUASHFS_MAGIC, "squashfs", 0 }, - 1036 : { SYSFS_MAGIC, "sysfs", 0 }, - 1037 : { SYSV2_SUPER_MAGIC, "sysv2", 0 }, - 1038 : { SYSV4_SUPER_MAGIC, "sysv4", 0 }, - 1039 : { TMPFS_MAGIC, "tmpfs", 0 }, - 1040 : { UDF_SUPER_MAGIC, "udf", 0 }, - 1041 : { UFS_MAGIC, "ufs", 0 }, - 1042 : { UFS_BYTESWAPPED_SUPER_MAGIC, "ufs", 0 }, - 1043 : { USBDEVICE_SUPER_MAGIC, "usbdevfs", 0 }, - 1044 : { V9FS_MAGIC, "v9fs", 0 }, - 1045 : { VMHGFS_SUPER_MAGIC, "vmhgfs", 1 }, - 1046 : { VXFS_SUPER_MAGIC, "vxfs", 0 }, - 1047 : { VZFS_SUPER_MAGIC, "vzfs", 0 }, - 1048 : { XENFS_SUPER_MAGIC, "xenfs", 0 }, - 1049 : { XENIX_SUPER_MAGIC, "xenix", 0 }, - 1050 : { XFS_SUPER_MAGIC, "xfs", 0 }, - 1051 : { _XIAFS_SUPER_MAGIC, "xia", 0 }, - 1052 : { ZFS_SUPER_MAGIC, "zfs", 0 }, - 1053 : { 0 } - 1054 : }; - 1055 : - 1056 6412 : int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space, char* fstype, size_t fstype_size, char* fslabel, size_t fslabel_size) - 1057 : { - 1058 : #if HAVE_STATFS - 1059 : struct statfs st; - 1060 : - 1061 6412 : if (statfs(path, &st) != 0) { - 1062 : char dir[PATH_MAX]; - 1063 : char* slash; - 1064 : - 1065 48 : if (errno != ENOENT) { - 1066 0 : return -1; - 1067 : } - 1068 : - 1069 : /* if it doesn't exist, we assume a file */ - 1070 : /* and we check for the containing dir */ - 1071 48 : if (strlen(path) + 1 > sizeof(dir)) { - 1072 0 : errno = ENAMETOOLONG; - 1073 0 : return -1; - 1074 : } - 1075 : - 1076 48 : strcpy(dir, path); - 1077 : - 1078 48 : slash = strrchr(dir, '/'); - 1079 48 : if (!slash) - 1080 0 : return -1; - 1081 : - 1082 48 : *slash = 0; - 1083 48 : if (statfs(dir, &st) != 0) - 1084 0 : return -1; - 1085 : } - 1086 : #endif - 1087 : - 1088 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ - 1089 6412 : if (has_persistent_inode) { - 1090 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 1091 605 : switch (st.f_type) { - 1092 0 : case FUSEBLK_SUPER_MAGIC : /* FUSE, "fuseblk" in the stat command */ - 1093 : case MSDOS_SUPER_MAGIC : /* VFAT, "msdos" in the stat command */ - 1094 0 : *has_persistent_inode = 0; - 1095 0 : break; - 1096 605 : default : - 1097 : /* by default assume yes */ - 1098 605 : *has_persistent_inode = 1; - 1099 605 : break; - 1100 : } - 1101 : #else - 1102 : /* in Unix inodes are persistent by default */ - 1103 : *has_persistent_inode = 1; - 1104 : #endif - 1105 : } - 1106 : - 1107 6412 : if (has_syncronized_hardlinks) { - 1108 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 1109 605 : switch (st.f_type) { - 1110 0 : case NTFS_SB_MAGIC : /* NTFS */ - 1111 : case MSDOS_SUPER_MAGIC : /* VFAT, "msdos" in the stat command */ - 1112 0 : *has_syncronized_hardlinks = 0; - 1113 0 : break; - 1114 605 : default : - 1115 : /* by default assume yes */ - 1116 605 : *has_syncronized_hardlinks = 1; - 1117 605 : break; - 1118 : } - 1119 : #else - 1120 : /* in Unix hardlinks share the same metadata by default */ - 1121 : *has_syncronized_hardlinks = 1; - 1122 : #endif - 1123 : } - 1124 : - 1125 6412 : if (total_space) { - 1126 : #if HAVE_STATFS - 1127 5807 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; - 1128 : #else - 1129 : *total_space = 0; - 1130 : #endif - 1131 : } - 1132 : - 1133 6412 : if (free_space) { - 1134 : #if HAVE_STATFS - 1135 5807 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; - 1136 : #else - 1137 : *free_space = 0; - 1138 : #endif - 1139 : } - 1140 : - 1141 6412 : const char* ptype = 0; - 1142 : - 1143 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME - 1144 : /* get the filesystem type directly from the struct (Mac OS X) */ - 1145 : ptype = st.f_fstypename; - 1146 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 1147 : /* get the filesystem type from f_type (Linux) */ - 1148 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */ - 1149 141064 : for (int i = 0; FILESYSTEMS[i].id != 0; ++i) { - 1150 141064 : if (st.f_type == FILESYSTEMS[i].id) { - 1151 6412 : ptype = FILESYSTEMS[i].name; - 1152 6412 : break; - 1153 : } - 1154 : } - 1155 : #endif - 1156 : - 1157 6412 : if (fstype) { - 1158 5807 : fstype[0] = 0; - 1159 5807 : if (ptype) - 1160 5807 : snprintf(fstype, fstype_size, "%s", ptype); - 1161 : } - 1162 : - 1163 6412 : if (fslabel) { - 1164 5807 : fslabel[0] = 0; - 1165 : #if HAVE_BLKID - 1166 : struct stat fst; - 1167 5807 : if (stat(path, &fst) == 0) - 1168 5759 : devuuid_label(fst.st_dev, fslabel, fslabel_size); - 1169 : #else - 1170 : (void)fslabel_size; - 1171 : #endif - 1172 : } - 1173 : - 1174 6412 : return 0; - 1175 : } - 1176 : - 1177 3817826 : uint64_t tick(void) - 1178 : { - 1179 : #if HAVE_MACH_ABSOLUTE_TIME - 1180 : /* for Mac OS X */ - 1181 : return mach_absolute_time(); - 1182 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) - 1183 : /* for Linux */ - 1184 : struct timespec tv; - 1185 : - 1186 : /* nanosecond precision with clock_gettime() */ - 1187 : #if defined(CLOCK_MONOTONIC_RAW) - 1188 3817826 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { - 1189 : #else - 1190 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { - 1191 : #endif - 1192 0 : return 0; - 1193 : } - 1194 : - 1195 3817826 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; - 1196 : #else - 1197 : /* other platforms */ - 1198 : struct timeval tv; - 1199 : - 1200 : /* microsecond precision with gettimeofday() */ - 1201 : if (gettimeofday(&tv, 0) != 0) { - 1202 : return 0; - 1203 : } - 1204 : - 1205 : return tv.tv_sec * 1000000ULL + tv.tv_usec; - 1206 : #endif - 1207 : } - 1208 : - 1209 3581 : uint64_t tick_ms(void) - 1210 : { - 1211 : struct timeval tv; - 1212 : - 1213 3581 : if (gettimeofday(&tv, 0) != 0) - 1214 0 : return 0; - 1215 : - 1216 3581 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; - 1217 : } - 1218 : - 1219 294 : int randomize(void* ptr, size_t size) - 1220 : { - 1221 : int f; - 1222 : ssize_t ret; - 1223 : - 1224 294 : f = open("/dev/urandom", O_RDONLY); - 1225 294 : if (f == -1) - 1226 0 : return -1; - 1227 : - 1228 294 : ret = read(f, ptr, size); - 1229 294 : if (ret < 0 || (size_t)ret != size) { - 1230 0 : close(f); - 1231 0 : return -1; - 1232 : } - 1233 : - 1234 294 : if (close(f) != 0) - 1235 0 : return -1; - 1236 : - 1237 294 : return 0; - 1238 : } - 1239 : - 1240 : /** - 1241 : * Read a file extracting the contained device number in %u:%u format. - 1242 : * Return 0 on error. - 1243 : */ - 1244 : #if HAVE_LINUX_DEVICE - 1245 130 : static dev_t devread(const char* path) - 1246 : { - 1247 : int f; - 1248 : int ret; - 1249 : int len; - 1250 : char buf[64]; - 1251 : char* e; - 1252 : unsigned ma; - 1253 : unsigned mi; - 1254 : - 1255 130 : f = open(path, O_RDONLY); - 1256 130 : if (f == -1) { - 1257 : /* LCOV_EXCL_START */ - 1258 : log_fatal(errno, "Failed to open '%s'.\n", path); - 1259 : return 0; - 1260 : /* LCOV_EXCL_STOP */ - 1261 : } - 1262 : - 1263 130 : len = read(f, buf, sizeof(buf)); - 1264 130 : if (len < 0) { - 1265 : /* LCOV_EXCL_START */ - 1266 : close(f); - 1267 : log_fatal(errno, "Failed to read '%s'.\n", path); - 1268 : return 0; - 1269 : /* LCOV_EXCL_STOP */ - 1270 : } - 1271 130 : if (len == sizeof(buf)) { - 1272 : /* LCOV_EXCL_START */ - 1273 : close(f); - 1274 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); - 1275 : return 0; - 1276 : /* LCOV_EXCL_STOP */ - 1277 : } - 1278 : - 1279 130 : ret = close(f); - 1280 130 : if (ret != 0) { - 1281 : /* LCOV_EXCL_START */ - 1282 : log_fatal(errno, "Failed to close '%s'.\n", path); - 1283 : return 0; - 1284 : /* LCOV_EXCL_STOP */ - 1285 : } - 1286 : - 1287 130 : buf[len] = 0; - 1288 : - 1289 130 : ma = strtoul(buf, &e, 10); - 1290 130 : if (*e != ':') { - 1291 : /* LCOV_EXCL_START */ - 1292 : log_fatal(EEXTERNAL, "Invalid format in '%s' for '%s'.\n", path, buf); - 1293 : return 0; - 1294 : /* LCOV_EXCL_STOP */ - 1295 : } - 1296 : - 1297 130 : mi = strtoul(e + 1, &e, 10); - 1298 130 : if (*e != 0 && !isspace(*e)) { - 1299 : /* LCOV_EXCL_START */ - 1300 : log_fatal(EEXTERNAL, "Invalid format in '%s' for '%s'.\n", path, buf); - 1301 : return 0; - 1302 : /* LCOV_EXCL_STOP */ - 1303 : } - 1304 : - 1305 130 : return makedev(ma, mi); - 1306 : } - 1307 : #endif - 1308 : - 1309 : /** - 1310 : * Read a device tree filling the specified list of disk_t entries. - 1311 : */ - 1312 : #if HAVE_LINUX_DEVICE - 1313 130 : static int devtree(devinfo_t* parent, dev_t device, tommy_list* list) - 1314 : { - 1315 : char path[PATH_MAX]; - 1316 : DIR* d; - 1317 130 : int slaves = 0; - 1318 : - 1319 130 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); - 1320 : - 1321 : /* check if there is a slaves list */ - 1322 130 : d = opendir(path); - 1323 130 : if (d != 0) { - 1324 : struct dirent* dd; - 1325 : - 1326 260 : while ((dd = readdir(d)) != 0) { - 1327 195 : if (dd->d_name[0] != '.') { - 1328 : dev_t subdev; - 1329 : - 1330 : /* for each slave, expand the full potential tree */ - 1331 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); - 1332 : - 1333 65 : subdev = devread(path); - 1334 65 : if (!subdev) { - 1335 : /* LCOV_EXCL_START */ - 1336 : closedir(d); - 1337 : return -1; - 1338 : /* LCOV_EXCL_STOP */ - 1339 : } - 1340 : - 1341 65 : if (devtree(parent, subdev, list) != 0) { - 1342 : /* LCOV_EXCL_START */ - 1343 : closedir(d); - 1344 : return -1; - 1345 : /* LCOV_EXCL_STOP */ - 1346 : } - 1347 : - 1348 65 : ++slaves; - 1349 : } - 1350 : } - 1351 : - 1352 65 : closedir(d); - 1353 : } - 1354 : - 1355 : /* if no slaves found */ - 1356 130 : if (!slaves) { - 1357 : /* this is a raw device */ - 1358 : devinfo_t* devinfo; - 1359 : - 1360 : /* check if it's a real device */ - 1361 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); - 1362 65 : if (access(path, F_OK) != 0) { - 1363 : /* get the parent device */ - 1364 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); - 1365 : - 1366 65 : device = devread(path); - 1367 65 : if (!device) { - 1368 : /* LCOV_EXCL_START */ - 1369 : return -1; - 1370 : /* LCOV_EXCL_STOP */ - 1371 : } - 1372 : } - 1373 : - 1374 : /* get the device file */ - 1375 65 : if (devresolve(device, path, sizeof(path)) != 0) { - 1376 : /* LCOV_EXCL_START */ - 1377 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1378 : return -1; - 1379 : /* LCOV_EXCL_STOP */ - 1380 : } - 1381 : - 1382 65 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); - 1383 : - 1384 65 : devinfo->device = device; - 1385 65 : pathcpy(devinfo->name, sizeof(devinfo->name), parent->name); - 1386 65 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), parent->smartctl); - 1387 65 : memcpy(devinfo->smartignore, parent->smartignore, sizeof(devinfo->smartignore)); - 1388 65 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 1389 65 : devinfo->parent = parent; - 1390 : - 1391 : /* insert in the list */ - 1392 65 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 1393 : } - 1394 : - 1395 130 : return 0; - 1396 : } - 1397 : #endif - 1398 : - 1399 : /** - 1400 : * Scan all the devices. - 1401 : * - 1402 : * If a device is already in, it's not added again. - 1403 : */ - 1404 : #if HAVE_LINUX_DEVICE - 1405 0 : static int devscan(tommy_list* list) - 1406 : { - 1407 : char dir[PATH_MAX]; - 1408 : DIR* d; - 1409 : struct dirent* dd; - 1410 : - 1411 0 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); - 1412 : - 1413 : /* check if there is a slaves list */ - 1414 0 : d = opendir(dir); - 1415 0 : if (d == 0) { - 1416 : /* LCOV_EXCL_START */ - 1417 : log_fatal(errno, "Failed to open dir '%s'.\n", dir); - 1418 : return -1; - 1419 : /* LCOV_EXCL_STOP */ - 1420 : } - 1421 : - 1422 0 : while ((dd = readdir(d)) != 0) { - 1423 : char path[PATH_MAX]; - 1424 : tommy_node* i; - 1425 : dev_t device; - 1426 : devinfo_t* devinfo; - 1427 : - 1428 0 : if (dd->d_name[0] == '.') - 1429 0 : continue; - 1430 : - 1431 0 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); - 1432 : - 1433 : /* check if it's a real device */ - 1434 0 : if (access(path, F_OK) != 0) - 1435 0 : continue; - 1436 : - 1437 0 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); - 1438 : - 1439 0 : device = devread(path); - 1440 0 : if (!device) { - 1441 : /* LCOV_EXCL_START */ - 1442 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name); - 1443 : continue; - 1444 : /* LCOV_EXCL_STOP */ - 1445 : } - 1446 : - 1447 : /* check if already present */ - 1448 0 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 1449 0 : devinfo = i->data; - 1450 0 : if (devinfo->device == device) - 1451 0 : break; - 1452 : } - 1453 : - 1454 : /* if already present */ - 1455 0 : if (i != 0) - 1456 0 : continue; - 1457 : - 1458 : /* get the device file */ - 1459 0 : if (devresolve(device, path, sizeof(path)) != 0) { - 1460 : /* LCOV_EXCL_START */ - 1461 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device)); - 1462 : continue; - 1463 : /* LCOV_EXCL_STOP */ - 1464 : } - 1465 : - 1466 0 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); - 1467 : - 1468 0 : devinfo->device = device; - 1469 0 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 1470 : - 1471 : /* insert in the list */ - 1472 0 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 1473 : } - 1474 : - 1475 0 : closedir(d); - 1476 0 : return 0; - 1477 : } - 1478 : #endif - 1479 : - 1480 : /** - 1481 : * Get SMART attributes. - 1482 : */ - 1483 : #if HAVE_LINUX_DEVICE - 1484 0 : static int devsmart(dev_t device, const char* name, const char* smartctl, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* interface) - 1485 : { - 1486 : char cmd[PATH_MAX + 64]; - 1487 : char file[PATH_MAX]; - 1488 : FILE* f; - 1489 : int ret; - 1490 : const char* x; - 1491 : - 1492 0 : x = find_smartctl(); - 1493 0 : if (!x) { - 1494 : /* LCOV_EXCL_START */ - 1495 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); - 1496 : return -1; - 1497 : /* LCOV_EXCL_STOP */ - 1498 : } - 1499 : - 1500 0 : if (devresolve(device, file, sizeof(file)) != 0) { - 1501 : /* LCOV_EXCL_START */ - 1502 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1503 : return -1; - 1504 : /* LCOV_EXCL_STOP */ - 1505 : } - 1506 : - 1507 : /* if there is a custom smartctl command */ - 1508 0 : if (smartctl[0]) { - 1509 : char option[PATH_MAX]; - 1510 0 : snprintf(option, sizeof(option), smartctl, file); - 1511 0 : snprintf(cmd, sizeof(cmd), "%s -a %s", x, option); - 1512 : } else { - 1513 0 : snprintf(cmd, sizeof(cmd), "%s -a %s", x, file); - 1514 : } - 1515 : - 1516 0 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 1517 : - 1518 0 : f = popen(cmd, "r"); - 1519 0 : if (!f) { - 1520 : /* LCOV_EXCL_START */ - 1521 : log_tag("device:%s:%s:shell\n", file, name); - 1522 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); - 1523 : return -1; - 1524 : /* LCOV_EXCL_STOP */ - 1525 : } - 1526 : - 1527 0 : if (smartctl_attribute(f, file, name, smart, info, serial, family, model, interface) != 0) { - 1528 : /* LCOV_EXCL_START */ - 1529 : pclose(f); - 1530 : log_tag("device:%s:%s:shell\n", file, name); - 1531 : return -1; - 1532 : /* LCOV_EXCL_STOP */ - 1533 : } - 1534 : - 1535 0 : ret = pclose(f); - 1536 : - 1537 0 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); - 1538 : - 1539 0 : if (!WIFEXITED(ret)) { - 1540 : /* LCOV_EXCL_START */ - 1541 : log_tag("device:%s:%s:abort\n", file, name); - 1542 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); - 1543 : return -1; - 1544 : /* LCOV_EXCL_STOP */ - 1545 : } - 1546 0 : if (WEXITSTATUS(ret) == 127) { - 1547 : /* LCOV_EXCL_START */ - 1548 : log_tag("device:%s:%s:shell\n", file, name); - 1549 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); - 1550 : return -1; - 1551 : /* LCOV_EXCL_STOP */ - 1552 : } - 1553 : - 1554 : /* store the return smartctl return value */ - 1555 0 : smart[SMART_FLAGS].raw = WEXITSTATUS(ret); - 1556 : - 1557 0 : return 0; - 1558 : } - 1559 : #endif - 1560 : - 1561 : /** - 1562 : * Compute disk usage by aggregating access statistics. - 1563 : */ - 1564 : #if HAVE_LINUX_DEVICE - 1565 65 : static int devstat(dev_t device, uint64_t* count) - 1566 : { - 1567 : char path[PATH_MAX]; - 1568 : char buf[512]; - 1569 : int token; - 1570 : int ret; - 1571 : char* i; - 1572 : - 1573 65 : *count = 0; - 1574 : - 1575 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/stat", major(device), minor(device)); - 1576 : - 1577 65 : ret = sysread(path, buf, sizeof(buf)); - 1578 65 : if (ret < 0) { - 1579 : /* LCOV_EXCL_START */ - 1580 : log_fatal(errno, "Failed to read '%s'.\n", path); - 1581 : return -1; - 1582 : /* LCOV_EXCL_STOP */ - 1583 : } - 1584 65 : if ((size_t)ret + 1 > sizeof(buf)) { - 1585 : /* LCOV_EXCL_START */ - 1586 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); - 1587 : return -1; - 1588 : /* LCOV_EXCL_STOP */ - 1589 : } - 1590 : - 1591 : /* ending 0 */ - 1592 65 : buf[ret] = 0; - 1593 : - 1594 65 : i = buf; - 1595 65 : token = 1; /* token number */ - 1596 325 : while (*i) { - 1597 : char* n; - 1598 : char* e; - 1599 : unsigned long long v; - 1600 : - 1601 : /* skip spaces */ - 1602 910 : while (*i && isspace(*i)) - 1603 585 : ++i; - 1604 : - 1605 : /* read digits */ - 1606 325 : n = i; - 1607 2405 : while (*i && isdigit(*i)) - 1608 2080 : ++i; - 1609 : - 1610 325 : if (i == n) /* if no digit, abort */ - 1611 65 : break; - 1612 325 : if (*i == 0 || !isspace(*i)) /* if no space, abort */ - 1613 : break; - 1614 325 : *i++ = 0; /* put a terminator */ - 1615 : - 1616 325 : v = strtoull(n, &e, 10); - 1617 325 : if (*e != 0) - 1618 0 : break; - 1619 : - 1620 : /* sum reads and writes completed */ - 1621 325 : if (token == 1 || token == 5) { - 1622 130 : *count += v; - 1623 130 : if (token == 5) - 1624 65 : break; /* stop here */ - 1625 : } - 1626 : - 1627 260 : ++token; - 1628 : } - 1629 : - 1630 65 : return 0; - 1631 : } - 1632 : #endif - 1633 : - 1634 : /** - 1635 : * Get device attributes. - 1636 : */ - 1637 : #if HAVE_LINUX_DEVICE - 1638 0 : static void devattr(dev_t device, uint64_t* info, char* serial, char* family, char* model, char* interface) - 1639 : { - 1640 : char path[PATH_MAX]; - 1641 : char buf[512]; - 1642 : int ret; - 1643 : char* attr; + 637 : + 638 : #ifdef __APPLE__ + 639 : static int devuuid_darwin(const char* path, char* uuid, size_t uuid_size) + 640 : { + 641 : CFStringRef path_apple = 0; + 642 : DASessionRef session = 0; + 643 : CFURLRef path_appler = 0; + 644 : int result = -1; + 645 : + 646 : *uuid = 0; + 647 : + 648 : path_apple = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); + 649 : if (!path_apple) + 650 : goto bail; + 651 : + 652 : session = DASessionCreate(kCFAllocatorDefault); + 653 : if (!session) + 654 : goto bail; + 655 : + 656 : path_appler = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_apple, kCFURLPOSIXPathStyle, false); + 657 : if (!path_appler) + 658 : goto bail; + 659 : + 660 : /* find the mount point */ + 661 : DADiskRef disk = NULL; + 662 : while (path_appler) { + 663 : disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, path_appler); + 664 : if (disk) + 665 : break; + 666 : + 667 : CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, path_appler); + 668 : if (!parent) + 669 : break; + 670 : + 671 : /* check if we hit the root (parent == child) */ + 672 : if (CFEqual(parent, path_appler)) { + 673 : CFRelease(parent); + 674 : break; + 675 : } + 676 : + 677 : CFRelease(path_appler); + 678 : path_appler = parent; + 679 : } + 680 : + 681 : /* safely extract the UUID */ + 682 : if (disk) { + 683 : CFDictionaryRef description = DADiskCopyDescription(disk); + 684 : if (description) { + 685 : /* key might not exist for NTFS/ExFAT on some drivers */ + 686 : const void* value = (CFUUIDRef)CFDictionaryGetValue(description, kDADiskDescriptionVolumeUUIDKey); + 687 : CFStringRef uuid_string = NULL; + 688 : + 689 : if (value) { + 690 : if (CFGetTypeID(value) == CFUUIDGetTypeID()) { + 691 : uuid_string = CFUUIDCreateString(kCFAllocatorDefault, (CFUUIDRef)value); + 692 : } else if (CFGetTypeID(value) == CFStringGetTypeID()) { + 693 : /* if it's already a string, retain it so we can release it later consistently */ + 694 : uuid_string = (CFStringRef)CFRetain(value); + 695 : } + 696 : } + 697 : + 698 : if (uuid_string) { + 699 : if (CFStringGetCString(uuid_string, uuid, uuid_size, kCFStringEncodingUTF8)) { + 700 : result = 0; /* success */ + 701 : } + 702 : CFRelease(uuid_string); + 703 : } + 704 : + 705 : CFRelease(description); + 706 : } + 707 : CFRelease(disk); + 708 : } + 709 : + 710 : bail: + 711 : /* clean up */ + 712 : if (path_appler) CFRelease(path_appler); + 713 : if (session) CFRelease(session); + 714 : if (path_apple) CFRelease(path_apple); + 715 : + 716 : return result; + 717 : } + 718 : #endif + 719 : + 720 10560 : int devuuid(uint64_t device, const char* path, char* uuid, size_t uuid_size) + 721 : { + 722 : (void)path; + 723 : (void)device; + 724 : + 725 : #ifdef __APPLE__ + 726 : if (devuuid_darwin(path, uuid, uuid_size) == 0) + 727 : return 0; + 728 : #endif + 729 : + 730 : #if HAVE_LINUX_DEVICE + 731 : /* if the major is the null device */ + 732 10560 : if (major(device) == 0) { + 733 : /* obtain the real device */ + 734 4 : if (devdereference(device, &device) != 0) { + 735 : /* LCOV_EXCL_START */ + 736 : return -1; + 737 : /* LCOV_EXCL_STOP */ + 738 : } + 739 : } + 740 : #endif + 741 : + 742 : /* first try with the /dev/disk/by-uuid version */ + 743 : #if HAVE_LINUX_DEVICE + 744 10556 : if (devuuid_dev(device, uuid, uuid_size) == 0) + 745 10556 : return 0; + 746 : #else + 747 : log_tag("uuid:by-uuid:%u:%u: by-uuid not supported\n", major(device), minor(device)); + 748 : #endif + 749 : + 750 : /* fall back to blkid for other cases */ + 751 : #if HAVE_BLKID + 752 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0) + 753 0 : return 0; + 754 : #else + 755 : log_tag("uuid:blkid:%u:%u: blkid support not compiled in\n", major(device), minor(device)); + 756 : #endif + 757 : + 758 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); + 759 : + 760 : /* not supported */ + 761 : (void)uuid; + 762 : (void)uuid_size; + 763 0 : return -1; + 764 : } + 765 : + 766 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) + 767 : { + 768 : #if HAVE_LINUX_FIEMAP_H + 769 : /* In Linux get the real physical address of the file */ + 770 : /* Note that FIEMAP doesn't require root permission */ + 771 : int f; + 772 : struct fiemap* fiemap; + 773 : size_t fiemap_size; + 774 : unsigned int blknum; + 775 : + 776 11432 : f = open(path, O_RDONLY); + 777 11432 : if (f == -1) { + 778 0 : return -1; + 779 : } + 780 : + 781 : /* first try with FIEMAP */ + 782 : /* if works for ext2, ext3, ext4, xfs, btrfs */ + 783 11432 : fiemap_size = sizeof(struct fiemap) + sizeof(struct fiemap_extent); + 784 11432 : fiemap = malloc_nofail(fiemap_size); + 785 11432 : memset(fiemap, 0, fiemap_size); + 786 11432 : fiemap->fm_start = 0; + 787 11432 : fiemap->fm_length = ~0ULL; + 788 11432 : fiemap->fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ + 789 11432 : fiemap->fm_extent_count = 1; /* we are interested only at the first block */ + 790 : + 791 11432 : if (ioctl(f, FS_IOC_FIEMAP, fiemap) != -1) { + 792 11432 : uint32_t flags = fiemap->fm_extents[0].fe_flags; + 793 11432 : uint64_t offset = fiemap->fm_extents[0].fe_physical; + 794 : + 795 : /* check some condition for validating the offset */ + 796 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) { + 797 : /* if the data is inline, we don't have an offset to report */ + 798 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 799 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) { + 800 : /* if the offset is unknown, we don't have an offset to report */ + 801 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 802 11432 : } else if (offset == 0) { + 803 : /* 0 is the general fallback for file-systems when */ + 804 : /* they don't have an offset to report */ + 805 14 : *physical = FILEPHY_WITHOUT_OFFSET; + 806 : } else { + 807 : /* finally report the real offset */ + 808 11418 : *physical = offset + FILEPHY_REAL_OFFSET; + 809 : } + 810 : + 811 11432 : if (close(f) == -1) + 812 0 : return -1; + 813 11432 : return 0; + 814 : } + 815 : + 816 0 : free(fiemap); + 817 : + 818 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ + 819 0 : if (size == 0) { + 820 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 821 0 : if (close(f) == -1) + 822 0 : return -1; + 823 0 : return 0; + 824 : } + 825 : + 826 : /* then try with FIBMAP */ + 827 : /* it works for jfs, reiserfs, ntfs-3g */ + 828 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ + 829 0 : blknum = 0; /* first block */ + 830 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { + 831 0 : *physical = blknum + FILEPHY_REAL_OFFSET; + 832 0 : if (close(f) == -1) + 833 0 : return -1; + 834 0 : return 0; + 835 : } + 836 : + 837 : /* otherwise don't use anything, and keep the directory traversal order */ + 838 : /* at now this should happen only for vfat */ + 839 : /* and it's surely better than using fake inodes */ + 840 0 : *physical = FILEPHY_UNREPORTED_OFFSET; + 841 0 : if (close(f) == -1) + 842 0 : return -1; + 843 : #else + 844 : /* In a generic Unix use a dummy value for all the files */ + 845 : /* We don't want to risk to use the inode without knowing */ + 846 : /* if it really improves performance. */ + 847 : /* In this way we keep them in the directory traversal order */ + 848 : /* that at least keeps files in the same directory together. */ + 849 : /* Note also that in newer file-system with snapshot, like ZFS, */ + 850 : /* the inode doesn't represent even more the disk position, because files */ + 851 : /* are not overwritten in place, but rewritten in another location */ + 852 : /* of the disk. */ + 853 : *physical = FILEPHY_UNREPORTED_OFFSET; + 854 : + 855 : (void)path; /* not used here */ + 856 : (void)size; + 857 : #endif + 858 : + 859 0 : return 0; + 860 : } + 861 : + 862 : /* from man statfs */ + 863 : #define ADFS_SUPER_MAGIC 0xadf5 + 864 : #define AFFS_SUPER_MAGIC 0xADFF + 865 : #define BDEVFS_MAGIC 0x62646576 + 866 : #define BEFS_SUPER_MAGIC 0x42465331 + 867 : #define BFS_MAGIC 0x1BADFACE + 868 : #define BINFMTFS_MAGIC 0x42494e4d + 869 : #define BTRFS_SUPER_MAGIC 0x9123683E + 870 : #define CGROUP_SUPER_MAGIC 0x27e0eb + 871 : #define CIFS_MAGIC_NUMBER 0xFF534D42 + 872 : #define CODA_SUPER_MAGIC 0x73757245 + 873 : #define COH_SUPER_MAGIC 0x012FF7B7 + 874 : #define CRAMFS_MAGIC 0x28cd3d45 + 875 : #define DEBUGFS_MAGIC 0x64626720 + 876 : #define DEVFS_SUPER_MAGIC 0x1373 + 877 : #define DEVPTS_SUPER_MAGIC 0x1cd1 + 878 : #define EFIVARFS_MAGIC 0xde5e81e4 + 879 : #define EFS_SUPER_MAGIC 0x00414A53 + 880 : #define EXT_SUPER_MAGIC 0x137D + 881 : #define EXT2_OLD_SUPER_MAGIC 0xEF51 + 882 : #define EXT4_SUPER_MAGIC 0xEF53 /* also ext2/ext3 */ + 883 : #define FUSE_SUPER_MAGIC 0x65735546 + 884 : #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA + 885 : #define HFS_SUPER_MAGIC 0x4244 + 886 : #define HFSPLUS_SUPER_MAGIC 0x482b + 887 : #define HOSTFS_SUPER_MAGIC 0x00c0ffee + 888 : #define HPFS_SUPER_MAGIC 0xF995E849 + 889 : #define HUGETLBFS_MAGIC 0x958458f6 + 890 : #define ISOFS_SUPER_MAGIC 0x9660 + 891 : #define JFFS2_SUPER_MAGIC 0x72b6 + 892 : #define JFS_SUPER_MAGIC 0x3153464a + 893 : #define MINIX_SUPER_MAGIC 0x137F + 894 : #define MINIX_SUPER_MAGIC2 0x138F + 895 : #define MINIX2_SUPER_MAGIC 0x2468 + 896 : #define MINIX2_SUPER_MAGIC2 0x2478 + 897 : #define MINIX3_SUPER_MAGIC 0x4d5a + 898 : #define MQUEUE_MAGIC 0x19800202 + 899 : #define MSDOS_SUPER_MAGIC 0x4d44 + 900 : #define NCP_SUPER_MAGIC 0x564c + 901 : #define NFS_SUPER_MAGIC 0x6969 + 902 : #define NILFS_SUPER_MAGIC 0x3434 + 903 : #define NTFS_SB_MAGIC 0x5346544e + 904 : #define OCFS2_SUPER_MAGIC 0x7461636f + 905 : #define OPENPROM_SUPER_MAGIC 0x9fa1 + 906 : #define PIPEFS_MAGIC 0x50495045 + 907 : #define PROC_SUPER_MAGIC 0x9fa0 + 908 : #define PSTOREFS_MAGIC 0x6165676C + 909 : #define QNX4_SUPER_MAGIC 0x002f + 910 : #define QNX6_SUPER_MAGIC 0x68191122 + 911 : #define RAMFS_MAGIC 0x858458f6 + 912 : #define REISERFS_SUPER_MAGIC 0x52654973 + 913 : #define ROMFS_MAGIC 0x7275 + 914 : #define SELINUX_MAGIC 0xf97cff8c + 915 : #define SMACK_MAGIC 0x43415d53 + 916 : #define SMB_SUPER_MAGIC 0x517B + 917 : #define SOCKFS_MAGIC 0x534F434B + 918 : #define SQUASHFS_MAGIC 0x73717368 + 919 : #define SYSFS_MAGIC 0x62656572 + 920 : #define SYSV2_SUPER_MAGIC 0x012FF7B6 + 921 : #define SYSV4_SUPER_MAGIC 0x012FF7B5 + 922 : #define TMPFS_MAGIC 0x01021994 + 923 : #define UDF_SUPER_MAGIC 0x15013346 + 924 : #define UFS_MAGIC 0x00011954 + 925 : #define USBDEVICE_SUPER_MAGIC 0x9fa2 + 926 : #define V9FS_MAGIC 0x01021997 + 927 : #define VXFS_SUPER_MAGIC 0xa501FCF5 + 928 : #define XENFS_SUPER_MAGIC 0xabba1974 + 929 : #define XENIX_SUPER_MAGIC 0x012FF7B4 + 930 : #define XFS_SUPER_MAGIC 0x58465342 + 931 : #define _XIAFS_SUPER_MAGIC 0x012FD16D + 932 : #define AFS_SUPER_MAGIC 0x5346414F + 933 : #define AUFS_SUPER_MAGIC 0x61756673 + 934 : #define ANON_INODE_FS_SUPER_MAGIC 0x09041934 + 935 : #define CEPH_SUPER_MAGIC 0x00C36400 + 936 : #define ECRYPTFS_SUPER_MAGIC 0xF15F + 937 : #define FAT_SUPER_MAGIC 0x4006 + 938 : #define FHGFS_SUPER_MAGIC 0x19830326 + 939 : #define FUSEBLK_SUPER_MAGIC 0x65735546 + 940 : #define FUSECTL_SUPER_MAGIC 0x65735543 + 941 : #define GFS_SUPER_MAGIC 0x1161970 + 942 : #define GPFS_SUPER_MAGIC 0x47504653 + 943 : #define MTD_INODE_FS_SUPER_MAGIC 0x11307854 + 944 : #define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA + 945 : #define ISOFS_R_WIN_SUPER_MAGIC 0x4004 + 946 : #define ISOFS_WIN_SUPER_MAGIC 0x4000 + 947 : #define JFFS_SUPER_MAGIC 0x07C0 + 948 : #define KAFS_SUPER_MAGIC 0x6B414653 + 949 : #define LUSTRE_SUPER_MAGIC 0x0BD00BD0 + 950 : #define NFSD_SUPER_MAGIC 0x6E667364 + 951 : #define PANFS_SUPER_MAGIC 0xAAD7AAEA + 952 : #define RPC_PIPEFS_SUPER_MAGIC 0x67596969 + 953 : #define SECURITYFS_SUPER_MAGIC 0x73636673 + 954 : #define UFS_BYTESWAPPED_SUPER_MAGIC 0x54190100 + 955 : #define VMHGFS_SUPER_MAGIC 0xBACBACBC + 956 : #define VZFS_SUPER_MAGIC 0x565A4653 + 957 : #define ZFS_SUPER_MAGIC 0x2FC12FC1 + 958 : + 959 : struct filesystem_entry { + 960 : unsigned id; + 961 : const char* name; + 962 : int remote; + 963 : } FILESYSTEMS[] = { + 964 : { ADFS_SUPER_MAGIC, "adfs", 0 }, + 965 : { AFFS_SUPER_MAGIC, "affs", 0 }, + 966 : { AFS_SUPER_MAGIC, "afs", 1 }, + 967 : { AUFS_SUPER_MAGIC, "aufs", 1 }, + 968 : { BEFS_SUPER_MAGIC, "befs", 0 }, + 969 : { BDEVFS_MAGIC, "bdevfs", 0 }, + 970 : { BFS_MAGIC, "bfs", 0 }, + 971 : { BINFMTFS_MAGIC, "binfmt_misc", 0 }, + 972 : { BTRFS_SUPER_MAGIC, "btrfs", 0 }, + 973 : { CEPH_SUPER_MAGIC, "ceph", 1 }, + 974 : { CGROUP_SUPER_MAGIC, "cgroupfs", 0 }, + 975 : { CIFS_MAGIC_NUMBER, "cifs", 1 }, + 976 : { CODA_SUPER_MAGIC, "coda", 1 }, + 977 : { COH_SUPER_MAGIC, "coh", 0 }, + 978 : { CRAMFS_MAGIC, "cramfs", 0 }, + 979 : { DEBUGFS_MAGIC, "debugfs", 0 }, + 980 : { DEVFS_SUPER_MAGIC, "devfs", 0 }, + 981 : { DEVPTS_SUPER_MAGIC, "devpts", 0 }, + 982 : { ECRYPTFS_SUPER_MAGIC, "ecryptfs", 0 }, + 983 : { EFS_SUPER_MAGIC, "efs", 0 }, + 984 : { EXT_SUPER_MAGIC, "ext", 0 }, + 985 : { EXT4_SUPER_MAGIC, "ext4", 0 }, + 986 : { EXT2_OLD_SUPER_MAGIC, "ext2", 0 }, + 987 : { FAT_SUPER_MAGIC, "fat", 0 }, + 988 : { FHGFS_SUPER_MAGIC, "fhgfs", 1 }, + 989 : { FUSEBLK_SUPER_MAGIC, "fuseblk", 1 }, + 990 : { FUSECTL_SUPER_MAGIC, "fusectl", 1 }, + 991 : { FUTEXFS_SUPER_MAGIC, "futexfs", 0 }, + 992 : { GFS_SUPER_MAGIC, "gfs/gfs2", 1 }, + 993 : { GPFS_SUPER_MAGIC, "gpfs", 1 }, + 994 : { HFS_SUPER_MAGIC, "hfs", 0 }, + 995 : { HFSPLUS_SUPER_MAGIC, "hfsplus", 0 }, + 996 : { HPFS_SUPER_MAGIC, "hpfs", 0 }, + 997 : { HUGETLBFS_MAGIC, "hugetlbfs", 0 }, + 998 : { MTD_INODE_FS_SUPER_MAGIC, "inodefs", 0 }, + 999 : { INOTIFYFS_SUPER_MAGIC, "inotifyfs", 0 }, + 1000 : { ISOFS_SUPER_MAGIC, "isofs", 0 }, + 1001 : { ISOFS_R_WIN_SUPER_MAGIC, "isofs", 0 }, + 1002 : { ISOFS_WIN_SUPER_MAGIC, "isofs", 0 }, + 1003 : { JFFS_SUPER_MAGIC, "jffs", 0 }, + 1004 : { JFFS2_SUPER_MAGIC, "jffs2", 0 }, + 1005 : { JFS_SUPER_MAGIC, "jfs", 0 }, + 1006 : { KAFS_SUPER_MAGIC, "k-afs", 1 }, + 1007 : { LUSTRE_SUPER_MAGIC, "lustre", 1 }, + 1008 : { MINIX_SUPER_MAGIC, "minix", 0 }, + 1009 : { MINIX_SUPER_MAGIC2, "minix", 0 }, + 1010 : { MINIX2_SUPER_MAGIC, "minix2", 0 }, + 1011 : { MINIX2_SUPER_MAGIC2, "minix2", 0 }, + 1012 : { MINIX3_SUPER_MAGIC, "minix3", 0 }, + 1013 : { MQUEUE_MAGIC, "mqueue", 0 }, + 1014 : { MSDOS_SUPER_MAGIC, "msdos", 0 }, + 1015 : { NCP_SUPER_MAGIC, "novell", 1 }, + 1016 : { NFS_SUPER_MAGIC, "nfs", 1 }, + 1017 : { NFSD_SUPER_MAGIC, "nfsd", 1 }, + 1018 : { NILFS_SUPER_MAGIC, "nilfs", 0 }, + 1019 : { NTFS_SB_MAGIC, "ntfs", 0 }, + 1020 : { OPENPROM_SUPER_MAGIC, "openprom", 0 }, + 1021 : { OCFS2_SUPER_MAGIC, "ocfs2", 1 }, + 1022 : { PANFS_SUPER_MAGIC, "panfs", 1 }, + 1023 : { PIPEFS_MAGIC, "pipefs", 1 }, + 1024 : { PROC_SUPER_MAGIC, "proc", 0 }, + 1025 : { PSTOREFS_MAGIC, "pstorefs", 0 }, + 1026 : { QNX4_SUPER_MAGIC, "qnx4", 0 }, + 1027 : { QNX6_SUPER_MAGIC, "qnx6", 0 }, + 1028 : { RAMFS_MAGIC, "ramfs", 0 }, + 1029 : { REISERFS_SUPER_MAGIC, "reiserfs", 0 }, + 1030 : { ROMFS_MAGIC, "romfs", 0 }, + 1031 : { RPC_PIPEFS_SUPER_MAGIC, "rpc_pipefs", 0 }, + 1032 : { SECURITYFS_SUPER_MAGIC, "securityfs", 0 }, + 1033 : { SELINUX_MAGIC, "selinux", 0 }, + 1034 : { SMB_SUPER_MAGIC, "smb", 1 }, + 1035 : { SOCKFS_MAGIC, "sockfs", 0 }, + 1036 : { SQUASHFS_MAGIC, "squashfs", 0 }, + 1037 : { SYSFS_MAGIC, "sysfs", 0 }, + 1038 : { SYSV2_SUPER_MAGIC, "sysv2", 0 }, + 1039 : { SYSV4_SUPER_MAGIC, "sysv4", 0 }, + 1040 : { TMPFS_MAGIC, "tmpfs", 0 }, + 1041 : { UDF_SUPER_MAGIC, "udf", 0 }, + 1042 : { UFS_MAGIC, "ufs", 0 }, + 1043 : { UFS_BYTESWAPPED_SUPER_MAGIC, "ufs", 0 }, + 1044 : { USBDEVICE_SUPER_MAGIC, "usbdevfs", 0 }, + 1045 : { V9FS_MAGIC, "v9fs", 0 }, + 1046 : { VMHGFS_SUPER_MAGIC, "vmhgfs", 1 }, + 1047 : { VXFS_SUPER_MAGIC, "vxfs", 0 }, + 1048 : { VZFS_SUPER_MAGIC, "vzfs", 0 }, + 1049 : { XENFS_SUPER_MAGIC, "xenfs", 0 }, + 1050 : { XENIX_SUPER_MAGIC, "xenix", 0 }, + 1051 : { XFS_SUPER_MAGIC, "xfs", 0 }, + 1052 : { _XIAFS_SUPER_MAGIC, "xia", 0 }, + 1053 : { ZFS_SUPER_MAGIC, "zfs", 0 }, + 1054 : { 0 } + 1055 : }; + 1056 : + 1057 6412 : int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space, char* fstype, size_t fstype_size, char* fslabel, size_t fslabel_size) + 1058 : { + 1059 : #if HAVE_STATFS + 1060 : struct statfs st; + 1061 : + 1062 6412 : if (statfs(path, &st) != 0) { + 1063 : char dir[PATH_MAX]; + 1064 : char* slash; + 1065 : + 1066 48 : if (errno != ENOENT) { + 1067 0 : return -1; + 1068 : } + 1069 : + 1070 : /* if it doesn't exist, we assume a file */ + 1071 : /* and we check for the containing dir */ + 1072 48 : if (strlen(path) + 1 > sizeof(dir)) { + 1073 0 : errno = ENAMETOOLONG; + 1074 0 : return -1; + 1075 : } + 1076 : + 1077 48 : strcpy(dir, path); + 1078 : + 1079 48 : slash = strrchr(dir, '/'); + 1080 48 : if (!slash) + 1081 0 : return -1; + 1082 : + 1083 48 : *slash = 0; + 1084 48 : if (statfs(dir, &st) != 0) + 1085 0 : return -1; + 1086 : } + 1087 : #endif + 1088 : + 1089 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ + 1090 6412 : if (has_persistent_inode) { + 1091 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 1092 605 : switch (st.f_type) { + 1093 0 : case FUSEBLK_SUPER_MAGIC : /* FUSE, "fuseblk" in the stat command */ + 1094 : case MSDOS_SUPER_MAGIC : /* VFAT, "msdos" in the stat command */ + 1095 0 : *has_persistent_inode = 0; + 1096 0 : break; + 1097 605 : default : + 1098 : /* by default assume yes */ + 1099 605 : *has_persistent_inode = 1; + 1100 605 : break; + 1101 : } + 1102 : #else + 1103 : /* in Unix inodes are persistent by default */ + 1104 : *has_persistent_inode = 1; + 1105 : #endif + 1106 : } + 1107 : + 1108 6412 : if (has_syncronized_hardlinks) { + 1109 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 1110 605 : switch (st.f_type) { + 1111 0 : case NTFS_SB_MAGIC : /* NTFS */ + 1112 : case MSDOS_SUPER_MAGIC : /* VFAT, "msdos" in the stat command */ + 1113 0 : *has_syncronized_hardlinks = 0; + 1114 0 : break; + 1115 605 : default : + 1116 : /* by default assume yes */ + 1117 605 : *has_syncronized_hardlinks = 1; + 1118 605 : break; + 1119 : } + 1120 : #else + 1121 : /* in Unix hardlinks share the same metadata by default */ + 1122 : *has_syncronized_hardlinks = 1; + 1123 : #endif + 1124 : } + 1125 : + 1126 6412 : if (total_space) { + 1127 : #if HAVE_STATFS + 1128 5807 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; + 1129 : #else + 1130 : *total_space = 0; + 1131 : #endif + 1132 : } + 1133 : + 1134 6412 : if (free_space) { + 1135 : #if HAVE_STATFS + 1136 5807 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; + 1137 : #else + 1138 : *free_space = 0; + 1139 : #endif + 1140 : } + 1141 : + 1142 6412 : const char* ptype = 0; + 1143 : + 1144 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME + 1145 : /* get the filesystem type directly from the struct (Mac OS X) */ + 1146 : ptype = st.f_fstypename; + 1147 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 1148 : /* get the filesystem type from f_type (Linux) */ + 1149 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */ + 1150 141064 : for (int i = 0; FILESYSTEMS[i].id != 0; ++i) { + 1151 141064 : if (st.f_type == FILESYSTEMS[i].id) { + 1152 6412 : ptype = FILESYSTEMS[i].name; + 1153 6412 : break; + 1154 : } + 1155 : } + 1156 : #endif + 1157 : + 1158 6412 : if (fstype) { + 1159 5807 : fstype[0] = 0; + 1160 5807 : if (ptype) + 1161 5807 : snprintf(fstype, fstype_size, "%s", ptype); + 1162 : } + 1163 : + 1164 6412 : if (fslabel) { + 1165 5807 : fslabel[0] = 0; + 1166 : #if HAVE_BLKID + 1167 : struct stat fst; + 1168 5807 : if (stat(path, &fst) == 0) + 1169 5759 : devuuid_label(fst.st_dev, fslabel, fslabel_size); + 1170 : #else + 1171 : (void)fslabel_size; + 1172 : #endif + 1173 : } + 1174 : + 1175 6412 : return 0; + 1176 : } + 1177 : + 1178 3816139 : uint64_t tick(void) + 1179 : { + 1180 : #if HAVE_MACH_ABSOLUTE_TIME + 1181 : /* for Mac OS X */ + 1182 : return mach_absolute_time(); + 1183 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) + 1184 : /* for Linux */ + 1185 : struct timespec tv; + 1186 : + 1187 : /* nanosecond precision with clock_gettime() */ + 1188 : #if defined(CLOCK_MONOTONIC_RAW) + 1189 3816139 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { + 1190 : #else + 1191 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { + 1192 : #endif + 1193 0 : return 0; + 1194 : } + 1195 : + 1196 3816139 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; + 1197 : #else + 1198 : /* other platforms */ + 1199 : struct timeval tv; + 1200 : + 1201 : /* microsecond precision with gettimeofday() */ + 1202 : if (gettimeofday(&tv, 0) != 0) { + 1203 : return 0; + 1204 : } + 1205 : + 1206 : return tv.tv_sec * 1000000ULL + tv.tv_usec; + 1207 : #endif + 1208 : } + 1209 : + 1210 3567 : uint64_t tick_ms(void) + 1211 : { + 1212 : struct timeval tv; + 1213 : + 1214 3567 : if (gettimeofday(&tv, 0) != 0) + 1215 0 : return 0; + 1216 : + 1217 3567 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; + 1218 : } + 1219 : + 1220 295 : int randomize(void* ptr, size_t size) + 1221 : { + 1222 : int f; + 1223 : ssize_t ret; + 1224 : + 1225 295 : f = open("/dev/urandom", O_RDONLY); + 1226 295 : if (f == -1) + 1227 0 : return -1; + 1228 : + 1229 295 : ret = read(f, ptr, size); + 1230 295 : if (ret < 0 || (size_t)ret != size) { + 1231 0 : close(f); + 1232 0 : return -1; + 1233 : } + 1234 : + 1235 295 : if (close(f) != 0) + 1236 0 : return -1; + 1237 : + 1238 295 : return 0; + 1239 : } + 1240 : + 1241 : /** + 1242 : * Read a file extracting the contained device number in %u:%u format. + 1243 : * Return 0 on error. + 1244 : */ + 1245 : #if HAVE_LINUX_DEVICE + 1246 168 : static dev_t devread(const char* path) + 1247 : { + 1248 : int f; + 1249 : int ret; + 1250 : int len; + 1251 : char buf[64]; + 1252 : char* e; + 1253 : unsigned ma; + 1254 : unsigned mi; + 1255 : + 1256 168 : f = open(path, O_RDONLY); + 1257 168 : if (f == -1) { + 1258 : /* LCOV_EXCL_START */ + 1259 : log_fatal(errno, "Failed to open '%s'.\n", path); + 1260 : return 0; + 1261 : /* LCOV_EXCL_STOP */ + 1262 : } + 1263 : + 1264 168 : len = read(f, buf, sizeof(buf)); + 1265 168 : if (len < 0) { + 1266 : /* LCOV_EXCL_START */ + 1267 : close(f); + 1268 : log_fatal(errno, "Failed to read '%s'.\n", path); + 1269 : return 0; + 1270 : /* LCOV_EXCL_STOP */ + 1271 : } + 1272 168 : if (len == sizeof(buf)) { + 1273 : /* LCOV_EXCL_START */ + 1274 : close(f); + 1275 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); + 1276 : return 0; + 1277 : /* LCOV_EXCL_STOP */ + 1278 : } + 1279 : + 1280 168 : ret = close(f); + 1281 168 : if (ret != 0) { + 1282 : /* LCOV_EXCL_START */ + 1283 : log_fatal(errno, "Failed to close '%s'.\n", path); + 1284 : return 0; + 1285 : /* LCOV_EXCL_STOP */ + 1286 : } + 1287 : + 1288 168 : buf[len] = 0; + 1289 : + 1290 168 : ma = strtoul(buf, &e, 10); + 1291 168 : if (*e != ':') { + 1292 : /* LCOV_EXCL_START */ + 1293 : log_fatal(EEXTERNAL, "Invalid format in '%s' for '%s'.\n", path, buf); + 1294 : return 0; + 1295 : /* LCOV_EXCL_STOP */ + 1296 : } + 1297 : + 1298 168 : mi = strtoul(e + 1, &e, 10); + 1299 168 : if (*e != 0 && !isspace(*e)) { + 1300 : /* LCOV_EXCL_START */ + 1301 : log_fatal(EEXTERNAL, "Invalid format in '%s' for '%s'.\n", path, buf); + 1302 : return 0; + 1303 : /* LCOV_EXCL_STOP */ + 1304 : } + 1305 : + 1306 168 : return makedev(ma, mi); + 1307 : } + 1308 : #endif + 1309 : + 1310 : /** + 1311 : * Read a device tree filling the specified list of disk_t entries. + 1312 : */ + 1313 : #if HAVE_LINUX_DEVICE + 1314 154 : static int devtree(devinfo_t* parent, dev_t device, tommy_list* list) + 1315 : { + 1316 : char path[PATH_MAX]; + 1317 : DIR* d; + 1318 154 : int slaves = 0; + 1319 : + 1320 154 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); + 1321 : + 1322 : /* check if there is a slaves list */ + 1323 154 : d = opendir(path); + 1324 154 : if (d != 0) { + 1325 : struct dirent* dd; + 1326 : + 1327 308 : while ((dd = readdir(d)) != 0) { + 1328 231 : if (dd->d_name[0] != '.') { + 1329 : dev_t subdev; + 1330 : + 1331 : /* for each slave, expand the full potential tree */ + 1332 77 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); + 1333 : + 1334 77 : subdev = devread(path); + 1335 77 : if (!subdev) { + 1336 : /* LCOV_EXCL_START */ + 1337 : closedir(d); + 1338 : return -1; + 1339 : /* LCOV_EXCL_STOP */ + 1340 : } + 1341 : + 1342 77 : if (devtree(parent, subdev, list) != 0) { + 1343 : /* LCOV_EXCL_START */ + 1344 : closedir(d); + 1345 : return -1; + 1346 : /* LCOV_EXCL_STOP */ + 1347 : } + 1348 : + 1349 77 : ++slaves; + 1350 : } + 1351 : } + 1352 : + 1353 77 : closedir(d); + 1354 : } + 1355 : + 1356 : /* if no slaves found */ + 1357 154 : if (!slaves) { + 1358 : /* this is a raw device */ + 1359 : devinfo_t* devinfo; + 1360 : + 1361 : /* check if it's a real device */ + 1362 77 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); + 1363 77 : if (access(path, F_OK) != 0) { + 1364 : /* get the parent device */ + 1365 77 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); + 1366 : + 1367 77 : device = devread(path); + 1368 77 : if (!device) { + 1369 : /* LCOV_EXCL_START */ + 1370 : return -1; + 1371 : /* LCOV_EXCL_STOP */ + 1372 : } + 1373 : } + 1374 : + 1375 : /* get the device file */ + 1376 77 : if (devresolve(device, path, sizeof(path)) != 0) { + 1377 : /* LCOV_EXCL_START */ + 1378 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1379 : return -1; + 1380 : /* LCOV_EXCL_STOP */ + 1381 : } + 1382 : + 1383 77 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 1384 : + 1385 77 : devinfo->device = device; + 1386 77 : pathcpy(devinfo->name, sizeof(devinfo->name), parent->name); + 1387 77 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), parent->smartctl); + 1388 77 : memcpy(devinfo->smartignore, parent->smartignore, sizeof(devinfo->smartignore)); + 1389 77 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 1390 77 : devinfo->parent = parent; + 1391 : + 1392 : /* insert in the list */ + 1393 77 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 1394 : } + 1395 : + 1396 154 : return 0; + 1397 : } + 1398 : #endif + 1399 : + 1400 : /** + 1401 : * Scan all the devices. + 1402 : * + 1403 : * If a device is already in, it's not added again. + 1404 : */ + 1405 : #if HAVE_LINUX_DEVICE + 1406 1 : static int devscan(tommy_list* list) + 1407 : { + 1408 : char dir[PATH_MAX]; + 1409 : DIR* d; + 1410 : struct dirent* dd; + 1411 : + 1412 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); + 1413 : + 1414 : /* check if there is a slaves list */ + 1415 1 : d = opendir(dir); + 1416 1 : if (d == 0) { + 1417 : /* LCOV_EXCL_START */ + 1418 : log_fatal(errno, "Failed to open dir '%s'.\n", dir); + 1419 : return -1; + 1420 : /* LCOV_EXCL_STOP */ + 1421 : } + 1422 : + 1423 75 : while ((dd = readdir(d)) != 0) { + 1424 : char path[PATH_MAX]; + 1425 : tommy_node* i; + 1426 : dev_t device; + 1427 : devinfo_t* devinfo; + 1428 : + 1429 74 : if (dd->d_name[0] == '.') + 1430 72 : continue; + 1431 : + 1432 72 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); + 1433 : + 1434 : /* check if it's a real device */ + 1435 72 : if (access(path, F_OK) != 0) + 1436 58 : continue; + 1437 : + 1438 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); + 1439 : + 1440 14 : device = devread(path); + 1441 14 : if (!device) { + 1442 : /* LCOV_EXCL_START */ + 1443 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name); + 1444 : continue; + 1445 : /* LCOV_EXCL_STOP */ + 1446 : } + 1447 : + 1448 : /* check if already present */ + 1449 105 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1450 103 : devinfo = i->data; + 1451 103 : if (devinfo->device == device) + 1452 12 : break; + 1453 : } + 1454 : + 1455 : /* if already present */ + 1456 14 : if (i != 0) + 1457 12 : continue; + 1458 : + 1459 : /* get the device file */ + 1460 2 : if (devresolve(device, path, sizeof(path)) != 0) { + 1461 : /* LCOV_EXCL_START */ + 1462 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device)); + 1463 : continue; + 1464 : /* LCOV_EXCL_STOP */ + 1465 : } + 1466 : + 1467 2 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 1468 : + 1469 2 : devinfo->device = device; + 1470 2 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 1471 : + 1472 : /* insert in the list */ + 1473 2 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 1474 : } + 1475 : + 1476 1 : closedir(d); + 1477 1 : return 0; + 1478 : } + 1479 : #endif + 1480 : + 1481 : /** + 1482 : * Get SMART attributes. + 1483 : */ + 1484 : #if HAVE_LINUX_DEVICE + 1485 0 : static int devsmart(dev_t device, const char* name, const char* smartctl, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* interface) + 1486 : { + 1487 : char cmd[PATH_MAX + 64]; + 1488 : char file[PATH_MAX]; + 1489 : FILE* f; + 1490 : int ret; + 1491 : const char* x; + 1492 : + 1493 0 : x = find_smartctl(); + 1494 0 : if (!x) { + 1495 : /* LCOV_EXCL_START */ + 1496 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); + 1497 : return -1; + 1498 : /* LCOV_EXCL_STOP */ + 1499 : } + 1500 : + 1501 0 : if (devresolve(device, file, sizeof(file)) != 0) { + 1502 : /* LCOV_EXCL_START */ + 1503 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1504 : return -1; + 1505 : /* LCOV_EXCL_STOP */ + 1506 : } + 1507 : + 1508 : /* if there is a custom smartctl command */ + 1509 0 : if (smartctl[0]) { + 1510 : char option[PATH_MAX]; + 1511 0 : snprintf(option, sizeof(option), smartctl, file); + 1512 0 : snprintf(cmd, sizeof(cmd), "%s -a %s", x, option); + 1513 : } else { + 1514 0 : snprintf(cmd, sizeof(cmd), "%s -a %s", x, file); + 1515 : } + 1516 : + 1517 0 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + 1518 : + 1519 0 : f = popen(cmd, "r"); + 1520 0 : if (!f) { + 1521 : /* LCOV_EXCL_START */ + 1522 : log_tag("device:%s:%s:shell\n", file, name); + 1523 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); + 1524 : return -1; + 1525 : /* LCOV_EXCL_STOP */ + 1526 : } + 1527 : + 1528 0 : if (smartctl_attribute(f, file, name, smart, info, serial, family, model, interface) != 0) { + 1529 : /* LCOV_EXCL_START */ + 1530 : pclose(f); + 1531 : log_tag("device:%s:%s:shell\n", file, name); + 1532 : return -1; + 1533 : /* LCOV_EXCL_STOP */ + 1534 : } + 1535 : + 1536 0 : ret = pclose(f); + 1537 : + 1538 0 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1539 : + 1540 0 : if (!WIFEXITED(ret)) { + 1541 : /* LCOV_EXCL_START */ + 1542 : log_tag("device:%s:%s:abort\n", file, name); + 1543 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); + 1544 : return -1; + 1545 : /* LCOV_EXCL_STOP */ + 1546 : } + 1547 0 : if (WEXITSTATUS(ret) == 127) { + 1548 : /* LCOV_EXCL_START */ + 1549 : log_tag("device:%s:%s:shell\n", file, name); + 1550 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); + 1551 : return -1; + 1552 : /* LCOV_EXCL_STOP */ + 1553 : } + 1554 : + 1555 : /* store the return smartctl return value */ + 1556 0 : smart[SMART_FLAGS].raw = WEXITSTATUS(ret); + 1557 : + 1558 0 : return 0; + 1559 : } + 1560 : #endif + 1561 : + 1562 : /** + 1563 : * Compute disk usage by aggregating access statistics. + 1564 : */ + 1565 : #if HAVE_LINUX_DEVICE + 1566 77 : static int devstat(dev_t device, uint64_t* count) + 1567 : { + 1568 : char path[PATH_MAX]; + 1569 : char buf[512]; + 1570 : int token; + 1571 : int ret; + 1572 : char* i; + 1573 : + 1574 77 : *count = 0; + 1575 : + 1576 77 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/stat", major(device), minor(device)); + 1577 : + 1578 77 : ret = sysread(path, buf, sizeof(buf)); + 1579 77 : if (ret < 0) { + 1580 : /* LCOV_EXCL_START */ + 1581 : log_fatal(errno, "Failed to read '%s'.\n", path); + 1582 : return -1; + 1583 : /* LCOV_EXCL_STOP */ + 1584 : } + 1585 77 : if ((size_t)ret + 1 > sizeof(buf)) { + 1586 : /* LCOV_EXCL_START */ + 1587 : log_fatal(EEXTERNAL, "Too long read '%s'.\n", path); + 1588 : return -1; + 1589 : /* LCOV_EXCL_STOP */ + 1590 : } + 1591 : + 1592 : /* ending 0 */ + 1593 77 : buf[ret] = 0; + 1594 : + 1595 77 : i = buf; + 1596 77 : token = 1; /* token number */ + 1597 385 : while (*i) { + 1598 : char* n; + 1599 : char* e; + 1600 : unsigned long long v; + 1601 : + 1602 : /* skip spaces */ + 1603 1119 : while (*i && isspace(*i)) + 1604 734 : ++i; + 1605 : + 1606 : /* read digits */ + 1607 385 : n = i; + 1608 2820 : while (*i && isdigit(*i)) + 1609 2435 : ++i; + 1610 : + 1611 385 : if (i == n) /* if no digit, abort */ + 1612 77 : break; + 1613 385 : if (*i == 0 || !isspace(*i)) /* if no space, abort */ + 1614 : break; + 1615 385 : *i++ = 0; /* put a terminator */ + 1616 : + 1617 385 : v = strtoull(n, &e, 10); + 1618 385 : if (*e != 0) + 1619 0 : break; + 1620 : + 1621 : /* sum reads and writes completed */ + 1622 385 : if (token == 1 || token == 5) { + 1623 154 : *count += v; + 1624 154 : if (token == 5) + 1625 77 : break; /* stop here */ + 1626 : } + 1627 : + 1628 308 : ++token; + 1629 : } + 1630 : + 1631 77 : return 0; + 1632 : } + 1633 : #endif + 1634 : + 1635 : /** + 1636 : * Get device attributes. + 1637 : */ + 1638 : #if HAVE_LINUX_DEVICE + 1639 14 : static void devattr(dev_t device, uint64_t* info, char* serial, char* family, char* model, char* interface) + 1640 : { + 1641 : char path[PATH_MAX]; + 1642 : char buf[512]; + 1643 : int ret; 1644 : 1645 : (void)family; /* not available, smartctl uses an internal database to get it */ 1646 : - 1647 0 : if (info[INFO_SIZE] == SMART_UNASSIGNED) { - 1648 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/size", major(device), minor(device)); - 1649 0 : attr = sysattr(path, buf, sizeof(buf)); - 1650 0 : if (attr) { - 1651 : char* e; - 1652 : uint64_t v; - 1653 0 : v = strtoul(attr, &e, 10); - 1654 0 : if (*e == 0) - 1655 0 : info[INFO_SIZE] = v * 512; - 1656 : } - 1657 : } - 1658 : - 1659 0 : if (info[INFO_ROTATION_RATE] == SMART_UNASSIGNED) { - 1660 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/queue/rotational", major(device), minor(device)); - 1661 0 : attr = sysattr(path, buf, sizeof(buf)); - 1662 0 : if (attr) { - 1663 : char* e; - 1664 : uint64_t v; - 1665 0 : v = strtoul(attr, &e, 10); - 1666 0 : if (*e == 0) - 1667 0 : info[INFO_ROTATION_RATE] = v; - 1668 : } - 1669 : } - 1670 : - 1671 0 : if (*model == 0) { - 1672 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/model", major(device), minor(device)); - 1673 0 : attr = sysattr(path, buf, sizeof(buf)); - 1674 0 : if (attr && *attr) { - 1675 0 : pathcpy(model, SMART_MAX, attr); - 1676 0 : strtrim(model); - 1677 : } - 1678 : } - 1679 : - 1680 0 : if (*serial == 0) { - 1681 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/serial", major(device), minor(device)); - 1682 0 : attr = sysattr(path, buf, sizeof(buf)); - 1683 0 : if (attr && *attr) { - 1684 0 : pathcpy(serial, SMART_MAX, attr); - 1685 0 : strtrim(serial); - 1686 : } - 1687 : } - 1688 : - 1689 0 : if (*serial == 0) { - 1690 : // --- Page 0x80: Unit Serial Number --- - 1691 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/vpd_pg80", major(device), minor(device)); - 1692 0 : ret = sysread(path, buf, sizeof(buf)); - 1693 0 : if (ret > 4) { - 1694 0 : unsigned len = (unsigned char)buf[3]; - 1695 0 : if (4 + len <= (size_t)ret && 4 + len + 1 <= sizeof(buf)) { - 1696 0 : attr = buf + 4; - 1697 0 : attr[len] = 0; - 1698 0 : strtrim(attr); - 1699 0 : if (*attr) { - 1700 0 : pathcpy(serial, SMART_MAX, attr); - 1701 0 : strtrim(serial); - 1702 : } - 1703 : } - 1704 : } - 1705 : } - 1706 : - 1707 : /* always override interface if it's usb */ - 1708 0 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u", major(device), minor(device)); - 1709 0 : ret = readlink(path, buf, sizeof(buf)); - 1710 0 : if (ret > 0 && (unsigned)ret < sizeof(buf)) { - 1711 0 : buf[ret] = 0; - 1712 0 : if (strstr(buf, "usb") != 0) - 1713 0 : strcpy(interface, "USB"); - 1714 : } - 1715 0 : } - 1716 : #endif - 1717 : - 1718 : /** - 1719 : * Get POWER state. - 1720 : */ - 1721 : #if HAVE_LINUX_DEVICE - 1722 0 : static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* interface) - 1723 : { - 1724 : char cmd[PATH_MAX + 64]; - 1725 : char file[PATH_MAX]; - 1726 : FILE* f; - 1727 : int ret; - 1728 : const char* x; - 1729 : - 1730 0 : x = find_smartctl(); - 1731 0 : if (!x) { - 1732 : /* LCOV_EXCL_START */ - 1733 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); - 1734 : return -1; - 1735 : /* LCOV_EXCL_STOP */ - 1736 : } - 1737 : - 1738 0 : if (devresolve(device, file, sizeof(file)) != 0) { - 1739 : /* LCOV_EXCL_START */ - 1740 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1741 : return -1; - 1742 : /* LCOV_EXCL_STOP */ - 1743 : } - 1744 : - 1745 : /* if there is a custom smartctl command */ - 1746 0 : if (smartctl[0]) { - 1747 : char option[PATH_MAX]; - 1748 0 : snprintf(option, sizeof(option), smartctl, file); - 1749 0 : snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, option); - 1750 : } else { - 1751 0 : snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, file); - 1752 : } - 1753 : - 1754 0 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 1755 : - 1756 0 : f = popen(cmd, "r"); - 1757 0 : if (!f) { - 1758 : /* LCOV_EXCL_START */ - 1759 : log_tag("device:%s:%s:shell\n", file, name); - 1760 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); - 1761 : return -1; - 1762 : /* LCOV_EXCL_STOP */ - 1763 : } - 1764 : - 1765 0 : if (smartctl_attribute(f, file, name, smart, info, serial, family, model, interface) != 0) { - 1766 : /* LCOV_EXCL_START */ - 1767 : pclose(f); - 1768 : log_tag("device:%s:%s:shell\n", file, name); - 1769 : return -1; - 1770 : /* LCOV_EXCL_STOP */ - 1771 : } - 1772 : - 1773 0 : ret = pclose(f); - 1774 : - 1775 0 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); - 1776 : - 1777 0 : if (!WIFEXITED(ret)) { - 1778 : /* LCOV_EXCL_START */ - 1779 : log_tag("device:%s:%s:abort\n", file, name); - 1780 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); - 1781 : return -1; - 1782 : /* LCOV_EXCL_STOP */ - 1783 : } - 1784 0 : if (WEXITSTATUS(ret) == 127) { - 1785 : /* LCOV_EXCL_START */ - 1786 : log_tag("device:%s:%s:shell\n", file, name); - 1787 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); - 1788 : return -1; - 1789 : /* LCOV_EXCL_STOP */ - 1790 : } - 1791 : - 1792 0 : if (WEXITSTATUS(ret) == 3) { - 1793 0 : log_tag("attr:%s:%s:power:standby\n", file, name); - 1794 0 : *power = POWER_STANDBY; - 1795 : } else { - 1796 0 : log_tag("attr:%s:%s:power:active\n", file, name); - 1797 0 : *power = POWER_ACTIVE; - 1798 : - 1799 : /* store the smartctl return value */ - 1800 0 : if (smart) - 1801 0 : smart[SMART_FLAGS].raw = WEXITSTATUS(ret); - 1802 : } - 1803 : - 1804 0 : return 0; - 1805 : } - 1806 : #endif - 1807 : - 1808 : /** - 1809 : * Spin down a specific device. - 1810 : */ - 1811 : #if HAVE_LINUX_DEVICE - 1812 5 : static int devdown(dev_t device, const char* name, const char* smartctl) - 1813 : { - 1814 : char cmd[PATH_MAX + 64]; - 1815 : char file[PATH_MAX]; - 1816 : FILE* f; - 1817 : int ret; - 1818 : const char* x; - 1819 : - 1820 5 : x = find_smartctl(); - 1821 5 : if (!x) { - 1822 : /* LCOV_EXCL_START */ - 1823 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); - 1824 : return -1; - 1825 : /* LCOV_EXCL_STOP */ - 1826 : } - 1827 : - 1828 5 : if (devresolve(device, file, sizeof(file)) != 0) { - 1829 : /* LCOV_EXCL_START */ - 1830 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1831 : return -1; - 1832 : /* LCOV_EXCL_STOP */ - 1833 : } - 1834 : - 1835 : /* if there is a custom smartctl command */ - 1836 5 : if (smartctl[0]) { - 1837 : char option[PATH_MAX]; - 1838 5 : snprintf(option, sizeof(option), smartctl, file); - 1839 5 : snprintf(cmd, sizeof(cmd), "%s -s standby,now %s", x, option); - 1840 : } else { - 1841 0 : snprintf(cmd, sizeof(cmd), "%s -s standby,now %s", x, file); - 1842 : } - 1843 : - 1844 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 1845 : - 1846 5 : f = popen(cmd, "r"); - 1847 5 : if (!f) { - 1848 : /* LCOV_EXCL_START */ - 1849 : log_tag("device:%s:%s:shell\n", file, name); - 1850 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); - 1851 : return -1; - 1852 : /* LCOV_EXCL_STOP */ - 1853 : } - 1854 : - 1855 5 : if (smartctl_flush(f, file, name) != 0) { - 1856 : /* LCOV_EXCL_START */ - 1857 : pclose(f); - 1858 : log_tag("device:%s:%s:shell\n", file, name); - 1859 : return -1; - 1860 : /* LCOV_EXCL_STOP */ - 1861 : } - 1862 : - 1863 5 : ret = pclose(f); - 1864 : - 1865 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); - 1866 : - 1867 5 : if (!WIFEXITED(ret)) { - 1868 : /* LCOV_EXCL_START */ - 1869 : log_tag("device:%s:%s:abort\n", file, name); - 1870 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); - 1871 : return -1; - 1872 : /* LCOV_EXCL_STOP */ - 1873 : } - 1874 5 : if (WEXITSTATUS(ret) == 127) { - 1875 : /* LCOV_EXCL_START */ - 1876 : log_tag("device:%s:%s:shell\n", file, name); - 1877 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); - 1878 : return -1; - 1879 : /* LCOV_EXCL_STOP */ - 1880 : } - 1881 5 : if (WEXITSTATUS(ret) != 0) { - 1882 : /* LCOV_EXCL_START */ - 1883 : log_tag("device:%s:%s:exit:%d\n", file, name, WEXITSTATUS(ret)); - 1884 : log_fatal(EEXTERNAL, "Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); - 1885 : return -1; - 1886 : /* LCOV_EXCL_STOP */ - 1887 : } + 1647 14 : if (info[INFO_SIZE] == SMART_UNASSIGNED) { + 1648 12 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/size", major(device), minor(device)); + 1649 12 : if (sysattr(path, buf, sizeof(buf)) == 0) { + 1650 : char* e; + 1651 : uint64_t v; + 1652 12 : v = strtoul(buf, &e, 10); + 1653 12 : if (*e == 0) + 1654 12 : info[INFO_SIZE] = v * 512; + 1655 : } + 1656 : } + 1657 : + 1658 14 : if (info[INFO_ROTATION_RATE] == SMART_UNASSIGNED) { + 1659 12 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/queue/rotational", major(device), minor(device)); + 1660 12 : if (sysattr(path, buf, sizeof(buf)) == 0) { + 1661 : char* e; + 1662 : uint64_t v; + 1663 12 : v = strtoul(buf, &e, 10); + 1664 12 : if (*e == 0) + 1665 12 : info[INFO_ROTATION_RATE] = v; + 1666 : } + 1667 : } + 1668 : + 1669 14 : if (*model == 0) { + 1670 12 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/model", major(device), minor(device)); + 1671 12 : if (sysattr(path, buf, sizeof(buf)) == 0) { + 1672 12 : if (buf[0] != 0) + 1673 12 : pathcpy(model, SMART_MAX, buf); + 1674 : } + 1675 : } + 1676 : + 1677 14 : if (*serial == 0) { + 1678 14 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/serial", major(device), minor(device)); + 1679 14 : if (sysattr(path, buf, sizeof(buf)) == 0) { + 1680 0 : if (buf[0] != 0) + 1681 0 : pathcpy(serial, SMART_MAX, buf); + 1682 : } + 1683 : } + 1684 : + 1685 14 : if (*serial == 0) { + 1686 : // --- Page 0x80: Unit Serial Number --- + 1687 14 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device/vpd_pg80", major(device), minor(device)); + 1688 14 : ret = sysread(path, buf, sizeof(buf)); + 1689 14 : if (ret > 4) { + 1690 14 : unsigned len = (unsigned char)buf[3]; + 1691 14 : if (4 + len <= (size_t)ret && 4 + len + 1 <= sizeof(buf)) { + 1692 14 : char* attr = buf + 4; + 1693 14 : attr[len] = 0; + 1694 14 : strtrim(attr); + 1695 14 : if (*attr) + 1696 14 : pathcpy(serial, SMART_MAX, attr); + 1697 : } + 1698 : } + 1699 : } + 1700 : + 1701 : /* always override interface if it's usb */ + 1702 14 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u", major(device), minor(device)); + 1703 14 : ret = readlink(path, buf, sizeof(buf)); + 1704 14 : if (ret > 0 && (unsigned)ret < sizeof(buf)) { + 1705 14 : buf[ret] = 0; + 1706 14 : if (strstr(buf, "usb") != 0) + 1707 0 : strcpy(interface, "USB"); + 1708 : } + 1709 14 : } + 1710 : #endif + 1711 : + 1712 : /** + 1713 : * Get POWER state. + 1714 : */ + 1715 : #if HAVE_LINUX_DEVICE + 1716 14 : static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, struct smart_attr* smart, uint64_t* info, char* serial, char* family, char* model, char* interface) + 1717 : { + 1718 : char cmd[PATH_MAX + 64]; + 1719 : char file[PATH_MAX]; + 1720 : FILE* f; + 1721 : int ret; + 1722 : const char* x; + 1723 : + 1724 14 : x = find_smartctl(); + 1725 14 : if (!x) { + 1726 : /* LCOV_EXCL_START */ + 1727 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); + 1728 : return -1; + 1729 : /* LCOV_EXCL_STOP */ + 1730 : } + 1731 : + 1732 14 : if (devresolve(device, file, sizeof(file)) != 0) { + 1733 : /* LCOV_EXCL_START */ + 1734 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1735 : return -1; + 1736 : /* LCOV_EXCL_STOP */ + 1737 : } + 1738 : + 1739 : /* if there is a custom smartctl command */ + 1740 14 : if (smartctl[0]) { + 1741 : char option[PATH_MAX]; + 1742 0 : snprintf(option, sizeof(option), smartctl, file); + 1743 0 : snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, option); + 1744 : } else { + 1745 14 : snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, file); + 1746 : } + 1747 : + 1748 14 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + 1749 : + 1750 14 : f = popen(cmd, "r"); + 1751 14 : if (!f) { + 1752 : /* LCOV_EXCL_START */ + 1753 : log_tag("device:%s:%s:shell\n", file, name); + 1754 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); + 1755 : return -1; + 1756 : /* LCOV_EXCL_STOP */ + 1757 : } + 1758 : + 1759 14 : if (smartctl_attribute(f, file, name, smart, info, serial, family, model, interface) != 0) { + 1760 : /* LCOV_EXCL_START */ + 1761 : pclose(f); + 1762 : log_tag("device:%s:%s:shell\n", file, name); + 1763 : return -1; + 1764 : /* LCOV_EXCL_STOP */ + 1765 : } + 1766 : + 1767 14 : ret = pclose(f); + 1768 : + 1769 14 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1770 : + 1771 14 : if (!WIFEXITED(ret)) { + 1772 : /* LCOV_EXCL_START */ + 1773 : log_tag("device:%s:%s:abort\n", file, name); + 1774 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); + 1775 : return -1; + 1776 : /* LCOV_EXCL_STOP */ + 1777 : } + 1778 14 : if (WEXITSTATUS(ret) == 127) { + 1779 : /* LCOV_EXCL_START */ + 1780 : log_tag("device:%s:%s:shell\n", file, name); + 1781 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); + 1782 : return -1; + 1783 : /* LCOV_EXCL_STOP */ + 1784 : } + 1785 : + 1786 14 : if (WEXITSTATUS(ret) == 3) { + 1787 12 : log_tag("attr:%s:%s:power:standby\n", file, name); + 1788 12 : *power = POWER_STANDBY; + 1789 : } else { + 1790 2 : log_tag("attr:%s:%s:power:active\n", file, name); + 1791 2 : *power = POWER_ACTIVE; + 1792 : + 1793 : /* store the smartctl return value */ + 1794 2 : if (smart) + 1795 2 : smart[SMART_FLAGS].raw = WEXITSTATUS(ret); + 1796 : } + 1797 : + 1798 14 : return 0; + 1799 : } + 1800 : #endif + 1801 : + 1802 : /** + 1803 : * Spin down a specific device. + 1804 : */ + 1805 : #if HAVE_LINUX_DEVICE + 1806 5 : static int devdown(dev_t device, const char* name, const char* smartctl) + 1807 : { + 1808 : char cmd[PATH_MAX + 64]; + 1809 : char file[PATH_MAX]; + 1810 : FILE* f; + 1811 : int ret; + 1812 : const char* x; + 1813 : + 1814 5 : x = find_smartctl(); + 1815 5 : if (!x) { + 1816 : /* LCOV_EXCL_START */ + 1817 : log_fatal(EEXTERNAL, "Cannot find smartctl.\n"); + 1818 : return -1; + 1819 : /* LCOV_EXCL_STOP */ + 1820 : } + 1821 : + 1822 5 : if (devresolve(device, file, sizeof(file)) != 0) { + 1823 : /* LCOV_EXCL_START */ + 1824 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1825 : return -1; + 1826 : /* LCOV_EXCL_STOP */ + 1827 : } + 1828 : + 1829 : /* if there is a custom smartctl command */ + 1830 5 : if (smartctl[0]) { + 1831 : char option[PATH_MAX]; + 1832 5 : snprintf(option, sizeof(option), smartctl, file); + 1833 5 : snprintf(cmd, sizeof(cmd), "%s -s standby,now %s", x, option); + 1834 : } else { + 1835 0 : snprintf(cmd, sizeof(cmd), "%s -s standby,now %s", x, file); + 1836 : } + 1837 : + 1838 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + 1839 : + 1840 5 : f = popen(cmd, "r"); + 1841 5 : if (!f) { + 1842 : /* LCOV_EXCL_START */ + 1843 : log_tag("device:%s:%s:shell\n", file, name); + 1844 : log_fatal(EEXTERNAL, "Failed to run '%s' (from popen).\n", cmd); + 1845 : return -1; + 1846 : /* LCOV_EXCL_STOP */ + 1847 : } + 1848 : + 1849 5 : if (smartctl_flush(f, file, name) != 0) { + 1850 : /* LCOV_EXCL_START */ + 1851 : pclose(f); + 1852 : log_tag("device:%s:%s:shell\n", file, name); + 1853 : return -1; + 1854 : /* LCOV_EXCL_STOP */ + 1855 : } + 1856 : + 1857 5 : ret = pclose(f); + 1858 : + 1859 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1860 : + 1861 5 : if (!WIFEXITED(ret)) { + 1862 : /* LCOV_EXCL_START */ + 1863 : log_tag("device:%s:%s:abort\n", file, name); + 1864 : log_fatal(EEXTERNAL, "Failed to run '%s' (not exited).\n", cmd); + 1865 : return -1; + 1866 : /* LCOV_EXCL_STOP */ + 1867 : } + 1868 5 : if (WEXITSTATUS(ret) == 127) { + 1869 : /* LCOV_EXCL_START */ + 1870 : log_tag("device:%s:%s:shell\n", file, name); + 1871 : log_fatal(EEXTERNAL, "Failed to run '%s' (from sh).\n", cmd); + 1872 : return -1; + 1873 : /* LCOV_EXCL_STOP */ + 1874 : } + 1875 5 : if (WEXITSTATUS(ret) != 0) { + 1876 : /* LCOV_EXCL_START */ + 1877 : log_tag("device:%s:%s:exit:%d\n", file, name, WEXITSTATUS(ret)); + 1878 : log_fatal(EEXTERNAL, "Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); + 1879 : return -1; + 1880 : /* LCOV_EXCL_STOP */ + 1881 : } + 1882 : + 1883 0 : log_tag("attr:%s:%s:power:down\n", file, name); + 1884 : + 1885 0 : return 0; + 1886 : } + 1887 : #endif 1888 : - 1889 0 : log_tag("attr:%s:%s:power:down\n", file, name); - 1890 : - 1891 0 : return 0; - 1892 : } - 1893 : #endif - 1894 : - 1895 : /** - 1896 : * Spin down a specific device if it's up. - 1897 : */ - 1898 : #if HAVE_LINUX_DEVICE - 1899 0 : static int devdownifup(dev_t device, const char* name, const char* smartctl, int* power) - 1900 : { - 1901 0 : *power = POWER_UNKNOWN; + 1889 : /** + 1890 : * Spin down a specific device if it's up. + 1891 : */ + 1892 : #if HAVE_LINUX_DEVICE + 1893 0 : static int devdownifup(dev_t device, const char* name, const char* smartctl, int* power) + 1894 : { + 1895 0 : *power = POWER_UNKNOWN; + 1896 : + 1897 0 : if (devprobe(device, name, smartctl, power, 0, 0, 0, 0, 0, 0) != 0) + 1898 0 : return -1; + 1899 : + 1900 0 : if (*power == POWER_ACTIVE) + 1901 0 : return devdown(device, name, smartctl); 1902 : - 1903 0 : if (devprobe(device, name, smartctl, power, 0, 0, 0, 0, 0, 0) != 0) - 1904 0 : return -1; - 1905 : - 1906 0 : if (*power == POWER_ACTIVE) - 1907 0 : return devdown(device, name, smartctl); - 1908 : - 1909 0 : return 0; - 1910 : } - 1911 : #endif - 1912 : - 1913 : /** - 1914 : * Spin up a specific device. - 1915 : */ - 1916 : #if HAVE_LINUX_DEVICE - 1917 30 : static int devup(dev_t device, const char* name) - 1918 : { - 1919 : char file[PATH_MAX]; - 1920 : int ret; - 1921 : int f; - 1922 : void* buf; - 1923 : uint64_t size; - 1924 : uint64_t offset; - 1925 : - 1926 30 : if (devresolve(device, file, sizeof(file)) != 0) { - 1927 : /* LCOV_EXCL_START */ - 1928 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1929 : return -1; - 1930 : /* LCOV_EXCL_STOP */ - 1931 : } - 1932 : - 1933 : /* O_DIRECT requires memory aligned to the block size */ - 1934 30 : if (posix_memalign(&buf, 4096, 4096) != 0) { - 1935 : /* LCOV_EXCL_START */ - 1936 : log_fatal(errno, "Failed to allocate aligned memory for device '%u:%u'.\n", major(device), minor(device)); - 1937 : return -1; - 1938 : /* LCOV_EXCL_STOP */ - 1939 : } - 1940 : - 1941 30 : f = open(file, O_RDONLY | O_DIRECT); - 1942 30 : if (f < 0) { - 1943 : /* LCOV_EXCL_START */ - 1944 : free(buf); - 1945 : log_tag("device:%s:%s:error:%d\n", file, name, errno); - 1946 : log_fatal(errno, "Failed to open device '%u:%u'.\n", major(device), minor(device)); - 1947 : return -1; - 1948 : /* LCOV_EXCL_STOP */ - 1949 : } - 1950 : - 1951 0 : if (ioctl(f, BLKGETSIZE64, &size) < 0) { - 1952 : /* LCOV_EXCL_START */ - 1953 : close(f); - 1954 : free(buf); - 1955 : log_tag("device:%s:%s:error:%d\n", file, name, errno); - 1956 : log_fatal(errno, "Failed to get device size '%u:%u'.\n", major(device), minor(device)); - 1957 : return -1; - 1958 : /* LCOV_EXCL_STOP */ - 1959 : } - 1960 : - 1961 : /* select a random offset */ - 1962 0 : offset = (random_u64() % (size / 4096)) * 4096; - 1963 : - 1964 : #if HAVE_POSIX_FADVISE - 1965 : /* clear cache */ - 1966 0 : ret = posix_fadvise(f, offset, 4096, POSIX_FADV_DONTNEED); - 1967 0 : if (ret != 0) { - 1968 : /* LCOV_EXCL_START */ - 1969 : close(f); - 1970 : free(buf); - 1971 : log_tag("device:%s:%s:error:%d\n", file, name, errno); - 1972 : log_fatal(errno, "Failed to advise device '%u:%u'.\n", major(device), minor(device)); - 1973 : return -1; - 1974 : /* LCOV_EXCL_STOP */ - 1975 : } - 1976 : #endif - 1977 : - 1978 0 : ret = pread(f, buf, 4096, offset); - 1979 0 : if (ret < 0) { - 1980 : /* LCOV_EXCL_START */ - 1981 : close(f); - 1982 : free(buf); - 1983 : log_tag("device:%s:%s:error:%d\n", file, name, errno); - 1984 : log_fatal(errno, "Failed to read device '%u:%u'.\n", major(device), minor(device)); - 1985 : return -1; - 1986 : /* LCOV_EXCL_STOP */ - 1987 : } - 1988 : - 1989 0 : ret = close(f); - 1990 0 : if (ret < 0) { - 1991 : /* LCOV_EXCL_START */ - 1992 : free(buf); - 1993 : log_tag("device:%s:%s:error:%d\n", file, name, errno); - 1994 : log_fatal(errno, "Failed to close device '%u:%u'.\n", major(device), minor(device)); - 1995 : return -1; - 1996 : /* LCOV_EXCL_STOP */ - 1997 : } - 1998 : - 1999 0 : log_tag("attr:%s:%s:power:up\n", file, name); - 2000 : - 2001 0 : free(buf); - 2002 0 : return 0; - 2003 : } - 2004 : #endif - 2005 : - 2006 : /** - 2007 : * Thread for spinning up. - 2008 : * - 2009 : * Note that filling up the devinfo object is done inside this thread, - 2010 : * to avoid to block the main thread if the device need to be spin up - 2011 : * to handle stat/resolve requests. - 2012 : */ - 2013 30 : static void* thread_spinup(void* arg) - 2014 : { - 2015 : #if HAVE_LINUX_DEVICE - 2016 30 : devinfo_t* devinfo = arg; - 2017 : uint64_t start; - 2018 : - 2019 30 : start = tick_ms(); + 1903 0 : return 0; + 1904 : } + 1905 : #endif + 1906 : + 1907 : /** + 1908 : * Spin up a specific device. + 1909 : */ + 1910 : #if HAVE_LINUX_DEVICE + 1911 30 : static int devup(dev_t device, const char* name) + 1912 : { + 1913 : char file[PATH_MAX]; + 1914 : int ret; + 1915 : int f; + 1916 : void* buf; + 1917 : uint64_t size; + 1918 : uint64_t offset; + 1919 : + 1920 30 : if (devresolve(device, file, sizeof(file)) != 0) { + 1921 : /* LCOV_EXCL_START */ + 1922 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1923 : return -1; + 1924 : /* LCOV_EXCL_STOP */ + 1925 : } + 1926 : + 1927 : /* O_DIRECT requires memory aligned to the block size */ + 1928 30 : if (posix_memalign(&buf, 4096, 4096) != 0) { + 1929 : /* LCOV_EXCL_START */ + 1930 : log_fatal(errno, "Failed to allocate aligned memory for device '%u:%u'.\n", major(device), minor(device)); + 1931 : return -1; + 1932 : /* LCOV_EXCL_STOP */ + 1933 : } + 1934 : + 1935 30 : f = open(file, O_RDONLY | O_DIRECT); + 1936 30 : if (f < 0) { + 1937 : /* LCOV_EXCL_START */ + 1938 : free(buf); + 1939 : log_tag("device:%s:%s:error:%d\n", file, name, errno); + 1940 : log_fatal(errno, "Failed to open device '%u:%u'.\n", major(device), minor(device)); + 1941 : return -1; + 1942 : /* LCOV_EXCL_STOP */ + 1943 : } + 1944 : + 1945 0 : if (ioctl(f, BLKGETSIZE64, &size) < 0) { + 1946 : /* LCOV_EXCL_START */ + 1947 : close(f); + 1948 : free(buf); + 1949 : log_tag("device:%s:%s:error:%d\n", file, name, errno); + 1950 : log_fatal(errno, "Failed to get device size '%u:%u'.\n", major(device), minor(device)); + 1951 : return -1; + 1952 : /* LCOV_EXCL_STOP */ + 1953 : } + 1954 : + 1955 : /* select a random offset */ + 1956 0 : offset = (random_u64() % (size / 4096)) * 4096; + 1957 : + 1958 : #if HAVE_POSIX_FADVISE + 1959 : /* clear cache */ + 1960 0 : ret = posix_fadvise(f, offset, 4096, POSIX_FADV_DONTNEED); + 1961 0 : if (ret != 0) { + 1962 : /* LCOV_EXCL_START */ + 1963 : close(f); + 1964 : free(buf); + 1965 : log_tag("device:%s:%s:error:%d\n", file, name, errno); + 1966 : log_fatal(errno, "Failed to advise device '%u:%u'.\n", major(device), minor(device)); + 1967 : return -1; + 1968 : /* LCOV_EXCL_STOP */ + 1969 : } + 1970 : #endif + 1971 : + 1972 0 : ret = pread(f, buf, 4096, offset); + 1973 0 : if (ret < 0) { + 1974 : /* LCOV_EXCL_START */ + 1975 : close(f); + 1976 : free(buf); + 1977 : log_tag("device:%s:%s:error:%d\n", file, name, errno); + 1978 : log_fatal(errno, "Failed to read device '%u:%u'.\n", major(device), minor(device)); + 1979 : return -1; + 1980 : /* LCOV_EXCL_STOP */ + 1981 : } + 1982 : + 1983 0 : ret = close(f); + 1984 0 : if (ret < 0) { + 1985 : /* LCOV_EXCL_START */ + 1986 : free(buf); + 1987 : log_tag("device:%s:%s:error:%d\n", file, name, errno); + 1988 : log_fatal(errno, "Failed to close device '%u:%u'.\n", major(device), minor(device)); + 1989 : return -1; + 1990 : /* LCOV_EXCL_STOP */ + 1991 : } + 1992 : + 1993 0 : log_tag("attr:%s:%s:power:up\n", file, name); + 1994 : + 1995 0 : free(buf); + 1996 0 : return 0; + 1997 : } + 1998 : #endif + 1999 : + 2000 : /** + 2001 : * Thread for spinning up. + 2002 : * + 2003 : * Note that filling up the devinfo object is done inside this thread, + 2004 : * to avoid to block the main thread if the device need to be spin up + 2005 : * to handle stat/resolve requests. + 2006 : */ + 2007 30 : static void* thread_spinup(void* arg) + 2008 : { + 2009 : #if HAVE_LINUX_DEVICE + 2010 30 : devinfo_t* devinfo = arg; + 2011 : uint64_t start; + 2012 : + 2013 30 : start = tick_ms(); + 2014 : + 2015 30 : if (devup(devinfo->device, devinfo->name) != 0) { + 2016 : /* LCOV_EXCL_START */ + 2017 : return (void*)-1; + 2018 : /* LCOV_EXCL_STOP */ + 2019 : } 2020 : - 2021 30 : if (devup(devinfo->device, devinfo->name) != 0) { - 2022 : /* LCOV_EXCL_START */ - 2023 : return (void*)-1; - 2024 : /* LCOV_EXCL_STOP */ - 2025 : } - 2026 : - 2027 0 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); - 2028 : - 2029 : /* after the spin up, get SMART info */ - 2030 0 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { - 2031 : /* LCOV_EXCL_START */ - 2032 : return (void*)-1; - 2033 : /* LCOV_EXCL_STOP */ - 2034 : } - 2035 : - 2036 : /* - 2037 : * Retrieve some attributes directly from the system. - 2038 : * - 2039 : * smartctl intentionally skips queries on devices in standby mode - 2040 : * to prevent accidentally spinning them up. - 2041 : */ - 2042 0 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); - 2043 : - 2044 0 : return 0; - 2045 : #else - 2046 : (void)arg; - 2047 : return (void*)-1; - 2048 : #endif - 2049 : } - 2050 : - 2051 : /** - 2052 : * Thread for spinning down. - 2053 : */ - 2054 5 : static void* thread_spindown(void* arg) - 2055 : { - 2056 : #if HAVE_LINUX_DEVICE - 2057 5 : devinfo_t* devinfo = arg; - 2058 : uint64_t start; - 2059 : - 2060 5 : start = tick_ms(); + 2021 0 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 2022 : + 2023 : /* after the spin up, get SMART info */ + 2024 0 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { + 2025 : /* LCOV_EXCL_START */ + 2026 : return (void*)-1; + 2027 : /* LCOV_EXCL_STOP */ + 2028 : } + 2029 : + 2030 : /* + 2031 : * Retrieve some attributes directly from the system. + 2032 : * + 2033 : * smartctl intentionally skips queries on devices in standby mode + 2034 : * to prevent accidentally spinning them up. + 2035 : */ + 2036 0 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); + 2037 : + 2038 0 : return 0; + 2039 : #else + 2040 : (void)arg; + 2041 : return (void*)-1; + 2042 : #endif + 2043 : } + 2044 : + 2045 : /** + 2046 : * Thread for spinning down. + 2047 : */ + 2048 5 : static void* thread_spindown(void* arg) + 2049 : { + 2050 : #if HAVE_LINUX_DEVICE + 2051 5 : devinfo_t* devinfo = arg; + 2052 : uint64_t start; + 2053 : + 2054 5 : start = tick_ms(); + 2055 : + 2056 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { + 2057 : /* LCOV_EXCL_START */ + 2058 : return (void*)-1; + 2059 : /* LCOV_EXCL_STOP */ + 2060 : } 2061 : - 2062 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { - 2063 : /* LCOV_EXCL_START */ - 2064 : return (void*)-1; - 2065 : /* LCOV_EXCL_STOP */ - 2066 : } - 2067 : - 2068 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); - 2069 : - 2070 0 : return 0; - 2071 : #else - 2072 : (void)arg; - 2073 : return (void*)-1; - 2074 : #endif - 2075 : } - 2076 : - 2077 : /** - 2078 : * Thread for spinning down. - 2079 : */ - 2080 0 : static void* thread_spindownifup(void* arg) - 2081 : { - 2082 : #if HAVE_LINUX_DEVICE - 2083 0 : devinfo_t* devinfo = arg; - 2084 : uint64_t start; - 2085 : int power; - 2086 : - 2087 0 : start = tick_ms(); + 2062 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 2063 : + 2064 0 : return 0; + 2065 : #else + 2066 : (void)arg; + 2067 : return (void*)-1; + 2068 : #endif + 2069 : } + 2070 : + 2071 : /** + 2072 : * Thread for spinning down. + 2073 : */ + 2074 0 : static void* thread_spindownifup(void* arg) + 2075 : { + 2076 : #if HAVE_LINUX_DEVICE + 2077 0 : devinfo_t* devinfo = arg; + 2078 : uint64_t start; + 2079 : int power; + 2080 : + 2081 0 : start = tick_ms(); + 2082 : + 2083 0 : if (devdownifup(devinfo->device, devinfo->name, devinfo->smartctl, &power) != 0) { + 2084 : /* LCOV_EXCL_START */ + 2085 : return (void*)-1; + 2086 : /* LCOV_EXCL_STOP */ + 2087 : } 2088 : - 2089 0 : if (devdownifup(devinfo->device, devinfo->name, devinfo->smartctl, &power) != 0) { - 2090 : /* LCOV_EXCL_START */ - 2091 : return (void*)-1; - 2092 : /* LCOV_EXCL_STOP */ - 2093 : } - 2094 : - 2095 0 : if (power == POWER_ACTIVE) - 2096 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); - 2097 : - 2098 0 : return 0; - 2099 : #else - 2100 : (void)arg; - 2101 : return (void*)-1; - 2102 : #endif - 2103 : } - 2104 : - 2105 : /** - 2106 : * Thread for getting smart info. - 2107 : */ - 2108 0 : static void* thread_smart(void* arg) - 2109 : { - 2110 : #if HAVE_LINUX_DEVICE - 2111 0 : devinfo_t* devinfo = arg; + 2089 0 : if (power == POWER_ACTIVE) + 2090 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 2091 : + 2092 0 : return 0; + 2093 : #else + 2094 : (void)arg; + 2095 : return (void*)-1; + 2096 : #endif + 2097 : } + 2098 : + 2099 : /** + 2100 : * Thread for getting smart info. + 2101 : */ + 2102 0 : static void* thread_smart(void* arg) + 2103 : { + 2104 : #if HAVE_LINUX_DEVICE + 2105 0 : devinfo_t* devinfo = arg; + 2106 : + 2107 0 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { + 2108 : /* LCOV_EXCL_START */ + 2109 : return (void*)-1; + 2110 : /* LCOV_EXCL_STOP */ + 2111 : } 2112 : - 2113 0 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { - 2114 : /* LCOV_EXCL_START */ - 2115 : return (void*)-1; - 2116 : /* LCOV_EXCL_STOP */ - 2117 : } - 2118 : - 2119 : /* - 2120 : * Retrieve some attributes directly from the system. - 2121 : * - 2122 : * smartctl intentionally skips queries on devices in standby mode - 2123 : * to prevent accidentally spinning them up. - 2124 : */ - 2125 0 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); - 2126 : - 2127 0 : return 0; - 2128 : #else - 2129 : (void)arg; - 2130 : return (void*)-1; - 2131 : #endif - 2132 : } - 2133 : - 2134 : /** - 2135 : * Thread for getting power info. - 2136 : */ - 2137 0 : static void* thread_probe(void* arg) - 2138 : { - 2139 : #if HAVE_LINUX_DEVICE - 2140 0 : devinfo_t* devinfo = arg; + 2113 : /* + 2114 : * Retrieve some attributes directly from the system. + 2115 : * + 2116 : * smartctl intentionally skips queries on devices in standby mode + 2117 : * to prevent accidentally spinning them up. + 2118 : */ + 2119 0 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); + 2120 : + 2121 0 : return 0; + 2122 : #else + 2123 : (void)arg; + 2124 : return (void*)-1; + 2125 : #endif + 2126 : } + 2127 : + 2128 : /** + 2129 : * Thread for getting power info. + 2130 : */ + 2131 14 : static void* thread_probe(void* arg) + 2132 : { + 2133 : #if HAVE_LINUX_DEVICE + 2134 14 : devinfo_t* devinfo = arg; + 2135 : + 2136 14 : if (devprobe(devinfo->device, devinfo->name, devinfo->smartctl, &devinfo->power, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { + 2137 : /* LCOV_EXCL_START */ + 2138 : return (void*)-1; + 2139 : /* LCOV_EXCL_STOP */ + 2140 : } 2141 : - 2142 0 : if (devprobe(devinfo->device, devinfo->name, devinfo->smartctl, &devinfo->power, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf) != 0) { - 2143 : /* LCOV_EXCL_START */ - 2144 : return (void*)-1; - 2145 : /* LCOV_EXCL_STOP */ - 2146 : } - 2147 : - 2148 : /* - 2149 : * Retrieve some attributes directly from the system. - 2150 : * - 2151 : * smartctl intentionally skips queries on devices in standby mode - 2152 : * to prevent accidentally spinning them up. - 2153 : */ - 2154 0 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); - 2155 : - 2156 0 : return 0; - 2157 : #else - 2158 : (void)arg; - 2159 : return (void*)-1; - 2160 : #endif - 2161 : } - 2162 : - 2163 2 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) - 2164 : { - 2165 2 : int fail = 0; - 2166 : tommy_node* i; - 2167 : - 2168 : #if HAVE_THREAD - 2169 : /* start all threads */ - 2170 37 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 2171 35 : devinfo_t* devinfo = i->data; - 2172 : - 2173 35 : thread_create(&devinfo->thread, func, devinfo); - 2174 : } - 2175 : - 2176 : /* join all threads */ - 2177 37 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 2178 35 : devinfo_t* devinfo = i->data; - 2179 : void* retval; - 2180 : - 2181 35 : thread_join(devinfo->thread, &retval); - 2182 : - 2183 35 : if (retval != 0) - 2184 35 : ++fail; - 2185 : } - 2186 : #else - 2187 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 2188 : devinfo_t* devinfo = i->data; - 2189 : - 2190 : if (func(devinfo) != 0) - 2191 : ++fail; + 2142 : /* + 2143 : * Retrieve some attributes directly from the system. + 2144 : * + 2145 : * smartctl intentionally skips queries on devices in standby mode + 2146 : * to prevent accidentally spinning them up. + 2147 : */ + 2148 14 : devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model, devinfo->interf); + 2149 : + 2150 14 : return 0; + 2151 : #else + 2152 : (void)arg; + 2153 : return (void*)-1; + 2154 : #endif + 2155 : } + 2156 : + 2157 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) + 2158 : { + 2159 3 : int fail = 0; + 2160 : tommy_node* i; + 2161 : + 2162 : #if HAVE_THREAD + 2163 : /* start all threads */ + 2164 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 2165 49 : devinfo_t* devinfo = i->data; + 2166 : + 2167 49 : thread_create(&devinfo->thread, func, devinfo); + 2168 : } + 2169 : + 2170 : /* join all threads */ + 2171 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 2172 49 : devinfo_t* devinfo = i->data; + 2173 : void* retval; + 2174 : + 2175 49 : thread_join(devinfo->thread, &retval); + 2176 : + 2177 49 : if (retval != 0) + 2178 35 : ++fail; + 2179 : } + 2180 : #else + 2181 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 2182 : devinfo_t* devinfo = i->data; + 2183 : + 2184 : if (func(devinfo) != 0) + 2185 : ++fail; + 2186 : } + 2187 : #endif + 2188 3 : if (fail != 0) { + 2189 : /* LCOV_EXCL_START */ + 2190 : return -1; + 2191 : /* LCOV_EXCL_STOP */ 2192 : } - 2193 : #endif - 2194 2 : if (fail != 0) { - 2195 : /* LCOV_EXCL_START */ - 2196 : return -1; - 2197 : /* LCOV_EXCL_STOP */ - 2198 : } - 2199 : - 2200 0 : return 0; - 2201 : } - 2202 : - 2203 3 : int devquery(tommy_list* high, tommy_list* low, int operation, int others) - 2204 : { - 2205 3 : void* (*func)(void* arg) = 0; - 2206 : - 2207 : #if HAVE_LINUX_DEVICE - 2208 : tommy_node* i; - 2209 : struct stat st; - 2210 : - 2211 : /* sysfs interface is required */ - 2212 3 : if (stat("/sys/dev/block", &st) != 0) { - 2213 : /* LCOV_EXCL_START */ - 2214 : log_fatal(EEXTERNAL, "Missing interface /sys/dev/block.\n"); - 2215 : return -1; - 2216 : /* LCOV_EXCL_STOP */ - 2217 : } + 2193 : + 2194 1 : return 0; + 2195 : } + 2196 : + 2197 4 : int devquery(tommy_list* high, tommy_list* low, int operation, int others) + 2198 : { + 2199 4 : void* (*func)(void* arg) = 0; + 2200 : + 2201 : #if HAVE_LINUX_DEVICE + 2202 : tommy_node* i; + 2203 : struct stat st; + 2204 : + 2205 : /* sysfs interface is required */ + 2206 4 : if (stat("/sys/dev/block", &st) != 0) { + 2207 : /* LCOV_EXCL_START */ + 2208 : log_fatal(EEXTERNAL, "Missing interface /sys/dev/block.\n"); + 2209 : return -1; + 2210 : /* LCOV_EXCL_STOP */ + 2211 : } + 2212 : + 2213 : /* for each device */ + 2214 81 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 2215 77 : devinfo_t* devinfo = i->data; + 2216 77 : uint64_t device = devinfo->device; + 2217 : uint64_t access_stat; 2218 : - 2219 : /* for each device */ - 2220 68 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 2221 65 : devinfo_t* devinfo = i->data; - 2222 65 : uint64_t device = devinfo->device; - 2223 : uint64_t access_stat; - 2224 : - 2225 : #if HAVE_SYNCFS - 2226 65 : if (operation == DEVICE_DOWN) { - 2227 : /* flush the high level filesystem before spinning down */ - 2228 5 : int f = open(devinfo->mount, O_RDONLY); - 2229 5 : if (f >= 0) { - 2230 5 : syncfs(f); - 2231 5 : close(f); - 2232 : } - 2233 : } - 2234 : #endif - 2235 : - 2236 : /* if the major is the null device, find the real one */ - 2237 65 : if (major(device) == 0) { - 2238 : /* obtain the real device */ - 2239 0 : if (devdereference(device, &device) != 0) { - 2240 : /* LCOV_EXCL_START */ - 2241 : log_fatal(EEXTERNAL, "Failed to dereference device '%u:%u'.\n", major(device), minor(device)); - 2242 : return -1; - 2243 : /* LCOV_EXCL_STOP */ - 2244 : } - 2245 : } - 2246 : - 2247 : /* retrieve access stat for the high level device */ - 2248 65 : if (devstat(device, &access_stat) == 0) { - 2249 : /* cumulate access stat in the first split */ - 2250 65 : if (devinfo->split) - 2251 39 : devinfo->split->access_stat += access_stat; - 2252 : else - 2253 26 : devinfo->access_stat += access_stat; - 2254 : } - 2255 : - 2256 : /* get the device file */ - 2257 65 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { - 2258 : /* LCOV_EXCL_START */ - 2259 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 2260 : return -1; - 2261 : /* LCOV_EXCL_STOP */ - 2262 : } - 2263 : - 2264 : /* expand the tree of devices */ - 2265 65 : if (devtree(devinfo, device, low) != 0) { - 2266 : /* LCOV_EXCL_START */ - 2267 : log_fatal(EEXTERNAL, "Failed to expand device '%u:%u'.\n", major(device), minor(device)); - 2268 : return -1; - 2269 : /* LCOV_EXCL_STOP */ - 2270 : } - 2271 : } - 2272 : - 2273 : /* add other devices */ - 2274 3 : if (others) { - 2275 0 : if (devscan(low) != 0) { - 2276 : /* LCOV_EXCL_START */ - 2277 : log_fatal(EEXTERNAL, "Failed to list other devices.\n"); - 2278 : return -1; - 2279 : /* LCOV_EXCL_STOP */ - 2280 : } - 2281 : } - 2282 : #else - 2283 : (void)high; - 2284 : (void)others; - 2285 : #endif - 2286 : - 2287 3 : switch (operation) { - 2288 1 : case DEVICE_UP : func = thread_spinup; break; - 2289 1 : case DEVICE_DOWN : func = thread_spindown; break; - 2290 0 : case DEVICE_SMART : func = thread_smart; break; - 2291 0 : case DEVICE_PROBE : func = thread_probe; break; - 2292 0 : case DEVICE_DOWNIFUP : func = thread_spindownifup; break; - 2293 : } + 2219 : #if HAVE_SYNCFS + 2220 77 : if (operation == DEVICE_DOWN) { + 2221 : /* flush the high level filesystem before spinning down */ + 2222 5 : int f = open(devinfo->mount, O_RDONLY); + 2223 5 : if (f >= 0) { + 2224 5 : syncfs(f); + 2225 5 : close(f); + 2226 : } + 2227 : } + 2228 : #endif + 2229 : + 2230 : /* if the major is the null device, find the real one */ + 2231 77 : if (major(device) == 0) { + 2232 : /* obtain the real device */ + 2233 0 : if (devdereference(device, &device) != 0) { + 2234 : /* LCOV_EXCL_START */ + 2235 : log_fatal(EEXTERNAL, "Failed to dereference device '%u:%u'.\n", major(device), minor(device)); + 2236 : return -1; + 2237 : /* LCOV_EXCL_STOP */ + 2238 : } + 2239 : } + 2240 : + 2241 : /* retrieve access stat for the high level device */ + 2242 77 : if (devstat(device, &access_stat) == 0) { + 2243 : /* cumulate access stat in the first split */ + 2244 77 : if (devinfo->split) + 2245 39 : devinfo->split->access_stat += access_stat; + 2246 : else + 2247 38 : devinfo->access_stat += access_stat; + 2248 : } + 2249 : + 2250 : /* get the device file */ + 2251 77 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { + 2252 : /* LCOV_EXCL_START */ + 2253 : log_fatal(EEXTERNAL, "Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 2254 : return -1; + 2255 : /* LCOV_EXCL_STOP */ + 2256 : } + 2257 : + 2258 : /* expand the tree of devices */ + 2259 77 : if (devtree(devinfo, device, low) != 0) { + 2260 : /* LCOV_EXCL_START */ + 2261 : log_fatal(EEXTERNAL, "Failed to expand device '%u:%u'.\n", major(device), minor(device)); + 2262 : return -1; + 2263 : /* LCOV_EXCL_STOP */ + 2264 : } + 2265 : } + 2266 : + 2267 : /* add other devices */ + 2268 4 : if (others) { + 2269 1 : if (devscan(low) != 0) { + 2270 : /* LCOV_EXCL_START */ + 2271 : log_fatal(EEXTERNAL, "Failed to list other devices.\n"); + 2272 : return -1; + 2273 : /* LCOV_EXCL_STOP */ + 2274 : } + 2275 : } + 2276 : #else + 2277 : (void)high; + 2278 : (void)others; + 2279 : #endif + 2280 : + 2281 4 : switch (operation) { + 2282 1 : case DEVICE_UP : func = thread_spinup; break; + 2283 1 : case DEVICE_DOWN : func = thread_spindown; break; + 2284 0 : case DEVICE_SMART : func = thread_smart; break; + 2285 1 : case DEVICE_PROBE : func = thread_probe; break; + 2286 0 : case DEVICE_DOWNIFUP : func = thread_spindownifup; break; + 2287 : } + 2288 : + 2289 4 : if (!func) + 2290 1 : return 0; + 2291 : + 2292 3 : return device_thread(low, func); + 2293 : } 2294 : - 2295 3 : if (!func) - 2296 1 : return 0; - 2297 : - 2298 2 : return device_thread(low, func); - 2299 : } - 2300 : - 2301 283 : void os_init(int opt) - 2302 : { - 2303 : #if HAVE_BLKID - 2304 : int ret; - 2305 283 : ret = blkid_get_cache(&cache, NULL); - 2306 283 : if (ret != 0) { - 2307 : /* LCOV_EXCL_START */ - 2308 : log_fatal(EEXTERNAL, "WARNING Failed to get blkid cache\n"); - 2309 : /* LCOV_EXCL_STOP */ - 2310 : } - 2311 : #endif - 2312 : - 2313 : (void)opt; - 2314 283 : } - 2315 : - 2316 272 : void os_done(void) - 2317 : { - 2318 : #if HAVE_BLKID - 2319 272 : if (cache != 0) - 2320 272 : blkid_put_cache(cache); - 2321 : #endif - 2322 272 : } - 2323 : - 2324 : /* LCOV_EXCL_START */ - 2325 : void os_abort(void) - 2326 : { - 2327 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS - 2328 : void* stack[32]; - 2329 : char** messages; - 2330 : size_t size; - 2331 : unsigned i; - 2332 : #endif - 2333 : - 2334 : printf("Stacktrace of " PACKAGE " v" VERSION); - 2335 : #ifdef _linux - 2336 : printf(", linux"); - 2337 : #endif - 2338 : #ifdef __GNUC__ - 2339 : printf(", gcc " __VERSION__); - 2340 : #endif - 2341 : printf(", %d-bit", (int)sizeof(void*) * 8); - 2342 : printf(", PATH_MAX=%d", PATH_MAX); - 2343 : printf("\n"); - 2344 : - 2345 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS - 2346 : size = backtrace(stack, 32); - 2347 : - 2348 : messages = backtrace_symbols(stack, size); - 2349 : - 2350 : for (i = 1; i < size; ++i) { - 2351 : const char* msg; - 2352 : - 2353 : if (messages) - 2354 : msg = messages[i]; - 2355 : else - 2356 : msg = "<unknown>"; - 2357 : - 2358 : printf("[bt] %02u: %s\n", i, msg); - 2359 : - 2360 : if (messages) { - 2361 : int ret; - 2362 : char addr2line[1024]; - 2363 : size_t j = 0; - 2364 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) - 2365 : ++j; - 2366 : - 2367 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); - 2368 : - 2369 : ret = system(addr2line); - 2370 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) - 2371 : printf("exit:%d\n", WEXITSTATUS(ret)); - 2372 : if (WIFSIGNALED(ret)) - 2373 : printf("signal:%d\n", WTERMSIG(ret)); - 2374 : } - 2375 : } - 2376 : #endif - 2377 : - 2378 : printf("Please report this error to the SnapRAID Forum:\n"); - 2379 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); - 2380 : - 2381 : abort(); - 2382 : } - 2383 : /* LCOV_EXCL_STOP */ - 2384 : - 2385 1 : void os_clear(void) - 2386 : { - 2387 : /* ANSI codes */ - 2388 1 : printf("\033[H"); /* cursor at topleft */ - 2389 1 : printf("\033[2J"); /* clear screen */ - 2390 1 : } + 2295 284 : void os_init(int opt) + 2296 : { + 2297 : #if HAVE_BLKID + 2298 : int ret; + 2299 284 : ret = blkid_get_cache(&cache, NULL); + 2300 284 : if (ret != 0) { + 2301 : /* LCOV_EXCL_START */ + 2302 : log_fatal(EEXTERNAL, "WARNING Failed to get blkid cache\n"); + 2303 : /* LCOV_EXCL_STOP */ + 2304 : } + 2305 : #endif + 2306 : + 2307 : (void)opt; + 2308 284 : } + 2309 : + 2310 273 : void os_done(void) + 2311 : { + 2312 : #if HAVE_BLKID + 2313 273 : if (cache != 0) + 2314 273 : blkid_put_cache(cache); + 2315 : #endif + 2316 273 : } + 2317 : + 2318 : /* LCOV_EXCL_START */ + 2319 : void os_abort(void) + 2320 : { + 2321 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 2322 : void* stack[32]; + 2323 : char** messages; + 2324 : size_t size; + 2325 : unsigned i; + 2326 : #endif + 2327 : + 2328 : printf("Stacktrace of " PACKAGE " v" VERSION); + 2329 : #ifdef _linux + 2330 : printf(", linux"); + 2331 : #endif + 2332 : #ifdef __GNUC__ + 2333 : printf(", gcc " __VERSION__); + 2334 : #endif + 2335 : printf(", %d-bit", (int)sizeof(void*) * 8); + 2336 : printf(", PATH_MAX=%d", PATH_MAX); + 2337 : printf("\n"); + 2338 : + 2339 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 2340 : size = backtrace(stack, 32); + 2341 : + 2342 : messages = backtrace_symbols(stack, size); + 2343 : + 2344 : for (i = 1; i < size; ++i) { + 2345 : const char* msg; + 2346 : + 2347 : if (messages) + 2348 : msg = messages[i]; + 2349 : else + 2350 : msg = "<unknown>"; + 2351 : + 2352 : printf("[bt] %02u: %s\n", i, msg); + 2353 : + 2354 : if (messages) { + 2355 : int ret; + 2356 : char addr2line[1024]; + 2357 : size_t j = 0; + 2358 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) + 2359 : ++j; + 2360 : + 2361 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); + 2362 : + 2363 : ret = system(addr2line); + 2364 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) + 2365 : printf("exit:%d\n", WEXITSTATUS(ret)); + 2366 : if (WIFSIGNALED(ret)) + 2367 : printf("signal:%d\n", WTERMSIG(ret)); + 2368 : } + 2369 : } + 2370 : #endif + 2371 : + 2372 : printf("Please report this error to the SnapRAID Forum:\n"); + 2373 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); + 2374 : + 2375 : abort(); + 2376 : } + 2377 : /* LCOV_EXCL_STOP */ + 2378 : + 2379 1 : void os_clear(void) + 2380 : { + 2381 : /* ANSI codes */ + 2382 1 : printf("\033[H"); /* cursor at topleft */ + 2383 1 : printf("\033[2J"); /* clear screen */ + 2384 1 : } + 2385 : + 2386 7 : size_t direct_size(void) + 2387 : { + 2388 : long size; + 2389 : + 2390 7 : size = sysconf(_SC_PAGESIZE); 2391 : - 2392 7 : size_t direct_size(void) - 2393 : { - 2394 : long size; - 2395 : - 2396 7 : size = sysconf(_SC_PAGESIZE); - 2397 : - 2398 7 : if (size == -1) { - 2399 : /* LCOV_EXCL_START */ - 2400 : log_fatal(EEXTERNAL, "No page size\n"); - 2401 : exit(EXIT_FAILURE); - 2402 : /* LCOV_EXCL_STOP */ - 2403 : } - 2404 : - 2405 7 : return size; - 2406 : } - 2407 : - 2408 : #if HAVE_LINUX_DEVICE - 2409 : - 2410 : /* List of possible ambient temperature labels */ - 2411 : const char* AMBIENT_LABEL[] = { - 2412 : "systin", - 2413 : "auxtin", - 2414 : "mb", - 2415 : "m/b", - 2416 : "board", - 2417 : "motherboard", - 2418 : "system", - 2419 : "chassis", - 2420 : "case", - 2421 : "room", - 2422 : "ambient", - 2423 : 0 - 2424 : }; + 2392 7 : if (size == -1) { + 2393 : /* LCOV_EXCL_START */ + 2394 : log_fatal(EEXTERNAL, "No page size\n"); + 2395 : exit(EXIT_FAILURE); + 2396 : /* LCOV_EXCL_STOP */ + 2397 : } + 2398 : + 2399 7 : return size; + 2400 : } + 2401 : + 2402 : #if HAVE_LINUX_DEVICE + 2403 : + 2404 : /* List of possible ambient temperature labels */ + 2405 : const char* AMBIENT_LABEL[] = { + 2406 : "systin", + 2407 : "auxtin", + 2408 : "mb", + 2409 : "m/b", + 2410 : "board", + 2411 : "motherboard", + 2412 : "system", + 2413 : "chassis", + 2414 : "case", + 2415 : "room", + 2416 : "ambient", + 2417 : 0 + 2418 : }; + 2419 : + 2420 1 : int ambient_temperature(void) + 2421 : { + 2422 : DIR* dir; + 2423 : struct dirent* entry; + 2424 1 : int lowest_temp = 0; 2425 : - 2426 1 : int ambient_temperature(void) - 2427 : { - 2428 : DIR* dir; - 2429 : struct dirent* entry; - 2430 1 : int lowest_temp = 0; - 2431 : - 2432 1 : dir = opendir("/sys/class/hwmon"); - 2433 1 : if (!dir) - 2434 0 : return 0; + 2426 1 : dir = opendir("/sys/class/hwmon"); + 2427 1 : if (!dir) + 2428 0 : return 0; + 2429 : + 2430 : /* iterate through hwmon devices */ + 2431 5 : while ((entry = readdir(dir)) != NULL) { + 2432 : char path[PATH_MAX]; + 2433 : DIR* hwmon_dir; + 2434 : struct dirent* hwmon_entry; 2435 : - 2436 : /* iterate through hwmon devices */ - 2437 5 : while ((entry = readdir(dir)) != NULL) { - 2438 : char path[PATH_MAX]; - 2439 : DIR* hwmon_dir; - 2440 : struct dirent* hwmon_entry; - 2441 : - 2442 4 : if (strncmp(entry->d_name, "hwmon", 5) != 0) - 2443 2 : continue; - 2444 : - 2445 2 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s", entry->d_name); - 2446 : - 2447 : /* iterate through temp*_input files */ - 2448 2 : hwmon_dir = opendir(path); - 2449 2 : if (!hwmon_dir) - 2450 0 : continue; - 2451 : - 2452 66 : while ((hwmon_entry = readdir(hwmon_dir)) != NULL) { - 2453 : char value[128]; - 2454 : char name[128]; - 2455 : char label[128]; - 2456 : char* dash; - 2457 : char* e; - 2458 : int temp; - 2459 : - 2460 64 : if (strncmp(hwmon_entry->d_name, "temp", 4) != 0) - 2461 63 : continue; - 2462 : - 2463 18 : dash = strrchr(hwmon_entry->d_name, '_'); - 2464 18 : if (dash == 0) - 2465 0 : continue; + 2436 4 : if (strncmp(entry->d_name, "hwmon", 5) != 0) + 2437 2 : continue; + 2438 : + 2439 2 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s", entry->d_name); + 2440 : + 2441 : /* iterate through temp*_input files */ + 2442 2 : hwmon_dir = opendir(path); + 2443 2 : if (!hwmon_dir) + 2444 0 : continue; + 2445 : + 2446 66 : while ((hwmon_entry = readdir(hwmon_dir)) != NULL) { + 2447 : char value[128]; + 2448 : char name[128]; + 2449 : char label[128]; + 2450 : char* dash; + 2451 : char* e; + 2452 : int temp; + 2453 : + 2454 64 : if (strncmp(hwmon_entry->d_name, "temp", 4) != 0) + 2455 63 : continue; + 2456 : + 2457 18 : dash = strrchr(hwmon_entry->d_name, '_'); + 2458 18 : if (dash == 0) + 2459 0 : continue; + 2460 : + 2461 18 : if (strcmp(dash, "_input") != 0) + 2462 14 : continue; + 2463 : + 2464 : /* read the temperature */ + 2465 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/%s", entry->d_name, hwmon_entry->d_name); 2466 : - 2467 18 : if (strcmp(dash, "_input") != 0) - 2468 14 : continue; + 2467 4 : if (sysattr(path, value, sizeof(value)) != 0) + 2468 0 : continue; 2469 : - 2470 : /* read the temperature */ - 2471 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/%s", entry->d_name, hwmon_entry->d_name); - 2472 : - 2473 4 : if (!sysattr(path, value, sizeof(value))) - 2474 0 : continue; - 2475 : - 2476 4 : temp = strtol(value, &e, 10) / 1000; - 2477 4 : if (*e != 0 && !isspace(*e)) - 2478 0 : continue; - 2479 : - 2480 : /* cut the file name at "_input" */ - 2481 4 : *dash = 0; - 2482 : - 2483 : /* read the corresponding name */ - 2484 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/name", entry->d_name); - 2485 4 : if (!sysattr(path, name, sizeof(name))) { - 2486 : /* fallback to using the hwmon entry */ - 2487 0 : pathcpy(name, sizeof(name), entry->d_name); - 2488 : } - 2489 : - 2490 : /* read the corresponding label file */ - 2491 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/%s_label", entry->d_name, hwmon_entry->d_name); - 2492 4 : if (!sysattr(path, label, sizeof(label))) { - 2493 : /* fallback to using the temp* name (e.g., temp1, temp2) */ - 2494 0 : pathcpy(label, sizeof(label), hwmon_entry->d_name); - 2495 : } + 2470 4 : temp = strtol(value, &e, 10) / 1000; + 2471 4 : if (*e != 0 && !isspace(*e)) + 2472 0 : continue; + 2473 : + 2474 : /* cut the file name at "_input" */ + 2475 4 : *dash = 0; + 2476 : + 2477 : /* read the corresponding name */ + 2478 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/name", entry->d_name); + 2479 4 : if (sysattr(path, name, sizeof(name)) != 0) { + 2480 : /* fallback to using the hwmon name */ + 2481 0 : pathcpy(name, sizeof(name), entry->d_name); + 2482 : } + 2483 : + 2484 : /* read the corresponding label file */ + 2485 4 : pathprint(path, sizeof(path), "/sys/class/hwmon/%s/%s_label", entry->d_name, hwmon_entry->d_name); + 2486 4 : if (sysattr(path, label, sizeof(label)) != 0) { + 2487 : /* fallback to using the temp* name (e.g., temp1, temp2) */ + 2488 0 : pathcpy(label, sizeof(label), hwmon_entry->d_name); + 2489 : } + 2490 : + 2491 4 : log_tag("thermal:ambient:device:%s:%s:%s:%s:%d\n", entry->d_name, name, hwmon_entry->d_name, label, temp); + 2492 : + 2493 : /* check if temperature is in reasonable range */ + 2494 4 : if (temp < 15 || temp > 40) + 2495 3 : continue; 2496 : - 2497 4 : log_tag("thermal:ambient:device:%s:%s:%s:%s:%d\n", entry->d_name, name, hwmon_entry->d_name, label, temp); - 2498 : - 2499 : /* check if temperature is in reasonable range */ - 2500 4 : if (temp < 15 || temp > 40) - 2501 3 : continue; - 2502 : - 2503 : /* lower case */ - 2504 1 : strlwr(label); - 2505 : - 2506 : /* check if label matches possible ambient labels */ - 2507 3 : for (int i = 0; AMBIENT_LABEL[i]; ++i) { - 2508 3 : if (worddigitstr(label, AMBIENT_LABEL[i]) != 0) { - 2509 1 : log_tag("thermal:ambient:candidate:%d\n", temp); - 2510 1 : if (lowest_temp == 0 || lowest_temp > temp) - 2511 1 : lowest_temp = temp; - 2512 1 : break; - 2513 : } - 2514 : } - 2515 : - 2516 : /* accept also generic "temp1" */ - 2517 1 : if (strcmp(label, "temp1") == 0) { - 2518 0 : log_tag("thermal:ambient:candidate:%d\n", temp); - 2519 0 : if (lowest_temp == 0 || lowest_temp > temp) - 2520 0 : lowest_temp = temp; - 2521 : } - 2522 : } - 2523 : - 2524 2 : closedir(hwmon_dir); - 2525 : } - 2526 : - 2527 1 : closedir(dir); - 2528 : - 2529 1 : return lowest_temp; - 2530 : } - 2531 : #else - 2532 : int ambient_temperature(void) - 2533 : { - 2534 : return 0; - 2535 : } - 2536 : #endif - 2537 : - 2538 : #endif - 2539 : + 2497 : /* lower case */ + 2498 1 : strlwr(label); + 2499 : + 2500 : /* check if label matches possible ambient labels */ + 2501 3 : for (int i = 0; AMBIENT_LABEL[i]; ++i) { + 2502 3 : if (worddigitstr(label, AMBIENT_LABEL[i]) != 0) { + 2503 1 : log_tag("thermal:ambient:candidate:%d\n", temp); + 2504 1 : if (lowest_temp == 0 || lowest_temp > temp) + 2505 1 : lowest_temp = temp; + 2506 1 : break; + 2507 : } + 2508 : } + 2509 : + 2510 : /* accept also generic "temp1" */ + 2511 1 : if (strcmp(label, "temp1") == 0) { + 2512 0 : log_tag("thermal:ambient:candidate:%d\n", temp); + 2513 0 : if (lowest_temp == 0 || lowest_temp > temp) + 2514 0 : lowest_temp = temp; + 2515 : } + 2516 : } + 2517 : + 2518 2 : closedir(hwmon_dir); + 2519 : } + 2520 : + 2521 1 : closedir(dir); + 2522 : + 2523 1 : return lowest_temp; + 2524 : } + 2525 : #else + 2526 : int ambient_temperature(void) + 2527 : { + 2528 : return 0; + 2529 : } + 2530 : #endif + 2531 : + 2532 : #endif + 2533 : diff --git a/cov/cmdline/util.c.func-sort-c.html b/cov/cmdline/util.c.func-sort-c.html index 2a205c44..1baa4e6c 100644 --- a/cov/cmdline/util.c.func-sort-c.html +++ b/cov/cmdline/util.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 30 @@ -103,37 +103,37 @@ lock_unlock 264 + + crc32c_gen + 265 + lock_lock 273 membesthash - 279 + 280 crc32c_init - 299 - - - crc32c_gen - 313 + 300 muldiv - 1033 + 1008 fast_mtest_vector - 2026 + 2019 malloc_nofail_test - 2026 + 2019 mtest_vector - 2026 + 2019 malloc_nofail_vector_align @@ -141,47 +141,47 @@ memdiff - 35593 + 35908 crc32c_x86 - 647248 + 647112 util_mum - 2100378 + 2231474 util_rotr64 - 3416264 + 4202896 memhash - 5919094 + 5918991 util_write64 - 7777674 + 7777502 util_write32 - 8121028 + 8120960 util_read32 - 8121160 + 8121092 util_read64 - 15388870 + 16437322 util_rotl64 - 510513033 + 511275929 util_rotl32 - 833601439 + 833614949
diff --git a/cov/cmdline/util.c.func.html b/cov/cmdline/util.c.func.html index e3488894..25f696bf 100644 --- a/cov/cmdline/util.c.func.html +++ b/cov/cmdline/util.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 30 @@ -61,19 +61,19 @@ crc32c_gen - 313 + 265 crc32c_init - 299 + 300 crc32c_x86 - 647248 + 647112 fast_mtest_vector - 2026 + 2019 hash_config_name @@ -97,7 +97,7 @@ malloc_nofail_test - 2026 + 2019 malloc_nofail_vector_align @@ -109,15 +109,15 @@ membesthash - 279 + 280 memdiff - 35593 + 35908 memhash - 5919094 + 5918991 memhashname @@ -125,11 +125,11 @@ mtest_vector - 2026 + 2019 muldiv - 1033 + 1008 muldiv_upper @@ -137,7 +137,7 @@ util_mum - 2100378 + 2231474 util_read16 @@ -145,11 +145,11 @@ util_read32 - 8121160 + 8121092 util_read64 - 15388870 + 16437322 util_read8 @@ -157,11 +157,11 @@ util_rotl32 - 833601439 + 833614949 util_rotl64 - 510513033 + 511275929 util_rotr32 @@ -169,7 +169,7 @@ util_rotr64 - 3416264 + 4202896 util_selftest @@ -177,11 +177,11 @@ util_write32 - 8121028 + 8120960 util_write64 - 7777674 + 7777502
diff --git a/cov/cmdline/util.c.gcov.html b/cov/cmdline/util.c.gcov.html index b934c9cd..798493ed 100644 --- a/cov/cmdline/util.c.gcov.html +++ b/cov/cmdline/util.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 30 @@ -151,15 +151,15 @@ 89 0 : return ptr; 90 : } 91 : - 92 2026 : void* malloc_nofail_test(size_t size) + 92 2019 : void* malloc_nofail_test(size_t size) 93 : { 94 : void* ptr; 95 : - 96 2026 : ptr = malloc_nofail(size); + 96 2019 : ptr = malloc_nofail(size); 97 : - 98 2026 : mtest_vector(1, size, &ptr); + 98 2019 : mtest_vector(1, size, &ptr); 99 : - 100 2026 : return ptr; + 100 2019 : return ptr; 101 : } 102 : 103 : /** @@ -168,40 +168,40 @@ 106 : * It's similar at raid_mtest_vector() but faster because 107 : * we have a lot of buffers to verify. 108 : */ - 109 2026 : static int fast_mtest_vector(int n, size_t size, void** vv) + 109 2019 : static int fast_mtest_vector(int n, size_t size, void** vv) 110 : { 111 : int i, j; 112 : 113 : /* test with all the bits */ - 114 18234 : for (i = 0; i < 8; ++i) { - 115 16208 : unsigned char value = 1 << i; + 114 18171 : for (i = 0; i < 8; ++i) { + 115 16152 : unsigned char value = 1 << i; 116 : 117 : /* fill first */ - 118 16208 : memset(vv[0], value, size); + 118 16152 : memset(vv[0], value, size); 119 : 120 : /* copy to the next */ - 121 16208 : for (j = 1; j < n; ++j) + 121 16152 : for (j = 1; j < n; ++j) 122 0 : memcpy(vv[j], vv[j - 1], size); 123 : 124 : /* compare with the previous */ - 125 32416 : for (j = 1; j <= n; ++j) - 126 16208 : if (memcmp(vv[j % n], vv[j - 1], size) != 0) + 125 32304 : for (j = 1; j <= n; ++j) + 126 16152 : if (memcmp(vv[j % n], vv[j - 1], size) != 0) 127 0 : return -1; 128 : } 129 : - 130 2026 : return 0; + 130 2019 : return 0; 131 : } 132 : - 133 2026 : void mtest_vector(int n, size_t size, void** vv) + 133 2019 : void mtest_vector(int n, size_t size, void** vv) 134 : { - 135 2026 : if (fast_mtest_vector(n, size, vv) != 0) { + 135 2019 : if (fast_mtest_vector(n, size, vv) != 0) { 136 : /* LCOV_EXCL_START */ 137 : log_fatal(EINTERNAL, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); 138 : log_fatal(EINTERNAL, "Try running a memory test like http://www.memtest86.com/\n"); 139 : exit(EXIT_FAILURE); 140 : /* LCOV_EXCL_STOP */ 141 : } - 142 2026 : } + 142 2019 : } 143 : 144 : /****************************************************************************/ 145 : /* crc */ @@ -478,42 +478,42 @@ 416 : int crc_x86; 417 : #endif 418 : - 419 313 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size) + 419 265 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size) 420 : { - 421 313 : crc ^= CRC_IV; + 421 265 : crc ^= CRC_IV; 422 : - 423 313 : crc = crc32c_gen_plain(crc, ptr, size); + 423 265 : crc = crc32c_gen_plain(crc, ptr, size); 424 : - 425 313 : crc ^= CRC_IV; + 425 265 : crc ^= CRC_IV; 426 : - 427 313 : return crc; + 427 265 : return crc; 428 : } 429 : 430 : #if HAVE_SSE42 - 431 647248 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) + 431 647112 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) 432 : { - 433 647248 : crc ^= CRC_IV; + 433 647112 : crc ^= CRC_IV; 434 : - 435 647248 : crc = crc32c_x86_plain(crc, ptr, size); + 435 647112 : crc = crc32c_x86_plain(crc, ptr, size); 436 : - 437 647248 : crc ^= CRC_IV; + 437 647112 : crc ^= CRC_IV; 438 : - 439 647248 : return crc; + 439 647112 : return crc; 440 : } 441 : #endif 442 : 443 : uint32_t (*crc32c)(uint32_t crc, const unsigned char* ptr, unsigned size); 444 : - 445 299 : void crc32c_init(void) + 445 300 : void crc32c_init(void) 446 : { - 447 299 : crc32c = crc32c_gen; + 447 300 : crc32c = crc32c_gen; 448 : #if HAVE_SSE42 - 449 299 : if (raid_cpu_has_crc32()) { - 450 297 : crc_x86 = 1; - 451 297 : crc32c = crc32c_x86; + 449 300 : if (raid_cpu_has_crc32()) { + 450 298 : crc_x86 = 1; + 451 298 : crc32c = crc32c_x86; 452 : } 453 : #endif - 454 299 : } + 454 300 : } 455 : 456 : /****************************************************************************/ 457 : /* byte operations */ @@ -522,14 +522,14 @@ 460 : * Rotate left. 461 : * In x86/x64 they are optimized with a single assembler instruction. 462 : */ - 463 833601439 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) + 463 833614949 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) 464 : { - 465 833601439 : return (x << r) | (x >> (32 - r)); + 465 833614949 : return (x << r) | (x >> (32 - r)); 466 : } 467 : - 468 510513033 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) + 468 511275929 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) 469 : { - 470 510513033 : return (x << r) | (x >> (64 - r)); + 470 511275929 : return (x << r) | (x >> (64 - r)); 471 : } 472 : 473 : /* @@ -541,9 +541,9 @@ 479 4 : return (x >> r) | (x << (32 - r)); 480 : } 481 : - 482 3416264 : static inline uint64_t util_rotr64(uint64_t x, int8_t r) + 482 4202896 : static inline uint64_t util_rotr64(uint64_t x, int8_t r) 483 : { - 484 3416264 : return (x >> r) | (x << (64 - r)); + 484 4202896 : return (x >> r) | (x << (64 - r)); 485 : } 486 : 487 : /** @@ -590,41 +590,41 @@ 528 135 : return ptr[0] + (ptr[1] << 8); 529 : } 530 : - 531 8121160 : static inline uint32_t util_read32(const void* ptr) + 531 8121092 : static inline uint32_t util_read32(const void* ptr) 532 : { 533 : uint32_t v; - 534 8121160 : memcpy(&v, ptr, sizeof(v)); + 534 8121092 : memcpy(&v, ptr, sizeof(v)); 535 : #if WORDS_BIGENDIAN 536 : v = util_swap32(v); 537 : #endif - 538 8121160 : return v; + 538 8121092 : return v; 539 : } 540 : - 541 15388870 : static inline uint64_t util_read64(const void* ptr) + 541 16437322 : static inline uint64_t util_read64(const void* ptr) 542 : { 543 : uint64_t v; - 544 15388870 : memcpy(&v, ptr, sizeof(v)); + 544 16437322 : memcpy(&v, ptr, sizeof(v)); 545 : #if WORDS_BIGENDIAN 546 : v = util_swap64(v); 547 : #endif - 548 15388870 : return v; + 548 16437322 : return v; 549 : } 550 : - 551 8121028 : static inline void util_write32(void* ptr, uint32_t v) + 551 8120960 : static inline void util_write32(void* ptr, uint32_t v) 552 : { 553 : #if WORDS_BIGENDIAN 554 : v = util_swap32(v); 555 : #endif - 556 8121028 : memcpy(ptr, &v, sizeof(v)); - 557 8121028 : } + 556 8120960 : memcpy(ptr, &v, sizeof(v)); + 557 8120960 : } 558 : - 559 7777674 : static inline void util_write64(void* ptr, uint64_t v) + 559 7777502 : static inline void util_write64(void* ptr, uint64_t v) 560 : { 561 : #if WORDS_BIGENDIAN 562 : v = util_swap64(v); 563 : #endif - 564 7777674 : memcpy(ptr, &v, sizeof(v)); - 565 7777674 : } + 564 7777502 : memcpy(ptr, &v, sizeof(v)); + 565 7777502 : } 566 : 567 : /* 568 : * 64*64 -> 128bit multiply function. @@ -638,22 +638,22 @@ 576 : * Overwrites B contents with C's high 64 bits. 577 : */ 578 : #if defined(__x86_64__) || defined(_M_X64) - 579 2100378 : static inline void util_mum(uint64_t* A, uint64_t* B) + 579 2231474 : static inline void util_mum(uint64_t* A, uint64_t* B) 580 : { - 581 2100378 : uint64_t a = *A; - 582 2100378 : uint64_t b = *B; + 581 2231474 : uint64_t a = *A; + 582 2231474 : uint64_t b = *B; 583 : uint64_t low, high; 584 : - 585 2100378 : __asm__ ( + 585 2231474 : __asm__ ( 586 : "mulq %3" 587 : : "=a" (low), "=d" (high) 588 : : "a" (a), "rm" (b) 589 : : "cc" 590 : ); 591 : - 592 2100378 : *A = low; - 593 2100378 : *B = high; - 594 2100378 : } + 592 2231474 : *A = low; + 593 2231474 : *B = high; + 594 2231474 : } 595 : #elif defined(__aarch64__) || defined(_M_ARM64) 596 : static inline void util_mum(uint64_t* A, uint64_t* B) 597 : { @@ -775,13 +775,13 @@ 713 0 : return 0; 714 : } 715 : - 716 279 : unsigned membesthash(void) + 716 280 : unsigned membesthash(void) 717 : { 718 : #ifdef CONFIG_X86 719 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) 720 : return HASH_MURMUR3; 721 : else - 722 279 : return HASH_SPOOKY2; + 722 280 : return HASH_SPOOKY2; 723 : #else 724 : if (sizeof(void*) == 4) 725 : return HASH_MURMUR3; @@ -795,21 +795,21 @@ 733 : #include "metro.c" 734 : #include "museair.c" 735 : - 736 5919094 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) + 736 5918991 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) 737 : { - 738 5919094 : switch (kind) { - 739 2030257 : case HASH_MURMUR3 : - 740 2030257 : MurmurHash3_x86_128(src, size, seed, digest); - 741 2030257 : break; - 742 3888115 : case HASH_SPOOKY2 : - 743 3888115 : SpookyHash128(src, size, seed, digest); - 744 3888115 : break; - 745 369 : case HASH_METRO : - 746 369 : MetroHash128(src, size, seed, digest); - 747 369 : break; - 748 353 : case HASH_MUSEAIR : - 749 353 : MuseAirLoong(src, size, seed, digest); - 750 353 : break; + 738 5918991 : switch (kind) { + 739 2030240 : case HASH_MURMUR3 : + 740 2030240 : MurmurHash3_x86_128(src, size, seed, digest); + 741 2030240 : break; + 742 3887997 : case HASH_SPOOKY2 : + 743 3887997 : SpookyHash128(src, size, seed, digest); + 744 3887997 : break; + 745 393 : case HASH_METRO : + 746 393 : MetroHash128(src, size, seed, digest); + 747 393 : break; + 748 361 : case HASH_MUSEAIR : + 749 361 : MuseAirLoong(src, size, seed, digest); + 750 361 : break; 751 0 : default : 752 : /* LCOV_EXCL_START */ 753 : log_fatal(EINTERNAL, "Internal inconsistency in hash function %u\n", kind); @@ -817,7 +817,7 @@ 755 : break; 756 : /* LCOV_EXCL_STOP */ 757 : } - 758 5919094 : } + 758 5918991 : } 759 : 760 45 : const char* hash_config_name(unsigned kind) 761 : { @@ -833,23 +833,23 @@ 771 : } 772 : } 773 : - 774 35593 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) + 774 35908 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) 775 : { 776 : size_t i; 777 : unsigned count; 778 : - 779 35593 : count = 0; - 780 22025081 : for (i = 0; i < size; ++i) { + 779 35908 : count = 0; + 780 22020356 : for (i = 0; i < size; ++i) { 781 : unsigned j; - 782 21989488 : unsigned char diff = data1[i] ^ data2[i]; - 783 197905392 : for (j = 0; j < 8; ++j) { - 784 175915904 : if ((diff & 1) != 0) - 785 76890098 : ++count; - 786 175915904 : diff >>= 1; + 782 21984448 : unsigned char diff = data1[i] ^ data2[i]; + 783 197860032 : for (j = 0; j < 8; ++j) { + 784 175875584 : if ((diff & 1) != 0) + 785 76878222 : ++count; + 786 175875584 : diff >>= 1; 787 : } 788 : } 789 : - 790 35593 : return count; + 790 35908 : return count; 791 : } 792 : 793 : /****************************************************************************/ @@ -900,12 +900,12 @@ 838 : /****************************************************************************/ 839 : /* muldiv */ 840 : - 841 1033 : unsigned muldiv(uint64_t v, uint64_t mul, uint64_t div) + 841 1008 : unsigned muldiv(uint64_t v, uint64_t mul, uint64_t div) 842 : { - 843 1033 : if (!div) + 843 1008 : if (!div) 844 49 : return 0; 845 : - 846 984 : return (uint32_t)(v * mul / div); + 846 959 : return (uint32_t)(v * mul / div); 847 : } 848 : 849 7 : unsigned muldiv_upper(uint64_t v, uint64_t mul, uint64_t div) diff --git a/cov/cmdline/util.h.func-sort-c.html b/cov/cmdline/util.h.func-sort-c.html index 06e403b2..25ad8387 100644 --- a/cov/cmdline/util.h.func-sort-c.html +++ b/cov/cmdline/util.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -65,11 +65,11 @@ crc32c_gen_plain - 313 + 265 bit_vect_set - 1053109 + 1053046 bit_vect_test @@ -77,15 +77,15 @@ crc32c_plain_char - 3968961 + 3933071 crc32c_plain - 21644594 + 21434636 crc32c_x86_plain - 22291842 + 22081748
diff --git a/cov/cmdline/util.h.func.html b/cov/cmdline/util.h.func.html index 00be9f96..8b118f23 100644 --- a/cov/cmdline/util.h.func.html +++ b/cov/cmdline/util.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -61,7 +61,7 @@ bit_vect_set - 1053109 + 1053046 bit_vect_size @@ -73,19 +73,19 @@ crc32c_gen_plain - 313 + 265 crc32c_plain - 21644594 + 21434636 crc32c_plain_char - 3968961 + 3933071 crc32c_x86_plain - 22291842 + 22081748
diff --git a/cov/cmdline/util.h.gcov.html b/cov/cmdline/util.h.gcov.html index a9eac264..fa314463 100644 --- a/cov/cmdline/util.h.gcov.html +++ b/cov/cmdline/util.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -145,12 +145,12 @@ 83 : /** 84 : * Compute CRC-32 (Castagnoli) for a single byte without the IV. 85 : */ - 86 3968961 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) + 86 3933071 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) 87 : { 88 : #if HAVE_SSE42 - 89 3968961 : if (tommy_likely(crc_x86)) { - 90 3968961 : asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); - 91 3968961 : return crc; + 89 3933071 : if (tommy_likely(crc_x86)) { + 90 3933071 : asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); + 91 3933071 : return crc; 92 : } 93 : #endif 94 0 : return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8); @@ -159,38 +159,38 @@ 97 : /** 98 : * Compute the CRC-32 (Castagnoli) without the IV. 99 : */ - 100 313 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 100 265 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 101 : { - 102 19399136 : while (size >= 4) { - 103 19398823 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; - 104 19398823 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24]; - 105 19398823 : ptr += 4; - 106 19398823 : size -= 4; + 102 16253360 : while (size >= 4) { + 103 16253095 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; + 104 16253095 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24]; + 105 16253095 : ptr += 4; + 106 16253095 : size -= 4; 107 : } 108 : - 109 322 : while (size) { + 109 274 : while (size) { 110 9 : crc = CRC32C_0[(crc ^ *ptr) & 0xff] ^ (crc >> 8); 111 9 : ++ptr; 112 9 : --size; 113 : } 114 : - 115 313 : return crc; + 115 265 : return crc; 116 : } 117 : 118 : /** 119 : * Compute the CRC-32 (Castagnoli) without the IV. 120 : */ 121 : #if HAVE_SSE42 - 122 22291842 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 122 22081748 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 123 : { 124 : #ifdef CONFIG_X86_64 - 125 22291842 : uint64_t crc64 = crc; - 126 219134388 : while (size >= 8) { - 127 196842546 : asm ("crc32q %1, %0\n" : "+r" (crc64) : "m" (*(const uint64_t*)ptr)); - 128 196842546 : ptr += 8; - 129 196842546 : size -= 8; + 125 22081748 : uint64_t crc64 = crc; + 126 219202533 : while (size >= 8) { + 127 197120785 : asm ("crc32q %1, %0\n" : "+r" (crc64) : "m" (*(const uint64_t*)ptr)); + 128 197120785 : ptr += 8; + 129 197120785 : size -= 8; 130 : } - 131 22291842 : crc = crc64; + 131 22081748 : crc = crc64; 132 : #else 133 : while (size >= 4) { 134 : asm ("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); @@ -198,24 +198,24 @@ 136 : size -= 4; 137 : } 138 : #endif - 139 69745235 : while (size) { - 140 47453393 : asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); - 141 47453393 : ++ptr; - 142 47453393 : --size; + 139 69279721 : while (size) { + 140 47197973 : asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); + 141 47197973 : ++ptr; + 142 47197973 : --size; 143 : } 144 : - 145 22291842 : return crc; + 145 22081748 : return crc; 146 : } 147 : #endif 148 : 149 : /** 150 : * Compute CRC-32 (Castagnoli) without the IV. 151 : */ - 152 21644594 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 152 21434636 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 153 : { 154 : #if HAVE_SSE42 - 155 21644594 : if (tommy_likely(crc_x86)) { - 156 21644594 : return crc32c_x86_plain(crc, ptr, size); + 155 21434636 : if (tommy_likely(crc_x86)) { + 156 21434636 : return crc32c_x86_plain(crc, ptr, size); 157 : } 158 : #endif 159 0 : return crc32c_gen_plain(crc, ptr, size); @@ -311,11 +311,11 @@ 249 217 : return (max + BIT_VECT_SIZE - 1) / BIT_VECT_SIZE; 250 : } 251 : - 252 1053109 : static inline void bit_vect_set(bit_vect_t* bit_vect, size_t off) + 252 1053046 : static inline void bit_vect_set(bit_vect_t* bit_vect, size_t off) 253 : { - 254 1053109 : bit_vect_t mask = 1 << (off % BIT_VECT_SIZE); - 255 1053109 : bit_vect[off / BIT_VECT_SIZE] |= mask; - 256 1053109 : } + 254 1053046 : bit_vect_t mask = 1 << (off % BIT_VECT_SIZE); + 255 1053046 : bit_vect[off / BIT_VECT_SIZE] |= mask; + 256 1053046 : } 257 : 258 : static inline void bit_vect_clear(bit_vect_t* bit_vect, size_t off) 259 : { diff --git a/cov/index-sort-f.html b/cov/index-sort-f.html index aa67e618..04e7fb6a 100644 --- a/cov/index-sort-f.html +++ b/cov/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 13864 - 15534 - 89.2 % + 14141 + 15494 + 91.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 739 + 747 774 - 95.5 % + 96.5 % @@ -72,12 +72,12 @@ cmdline -
86.4%86.4%
+
89.0%89.0%
- 86.4 % - 10504 / 12155 - 94.2 % - 565 / 600 + 89.0 % + 10781 / 12115 + 95.5 % + 573 / 600 tommyds diff --git a/cov/index-sort-l.html b/cov/index-sort-l.html index 0ca941b4..4c3db9f7 100644 --- a/cov/index-sort-l.html +++ b/cov/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 13864 - 15534 - 89.2 % + 14141 + 15494 + 91.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 739 + 747 774 - 95.5 % + 96.5 % @@ -72,12 +72,12 @@ cmdline -
86.4%86.4%
+
89.0%89.0%
- 86.4 % - 10504 / 12155 - 94.2 % - 565 / 600 + 89.0 % + 10781 / 12115 + 95.5 % + 573 / 600 raid diff --git a/cov/index.html b/cov/index.html index a02b5ed1..dc3a46c9 100644 --- a/cov/index.html +++ b/cov/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 13864 - 15534 - 89.2 % + 14141 + 15494 + 91.3 % Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: - 739 + 747 774 - 95.5 % + 96.5 % @@ -72,12 +72,12 @@ cmdline -
86.4%86.4%
+
89.0%89.0%
- 86.4 % - 10504 / 12155 - 94.2 % - 565 / 600 + 89.0 % + 10781 / 12115 + 95.5 % + 573 / 600 raid diff --git a/cov/raid/check.c.func-sort-c.html b/cov/raid/check.c.func-sort-c.html index 6ac4218b..9e28f8c8 100644 --- a/cov/raid/check.c.func-sort-c.html +++ b/cov/raid/check.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 diff --git a/cov/raid/check.c.func.html b/cov/raid/check.c.func.html index 9e08ecd4..23ea62b0 100644 --- a/cov/raid/check.c.func.html +++ b/cov/raid/check.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 diff --git a/cov/raid/check.c.gcov.html b/cov/raid/check.c.gcov.html index f6a8c6ed..994c0588 100644 --- a/cov/raid/check.c.gcov.html +++ b/cov/raid/check.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 diff --git a/cov/raid/combo.h.func-sort-c.html b/cov/raid/combo.h.func-sort-c.html index 7130295c..4ada51a6 100644 --- a/cov/raid/combo.h.func-sort-c.html +++ b/cov/raid/combo.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/combo.h.func.html b/cov/raid/combo.h.func.html index 251d4d09..55c30efe 100644 --- a/cov/raid/combo.h.func.html +++ b/cov/raid/combo.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/combo.h.gcov.html b/cov/raid/combo.h.gcov.html index c47a489e..1236a46a 100644 --- a/cov/raid/combo.h.gcov.html +++ b/cov/raid/combo.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 @@ -170,11 +170,11 @@ 108 : int i; 109 : 110 : (void)n; /* unused, but kept for clarity */ - 111 207791 : assert(0 < r && r <= n); + 111 207971 : assert(0 < r && r <= n); 112 : - 113 689014 : for (i = 0; i < r; ++i) - 114 481223 : c[i] = i; - 115 207791 : } + 113 689369 : for (i = 0; i < r; ++i) + 114 481398 : c[i] = i; + 115 207971 : } 116 : 117 : /** 118 : * Get the next combination without repetition of r of n elements. @@ -182,19 +182,19 @@ 120 : */ 121 : static __always_inline int combination_next(int r, int n, int *c) 122 : { - 123 52198 : int i = r - 1; /* present position */ - 124 52198 : int h = n; /* high limit for this position */ + 123 52228 : int i = r - 1; /* present position */ + 124 52228 : int h = n; /* high limit for this position */ 125 : - 126 85071 : recurse: + 126 85101 : recurse: 127 : /* next element at position i */ - 128 85071 : ++c[i]; + 128 85101 : ++c[i]; 129 : 130 : /* if the position has reached the max */ - 131 85071 : if (c[i] >= h) { + 131 85101 : if (c[i] >= h) { 132 : 133 : /* if we are at the first level, we have finished */ - 134 45033 : if (i == 0) - 135 12160 : return 0; + 134 45043 : if (i == 0) + 135 12170 : return 0; 136 : 137 : /* increase the previous position */ 138 32873 : --i; @@ -202,16 +202,16 @@ 140 32873 : goto recurse; 141 : } 142 : - 143 40038 : ++i; + 143 40058 : ++i; 144 : 145 : /* initialize all the next positions, if any */ - 146 62583 : while (i < r) { + 146 62603 : 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 40038 : return 1; + 152 40058 : 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 03c4d59e..62628524 100644 --- a/cov/raid/cpu.h.func-sort-c.html +++ b/cov/raid/cpu.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -69,43 +69,43 @@ raid_cpu_has_crc32 - 307 + 308 raid_cpu_has_sse2 - 319 + 320 raid_cpu_has_avx2 - 354 + 355 raid_cpu_match_avx - 354 + 355 raid_cpu_has_slowextendedreg - 569 + 571 raid_cpu_is_atom - 573 + 575 raid_cpu_info - 577 + 579 raid_cpu_has_ssse3 - 615 + 617 raid_cpu_match_sse - 1241 + 1245 raid_cpuid - 2780 + 2789
diff --git a/cov/raid/cpu.h.func.html b/cov/raid/cpu.h.func.html index 65099a9e..2a752f07 100644 --- a/cov/raid/cpu.h.func.html +++ b/cov/raid/cpu.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -61,15 +61,15 @@ raid_cpu_has_avx2 - 354 + 355 raid_cpu_has_crc32 - 307 + 308 raid_cpu_has_slowextendedreg - 569 + 571 raid_cpu_has_slowmult @@ -77,31 +77,31 @@ raid_cpu_has_sse2 - 319 + 320 raid_cpu_has_ssse3 - 615 + 617 raid_cpu_info - 577 + 579 raid_cpu_is_atom - 573 + 575 raid_cpu_match_avx - 354 + 355 raid_cpu_match_sse - 1241 + 1245 raid_cpuid - 2780 + 2789 raid_xgetbv diff --git a/cov/raid/cpu.h.gcov.html b/cov/raid/cpu.h.gcov.html index 5c0d6939..265789c7 100644 --- a/cov/raid/cpu.h.gcov.html +++ b/cov/raid/cpu.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -79,9 +79,9 @@ 17 : 18 : #ifdef CONFIG_X86 19 : - 20 2780 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg) + 20 2789 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg) 21 : { - 22 2780 : asm volatile ( + 22 2789 : asm volatile ( 23 : #if defined(__i386__) && defined(__PIC__) 24 : /* allow compilation in PIC mode saving ebx */ 25 : "xchgl %%ebx, %1\n" @@ -91,11 +91,11 @@ 29 : : "0" (func_eax), "2" (sub_ecx) 30 : #else 31 : "cpuid\n" - 32 2780 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) + 32 2789 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) 33 : : "0" (func_eax), "2" (sub_ecx) 34 : #endif 35 : ); - 36 2780 : } + 36 2789 : } 37 : 38 31 : static inline void raid_xgetbv(uint32_t* reg) 39 : { @@ -112,26 +112,26 @@ 50 : 51 : #define CPU_VENDOR_MAX 13 52 : - 53 577 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model) + 53 579 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model) 54 : { 55 : uint32_t reg[4]; 56 : unsigned f, ef, m, em; 57 : - 58 577 : raid_cpuid(0, 0, reg); + 58 579 : raid_cpuid(0, 0, reg); 59 : - 60 577 : ((uint32_t*)vendor)[0] = reg[1]; - 61 577 : ((uint32_t*)vendor)[1] = reg[3]; - 62 577 : ((uint32_t*)vendor)[2] = reg[2]; - 63 577 : vendor[12] = 0; + 60 579 : ((uint32_t*)vendor)[0] = reg[1]; + 61 579 : ((uint32_t*)vendor)[1] = reg[3]; + 62 579 : ((uint32_t*)vendor)[2] = reg[2]; + 63 579 : vendor[12] = 0; 64 : - 65 577 : raid_cpuid(1, 0, reg); + 65 579 : raid_cpuid(1, 0, reg); 66 : - 67 577 : f = (reg[0] >> 8) & 0xF; - 68 577 : ef = (reg[0] >> 20) & 0xFF; - 69 577 : m = (reg[0] >> 4) & 0xF; - 70 577 : em = (reg[0] >> 16) & 0xF; + 67 579 : f = (reg[0] >> 8) & 0xF; + 68 579 : ef = (reg[0] >> 20) & 0xFF; + 69 579 : m = (reg[0] >> 4) & 0xF; + 70 579 : em = (reg[0] >> 16) & 0xF; 71 : - 72 577 : if (strcmp(vendor, "AuthenticAMD") == 0) { + 72 579 : if (strcmp(vendor, "AuthenticAMD") == 0) { 73 0 : if (f < 15) { 74 0 : *family = f; 75 0 : *model = m; @@ -140,31 +140,31 @@ 78 0 : *model = m + (em << 4); 79 : } 80 : } else { - 81 577 : *family = f + ef; - 82 577 : *model = m + (em << 4); + 81 579 : *family = f + ef; + 82 579 : *model = m + (em << 4); 83 : } - 84 577 : } + 84 579 : } 85 : - 86 1241 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx) + 86 1245 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx) 87 : { 88 : uint32_t reg[4]; 89 : - 90 1241 : raid_cpuid(1, 0, reg); - 91 1241 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + 90 1245 : raid_cpuid(1, 0, reg); + 91 1245 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) 92 18 : return 0; - 93 1223 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx) + 93 1227 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx) 94 0 : return 0; 95 : - 96 1223 : return 1; + 96 1227 : return 1; 97 : } 98 : - 99 354 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0) + 99 355 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0) 100 : { 101 : uint32_t reg[4]; 102 : - 103 354 : raid_cpuid(1, 0, reg); - 104 354 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) - 105 323 : return 0; + 103 355 : raid_cpuid(1, 0, reg); + 104 355 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + 105 324 : return 0; 106 : 107 31 : raid_xgetbv(reg); 108 31 : if ((reg[0] & xcr0) != xcr0) @@ -177,7 +177,7 @@ 115 31 : return 1; 116 : } 117 : - 118 319 : static inline int raid_cpu_has_sse2(void) + 118 320 : static inline int raid_cpu_has_sse2(void) 119 : { 120 : /* 121 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -191,12 +191,12 @@ 129 : * 2. Check that the processor supports the SSE and/or SSE2 extensions (true if 130 : * CPUID.01H:EDX.SSE[bit 25] = 1 and/or CPUID.01H:EDX.SSE2[bit 26] = 1). 131 : */ - 132 319 : return raid_cpu_match_sse( + 132 320 : return raid_cpu_match_sse( 133 : 0, 134 : 1 << 26); /* SSE2 */ 135 : } 136 : - 137 615 : static inline int raid_cpu_has_ssse3(void) + 137 617 : static inline int raid_cpu_has_ssse3(void) 138 : { 139 : /* 140 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -208,12 +208,12 @@ 146 : * Next, use the additional step provided below: 147 : * Check that the processor supports SSSE3 (if CPUID.01H:ECX.SSSE3[bit 9] = 1). 148 : */ - 149 615 : return raid_cpu_match_sse( + 149 617 : return raid_cpu_match_sse( 150 : 1 << 9, /* SSSE3 */ 151 : 1 << 26); /* SSE2 */ 152 : } 153 : - 154 307 : static inline int raid_cpu_has_crc32(void) + 154 308 : static inline int raid_cpu_has_crc32(void) 155 : { 156 : /* 157 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -224,12 +224,12 @@ 162 : * Before an application attempts to use the CRC32 instruction, it must check 163 : * that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1). 164 : */ - 165 307 : return raid_cpu_match_sse( + 165 308 : return raid_cpu_match_sse( 166 : 1 << 20, /* CRC32 */ 167 : 0); 168 : } 169 : - 170 354 : static inline int raid_cpu_has_avx2(void) + 170 355 : static inline int raid_cpu_has_avx2(void) 171 : { 172 : /* 173 : * Intel Architecture Instruction Set Extensions Programming Reference @@ -246,7 +246,7 @@ 184 : * Application Software must identify that hardware supports AVX, after that it must 185 : * also detect support for AVX2 by checking CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]. 186 : */ - 187 354 : return raid_cpu_match_avx( + 187 355 : return raid_cpu_match_avx( 188 : (1 << 27) | (1 << 28), /* OSXSAVE and AVX */ 189 : 1 << 5, /* AVX2 */ 190 : 3 << 1); /* OS saves XMM and YMM registers */ @@ -277,9 +277,9 @@ 215 : /** 216 : * Check if it's an Intel Atom CPU. 217 : */ - 218 573 : static inline int raid_cpu_is_atom(unsigned family, unsigned model) + 218 575 : static inline int raid_cpu_is_atom(unsigned family, unsigned model) 219 : { - 220 573 : if (family != 6) + 220 575 : if (family != 6) 221 3 : return 0; 222 : 223 : /* @@ -300,10 +300,10 @@ 238 : * 4D (77) Atom 8C (22 nm) 4 MB L2 (AVN) 239 : * ?? Atom ?C (14 nm) ? MB L2 (DVN) 240 : */ - 241 570 : return model == 28 || model == 38 || model == 54 - 242 570 : || model == 39 || model == 53 || model == 74 - 243 570 : || model == 90 || model == 55 || model == 76 - 244 1140 : || model == 93 || model == 77; + 241 572 : return model == 28 || model == 38 || model == 54 + 242 572 : || model == 39 || model == 53 || model == 74 + 243 572 : || model == 90 || model == 55 || model == 76 + 244 1144 : || model == 93 || model == 77; 245 : } 246 : 247 : /** @@ -341,7 +341,7 @@ 279 : * Check if the processor has a slow extended set of SSE registers. 280 : * If yes, it's better to limit the unroll to the firsrt 8 registers. 281 : */ - 282 569 : static inline int raid_cpu_has_slowextendedreg(void) + 282 571 : static inline int raid_cpu_has_slowextendedreg(void) 283 : { 284 : char vendor[CPU_VENDOR_MAX]; 285 : unsigned family; @@ -352,9 +352,9 @@ 290 : * is a LITTLE slower than the one using only the first 8 registers. 291 : * This doesn't happen for PARZ. 292 : */ - 293 569 : raid_cpu_info(vendor, &family, &model); + 293 571 : raid_cpu_info(vendor, &family, &model); 294 : - 295 569 : if (strcmp(vendor, "AuthenticAMD") == 0) { + 295 571 : if (strcmp(vendor, "AuthenticAMD") == 0) { 296 : /* 297 : * AMD Bulldozer 298 : * par2_sse2:4922 MB/s, par2_sse2e:4465 MB/s @@ -363,7 +363,7 @@ 301 0 : return 1; 302 : } 303 : - 304 569 : if (strcmp(vendor, "GenuineIntel") == 0) { + 304 571 : if (strcmp(vendor, "GenuineIntel") == 0) { 305 : /* 306 : * Intel Atom (Model 77) 307 : * par2_sse2:5686 MB/s, par2_sse2e:5250 MB/s @@ -381,11 +381,11 @@ 319 : * par5_sse3:910 MB/s, par5_sse3e:675 MB/s 320 : * par6_sse3:720 MB/s, par6_sse3e:534 MB/s 321 : */ - 322 569 : if (raid_cpu_is_atom(family, model)) + 322 571 : if (raid_cpu_is_atom(family, model)) 323 0 : return 1; 324 : } 325 : - 326 569 : return 0; + 326 571 : return 0; 327 : } 328 : #endif 329 : diff --git a/cov/raid/gf.h.func-sort-c.html b/cov/raid/gf.h.func-sort-c.html index 3b6821fc..c8f04224 100644 --- a/cov/raid/gf.h.func-sort-c.html +++ b/cov/raid/gf.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/gf.h.func.html b/cov/raid/gf.h.func.html index fc183f91..2368980f 100644 --- a/cov/raid/gf.h.func.html +++ b/cov/raid/gf.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/gf.h.gcov.html b/cov/raid/gf.h.gcov.html index eeb487db..670aa201 100644 --- a/cov/raid/gf.h.gcov.html +++ b/cov/raid/gf.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 @@ -88,7 +88,7 @@ 26 : */ 27 : static __always_inline uint8_t mul(uint8_t a, uint8_t b) 28 : { - 29 23792794 : return gfmul[a][b]; + 29 23792730 : return gfmul[a][b]; 30 : } 31 : 32 : /* @@ -97,9 +97,9 @@ 35 : */ 36 : static __always_inline uint8_t inv(uint8_t v) 37 : { - 38 635486 : BUG_ON(v == 0); /* division by zero */ + 38 635498 : BUG_ON(v == 0); /* division by zero */ 39 : - 40 635486 : return gfinv[v]; + 40 635498 : return gfinv[v]; 41 : } 42 : 43 : /* @@ -125,7 +125,7 @@ 63 : */ 64 : static __always_inline uint8_t A(int p, int d) 65 : { - 66 2604612 : return gfgen[p][d]; + 66 2604616 : 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 30283584 : uint32_t mask = v & 0x80808080U; + 89 31201088 : uint32_t mask = v & 0x80808080U; 90 : - 91 30283584 : mask = (mask << 1) - (mask >> 7); - 92 30283584 : v = (v << 1) & 0xfefefefeU; - 93 30283584 : v ^= mask & 0x1d1d1d1dU; - 94 30283584 : return v; + 91 31201088 : mask = (mask << 1) - (mask >> 7); + 92 31201088 : v = (v << 1) & 0xfefefefeU; + 93 31201088 : v ^= mask & 0x1d1d1d1dU; + 94 31201088 : return v; 95 : } 96 : 97 : /* @@ -161,12 +161,12 @@ 99 : */ 100 : static __always_inline uint64_t x2_64(uint64_t v) 101 : { - 102 30051232 : uint64_t mask = v & 0x8080808080808080ULL; + 102 29592480 : uint64_t mask = v & 0x8080808080808080ULL; 103 : - 104 30051232 : mask = (mask << 1) - (mask >> 7); - 105 30051232 : v = (v << 1) & 0xfefefefefefefefeULL; - 106 30051232 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL; - 107 30051232 : return v; + 104 29592480 : mask = (mask << 1) - (mask >> 7); + 105 29592480 : v = (v << 1) & 0xfefefefefefefefeULL; + 106 29592480 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL; + 107 29592480 : return v; 108 : } 109 : 110 : /* @@ -187,12 +187,12 @@ 125 : */ 126 : static __always_inline uint64_t d2_64(uint64_t v) 127 : { - 128 11240416 : uint64_t mask = v & 0x0101010101010101ULL; + 128 11699168 : uint64_t mask = v & 0x0101010101010101ULL; 129 : - 130 11240416 : mask = (mask << 8) - mask; - 131 11240416 : v = (v >> 1) & 0x7f7f7f7f7f7f7f7fULL; - 132 11240416 : v ^= mask & 0x8e8e8e8e8e8e8e8eULL; - 133 11240416 : return v; + 130 11699168 : mask = (mask << 8) - mask; + 131 11699168 : v = (v >> 1) & 0x7f7f7f7f7f7f7f7fULL; + 132 11699168 : v ^= mask & 0x8e8e8e8e8e8e8e8eULL; + 133 11699168 : return v; 134 : } 135 : 136 : #endif diff --git a/cov/raid/helper.c.func-sort-c.html b/cov/raid/helper.c.func-sort-c.html index e4c44c02..cb0e67f7 100644 --- a/cov/raid/helper.c.func-sort-c.html +++ b/cov/raid/helper.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/raid/helper.c.func.html b/cov/raid/helper.c.func.html index 52f96f2d..54647c3b 100644 --- a/cov/raid/helper.c.func.html +++ b/cov/raid/helper.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/raid/helper.c.gcov.html b/cov/raid/helper.c.gcov.html index 03e43de7..abf06a27 100644 --- a/cov/raid/helper.c.gcov.html +++ b/cov/raid/helper.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 diff --git a/cov/raid/index-sort-f.html b/cov/raid/index-sort-f.html index f4c95883..f367d0dc 100644 --- a/cov/raid/index-sort-f.html +++ b/cov/raid/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 96 @@ -69,6 +69,16 @@ Line Coverage Sort by line coverage Functions Sort by function coverage + + combo.h + +
100.0%
+ + 100.0 % + 36 / 36 + - + 0 / 0 + gf.h @@ -90,14 +100,14 @@ 0 / 0 - combo.h + intz.c
100.0%
100.0 % - 36 / 36 - - - 0 / 0 + 58 / 58 + 100.0 % + 2 / 2 helper.c @@ -110,14 +120,14 @@ 2 / 2 - intz.c + check.c
100.0%
100.0 % - 58 / 58 + 60 / 60 100.0 % - 2 / 2 + 3 / 3 x86z.c @@ -129,16 +139,6 @@ 100.0 % 3 / 3 - - check.c - -
100.0%
- - 100.0 % - 60 / 60 - 100.0 % - 3 / 3 - memory.c @@ -149,16 +149,6 @@ 100.0 % 6 / 6 - - test.c - -
98.7%98.7%
- - 98.7 % - 153 / 155 - 100.0 % - 7 / 7 - module.c @@ -169,6 +159,16 @@ 100.0 % 7 / 7 + + test.c + +
98.7%98.7%
+ + 98.7 % + 153 / 155 + 100.0 % + 7 / 7 + raid.c diff --git a/cov/raid/index-sort-l.html b/cov/raid/index-sort-l.html index d320617e..1224a797 100644 --- a/cov/raid/index-sort-l.html +++ b/cov/raid/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 96 diff --git a/cov/raid/index.html b/cov/raid/index.html index a50e3d9a..a948ee2f 100644 --- a/cov/raid/index.html +++ b/cov/raid/index.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 96 diff --git a/cov/raid/int.c.func-sort-c.html b/cov/raid/int.c.func-sort-c.html index 29f3480e..ce835fac 100644 --- a/cov/raid/int.c.func-sort-c.html +++ b/cov/raid/int.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 @@ -59,6 +59,10 @@ Function Name Sort by function name Hit count Sort by hit count + + raid_gen6_int8 + 17 + raid_gen4_int8 18 @@ -67,25 +71,21 @@ raid_gen5_int8 18 - - raid_gen6_int8 - 18 - raid_gen3_int8 - 28 + 27 raid_gen2_int32 - 43 - - - raid_gen2_int64 - 85 + 45 raid_gen1_int32 - 87 + 81 + + + raid_gen2_int64 + 81 raid_rec1_int8 @@ -93,7 +93,7 @@ raid_gen1_int64 - 170 + 159 raid_rec2_int8 diff --git a/cov/raid/int.c.func.html b/cov/raid/int.c.func.html index a9dce16b..6814e454 100644 --- a/cov/raid/int.c.func.html +++ b/cov/raid/int.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 @@ -61,23 +61,23 @@ raid_gen1_int32 - 87 + 81 raid_gen1_int64 - 170 + 159 raid_gen2_int32 - 43 + 45 raid_gen2_int64 - 85 + 81 raid_gen3_int8 - 28 + 27 raid_gen4_int8 @@ -89,7 +89,7 @@ raid_gen6_int8 - 18 + 17 raid_rec1_int8 diff --git a/cov/raid/int.c.gcov.html b/cov/raid/int.c.gcov.html index 20a57576..d875b13f 100644 --- a/cov/raid/int.c.gcov.html +++ b/cov/raid/int.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 @@ -80,9 +80,9 @@ 18 : /* 19 : * GEN1 (RAID5 with xor) 32bit C implementation 20 : */ - 21 87 : void raid_gen1_int32(int nd, size_t size, void **vv) + 21 81 : void raid_gen1_int32(int nd, size_t size, void **vv) 22 : { - 23 87 : uint8_t **v = (uint8_t **)vv; + 23 81 : 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 87 : l = nd - 1; - 32 87 : p = v[nd]; + 31 81 : l = nd - 1; + 32 81 : p = v[nd]; 33 : - 34 2752695 : for (i = 0; i < size; i += 8) { - 35 2752608 : p0 = v_32(v[l][i]); - 36 2752608 : p1 = v_32(v[l][i + 4]); - 37 22022176 : for (d = l - 1; d >= 0; --d) { - 38 19269568 : p0 ^= v_32(v[d][i]); - 39 19269568 : p1 ^= v_32(v[d][i + 4]); + 34 2556081 : for (i = 0; i < size; i += 8) { + 35 2556000 : p0 = v_32(v[l][i]); + 36 2556000 : p1 = v_32(v[l][i + 4]); + 37 20449312 : for (d = l - 1; d >= 0; --d) { + 38 17893312 : p0 ^= v_32(v[d][i]); + 39 17893312 : p1 ^= v_32(v[d][i + 4]); 40 : } - 41 2752608 : v_32(p[i]) = p0; - 42 2752608 : v_32(p[i + 4]) = p1; + 41 2556000 : v_32(p[i]) = p0; + 42 2556000 : v_32(p[i + 4]) = p1; 43 : } - 44 87 : } + 44 81 : } 45 : 46 : /* 47 : * GEN1 (RAID5 with xor) 64bit C implementation 48 : */ - 49 170 : void raid_gen1_int64(int nd, size_t size, void **vv) + 49 159 : void raid_gen1_int64(int nd, size_t size, void **vv) 50 : { - 51 170 : uint8_t **v = (uint8_t **)vv; + 51 159 : 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 170 : l = nd - 1; - 60 170 : p = v[nd]; + 59 159 : l = nd - 1; + 60 159 : p = v[nd]; 61 : - 62 2736346 : for (i = 0; i < size; i += 16) { - 63 2736176 : p0 = v_64(v[l][i]); - 64 2736176 : p1 = v_64(v[l][i + 8]); - 65 21890064 : for (d = l - 1; d >= 0; --d) { - 66 19153888 : p0 ^= v_64(v[d][i]); - 67 19153888 : p1 ^= v_64(v[d][i + 8]); + 62 2556111 : for (i = 0; i < size; i += 16) { + 63 2555952 : p0 = v_64(v[l][i]); + 64 2555952 : p1 = v_64(v[l][i + 8]); + 65 20448272 : for (d = l - 1; d >= 0; --d) { + 66 17892320 : p0 ^= v_64(v[d][i]); + 67 17892320 : p1 ^= v_64(v[d][i + 8]); 68 : } - 69 2736176 : v_64(p[i]) = p0; - 70 2736176 : v_64(p[i + 8]) = p1; + 69 2555952 : v_64(p[i]) = p0; + 70 2555952 : v_64(p[i + 8]) = p1; 71 : } - 72 170 : } + 72 159 : } 73 : 74 : /* 75 : * GEN2 (RAID6 with powers of 2) 32bit C implementation 76 : */ - 77 43 : void raid_gen2_int32(int nd, size_t size, void **vv) + 77 45 : void raid_gen2_int32(int nd, size_t size, void **vv) 78 : { - 79 43 : uint8_t **v = (uint8_t **)vv; + 79 45 : 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 43 : l = nd - 1; - 89 43 : p = v[nd]; - 90 43 : q = v[nd + 1]; + 88 45 : l = nd - 1; + 89 45 : p = v[nd]; + 90 45 : q = v[nd + 1]; 91 : - 92 1310859 : for (i = 0; i < size; i += 8) { - 93 1310816 : q0 = p0 = v_32(v[l][i]); - 94 1310816 : q1 = p1 = v_32(v[l][i + 4]); - 95 10487840 : for (d = l - 1; d >= 0; --d) { - 96 9177024 : d0 = v_32(v[d][i]); - 97 9177024 : d1 = v_32(v[d][i + 4]); + 92 1376397 : for (i = 0; i < size; i += 8) { + 93 1376352 : q0 = p0 = v_32(v[l][i]); + 94 1376352 : q1 = p1 = v_32(v[l][i + 4]); + 95 11012128 : for (d = l - 1; d >= 0; --d) { + 96 9635776 : d0 = v_32(v[d][i]); + 97 9635776 : d1 = v_32(v[d][i + 4]); 98 : - 99 9177024 : p0 ^= d0; - 100 9177024 : p1 ^= d1; + 99 9635776 : p0 ^= d0; + 100 9635776 : p1 ^= d1; 101 : - 102 9177024 : q0 = x2_32(q0); - 103 9177024 : q1 = x2_32(q1); + 102 9635776 : q0 = x2_32(q0); + 103 9635776 : q1 = x2_32(q1); 104 : - 105 9177024 : q0 ^= d0; - 106 9177024 : q1 ^= d1; + 105 9635776 : q0 ^= d0; + 106 9635776 : q1 ^= d1; 107 : } - 108 1310816 : v_32(p[i]) = p0; - 109 1310816 : v_32(p[i + 4]) = p1; - 110 1310816 : v_32(q[i]) = q0; - 111 1310816 : v_32(q[i + 4]) = q1; + 108 1376352 : v_32(p[i]) = p0; + 109 1376352 : v_32(p[i + 4]) = p1; + 110 1376352 : v_32(q[i]) = q0; + 111 1376352 : v_32(q[i + 4]) = q1; 112 : } - 113 43 : } + 113 45 : } 114 : 115 : /* 116 : * GEN2 (RAID6 with powers of 2) 64bit C implementation 117 : */ - 118 85 : void raid_gen2_int64(int nd, size_t size, void **vv) + 118 81 : void raid_gen2_int64(int nd, size_t size, void **vv) 119 : { - 120 85 : uint8_t **v = (uint8_t **)vv; + 120 81 : 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 85 : l = nd - 1; - 130 85 : p = v[nd]; - 131 85 : q = v[nd + 1]; + 129 81 : l = nd - 1; + 130 81 : p = v[nd]; + 131 81 : q = v[nd + 1]; 132 : - 133 1343621 : for (i = 0; i < size; i += 16) { - 134 1343536 : q0 = p0 = v_64(v[l][i]); - 135 1343536 : q1 = p1 = v_64(v[l][i + 8]); - 136 10748944 : for (d = l - 1; d >= 0; --d) { - 137 9405408 : d0 = v_64(v[d][i]); - 138 9405408 : d1 = v_64(v[d][i + 8]); + 133 1278081 : for (i = 0; i < size; i += 16) { + 134 1278000 : q0 = p0 = v_64(v[l][i]); + 135 1278000 : q1 = p1 = v_64(v[l][i + 8]); + 136 10224656 : for (d = l - 1; d >= 0; --d) { + 137 8946656 : d0 = v_64(v[d][i]); + 138 8946656 : d1 = v_64(v[d][i + 8]); 139 : - 140 9405408 : p0 ^= d0; - 141 9405408 : p1 ^= d1; + 140 8946656 : p0 ^= d0; + 141 8946656 : p1 ^= d1; 142 : - 143 9405408 : q0 = x2_64(q0); - 144 9405408 : q1 = x2_64(q1); + 143 8946656 : q0 = x2_64(q0); + 144 8946656 : q1 = x2_64(q1); 145 : - 146 9405408 : q0 ^= d0; - 147 9405408 : q1 ^= d1; + 146 8946656 : q0 ^= d0; + 147 8946656 : q1 ^= d1; 148 : } - 149 1343536 : v_64(p[i]) = p0; - 150 1343536 : v_64(p[i + 8]) = p1; - 151 1343536 : v_64(q[i]) = q0; - 152 1343536 : v_64(q[i + 8]) = q1; + 149 1278000 : v_64(p[i]) = p0; + 150 1278000 : v_64(p[i + 8]) = p1; + 151 1278000 : v_64(q[i]) = q0; + 152 1278000 : v_64(q[i + 8]) = q1; 153 : } - 154 85 : } + 154 81 : } 155 : 156 : /* 157 : * GEN3 (triple parity with Cauchy matrix) 8bit C implementation @@ -223,9 +223,9 @@ 161 : * But this is only a kind of reference function, and we are not really 162 : * interested in speed. 163 : */ - 164 28 : void raid_gen3_int8(int nd, size_t size, void **vv) + 164 27 : void raid_gen3_int8(int nd, size_t size, void **vv) 165 : { - 166 28 : uint8_t **v = (uint8_t **)vv; + 166 27 : uint8_t **v = (uint8_t **)vv; 167 : uint8_t *p; 168 : uint8_t *q; 169 : uint8_t *r; @@ -234,33 +234,33 @@ 172 : 173 : uint8_t d0, r0, q0, p0; 174 : - 175 28 : l = nd - 1; - 176 28 : p = v[nd]; - 177 28 : q = v[nd + 1]; - 178 28 : r = v[nd + 2]; + 175 27 : l = nd - 1; + 176 27 : p = v[nd]; + 177 27 : q = v[nd + 1]; + 178 27 : r = v[nd + 2]; 179 : - 180 6816284 : for (i = 0; i < size; i += 1) { - 181 6816256 : p0 = q0 = r0 = 0; - 182 54534400 : for (d = l; d > 0; --d) { - 183 47718144 : d0 = v_8(v[d][i]); + 180 6554139 : for (i = 0; i < size; i += 1) { + 181 6554112 : p0 = q0 = r0 = 0; + 182 52437248 : for (d = l; d > 0; --d) { + 183 45883136 : d0 = v_8(v[d][i]); 184 : - 185 47718144 : p0 ^= d0; - 186 47718144 : q0 ^= gfmul[d0][gfgen[1][d]]; - 187 47718144 : r0 ^= gfmul[d0][gfgen[2][d]]; + 185 45883136 : p0 ^= d0; + 186 45883136 : q0 ^= gfmul[d0][gfgen[1][d]]; + 187 45883136 : r0 ^= gfmul[d0][gfgen[2][d]]; 188 : } 189 : 190 : /* first disk with all coefficients at 1 */ - 191 6816256 : d0 = v_8(v[0][i]); + 191 6554112 : d0 = v_8(v[0][i]); 192 : - 193 6816256 : p0 ^= d0; - 194 6816256 : q0 ^= d0; - 195 6816256 : r0 ^= d0; + 193 6554112 : p0 ^= d0; + 194 6554112 : q0 ^= d0; + 195 6554112 : r0 ^= d0; 196 : - 197 6816256 : v_8(p[i]) = p0; - 198 6816256 : v_8(q[i]) = q0; - 199 6816256 : v_8(r[i]) = r0; + 197 6554112 : v_8(p[i]) = p0; + 198 6554112 : v_8(q[i]) = q0; + 199 6554112 : v_8(r[i]) = r0; 200 : } - 201 28 : } + 201 27 : } 202 : 203 : /* 204 : * GEN4 (quad 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 18 : void raid_gen6_int8(int nd, size_t size, void **vv) + 320 17 : void raid_gen6_int8(int nd, size_t size, void **vv) 321 : { - 322 18 : uint8_t **v = (uint8_t **)vv; + 322 17 : 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 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]; + 334 17 : l = nd - 1; + 335 17 : p = v[nd]; + 336 17 : q = v[nd + 1]; + 337 17 : r = v[nd + 2]; + 338 17 : s = v[nd + 3]; + 339 17 : t = v[nd + 4]; + 340 17 : u = v[nd + 5]; 341 : - 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]); + 342 3932689 : for (i = 0; i < size; i += 1) { + 343 3932672 : p0 = q0 = r0 = s0 = t0 = u0 = 0; + 344 31465728 : for (d = l; d > 0; --d) { + 345 27533056 : d0 = v_8(v[d][i]); 346 : - 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]]; + 347 27533056 : p0 ^= d0; + 348 27533056 : q0 ^= gfmul[d0][gfgen[1][d]]; + 349 27533056 : r0 ^= gfmul[d0][gfgen[2][d]]; + 350 27533056 : s0 ^= gfmul[d0][gfgen[3][d]]; + 351 27533056 : t0 ^= gfmul[d0][gfgen[4][d]]; + 352 27533056 : u0 ^= gfmul[d0][gfgen[5][d]]; 353 : } 354 : 355 : /* first disk with all coefficients at 1 */ - 356 4194816 : d0 = v_8(v[0][i]); + 356 3932672 : d0 = v_8(v[0][i]); 357 : - 358 4194816 : p0 ^= d0; - 359 4194816 : q0 ^= d0; - 360 4194816 : r0 ^= d0; - 361 4194816 : s0 ^= d0; - 362 4194816 : t0 ^= d0; - 363 4194816 : u0 ^= d0; + 358 3932672 : p0 ^= d0; + 359 3932672 : q0 ^= d0; + 360 3932672 : r0 ^= d0; + 361 3932672 : s0 ^= d0; + 362 3932672 : t0 ^= d0; + 363 3932672 : u0 ^= d0; 364 : - 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; + 365 3932672 : v_8(p[i]) = p0; + 366 3932672 : v_8(q[i]) = q0; + 367 3932672 : v_8(r[i]) = r0; + 368 3932672 : v_8(s[i]) = s0; + 369 3932672 : v_8(t[i]) = t0; + 370 3932672 : v_8(u[i]) = u0; 371 : } - 372 18 : } + 372 17 : } 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 2c544d80..22a993b8 100644 --- a/cov/raid/internal.h.func-sort-c.html +++ b/cov/raid/internal.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/internal.h.func.html b/cov/raid/internal.h.func.html index def6d77b..10ed9b0a 100644 --- a/cov/raid/internal.h.func.html +++ b/cov/raid/internal.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 diff --git a/cov/raid/internal.h.gcov.html b/cov/raid/internal.h.gcov.html index 3708373a..be8e1db7 100644 --- a/cov/raid/internal.h.gcov.html +++ b/cov/raid/internal.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 0 @@ -286,7 +286,7 @@ 224 : #ifdef CONFIG_SSE2 225 : static __always_inline void raid_sse_begin(void) 226 : { - 227 1384907 : } + 227 1385012 : } 228 : 229 : static __always_inline void raid_sse_end(void) 230 : { @@ -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 1384907 : asm volatile ("sfence" : : : "memory"); + 235 1385012 : asm volatile ("sfence" : : : "memory"); 236 : 237 : /* clobbers registers used in the asm code */ 238 : /* this is required because in the Windows ABI, */ @@ -304,21 +304,21 @@ 242 : /* we check for __SSE2_ because we require that the */ 243 : /* compiler supports SSE2 registers in the clobber list */ 244 : #ifdef __SSE2__ - 245 1384907 : asm volatile ("" : : : "%xmm0", "%xmm1", "%xmm2", "%xmm3"); - 246 1384907 : asm volatile ("" : : : "%xmm4", "%xmm5", "%xmm6", "%xmm7"); + 245 1385012 : asm volatile ("" : : : "%xmm0", "%xmm1", "%xmm2", "%xmm3"); + 246 1385012 : asm volatile ("" : : : "%xmm4", "%xmm5", "%xmm6", "%xmm7"); 247 : #ifdef CONFIG_X86_64 - 248 1384907 : asm volatile ("" : : : "%xmm8", "%xmm9", "%xmm10", "%xmm11"); - 249 1384907 : asm volatile ("" : : : "%xmm12", "%xmm13", "%xmm14", "%xmm15"); + 248 1385012 : asm volatile ("" : : : "%xmm8", "%xmm9", "%xmm10", "%xmm11"); + 249 1385012 : asm volatile ("" : : : "%xmm12", "%xmm13", "%xmm14", "%xmm15"); 250 : #endif 251 : #endif - 252 1384907 : } + 252 1385012 : } 253 : #endif 254 : 255 : #ifdef CONFIG_AVX2 256 : static __always_inline void raid_avx_begin(void) 257 : { 258 : raid_sse_begin(); - 259 76343 : } + 259 76341 : } 260 : 261 : static __always_inline void raid_avx_end(void) 262 : { @@ -327,8 +327,8 @@ 265 : /* reset the upper part of the ymm registers */ 266 : /* to avoid the 70 clocks penalty on the next */ 267 : /* xmm register use */ - 268 76343 : asm volatile ("vzeroupper" : : : "memory"); - 269 76343 : } + 268 76341 : asm volatile ("vzeroupper" : : : "memory"); + 269 76341 : } 270 : #endif 271 : #endif /* CONFIG_X86 */ 272 : diff --git a/cov/raid/intz.c.func-sort-c.html b/cov/raid/intz.c.func-sort-c.html index 3ba5d52b..57b4d6ec 100644 --- a/cov/raid/intz.c.func-sort-c.html +++ b/cov/raid/intz.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ raid_genz_int64 - 50 + 52
diff --git a/cov/raid/intz.c.func.html b/cov/raid/intz.c.func.html index 312f1401..ab130941 100644 --- a/cov/raid/intz.c.func.html +++ b/cov/raid/intz.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -65,7 +65,7 @@ raid_genz_int64 - 50 + 52
diff --git a/cov/raid/intz.c.gcov.html b/cov/raid/intz.c.gcov.html index 1ad1506b..865608c8 100644 --- a/cov/raid/intz.c.gcov.html +++ b/cov/raid/intz.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -131,9 +131,9 @@ 69 : /* 70 : * GENz (triple parity with powers of 2^-1) 64bit C implementation 71 : */ - 72 50 : void raid_genz_int64(int nd, size_t size, void **vv) + 72 52 : void raid_genz_int64(int nd, size_t size, void **vv) 73 : { - 74 50 : uint8_t **v = (uint8_t**)vv; + 74 52 : uint8_t **v = (uint8_t**)vv; 75 : uint8_t *p; 76 : uint8_t *q; 77 : uint8_t *r; @@ -143,41 +143,41 @@ 81 : uint64_t d0, r0, q0, p0; 82 : uint64_t d1, r1, q1, p1; 83 : - 84 50 : l = nd - 1; - 85 50 : p = v[nd]; - 86 50 : q = v[nd + 1]; - 87 50 : r = v[nd + 2]; + 84 52 : l = nd - 1; + 85 52 : p = v[nd]; + 86 52 : q = v[nd + 1]; + 87 52 : r = v[nd + 2]; 88 : - 89 802882 : for (i = 0; i < size; i += 16) { - 90 802832 : r0 = q0 = p0 = v_64(v[l][i]); - 91 802832 : r1 = q1 = p1 = v_64(v[l][i + 8]); - 92 6423040 : for (d = l - 1; d >= 0; --d) { - 93 5620208 : d0 = v_64(v[d][i]); - 94 5620208 : d1 = v_64(v[d][i + 8]); + 89 835652 : for (i = 0; i < size; i += 16) { + 90 835600 : r0 = q0 = p0 = v_64(v[l][i]); + 91 835600 : r1 = q1 = p1 = v_64(v[l][i + 8]); + 92 6685184 : for (d = l - 1; d >= 0; --d) { + 93 5849584 : d0 = v_64(v[d][i]); + 94 5849584 : d1 = v_64(v[d][i + 8]); 95 : - 96 5620208 : p0 ^= d0; - 97 5620208 : p1 ^= d1; + 96 5849584 : p0 ^= d0; + 97 5849584 : p1 ^= d1; 98 : - 99 5620208 : q0 = x2_64(q0); - 100 5620208 : q1 = x2_64(q1); + 99 5849584 : q0 = x2_64(q0); + 100 5849584 : q1 = x2_64(q1); 101 : - 102 5620208 : q0 ^= d0; - 103 5620208 : q1 ^= d1; + 102 5849584 : q0 ^= d0; + 103 5849584 : q1 ^= d1; 104 : - 105 5620208 : r0 = d2_64(r0); - 106 5620208 : r1 = d2_64(r1); + 105 5849584 : r0 = d2_64(r0); + 106 5849584 : r1 = d2_64(r1); 107 : - 108 5620208 : r0 ^= d0; - 109 5620208 : r1 ^= d1; + 108 5849584 : r0 ^= d0; + 109 5849584 : r1 ^= d1; 110 : } - 111 802832 : v_64(p[i]) = p0; - 112 802832 : v_64(p[i + 8]) = p1; - 113 802832 : v_64(q[i]) = q0; - 114 802832 : v_64(q[i + 8]) = q1; - 115 802832 : v_64(r[i]) = r0; - 116 802832 : v_64(r[i + 8]) = r1; + 111 835600 : v_64(p[i]) = p0; + 112 835600 : v_64(p[i + 8]) = p1; + 113 835600 : v_64(q[i]) = q0; + 114 835600 : v_64(q[i + 8]) = q1; + 115 835600 : v_64(r[i]) = r0; + 116 835600 : v_64(r[i + 8]) = r1; 117 : } - 118 50 : } + 118 52 : } 119 : diff --git a/cov/raid/memory.c.func-sort-c.html b/cov/raid/memory.c.func-sort-c.html index 7ca2bab7..15d9d735 100644 --- a/cov/raid/memory.c.func-sort-c.html +++ b/cov/raid/memory.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 diff --git a/cov/raid/memory.c.func.html b/cov/raid/memory.c.func.html index 9af16b33..71350f7e 100644 --- a/cov/raid/memory.c.func.html +++ b/cov/raid/memory.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 diff --git a/cov/raid/memory.c.gcov.html b/cov/raid/memory.c.gcov.html index ef7529bc..80beed4b 100644 --- a/cov/raid/memory.c.gcov.html +++ b/cov/raid/memory.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 6 @@ -94,7 +94,7 @@ 32 13341 : offset = ((uintptr_t)ptr) % align_size; 33 : 34 13341 : if (offset != 0) - 35 12532 : ptr += align_size - offset; + 35 12568 : ptr += align_size - offset; 36 : 37 13341 : return ptr; 38 : } diff --git a/cov/raid/module.c.func-sort-c.html b/cov/raid/module.c.func-sort-c.html index 3b26c283..80266f0d 100644 --- a/cov/raid/module.c.func-sort-c.html +++ b/cov/raid/module.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -85,7 +85,7 @@ raid_init - 283 + 284
diff --git a/cov/raid/module.c.func.html b/cov/raid/module.c.func.html index bb0ce76e..765ac923 100644 --- a/cov/raid/module.c.func.html +++ b/cov/raid/module.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -65,7 +65,7 @@ raid_init - 283 + 284 raid_selftest diff --git a/cov/raid/module.c.gcov.html b/cov/raid/module.c.gcov.html index 6f816fb8..5abe522c 100644 --- a/cov/raid/module.c.gcov.html +++ b/cov/raid/module.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 @@ -81,42 +81,42 @@ 19 : /* 20 : * Initializes and selects the best algorithm. 21 : */ - 22 283 : void raid_init(void) + 22 284 : void raid_init(void) 23 : { - 24 283 : raid_gen3_ptr = raid_gen3_int8; - 25 283 : raid_gen_ptr[3] = raid_gen4_int8; - 26 283 : raid_gen_ptr[4] = raid_gen5_int8; - 27 283 : raid_gen_ptr[5] = raid_gen6_int8; + 24 284 : raid_gen3_ptr = raid_gen3_int8; + 25 284 : raid_gen_ptr[3] = raid_gen4_int8; + 26 284 : raid_gen_ptr[4] = raid_gen5_int8; + 27 284 : raid_gen_ptr[5] = raid_gen6_int8; 28 : 29 : if (sizeof(void *) == 4) { 30 : raid_gen_ptr[0] = raid_gen1_int32; 31 : raid_gen_ptr[1] = raid_gen2_int32; 32 : raid_genz_ptr = raid_genz_int32; 33 : } else { - 34 283 : raid_gen_ptr[0] = raid_gen1_int64; - 35 283 : raid_gen_ptr[1] = raid_gen2_int64; - 36 283 : raid_genz_ptr = raid_genz_int64; + 34 284 : raid_gen_ptr[0] = raid_gen1_int64; + 35 284 : raid_gen_ptr[1] = raid_gen2_int64; + 36 284 : raid_genz_ptr = raid_genz_int64; 37 : } 38 : - 39 283 : raid_rec_ptr[0] = raid_rec1_int8; - 40 283 : raid_rec_ptr[1] = raid_rec2_int8; - 41 283 : raid_rec_ptr[2] = raid_recX_int8; - 42 283 : raid_rec_ptr[3] = raid_recX_int8; - 43 283 : raid_rec_ptr[4] = raid_recX_int8; - 44 283 : raid_rec_ptr[5] = raid_recX_int8; + 39 284 : raid_rec_ptr[0] = raid_rec1_int8; + 40 284 : raid_rec_ptr[1] = raid_rec2_int8; + 41 284 : raid_rec_ptr[2] = raid_recX_int8; + 42 284 : raid_rec_ptr[3] = raid_recX_int8; + 43 284 : raid_rec_ptr[4] = raid_recX_int8; + 44 284 : raid_rec_ptr[5] = raid_recX_int8; 45 : 46 : #ifdef CONFIG_X86 47 : #ifdef CONFIG_SSE2 - 48 283 : if (raid_cpu_has_sse2()) { - 49 283 : raid_gen_ptr[0] = raid_gen1_sse2; + 48 284 : if (raid_cpu_has_sse2()) { + 49 284 : raid_gen_ptr[0] = raid_gen1_sse2; 50 : #ifdef CONFIG_X86_64 - 51 283 : if (raid_cpu_has_slowextendedreg()) { + 51 284 : if (raid_cpu_has_slowextendedreg()) { 52 0 : raid_gen_ptr[1] = raid_gen2_sse2; 53 : } else { - 54 283 : raid_gen_ptr[1] = raid_gen2_sse2ext; + 54 284 : raid_gen_ptr[1] = raid_gen2_sse2ext; 55 : } 56 : /* note that raid_cpu_has_slowextendedreg() doesn't affect parz */ - 57 283 : raid_genz_ptr = raid_genz_sse2ext; + 57 284 : raid_genz_ptr = raid_genz_sse2ext; 58 : #else 59 : raid_gen_ptr[1] = raid_gen2_sse2; 60 : raid_genz_ptr = raid_genz_sse2; @@ -125,18 +125,18 @@ 63 : #endif 64 : 65 : #ifdef CONFIG_SSSE3 - 66 283 : if (raid_cpu_has_ssse3()) { + 66 284 : if (raid_cpu_has_ssse3()) { 67 : #ifdef CONFIG_X86_64 - 68 282 : if (raid_cpu_has_slowextendedreg()) { + 68 283 : if (raid_cpu_has_slowextendedreg()) { 69 0 : raid_gen3_ptr = raid_gen3_ssse3; 70 0 : raid_gen_ptr[3] = raid_gen4_ssse3; 71 0 : raid_gen_ptr[4] = raid_gen5_ssse3; 72 0 : raid_gen_ptr[5] = raid_gen6_ssse3; 73 : } else { - 74 282 : raid_gen3_ptr = raid_gen3_ssse3ext; - 75 282 : raid_gen_ptr[3] = raid_gen4_ssse3ext; - 76 282 : raid_gen_ptr[4] = raid_gen5_ssse3ext; - 77 282 : raid_gen_ptr[5] = raid_gen6_ssse3ext; + 74 283 : raid_gen3_ptr = raid_gen3_ssse3ext; + 75 283 : raid_gen_ptr[3] = raid_gen4_ssse3ext; + 76 283 : raid_gen_ptr[4] = raid_gen5_ssse3ext; + 77 283 : raid_gen_ptr[5] = raid_gen6_ssse3ext; 78 : } 79 : #else 80 : raid_gen3_ptr = raid_gen3_ssse3; @@ -144,17 +144,17 @@ 82 : raid_gen_ptr[4] = raid_gen5_ssse3; 83 : raid_gen_ptr[5] = raid_gen6_ssse3; 84 : #endif - 85 282 : raid_rec_ptr[0] = raid_rec1_ssse3; - 86 282 : raid_rec_ptr[1] = raid_rec2_ssse3; - 87 282 : raid_rec_ptr[2] = raid_recX_ssse3; - 88 282 : raid_rec_ptr[3] = raid_recX_ssse3; - 89 282 : raid_rec_ptr[4] = raid_recX_ssse3; - 90 282 : raid_rec_ptr[5] = raid_recX_ssse3; + 85 283 : raid_rec_ptr[0] = raid_rec1_ssse3; + 86 283 : raid_rec_ptr[1] = raid_rec2_ssse3; + 87 283 : raid_rec_ptr[2] = raid_recX_ssse3; + 88 283 : raid_rec_ptr[3] = raid_recX_ssse3; + 89 283 : raid_rec_ptr[4] = raid_recX_ssse3; + 90 283 : raid_rec_ptr[5] = raid_recX_ssse3; 91 : } 92 : #endif 93 : 94 : #ifdef CONFIG_AVX2 - 95 283 : if (raid_cpu_has_avx2()) { + 95 284 : if (raid_cpu_has_avx2()) { 96 2 : raid_gen_ptr[0] = raid_gen1_avx2; 97 2 : raid_gen_ptr[1] = raid_gen2_avx2; 98 : #ifdef CONFIG_X86_64 @@ -175,8 +175,8 @@ 113 : #endif /* CONFIG_X86 */ 114 : 115 : /* set the default mode */ - 116 283 : raid_mode(RAID_MODE_CAUCHY); - 117 283 : } + 116 284 : raid_mode(RAID_MODE_CAUCHY); + 117 284 : } 118 : 119 : /* 120 : * Reference parity computation. diff --git a/cov/raid/raid.c.func-sort-c.html b/cov/raid/raid.c.func-sort-c.html index 01a6dfd2..e4208e4e 100644 --- a/cov/raid/raid.c.func-sort-c.html +++ b/cov/raid/raid.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 @@ -69,31 +69,31 @@ raid_mode - 565 + 567 raid_rec - 869 + 870 raid_rec1of1 - 96873 + 97058 raid_delta_gen - 171489 + 171505 raid_invert - 172553 + 172549 raid_data - 210062 + 210262 raid_gen - 1232444 + 1232542
diff --git a/cov/raid/raid.c.func.html b/cov/raid/raid.c.func.html index 1d966ca9..f98041e6 100644 --- a/cov/raid/raid.c.func.html +++ b/cov/raid/raid.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 @@ -61,31 +61,31 @@ raid_data - 210062 + 210262 raid_delta_gen - 171489 + 171505 raid_gen - 1232444 + 1232542 raid_invert - 172553 + 172549 raid_mode - 565 + 567 raid_rec - 869 + 870 raid_rec1of1 - 96873 + 97058 raid_rec2of2_int8 diff --git a/cov/raid/raid.c.gcov.html b/cov/raid/raid.c.gcov.html index 363afff5..90ae049a 100644 --- a/cov/raid/raid.c.gcov.html +++ b/cov/raid/raid.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 9 @@ -274,16 +274,16 @@ 212 : */ 213 : const uint8_t (*raid_gfgen)[256]; 214 : - 215 565 : void raid_mode(int mode) + 215 567 : void raid_mode(int mode) 216 : { - 217 565 : if (mode == RAID_MODE_VANDERMONDE) { + 217 567 : if (mode == RAID_MODE_VANDERMONDE) { 218 2 : raid_gen_ptr[2] = raid_genz_ptr; 219 2 : raid_gfgen = gfvandermonde; 220 : } else { - 221 563 : raid_gen_ptr[2] = raid_gen3_ptr; - 222 563 : raid_gfgen = gfcauchy; + 221 565 : raid_gen_ptr[2] = raid_gen3_ptr; + 222 565 : raid_gfgen = gfcauchy; 223 : } - 224 565 : } + 224 567 : } 225 : 226 : /** 227 : * Buffer filled with 0 used in recovering. @@ -321,17 +321,17 @@ 259 : void (*raid_gen3_ptr)(int nd, size_t size, void **vv); 260 : void (*raid_genz_ptr)(int nd, size_t size, void **vv); 261 : - 262 1232444 : void raid_gen(int nd, int np, size_t size, void **v) + 262 1232542 : void raid_gen(int nd, int np, size_t size, void **v) 263 : { 264 : /* enforce limit on size */ - 265 1232444 : BUG_ON(size % 64 != 0); + 265 1232542 : BUG_ON(size % 64 != 0); 266 : 267 : /* enforce limit on number of failures */ - 268 1232444 : BUG_ON(np < 1); - 269 1232444 : BUG_ON(np > RAID_PARITY_MAX); + 268 1232542 : BUG_ON(np < 1); + 269 1232542 : BUG_ON(np > RAID_PARITY_MAX); 270 : - 271 1232444 : raid_gen_ptr[np - 1](nd, size, v); - 272 1232444 : } + 271 1232542 : raid_gen_ptr[np - 1](nd, size, v); + 272 1232542 : } 273 : 274 : /** 275 : * Inverts the square matrix M of size nxn into V. @@ -344,44 +344,44 @@ 282 : * @V Destination matrix where the result is put. 283 : * @n Number of rows and columns of the matrix. 284 : */ - 285 172553 : void raid_invert(uint8_t *M, uint8_t *V, int n) + 285 172549 : void raid_invert(uint8_t *M, uint8_t *V, int n) 286 : { 287 : int i, j, k; 288 : 289 : /* set the identity matrix in V */ - 290 797716 : for (i = 0; i < n; ++i) - 291 3219716 : for (j = 0; j < n; ++j) - 292 2594553 : V[i * n + j] = i == j; + 290 797704 : for (i = 0; i < n; ++i) + 291 3219692 : for (j = 0; j < n; ++j) + 292 2594537 : V[i * n + j] = i == j; 293 : 294 : /* for each element in the diagonal */ - 295 797716 : for (k = 0; k < n; ++k) { + 295 797704 : for (k = 0; k < n; ++k) { 296 : uint8_t f; 297 : 298 : /* the diagonal element cannot be 0 because */ 299 : /* we are inverting matrices with all the square */ 300 : /* submatrices not singular */ - 301 625163 : BUG_ON(M[k * n + k] == 0); + 301 625155 : BUG_ON(M[k * n + k] == 0); 302 : 303 : /* make the diagonal element to be 1 */ - 304 625163 : f = inv(M[k * n + k]); - 305 3219716 : for (j = 0; j < n; ++j) { - 306 2594553 : M[k * n + j] = mul(f, M[k * n + j]); - 307 5189106 : V[k * n + j] = mul(f, V[k * n + j]); + 304 625155 : f = inv(M[k * n + k]); + 305 3219692 : for (j = 0; j < n; ++j) { + 306 2594537 : M[k * n + j] = mul(f, M[k * n + j]); + 307 5189074 : V[k * n + j] = mul(f, V[k * n + j]); 308 : } 309 : 310 : /* make all the elements over and under the diagonal */ 311 : /* to be zero */ - 312 3219716 : for (i = 0; i < n; ++i) { - 313 2594553 : if (i == k) - 314 625163 : continue; - 315 1969390 : f = M[i * n + k]; - 316 11271234 : for (j = 0; j < n; ++j) { - 317 9301844 : M[i * n + j] ^= mul(f, M[k * n + j]); - 318 18603688 : V[i * n + j] ^= mul(f, V[k * n + j]); + 312 3219692 : for (i = 0; i < n; ++i) { + 313 2594537 : if (i == k) + 314 625155 : continue; + 315 1969382 : f = M[i * n + k]; + 316 11271210 : for (j = 0; j < n; ++j) { + 317 9301828 : M[i * n + j] ^= mul(f, M[k * n + j]); + 318 18603656 : V[i * n + j] ^= mul(f, V[k * n + j]); 319 : } 320 : } 321 : } - 322 172553 : } + 322 172549 : } 323 : 324 : /** 325 : * Computes the parity without the missing data blocks @@ -389,7 +389,7 @@ 327 : * 328 : * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua in the equations. 329 : */ - 330 171489 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) + 330 171505 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) 331 : { 332 : void *p[RAID_PARITY_MAX]; 333 : void *pa[RAID_PARITY_MAX]; @@ -399,17 +399,17 @@ 337 : 338 : /* total number of parities we are going to process */ 339 : /* they are both the used and the unused ones */ - 340 171489 : np = ip[nr - 1] + 1; + 340 171505 : np = ip[nr - 1] + 1; 341 : 342 : /* latest missing data block */ - 343 171489 : latest = v[id[nr - 1]]; + 343 171505 : latest = v[id[nr - 1]]; 344 : 345 : /* setup pointers for delta computation */ - 346 872987 : for (i = 0, j = 0; i < np; ++i) { + 346 873035 : for (i = 0, j = 0; i < np; ++i) { 347 : /* keep a copy of the original parity vector */ - 348 701498 : p[i] = v[nd + i]; + 348 701530 : p[i] = v[nd + i]; 349 : - 350 701498 : if (ip[j] == i) { + 350 701530 : if (ip[j] == i) { 351 : /* 352 : * Set used parities to point to the missing 353 : * data blocks. @@ -420,19 +420,19 @@ 358 : 359 : /* the latest parity to use ends the for loop and */ 360 : /* then it cannot happen to process more of them */ - 361 605425 : BUG_ON(j >= nr); + 361 605437 : BUG_ON(j >= nr); 362 : 363 : /* buffer for missing data blocks */ - 364 605425 : pa[j] = v[id[j]]; + 364 605437 : pa[j] = v[id[j]]; 365 : 366 : /* set at zero the missing data blocks */ - 367 605425 : v[id[j]] = raid_zero_block; + 367 605437 : v[id[j]] = raid_zero_block; 368 : 369 : /* compute the parity over the missing data blocks */ - 370 605425 : v[nd + i] = pa[j]; + 370 605437 : v[nd + i] = pa[j]; 371 : 372 : /* check for the next used entry */ - 373 605425 : ++j; + 373 605437 : ++j; 374 : } else { 375 : /* 376 : * Unused parities are going to be rewritten with @@ -452,25 +452,25 @@ 390 : * multiple times and only the latest write will 391 : * contain the correct data. 392 : */ - 393 96073 : v[nd + i] = latest; + 393 96093 : v[nd + i] = latest; 394 : } 395 : } 396 : 397 : /* all the parities have to be processed */ - 398 171489 : BUG_ON(j != nr); + 398 171505 : BUG_ON(j != nr); 399 : 400 : /* recompute the parity, note that np may be smaller than the */ 401 : /* total number of parities available */ - 402 171489 : raid_gen(nd, np, size, v); + 402 171505 : raid_gen(nd, np, size, v); 403 : 404 : /* restore data buffers as before */ - 405 776914 : for (j = 0; j < nr; ++j) - 406 605425 : v[id[j]] = pa[j]; + 405 776942 : for (j = 0; j < nr; ++j) + 406 605437 : v[id[j]] = pa[j]; 407 : 408 : /* restore parity buffers as before */ - 409 872987 : for (i = 0; i < np; ++i) - 410 701498 : v[nd + i] = p[i]; - 411 171489 : } + 409 873035 : for (i = 0; i < np; ++i) + 410 701530 : v[nd + i] = p[i]; + 411 171505 : } 412 : 413 : /** 414 : * Recover failure of one data block for PAR1. @@ -483,29 +483,29 @@ 421 : * 422 : * Dx = Pd 423 : */ - 424 96873 : void raid_rec1of1(int *id, int nd, size_t size, void **v) + 424 97058 : void raid_rec1of1(int *id, int nd, size_t size, void **v) 425 : { 426 : void *p; 427 : void *pa; 428 : 429 : /* for PAR1 we can directly compute the missing block */ 430 : /* and we don't need to use the zero buffer */ - 431 96873 : p = v[nd]; - 432 96873 : pa = v[id[0]]; + 431 97058 : p = v[nd]; + 432 97058 : pa = v[id[0]]; 433 : 434 : /* use the parity as missing data block */ - 435 96873 : v[id[0]] = p; + 435 97058 : v[id[0]] = p; 436 : 437 : /* compute the parity over the missing data block */ - 438 96873 : v[nd] = pa; + 438 97058 : v[nd] = pa; 439 : 440 : /* compute */ - 441 96873 : raid_gen(nd, 1, size, v); + 441 97058 : raid_gen(nd, 1, size, v); 442 : 443 : /* restore as before */ - 444 96873 : v[id[0]] = pa; - 445 96873 : v[nd] = p; - 446 96873 : } + 444 97058 : v[id[0]] = pa; + 445 97058 : v[nd] = p; + 446 97058 : } 447 : 448 : /** 449 : * Recover failure of two data blocks for PAR2. @@ -593,97 +593,97 @@ 531 : void (*raid_rec_ptr[RAID_PARITY_MAX])( 532 : int nr, int *id, int *ip, int nd, size_t size, void **vv); 533 : - 534 869 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v) + 534 870 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v) 535 : { 536 : int nrd; /* number of data blocks to recover */ 537 : int nrp; /* number of parity blocks to recover */ 538 : 539 : /* enforce limit on size */ - 540 869 : BUG_ON(size % 64 != 0); + 540 870 : BUG_ON(size % 64 != 0); 541 : 542 : /* enforce limit on number of failures */ - 543 869 : BUG_ON(nr > np); - 544 869 : BUG_ON(np > RAID_PARITY_MAX); + 543 870 : BUG_ON(nr > np); + 544 870 : BUG_ON(np > RAID_PARITY_MAX); 545 : 546 : /* enforce order in index vector */ - 547 869 : BUG_ON(nr >= 2 && ir[0] >= ir[1]); - 548 869 : BUG_ON(nr >= 3 && ir[1] >= ir[2]); - 549 869 : BUG_ON(nr >= 4 && ir[2] >= ir[3]); - 550 869 : BUG_ON(nr >= 5 && ir[3] >= ir[4]); - 551 869 : BUG_ON(nr >= 6 && ir[4] >= ir[5]); + 547 870 : BUG_ON(nr >= 2 && ir[0] >= ir[1]); + 548 870 : BUG_ON(nr >= 3 && ir[1] >= ir[2]); + 549 870 : BUG_ON(nr >= 4 && ir[2] >= ir[3]); + 550 870 : BUG_ON(nr >= 5 && ir[3] >= ir[4]); + 551 870 : BUG_ON(nr >= 6 && ir[4] >= ir[5]); 552 : 553 : /* enforce limit on index vector */ - 554 869 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np); + 554 870 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np); 555 : 556 : /* count the number of data blocks to recover */ - 557 869 : nrd = 0; - 558 2610 : while (nrd < nr && ir[nrd] < nd) - 559 1741 : ++nrd; + 557 870 : nrd = 0; + 558 2613 : while (nrd < nr && ir[nrd] < nd) + 559 1743 : ++nrd; 560 : 561 : /* all the remaining are parity */ - 562 869 : nrp = nr - nrd; + 562 870 : nrp = nr - nrd; 563 : 564 : /* enforce limit on number of failures */ - 565 869 : BUG_ON(nrd > nd); - 566 869 : BUG_ON(nrp > np); + 565 870 : BUG_ON(nrd > nd); + 566 870 : BUG_ON(nrp > np); 567 : 568 : /* if failed data is present */ - 569 869 : if (nrd != 0) { + 569 870 : if (nrd != 0) { 570 : int ip[RAID_PARITY_MAX]; 571 : int i, j, k; 572 : 573 : /* setup the vector of parities to use */ - 574 6034 : for (i = 0, j = 0, k = 0; i < np; ++i) { - 575 5167 : if (j < nrp && ir[nrd + j] == nd + i) { + 574 6041 : for (i = 0, j = 0, k = 0; i < np; ++i) { + 575 5173 : if (j < nrp && ir[nrd + j] == nd + i) { 576 : /* this parity has to be recovered */ 577 22 : ++j; 578 : } else { 579 : /* this parity is used for recovering */ - 580 5145 : ip[k] = i; - 581 5145 : ++k; + 580 5151 : ip[k] = i; + 581 5151 : ++k; 582 : } 583 : } 584 : 585 : /* recover the nrd data blocks specified in ir[], */ 586 : /* using the first nrd parity in ip[] for recovering */ - 587 867 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v); + 587 868 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v); 588 : } 589 : 590 : /* recompute all the parities up to the last bad one */ - 591 869 : if (nrp != 0) + 591 870 : if (nrp != 0) 592 12 : raid_gen(nd, ir[nr - 1] - nd + 1, size, v); - 593 869 : } + 593 870 : } 594 : - 595 210062 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) + 595 210262 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) 596 : { 597 : /* enforce limit on size */ - 598 210062 : BUG_ON(size % 64 != 0); + 598 210262 : BUG_ON(size % 64 != 0); 599 : 600 : /* enforce limit on number of failures */ - 601 210062 : BUG_ON(nr > nd); - 602 210062 : BUG_ON(nr > RAID_PARITY_MAX); + 601 210262 : BUG_ON(nr > nd); + 602 210262 : BUG_ON(nr > RAID_PARITY_MAX); 603 : 604 : /* enforce order in index vector for data */ - 605 210062 : BUG_ON(nr >= 2 && id[0] >= id[1]); - 606 210062 : BUG_ON(nr >= 3 && id[1] >= id[2]); - 607 210062 : BUG_ON(nr >= 4 && id[2] >= id[3]); - 608 210062 : BUG_ON(nr >= 5 && id[3] >= id[4]); - 609 210062 : BUG_ON(nr >= 6 && id[4] >= id[5]); + 605 210262 : BUG_ON(nr >= 2 && id[0] >= id[1]); + 606 210262 : BUG_ON(nr >= 3 && id[1] >= id[2]); + 607 210262 : BUG_ON(nr >= 4 && id[2] >= id[3]); + 608 210262 : BUG_ON(nr >= 5 && id[3] >= id[4]); + 609 210262 : BUG_ON(nr >= 6 && id[4] >= id[5]); 610 : 611 : /* enforce limit on index vector for data */ - 612 210062 : BUG_ON(nr > 0 && id[nr-1] >= nd); + 612 210262 : BUG_ON(nr > 0 && id[nr-1] >= nd); 613 : 614 : /* enforce order in index vector for parity */ - 615 210062 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); - 616 210062 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); - 617 210062 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); - 618 210062 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); - 619 210062 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); + 615 210262 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); + 616 210262 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); + 617 210262 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); + 618 210262 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); + 619 210262 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); 620 : 621 : /* if failed data is present */ - 622 210062 : if (nr != 0) - 623 210060 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); - 624 210062 : } + 622 210262 : if (nr != 0) + 623 210260 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); + 624 210262 : } 625 : diff --git a/cov/raid/tag.c.func-sort-c.html b/cov/raid/tag.c.func-sort-c.html index 38a084fc..eff176fa 100644 --- a/cov/raid/tag.c.func-sort-c.html +++ b/cov/raid/tag.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 diff --git a/cov/raid/tag.c.func.html b/cov/raid/tag.c.func.html index f4ede672..a883bca6 100644 --- a/cov/raid/tag.c.func.html +++ b/cov/raid/tag.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 diff --git a/cov/raid/tag.c.gcov.html b/cov/raid/tag.c.gcov.html index 39e7393b..c47a4afb 100644 --- a/cov/raid/tag.c.gcov.html +++ b/cov/raid/tag.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 11 diff --git a/cov/raid/test.c.func-sort-c.html b/cov/raid/test.c.func-sort-c.html index 178ea7a3..baa87ae2 100644 --- a/cov/raid/test.c.func-sort-c.html +++ b/cov/raid/test.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 diff --git a/cov/raid/test.c.func.html b/cov/raid/test.c.func.html index 88f79097..ef8aecb1 100644 --- a/cov/raid/test.c.func.html +++ b/cov/raid/test.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 diff --git a/cov/raid/test.c.gcov.html b/cov/raid/test.c.gcov.html index 6624295e..73fa39b5 100644 --- a/cov/raid/test.c.gcov.html +++ b/cov/raid/test.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 7 diff --git a/cov/raid/x86.c.func-sort-c.html b/cov/raid/x86.c.func-sort-c.html index 7367a480..5c456d2e 100644 --- a/cov/raid/x86.c.func-sort-c.html +++ b/cov/raid/x86.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 23 @@ -73,7 +73,7 @@ raid_gen3_ssse3 - 11 + 9 raid_gen2_sse2 @@ -81,7 +81,7 @@ raid_gen1_avx2 - 97 + 96 raid_rec1_avx2 @@ -89,7 +89,7 @@ raid_gen2_avx2 - 510 + 509 raid_gen3_avx2ext @@ -129,7 +129,7 @@ raid_rec2_ssse3 - 44102 + 44098 raid_recX_ssse3 @@ -137,19 +137,19 @@ raid_rec1_ssse3 - 106666 + 106871 raid_gen2_sse2ext - 268615 + 268631 raid_gen1_sse2 - 284018 + 284150 raid_gen6_ssse3ext - 528480 + 528427
diff --git a/cov/raid/x86.c.func.html b/cov/raid/x86.c.func.html index a3f5c14e..1e887468 100644 --- a/cov/raid/x86.c.func.html +++ b/cov/raid/x86.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 23 @@ -61,15 +61,15 @@ raid_gen1_avx2 - 97 + 96 raid_gen1_sse2 - 284018 + 284150 raid_gen2_avx2 - 510 + 509 raid_gen2_sse2 @@ -77,7 +77,7 @@ raid_gen2_sse2ext - 268615 + 268631 raid_gen3_avx2ext @@ -85,7 +85,7 @@ raid_gen3_ssse3 - 11 + 9 raid_gen3_ssse3ext @@ -125,7 +125,7 @@ raid_gen6_ssse3ext - 528480 + 528427 raid_rec1_avx2 @@ -133,7 +133,7 @@ raid_rec1_ssse3 - 106666 + 106871 raid_rec2_avx2 @@ -141,7 +141,7 @@ raid_rec2_ssse3 - 44102 + 44098 raid_recX_avx2 diff --git a/cov/raid/x86.c.gcov.html b/cov/raid/x86.c.gcov.html index 22212d83..4311eff2 100644 --- a/cov/raid/x86.c.gcov.html +++ b/cov/raid/x86.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 23 @@ -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 284018 : void raid_gen1_sse2(int nd, size_t size, void **vv) + 36 284150 : void raid_gen1_sse2(int nd, size_t size, void **vv) 37 : { - 38 284018 : uint8_t **v = (uint8_t **)vv; + 38 284150 : uint8_t **v = (uint8_t **)vv; 39 : uint8_t *p; 40 : int d, l; 41 : size_t i; 42 : - 43 284018 : l = nd - 1; - 44 284018 : p = v[nd]; + 43 284150 : l = nd - 1; + 44 284150 : p = v[nd]; 45 : 46 : raid_sse_begin(); 47 : - 48 5032270 : for (i = 0; i < size; i += 64) { - 49 4748252 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 50 4748252 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 51 4748252 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); - 52 4748252 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); - 53 28899300 : for (d = l - 1; d >= 0; --d) { - 54 24151048 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); - 55 24151048 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); - 56 24151048 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); - 57 24151048 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); + 48 5026354 : for (i = 0; i < size; i += 64) { + 49 4742204 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 50 4742204 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 51 4742204 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + 52 4742204 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + 53 28846628 : for (d = l - 1; d >= 0; --d) { + 54 24104424 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); + 55 24104424 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); + 56 24104424 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); + 57 24104424 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); 58 : } - 59 4748252 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 60 4748252 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 61 4748252 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); - 62 4748252 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + 59 4742204 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 60 4742204 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 61 4742204 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + 62 4742204 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); 63 : } 64 : 65 : raid_sse_end(); - 66 284018 : } + 66 284150 : } 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 96 : void raid_gen1_avx2(int nd, size_t size, void **vv) 78 : { - 79 97 : uint8_t **v = (uint8_t **)vv; + 79 96 : 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 96 : l = nd - 1; + 85 96 : 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 46092 : for (i = 0; i < size; i += 64) { + 90 45996 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + 91 45996 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); + 92 374404 : for (d = l - 1; d >= 0; --d) { + 93 328408 : asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i])); + 94 328408 : 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 45996 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + 97 45996 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); 98 : } 99 : 100 : raid_avx_end(); - 101 97 : } + 101 96 : } 102 : #endif 103 : 104 : #if defined(CONFIG_X86) && defined(CONFIG_SSE2) @@ -237,53 +237,53 @@ 175 : /* 176 : * GEN2 (RAID6 with powers of 2) AVX2 implementation 177 : */ - 178 510 : void raid_gen2_avx2(int nd, size_t size, void **vv) + 178 509 : void raid_gen2_avx2(int nd, size_t size, void **vv) 179 : { - 180 510 : uint8_t **v = (uint8_t **)vv; + 180 509 : uint8_t **v = (uint8_t **)vv; 181 : uint8_t *p; 182 : uint8_t *q; 183 : int d, l; 184 : size_t i; 185 : - 186 510 : l = nd - 1; - 187 510 : p = v[nd]; - 188 510 : q = v[nd + 1]; + 186 509 : l = nd - 1; + 187 509 : p = v[nd]; + 188 509 : q = v[nd + 1]; 189 : 190 : raid_avx_begin(); 191 : - 192 510 : asm volatile ("vbroadcasti128 %0, %%ymm7" : : "m" (gfconst16.poly[0])); - 193 510 : asm volatile ("vpxor %ymm6,%ymm6,%ymm6"); + 192 509 : asm volatile ("vbroadcasti128 %0, %%ymm7" : : "m" (gfconst16.poly[0])); + 193 509 : asm volatile ("vpxor %ymm6,%ymm6,%ymm6"); 194 : - 195 113754 : for (i = 0; i < size; i += 64) { - 196 113244 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); - 197 113244 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); - 198 113244 : asm volatile ("vmovdqa %ymm0,%ymm2"); - 199 113244 : asm volatile ("vmovdqa %ymm1,%ymm3"); - 200 919748 : for (d = l - 1; d >= 0; --d) { - 201 806504 : asm volatile ("vpcmpgtb %ymm2,%ymm6,%ymm4"); - 202 806504 : asm volatile ("vpcmpgtb %ymm3,%ymm6,%ymm5"); - 203 806504 : asm volatile ("vpaddb %ymm2,%ymm2,%ymm2"); - 204 806504 : asm volatile ("vpaddb %ymm3,%ymm3,%ymm3"); - 205 806504 : asm volatile ("vpand %ymm7,%ymm4,%ymm4"); - 206 806504 : asm volatile ("vpand %ymm7,%ymm5,%ymm5"); - 207 806504 : asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); - 208 806504 : asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); + 195 109657 : for (i = 0; i < size; i += 64) { + 196 109148 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + 197 109148 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); + 198 109148 : asm volatile ("vmovdqa %ymm0,%ymm2"); + 199 109148 : asm volatile ("vmovdqa %ymm1,%ymm3"); + 200 886980 : for (d = l - 1; d >= 0; --d) { + 201 777832 : asm volatile ("vpcmpgtb %ymm2,%ymm6,%ymm4"); + 202 777832 : asm volatile ("vpcmpgtb %ymm3,%ymm6,%ymm5"); + 203 777832 : asm volatile ("vpaddb %ymm2,%ymm2,%ymm2"); + 204 777832 : asm volatile ("vpaddb %ymm3,%ymm3,%ymm3"); + 205 777832 : asm volatile ("vpand %ymm7,%ymm4,%ymm4"); + 206 777832 : asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + 207 777832 : asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + 208 777832 : asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); 209 : - 210 806504 : asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); - 211 806504 : asm volatile ("vmovdqa %0,%%ymm5" : : "m" (v[d][i + 32])); - 212 806504 : asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); - 213 806504 : asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); - 214 806504 : asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); - 215 806504 : asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); + 210 777832 : asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); + 211 777832 : asm volatile ("vmovdqa %0,%%ymm5" : : "m" (v[d][i + 32])); + 212 777832 : asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + 213 777832 : asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + 214 777832 : asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + 215 777832 : asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); 216 : } - 217 113244 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); - 218 113244 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); - 219 113244 : asm volatile ("vmovntdq %%ymm2,%0" : "=m" (q[i])); - 220 113244 : asm volatile ("vmovntdq %%ymm3,%0" : "=m" (q[i + 32])); + 217 109148 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + 218 109148 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); + 219 109148 : asm volatile ("vmovntdq %%ymm2,%0" : "=m" (q[i])); + 220 109148 : asm volatile ("vmovntdq %%ymm3,%0" : "=m" (q[i + 32])); 221 : } 222 : 223 : raid_avx_end(); - 224 510 : } + 224 509 : } 225 : #endif 226 : 227 : #if defined(CONFIG_X86_64) && defined(CONFIG_SSE2) @@ -292,100 +292,100 @@ 230 : * 231 : * Note that it uses 16 registers, meaning that x64 is required. 232 : */ - 233 268615 : void raid_gen2_sse2ext(int nd, size_t size, void **vv) + 233 268631 : void raid_gen2_sse2ext(int nd, size_t size, void **vv) 234 : { - 235 268615 : uint8_t **v = (uint8_t **)vv; + 235 268631 : uint8_t **v = (uint8_t **)vv; 236 : uint8_t *p; 237 : uint8_t *q; 238 : int d, l; 239 : size_t i; 240 : - 241 268615 : l = nd - 1; - 242 268615 : p = v[nd]; - 243 268615 : q = v[nd + 1]; + 241 268631 : l = nd - 1; + 242 268631 : p = v[nd]; + 243 268631 : q = v[nd + 1]; 244 : 245 : raid_sse_begin(); 246 : - 247 268615 : asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.poly[0])); + 247 268631 : asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.poly[0])); 248 : - 249 4794899 : for (i = 0; i < size; i += 64) { - 250 4526284 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 251 4526284 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 252 4526284 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); - 253 4526284 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); - 254 4526284 : asm volatile ("movdqa %xmm0,%xmm4"); - 255 4526284 : asm volatile ("movdqa %xmm1,%xmm5"); - 256 4526284 : asm volatile ("movdqa %xmm2,%xmm6"); - 257 4526284 : asm volatile ("movdqa %xmm3,%xmm7"); - 258 27616644 : for (d = l - 1; d >= 0; --d) { - 259 23090360 : asm volatile ("pxor %xmm8,%xmm8"); - 260 23090360 : asm volatile ("pxor %xmm9,%xmm9"); - 261 23090360 : asm volatile ("pxor %xmm10,%xmm10"); - 262 23090360 : asm volatile ("pxor %xmm11,%xmm11"); - 263 23090360 : asm volatile ("pcmpgtb %xmm4,%xmm8"); - 264 23090360 : asm volatile ("pcmpgtb %xmm5,%xmm9"); - 265 23090360 : asm volatile ("pcmpgtb %xmm6,%xmm10"); - 266 23090360 : asm volatile ("pcmpgtb %xmm7,%xmm11"); - 267 23090360 : asm volatile ("paddb %xmm4,%xmm4"); - 268 23090360 : asm volatile ("paddb %xmm5,%xmm5"); - 269 23090360 : asm volatile ("paddb %xmm6,%xmm6"); - 270 23090360 : asm volatile ("paddb %xmm7,%xmm7"); - 271 23090360 : asm volatile ("pand %xmm15,%xmm8"); - 272 23090360 : asm volatile ("pand %xmm15,%xmm9"); - 273 23090360 : asm volatile ("pand %xmm15,%xmm10"); - 274 23090360 : asm volatile ("pand %xmm15,%xmm11"); - 275 23090360 : asm volatile ("pxor %xmm8,%xmm4"); - 276 23090360 : asm volatile ("pxor %xmm9,%xmm5"); - 277 23090360 : asm volatile ("pxor %xmm10,%xmm6"); - 278 23090360 : asm volatile ("pxor %xmm11,%xmm7"); + 249 4795171 : for (i = 0; i < size; i += 64) { + 250 4526540 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 251 4526540 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 252 4526540 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + 253 4526540 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + 254 4526540 : asm volatile ("movdqa %xmm0,%xmm4"); + 255 4526540 : asm volatile ("movdqa %xmm1,%xmm5"); + 256 4526540 : asm volatile ("movdqa %xmm2,%xmm6"); + 257 4526540 : asm volatile ("movdqa %xmm3,%xmm7"); + 258 27618180 : for (d = l - 1; d >= 0; --d) { + 259 23091640 : asm volatile ("pxor %xmm8,%xmm8"); + 260 23091640 : asm volatile ("pxor %xmm9,%xmm9"); + 261 23091640 : asm volatile ("pxor %xmm10,%xmm10"); + 262 23091640 : asm volatile ("pxor %xmm11,%xmm11"); + 263 23091640 : asm volatile ("pcmpgtb %xmm4,%xmm8"); + 264 23091640 : asm volatile ("pcmpgtb %xmm5,%xmm9"); + 265 23091640 : asm volatile ("pcmpgtb %xmm6,%xmm10"); + 266 23091640 : asm volatile ("pcmpgtb %xmm7,%xmm11"); + 267 23091640 : asm volatile ("paddb %xmm4,%xmm4"); + 268 23091640 : asm volatile ("paddb %xmm5,%xmm5"); + 269 23091640 : asm volatile ("paddb %xmm6,%xmm6"); + 270 23091640 : asm volatile ("paddb %xmm7,%xmm7"); + 271 23091640 : asm volatile ("pand %xmm15,%xmm8"); + 272 23091640 : asm volatile ("pand %xmm15,%xmm9"); + 273 23091640 : asm volatile ("pand %xmm15,%xmm10"); + 274 23091640 : asm volatile ("pand %xmm15,%xmm11"); + 275 23091640 : asm volatile ("pxor %xmm8,%xmm4"); + 276 23091640 : asm volatile ("pxor %xmm9,%xmm5"); + 277 23091640 : asm volatile ("pxor %xmm10,%xmm6"); + 278 23091640 : asm volatile ("pxor %xmm11,%xmm7"); 279 : - 280 23090360 : asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i])); - 281 23090360 : asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d][i + 16])); - 282 23090360 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i + 32])); - 283 23090360 : asm volatile ("movdqa %0,%%xmm11" : : "m" (v[d][i + 48])); - 284 23090360 : asm volatile ("pxor %xmm8,%xmm0"); - 285 23090360 : asm volatile ("pxor %xmm9,%xmm1"); - 286 23090360 : asm volatile ("pxor %xmm10,%xmm2"); - 287 23090360 : asm volatile ("pxor %xmm11,%xmm3"); - 288 23090360 : asm volatile ("pxor %xmm8,%xmm4"); - 289 23090360 : asm volatile ("pxor %xmm9,%xmm5"); - 290 23090360 : asm volatile ("pxor %xmm10,%xmm6"); - 291 23090360 : asm volatile ("pxor %xmm11,%xmm7"); + 280 23091640 : asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i])); + 281 23091640 : asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d][i + 16])); + 282 23091640 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i + 32])); + 283 23091640 : asm volatile ("movdqa %0,%%xmm11" : : "m" (v[d][i + 48])); + 284 23091640 : asm volatile ("pxor %xmm8,%xmm0"); + 285 23091640 : asm volatile ("pxor %xmm9,%xmm1"); + 286 23091640 : asm volatile ("pxor %xmm10,%xmm2"); + 287 23091640 : asm volatile ("pxor %xmm11,%xmm3"); + 288 23091640 : asm volatile ("pxor %xmm8,%xmm4"); + 289 23091640 : asm volatile ("pxor %xmm9,%xmm5"); + 290 23091640 : asm volatile ("pxor %xmm10,%xmm6"); + 291 23091640 : asm volatile ("pxor %xmm11,%xmm7"); 292 : } - 293 4526284 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 294 4526284 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 295 4526284 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); - 296 4526284 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); - 297 4526284 : asm volatile ("movntdq %%xmm4,%0" : "=m" (q[i])); - 298 4526284 : asm volatile ("movntdq %%xmm5,%0" : "=m" (q[i + 16])); - 299 4526284 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i + 32])); - 300 4526284 : asm volatile ("movntdq %%xmm7,%0" : "=m" (q[i + 48])); + 293 4526540 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 294 4526540 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 295 4526540 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + 296 4526540 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + 297 4526540 : asm volatile ("movntdq %%xmm4,%0" : "=m" (q[i])); + 298 4526540 : asm volatile ("movntdq %%xmm5,%0" : "=m" (q[i + 16])); + 299 4526540 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i + 32])); + 300 4526540 : asm volatile ("movntdq %%xmm7,%0" : "=m" (q[i + 48])); 301 : } 302 : 303 : raid_sse_end(); - 304 268615 : } + 304 268631 : } 305 : #endif 306 : 307 : #if defined(CONFIG_X86) && defined(CONFIG_SSSE3) 308 : /* 309 : * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation 310 : */ - 311 11 : void raid_gen3_ssse3(int nd, size_t size, void **vv) + 311 9 : void raid_gen3_ssse3(int nd, size_t size, void **vv) 312 : { - 313 11 : uint8_t **v = (uint8_t **)vv; + 313 9 : 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 11 : l = nd - 1; - 321 11 : p = v[nd]; - 322 11 : q = v[nd + 1]; - 323 11 : r = v[nd + 2]; + 320 9 : l = nd - 1; + 321 9 : p = v[nd]; + 322 9 : q = v[nd + 1]; + 323 9 : r = v[nd + 2]; 324 : 325 : /* special case with only one data disk */ - 326 11 : if (l == 0) { + 326 9 : if (l == 0) { 327 4 : for (i = 0; i < 3; ++i) 328 3 : memcpy(v[1 + i], v[0], size); 329 1 : return; @@ -394,69 +394,69 @@ 332 : raid_sse_begin(); 333 : 334 : /* generic case with at least two data disks */ - 335 10 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); - 336 10 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 335 8 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); + 336 8 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 337 : - 338 147482 : for (i = 0; i < size; i += 16) { + 338 114712 : for (i = 0; i < size; i += 16) { 339 : /* last disk without the by two multiplication */ - 340 147472 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 340 114704 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 341 : - 342 147472 : asm volatile ("movdqa %xmm4,%xmm0"); - 343 147472 : asm volatile ("movdqa %xmm4,%xmm1"); + 342 114704 : asm volatile ("movdqa %xmm4,%xmm0"); + 343 114704 : asm volatile ("movdqa %xmm4,%xmm1"); 344 : - 345 147472 : asm volatile ("movdqa %xmm4,%xmm5"); - 346 147472 : asm volatile ("psrlw $4,%xmm5"); - 347 147472 : asm volatile ("pand %xmm7,%xmm4"); - 348 147472 : asm volatile ("pand %xmm7,%xmm5"); + 345 114704 : asm volatile ("movdqa %xmm4,%xmm5"); + 346 114704 : asm volatile ("psrlw $4,%xmm5"); + 347 114704 : asm volatile ("pand %xmm7,%xmm4"); + 348 114704 : asm volatile ("pand %xmm7,%xmm5"); 349 : - 350 147472 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); - 351 147472 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); - 352 147472 : asm volatile ("pshufb %xmm4,%xmm2"); - 353 147472 : asm volatile ("pshufb %xmm5,%xmm6"); - 354 147472 : asm volatile ("pxor %xmm6,%xmm2"); + 350 114704 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + 351 114704 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); + 352 114704 : asm volatile ("pshufb %xmm4,%xmm2"); + 353 114704 : asm volatile ("pshufb %xmm5,%xmm6"); + 354 114704 : asm volatile ("pxor %xmm6,%xmm2"); 355 : 356 : /* intermediate disks */ - 357 1032688 : for (d = l - 1; d > 0; --d) { - 358 885216 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 357 803312 : for (d = l - 1; d > 0; --d) { + 358 688608 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 359 : - 360 885216 : asm volatile ("pxor %xmm5,%xmm5"); - 361 885216 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 362 885216 : asm volatile ("paddb %xmm1,%xmm1"); - 363 885216 : asm volatile ("pand %xmm3,%xmm5"); - 364 885216 : asm volatile ("pxor %xmm5,%xmm1"); + 360 688608 : asm volatile ("pxor %xmm5,%xmm5"); + 361 688608 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 362 688608 : asm volatile ("paddb %xmm1,%xmm1"); + 363 688608 : asm volatile ("pand %xmm3,%xmm5"); + 364 688608 : asm volatile ("pxor %xmm5,%xmm1"); 365 : - 366 885216 : asm volatile ("pxor %xmm4,%xmm0"); - 367 885216 : asm volatile ("pxor %xmm4,%xmm1"); + 366 688608 : asm volatile ("pxor %xmm4,%xmm0"); + 367 688608 : asm volatile ("pxor %xmm4,%xmm1"); 368 : - 369 885216 : asm volatile ("movdqa %xmm4,%xmm5"); - 370 885216 : asm volatile ("psrlw $4,%xmm5"); - 371 885216 : asm volatile ("pand %xmm7,%xmm4"); - 372 885216 : asm volatile ("pand %xmm7,%xmm5"); + 369 688608 : asm volatile ("movdqa %xmm4,%xmm5"); + 370 688608 : asm volatile ("psrlw $4,%xmm5"); + 371 688608 : asm volatile ("pand %xmm7,%xmm4"); + 372 688608 : asm volatile ("pand %xmm7,%xmm5"); 373 : - 374 885216 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 375 885216 : asm volatile ("pshufb %xmm4,%xmm6"); - 376 885216 : asm volatile ("pxor %xmm6,%xmm2"); - 377 885216 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); - 378 885216 : asm volatile ("pshufb %xmm5,%xmm6"); - 379 885216 : asm volatile ("pxor %xmm6,%xmm2"); + 374 688608 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 375 688608 : asm volatile ("pshufb %xmm4,%xmm6"); + 376 688608 : asm volatile ("pxor %xmm6,%xmm2"); + 377 688608 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); + 378 688608 : asm volatile ("pshufb %xmm5,%xmm6"); + 379 688608 : asm volatile ("pxor %xmm6,%xmm2"); 380 : } 381 : 382 : /* first disk with all coefficients at 1 */ - 383 147472 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 383 114704 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); 384 : - 385 147472 : asm volatile ("pxor %xmm5,%xmm5"); - 386 147472 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 387 147472 : asm volatile ("paddb %xmm1,%xmm1"); - 388 147472 : asm volatile ("pand %xmm3,%xmm5"); - 389 147472 : asm volatile ("pxor %xmm5,%xmm1"); + 385 114704 : asm volatile ("pxor %xmm5,%xmm5"); + 386 114704 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 387 114704 : asm volatile ("paddb %xmm1,%xmm1"); + 388 114704 : asm volatile ("pand %xmm3,%xmm5"); + 389 114704 : asm volatile ("pxor %xmm5,%xmm1"); 390 : - 391 147472 : asm volatile ("pxor %xmm4,%xmm0"); - 392 147472 : asm volatile ("pxor %xmm4,%xmm1"); - 393 147472 : asm volatile ("pxor %xmm4,%xmm2"); + 391 114704 : asm volatile ("pxor %xmm4,%xmm0"); + 392 114704 : asm volatile ("pxor %xmm4,%xmm1"); + 393 114704 : asm volatile ("pxor %xmm4,%xmm2"); 394 : - 395 147472 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 396 147472 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 397 147472 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 395 114704 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 396 114704 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 397 114704 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 398 : } 399 : 400 : raid_sse_end(); @@ -1751,9 +1751,9 @@ 1689 : * 1690 : * Note that it uses 16 registers, meaning that x64 is required. 1691 : */ - 1692 528480 : void raid_gen6_ssse3ext(int nd, size_t size, void **vv) + 1692 528427 : void raid_gen6_ssse3ext(int nd, size_t size, void **vv) 1693 : { - 1694 528480 : uint8_t **v = (uint8_t **)vv; + 1694 528427 : uint8_t **v = (uint8_t **)vv; 1695 : uint8_t *p; 1696 : uint8_t *q; 1697 : uint8_t *r; @@ -1763,16 +1763,16 @@ 1701 : int d, l; 1702 : size_t i; 1703 : - 1704 528480 : l = nd - 1; - 1705 528480 : p = v[nd]; - 1706 528480 : q = v[nd + 1]; - 1707 528480 : r = v[nd + 2]; - 1708 528480 : s = v[nd + 3]; - 1709 528480 : t = v[nd + 4]; - 1710 528480 : u = v[nd + 5]; + 1704 528427 : l = nd - 1; + 1705 528427 : p = v[nd]; + 1706 528427 : q = v[nd + 1]; + 1707 528427 : r = v[nd + 2]; + 1708 528427 : s = v[nd + 3]; + 1709 528427 : t = v[nd + 4]; + 1710 528427 : u = v[nd + 5]; 1711 : 1712 : /* special case with only one data disk */ - 1713 528480 : if (l == 0) { + 1713 528427 : if (l == 0) { 1714 7 : for (i = 0; i < 6; ++i) 1715 6 : memcpy(v[1 + i], v[0], size); 1716 1 : return; @@ -1781,114 +1781,114 @@ 1719 : raid_sse_begin(); 1720 : 1721 : /* generic case with at least two data disks */ - 1722 528479 : asm volatile ("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0])); - 1723 528479 : asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + 1722 528426 : asm volatile ("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0])); + 1723 528426 : asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); 1724 : - 1725 34938607 : for (i = 0; i < size; i += 16) { + 1725 34918842 : for (i = 0; i < size; i += 16) { 1726 : /* last disk without the by two multiplication */ - 1727 34410128 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[l][i])); + 1727 34390416 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[l][i])); 1728 : - 1729 34410128 : asm volatile ("movdqa %xmm10,%xmm0"); - 1730 34410128 : asm volatile ("movdqa %xmm10,%xmm1"); + 1729 34390416 : asm volatile ("movdqa %xmm10,%xmm0"); + 1730 34390416 : asm volatile ("movdqa %xmm10,%xmm1"); 1731 : - 1732 34410128 : asm volatile ("movdqa %xmm10,%xmm11"); - 1733 34410128 : asm volatile ("psrlw $4,%xmm11"); - 1734 34410128 : asm volatile ("pand %xmm15,%xmm10"); - 1735 34410128 : asm volatile ("pand %xmm15,%xmm11"); + 1732 34390416 : asm volatile ("movdqa %xmm10,%xmm11"); + 1733 34390416 : asm volatile ("psrlw $4,%xmm11"); + 1734 34390416 : asm volatile ("pand %xmm15,%xmm10"); + 1735 34390416 : asm volatile ("pand %xmm15,%xmm11"); 1736 : - 1737 34410128 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); - 1738 34410128 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][0][1][0])); - 1739 34410128 : asm volatile ("pshufb %xmm10,%xmm2"); - 1740 34410128 : asm volatile ("pshufb %xmm11,%xmm13"); - 1741 34410128 : asm volatile ("pxor %xmm13,%xmm2"); + 1737 34390416 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + 1738 34390416 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][0][1][0])); + 1739 34390416 : asm volatile ("pshufb %xmm10,%xmm2"); + 1740 34390416 : asm volatile ("pshufb %xmm11,%xmm13"); + 1741 34390416 : asm volatile ("pxor %xmm13,%xmm2"); 1742 : - 1743 34410128 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); - 1744 34410128 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][1][1][0])); - 1745 34410128 : asm volatile ("pshufb %xmm10,%xmm3"); - 1746 34410128 : asm volatile ("pshufb %xmm11,%xmm13"); - 1747 34410128 : asm volatile ("pxor %xmm13,%xmm3"); + 1743 34390416 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + 1744 34390416 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][1][1][0])); + 1745 34390416 : asm volatile ("pshufb %xmm10,%xmm3"); + 1746 34390416 : asm volatile ("pshufb %xmm11,%xmm13"); + 1747 34390416 : asm volatile ("pxor %xmm13,%xmm3"); 1748 : - 1749 34410128 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfgenpshufb[l][2][0][0])); - 1750 34410128 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][2][1][0])); - 1751 34410128 : asm volatile ("pshufb %xmm10,%xmm4"); - 1752 34410128 : asm volatile ("pshufb %xmm11,%xmm13"); - 1753 34410128 : asm volatile ("pxor %xmm13,%xmm4"); + 1749 34390416 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfgenpshufb[l][2][0][0])); + 1750 34390416 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][2][1][0])); + 1751 34390416 : asm volatile ("pshufb %xmm10,%xmm4"); + 1752 34390416 : asm volatile ("pshufb %xmm11,%xmm13"); + 1753 34390416 : asm volatile ("pxor %xmm13,%xmm4"); 1754 : - 1755 34410128 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfgenpshufb[l][3][0][0])); - 1756 34410128 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][3][1][0])); - 1757 34410128 : asm volatile ("pshufb %xmm10,%xmm5"); - 1758 34410128 : asm volatile ("pshufb %xmm11,%xmm13"); - 1759 34410128 : asm volatile ("pxor %xmm13,%xmm5"); + 1755 34390416 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfgenpshufb[l][3][0][0])); + 1756 34390416 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][3][1][0])); + 1757 34390416 : asm volatile ("pshufb %xmm10,%xmm5"); + 1758 34390416 : asm volatile ("pshufb %xmm11,%xmm13"); + 1759 34390416 : asm volatile ("pxor %xmm13,%xmm5"); 1760 : 1761 : /* intermediate disks */ - 1762 173230704 : for (d = l - 1; d > 0; --d) { - 1763 138820576 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i])); + 1762 173099376 : for (d = l - 1; d > 0; --d) { + 1763 138708960 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i])); 1764 : - 1765 138820576 : asm volatile ("pxor %xmm11,%xmm11"); - 1766 138820576 : asm volatile ("pcmpgtb %xmm1,%xmm11"); - 1767 138820576 : asm volatile ("paddb %xmm1,%xmm1"); - 1768 138820576 : asm volatile ("pand %xmm14,%xmm11"); - 1769 138820576 : asm volatile ("pxor %xmm11,%xmm1"); + 1765 138708960 : asm volatile ("pxor %xmm11,%xmm11"); + 1766 138708960 : asm volatile ("pcmpgtb %xmm1,%xmm11"); + 1767 138708960 : asm volatile ("paddb %xmm1,%xmm1"); + 1768 138708960 : asm volatile ("pand %xmm14,%xmm11"); + 1769 138708960 : asm volatile ("pxor %xmm11,%xmm1"); 1770 : - 1771 138820576 : asm volatile ("pxor %xmm10,%xmm0"); - 1772 138820576 : asm volatile ("pxor %xmm10,%xmm1"); + 1771 138708960 : asm volatile ("pxor %xmm10,%xmm0"); + 1772 138708960 : asm volatile ("pxor %xmm10,%xmm1"); 1773 : - 1774 138820576 : asm volatile ("movdqa %xmm10,%xmm11"); - 1775 138820576 : asm volatile ("psrlw $4,%xmm11"); - 1776 138820576 : asm volatile ("pand %xmm15,%xmm10"); - 1777 138820576 : asm volatile ("pand %xmm15,%xmm11"); + 1774 138708960 : asm volatile ("movdqa %xmm10,%xmm11"); + 1775 138708960 : asm volatile ("psrlw $4,%xmm11"); + 1776 138708960 : asm volatile ("pand %xmm15,%xmm10"); + 1777 138708960 : asm volatile ("pand %xmm15,%xmm11"); 1778 : - 1779 138820576 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][0][0][0])); - 1780 138820576 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][0][1][0])); - 1781 138820576 : asm volatile ("pshufb %xmm10,%xmm12"); - 1782 138820576 : asm volatile ("pshufb %xmm11,%xmm13"); - 1783 138820576 : asm volatile ("pxor %xmm12,%xmm2"); - 1784 138820576 : asm volatile ("pxor %xmm13,%xmm2"); + 1779 138708960 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][0][0][0])); + 1780 138708960 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][0][1][0])); + 1781 138708960 : asm volatile ("pshufb %xmm10,%xmm12"); + 1782 138708960 : asm volatile ("pshufb %xmm11,%xmm13"); + 1783 138708960 : asm volatile ("pxor %xmm12,%xmm2"); + 1784 138708960 : asm volatile ("pxor %xmm13,%xmm2"); 1785 : - 1786 138820576 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][1][0][0])); - 1787 138820576 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][1][1][0])); - 1788 138820576 : asm volatile ("pshufb %xmm10,%xmm12"); - 1789 138820576 : asm volatile ("pshufb %xmm11,%xmm13"); - 1790 138820576 : asm volatile ("pxor %xmm12,%xmm3"); - 1791 138820576 : asm volatile ("pxor %xmm13,%xmm3"); + 1786 138708960 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][1][0][0])); + 1787 138708960 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][1][1][0])); + 1788 138708960 : asm volatile ("pshufb %xmm10,%xmm12"); + 1789 138708960 : asm volatile ("pshufb %xmm11,%xmm13"); + 1790 138708960 : asm volatile ("pxor %xmm12,%xmm3"); + 1791 138708960 : asm volatile ("pxor %xmm13,%xmm3"); 1792 : - 1793 138820576 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][2][0][0])); - 1794 138820576 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][2][1][0])); - 1795 138820576 : asm volatile ("pshufb %xmm10,%xmm12"); - 1796 138820576 : asm volatile ("pshufb %xmm11,%xmm13"); - 1797 138820576 : asm volatile ("pxor %xmm12,%xmm4"); - 1798 138820576 : asm volatile ("pxor %xmm13,%xmm4"); + 1793 138708960 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][2][0][0])); + 1794 138708960 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][2][1][0])); + 1795 138708960 : asm volatile ("pshufb %xmm10,%xmm12"); + 1796 138708960 : asm volatile ("pshufb %xmm11,%xmm13"); + 1797 138708960 : asm volatile ("pxor %xmm12,%xmm4"); + 1798 138708960 : asm volatile ("pxor %xmm13,%xmm4"); 1799 : - 1800 138820576 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][3][0][0])); - 1801 138820576 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][3][1][0])); - 1802 138820576 : asm volatile ("pshufb %xmm10,%xmm12"); - 1803 138820576 : asm volatile ("pshufb %xmm11,%xmm13"); - 1804 138820576 : asm volatile ("pxor %xmm12,%xmm5"); - 1805 138820576 : asm volatile ("pxor %xmm13,%xmm5"); + 1800 138708960 : asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][3][0][0])); + 1801 138708960 : asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][3][1][0])); + 1802 138708960 : asm volatile ("pshufb %xmm10,%xmm12"); + 1803 138708960 : asm volatile ("pshufb %xmm11,%xmm13"); + 1804 138708960 : asm volatile ("pxor %xmm12,%xmm5"); + 1805 138708960 : asm volatile ("pxor %xmm13,%xmm5"); 1806 : } 1807 : 1808 : /* first disk with all coefficients at 1 */ - 1809 34410128 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[0][i])); + 1809 34390416 : asm volatile ("movdqa %0,%%xmm10" : : "m" (v[0][i])); 1810 : - 1811 34410128 : asm volatile ("pxor %xmm11,%xmm11"); - 1812 34410128 : asm volatile ("pcmpgtb %xmm1,%xmm11"); - 1813 34410128 : asm volatile ("paddb %xmm1,%xmm1"); - 1814 34410128 : asm volatile ("pand %xmm14,%xmm11"); - 1815 34410128 : asm volatile ("pxor %xmm11,%xmm1"); + 1811 34390416 : asm volatile ("pxor %xmm11,%xmm11"); + 1812 34390416 : asm volatile ("pcmpgtb %xmm1,%xmm11"); + 1813 34390416 : asm volatile ("paddb %xmm1,%xmm1"); + 1814 34390416 : asm volatile ("pand %xmm14,%xmm11"); + 1815 34390416 : asm volatile ("pxor %xmm11,%xmm1"); 1816 : - 1817 34410128 : asm volatile ("pxor %xmm10,%xmm0"); - 1818 34410128 : asm volatile ("pxor %xmm10,%xmm1"); - 1819 34410128 : asm volatile ("pxor %xmm10,%xmm2"); - 1820 34410128 : asm volatile ("pxor %xmm10,%xmm3"); - 1821 34410128 : asm volatile ("pxor %xmm10,%xmm4"); - 1822 34410128 : asm volatile ("pxor %xmm10,%xmm5"); + 1817 34390416 : asm volatile ("pxor %xmm10,%xmm0"); + 1818 34390416 : asm volatile ("pxor %xmm10,%xmm1"); + 1819 34390416 : asm volatile ("pxor %xmm10,%xmm2"); + 1820 34390416 : asm volatile ("pxor %xmm10,%xmm3"); + 1821 34390416 : asm volatile ("pxor %xmm10,%xmm4"); + 1822 34390416 : asm volatile ("pxor %xmm10,%xmm5"); 1823 : - 1824 34410128 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 1825 34410128 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 1826 34410128 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); - 1827 34410128 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); - 1828 34410128 : asm volatile ("movntdq %%xmm4,%0" : "=m" (t[i])); - 1829 34410128 : asm volatile ("movntdq %%xmm5,%0" : "=m" (u[i])); + 1824 34390416 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 1825 34390416 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 1826 34390416 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 1827 34390416 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + 1828 34390416 : asm volatile ("movntdq %%xmm4,%0" : "=m" (t[i])); + 1829 34390416 : asm volatile ("movntdq %%xmm5,%0" : "=m" (u[i])); 1830 : } 1831 : 1832 : raid_sse_end(); @@ -2046,9 +2046,9 @@ 1984 : /* 1985 : * RAID recovering for one disk SSSE3 implementation 1986 : */ - 1987 106666 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 1987 106871 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 1988 : { - 1989 106666 : uint8_t **v = (uint8_t **)vv; + 1989 106871 : 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 106666 : if (ip[0] == 0) { - 2000 96819 : raid_rec1of1(id, nd, size, vv); - 2001 96819 : return; + 1999 106871 : if (ip[0] == 0) { + 2000 97004 : raid_rec1of1(id, nd, size, vv); + 2001 97004 : return; 2002 : } 2003 : 2004 : /* setup the coefficients matrix */ - 2005 9847 : G = A(ip[0], id[0]); + 2005 9867 : G = A(ip[0], id[0]); 2006 : 2007 : /* invert it to solve the system of linear equations */ - 2008 9847 : V = inv(G); + 2008 9867 : V = inv(G); 2009 : 2010 : /* compute delta parity */ - 2011 9847 : raid_delta_gen(1, id, ip, nd, size, vv); + 2011 9867 : raid_delta_gen(1, id, ip, nd, size, vv); 2012 : - 2013 9847 : p = v[nd + ip[0]]; - 2014 9847 : pa = v[id[0]]; + 2013 9867 : p = v[nd + ip[0]]; + 2014 9867 : pa = v[id[0]]; 2015 : 2016 : raid_sse_begin(); 2017 : - 2018 9847 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 2019 9847 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); - 2020 9847 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); + 2018 9867 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2019 9867 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); + 2020 9867 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); 2021 : - 2022 1027703 : for (i = 0; i < size; i += 16) { - 2023 1017856 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); - 2024 1017856 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); - 2025 1017856 : asm volatile ("movdqa %xmm4,%xmm2"); - 2026 1017856 : asm volatile ("movdqa %xmm5,%xmm3"); - 2027 1017856 : asm volatile ("pxor %xmm0,%xmm1"); - 2028 1017856 : asm volatile ("movdqa %xmm1,%xmm0"); - 2029 1017856 : asm volatile ("psrlw $4,%xmm1"); - 2030 1017856 : asm volatile ("pand %xmm7,%xmm0"); - 2031 1017856 : asm volatile ("pand %xmm7,%xmm1"); - 2032 1017856 : asm volatile ("pshufb %xmm0,%xmm2"); - 2033 1017856 : asm volatile ("pshufb %xmm1,%xmm3"); - 2034 1017856 : asm volatile ("pxor %xmm3,%xmm2"); - 2035 1017856 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); + 2022 1029003 : for (i = 0; i < size; i += 16) { + 2023 1019136 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); + 2024 1019136 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); + 2025 1019136 : asm volatile ("movdqa %xmm4,%xmm2"); + 2026 1019136 : asm volatile ("movdqa %xmm5,%xmm3"); + 2027 1019136 : asm volatile ("pxor %xmm0,%xmm1"); + 2028 1019136 : asm volatile ("movdqa %xmm1,%xmm0"); + 2029 1019136 : asm volatile ("psrlw $4,%xmm1"); + 2030 1019136 : asm volatile ("pand %xmm7,%xmm0"); + 2031 1019136 : asm volatile ("pand %xmm7,%xmm1"); + 2032 1019136 : asm volatile ("pshufb %xmm0,%xmm2"); + 2033 1019136 : asm volatile ("pshufb %xmm1,%xmm3"); + 2034 1019136 : asm volatile ("pxor %xmm3,%xmm2"); + 2035 1019136 : 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 44102 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) - 2047 44102 : { - 2048 44102 : uint8_t **v = (uint8_t **)vv; - 2049 44102 : const int N = 2; - 2050 44102 : uint8_t *p[N]; - 2051 44102 : uint8_t *pa[N]; - 2052 44102 : uint8_t G[N * N]; - 2053 44102 : uint8_t V[N * N]; + 2046 44098 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 2047 44098 : { + 2048 44098 : uint8_t **v = (uint8_t **)vv; + 2049 44098 : const int N = 2; + 2050 44098 : uint8_t *p[N]; + 2051 44098 : uint8_t *pa[N]; + 2052 44098 : uint8_t G[N * N]; + 2053 44098 : 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 132306 : for (j = 0; j < N; ++j) - 2061 264612 : for (k = 0; k < N; ++k) - 2062 352816 : G[j * N + k] = A(ip[j], id[k]); + 2060 132294 : for (j = 0; j < N; ++j) + 2061 264588 : for (k = 0; k < N; ++k) + 2062 352784 : G[j * N + k] = A(ip[j], id[k]); 2063 : 2064 : /* invert it to solve the system of linear equations */ - 2065 44102 : raid_invert(G, V, N); + 2065 44098 : raid_invert(G, V, N); 2066 : 2067 : /* compute delta parity */ - 2068 44102 : raid_delta_gen(N, id, ip, nd, size, vv); + 2068 44098 : raid_delta_gen(N, id, ip, nd, size, vv); 2069 : - 2070 132306 : for (j = 0; j < N; ++j) { - 2071 88204 : p[j] = v[nd + ip[j]]; - 2072 88204 : pa[j] = v[id[j]]; + 2070 132294 : for (j = 0; j < N; ++j) { + 2071 88196 : p[j] = v[nd + ip[j]]; + 2072 88196 : pa[j] = v[id[j]]; 2073 : } 2074 : 2075 : raid_sse_begin(); 2076 : - 2077 44102 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2077 44098 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 2078 : - 2079 3201286 : for (i = 0; i < size; i += 16) { - 2080 3157184 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); - 2081 3157184 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); - 2082 3157184 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); - 2083 3157184 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); - 2084 3157184 : asm volatile ("pxor %xmm2,%xmm0"); - 2085 3157184 : asm volatile ("pxor %xmm3,%xmm1"); + 2079 3201026 : for (i = 0; i < size; i += 16) { + 2080 3156928 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); + 2081 3156928 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); + 2082 3156928 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); + 2083 3156928 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); + 2084 3156928 : asm volatile ("pxor %xmm2,%xmm0"); + 2085 3156928 : asm volatile ("pxor %xmm3,%xmm1"); 2086 : - 2087 3157184 : asm volatile ("pxor %xmm6,%xmm6"); + 2087 3156928 : asm volatile ("pxor %xmm6,%xmm6"); 2088 : - 2089 3157184 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); - 2090 3157184 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); - 2091 3157184 : asm volatile ("movdqa %xmm0,%xmm4"); - 2092 3157184 : asm volatile ("movdqa %xmm0,%xmm5"); - 2093 3157184 : asm volatile ("psrlw $4,%xmm5"); - 2094 3157184 : asm volatile ("pand %xmm7,%xmm4"); - 2095 3157184 : asm volatile ("pand %xmm7,%xmm5"); - 2096 3157184 : asm volatile ("pshufb %xmm4,%xmm2"); - 2097 3157184 : asm volatile ("pshufb %xmm5,%xmm3"); - 2098 3157184 : asm volatile ("pxor %xmm2,%xmm6"); - 2099 3157184 : asm volatile ("pxor %xmm3,%xmm6"); + 2089 3156928 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); + 2090 3156928 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); + 2091 3156928 : asm volatile ("movdqa %xmm0,%xmm4"); + 2092 3156928 : asm volatile ("movdqa %xmm0,%xmm5"); + 2093 3156928 : asm volatile ("psrlw $4,%xmm5"); + 2094 3156928 : asm volatile ("pand %xmm7,%xmm4"); + 2095 3156928 : asm volatile ("pand %xmm7,%xmm5"); + 2096 3156928 : asm volatile ("pshufb %xmm4,%xmm2"); + 2097 3156928 : asm volatile ("pshufb %xmm5,%xmm3"); + 2098 3156928 : asm volatile ("pxor %xmm2,%xmm6"); + 2099 3156928 : asm volatile ("pxor %xmm3,%xmm6"); 2100 : - 2101 3157184 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); - 2102 3157184 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); - 2103 3157184 : asm volatile ("movdqa %xmm1,%xmm4"); - 2104 3157184 : asm volatile ("movdqa %xmm1,%xmm5"); - 2105 3157184 : asm volatile ("psrlw $4,%xmm5"); - 2106 3157184 : asm volatile ("pand %xmm7,%xmm4"); - 2107 3157184 : asm volatile ("pand %xmm7,%xmm5"); - 2108 3157184 : asm volatile ("pshufb %xmm4,%xmm2"); - 2109 3157184 : asm volatile ("pshufb %xmm5,%xmm3"); - 2110 3157184 : asm volatile ("pxor %xmm2,%xmm6"); - 2111 3157184 : asm volatile ("pxor %xmm3,%xmm6"); + 2101 3156928 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); + 2102 3156928 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); + 2103 3156928 : asm volatile ("movdqa %xmm1,%xmm4"); + 2104 3156928 : asm volatile ("movdqa %xmm1,%xmm5"); + 2105 3156928 : asm volatile ("psrlw $4,%xmm5"); + 2106 3156928 : asm volatile ("pand %xmm7,%xmm4"); + 2107 3156928 : asm volatile ("pand %xmm7,%xmm5"); + 2108 3156928 : asm volatile ("pshufb %xmm4,%xmm2"); + 2109 3156928 : asm volatile ("pshufb %xmm5,%xmm3"); + 2110 3156928 : asm volatile ("pxor %xmm2,%xmm6"); + 2111 3156928 : asm volatile ("pxor %xmm3,%xmm6"); 2112 : - 2113 3157184 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); + 2113 3156928 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); 2114 : - 2115 3157184 : asm volatile ("pxor %xmm6,%xmm6"); + 2115 3156928 : asm volatile ("pxor %xmm6,%xmm6"); 2116 : - 2117 3157184 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); - 2118 3157184 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); - 2119 3157184 : asm volatile ("movdqa %xmm0,%xmm4"); - 2120 3157184 : asm volatile ("movdqa %xmm0,%xmm5"); - 2121 3157184 : asm volatile ("psrlw $4,%xmm5"); - 2122 3157184 : asm volatile ("pand %xmm7,%xmm4"); - 2123 3157184 : asm volatile ("pand %xmm7,%xmm5"); - 2124 3157184 : asm volatile ("pshufb %xmm4,%xmm2"); - 2125 3157184 : asm volatile ("pshufb %xmm5,%xmm3"); - 2126 3157184 : asm volatile ("pxor %xmm2,%xmm6"); - 2127 3157184 : asm volatile ("pxor %xmm3,%xmm6"); + 2117 3156928 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); + 2118 3156928 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); + 2119 3156928 : asm volatile ("movdqa %xmm0,%xmm4"); + 2120 3156928 : asm volatile ("movdqa %xmm0,%xmm5"); + 2121 3156928 : asm volatile ("psrlw $4,%xmm5"); + 2122 3156928 : asm volatile ("pand %xmm7,%xmm4"); + 2123 3156928 : asm volatile ("pand %xmm7,%xmm5"); + 2124 3156928 : asm volatile ("pshufb %xmm4,%xmm2"); + 2125 3156928 : asm volatile ("pshufb %xmm5,%xmm3"); + 2126 3156928 : asm volatile ("pxor %xmm2,%xmm6"); + 2127 3156928 : asm volatile ("pxor %xmm3,%xmm6"); 2128 : - 2129 3157184 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); - 2130 3157184 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); - 2131 3157184 : asm volatile ("movdqa %xmm1,%xmm4"); - 2132 3157184 : asm volatile ("movdqa %xmm1,%xmm5"); - 2133 3157184 : asm volatile ("psrlw $4,%xmm5"); - 2134 3157184 : asm volatile ("pand %xmm7,%xmm4"); - 2135 3157184 : asm volatile ("pand %xmm7,%xmm5"); - 2136 3157184 : asm volatile ("pshufb %xmm4,%xmm2"); - 2137 3157184 : asm volatile ("pshufb %xmm5,%xmm3"); - 2138 3157184 : asm volatile ("pxor %xmm2,%xmm6"); - 2139 3157184 : asm volatile ("pxor %xmm3,%xmm6"); + 2129 3156928 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); + 2130 3156928 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); + 2131 3156928 : asm volatile ("movdqa %xmm1,%xmm4"); + 2132 3156928 : asm volatile ("movdqa %xmm1,%xmm5"); + 2133 3156928 : asm volatile ("psrlw $4,%xmm5"); + 2134 3156928 : asm volatile ("pand %xmm7,%xmm4"); + 2135 3156928 : asm volatile ("pand %xmm7,%xmm5"); + 2136 3156928 : asm volatile ("pshufb %xmm4,%xmm2"); + 2137 3156928 : asm volatile ("pshufb %xmm5,%xmm3"); + 2138 3156928 : asm volatile ("pxor %xmm2,%xmm6"); + 2139 3156928 : asm volatile ("pxor %xmm3,%xmm6"); 2140 : - 2141 3157184 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); + 2141 3156928 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); 2142 : } 2143 : 2144 : raid_sse_end(); - 2145 44102 : } + 2145 44098 : } 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 b3e1a7df..18507f8c 100644 --- a/cov/raid/x86z.c.func-sort-c.html +++ b/cov/raid/x86z.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -61,7 +61,7 @@ raid_genz_sse2 - 13 + 11 raid_genz_sse2ext diff --git a/cov/raid/x86z.c.func.html b/cov/raid/x86z.c.func.html index 28ba68c6..252c5dff 100644 --- a/cov/raid/x86z.c.func.html +++ b/cov/raid/x86z.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -65,7 +65,7 @@ raid_genz_sse2 - 13 + 11 raid_genz_sse2ext diff --git a/cov/raid/x86z.c.gcov.html b/cov/raid/x86z.c.gcov.html index 88d86f76..ffc8c5f5 100644 --- a/cov/raid/x86z.c.gcov.html +++ b/cov/raid/x86z.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -102,58 +102,58 @@ 40 : /* 41 : * GENz (triple parity with powers of 2^-1) SSE2 implementation 42 : */ - 43 13 : void raid_genz_sse2(int nd, size_t size, void **vv) + 43 11 : void raid_genz_sse2(int nd, size_t size, void **vv) 44 : { - 45 13 : uint8_t **v = (uint8_t**)vv; + 45 11 : 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 13 : l = nd - 1; - 53 13 : p = v[nd]; - 54 13 : q = v[nd + 1]; - 55 13 : r = v[nd + 2]; + 52 11 : l = nd - 1; + 53 11 : p = v[nd]; + 54 11 : q = v[nd + 1]; + 55 11 : r = v[nd + 2]; 56 : 57 : raid_sse_begin(); 58 : - 59 13 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); - 60 13 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); - 61 13 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); + 59 11 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); + 60 11 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); + 61 11 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); 62 : - 63 196637 : for (i = 0; i < size; i += 16) { - 64 196624 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 65 196624 : asm volatile ("movdqa %xmm0,%xmm1"); - 66 196624 : asm volatile ("movdqa %xmm0,%xmm2"); - 67 1573376 : for (d = l - 1; d >= 0; --d) { - 68 1376752 : asm volatile ("pxor %xmm4,%xmm4"); - 69 1376752 : asm volatile ("pcmpgtb %xmm1,%xmm4"); - 70 1376752 : asm volatile ("paddb %xmm1,%xmm1"); - 71 1376752 : asm volatile ("pand %xmm7,%xmm4"); - 72 1376752 : asm volatile ("pxor %xmm4,%xmm1"); + 63 163867 : for (i = 0; i < size; i += 16) { + 64 163856 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 65 163856 : asm volatile ("movdqa %xmm0,%xmm1"); + 66 163856 : asm volatile ("movdqa %xmm0,%xmm2"); + 67 1311232 : for (d = l - 1; d >= 0; --d) { + 68 1147376 : asm volatile ("pxor %xmm4,%xmm4"); + 69 1147376 : asm volatile ("pcmpgtb %xmm1,%xmm4"); + 70 1147376 : asm volatile ("paddb %xmm1,%xmm1"); + 71 1147376 : asm volatile ("pand %xmm7,%xmm4"); + 72 1147376 : asm volatile ("pxor %xmm4,%xmm1"); 73 : - 74 1376752 : asm volatile ("movdqa %xmm2,%xmm4"); - 75 1376752 : asm volatile ("pxor %xmm5,%xmm5"); - 76 1376752 : asm volatile ("psllw $7,%xmm4"); - 77 1376752 : asm volatile ("psrlw $1,%xmm2"); - 78 1376752 : asm volatile ("pcmpgtb %xmm4,%xmm5"); - 79 1376752 : asm volatile ("pand %xmm6,%xmm2"); - 80 1376752 : asm volatile ("pand %xmm3,%xmm5"); - 81 1376752 : asm volatile ("pxor %xmm5,%xmm2"); + 74 1147376 : asm volatile ("movdqa %xmm2,%xmm4"); + 75 1147376 : asm volatile ("pxor %xmm5,%xmm5"); + 76 1147376 : asm volatile ("psllw $7,%xmm4"); + 77 1147376 : asm volatile ("psrlw $1,%xmm2"); + 78 1147376 : asm volatile ("pcmpgtb %xmm4,%xmm5"); + 79 1147376 : asm volatile ("pand %xmm6,%xmm2"); + 80 1147376 : asm volatile ("pand %xmm3,%xmm5"); + 81 1147376 : asm volatile ("pxor %xmm5,%xmm2"); 82 : - 83 1376752 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 84 1376752 : asm volatile ("pxor %xmm4,%xmm0"); - 85 1376752 : asm volatile ("pxor %xmm4,%xmm1"); - 86 1376752 : asm volatile ("pxor %xmm4,%xmm2"); + 83 1147376 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 84 1147376 : asm volatile ("pxor %xmm4,%xmm0"); + 85 1147376 : asm volatile ("pxor %xmm4,%xmm1"); + 86 1147376 : asm volatile ("pxor %xmm4,%xmm2"); 87 : } - 88 196624 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 89 196624 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 90 196624 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 88 163856 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 89 163856 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 90 163856 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 91 : } 92 : 93 : raid_sse_end(); - 94 13 : } + 94 11 : } 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 84c0d9aa..410dc457 100644 --- a/cov/tommyds/index-sort-f.html +++ b/cov/tommyds/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 78 @@ -89,16 +89,6 @@ 100.0 % 2 / 2 - - tommyhash.h - -
100.0%
- - 100.0 % - 18 / 18 - 100.0 % - 2 / 2 - tommyarrayblkof.h @@ -109,6 +99,16 @@ 100.0 % 2 / 2 + + tommyhash.h + +
100.0%
+ + 100.0 % + 18 / 18 + 100.0 % + 2 / 2 + tommytypes.h @@ -139,16 +139,6 @@ 100.0 % 4 / 4 - - tommyhash.c - -
100.0%
- - 100.0 % - 115 / 115 - 100.0 % - 4 / 4 - tommyarray.c @@ -159,6 +149,16 @@ 100.0 % 4 / 4 + + tommyhash.c + +
100.0%
+ + 100.0 % + 115 / 115 + 100.0 % + 4 / 4 + tommyarray.h diff --git a/cov/tommyds/index-sort-l.html b/cov/tommyds/index-sort-l.html index 9aff068d..58c14186 100644 --- a/cov/tommyds/index-sort-l.html +++ b/cov/tommyds/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 78 @@ -79,16 +79,6 @@ 100.0 % 1 / 1 - - tommyarrayblkof.h - -
100.0%
- - 100.0 % - 6 / 6 - 100.0 % - 2 / 2 - tommytypes.h @@ -99,6 +89,16 @@ 100.0 % 3 / 3 + + tommyarrayblkof.h + +
100.0%
+ + 100.0 % + 6 / 6 + 100.0 % + 2 / 2 + tommyhashdyn.h diff --git a/cov/tommyds/index.html b/cov/tommyds/index.html index 04122e68..fa0de117 100644 --- a/cov/tommyds/index.html +++ b/cov/tommyds/index.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 78 diff --git a/cov/tommyds/tommyarray.c.func-sort-c.html b/cov/tommyds/tommyarray.c.func-sort-c.html index 565c176b..3c9c643f 100644 --- a/cov/tommyds/tommyarray.c.func-sort-c.html +++ b/cov/tommyds/tommyarray.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -65,11 +65,11 @@ tommy_array_done - 534 + 535 tommy_array_init - 546 + 547 tommy_array_grow diff --git a/cov/tommyds/tommyarray.c.func.html b/cov/tommyds/tommyarray.c.func.html index f5c5f0be..53604583 100644 --- a/cov/tommyds/tommyarray.c.func.html +++ b/cov/tommyds/tommyarray.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -61,7 +61,7 @@ tommy_array_done - 534 + 535 tommy_array_grow @@ -69,7 +69,7 @@ tommy_array_init - 546 + 547 tommy_array_memory_usage diff --git a/cov/tommyds/tommyarray.c.gcov.html b/cov/tommyds/tommyarray.c.gcov.html index 9ffd3513..c742821e 100644 --- a/cov/tommyds/tommyarray.c.gcov.html +++ b/cov/tommyds/tommyarray.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -92,30 +92,30 @@ 30 : /******************************************************************************/ 31 : /* array */ 32 : - 33 546 : TOMMY_API void tommy_array_init(tommy_array* array) + 33 547 : TOMMY_API void tommy_array_init(tommy_array* array) 34 : { 35 : tommy_uint_t i; 36 : 37 : /* fixed initial size */ - 38 546 : array->bucket_bit = TOMMY_ARRAY_BIT; - 39 546 : array->bucket_max = (tommy_size_t)1 << array->bucket_bit; - 40 546 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); - 41 3276 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i) - 42 2730 : array->bucket[i] = array->bucket[0]; + 38 547 : array->bucket_bit = TOMMY_ARRAY_BIT; + 39 547 : array->bucket_max = (tommy_size_t)1 << array->bucket_bit; + 40 547 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + 41 3282 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i) + 42 2735 : array->bucket[i] = array->bucket[0]; 43 : - 44 546 : array->count = 0; - 45 546 : } + 44 547 : array->count = 0; + 45 547 : } 46 : - 47 534 : TOMMY_API void tommy_array_done(tommy_array* array) + 47 535 : TOMMY_API void tommy_array_done(tommy_array* array) 48 : { 49 : tommy_uint_t i; 50 : - 51 534 : tommy_free(array->bucket[0]); - 52 536 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) { + 51 535 : tommy_free(array->bucket[0]); + 52 537 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) { 53 2 : void** segment = array->bucket[i]; 54 2 : tommy_free(&segment[(tommy_ptrdiff_t)1 << i]); 55 : } - 56 534 : } + 56 535 : } 57 : 58 2302 : TOMMY_API void tommy_array_grow(tommy_array* array, tommy_size_t count) 59 : { diff --git a/cov/tommyds/tommyarray.h.func-sort-c.html b/cov/tommyds/tommyarray.h.func-sort-c.html index 793d1f6b..fc67005b 100644 --- a/cov/tommyds/tommyarray.h.func-sort-c.html +++ b/cov/tommyds/tommyarray.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -69,15 +69,15 @@ tommy_array_size - 1635800 + 1635801 tommy_array_get - 8513524 + 8494577 tommy_array_ref - 8515825 + 8496878
diff --git a/cov/tommyds/tommyarray.h.func.html b/cov/tommyds/tommyarray.h.func.html index 7d572ce2..fd6107c7 100644 --- a/cov/tommyds/tommyarray.h.func.html +++ b/cov/tommyds/tommyarray.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -61,7 +61,7 @@ tommy_array_get - 8513524 + 8494577 tommy_array_insert @@ -69,7 +69,7 @@ tommy_array_ref - 8515825 + 8496878 tommy_array_set @@ -77,7 +77,7 @@ tommy_array_size - 1635800 + 1635801
diff --git a/cov/tommyds/tommyarray.h.gcov.html b/cov/tommyds/tommyarray.h.gcov.html index 44a38efd..ae841587 100644 --- a/cov/tommyds/tommyarray.h.gcov.html +++ b/cov/tommyds/tommyarray.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -147,16 +147,16 @@ 85 : * You must be sure that space for this position is already 86 : * allocated calling tommy_array_grow(). 87 : */ - 88 8515825 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_size_t pos) + 88 8496878 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_size_t pos) 89 : { 90 : tommy_uint_t bsr; 91 : - 92 8515825 : assert(pos < array->count); + 92 8496878 : assert(pos < array->count); 93 : 94 : /* get the highest bit set, in case of all 0, return 0 */ - 95 8515825 : bsr = tommy_ilog2(pos | 1); + 95 8496878 : bsr = tommy_ilog2(pos | 1); 96 : - 97 8515825 : return &array->bucket[bsr][pos]; + 97 8496878 : return &array->bucket[bsr][pos]; 98 : } 99 : 100 : /** @@ -174,9 +174,9 @@ 112 : * You must be sure that space for this position is already 113 : * allocated calling tommy_array_grow(). 114 : */ - 115 8513524 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_size_t pos) + 115 8494577 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_size_t pos) 116 : { - 117 8513524 : return *tommy_array_ref(array, pos); + 117 8494577 : return *tommy_array_ref(array, pos); 118 : } 119 : 120 : /** @@ -194,9 +194,9 @@ 132 : /** 133 : * Gets the initialized size of the array. 134 : */ - 135 1635800 : tommy_inline tommy_size_t tommy_array_size(tommy_array* array) + 135 1635801 : tommy_inline tommy_size_t tommy_array_size(tommy_array* array) 136 : { - 137 1635800 : return array->count; + 137 1635801 : return array->count; 138 : } 139 : 140 : /** diff --git a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html index 5cac0cbe..3aae58f6 100644 --- a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -65,15 +65,15 @@ tommy_arrayblkof_done - 269 + 270 tommy_arrayblkof_init - 280 + 281 tommy_arrayblkof_grow - 1757830 + 1757779
diff --git a/cov/tommyds/tommyarrayblkof.c.func.html b/cov/tommyds/tommyarrayblkof.c.func.html index 2c9dc2fc..b07e59b5 100644 --- a/cov/tommyds/tommyarrayblkof.c.func.html +++ b/cov/tommyds/tommyarrayblkof.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -61,15 +61,15 @@ tommy_arrayblkof_done - 269 + 270 tommy_arrayblkof_grow - 1757830 + 1757779 tommy_arrayblkof_init - 280 + 281 tommy_arrayblkof_memory_usage diff --git a/cov/tommyds/tommyarrayblkof.c.gcov.html b/cov/tommyds/tommyarrayblkof.c.gcov.html index 48e5a85c..31246f1a 100644 --- a/cov/tommyds/tommyarrayblkof.c.gcov.html +++ b/cov/tommyds/tommyarrayblkof.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -92,31 +92,31 @@ 30 : /******************************************************************************/ 31 : /* array */ 32 : - 33 280 : TOMMY_API void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) + 33 281 : TOMMY_API void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) 34 : { - 35 280 : tommy_array_init(&array->block); + 35 281 : tommy_array_init(&array->block); 36 : - 37 280 : array->element_size = element_size; - 38 280 : array->count = 0; - 39 280 : } + 37 281 : array->element_size = element_size; + 38 281 : array->count = 0; + 39 281 : } 40 : - 41 269 : TOMMY_API void tommy_arrayblkof_done(tommy_arrayblkof* array) + 41 270 : TOMMY_API void tommy_arrayblkof_done(tommy_arrayblkof* array) 42 : { 43 : tommy_size_t i; 44 : - 45 837 : for (i = 0; i < tommy_array_size(&array->block); ++i) + 45 838 : for (i = 0; i < tommy_array_size(&array->block); ++i) 46 568 : tommy_free(tommy_array_get(&array->block, i)); 47 : - 48 269 : tommy_array_done(&array->block); - 49 269 : } + 48 270 : tommy_array_done(&array->block); + 49 270 : } 50 : - 51 1757830 : TOMMY_API void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count) + 51 1757779 : TOMMY_API void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count) 52 : { 53 : tommy_size_t block_max; 54 : tommy_size_t block_mac; 55 : - 56 1757830 : if (array->count >= count) - 57 122868 : return; + 56 1757779 : if (array->count >= count) + 57 122817 : return; 58 1634962 : array->count = count; 59 : 60 1634962 : 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 3d0874f7..6ce461bf 100644 --- a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_size - 3171512 + 3152579 tommy_arrayblkof_ref - 4659100 + 4640116
diff --git a/cov/tommyds/tommyarrayblkof.h.func.html b/cov/tommyds/tommyarrayblkof.h.func.html index 29a7986f..6a37a67c 100644 --- a/cov/tommyds/tommyarrayblkof.h.func.html +++ b/cov/tommyds/tommyarrayblkof.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_ref - 4659100 + 4640116 tommy_arrayblkof_size - 3171512 + 3152579
diff --git a/cov/tommyds/tommyarrayblkof.h.gcov.html b/cov/tommyds/tommyarrayblkof.h.gcov.html index 551752fd..f46ba300 100644 --- a/cov/tommyds/tommyarrayblkof.h.gcov.html +++ b/cov/tommyds/tommyarrayblkof.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -148,23 +148,23 @@ 86 : * You must be sure that space for this position is already 87 : * allocated calling tommy_arrayblkof_grow(). 88 : */ - 89 4659100 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_size_t pos) + 89 4640116 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_size_t pos) 90 : { 91 : unsigned char* base; 92 : - 93 4659100 : assert(pos < array->count); + 93 4640116 : assert(pos < array->count); 94 : - 95 4659100 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); + 95 4640116 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); 96 : - 97 4659100 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; + 97 4640116 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; 98 : } 99 : 100 : /** 101 : * Gets the initialized size of the array. 102 : */ - 103 3171512 : tommy_inline tommy_size_t tommy_arrayblkof_size(tommy_arrayblkof* array) + 103 3152579 : tommy_inline tommy_size_t tommy_arrayblkof_size(tommy_arrayblkof* array) 104 : { - 105 3171512 : return array->count; + 105 3152579 : 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 77478aa4..f5e3678d 100644 --- a/cov/tommyds/tommychain.h.func-sort-c.html +++ b/cov/tommyds/tommychain.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -61,23 +61,23 @@ tommy_chain_mergesort - 2198 + 2196 tommy_chain_merge - 498587 + 498640 tommy_chain_concat - 1349545 + 1349758 tommy_chain_merge_degenerated - 1351364 + 1351313 tommy_chain_splice - 4749204 + 4745891
diff --git a/cov/tommyds/tommychain.h.func.html b/cov/tommyds/tommychain.h.func.html index 3840c72f..660d60d9 100644 --- a/cov/tommyds/tommychain.h.func.html +++ b/cov/tommyds/tommychain.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -61,23 +61,23 @@ tommy_chain_concat - 1349545 + 1349758 tommy_chain_merge - 498587 + 498640 tommy_chain_merge_degenerated - 1351364 + 1351313 tommy_chain_mergesort - 2198 + 2196 tommy_chain_splice - 4749204 + 4745891
diff --git a/cov/tommyds/tommychain.h.gcov.html b/cov/tommyds/tommychain.h.gcov.html index 165926a5..16a65703 100644 --- a/cov/tommyds/tommychain.h.gcov.html +++ b/cov/tommyds/tommychain.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 5 @@ -123,30 +123,30 @@ 61 : * \param second_head Head of the chain to splice in. 62 : * \param second_tail Tail of the chain to splice in. 63 : */ - 64 4749204 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) + 64 4745891 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) 65 : { 66 : /* set the prev list */ - 67 4749204 : first_after->prev = second_tail; - 68 4749204 : second_head->prev = first_before; + 67 4745891 : first_after->prev = second_tail; + 68 4745891 : second_head->prev = first_before; 69 : 70 : /* set the next list */ - 71 4749204 : first_before->next = second_head; - 72 4749204 : second_tail->next = first_after; - 73 4749204 : } + 71 4745891 : first_before->next = second_head; + 72 4745891 : second_tail->next = first_after; + 73 4745891 : } 74 : 75 : /** 76 : * Concatenates two chains. 77 : * \param first_tail Tail of the first chain. 78 : * \param second_head Head of the second chain. 79 : */ - 80 1349545 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) + 80 1349758 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) 81 : { 82 : /* set the prev list */ - 83 1349545 : second_head->prev = first_tail; + 83 1349758 : second_head->prev = first_tail; 84 : 85 : /* set the next list */ - 86 1349545 : first_tail->next = second_head; - 87 1349545 : } + 86 1349758 : first_tail->next = second_head; + 87 1349758 : } 88 : 89 : /** 90 : * Merges two chains. @@ -154,34 +154,34 @@ 92 : * \param second Second chain (will be empty after the merge). 93 : * \param cmp Comparison function. 94 : */ - 95 498587 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 95 498640 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 96 : { - 97 498587 : tommy_node* first_i = first->head; - 98 498587 : tommy_node* second_i = second->head; + 97 498640 : tommy_node* first_i = first->head; + 98 498640 : tommy_node* second_i = second->head; 99 : 100 : /* merge */ 101 : while (1) { - 102 10347373 : if (cmp(first_i->data, second_i->data) > 0) { - 103 4999216 : tommy_node* next = second_i->next; - 104 4999216 : if (first_i == first->head) { - 105 250012 : tommy_chain_concat(second_i, first_i); - 106 250012 : first->head = second_i; + 102 10344008 : if (cmp(first_i->data, second_i->data) > 0) { + 103 4995826 : tommy_node* next = second_i->next; + 104 4995826 : if (first_i == first->head) { + 105 249935 : tommy_chain_concat(second_i, first_i); + 106 249935 : first->head = second_i; 107 : } else { - 108 4749204 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); + 108 4745891 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); 109 : } - 110 4999216 : if (second_i == second->tail) - 111 251831 : break; - 112 4747385 : second_i = next; + 110 4995826 : if (second_i == second->tail) + 111 251490 : break; + 112 4744336 : second_i = next; 113 : } else { - 114 5348157 : if (first_i == first->tail) { - 115 246756 : tommy_chain_concat(first_i, second_i); - 116 246756 : first->tail = second->tail; - 117 246756 : break; + 114 5348182 : if (first_i == first->tail) { + 115 247150 : tommy_chain_concat(first_i, second_i); + 116 247150 : first->tail = second->tail; + 117 247150 : break; 118 : } - 119 5101401 : first_i = first_i->next; + 119 5101032 : first_i = first_i->next; 120 : } 121 : } - 122 498587 : } + 122 498640 : } 123 : 124 : /** 125 : * Merges two chains managing special degenerated cases. @@ -190,24 +190,24 @@ 128 : * \param second Second chain (will be empty after the merge). 129 : * \param cmp Comparison function. 130 : */ - 131 1351364 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 131 1351313 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 132 : { 133 : /* identify the condition first <= second */ - 134 1351364 : if (cmp(first->tail->data, second->head->data) <= 0) { - 135 497826 : tommy_chain_concat(first->tail, second->head); - 136 497826 : first->tail = second->tail; - 137 497826 : return; + 134 1351313 : if (cmp(first->tail->data, second->head->data) <= 0) { + 135 497557 : tommy_chain_concat(first->tail, second->head); + 136 497557 : first->tail = second->tail; + 137 497557 : return; 138 : } 139 : 140 : /* identify the condition second < first */ 141 : /* here we must be strict on comparison to keep the sort stable */ - 142 853538 : if (cmp(second->tail->data, first->head->data) < 0) { - 143 354951 : tommy_chain_concat(second->tail, first->head); - 144 354951 : first->head = second->head; - 145 354951 : return; + 142 853756 : if (cmp(second->tail->data, first->head->data) < 0) { + 143 355116 : tommy_chain_concat(second->tail, first->head); + 144 355116 : first->head = second->head; + 145 355116 : return; 146 : } 147 : - 148 498587 : tommy_chain_merge(first, second, cmp); + 148 498640 : tommy_chain_merge(first, second, cmp); 149 : } 150 : 151 : /** @@ -225,7 +225,7 @@ 163 : * \param chain Chain to sort. 164 : * \param cmp Comparison function. 165 : */ - 166 2198 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) + 166 2196 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) 167 : { 168 : /* 169 : * Bit buckets of chains. @@ -240,57 +240,57 @@ 178 : * It's used to know which bucket is empty or full. 179 : */ 180 : tommy_size_t counter; - 181 2198 : tommy_node* node = chain->head; - 182 2198 : tommy_node* tail = chain->tail; + 181 2196 : tommy_node* node = chain->head; + 182 2196 : tommy_node* tail = chain->tail; 183 : tommy_size_t mask; 184 : tommy_size_t i; 185 : - 186 2198 : counter = 0; - 187 1351364 : while (1) { + 186 2196 : counter = 0; + 187 1351313 : while (1) { 188 : tommy_node* next; 189 : tommy_chain* last; 190 : 191 : /* carry bit to add */ - 192 1353562 : last = &bit[TOMMY_SIZE_BIT]; - 193 1353562 : bit[TOMMY_SIZE_BIT].head = node; - 194 1353562 : bit[TOMMY_SIZE_BIT].tail = node; - 195 1353562 : next = node->next; + 192 1353509 : last = &bit[TOMMY_SIZE_BIT]; + 193 1353509 : bit[TOMMY_SIZE_BIT].head = node; + 194 1353509 : bit[TOMMY_SIZE_BIT].tail = node; + 195 1353509 : next = node->next; 196 : 197 : /* add the bit, propagating the carry */ - 198 1353562 : i = 0; - 199 1353562 : mask = counter; - 200 2698464 : while ((mask & 1) != 0) { - 201 1344902 : tommy_chain_merge_degenerated(&bit[i], last, cmp); - 202 1344902 : mask >>= 1; - 203 1344902 : last = &bit[i]; - 204 1344902 : ++i; + 198 1353509 : i = 0; + 199 1353509 : mask = counter; + 200 2698356 : while ((mask & 1) != 0) { + 201 1344847 : tommy_chain_merge_degenerated(&bit[i], last, cmp); + 202 1344847 : mask >>= 1; + 203 1344847 : last = &bit[i]; + 204 1344847 : ++i; 205 : } 206 : 207 : /* copy the carry in the first empty bit */ - 208 1353562 : bit[i] = *last; + 208 1353509 : bit[i] = *last; 209 : 210 : /* add the carry in the counter */ - 211 1353562 : ++counter; + 211 1353509 : ++counter; 212 : - 213 1353562 : if (node == tail) - 214 2198 : break; - 215 1351364 : node = next; + 213 1353509 : if (node == tail) + 214 2196 : break; + 215 1351313 : node = next; 216 : } 217 : 218 : /* merge the buckets */ - 219 2198 : i = tommy_ctz(counter); - 220 2198 : mask = counter >> i; - 221 11800 : while (mask != 1) { - 222 9602 : mask >>= 1; - 223 9602 : if (mask & 1) - 224 6462 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); + 219 2196 : i = tommy_ctz(counter); + 220 2196 : mask = counter >> i; + 221 11795 : while (mask != 1) { + 222 9599 : mask >>= 1; + 223 9599 : if (mask & 1) + 224 6466 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); 225 : else - 226 3140 : bit[i + 1] = bit[i]; - 227 9602 : ++i; + 226 3133 : bit[i + 1] = bit[i]; + 227 9599 : ++i; 228 : } 229 : - 230 2198 : *chain = bit[i]; - 231 2198 : } + 230 2196 : *chain = bit[i]; + 231 2196 : } 232 : 233 : #endif diff --git a/cov/tommyds/tommyhash.c.func-sort-c.html b/cov/tommyds/tommyhash.c.func-sort-c.html index 887b5365..c84c1192 100644 --- a/cov/tommyds/tommyhash.c.func-sort-c.html +++ b/cov/tommyds/tommyhash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -69,11 +69,11 @@ tommy_hash_u32 - 4205922 + 4205889 tommy_le_uint32_read - 12197351 + 12197247
diff --git a/cov/tommyds/tommyhash.c.func.html b/cov/tommyds/tommyhash.c.func.html index fca233d6..240cac72 100644 --- a/cov/tommyds/tommyhash.c.func.html +++ b/cov/tommyds/tommyhash.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -61,7 +61,7 @@ tommy_hash_u32 - 4205922 + 4205889 tommy_hash_u64 @@ -69,7 +69,7 @@ tommy_le_uint32_read - 12197351 + 12197247 tommy_strhash_u32 diff --git a/cov/tommyds/tommyhash.c.gcov.html b/cov/tommyds/tommyhash.c.gcov.html index be57b01f..2bf99ba0 100644 --- a/cov/tommyds/tommyhash.c.gcov.html +++ b/cov/tommyds/tommyhash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 4 @@ -110,15 +110,15 @@ 48 : } 49 : #endif 50 : - 51 12197351 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) + 51 12197247 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) 52 : { 53 : tommy_uint32_t v; - 54 12197351 : memcpy(&v, ptr, sizeof(v)); + 54 12197247 : memcpy(&v, ptr, sizeof(v)); 55 : #if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) || \ 56 : (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 57 : v = tommy_swap32(v); 58 : #endif - 59 12197351 : return v; + 59 12197247 : return v; 60 : } 61 : 62 : #define tommy_rot(x, k) \ @@ -145,53 +145,53 @@ 83 : c ^= b; c -= tommy_rot(b, 24); \ 84 : } while (0) 85 : - 86 4205922 : TOMMY_API tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) + 86 4205889 : TOMMY_API tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) 87 : { - 88 4205922 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); + 88 4205889 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); 89 : tommy_uint32_t a, b, c; 90 : - 91 4205922 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; + 91 4205889 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; 92 : - 93 6400524 : while (key_len > 12) { - 94 2194602 : a += tommy_le_uint32_read(key + 0); - 95 2194602 : b += tommy_le_uint32_read(key + 4); - 96 2194602 : c += tommy_le_uint32_read(key + 8); + 93 6400465 : while (key_len > 12) { + 94 2194576 : a += tommy_le_uint32_read(key + 0); + 95 2194576 : b += tommy_le_uint32_read(key + 4); + 96 2194576 : c += tommy_le_uint32_read(key + 8); 97 : - 98 2194602 : tommy_mix(a, b, c); + 98 2194576 : tommy_mix(a, b, c); 99 : - 100 2194602 : key_len -= 12; - 101 2194602 : key += 12; + 100 2194576 : key_len -= 12; + 101 2194576 : key += 12; 102 : } 103 : - 104 4205922 : switch (key_len) { + 104 4205889 : switch (key_len) { 105 1 : case 0 : 106 1 : return c; /* used only when called with a zero length */ - 107 214636 : case 12 : - 108 214636 : c += tommy_le_uint32_read(key + 8); - 109 214636 : b += tommy_le_uint32_read(key + 4); - 110 214636 : a += tommy_le_uint32_read(key + 0); - 111 214636 : break; - 112 224879 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; /* fallthrough */ - 113 662895 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; /* fallthrough */ - 114 1097631 : case 9 : c += key[8]; /* fallthrough */ - 115 1523522 : case 8 : - 116 1523522 : b += tommy_le_uint32_read(key + 4); - 117 1523522 : a += tommy_le_uint32_read(key + 0); - 118 1523522 : break; - 119 428407 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; /* fallthrough */ - 120 842490 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; /* fallthrough */ - 121 1274225 : case 5 : b += key[4]; /* fallthrough */ - 122 1721682 : case 4 : - 123 1721682 : a += tommy_le_uint32_read(key + 0); - 124 1721682 : break; - 125 313312 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; /* fallthrough */ - 126 528569 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; /* fallthrough */ - 127 746081 : case 1 : a += key[0]; /* fallthrough */ + 107 214618 : case 12 : + 108 214618 : c += tommy_le_uint32_read(key + 8); + 109 214618 : b += tommy_le_uint32_read(key + 4); + 110 214618 : a += tommy_le_uint32_read(key + 0); + 111 214618 : break; + 112 224880 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; /* fallthrough */ + 113 662911 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; /* fallthrough */ + 114 1097644 : case 9 : c += key[8]; /* fallthrough */ + 115 1523549 : case 8 : + 116 1523549 : b += tommy_le_uint32_read(key + 4); + 117 1523549 : a += tommy_le_uint32_read(key + 0); + 118 1523549 : break; + 119 428404 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; /* fallthrough */ + 120 842492 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; /* fallthrough */ + 121 1274173 : case 5 : b += key[4]; /* fallthrough */ + 122 1721656 : case 4 : + 123 1721656 : a += tommy_le_uint32_read(key + 0); + 124 1721656 : break; + 125 313308 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; /* fallthrough */ + 126 528545 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; /* fallthrough */ + 127 746065 : case 1 : a += key[0]; /* fallthrough */ 128 : } 129 : - 130 4205921 : tommy_final(a, b, c); + 130 4205888 : tommy_final(a, b, c); 131 : - 132 4205921 : return c; + 132 4205888 : return c; 133 : } 134 : 135 19 : TOMMY_API 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 9177d23f..325e12f7 100644 --- a/cov/tommyds/tommyhash.h.func-sort-c.html +++ b/cov/tommyds/tommyhash.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u64 - 5292402 + 5276850 tommy_inthash_u32 - 19170915 + 19171890
diff --git a/cov/tommyds/tommyhash.h.func.html b/cov/tommyds/tommyhash.h.func.html index 80297889..dd0802d6 100644 --- a/cov/tommyds/tommyhash.h.func.html +++ b/cov/tommyds/tommyhash.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u32 - 19170915 + 19171890 tommy_inthash_u64 - 5292402 + 5276850
diff --git a/cov/tommyds/tommyhash.h.gcov.html b/cov/tommyds/tommyhash.h.gcov.html index 68d6e103..7d72ea35 100644 --- a/cov/tommyds/tommyhash.h.gcov.html +++ b/cov/tommyds/tommyhash.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -162,17 +162,17 @@ 100 : * Implementation of the Robert Jenkins "4-byte Integer Hashing", 101 : * from http://burtleburtle.net/bob/hash/integer.html 102 : */ - 103 19170915 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) + 103 19171890 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) 104 : { - 105 19170915 : key -= key << 6; - 106 19170915 : key ^= key >> 17; - 107 19170915 : key -= key << 9; - 108 19170915 : key ^= key << 4; - 109 19170915 : key -= key << 3; - 110 19170915 : key ^= key << 10; - 111 19170915 : key ^= key >> 15; + 105 19171890 : key -= key << 6; + 106 19171890 : key ^= key >> 17; + 107 19171890 : key -= key << 9; + 108 19171890 : key ^= key << 4; + 109 19171890 : key -= key << 3; + 110 19171890 : key ^= key << 10; + 111 19171890 : key ^= key >> 15; 112 : - 113 19170915 : return key; + 113 19171890 : return key; 114 : } 115 : 116 : /** @@ -180,17 +180,17 @@ 118 : * Implementation of the Thomas Wang "Integer Hash Function", 119 : * from http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm 120 : */ - 121 5292402 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) + 121 5276850 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) 122 : { - 123 5292402 : key = ~key + (key << 21); - 124 5292402 : key = key ^ (key >> 24); - 125 5292402 : key = key + (key << 3) + (key << 8); - 126 5292402 : key = key ^ (key >> 14); - 127 5292402 : key = key + (key << 2) + (key << 4); - 128 5292402 : key = key ^ (key >> 28); - 129 5292402 : key = key + (key << 31); + 123 5276850 : key = ~key + (key << 21); + 124 5276850 : key = key ^ (key >> 24); + 125 5276850 : key = key + (key << 3) + (key << 8); + 126 5276850 : key = key ^ (key >> 14); + 127 5276850 : key = key + (key << 2) + (key << 4); + 128 5276850 : key = key ^ (key >> 28); + 129 5276850 : key = key + (key << 31); 130 : - 131 5292402 : return key; + 131 5276850 : return key; 132 : } 133 : 134 : #endif diff --git a/cov/tommyds/tommyhashdyn.c.func-sort-c.html b/cov/tommyds/tommyhashdyn.c.func-sort-c.html index 4be71c95..ab483979 100644 --- a/cov/tommyds/tommyhashdyn.c.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -73,39 +73,39 @@ tommy_hashdyn_foreach - 275 + 276 tommy_hashdyn_to_list - 421 + 420 tommy_hashdyn_done - 9247 + 9299 tommy_hashdyn_init - 9581 + 9633 tommy_hashdyn_resize - 43338 + 43341 tommy_hashdyn_remove_existing - 280123 + 280572 hashdyn_shrink_step - 280251 + 280700 hashdyn_grow_step - 13595041 + 13595618 tommy_hashdyn_insert - 13595041 + 13595618
diff --git a/cov/tommyds/tommyhashdyn.c.func.html b/cov/tommyds/tommyhashdyn.c.func.html index a6284c18..00462fa3 100644 --- a/cov/tommyds/tommyhashdyn.c.func.html +++ b/cov/tommyds/tommyhashdyn.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -61,19 +61,19 @@ hashdyn_grow_step - 13595041 + 13595618 hashdyn_shrink_step - 280251 + 280700 tommy_hashdyn_done - 9247 + 9299 tommy_hashdyn_foreach - 275 + 276 tommy_hashdyn_foreach_arg @@ -81,11 +81,11 @@ tommy_hashdyn_init - 9581 + 9633 tommy_hashdyn_insert - 13595041 + 13595618 tommy_hashdyn_memory_usage @@ -97,15 +97,15 @@ tommy_hashdyn_remove_existing - 280123 + 280572 tommy_hashdyn_resize - 43338 + 43341 tommy_hashdyn_to_list - 421 + 420
diff --git a/cov/tommyds/tommyhashdyn.c.gcov.html b/cov/tommyds/tommyhashdyn.c.gcov.html index 7b23c703..8510055e 100644 --- a/cov/tommyds/tommyhashdyn.c.gcov.html +++ b/cov/tommyds/tommyhashdyn.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -93,26 +93,26 @@ 31 : /******************************************************************************/ 32 : /* hashdyn */ 33 : - 34 9581 : TOMMY_API void tommy_hashdyn_init(tommy_hashdyn* hashdyn) + 34 9633 : TOMMY_API void tommy_hashdyn_init(tommy_hashdyn* hashdyn) 35 : { 36 : /* fixed initial size */ - 37 9581 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; - 38 9581 : hashdyn->bucket_max = (tommy_size_t)1 << hashdyn->bucket_bit; - 39 9581 : hashdyn->bucket_mask = hashdyn->bucket_max - 1; - 40 9581 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); + 37 9633 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; + 38 9633 : hashdyn->bucket_max = (tommy_size_t)1 << hashdyn->bucket_bit; + 39 9633 : hashdyn->bucket_mask = hashdyn->bucket_max - 1; + 40 9633 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); 41 : - 42 9581 : hashdyn->count = 0; - 43 9581 : } + 42 9633 : hashdyn->count = 0; + 43 9633 : } 44 : - 45 9247 : TOMMY_API void tommy_hashdyn_done(tommy_hashdyn* hashdyn) + 45 9299 : TOMMY_API void tommy_hashdyn_done(tommy_hashdyn* hashdyn) 46 : { - 47 9247 : tommy_free(hashdyn->bucket); - 48 9247 : } + 47 9299 : tommy_free(hashdyn->bucket); + 48 9299 : } 49 : 50 : /** 51 : * Resize the bucket vector. 52 : */ - 53 43338 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_uint_t new_bucket_bit) + 53 43341 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_uint_t new_bucket_bit) 54 : { 55 : tommy_size_t bucket_bit; 56 : tommy_size_t bucket_max; @@ -120,38 +120,38 @@ 58 : tommy_size_t new_bucket_mask; 59 : tommy_hashdyn_node** new_bucket; 60 : - 61 43338 : bucket_bit = hashdyn->bucket_bit; - 62 43338 : bucket_max = hashdyn->bucket_max; + 61 43341 : bucket_bit = hashdyn->bucket_bit; + 62 43341 : bucket_max = hashdyn->bucket_max; 63 : - 64 43338 : new_bucket_max = (tommy_size_t)1 << new_bucket_bit; - 65 43338 : new_bucket_mask = new_bucket_max - 1; + 64 43341 : new_bucket_max = (tommy_size_t)1 << new_bucket_bit; + 65 43341 : new_bucket_mask = new_bucket_max - 1; 66 : 67 : /* allocate the new vector using malloc() and not calloc() */ 68 : /* because data is fully initialized in the update process */ - 69 43338 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); + 69 43341 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); 70 : 71 : /* reinsert all the elements */ - 72 43338 : if (new_bucket_bit > bucket_bit) { + 72 43341 : if (new_bucket_bit > bucket_bit) { 73 : tommy_size_t i; 74 : 75 : /* grow */ - 76 32995971 : for (i = 0; i < bucket_max; ++i) { + 76 32996166 : for (i = 0; i < bucket_max; ++i) { 77 : tommy_hashdyn_node* j; 78 : 79 : /* setup the new two buckets */ - 80 32952688 : new_bucket[i] = 0; - 81 32952688 : new_bucket[i + bucket_max] = 0; + 80 32952880 : new_bucket[i] = 0; + 81 32952880 : new_bucket[i + bucket_max] = 0; 82 : 83 : /* reinsert the bucket */ - 84 32952688 : j = hashdyn->bucket[i]; - 85 49429032 : while (j) { - 86 16476344 : tommy_hashdyn_node* j_next = j->next; - 87 16476344 : tommy_size_t pos = j->index & new_bucket_mask; - 88 16476344 : if (new_bucket[pos]) - 89 1933530 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); + 84 32952880 : j = hashdyn->bucket[i]; + 85 49429320 : while (j) { + 86 16476440 : tommy_hashdyn_node* j_next = j->next; + 87 16476440 : tommy_size_t pos = j->index & new_bucket_mask; + 88 16476440 : if (new_bucket[pos]) + 89 1945137 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); 90 : else - 91 14542814 : tommy_list_insert_first(&new_bucket[pos], j); - 92 16476344 : j = j_next; + 91 14531303 : tommy_list_insert_first(&new_bucket[pos], j); + 92 16476440 : j = j_next; 93 : } 94 : } 95 : } else { @@ -167,59 +167,59 @@ 105 : } 106 : } 107 : - 108 43338 : tommy_free(hashdyn->bucket); + 108 43341 : tommy_free(hashdyn->bucket); 109 : 110 : /* setup */ - 111 43338 : hashdyn->bucket_bit = new_bucket_bit; - 112 43338 : hashdyn->bucket_max = new_bucket_max; - 113 43338 : hashdyn->bucket_mask = new_bucket_mask; - 114 43338 : hashdyn->bucket = new_bucket; - 115 43338 : } + 111 43341 : hashdyn->bucket_bit = new_bucket_bit; + 112 43341 : hashdyn->bucket_max = new_bucket_max; + 113 43341 : hashdyn->bucket_mask = new_bucket_mask; + 114 43341 : hashdyn->bucket = new_bucket; + 115 43341 : } 116 : 117 : /** 118 : * Grow. 119 : */ - 120 13595041 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) + 120 13595618 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) 121 : { 122 : /* grow if more than 50% full */ - 123 13595041 : if (hashdyn->count >= hashdyn->bucket_max / 2) - 124 43283 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); - 125 13595041 : } + 123 13595618 : if (hashdyn->count >= hashdyn->bucket_max / 2) + 124 43286 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); + 125 13595618 : } 126 : 127 : /** 128 : * Shrink. 129 : */ - 130 280251 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) + 130 280700 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) 131 : { 132 : /* shrink if less than 12.5% full */ - 133 280251 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) + 133 280700 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) 134 55 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1); - 135 280251 : } + 135 280700 : } 136 : - 137 13595041 : TOMMY_API void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) + 137 13595618 : TOMMY_API void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) 138 : { - 139 13595041 : tommy_size_t pos = hash & hashdyn->bucket_mask; + 139 13595618 : tommy_size_t pos = hash & hashdyn->bucket_mask; 140 : - 141 13595041 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); + 141 13595618 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); 142 : - 143 13595041 : node->index = hash; + 143 13595618 : node->index = hash; 144 : - 145 13595041 : ++hashdyn->count; + 145 13595618 : ++hashdyn->count; 146 : - 147 13595041 : hashdyn_grow_step(hashdyn); - 148 13595041 : } + 147 13595618 : hashdyn_grow_step(hashdyn); + 148 13595618 : } 149 : - 150 280123 : TOMMY_API void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) + 150 280572 : TOMMY_API void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) 151 : { - 152 280123 : tommy_size_t pos = node->index & hashdyn->bucket_mask; + 152 280572 : tommy_size_t pos = node->index & hashdyn->bucket_mask; 153 : - 154 280123 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); + 154 280572 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); 155 : - 156 280123 : --hashdyn->count; + 156 280572 : --hashdyn->count; 157 : - 158 280123 : hashdyn_shrink_step(hashdyn); + 158 280572 : hashdyn_shrink_step(hashdyn); 159 : - 160 280123 : return node->data; + 160 280572 : return node->data; 161 : } 162 : 163 256 : TOMMY_API void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) @@ -244,22 +244,22 @@ 182 128 : return 0; 183 : } 184 : - 185 275 : TOMMY_API void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) + 185 276 : TOMMY_API void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) 186 : { - 187 275 : tommy_size_t bucket_max = hashdyn->bucket_max; - 188 275 : tommy_hashdyn_node** bucket = hashdyn->bucket; + 187 276 : tommy_size_t bucket_max = hashdyn->bucket_max; + 188 276 : tommy_hashdyn_node** bucket = hashdyn->bucket; 189 : tommy_size_t pos; 190 : - 191 5813251 : for (pos = 0; pos < bucket_max; ++pos) { - 192 5812976 : tommy_hashdyn_node* node = bucket[pos]; + 191 5813268 : for (pos = 0; pos < bucket_max; ++pos) { + 192 5812992 : tommy_hashdyn_node* node = bucket[pos]; 193 : - 194 7674048 : while (node) { - 195 1861072 : void* data = node->data; - 196 1861072 : node = node->next; - 197 1861072 : func(data); + 194 7674121 : while (node) { + 195 1861129 : void* data = node->data; + 196 1861129 : node = node->next; + 197 1861129 : func(data); 198 : } 199 : } - 200 275 : } + 200 276 : } 201 : 202 4 : TOMMY_API void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) 203 : { @@ -321,27 +321,27 @@ 259 : * \param hashdyn The dynamic hashtable to drain 260 : * \param list The list that will receive all the elements 261 : */ - 262 421 : TOMMY_API void tommy_hashdyn_to_list(tommy_hashdyn* hashdyn, tommy_list* list) + 262 420 : TOMMY_API void tommy_hashdyn_to_list(tommy_hashdyn* hashdyn, tommy_list* list) 263 : { - 264 421 : tommy_size_t bucket_max = hashdyn->bucket_max; - 265 421 : tommy_hashdyn_node** bucket = hashdyn->bucket; + 264 420 : tommy_size_t bucket_max = hashdyn->bucket_max; + 265 420 : tommy_hashdyn_node** bucket = hashdyn->bucket; 266 : tommy_size_t pos; 267 : 268 : /* move everything to the list */ - 269 7157 : for (pos = 0; pos < bucket_max; ++pos) { - 270 6736 : tommy_hashdyn_node* node = bucket[pos]; + 269 7140 : for (pos = 0; pos < bucket_max; ++pos) { + 270 6720 : tommy_hashdyn_node* node = bucket[pos]; 271 : - 272 7492 : while (node) { - 273 756 : tommy_node* node_next = node->next; - 274 756 : tommy_list_insert_tail(list, node, node->data); - 275 756 : node = node_next; + 272 7436 : while (node) { + 273 716 : tommy_node* node_next = node->next; + 274 716 : tommy_list_insert_tail(list, node, node->data); + 275 716 : node = node_next; 276 : } 277 : } 278 : 279 : /* clear all */ - 280 421 : memset(hashdyn->bucket, 0, hashdyn->bucket_max * sizeof(tommy_hashdyn_node*)); - 281 421 : hashdyn->count = 0; - 282 421 : } + 280 420 : memset(hashdyn->bucket, 0, hashdyn->bucket_max * sizeof(tommy_hashdyn_node*)); + 281 420 : hashdyn->count = 0; + 282 420 : } diff --git a/cov/tommyds/tommyhashdyn.h.func-sort-c.html b/cov/tommyds/tommyhashdyn.h.func-sort-c.html index 70e1c5bf..35bd3f06 100644 --- a/cov/tommyds/tommyhashdyn.h.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -61,15 +61,15 @@ tommy_hashdyn_count - 424 + 423 tommy_hashdyn_search - 3175958 + 3176368 tommy_hashdyn_bucket - 3248010 + 3232326
diff --git a/cov/tommyds/tommyhashdyn.h.func.html b/cov/tommyds/tommyhashdyn.h.func.html index d7632067..63206825 100644 --- a/cov/tommyds/tommyhashdyn.h.func.html +++ b/cov/tommyds/tommyhashdyn.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -61,15 +61,15 @@ tommy_hashdyn_bucket - 3248010 + 3232326 tommy_hashdyn_count - 424 + 423 tommy_hashdyn_search - 3175958 + 3176368
diff --git a/cov/tommyds/tommyhashdyn.h.gcov.html b/cov/tommyds/tommyhashdyn.h.gcov.html index 54b99c47..0226753f 100644 --- a/cov/tommyds/tommyhashdyn.h.gcov.html +++ b/cov/tommyds/tommyhashdyn.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -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 3248010 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) + 208 3232326 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) 209 : { - 210 3248010 : return hashdyn->bucket[hash & hashdyn->bucket_mask]; + 210 3232326 : 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 3175958 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) + 223 3176368 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) 224 : { - 225 3175958 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); + 225 3176368 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); 226 : - 227 3864355 : while (i) { + 227 3868088 : while (i) { 228 : /* we first check if the hash matches, as in the same bucket we may have multiple hash values */ - 229 1917649 : if (i->index == hash && cmp(cmp_arg, i->data) == 0) - 230 1229252 : return i->data; - 231 688397 : i = i->next; + 229 1923487 : if (i->index == hash && cmp(cmp_arg, i->data) == 0) + 230 1231767 : return i->data; + 231 691720 : i = i->next; 232 : } - 233 1946706 : return 0; + 233 1944601 : return 0; 234 : } 235 : 236 : /** @@ -343,9 +343,9 @@ 281 : /** 282 : * Gets the number of elements. 283 : */ - 284 424 : tommy_inline tommy_size_t tommy_hashdyn_count(tommy_hashdyn* hashdyn) + 284 423 : tommy_inline tommy_size_t tommy_hashdyn_count(tommy_hashdyn* hashdyn) 285 : { - 286 424 : return hashdyn->count; + 286 423 : return hashdyn->count; 287 : } 288 : 289 : /** diff --git a/cov/tommyds/tommylist.c.func-sort-c.html b/cov/tommyds/tommylist.c.func-sort-c.html index 9c7ad4b0..9a255f4a 100644 --- a/cov/tommyds/tommylist.c.func-sort-c.html +++ b/cov/tommyds/tommylist.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_list_set - 2198 + 2196 tommy_list_sort - 3052 + 3051
diff --git a/cov/tommyds/tommylist.c.func.html b/cov/tommyds/tommylist.c.func.html index 99238bf2..b59b484b 100644 --- a/cov/tommyds/tommylist.c.func.html +++ b/cov/tommyds/tommylist.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -61,11 +61,11 @@ tommy_list_set - 2198 + 2196 tommy_list_sort - 3052 + 3051
diff --git a/cov/tommyds/tommylist.c.gcov.html b/cov/tommyds/tommylist.c.gcov.html index c036b347..bae8f6cb 100644 --- a/cov/tommyds/tommylist.c.gcov.html +++ b/cov/tommyds/tommylist.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 2 @@ -93,31 +93,31 @@ 31 : /** \internal 32 : * Setup a list. 33 : */ - 34 2198 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail) + 34 2196 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail) 35 : { - 36 2198 : head->prev = tail; - 37 2198 : tail->next = 0; - 38 2198 : *list = head; - 39 2198 : } + 36 2196 : head->prev = tail; + 37 2196 : tail->next = 0; + 38 2196 : *list = head; + 39 2196 : } 40 : - 41 3052 : TOMMY_API void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) + 41 3051 : TOMMY_API void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) 42 : { 43 : tommy_chain chain; 44 : tommy_node* head; 45 : - 46 3052 : if (tommy_list_empty(list)) - 47 854 : return; + 46 3051 : if (tommy_list_empty(list)) + 47 855 : return; 48 : - 49 2198 : head = tommy_list_head(list); + 49 2196 : head = tommy_list_head(list); 50 : 51 : /* create a chain from the list */ - 52 2198 : chain.head = head; - 53 2198 : chain.tail = head->prev; + 52 2196 : chain.head = head; + 53 2196 : chain.tail = head->prev; 54 : - 55 2198 : tommy_chain_mergesort(&chain, cmp); + 55 2196 : tommy_chain_mergesort(&chain, cmp); 56 : 57 : /* restore the list */ - 58 2198 : tommy_list_set(list, chain.head, chain.tail); + 58 2196 : tommy_list_set(list, chain.head, chain.tail); 59 : } 60 : diff --git a/cov/tommyds/tommylist.h.func-sort-c.html b/cov/tommyds/tommylist.h.func-sort-c.html index 22e8ad7a..97ad0d68 100644 --- a/cov/tommyds/tommylist.h.func-sort-c.html +++ b/cov/tommyds/tommylist.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -73,15 +73,15 @@ tommy_list_empty - 7447 + 7444 tommy_list_foreach - 14796 + 14846 tommy_list_init - 18934 + 18984 tommy_list_concat @@ -89,23 +89,23 @@ tommy_list_remove_existing - 336440 + 336876 tommy_list_insert_tail_not_empty - 11532222 + 11558516 tommy_list_insert_tail - 19084521 + 19085101 tommy_list_insert_first - 24028643 + 24003025 tommy_list_head - 27439506 + 27440663
diff --git a/cov/tommyds/tommylist.h.func.html b/cov/tommyds/tommylist.h.func.html index 42cf83a0..6193477a 100644 --- a/cov/tommyds/tommylist.h.func.html +++ b/cov/tommyds/tommylist.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -69,11 +69,11 @@ tommy_list_empty - 7447 + 7444 tommy_list_foreach - 14796 + 14846 tommy_list_foreach_arg @@ -81,27 +81,27 @@ tommy_list_head - 27439506 + 27440663 tommy_list_init - 18934 + 18984 tommy_list_insert_first - 24028643 + 24003025 tommy_list_insert_tail - 19084521 + 19085101 tommy_list_insert_tail_not_empty - 11532222 + 11558516 tommy_list_remove_existing - 336440 + 336876 tommy_list_tail diff --git a/cov/tommyds/tommylist.h.gcov.html b/cov/tommyds/tommylist.h.gcov.html index 23f948b5..40632480 100644 --- a/cov/tommyds/tommylist.h.gcov.html +++ b/cov/tommyds/tommylist.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 12 @@ -173,18 +173,18 @@ 111 : * Initializes the list. 112 : * The list is completely inplace, so it doesn't need to be deinitialized. 113 : */ - 114 18934 : tommy_inline void tommy_list_init(tommy_list* list) + 114 18984 : tommy_inline void tommy_list_init(tommy_list* list) 115 : { - 116 18934 : *list = 0; - 117 18934 : } + 116 18984 : *list = 0; + 117 18984 : } 118 : 119 : /** 120 : * Gets the head of the list. 121 : * \return The head node. For empty lists 0 is returned. 122 : */ - 123 27439506 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) + 123 27440663 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) 124 : { - 125 27439506 : return *list; + 125 27440663 : 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 24028643 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) + 147 24003025 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) 148 : { 149 : /* one element "circular" prev list */ - 150 24028643 : node->prev = node; + 150 24003025 : node->prev = node; 151 : 152 : /* one element "0 terminated" next list */ - 153 24028643 : node->next = 0; + 153 24003025 : node->next = 0; 154 : - 155 24028643 : *list = node; - 156 24028643 : } + 155 24003025 : *list = node; + 156 24003025 : } 157 : 158 : /** \internal 159 : * Inserts an element at the head of a non-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 11532222 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) + 184 11558516 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) 185 : { 186 : /* insert in the "circular" prev list */ - 187 11532222 : node->prev = head->prev; - 188 11532222 : head->prev = node; + 187 11558516 : node->prev = head->prev; + 188 11558516 : head->prev = node; 189 : 190 : /* insert in the "0 terminated" next list */ - 191 11532222 : node->next = 0; - 192 11532222 : node->prev->next = node; - 193 11532222 : } + 191 11558516 : node->next = 0; + 192 11558516 : node->prev->next = node; + 193 11558516 : } 194 : 195 : /** 196 : * Inserts an element at the head of a list. @@ -278,17 +278,17 @@ 216 : * \param node The node to insert. 217 : * \param data The object containing the node. It's used to set the tommy_node::data field of the node. 218 : */ - 219 19084521 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) + 219 19085101 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) 220 : { - 221 19084521 : tommy_node* head = tommy_list_head(list); + 221 19085101 : tommy_node* head = tommy_list_head(list); 222 : - 223 19084521 : if (head) - 224 9598692 : tommy_list_insert_tail_not_empty(head, node); + 223 19085101 : if (head) + 224 9613379 : tommy_list_insert_tail_not_empty(head, node); 225 : else - 226 9485829 : tommy_list_insert_first(list, node); + 226 9471722 : tommy_list_insert_first(list, node); 227 : - 228 19084521 : node->data = data; - 229 19084521 : } + 228 19085101 : node->data = data; + 229 19085101 : } 230 : 231 : /** 232 : * Removes an element from the list. @@ -299,23 +299,23 @@ 237 : * \param node The node to remove. The node must be in the list. 238 : * \return The tommy_node::data field of the node removed. 239 : */ - 240 336440 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) + 240 336876 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) 241 : { - 242 336440 : tommy_node* head = tommy_list_head(list); + 242 336876 : tommy_node* head = tommy_list_head(list); 243 : 244 : /* remove from the "circular" prev list */ - 245 336440 : if (node->next) - 246 114378 : node->next->prev = node->prev; + 245 336876 : if (node->next) + 246 114609 : node->next->prev = node->prev; 247 : else - 248 222062 : head->prev = node->prev; /* the last */ + 248 222267 : head->prev = node->prev; /* the last */ 249 : 250 : /* remove from the "0 terminated" next list */ - 251 336440 : if (head == node) - 252 238235 : *list = node->next; /* the new head, in case 0 */ + 251 336876 : if (head == node) + 252 238682 : *list = node->next; /* the new head, in case 0 */ 253 : else - 254 98205 : node->prev->next = node->next; + 254 98194 : node->prev->next = node->next; 255 : - 256 336440 : return node->data; + 256 336876 : return node->data; 257 : } 258 : 259 : /** @@ -334,24 +334,24 @@ 272 : /* if the second is empty, nothing to do */ 273 79280 : second_head = tommy_list_head(second); 274 79280 : if (second_head == 0) - 275 69889 : return; + 275 70071 : return; 276 : 277 : /* if the first is empty, copy the second */ - 278 9391 : first_head = tommy_list_head(first); - 279 9391 : if (first_head == 0) { - 280 8317 : *first = *second; - 281 8317 : return; + 278 9209 : first_head = tommy_list_head(first); + 279 9209 : if (first_head == 0) { + 280 8162 : *first = *second; + 281 8162 : return; 282 : } 283 : 284 : /* tail of the first list */ - 285 1074 : first_tail = first_head->prev; + 285 1047 : first_tail = first_head->prev; 286 : 287 : /* set the "circular" prev list */ - 288 1074 : first_head->prev = second_head->prev; - 289 1074 : second_head->prev = first_tail; + 288 1047 : first_head->prev = second_head->prev; + 289 1047 : second_head->prev = first_tail; 290 : 291 : /* set the "0 terminated" next list */ - 292 1074 : first_tail->next = second_head; + 292 1047 : first_tail->next = second_head; 293 : } 294 : 295 : /** @@ -367,9 +367,9 @@ 305 : * Checks if empty. 306 : * \return If the list is empty. 307 : */ - 308 7447 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) + 308 7444 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) 309 : { - 310 7447 : return tommy_list_head(list) == 0; + 310 7444 : return tommy_list_head(list) == 0; 311 : } 312 : 313 : /** @@ -417,16 +417,16 @@ 355 : * tommy_list_foreach(&list, free); 356 : * \endcode 357 : */ - 358 14796 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) + 358 14846 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) 359 : { - 360 14796 : tommy_node* node = tommy_list_head(list); + 360 14846 : tommy_node* node = tommy_list_head(list); 361 : - 362 4108729 : while (node) { - 363 4093933 : void* data = node->data; - 364 4093933 : node = node->next; - 365 4093933 : func(data); + 362 4108770 : while (node) { + 363 4093924 : void* data = node->data; + 364 4093924 : node = node->next; + 365 4093924 : func(data); 366 : } - 367 14796 : } + 367 14846 : } 368 : 369 : /** 370 : * Calls the specified function with an argument for each element in the list. diff --git a/cov/tommyds/tommytree.c.func-sort-c.html b/cov/tommyds/tommytree.c.func-sort-c.html index a21af37e..d6986d3b 100644 --- a/cov/tommyds/tommytree.c.func-sort-c.html +++ b/cov/tommyds/tommytree.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 19 @@ -73,67 +73,67 @@ tommy_tree_foreach - 1604 + 1614 tommy_tree_init - 3327 + 3347 tommy_tree_foreach_arg - 6241 + 6229 tommy_tree_remove - 76114 + 76084 tommy_tree_move_right - 175888 + 175516 tommy_tree_rotate_right - 184746 + 183361 tommy_tree_remove_node - 754198 + 752904 tommy_tree_foreach_node - 7539256 + 7539142 tommy_tree_insert - 7704289 + 7704209 tommy_tree_rotate_left - 7711736 + 7710097 tommy_tree_search_compare - 16671172 + 16616314 tommy_tree_foreach_arg_node - 27357453 + 27289637 tommy_tree_insert_node - 98881758 + 98880309 tommy_tree_balance - 107748419 + 107739396 tommy_tree_delta - 115475682 + 115464816 tommy_tree_search_node - 183509139 + 182914273
diff --git a/cov/tommyds/tommytree.c.func.html b/cov/tommyds/tommytree.c.func.html index fa6b3f2e..a7044193 100644 --- a/cov/tommyds/tommytree.c.func.html +++ b/cov/tommyds/tommytree.c.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 19 @@ -61,39 +61,39 @@ tommy_tree_balance - 107748419 + 107739396 tommy_tree_delta - 115475682 + 115464816 tommy_tree_foreach - 1604 + 1614 tommy_tree_foreach_arg - 6241 + 6229 tommy_tree_foreach_arg_node - 27357453 + 27289637 tommy_tree_foreach_node - 7539256 + 7539142 tommy_tree_init - 3327 + 3347 tommy_tree_insert - 7704289 + 7704209 tommy_tree_insert_node - 98881758 + 98880309 tommy_tree_memory_usage @@ -101,11 +101,11 @@ tommy_tree_move_right - 175888 + 175516 tommy_tree_remove - 76114 + 76084 tommy_tree_remove_existing @@ -113,15 +113,15 @@ tommy_tree_remove_node - 754198 + 752904 tommy_tree_rotate_left - 7711736 + 7710097 tommy_tree_rotate_right - 184746 + 183361 tommy_tree_search @@ -129,11 +129,11 @@ tommy_tree_search_compare - 16671172 + 16616314 tommy_tree_search_node - 183509139 + 182914273
diff --git a/cov/tommyds/tommytree.c.gcov.html b/cov/tommyds/tommytree.c.gcov.html index 3839bed2..d1d9f4bc 100644 --- a/cov/tommyds/tommytree.c.gcov.html +++ b/cov/tommyds/tommytree.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 19 @@ -94,104 +94,104 @@ 32 : /******************************************************************************/ 33 : /* tree */ 34 : - 35 3327 : TOMMY_API void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) + 35 3347 : TOMMY_API void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) 36 : { - 37 3327 : tree->root = 0; - 38 3327 : tree->count = 0; - 39 3327 : tree->cmp = cmp; - 40 3327 : } + 37 3347 : tree->root = 0; + 38 3347 : tree->count = 0; + 39 3347 : tree->cmp = cmp; + 40 3347 : } 41 : - 42 115475682 : static tommy_ssize_t tommy_tree_delta(tommy_tree_node* root) + 42 115464816 : static tommy_ssize_t tommy_tree_delta(tommy_tree_node* root) 43 : { - 44 115475682 : tommy_ssize_t left_height = root->prev ? root->prev->index : 0; - 45 115475682 : tommy_ssize_t right_height = root->next ? root->next->index : 0; + 44 115464816 : tommy_ssize_t left_height = root->prev ? root->prev->index : 0; + 45 115464816 : tommy_ssize_t right_height = root->next ? root->next->index : 0; 46 : - 47 115475682 : return left_height - right_height; + 47 115464816 : return left_height - right_height; 48 : } 49 : 50 : /* AVL tree operations */ 51 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*); 52 : - 53 7711736 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) + 53 7710097 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) 54 : { - 55 7711736 : tommy_tree_node* next = root->next; + 55 7710097 : tommy_tree_node* next = root->next; 56 : - 57 7711736 : root->next = next->prev; + 57 7710097 : root->next = next->prev; 58 : - 59 7711736 : next->prev = tommy_tree_balance(root); + 59 7710097 : next->prev = tommy_tree_balance(root); 60 : - 61 7711736 : return tommy_tree_balance(next); + 61 7710097 : return tommy_tree_balance(next); 62 : } 63 : - 64 184746 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) + 64 183361 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) 65 : { - 66 184746 : tommy_tree_node* prev = root->prev; + 66 183361 : tommy_tree_node* prev = root->prev; 67 : - 68 184746 : root->prev = prev->next; + 68 183361 : root->prev = prev->next; 69 : - 70 184746 : prev->next = tommy_tree_balance(root); + 70 183361 : prev->next = tommy_tree_balance(root); 71 : - 72 184746 : return tommy_tree_balance(prev); + 72 183361 : return tommy_tree_balance(prev); 73 : } 74 : - 75 175888 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) + 75 175516 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) 76 : { - 77 175888 : if (!root) - 78 75986 : return node; + 77 175516 : if (!root) + 78 75956 : return node; 79 : - 80 99902 : root->next = tommy_tree_move_right(root->next, node); + 80 99560 : root->next = tommy_tree_move_right(root->next, node); 81 : - 82 99902 : return tommy_tree_balance(root); + 82 99560 : return tommy_tree_balance(root); 83 : } 84 : - 85 107748419 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) + 85 107739396 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) 86 : { - 87 107748419 : tommy_ssize_t delta = tommy_tree_delta(root); + 87 107739396 : tommy_ssize_t delta = tommy_tree_delta(root); 88 : - 89 107748419 : if (delta < -1) { - 90 7586852 : if (tommy_tree_delta(root->next) > 0) - 91 44335 : root->next = tommy_tree_rotate_right(root->next); - 92 7586852 : return tommy_tree_rotate_left(root); + 89 107739396 : if (delta < -1) { + 90 7586146 : if (tommy_tree_delta(root->next) > 0) + 91 44087 : root->next = tommy_tree_rotate_right(root->next); + 92 7586146 : return tommy_tree_rotate_left(root); 93 : } 94 : - 95 100161567 : if (delta > 1) { - 96 140411 : if (tommy_tree_delta(root->prev) < 0) - 97 124884 : root->prev = tommy_tree_rotate_left(root->prev); - 98 140411 : return tommy_tree_rotate_right(root); + 95 100153250 : if (delta > 1) { + 96 139274 : if (tommy_tree_delta(root->prev) < 0) + 97 123951 : root->prev = tommy_tree_rotate_left(root->prev); + 98 139274 : return tommy_tree_rotate_right(root); 99 : } 100 : 101 : /* recompute key */ - 102 100021156 : root->index = 0; + 102 100013976 : root->index = 0; 103 : - 104 100021156 : if (root->prev && root->prev->index > root->index) - 105 80851276 : root->index = root->prev->index; + 104 100013976 : if (root->prev && root->prev->index > root->index) + 105 80844985 : root->index = root->prev->index; 106 : - 107 100021156 : if (root->next && root->next->index > root->index) - 108 46028890 : root->index = root->next->index; + 107 100013976 : if (root->next && root->next->index > root->index) + 108 46033228 : root->index = root->next->index; 109 : 110 : /* count itself */ - 111 100021156 : root->index += 1; + 111 100013976 : root->index += 1; 112 : - 113 100021156 : return root; + 113 100013976 : return root; 114 : } 115 : - 116 98881758 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) + 116 98880309 : 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 98881758 : if (!root) - 121 7704288 : return *let; + 120 98880309 : if (!root) + 121 7704208 : return *let; 122 : - 123 91177470 : c = cmp((*let)->data, root->data); + 123 91176101 : c = cmp((*let)->data, root->data); 124 : - 125 91177470 : if (c < 0) { - 126 1679959 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); - 127 1679959 : return tommy_tree_balance(root); + 125 91176101 : if (c < 0) { + 126 1671201 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); + 127 1671201 : return tommy_tree_balance(root); 128 : } 129 : - 130 89497511 : if (c > 0) { - 131 89497510 : root->next = tommy_tree_insert_node(cmp, root->next, let); - 132 89497510 : return tommy_tree_balance(root); + 130 89504900 : if (c > 0) { + 131 89504899 : root->next = tommy_tree_insert_node(cmp, root->next, let); + 132 89504899 : 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 7704289 : TOMMY_API void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) + 141 7704209 : TOMMY_API void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) 142 : { - 143 7704289 : tommy_tree_node* insert = node; + 143 7704209 : tommy_tree_node* insert = node; 144 : - 145 7704289 : insert->data = data; - 146 7704289 : insert->prev = 0; - 147 7704289 : insert->next = 0; - 148 7704289 : insert->index = 0; + 145 7704209 : insert->data = data; + 146 7704209 : insert->prev = 0; + 147 7704209 : insert->next = 0; + 148 7704209 : insert->index = 0; 149 : - 150 7704289 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); + 150 7704209 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); 151 : - 152 7704289 : if (insert == node) - 153 7704288 : ++tree->count; + 152 7704209 : if (insert == node) + 153 7704208 : ++tree->count; 154 : - 155 7704289 : return insert->data; + 155 7704209 : return insert->data; 156 : } 157 : - 158 754198 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) + 158 752904 : 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 754198 : if (!root) + 162 752904 : if (!root) 163 128 : return 0; 164 : - 165 754070 : c = cmp(data, root->data); + 165 752776 : c = cmp(data, root->data); 166 : - 167 754070 : if (c < 0) { - 168 310729 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); - 169 310729 : return tommy_tree_balance(root); + 167 752776 : if (c < 0) { + 168 310920 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); + 169 310920 : return tommy_tree_balance(root); 170 : } 171 : - 172 443341 : if (c > 0) { - 173 367355 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); - 174 367355 : return tommy_tree_balance(root); + 172 441856 : if (c > 0) { + 173 365900 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); + 174 365900 : return tommy_tree_balance(root); 175 : } 176 : 177 : /* found */ - 178 75986 : *let = root; + 178 75956 : *let = root; 179 : - 180 75986 : return tommy_tree_move_right(root->prev, root->next); + 180 75956 : return tommy_tree_move_right(root->prev, root->next); 181 : } 182 : - 183 76114 : TOMMY_API void* tommy_tree_remove(tommy_tree* tree, void* data) + 183 76084 : TOMMY_API void* tommy_tree_remove(tommy_tree* tree, void* data) 184 : { - 185 76114 : tommy_tree_node* node = 0; + 185 76084 : tommy_tree_node* node = 0; 186 : - 187 76114 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); + 187 76084 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); 188 : - 189 76114 : if (!node) + 189 76084 : if (!node) 190 128 : return 0; 191 : - 192 75986 : --tree->count; + 192 75956 : --tree->count; 193 : - 194 75986 : return node->data; + 194 75956 : return node->data; 195 : } 196 : - 197 183509139 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) + 197 182914273 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) 198 : { 199 : int c; 200 : - 201 183509139 : if (!root) - 202 1927556 : return 0; + 201 182914273 : if (!root) + 202 1925494 : return 0; 203 : - 204 181581583 : c = cmp(data, root->data); + 204 180988779 : c = cmp(data, root->data); 205 : - 206 181581583 : if (c < 0) - 207 67861047 : return tommy_tree_search_node(cmp, root->prev, data); + 206 180988779 : if (c < 0) + 207 67621145 : return tommy_tree_search_node(cmp, root->prev, data); 208 : - 209 113720536 : if (c > 0) - 210 98976918 : return tommy_tree_search_node(cmp, root->next, data); + 209 113367634 : if (c > 0) + 210 98676812 : return tommy_tree_search_node(cmp, root->next, data); 211 : - 212 14743618 : return root; + 212 14690822 : return root; 213 : } 214 : 215 2 : TOMMY_API void* tommy_tree_search(tommy_tree* tree, void* data) @@ -284,14 +284,14 @@ 222 1 : return node->data; 223 : } 224 : - 225 16671172 : TOMMY_API void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) + 225 16616314 : TOMMY_API void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) 226 : { - 227 16671172 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); + 227 16616314 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); 228 : - 229 16671172 : if (!node) - 230 1927555 : return 0; + 229 16616314 : if (!node) + 230 1925493 : return 0; 231 : - 232 14743617 : return node->data; + 232 14690821 : return node->data; 233 : } 234 : 235 128 : TOMMY_API void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) @@ -303,49 +303,49 @@ 241 128 : return data; 242 : } 243 : - 244 7539256 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) + 244 7539142 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) 245 : { 246 : tommy_tree_node* next; 247 : - 248 7539256 : if (!root) - 249 3770430 : return; + 248 7539142 : if (!root) + 249 3770378 : return; 250 : - 251 3768826 : tommy_tree_foreach_node(root->prev, func); + 251 3768764 : tommy_tree_foreach_node(root->prev, func); 252 : 253 : /* make a copy in case func is free() */ - 254 3768826 : next = root->next; + 254 3768764 : next = root->next; 255 : - 256 3768826 : func(root->data); + 256 3768764 : func(root->data); 257 : - 258 3768826 : tommy_tree_foreach_node(next, func); + 258 3768764 : tommy_tree_foreach_node(next, func); 259 : } 260 : - 261 1604 : TOMMY_API void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) + 261 1614 : TOMMY_API void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) 262 : { - 263 1604 : tommy_tree_foreach_node(tree->root, func); - 264 1604 : } + 263 1614 : tommy_tree_foreach_node(tree->root, func); + 264 1614 : } 265 : - 266 27357453 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) + 266 27289637 : 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 27357453 : if (!root) - 271 13681847 : return; + 270 27289637 : if (!root) + 271 13647933 : return; 272 : - 273 13675606 : tommy_tree_foreach_arg_node(root->prev, func, arg); + 273 13641704 : tommy_tree_foreach_arg_node(root->prev, func, arg); 274 : 275 : /* make a copy in case func is free() */ - 276 13675606 : next = root->next; + 276 13641704 : next = root->next; 277 : - 278 13675606 : func(arg, root->data); + 278 13641704 : func(arg, root->data); 279 : - 280 13675606 : tommy_tree_foreach_arg_node(next, func, arg); + 280 13641704 : tommy_tree_foreach_arg_node(next, func, arg); 281 : } 282 : - 283 6241 : TOMMY_API void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) + 283 6229 : TOMMY_API void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) 284 : { - 285 6241 : tommy_tree_foreach_arg_node(tree->root, func, arg); - 286 6241 : } + 285 6229 : tommy_tree_foreach_arg_node(tree->root, func, arg); + 286 6229 : } 287 : 288 1 : TOMMY_API tommy_size_t tommy_tree_memory_usage(tommy_tree* tree) 289 : { diff --git a/cov/tommyds/tommytree.h.func-sort-c.html b/cov/tommyds/tommytree.h.func-sort-c.html index 916e42d1..f366a29f 100644 --- a/cov/tommyds/tommytree.h.func-sort-c.html +++ b/cov/tommyds/tommytree.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/tommyds/tommytree.h.func.html b/cov/tommyds/tommytree.h.func.html index bd916045..a085e2ca 100644 --- a/cov/tommyds/tommytree.h.func.html +++ b/cov/tommyds/tommytree.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/tommyds/tommytree.h.gcov.html b/cov/tommyds/tommytree.h.gcov.html index 61fc0b63..a112cb4c 100644 --- a/cov/tommyds/tommytree.h.gcov.html +++ b/cov/tommyds/tommytree.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 1 diff --git a/cov/tommyds/tommytypes.h.func-sort-c.html b/cov/tommyds/tommytypes.h.func-sort-c.html index f63cc84d..e9841cf5 100644 --- a/cov/tommyds/tommytypes.h.func-sort-c.html +++ b/cov/tommyds/tommytypes.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -61,7 +61,7 @@ tommy_ctz_u64 - 2198 + 2196 tommy_haszero_u32 @@ -69,7 +69,7 @@ tommy_ilog2_u64 - 8515825 + 8496878
diff --git a/cov/tommyds/tommytypes.h.func.html b/cov/tommyds/tommytypes.h.func.html index d6380a12..3a591bdc 100644 --- a/cov/tommyds/tommytypes.h.func.html +++ b/cov/tommyds/tommytypes.h.func.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -61,7 +61,7 @@ tommy_ctz_u64 - 2198 + 2196 tommy_haszero_u32 @@ -69,7 +69,7 @@ tommy_ilog2_u64 - 8515825 + 8496878
diff --git a/cov/tommyds/tommytypes.h.gcov.html b/cov/tommyds/tommytypes.h.gcov.html index 147e00be..0424040f 100644 --- a/cov/tommyds/tommytypes.h.gcov.html +++ b/cov/tommyds/tommytypes.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-02-28 09:49:08 + 2026-02-28 10:17:21 Functions: 3 @@ -462,14 +462,14 @@ 400 : /** 401 : * Bit scan reverse or integer log2 for 64 bits. 402 : */ - 403 8515825 : tommy_inline tommy_uint_t tommy_ilog2_u64(tommy_uint64_t value) + 403 8496878 : tommy_inline tommy_uint_t tommy_ilog2_u64(tommy_uint64_t value) 404 : { 405 : #if defined(_MSC_VER) 406 : unsigned long count; 407 : _BitScanReverse64(&count, value); 408 : return count; 409 : #elif defined(__GNUC__) - 410 8515825 : return __builtin_clzll(value) ^ 63; + 410 8496878 : return __builtin_clzll(value) ^ 63; 411 : #else 412 : tommy_uint32_t l = value & 0xFFFFFFFFU; 413 : tommy_uint32_t h = value >> 32; @@ -513,14 +513,14 @@ 451 : /** 452 : * Bit scan forward or trailing zero count for 64 bits. 453 : */ - 454 2198 : tommy_inline tommy_uint_t tommy_ctz_u64(tommy_uint64_t value) + 454 2196 : tommy_inline tommy_uint_t tommy_ctz_u64(tommy_uint64_t value) 455 : { 456 : #if defined(_MSC_VER) 457 : unsigned long count; 458 : _BitScanForward64(&count, value); 459 : return count; 460 : #elif defined(__GNUC__) - 461 2198 : return __builtin_ctzll(value); + 461 2196 : return __builtin_ctzll(value); 462 : #else 463 : tommy_uint32_t l = value & 0xFFFFFFFFU; 464 : tommy_uint32_t h = value >> 32;