From bdbe4f70fad653c5d1a9ab70f001dcf784560244 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 13 May 2017 13:56:56 +0200 Subject: [PATCH] Auto update --- cov/cmdline/check.c.func-sort-c.html | 16 +- cov/cmdline/check.c.func.html | 16 +- cov/cmdline/check.c.gcov.html | 2704 +++--- cov/cmdline/device.c.func-sort-c.html | 2 +- cov/cmdline/device.c.func.html | 2 +- cov/cmdline/device.c.gcov.html | 2 +- cov/cmdline/dry.c.func-sort-c.html | 10 +- cov/cmdline/dry.c.func.html | 6 +- cov/cmdline/dry.c.gcov.html | 72 +- cov/cmdline/dup.c.func-sort-c.html | 2 +- cov/cmdline/dup.c.func.html | 2 +- cov/cmdline/dup.c.gcov.html | 2 +- cov/cmdline/elem.c.func-sort-c.html | 92 +- cov/cmdline/elem.c.func.html | 80 +- cov/cmdline/elem.c.gcov.html | 614 +- cov/cmdline/elem.h.func-sort-c.html | 66 +- cov/cmdline/elem.h.func.html | 60 +- cov/cmdline/elem.h.gcov.html | 192 +- cov/cmdline/handle.c.func-sort-c.html | 16 +- cov/cmdline/handle.c.func.html | 16 +- cov/cmdline/handle.c.gcov.html | 202 +- cov/cmdline/import.c.func-sort-c.html | 6 +- cov/cmdline/import.c.func.html | 6 +- cov/cmdline/import.c.gcov.html | 20 +- cov/cmdline/index-sort-f.html | 78 +- cov/cmdline/index-sort-l.html | 110 +- cov/cmdline/index.html | 70 +- cov/cmdline/io.c.func-sort-c.html | 48 +- cov/cmdline/io.c.func.html | 42 +- cov/cmdline/io.c.gcov.html | 454 +- cov/cmdline/list.c.func-sort-c.html | 2 +- cov/cmdline/list.c.func.html | 2 +- cov/cmdline/list.c.gcov.html | 2 +- cov/cmdline/mkstream.c.func-sort-c.html | 2 +- cov/cmdline/mkstream.c.func.html | 2 +- cov/cmdline/mkstream.c.gcov.html | 2 +- cov/cmdline/mktest.c.func-sort-c.html | 34 +- cov/cmdline/mktest.c.func.html | 22 +- cov/cmdline/mktest.c.gcov.html | 176 +- cov/cmdline/murmur3.c.func-sort-c.html | 6 +- cov/cmdline/murmur3.c.func.html | 6 +- cov/cmdline/murmur3.c.gcov.html | 142 +- cov/cmdline/parity.c.func-sort-c.html | 8 +- cov/cmdline/parity.c.func.html | 8 +- cov/cmdline/parity.c.gcov.html | 64 +- cov/cmdline/pool.c.func-sort-c.html | 10 +- cov/cmdline/pool.c.func.html | 10 +- cov/cmdline/pool.c.gcov.html | 142 +- cov/cmdline/portable.h.func-sort-c.html | 4 +- cov/cmdline/portable.h.func.html | 4 +- cov/cmdline/portable.h.gcov.html | 544 +- cov/cmdline/rehash.c.func-sort-c.html | 2 +- cov/cmdline/rehash.c.func.html | 2 +- cov/cmdline/rehash.c.gcov.html | 2 +- cov/cmdline/scan.c.func-sort-c.html | 20 +- cov/cmdline/scan.c.func.html | 20 +- cov/cmdline/scan.c.gcov.html | 312 +- cov/cmdline/scrub.c.func-sort-c.html | 6 +- cov/cmdline/scrub.c.func.html | 6 +- cov/cmdline/scrub.c.gcov.html | 98 +- cov/cmdline/search.c.func-sort-c.html | 10 +- cov/cmdline/search.c.func.html | 10 +- cov/cmdline/search.c.gcov.html | 124 +- cov/cmdline/selftest.c.func-sort-c.html | 2 +- cov/cmdline/selftest.c.func.html | 2 +- cov/cmdline/selftest.c.gcov.html | 2 +- cov/cmdline/snapraid.c.func-sort-c.html | 2 +- cov/cmdline/snapraid.c.func.html | 2 +- cov/cmdline/snapraid.c.gcov.html | 4 +- cov/cmdline/speed.c.func-sort-c.html | 4 +- cov/cmdline/speed.c.func.html | 4 +- cov/cmdline/speed.c.gcov.html | 100 +- cov/cmdline/spooky2.c.func-sort-c.html | 4 +- cov/cmdline/spooky2.c.func.html | 4 +- cov/cmdline/spooky2.c.gcov.html | 42 +- cov/cmdline/state.c.func-sort-c.html | 112 +- cov/cmdline/state.c.func.html | 112 +- cov/cmdline/state.c.gcov.html | 7999 +++++++++-------- cov/cmdline/status.c.func-sort-c.html | 2 +- cov/cmdline/status.c.func.html | 2 +- cov/cmdline/status.c.gcov.html | 36 +- cov/cmdline/stream.c.func-sort-c.html | 14 +- cov/cmdline/stream.c.func.html | 14 +- cov/cmdline/stream.c.gcov.html | 160 +- cov/cmdline/stream.h.func-sort-c.html | 14 +- cov/cmdline/stream.h.func.html | 14 +- cov/cmdline/stream.h.gcov.html | 36 +- cov/cmdline/support.c.func-sort-c.html | 186 +- cov/cmdline/support.c.func.html | 164 +- cov/cmdline/support.c.gcov.html | 2475 ++--- cov/cmdline/support.h.func-sort-c.html | 4 +- cov/cmdline/support.h.func.html | 4 +- cov/cmdline/support.h.gcov.html | 196 +- cov/cmdline/sync.c.func-sort-c.html | 10 +- cov/cmdline/sync.c.func.html | 10 +- cov/cmdline/sync.c.gcov.html | 278 +- cov/cmdline/touch.c.func-sort-c.html | 2 +- cov/cmdline/touch.c.func.html | 2 +- cov/cmdline/touch.c.gcov.html | 2 +- cov/cmdline/unix.c.func-sort-c.html | 82 +- cov/cmdline/unix.c.func.html | 78 +- cov/cmdline/unix.c.gcov.html | 2741 +++--- cov/cmdline/util.c.func-sort-c.html | 20 +- cov/cmdline/util.c.func.html | 20 +- cov/cmdline/util.c.gcov.html | 76 +- cov/cmdline/util.h.func-sort-c.html | 8 +- cov/cmdline/util.h.func.html | 8 +- cov/cmdline/util.h.gcov.html | 36 +- cov/index-sort-f.html | 24 +- cov/index-sort-l.html | 24 +- cov/index.html | 24 +- cov/raid/check.c.func-sort-c.html | 2 +- cov/raid/check.c.func.html | 2 +- cov/raid/check.c.gcov.html | 2 +- cov/raid/combo.h.func-sort-c.html | 2 +- cov/raid/combo.h.func.html | 2 +- cov/raid/combo.h.gcov.html | 26 +- cov/raid/cpu.h.func-sort-c.html | 2 +- cov/raid/cpu.h.func.html | 2 +- cov/raid/cpu.h.gcov.html | 2 +- cov/raid/gf.h.func-sort-c.html | 2 +- cov/raid/gf.h.func.html | 2 +- cov/raid/gf.h.gcov.html | 30 +- cov/raid/helper.c.func-sort-c.html | 2 +- cov/raid/helper.c.func.html | 2 +- cov/raid/helper.c.gcov.html | 2 +- cov/raid/index-sort-f.html | 2 +- cov/raid/index-sort-l.html | 2 +- cov/raid/index.html | 2 +- cov/raid/int.c.func-sort-c.html | 12 +- cov/raid/int.c.func.html | 12 +- cov/raid/int.c.gcov.html | 208 +- cov/raid/internal.h.func-sort-c.html | 2 +- cov/raid/internal.h.func.html | 2 +- cov/raid/internal.h.gcov.html | 12 +- cov/raid/intz.c.func-sort-c.html | 2 +- cov/raid/intz.c.func.html | 2 +- cov/raid/intz.c.gcov.html | 2 +- cov/raid/memory.c.func-sort-c.html | 2 +- cov/raid/memory.c.func.html | 2 +- cov/raid/memory.c.gcov.html | 4 +- cov/raid/module.c.func-sort-c.html | 2 +- cov/raid/module.c.func.html | 2 +- cov/raid/module.c.gcov.html | 2 +- cov/raid/raid.c.func-sort-c.html | 12 +- cov/raid/raid.c.func.html | 12 +- cov/raid/raid.c.gcov.html | 142 +- cov/raid/tag.c.func-sort-c.html | 2 +- cov/raid/tag.c.func.html | 2 +- cov/raid/tag.c.gcov.html | 2 +- cov/raid/test.c.func-sort-c.html | 2 +- cov/raid/test.c.func.html | 2 +- cov/raid/test.c.gcov.html | 2 +- cov/raid/x86.c.func-sort-c.html | 18 +- cov/raid/x86.c.func.html | 18 +- cov/raid/x86.c.gcov.html | 824 +- cov/raid/x86z.c.func-sort-c.html | 4 +- cov/raid/x86z.c.func.html | 4 +- cov/raid/x86z.c.gcov.html | 72 +- cov/tommyds/index-sort-f.html | 2 +- cov/tommyds/index-sort-l.html | 2 +- cov/tommyds/index.html | 2 +- cov/tommyds/tommyarray.c.func-sort-c.html | 2 +- cov/tommyds/tommyarray.c.func.html | 2 +- cov/tommyds/tommyarray.c.gcov.html | 2 +- cov/tommyds/tommyarray.h.func-sort-c.html | 6 +- cov/tommyds/tommyarray.h.func.html | 6 +- cov/tommyds/tommyarray.h.gcov.html | 14 +- .../tommyarrayblkof.c.func-sort-c.html | 4 +- cov/tommyds/tommyarrayblkof.c.func.html | 4 +- cov/tommyds/tommyarrayblkof.c.gcov.html | 8 +- .../tommyarrayblkof.h.func-sort-c.html | 6 +- cov/tommyds/tommyarrayblkof.h.func.html | 6 +- cov/tommyds/tommyarrayblkof.h.gcov.html | 14 +- cov/tommyds/tommychain.h.func-sort-c.html | 10 +- cov/tommyds/tommychain.h.func.html | 10 +- cov/tommyds/tommychain.h.gcov.html | 122 +- cov/tommyds/tommyhash.c.func-sort-c.html | 6 +- cov/tommyds/tommyhash.c.func.html | 6 +- cov/tommyds/tommyhash.c.gcov.html | 68 +- cov/tommyds/tommyhash.h.func-sort-c.html | 6 +- cov/tommyds/tommyhash.h.func.html | 6 +- cov/tommyds/tommyhash.h.gcov.html | 38 +- cov/tommyds/tommyhashdyn.c.func-sort-c.html | 10 +- cov/tommyds/tommyhashdyn.c.func.html | 10 +- cov/tommyds/tommyhashdyn.c.gcov.html | 52 +- cov/tommyds/tommyhashdyn.h.func-sort-c.html | 6 +- cov/tommyds/tommyhashdyn.h.func.html | 6 +- cov/tommyds/tommyhashdyn.h.gcov.html | 20 +- cov/tommyds/tommylist.c.func-sort-c.html | 2 +- cov/tommyds/tommylist.c.func.html | 2 +- cov/tommyds/tommylist.c.gcov.html | 2 +- cov/tommyds/tommylist.h.func-sort-c.html | 12 +- cov/tommyds/tommylist.h.func.html | 12 +- cov/tommyds/tommylist.h.gcov.html | 86 +- cov/tommyds/tommytree.c.func-sort-c.html | 28 +- cov/tommyds/tommytree.c.func.html | 28 +- cov/tommyds/tommytree.c.gcov.html | 204 +- cov/tommyds/tommytree.h.func-sort-c.html | 2 +- cov/tommyds/tommytree.h.func.html | 2 +- cov/tommyds/tommytree.h.gcov.html | 2 +- cov/tommyds/tommytypes.h.func-sort-c.html | 4 +- cov/tommyds/tommytypes.h.func.html | 4 +- cov/tommyds/tommytypes.h.gcov.html | 6 +- 204 files changed, 12214 insertions(+), 12085 deletions(-) diff --git a/cov/cmdline/check.c.func-sort-c.html b/cov/cmdline/check.c.func-sort-c.html index cf689f09..4cfb7ec2 100644 --- a/cov/cmdline/check.c.func-sort-c.html +++ b/cov/cmdline/check.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 709 - 775 + 711 + 777 91.5 % Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -73,22 +73,22 @@ blockcmp - 473119 + 473361 repair_step - 252549 + 252783 is_hash_matching - 214644 + 214767 - state_check + state_check 120 - state_check_process + state_check_process 118 diff --git a/cov/cmdline/check.c.func.html b/cov/cmdline/check.c.func.html index d1422056..facd5d69 100644 --- a/cov/cmdline/check.c.func.html +++ b/cov/cmdline/check.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 709 - 775 + 711 + 777 91.5 % Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -65,7 +65,7 @@ blockcmp - 473119 + 473361 file_post @@ -73,7 +73,7 @@ is_hash_matching - 214644 + 214767 is_parity_matching @@ -85,14 +85,14 @@ repair_step - 252549 + 252783 - state_check + state_check 120 - state_check_process + state_check_process 118 diff --git a/cov/cmdline/check.c.gcov.html b/cov/cmdline/check.c.gcov.html index a9fbb187..530d8a18 100644 --- a/cov/cmdline/check.c.gcov.html +++ b/cov/cmdline/check.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 709 - 775 + 711 + 777 91.5 % Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -129,64 +129,64 @@ 67 : * Check if a block hash matches the specified buffer. 68 : * Return ==0 if equal 69 : */ - 70 473119 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) + 70 473361 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) 71 : { 72 : unsigned char hash[HASH_MAX]; 73 : 74 : /* now compute the hash of the valid part */ - 75 473119 : if (rehash) { + 75 473361 : if (rehash) { 76 0 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size); 77 : } else { - 78 473119 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); + 78 473361 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); 79 : } 80 : 81 : /* compare the hash */ - 82 473119 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { - 83 19028 : return -1; + 82 473361 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 83 19016 : return -1; 84 : } 85 : 86 : /* compare to the end of the block */ - 87 454091 : if (pos_size < state->block_size) { - 88 187372 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { - 89 54 : return -1; + 87 454345 : if (pos_size < state->block_size) { + 88 187561 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { + 89 36 : return -1; 90 : } 91 : } 92 : - 93 454037 : return 0; + 93 454309 : return 0; 94 : } 95 : 96 : /** 97 : * Check if the hash of all the failed block we are expecting to recover are now matching. 98 : */ - 99 214644 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero) + 99 214767 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero) 100 : { 101 : unsigned j; 102 : int hash_checked; 103 : - 104 214644 : hash_checked = 0; /* keep track if we check at least one block */ + 104 214767 : hash_checked = 0; /* keep track if we check at least one block */ 105 : 106 : /* check if the recovered blocks are OK */ - 107 673203 : for (j = 0; j < failed_count; ++j) { + 107 673598 : for (j = 0; j < failed_count; ++j) { 108 : /* if we are expected to recover this block */ - 109 477641 : if (!failed[failed_map[j]].is_outofdate + 109 477883 : if (!failed[failed_map[j]].is_outofdate 110 : /* if the block has a hash to check */ - 111 473119 : && block_has_updated_hash(failed[failed_map[j]].block) + 111 473361 : && block_has_updated_hash(failed[failed_map[j]].block) 112 : ) { 113 : /* if a hash doesn't match, fail the check */ - 114 473119 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); - 115 473119 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { - 116 19082 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]); - 117 19082 : return 0; + 114 473361 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); + 115 473361 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { + 116 19052 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]); + 117 19052 : return 0; 118 : } 119 : - 120 454037 : hash_checked = 1; + 120 454309 : hash_checked = 1; 121 : } 122 : } 123 : 124 : /* if nothing checked, we reject it */ 125 : /* note that we are excluding this case at upper level */ 126 : /* but checking again doesn't hurt */ - 127 195562 : if (!hash_checked) { + 127 195715 : if (!hash_checked) { 128 : /* LCOV_EXCL_START */ 129 : return 0; 130 : /* LCOV_EXCL_STOP */ @@ -194,8 +194,8 @@ 132 : 133 : /* if we checked something, and no block failed the check */ 134 : /* recompute all the redundancy information */ - 135 195562 : raid_gen(diskmax, state->level, state->block_size, buffer); - 136 195562 : return 1; + 135 195715 : raid_gen(diskmax, state->level, state->block_size, buffer); + 136 195715 : return 1; 137 : } 138 : 139 : /** @@ -221,7 +221,7 @@ 159 : * Return <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. 160 : * If success, the parity are computed in the buffer variable. 161 : */ - 162 252549 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) + 162 252783 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) 163 : { 164 : unsigned i, n; 165 : int error; @@ -230,7 +230,7 @@ 168 : int ip[LEV_MAX]; 169 : 170 : /* no fix required, already checked at higher level, but just to be sure */ - 171 252549 : if (failed_count == 0) { + 171 252783 : if (failed_count == 0) { 172 : /* LCOV_EXCL_START */ 173 : /* recompute only the parity */ 174 : raid_gen(diskmax, state->level, state->block_size, buffer); @@ -238,28 +238,28 @@ 176 : /* LCOV_EXCL_STOP */ 177 : } 178 : - 179 252549 : n = state->level; - 180 252549 : error = 0; + 179 252783 : n = state->level; + 180 252783 : error = 0; 181 : 182 : /* setup vector of failed disk indexes */ - 183 891351 : for (i = 0; i < failed_count; ++i) - 184 638802 : id[i] = failed[failed_map[i]].index; + 183 892029 : for (i = 0; i < failed_count; ++i) + 184 639246 : id[i] = failed[failed_map[i]].index; 185 : 186 : /* check if there is at least a failed block that can be checked for correctness using the hash */ 187 : /* if there isn't, we have to sacrifice a parity block to check that the result is correct */ - 188 252549 : has_hash = 0; - 189 891351 : for (i = 0; i < failed_count; ++i) { + 188 252783 : has_hash = 0; + 189 892029 : for (i = 0; i < failed_count; ++i) { 190 : /* if we are expected to recover this block */ - 191 638802 : if (!failed[failed_map[i]].is_outofdate + 191 639246 : if (!failed[failed_map[i]].is_outofdate 192 : /* if the block has a hash to check */ - 193 629758 : && block_has_updated_hash(failed[failed_map[i]].block) + 193 630202 : && block_has_updated_hash(failed[failed_map[i]].block) 194 : ) - 195 629750 : has_hash = 1; + 195 630194 : has_hash = 1; 196 : } 197 : 198 : /* if we don't have a hash, but we have an extra parity */ 199 : /* (strictly-less failures than number of parities) */ - 200 252549 : if (!has_hash && failed_count < n) { + 200 252783 : if (!has_hash && failed_count < n) { 201 : /* number of parity to use, one more to check the recovering */ 202 8 : unsigned r = failed_count + 1; 203 : @@ -299,51 +299,51 @@ 237 : 238 : /* if we have a hash, and enough parities */ 239 : /* (less-or-equal failures than number of parities) */ - 240 252541 : if (has_hash && failed_count <= n) { + 240 252775 : if (has_hash && failed_count <= n) { 241 : /* number of parities to use equal at the number of failures */ - 242 204895 : unsigned r = failed_count; + 242 205038 : unsigned r = failed_count; 243 : 244 : /* all combinations (r of n) parities */ - 245 204895 : combination_first(r, n, ip); + 245 205038 : combination_first(r, n, ip); 246 : do { 247 : /* if a parity is missing, do nothing */ - 248 692285 : for (i = 0; i < r; ++i) { - 249 477641 : if (buffer_recov[ip[i]] == 0) + 248 692650 : for (i = 0; i < r; ++i) { + 249 477883 : if (buffer_recov[ip[i]] == 0) 250 0 : break; 251 : } - 252 214644 : if (i != r) + 252 214767 : if (i != r) 253 0 : continue; 254 : 255 : /* copy the parities to use */ - 256 692285 : for (i = 0; i < r; ++i) - 257 477641 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + 256 692650 : for (i = 0; i < r; ++i) + 257 477883 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); 258 : 259 : /* recover */ - 260 214644 : raid_data(r, id, ip, diskmax, state->block_size, buffer); + 260 214767 : raid_data(r, id, ip, diskmax, state->block_size, buffer); 261 : 262 : /* use the hash to check the result */ - 263 214644 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) - 264 195562 : return 0; + 263 214767 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) + 264 195715 : return 0; 265 : 266 : /* log */ - 267 19082 : log_tag("parity_error:%u:", pos); - 268 38164 : for (i = 0; i < r; ++i) { - 269 19082 : if (i != 0) + 267 19052 : log_tag("parity_error:%u:", pos); + 268 38104 : for (i = 0; i < r; ++i) { + 269 19052 : if (i != 0) 270 0 : log_tag("/"); - 271 19082 : log_tag("%s", lev_config_name(ip[i])); + 271 19052 : log_tag("%s", lev_config_name(ip[i])); 272 : } - 273 19082 : log_tag(":hash: Hash mismatch\n"); - 274 19082 : ++error; - 275 38164 : } while (combination_next(r, n, ip)); + 273 19052 : log_tag(":hash: Hash mismatch\n"); + 274 19052 : ++error; + 275 38104 : } while (combination_next(r, n, ip)); 276 : } 277 : 278 : /* return the number of failed attempts, or -1 if no strategy */ - 279 56979 : if (error) - 280 9333 : return error; + 279 57060 : if (error) + 280 9323 : return error; 281 : - 282 47646 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", + 282 47737 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", 283 : pos, failed_count, n, has_hash ? "with" : "without"); - 284 47646 : return -1; + 284 47737 : return -1; 285 : } 286 : 287 870958 : static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) @@ -360,47 +360,47 @@ 298 : 299 : /* if nothing failed, just recompute the parity */ 300 870958 : if (failed_count == 0) { - 301 583497 : raid_gen(diskmax, state->level, state->block_size, buffer); - 302 583497 : return 0; + 301 583263 : raid_gen(diskmax, state->level, state->block_size, buffer); + 302 583263 : return 0; 303 : } 304 : 305 : /* logs the status */ - 306 1016282 : for (j = 0; j < failed_count; ++j) { + 306 1016960 : for (j = 0; j < failed_count; ++j) { 307 : const char* desc; 308 : const char* hash; 309 : const char* data; - 310 728821 : struct snapraid_block* block = failed[j].block; - 311 728821 : unsigned block_state = block_state_get(block); + 310 729265 : struct snapraid_block* block = failed[j].block; + 311 729265 : unsigned block_state = block_state_get(block); 312 : - 313 728821 : switch (block_state) { + 313 729265 : switch (block_state) { 314 18454 : case BLOCK_STATE_DELETED : desc = "delete"; break; 315 13851 : case BLOCK_STATE_CHG : desc = "change"; break; 316 62282 : case BLOCK_STATE_REP : desc = "replace"; break; - 317 634234 : case BLOCK_STATE_BLK : desc = "block"; break; + 317 634678 : case BLOCK_STATE_BLK : desc = "block"; break; 318 : /* LCOV_EXCL_START */ 319 : default : desc = "unknown"; break; 320 : /* LCOV_EXCL_STOP */ 321 : } 322 : - 323 728821 : if (hash_is_invalid(block->hash)) { + 323 729265 : if (hash_is_invalid(block->hash)) { 324 13843 : hash = "lost"; - 325 714978 : } else if (hash_is_zero(block->hash)) { + 325 715422 : } else if (hash_is_zero(block->hash)) { 326 8 : hash = "zero"; 327 : } else { - 328 714970 : hash = "known"; + 328 715414 : hash = "known"; 329 : } 330 : - 331 728821 : if (failed[j].is_bad) - 332 643096 : data = "bad"; + 331 729265 : if (failed[j].is_bad) + 332 643540 : data = "bad"; 333 : else 334 85725 : data = "good"; 335 : - 336 728821 : if (failed[j].file) { - 337 710367 : struct snapraid_disk* disk = failed[j].disk; - 338 710367 : struct snapraid_file* file = failed[j].file; - 339 710367 : block_off_t file_pos = failed[j].file_pos; + 336 729265 : if (failed[j].file) { + 337 710811 : struct snapraid_disk* disk = failed[j].disk; + 338 710811 : struct snapraid_file* file = failed[j].file; + 339 710811 : block_off_t file_pos = failed[j].file_pos; 340 : - 341 710367 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + 341 710811 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos); 342 : } else { 343 18454 : log_tag("entry:%u:%s:%s:%s:\n", j, desc, hash, data); 344 : } @@ -422,35 +422,35 @@ 360 : /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */ 361 : /* but we are not interested in DELETED ones. */ 362 : - 363 287461 : n = 0; - 364 287461 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 365 1016282 : for (j = 0; j < failed_count; ++j) { - 366 728821 : if (failed[j].is_bad) { - 367 643096 : unsigned block_state = block_state_get(failed[j].block); + 363 287695 : n = 0; + 364 287695 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 365 1016960 : for (j = 0; j < failed_count; ++j) { + 366 729265 : if (failed[j].is_bad) { + 367 643540 : unsigned block_state = block_state_get(failed[j].block); 368 : - 369 643096 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ + 369 643540 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ 370 : 371 : /* if we have the hash for it */ - 372 643096 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) + 372 643540 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) 373 : /* try to fetch the block using the known hash */ - 374 643088 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 - 375 638616 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) + 374 643532 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 + 375 639060 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) 376 : ) { 377 : /* we already have corrected it! */ 378 22382 : log_tag("hash_import: Fixed entry %u\n", j); 379 : } else { 380 : /* otherwise try to recover it */ - 381 620714 : failed_map[n] = j; - 382 620714 : ++n; + 381 621158 : failed_map[n] = j; + 382 621158 : ++n; 383 : 384 : /* we have something to try to recover */ - 385 620714 : something_to_recover = 1; + 385 621158 : something_to_recover = 1; 386 : } 387 : } 388 : } 389 : 390 : /* if nothing to fix */ - 391 287461 : if (!something_to_recover) { + 391 287695 : if (!something_to_recover) { 392 43956 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n); 393 : 394 : /* recompute only the parity */ @@ -458,22 +458,22 @@ 396 43956 : return 0; 397 : } 398 : - 399 243505 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); - 400 243505 : if (ret == 0) { + 399 243739 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); + 400 243739 : if (ret == 0) { 401 : /* reprocess the CHG blocks, for which we don't have a hash to check */ 402 : /* if they were BAD we have to use some heuristics to ensure that we have recovered */ 403 : /* the state after the sync. If unsure, we assume the worst case */ 404 : - 405 667198 : for (j = 0; j < failed_count; ++j) { + 405 667623 : for (j = 0; j < failed_count; ++j) { 406 : /* we take care only of BAD blocks we have to write back */ - 407 476150 : if (failed[j].is_bad) { - 408 462678 : unsigned block_state = block_state_get(failed[j].block); + 407 476422 : if (failed[j].is_bad) { + 408 462950 : unsigned block_state = block_state_get(failed[j].block); 409 : 410 : /* BLK and REP blocks are always OK, because at this point */ 411 : /* we have already checked their hash */ - 412 462678 : if (block_state != BLOCK_STATE_CHG) { - 413 462670 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); - 414 462670 : continue; + 412 462950 : if (block_state != BLOCK_STATE_CHG) { + 413 462942 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 414 462942 : continue; 415 : } 416 : 417 : /* for CHG blocks we have to 'guess' if they are correct or not */ @@ -515,15 +515,15 @@ 453 : } 454 : } 455 : - 456 191048 : return 0; + 456 191201 : return 0; 457 : } - 458 52457 : if (ret > 0) - 459 9333 : error += ret; + 458 52538 : if (ret > 0) + 459 9323 : error += ret; 460 : - 461 52457 : if (ret < 0) - 462 43124 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); + 461 52538 : if (ret < 0) + 462 43215 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); 463 : else - 464 9333 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); + 464 9323 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); 465 : 466 : /* Now assume that the parity IS NOT updated at the current state, */ 467 : /* but still represent the state before the last 'sync' process. */ @@ -533,15 +533,15 @@ 471 : /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */ 472 : /* even if marked as bad, because we don't have parity for them and it's just impossible, */ 473 : /* and we are not interested to recover DELETED ones. */ - 474 52457 : n = 0; - 475 52457 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 476 52457 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ - 477 232692 : for (j = 0; j < failed_count; ++j) { - 478 180235 : unsigned block_state = block_state_get(failed[j].block); + 474 52538 : n = 0; + 475 52538 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 476 52538 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ + 477 232945 : for (j = 0; j < failed_count; ++j) { + 478 180407 : unsigned block_state = block_state_get(failed[j].block); 479 : - 480 180235 : if (block_state == BLOCK_STATE_DELETED - 481 171191 : || block_state == BLOCK_STATE_CHG - 482 171191 : || block_state == BLOCK_STATE_REP + 480 180407 : if (block_state == BLOCK_STATE_DELETED + 481 171363 : || block_state == BLOCK_STATE_CHG + 482 171363 : || block_state == BLOCK_STATE_REP 483 : ) { 484 : /* If the block is CHG, REP or DELETED, we don't have the original content of block, */ 485 : /* and we must try to recover it. */ @@ -583,24 +583,24 @@ 521 : /* it also applies to CHG and DELETE blocks because we want to have */ 522 : /* a successful recovering only if a BLK one is matching */ 523 9044 : failed[j].is_outofdate = 1; - 524 171191 : } else if (failed[j].is_bad) { + 524 171363 : } else if (failed[j].is_bad) { 525 : /* If the block is bad we don't know its content, and we try to recover it */ 526 : /* At this point, we can have only BLK ones */ 527 : - 528 171191 : assert(block_state == BLOCK_STATE_BLK); + 528 171363 : assert(block_state == BLOCK_STATE_BLK); 529 : 530 : /* we have something we are interested to recover */ - 531 171191 : something_to_recover = 1; + 531 171363 : something_to_recover = 1; 532 : 533 : /* we try to recover it */ - 534 171191 : failed_map[n] = j; - 535 171191 : ++n; + 534 171363 : failed_map[n] = j; + 535 171363 : ++n; 536 : } 537 : } 538 : 539 : /* if nothing to fix, we just don't try */ 540 : /* if nothing unsynced we also don't retry, because it's the same try as before */ - 541 52457 : if (something_to_recover && something_unsynced) { + 541 52538 : if (something_to_recover && something_unsynced) { 542 9044 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); 543 9044 : if (ret == 0) { 544 : /* reprocess the REP and CHG blocks, for which we have recovered and old state */ @@ -634,17 +634,17 @@ 572 : else 573 0 : log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret); 574 : } else { - 575 43413 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, + 575 43494 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, 576 : !something_to_recover ? " nothing to recover" : "", 577 : !something_unsynced ? " nothing unsynched" : "" 578 : ); 579 : } 580 : 581 : /* return the number of failed attempts, or -1 if no strategy */ - 582 47935 : if (error) - 583 4811 : return error; + 582 48016 : if (error) + 583 4801 : return error; 584 : else - 585 43124 : return -1; + 585 43215 : return -1; 586 : } 587 : 588 : /** @@ -718,12 +718,12 @@ 656 : /* rename it to .unrecoverable */ 657 : char path_to[PATH_MAX]; 658 : - 659 63275 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); + 659 63324 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); 660 : 661 : /* ensure to close the file before renaming */ - 662 63275 : if (handle[j].file == file) { - 663 63275 : ret = handle_close(&handle[j]); - 664 63275 : if (ret != 0) { + 662 63324 : if (handle[j].file == file) { + 663 63324 : ret = handle_close(&handle[j]); + 664 63324 : if (ret != 0) { 665 : /* LCOV_EXCL_START */ 666 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 667 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -732,8 +732,8 @@ 670 : } 671 : } 672 : - 673 63275 : ret = rename(path, path_to); - 674 63275 : if (ret != 0) { + 673 63324 : ret = rename(path, path_to); + 674 63324 : if (ret != 0) { 675 : /* LCOV_EXCL_START */ 676 : log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno)); 677 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); @@ -741,22 +741,22 @@ 679 : /* LCOV_EXCL_STOP */ 680 : } 681 : - 682 63275 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 683 63275 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 682 63324 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 683 63324 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); 684 : 685 : /* and do not set the time if damaged */ - 686 63275 : goto close_and_continue; + 686 63324 : goto close_and_continue; 687 : } 688 : 689 : /* if the file is not fixed, meaning that it is untouched */ - 690 693959 : if (!file_flag_has(file, FILE_IS_FIXED)) { + 690 693910 : if (!file_flag_has(file, FILE_IS_FIXED)) { 691 : /* nothing to do, but close the file */ - 692 574554 : goto close_and_continue; + 692 574448 : goto close_and_continue; 693 : } 694 : 695 : /* if the file is closed or different than the one expected, reopen it */ 696 : /* a different open file could happen when filtering for bad blocks */ - 697 119405 : if (handle[j].file != file) { + 697 119462 : if (handle[j].file != file) { 698 : /* close a potential different file */ 699 0 : ret = handle_close(&handle[j]); 700 0 : if (ret != 0) { @@ -779,13 +779,13 @@ 717 : } 718 : } 719 : - 720 119405 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 721 119405 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); + 720 119462 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 721 119462 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); 722 : - 723 119405 : inode = handle[j].st.st_ino; + 723 119462 : inode = handle[j].st.st_ino; 724 : 725 : /* search for the corresponding inode */ - 726 119405 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + 726 119462 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); 727 : 728 : /* if the inode is already in the database and it refers at a different file name, */ 729 : /* we can fix the file time ONLY if the time and size allow to differentiate */ @@ -795,15 +795,15 @@ 733 : /* when recreating them the inodes may be reused in a different order, */ 734 : /* and at the next sync some files may have matching inode/size/time even if different name */ 735 : /* not allowing sync to detect that the file is changed and not renamed */ - 736 119405 : if (!collide_file /* if not in the database, there is no collision */ - 737 31334 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ - 738 22534 : || collide_file->size != file->size /* if the size is different, the collision is identified */ - 739 2 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ - 740 1 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ + 736 119462 : if (!collide_file /* if not in the database, there is no collision */ + 737 42083 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ + 738 39012 : || collide_file->size != file->size /* if the size is different, the collision is identified */ + 739 7 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ + 740 5 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ 741 : ) { 742 : /* set the original modification time */ - 743 119405 : ret = handle_utime(&handle[j]); - 744 238810 : if (ret == -1) { + 743 119462 : ret = handle_utime(&handle[j]); + 744 238924 : if (ret == -1) { 745 : /* LCOV_EXCL_START */ 746 : /* mark the file as damaged */ 747 : file_flag_set(file, FILE_IS_DAMAGED); @@ -818,21 +818,21 @@ 756 : /* we are not fixing, but only checking */ 757 : /* print just the final status */ 758 1308032 : if (file_flag_has(file, FILE_IS_DAMAGED)) { - 759 9420 : if (state->opt.auditonly) { - 760 2798 : log_tag("status:damaged:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 761 2798 : msg_info("damaged %s\n", fmt_term(disk, file->sub, esc_buffer)); + 759 9546 : if (state->opt.auditonly) { + 760 2866 : log_tag("status:damaged:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 761 2866 : msg_info("damaged %s\n", fmt_term(disk, file->sub, esc_buffer)); 762 : } else { - 763 6622 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 764 6622 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 763 6680 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 764 6680 : msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); 765 : } - 766 1298612 : } else if (file_flag_has(file, FILE_IS_FIXED)) { - 767 76223 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 768 76223 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + 766 1298486 : } else if (file_flag_has(file, FILE_IS_FIXED)) { + 767 76269 : log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 768 76269 : msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); 769 : } else { 770 : /* we don't use msg_verbose() because it also goes into the log */ - 771 1222389 : if (msg_level >= MSG_VERBOSE) { - 772 23229 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 773 23229 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer)); + 771 1222217 : if (msg_level >= MSG_VERBOSE) { + 772 23189 : log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 773 23189 : msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer)); 774 : } 775 : } 776 : } @@ -844,8 +844,8 @@ 782 2162259 : if (handle[j].file == file) { 783 : /* ensure to close the file just after finishing with it */ 784 : /* to avoid to keep it open without any possible use */ - 785 1978605 : ret = handle_close(&handle[j]); - 786 1978605 : if (ret != 0) { + 785 1978363 : ret = handle_close(&handle[j]); + 786 1978363 : if (ret != 0) { 787 : /* LCOV_EXCL_START */ 788 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); 789 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -877,1216 +877,1238 @@ 815 15204 : return 0; 816 : } 817 : - 818 : /* for each parity */ - 819 2125818 : for (l = 0; l < state->level; ++l) { - 820 2042438 : if (!state->parity[l].is_excluded) { - 821 1772374 : return 1; - 822 : } - 823 : } - 824 : - 825 : /* for each disk */ - 826 386636 : for (j = 0; j < diskmax; ++j) { - 827 : struct snapraid_block* block; - 828 : - 829 : /* if no disk, nothing to check */ - 830 351348 : if (!handle[j].disk) - 831 0 : continue; - 832 : - 833 351348 : block = fs_par2block_find(handle[j].disk, i); + 818 : /* now apply the filters */ + 819 : + 820 : /* if a parity is not excluded, include all blocks, even unused ones */ + 821 2125818 : for (l = 0; l < state->level; ++l) { + 822 2042438 : if (!state->parity[l].is_excluded_by_filter) { + 823 1772374 : return 1; + 824 : } + 825 : } + 826 : + 827 : /* otherwise include only used blocks */ + 828 386636 : for (j = 0; j < diskmax; ++j) { + 829 : struct snapraid_block* block; + 830 : + 831 : /* if no disk, nothing to check */ + 832 351348 : if (!handle[j].disk) + 833 0 : continue; 834 : - 835 : /* try to recover all files, even the ones without hash */ - 836 : /* because in some cases we can recover also them */ - 837 351348 : if (block_has_file(block)) { - 838 344686 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); - 839 344686 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ - 840 48092 : return 1; - 841 : } - 842 : } - 843 : } - 844 : - 845 35288 : return 0; - 846 : } - 847 : - 848 118 : static int state_check_process(struct snapraid_state* state, int fix, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) - 849 : { - 850 : struct snapraid_handle* handle; - 851 : unsigned diskmax; - 852 : block_off_t i; - 853 : unsigned j; - 854 : void* buffer_alloc; - 855 : void** buffer; - 856 : unsigned buffermax; - 857 : int ret; - 858 : data_off_t countsize; - 859 : block_off_t countpos; - 860 : block_off_t countmax; - 861 : unsigned error; - 862 : unsigned unrecoverable_error; - 863 : unsigned recovered_error; - 864 : struct failed_struct* failed; - 865 : unsigned* failed_map; - 866 : unsigned l; - 867 : char esc_buffer[ESC_MAX]; - 868 : char esc_buffer_alt[ESC_MAX]; - 869 : - 870 118 : handle = handle_mapping(state, &diskmax); + 835 351348 : block = fs_par2block_find(handle[j].disk, i); + 836 : + 837 : /* try to recover all files, even the ones without hash */ + 838 : /* because in some cases we can recover also them */ + 839 351348 : if (block_has_file(block)) { + 840 344686 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); + 841 344686 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ + 842 48092 : return 1; + 843 : } + 844 : } + 845 : } + 846 : + 847 35288 : return 0; + 848 : } + 849 : + 850 118 : static int state_check_process(struct snapraid_state* state, int fix, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) + 851 : { + 852 : struct snapraid_handle* handle; + 853 : unsigned diskmax; + 854 : block_off_t i; + 855 : unsigned j; + 856 : void* buffer_alloc; + 857 : void** buffer; + 858 : unsigned buffermax; + 859 : int ret; + 860 : data_off_t countsize; + 861 : block_off_t countpos; + 862 : block_off_t countmax; + 863 : unsigned error; + 864 : unsigned unrecoverable_error; + 865 : unsigned recovered_error; + 866 : struct failed_struct* failed; + 867 : unsigned* failed_map; + 868 : unsigned l; + 869 : char esc_buffer[ESC_MAX]; + 870 : char esc_buffer_alt[ESC_MAX]; 871 : - 872 : /* we need 1 * data + 2 * parity + 1 * zero */ - 873 118 : buffermax = diskmax + 2 * state->level + 1; - 874 : - 875 118 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); - 876 118 : if (!state->opt.skip_self) - 877 0 : mtest_vector(buffermax, state->block_size, buffer); - 878 : - 879 : /* fill up the zero buffer */ - 880 118 : memset(buffer[buffermax - 1], 0, state->block_size); - 881 118 : raid_zero(buffer[buffermax - 1]); - 882 : - 883 118 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); - 884 118 : failed_map = malloc_nofail(diskmax * sizeof(unsigned)); - 885 : - 886 118 : error = 0; - 887 118 : unrecoverable_error = 0; - 888 118 : recovered_error = 0; - 889 : - 890 : /* first count the number of blocks to process */ - 891 118 : countmax = 0; - 892 935597 : for (i = blockstart; i < blockmax; ++i) { - 893 935479 : if (!block_is_enabled(state, i, handle, diskmax)) - 894 25246 : continue; - 895 910233 : ++countmax; - 896 : } - 897 : - 898 : /* check all the blocks in files */ - 899 118 : countsize = 0; - 900 118 : countpos = 0; - 901 118 : state_progress_begin(state, blockstart, blockmax, countmax); - 902 935597 : for (i = blockstart; i < blockmax; ++i) { - 903 : unsigned failed_count; - 904 : int valid_parity; - 905 : snapraid_info info; - 906 : int rehash; - 907 : - 908 935479 : if (!block_is_enabled(state, i, handle, diskmax)) { - 909 : /* post process the files */ - 910 25246 : ret = file_post(state, fix, i, handle, diskmax); - 911 25246 : if (ret == -1) { - 912 : /* LCOV_EXCL_START */ - 913 : log_fatal("Stopping at block %u\n", i); - 914 : ++unrecoverable_error; - 915 : goto bail; - 916 : /* LCOV_EXCL_STOP */ - 917 : } - 918 : - 919 : /* and now continue with the next block */ - 920 25246 : continue; - 921 : } - 922 : - 923 : /* If we have valid parity, and it makes sense to check its content. */ - 924 : /* If we already know that the parity is invalid, we just read the file */ - 925 : /* but we don't report parity errors */ - 926 : /* Note that with auditonly, we anyway skip the full parity check, */ - 927 : /* because we also don't read it at all */ - 928 910233 : valid_parity = 1; - 929 : - 930 : /* keep track of the number of failed blocks */ - 931 910233 : failed_count = 0; + 872 118 : handle = handle_mapping(state, &diskmax); + 873 : + 874 : /* we need 1 * data + 2 * parity + 1 * zero */ + 875 118 : buffermax = diskmax + 2 * state->level + 1; + 876 : + 877 118 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); + 878 118 : if (!state->opt.skip_self) + 879 0 : mtest_vector(buffermax, state->block_size, buffer); + 880 : + 881 : /* fill up the zero buffer */ + 882 118 : memset(buffer[buffermax - 1], 0, state->block_size); + 883 118 : raid_zero(buffer[buffermax - 1]); + 884 : + 885 118 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); + 886 118 : failed_map = malloc_nofail(diskmax * sizeof(unsigned)); + 887 : + 888 118 : error = 0; + 889 118 : unrecoverable_error = 0; + 890 118 : recovered_error = 0; + 891 : + 892 : /* first count the number of blocks to process */ + 893 118 : countmax = 0; + 894 935597 : for (i = blockstart; i < blockmax; ++i) { + 895 935479 : if (!block_is_enabled(state, i, handle, diskmax)) + 896 25246 : continue; + 897 910233 : ++countmax; + 898 : } + 899 : + 900 : /* check all the blocks in files */ + 901 118 : countsize = 0; + 902 118 : countpos = 0; + 903 118 : state_progress_begin(state, blockstart, blockmax, countmax); + 904 935597 : for (i = blockstart; i < blockmax; ++i) { + 905 : unsigned failed_count; + 906 : int valid_parity; + 907 : int used_parity; + 908 : snapraid_info info; + 909 : int rehash; + 910 : + 911 935479 : if (!block_is_enabled(state, i, handle, diskmax)) { + 912 : /* post process the files */ + 913 25246 : ret = file_post(state, fix, i, handle, diskmax); + 914 25246 : if (ret == -1) { + 915 : /* LCOV_EXCL_START */ + 916 : log_fatal("Stopping at block %u\n", i); + 917 : ++unrecoverable_error; + 918 : goto bail; + 919 : /* LCOV_EXCL_STOP */ + 920 : } + 921 : + 922 : /* and now continue with the next block */ + 923 25246 : continue; + 924 : } + 925 : + 926 : /* If we have valid parity, and it makes sense to check its content. */ + 927 : /* If we already know that the parity is invalid, we just read the file */ + 928 : /* but we don't report parity errors */ + 929 : /* Note that with auditonly, we anyway skip the full parity check, */ + 930 : /* because we also don't read it at all */ + 931 910233 : valid_parity = 1; 932 : - 933 : /* get block specific info */ - 934 910233 : info = info_get(&state->infoarr, i); + 933 : /* If the parity is used by at least one file */ + 934 910233 : used_parity = 0; 935 : - 936 : /* if we have to use the old hash */ - 937 910233 : rehash = info_get_rehash(info); + 936 : /* keep track of the number of failed blocks */ + 937 910233 : failed_count = 0; 938 : - 939 : /* for each disk, process the block */ - 940 6371631 : for (j = 0; j < diskmax; ++j) { - 941 : int read_size; - 942 : unsigned char hash[HASH_MAX]; - 943 : struct snapraid_disk* disk; - 944 : struct snapraid_block* block; - 945 : struct snapraid_file* file; - 946 : block_off_t file_pos; - 947 : unsigned block_state; - 948 : - 949 : /* if the disk position is not used */ - 950 5461398 : disk = handle[j].disk; - 951 5461398 : if (!disk) { - 952 : /* use an empty block */ - 953 14061 : memset(buffer[j], 0, state->block_size); - 954 954823 : continue; - 955 : } - 956 : - 957 : /* if the disk block is not used */ - 958 5447337 : block = fs_par2block_find(disk, i); - 959 5447337 : if (block == BLOCK_NULL) { - 960 : /* use an empty block */ - 961 192063 : memset(buffer[j], 0, state->block_size); - 962 192063 : continue; - 963 : } - 964 : - 965 : /* get the state of the block */ - 966 5255274 : block_state = block_state_get(block); - 967 : - 968 : /* if the parity is not valid */ - 969 5255274 : if (block_has_invalid_parity(block)) { - 970 : /* mark the parity as invalid, and don't try to check/fix it */ - 971 : /* because it will be recomputed at the next sync */ - 972 94587 : valid_parity = 0; - 973 : /* follow */ - 974 : } - 975 : - 976 : /* if the block is DELETED */ - 977 5255274 : if (block_state == BLOCK_STATE_DELETED) { - 978 : /* use an empty block */ - 979 18454 : memset(buffer[j], 0, state->block_size); - 980 : - 981 : /* store it in the failed set, because potentially */ - 982 : /* the parity may be still computed with the previous content */ - 983 18454 : failed[failed_count].is_bad = 0; /* note that is_bad==0 <=> file==0 */ - 984 18454 : failed[failed_count].is_outofdate = 0; - 985 18454 : failed[failed_count].index = j; - 986 18454 : failed[failed_count].block = block; - 987 18454 : failed[failed_count].disk = disk; - 988 18454 : failed[failed_count].file = 0; - 989 18454 : failed[failed_count].file_pos = 0; - 990 18454 : failed[failed_count].handle = 0; - 991 18454 : ++failed_count; - 992 18454 : continue; - 993 : } - 994 : - 995 : /* get the file of this block */ - 996 5236820 : file = fs_par2file_get(disk, i, &file_pos); - 997 : - 998 : /* if we are only hashing, we can skip excluded files and don't even read them */ - 999 5236820 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) { - 1000 : /* use an empty block */ - 1001 : /* in true, this is unnecessary, because we are not checking any parity */ - 1002 : /* but we keep it for completeness */ - 1003 0 : memset(buffer[j], 0, state->block_size); - 1004 0 : continue; - 1005 : } + 939 : /* get block specific info */ + 940 910233 : info = info_get(&state->infoarr, i); + 941 : + 942 : /* if we have to use the old hash */ + 943 910233 : rehash = info_get_rehash(info); + 944 : + 945 : /* for each disk, process the block */ + 946 6371631 : for (j = 0; j < diskmax; ++j) { + 947 : int read_size; + 948 : unsigned char hash[HASH_MAX]; + 949 : struct snapraid_disk* disk; + 950 : struct snapraid_block* block; + 951 : struct snapraid_file* file; + 952 : block_off_t file_pos; + 953 : unsigned block_state; + 954 : + 955 : /* if the disk position is not used */ + 956 5461398 : disk = handle[j].disk; + 957 5461398 : if (!disk) { + 958 : /* use an empty block */ + 959 14061 : memset(buffer[j], 0, state->block_size); + 960 955476 : continue; + 961 : } + 962 : + 963 : /* if the disk block is not used */ + 964 5447337 : block = fs_par2block_find(disk, i); + 965 5447337 : if (block == BLOCK_NULL) { + 966 : /* use an empty block */ + 967 192063 : memset(buffer[j], 0, state->block_size); + 968 192063 : continue; + 969 : } + 970 : + 971 : /* get the state of the block */ + 972 5255274 : block_state = block_state_get(block); + 973 : + 974 : /* if the parity is not valid */ + 975 5255274 : if (block_has_invalid_parity(block)) { + 976 : /* mark the parity as invalid, and don't try to check/fix it */ + 977 : /* because it will be recomputed at the next sync */ + 978 94587 : valid_parity = 0; + 979 : /* follow */ + 980 : } + 981 : + 982 : /* if the block is DELETED */ + 983 5255274 : if (block_state == BLOCK_STATE_DELETED) { + 984 : /* use an empty block */ + 985 18454 : memset(buffer[j], 0, state->block_size); + 986 : + 987 : /* store it in the failed set, because potentially */ + 988 : /* the parity may be still computed with the previous content */ + 989 18454 : failed[failed_count].is_bad = 0; /* note that is_bad==0 <=> file==0 */ + 990 18454 : failed[failed_count].is_outofdate = 0; + 991 18454 : failed[failed_count].index = j; + 992 18454 : failed[failed_count].block = block; + 993 18454 : failed[failed_count].disk = disk; + 994 18454 : failed[failed_count].file = 0; + 995 18454 : failed[failed_count].file_pos = 0; + 996 18454 : failed[failed_count].handle = 0; + 997 18454 : ++failed_count; + 998 18454 : continue; + 999 : } + 1000 : + 1001 : /* here we are sure that the parity is used by a file */ + 1002 5236820 : used_parity = 1; + 1003 : + 1004 : /* get the file of this block */ + 1005 5236820 : file = fs_par2file_get(disk, i, &file_pos); 1006 : - 1007 : /* if the file is closed or different than the current one */ - 1008 5236820 : if (handle[j].file == 0 || handle[j].file != file) { - 1009 : /* close the old one, if any */ - 1010 2259576 : ret = handle_close(&handle[j]); - 1011 2259576 : if (ret == -1) { - 1012 : /* LCOV_EXCL_START */ - 1013 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno)); - 1014 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); - 1015 : log_fatal("Stopping at block %u\n", i); - 1016 : ++unrecoverable_error; - 1017 : goto bail; - 1018 : /* LCOV_EXCL_STOP */ - 1019 : } - 1020 : - 1021 : /* if fixing, and the file is not excluded, we must open for writing */ - 1022 2259576 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { - 1023 : /* if fixing, create the file, open for writing and resize if required */ - 1024 771283 : ret = handle_create(&handle[j], file, state->file_mode); - 1025 771283 : if (ret == -1) { - 1026 : /* LCOV_EXCL_START */ - 1027 : if (errno == EACCES) { - 1028 : log_fatal("WARNING! Please give write permission to the file.\n"); - 1029 : } else { - 1030 : log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1031 : } - 1032 : log_fatal("Stopping at block %u\n", i); - 1033 : ++unrecoverable_error; - 1034 : goto bail; - 1035 : /* LCOV_EXCL_STOP */ - 1036 : } - 1037 : - 1038 : /* check if the file was just created */ - 1039 1542566 : if (handle[j].created != 0) { - 1040 : /* if fragmented, it may be reopened, so remember that the file */ - 1041 : /* was originally missing */ - 1042 113044 : file_flag_set(file, FILE_IS_CREATED); - 1043 : } - 1044 : } else { - 1045 : /* open the file only for reading */ - 1046 1488293 : if (!file_flag_has(file, FILE_IS_MISSING)) - 1047 1372856 : ret = handle_open(&handle[j], file, state->file_mode, - 1048 1372856 : log_error, state->opt.expected_missing ? log_expected : 0); - 1049 : else - 1050 115437 : ret = -1; /* if the file is missing, we cannot open it */ - 1051 1488293 : if (ret == -1) { - 1052 : /* save the failed block for the check/fix */ - 1053 194019 : failed[failed_count].is_bad = 1; - 1054 194019 : failed[failed_count].is_outofdate = 0; - 1055 194019 : failed[failed_count].index = j; - 1056 194019 : failed[failed_count].block = block; - 1057 194019 : failed[failed_count].disk = disk; - 1058 194019 : failed[failed_count].file = file; - 1059 194019 : failed[failed_count].file_pos = file_pos; - 1060 194019 : failed[failed_count].handle = &handle[j]; - 1061 194019 : ++failed_count; - 1062 : - 1063 194019 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); - 1064 194019 : ++error; - 1065 : - 1066 : /* mark the file as missing, to avoid to retry to open it again */ - 1067 : /* note that this can be done only if we are not fixing it */ - 1068 : /* otherwise, it could be recreated */ - 1069 194019 : file_flag_set(file, FILE_IS_MISSING); - 1070 194019 : continue; - 1071 : } - 1072 : } - 1073 : - 1074 : /* if it's the first open, and not excluded */ - 1075 2065557 : if (!file_flag_has(file, FILE_IS_OPENED) - 1076 2050191 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { - 1077 : - 1078 : /* check if the file is changed */ - 1079 1998760 : if (handle[j].st.st_size != file->size - 1080 1805894 : || handle[j].st.st_mtime != file->mtime_sec - 1081 1781363 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec - 1082 : /* don't check the inode to support file-system without persistent inodes */ - 1083 : ) { - 1084 : /* report that the file is not synced */ - 1085 217397 : file_flag_set(file, FILE_IS_UNSYNCED); - 1086 : } - 1087 : } - 1088 : - 1089 : /* if it's the first open, and not excluded and larger */ - 1090 2065557 : if (!file_flag_has(file, FILE_IS_OPENED) - 1091 2050191 : && !file_flag_has(file, FILE_IS_EXCLUDED) - 1092 1998760 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) - 1093 1998760 : && handle[j].st.st_size > file->size - 1094 : ) { - 1095 8819 : log_error("File '%s' is larger than expected.\n", handle[j].path); - 1096 8819 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); - 1097 8819 : ++error; - 1098 : - 1099 8819 : if (fix) { - 1100 3254 : ret = handle_truncate(&handle[j], file); - 1101 3254 : if (ret == -1) { - 1102 : /* LCOV_EXCL_START */ - 1103 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n"); - 1104 : log_fatal("Stopping at block %u\n", i); - 1105 : ++unrecoverable_error; - 1106 : goto bail; - 1107 : /* LCOV_EXCL_STOP */ - 1108 : } - 1109 : - 1110 3254 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer)); - 1111 3254 : ++recovered_error; - 1112 : } - 1113 : } - 1114 : - 1115 : /* mark the file as opened at least one time */ - 1116 : /* this is used to avoid to check the unsynced and size */ - 1117 : /* more than one time, in case the file is reopened later */ - 1118 2065557 : file_flag_set(file, FILE_IS_OPENED); - 1119 : } - 1120 : - 1121 : /* read from the file */ - 1122 5042801 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, - 1123 5042801 : log_error, state->opt.expected_missing ? log_expected : 0); - 1124 5042801 : if (read_size == -1) { - 1125 : /* save the failed block for the check/fix */ - 1126 442126 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ - 1127 442126 : failed[failed_count].is_outofdate = 0; - 1128 442126 : failed[failed_count].index = j; - 1129 442126 : failed[failed_count].block = block; - 1130 442126 : failed[failed_count].disk = disk; - 1131 442126 : failed[failed_count].file = file; - 1132 442126 : failed[failed_count].file_pos = file_pos; - 1133 442126 : failed[failed_count].handle = &handle[j]; - 1134 442126 : ++failed_count; - 1135 : - 1136 442126 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); - 1137 442126 : ++error; - 1138 442126 : continue; - 1139 : } - 1140 : - 1141 4600675 : countsize += read_size; - 1142 : - 1143 : /* always insert CHG blocks, the repair functions needs all of them */ - 1144 : /* because the parity may be still referring at the old state */ - 1145 : /* and the repair must be aware of it */ - 1146 4600675 : if (block_state == BLOCK_STATE_CHG) { - 1147 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */ - 1148 : /* if we don't have a hash, we always assume the first read of the block correct. */ - 1149 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ - 1150 13843 : failed[failed_count].is_outofdate = 0; - 1151 13843 : failed[failed_count].index = j; - 1152 13843 : failed[failed_count].block = block; - 1153 13843 : failed[failed_count].disk = disk; - 1154 13843 : failed[failed_count].file = file; - 1155 13843 : failed[failed_count].file_pos = file_pos; - 1156 13843 : failed[failed_count].handle = &handle[j]; - 1157 13843 : ++failed_count; - 1158 13843 : continue; - 1159 : } - 1160 : - 1161 4586832 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); - 1162 : - 1163 : /* compute the hash of the block just read */ - 1164 4586832 : if (rehash) { - 1165 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); - 1166 : } else { - 1167 4559589 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 1007 : /* if we are only hashing, we can skip excluded files and don't even read them */ + 1008 5236820 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) { + 1009 : /* use an empty block */ + 1010 : /* in true, this is unnecessary, because we are not checking any parity */ + 1011 : /* but we keep it for completeness */ + 1012 0 : memset(buffer[j], 0, state->block_size); + 1013 0 : continue; + 1014 : } + 1015 : + 1016 : /* if the file is closed or different than the current one */ + 1017 5236820 : if (handle[j].file == 0 || handle[j].file != file) { + 1018 : /* close the old one, if any */ + 1019 2259927 : ret = handle_close(&handle[j]); + 1020 2259927 : if (ret == -1) { + 1021 : /* LCOV_EXCL_START */ + 1022 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno)); + 1023 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); + 1024 : log_fatal("Stopping at block %u\n", i); + 1025 : ++unrecoverable_error; + 1026 : goto bail; + 1027 : /* LCOV_EXCL_STOP */ + 1028 : } + 1029 : + 1030 : /* if fixing, and the file is not excluded, we must open for writing */ + 1031 2259927 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1032 : /* if fixing, create the file, open for writing and resize if required */ + 1033 771310 : ret = handle_create(&handle[j], file, state->file_mode); + 1034 771310 : if (ret == -1) { + 1035 : /* LCOV_EXCL_START */ + 1036 : if (errno == EACCES) { + 1037 : log_fatal("WARNING! Please give write permission to the file.\n"); + 1038 : } else { + 1039 : log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1040 : } + 1041 : log_fatal("Stopping at block %u\n", i); + 1042 : ++unrecoverable_error; + 1043 : goto bail; + 1044 : /* LCOV_EXCL_STOP */ + 1045 : } + 1046 : + 1047 : /* check if the file was just created */ + 1048 1542620 : if (handle[j].created != 0) { + 1049 : /* if fragmented, it may be reopened, so remember that the file */ + 1050 : /* was originally missing */ + 1051 113118 : file_flag_set(file, FILE_IS_CREATED); + 1052 : } + 1053 : } else { + 1054 : /* open the file only for reading */ + 1055 1488617 : if (!file_flag_has(file, FILE_IS_MISSING)) + 1056 1372878 : ret = handle_open(&handle[j], file, state->file_mode, + 1057 1372878 : log_error, state->opt.expected_missing ? log_expected : 0); + 1058 : else + 1059 115739 : ret = -1; /* if the file is missing, we cannot open it */ + 1060 1488617 : if (ret == -1) { + 1061 : /* save the failed block for the check/fix */ + 1062 194514 : failed[failed_count].is_bad = 1; + 1063 194514 : failed[failed_count].is_outofdate = 0; + 1064 194514 : failed[failed_count].index = j; + 1065 194514 : failed[failed_count].block = block; + 1066 194514 : failed[failed_count].disk = disk; + 1067 194514 : failed[failed_count].file = file; + 1068 194514 : failed[failed_count].file_pos = file_pos; + 1069 194514 : failed[failed_count].handle = &handle[j]; + 1070 194514 : ++failed_count; + 1071 : + 1072 194514 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + 1073 194514 : ++error; + 1074 : + 1075 : /* mark the file as missing, to avoid to retry to open it again */ + 1076 : /* note that this can be done only if we are not fixing it */ + 1077 : /* otherwise, it could be recreated */ + 1078 194514 : file_flag_set(file, FILE_IS_MISSING); + 1079 194514 : continue; + 1080 : } + 1081 : } + 1082 : + 1083 : /* if it's the first open, and not excluded */ + 1084 2065413 : if (!file_flag_has(file, FILE_IS_OPENED) + 1085 2050030 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1086 : + 1087 : /* check if the file is changed */ + 1088 1998599 : if (handle[j].st.st_size != file->size + 1089 1805915 : || handle[j].st.st_mtime != file->mtime_sec + 1090 1781217 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec + 1091 : /* don't check the inode to support file-system without persistent inodes */ + 1092 : ) { + 1093 : /* report that the file is not synced */ + 1094 217382 : file_flag_set(file, FILE_IS_UNSYNCED); + 1095 : } + 1096 : } + 1097 : + 1098 : /* if it's the first open, and not excluded and larger */ + 1099 2065413 : if (!file_flag_has(file, FILE_IS_OPENED) + 1100 2050030 : && !file_flag_has(file, FILE_IS_EXCLUDED) + 1101 1998599 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) + 1102 1998599 : && handle[j].st.st_size > file->size + 1103 : ) { + 1104 8668 : log_error("File '%s' is larger than expected.\n", handle[j].path); + 1105 8668 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + 1106 8668 : ++error; + 1107 : + 1108 8668 : if (fix) { + 1109 3189 : ret = handle_truncate(&handle[j], file); + 1110 3189 : if (ret == -1) { + 1111 : /* LCOV_EXCL_START */ + 1112 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n"); + 1113 : log_fatal("Stopping at block %u\n", i); + 1114 : ++unrecoverable_error; + 1115 : goto bail; + 1116 : /* LCOV_EXCL_STOP */ + 1117 : } + 1118 : + 1119 3189 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + 1120 3189 : ++recovered_error; + 1121 : } + 1122 : } + 1123 : + 1124 : /* mark the file as opened at least one time */ + 1125 : /* this is used to avoid to check the unsynced and size */ + 1126 : /* more than one time, in case the file is reopened later */ + 1127 2065413 : file_flag_set(file, FILE_IS_OPENED); + 1128 : } + 1129 : + 1130 : /* read from the file */ + 1131 5042306 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, + 1132 5042306 : log_error, state->opt.expected_missing ? log_expected : 0); + 1133 5042306 : if (read_size == -1) { + 1134 : /* save the failed block for the check/fix */ + 1135 442190 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ + 1136 442190 : failed[failed_count].is_outofdate = 0; + 1137 442190 : failed[failed_count].index = j; + 1138 442190 : failed[failed_count].block = block; + 1139 442190 : failed[failed_count].disk = disk; + 1140 442190 : failed[failed_count].file = file; + 1141 442190 : failed[failed_count].file_pos = file_pos; + 1142 442190 : failed[failed_count].handle = &handle[j]; + 1143 442190 : ++failed_count; + 1144 : + 1145 442190 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + 1146 442190 : ++error; + 1147 442190 : continue; + 1148 : } + 1149 : + 1150 4600116 : countsize += read_size; + 1151 : + 1152 : /* always insert CHG blocks, the repair functions needs all of them */ + 1153 : /* because the parity may be still referring at the old state */ + 1154 : /* and the repair must be aware of it */ + 1155 4600116 : if (block_state == BLOCK_STATE_CHG) { + 1156 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */ + 1157 : /* if we don't have a hash, we always assume the first read of the block correct. */ + 1158 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ + 1159 13843 : failed[failed_count].is_outofdate = 0; + 1160 13843 : failed[failed_count].index = j; + 1161 13843 : failed[failed_count].block = block; + 1162 13843 : failed[failed_count].disk = disk; + 1163 13843 : failed[failed_count].file = file; + 1164 13843 : failed[failed_count].file_pos = file_pos; + 1165 13843 : failed[failed_count].handle = &handle[j]; + 1166 13843 : ++failed_count; + 1167 13843 : continue; 1168 : } 1169 : - 1170 : /* compare the hash */ - 1171 4586832 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { - 1172 12768 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); - 1173 : - 1174 : /* save the failed block for the check/fix */ - 1175 12768 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ - 1176 12768 : failed[failed_count].is_outofdate = 0; - 1177 12768 : failed[failed_count].index = j; - 1178 12768 : failed[failed_count].block = block; - 1179 12768 : failed[failed_count].disk = disk; - 1180 12768 : failed[failed_count].file = file; - 1181 12768 : failed[failed_count].file_pos = file_pos; - 1182 12768 : failed[failed_count].handle = &handle[j]; - 1183 12768 : ++failed_count; - 1184 : - 1185 12768 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff); - 1186 12768 : ++error; - 1187 12768 : continue; - 1188 : } - 1189 : - 1190 : /* always insert REP blocks, the repair functions needs all of them */ - 1191 : /* because the parity may be still referring at the old state */ - 1192 : /* and the repair must be aware of it */ - 1193 4574064 : if (block_state == BLOCK_STATE_REP) { - 1194 53428 : failed[failed_count].is_bad = 0; /* it's not bad */ - 1195 53428 : failed[failed_count].is_outofdate = 0; - 1196 53428 : failed[failed_count].index = j; - 1197 53428 : failed[failed_count].block = block; - 1198 53428 : failed[failed_count].disk = disk; - 1199 53428 : failed[failed_count].file = file; - 1200 53428 : failed[failed_count].file_pos = file_pos; - 1201 53428 : failed[failed_count].handle = &handle[j]; - 1202 53428 : ++failed_count; - 1203 53428 : continue; - 1204 : } - 1205 : } - 1206 : - 1207 : /* now read and check the parity if requested */ - 1208 910233 : if (!state->opt.auditonly) { - 1209 : void* buffer_recov[LEV_MAX]; - 1210 : void* buffer_zero; - 1211 : - 1212 : /* buffers for parity read and not computed */ - 1213 4170787 : for (l = 0; l < state->level; ++l) - 1214 3299829 : buffer_recov[l] = buffer[diskmax + state->level + l]; - 1215 2796877 : for (; l < LEV_MAX; ++l) - 1216 1925919 : buffer_recov[l] = 0; - 1217 : - 1218 : /* the zero buffer is the last one */ - 1219 870958 : buffer_zero = buffer[buffermax - 1]; + 1170 4586273 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 1171 : + 1172 : /* compute the hash of the block just read */ + 1173 4586273 : if (rehash) { + 1174 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); + 1175 : } else { + 1176 4559030 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 1177 : } + 1178 : + 1179 : /* compare the hash */ + 1180 4586273 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 1181 12862 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + 1182 : + 1183 : /* save the failed block for the check/fix */ + 1184 12862 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ + 1185 12862 : failed[failed_count].is_outofdate = 0; + 1186 12862 : failed[failed_count].index = j; + 1187 12862 : failed[failed_count].block = block; + 1188 12862 : failed[failed_count].disk = disk; + 1189 12862 : failed[failed_count].file = file; + 1190 12862 : failed[failed_count].file_pos = file_pos; + 1191 12862 : failed[failed_count].handle = &handle[j]; + 1192 12862 : ++failed_count; + 1193 : + 1194 12862 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8); + 1195 12862 : ++error; + 1196 12862 : continue; + 1197 : } + 1198 : + 1199 : /* always insert REP blocks, the repair functions needs all of them */ + 1200 : /* because the parity may be still referring at the old state */ + 1201 : /* and the repair must be aware of it */ + 1202 4573411 : if (block_state == BLOCK_STATE_REP) { + 1203 53428 : failed[failed_count].is_bad = 0; /* it's not bad */ + 1204 53428 : failed[failed_count].is_outofdate = 0; + 1205 53428 : failed[failed_count].index = j; + 1206 53428 : failed[failed_count].block = block; + 1207 53428 : failed[failed_count].disk = disk; + 1208 53428 : failed[failed_count].file = file; + 1209 53428 : failed[failed_count].file_pos = file_pos; + 1210 53428 : failed[failed_count].handle = &handle[j]; + 1211 53428 : ++failed_count; + 1212 53428 : continue; + 1213 : } + 1214 : } + 1215 : + 1216 : /* now read and check the parity if requested */ + 1217 910233 : if (!state->opt.auditonly) { + 1218 : void* buffer_recov[LEV_MAX]; + 1219 : void* buffer_zero; 1220 : - 1221 : /* read the parity */ - 1222 4170787 : for (l = 0; l < state->level; ++l) { - 1223 3299829 : if (parity[l]) { - 1224 3285927 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); - 1225 3285927 : if (ret == -1) { - 1226 11360 : buffer_recov[l] = 0; /* no parity to use */ - 1227 : - 1228 11360 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); - 1229 11360 : ++error; - 1230 : } - 1231 : } else { - 1232 13902 : buffer_recov[l] = 0; - 1233 : } - 1234 : } - 1235 : - 1236 : /* try all the recovering strategies */ - 1237 870958 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); - 1238 870958 : if (ret != 0) { - 1239 : /* increment the number of errors */ - 1240 47935 : if (ret > 0) - 1241 4811 : error += ret; - 1242 47935 : ++unrecoverable_error; - 1243 : - 1244 : /* print a list of all the errors in files */ - 1245 219126 : for (j = 0; j < failed_count; ++j) { - 1246 171191 : if (failed[j].is_bad) - 1247 166669 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); - 1248 : } - 1249 : - 1250 : /* keep track of damaged files */ - 1251 219126 : for (j = 0; j < failed_count; ++j) { - 1252 171191 : if (failed[j].is_bad) - 1253 166669 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); - 1254 : } - 1255 : } else { - 1256 : /* now counts partial recovers */ - 1257 : /* note that this could happen only when we have an incomplete 'sync' */ - 1258 : /* and that we have recovered is the state before the 'sync' */ - 1259 823023 : int partial_recover_error = 0; - 1260 : - 1261 : /* print a list of all the errors in files */ - 1262 1380653 : for (j = 0; j < failed_count; ++j) { - 1263 557630 : if (failed[j].is_bad && failed[j].is_outofdate) { - 1264 8 : ++partial_recover_error; - 1265 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); - 1266 : } - 1267 : } - 1268 823023 : if (partial_recover_error != 0) { - 1269 8 : error += partial_recover_error; - 1270 8 : ++unrecoverable_error; - 1271 : } - 1272 : - 1273 : /* now check parities, but only if all the blocks have it computed */ - 1274 : /* if you check/fix after a partial sync, it's OK to have parity errors on the blocks with invalid parity */ - 1275 : /* and doesn't make sense to try to fix it */ - 1276 823023 : if (valid_parity) { - 1277 : /* check the parity */ - 1278 3728946 : for (l = 0; l < state->level; ++l) { - 1279 2967508 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { - 1280 78680 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); + 1221 : /* buffers for parity read and not computed */ + 1222 4170787 : for (l = 0; l < state->level; ++l) + 1223 3299829 : buffer_recov[l] = buffer[diskmax + state->level + l]; + 1224 2796877 : for (; l < LEV_MAX; ++l) + 1225 1925919 : buffer_recov[l] = 0; + 1226 : + 1227 : /* the zero buffer is the last one */ + 1228 870958 : buffer_zero = buffer[buffermax - 1]; + 1229 : + 1230 : /* read the parity */ + 1231 4170787 : for (l = 0; l < state->level; ++l) { + 1232 3299829 : if (parity[l]) { + 1233 3285927 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); + 1234 3285927 : if (ret == -1) { + 1235 11360 : buffer_recov[l] = 0; /* no parity to use */ + 1236 : + 1237 11360 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); + 1238 11360 : ++error; + 1239 : } + 1240 : } else { + 1241 13902 : buffer_recov[l] = 0; + 1242 : } + 1243 : } + 1244 : + 1245 : /* try all the recovering strategies */ + 1246 870958 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); + 1247 870958 : if (ret != 0) { + 1248 : /* increment the number of errors */ + 1249 48016 : if (ret > 0) + 1250 4801 : error += ret; + 1251 48016 : ++unrecoverable_error; + 1252 : + 1253 : /* print a list of all the errors in files */ + 1254 219379 : for (j = 0; j < failed_count; ++j) { + 1255 171363 : if (failed[j].is_bad) + 1256 166841 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + 1257 : } + 1258 : + 1259 : /* keep track of damaged files */ + 1260 219379 : for (j = 0; j < failed_count; ++j) { + 1261 171363 : if (failed[j].is_bad) + 1262 166841 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1263 : } + 1264 : } else { + 1265 : /* now counts partial recovers */ + 1266 : /* note that this could happen only when we have an incomplete 'sync' */ + 1267 : /* and that we have recovered is the state before the 'sync' */ + 1268 822942 : int partial_recover_error = 0; + 1269 : + 1270 : /* print a list of all the errors in files */ + 1271 1380844 : for (j = 0; j < failed_count; ++j) { + 1272 557902 : if (failed[j].is_bad && failed[j].is_outofdate) { + 1273 8 : ++partial_recover_error; + 1274 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + 1275 : } + 1276 : } + 1277 822942 : if (partial_recover_error != 0) { + 1278 8 : error += partial_recover_error; + 1279 8 : ++unrecoverable_error; + 1280 : } 1281 : - 1282 : /* mark that the read parity is wrong, setting ptr to 0 */ - 1283 78680 : buffer_recov[l] = 0; - 1284 : - 1285 78680 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff); - 1286 78680 : ++error; - 1287 : } - 1288 : } - 1289 : } - 1290 : - 1291 : /* now write recovered files */ - 1292 823023 : if (fix) { - 1293 : /* update the fixed files */ - 1294 652640 : for (j = 0; j < failed_count; ++j) { - 1295 : /* nothing to do if it doesn't need recovering */ - 1296 337975 : if (!failed[j].is_bad) - 1297 40318 : continue; - 1298 : - 1299 : /* do not fix if the file is excluded */ - 1300 297657 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) - 1301 288377 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) - 1302 9280 : continue; - 1303 : - 1304 288377 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); - 1305 288377 : if (ret == -1) { - 1306 : /* LCOV_EXCL_START */ - 1307 : /* mark the file as damaged */ - 1308 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); - 1309 : - 1310 : if (errno == EACCES) { - 1311 : log_fatal("WARNING! Please give write permission to the file.\n"); - 1312 : } else { - 1313 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1314 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1315 : } - 1316 : log_fatal("Stopping at block %u\n", i); - 1317 : ++unrecoverable_error; - 1318 : goto bail; - 1319 : /* LCOV_EXCL_STOP */ - 1320 : } - 1321 : - 1322 : /* if we are not sure that the recovered content is uptodate */ - 1323 288377 : if (failed[j].is_outofdate) { - 1324 : /* mark the file as damaged */ - 1325 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); - 1326 8 : continue; - 1327 : } - 1328 : - 1329 : /* mark the file as containing some fixes */ - 1330 : /* note that it could be also marked as damaged in other iterations */ - 1331 288369 : file_flag_set(failed[j].file, FILE_IS_FIXED); - 1332 : - 1333 288369 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); - 1334 288369 : ++recovered_error; - 1335 : } + 1282 : /* + 1283 : * Check parities, but only if all the blocks have it computed and it's used. + 1284 : * + 1285 : * If you check/fix after a partial sync, it's OK to have parity errors + 1286 : * on the blocks with invalid parity and doesn't make sense to try to fix it. + 1287 : * + 1288 : * It's also OK to have data errors on unused parity, because sync doesn't + 1289 : * update it. + 1290 : */ + 1291 822942 : if (used_parity && valid_parity) { + 1292 : /* check the parity */ + 1293 3728784 : for (l = 0; l < state->level; ++l) { + 1294 2967427 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { + 1295 78690 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); + 1296 : + 1297 : /* mark that the read parity is wrong, setting ptr to 0 */ + 1298 78690 : buffer_recov[l] = 0; + 1299 : + 1300 78690 : log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", i, lev_config_name(l), diff, state->block_size*8); + 1301 78690 : ++error; + 1302 : } + 1303 : } + 1304 : } + 1305 : + 1306 : /* now write recovered files */ + 1307 822942 : if (fix) { + 1308 : /* update the fixed files */ + 1309 652736 : for (j = 0; j < failed_count; ++j) { + 1310 : /* nothing to do if it doesn't need recovering */ + 1311 338113 : if (!failed[j].is_bad) + 1312 40318 : continue; + 1313 : + 1314 : /* do not fix if the file is excluded */ + 1315 297795 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) + 1316 288515 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) + 1317 9280 : continue; + 1318 : + 1319 288515 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); + 1320 288515 : if (ret == -1) { + 1321 : /* LCOV_EXCL_START */ + 1322 : /* mark the file as damaged */ + 1323 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1324 : + 1325 : if (errno == EACCES) { + 1326 : log_fatal("WARNING! Please give write permission to the file.\n"); + 1327 : } else { + 1328 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1329 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1330 : } + 1331 : log_fatal("Stopping at block %u\n", i); + 1332 : ++unrecoverable_error; + 1333 : goto bail; + 1334 : /* LCOV_EXCL_STOP */ + 1335 : } 1336 : - 1337 : /* update parity only if all the blocks have it computed */ - 1338 : /* if you check/fix after a partial sync, you do not want to fix parity */ - 1339 : /* for blocks that are going to have it computed in the sync completion */ - 1340 314665 : if (valid_parity) { - 1341 : /* update the parity */ - 1342 964055 : for (l = 0; l < state->level; ++l) { - 1343 : /* if the parity on disk is wrong */ - 1344 698570 : if (buffer_recov[l] == 0 - 1345 : /* and we have access at the parity */ - 1346 72150 : && parity[l] != 0 - 1347 : /* and the parity is not excluded */ - 1348 67463 : && !state->parity[l].is_excluded - 1349 : ) { - 1350 67463 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); - 1351 67463 : if (ret == -1) { - 1352 : /* LCOV_EXCL_START */ - 1353 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1354 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l)); - 1355 : log_fatal("Stopping at block %u\n", i); - 1356 : ++unrecoverable_error; - 1357 : goto bail; - 1358 : /* LCOV_EXCL_STOP */ - 1359 : } - 1360 : - 1361 67463 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); - 1362 67463 : ++recovered_error; - 1363 : } - 1364 : } - 1365 : } - 1366 : } else { - 1367 : /* if we are not fixing, we just set the FIXED flag */ - 1368 : /* meaning that we could fix this file if we try */ - 1369 728013 : for (j = 0; j < failed_count; ++j) { - 1370 219655 : if (failed[j].is_bad) { - 1371 178770 : file_flag_set(failed[j].file, FILE_IS_FIXED); - 1372 : } - 1373 : } - 1374 : } - 1375 : } - 1376 : } else { - 1377 : /* if we are not checking, we just set the DAMAGED flag */ - 1378 : /* to report that the file is damaged, and we don't know if we can fix it */ - 1379 45092 : for (j = 0; j < failed_count; ++j) { - 1380 5817 : if (failed[j].is_bad) { - 1381 5817 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); - 1382 : } - 1383 : } - 1384 : } - 1385 : - 1386 : /* post process the files */ - 1387 910233 : ret = file_post(state, fix, i, handle, diskmax); - 1388 910233 : if (ret == -1) { - 1389 : /* LCOV_EXCL_START */ - 1390 : log_fatal("Stopping at block %u\n", i); - 1391 : ++unrecoverable_error; - 1392 : goto bail; - 1393 : /* LCOV_EXCL_STOP */ - 1394 : } - 1395 : - 1396 : /* count the number of processed block */ - 1397 910233 : ++countpos; - 1398 : - 1399 : /* progress */ - 1400 910233 : if (state_progress(state, 0, i, countpos, countmax, countsize)) { - 1401 : /* LCOV_EXCL_START */ - 1402 : break; - 1403 : /* LCOV_EXCL_STOP */ - 1404 : } - 1405 : } - 1406 : - 1407 : /* for each disk, recover empty files, symlinks and empty dirs */ - 1408 826 : for (i = 0; i < diskmax; ++i) { - 1409 : tommy_node* node; - 1410 : struct snapraid_disk* disk; - 1411 : - 1412 708 : if (!handle[i].disk) - 1413 3 : continue; - 1414 : - 1415 : /* for each empty file in the disk */ - 1416 705 : disk = handle[i].disk; - 1417 705 : node = disk->filelist; - 1418 2189135 : while (node) { - 1419 : char path[PATH_MAX]; - 1420 : struct stat st; - 1421 : struct snapraid_file* file; - 1422 2187725 : int unsuccesful = 0; - 1423 : - 1424 2187725 : file = node->data; - 1425 2187725 : node = node->next; /* next node */ - 1426 : - 1427 : /* if not empty, it's already checked and continue to the next one */ - 1428 2187725 : if (file->size != 0) { - 1429 4369715 : continue; - 1430 : } - 1431 : - 1432 : /* if excluded continue to the next one */ - 1433 2952 : if (file_flag_has(file, FILE_IS_EXCLUDED)) { - 1434 169 : continue; - 1435 : } + 1337 : /* if we are not sure that the recovered content is uptodate */ + 1338 288515 : if (failed[j].is_outofdate) { + 1339 : /* mark the file as damaged */ + 1340 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1341 8 : continue; + 1342 : } + 1343 : + 1344 : /* mark the file as containing some fixes */ + 1345 : /* note that it could be also marked as damaged in other iterations */ + 1346 288507 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1347 : + 1348 288507 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + 1349 288507 : ++recovered_error; + 1350 : } + 1351 : + 1352 : /* + 1353 : * Update parity only if all the blocks have it computed and it's used. + 1354 : * + 1355 : * If you check/fix after a partial sync, you do not want to fix parity + 1356 : * for blocks that are going to have it computed in the sync completion. + 1357 : * + 1358 : * For unused parity there is no need to write it, because when fixing + 1359 : * we already have allocated space for it on parity file creation, + 1360 : * and its content doesn't matter. + 1361 : */ + 1362 314623 : if (used_parity && valid_parity) { + 1363 : /* update the parity */ + 1364 963971 : for (l = 0; l < state->level; ++l) { + 1365 : /* if the parity on disk is wrong */ + 1366 698528 : if (buffer_recov[l] == 0 + 1367 : /* and we have access at the parity */ + 1368 72150 : && parity[l] != 0 + 1369 : /* and the parity is not excluded */ + 1370 67463 : && !state->parity[l].is_excluded_by_filter + 1371 : ) { + 1372 67463 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); + 1373 67463 : if (ret == -1) { + 1374 : /* LCOV_EXCL_START */ + 1375 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1376 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l)); + 1377 : log_fatal("Stopping at block %u\n", i); + 1378 : ++unrecoverable_error; + 1379 : goto bail; + 1380 : /* LCOV_EXCL_STOP */ + 1381 : } + 1382 : + 1383 67463 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); + 1384 67463 : ++recovered_error; + 1385 : } + 1386 : } + 1387 : } + 1388 : } else { + 1389 : /* if we are not fixing, we just set the FIXED flag */ + 1390 : /* meaning that we could fix this file if we try */ + 1391 728108 : for (j = 0; j < failed_count; ++j) { + 1392 219789 : if (failed[j].is_bad) { + 1393 178904 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1394 : } + 1395 : } + 1396 : } + 1397 : } + 1398 : } else { + 1399 : /* if we are not checking, we just set the DAMAGED flag */ + 1400 : /* to report that the file is damaged, and we don't know if we can fix it */ + 1401 45301 : for (j = 0; j < failed_count; ++j) { + 1402 6026 : if (failed[j].is_bad) { + 1403 6026 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1404 : } + 1405 : } + 1406 : } + 1407 : + 1408 : /* post process the files */ + 1409 910233 : ret = file_post(state, fix, i, handle, diskmax); + 1410 910233 : if (ret == -1) { + 1411 : /* LCOV_EXCL_START */ + 1412 : log_fatal("Stopping at block %u\n", i); + 1413 : ++unrecoverable_error; + 1414 : goto bail; + 1415 : /* LCOV_EXCL_STOP */ + 1416 : } + 1417 : + 1418 : /* count the number of processed block */ + 1419 910233 : ++countpos; + 1420 : + 1421 : /* progress */ + 1422 910233 : if (state_progress(state, 0, i, countpos, countmax, countsize)) { + 1423 : /* LCOV_EXCL_START */ + 1424 : break; + 1425 : /* LCOV_EXCL_STOP */ + 1426 : } + 1427 : } + 1428 : + 1429 : /* for each disk, recover empty files, symlinks and empty dirs */ + 1430 826 : for (i = 0; i < diskmax; ++i) { + 1431 : tommy_node* node; + 1432 : struct snapraid_disk* disk; + 1433 : + 1434 708 : if (!handle[i].disk) + 1435 3 : continue; 1436 : - 1437 : /* stat the file */ - 1438 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); - 1439 2783 : ret = stat(path, &st); - 1440 2783 : if (ret == -1) { - 1441 179 : unsuccesful = 1; - 1442 : - 1443 179 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); - 1444 179 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1445 179 : ++error; - 1446 2604 : } else if (!S_ISREG(st.st_mode)) { - 1447 0 : unsuccesful = 1; + 1437 : /* for each empty file in the disk */ + 1438 705 : disk = handle[i].disk; + 1439 705 : node = disk->filelist; + 1440 2189135 : while (node) { + 1441 : char path[PATH_MAX]; + 1442 : struct stat st; + 1443 : struct snapraid_file* file; + 1444 2187725 : int unsuccesful = 0; + 1445 : + 1446 2187725 : file = node->data; + 1447 2187725 : node = node->next; /* next node */ 1448 : - 1449 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1450 0 : ++error; - 1451 2604 : } else if (st.st_size != 0) { - 1452 6 : unsuccesful = 1; + 1449 : /* if not empty, it's already checked and continue to the next one */ + 1450 2187725 : if (file->size != 0) { + 1451 4369715 : continue; + 1452 : } 1453 : - 1454 6 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), st.st_size); - 1455 6 : ++error; - 1456 : } - 1457 : - 1458 2783 : if (fix && unsuccesful) { - 1459 : int f; - 1460 : - 1461 : /* create the ancestor directories */ - 1462 159 : ret = mkancestor(path); - 1463 159 : if (ret != 0) { - 1464 : /* LCOV_EXCL_START */ - 1465 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1466 : log_fatal("Stopping\n"); - 1467 : ++unrecoverable_error; - 1468 : goto bail; - 1469 : /* LCOV_EXCL_STOP */ - 1470 : } - 1471 : - 1472 : /* create it */ - 1473 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ - 1474 159 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); - 1475 159 : if (f == -1) { - 1476 : /* LCOV_EXCL_START */ - 1477 : log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno)); - 1478 : if (errno == EACCES) { - 1479 : log_fatal("WARNING! Please give write permission to the file.\n"); - 1480 : } else { - 1481 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1482 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1483 : } - 1484 : log_fatal("Stopping\n"); - 1485 : ++unrecoverable_error; - 1486 : goto bail; - 1487 : /* LCOV_EXCL_STOP */ - 1488 : } - 1489 : - 1490 : /* set the original modification time */ - 1491 159 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec); - 1492 159 : if (ret != 0) { - 1493 : /* LCOV_EXCL_START */ - 1494 : close(f); - 1495 : - 1496 : log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno)); - 1497 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1498 : log_fatal("Stopping\n"); - 1499 : ++unrecoverable_error; - 1500 : goto bail; - 1501 : /* LCOV_EXCL_STOP */ - 1502 : } - 1503 : - 1504 : /* close it */ - 1505 159 : ret = close(f); - 1506 159 : if (ret != 0) { - 1507 : /* LCOV_EXCL_START */ - 1508 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1509 : log_fatal("Stopping\n"); - 1510 : ++unrecoverable_error; - 1511 : goto bail; - 1512 : /* LCOV_EXCL_STOP */ - 1513 : } - 1514 : - 1515 159 : log_tag("fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1516 159 : ++recovered_error; + 1454 : /* if excluded continue to the next one */ + 1455 2952 : if (file_flag_has(file, FILE_IS_EXCLUDED)) { + 1456 169 : continue; + 1457 : } + 1458 : + 1459 : /* stat the file */ + 1460 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + 1461 2783 : ret = stat(path, &st); + 1462 2783 : if (ret == -1) { + 1463 171 : unsuccesful = 1; + 1464 : + 1465 171 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); + 1466 171 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1467 171 : ++error; + 1468 2612 : } else if (!S_ISREG(st.st_mode)) { + 1469 0 : unsuccesful = 1; + 1470 : + 1471 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1472 0 : ++error; + 1473 2612 : } else if (st.st_size != 0) { + 1474 9 : unsuccesful = 1; + 1475 : + 1476 9 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), st.st_size); + 1477 9 : ++error; + 1478 : } + 1479 : + 1480 2783 : if (fix && unsuccesful) { + 1481 : int f; + 1482 : + 1483 : /* create the ancestor directories */ + 1484 158 : ret = mkancestor(path); + 1485 158 : if (ret != 0) { + 1486 : /* LCOV_EXCL_START */ + 1487 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1488 : log_fatal("Stopping\n"); + 1489 : ++unrecoverable_error; + 1490 : goto bail; + 1491 : /* LCOV_EXCL_STOP */ + 1492 : } + 1493 : + 1494 : /* create it */ + 1495 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ + 1496 158 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); + 1497 158 : if (f == -1) { + 1498 : /* LCOV_EXCL_START */ + 1499 : log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno)); + 1500 : if (errno == EACCES) { + 1501 : log_fatal("WARNING! Please give write permission to the file.\n"); + 1502 : } else { + 1503 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1504 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1505 : } + 1506 : log_fatal("Stopping\n"); + 1507 : ++unrecoverable_error; + 1508 : goto bail; + 1509 : /* LCOV_EXCL_STOP */ + 1510 : } + 1511 : + 1512 : /* set the original modification time */ + 1513 158 : ret = fmtime(f, file->mtime_sec, file->mtime_nsec); + 1514 158 : if (ret != 0) { + 1515 : /* LCOV_EXCL_START */ + 1516 : close(f); 1517 : - 1518 159 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); - 1519 159 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); - 1520 : } - 1521 : } - 1522 : - 1523 : /* for each link in the disk */ - 1524 705 : disk = handle[i].disk; - 1525 705 : node = disk->linklist; - 1526 71537 : while (node) { - 1527 : char path[PATH_MAX]; - 1528 : char pathto[PATH_MAX]; - 1529 : char linkto[PATH_MAX]; - 1530 : struct stat st; - 1531 : struct stat stto; - 1532 : struct snapraid_link* slink; - 1533 70127 : int unsuccesful = 0; - 1534 70127 : int unrecoverable = 0; - 1535 : - 1536 70127 : slink = node->data; - 1537 70127 : node = node->next; /* next node */ - 1538 : - 1539 : /* if excluded continue to the next one */ - 1540 70127 : if (link_flag_has(slink, FILE_IS_EXCLUDED)) { - 1541 3277 : continue; + 1518 : log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno)); + 1519 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1520 : log_fatal("Stopping\n"); + 1521 : ++unrecoverable_error; + 1522 : goto bail; + 1523 : /* LCOV_EXCL_STOP */ + 1524 : } + 1525 : + 1526 : /* close it */ + 1527 158 : ret = close(f); + 1528 158 : if (ret != 0) { + 1529 : /* LCOV_EXCL_START */ + 1530 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1531 : log_fatal("Stopping\n"); + 1532 : ++unrecoverable_error; + 1533 : goto bail; + 1534 : /* LCOV_EXCL_STOP */ + 1535 : } + 1536 : + 1537 158 : log_tag("fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1538 158 : ++recovered_error; + 1539 : + 1540 158 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + 1541 158 : msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); 1542 : } - 1543 : - 1544 66850 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { - 1545 : /* stat the link */ - 1546 318 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); - 1547 318 : ret = stat(path, &st); - 1548 318 : if (ret == -1) { - 1549 36 : unsuccesful = 1; - 1550 : - 1551 36 : log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno)); - 1552 36 : log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - 1553 36 : ++error; - 1554 282 : } else if (!S_ISREG(st.st_mode)) { - 1555 0 : unsuccesful = 1; - 1556 : - 1557 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - 1558 0 : ++error; - 1559 : } + 1543 : } + 1544 : + 1545 : /* for each link in the disk */ + 1546 705 : disk = handle[i].disk; + 1547 705 : node = disk->linklist; + 1548 71537 : while (node) { + 1549 : char path[PATH_MAX]; + 1550 : char pathto[PATH_MAX]; + 1551 : char linkto[PATH_MAX]; + 1552 : struct stat st; + 1553 : struct stat stto; + 1554 : struct snapraid_link* slink; + 1555 70127 : int unsuccesful = 0; + 1556 70127 : int unrecoverable = 0; + 1557 : + 1558 70127 : slink = node->data; + 1559 70127 : node = node->next; /* next node */ 1560 : - 1561 : /* stat the "to" file */ - 1562 318 : pathprint(pathto, sizeof(pathto), "%s%s", disk->dir, slink->linkto); - 1563 318 : ret = stat(pathto, &stto); - 1564 318 : if (ret == -1) { - 1565 24 : unsuccesful = 1; - 1566 : - 1567 24 : if (errno == ENOENT) { - 1568 24 : unrecoverable = 1; - 1569 24 : if (fix) { - 1570 : /* if the target doesn't exist, it's unrecoverable */ - 1571 : /* because we cannot create an hardlink of a file that */ - 1572 : /* doesn't exists */ - 1573 12 : ++unrecoverable_error; - 1574 : } else { - 1575 : /* but in check, we can assume that fixing will recover */ - 1576 : /* such missing file, so we assume a less drastic error */ - 1577 12 : ++error; - 1578 : } - 1579 : } - 1580 : - 1581 24 : log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno)); - 1582 24 : log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - 1583 24 : ++error; - 1584 294 : } else if (!S_ISREG(stto.st_mode)) { - 1585 0 : unsuccesful = 1; - 1586 : - 1587 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - 1588 0 : ++error; - 1589 294 : } else if (!unsuccesful && st.st_ino != stto.st_ino) { - 1590 0 : unsuccesful = 1; - 1591 : - 1592 0 : log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto); - 1593 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - 1594 0 : ++error; - 1595 : } - 1596 : } else { - 1597 : /* read the symlink */ - 1598 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); - 1599 66532 : ret = readlink(path, linkto, sizeof(linkto)); - 1600 66532 : if (ret < 0) { - 1601 4278 : unsuccesful = 1; + 1561 : /* if excluded continue to the next one */ + 1562 70127 : if (link_flag_has(slink, FILE_IS_EXCLUDED)) { + 1563 3277 : continue; + 1564 : } + 1565 : + 1566 66850 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { + 1567 : /* stat the link */ + 1568 318 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); + 1569 318 : ret = stat(path, &st); + 1570 318 : if (ret == -1) { + 1571 36 : unsuccesful = 1; + 1572 : + 1573 36 : log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno)); + 1574 36 : log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + 1575 36 : ++error; + 1576 282 : } else if (!S_ISREG(st.st_mode)) { + 1577 0 : unsuccesful = 1; + 1578 : + 1579 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + 1580 0 : ++error; + 1581 : } + 1582 : + 1583 : /* stat the "to" file */ + 1584 318 : pathprint(pathto, sizeof(pathto), "%s%s", disk->dir, slink->linkto); + 1585 318 : ret = stat(pathto, &stto); + 1586 318 : if (ret == -1) { + 1587 24 : unsuccesful = 1; + 1588 : + 1589 24 : if (errno == ENOENT) { + 1590 24 : unrecoverable = 1; + 1591 24 : if (fix) { + 1592 : /* if the target doesn't exist, it's unrecoverable */ + 1593 : /* because we cannot create an hardlink of a file that */ + 1594 : /* doesn't exists */ + 1595 12 : ++unrecoverable_error; + 1596 : } else { + 1597 : /* but in check, we can assume that fixing will recover */ + 1598 : /* such missing file, so we assume a less drastic error */ + 1599 12 : ++error; + 1600 : } + 1601 : } 1602 : - 1603 4278 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); - 1604 4278 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); - 1605 4278 : ++error; - 1606 62254 : } else if (ret >= PATH_MAX) { + 1603 24 : log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno)); + 1604 24 : log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + 1605 24 : ++error; + 1606 294 : } else if (!S_ISREG(stto.st_mode)) { 1607 0 : unsuccesful = 1; 1608 : - 1609 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path); - 1610 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); - 1611 0 : ++error; - 1612 : } else { - 1613 62254 : linkto[ret] = 0; - 1614 : - 1615 62254 : if (strcmp(linkto, slink->linkto) != 0) { - 1616 555 : unsuccesful = 1; - 1617 : - 1618 555 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto); - 1619 555 : ++error; - 1620 : } - 1621 : } - 1622 : } - 1623 : - 1624 66850 : if (fix && unsuccesful && !unrecoverable) { - 1625 : /* create the ancestor directories */ - 1626 3941 : ret = mkancestor(path); - 1627 3941 : if (ret != 0) { - 1628 : /* LCOV_EXCL_START */ - 1629 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1630 : log_fatal("Stopping\n"); - 1631 : ++unrecoverable_error; - 1632 : goto bail; - 1633 : /* LCOV_EXCL_STOP */ - 1634 : } - 1635 : - 1636 : /* if it exists, it must be deleted before recreating */ - 1637 3941 : ret = remove(path); - 1638 3941 : if (ret != 0 && errno != ENOENT) { - 1639 : /* LCOV_EXCL_START */ - 1640 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); - 1641 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1642 : log_fatal("Stopping\n"); - 1643 : ++unrecoverable_error; - 1644 : goto bail; - 1645 : /* LCOV_EXCL_STOP */ - 1646 : } - 1647 : - 1648 : /* create it */ - 1649 3941 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { - 1650 12 : ret = hardlink(pathto, path); - 1651 12 : if (ret != 0) { - 1652 : /* LCOV_EXCL_START */ - 1653 : log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno)); - 1654 : if (errno == EACCES) { - 1655 : log_fatal("WARNING! Please give write permission to the hardlink.\n"); - 1656 : } else { - 1657 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1658 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1659 : } - 1660 : log_fatal("Stopping\n"); - 1661 : ++unrecoverable_error; - 1662 : goto bail; - 1663 : /* LCOV_EXCL_STOP */ - 1664 : } - 1665 : - 1666 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); - 1667 12 : ++recovered_error; - 1668 : } else { - 1669 3929 : ret = symlink(slink->linkto, path); - 1670 3929 : if (ret != 0) { - 1671 : /* LCOV_EXCL_START */ - 1672 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno)); - 1673 : if (errno == EACCES) { - 1674 : log_fatal("WARNING! Please give write permission to the symlink.\n"); - 1675 : } else { - 1676 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1677 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1678 : } - 1679 : log_fatal("Stopping\n"); - 1680 : ++unrecoverable_error; - 1681 : goto bail; - 1682 : /* LCOV_EXCL_STOP */ - 1683 : } - 1684 : - 1685 3929 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); - 1686 3929 : ++recovered_error; - 1687 : } - 1688 : - 1689 3941 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); - 1690 3941 : msg_info("recovered %s\n", fmt_term(disk, slink->sub, esc_buffer)); - 1691 : } - 1692 : } - 1693 : - 1694 : /* for each dir in the disk */ - 1695 705 : disk = handle[i].disk; - 1696 705 : node = disk->dirlist; - 1697 1850 : while (node) { - 1698 : char path[PATH_MAX]; - 1699 : struct stat st; - 1700 : struct snapraid_dir* dir; - 1701 440 : int unsuccesful = 0; - 1702 : - 1703 440 : dir = node->data; - 1704 440 : node = node->next; /* next node */ - 1705 : - 1706 : /* if excluded continue to the next one */ - 1707 440 : if (dir_flag_has(dir, FILE_IS_EXCLUDED)) { - 1708 19 : continue; - 1709 : } + 1609 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + 1610 0 : ++error; + 1611 294 : } else if (!unsuccesful && st.st_ino != stto.st_ino) { + 1612 0 : unsuccesful = 1; + 1613 : + 1614 0 : log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto); + 1615 0 : log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + 1616 0 : ++error; + 1617 : } + 1618 : } else { + 1619 : /* read the symlink */ + 1620 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); + 1621 66532 : ret = readlink(path, linkto, sizeof(linkto)); + 1622 66532 : if (ret < 0) { + 1623 4300 : unsuccesful = 1; + 1624 : + 1625 4300 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); + 1626 4300 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + 1627 4300 : ++error; + 1628 62232 : } else if (ret >= PATH_MAX) { + 1629 0 : unsuccesful = 1; + 1630 : + 1631 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path); + 1632 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + 1633 0 : ++error; + 1634 : } else { + 1635 62232 : linkto[ret] = 0; + 1636 : + 1637 62232 : if (strcmp(linkto, slink->linkto) != 0) { + 1638 536 : unsuccesful = 1; + 1639 : + 1640 536 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto); + 1641 536 : ++error; + 1642 : } + 1643 : } + 1644 : } + 1645 : + 1646 66850 : if (fix && unsuccesful && !unrecoverable) { + 1647 : /* create the ancestor directories */ + 1648 3942 : ret = mkancestor(path); + 1649 3942 : if (ret != 0) { + 1650 : /* LCOV_EXCL_START */ + 1651 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1652 : log_fatal("Stopping\n"); + 1653 : ++unrecoverable_error; + 1654 : goto bail; + 1655 : /* LCOV_EXCL_STOP */ + 1656 : } + 1657 : + 1658 : /* if it exists, it must be deleted before recreating */ + 1659 3942 : ret = remove(path); + 1660 3942 : if (ret != 0 && errno != ENOENT) { + 1661 : /* LCOV_EXCL_START */ + 1662 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); + 1663 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1664 : log_fatal("Stopping\n"); + 1665 : ++unrecoverable_error; + 1666 : goto bail; + 1667 : /* LCOV_EXCL_STOP */ + 1668 : } + 1669 : + 1670 : /* create it */ + 1671 3942 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { + 1672 12 : ret = hardlink(pathto, path); + 1673 12 : if (ret != 0) { + 1674 : /* LCOV_EXCL_START */ + 1675 : log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno)); + 1676 : if (errno == EACCES) { + 1677 : log_fatal("WARNING! Please give write permission to the hardlink.\n"); + 1678 : } else { + 1679 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1680 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1681 : } + 1682 : log_fatal("Stopping\n"); + 1683 : ++unrecoverable_error; + 1684 : goto bail; + 1685 : /* LCOV_EXCL_STOP */ + 1686 : } + 1687 : + 1688 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + 1689 12 : ++recovered_error; + 1690 : } else { + 1691 3930 : ret = symlink(slink->linkto, path); + 1692 3930 : if (ret != 0) { + 1693 : /* LCOV_EXCL_START */ + 1694 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno)); + 1695 : if (errno == EACCES) { + 1696 : log_fatal("WARNING! Please give write permission to the symlink.\n"); + 1697 : } else { + 1698 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1699 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1700 : } + 1701 : log_fatal("Stopping\n"); + 1702 : ++unrecoverable_error; + 1703 : goto bail; + 1704 : /* LCOV_EXCL_STOP */ + 1705 : } + 1706 : + 1707 3930 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + 1708 3930 : ++recovered_error; + 1709 : } 1710 : - 1711 : /* stat the dir */ - 1712 421 : pathprint(path, sizeof(path), "%s%s", disk->dir, dir->sub); - 1713 421 : ret = stat(path, &st); - 1714 421 : if (ret == -1) { - 1715 23 : unsuccesful = 1; - 1716 : - 1717 23 : log_error("Error stating dir '%s'. %s.\n", path, strerror(errno)); - 1718 23 : log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer)); - 1719 23 : ++error; - 1720 398 : } else if (!S_ISDIR(st.st_mode)) { - 1721 0 : unsuccesful = 1; - 1722 : - 1723 0 : log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer)); - 1724 0 : ++error; - 1725 : } - 1726 : - 1727 421 : if (fix && unsuccesful) { - 1728 : /* create the ancestor directories */ - 1729 21 : ret = mkancestor(path); - 1730 21 : if (ret != 0) { - 1731 : /* LCOV_EXCL_START */ - 1732 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1733 : log_fatal("Stopping\n"); - 1734 : ++unrecoverable_error; - 1735 : goto bail; - 1736 : /* LCOV_EXCL_STOP */ - 1737 : } + 1711 3942 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); + 1712 3942 : msg_info("recovered %s\n", fmt_term(disk, slink->sub, esc_buffer)); + 1713 : } + 1714 : } + 1715 : + 1716 : /* for each dir in the disk */ + 1717 705 : disk = handle[i].disk; + 1718 705 : node = disk->dirlist; + 1719 1850 : while (node) { + 1720 : char path[PATH_MAX]; + 1721 : struct stat st; + 1722 : struct snapraid_dir* dir; + 1723 440 : int unsuccesful = 0; + 1724 : + 1725 440 : dir = node->data; + 1726 440 : node = node->next; /* next node */ + 1727 : + 1728 : /* if excluded continue to the next one */ + 1729 440 : if (dir_flag_has(dir, FILE_IS_EXCLUDED)) { + 1730 19 : continue; + 1731 : } + 1732 : + 1733 : /* stat the dir */ + 1734 421 : pathprint(path, sizeof(path), "%s%s", disk->dir, dir->sub); + 1735 421 : ret = stat(path, &st); + 1736 421 : if (ret == -1) { + 1737 23 : unsuccesful = 1; 1738 : - 1739 : /* create it */ - 1740 21 : ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - 1741 21 : if (ret != 0) { - 1742 : /* LCOV_EXCL_START */ - 1743 : log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno)); - 1744 : if (errno == EACCES) { - 1745 : log_fatal("WARNING! Please give write permission to the dir.\n"); - 1746 : } else { - 1747 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ - 1748 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1749 : } - 1750 : log_fatal("Stopping\n"); - 1751 : ++unrecoverable_error; - 1752 : goto bail; - 1753 : /* LCOV_EXCL_STOP */ - 1754 : } - 1755 : - 1756 21 : log_tag("dir_fixed:%s:%s: Fixed dir error\n", disk->name, esc_tag(dir->sub, esc_buffer)); - 1757 21 : ++recovered_error; - 1758 : - 1759 21 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(dir->sub, esc_buffer)); - 1760 21 : msg_info("recovered %s\n", fmt_term(disk, dir->sub, esc_buffer)); - 1761 : } - 1762 : } - 1763 : } - 1764 : - 1765 118 : state_progress_end(state, countpos, countmax, countsize); - 1766 : - 1767 : bail: - 1768 : /* close all the files left open */ - 1769 826 : for (j = 0; j < diskmax; ++j) { - 1770 708 : struct snapraid_file* file = handle[j].file; - 1771 708 : struct snapraid_disk* disk = handle[j].disk; - 1772 708 : ret = handle_close(&handle[j]); - 1773 708 : if (ret == -1) { - 1774 : /* LCOV_EXCL_START */ - 1775 : log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); - 1776 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); - 1777 : ++unrecoverable_error; - 1778 : /* continue, as we are already exiting */ - 1779 : /* LCOV_EXCL_STOP */ - 1780 : } - 1781 : } - 1782 : - 1783 : /* remove all the files created from scratch that have not finished the processing */ - 1784 : /* it happens only when aborting pressing Ctrl+C or other reason. */ - 1785 118 : if (fix) { - 1786 : /* for each disk */ - 1787 315 : for (i = 0; i < diskmax; ++i) { - 1788 : tommy_node* node; - 1789 : struct snapraid_disk* disk; - 1790 : - 1791 270 : if (!handle[i].disk) - 1792 1 : continue; - 1793 : - 1794 : /* for each file in the disk */ - 1795 269 : disk = handle[i].disk; - 1796 269 : node = disk->filelist; - 1797 870849 : while (node) { - 1798 : char path[PATH_MAX]; - 1799 : struct snapraid_file* file; - 1800 : - 1801 870311 : file = node->data; - 1802 870311 : node = node->next; /* next node */ - 1803 : - 1804 : /* if the file was not created, meaning that it was already existing */ - 1805 870311 : if (!file_flag_has(file, FILE_IS_CREATED)) { - 1806 : /* nothing to do */ - 1807 1627578 : continue; - 1808 : } - 1809 : - 1810 : /* if processing was finished */ - 1811 113044 : if (file_flag_has(file, FILE_IS_FINISHED)) { - 1812 : /* nothing to do */ - 1813 113044 : continue; - 1814 : } + 1739 23 : log_error("Error stating dir '%s'. %s.\n", path, strerror(errno)); + 1740 23 : log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer)); + 1741 23 : ++error; + 1742 398 : } else if (!S_ISDIR(st.st_mode)) { + 1743 0 : unsuccesful = 1; + 1744 : + 1745 0 : log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer)); + 1746 0 : ++error; + 1747 : } + 1748 : + 1749 421 : if (fix && unsuccesful) { + 1750 : /* create the ancestor directories */ + 1751 21 : ret = mkancestor(path); + 1752 21 : if (ret != 0) { + 1753 : /* LCOV_EXCL_START */ + 1754 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1755 : log_fatal("Stopping\n"); + 1756 : ++unrecoverable_error; + 1757 : goto bail; + 1758 : /* LCOV_EXCL_STOP */ + 1759 : } + 1760 : + 1761 : /* create it */ + 1762 21 : ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + 1763 21 : if (ret != 0) { + 1764 : /* LCOV_EXCL_START */ + 1765 : log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno)); + 1766 : if (errno == EACCES) { + 1767 : log_fatal("WARNING! Please give write permission to the dir.\n"); + 1768 : } else { + 1769 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + 1770 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1771 : } + 1772 : log_fatal("Stopping\n"); + 1773 : ++unrecoverable_error; + 1774 : goto bail; + 1775 : /* LCOV_EXCL_STOP */ + 1776 : } + 1777 : + 1778 21 : log_tag("dir_fixed:%s:%s: Fixed dir error\n", disk->name, esc_tag(dir->sub, esc_buffer)); + 1779 21 : ++recovered_error; + 1780 : + 1781 21 : log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(dir->sub, esc_buffer)); + 1782 21 : msg_info("recovered %s\n", fmt_term(disk, dir->sub, esc_buffer)); + 1783 : } + 1784 : } + 1785 : } + 1786 : + 1787 118 : state_progress_end(state, countpos, countmax, countsize); + 1788 : + 1789 : bail: + 1790 : /* close all the files left open */ + 1791 826 : for (j = 0; j < diskmax; ++j) { + 1792 708 : struct snapraid_file* file = handle[j].file; + 1793 708 : struct snapraid_disk* disk = handle[j].disk; + 1794 708 : ret = handle_close(&handle[j]); + 1795 708 : if (ret == -1) { + 1796 : /* LCOV_EXCL_START */ + 1797 : log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + 1798 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); + 1799 : ++unrecoverable_error; + 1800 : /* continue, as we are already exiting */ + 1801 : /* LCOV_EXCL_STOP */ + 1802 : } + 1803 : } + 1804 : + 1805 : /* remove all the files created from scratch that have not finished the processing */ + 1806 : /* it happens only when aborting pressing Ctrl+C or other reason. */ + 1807 118 : if (fix) { + 1808 : /* for each disk */ + 1809 315 : for (i = 0; i < diskmax; ++i) { + 1810 : tommy_node* node; + 1811 : struct snapraid_disk* disk; + 1812 : + 1813 270 : if (!handle[i].disk) + 1814 1 : continue; 1815 : - 1816 : /* if the file was originally missing, and processing not yet finished */ - 1817 : /* we have to throw it away to ensure that at the next run we will retry */ - 1818 : /* to fix it, in case we select to undelete missing files */ - 1819 0 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); - 1820 : - 1821 0 : ret = remove(path); - 1822 0 : if (ret != 0) { - 1823 : /* LCOV_EXCL_START */ - 1824 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); - 1825 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); - 1826 : ++unrecoverable_error; - 1827 : /* continue, as we are already exiting */ - 1828 : /* LCOV_EXCL_STOP */ - 1829 : } - 1830 : } - 1831 : } - 1832 : } - 1833 : - 1834 118 : if (error || recovered_error || unrecoverable_error) { - 1835 67 : msg_status("\n"); - 1836 67 : msg_status("%8u errors\n", error); - 1837 67 : if (fix) { - 1838 43 : msg_status("%8u recovered errors\n", recovered_error); - 1839 : } - 1840 134 : if (unrecoverable_error) { - 1841 13 : msg_status("%8u UNRECOVERABLE errors\n", unrecoverable_error); - 1842 : } else { - 1843 : /* without checking, we don't know if they are really recoverable or not */ - 1844 54 : if (!state->opt.auditonly) - 1845 52 : msg_status("%8u unrecoverable errors\n", unrecoverable_error); - 1846 54 : if (fix) - 1847 34 : msg_status("Everything OK\n"); - 1848 : } - 1849 : } else { - 1850 51 : msg_status("Everything OK\n"); - 1851 : } - 1852 : - 1853 118 : if (error && !fix) - 1854 24 : log_fatal("WARNING! There are errors!\n"); - 1855 118 : if (unrecoverable_error) - 1856 13 : log_fatal("DANGER! There are unrecoverable errors!\n"); - 1857 : - 1858 118 : log_tag("summary:error:%u\n", error); - 1859 118 : if (fix) - 1860 45 : log_tag("summary:error_recovered:%u\n", recovered_error); - 1861 118 : if (!state->opt.auditonly) - 1862 113 : log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error); - 1863 118 : if (fix) { - 1864 45 : if (error + recovered_error + unrecoverable_error == 0) - 1865 2 : log_tag("summary:exit:ok\n"); - 1866 43 : else if (unrecoverable_error == 0) - 1867 34 : log_tag("summary:exit:recovered\n"); - 1868 : else - 1869 9 : log_tag("summary:exit:unrecoverable\n"); - 1870 73 : } else if (!state->opt.auditonly) { - 1871 68 : if (error + unrecoverable_error == 0) - 1872 46 : log_tag("summary:exit:ok\n"); - 1873 22 : else if (unrecoverable_error == 0) - 1874 18 : log_tag("summary:exit:recoverable\n"); - 1875 : else - 1876 4 : log_tag("summary:exit:unrecoverable\n"); - 1877 : } else { /* audit only */ - 1878 5 : if (error == 0) - 1879 3 : log_tag("summary:exit:ok\n"); - 1880 : else - 1881 2 : log_tag("summary:exit:error\n"); - 1882 : } - 1883 118 : log_flush(); - 1884 : - 1885 118 : free(failed); - 1886 118 : free(failed_map); - 1887 118 : free(handle); - 1888 118 : free(buffer_alloc); - 1889 118 : free(buffer); - 1890 : - 1891 : /* fail if some error are present after the run */ - 1892 118 : if (fix) { - 1893 45 : if (state->opt.expect_unrecoverable) { - 1894 9 : if (unrecoverable_error == 0) - 1895 0 : return -1; - 1896 : } else { - 1897 36 : if (unrecoverable_error != 0) - 1898 0 : return -1; - 1899 : } - 1900 : } else { - 1901 73 : if (state->opt.expect_unrecoverable) { - 1902 4 : if (unrecoverable_error == 0) - 1903 0 : return -1; - 1904 69 : } else if (state->opt.expect_recoverable) { - 1905 20 : if (unrecoverable_error != 0 || error == 0) - 1906 0 : return -1; - 1907 : } else { - 1908 49 : if (error != 0 || unrecoverable_error != 0) - 1909 0 : return -1; - 1910 : } - 1911 : } + 1816 : /* for each file in the disk */ + 1817 269 : disk = handle[i].disk; + 1818 269 : node = disk->filelist; + 1819 870849 : while (node) { + 1820 : char path[PATH_MAX]; + 1821 : struct snapraid_file* file; + 1822 : + 1823 870311 : file = node->data; + 1824 870311 : node = node->next; /* next node */ + 1825 : + 1826 : /* if the file was not created, meaning that it was already existing */ + 1827 870311 : if (!file_flag_has(file, FILE_IS_CREATED)) { + 1828 : /* nothing to do */ + 1829 1627504 : continue; + 1830 : } + 1831 : + 1832 : /* if processing was finished */ + 1833 113118 : if (file_flag_has(file, FILE_IS_FINISHED)) { + 1834 : /* nothing to do */ + 1835 113118 : continue; + 1836 : } + 1837 : + 1838 : /* if the file was originally missing, and processing not yet finished */ + 1839 : /* we have to throw it away to ensure that at the next run we will retry */ + 1840 : /* to fix it, in case we select to undelete missing files */ + 1841 0 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + 1842 : + 1843 0 : ret = remove(path); + 1844 0 : if (ret != 0) { + 1845 : /* LCOV_EXCL_START */ + 1846 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); + 1847 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + 1848 : ++unrecoverable_error; + 1849 : /* continue, as we are already exiting */ + 1850 : /* LCOV_EXCL_STOP */ + 1851 : } + 1852 : } + 1853 : } + 1854 : } + 1855 : + 1856 118 : if (error || recovered_error || unrecoverable_error) { + 1857 67 : msg_status("\n"); + 1858 67 : msg_status("%8u errors\n", error); + 1859 67 : if (fix) { + 1860 43 : msg_status("%8u recovered errors\n", recovered_error); + 1861 : } + 1862 134 : if (unrecoverable_error) { + 1863 13 : msg_status("%8u UNRECOVERABLE errors\n", unrecoverable_error); + 1864 : } else { + 1865 : /* without checking, we don't know if they are really recoverable or not */ + 1866 54 : if (!state->opt.auditonly) + 1867 52 : msg_status("%8u unrecoverable errors\n", unrecoverable_error); + 1868 54 : if (fix) + 1869 34 : msg_status("Everything OK\n"); + 1870 : } + 1871 : } else { + 1872 51 : msg_status("Everything OK\n"); + 1873 : } + 1874 : + 1875 118 : if (error && !fix) + 1876 24 : log_fatal("WARNING! There are errors!\n"); + 1877 118 : if (unrecoverable_error) + 1878 13 : log_fatal("DANGER! There are unrecoverable errors!\n"); + 1879 : + 1880 118 : log_tag("summary:error:%u\n", error); + 1881 118 : if (fix) + 1882 45 : log_tag("summary:error_recovered:%u\n", recovered_error); + 1883 118 : if (!state->opt.auditonly) + 1884 113 : log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error); + 1885 118 : if (fix) { + 1886 45 : if (error + recovered_error + unrecoverable_error == 0) + 1887 2 : log_tag("summary:exit:ok\n"); + 1888 43 : else if (unrecoverable_error == 0) + 1889 34 : log_tag("summary:exit:recovered\n"); + 1890 : else + 1891 9 : log_tag("summary:exit:unrecoverable\n"); + 1892 73 : } else if (!state->opt.auditonly) { + 1893 68 : if (error + unrecoverable_error == 0) + 1894 46 : log_tag("summary:exit:ok\n"); + 1895 22 : else if (unrecoverable_error == 0) + 1896 18 : log_tag("summary:exit:recoverable\n"); + 1897 : else + 1898 4 : log_tag("summary:exit:unrecoverable\n"); + 1899 : } else { /* audit only */ + 1900 5 : if (error == 0) + 1901 3 : log_tag("summary:exit:ok\n"); + 1902 : else + 1903 2 : log_tag("summary:exit:error\n"); + 1904 : } + 1905 118 : log_flush(); + 1906 : + 1907 118 : free(failed); + 1908 118 : free(failed_map); + 1909 118 : free(handle); + 1910 118 : free(buffer_alloc); + 1911 118 : free(buffer); 1912 : - 1913 118 : return 0; - 1914 : } - 1915 : - 1916 120 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount) - 1917 : { - 1918 : block_off_t blockmax; - 1919 : data_off_t size; - 1920 : int ret; - 1921 : struct snapraid_parity_handle parity[LEV_MAX]; - 1922 : struct snapraid_parity_handle* parity_ptr[LEV_MAX]; - 1923 : unsigned error; - 1924 : unsigned l; - 1925 : - 1926 120 : msg_progress("Initializing...\n"); - 1927 : - 1928 120 : blockmax = parity_allocated_size(state); - 1929 120 : size = blockmax * (data_off_t)state->block_size; - 1930 : - 1931 120 : if (blockstart > blockmax) { - 1932 : /* LCOV_EXCL_START */ - 1933 : log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); - 1934 : exit(EXIT_FAILURE); - 1935 : /* LCOV_EXCL_STOP */ - 1936 : } + 1913 : /* fail if some error are present after the run */ + 1914 118 : if (fix) { + 1915 45 : if (state->opt.expect_unrecoverable) { + 1916 9 : if (unrecoverable_error == 0) + 1917 0 : return -1; + 1918 : } else { + 1919 36 : if (unrecoverable_error != 0) + 1920 0 : return -1; + 1921 : } + 1922 : } else { + 1923 73 : if (state->opt.expect_unrecoverable) { + 1924 4 : if (unrecoverable_error == 0) + 1925 0 : return -1; + 1926 69 : } else if (state->opt.expect_recoverable) { + 1927 20 : if (unrecoverable_error != 0 || error == 0) + 1928 0 : return -1; + 1929 : } else { + 1930 49 : if (error != 0 || unrecoverable_error != 0) + 1931 0 : return -1; + 1932 : } + 1933 : } + 1934 : + 1935 118 : return 0; + 1936 : } 1937 : - 1938 : /* adjust the number of block to process */ - 1939 120 : if (blockcount != 0 && blockstart + blockcount < blockmax) { - 1940 0 : blockmax = blockstart + blockcount; - 1941 : } - 1942 : - 1943 120 : if (fix) { - 1944 : /* if fixing, create the file and open for writing */ - 1945 : /* if it fails, we cannot continue */ - 1946 180 : for (l = 0; l < state->level; ++l) { - 1947 : /* skip parity disks that are not accessible */ - 1948 135 : if (state->parity[l].skip_access) { - 1949 1 : parity_ptr[l] = 0; - 1950 1 : continue; - 1951 : } + 1938 120 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount) + 1939 : { + 1940 : block_off_t blockmax; + 1941 : data_off_t size; + 1942 : int ret; + 1943 : struct snapraid_parity_handle parity[LEV_MAX]; + 1944 : struct snapraid_parity_handle* parity_ptr[LEV_MAX]; + 1945 : unsigned error; + 1946 : unsigned l; + 1947 : + 1948 120 : msg_progress("Initializing...\n"); + 1949 : + 1950 120 : blockmax = parity_allocated_size(state); + 1951 120 : size = blockmax * (data_off_t)state->block_size; 1952 : - 1953 134 : parity_ptr[l] = &parity[l]; - 1954 134 : ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); - 1955 134 : if (ret == -1) { - 1956 : /* LCOV_EXCL_START */ - 1957 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l)); - 1958 : exit(EXIT_FAILURE); - 1959 : /* LCOV_EXCL_STOP */ - 1960 : } - 1961 : - 1962 134 : ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); - 1963 134 : if (ret == -1) { - 1964 : /* LCOV_EXCL_START */ - 1965 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); - 1966 : exit(EXIT_FAILURE); - 1967 : /* LCOV_EXCL_STOP */ - 1968 : } - 1969 : } - 1970 75 : } else if (!state->opt.auditonly) { - 1971 : /* if checking, open the file for reading */ - 1972 : /* it may fail if the file doesn't exist, in this case we continue to check the files */ - 1973 393 : for (l = 0; l < state->level; ++l) { - 1974 324 : parity_ptr[l] = &parity[l]; - 1975 324 : ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); - 1976 324 : if (ret == -1) { - 1977 1 : msg_status("No accessible %s file, only files will be checked.\n", lev_name(l)); - 1978 : /* continue anyway */ - 1979 1 : parity_ptr[l] = 0; - 1980 : } - 1981 : } - 1982 : } else { - 1983 : /* otherwise don't use any parity */ - 1984 28 : for (l = 0; l < state->level; ++l) - 1985 22 : parity_ptr[l] = 0; - 1986 : } - 1987 : - 1988 120 : if (fix) - 1989 45 : msg_progress("Fixing...\n"); - 1990 75 : else if (!state->opt.auditonly) - 1991 69 : msg_progress("Checking...\n"); - 1992 : else - 1993 6 : msg_progress("Hashing...\n"); - 1994 : - 1995 120 : error = 0; - 1996 : - 1997 : /* skip degenerated cases of empty parity, or skipping all */ - 1998 120 : if (blockstart < blockmax) { - 1999 118 : ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax); - 2000 118 : if (ret == -1) { - 2001 : /* LCOV_EXCL_START */ - 2002 : ++error; - 2003 : /* continue, as we are already exiting */ - 2004 : /* LCOV_EXCL_STOP */ - 2005 : } - 2006 : } - 2007 : - 2008 : /* try to close only if opened */ - 2009 601 : for (l = 0; l < state->level; ++l) { - 2010 481 : if (parity_ptr[l]) { - 2011 457 : ret = parity_close(parity_ptr[l]); - 2012 : /* LCOV_EXCL_START */ - 2013 : if (ret == -1) { - 2014 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); - 2015 : ++error; - 2016 : /* continue, as we are already exiting */ - 2017 : } - 2018 : /* LCOV_EXCL_STOP */ - 2019 : } - 2020 : } - 2021 : - 2022 : /* abort if error are present */ - 2023 120 : if (error != 0) - 2024 0 : return -1; - 2025 120 : return 0; - 2026 : } - 2027 : + 1953 120 : if (blockstart > blockmax) { + 1954 : /* LCOV_EXCL_START */ + 1955 : log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); + 1956 : exit(EXIT_FAILURE); + 1957 : /* LCOV_EXCL_STOP */ + 1958 : } + 1959 : + 1960 : /* adjust the number of block to process */ + 1961 120 : if (blockcount != 0 && blockstart + blockcount < blockmax) { + 1962 0 : blockmax = blockstart + blockcount; + 1963 : } + 1964 : + 1965 120 : if (fix) { + 1966 : /* if fixing, create the file and open for writing */ + 1967 : /* if it fails, we cannot continue */ + 1968 180 : for (l = 0; l < state->level; ++l) { + 1969 : /* skip parity disks that are not accessible */ + 1970 135 : if (state->parity[l].skip_access) { + 1971 1 : parity_ptr[l] = 0; + 1972 1 : continue; + 1973 : } + 1974 : + 1975 134 : parity_ptr[l] = &parity[l]; + 1976 134 : ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + 1977 134 : if (ret == -1) { + 1978 : /* LCOV_EXCL_START */ + 1979 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l)); + 1980 : exit(EXIT_FAILURE); + 1981 : /* LCOV_EXCL_STOP */ + 1982 : } + 1983 : + 1984 134 : ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); + 1985 134 : if (ret == -1) { + 1986 : /* LCOV_EXCL_START */ + 1987 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); + 1988 : exit(EXIT_FAILURE); + 1989 : /* LCOV_EXCL_STOP */ + 1990 : } + 1991 : } + 1992 75 : } else if (!state->opt.auditonly) { + 1993 : /* if checking, open the file for reading */ + 1994 : /* it may fail if the file doesn't exist, in this case we continue to check the files */ + 1995 393 : for (l = 0; l < state->level; ++l) { + 1996 324 : parity_ptr[l] = &parity[l]; + 1997 324 : ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + 1998 324 : if (ret == -1) { + 1999 1 : msg_status("No accessible %s file, only files will be checked.\n", lev_name(l)); + 2000 : /* continue anyway */ + 2001 1 : parity_ptr[l] = 0; + 2002 : } + 2003 : } + 2004 : } else { + 2005 : /* otherwise don't use any parity */ + 2006 28 : for (l = 0; l < state->level; ++l) + 2007 22 : parity_ptr[l] = 0; + 2008 : } + 2009 : + 2010 120 : if (fix) + 2011 45 : msg_progress("Fixing...\n"); + 2012 75 : else if (!state->opt.auditonly) + 2013 69 : msg_progress("Checking...\n"); + 2014 : else + 2015 6 : msg_progress("Hashing...\n"); + 2016 : + 2017 120 : error = 0; + 2018 : + 2019 : /* skip degenerated cases of empty parity, or skipping all */ + 2020 120 : if (blockstart < blockmax) { + 2021 118 : ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax); + 2022 118 : if (ret == -1) { + 2023 : /* LCOV_EXCL_START */ + 2024 : ++error; + 2025 : /* continue, as we are already exiting */ + 2026 : /* LCOV_EXCL_STOP */ + 2027 : } + 2028 : } + 2029 : + 2030 : /* try to close only if opened */ + 2031 601 : for (l = 0; l < state->level; ++l) { + 2032 481 : if (parity_ptr[l]) { + 2033 457 : ret = parity_close(parity_ptr[l]); + 2034 : /* LCOV_EXCL_START */ + 2035 : if (ret == -1) { + 2036 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); + 2037 : ++error; + 2038 : /* continue, as we are already exiting */ + 2039 : } + 2040 : /* LCOV_EXCL_STOP */ + 2041 : } + 2042 : } + 2043 : + 2044 : /* abort if error are present */ + 2045 120 : if (error != 0) + 2046 0 : return -1; + 2047 120 : return 0; + 2048 : } + 2049 : diff --git a/cov/cmdline/device.c.func-sort-c.html b/cov/cmdline/device.c.func-sort-c.html index 4e4f2c23..e3e5564e 100644 --- a/cov/cmdline/device.c.func-sort-c.html +++ b/cov/cmdline/device.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 diff --git a/cov/cmdline/device.c.func.html b/cov/cmdline/device.c.func.html index 4891bbe1..b3af7c19 100644 --- a/cov/cmdline/device.c.func.html +++ b/cov/cmdline/device.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 diff --git a/cov/cmdline/device.c.gcov.html b/cov/cmdline/device.c.gcov.html index d2d91e48..b5f7e1bc 100644 --- a/cov/cmdline/device.c.gcov.html +++ b/cov/cmdline/device.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 diff --git a/cov/cmdline/dry.c.func-sort-c.html b/cov/cmdline/dry.c.func-sort-c.html index aebd4849..7bf68dc0 100644 --- a/cov/cmdline/dry.c.func-sort-c.html +++ b/cov/cmdline/dry.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -60,12 +60,12 @@ Hit count Sort by hit count - dry_data_reader - 42601 + dry_parity_reader + 42579 - dry_parity_reader - 42274 + dry_data_reader + 42575 block_is_enabled diff --git a/cov/cmdline/dry.c.func.html b/cov/cmdline/dry.c.func.html index 7a6439a5..d92de451 100644 --- a/cov/cmdline/dry.c.func.html +++ b/cov/cmdline/dry.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -65,11 +65,11 @@ dry_data_reader - 42601 + 42575 dry_parity_reader - 42274 + 42579 state_dry diff --git a/cov/cmdline/dry.c.gcov.html b/cov/cmdline/dry.c.gcov.html index a8f0bb53..426c362f 100644 --- a/cov/cmdline/dry.c.gcov.html +++ b/cov/cmdline/dry.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -101,45 +101,45 @@ 39 7102 : return 1; 40 : } 41 : - 42 42601 : static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 42 42575 : static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) 43 : { - 44 42601 : struct snapraid_io* io = worker->io; - 45 42601 : struct snapraid_state* state = io->state; - 46 42601 : struct snapraid_handle* handle = worker->handle; - 47 42601 : struct snapraid_disk* disk = handle->disk; - 48 42601 : block_off_t blockcur = task->position; - 49 42601 : unsigned char* buffer = task->buffer; + 44 42575 : struct snapraid_io* io = worker->io; + 45 42575 : struct snapraid_state* state = io->state; + 46 42575 : struct snapraid_handle* handle = worker->handle; + 47 42575 : struct snapraid_disk* disk = handle->disk; + 48 42575 : block_off_t blockcur = task->position; + 49 42575 : unsigned char* buffer = task->buffer; 50 : int ret; 51 : char esc_buffer[ESC_MAX]; 52 : 53 : /* if the disk position is not used */ - 54 42601 : if (!disk) { + 54 42575 : if (!disk) { 55 : /* use an empty block */ 56 4686 : memset(buffer, 0, state->block_size); 57 4686 : task->state = TASK_STATE_DONE; - 58 9917 : return; + 58 9912 : return; 59 : } 60 : 61 : /* get the block */ - 62 37915 : task->block = fs_par2block_find(disk, blockcur); + 62 37889 : task->block = fs_par2block_find(disk, blockcur); 63 : 64 : /* if the block is not used */ - 65 37902 : if (!block_has_file(task->block)) { + 65 37855 : if (!block_has_file(task->block)) { 66 : /* use an empty block */ - 67 545 : memset(buffer, 0, state->block_size); - 68 545 : task->state = TASK_STATE_DONE; - 69 545 : return; + 67 540 : memset(buffer, 0, state->block_size); + 68 540 : task->state = TASK_STATE_DONE; + 69 540 : return; 70 : } 71 : 72 : /* get the file of this block */ - 73 37352 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + 73 37298 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); 74 : 75 : /* if the file is different than the current one, close it */ - 76 37365 : if (handle->file != 0 && handle->file != task->file) { + 76 37356 : if (handle->file != 0 && handle->file != task->file) { 77 : /* keep a pointer at the file we are going to close for error reporting */ - 78 15088 : struct snapraid_file* report = handle->file; - 79 15088 : ret = handle_close(handle); - 80 15084 : if (ret == -1) { + 78 15083 : struct snapraid_file* report = handle->file; + 79 15083 : ret = handle_close(handle); + 80 15069 : if (ret == -1) { 81 : /* LCOV_EXCL_START */ 82 : /* This one is really an unexpected error, because we are only reading */ 83 : /* and closing a descriptor should never fail */ @@ -162,8 +162,8 @@ 100 : } 101 : } 102 : - 103 37361 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); - 104 37368 : if (ret == -1) { + 103 37342 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + 104 37201 : if (ret == -1) { 105 0 : if (errno == EIO) { 106 : /* LCOV_EXCL_START */ 107 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); @@ -180,8 +180,8 @@ 118 0 : return; 119 : } 120 : - 121 37368 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); - 122 37305 : if (task->read_size == -1) { + 121 37201 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + 122 37222 : if (task->read_size == -1) { 123 0 : if (errno == EIO) { 124 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); 125 0 : log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos); @@ -195,24 +195,24 @@ 133 : } 134 : 135 : /* store the path of the opened file */ - 136 37305 : pathcpy(task->path, sizeof(task->path), handle->path); + 136 37222 : pathcpy(task->path, sizeof(task->path), handle->path); 137 : - 138 37345 : task->state = TASK_STATE_DONE; + 138 37240 : task->state = TASK_STATE_DONE; 139 : } 140 : - 141 42274 : static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 141 42579 : static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) 142 : { - 143 42274 : struct snapraid_io* io = worker->io; - 144 42274 : struct snapraid_state* state = io->state; - 145 42274 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; - 146 42274 : unsigned level = parity_handle->level; - 147 42274 : block_off_t blockcur = task->position; - 148 42274 : unsigned char* buffer = task->buffer; + 143 42579 : struct snapraid_io* io = worker->io; + 144 42579 : struct snapraid_state* state = io->state; + 145 42579 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; + 146 42579 : unsigned level = parity_handle->level; + 147 42579 : block_off_t blockcur = task->position; + 148 42579 : unsigned char* buffer = task->buffer; 149 : int ret; 150 : 151 : /* read the parity */ - 152 42274 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); - 153 42574 : if (ret == -1) { + 152 42579 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); + 153 42483 : if (ret == -1) { 154 0 : if (errno == EIO) { 155 0 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); 156 0 : log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur); @@ -225,7 +225,7 @@ 163 0 : return; 164 : } 165 : - 166 42574 : task->state = TASK_STATE_DONE; + 166 42483 : task->state = TASK_STATE_DONE; 167 : } 168 : 169 2 : static int state_dry_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax) diff --git a/cov/cmdline/dup.c.func-sort-c.html b/cov/cmdline/dup.c.func-sort-c.html index dac74296..3c467d81 100644 --- a/cov/cmdline/dup.c.func-sort-c.html +++ b/cov/cmdline/dup.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 diff --git a/cov/cmdline/dup.c.func.html b/cov/cmdline/dup.c.func.html index 2517f6af..3b96aafc 100644 --- a/cov/cmdline/dup.c.func.html +++ b/cov/cmdline/dup.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 diff --git a/cov/cmdline/dup.c.gcov.html b/cov/cmdline/dup.c.gcov.html index c96f63d9..852b0f32 100644 --- a/cov/cmdline/dup.c.gcov.html +++ b/cov/cmdline/dup.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 diff --git a/cov/cmdline/elem.c.func-sort-c.html b/cov/cmdline/elem.c.func-sort-c.html index 90931dd5..04917e92 100644 --- a/cov/cmdline/elem.c.func-sort-c.html +++ b/cov/cmdline/elem.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 597 + 598 632 - 94.5 % + 94.6 % Date: - 2016-11-21 + 2017-05-13 Functions: 67 @@ -61,71 +61,71 @@ extent_parity_inside_compare_unlock - 114575009 - - - fs_lock - 53195526 + 113415111 fs_unlock - 53195112 + 53194752 + + + fs_lock + 53193825 extent_file_compare - 45005658 + 45007474 fs_file2block_get - 44945354 + 44945861 extent_parity_compare - 44509325 + 44510915 fs_par2extent_get_unlock - 39143508 + 39142622 fs_par2file_find - 39036978 + 39034767 fs_par2block_find - 27313631 + 27313617 extent_file_inside_compare_unlock - 21310995 + 21313929 filter_apply - 12457044 + 12456472 fs_file2extent_get_unlock - 10336255 + 10336367 fs_allocate - 9175178 + 9175254 file_block_size - 6823038 + 6820121 extent_file_check_foreach_unlock - 6584473 + 6584561 extent_parity_check_foreach_unlock - 6584473 + 6584561 filter_recurse - 6236629 + 6236343 file_block_is_last @@ -133,55 +133,55 @@ fs_file2par_find - 4869703 + 4869735 extent_alloc - 3735289 + 3735329 file_alloc - 3690991 + 3690989 extent_free - 3564865 + 3564905 file_free - 3543815 + 3543813 filter_element - 3332859 + 3332716 filter_path - 3329762 + 3329619 filter_content - 3173372 + 3173210 file_inode_compare_to_arg - 975235 + 987374 time_compare - 691801 + 675269 fmt_term - 355906 + 356144 file_path_compare - 189475 + 189473 filter_type - 125233 + 125331 link_alloc @@ -193,27 +193,27 @@ fs_deallocate - 106232 + 106308 file_path_compare_to_arg - 97871 + 103588 filter_existence 80691 + + file_physical_compare + 53902 + extent_disk_size_compare_unlock - 50514 + 50518 file_name - 47954 - - - file_physical_compare - 44212 + 47970 filter_correctness @@ -225,11 +225,11 @@ file_namestamp_compare - 23977 + 23985 file_name_compare - 23977 + 23985 file_stamp_compare diff --git a/cov/cmdline/elem.c.func.html b/cov/cmdline/elem.c.func.html index 63f4cf7d..6b79b04f 100644 --- a/cov/cmdline/elem.c.func.html +++ b/cov/cmdline/elem.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 597 + 598 632 - 94.5 % + 94.6 % Date: - 2016-11-21 + 2017-05-13 Functions: 67 @@ -89,7 +89,7 @@ extent_alloc - 3735289 + 3735329 extent_disk_empty_compare_unlock @@ -97,39 +97,39 @@ extent_disk_size_compare_unlock - 50514 + 50518 extent_file_check_foreach_unlock - 6584473 + 6584561 extent_file_compare - 45005658 + 45007474 extent_file_inside_compare_unlock - 21310995 + 21313929 extent_free - 3564865 + 3564905 extent_parity_check_foreach_unlock - 6584473 + 6584561 extent_parity_compare - 44509325 + 44510915 extent_parity_inside_compare_unlock - 114575009 + 113415111 file_alloc - 3690991 + 3690989 file_block_is_last @@ -137,7 +137,7 @@ file_block_size - 6823038 + 6820121 file_copy @@ -149,7 +149,7 @@ file_free - 3543815 + 3543813 file_inode_compare @@ -157,27 +157,27 @@ file_inode_compare_to_arg - 975235 + 987374 file_name - 47954 + 47970 file_name_compare - 23977 + 23985 file_namestamp_compare - 23977 + 23985 file_path_compare - 189475 + 189473 file_path_compare_to_arg - 97871 + 103588 file_pathstamp_compare @@ -185,7 +185,7 @@ file_physical_compare - 44212 + 53902 file_rename @@ -205,11 +205,11 @@ filter_apply - 12457044 + 12456472 filter_content - 3173372 + 3173210 filter_correctness @@ -217,7 +217,7 @@ filter_element - 3332859 + 3332716 filter_emptydir @@ -233,11 +233,11 @@ filter_path - 3329762 + 3329619 filter_recurse - 6236629 + 6236343 filter_subdir @@ -245,7 +245,7 @@ filter_type - 125233 + 125331 fmt_poll @@ -253,11 +253,11 @@ fmt_term - 355906 + 356144 fs_allocate - 9175178 + 9175254 fs_check @@ -265,19 +265,19 @@ fs_deallocate - 106232 + 106308 fs_file2block_get - 44945354 + 44945861 fs_file2extent_get_unlock - 10336255 + 10336367 fs_file2par_find - 4869703 + 4869735 fs_is_empty @@ -285,19 +285,19 @@ fs_lock - 53195526 + 53193825 fs_par2block_find - 27313631 + 27313617 fs_par2extent_get_unlock - 39143508 + 39142622 fs_par2file_find - 39036978 + 39034767 fs_size @@ -305,7 +305,7 @@ fs_unlock - 53195112 + 53194752 link_alloc @@ -333,7 +333,7 @@ time_compare - 691801 + 675269
diff --git a/cov/cmdline/elem.c.gcov.html b/cov/cmdline/elem.c.gcov.html index 2f2b118f..bed1d37a 100644 --- a/cov/cmdline/elem.c.gcov.html +++ b/cov/cmdline/elem.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 597 + 598 632 - 94.5 % + 94.6 % Date: - 2016-11-21 + 2017-05-13 Functions: 67 @@ -212,96 +212,96 @@ 150 499 : free(filter); 151 499 : } 152 : - 153 125233 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) + 153 125331 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) 154 : { 155 : const char* direction; 156 : - 157 125233 : if (filter->direction < 0) - 158 124968 : direction = "exclude"; + 157 125331 : if (filter->direction < 0) + 158 125066 : direction = "exclude"; 159 : else 160 265 : direction = "include"; 161 : - 162 125233 : if (filter->is_disk) + 162 125331 : if (filter->is_disk) 163 0 : pathprint(out, out_size, "%s %s:", direction, filter->pattern); - 164 125233 : else if (filter->is_dir) + 164 125331 : else if (filter->is_dir) 165 0 : pathprint(out, out_size, "%s %s/", direction, filter->pattern); 166 : else - 167 125233 : pathprint(out, out_size, "%s %s", direction, filter->pattern); + 167 125331 : pathprint(out, out_size, "%s %s", direction, filter->pattern); 168 : - 169 125233 : return out; + 169 125331 : return out; 170 : } 171 : - 172 12457044 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir) + 172 12456472 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir) 173 : { - 174 12457044 : int ret = 0; + 174 12456472 : int ret = 0; 175 : 176 : /* match dirs with dirs and files with files */ - 177 12457044 : if (filter->is_dir && !is_dir) + 177 12456472 : if (filter->is_dir && !is_dir) 178 2949 : return 0; - 179 12454095 : if (!filter->is_dir && is_dir) - 180 6223584 : return 0; + 179 12453523 : if (!filter->is_dir && is_dir) + 180 6223298 : return 0; 181 : - 182 6230511 : if (filter->is_path) { + 182 6230225 : if (filter->is_path) { 183 : /* skip initial slash, as always missing from the path */ 184 2949 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0) 185 0 : ret = filter->direction; 186 : } else { - 187 6227562 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) - 188 127693 : ret = filter->direction; + 187 6227276 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 188 127791 : ret = filter->direction; 189 : } 190 : - 191 6230511 : if (reason != 0 && ret < 0) - 192 124703 : *reason = filter; + 191 6230225 : if (reason != 0 && ret < 0) + 192 124801 : *reason = filter; 193 : - 194 6230511 : return ret; + 194 6230225 : return ret; 195 : } 196 : - 197 6236629 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir) + 197 6236343 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir) 198 : { 199 : char path[PATH_MAX]; 200 : char* name; 201 : unsigned i; 202 : - 203 6236629 : pathcpy(path, sizeof(path), const_path); + 203 6236343 : pathcpy(path, sizeof(path), const_path); 204 : 205 : /* filter for all the directories */ - 206 6236629 : name = path; - 207 89821180 : for (i = 0; path[i] != 0; ++i) { - 208 83587541 : if (path[i] == '/') { + 206 6236343 : name = path; + 207 89822608 : for (i = 0; path[i] != 0; ++i) { + 208 83589255 : if (path[i] == '/') { 209 : /* set a terminator */ - 210 6223405 : path[i] = 0; + 210 6223119 : path[i] = 0; 211 : 212 : /* filter the directory */ - 213 6223405 : if (filter_apply(filter, reason, path, name, 1) != 0) + 213 6223119 : if (filter_apply(filter, reason, path, name, 1) != 0) 214 2990 : return filter->direction; 215 : 216 : /* restore the slash */ - 217 6220415 : path[i] = '/'; + 217 6220129 : path[i] = '/'; 218 : 219 : /* next name */ - 220 6220415 : name = path + i + 1; + 220 6220129 : name = path + i + 1; 221 : } 222 : } 223 : 224 : /* filter the final file */ - 225 6233639 : if (filter_apply(filter, reason, path, name, is_dir) != 0) - 226 124703 : return filter->direction; + 225 6233353 : if (filter_apply(filter, reason, path, name, is_dir) != 0) + 226 124801 : return filter->direction; 227 : - 228 6108936 : return 0; + 228 6108552 : return 0; 229 : } 230 : - 231 3332859 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include) + 231 3332716 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include) 232 : { 233 : tommy_node* i; 234 : - 235 3332859 : int direction = 1; /* by default include all */ + 235 3332716 : int direction = 1; /* by default include all */ 236 : 237 : /* for each filter */ - 238 9543103 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { + 238 9542576 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { 239 : int ret; - 240 6346617 : struct snapraid_filter* filter = i->data; + 240 6346331 : struct snapraid_filter* filter = i->data; 241 : - 242 6346617 : if (filter->is_disk) { + 242 6346331 : if (filter->is_disk) { 243 109988 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0) 244 8680 : ret = filter->direction; 245 : else @@ -309,39 +309,39 @@ 247 109988 : if (reason != 0 && ret < 0) 248 0 : *reason = filter; 249 : } else { - 250 6236629 : ret = filter_recurse(filter, reason, sub, is_dir); + 250 6236343 : ret = filter_recurse(filter, reason, sub, is_dir); 251 : } 252 : - 253 6346617 : if (ret > 0) { + 253 6346331 : if (ret > 0) { 254 : /* include the file */ 255 11670 : return 0; - 256 6334947 : } else if (ret < 0) { + 256 6334661 : } else if (ret < 0) { 257 : /* exclude the file */ - 258 124703 : return -1; + 258 124801 : return -1; 259 : } else { 260 : /* default is opposite of the last filter */ - 261 6210244 : direction = -filter->direction; - 262 6210244 : if (reason != 0 && direction < 0) - 263 3110901 : *reason = filter; + 261 6209860 : direction = -filter->direction; + 262 6209860 : if (reason != 0 && direction < 0) + 263 3110758 : *reason = filter; 264 : /* continue with the next one */ 265 : } 266 : } 267 : 268 : /* directories are always included by default, otherwise we cannot apply rules */ 269 : /* to the contained files */ - 270 3196486 : if (is_def_include) + 270 3196245 : if (is_def_include) 271 3052 : return 0; 272 : 273 : /* files are excluded/included depending of the last rule processed */ - 274 3193434 : if (direction < 0) + 274 3193193 : if (direction < 0) 275 57608 : return -1; 276 : - 277 3135826 : return 0; + 277 3135585 : return 0; 278 : } 279 : - 280 3329762 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) + 280 3329619 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) 281 : { - 282 3329762 : return filter_element(filterlist, reason, disk, sub, 0, 0); + 282 3329619 : return filter_element(filterlist, reason, disk, sub, 0, 0); 283 : } 284 : 285 3052 : int filter_subdir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) @@ -387,67 +387,67 @@ 325 16098 : return 0; 326 : 327 : /* check each block of the file */ - 328 60692 : for (i = 0; i < file->blockmax; ++i) { - 329 46446 : block_off_t parity_pos = fs_file2par_get(disk, file, i); - 330 46446 : snapraid_info info = info_get(infoarr, parity_pos); + 328 60648 : for (i = 0; i < file->blockmax; ++i) { + 329 46434 : block_off_t parity_pos = fs_file2par_get(disk, file, i); + 330 46434 : snapraid_info info = info_get(infoarr, parity_pos); 331 : 332 : /* if the file has a bad block, don't exclude it */ - 333 46446 : if (info_get_bad(info)) - 334 8302 : return 0; + 333 46434 : if (info_get_bad(info)) + 334 8334 : return 0; 335 : } 336 : 337 : /* the file is correct, so we filter it out */ - 338 14246 : return 1; + 338 14214 : return 1; 339 : } 340 : - 341 3173372 : int filter_content(tommy_list* contentlist, const char* path) + 341 3173210 : int filter_content(tommy_list* contentlist, const char* path) 342 : { 343 : tommy_node* i; 344 : - 345 40913052 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { - 346 17283154 : struct snapraid_content* content = i->data; + 345 40912088 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { + 346 17282834 : struct snapraid_content* content = i->data; 347 : char tmp[PATH_MAX]; 348 : - 349 17283154 : if (pathcmp(content->content, path) == 0) + 349 17282834 : if (pathcmp(content->content, path) == 0) 350 0 : return -1; 351 : 352 : /* exclude also the ".tmp" copy used to save it */ - 353 17283154 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 354 17283154 : if (pathcmp(tmp, path) == 0) + 353 17282834 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 354 17282834 : if (pathcmp(tmp, path) == 0) 355 0 : return -1; 356 : 357 : /* exclude also the ".lock" file */ - 358 17283154 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); - 359 17283154 : if (pathcmp(tmp, path) == 0) + 358 17282834 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); + 359 17282834 : if (pathcmp(tmp, path) == 0) 360 0 : return -1; 361 : } 362 : - 363 3173372 : return 0; + 363 3173210 : return 0; 364 : } 365 : - 366 3690991 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical) + 366 3690989 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical) 367 : { 368 : struct snapraid_file* file; 369 : block_off_t i; 370 : - 371 3690991 : file = malloc_nofail(sizeof(struct snapraid_file)); - 372 3690991 : file->sub = strdup_nofail(sub); - 373 3690991 : file->size = size; - 374 3690991 : file->blockmax = (size + block_size - 1) / block_size; - 375 3690991 : file->mtime_sec = mtime_sec; - 376 3690991 : file->mtime_nsec = mtime_nsec; - 377 3690991 : file->inode = inode; - 378 3690991 : file->physical = physical; - 379 3690991 : file->flag = 0; - 380 3690991 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); + 371 3690989 : file = malloc_nofail(sizeof(struct snapraid_file)); + 372 3690989 : file->sub = strdup_nofail(sub); + 373 3690989 : file->size = size; + 374 3690989 : file->blockmax = (size + block_size - 1) / block_size; + 375 3690989 : file->mtime_sec = mtime_sec; + 376 3690989 : file->mtime_nsec = mtime_nsec; + 377 3690989 : file->inode = inode; + 378 3690989 : file->physical = physical; + 379 3690989 : file->flag = 0; + 380 3690989 : file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); 381 : - 382 12810201 : for (i = 0; i < file->blockmax; ++i) { - 383 9119210 : struct snapraid_block* block = file_block(file, i); - 384 9119210 : block_state_set(block, BLOCK_STATE_CHG); - 385 9119210 : hash_invalid_set(block->hash); + 382 12810275 : for (i = 0; i < file->blockmax; ++i) { + 383 9119286 : struct snapraid_block* block = file_block(file, i); + 384 9119286 : block_state_set(block, BLOCK_STATE_CHG); + 385 9119286 : hash_invalid_set(block->hash); 386 : } 387 : - 388 3690991 : return file; + 388 3690989 : return file; 389 : } 390 : 391 22687 : struct snapraid_file* file_dup(struct snapraid_file* copy) @@ -476,14 +476,14 @@ 414 22687 : return file; 415 : } 416 : - 417 3543815 : void file_free(struct snapraid_file* file) + 417 3543813 : void file_free(struct snapraid_file* file) 418 : { - 419 3543815 : free(file->sub); - 420 3543815 : file->sub = 0; - 421 3543815 : free(file->blockvec); - 422 3543815 : file->blockvec = 0; - 423 3543815 : free(file); - 424 3543815 : } + 419 3543813 : free(file->sub); + 420 3543813 : file->sub = 0; + 421 3543813 : free(file->blockvec); + 422 3543813 : file->blockvec = 0; + 423 3543813 : free(file); + 424 3543813 : } 425 : 426 155 : void file_rename(struct snapraid_file* file, const char* sub) 427 : { @@ -527,31 +527,31 @@ 465 23636 : file_flag_set(dst_file, FILE_IS_COPY); 466 23636 : } 467 : - 468 47954 : const char* file_name(const struct snapraid_file* file) + 468 47970 : const char* file_name(const struct snapraid_file* file) 469 : { - 470 47954 : const char* r = strrchr(file->sub, '/'); + 470 47970 : const char* r = strrchr(file->sub, '/'); 471 : - 472 47954 : if (!r) + 472 47970 : if (!r) 473 78 : r = file->sub; 474 : else - 475 47876 : ++r; - 476 47954 : return r; + 475 47892 : ++r; + 476 47970 : return r; 477 : } 478 : - 479 6823038 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) + 479 6820121 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) 480 : { 481 : /* if it's the last block */ - 482 6823038 : if (file_pos + 1 == file->blockmax) { + 482 6820121 : if (file_pos + 1 == file->blockmax) { 483 : unsigned block_remainder; - 484 2775121 : if (file->size == 0) + 484 2774907 : if (file->size == 0) 485 0 : return 0; - 486 2775121 : block_remainder = file->size % block_size; - 487 2775121 : if (block_remainder == 0) + 486 2774907 : block_remainder = file->size % block_size; + 487 2774907 : if (block_remainder == 0) 488 3044 : block_remainder = block_size; - 489 2775121 : return block_remainder; + 489 2774907 : return block_remainder; 490 : } 491 : - 492 4047917 : return block_size; + 492 4045214 : return block_size; 493 : } 494 : 495 5329167 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) @@ -569,16 +569,16 @@ 507 5329167 : return file_pos == file->blockmax - 1; 508 : } 509 : - 510 975235 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) + 510 987374 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) 511 : { - 512 975235 : const uint64_t* arg = void_arg; - 513 975235 : const struct snapraid_file* file = void_data; + 512 987374 : const uint64_t* arg = void_arg; + 513 987374 : const struct snapraid_file* file = void_data; 514 : - 515 975235 : if (*arg < file->inode) - 516 0 : return -1; - 517 975235 : if (*arg > file->inode) + 515 987374 : if (*arg < file->inode) + 516 1 : return -1; + 517 987373 : if (*arg > file->inode) 518 0 : return 1; - 519 975235 : return 0; + 519 987373 : return 0; 520 : } 521 : 522 0 : int file_inode_compare(const void* void_a, const void* void_b) @@ -593,42 +593,42 @@ 531 0 : return 0; 532 : } 533 : - 534 189475 : int file_path_compare(const void* void_a, const void* void_b) + 534 189473 : int file_path_compare(const void* void_a, const void* void_b) 535 : { - 536 189475 : const struct snapraid_file* file_a = void_a; - 537 189475 : const struct snapraid_file* file_b = void_b; + 536 189473 : const struct snapraid_file* file_a = void_a; + 537 189473 : const struct snapraid_file* file_b = void_b; 538 : - 539 189475 : return strcmp(file_a->sub, file_b->sub); + 539 189473 : return strcmp(file_a->sub, file_b->sub); 540 : } 541 : - 542 44212 : int file_physical_compare(const void* void_a, const void* void_b) + 542 53902 : int file_physical_compare(const void* void_a, const void* void_b) 543 : { - 544 44212 : const struct snapraid_file* file_a = void_a; - 545 44212 : const struct snapraid_file* file_b = void_b; + 544 53902 : const struct snapraid_file* file_a = void_a; + 545 53902 : const struct snapraid_file* file_b = void_b; 546 : - 547 44212 : if (file_a->physical < file_b->physical) - 548 31866 : return -1; - 549 12346 : if (file_a->physical > file_b->physical) - 550 12344 : return 1; + 547 53902 : if (file_a->physical < file_b->physical) + 548 37798 : return -1; + 549 16104 : if (file_a->physical > file_b->physical) + 550 16102 : return 1; 551 2 : return 0; 552 : } 553 : - 554 97871 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) + 554 103588 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) 555 : { - 556 97871 : const char* arg = void_arg; - 557 97871 : const struct snapraid_file* file = void_data; + 556 103588 : const char* arg = void_arg; + 557 103588 : const struct snapraid_file* file = void_data; 558 : - 559 97871 : return strcmp(arg, file->sub); + 559 103588 : return strcmp(arg, file->sub); 560 : } 561 : - 562 23977 : int file_name_compare(const void* void_a, const void* void_b) + 562 23985 : int file_name_compare(const void* void_a, const void* void_b) 563 : { - 564 23977 : const struct snapraid_file* file_a = void_a; - 565 23977 : const struct snapraid_file* file_b = void_b; - 566 23977 : const char* name_a = file_name(file_a); - 567 23977 : const char* name_b = file_name(file_b); + 564 23985 : const struct snapraid_file* file_a = void_a; + 565 23985 : const struct snapraid_file* file_b = void_b; + 566 23985 : const char* name_a = file_name(file_a); + 567 23985 : const char* name_b = file_name(file_b); 568 : - 569 23977 : return strcmp(name_a, name_b); + 569 23985 : return strcmp(name_a, name_b); 570 : } 571 : 572 23670 : int file_stamp_compare(const void* void_a, const void* void_b) @@ -654,13 +654,13 @@ 592 23670 : return 0; 593 : } 594 : - 595 23977 : int file_namestamp_compare(const void* void_a, const void* void_b) + 595 23985 : int file_namestamp_compare(const void* void_a, const void* void_b) 596 : { 597 : int ret; 598 : - 599 23977 : ret = file_name_compare(void_a, void_b); - 600 23977 : if (ret != 0) - 601 307 : return ret; + 599 23985 : ret = file_name_compare(void_a, void_b); + 600 23985 : if (ret != 0) + 601 315 : return ret; 602 : 603 23670 : return file_stamp_compare(void_a, void_b); 604 : } @@ -676,66 +676,66 @@ 614 0 : return file_stamp_compare(void_a, void_b); 615 : } 616 : - 617 3735289 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) + 617 3735329 : struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) 618 : { 619 : struct snapraid_extent* extent; 620 : - 621 3735289 : if (count == 0) { + 621 3735329 : if (count == 0) { 622 : /* LCOV_EXCL_START */ 623 : log_fatal("Internal inconsistency when allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); 624 : os_abort(); 625 : /* LCOV_EXCL_STOP */ 626 : } - 627 3735289 : if (file_pos + count > file->blockmax) { + 627 3735329 : if (file_pos + count > file->blockmax) { 628 : /* LCOV_EXCL_START */ 629 : log_fatal("Internal inconsistency when allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax); 630 : os_abort(); 631 : /* LCOV_EXCL_STOP */ 632 : } 633 : - 634 3735289 : extent = malloc_nofail(sizeof(struct snapraid_extent)); - 635 3735289 : extent->parity_pos = parity_pos; - 636 3735289 : extent->file = file; - 637 3735289 : extent->file_pos = file_pos; - 638 3735289 : extent->count = count; + 634 3735329 : extent = malloc_nofail(sizeof(struct snapraid_extent)); + 635 3735329 : extent->parity_pos = parity_pos; + 636 3735329 : extent->file = file; + 637 3735329 : extent->file_pos = file_pos; + 638 3735329 : extent->count = count; 639 : - 640 3735289 : return extent; + 640 3735329 : return extent; 641 : } 642 : - 643 3564865 : void extent_free(struct snapraid_extent* extent) + 643 3564905 : void extent_free(struct snapraid_extent* extent) 644 : { - 645 3564865 : free(extent); - 646 3564865 : } + 645 3564905 : free(extent); + 646 3564905 : } 647 : - 648 44509325 : int extent_parity_compare(const void* void_a, const void* void_b) + 648 44510915 : int extent_parity_compare(const void* void_a, const void* void_b) 649 : { - 650 44509325 : const struct snapraid_extent* arg_a = void_a; - 651 44509325 : const struct snapraid_extent* arg_b = void_b; + 650 44510915 : const struct snapraid_extent* arg_a = void_a; + 651 44510915 : const struct snapraid_extent* arg_b = void_b; 652 : - 653 44509325 : if (arg_a->parity_pos < arg_b->parity_pos) - 654 960426 : return -1; - 655 43548899 : if (arg_a->parity_pos > arg_b->parity_pos) - 656 43509241 : return 1; + 653 44510915 : if (arg_a->parity_pos < arg_b->parity_pos) + 654 961025 : return -1; + 655 43549890 : if (arg_a->parity_pos > arg_b->parity_pos) + 656 43510236 : return 1; 657 : - 658 39658 : return 0; + 658 39654 : return 0; 659 : } 660 : - 661 45005658 : int extent_file_compare(const void* void_a, const void* void_b) + 661 45007474 : int extent_file_compare(const void* void_a, const void* void_b) 662 : { - 663 45005658 : const struct snapraid_extent* arg_a = void_a; - 664 45005658 : const struct snapraid_extent* arg_b = void_b; + 663 45007474 : const struct snapraid_extent* arg_a = void_a; + 664 45007474 : const struct snapraid_extent* arg_b = void_b; 665 : - 666 45005658 : if (arg_a->file < arg_b->file) - 667 875311 : return -1; - 668 44130347 : if (arg_a->file > arg_b->file) - 669 44059546 : return 1; + 666 45007474 : if (arg_a->file < arg_b->file) + 667 874959 : return -1; + 668 44132515 : if (arg_a->file > arg_b->file) + 669 44061652 : return 1; 670 : - 671 70801 : if (arg_a->file_pos < arg_b->file_pos) + 671 70863 : if (arg_a->file_pos < arg_b->file_pos) 672 208 : return -1; - 673 70593 : if (arg_a->file_pos > arg_b->file_pos) - 674 30935 : return 1; + 673 70655 : if (arg_a->file_pos > arg_b->file_pos) + 674 31001 : return 1; 675 : - 676 39658 : return 0; + 676 39654 : return 0; 677 : } 678 : 679 119522 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag) @@ -864,23 +864,23 @@ 802 1459 : free(disk); 803 1459 : } 804 : - 805 53195526 : static inline void fs_lock(struct snapraid_disk* disk) + 805 53193825 : static inline void fs_lock(struct snapraid_disk* disk) 806 : { 807 : #if HAVE_PTHREAD - 808 53195526 : thread_mutex_lock(&disk->fs_mutex); + 808 53193825 : thread_mutex_lock(&disk->fs_mutex); 809 : #else 810 : (void)disk; 811 : #endif - 812 53196097 : } + 812 53196398 : } 813 : - 814 53195112 : static inline void fs_unlock(struct snapraid_disk* disk) + 814 53194752 : static inline void fs_unlock(struct snapraid_disk* disk) 815 : { 816 : #if HAVE_PTHREAD - 817 53195112 : thread_mutex_unlock(&disk->fs_mutex); + 817 53194752 : thread_mutex_unlock(&disk->fs_mutex); 818 : #else 819 : (void)disk; 820 : #endif - 821 53196272 : } + 821 53196925 : } 822 : 823 : struct extent_disk_empty { 824 : block_off_t blockmax; @@ -937,17 +937,17 @@ 875 : * 876 : * The maximum parity position is stored as size. 877 : */ - 878 50514 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b) + 878 50518 : static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b) 879 : { - 880 50514 : struct extent_disk_size* arg_a = (void*)void_a; - 881 50514 : const struct snapraid_extent* arg_b = void_b; + 880 50518 : struct extent_disk_size* arg_a = (void*)void_a; + 881 50518 : const struct snapraid_extent* arg_b = void_b; 882 : 883 : /* get the maximum size */ - 884 50514 : if (arg_a->size < arg_b->parity_pos + arg_b->count) - 885 50514 : arg_a->size = arg_b->parity_pos + arg_b->count; + 884 50518 : if (arg_a->size < arg_b->parity_pos + arg_b->count) + 885 50518 : arg_a->size = arg_b->parity_pos + arg_b->count; 886 : 887 : /* search always for a bigger one */ - 888 50514 : return 1; + 888 50518 : return 1; 889 : } 890 : 891 4363 : block_off_t fs_size(struct snapraid_disk* disk) @@ -968,23 +968,23 @@ 906 : int result; 907 : }; 908 : - 909 6584473 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj) + 909 6584561 : static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj) 910 : { - 911 6584473 : struct extent_check* arg = void_arg; - 912 6584473 : const struct snapraid_extent* obj = void_obj; - 913 6584473 : const struct snapraid_extent* prev = arg->prev; + 911 6584561 : struct extent_check* arg = void_arg; + 912 6584561 : const struct snapraid_extent* obj = void_obj; + 913 6584561 : const struct snapraid_extent* prev = arg->prev; 914 : 915 : /* set the next previous block */ - 916 6584473 : arg->prev = obj; + 916 6584561 : arg->prev = obj; 917 : 918 : /* stop reporting if too many errors */ - 919 6584473 : if (arg->result > 100) { + 919 6584561 : if (arg->result > 100) { 920 : /* LCOV_EXCL_START */ 921 : return; 922 : /* LCOV_EXCL_STOP */ 923 : } 924 : - 925 6584473 : if (obj->count == 0) { + 925 6584561 : if (obj->count == 0) { 926 : /* LCOV_EXCL_START */ 927 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n", 928 : obj->file->sub, obj->parity_pos); @@ -994,11 +994,11 @@ 932 : } 933 : 934 : /* check only if there is a previous block */ - 935 6584473 : if (!prev) + 935 6584561 : if (!prev) 936 2723 : return; 937 : 938 : /* check the order */ - 939 6581750 : if (prev->parity_pos >= obj->parity_pos) { + 939 6581838 : if (prev->parity_pos >= obj->parity_pos) { 940 : /* LCOV_EXCL_START */ 941 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", 942 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); @@ -1008,7 +1008,7 @@ 946 : } 947 : 948 : /* check that the extents don't overlap */ - 949 6581750 : if (prev->parity_pos + prev->count > obj->parity_pos) { + 949 6581838 : if (prev->parity_pos + prev->count > obj->parity_pos) { 950 : /* LCOV_EXCL_START */ 951 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", 952 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); @@ -1018,23 +1018,23 @@ 956 : } 957 : } 958 : - 959 6584473 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj) + 959 6584561 : static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj) 960 : { - 961 6584473 : struct extent_check* arg = void_arg; - 962 6584473 : const struct snapraid_extent* obj = void_obj; - 963 6584473 : const struct snapraid_extent* prev = arg->prev; + 961 6584561 : struct extent_check* arg = void_arg; + 962 6584561 : const struct snapraid_extent* obj = void_obj; + 963 6584561 : const struct snapraid_extent* prev = arg->prev; 964 : 965 : /* set the next previous block */ - 966 6584473 : arg->prev = obj; + 966 6584561 : arg->prev = obj; 967 : 968 : /* stop reporting if too many errors */ - 969 6584473 : if (arg->result > 100) { + 969 6584561 : if (arg->result > 100) { 970 : /* LCOV_EXCL_START */ 971 : return; 972 : /* LCOV_EXCL_STOP */ 973 : } 974 : - 975 6584473 : if (obj->count == 0) { + 975 6584561 : if (obj->count == 0) { 976 : /* LCOV_EXCL_START */ 977 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n", 978 : obj->file->sub, obj->file_pos); @@ -1046,7 +1046,7 @@ 984 : /* note that for deleted files, some extents may be missing */ 985 : 986 : /* if the files are different */ - 987 6584473 : if (!prev || prev->file != obj->file) { + 987 6584561 : if (!prev || prev->file != obj->file) { 988 6538269 : if (prev != 0) { 989 6535546 : if (file_flag_has(prev->file, FILE_IS_DELETED)) { 990 : /* check that the extent doesn't overflow the file */ @@ -1094,7 +1094,7 @@ 1032 : } 1033 : } else { 1034 : /* check the order */ - 1035 46204 : if (prev->file_pos >= obj->file_pos) { + 1035 46292 : if (prev->file_pos >= obj->file_pos) { 1036 : /* LCOV_EXCL_START */ 1037 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n", 1038 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); @@ -1103,7 +1103,7 @@ 1041 : /* LCOV_EXCL_STOP */ 1042 : } 1043 : - 1044 46204 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { + 1044 46292 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { 1045 : /* check that the extents don't overlap */ 1046 27 : if (prev->file_pos + prev->count > obj->file_pos) { 1047 : /* LCOV_EXCL_START */ @@ -1115,7 +1115,7 @@ 1053 : } 1054 : } else { 1055 : /* check that the extents are sequential */ - 1056 46177 : if (prev->file_pos + prev->count != obj->file_pos) { + 1056 46265 : if (prev->file_pos + prev->count != obj->file_pos) { 1057 : /* LCOV_EXCL_START */ 1058 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n", 1059 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); @@ -1159,17 +1159,17 @@ 1097 : /** 1098 : * Compare the extent if containing the specified parity position. 1099 : */ - 1100 114575009 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b) + 1100 113415111 : static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b) 1101 : { - 1102 114575009 : const struct extent_parity_inside* arg_a = void_a; - 1103 114575009 : const struct snapraid_extent* arg_b = void_b; + 1102 113415111 : const struct extent_parity_inside* arg_a = void_a; + 1103 113415111 : const struct snapraid_extent* arg_b = void_b; 1104 : - 1105 114575009 : if (arg_a->parity_pos < arg_b->parity_pos) - 1106 40547890 : return -1; - 1107 74027119 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) - 1108 65245847 : return 1; + 1105 113415111 : if (arg_a->parity_pos < arg_b->parity_pos) + 1106 40067087 : return -1; + 1107 73348024 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) + 1108 64675056 : return 1; 1109 : - 1110 8781272 : return 0; + 1110 8672968 : return 0; 1111 : } 1112 : 1113 : /** @@ -1177,28 +1177,28 @@ 1115 : * The search is optimized for sequential accesses. 1116 : * \return If not found return 0 1117 : */ - 1118 39143508 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos) + 1118 39142622 : static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos) 1119 : { 1120 : struct snapraid_extent* extent; 1121 : 1122 : /* check if the last accessed extent matches */ - 1123 39143508 : if (*fs_last - 1124 39125091 : && parity_pos >= (*fs_last)->parity_pos - 1125 38408678 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count + 1123 39142622 : if (*fs_last + 1124 39124369 : && parity_pos >= (*fs_last)->parity_pos + 1125 38409994 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count 1126 : ) { - 1127 28777623 : extent = *fs_last; + 1127 28886530 : extent = *fs_last; 1128 : } else { - 1129 10365885 : struct extent_parity_inside arg = { parity_pos }; - 1130 10365885 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg); + 1129 10256092 : struct extent_parity_inside arg = { parity_pos }; + 1130 10256092 : extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg); 1131 : } 1132 : - 1133 39143433 : if (!extent) - 1134 1584679 : return 0; + 1133 39144071 : if (!extent) + 1134 1584630 : return 0; 1135 : 1136 : /* store the last accessed extent */ - 1137 37558754 : *fs_last = extent; + 1137 37559441 : *fs_last = extent; 1138 : - 1139 37558754 : return extent; + 1139 37559441 : return extent; 1140 : } 1141 : 1142 : struct extent_file_inside { @@ -1209,22 +1209,22 @@ 1147 : /** 1148 : * Compare the extent if containing the specified file position. 1149 : */ - 1150 21310995 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b) + 1150 21313929 : static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b) 1151 : { - 1152 21310995 : const struct extent_file_inside* arg_a = void_a; - 1153 21310995 : const struct snapraid_extent* arg_b = void_b; + 1152 21313929 : const struct extent_file_inside* arg_a = void_a; + 1153 21313929 : const struct snapraid_extent* arg_b = void_b; 1154 : - 1155 21310995 : if (arg_a->file < arg_b->file) - 1156 8885792 : return -1; - 1157 12425203 : if (arg_a->file > arg_b->file) - 1158 10405515 : return 1; + 1155 21313929 : if (arg_a->file < arg_b->file) + 1156 8885403 : return -1; + 1157 12428526 : if (arg_a->file > arg_b->file) + 1158 10408652 : return 1; 1159 : - 1160 2019688 : if (arg_a->file_pos < arg_b->file_pos) - 1161 8333 : return -1; - 1162 2011355 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) - 1163 7947 : return 1; + 1160 2019874 : if (arg_a->file_pos < arg_b->file_pos) + 1161 8344 : return -1; + 1162 2011530 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) + 1163 7997 : return 1; 1164 : - 1165 2003408 : return 0; + 1165 2003533 : return 0; 1166 : } 1167 : 1168 : /** @@ -1232,88 +1232,88 @@ 1170 : * The search is optimized for sequential accesses. 1171 : * \return If not found return 0 1172 : */ - 1173 10336255 : static struct snapraid_extent* fs_file2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, struct snapraid_file* file, block_off_t file_pos) + 1173 10336367 : static struct snapraid_extent* fs_file2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, struct snapraid_file* file, block_off_t file_pos) 1174 : { 1175 : struct snapraid_extent* extent; 1176 : 1177 : /* check if the last accessed extent matches */ - 1178 10336255 : if (*fs_last - 1179 10312569 : && file == (*fs_last)->file - 1180 8347073 : && file_pos >= (*fs_last)->file_pos - 1181 8347073 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count + 1178 10336367 : if (*fs_last + 1179 10312681 : && file == (*fs_last)->file + 1180 8347105 : && file_pos >= (*fs_last)->file_pos + 1181 8347105 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count 1182 : ) { - 1183 8332839 : extent = *fs_last; + 1183 8332826 : extent = *fs_last; 1184 : } else { - 1185 2003416 : struct extent_file_inside arg = { file, file_pos }; - 1186 2003416 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg); + 1185 2003541 : struct extent_file_inside arg = { file, file_pos }; + 1186 2003541 : extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg); 1187 : } 1188 : - 1189 10336255 : if (!extent) + 1189 10336367 : if (!extent) 1190 8 : return 0; 1191 : 1192 : /* store the last accessed extent */ - 1193 10336247 : *fs_last = extent; + 1193 10336359 : *fs_last = extent; 1194 : - 1195 10336247 : return extent; + 1195 10336359 : return extent; 1196 : } 1197 : - 1198 39036978 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) + 1198 39034767 : struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) 1199 : { 1200 : struct snapraid_extent* extent; 1201 : struct snapraid_file* file; 1202 : - 1203 39036978 : fs_lock(disk); + 1203 39034767 : fs_lock(disk); 1204 : - 1205 39037785 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + 1205 39037534 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); 1206 : - 1207 39036721 : if (!extent) { - 1208 1584680 : fs_unlock(disk); - 1209 1584723 : return 0; + 1207 39037013 : if (!extent) { + 1208 1584625 : fs_unlock(disk); + 1209 1584635 : return 0; 1210 : } 1211 : - 1212 37452041 : if (file_pos) - 1213 37107540 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos); + 1212 37452388 : if (file_pos) + 1213 37108181 : *file_pos = extent->file_pos + (parity_pos - extent->parity_pos); 1214 : - 1215 37452041 : file = extent->file; + 1215 37452388 : file = extent->file; 1216 : - 1217 37452041 : fs_unlock(disk); - 1218 37453073 : return file; + 1217 37452388 : fs_unlock(disk); + 1218 37453620 : return file; 1219 : } 1220 : - 1221 4869703 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) + 1221 4869735 : block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) 1222 : { 1223 : struct snapraid_extent* extent; 1224 : block_off_t ret; 1225 : - 1226 4869703 : fs_lock(disk); + 1226 4869735 : fs_lock(disk); 1227 : - 1228 4869703 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos); - 1229 4869703 : if (!extent) { + 1228 4869735 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos); + 1229 4869735 : if (!extent) { 1230 8 : fs_unlock(disk); 1231 8 : return POS_NULL; 1232 : } 1233 : - 1234 4869695 : ret = extent->parity_pos + (file_pos - extent->file_pos); + 1234 4869727 : ret = extent->parity_pos + (file_pos - extent->file_pos); 1235 : - 1236 4869695 : fs_unlock(disk); - 1237 4869695 : return ret; + 1236 4869727 : fs_unlock(disk); + 1237 4869727 : return ret; 1238 : } 1239 : - 1240 9175178 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) + 1240 9175254 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) 1241 : { 1242 : struct snapraid_extent* extent; 1243 : struct snapraid_extent* parity_extent; 1244 : struct snapraid_extent* file_extent; 1245 : - 1246 9175178 : fs_lock(disk); + 1246 9175254 : fs_lock(disk); 1247 : - 1248 9175178 : if (file_pos > 0) { + 1248 9175254 : if (file_pos > 0) { 1249 : /* search an existing extent for the previous file_pos */ - 1250 5466552 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1); + 1250 5466632 : extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1); 1251 : - 1252 5466552 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) { + 1252 5466632 : if (extent != 0 && parity_pos == extent->parity_pos + extent->count) { 1253 : /* ensure that we are extending the extent at the end */ - 1254 5439890 : if (file_pos != extent->file_pos + extent->count) { + 1254 5439926 : if (file_pos != extent->file_pos + extent->count) { 1255 : /* LCOV_EXCL_START */ 1256 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name); 1257 : os_abort(); @@ -1321,21 +1321,21 @@ 1259 : } 1260 : 1261 : /* extend the existing extent */ - 1262 5439890 : ++extent->count; + 1262 5439926 : ++extent->count; 1263 : - 1264 5439890 : fs_unlock(disk); - 1265 14615068 : return; + 1264 5439926 : fs_unlock(disk); + 1265 14615180 : return; 1266 : } 1267 : } 1268 : 1269 : /* a extent doesn't exist, and we have to create a new one */ - 1270 3735288 : extent = extent_alloc(parity_pos, file, file_pos, 1); + 1270 3735328 : extent = extent_alloc(parity_pos, file, file_pos, 1); 1271 : 1272 : /* insert the extent in the trees */ - 1273 3735288 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent); - 1274 3735288 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent); + 1273 3735328 : parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent); + 1274 3735328 : file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent); 1275 : - 1276 3735288 : if (parity_extent != extent || file_extent != extent) { + 1276 3735328 : if (parity_extent != extent || file_extent != extent) { 1277 : /* LCOV_EXCL_START */ 1278 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name); 1279 : os_abort(); @@ -1343,12 +1343,12 @@ 1281 : } 1282 : 1283 : /* store the last accessed extent */ - 1284 3735288 : disk->fs_last = extent; + 1284 3735328 : disk->fs_last = extent; 1285 : - 1286 3735288 : fs_unlock(disk); + 1286 3735328 : fs_unlock(disk); 1287 : } 1288 : - 1289 106232 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) + 1289 106308 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) 1290 : { 1291 : struct snapraid_extent* extent; 1292 : struct snapraid_extent* second_extent; @@ -1356,10 +1356,10 @@ 1294 : struct snapraid_extent* file_extent; 1295 : block_off_t first_count, second_count; 1296 : - 1297 106232 : fs_lock(disk); + 1297 106308 : fs_lock(disk); 1298 : - 1299 106232 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); - 1300 106232 : if (!extent) { + 1299 106308 : extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + 1300 106308 : if (!extent) { 1301 : /* LCOV_EXCL_START */ 1302 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name); 1303 : os_abort(); @@ -1367,29 +1367,29 @@ 1305 : } 1306 : 1307 : /* if it's the only block of the extent, delete it */ - 1308 106232 : if (extent->count == 1) { + 1308 106308 : if (extent->count == 1) { 1309 : /* remove from the trees */ - 1310 39658 : tommy_tree_remove(&disk->fs_parity, extent); - 1311 39658 : tommy_tree_remove(&disk->fs_file, extent); + 1310 39654 : tommy_tree_remove(&disk->fs_parity, extent); + 1311 39654 : tommy_tree_remove(&disk->fs_file, extent); 1312 : 1313 : /* deallocate */ - 1314 39658 : extent_free(extent); + 1314 39654 : extent_free(extent); 1315 : 1316 : /* clear the last accessed extent */ - 1317 39658 : disk->fs_last = 0; + 1317 39654 : disk->fs_last = 0; 1318 : - 1319 39658 : fs_unlock(disk); - 1320 39658 : return; + 1319 39654 : fs_unlock(disk); + 1320 39654 : return; 1321 : } 1322 : 1323 : /* if it's at the start of the extent, shrink the extent */ - 1324 66574 : if (parity_pos == extent->parity_pos) { - 1325 66572 : ++extent->parity_pos; - 1326 66572 : ++extent->file_pos; - 1327 66572 : --extent->count; + 1324 66654 : if (parity_pos == extent->parity_pos) { + 1325 66652 : ++extent->parity_pos; + 1326 66652 : ++extent->file_pos; + 1327 66652 : --extent->count; 1328 : - 1329 66572 : fs_unlock(disk); - 1330 66572 : return; + 1329 66652 : fs_unlock(disk); + 1330 66652 : return; 1331 : } 1332 : 1333 : /* if it's at the end of the extent, shrink the extent */ @@ -1427,28 +1427,28 @@ 1365 1 : fs_unlock(disk); 1366 : } 1367 : - 1368 44945354 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) + 1368 44945861 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) 1369 : { - 1370 44945354 : if (file_pos >= file->blockmax) { + 1370 44945861 : if (file_pos >= file->blockmax) { 1371 : /* LCOV_EXCL_START */ 1372 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); 1373 : os_abort(); 1374 : /* LCOV_EXCL_STOP */ 1375 : } 1376 : - 1377 44945354 : return file_block(file, file_pos); + 1377 44945861 : return file_block(file, file_pos); 1378 : } 1379 : - 1380 27313631 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos) + 1380 27313617 : struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos) 1381 : { 1382 : struct snapraid_file* file; 1383 : block_off_t file_pos; 1384 : - 1385 27313631 : file = fs_par2file_find(disk, parity_pos, &file_pos); - 1386 27313916 : if (file == 0) - 1387 1584719 : return BLOCK_NULL; + 1385 27313617 : file = fs_par2file_find(disk, parity_pos, &file_pos); + 1386 27314375 : if (file == 0) + 1387 1584611 : return BLOCK_NULL; 1388 : - 1389 25729197 : return fs_file2block_get(file, file_pos); + 1389 25729764 : return fs_file2block_get(file, file_pos); 1390 : } 1391 : 1392 1561 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid) @@ -1470,16 +1470,16 @@ 1408 1435 : free(map); 1409 1435 : } 1410 : - 1411 691801 : int time_compare(const void* void_a, const void* void_b) + 1411 675269 : int time_compare(const void* void_a, const void* void_b) 1412 : { - 1413 691801 : const time_t* time_a = void_a; - 1414 691801 : const time_t* time_b = void_b; + 1413 675269 : const time_t* time_a = void_a; + 1414 675269 : const time_t* time_b = void_b; 1415 : - 1416 691801 : if (*time_a < *time_b) - 1417 18310 : return -1; - 1418 673491 : if (*time_a > *time_b) - 1419 129297 : return 1; - 1420 544194 : return 0; + 1416 675269 : if (*time_a < *time_b) + 1417 16327 : return -1; + 1418 658942 : if (*time_a > *time_b) + 1419 110431 : return 1; + 1420 548511 : return 0; 1421 : } 1422 : 1423 : /****************************************************************************/ @@ -1499,14 +1499,14 @@ 1437 : /** 1438 : * Format a path name for terminal reference 1439 : */ - 1440 355906 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer) + 1440 356144 : const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer) 1441 : { 1442 : const char* out[3]; 1443 : - 1444 355906 : switch (FMT_MODE) { + 1444 356144 : switch (FMT_MODE) { 1445 : case FMT_FILE : 1446 : default : - 1447 331846 : return esc_shell(str, buffer); + 1447 332084 : return esc_shell(str, buffer); 1448 : case FMT_DISK : 1449 12030 : out[0] = disk->name; 1450 12030 : out[1] = ":"; diff --git a/cov/cmdline/elem.h.func-sort-c.html b/cov/cmdline/elem.h.func-sort-c.html index b2224709..7535ce31 100644 --- a/cov/cmdline/elem.h.func-sort-c.html +++ b/cov/cmdline/elem.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 41 @@ -61,67 +61,67 @@ block_sizeof - 58065128 + 58065229 file_block - 54351316 + 54351162 block_state_get - 52304023 + 52305826 file_flag_has - 34089332 + 34102051 block_state_set - 19117096 + 19117692 block_has_file - 14591493 + 14589756 block_has_invalid_parity - 12320585 + 12320925 fs_par2file_get - 11723835 + 11722518 hash_invalid_set - 9234067 + 9234143 file_stamp_hash - 6275421 + 6275620 file_flag_set - 5295048 + 5303183 info_get - 5098669 + 5098731 file_inode_hash - 5042449 + 5055357 fs_file2par_get - 4755492 + 4755524 file_path_hash - 3886182 + 3891897 filter_hidden - 3173372 + 3173210 block_has_past_hash @@ -129,43 +129,43 @@ block_has_updated_hash - 2217099 + 2218229 info_get_rehash - 2046851 + 2046849 info_set - 1698121 + 1698196 info_get_time - 883203 + 883145 hash_is_zero - 760108 + 760608 hash_is_invalid - 758645 + 759146 info_get_bad - 352076 + 352062 block_has_file_and_valid_parity - 220962 + 220963 link_flag_has - 209328 + 209329 info_make - 194583 + 194621 link_name_hash @@ -181,23 +181,23 @@ info_get_justsynced - 68634 + 68576 hash_is_unique - 44270 + 44326 link_flag_set 39461 - fs_par2block_get - 15867 + file_flag_clear + 18420 - file_flag_clear - 11286 + fs_par2block_get + 15867 info_set_rehash diff --git a/cov/cmdline/elem.h.func.html b/cov/cmdline/elem.h.func.html index 36d3ea93..4729ebe7 100644 --- a/cov/cmdline/elem.h.func.html +++ b/cov/cmdline/elem.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 41 @@ -61,15 +61,15 @@ block_has_file - 14591493 + 14589756 block_has_file_and_valid_parity - 220962 + 220963 block_has_invalid_parity - 12320585 + 12320925 block_has_past_hash @@ -77,19 +77,19 @@ block_has_updated_hash - 2217099 + 2218229 block_sizeof - 58065128 + 58065229 block_state_get - 52304023 + 52305826 block_state_set - 19117096 + 19117692 dir_flag_has @@ -105,39 +105,39 @@ file_block - 54351316 + 54351162 file_flag_clear - 11286 + 18420 file_flag_has - 34089332 + 34102051 file_flag_set - 5295048 + 5303183 file_inode_hash - 5042449 + 5055357 file_path_hash - 3886182 + 3891897 file_stamp_hash - 6275421 + 6275620 filter_hidden - 3173372 + 3173210 fs_file2par_get - 4755492 + 4755524 fs_par2block_get @@ -145,23 +145,23 @@ fs_par2file_get - 11723835 + 11722518 hash_invalid_set - 9234067 + 9234143 hash_is_invalid - 758645 + 759146 hash_is_unique - 44270 + 44326 hash_is_zero - 760108 + 760608 hash_zero_set @@ -169,31 +169,31 @@ info_get - 5098669 + 5098731 info_get_bad - 352076 + 352062 info_get_justsynced - 68634 + 68576 info_get_rehash - 2046851 + 2046849 info_get_time - 883203 + 883145 info_make - 194583 + 194621 info_set - 1698121 + 1698196 info_set_bad @@ -209,7 +209,7 @@ link_flag_has - 209328 + 209329 link_flag_let diff --git a/cov/cmdline/elem.h.gcov.html b/cov/cmdline/elem.h.gcov.html index ddba0d94..ebdda3ae 100644 --- a/cov/cmdline/elem.h.gcov.html +++ b/cov/cmdline/elem.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 41 @@ -525,7 +525,7 @@ 463 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ 464 : block_off_t total_blocks; /**< Number of total blocks. */ 465 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */ - 466 : int is_excluded; /**< If the parity is excluded by disk filter. */ + 466 : int is_excluded_by_filter; /**< If the parity is excluded by filters. */ 467 : int skip_access; /**< If at least one of the parity disk is inaccessible and it should be skipped. */ 468 : uint64_t tick; /**< Usage time. */ 469 : uint64_t progress_tick[PROGRESS_MAX]; /**< Last cpu ticks of progress. */ @@ -571,13 +571,13 @@ 509 : * Filter hidden files. 510 : * Return !=0 if it matches and it should be excluded. 511 : */ - 512 3173372 : static inline int filter_hidden(int enable, struct dirent* dd) + 512 3173210 : static inline int filter_hidden(int enable, struct dirent* dd) 513 : { - 514 3173372 : if (enable && dirent_hidden(dd)) { + 514 3173210 : if (enable && dirent_hidden(dd)) { 515 0 : return 1; /* filter out */ 516 : } 517 : - 518 3173372 : return 0; + 518 3173210 : return 0; 519 : } 520 : 521 : /** @@ -628,17 +628,17 @@ 566 : * 567 : * If working with reduced hash lengths, this function always return 0. 568 : */ - 569 758645 : static inline int hash_is_invalid(const unsigned char* hash) + 569 759146 : static inline int hash_is_invalid(const unsigned char* hash) 570 : { 571 : int i; 572 : 573 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 574 758645 : if (BLOCK_HASH_SIZE != HASH_MAX) + 574 759146 : if (BLOCK_HASH_SIZE != HASH_MAX) 575 0 : return 0; 576 : - 577 1178483 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) - 578 1152419 : if (hash[i] != 0x00) - 579 732581 : return 0; + 577 1179527 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) + 578 1153463 : if (hash[i] != 0x00) + 579 733082 : return 0; 580 : 581 26064 : return 1; 582 : } @@ -650,19 +650,19 @@ 588 : * 589 : * If working with reduced hash lengths, this function always return 0. 590 : */ - 591 760108 : static inline int hash_is_zero(const unsigned char* hash) + 591 760608 : static inline int hash_is_zero(const unsigned char* hash) 592 : { 593 : int i; 594 : 595 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 596 760108 : if (BLOCK_HASH_SIZE != HASH_MAX) + 596 760608 : if (BLOCK_HASH_SIZE != HASH_MAX) 597 0 : return 0; 598 : - 599 994848 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) - 600 980378 : if (hash[i] != 0xFF) - 601 745638 : return 0; + 599 995114 : for (i = 0; i < BLOCK_HASH_SIZE; ++i) + 600 980645 : if (hash[i] != 0xFF) + 601 746139 : return 0; 602 : - 603 14470 : return 1; + 603 14469 : return 1; 604 : } 605 : 606 : /** @@ -670,22 +670,22 @@ 608 : * 609 : * If working with reduced hash lengths, this function always return 0. 610 : */ - 611 44270 : static inline int hash_is_unique(const unsigned char* hash) + 611 44326 : static inline int hash_is_unique(const unsigned char* hash) 612 : { 613 : /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ - 614 44270 : if (BLOCK_HASH_SIZE != HASH_MAX) + 614 44326 : if (BLOCK_HASH_SIZE != HASH_MAX) 615 0 : return 0; 616 : - 617 44270 : return !hash_is_zero(hash) && !hash_is_invalid(hash); + 617 44326 : return !hash_is_zero(hash) && !hash_is_invalid(hash); 618 : } 619 : 620 : /** 621 : * Set the hash to the special INVALID value. 622 : */ - 623 9234067 : static inline void hash_invalid_set(unsigned char* hash) + 623 9234143 : static inline void hash_invalid_set(unsigned char* hash) 624 : { - 625 9234067 : memset(hash, 0x00, BLOCK_HASH_SIZE); - 626 9234067 : } + 625 9234143 : memset(hash, 0x00, BLOCK_HASH_SIZE); + 626 9234143 : } 627 : 628 : /** 629 : * Set the hash to the special ZERO value. @@ -698,9 +698,9 @@ 636 : /** 637 : * Allocated space for block. 638 : */ - 639 58065128 : static inline size_t block_sizeof(void) + 639 58065229 : static inline size_t block_sizeof(void) 640 : { - 641 58065128 : return 1 + BLOCK_HASH_SIZE; + 641 58065229 : return 1 + BLOCK_HASH_SIZE; 642 : } 643 : 644 : /** @@ -709,32 +709,32 @@ 647 : * For this function, it's allowed to pass a NULL block 648 : * pointer than results in the BLOCK_STATE_EMPTY state. 649 : */ - 650 52304023 : static inline unsigned block_state_get(const struct snapraid_block* block) + 650 52305826 : static inline unsigned block_state_get(const struct snapraid_block* block) 651 : { - 652 52304023 : if (block == BLOCK_NULL) - 653 1722497 : return BLOCK_STATE_EMPTY; + 652 52305826 : if (block == BLOCK_NULL) + 653 1722139 : return BLOCK_STATE_EMPTY; 654 : - 655 50581526 : return block->state; + 655 50583687 : return block->state; 656 : } 657 : 658 : /** 659 : * Set the state of the block. 660 : */ - 661 19117096 : static inline void block_state_set(struct snapraid_block* block, unsigned state) + 661 19117692 : static inline void block_state_set(struct snapraid_block* block, unsigned state) 662 : { - 663 19117096 : block->state = state; - 664 19117096 : } + 663 19117692 : block->state = state; + 664 19117692 : } 665 : 666 : /** 667 : * Check if the specified block has an updated hash. 668 : * 669 : * Note that EMPTY / CHG / DELETED return 0. 670 : */ - 671 2217099 : static inline int block_has_updated_hash(const struct snapraid_block* block) + 671 2218229 : static inline int block_has_updated_hash(const struct snapraid_block* block) 672 : { - 673 2217099 : unsigned state = block_state_get(block); + 673 2218229 : unsigned state = block_state_get(block); 674 : - 675 2217099 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; + 675 2218229 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; 676 : } 677 : 678 : /** @@ -755,12 +755,12 @@ 693 : * 694 : * Note that EMPTY / DELETED return 0. 695 : */ - 696 14591493 : static inline int block_has_file(const struct snapraid_block* block) + 696 14589756 : static inline int block_has_file(const struct snapraid_block* block) 697 : { - 698 14591493 : unsigned state = block_state_get(block); + 698 14589756 : unsigned state = block_state_get(block); 699 : - 700 14591444 : return state == BLOCK_STATE_BLK - 701 14591444 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 700 14590663 : return state == BLOCK_STATE_BLK + 701 14590663 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; 702 : } 703 : 704 : /** @@ -768,12 +768,12 @@ 706 : * 707 : * Note that EMPTY / BLK return 0. 708 : */ - 709 12320585 : static inline int block_has_invalid_parity(const struct snapraid_block* block) + 709 12320925 : static inline int block_has_invalid_parity(const struct snapraid_block* block) 710 : { - 711 12320585 : unsigned state = block_state_get(block); + 711 12320925 : unsigned state = block_state_get(block); 712 : - 713 12320585 : return state == BLOCK_STATE_DELETED - 714 12320585 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 713 12320925 : return state == BLOCK_STATE_DELETED + 714 12320925 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; 715 : } 716 : 717 : /** @@ -781,27 +781,27 @@ 719 : * 720 : * Note that anything different than BLK return 0. 721 : */ - 722 220962 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) + 722 220963 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) 723 : { - 724 220962 : unsigned state = block_state_get(block); + 724 220963 : unsigned state = block_state_get(block); 725 : - 726 220962 : return state == BLOCK_STATE_BLK; + 726 220963 : return state == BLOCK_STATE_BLK; 727 : } 728 : - 729 34089332 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) + 729 34102051 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) 730 : { - 731 34089332 : return (file->flag & mask) == mask; + 731 34102051 : return (file->flag & mask) == mask; 732 : } 733 : - 734 5295048 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) + 734 5303183 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) 735 : { - 736 5295048 : file->flag |= mask; - 737 5295048 : } + 736 5303183 : file->flag |= mask; + 737 5303183 : } 738 : - 739 11286 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) + 739 18420 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) 740 : { - 741 11286 : file->flag &= ~mask; - 742 11286 : } + 741 18420 : file->flag &= ~mask; + 742 18420 : } 743 : 744 : /** 745 : * Allocate a file. @@ -833,11 +833,11 @@ 771 : * 772 : * Note that the block size if a runtime value. 773 : */ - 774 54351316 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos) + 774 54351162 : static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos) 775 : { - 776 54351316 : unsigned char* ptr = (unsigned char*)file->blockvec; + 776 54351162 : unsigned char* ptr = (unsigned char*)file->blockvec; 777 : - 778 54351316 : return (struct snapraid_block*)(ptr + pos * block_sizeof()); + 778 54351162 : return (struct snapraid_block*)(ptr + pos * block_sizeof()); 779 : } 780 : 781 : /** @@ -879,9 +879,9 @@ 817 : /** 818 : * Compute the hash of a file inode. 819 : */ - 820 5042449 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) + 820 5055357 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) 821 : { - 822 5042449 : return (tommy_uint32_t)tommy_inthash_u64(inode); + 822 5055357 : return (tommy_uint32_t)tommy_inthash_u64(inode); 823 : } 824 : 825 : /** @@ -900,17 +900,17 @@ 838 : /** 839 : * Compute the hash of a file path. 840 : */ - 841 3886182 : static inline tommy_uint32_t file_path_hash(const char* sub) + 841 3891897 : static inline tommy_uint32_t file_path_hash(const char* sub) 842 : { - 843 3886182 : return tommy_hash_u32(0, sub, strlen(sub)); + 843 3891897 : return tommy_hash_u32(0, sub, strlen(sub)); 844 : } 845 : 846 : /** 847 : * Compute the hash of a file stamp. 848 : */ - 849 6275421 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) + 849 6275620 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) 850 : { - 851 6275421 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); + 851 6275620 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); 852 : } 853 : 854 : /** @@ -933,9 +933,9 @@ 871 : */ 872 : int extent_file_compare(const void* void_a, const void* void_b); 873 : - 874 209328 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask) + 874 209329 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask) 875 : { - 876 209328 : return (slink->flag & mask) == mask; + 876 209329 : return (slink->flag & mask) == mask; 877 : } 878 : 879 39461 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask) @@ -1088,19 +1088,19 @@ 1026 : /** 1027 : * Get the file position from the parity position. 1028 : */ - 1029 11723835 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) + 1029 11722518 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) 1030 : { 1031 : struct snapraid_file* ret; 1032 : - 1033 11723835 : ret = fs_par2file_find(disk, parity_pos, file_pos); - 1034 11724079 : if (ret == 0) { + 1033 11722518 : ret = fs_par2file_find(disk, parity_pos, file_pos); + 1034 11724212 : if (ret == 0) { 1035 : /* LCOV_EXCL_START */ 1036 : log_fatal("Internal inconsistency when deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name); 1037 : os_abort(); 1038 : /* LCOV_EXCL_STOP */ 1039 : } 1040 : - 1041 11724079 : return ret; + 1041 11724212 : return ret; 1042 : } 1043 : 1044 : /** @@ -1112,19 +1112,19 @@ 1050 : /** 1051 : * Get the parity position from the file position. 1052 : */ - 1053 4755492 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) + 1053 4755524 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) 1054 : { 1055 : block_off_t ret; 1056 : - 1057 4755492 : ret = fs_file2par_find(disk, file, file_pos); - 1058 4755492 : if (ret == POS_NULL) { + 1057 4755524 : ret = fs_file2par_find(disk, file, file_pos); + 1058 4755524 : if (ret == POS_NULL) { 1059 : /* LCOV_EXCL_START */ 1060 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); 1061 : os_abort(); 1062 : /* LCOV_EXCL_STOP */ 1063 : } 1064 : - 1065 4755492 : return ret; + 1065 4755524 : return ret; 1066 : } 1067 : 1068 : /** @@ -1172,18 +1172,18 @@ 1110 : /** 1111 : * Make an info. 1112 : */ - 1113 194583 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) + 1113 194621 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) 1114 : { 1115 : /* clear the lowest bits as reserved for other information */ - 1116 194583 : snapraid_info info = last_access & ~INFO_MASK; + 1116 194621 : snapraid_info info = last_access & ~INFO_MASK; 1117 : - 1118 194583 : if (error != 0) - 1119 5278 : info |= 0x1; - 1120 194583 : if (rehash != 0) + 1118 194621 : if (error != 0) + 1119 5330 : info |= 0x1; + 1120 194621 : if (rehash != 0) 1121 14426 : info |= 0x2; - 1122 194583 : if (justsynced != 0) - 1123 143045 : info |= 0x4; - 1124 194583 : return info; + 1122 194621 : if (justsynced != 0) + 1123 143140 : info |= 0x4; + 1124 194621 : return info; 1125 : } 1126 : 1127 : /** @@ -1191,36 +1191,36 @@ 1129 : * This is the last time when the block was know to be correct. 1130 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub. 1131 : */ - 1132 883203 : static inline time_t info_get_time(snapraid_info info) + 1132 883145 : static inline time_t info_get_time(snapraid_info info) 1133 : { - 1134 883203 : return info & ~INFO_MASK; + 1134 883145 : return info & ~INFO_MASK; 1135 : } 1136 : 1137 : /** 1138 : * Extract the error information. 1139 : * Report if the block address had some problem. 1140 : */ - 1141 352076 : static inline int info_get_bad(snapraid_info info) + 1141 352062 : static inline int info_get_bad(snapraid_info info) 1142 : { - 1143 352076 : return (info & 0x1) != 0; + 1143 352062 : return (info & 0x1) != 0; 1144 : } 1145 : 1146 : /** 1147 : * Extract the rehash information. 1148 : * Report if the block address is using the old hash and needs to be rehashed. 1149 : */ - 1150 2046851 : static inline int info_get_rehash(snapraid_info info) + 1150 2046849 : static inline int info_get_rehash(snapraid_info info) 1151 : { - 1152 2046851 : return (info & 0x2) != 0; + 1152 2046849 : return (info & 0x2) != 0; 1153 : } 1154 : 1155 : /** 1156 : * Extract the scrubbed information. 1157 : * Report if the block address was never scrubbed. 1158 : */ - 1159 68634 : static inline int info_get_justsynced(snapraid_info info) + 1159 68576 : static inline int info_get_justsynced(snapraid_info info) 1160 : { - 1161 68634 : return (info & 0x4) != 0; + 1161 68576 : return (info & 0x4) != 0; 1162 : } 1163 : 1164 : /** @@ -1243,27 +1243,27 @@ 1181 : * Set the info at the specified position. 1182 : * The position is allocated if not yet done. 1183 : */ - 1184 1698121 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info) + 1184 1698196 : static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info) 1185 : { - 1186 1698121 : tommy_arrayblkof_grow(array, pos + 1); + 1186 1698196 : tommy_arrayblkof_grow(array, pos + 1); 1187 : - 1188 1698121 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); - 1189 1698121 : } + 1188 1698196 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); + 1189 1698196 : } 1190 : 1191 : /** 1192 : * Get the info at the specified position. 1193 : * For not allocated position, 0 is returned. 1194 : */ - 1195 5098669 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos) + 1195 5098731 : static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos) 1196 : { 1197 : snapraid_info info; 1198 : - 1199 5098669 : if (pos >= tommy_arrayblkof_size(array)) + 1199 5098731 : if (pos >= tommy_arrayblkof_size(array)) 1200 262643 : return 0; 1201 : - 1202 4836026 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); + 1202 4836088 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); 1203 : - 1204 4836026 : return info; + 1204 4836088 : return info; 1205 : } 1206 : 1207 : /** diff --git a/cov/cmdline/handle.c.func-sort-c.html b/cov/cmdline/handle.c.func-sort-c.html index 3014505f..a0e7b803 100644 --- a/cov/cmdline/handle.c.func-sort-c.html +++ b/cov/cmdline/handle.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 @@ -61,31 +61,31 @@ handle_read - 5856126 + 5854217 handle_close - 4647204 + 4646580 handle_open - 2185997 + 2184769 handle_create - 771283 + 771310 handle_write - 288377 + 288515 handle_utime - 119405 + 119462 handle_truncate - 3254 + 3189 handle_mapping diff --git a/cov/cmdline/handle.c.func.html b/cov/cmdline/handle.c.func.html index 75b05487..9cac3192 100644 --- a/cov/cmdline/handle.c.func.html +++ b/cov/cmdline/handle.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 @@ -61,11 +61,11 @@ handle_close - 4647204 + 4646580 handle_create - 771283 + 771310 handle_mapping @@ -73,23 +73,23 @@ handle_open - 2185997 + 2184769 handle_read - 5856126 + 5854217 handle_truncate - 3254 + 3189 handle_utime - 119405 + 119462 handle_write - 288377 + 288515
diff --git a/cov/cmdline/handle.c.gcov.html b/cov/cmdline/handle.c.gcov.html index 3d2ab90a..86c64076 100644 --- a/cov/cmdline/handle.c.gcov.html +++ b/cov/cmdline/handle.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 @@ -86,64 +86,64 @@ 24 : /****************************************************************************/ 25 : /* handle */ 26 : - 27 771283 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) + 27 771310 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) 28 : { 29 : int ret; 30 : int flags; 31 : 32 : /* if it's the same file, and already opened, nothing to do */ - 33 771283 : if (handle->file == file && handle->f != -1) { + 33 771310 : if (handle->file == file && handle->f != -1) { 34 0 : return 0; 35 : } 36 : - 37 771283 : advise_init(&handle->advise, mode); - 38 771283 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 37 771310 : advise_init(&handle->advise, mode); + 38 771310 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 39 : - 40 771283 : ret = mkancestor(handle->path); - 41 771283 : if (ret != 0) { + 40 771310 : ret = mkancestor(handle->path); + 41 771310 : if (ret != 0) { 42 : /* LCOV_EXCL_START */ 43 : return -1; 44 : /* LCOV_EXCL_STOP */ 45 : } 46 : 47 : /* initial values, changed later if required */ - 48 771283 : handle->created = 0; + 48 771310 : handle->created = 0; 49 : 50 : /* flags for opening */ 51 : /* O_BINARY: open as binary file (Windows only) */ 52 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ - 53 771283 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + 53 771310 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); 54 : 55 : /* open for read write */ - 56 771283 : handle->f = open(handle->path, flags | O_RDWR); + 56 771310 : handle->f = open(handle->path, flags | O_RDWR); 57 : 58 : /* if failed for missing write permission */ - 59 771283 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { + 59 771310 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { 60 : /* open for real-only */ 61 0 : handle->f = open(handle->path, flags | O_RDONLY); 62 : } 63 : 64 : /* if failed for missing file */ - 65 771283 : if (handle->f == -1 && errno == ENOENT) { + 65 771310 : if (handle->f == -1 && errno == ENOENT) { 66 : char path_from[PATH_MAX]; 67 : 68 : /* check if exists a .unrecoverable copy, and rename to the real one */ - 69 176318 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); + 69 176441 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); 70 : - 71 176318 : if (rename(path_from, handle->path) == 0) { + 71 176441 : if (rename(path_from, handle->path) == 0) { 72 : /* open for read write */ - 73 63274 : handle->f = open(handle->path, flags | O_RDWR); + 73 63323 : handle->f = open(handle->path, flags | O_RDWR); 74 : } else { 75 : /* create it */ - 76 113044 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); - 77 113044 : if (handle->f != -1) { + 76 113118 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); + 77 113118 : if (handle->f != -1) { 78 : /* mark it as created if really done */ - 79 113044 : handle->created = 1; + 79 113118 : handle->created = 1; 80 : } 81 : } 82 : } 83 : - 84 771283 : if (handle->f == -1) { + 84 771310 : if (handle->f == -1) { 85 : /* LCOV_EXCL_START */ 86 : /* invalidate for error */ 87 : handle->file = 0; @@ -156,11 +156,11 @@ 94 : } 95 : 96 : /* just opened */ - 97 771283 : handle->file = file; + 97 771310 : handle->file = file; 98 : 99 : /* get the stat info */ - 100 771283 : ret = fstat(handle->f, &handle->st); - 101 771283 : if (ret != 0) { + 100 771310 : ret = fstat(handle->f, &handle->st); + 101 771310 : if (ret != 0) { 102 : /* LCOV_EXCL_START */ 103 : log_fatal("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); 104 : return -1; @@ -168,25 +168,25 @@ 106 : } 107 : 108 : /* get the size of the existing data */ - 109 771283 : handle->valid_size = handle->st.st_size; + 109 771310 : handle->valid_size = handle->st.st_size; 110 : - 111 771283 : ret = advise_open(&handle->advise, handle->f); - 112 771283 : if (ret != 0) { + 111 771310 : ret = advise_open(&handle->advise, handle->f); + 112 771310 : if (ret != 0) { 113 : /* LCOV_EXCL_START */ 114 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 115 : return -1; 116 : /* LCOV_EXCL_STOP */ 117 : } 118 : - 119 771283 : return 0; + 119 771310 : return 0; 120 : } 121 : - 122 3254 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) + 122 3189 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) 123 : { 124 : int ret; 125 : - 126 3254 : ret = ftruncate(handle->f, file->size); - 127 3254 : if (ret != 0) { + 126 3189 : ret = ftruncate(handle->f, file->size); + 127 3189 : if (ret != 0) { 128 : /* LCOV_EXCL_START */ 129 : if (errno == EACCES) { 130 : log_fatal("Failed to truncate file '%s' for missing write permission.\n", handle->path); @@ -198,56 +198,56 @@ 136 : } 137 : 138 : /* adjust the size to the truncated size */ - 139 3254 : handle->valid_size = file->size; + 139 3189 : handle->valid_size = file->size; 140 : - 141 3254 : return 0; + 141 3189 : return 0; 142 : } 143 : - 144 2185997 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing) + 144 2184769 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing) 145 : { 146 : int ret; 147 : int flags; 148 : - 149 2185997 : if (!out_missing) - 150 2185561 : out_missing = out; + 149 2184769 : if (!out_missing) + 150 2184975 : out_missing = out; 151 : 152 : /* if already opened, nothing to do */ - 153 2185997 : if (handle->file == file && handle->file != 0 && handle->f != -1) { - 154 468413 : return 0; + 153 2184769 : if (handle->file == file && handle->file != 0 && handle->f != -1) { + 154 468469 : return 0; 155 : } 156 : - 157 1717584 : advise_init(&handle->advise, mode); - 158 1717759 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 157 1716300 : advise_init(&handle->advise, mode); + 158 1717209 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 159 : 160 : /* for sure not created */ - 161 1717867 : handle->created = 0; + 161 1717080 : handle->created = 0; 162 : 163 : /* flags for opening */ 164 : /* O_BINARY: open as binary file (Windows only) */ 165 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ - 166 1717867 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + 166 1717080 : flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); 167 : 168 : /* open for read */ - 169 1717825 : handle->f = open_noatime(handle->path, flags | O_RDONLY); - 170 1717829 : if (handle->f == -1) { + 169 1717490 : handle->f = open_noatime(handle->path, flags | O_RDONLY); + 170 1715996 : if (handle->f == -1) { 171 : /* invalidate for error */ - 172 78600 : handle->file = 0; - 173 78600 : handle->f = -1; - 174 78600 : handle->valid_size = 0; + 172 78793 : handle->file = 0; + 173 78793 : handle->f = -1; + 174 78793 : handle->valid_size = 0; 175 : - 176 78600 : if (errno == ENOENT) - 177 78588 : out_missing("Missing file '%s'.\n", handle->path); + 176 78793 : if (errno == ENOENT) + 177 78781 : out_missing("Missing file '%s'.\n", handle->path); 178 : else 179 12 : out("Error opening file '%s'. %s.\n", handle->path, strerror(errno)); - 180 78600 : return -1; + 180 78793 : return -1; 181 : } 182 : 183 : /* just opened */ - 184 1639229 : handle->file = file; + 184 1637203 : handle->file = file; 185 : 186 : /* get the stat info */ - 187 1639229 : ret = fstat(handle->f, &handle->st); - 188 1639236 : if (ret != 0) { + 187 1637203 : ret = fstat(handle->f, &handle->st); + 188 1636791 : if (ret != 0) { 189 : /* LCOV_EXCL_START */ 190 : out("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); 191 : return -1; @@ -255,27 +255,27 @@ 193 : } 194 : 195 : /* get the size of the existing data */ - 196 1639236 : handle->valid_size = handle->st.st_size; + 196 1636791 : handle->valid_size = handle->st.st_size; 197 : - 198 1639236 : ret = advise_open(&handle->advise, handle->f); - 199 1639253 : if (ret != 0) { + 198 1636791 : ret = advise_open(&handle->advise, handle->f); + 199 1634580 : if (ret != 0) { 200 : /* LCOV_EXCL_START */ 201 : out("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 202 : return -1; 203 : /* LCOV_EXCL_STOP */ 204 : } 205 : - 206 1639253 : return 0; + 206 1634580 : return 0; 207 : } 208 : - 209 4647204 : int handle_close(struct snapraid_handle* handle) + 209 4646580 : int handle_close(struct snapraid_handle* handle) 210 : { 211 : int ret; 212 : 213 : /* close if open */ - 214 4647204 : if (handle->f != -1) { - 215 2410548 : ret = close(handle->f); - 216 2410577 : if (ret != 0) { + 214 4646580 : if (handle->f != -1) { + 215 2410222 : ret = close(handle->f); + 216 2410480 : if (ret != 0) { 217 : /* LCOV_EXCL_START */ 218 : log_fatal("Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 219 : @@ -289,14 +289,14 @@ 227 : } 228 : 229 : /* reset the descriptor */ - 230 4647233 : handle->file = 0; - 231 4647233 : handle->f = -1; - 232 4647233 : handle->valid_size = 0; + 230 4646838 : handle->file = 0; + 231 4646838 : handle->f = -1; + 232 4646838 : handle->valid_size = 0; 233 : - 234 4647233 : return 0; + 234 4646838 : return 0; 235 : } 236 : - 237 5856126 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing) + 237 5854217 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing) 238 : { 239 : ssize_t read_ret; 240 : data_off_t offset; @@ -304,70 +304,70 @@ 242 : unsigned count; 243 : int ret; 244 : - 245 5856126 : offset = file_pos * (data_off_t)block_size; + 245 5854217 : offset = file_pos * (data_off_t)block_size; 246 : - 247 5856126 : if (!out_missing) - 248 5843207 : out_missing = out; + 247 5854217 : if (!out_missing) + 248 5837298 : out_missing = out; 249 : 250 : /* check if we are going to read only not initialized data */ - 251 5856126 : if (offset >= handle->valid_size) { + 251 5854217 : if (offset >= handle->valid_size) { 252 : /* if the file is missing, it's at 0 size, or it's rebuilt while reading */ - 253 433247 : if (offset == handle->valid_size || handle->valid_size == 0) - 254 431947 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 253 433443 : if (offset == handle->valid_size || handle->valid_size == 0) + 254 432152 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset); 255 : else - 256 1300 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); - 257 433247 : return -1; + 256 1291 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 257 433443 : return -1; 258 : } 259 : - 260 5422879 : read_size = file_block_size(handle->file, file_pos, block_size); + 260 5420774 : read_size = file_block_size(handle->file, file_pos, block_size); 261 : - 262 5422871 : count = 0; + 262 5418955 : count = 0; 263 : do { 264 : /* read the full block to support O_DIRECT */ - 265 5431700 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count); - 266 5431360 : if (read_ret < 0) { + 265 5429094 : read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count); + 266 5428298 : if (read_ret < 0) { 267 : /* LCOV_EXCL_START */ 268 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, block_size - count, strerror(errno)); 269 : return -1; 270 : /* LCOV_EXCL_STOP */ 271 : } - 272 5431360 : if (read_ret == 0) { - 273 8879 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno)); - 274 8879 : return -1; + 272 5428298 : if (read_ret == 0) { + 273 8747 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno)); + 274 8747 : return -1; 275 : } 276 : - 277 5422481 : count += read_ret; - 278 5422481 : } while (count < read_size); + 277 5419551 : count += read_ret; + 278 5419551 : } while (count < read_size); 279 : 280 : /* pad with 0 */ - 281 5413652 : if (read_size < block_size) { - 282 2188671 : memset(block_buffer + read_size, 0, block_size - read_size); + 281 5409412 : if (read_size < block_size) { + 282 2188268 : memset(block_buffer + read_size, 0, block_size - read_size); 283 : } 284 : - 285 5413652 : ret = advise_read(&handle->advise, handle->f, offset, block_size); - 286 5413607 : if (ret != 0) { + 285 5409412 : ret = advise_read(&handle->advise, handle->f, offset, block_size); + 286 5410633 : if (ret != 0) { 287 : /* LCOV_EXCL_START */ 288 : out("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 289 : return -1; 290 : /* LCOV_EXCL_STOP */ 291 : } 292 : - 293 5413607 : return read_size; + 293 5410633 : return read_size; 294 : } 295 : - 296 288377 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) + 296 288515 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) 297 : { 298 : ssize_t write_ret; 299 : data_off_t offset; 300 : unsigned write_size; 301 : int ret; 302 : - 303 288377 : offset = file_pos * (data_off_t)block_size; + 303 288515 : offset = file_pos * (data_off_t)block_size; 304 : - 305 288377 : write_size = file_block_size(handle->file, file_pos, block_size); + 305 288515 : write_size = file_block_size(handle->file, file_pos, block_size); 306 : - 307 288377 : write_ret = pwrite(handle->f, block_buffer, write_size, offset); - 308 288377 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */ + 307 288515 : write_ret = pwrite(handle->f, block_buffer, write_size, offset); + 308 288515 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */ 309 : /* LCOV_EXCL_START */ 310 : log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno)); 311 : return -1; @@ -375,39 +375,39 @@ 313 : } 314 : 315 : /* adjust the size of the valid data */ - 316 288377 : if (handle->valid_size < offset + write_size) { - 317 282355 : handle->valid_size = offset + write_size; + 316 288515 : if (handle->valid_size < offset + write_size) { + 317 282439 : handle->valid_size = offset + write_size; 318 : } 319 : - 320 288377 : ret = advise_write(&handle->advise, handle->f, offset, block_size); - 321 288377 : if (ret != 0) { + 320 288515 : ret = advise_write(&handle->advise, handle->f, offset, block_size); + 321 288515 : if (ret != 0) { 322 : /* LCOV_EXCL_START */ 323 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); 324 : return -1; 325 : /* LCOV_EXCL_STOP */ 326 : } 327 : - 328 288377 : return 0; + 328 288515 : return 0; 329 : } 330 : - 331 119405 : int handle_utime(struct snapraid_handle* handle) + 331 119462 : int handle_utime(struct snapraid_handle* handle) 332 : { 333 : int ret; 334 : 335 : /* do nothing if not opened */ - 336 119405 : if (handle->f == -1) + 336 119462 : if (handle->f == -1) 337 0 : return 0; 338 : - 339 119405 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); + 339 119462 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); 340 : - 341 119405 : if (ret != 0) { + 341 119462 : if (ret != 0) { 342 : /* LCOV_EXCL_START */ 343 : log_fatal("Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 344 : return -1; 345 : /* LCOV_EXCL_STOP */ 346 : } 347 : - 348 119405 : return 0; + 348 119462 : return 0; 349 : } 350 : 351 221 : struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* handlemax) diff --git a/cov/cmdline/import.c.func-sort-c.html b/cov/cmdline/import.c.func-sort-c.html index 458a15a3..099061f5 100644 --- a/cov/cmdline/import.c.func-sort-c.html +++ b/cov/cmdline/import.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -61,11 +61,11 @@ import_block_hash - 656604 + 657048 state_import_fetch - 652132 + 652576 import_block_hash_compare diff --git a/cov/cmdline/import.c.func.html b/cov/cmdline/import.c.func.html index 384ffe57..20e9ef26 100644 --- a/cov/cmdline/import.c.func.html +++ b/cov/cmdline/import.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -61,7 +61,7 @@ import_block_hash - 656604 + 657048 import_block_hash_compare @@ -89,7 +89,7 @@ state_import_fetch - 652132 + 652576
diff --git a/cov/cmdline/import.c.gcov.html b/cov/cmdline/import.c.gcov.html index 307cb412..e1673ac2 100644 --- a/cov/cmdline/import.c.gcov.html +++ b/cov/cmdline/import.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 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 656604 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash) + 49 657048 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash) 50 : { 51 : /* the hash data is not aligned, and we cannot access it with a direct cast */ - 52 656604 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24); + 52 657048 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24); 53 : } 54 : 55 1750 : static void import_file(struct snapraid_state* state, const char* path, uint64_t size) @@ -207,24 +207,24 @@ 145 1750 : free(file); 146 1750 : } 147 : - 148 652132 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) + 148 652576 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) 149 : { 150 : struct snapraid_import_block* block; 151 : int ret; 152 : int f; - 153 652132 : const unsigned char* hash = missing_block->hash; - 154 652132 : unsigned block_size = state->block_size; + 153 652576 : const unsigned char* hash = missing_block->hash; + 154 652576 : unsigned block_size = state->block_size; 155 : unsigned read_size; 156 : unsigned char buffer_hash[HASH_MAX]; 157 : const char* path; 158 : - 159 652132 : if (rehash) { + 159 652576 : if (rehash) { 160 0 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash)); 161 : } else { - 162 652132 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); + 162 652576 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); 163 : } - 164 652132 : if (!block) - 165 647660 : return -1; + 164 652576 : if (!block) + 165 648104 : return -1; 166 : 167 4472 : path = block->file->path; 168 4472 : read_size = block->size; diff --git a/cov/cmdline/index-sort-f.html b/cov/cmdline/index-sort-f.html index 90111741..036a3312 100644 --- a/cov/cmdline/index-sort-f.html +++ b/cov/cmdline/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 8683 - 9562 - 90.8 % + 8640 + 9584 + 90.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 488 - 503 - 97.0 % + 487 + 504 + 96.6 % @@ -69,6 +69,16 @@ Line Coverage Sort by line coverage Functions Sort by function coverage + + unix.c + +
70.2%70.2%
+ + 70.2 % + 314 / 447 + 87.1 % + 27 / 31 + import.c @@ -80,12 +90,12 @@ 7 / 8 - unix.c + io.c -
72.4%72.4%
+
92.6%92.6%
- 72.4 % - 320 / 442 + 92.6 % + 386 / 417 90.3 % 28 / 31 @@ -99,16 +109,6 @@ 90.9 % 10 / 11 - - io.c - -
97.6%97.6%
- - 97.6 % - 407 / 417 - 93.5 % - 29 / 31 - parity.c @@ -142,30 +142,30 @@ support.c -
80.2%80.2%
+
80.3%80.3%
- 80.2 % - 441 / 550 + 80.3 % + 449 / 559 96.8 % - 60 / 62 + 61 / 63 elem.c -
94.5%94.5%
+
94.6%94.6%
- 94.5 % - 597 / 632 + 94.6 % + 598 / 632 97.1 % 67 / 69 state.c -
91.7%91.7%
+
89.8%89.8%
- 91.7 % - 1478 / 1612 + 89.8 % + 1450 / 1615 97.8 % 45 / 46 @@ -262,10 +262,10 @@ pool.c -
94.1%94.1%
+
94.4%94.4%
- 94.1 % - 64 / 68 + 94.4 % + 67 / 71 100.0 % 3 / 3 @@ -332,10 +332,10 @@ sync.c -
91.8%91.8%
+
91.4%91.4%
- 91.8 % - 501 / 546 + 91.4 % + 499 / 546 100.0 % 7 / 7 @@ -372,10 +372,10 @@ check.c -
91.5%91.5%
+
91.5%91.5%
91.5 % - 709 / 775 + 711 / 777 100.0 % 9 / 9 diff --git a/cov/cmdline/index-sort-l.html b/cov/cmdline/index-sort-l.html index 7f0baa1d..c484c863 100644 --- a/cov/cmdline/index-sort-l.html +++ b/cov/cmdline/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 8683 - 9562 - 90.8 % + 8640 + 9584 + 90.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 488 - 503 - 97.0 % + 487 + 504 + 96.6 % @@ -72,12 +72,12 @@ unix.c -
72.4%72.4%
+
70.2%70.2%
- 72.4 % - 320 / 442 - 90.3 % - 28 / 31 + 70.2 % + 314 / 447 + 87.1 % + 27 / 31 dry.c @@ -92,12 +92,12 @@ support.c -
80.2%80.2%
+
80.3%80.3%
- 80.2 % - 441 / 550 + 80.3 % + 449 / 559 96.8 % - 60 / 62 + 61 / 63 scrub.c @@ -119,6 +119,16 @@ 100.0 % 23 / 23 + + state.c + +
89.8%89.8%
+ + 89.8 % + 1450 / 1615 + 97.8 % + 45 / 46 + stream.h @@ -169,36 +179,26 @@ 100.0 % 9 / 9 - - check.c - -
91.5%91.5%
- - 91.5 % - 709 / 775 - 100.0 % - 9 / 9 - - - state.c - -
91.7%91.7%
- - 91.7 % - 1478 / 1612 - 97.8 % - 45 / 46 - sync.c -
91.8%91.8%
+
91.4%91.4%
- 91.8 % - 501 / 546 + 91.4 % + 499 / 546 100.0 % 7 / 7 + + check.c + +
91.5%91.5%
+ + 91.5 % + 711 / 777 + 100.0 % + 9 / 9 + parity.c @@ -209,6 +209,16 @@ 94.7 % 18 / 19 + + io.c + +
92.6%92.6%
+ + 92.6 % + 386 / 417 + 90.3 % + 28 / 31 + mktest.c @@ -252,20 +262,20 @@ pool.c -
94.1%94.1%
+
94.4%94.4%
- 94.1 % - 64 / 68 + 94.4 % + 67 / 71 100.0 % 3 / 3 elem.c -
94.5%94.5%
+
94.6%94.6%
- 94.5 % - 597 / 632 + 94.6 % + 598 / 632 97.1 % 67 / 69 @@ -329,16 +339,6 @@ 100.0 % 8 / 8 - - io.c - -
97.6%97.6%
- - 97.6 % - 407 / 417 - 93.5 % - 29 / 31 - speed.c diff --git a/cov/cmdline/index.html b/cov/cmdline/index.html index 4531671e..054a9a21 100644 --- a/cov/cmdline/index.html +++ b/cov/cmdline/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 8683 - 9562 - 90.8 % + 8640 + 9584 + 90.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 488 - 503 - 97.0 % + 487 + 504 + 96.6 % @@ -72,10 +72,10 @@ check.c -
91.5%91.5%
+
91.5%91.5%
91.5 % - 709 / 775 + 711 / 777 100.0 % 9 / 9 @@ -112,10 +112,10 @@ elem.c -
94.5%94.5%
+
94.6%94.6%
- 94.5 % - 597 / 632 + 94.6 % + 598 / 632 97.1 % 67 / 69 @@ -152,12 +152,12 @@ io.c -
97.6%97.6%
+
92.6%92.6%
- 97.6 % - 407 / 417 - 93.5 % - 29 / 31 + 92.6 % + 386 / 417 + 90.3 % + 28 / 31 list.c @@ -212,10 +212,10 @@ pool.c -
94.1%94.1%
+
94.4%94.4%
- 94.1 % - 64 / 68 + 94.4 % + 67 / 71 100.0 % 3 / 3 @@ -312,10 +312,10 @@ state.c -
91.7%91.7%
+
89.8%89.8%
- 91.7 % - 1478 / 1612 + 89.8 % + 1450 / 1615 97.8 % 45 / 46 @@ -352,12 +352,12 @@ support.c -
80.2%80.2%
+
80.3%80.3%
- 80.2 % - 441 / 550 + 80.3 % + 449 / 559 96.8 % - 60 / 62 + 61 / 63 support.h @@ -372,10 +372,10 @@ sync.c -
91.8%91.8%
+
91.4%91.4%
- 91.8 % - 501 / 546 + 91.4 % + 499 / 546 100.0 % 7 / 7 @@ -392,12 +392,12 @@ unix.c -
72.4%72.4%
+
70.2%70.2%
- 72.4 % - 320 / 442 - 90.3 % - 28 / 31 + 70.2 % + 314 / 447 + 87.1 % + 27 / 31 util.c diff --git a/cov/cmdline/io.c.func-sort-c.html b/cov/cmdline/io.c.func-sort-c.html index c7526147..63937ef6 100644 --- a/cov/cmdline/io.c.func-sort-c.html +++ b/cov/cmdline/io.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 407 + 386 417 - 97.6 % + 92.6 % Date: - 2016-11-21 + 2017-05-13 Functions: - 29 + 28 31 - 93.5 % + 90.3 % @@ -61,27 +61,27 @@ io_reader_step - 1162708 + 1156990 io_task_read_thread - 1081860 + 1082196 io_reader_worker - 1081809 + 1081760 io_data_read_thread - 871056 + 871392 io_writer_step - 554042 + 554063 io_parity_write_thread - 553582 + 553918 io_parity_read_thread @@ -89,27 +89,27 @@ io_position_next - 162024 + 162080 io_reader_sched - 162024 + 162080 io_read_next_thread - 145271 + 145327 io_writer_sched - 112438 + 112510 io_write_preset_thread - 110042 + 110098 io_write_next_thread - 110042 + 110098 io_task_read_mono @@ -137,15 +137,15 @@ io_writer_sched_empty - 2291 + 2275 io_reader_thread - 648 + 615 io_writer_thread - 462 + 461 io_init @@ -163,10 +163,6 @@ io_stop_thread 95 - - io_refresh_thread - 1 - io_start_mono 1 @@ -179,6 +175,10 @@ io_refresh_mono 0 + + io_refresh_thread + 0 + io_parity_read_mono 0 diff --git a/cov/cmdline/io.c.func.html b/cov/cmdline/io.c.func.html index 87d56824..3741101d 100644 --- a/cov/cmdline/io.c.func.html +++ b/cov/cmdline/io.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 407 + 386 417 - 97.6 % + 92.6 % Date: - 2016-11-21 + 2017-05-13 Functions: - 29 + 28 31 - 93.5 % + 90.3 % @@ -65,7 +65,7 @@ io_data_read_thread - 871056 + 871392 io_done @@ -89,11 +89,11 @@ io_parity_write_thread - 553582 + 553918 io_position_next - 162024 + 162080 io_read_next_mono @@ -101,23 +101,23 @@ io_read_next_thread - 145271 + 145327 io_reader_sched - 162024 + 162080 io_reader_step - 1162708 + 1156990 io_reader_thread - 648 + 615 io_reader_worker - 1081809 + 1081760 io_refresh_mono @@ -125,7 +125,7 @@ io_refresh_thread - 1 + 0 io_start_mono @@ -149,7 +149,7 @@ io_task_read_thread - 1081860 + 1082196 io_write_next_mono @@ -157,7 +157,7 @@ io_write_next_thread - 110042 + 110098 io_write_preset_mono @@ -165,23 +165,23 @@ io_write_preset_thread - 110042 + 110098 io_writer_sched - 112438 + 112510 io_writer_sched_empty - 2291 + 2275 io_writer_step - 554042 + 554063 io_writer_thread - 462 + 461
diff --git a/cov/cmdline/io.c.gcov.html b/cov/cmdline/io.c.gcov.html index c7a9d8f2..41143203 100644 --- a/cov/cmdline/io.c.gcov.html +++ b/cov/cmdline/io.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 407 + 386 417 - 97.6 % + 92.6 % Date: - 2016-11-21 + 2017-05-13 Functions: - 29 + 28 31 - 93.5 % + 90.3 % @@ -84,103 +84,103 @@ 22 : /** 23 : * Get the next block position to process. 24 : */ - 25 162024 : static block_off_t io_position_next(struct snapraid_io* io) + 25 162080 : static block_off_t io_position_next(struct snapraid_io* io) 26 : { 27 : block_off_t blockcur; 28 : 29 : /* get the next position */ - 30 647457 : while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next)) - 31 323409 : ++io->block_next; + 30 647513 : while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next)) + 31 323353 : ++io->block_next; 32 : - 33 162024 : blockcur = io->block_next; + 33 162080 : blockcur = io->block_next; 34 : 35 : /* next block for the next call */ - 36 162024 : ++io->block_next; + 36 162080 : ++io->block_next; 37 : - 38 162024 : return blockcur; + 38 162080 : return blockcur; 39 : } 40 : 41 : /** 42 : * Setup the next pending task for all readers. 43 : */ - 44 162024 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) + 44 162080 : static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) 45 : { 46 : unsigned i; 47 : - 48 1354956 : for (i = 0; i < io->reader_max; ++i) { - 49 1192932 : struct snapraid_worker* worker = &io->reader_map[i]; - 50 1192932 : struct snapraid_task* task = &worker->task_map[task_index]; + 48 1355348 : for (i = 0; i < io->reader_max; ++i) { + 49 1193268 : struct snapraid_worker* worker = &io->reader_map[i]; + 50 1193268 : struct snapraid_task* task = &worker->task_map[task_index]; 51 : 52 : /* setup the new pending task */ - 53 1192932 : if (blockcur < io->block_max) - 54 1109982 : task->state = TASK_STATE_READY; + 53 1193268 : if (blockcur < io->block_max) + 54 1110318 : task->state = TASK_STATE_READY; 55 : else 56 82950 : task->state = TASK_STATE_EMPTY; 57 : - 58 1192932 : task->path[0] = 0; - 59 1192932 : if (worker->handle) - 60 972144 : task->disk = worker->handle->disk; + 58 1193268 : task->path[0] = 0; + 59 1193268 : if (worker->handle) + 60 972480 : task->disk = worker->handle->disk; 61 : else 62 220788 : task->disk = 0; - 63 1192932 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; - 64 1192932 : task->position = blockcur; - 65 1192932 : task->block = 0; - 66 1192932 : task->file = 0; - 67 1192932 : task->file_pos = 0; - 68 1192932 : task->read_size = 0; - 69 1192932 : task->is_timestamp_different = 0; + 63 1193268 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + 64 1193268 : task->position = blockcur; + 65 1193268 : task->block = 0; + 66 1193268 : task->file = 0; + 67 1193268 : task->file_pos = 0; + 68 1193268 : task->read_size = 0; + 69 1193268 : task->is_timestamp_different = 0; 70 : } - 71 162024 : } + 71 162080 : } 72 : 73 : /** 74 : * Setup the next pending task for all writers. 75 : */ - 76 112438 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) + 76 112510 : static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) 77 : { 78 : unsigned i; 79 : - 80 656961 : for (i = 0; i < io->writer_max; ++i) { - 81 544523 : struct snapraid_worker* worker = &io->writer_map[i]; - 82 544523 : struct snapraid_task* task = &worker->task_map[task_index]; + 80 657465 : for (i = 0; i < io->writer_max; ++i) { + 81 544955 : struct snapraid_worker* worker = &io->writer_map[i]; + 82 544955 : struct snapraid_task* task = &worker->task_map[task_index]; 83 : 84 : /* setup the new pending task */ - 85 544523 : task->state = TASK_STATE_READY; - 86 544523 : task->path[0] = 0; - 87 544523 : task->disk = 0; - 88 544523 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; - 89 544523 : task->position = blockcur; - 90 544523 : task->block = 0; - 91 544523 : task->file = 0; - 92 544523 : task->file_pos = 0; - 93 544523 : task->read_size = 0; - 94 544523 : task->is_timestamp_different = 0; + 85 544955 : task->state = TASK_STATE_READY; + 86 544955 : task->path[0] = 0; + 87 544955 : task->disk = 0; + 88 544955 : task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + 89 544955 : task->position = blockcur; + 90 544955 : task->block = 0; + 91 544955 : task->file = 0; + 92 544955 : task->file_pos = 0; + 93 544955 : task->read_size = 0; + 94 544955 : task->is_timestamp_different = 0; 95 : } - 96 112438 : } + 96 112510 : } 97 : 98 : /** 99 : * Setup an empty next pending task for all writers. 100 : */ - 101 2291 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur) + 101 2275 : static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur) 102 : { 103 : unsigned i; 104 : - 105 16037 : for (i = 0; i < io->writer_max; ++i) { - 106 13746 : struct snapraid_worker* worker = &io->writer_map[i]; - 107 13746 : struct snapraid_task* task = &worker->task_map[task_index]; + 105 15925 : for (i = 0; i < io->writer_max; ++i) { + 106 13650 : struct snapraid_worker* worker = &io->writer_map[i]; + 107 13650 : struct snapraid_task* task = &worker->task_map[task_index]; 108 : 109 : /* setup the new pending task */ - 110 13746 : task->state = TASK_STATE_EMPTY; - 111 13746 : task->path[0] = 0; - 112 13746 : task->disk = 0; - 113 13746 : task->buffer = 0; - 114 13746 : task->position = blockcur; - 115 13746 : task->block = 0; - 116 13746 : task->file = 0; - 117 13746 : task->file_pos = 0; - 118 13746 : task->read_size = 0; - 119 13746 : task->is_timestamp_different = 0; + 110 13650 : task->state = TASK_STATE_EMPTY; + 111 13650 : task->path[0] = 0; + 112 13650 : task->disk = 0; + 113 13650 : task->buffer = 0; + 114 13650 : task->position = blockcur; + 115 13650 : task->block = 0; + 116 13650 : task->file = 0; + 117 13650 : task->file_pos = 0; + 118 13650 : task->read_size = 0; + 119 13650 : task->is_timestamp_different = 0; 120 : } - 121 2291 : } + 121 2275 : } 122 : 123 : /*****************************************************************************/ 124 : /* mono thread */ @@ -331,55 +331,55 @@ 269 : * 270 : * This is the synchronization point for workers with the io. 271 : */ - 272 1162708 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) + 272 1156990 : static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) 273 : { - 274 1162708 : struct snapraid_io* io = worker->io; + 274 1156990 : struct snapraid_io* io = worker->io; 275 : 276 : /* the synchronization is protected by the io mutex */ - 277 1162708 : thread_mutex_lock(&io->io_mutex); + 277 1156990 : thread_mutex_lock(&io->io_mutex); 278 : 279 : while (1) { 280 : unsigned next_index; 281 : 282 : /* check if the worker has to exit */ 283 : /* even if there is work to do */ - 284 2057573 : if (io->done) { + 284 2137549 : if (io->done) { 285 648 : thread_mutex_unlock(&io->io_mutex); 286 648 : return 0; 287 : } 288 : 289 : /* get the next pending task */ - 290 2056925 : next_index = (worker->index + 1) % io->io_max; + 290 2136901 : next_index = (worker->index + 1) % io->io_max; 291 : 292 : /* if the queue of pending tasks is not empty */ - 293 2056925 : if (next_index != io->reader_index) { + 293 2136901 : if (next_index != io->reader_index) { 294 : struct snapraid_task* task; 295 : 296 : /* the index that the IO may be waiting for */ - 297 1162618 : unsigned waiting_index = io->reader_index; + 297 1164456 : unsigned waiting_index = io->reader_index; 298 : 299 : /* the index that worker just completed */ - 300 1162618 : unsigned done_index = worker->index; + 300 1164456 : unsigned done_index = worker->index; 301 : 302 : /* get the new working task */ - 303 1162618 : worker->index = next_index; - 304 1162618 : task = &worker->task_map[worker->index]; + 303 1164456 : worker->index = next_index; + 304 1164456 : task = &worker->task_map[worker->index]; 305 : 306 : /* if the just completed task is at this index */ - 307 1162618 : if (done_index == waiting_index) { + 307 1164456 : if (done_index == waiting_index) { 308 : /* notify the IO that a new read is complete */ - 309 2747 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex); + 309 1053 : thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex); 310 : } else { - 311 1159871 : thread_mutex_unlock(&io->io_mutex); + 311 1163403 : thread_mutex_unlock(&io->io_mutex); 312 : } 313 : 314 : /* return the new task */ - 315 1162520 : return task; + 315 1163731 : return task; 316 : } 317 : 318 : /* otherwise wait for a read_sched event */ - 319 894307 : thread_cond_wait(&io->read_sched, &io->io_mutex); - 320 894307 : } + 319 972445 : thread_cond_wait(&io->read_sched, &io->io_mutex); + 320 972445 : } 321 : } 322 : 323 : /** @@ -387,61 +387,61 @@ 325 : * 326 : * This is the synchronization point for workers with the io. 327 : */ - 328 554042 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state) + 328 554063 : static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state) 329 : { - 330 554042 : struct snapraid_io* io = worker->io; + 330 554063 : struct snapraid_io* io = worker->io; 331 : int error_index; 332 : 333 : /* the synchronization is protected by the io mutex */ - 334 554042 : thread_mutex_lock(&io->io_mutex); + 334 554063 : thread_mutex_lock(&io->io_mutex); 335 : 336 : /* counts the number of errors in the global state */ - 337 554044 : error_index = state - IO_WRITER_ERROR_BASE; - 338 554044 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX) + 337 554380 : error_index = state - IO_WRITER_ERROR_BASE; + 338 554380 : if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX) 339 0 : ++io->writer_error[error_index]; 340 : 341 : while (1) { 342 : unsigned next_index; 343 : 344 : /* get the next pending task */ - 345 625754 : next_index = (worker->index + 1) % io->io_max; + 345 637383 : next_index = (worker->index + 1) % io->io_max; 346 : 347 : /* if the queue of pending tasks is not empty */ - 348 625754 : if (next_index != io->writer_index) { + 348 637383 : if (next_index != io->writer_index) { 349 : struct snapraid_task* task; 350 : 351 : /* the index that the IO may be waiting for */ - 352 553582 : unsigned waiting_index = (io->writer_index + 1) % io->io_max; + 352 553918 : unsigned waiting_index = (io->writer_index + 1) % io->io_max; 353 : 354 : /* the index that worker just completed */ - 355 553582 : unsigned done_index = worker->index; + 355 553918 : unsigned done_index = worker->index; 356 : 357 : /* get the new working task */ - 358 553582 : worker->index = next_index; - 359 553582 : task = &worker->task_map[worker->index]; + 358 553918 : worker->index = next_index; + 359 553918 : task = &worker->task_map[worker->index]; 360 : 361 : /* if the just completed task is at this index */ - 362 553582 : if (done_index == waiting_index) { + 362 553918 : if (done_index == waiting_index) { 363 : /* notify the IO that a new write is complete */ - 364 83140 : thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex); + 364 86028 : thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex); 365 : } else { - 366 470442 : thread_mutex_unlock(&io->io_mutex); + 366 467890 : thread_mutex_unlock(&io->io_mutex); 367 : } 368 : 369 : /* return the new task */ - 370 553581 : return task; + 370 553862 : return task; 371 : } 372 : 373 : /* check if the worker has to exit */ 374 : /* but only if there is no work to do */ - 375 72172 : if (io->done) { + 375 83465 : if (io->done) { 376 462 : thread_mutex_unlock(&io->io_mutex); - 377 462 : return 0; + 377 461 : return 0; 378 : } 379 : 380 : /* otherwise wait for a write_sched event */ - 381 71710 : thread_cond_wait(&io->write_sched, &io->io_mutex); - 382 71710 : } + 381 83003 : thread_cond_wait(&io->write_sched, &io->io_mutex); + 382 83003 : } 383 : } 384 : 385 : /** @@ -449,146 +449,146 @@ 387 : * 388 : * This is the synchronization point for workers with the io. 389 : */ - 390 145271 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer) + 390 145327 : static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer) 391 : { 392 : block_off_t blockcur_schedule; 393 : block_off_t blockcur_caller; 394 : unsigned i; 395 : 396 : /* get the next parity position to process */ - 397 145271 : blockcur_schedule = io_position_next(io); + 397 145327 : blockcur_schedule = io_position_next(io); 398 : 399 : /* ensure that all data/parity was read */ - 400 145271 : assert(io->reader_list[0] == io->reader_max); + 400 145327 : assert(io->reader_list[0] == io->reader_max); 401 : 402 : /* setup the list of workers to process */ - 403 1373050 : for (i = 0; i <= io->reader_max; ++i) - 404 1227779 : io->reader_list[i] = i; + 403 1373498 : for (i = 0; i <= io->reader_max; ++i) + 404 1228171 : io->reader_list[i] = i; 405 : 406 : /* the synchronization is protected by the io mutex */ - 407 145271 : thread_mutex_lock(&io->io_mutex); + 407 145327 : thread_mutex_lock(&io->io_mutex); 408 : 409 : /* schedule the next read */ - 410 145271 : io_reader_sched(io, io->reader_index, blockcur_schedule); + 410 145327 : io_reader_sched(io, io->reader_index, blockcur_schedule); 411 : 412 : /* set the index for the tasks to return to the caller */ - 413 145271 : io->reader_index = (io->reader_index + 1) % io->io_max; + 413 145327 : io->reader_index = (io->reader_index + 1) % io->io_max; 414 : 415 : /* get the position to operate at high level from one task */ - 416 145271 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position; + 416 145327 : blockcur_caller = io->reader_map[0].task_map[io->reader_index].position; 417 : 418 : /* set the buffer to use */ - 419 145271 : *buffer = io->buffer_map[io->reader_index]; + 419 145327 : *buffer = io->buffer_map[io->reader_index]; 420 : 421 : /* signal all the workers that there is a new pending task */ - 422 145271 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex); + 422 145327 : thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex); 423 : - 424 145271 : return blockcur_caller; + 424 145327 : return blockcur_caller; 425 : } 426 : - 427 110042 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip) + 427 110098 : static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip) 428 : { 429 : (void)io; 430 : (void)blockcur; 431 : (void)skip; - 432 110042 : } + 432 110098 : } 433 : - 434 110042 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) + 434 110098 : static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) 435 : { 436 : unsigned i; 437 : 438 : /* ensure that all parity was written */ - 439 110042 : assert(io->writer_list[0] == io->writer_max); + 439 110098 : assert(io->writer_list[0] == io->writer_max); 440 : 441 : /* setup the list of workers to process */ - 442 773666 : for (i = 0; i <= io->writer_max; ++i) - 443 663624 : io->writer_list[i] = i; + 442 774114 : for (i = 0; i <= io->writer_max; ++i) + 443 664016 : io->writer_list[i] = i; 444 : 445 : /* the synchronization is protected by the io mutex */ - 446 110042 : thread_mutex_lock(&io->io_mutex); + 446 110098 : thread_mutex_lock(&io->io_mutex); 447 : 448 : /* report errors */ - 449 550210 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { - 450 440168 : writer_error[i] = io->writer_error[i]; - 451 440168 : io->writer_error[i] = 0; + 449 550490 : for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { + 450 440392 : writer_error[i] = io->writer_error[i]; + 451 440392 : io->writer_error[i] = 0; 452 : } 453 : - 454 110042 : if (skip) { + 454 110098 : if (skip) { 455 : /* skip the next write */ - 456 2291 : io_writer_sched_empty(io, io->writer_index, blockcur); + 456 2275 : io_writer_sched_empty(io, io->writer_index, blockcur); 457 : } else { 458 : /* schedule the next write */ - 459 107751 : io_writer_sched(io, io->writer_index, blockcur); + 459 107823 : io_writer_sched(io, io->writer_index, blockcur); 460 : } 461 : 462 : /* at this point the writers must be in sync with the readers */ - 463 110042 : assert(io->writer_index == io->reader_index); + 463 110098 : assert(io->writer_index == io->reader_index); 464 : 465 : /* set the index to be used for the next write */ - 466 110042 : io->writer_index = (io->writer_index + 1) % io->io_max; + 466 110098 : io->writer_index = (io->writer_index + 1) % io->io_max; 467 : 468 : /* signal all the workers that there is a new pending task */ - 469 110042 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex); - 470 110042 : } + 469 110098 : thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex); + 470 110098 : } 471 : - 472 1 : static void io_refresh_thread(struct snapraid_io* io) + 472 0 : static void io_refresh_thread(struct snapraid_io* io) 473 : { 474 : unsigned i; 475 : 476 : /* the synchronization is protected by the io mutex */ - 477 1 : thread_mutex_lock(&io->io_mutex); + 477 0 : thread_mutex_lock(&io->io_mutex); 478 : 479 : /* for all readers, count the number of read blocks */ - 480 7 : for (i = 0; i < io->reader_max; ++i) { + 480 0 : for (i = 0; i < io->reader_max; ++i) { 481 : unsigned begin, end, cached; - 482 6 : struct snapraid_worker* worker = &io->reader_map[i]; + 482 0 : struct snapraid_worker* worker = &io->reader_map[i]; 483 : 484 : /* the first block read */ - 485 6 : begin = io->reader_index + 1; + 485 0 : begin = io->reader_index + 1; 486 : /* the block in reading */ - 487 6 : end = worker->index; - 488 6 : if (begin > end) - 489 6 : end += io->io_max; - 490 6 : cached = end - begin; + 487 0 : end = worker->index; + 488 0 : if (begin > end) + 489 0 : end += io->io_max; + 490 0 : cached = end - begin; 491 : - 492 6 : if (worker->parity_handle) + 492 0 : if (worker->parity_handle) 493 0 : io->state->parity[worker->parity_handle->level].cached = cached; 494 : else - 495 6 : worker->handle->disk->cached = cached; + 495 0 : worker->handle->disk->cached = cached; 496 : } 497 : 498 : /* for all writers, count the number of written blocks */ 499 : /* note that this is a kind of "opposite" of cached blocks */ - 500 2 : for (i = 0; i < io->writer_max; ++i) { + 500 0 : for (i = 0; i < io->writer_max; ++i) { 501 : unsigned begin, end, cached; - 502 1 : struct snapraid_worker* worker = &io->writer_map[i]; + 502 0 : struct snapraid_worker* worker = &io->writer_map[i]; 503 : 504 : /* the first block written */ - 505 1 : begin = io->writer_index + 1; + 505 0 : begin = io->writer_index + 1; 506 : /* the block in writing */ - 507 1 : end = worker->index; - 508 1 : if (begin > end) - 509 1 : end += io->io_max; - 510 1 : cached = end - begin; + 507 0 : end = worker->index; + 508 0 : if (begin > end) + 509 0 : end += io->io_max; + 510 0 : cached = end - begin; 511 : - 512 1 : io->state->parity[worker->parity_handle->level].cached = cached; + 512 0 : io->state->parity[worker->parity_handle->level].cached = cached; 513 : } 514 : - 515 1 : thread_mutex_unlock(&io->io_mutex); - 516 1 : } + 515 0 : thread_mutex_unlock(&io->io_mutex); + 516 0 : } 517 : - 518 1081860 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 518 1082196 : static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 519 : { 520 : unsigned waiting_cycle; 521 : 522 : /* count the waiting cycle */ - 523 1081860 : waiting_cycle = 0; + 523 1082196 : waiting_cycle = 0; 524 : 525 : /* clear the waiting indexes */ - 526 1081860 : *waiting_mac = 0; + 526 1082196 : *waiting_mac = 0; 527 : 528 : /* the synchronization is protected by the io mutex */ - 529 1081860 : thread_mutex_lock(&io->io_mutex); + 529 1082196 : thread_mutex_lock(&io->io_mutex); 530 : 531 : while (1) { 532 : unsigned char* let; @@ -597,67 +597,67 @@ 535 : /* get the index the IO is using */ 536 : /* we must ensure that this index has not a read in progress */ 537 : /* to avoid a concurrent access */ - 538 1084465 : busy_index = io->reader_index; + 538 1083198 : busy_index = io->reader_index; 539 : 540 : /* search for a worker that has already finished */ - 541 1084465 : let = &io->reader_list[0]; + 541 1083198 : let = &io->reader_list[0]; 542 : while (1) { - 543 1097188 : unsigned i = *let; + 543 1087885 : unsigned i = *let; 544 : 545 : /* if we are at the end */ - 546 1097188 : if (i == io->reader_max) - 547 2605 : break; + 546 1087885 : if (i == io->reader_max) + 547 1002 : break; 548 : 549 : /* if it's in range */ - 550 1094583 : if (base <= i && i < base + count) { + 550 1086883 : if (base <= i && i < base + count) { 551 : struct snapraid_worker* worker; 552 : 553 : /* if it's the first cycle */ - 554 1092105 : if (waiting_cycle == 0) { + 554 1085977 : if (waiting_cycle == 0) { 555 : /* store the waiting indexes */ - 556 1088986 : waiting_map[(*waiting_mac)++] = i - base; + 556 1084926 : waiting_map[(*waiting_mac)++] = i - base; 557 : } 558 : - 559 1092105 : worker = &io->reader_map[i]; + 559 1085977 : worker = &io->reader_map[i]; 560 : 561 : /* if the worker has finished this index */ - 562 1092105 : if (busy_index != worker->index) { + 562 1085977 : if (busy_index != worker->index) { 563 : struct snapraid_task* task; 564 : - 565 1081860 : task = &worker->task_map[io->reader_index]; + 565 1082196 : task = &worker->task_map[io->reader_index]; 566 : - 567 1081860 : thread_mutex_unlock(&io->io_mutex); + 567 1082196 : thread_mutex_unlock(&io->io_mutex); 568 : 569 : /* mark the worker as processed */ 570 : /* setting the previous one to point at the next one */ - 571 1081860 : *let = io->reader_list[i + 1]; + 571 1082196 : *let = io->reader_list[i + 1]; 572 : 573 : /* return the position */ - 574 1081860 : *pos = i - base; + 574 1082196 : *pos = i - base; 575 : 576 : /* on the first cycle, no one is waiting */ - 577 1081860 : if (waiting_cycle == 0) - 578 1079288 : *waiting_mac = 0; + 577 1082196 : if (waiting_cycle == 0) + 578 1081206 : *waiting_mac = 0; 579 : - 580 2163720 : return task; + 580 2164392 : return task; 581 : } 582 : } 583 : 584 : /* next position to check */ - 585 12723 : let = &io->reader_list[i + 1]; - 586 12723 : } + 585 4687 : let = &io->reader_list[i + 1]; + 586 4687 : } 587 : 588 : /* if no worker is ready, wait for an event */ - 589 2605 : thread_cond_wait(&io->read_done, &io->io_mutex); + 589 1002 : thread_cond_wait(&io->read_done, &io->io_mutex); 590 : 591 : /* count the cycles */ - 592 2605 : ++waiting_cycle; - 593 2605 : } + 592 1002 : ++waiting_cycle; + 593 1002 : } 594 : } 595 : - 596 871056 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 596 871392 : static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 597 : { - 598 871056 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); + 598 871392 : return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); 599 : } 600 : 601 210804 : static struct snapraid_task* io_parity_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) @@ -665,18 +665,18 @@ 603 210804 : return io_task_read_thread(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac); 604 : } 605 : - 606 553582 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) + 606 553918 : static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) 607 : { 608 : unsigned waiting_cycle; 609 : 610 : /* count the waiting cycle */ - 611 553582 : waiting_cycle = 0; + 611 553918 : waiting_cycle = 0; 612 : 613 : /* clear the waiting indexes */ - 614 553582 : *waiting_mac = 0; + 614 553918 : *waiting_mac = 0; 615 : 616 : /* the synchronization is protected by the io mutex */ - 617 553582 : thread_mutex_lock(&io->io_mutex); + 617 553918 : thread_mutex_lock(&io->io_mutex); 618 : 619 : while (1) { 620 : unsigned char* let; @@ -687,131 +687,131 @@ 625 : /* to avoid a concurrent access */ 626 : /* note that we are already sure that a write is not in progress */ 627 : /* at the index the IO is using at now */ - 628 622113 : busy_index = (io->writer_index + 1) % io->io_max; + 628 622507 : busy_index = (io->writer_index + 1) % io->io_max; 629 : 630 : /* search for a worker that has already finished */ - 631 622113 : let = &io->writer_list[0]; + 631 622507 : let = &io->writer_list[0]; 632 : while (1) { - 633 854835 : unsigned i = *let; + 633 899608 : unsigned i = *let; 634 : struct snapraid_worker* worker; 635 : 636 : /* if we are at the end */ - 637 854835 : if (i == io->writer_max) - 638 68531 : break; + 637 899608 : if (i == io->writer_max) + 638 68589 : break; 639 : 640 : /* if it's the first cycle */ - 641 786304 : if (waiting_cycle == 0) { + 641 831019 : if (waiting_cycle == 0) { 642 : /* store the waiting indexes */ - 643 717089 : waiting_map[(*waiting_mac)++] = i; + 643 761956 : waiting_map[(*waiting_mac)++] = i; 644 : } 645 : - 646 786304 : worker = &io->writer_map[i]; + 646 831019 : worker = &io->writer_map[i]; 647 : 648 : /* the two indexes cannot be equal */ - 649 786304 : assert(io->writer_index != worker->index); + 649 831019 : assert(io->writer_index != worker->index); 650 : 651 : /* if the worker has finished this index */ - 652 786304 : if (busy_index != worker->index) { - 653 553582 : thread_mutex_unlock(&io->io_mutex); + 652 831019 : if (busy_index != worker->index) { + 653 553918 : thread_mutex_unlock(&io->io_mutex); 654 : 655 : /* mark the worker as processed */ 656 : /* setting the previous one to point at the next one */ - 657 553582 : *let = io->writer_list[i + 1]; + 657 553918 : *let = io->writer_list[i + 1]; 658 : 659 : /* return the position */ - 660 553582 : *pos = i; + 660 553918 : *pos = i; 661 : 662 : /* on the first cycle, no one is waiting */ - 663 553582 : if (waiting_cycle == 0) - 664 485051 : *waiting_mac = 0; + 663 553918 : if (waiting_cycle == 0) + 664 485329 : *waiting_mac = 0; 665 : - 666 1107164 : return; + 666 1107836 : return; 667 : } 668 : 669 : /* next position to check */ - 670 232722 : let = &io->writer_list[i + 1]; - 671 232722 : } + 670 277101 : let = &io->writer_list[i + 1]; + 671 277101 : } 672 : 673 : /* if no worker is ready, wait for an event */ - 674 68531 : thread_cond_wait(&io->write_done, &io->io_mutex); + 674 68589 : thread_cond_wait(&io->write_done, &io->io_mutex); 675 : 676 : /* count the cycles */ - 677 68531 : ++waiting_cycle; - 678 68531 : } + 677 68589 : ++waiting_cycle; + 678 68589 : } 679 : } 680 : - 681 1081809 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task) + 681 1081760 : static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task) 682 : { 683 : /* if we reached the end */ - 684 1081809 : if (task->position >= worker->io->block_max) { + 684 1081760 : if (task->position >= worker->io->block_max) { 685 : /* complete a dummy task */ - 686 120 : task->state = TASK_STATE_EMPTY; + 686 111 : task->state = TASK_STATE_EMPTY; 687 : } else { - 688 1081689 : worker->func(worker, task); + 688 1081649 : worker->func(worker, task); 689 : } - 690 1081474 : } + 690 1073313 : } 691 : - 692 648 : static void* io_reader_thread(void* arg) + 692 615 : static void* io_reader_thread(void* arg) 693 : { - 694 648 : struct snapraid_worker* worker = arg; + 694 615 : struct snapraid_worker* worker = arg; 695 : 696 : /* force completion of the first task */ - 697 648 : io_reader_worker(worker, &worker->task_map[0]); + 697 615 : io_reader_worker(worker, &worker->task_map[0]); 698 : 699 : while (1) { 700 : struct snapraid_task* task; 701 : 702 : /* get the new task */ - 703 1162742 : task = io_reader_step(worker); + 703 1159382 : task = io_reader_step(worker); 704 : 705 : /* if no task, it means to exit */ - 706 1163099 : if (!task) - 707 647 : break; + 706 1164112 : if (!task) + 707 648 : break; 708 : 709 : /* nothing more to do */ - 710 1162452 : if (task->state == TASK_STATE_EMPTY) - 711 81239 : continue; + 710 1163464 : if (task->state == TASK_STATE_EMPTY) + 711 82522 : continue; 712 : - 713 1081213 : assert(task->state == TASK_STATE_READY); + 713 1080942 : assert(task->state == TASK_STATE_READY); 714 : 715 : /* work on the assigned task */ - 716 1081213 : io_reader_worker(worker, task); - 717 1162097 : } + 716 1080942 : io_reader_worker(worker, task); + 717 1158768 : } 718 : - 719 647 : return 0; + 719 648 : return 0; 720 : } 721 : - 722 462 : static void* io_writer_thread(void* arg) + 722 461 : static void* io_writer_thread(void* arg) 723 : { - 724 462 : struct snapraid_worker* worker = arg; - 725 462 : int latest_state = TASK_STATE_DONE; + 724 461 : struct snapraid_worker* worker = arg; + 725 461 : int latest_state = TASK_STATE_DONE; 726 : 727 : while (1) { 728 : struct snapraid_task* task; 729 : 730 : /* get the new task */ - 731 554042 : task = io_writer_step(worker, latest_state); + 731 554142 : task = io_writer_step(worker, latest_state); 732 : 733 : /* if no task, it means to exit */ - 734 554046 : if (!task) - 735 462 : break; + 734 554366 : if (!task) + 735 461 : break; 736 : 737 : /* nothing more to do */ - 738 553584 : if (task->state == TASK_STATE_EMPTY) { - 739 13749 : latest_state = TASK_STATE_DONE; - 740 13749 : continue; + 738 553905 : if (task->state == TASK_STATE_EMPTY) { + 739 13659 : latest_state = TASK_STATE_DONE; + 740 13659 : continue; 741 : } 742 : - 743 539835 : assert(task->state == TASK_STATE_READY); + 743 540246 : assert(task->state == TASK_STATE_READY); 744 : 745 : /* work on the assigned task */ - 746 539835 : worker->func(worker, task); + 746 540246 : worker->func(worker, task); 747 : 748 : /* save the resulting state */ - 749 539831 : latest_state = task->state; - 750 553580 : } + 749 540022 : latest_state = task->state; + 750 553681 : } 751 : - 752 462 : return 0; + 752 461 : return 0; 753 : } 754 : 755 95 : static void io_start_thread(struct snapraid_io* io, diff --git a/cov/cmdline/list.c.func-sort-c.html b/cov/cmdline/list.c.func-sort-c.html index 2f6976a1..d0ccec74 100644 --- a/cov/cmdline/list.c.func-sort-c.html +++ b/cov/cmdline/list.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/list.c.func.html b/cov/cmdline/list.c.func.html index e01efb55..5781b04e 100644 --- a/cov/cmdline/list.c.func.html +++ b/cov/cmdline/list.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/list.c.gcov.html b/cov/cmdline/list.c.gcov.html index 8846cd26..8379ed5e 100644 --- a/cov/cmdline/list.c.gcov.html +++ b/cov/cmdline/list.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/mkstream.c.func-sort-c.html b/cov/cmdline/mkstream.c.func-sort-c.html index 763bb84b..95ea1869 100644 --- a/cov/cmdline/mkstream.c.func-sort-c.html +++ b/cov/cmdline/mkstream.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/cmdline/mkstream.c.func.html b/cov/cmdline/mkstream.c.func.html index 3288f869..b9b8afb5 100644 --- a/cov/cmdline/mkstream.c.func.html +++ b/cov/cmdline/mkstream.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/cmdline/mkstream.c.gcov.html b/cov/cmdline/mkstream.c.gcov.html index 461671b3..f477ea41 100644 --- a/cov/cmdline/mkstream.c.gcov.html +++ b/cov/cmdline/mkstream.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/cmdline/mktest.c.func-sort-c.html b/cov/cmdline/mktest.c.func-sort-c.html index 2def4c3e..664571fa 100644 --- a/cov/cmdline/mktest.c.func-sort-c.html +++ b/cov/cmdline/mktest.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -61,23 +61,23 @@ rnd - 56072909 + 56053599 rndnz - 55661691 + 55642239 file_cmp - 146571 + 146564 rndnz_range - 32723 + 32684 rnd_name - 26849 + 26839 cmd_generate @@ -93,19 +93,19 @@ cmd_write - 6227 - - - cmd_append - 3256 - - - cmd_truncate - 3141 + 6251 cmd_delete - 3136 + 3207 + + + cmd_append + 3193 + + + cmd_truncate + 3103 cmd_damage @@ -121,7 +121,7 @@ cmd_generate_symlink - 940 + 930 main diff --git a/cov/cmdline/mktest.c.func.html b/cov/cmdline/mktest.c.func.html index 24136aa2..6c779ca9 100644 --- a/cov/cmdline/mktest.c.func.html +++ b/cov/cmdline/mktest.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -61,7 +61,7 @@ cmd_append - 3256 + 3193 cmd_change @@ -73,7 +73,7 @@ cmd_delete - 3136 + 3207 cmd_generate @@ -85,15 +85,15 @@ cmd_generate_symlink - 940 + 930 cmd_truncate - 3141 + 3103 cmd_write - 6227 + 6251 fallback @@ -101,7 +101,7 @@ file_cmp - 146571 + 146564 help @@ -113,15 +113,15 @@ rnd - 56072909 + 56053599 rnd_name - 26849 + 26839 rndnz - 55661691 + 55642239 rndnz_damage @@ -129,7 +129,7 @@ rndnz_range - 32723 + 32684
diff --git a/cov/cmdline/mktest.c.gcov.html b/cov/cmdline/mktest.c.gcov.html index 584eab4f..bae0e142 100644 --- a/cov/cmdline/mktest.c.gcov.html +++ b/cov/cmdline/mktest.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -89,28 +89,28 @@ 27 : */ 28 : unsigned long long seed = 0; 29 : - 30 56072909 : unsigned rnd(unsigned max) + 30 56053599 : unsigned rnd(unsigned max) 31 : { - 32 56072909 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; + 32 56053599 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; 33 : - 34 56072909 : return (seed >> 32) % max; + 34 56053599 : return (seed >> 32) % max; 35 : } 36 : - 37 55661691 : unsigned rndnz(unsigned max) + 37 55642239 : unsigned rndnz(unsigned max) 38 : { - 39 55661691 : if (max <= 1) + 39 55642239 : if (max <= 1) 40 2831 : return 1; 41 : else - 42 55658860 : return rnd(max - 1) + 1; + 42 55639408 : return rnd(max - 1) + 1; 43 : } 44 : - 45 32723 : void rndnz_range(unsigned char* data, int size) + 45 32684 : void rndnz_range(unsigned char* data, int size) 46 : { 47 : int i; 48 : - 49 55687651 : for (i = 0; i < size; ++i) - 50 55654928 : data[i] = rndnz(256); - 51 32723 : } + 49 55668161 : for (i = 0; i < size; ++i) + 50 55635477 : data[i] = rndnz(256); + 51 32684 : } 52 : 53 1821 : void rndnz_damage(unsigned char* data, int size) 54 : { @@ -121,8 +121,8 @@ 59 : unsigned char c; 60 : 61 : do { - 62 1832 : c = rndnz(256); - 63 1832 : } while (c == data[i]); + 62 1831 : c = rndnz(256); + 63 1831 : } while (c == data[i]); 64 : 65 1821 : data[i] = c; 66 : } @@ -131,23 +131,23 @@ 69 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+"; 70 : #define CHARSET_LEN (sizeof(CHARSET) - 1) 71 : - 72 26849 : void rnd_name(char* file) + 72 26839 : void rnd_name(char* file) 73 : { - 74 26849 : int l = 1 + rnd(20); + 74 26839 : int l = 1 + rnd(20); 75 : - 76 335390 : while (l) { - 77 281692 : *file++ = CHARSET[rnd(CHARSET_LEN)]; - 78 281692 : --l; + 76 335505 : while (l) { + 77 281827 : *file++ = CHARSET[rnd(CHARSET_LEN)]; + 78 281827 : --l; 79 : } - 80 26849 : *file = 0; - 81 26849 : } + 80 26839 : *file = 0; + 81 26839 : } 82 : 83 : /****************************************************************************/ 84 : /* file */ 85 : - 86 146571 : int file_cmp(const void* a, const void* b) + 86 146564 : int file_cmp(const void* a, const void* b) 87 : { - 88 146571 : return strcmp(a, b); + 88 146564 : return strcmp(a, b); 89 : } 90 : 91 1821 : int fallback(int f, struct stat* st) @@ -259,11 +259,11 @@ 197 : * Create a symlink. 198 : * - If the file already exists, it's removed. 199 : */ - 200 940 : void cmd_generate_symlink(const char* path, const char* linkto) + 200 930 : void cmd_generate_symlink(const char* path, const char* linkto) 201 : { 202 : /* remove the existing file/symlink if any */ - 203 940 : if (remove(path) != 0) { - 204 919 : if (errno != ENOENT) { + 203 930 : if (remove(path) != 0) { + 204 909 : if (errno != ENOENT) { 205 : /* LCOV_EXCL_START */ 206 : log_fatal("Error removing file %s\n", path); 207 : exit(EXIT_FAILURE); @@ -271,13 +271,13 @@ 209 : } 210 : } 211 : - 212 940 : if (symlink(linkto, path) != 0) { + 212 930 : if (symlink(linkto, path) != 0) { 213 : /* LCOV_EXCL_START */ 214 : log_fatal("Error writing symlink %s\n", path); 215 : exit(EXIT_FAILURE); 216 : /* LCOV_EXCL_STOP */ 217 : } - 218 940 : } + 218 930 : } 219 : 220 : /** 221 : * Create a file or a symlink with a random name. @@ -350,68 +350,68 @@ 288 : * - The written data may be equal or not at the already existing one. 289 : * - If it's a symlink nothing is done. 290 : */ - 291 6227 : void cmd_write(const char* path, int size) + 291 6251 : void cmd_write(const char* path, int size) 292 : { 293 : struct stat st; 294 : - 295 6227 : if (lstat(path, &st) != 0) { + 295 6251 : if (lstat(path, &st) != 0) { 296 : /* LCOV_EXCL_START */ 297 : log_fatal("Error accessing %s\n", path); 298 : exit(EXIT_FAILURE); 299 : /* LCOV_EXCL_STOP */ 300 : } 301 : - 302 6227 : if (S_ISREG(st.st_mode)) { + 302 6251 : if (S_ISREG(st.st_mode)) { 303 : unsigned char* data; 304 : off_t off; 305 : int f; 306 : 307 : /* not over the end */ - 308 6200 : if (size > st.st_size) - 309 695 : size = st.st_size; + 308 6224 : if (size > st.st_size) + 309 696 : size = st.st_size; 310 : 311 : /* start at random position inside the file */ - 312 6200 : if (size < st.st_size) - 313 5504 : off = rnd(st.st_size - size); + 312 6224 : if (size < st.st_size) + 313 5526 : off = rnd(st.st_size - size); 314 : else - 315 696 : off = 0; + 315 698 : off = 0; 316 : - 317 6200 : data = malloc(size); + 317 6224 : data = malloc(size); 318 : - 319 6200 : rndnz_range(data, size); + 319 6224 : rndnz_range(data, size); 320 : - 321 6200 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 322 6200 : if (f < 0) { + 321 6224 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 322 6224 : if (f < 0) { 323 : /* LCOV_EXCL_START */ 324 : log_fatal("Error creating file %s\n", path); 325 : exit(EXIT_FAILURE); 326 : /* LCOV_EXCL_STOP */ 327 : } 328 : - 329 6200 : if (lseek(f, off, SEEK_SET) != off) { + 329 6224 : if (lseek(f, off, SEEK_SET) != off) { 330 : /* LCOV_EXCL_START */ 331 : log_fatal("Error seeking file %s\n", path); 332 : exit(EXIT_FAILURE); 333 : /* LCOV_EXCL_STOP */ 334 : } 335 : - 336 6200 : if (write(f, data, size) != size) { + 336 6224 : if (write(f, data, size) != size) { 337 : /* LCOV_EXCL_START */ 338 : log_fatal("Error writing file %s\n", path); 339 : exit(EXIT_FAILURE); 340 : /* LCOV_EXCL_STOP */ 341 : } 342 : - 343 6200 : if (close(f) != 0) { + 343 6224 : if (close(f) != 0) { 344 : /* LCOV_EXCL_START */ 345 : log_fatal("Error closing file %s\n", path); 346 : exit(EXIT_FAILURE); 347 : /* LCOV_EXCL_STOP */ 348 : } 349 : - 350 6200 : free(data); + 350 6224 : free(data); 351 : } - 352 6227 : } + 352 6251 : } 353 : 354 : /** 355 : * Damage a file. @@ -518,50 +518,50 @@ 456 : * - The file must exist. 457 : * - If it's a symlink nothing is done. 458 : */ - 459 3256 : void cmd_append(const char* path, int size) + 459 3193 : void cmd_append(const char* path, int size) 460 : { 461 : struct stat st; 462 : - 463 3256 : if (lstat(path, &st) != 0) { + 463 3193 : if (lstat(path, &st) != 0) { 464 : /* LCOV_EXCL_START */ 465 : log_fatal("Error accessing %s\n", path); 466 : exit(EXIT_FAILURE); 467 : /* LCOV_EXCL_STOP */ 468 : } 469 : - 470 3256 : if (S_ISREG(st.st_mode)) { + 470 3193 : if (S_ISREG(st.st_mode)) { 471 : unsigned char* data; 472 : int f; 473 : - 474 3256 : data = malloc(size); + 474 3193 : data = malloc(size); 475 : - 476 3256 : rndnz_range(data, size); + 476 3193 : rndnz_range(data, size); 477 : - 478 3256 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); - 479 3256 : if (f < 0) { + 478 3193 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); + 479 3193 : if (f < 0) { 480 : /* LCOV_EXCL_START */ 481 : log_fatal("Error opening file %s\n", path); 482 : exit(EXIT_FAILURE); 483 : /* LCOV_EXCL_STOP */ 484 : } 485 : - 486 3256 : if (write(f, data, size) != size) { + 486 3193 : if (write(f, data, size) != size) { 487 : /* LCOV_EXCL_START */ 488 : log_fatal("Error writing file %s\n", path); 489 : exit(EXIT_FAILURE); 490 : /* LCOV_EXCL_STOP */ 491 : } 492 : - 493 3256 : if (close(f) != 0) { + 493 3193 : if (close(f) != 0) { 494 : /* LCOV_EXCL_START */ 495 : log_fatal("Error closing file %s\n", path); 496 : exit(EXIT_FAILURE); 497 : /* LCOV_EXCL_STOP */ 498 : } 499 : - 500 3256 : free(data); + 500 3193 : free(data); 501 : } - 502 3256 : } + 502 3193 : } 503 : 504 : /** 505 : * Truncate a file. @@ -569,69 +569,69 @@ 507 : * - The file is NEVER truncated to 0. 508 : * - If it's a symlink nothing is done. 509 : */ - 510 3141 : void cmd_truncate(const char* path, int size) + 510 3103 : void cmd_truncate(const char* path, int size) 511 : { 512 : struct stat st; 513 : - 514 3141 : if (lstat(path, &st) != 0) { + 514 3103 : if (lstat(path, &st) != 0) { 515 : /* LCOV_EXCL_START */ 516 : log_fatal("Error accessing %s\n", path); 517 : exit(EXIT_FAILURE); 518 : /* LCOV_EXCL_STOP */ 519 : } 520 : - 521 3141 : if (S_ISREG(st.st_mode)) { + 521 3103 : if (S_ISREG(st.st_mode)) { 522 : off_t off; 523 : int f; 524 : 525 : /* if file is empty, just rewrite it */ - 526 3141 : if (st.st_size == 0) { - 527 1 : size = 0; + 526 3103 : if (st.st_size == 0) { + 527 3 : size = 0; 528 : } else { 529 : /* don't truncate files to 0 size to avoid ZERO file size protection */ - 530 3140 : if (size >= st.st_size) - 531 200 : size = st.st_size - 1; + 530 3100 : if (size >= st.st_size) + 531 195 : size = st.st_size - 1; 532 : } 533 : - 534 3141 : off = st.st_size - size; + 534 3103 : off = st.st_size - size; 535 : - 536 3141 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 537 3141 : if (f < 0) { + 536 3103 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 537 3103 : if (f < 0) { 538 : /* LCOV_EXCL_START */ 539 : log_fatal("Error opening file %s\n", path); 540 : exit(EXIT_FAILURE); 541 : /* LCOV_EXCL_STOP */ 542 : } 543 : - 544 3141 : if (ftruncate(f, off) != 0) { + 544 3103 : if (ftruncate(f, off) != 0) { 545 : /* LCOV_EXCL_START */ 546 : log_fatal("Error truncating file %s\n", path); 547 : exit(EXIT_FAILURE); 548 : /* LCOV_EXCL_STOP */ 549 : } 550 : - 551 3141 : if (close(f) != 0) { + 551 3103 : if (close(f) != 0) { 552 : /* LCOV_EXCL_START */ 553 : log_fatal("Error closing file %s\n", path); 554 : exit(EXIT_FAILURE); 555 : /* LCOV_EXCL_STOP */ 556 : } 557 : } - 558 3141 : } + 558 3103 : } 559 : 560 : /** 561 : * Delete a file. 562 : * - The file must exist. 563 : */ - 564 3136 : void cmd_delete(const char* path) + 564 3207 : void cmd_delete(const char* path) 565 : { - 566 3136 : if (remove(path) != 0) { + 566 3207 : if (remove(path) != 0) { 567 : /* LCOV_EXCL_START */ 568 : log_fatal("Error removing %s\n", path); 569 : exit(EXIT_FAILURE); 570 : /* LCOV_EXCL_STOP */ 571 : } - 572 3136 : } + 572 3207 : } 573 : 574 : /** 575 : * Change a file. Or deleted/truncated/append/created. @@ -642,20 +642,20 @@ 580 : struct stat st; 581 : 582 13128 : if (!size) - 583 13152 : return; + 583 13157 : return; 584 : - 585 13104 : if (lstat(path, &st) != 0) { + 585 13099 : if (lstat(path, &st) != 0) { 586 : /* LCOV_EXCL_START */ 587 : log_fatal("Error accessing %s\n", path); 588 : exit(EXIT_FAILURE); 589 : /* LCOV_EXCL_STOP */ 590 : } 591 : - 592 13104 : if (S_ISLNK(st.st_mode)) { + 592 13099 : if (S_ISLNK(st.st_mode)) { 593 : /* symlink */ - 594 393 : if (rnd(2) == 0) { + 594 394 : if (rnd(2) == 0) { 595 : /* delete */ - 596 186 : if (remove(path) != 0) { + 596 197 : if (remove(path) != 0) { 597 : /* LCOV_EXCL_START */ 598 : log_fatal("Error removing %s\n", path); 599 : exit(EXIT_FAILURE); @@ -665,30 +665,30 @@ 603 : /* recreate */ 604 : char linkto[PATH_MAX]; 605 : - 606 207 : if (remove(path) != 0) { + 606 197 : if (remove(path) != 0) { 607 : /* LCOV_EXCL_START */ 608 : log_fatal("Error removing %s\n", path); 609 : exit(EXIT_FAILURE); 610 : /* LCOV_EXCL_STOP */ 611 : } 612 : - 613 207 : rnd_name(linkto); + 613 197 : rnd_name(linkto); 614 : - 615 207 : cmd_generate_symlink(path, linkto); + 615 197 : cmd_generate_symlink(path, linkto); 616 : } - 617 12711 : } else if (S_ISREG(st.st_mode)) { + 617 12705 : } else if (S_ISREG(st.st_mode)) { 618 : int r; 619 : - 620 12711 : r = rnd(4); + 620 12705 : r = rnd(4); 621 : - 622 12711 : if (r == 0) { - 623 3178 : cmd_write(path, size); - 624 9533 : } else if (r == 1) { - 625 3256 : cmd_append(path, size); - 626 6277 : } else if (r == 2) { - 627 3141 : cmd_truncate(path, size); + 622 12705 : if (r == 0) { + 623 3202 : cmd_write(path, size); + 624 9503 : } else if (r == 1) { + 625 3193 : cmd_append(path, size); + 626 6310 : } else if (r == 2) { + 627 3103 : cmd_truncate(path, size); 628 : } else { - 629 3136 : cmd_delete(path); + 629 3207 : cmd_delete(path); 630 : } 631 : } 632 : } diff --git a/cov/cmdline/murmur3.c.func-sort-c.html b/cov/cmdline/murmur3.c.func-sort-c.html index b8fd330e..1fc77637 100644 --- a/cov/cmdline/murmur3.c.func-sort-c.html +++ b/cov/cmdline/murmur3.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ fmix32 - 8307408 + 8307428 MurmurHash3_x86_128 - 2076852 + 2076857
diff --git a/cov/cmdline/murmur3.c.func.html b/cov/cmdline/murmur3.c.func.html index 40d30fc9..1cb04e4d 100644 --- a/cov/cmdline/murmur3.c.func.html +++ b/cov/cmdline/murmur3.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ MurmurHash3_x86_128 - 2076852 + 2076857 fmix32 - 8307408 + 8307428
diff --git a/cov/cmdline/murmur3.c.gcov.html b/cov/cmdline/murmur3.c.gcov.html index 5f7069e2..fee01498 100644 --- a/cov/cmdline/murmur3.c.gcov.html +++ b/cov/cmdline/murmur3.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 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 8307408 : static inline uint32_t fmix32(uint32_t h) + 32 8307428 : static inline uint32_t fmix32(uint32_t h) 33 : { - 34 8307408 : h ^= h >> 16; - 35 8307408 : h *= 0x85ebca6b; - 36 8307408 : h ^= h >> 13; - 37 8307408 : h *= 0xc2b2ae35; - 38 8307408 : h ^= h >> 16; - 39 8307408 : return h; + 34 8307428 : h ^= h >> 16; + 35 8307428 : h *= 0x85ebca6b; + 36 8307428 : h ^= h >> 13; + 37 8307428 : h *= 0xc2b2ae35; + 38 8307428 : h ^= h >> 16; + 39 8307428 : return h; 40 : } 41 : 42 : /* @@ -137,7 +137,7 @@ 75 : uint32_t c3 = 0x38b34ae5; 76 : uint32_t c4 = 0xa1e38b93; 77 : - 78 2076852 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) + 78 2076857 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) 79 : { 80 : size_t nblocks; 81 : const uint32_t* blocks; @@ -145,21 +145,21 @@ 83 : size_t size_remainder; 84 : uint32_t h1, h2, h3, h4; 85 : - 86 2076852 : h1 = util_read32(seed + 0); - 87 2076852 : h2 = util_read32(seed + 4); - 88 2076852 : h3 = util_read32(seed + 8); - 89 2076852 : h4 = util_read32(seed + 12); + 86 2076857 : h1 = util_read32(seed + 0); + 87 2076857 : h2 = util_read32(seed + 4); + 88 2076857 : h3 = util_read32(seed + 8); + 89 2076857 : h4 = util_read32(seed + 12); 90 : - 91 2076852 : nblocks = size / 16; - 92 2076852 : blocks = data; - 93 2076852 : end = blocks + nblocks * 4; + 91 2076857 : nblocks = size / 16; + 92 2076857 : blocks = data; + 93 2076857 : end = blocks + nblocks * 4; 94 : 95 : /* body */ - 96 110684486 : while (blocks < end) { - 97 106530782 : uint32_t k1 = blocks[0]; - 98 106530782 : uint32_t k2 = blocks[1]; - 99 106530782 : uint32_t k3 = blocks[2]; - 100 106530782 : uint32_t k4 = blocks[3]; + 96 110684757 : while (blocks < end) { + 97 106531043 : uint32_t k1 = blocks[0]; + 98 106531043 : uint32_t k2 = blocks[1]; + 99 106531043 : uint32_t k3 = blocks[2]; + 100 106531043 : uint32_t k4 = blocks[3]; 101 : 102 : #if WORDS_BIGENDIAN 103 : k1 = util_swap32(k1); @@ -168,77 +168,77 @@ 106 : k4 = util_swap32(k4); 107 : #endif 108 : - 109 106530782 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 109 106531043 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 110 : - 111 106530782 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; + 111 106531043 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; 112 : - 113 106530782 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 113 106531043 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; 114 : - 115 106530782 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; + 115 106531043 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; 116 : - 117 106530782 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 117 106531043 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; 118 : - 119 106530782 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; + 119 106531043 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; 120 : - 121 106530782 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 121 106531043 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; 122 : - 123 106530782 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; + 123 106531043 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; 124 : - 125 106530782 : blocks += 4; + 125 106531043 : blocks += 4; 126 : } 127 : 128 : /* tail */ - 129 2076852 : size_remainder = size & 15; - 130 2076852 : if (size_remainder != 0) { - 131 779223 : const uint8_t* tail = (const uint8_t*)blocks; + 129 2076857 : size_remainder = size & 15; + 130 2076857 : if (size_remainder != 0) { + 131 779280 : const uint8_t* tail = (const uint8_t*)blocks; 132 : - 133 779223 : uint32_t k1 = 0; - 134 779223 : uint32_t k2 = 0; - 135 779223 : uint32_t k3 = 0; - 136 779223 : uint32_t k4 = 0; + 133 779280 : uint32_t k1 = 0; + 134 779280 : uint32_t k2 = 0; + 135 779280 : uint32_t k3 = 0; + 136 779280 : uint32_t k4 = 0; 137 : - 138 779223 : switch (size_remainder) { - 139 51253 : case 15 : k4 ^= (uint32_t)tail[14] << 16; - 140 103976 : case 14 : k4 ^= (uint32_t)tail[13] << 8; - 141 156183 : case 13 : k4 ^= (uint32_t)tail[12] << 0; - 142 156183 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; - 143 208955 : case 12 : k3 ^= (uint32_t)tail[11] << 24; - 144 261477 : case 11 : k3 ^= (uint32_t)tail[10] << 16; - 145 313646 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8; - 146 366950 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0; - 147 366950 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; - 148 420888 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24; - 149 470405 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16; - 150 523044 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8; - 151 573538 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0; - 152 573538 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; - 153 625492 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24; - 154 675841 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16; - 155 726916 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8; - 156 779223 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0; - 157 779223 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 138 779280 : switch (size_remainder) { + 139 51283 : case 15 : k4 ^= (uint32_t)tail[14] << 16; + 140 104014 : case 14 : k4 ^= (uint32_t)tail[13] << 8; + 141 156219 : case 13 : k4 ^= (uint32_t)tail[12] << 0; + 142 156219 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 143 208972 : case 12 : k3 ^= (uint32_t)tail[11] << 24; + 144 261514 : case 11 : k3 ^= (uint32_t)tail[10] << 16; + 145 313715 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8; + 146 366995 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0; + 147 366995 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 148 420927 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24; + 149 470437 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16; + 150 523081 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8; + 151 573603 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0; + 152 573603 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 153 625568 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24; + 154 675931 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16; + 155 726990 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8; + 156 779280 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0; + 157 779280 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 158 : } 159 : } 160 : 161 : /* finalization */ - 162 2076852 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; + 162 2076857 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; 163 : - 164 2076852 : h1 += h2; h1 += h3; h1 += h4; - 165 2076852 : h2 += h1; h3 += h1; h4 += h1; + 164 2076857 : h1 += h2; h1 += h3; h1 += h4; + 165 2076857 : h2 += h1; h3 += h1; h4 += h1; 166 : - 167 2076852 : h1 = fmix32(h1); - 168 2076852 : h2 = fmix32(h2); - 169 2076852 : h3 = fmix32(h3); - 170 2076852 : h4 = fmix32(h4); + 167 2076857 : h1 = fmix32(h1); + 168 2076857 : h2 = fmix32(h2); + 169 2076857 : h3 = fmix32(h3); + 170 2076857 : h4 = fmix32(h4); 171 : - 172 2076852 : h1 += h2; h1 += h3; h1 += h4; - 173 2076852 : h2 += h1; h3 += h1; h4 += h1; + 172 2076857 : h1 += h2; h1 += h3; h1 += h4; + 173 2076857 : h2 += h1; h3 += h1; h4 += h1; 174 : - 175 2076852 : util_write32(digest + 0, h1); - 176 2076852 : util_write32(digest + 4, h2); - 177 2076852 : util_write32(digest + 8, h3); - 178 2076852 : util_write32(digest + 12, h4); - 179 2076852 : } + 175 2076857 : util_write32(digest + 0, h1); + 176 2076857 : util_write32(digest + 4, h2); + 177 2076857 : util_write32(digest + 8, h3); + 178 2076857 : util_write32(digest + 12, h4); + 179 2076857 : } 180 : diff --git a/cov/cmdline/parity.c.func-sort-c.html b/cov/cmdline/parity.c.func-sort-c.html index 494a1ed5..6be34ce5 100644 --- a/cov/cmdline/parity.c.func-sort-c.html +++ b/cov/cmdline/parity.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -61,15 +61,15 @@ parity_split_find - 4113807 + 4114072 parity_read - 3501819 + 3501740 parity_write - 611983 + 612363 parity_handle_chsize diff --git a/cov/cmdline/parity.c.func.html b/cov/cmdline/parity.c.func.html index 0610c73a..5a320fbc 100644 --- a/cov/cmdline/parity.c.func.html +++ b/cov/cmdline/parity.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -109,7 +109,7 @@ parity_read - 3501819 + 3501740 parity_size @@ -117,7 +117,7 @@ parity_split_find - 4113807 + 4114072 parity_split_is_fixed @@ -133,7 +133,7 @@ parity_write - 611983 + 612363
diff --git a/cov/cmdline/parity.c.gcov.html b/cov/cmdline/parity.c.gcov.html index b43a0239..af7bdf5c 100644 --- a/cov/cmdline/parity.c.gcov.html +++ b/cov/cmdline/parity.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 18 @@ -135,8 +135,8 @@ 73 521 : block_off_t block = fs_size(disk); 74 : 75 : /* decrease the block until an used one */ - 76 221718 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1))) - 77 220676 : --block; + 76 221719 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1))) + 77 220677 : --block; 78 : 79 : /* get the highest value */ 80 521 : if (block > parity_block) @@ -826,44 +826,44 @@ 764 1022 : return f_ret; 765 : } 766 : - 767 4113807 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset) + 767 4114072 : struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset) 768 : { 769 : unsigned s; 770 : - 771 4113807 : if (*offset < 0) + 771 4114072 : if (*offset < 0) 772 0 : return 0; 773 : - 774 6502165 : for (s = 0;s < handle->split_mac;++s) { - 775 6490805 : struct snapraid_split_handle* split = &handle->split_map[s]; + 774 6502675 : for (s = 0;s < handle->split_mac;++s) { + 775 6491315 : struct snapraid_split_handle* split = &handle->split_map[s]; 776 : - 777 6490805 : if (*offset < split->size) - 778 4102447 : return split; + 777 6491315 : if (*offset < split->size) + 778 4102712 : return split; 779 : - 780 2388358 : *offset -= split->size; + 780 2388603 : *offset -= split->size; 781 : } 782 : 783 11360 : return 0; 784 : } 785 : - 786 611983 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size) + 786 612363 : int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size) 787 : { 788 : ssize_t write_ret; 789 : data_off_t offset; 790 : struct snapraid_split_handle* split; 791 : int ret; 792 : - 793 611983 : offset = pos * (data_off_t)block_size; + 793 612363 : offset = pos * (data_off_t)block_size; 794 : - 795 611983 : split = parity_split_find(handle, &offset); - 796 611984 : if (!split) { + 795 612363 : split = parity_split_find(handle, &offset); + 796 612400 : if (!split) { 797 : /* LCOV_EXCL_START */ 798 : log_fatal("Writing parity data outside range at extra offset %" PRIu64 ".\n", offset); 799 : return -1; 800 : /* LCOV_EXCL_STOP */ 801 : } 802 : - 803 611984 : write_ret = pwrite(split->f, block_buffer, block_size, offset); - 804 611983 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */ + 803 612400 : write_ret = pwrite(split->f, block_buffer, block_size, offset); + 804 612277 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */ 805 : /* LCOV_EXCL_START */ 806 : if (errno == ENOSPC) { 807 : log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", split->path); @@ -874,18 +874,18 @@ 812 : /* LCOV_EXCL_STOP */ 813 : } 814 : - 815 611983 : ret = advise_write(&split->advise, split->f, offset, block_size); - 816 611981 : if (ret != 0) { + 815 612277 : ret = advise_write(&split->advise, split->f, offset, block_size); + 816 612100 : if (ret != 0) { 817 : /* LCOV_EXCL_START */ 818 : log_fatal("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); 819 : return -1; 820 : /* LCOV_EXCL_STOP */ 821 : } 822 : - 823 611981 : return 0; + 823 612100 : return 0; 824 : } 825 : - 826 3501819 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out) + 826 3501740 : int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out) 827 : { 828 : ssize_t read_ret; 829 : data_off_t offset; @@ -893,44 +893,44 @@ 831 : struct snapraid_split_handle* split; 832 : int ret; 833 : - 834 3501819 : offset = pos * (data_off_t)block_size; + 834 3501740 : offset = pos * (data_off_t)block_size; 835 : - 836 3501819 : split = parity_split_find(handle, &offset); - 837 3501808 : if (!split) { + 836 3501740 : split = parity_split_find(handle, &offset); + 837 3501789 : if (!split) { 838 : /* LCOV_EXCL_START */ 839 : out("Reading parity data outside range at extra offset %" PRIu64 ".\n", offset); 840 : return -1; 841 : /* LCOV_EXCL_STOP */ 842 : } 843 : - 844 3490448 : count = 0; + 844 3490429 : count = 0; 845 : do { - 846 3490446 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count); - 847 3490413 : if (read_ret < 0) { + 846 3490283 : read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count); + 847 3490289 : if (read_ret < 0) { 848 : /* LCOV_EXCL_START */ 849 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno)); 850 : return -1; 851 : /* LCOV_EXCL_STOP */ 852 : } - 853 3490413 : if (read_ret == 0) { + 853 3490289 : if (read_ret == 0) { 854 : /* LCOV_EXCL_START */ 855 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno)); 856 : return -1; 857 : /* LCOV_EXCL_STOP */ 858 : } 859 : - 860 3490413 : count += read_ret; - 861 3490413 : } while (count < block_size); + 860 3490289 : count += read_ret; + 861 3490289 : } while (count < block_size); 862 : - 863 3490415 : ret = advise_read(&split->advise, split->f, offset, block_size); - 864 3490417 : if (ret != 0) { + 863 3490435 : ret = advise_read(&split->advise, split->f, offset, block_size); + 864 3490346 : if (ret != 0) { 865 : /* LCOV_EXCL_START */ 866 : out("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); 867 : return -1; 868 : /* LCOV_EXCL_STOP */ 869 : } 870 : - 871 3490417 : return block_size; + 871 3490346 : return block_size; 872 : } 873 : diff --git a/cov/cmdline/pool.c.func-sort-c.html b/cov/cmdline/pool.c.func-sort-c.html index 154e338e..06ab1417 100644 --- a/cov/cmdline/pool.c.func-sort-c.html +++ b/cov/cmdline/pool.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 64 - 68 - 94.1 % + 67 + 71 + 94.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -68,7 +68,7 @@ 5 - state_pool + state_pool 3 diff --git a/cov/cmdline/pool.c.func.html b/cov/cmdline/pool.c.func.html index 97212d32..4d58039c 100644 --- a/cov/cmdline/pool.c.func.html +++ b/cov/cmdline/pool.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 64 - 68 - 94.1 % + 67 + 71 + 94.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -68,7 +68,7 @@ 17589 - state_pool + state_pool 3 diff --git a/cov/cmdline/pool.c.gcov.html b/cov/cmdline/pool.c.gcov.html index c1a4eec7..9a3e0678 100644 --- a/cov/cmdline/pool.c.gcov.html +++ b/cov/cmdline/pool.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 64 - 68 - 94.1 % + 67 + 71 + 94.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -209,7 +209,7 @@ 147 : /** 148 : * Create a link to the specified disk entry. 149 : */ - 150 17589 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub) + 150 17589 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub, int64_t mtime_sec, int mtime_nsec) 151 : { 152 : char path[PATH_MAX]; 153 : char linkto[PATH_MAX]; @@ -258,70 +258,80 @@ 196 : /* LCOV_EXCL_STOP */ 197 : } 198 : } - 199 17589 : } - 200 : - 201 3 : void state_pool(struct snapraid_state* state) - 202 : { - 203 : tommy_node* i; - 204 : char pool_dir[PATH_MAX]; - 205 : char share_dir[PATH_MAX]; - 206 : unsigned count; - 207 : - 208 3 : if (state->pool[0] == 0) { - 209 : /* LCOV_EXCL_START */ - 210 : log_fatal("To use the 'pool' command you must set the pool directory in the configuration file\n"); - 211 : exit(EXIT_FAILURE); - 212 : /* LCOV_EXCL_STOP */ - 213 : } - 214 : - 215 3 : msg_progress("Cleaning...\n"); - 216 : - 217 : /* pool directory with final slash */ - 218 3 : pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool); - 219 3 : pathslash(pool_dir, sizeof(pool_dir)); - 220 : - 221 : /* share directory with final slash */ - 222 3 : pathprint(share_dir, sizeof(share_dir), "%s", state->share); - 223 3 : pathslash(share_dir, sizeof(share_dir)); + 199 : + 200 17589 : if (mtime_sec) { + 201 17000 : ret = lmtime(path, mtime_sec, mtime_nsec); + 202 17000 : if (ret != 0) { + 203 : /* LCOV_EXCL_START */ + 204 : log_fatal("Error setting time to symlink '%s'. %s.\n", path, strerror(errno)); + 205 : exit(EXIT_FAILURE); + 206 : /* LCOV_EXCL_STOP */ + 207 : } + 208 : } + 209 17589 : } + 210 : + 211 3 : void state_pool(struct snapraid_state* state) + 212 : { + 213 : tommy_node* i; + 214 : char pool_dir[PATH_MAX]; + 215 : char share_dir[PATH_MAX]; + 216 : unsigned count; + 217 : + 218 3 : if (state->pool[0] == 0) { + 219 : /* LCOV_EXCL_START */ + 220 : log_fatal("To use the 'pool' command you must set the pool directory in the configuration file\n"); + 221 : exit(EXIT_FAILURE); + 222 : /* LCOV_EXCL_STOP */ + 223 : } 224 : - 225 : /* first clear the previous pool tree */ - 226 3 : clean_dir(state, pool_dir); - 227 : - 228 3 : msg_progress("Pooling...\n"); - 229 : - 230 : /* for each disk */ - 231 3 : count = 0; - 232 21 : for (i = state->disklist; i != 0; i = i->next) { - 233 : tommy_node* j; - 234 18 : struct snapraid_disk* disk = i->data; - 235 : - 236 : /* for each file */ - 237 17018 : for (j = disk->filelist; j != 0; j = j->next) { - 238 17000 : struct snapraid_file* file = j->data; - 239 17000 : make_link(pool_dir, share_dir, disk, file->sub); - 240 17000 : ++count; - 241 : } - 242 : - 243 : /* for each link */ - 244 607 : for (j = disk->linklist; j != 0; j = j->next) { - 245 589 : struct snapraid_link* slink = j->data; - 246 589 : make_link(pool_dir, share_dir, disk, slink->sub); - 247 589 : ++count; - 248 : } - 249 : - 250 : /* we ignore empty dirs in disk->dir */ - 251 : } + 225 3 : msg_progress("Cleaning...\n"); + 226 : + 227 : /* pool directory with final slash */ + 228 3 : pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool); + 229 3 : pathslash(pool_dir, sizeof(pool_dir)); + 230 : + 231 : /* share directory with final slash */ + 232 3 : pathprint(share_dir, sizeof(share_dir), "%s", state->share); + 233 3 : pathslash(share_dir, sizeof(share_dir)); + 234 : + 235 : /* first clear the previous pool tree */ + 236 3 : clean_dir(state, pool_dir); + 237 : + 238 3 : msg_progress("Pooling...\n"); + 239 : + 240 : /* for each disk */ + 241 3 : count = 0; + 242 21 : for (i = state->disklist; i != 0; i = i->next) { + 243 : tommy_node* j; + 244 18 : struct snapraid_disk* disk = i->data; + 245 : + 246 : /* for each file */ + 247 17018 : for (j = disk->filelist; j != 0; j = j->next) { + 248 17000 : struct snapraid_file* file = j->data; + 249 17000 : make_link(pool_dir, share_dir, disk, file->sub, file->mtime_sec, file->mtime_nsec); + 250 17000 : ++count; + 251 : } 252 : - 253 3 : if (count) - 254 2 : msg_status("%u links created\n", count); - 255 : else - 256 1 : msg_status("No link created\n"); - 257 : - 258 3 : log_tag("summary:link_count::%u\n", count); - 259 3 : log_tag("summary:exit:ok\n"); - 260 3 : log_flush(); - 261 3 : } + 253 : /* for each link */ + 254 607 : for (j = disk->linklist; j != 0; j = j->next) { + 255 589 : struct snapraid_link* slink = j->data; + 256 589 : make_link(pool_dir, share_dir, disk, slink->sub, 0, 0); + 257 589 : ++count; + 258 : } + 259 : + 260 : /* we ignore empty dirs in disk->dir */ + 261 : } 262 : + 263 3 : if (count) + 264 2 : msg_status("%u links created\n", count); + 265 : else + 266 1 : msg_status("No link created\n"); + 267 : + 268 3 : log_tag("summary:link_count::%u\n", count); + 269 3 : log_tag("summary:exit:ok\n"); + 270 3 : log_flush(); + 271 3 : } + 272 : diff --git a/cov/cmdline/portable.h.func-sort-c.html b/cov/cmdline/portable.h.func-sort-c.html index fb8ed345..13fa0cdc 100644 --- a/cov/cmdline/portable.h.func-sort-c.html +++ b/cov/cmdline/portable.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -60,7 +60,7 @@ Hit count Sort by hit count - hardlink + hardlink 12 diff --git a/cov/cmdline/portable.h.func.html b/cov/cmdline/portable.h.func.html index 6ae6ba87..24081d3d 100644 --- a/cov/cmdline/portable.h.func.html +++ b/cov/cmdline/portable.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -60,7 +60,7 @@ Hit count Sort by hit count - hardlink + hardlink 12 diff --git a/cov/cmdline/portable.h.gcov.html b/cov/cmdline/portable.h.gcov.html index 31070c84..7577fe1a 100644 --- a/cov/cmdline/portable.h.gcov.html +++ b/cov/cmdline/portable.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -260,292 +260,298 @@ 198 : #include <sys/types.h> 199 : #endif 200 : - 201 : #if HAVE_SYS_STAT_H - 202 : #include <sys/stat.h> - 203 : #endif - 204 : - 205 : #if HAVE_SYS_WAIT_H - 206 : #include <sys/wait.h> - 207 : #endif - 208 : #ifndef WEXITSTATUS - 209 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) - 210 : #endif - 211 : #ifndef WIFEXITED - 212 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) + 201 : #if MAJOR_IN_MKDEV + 202 : #include <sys/mkdev.h> + 203 : #elif MAJOR_IN_SYSMACROS + 204 : #include <sys/sysmacros.h> + 205 : #endif + 206 : + 207 : #if HAVE_SYS_STAT_H + 208 : #include <sys/stat.h> + 209 : #endif + 210 : + 211 : #if HAVE_SYS_WAIT_H + 212 : #include <sys/wait.h> 213 : #endif - 214 : - 215 : #if HAVE_GETOPT_H - 216 : #include <getopt.h> - 217 : #endif - 218 : - 219 : #if HAVE_FNMATCH_H - 220 : #include <fnmatch.h> - 221 : #else - 222 : #include "fnmatch.h" + 214 : #ifndef WEXITSTATUS + 215 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) + 216 : #endif + 217 : #ifndef WIFEXITED + 218 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) + 219 : #endif + 220 : + 221 : #if HAVE_GETOPT_H + 222 : #include <getopt.h> 223 : #endif 224 : - 225 : #if HAVE_PTHREAD_H - 226 : #include <pthread.h> - 227 : #endif - 228 : - 229 : #if HAVE_MATH_H - 230 : #include <math.h> - 231 : #endif - 232 : - 233 : #if HAVE_EXECINFO_H - 234 : #include <execinfo.h> - 235 : #endif - 236 : - 237 : /** - 238 : * Enable thread use. - 239 : */ - 240 : #if HAVE_PTHREAD_CREATE - 241 : #define HAVE_PTHREAD 1 - 242 : #endif - 243 : - 244 : /** - 245 : * Disable case check in Windows. - 246 : */ - 247 : #ifdef _WIN32 - 248 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD - 249 : #else - 250 : #define FNM_CASEINSENSITIVE_FOR_WIN 0 - 251 : #endif - 252 : - 253 : #if HAVE_IO_H - 254 : #include <io.h> - 255 : #endif - 256 : - 257 : #if HAVE_GETOPT_LONG - 258 : #define SWITCH_GETOPT_LONG(a, b) a - 259 : #else - 260 : #define SWITCH_GETOPT_LONG(a, b) b + 225 : #if HAVE_FNMATCH_H + 226 : #include <fnmatch.h> + 227 : #else + 228 : #include "fnmatch.h" + 229 : #endif + 230 : + 231 : #if HAVE_PTHREAD_H + 232 : #include <pthread.h> + 233 : #endif + 234 : + 235 : #if HAVE_MATH_H + 236 : #include <math.h> + 237 : #endif + 238 : + 239 : #if HAVE_EXECINFO_H + 240 : #include <execinfo.h> + 241 : #endif + 242 : + 243 : /** + 244 : * Enable thread use. + 245 : */ + 246 : #if HAVE_PTHREAD_CREATE + 247 : #define HAVE_PTHREAD 1 + 248 : #endif + 249 : + 250 : /** + 251 : * Disable case check in Windows. + 252 : */ + 253 : #ifdef _WIN32 + 254 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD + 255 : #else + 256 : #define FNM_CASEINSENSITIVE_FOR_WIN 0 + 257 : #endif + 258 : + 259 : #if HAVE_IO_H + 260 : #include <io.h> 261 : #endif 262 : - 263 : /** - 264 : * Enables lock file support. - 265 : */ - 266 : #if HAVE_FLOCK && HAVE_FTRUNCATE - 267 : #define HAVE_LOCKFILE 1 - 268 : #endif - 269 : - 270 : /** - 271 : * Basic block position type. - 272 : * With 32 bits and 128k blocks you can address 256 TB. - 273 : */ - 274 : typedef uint32_t block_off_t; + 263 : #if HAVE_GETOPT_LONG + 264 : #define SWITCH_GETOPT_LONG(a, b) a + 265 : #else + 266 : #define SWITCH_GETOPT_LONG(a, b) b + 267 : #endif + 268 : + 269 : /** + 270 : * Enables lock file support. + 271 : */ + 272 : #if HAVE_FLOCK && HAVE_FTRUNCATE + 273 : #define HAVE_LOCKFILE 1 + 274 : #endif 275 : 276 : /** - 277 : * Basic data position type. - 278 : * It's signed as file size and offset are usually signed. + 277 : * Basic block position type. + 278 : * With 32 bits and 128k blocks you can address 256 TB. 279 : */ - 280 : typedef int64_t data_off_t; + 280 : typedef uint32_t block_off_t; 281 : 282 : /** - 283 : * Includes specific support for Windows or Linux. - 284 : */ - 285 : #ifdef __MINGW32__ - 286 : #include "mingw.h" - 287 : #else - 288 : #include "unix.h" - 289 : #endif - 290 : - 291 : /** - 292 : * Include list support to have tommy_node. - 293 : */ - 294 : #include "tommyds/tommylist.h" - 295 : - 296 : /** - 297 : * Another name for link() to avoid confusion with local variables called "link". - 298 : */ - 299 12 : static inline int hardlink(const char* a, const char* b) - 300 : { - 301 12 : return link(a, b); - 302 : } - 303 : - 304 : /** - 305 : * Get the device UUID. - 306 : * Return 0 on success. - 307 : */ - 308 : int devuuid(uint64_t device, char* uuid, size_t size); + 283 : * Basic data position type. + 284 : * It's signed as file size and offset are usually signed. + 285 : */ + 286 : typedef int64_t data_off_t; + 287 : + 288 : /** + 289 : * Includes specific support for Windows or Linux. + 290 : */ + 291 : #ifdef __MINGW32__ + 292 : #include "mingw.h" + 293 : #else + 294 : #include "unix.h" + 295 : #endif + 296 : + 297 : /** + 298 : * Include list support to have tommy_node. + 299 : */ + 300 : #include "tommyds/tommylist.h" + 301 : + 302 : /** + 303 : * Another name for link() to avoid confusion with local variables called "link". + 304 : */ + 305 12 : static inline int hardlink(const char* a, const char* b) + 306 : { + 307 12 : return link(a, b); + 308 : } 309 : 310 : /** - 311 : * Physical offset not yet read. - 312 : */ - 313 : #define FILEPHY_UNREAD_OFFSET 0 - 314 : - 315 : /** - 316 : * Special value returned when the file-system doesn't report any offset for unknown reason. - 317 : */ - 318 : #define FILEPHY_UNREPORTED_OFFSET 1 - 319 : - 320 : /** - 321 : * Special value returned when the file doesn't have a real offset. - 322 : * For example, because it's stored in the NTFS MFT. + 311 : * Get the device UUID. + 312 : * Return 0 on success. + 313 : */ + 314 : int devuuid(uint64_t device, char* uuid, size_t size); + 315 : + 316 : /** + 317 : * Physical offset not yet read. + 318 : */ + 319 : #define FILEPHY_UNREAD_OFFSET 0 + 320 : + 321 : /** + 322 : * Special value returned when the file-system doesn't report any offset for unknown reason. 323 : */ - 324 : #define FILEPHY_WITHOUT_OFFSET 2 + 324 : #define FILEPHY_UNREPORTED_OFFSET 1 325 : 326 : /** - 327 : * Value indicating real offsets. All offsets greater or equal at this one are real. - 328 : */ - 329 : #define FILEPHY_REAL_OFFSET 3 - 330 : - 331 : /** - 332 : * Get the physcal address of the specified file. - 333 : * This is expected to be just a hint and not necessarily correct or unique. - 334 : * Return 0 on success. - 335 : */ - 336 : int filephy(const char* path, uint64_t size, uint64_t* physical); - 337 : - 338 : /** - 339 : * Check if the underline file-system support persistent inodes. - 340 : * Return -1 on error, 0 on success. + 327 : * Special value returned when the file doesn't have a real offset. + 328 : * For example, because it's stored in the NTFS MFT. + 329 : */ + 330 : #define FILEPHY_WITHOUT_OFFSET 2 + 331 : + 332 : /** + 333 : * Value indicating real offsets. All offsets greater or equal at this one are real. + 334 : */ + 335 : #define FILEPHY_REAL_OFFSET 3 + 336 : + 337 : /** + 338 : * Get the physcal address of the specified file. + 339 : * This is expected to be just a hint and not necessarily correct or unique. + 340 : * Return 0 on success. 341 : */ - 342 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space); + 342 : int filephy(const char* path, uint64_t size, uint64_t* physical); 343 : 344 : /** - 345 : * Get the tick counter value. - 346 : * - 347 : * Note that the frequency is unspecified, because the time measure - 348 : * is meant to be used to compare the ratio between usage times. - 349 : */ - 350 : uint64_t tick(void); - 351 : - 352 : /** - 353 : * Get the tick counter value in millisecond. - 354 : */ - 355 : uint64_t tick_ms(void); - 356 : - 357 : /** - 358 : * Initializes the system. - 359 : */ - 360 : void os_init(int opt); - 361 : - 362 : /** - 363 : * Deinitialize the system. - 364 : */ - 365 : void os_done(void); - 366 : - 367 : /** - 368 : * Abort the process with a stacktrace. - 369 : */ - 370 : void os_abort(void) __noreturn; - 371 : - 372 : /** - 373 : * Clear the screen. - 374 : */ - 375 : void os_clear(void); - 376 : - 377 : /** - 378 : * Log file. - 379 : * - 380 : * This stream if fully buffered. - 381 : * - 382 : * If no log file is selected, it's 0. - 383 : */ - 384 : FILE* stdlog; - 385 : - 386 : /** - 387 : * Exit codes for testing. - 388 : */ - 389 : int exit_success; - 390 : int exit_failure; - 391 : int exit_sync_needed; - 392 : #undef EXIT_SUCCESS - 393 : #undef EXIT_FAILURE - 394 : #define EXIT_SUCCESS exit_success - 395 : #define EXIT_FAILURE exit_failure - 396 : #define EXIT_SYNC_NEEDED exit_sync_needed - 397 : - 398 : /** - 399 : * Fill memory with pseudo-random values. - 400 : */ - 401 : int randomize(void* ptr, size_t size); - 402 : - 403 : /** - 404 : * Standard SMART attributes. - 405 : */ - 406 : #define SMART_START_STOP_COUNT 4 - 407 : #define SMART_REALLOCATED_SECTOR_COUNT 5 - 408 : #define SMART_POWER_ON_HOURS 9 - 409 : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190 - 410 : #define SMART_LOAD_CYCLE_COUNT 193 - 411 : #define SMART_TEMPERATURE_CELSIUS 194 - 412 : - 413 : /** - 414 : * Additional SMART attributes. - 415 : */ - 416 : #define SMART_ERROR 256 /**< ATA Error count. */ - 417 : #define SMART_SIZE 257 /**< Size in bytes. */ - 418 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ - 419 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ - 420 : - 421 : /** - 422 : * SMART attributes count. - 423 : */ - 424 : #define SMART_COUNT 260 - 425 : - 426 : /** - 427 : * Flags returned by smartctl. - 428 : */ - 429 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ - 430 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ - 431 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ - 432 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ - 433 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ - 434 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */ - 435 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ - 436 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ - 437 : - 438 : /** - 439 : * SMART max attribute length. - 440 : */ - 441 : #define SMART_MAX 64 - 442 : - 443 : /** - 444 : * Value for unassigned SMART attribute. - 445 : */ - 446 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL - 447 : - 448 : /** - 449 : * Device info entry. - 450 : */ - 451 : struct devinfo_struct { - 452 : uint64_t device; /**< Device ID. */ - 453 : char name[PATH_MAX]; /**< Name of the disk. */ - 454 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */ - 455 : char smartctl[PATH_MAX]; /**< Options for smartctl. */ - 456 : char file[PATH_MAX]; /**< File device. */ - 457 : #ifdef _WIN32 - 458 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ - 459 : #endif - 460 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */ - 461 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ - 462 : char smart_serial[SMART_MAX]; /**< SMART serial number. */ - 463 : char smart_vendor[SMART_MAX]; /**< SMART vendor. */ - 464 : char smart_model[SMART_MAX]; /**< SMART model. */ - 465 : #if HAVE_PTHREAD - 466 : pthread_t thread; - 467 : #endif - 468 : tommy_node node; - 469 : }; - 470 : typedef struct devinfo_struct devinfo_t; - 471 : - 472 : #define DEVICE_LIST 0 - 473 : #define DEVICE_DOWN 1 - 474 : #define DEVICE_UP 2 - 475 : #define DEVICE_SMART 3 - 476 : - 477 : /** - 478 : * Query all the "high" level devices with the specified operation, - 479 : * and produces a list of "low" level devices to operate on. - 480 : * - 481 : * The passed "low" device list must be already initialized. - 482 : */ - 483 : int devquery(tommy_list* high, tommy_list* low, int operation, int others); - 484 : - 485 : #endif - 486 : + 345 : * Check if the underline file-system support persistent inodes. + 346 : * Return -1 on error, 0 on success. + 347 : */ + 348 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space); + 349 : + 350 : /** + 351 : * Get the tick counter value. + 352 : * + 353 : * Note that the frequency is unspecified, because the time measure + 354 : * is meant to be used to compare the ratio between usage times. + 355 : */ + 356 : uint64_t tick(void); + 357 : + 358 : /** + 359 : * Get the tick counter value in millisecond. + 360 : */ + 361 : uint64_t tick_ms(void); + 362 : + 363 : /** + 364 : * Initializes the system. + 365 : */ + 366 : void os_init(int opt); + 367 : + 368 : /** + 369 : * Deinitialize the system. + 370 : */ + 371 : void os_done(void); + 372 : + 373 : /** + 374 : * Abort the process with a stacktrace. + 375 : */ + 376 : void os_abort(void) __noreturn; + 377 : + 378 : /** + 379 : * Clear the screen. + 380 : */ + 381 : void os_clear(void); + 382 : + 383 : /** + 384 : * Log file. + 385 : * + 386 : * This stream if fully buffered. + 387 : * + 388 : * If no log file is selected, it's 0. + 389 : */ + 390 : FILE* stdlog; + 391 : + 392 : /** + 393 : * Exit codes for testing. + 394 : */ + 395 : int exit_success; + 396 : int exit_failure; + 397 : int exit_sync_needed; + 398 : #undef EXIT_SUCCESS + 399 : #undef EXIT_FAILURE + 400 : #define EXIT_SUCCESS exit_success + 401 : #define EXIT_FAILURE exit_failure + 402 : #define EXIT_SYNC_NEEDED exit_sync_needed + 403 : + 404 : /** + 405 : * Fill memory with pseudo-random values. + 406 : */ + 407 : int randomize(void* ptr, size_t size); + 408 : + 409 : /** + 410 : * Standard SMART attributes. + 411 : */ + 412 : #define SMART_START_STOP_COUNT 4 + 413 : #define SMART_REALLOCATED_SECTOR_COUNT 5 + 414 : #define SMART_POWER_ON_HOURS 9 + 415 : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190 + 416 : #define SMART_LOAD_CYCLE_COUNT 193 + 417 : #define SMART_TEMPERATURE_CELSIUS 194 + 418 : + 419 : /** + 420 : * Additional SMART attributes. + 421 : */ + 422 : #define SMART_ERROR 256 /**< ATA Error count. */ + 423 : #define SMART_SIZE 257 /**< Size in bytes. */ + 424 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ + 425 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ + 426 : + 427 : /** + 428 : * SMART attributes count. + 429 : */ + 430 : #define SMART_COUNT 260 + 431 : + 432 : /** + 433 : * Flags returned by smartctl. + 434 : */ + 435 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ + 436 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ + 437 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ + 438 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ + 439 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ + 440 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */ + 441 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ + 442 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ + 443 : + 444 : /** + 445 : * SMART max attribute length. + 446 : */ + 447 : #define SMART_MAX 64 + 448 : + 449 : /** + 450 : * Value for unassigned SMART attribute. + 451 : */ + 452 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL + 453 : + 454 : /** + 455 : * Device info entry. + 456 : */ + 457 : struct devinfo_struct { + 458 : uint64_t device; /**< Device ID. */ + 459 : char name[PATH_MAX]; /**< Name of the disk. */ + 460 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */ + 461 : char smartctl[PATH_MAX]; /**< Options for smartctl. */ + 462 : char file[PATH_MAX]; /**< File device. */ + 463 : #ifdef _WIN32 + 464 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ + 465 : #endif + 466 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */ + 467 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ + 468 : char smart_serial[SMART_MAX]; /**< SMART serial number. */ + 469 : char smart_vendor[SMART_MAX]; /**< SMART vendor. */ + 470 : char smart_model[SMART_MAX]; /**< SMART model. */ + 471 : #if HAVE_PTHREAD + 472 : pthread_t thread; + 473 : #endif + 474 : tommy_node node; + 475 : }; + 476 : typedef struct devinfo_struct devinfo_t; + 477 : + 478 : #define DEVICE_LIST 0 + 479 : #define DEVICE_DOWN 1 + 480 : #define DEVICE_UP 2 + 481 : #define DEVICE_SMART 3 + 482 : + 483 : /** + 484 : * Query all the "high" level devices with the specified operation, + 485 : * and produces a list of "low" level devices to operate on. + 486 : * + 487 : * The passed "low" device list must be already initialized. + 488 : */ + 489 : int devquery(tommy_list* high, tommy_list* low, int operation, int others); + 490 : + 491 : #endif + 492 : diff --git a/cov/cmdline/rehash.c.func-sort-c.html b/cov/cmdline/rehash.c.func-sort-c.html index 8a66d85e..a7888c53 100644 --- a/cov/cmdline/rehash.c.func-sort-c.html +++ b/cov/cmdline/rehash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/rehash.c.func.html b/cov/cmdline/rehash.c.func.html index 84923317..091c105e 100644 --- a/cov/cmdline/rehash.c.func.html +++ b/cov/cmdline/rehash.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/rehash.c.gcov.html b/cov/cmdline/rehash.c.gcov.html index 3d0d0126..d3f78e7d 100644 --- a/cov/cmdline/rehash.c.gcov.html +++ b/cov/cmdline/rehash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/scan.c.func-sort-c.html b/cov/cmdline/scan.c.func-sort-c.html index ffed18f4..137bfc7d 100644 --- a/cov/cmdline/scan.c.func-sort-c.html +++ b/cov/cmdline/scan.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 23 @@ -73,39 +73,39 @@ scan_file_keep - 1025550 + 1025552 file_is_full_invalid_parity_and_stable - 1025550 + 1025552 dd_ino_compare - 103390 + 103400 scan_file_delayed_allocate - 101881 + 101879 scan_file_insert - 101881 + 101879 scan_file_allocate - 101881 + 101879 scan_file_refresh - 79194 + 79192 scan_file_remove - 57015 + 57013 scan_file_deallocate - 57015 + 57013 scan_link diff --git a/cov/cmdline/scan.c.func.html b/cov/cmdline/scan.c.func.html index 28656181..78e78b2e 100644 --- a/cov/cmdline/scan.c.func.html +++ b/cov/cmdline/scan.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 23 @@ -61,7 +61,7 @@ dd_ino_compare - 103390 + 103400 dd_name_compare @@ -77,7 +77,7 @@ file_is_full_invalid_parity_and_stable - 1025550 + 1025552 scan_dir @@ -101,31 +101,31 @@ scan_file_allocate - 101881 + 101879 scan_file_deallocate - 57015 + 57013 scan_file_delayed_allocate - 101881 + 101879 scan_file_insert - 101881 + 101879 scan_file_keep - 1025550 + 1025552 scan_file_refresh - 79194 + 79192 scan_file_remove - 57015 + 57013 scan_link diff --git a/cov/cmdline/scan.c.gcov.html b/cov/cmdline/scan.c.gcov.html index 1e9ebb3c..43b28eee 100644 --- a/cov/cmdline/scan.c.gcov.html +++ b/cov/cmdline/scan.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 23 @@ -220,42 +220,42 @@ 158 : /** 159 : * Insert the specified file in the parity. 160 : */ - 161 101881 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 161 101879 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 162 : { - 163 101881 : struct snapraid_state* state = scan->state; - 164 101881 : struct snapraid_disk* disk = scan->disk; + 163 101879 : struct snapraid_state* state = scan->state; + 164 101879 : struct snapraid_disk* disk = scan->disk; 165 : block_off_t i; 166 : block_off_t parity_pos; 167 : 168 : /* state changed */ - 169 101881 : state->need_write = 1; + 169 101879 : state->need_write = 1; 170 : 171 : /* allocate the blocks of the file */ - 172 101881 : parity_pos = disk->first_free_block; - 173 353073 : for (i = 0; i < file->blockmax; ++i) { + 172 101879 : parity_pos = disk->first_free_block; + 173 353147 : for (i = 0; i < file->blockmax; ++i) { 174 : struct snapraid_block* block; 175 : struct snapraid_block* over_block; 176 : snapraid_info info; 177 : 178 : /* increment the position until the first really free block */ - 179 1022715 : while (block_has_file(fs_par2block_find(disk, parity_pos))) - 180 520331 : ++parity_pos; + 179 1022869 : while (block_has_file(fs_par2block_find(disk, parity_pos))) + 180 520333 : ++parity_pos; 181 : 182 : /* get block we are going to overwrite, if any */ - 183 251192 : over_block = fs_par2block_find(disk, parity_pos); + 183 251268 : over_block = fs_par2block_find(disk, parity_pos); 184 : 185 : /* deallocate it */ - 186 251192 : if (over_block != BLOCK_NULL) - 187 95279 : fs_deallocate(disk, parity_pos); + 186 251268 : if (over_block != BLOCK_NULL) + 187 95355 : fs_deallocate(disk, parity_pos); 188 : 189 : /* get block specific info */ - 190 251192 : info = info_get(&state->infoarr, parity_pos); + 190 251268 : info = info_get(&state->infoarr, parity_pos); 191 : 192 : /* get the new block we are going to write */ - 193 251192 : block = fs_file2block_get(file, i); + 193 251268 : block = fs_file2block_get(file, i); 194 : 195 : /* if the file block already has an updated hash without rehash */ - 196 251192 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { + 196 251268 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { 197 : /* the only possible case is for REP blocks */ 198 86215 : assert(block_state_get(block) == BLOCK_STATE_REP); 199 : @@ -267,25 +267,25 @@ 205 : unsigned over_state; 206 : 207 : /* convert to a CHG block */ - 208 164977 : block_state_set(block, BLOCK_STATE_CHG); + 208 165053 : block_state_set(block, BLOCK_STATE_CHG); 209 : 210 : /* state of the block we are going to overwrite */ - 211 164977 : over_state = block_state_get(over_block); + 211 165053 : over_state = block_state_get(over_block); 212 : 213 : /* if the block is an empty one */ - 214 164977 : if (over_state == BLOCK_STATE_EMPTY) { + 214 165053 : if (over_state == BLOCK_STATE_EMPTY) { 215 : /* the block was empty and filled with zeros */ 216 : /* set the hash to the special ZERO value */ 217 115543 : hash_zero_set(block->hash); 218 : } else { 219 : /* otherwise it's a DELETED one */ - 220 49434 : assert(over_state == BLOCK_STATE_DELETED); + 220 49510 : assert(over_state == BLOCK_STATE_DELETED); 221 : 222 : /* copy the past hash of the block */ - 223 49434 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE); + 223 49510 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE); 224 : 225 : /* if we have not already cleared the past hash */ - 226 49434 : if (!state->clear_past_hash) { + 226 49510 : if (!state->clear_past_hash) { 227 : /* in this case we don't know if the old state is still the one */ 228 : /* stored inside the parity, because after an aborted sync, the parity */ 229 : /* may be or may be not have been updated with the new data */ @@ -302,15 +302,15 @@ 240 : } 241 : 242 : /* store in the disk map, after invalidating all the other blocks */ - 243 251192 : fs_allocate(disk, parity_pos, file, i); + 243 251268 : fs_allocate(disk, parity_pos, file, i); 244 : 245 : /* set the new free position */ - 246 251192 : disk->first_free_block = parity_pos + 1; + 246 251268 : disk->first_free_block = parity_pos + 1; 247 : } 248 : 249 : /* insert in the list of contained files */ - 250 101881 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); - 251 101881 : } + 250 101879 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 251 101879 : } 252 : 253 : /** 254 : * Delete the specified file from the parity. @@ -319,23 +319,23 @@ 257 : * The file is then inserted in the deleted set, and it should not be deallocated, 258 : * as the parity still references it. 259 : */ - 260 57015 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) + 260 57013 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) 261 : { - 262 57015 : struct snapraid_state* state = scan->state; - 263 57015 : struct snapraid_disk* disk = scan->disk; + 262 57013 : struct snapraid_state* state = scan->state; + 263 57013 : struct snapraid_disk* disk = scan->disk; 264 : block_off_t i; 265 : 266 : /* remove from the list of contained files */ - 267 57015 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); + 267 57013 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); 268 : 269 : /* state changed */ - 270 57015 : state->need_write = 1; + 270 57013 : state->need_write = 1; 271 : 272 : /* here we are supposed to adjust the ::first_free_block position */ 273 : /* with the parity position we are deleting */ 274 : /* but we also know that we do only delayed insert, after all the deletion, */ 275 : /* so at this point ::first_free_block is always at 0, and we don't need to update it */ - 276 57015 : if (disk->first_free_block != 0) { + 276 57013 : if (disk->first_free_block != 0) { 277 : /* LCOV_EXCL_START */ 278 : log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub); 279 : os_abort(); @@ -343,17 +343,17 @@ 281 : } 282 : 283 : /* free all the blocks of the file */ - 284 197592 : for (i = 0; i < file->blockmax; ++i) { - 285 140577 : struct snapraid_block* block = fs_file2block_get(file, i); + 284 197666 : for (i = 0; i < file->blockmax; ++i) { + 285 140653 : struct snapraid_block* block = fs_file2block_get(file, i); 286 : unsigned block_state; 287 : 288 : /* in case we scan after an aborted sync, */ 289 : /* we could get also intermediate states */ - 290 140577 : block_state = block_state_get(block); - 291 140577 : switch (block_state) { + 290 140653 : block_state = block_state_get(block); + 291 140653 : switch (block_state) { 292 : case BLOCK_STATE_BLK : 293 : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */ - 294 35580 : break; + 294 35656 : break; 295 : case BLOCK_STATE_CHG : 296 : /* if we have not already cleared the past hash */ 297 28040 : if (!state->clear_past_hash) { @@ -383,23 +383,23 @@ 321 : } 322 : 323 : /* set the block as deleted */ - 324 140577 : block_state_set(block, BLOCK_STATE_DELETED); + 324 140653 : block_state_set(block, BLOCK_STATE_DELETED); 325 : } 326 : 327 : /* mark the file as deleted */ - 328 57015 : file_flag_set(file, FILE_IS_DELETED); + 328 57013 : file_flag_set(file, FILE_IS_DELETED); 329 : 330 : /* insert it in the list of deleted blocks */ - 331 57015 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); - 332 57015 : } + 331 57013 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); + 332 57013 : } 333 : - 334 101881 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 334 101879 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 335 : { - 336 101881 : struct snapraid_state* state = scan->state; - 337 101881 : struct snapraid_disk* disk = scan->disk; + 336 101879 : struct snapraid_state* state = scan->state; + 337 101879 : struct snapraid_disk* disk = scan->disk; 338 : 339 : /* if we sort for physical offsets we have to read them for new files */ - 340 101881 : if (state->opt.force_order == SORT_PHYSICAL + 340 101879 : if (state->opt.force_order == SORT_PHYSICAL 341 11432 : && file->physical == FILEPHY_UNREAD_OFFSET 342 : ) { 343 : char path_next[PATH_MAX]; @@ -415,30 +415,30 @@ 353 : } 354 : 355 : /* insert in the delayed list */ - 356 101881 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); - 357 101881 : } + 356 101879 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); + 357 101879 : } 358 : 359 : /** 360 : * Check if a file is completely formed of blocks with invalid parity, 361 : * and no rehash is tagged, and if it has at least one block. 362 : */ - 363 1025550 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 363 1025552 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 364 : { 365 : block_off_t i; 366 : 367 : /* with no block, it never has an invalid parity */ - 368 1025550 : if (file->blockmax == 0) - 369 1439 : return 0; + 368 1025552 : if (file->blockmax == 0) + 369 1437 : return 0; 370 : 371 : /* check all blocks */ - 372 1080079 : for (i = 0; i < file->blockmax; ++i) { + 372 1080083 : for (i = 0; i < file->blockmax; ++i) { 373 : snapraid_info info; - 374 1057392 : struct snapraid_block* block = fs_file2block_get(file, i); + 374 1057396 : struct snapraid_block* block = fs_file2block_get(file, i); 375 : block_off_t parity_pos; 376 : 377 : /* exclude blocks with parity */ - 378 1057392 : if (!block_has_invalid_parity(block)) - 379 1001424 : return 0; + 378 1057396 : if (!block_has_invalid_parity(block)) + 379 1001428 : return 0; 380 : 381 : /* 382 : * Get the parity position. @@ -525,7 +525,7 @@ 463 : * 464 : * If this happens, we read also the physical offset, to avoid to read it later. 465 : */ - 466 79194 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) + 466 79192 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) 467 : { 468 : #if HAVE_LSTAT_SYNC 469 : struct snapraid_state* state = scan->state; @@ -597,43 +597,43 @@ 535 : (void)st; 536 : (void)physical; 537 : #endif - 538 79194 : } + 538 79192 : } 539 : 540 : /** 541 : * Insert the file in the data set. 542 : */ - 543 101881 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) + 543 101879 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) 544 : { - 545 101881 : struct snapraid_disk* disk = scan->disk; + 545 101879 : struct snapraid_disk* disk = scan->disk; 546 : 547 : /* insert the file in the containers */ - 548 101881 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 549 101881 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - 550 101881 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 551 101881 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 548 101879 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 549 101879 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 550 101879 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 551 101879 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); 552 : 553 : /* delayed allocation of the parity */ - 554 101881 : scan_file_delayed_allocate(scan, file); - 555 101881 : } + 554 101879 : scan_file_delayed_allocate(scan, file); + 555 101879 : } 556 : 557 : /** 558 : * Remove the file from the data set. 559 : * 560 : * File is then deleted. 561 : */ - 562 57015 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) + 562 57013 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) 563 : { - 564 57015 : struct snapraid_disk* disk = scan->disk; + 564 57013 : struct snapraid_disk* disk = scan->disk; 565 : 566 : /* remove the file from the containers */ - 567 57015 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 568 56941 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); - 569 57015 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); - 570 57015 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); + 567 57013 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 568 56967 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 569 57013 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + 570 57013 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); 571 : 572 : /* deallocate the file from the parity */ - 573 57015 : scan_file_deallocate(scan, file); - 574 57015 : } + 573 57013 : scan_file_deallocate(scan, file); + 574 57013 : } 575 : 576 : /** 577 : * Keep the file as it's (or with only a name/inode modification). @@ -646,12 +646,12 @@ 584 : * This could happen after a failed sync, when some other files are deleted, 585 : * and then new ones can be moved backward to fill the hole created. 586 : */ - 587 1025550 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) + 587 1025552 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) 588 : { - 589 1025550 : struct snapraid_disk* disk = scan->disk; + 589 1025552 : struct snapraid_disk* disk = scan->disk; 590 : 591 : /* if the file is full invalid, schedule a reinsert at later stage */ - 592 1025550 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { + 592 1025552 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { 593 22687 : struct snapraid_file* copy = file_dup(file); 594 : 595 : /* remove the file */ @@ -660,7 +660,7 @@ 598 : /* reinsert the copy in the delayed list */ 599 22687 : scan_file_insert(scan, copy); 600 : } - 601 1025550 : } + 601 1025552 : } 602 : 603 : /** 604 : * Process a file. @@ -717,17 +717,17 @@ 655 : /* identify moved files with past inodes and hardlinks with the new inodes */ 656 1104939 : if (file) { 657 : /* check if the file is not changed */ - 658 943901 : if (file->size == st->st_size - 659 935613 : && file->mtime_sec == st->st_mtime - 660 932556 : && (file->mtime_nsec == STAT_NSEC(st) + 658 945290 : if (file->size == st->st_size + 659 929850 : && file->mtime_sec == st->st_mtime + 660 926844 : && (file->mtime_nsec == STAT_NSEC(st) 661 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 662 : /* it happens when upgrading from an old version of SnapRAID */ 663 : /* not yet supporting the nanosecond field */ - 664 1 : || file->mtime_nsec == STAT_NSEC_INVALID + 664 6 : || file->mtime_nsec == STAT_NSEC_INVALID 665 : ) 666 : ) { 667 : /* check if multiple files have the same inode */ - 668 932555 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 668 926838 : if (file_flag_has(file, FILE_IS_PRESENT)) { 669 : #if HAVE_STRUCT_STAT_ST_NLINK 670 195 : if (st->st_nlink <= 1) { 671 : /* LCOV_EXCL_START */ @@ -742,11 +742,11 @@ 680 : } 681 : 682 : /* mark as present */ - 683 932360 : file_flag_set(file, FILE_IS_PRESENT); + 683 926643 : file_flag_set(file, FILE_IS_PRESENT); 684 : 685 : /* update the nanoseconds mtime only if different */ 686 : /* to avoid unneeded updates */ - 687 932360 : if (file->mtime_nsec == STAT_NSEC_INVALID + 687 926643 : if (file->mtime_nsec == STAT_NSEC_INVALID 688 0 : && STAT_NSEC(st) != file->mtime_nsec 689 : ) { 690 0 : file->mtime_nsec = STAT_NSEC(st); @@ -755,7 +755,7 @@ 693 0 : state->need_write = 1; 694 : } 695 : - 696 932360 : if (strcmp(file->sub, sub) != 0) { + 696 926643 : if (strcmp(file->sub, sub) != 0) { 697 : /* if the path is different, it means a moved file with the same inode */ 698 155 : ++scan->count_move; 699 : @@ -777,18 +777,18 @@ 715 155 : state->need_write = 1; 716 : } else { 717 : /* otherwise it's equal */ - 718 932205 : ++scan->count_equal; + 718 926488 : ++scan->count_equal; 719 : - 720 932205 : if (state->opt.gui) { + 720 926488 : if (state->opt.gui) { 721 22611 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); 722 : } 723 : } 724 : 725 : /* mark the file as kept */ - 726 932360 : scan_file_keep(scan, file); + 726 926643 : scan_file_keep(scan, file); 727 : 728 : /* nothing more to do */ - 729 932360 : return; + 729 926643 : return; 730 : } 731 : 732 : /* here the file matches the inode, but not the other info */ @@ -797,7 +797,7 @@ 735 : /* or a file-system with not persistent inodes */ 736 : 737 : /* for sure it cannot be already present */ - 738 11346 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 738 18452 : if (file_flag_has(file, FILE_IS_PRESENT)) { 739 : /* LCOV_EXCL_START */ 740 : log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub); 741 : os_abort(); @@ -810,44 +810,44 @@ 748 : /* otherwise, it will get removed */ 749 : 750 : /* remove from the inode set */ - 751 11346 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 751 18452 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 752 : 753 : /* clear the inode */ 754 : /* this is not really needed for correct functionality */ 755 : /* because we are going to set FILE_IS_WITHOUT_INODE */ 756 : /* but it's easier for debugging to have invalid inodes set to 0 */ - 757 11346 : file->inode = 0; + 757 18452 : file->inode = 0; 758 : 759 : /* mark as missing inode */ - 760 11346 : file_flag_set(file, FILE_IS_WITHOUT_INODE); + 760 18452 : file_flag_set(file, FILE_IS_WITHOUT_INODE); 761 : 762 : /* go further to find it by name */ 763 : } 764 : 765 : /* initialize for later overwrite */ - 766 172384 : is_file_reported = 0; - 767 172384 : is_original_file_size_different_than_zero = 0; + 766 178101 : is_file_reported = 0; + 767 178101 : is_original_file_size_different_than_zero = 0; 768 : 769 : /* then try finding it by name */ - 770 172384 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); + 770 178101 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); 771 : 772 : /* keep track if the file already exists */ - 773 172384 : is_file_already_present = file != 0; + 773 178101 : is_file_already_present = file != 0; 774 : - 775 172384 : if (is_file_already_present) { + 775 178101 : if (is_file_already_present) { 776 : /* if the file is without an inode */ - 777 97871 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { + 777 103588 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { 778 : /* set it now */ - 779 11286 : file->inode = st->st_ino; + 779 18420 : file->inode = st->st_ino; 780 : 781 : /* insert in the set */ - 782 11286 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 782 18420 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 783 : 784 : /* unmark as missing inode */ - 785 11286 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); + 785 18420 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); 786 : } else { 787 : /* here the inode has to be different, otherwise we would have found it before */ - 788 86585 : if (file->inode == st->st_ino) { + 788 85168 : if (file->inode == st->st_ino) { 789 : /* LCOV_EXCL_START */ 790 : log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub); 791 : os_abort(); @@ -856,7 +856,7 @@ 794 : } 795 : 796 : /* for sure it cannot be already present */ - 797 97871 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 797 103588 : if (file_flag_has(file, FILE_IS_PRESENT)) { 798 : /* LCOV_EXCL_START */ 799 : log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub); 800 : os_abort(); @@ -864,9 +864,9 @@ 802 : } 803 : 804 : /* check if the file is not changed */ - 805 97871 : if (file->size == st->st_size - 806 97275 : && file->mtime_sec == st->st_mtime - 807 93190 : && (file->mtime_nsec == STAT_NSEC(st) + 805 103588 : if (file->size == st->st_size + 806 102992 : && file->mtime_sec == st->st_mtime + 807 98909 : && (file->mtime_nsec == STAT_NSEC(st) 808 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 809 : /* it happens when upgrading from an old version of SnapRAID */ 810 : /* not yet supporting the nanosecond field */ @@ -874,11 +874,11 @@ 812 : ) 813 : ) { 814 : /* mark as present */ - 815 93190 : file_flag_set(file, FILE_IS_PRESENT); + 815 98909 : file_flag_set(file, FILE_IS_PRESENT); 816 : 817 : /* update the nano seconds mtime only if different */ 818 : /* to avoid unneeded updates */ - 819 93190 : if (file->mtime_nsec == STAT_NSEC_INVALID + 819 98909 : if (file->mtime_nsec == STAT_NSEC_INVALID 820 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID 821 : ) { 822 0 : file->mtime_nsec = STAT_NSEC(st); @@ -888,30 +888,30 @@ 826 : } 827 : 828 : /* if when processing the disk we used the past inodes values */ - 829 93190 : if (has_past_inodes) { + 829 98909 : if (has_past_inodes) { 830 : /* if persistent inodes are supported, we are sure that the inode number */ 831 : /* is now different, because otherwise the file would have been found */ 832 : /* when searching by inode. */ 833 : /* if the inode is different, it means a rewritten file with the same path */ 834 : /* like when restoring a backup that restores also the timestamp */ - 835 93176 : ++scan->count_restore; + 835 98895 : ++scan->count_restore; 836 : - 837 93176 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); - 838 93176 : if (is_diff) { + 837 98895 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); + 838 98895 : if (is_diff) { 839 0 : printf("restore %s\n", fmt_term(disk, sub, esc_buffer)); 840 : } 841 : 842 : /* remove from the inode set */ - 843 93176 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 843 98895 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 844 : 845 : /* save the new inode */ - 846 93176 : file->inode = st->st_ino; + 846 98895 : file->inode = st->st_ino; 847 : 848 : /* reinsert in the inode set */ - 849 93176 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 849 98895 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 850 : 851 : /* we have to save the new inode */ - 852 93176 : state->need_write = 1; + 852 98895 : state->need_write = 1; 853 : } else { 854 : /* otherwise it's the case of not persistent inode, where doesn't */ 855 : /* matter if the inode is different or equal, because they have no */ @@ -924,24 +924,24 @@ 862 : } 863 : 864 : /* mark the file as kept */ - 865 93190 : scan_file_keep(scan, file); + 865 98909 : scan_file_keep(scan, file); 866 : 867 : /* nothing more to do */ - 868 93190 : return; + 868 98909 : return; 869 : } 870 : 871 : /* here if the file is changed but with the correct name */ 872 : 873 : /* save the info for later printout */ - 874 4681 : file_already_present_size = file->size; - 875 4681 : file_already_present_mtime_sec = file->mtime_sec; - 876 4681 : file_already_present_mtime_nsec = file->mtime_nsec; + 874 4679 : file_already_present_size = file->size; + 875 4679 : file_already_present_mtime_sec = file->mtime_sec; + 876 4679 : file_already_present_mtime_nsec = file->mtime_nsec; 877 : 878 : /* keep track if the original file was not of zero size */ - 879 4681 : is_original_file_size_different_than_zero = file->size != 0; + 879 4679 : is_original_file_size_different_than_zero = file->size != 0; 880 : 881 : /* remove it, and continue to insert it again */ - 882 4681 : scan_file_remove(scan, file); + 882 4679 : scan_file_remove(scan, file); 883 : 884 : /* and continue to insert it again */ 885 : } else { @@ -953,13 +953,13 @@ 891 : /* refresh the info, to ensure that they are synced, */ 892 : /* note that we refresh only the info of the new or modified files */ 893 : /* because this is slow operation */ - 894 79194 : scan_file_refresh(scan, sub, st, &physical); + 894 79192 : scan_file_refresh(scan, sub, st, &physical); 895 : 896 : #ifndef _WIN32 897 : /* do a safety check to ensure that the common ext4 case of zeroing */ 898 : /* the size of a file after a crash doesn't propagate to the backup */ 899 : /* this check is specific for Linux, so we disable it on Windows */ - 900 79194 : if (is_original_file_size_different_than_zero && st->st_size == 0) { + 900 79192 : if (is_original_file_size_different_than_zero && st->st_size == 0) { 901 0 : if (!state->opt.force_zero) { 902 : /* LCOV_EXCL_START */ 903 : log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub); @@ -978,33 +978,33 @@ 916 : #endif 917 : 918 : /* insert it */ - 919 79194 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); + 919 79192 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); 920 : 921 : /* mark it as present */ - 922 79194 : file_flag_set(file, FILE_IS_PRESENT); + 922 79192 : file_flag_set(file, FILE_IS_PRESENT); 923 : 924 : /* if copy detection is enabled */ 925 : /* note that the copy detection is tried also for updated files */ 926 : /* this makes sense because it may happen to have two different copies */ 927 : /* of the same file, and we move the right one over the wrong one */ 928 : /* in such case we have a "copy" over an "update" */ - 929 79194 : if (!state->opt.force_nocopy) { - 930 79194 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 929 79192 : if (!state->opt.force_nocopy) { + 930 79192 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 931 : 932 : /* search for a file with the same name and stamp in all the disks */ - 933 423410 : for (i = state->disklist; i != 0; i = i->next) { - 934 367852 : struct snapraid_disk* other_disk = i->data; + 933 423396 : for (i = state->disklist; i != 0; i = i->next) { + 934 367840 : struct snapraid_disk* other_disk = i->data; 935 : struct snapraid_file* other_file; 936 : 937 : /* if the nanosecond part of the time stamp is valid, search */ 938 : /* for name and stamp, otherwise for path and stamp */ - 939 367852 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) - 940 367744 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); + 939 367840 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) + 940 367732 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); 941 : else 942 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); 943 : 944 : /* if found, and it's a fully hashed file */ - 945 367852 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { + 945 367840 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { 946 : /* assume that the file is a copy, and reuse the hash */ 947 23636 : file_copy(other_file, file); 948 : @@ -1027,16 +1027,16 @@ 965 : 966 : /* if not yet reported, do it now */ 967 : /* we postpone this to avoid to print two times the copied files */ - 968 79194 : if (!is_file_reported) { - 969 55558 : if (is_file_already_present) { - 970 4681 : ++scan->count_change; + 968 79192 : if (!is_file_reported) { + 969 55556 : if (is_file_already_present) { + 970 4679 : ++scan->count_change; 971 : - 972 14043 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer), + 972 14037 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer), 973 : (uint64_t)file_already_present_size, (uint64_t)file_already_present_mtime_sec, file_already_present_mtime_nsec, - 974 9362 : (uint64_t)file->size, (uint64_t)file->mtime_sec, file->mtime_nsec + 974 9358 : (uint64_t)file->size, (uint64_t)file->mtime_sec, file->mtime_nsec 975 : ); 976 : - 977 4681 : if (is_diff) { + 977 4679 : if (is_diff) { 978 118 : printf("update %s\n", fmt_term(disk, sub, esc_buffer)); 979 : } 980 : } else { @@ -1050,7 +1050,7 @@ 988 : } 989 : 990 : /* insert the file in the delayed list */ - 991 79194 : scan_file_insert(scan, file); + 991 79192 : scan_file_insert(scan, file); 992 : } 993 : 994 : /** @@ -1143,15 +1143,15 @@ 1081 : }; 1082 : 1083 : #if HAVE_STRUCT_DIRENT_D_INO - 1084 103390 : static int dd_ino_compare(const void* void_a, const void* void_b) + 1084 103400 : static int dd_ino_compare(const void* void_a, const void* void_b) 1085 : { - 1086 103390 : const struct dirent_sorted* a = void_a; - 1087 103390 : const struct dirent_sorted* b = void_b; + 1086 103400 : const struct dirent_sorted* a = void_a; + 1087 103400 : const struct dirent_sorted* b = void_b; 1088 : - 1089 103390 : if (a->d_ino < b->d_ino) - 1090 49438 : return -1; - 1091 53952 : if (a->d_ino > b->d_ino) - 1092 53952 : return 1; + 1089 103400 : if (a->d_ino < b->d_ino) + 1090 49432 : return -1; + 1091 53968 : if (a->d_ino > b->d_ino) + 1092 53968 : return 1; 1093 : 1094 0 : return 0; 1095 : } @@ -1584,14 +1584,14 @@ 1522 : 1523 : /* check for removed files */ 1524 575 : node = disk->filelist; - 1525 1033660 : while (node) { - 1526 1032510 : struct snapraid_file* file = node->data; + 1525 1033662 : while (node) { + 1526 1032512 : struct snapraid_file* file = node->data; 1527 : 1528 : /* next node */ - 1529 1032510 : node = node->next; + 1529 1032512 : node = node->next; 1530 : 1531 : /* remove if not present */ - 1532 1032510 : if (!file_flag_has(file, FILE_IS_PRESENT)) { + 1532 1032512 : if (!file_flag_has(file, FILE_IS_PRESENT)) { 1533 29647 : ++scan->count_remove; 1534 : 1535 29647 : log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); @@ -1664,11 +1664,11 @@ 1602 575 : phy_dup = 0; 1603 575 : phy_last = FILEPHY_UNREAD_OFFSET; 1604 575 : phy_file_last = 0; - 1605 103031 : while (node) { - 1606 101881 : struct snapraid_file* file = node->data; + 1605 103029 : while (node) { + 1606 101879 : struct snapraid_file* file = node->data; 1607 : 1608 : /* if the file is not empty, count duplicate physical offsets */ - 1609 101881 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { + 1609 101879 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { 1610 11418 : if (phy_file_last != 0 && file->physical == phy_last 1611 : /* files without offset are expected to have duplicates */ 1612 0 : && phy_last != FILEPHY_WITHOUT_OFFSET @@ -1686,10 +1686,10 @@ 1624 : } 1625 : 1626 : /* next node */ - 1627 101881 : node = node->next; + 1627 101879 : node = node->next; 1628 : 1629 : /* insert in the parity */ - 1630 101881 : scan_file_allocate(scan, file); + 1630 101879 : scan_file_allocate(scan, file); 1631 : } 1632 : 1633 : /* mark the disk without reliable physical offset if it has duplicates */ diff --git a/cov/cmdline/scrub.c.func-sort-c.html b/cov/cmdline/scrub.c.func-sort-c.html index 2a8c6b02..3037f874 100644 --- a/cov/cmdline/scrub.c.func-sort-c.html +++ b/cov/cmdline/scrub.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 @@ -61,11 +61,11 @@ scrub_parity_reader - 168180 + 168175 scrub_data_reader - 168176 + 168095 block_is_enabled diff --git a/cov/cmdline/scrub.c.func.html b/cov/cmdline/scrub.c.func.html index 9e501fea..ce569665 100644 --- a/cov/cmdline/scrub.c.func.html +++ b/cov/cmdline/scrub.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 @@ -69,11 +69,11 @@ scrub_data_reader - 168176 + 168095 scrub_parity_reader - 168180 + 168175 state_scrub diff --git a/cov/cmdline/scrub.c.gcov.html b/cov/cmdline/scrub.c.gcov.html index c01a6687..d1db3045 100644 --- a/cov/cmdline/scrub.c.gcov.html +++ b/cov/cmdline/scrub.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 @@ -164,45 +164,45 @@ 102 21730 : return 1; 103 : } 104 : - 105 168176 : static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 105 168095 : static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) 106 : { - 107 168176 : struct snapraid_io* io = worker->io; - 108 168176 : struct snapraid_state* state = io->state; - 109 168176 : struct snapraid_handle* handle = worker->handle; - 110 168176 : struct snapraid_disk* disk = handle->disk; - 111 168176 : block_off_t blockcur = task->position; - 112 168176 : unsigned char* buffer = task->buffer; + 107 168095 : struct snapraid_io* io = worker->io; + 108 168095 : struct snapraid_state* state = io->state; + 109 168095 : struct snapraid_handle* handle = worker->handle; + 110 168095 : struct snapraid_disk* disk = handle->disk; + 111 168095 : block_off_t blockcur = task->position; + 112 168095 : unsigned char* buffer = task->buffer; 113 : int ret; 114 : char esc_buffer[ESC_MAX]; 115 : 116 : /* if the disk position is not used */ - 117 168176 : if (!disk) { + 117 168095 : if (!disk) { 118 : /* use an empty block */ 119 0 : memset(buffer, 0, state->block_size); 120 0 : task->state = TASK_STATE_DONE; - 121 1585 : return; + 121 1584 : return; 122 : } 123 : 124 : /* get the block */ - 125 168176 : task->block = fs_par2block_find(disk, blockcur); + 125 168095 : task->block = fs_par2block_find(disk, blockcur); 126 : 127 : /* if the block is not used */ - 128 168151 : if (!block_has_file(task->block)) { + 128 168015 : if (!block_has_file(task->block)) { 129 : /* use an empty block */ - 130 1585 : memset(buffer, 0, state->block_size); - 131 1585 : task->state = TASK_STATE_DONE; - 132 1585 : return; + 130 1584 : memset(buffer, 0, state->block_size); + 131 1584 : task->state = TASK_STATE_DONE; + 132 1584 : return; 133 : } 134 : 135 : /* get the file of this block */ - 136 166552 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + 136 166341 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); 137 : 138 : /* if the file is different than the current one, close it */ - 139 166584 : if (handle->file != 0 && handle->file != task->file) { + 139 166530 : if (handle->file != 0 && handle->file != task->file) { 140 : /* keep a pointer at the file we are going to close for error reporting */ - 141 78061 : struct snapraid_file* report = handle->file; - 142 78061 : ret = handle_close(handle); - 143 78037 : if (ret == -1) { + 141 78070 : struct snapraid_file* report = handle->file; + 142 78070 : ret = handle_close(handle); + 143 77914 : if (ret == -1) { 144 : /* LCOV_EXCL_START */ 145 : /* This one is really an unexpected error, because we are only reading */ 146 : /* and closing a descriptor should never fail */ @@ -225,8 +225,8 @@ 163 : } 164 : } 165 : - 166 166560 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); - 167 166583 : if (ret == -1) { + 166 166374 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + 167 165524 : if (ret == -1) { 168 0 : if (errno == EIO) { 169 : /* LCOV_EXCL_START */ 170 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); @@ -244,9 +244,9 @@ 182 : } 183 : 184 : /* check if the file is changed */ - 185 166583 : if (handle->st.st_size != task->file->size - 186 166587 : || handle->st.st_mtime != task->file->mtime_sec - 187 160985 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec + 185 165524 : if (handle->st.st_size != task->file->size + 186 165815 : || handle->st.st_mtime != task->file->mtime_sec + 187 160635 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec 188 : /* don't check the inode to support filesystem without persistent inodes */ 189 : ) { 190 : /* report that the block and the file are not synced */ @@ -258,8 +258,8 @@ 196 : /* from the last sync, as we are expected to return errors if running */ 197 : /* in an unsynced array. This is just like the check command. */ 198 : - 199 166583 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); - 200 166507 : if (task->read_size == -1) { + 199 165524 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + 200 166073 : if (task->read_size == -1) { 201 0 : if (errno == EIO) { 202 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); 203 0 : log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos); @@ -273,24 +273,24 @@ 211 : } 212 : 213 : /* store the path of the opened file */ - 214 166507 : pathcpy(task->path, sizeof(task->path), handle->path); + 214 166073 : pathcpy(task->path, sizeof(task->path), handle->path); 215 : - 216 166554 : task->state = TASK_STATE_DONE; + 216 165226 : task->state = TASK_STATE_DONE; 217 : } 218 : - 219 168180 : static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 219 168175 : static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) 220 : { - 221 168180 : struct snapraid_io* io = worker->io; - 222 168180 : struct snapraid_state* state = io->state; - 223 168180 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; - 224 168180 : unsigned level = parity_handle->level; - 225 168180 : block_off_t blockcur = task->position; - 226 168180 : unsigned char* buffer = task->buffer; + 221 168175 : struct snapraid_io* io = worker->io; + 222 168175 : struct snapraid_state* state = io->state; + 223 168175 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; + 224 168175 : unsigned level = parity_handle->level; + 225 168175 : block_off_t blockcur = task->position; + 226 168175 : unsigned char* buffer = task->buffer; 227 : int ret; 228 : 229 : /* read the parity */ - 230 168180 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); - 231 168156 : if (ret == -1) { + 230 168175 : ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); + 231 168065 : if (ret == -1) { 232 0 : if (errno == EIO) { 233 0 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); 234 0 : log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur); @@ -303,7 +303,7 @@ 241 0 : return; 242 : } 243 : - 244 168156 : task->state = TASK_STATE_DONE; + 244 168065 : task->state = TASK_STATE_DONE; 245 : } 246 : 247 11 : static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax, struct snapraid_plan* plan, time_t now) @@ -535,14 +535,14 @@ 473 166607 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { 474 920 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); 475 : - 476 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff); + 476 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8); 477 : 478 : /* it's a silent error only if we are dealing with synced files */ 479 920 : if (file_is_unsynced) { 480 0 : ++error; 481 0 : error_on_this_block = 1; 482 : } else { - 483 920 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", task->path, file_pos, diff); + 483 920 : log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE*8); 484 920 : ++silent_error; 485 920 : silent_error_on_this_block = 1; 486 : } @@ -628,14 +628,14 @@ 566 162672 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { 567 0 : unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size); 568 : - 569 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", blockcur, lev_config_name(l), diff); + 569 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size*8); 570 : 571 : /* it's a silent error only if we are dealing with synced blocks */ 572 0 : if (block_is_unsynced) { 573 0 : ++error; 574 0 : error_on_this_block = 1; 575 : } else { - 576 0 : log_fatal("Data error in parity '%s' at position '%u', diff bits %u\n", lev_config_name(l), blockcur, diff); + 576 0 : log_fatal("Data error in parity '%s' at position '%u', diff bits %u/%u\n", lev_config_name(l), blockcur, diff, state->block_size*8); 577 0 : ++silent_error; 578 0 : silent_error_on_this_block = 1; 579 : } @@ -880,12 +880,12 @@ 818 : /* output the info map */ 819 11 : i = 0; 820 11 : log_tag("info_count:%u\n", count); - 821 45 : while (i < count) { - 822 23 : unsigned j = i + 1; - 823 56108 : while (j < count && timemap[i] == timemap[j]) - 824 56062 : ++j; - 825 23 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i); - 826 23 : i = j; + 821 44 : while (i < count) { + 822 22 : unsigned j = i + 1; + 823 56107 : while (j < count && timemap[i] == timemap[j]) + 824 56063 : ++j; + 825 22 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i); + 826 22 : i = j; 827 : } 828 : 829 : /* compute the limits from count/recentlimit */ diff --git a/cov/cmdline/search.c.func-sort-c.html b/cov/cmdline/search.c.func-sort-c.html index 031e5215..8a0c9c3b 100644 --- a/cov/cmdline/search.c.func-sort-c.html +++ b/cov/cmdline/search.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -61,19 +61,19 @@ search_file - 1843968 + 1843727 search_file_free - 1843968 + 1843727 state_search_fetch - 638616 + 639060 search_file_compare - 20133 + 20106 search_dir diff --git a/cov/cmdline/search.c.func.html b/cov/cmdline/search.c.func.html index 9631a1e2..4648f7f6 100644 --- a/cov/cmdline/search.c.func.html +++ b/cov/cmdline/search.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -65,15 +65,15 @@ search_file - 1843968 + 1843727 search_file_compare - 20133 + 20106 search_file_free - 1843968 + 1843727 state_search @@ -85,7 +85,7 @@ state_search_fetch - 638616 + 639060
diff --git a/cov/cmdline/search.c.gcov.html b/cov/cmdline/search.c.gcov.html index 3485994f..328ba9d5 100644 --- a/cov/cmdline/search.c.gcov.html +++ b/cov/cmdline/search.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -85,27 +85,27 @@ 23 : /****************************************************************************/ 24 : /* search */ 25 : - 26 1843968 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) + 26 1843727 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) 27 : { 28 : struct snapraid_search_file* file; 29 : tommy_uint32_t file_hash; 30 : - 31 1843968 : file = malloc_nofail(sizeof(struct snapraid_search_file)); - 32 1843968 : file->path = strdup_nofail(path); - 33 1843968 : file->size = size; - 34 1843968 : file->mtime_sec = mtime_sec; - 35 1843968 : file->mtime_nsec = mtime_nsec; + 31 1843727 : file = malloc_nofail(sizeof(struct snapraid_search_file)); + 32 1843727 : file->path = strdup_nofail(path); + 33 1843727 : file->size = size; + 34 1843727 : file->mtime_sec = mtime_sec; + 35 1843727 : file->mtime_nsec = mtime_nsec; 36 : - 37 1843968 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 37 1843727 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 38 : - 39 1843968 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); - 40 1843968 : } + 39 1843727 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); + 40 1843727 : } 41 : - 42 1843968 : void search_file_free(struct snapraid_search_file* file) + 42 1843727 : void search_file_free(struct snapraid_search_file* file) 43 : { - 44 1843968 : free(file->path); - 45 1843968 : free(file); - 46 1843968 : } + 44 1843727 : free(file->path); + 45 1843727 : free(file); + 46 1843727 : } 47 : 48 : struct search_file_compare_arg { 49 : const struct snapraid_state* state; @@ -117,29 +117,29 @@ 55 : int prevhash; 56 : }; 57 : - 58 20133 : int search_file_compare(const void* void_arg, const void* void_data) + 58 20106 : int search_file_compare(const void* void_arg, const void* void_data) 59 : { - 60 20133 : const struct search_file_compare_arg* arg = void_arg; - 61 20133 : const struct snapraid_search_file* file = void_data; - 62 20133 : const struct snapraid_state* state = arg->state; + 60 20106 : const struct search_file_compare_arg* arg = void_arg; + 61 20106 : const struct snapraid_search_file* file = void_data; + 62 20106 : const struct snapraid_state* state = arg->state; 63 : unsigned char buffer_hash[HASH_MAX]; - 64 20133 : const char* path = file->path; + 64 20106 : const char* path = file->path; 65 : int f; 66 : ssize_t ret; 67 : 68 : /* compare file info */ - 69 20133 : if (arg->file->size != file->size) + 69 20106 : if (arg->file->size != file->size) 70 0 : return -1; 71 : - 72 20133 : if (arg->file->mtime_sec != file->mtime_sec) + 72 20106 : if (arg->file->mtime_sec != file->mtime_sec) 73 0 : return -1; 74 : - 75 20133 : if (arg->file->mtime_nsec != file->mtime_nsec) + 75 20106 : if (arg->file->mtime_nsec != file->mtime_nsec) 76 0 : return -1; 77 : 78 : /* read the block and compare the hash */ - 79 20133 : f = open(path, O_RDONLY | O_BINARY); - 80 20133 : if (f == -1) { + 79 20106 : f = open(path, O_RDONLY | O_BINARY); + 80 20106 : if (f == -1) { 81 : /* LCOV_EXCL_START */ 82 : if (errno == ENOENT) { 83 : log_fatal("DANGER! file '%s' disappeared.\n", path); @@ -151,16 +151,16 @@ 89 : /* LCOV_EXCL_STOP */ 90 : } 91 : - 92 20133 : ret = pread(f, arg->buffer, arg->read_size, arg->offset); - 93 20133 : if (ret < 0 || (unsigned)ret != arg->read_size) { + 92 20106 : ret = pread(f, arg->buffer, arg->read_size, arg->offset); + 93 20106 : if (ret < 0 || (unsigned)ret != arg->read_size) { 94 : /* LCOV_EXCL_START */ 95 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); 96 : exit(EXIT_FAILURE); 97 : /* LCOV_EXCL_STOP */ 98 : } 99 : - 100 20133 : ret = close(f); - 101 20133 : if (ret != 0) { + 100 20106 : ret = close(f); + 101 20106 : if (ret != 0) { 102 : /* LCOV_EXCL_START */ 103 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); 104 : exit(EXIT_FAILURE); @@ -168,14 +168,14 @@ 106 : } 107 : 108 : /* compute the hash */ - 109 20133 : if (arg->prevhash) + 109 20106 : if (arg->prevhash) 110 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size); 111 : else - 112 20133 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); + 112 20106 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); 113 : 114 : /* check if the hash is matching */ - 115 20133 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0) - 116 2223 : return -1; + 115 20106 : if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0) + 116 2196 : return -1; 117 : 118 17910 : if (arg->read_size != state->block_size) { 119 : /* fill the remaining with 0 */ @@ -185,26 +185,26 @@ 123 17910 : return 0; 124 : } 125 : - 126 638616 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer) + 126 639060 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer) 127 : { 128 : struct snapraid_search_file* file; 129 : tommy_uint32_t file_hash; 130 : struct search_file_compare_arg arg; 131 : - 132 638616 : arg.state = state; - 133 638616 : arg.block = missing_block; - 134 638616 : arg.file = missing_file; - 135 638616 : arg.buffer = buffer; - 136 638616 : arg.offset = state->block_size * (data_off_t)missing_file_pos; - 137 638616 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); - 138 638616 : arg.prevhash = prevhash; + 132 639060 : arg.state = state; + 133 639060 : arg.block = missing_block; + 134 639060 : arg.file = missing_file; + 135 639060 : arg.buffer = buffer; + 136 639060 : arg.offset = state->block_size * (data_off_t)missing_file_pos; + 137 639060 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); + 138 639060 : arg.prevhash = prevhash; 139 : - 140 638616 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); + 140 639060 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); 141 : 142 : /* search in the hashtable, and also check if the data matches the hash */ - 143 638616 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); - 144 638616 : if (!file) - 145 620706 : return -1; + 143 639060 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); + 144 639060 : if (!file) + 145 621150 : return -1; 146 : 147 : /* if found, buffer is already set with data */ 148 17910 : return 0; @@ -226,40 +226,40 @@ 164 : char path_next[PATH_MAX]; 165 : char sub_next[PATH_MAX]; 166 : char out[PATH_MAX]; - 167 2040368 : struct snapraid_filter* reason = 0; + 167 2040206 : struct snapraid_filter* reason = 0; 168 : struct stat st; 169 : const char* name; 170 : struct dirent* dd; 171 : 172 : /* clear errno to detect erroneous conditions */ - 173 2040368 : errno = 0; - 174 2040368 : dd = readdir(d); - 175 2040368 : if (dd == 0 && errno != 0) { + 173 2040206 : errno = 0; + 174 2040206 : dd = readdir(d); + 175 2040206 : if (dd == 0 && errno != 0) { 176 : /* LCOV_EXCL_START */ 177 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); 178 : exit(EXIT_FAILURE); 179 : /* LCOV_EXCL_STOP */ 180 : } - 181 2040368 : if (dd == 0) { + 181 2040206 : if (dd == 0) { 182 2462 : break; /* finished */ 183 : } 184 : 185 : /* skip "." and ".." files */ - 186 2037906 : name = dd->d_name; - 187 2037906 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 186 2037744 : name = dd->d_name; + 187 2037744 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 188 9848 : continue; 189 : - 190 2032982 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 191 2032982 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + 190 2032820 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 191 2032820 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); 192 : 193 : /* exclude hidden files even before calling lstat() */ - 194 2032982 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { + 194 2032820 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { 195 0 : msg_verbose("Excluding hidden '%s'\n", path_next); 196 0 : continue; 197 : } 198 : 199 : /* exclude content files even before calling lstat() */ - 200 2032982 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { + 200 2032820 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { 201 0 : msg_verbose("Excluding content '%s'\n", path_next); 202 0 : continue; 203 : } @@ -283,7 +283,7 @@ 221 : } 222 : #else 223 : /* get lstat info about the file */ - 224 2032982 : if (lstat(path_next, &st) != 0) { + 224 2032820 : if (lstat(path_next, &st) != 0) { 225 : /* LCOV_EXCL_START */ 226 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); 227 : exit(EXIT_FAILURE); @@ -291,13 +291,13 @@ 229 : } 230 : #endif 231 : - 232 2032982 : if (S_ISREG(st.st_mode)) { - 233 1968671 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { - 234 1843968 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); + 232 2032820 : if (S_ISREG(st.st_mode)) { + 233 1968528 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 234 1843727 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); 235 : } else { - 236 124703 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 236 124801 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 237 : } - 238 64311 : } else if (S_ISDIR(st.st_mode)) { + 238 64292 : } else if (S_ISDIR(st.st_mode)) { 239 1781 : if (disk == 0 || filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) { 240 1781 : pathslash(path_next, sizeof(path_next)); 241 1781 : pathslash(sub_next, sizeof(sub_next)); @@ -306,7 +306,7 @@ 244 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 245 : } 246 : } - 247 2037906 : } + 247 2037744 : } 248 : 249 2462 : if (closedir(d) != 0) { 250 : /* LCOV_EXCL_START */ diff --git a/cov/cmdline/selftest.c.func-sort-c.html b/cov/cmdline/selftest.c.func-sort-c.html index 65f3fb9d..038fd913 100644 --- a/cov/cmdline/selftest.c.func-sort-c.html +++ b/cov/cmdline/selftest.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 diff --git a/cov/cmdline/selftest.c.func.html b/cov/cmdline/selftest.c.func.html index 560f0b0f..eb01ebf0 100644 --- a/cov/cmdline/selftest.c.func.html +++ b/cov/cmdline/selftest.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 diff --git a/cov/cmdline/selftest.c.gcov.html b/cov/cmdline/selftest.c.gcov.html index 0c7c4c26..932ed1cb 100644 --- a/cov/cmdline/selftest.c.gcov.html +++ b/cov/cmdline/selftest.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 8 diff --git a/cov/cmdline/snapraid.c.func-sort-c.html b/cov/cmdline/snapraid.c.func-sort-c.html index d95907bb..df97fc21 100644 --- a/cov/cmdline/snapraid.c.func-sort-c.html +++ b/cov/cmdline/snapraid.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 diff --git a/cov/cmdline/snapraid.c.func.html b/cov/cmdline/snapraid.c.func.html index 07ec904e..084a15d6 100644 --- a/cov/cmdline/snapraid.c.func.html +++ b/cov/cmdline/snapraid.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 diff --git a/cov/cmdline/snapraid.c.gcov.html b/cov/cmdline/snapraid.c.gcov.html index c3a2aff1..64d66e89 100644 --- a/cov/cmdline/snapraid.c.gcov.html +++ b/cov/cmdline/snapraid.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -526,7 +526,7 @@ 464 : /* Skip space holder file in parity disks */ 465 : { "test-skip-space-holder", 0, 0, OPT_TEST_SKIP_SPACE_HOLDER }, 466 : - 467 : /* Set the ourput format */ + 467 : /* Set the output format */ 468 : { "test-fmt", 1, 0, OPT_TEST_FORMAT }, 469 : 470 : { 0, 0, 0, 0 } diff --git a/cov/cmdline/speed.c.func-sort-c.html b/cov/cmdline/speed.c.func-sort-c.html index 70d26600..790d9412 100644 --- a/cov/cmdline/speed.c.func-sort-c.html +++ b/cov/cmdline/speed.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,7 +61,7 @@ diffgettimeofday - 1814 + 1849 speed diff --git a/cov/cmdline/speed.c.func.html b/cov/cmdline/speed.c.func.html index c6485ff8..4811a770 100644 --- a/cov/cmdline/speed.c.func.html +++ b/cov/cmdline/speed.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,7 +61,7 @@ diffgettimeofday - 1814 + 1849 speed diff --git a/cov/cmdline/speed.c.gcov.html b/cov/cmdline/speed.c.gcov.html index 24c2c5d8..26fc4c22 100644 --- a/cov/cmdline/speed.c.gcov.html +++ b/cov/cmdline/speed.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -100,14 +100,14 @@ 38 : /** 39 : * Differential us of two timeval. 40 : */ - 41 1814 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) + 41 1849 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) 42 : { 43 : int64_t d; 44 : - 45 1814 : d = 1000000LL * (stop->tv_sec - start->tv_sec); - 46 1814 : d += stop->tv_usec - start->tv_usec; + 45 1849 : d = 1000000LL * (stop->tv_sec - start->tv_sec); + 46 1849 : d += stop->tv_usec - start->tv_usec; 47 : - 48 1814 : return d; + 48 1849 : return d; 49 : } 50 : 51 : /** @@ -232,10 +232,10 @@ 170 4 : printf("%8s", "memset"); 171 4 : fflush(stdout); 172 : - 173 374 : SPEED_START { - 174 3330 : for (j = 0; j < nd; ++j) - 175 2960 : memset(v[j], j, size); - 176 370 : } SPEED_STOP + 173 375 : SPEED_START { + 174 3339 : for (j = 0; j < nd; ++j) + 175 2968 : memset(v[j], j, size); + 176 371 : } SPEED_STOP 177 : 178 4 : printf("%8" PRIu64, ds / dt); 179 4 : printf("\n"); @@ -260,10 +260,10 @@ 198 : 199 : #if HAVE_SSE42 200 4 : if (raid_cpu_has_crc32()) { - 201 58 : SPEED_START { - 202 504 : for (j = 0; j < nd; ++j) - 203 448 : side_effect += crc32c_x86(0, v[j], size); - 204 56 : } SPEED_STOP + 201 60 : SPEED_START { + 202 522 : for (j = 0; j < nd; ++j) + 203 464 : side_effect += crc32c_x86(0, v[j], size); + 204 58 : } SPEED_STOP 205 : 206 2 : printf("%8" PRIu64, ds / dt); 207 : } @@ -302,10 +302,10 @@ 240 4 : printf("%8" PRIu64, ds / dt); 241 4 : fflush(stdout); 242 : - 243 30 : SPEED_START { - 244 234 : for (j = 0; j < nd; ++j) - 245 208 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); - 246 26 : } SPEED_STOP + 243 32 : SPEED_START { + 244 252 : for (j = 0; j < nd; ++j) + 245 224 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); + 246 28 : } SPEED_STOP 247 : 248 4 : printf("%8" PRIu64, ds / dt); 249 4 : printf("\n"); @@ -341,16 +341,16 @@ 279 : 280 4 : printf("%8s", ""); 281 : - 282 114 : SPEED_START { - 283 110 : raid_gen1_int32(nd, size, v); - 284 110 : } SPEED_STOP + 282 119 : SPEED_START { + 283 115 : raid_gen1_int32(nd, size, v); + 284 115 : } SPEED_STOP 285 : 286 4 : printf("%8" PRIu64, ds / dt); 287 4 : fflush(stdout); 288 : - 289 181 : SPEED_START { - 290 177 : raid_gen1_int64(nd, size, v); - 291 177 : } SPEED_STOP + 289 184 : SPEED_START { + 290 180 : raid_gen1_int64(nd, size, v); + 291 180 : } SPEED_STOP 292 : 293 4 : printf("%8" PRIu64, ds / dt); 294 4 : fflush(stdout); @@ -358,9 +358,9 @@ 296 : #ifdef CONFIG_X86 297 : #ifdef CONFIG_SSE2 298 4 : if (raid_cpu_has_sse2()) { - 299 305 : SPEED_START { - 300 301 : raid_gen1_sse2(nd, size, v); - 301 301 : } SPEED_STOP + 299 309 : SPEED_START { + 300 305 : raid_gen1_sse2(nd, size, v); + 301 305 : } SPEED_STOP 302 : 303 4 : printf("%8" PRIu64, ds / dt); 304 4 : fflush(stdout); @@ -376,9 +376,9 @@ 314 : #endif 315 : #ifdef CONFIG_AVX2 316 4 : if (raid_cpu_has_avx2()) { - 317 13 : SPEED_START { - 318 12 : raid_gen1_avx2(nd, size, v); - 319 12 : } SPEED_STOP + 317 14 : SPEED_START { + 318 13 : raid_gen1_avx2(nd, size, v); + 319 13 : } SPEED_STOP 320 : 321 1 : printf("%8" PRIu64, ds / dt); 322 1 : fflush(stdout); @@ -394,16 +394,16 @@ 332 : 333 4 : printf("%8s", ""); 334 : - 335 47 : SPEED_START { - 336 43 : raid_gen2_int32(nd, size, v); - 337 43 : } SPEED_STOP + 335 48 : SPEED_START { + 336 44 : raid_gen2_int32(nd, size, v); + 337 44 : } SPEED_STOP 338 : 339 4 : printf("%8" PRIu64, ds / dt); 340 4 : fflush(stdout); 341 : - 342 47 : SPEED_START { - 343 43 : raid_gen2_int64(nd, size, v); - 344 43 : } SPEED_STOP + 342 48 : SPEED_START { + 343 44 : raid_gen2_int64(nd, size, v); + 344 44 : } SPEED_STOP 345 : 346 4 : printf("%8" PRIu64, ds / dt); 347 4 : fflush(stdout); @@ -411,9 +411,9 @@ 349 : #ifdef CONFIG_X86 350 : #ifdef CONFIG_SSE2 351 4 : if (raid_cpu_has_sse2()) { - 352 143 : SPEED_START { - 353 139 : raid_gen2_sse2(nd, size, v); - 354 139 : } SPEED_STOP + 352 150 : SPEED_START { + 353 146 : raid_gen2_sse2(nd, size, v); + 354 146 : } SPEED_STOP 355 : 356 4 : printf("%8" PRIu64, ds / dt); 357 4 : fflush(stdout); @@ -470,9 +470,9 @@ 408 : #ifdef CONFIG_X86 409 : #ifdef CONFIG_SSE2 410 4 : if (raid_cpu_has_sse2()) { - 411 87 : SPEED_START { - 412 83 : raid_genz_sse2(nd, size, v); - 413 83 : } SPEED_STOP + 411 91 : SPEED_START { + 412 87 : raid_genz_sse2(nd, size, v); + 413 87 : } SPEED_STOP 414 : 415 4 : printf("%8" PRIu64, ds / dt); 416 4 : fflush(stdout); @@ -537,9 +537,9 @@ 475 : #ifdef CONFIG_X86 476 : #ifdef CONFIG_SSSE3 477 4 : if (raid_cpu_has_ssse3()) { - 478 52 : SPEED_START { - 479 49 : raid_gen3_ssse3(nd, size, v); - 480 49 : } SPEED_STOP + 478 51 : SPEED_START { + 479 48 : raid_gen3_ssse3(nd, size, v); + 480 48 : } SPEED_STOP 481 : 482 3 : printf("%8" PRIu64, ds / dt); 483 3 : fflush(stdout); @@ -667,9 +667,9 @@ 605 : #ifdef CONFIG_X86 606 : #ifdef CONFIG_SSSE3 607 4 : if (raid_cpu_has_ssse3()) { - 608 25 : SPEED_START { - 609 22 : raid_gen5_ssse3(nd, size, v); - 610 22 : } SPEED_STOP + 608 27 : SPEED_START { + 609 24 : raid_gen5_ssse3(nd, size, v); + 610 24 : } SPEED_STOP 611 : 612 3 : printf("%8" PRIu64, ds / dt); 613 3 : fflush(stdout); @@ -707,9 +707,9 @@ 645 4 : printf("%8s", raid_gen6_tag()); 646 4 : fflush(stdout); 647 : - 648 9 : SPEED_START { - 649 5 : raid_gen6_int8(nd, size, v); - 650 5 : } SPEED_STOP + 648 12 : SPEED_START { + 649 8 : raid_gen6_int8(nd, size, v); + 650 8 : } SPEED_STOP 651 : 652 4 : printf("%8" PRIu64, ds / dt); 653 4 : fflush(stdout); diff --git a/cov/cmdline/spooky2.c.func-sort-c.html b/cov/cmdline/spooky2.c.func-sort-c.html index fd355ad2..76b5571f 100644 --- a/cov/cmdline/spooky2.c.func-sort-c.html +++ b/cov/cmdline/spooky2.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3861457 + 3861492
diff --git a/cov/cmdline/spooky2.c.func.html b/cov/cmdline/spooky2.c.func.html index 3dfa7070..b4ea5391 100644 --- a/cov/cmdline/spooky2.c.func.html +++ b/cov/cmdline/spooky2.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3861457 + 3861492
diff --git a/cov/cmdline/spooky2.c.gcov.html b/cov/cmdline/spooky2.c.gcov.html index 34fefeb4..1b9812b1 100644 --- a/cov/cmdline/spooky2.c.gcov.html +++ b/cov/cmdline/spooky2.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -170,7 +170,7 @@ 108 : // 109 : #define sc_const 0xdeadbeefdeadbeefLL 110 : - 111 3861457 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) + 111 3861492 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) 112 : { 113 : uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11; 114 : uint64_t buf[sc_numVars]; @@ -182,45 +182,45 @@ 120 : unsigned i; 121 : #endif 122 : - 123 3861457 : h9 = util_read64(seed + 0); - 124 3861457 : h10 = util_read64(seed + 8); + 123 3861492 : h9 = util_read64(seed + 0); + 124 3861492 : h10 = util_read64(seed + 8); 125 : - 126 3861457 : h0 = h3 = h6 = h9; - 127 3861457 : h1 = h4 = h7 = h10; - 128 3861457 : h2 = h5 = h8 = h11 = sc_const; + 126 3861492 : h0 = h3 = h6 = h9; + 127 3861492 : h1 = h4 = h7 = h10; + 128 3861492 : h2 = h5 = h8 = h11 = sc_const; 129 : - 130 3861457 : nblocks = size / sc_blockSize; - 131 3861457 : blocks = data; - 132 3861457 : end = blocks + nblocks * sc_numVars; + 130 3861492 : nblocks = size / sc_blockSize; + 131 3861492 : blocks = data; + 132 3861492 : end = blocks + nblocks * sc_numVars; 133 : 134 : /* body */ - 135 38698449 : while (blocks < end) { + 135 38741744 : while (blocks < end) { 136 : #if WORDS_BIGENDIAN 137 : for (i = 0; i < sc_numVars; ++i) 138 : buf[i] = util_swap64(blocks[i]); 139 : Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 140 : #else - 141 30975535 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 141 31018760 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 142 : #endif - 143 30975535 : blocks += sc_numVars; + 143 31018760 : blocks += sc_numVars; 144 : } 145 : 146 : /* tail */ - 147 3861457 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); - 148 3861457 : memcpy(buf, end, size_remainder); - 149 3861457 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); - 150 3861457 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; + 147 3861492 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); + 148 3861492 : memcpy(buf, end, size_remainder); + 149 3861492 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); + 150 3861492 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; 151 : 152 : /* finalization */ 153 : #if WORDS_BIGENDIAN 154 : for (i = 0; i < sc_numVars; ++i) 155 : buf[i] = util_swap64(buf[i]); 156 : #endif - 157 3861457 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 157 3861492 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 158 : - 159 3861457 : util_write64(digest + 0, h0); - 160 3861457 : util_write64(digest + 8, h1); - 161 3861457 : } + 159 3861492 : util_write64(digest + 0, h0); + 160 3861492 : util_write64(digest + 8, h1); + 161 3861492 : } 162 : diff --git a/cov/cmdline/state.c.func-sort-c.html b/cov/cmdline/state.c.func-sort-c.html index bd1dec5b..659e86c4 100644 --- a/cov/cmdline/state.c.func-sort-c.html +++ b/cov/cmdline/state.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1478 - 1612 - 91.7 % + 1450 + 1615 + 89.8 % Date: - 2016-11-21 + 2017-05-13 Functions: 45 @@ -60,51 +60,51 @@ Hit count Sort by hit count - fs_is_block_deleted + fs_is_block_deleted 4529621 - fs_info_is_required + fs_info_is_required 1547923 - state_progress - 1073436 + state_progress + 1073492 - state_usage_misc - 1063244 + state_usage_misc + 1063636 - state_usage_disk - 912519 + state_usage_disk + 912855 - state_usage_hash - 776953 + state_usage_hash + 777321 - state_usage_parity - 774185 + state_usage_parity + 774521 - fs_position_is_required + fs_position_is_required 756099 lev_config_name - 186623 + 186606 - state_usage_sched - 149863 + state_usage_sched + 149919 - state_usage_raid - 140402 + state_usage_raid + 140474 - find_disk_by_name + find_disk_by_name 7047 @@ -112,17 +112,17 @@ 6345 - state_verify_thread - 1012 + state_verify_thread + 1009 - state_progress_latest - 532 - - - state_fscheck + state_fscheck 499 + + state_progress_latest + 478 + validate_smartctl 366 @@ -144,19 +144,19 @@ 265 - state_read + state_read 261 - state_map + state_map 260 - state_read_content + state_read_content 254 - state_content_check + state_content_check 253 @@ -164,51 +164,51 @@ 244 - state_progress_end + state_progress_end 221 - state_progress_begin + state_progress_begin 221 - state_refresh + state_refresh 173 - state_write + state_write 151 - state_write_thread + state_write_thread 151 - state_write_content + state_write_content 151 - state_verify_content + state_verify_content 151 - state_rename_content + state_rename_content 151 - state_skip + state_skip 122 - state_filter + state_filter 122 - state_usage_waste + state_usage_waste 104 - state_usage_print + state_usage_print 96 @@ -216,31 +216,31 @@ 7 - state_progress_graph + find_disk_by_uuid 2 - find_disk_by_uuid - 2 - - - state_progress_restart + state_progress_graph 1 - generate_configuration + state_progress_restart 1 - decoding_error + generate_configuration 1 - state_progress_stop + decoding_error 1 - fs_position_clear_deleted + state_progress_stop + 1 + + + fs_position_clear_deleted 0 diff --git a/cov/cmdline/state.c.func.html b/cov/cmdline/state.c.func.html index a2f569e6..5cabaa59 100644 --- a/cov/cmdline/state.c.func.html +++ b/cov/cmdline/state.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1478 - 1612 - 91.7 % + 1450 + 1615 + 89.8 % Date: - 2016-11-21 + 2017-05-13 Functions: 45 @@ -60,40 +60,40 @@ Hit count Sort by hit count - decoding_error + decoding_error 1 - find_disk_by_name + find_disk_by_name 7047 - find_disk_by_uuid + find_disk_by_uuid 2 - fs_info_is_required + fs_info_is_required 1547923 - fs_is_block_deleted + fs_is_block_deleted 4529621 - fs_position_clear_deleted + fs_position_clear_deleted 0 - fs_position_is_required + fs_position_is_required 756099 - generate_configuration + generate_configuration 1 lev_config_name - 186623 + 186606 lev_config_scan @@ -116,7 +116,7 @@ 265 - state_content_check + state_content_check 253 @@ -124,11 +124,11 @@ 244 - state_filter + state_filter 122 - state_fscheck + state_fscheck 499 @@ -136,107 +136,107 @@ 267 - state_map + state_map 260 - state_progress - 1073436 + state_progress + 1073492 - state_progress_begin + state_progress_begin 221 - state_progress_end + state_progress_end 221 - state_progress_graph - 2 - - - state_progress_latest - 532 - - - state_progress_restart + state_progress_graph 1 - state_progress_stop + state_progress_latest + 478 + + + state_progress_restart 1 - state_read + state_progress_stop + 1 + + + state_read 261 - state_read_content + state_read_content 254 - state_refresh + state_refresh 173 - state_rename_content + state_rename_content 151 - state_skip + state_skip 122 - state_usage_disk - 912519 + state_usage_disk + 912855 - state_usage_hash - 776953 + state_usage_hash + 777321 - state_usage_misc - 1063244 + state_usage_misc + 1063636 - state_usage_parity - 774185 + state_usage_parity + 774521 - state_usage_print + state_usage_print 96 - state_usage_raid - 140402 + state_usage_raid + 140474 - state_usage_sched - 149863 + state_usage_sched + 149919 - state_usage_waste + state_usage_waste 104 - state_verify_content + state_verify_content 151 - state_verify_thread - 1012 + state_verify_thread + 1009 - state_write + state_write 151 - state_write_content + state_write_content 151 - state_write_thread + state_write_thread 151 diff --git a/cov/cmdline/state.c.gcov.html b/cov/cmdline/state.c.gcov.html index d4eda724..ed55a4e3 100644 --- a/cov/cmdline/state.c.gcov.html +++ b/cov/cmdline/state.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 1478 - 1612 - 91.7 % + 1450 + 1615 + 89.8 % Date: - 2016-11-21 + 2017-05-13 Functions: 45 @@ -125,13 +125,13 @@ 63 0 : return 0; 64 : } 65 : - 66 186623 : const char* lev_config_name(unsigned l) + 66 186606 : const char* lev_config_name(unsigned l) 67 : { - 68 186623 : switch (l) { - 69 86887 : case 0 : return "parity"; + 68 186606 : switch (l) { + 69 86864 : case 0 : return "parity"; 70 60630 : case 1 : return "2-parity"; - 71 9816 : case 2 : return "3-parity"; - 72 9791 : case 3 : return "4-parity"; + 71 9820 : case 2 : return "3-parity"; + 72 9793 : case 3 : return "4-parity"; 73 9766 : case 4 : return "5-parity"; 74 9733 : case 5 : return "6-parity"; 75 : } @@ -224,7 +224,7 @@ 162 1602 : state->parity[l].skip_access = 0; 163 1602 : state->parity[l].tick = 0; 164 1602 : state->parity[l].cached = 0; - 165 1602 : state->parity[l].is_excluded = 0; + 165 1602 : state->parity[l].is_excluded_by_filter = 0; 166 : } 167 267 : state->tick_io = 0; 168 267 : state->tick_misc = 0; @@ -683,4063 +683,4072 @@ 621 : /* LCOV_EXCL_STOP */ 622 : } 623 266 : state->block_size *= KIBI; - 624 5979 : } else if (strcmp(tag, "hash_size") == 0) { - 625 : uint32_t hash_size; - 626 : - 627 0 : ret = sgetu32(f, &hash_size); - 628 0 : if (ret < 0) { - 629 : /* LCOV_EXCL_START */ - 630 : log_fatal("Invalid 'hashsize' specification in '%s' at line %u\n", path, line); - 631 : exit(EXIT_FAILURE); - 632 : /* LCOV_EXCL_STOP */ - 633 : } - 634 0 : if (hash_size < 2) { - 635 : /* LCOV_EXCL_START */ - 636 : log_fatal("Too small 'hashsize' specification in '%s' at line %u\n", path, line); - 637 : exit(EXIT_FAILURE); - 638 : /* LCOV_EXCL_STOP */ - 639 : } - 640 0 : if (hash_size > HASH_MAX) { - 641 : /* LCOV_EXCL_START */ - 642 : log_fatal("Too big 'hashsize' specification in '%s' at line %u\n", path, line); - 643 : exit(EXIT_FAILURE); - 644 : /* LCOV_EXCL_STOP */ - 645 : } - 646 : /* check if it's a power of 2 */ - 647 0 : if ((hash_size & (hash_size - 1)) != 0) { - 648 : /* LCOV_EXCL_START */ - 649 : log_fatal("Not power of 2 'hashsize' specification in '%s' at line %u\n", path, line); - 650 : exit(EXIT_FAILURE); - 651 : /* LCOV_EXCL_STOP */ - 652 : } - 653 : - 654 0 : BLOCK_HASH_SIZE = hash_size; - 655 5979 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { - 656 : char device[PATH_MAX]; - 657 : char* split_map[SPLIT_MAX+1]; - 658 : unsigned split_mac; - 659 : char* slash; - 660 : uint64_t dev; - 661 : int skip_access; - 662 : - 663 1272 : if (state->parity[level].split_mac != 0) { - 664 : /* LCOV_EXCL_START */ - 665 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line); - 666 : exit(EXIT_FAILURE); - 667 : /* LCOV_EXCL_STOP */ - 668 : } - 669 : - 670 1272 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 671 1272 : if (ret < 0) { - 672 : /* LCOV_EXCL_START */ - 673 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - 674 : exit(EXIT_FAILURE); - 675 : /* LCOV_EXCL_STOP */ - 676 : } - 677 : - 678 1272 : if (!*buffer) { - 679 : /* LCOV_EXCL_START */ - 680 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line); - 681 : exit(EXIT_FAILURE); - 682 : /* LCOV_EXCL_STOP */ - 683 : } - 684 : - 685 1272 : split_mac = strsplit(split_map, SPLIT_MAX+1, buffer, ","); + 624 5979 : } else if (strcmp(tag, "hashsize") == 0 + 625 5979 : || strcmp(tag, "hash_size") == 0 /* v11.0 used incorretly this one, kept now for backward compatibility */ + 626 0 : ) { + 627 : uint32_t hash_size; + 628 : + 629 0 : ret = sgetu32(f, &hash_size); + 630 0 : if (ret < 0) { + 631 : /* LCOV_EXCL_START */ + 632 : log_fatal("Invalid 'hashsize' specification in '%s' at line %u\n", path, line); + 633 : exit(EXIT_FAILURE); + 634 : /* LCOV_EXCL_STOP */ + 635 : } + 636 0 : if (hash_size < 2) { + 637 : /* LCOV_EXCL_START */ + 638 : log_fatal("Too small 'hashsize' specification in '%s' at line %u\n", path, line); + 639 : exit(EXIT_FAILURE); + 640 : /* LCOV_EXCL_STOP */ + 641 : } + 642 0 : if (hash_size > HASH_MAX) { + 643 : /* LCOV_EXCL_START */ + 644 : log_fatal("Too big 'hashsize' specification in '%s' at line %u\n", path, line); + 645 : exit(EXIT_FAILURE); + 646 : /* LCOV_EXCL_STOP */ + 647 : } + 648 : /* check if it's a power of 2 */ + 649 0 : if ((hash_size & (hash_size - 1)) != 0) { + 650 : /* LCOV_EXCL_START */ + 651 : log_fatal("Not power of 2 'hashsize' specification in '%s' at line %u\n", path, line); + 652 : exit(EXIT_FAILURE); + 653 : /* LCOV_EXCL_STOP */ + 654 : } + 655 : + 656 0 : BLOCK_HASH_SIZE = hash_size; + 657 5979 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { + 658 : char device[PATH_MAX]; + 659 : char* split_map[SPLIT_MAX+1]; + 660 : unsigned split_mac; + 661 : char* slash; + 662 : uint64_t dev; + 663 : int skip_access; + 664 : + 665 1272 : if (state->parity[level].split_mac != 0) { + 666 : /* LCOV_EXCL_START */ + 667 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line); + 668 : exit(EXIT_FAILURE); + 669 : /* LCOV_EXCL_STOP */ + 670 : } + 671 : + 672 1272 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 673 1272 : if (ret < 0) { + 674 : /* LCOV_EXCL_START */ + 675 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); + 676 : exit(EXIT_FAILURE); + 677 : /* LCOV_EXCL_STOP */ + 678 : } + 679 : + 680 1272 : if (!*buffer) { + 681 : /* LCOV_EXCL_START */ + 682 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line); + 683 : exit(EXIT_FAILURE); + 684 : /* LCOV_EXCL_STOP */ + 685 : } 686 : - 687 1272 : if (split_mac > SPLIT_MAX) { - 688 : /* LCOV_EXCL_START */ - 689 : log_fatal("Too many files in '%s' specification in '%s' at line %u\n", tag, path, line); - 690 : exit(EXIT_FAILURE); - 691 : /* LCOV_EXCL_STOP */ - 692 : } - 693 : - 694 1272 : skip_access = 0; - 695 1272 : state->parity[level].split_mac = split_mac; - 696 6356 : for (s = 0; s < split_mac; ++s) { - 697 5085 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]); - 698 : - 699 5085 : if (!state->opt.skip_parity_access) { - 700 : struct stat st; - 701 : - 702 : /* get the device of the directory containing the parity file */ - 703 4349 : pathimport(device, sizeof(device), split_map[s]); - 704 4349 : slash = strrchr(device, '/'); - 705 4349 : if (slash) - 706 4349 : *slash = 0; - 707 : else - 708 0 : pathcpy(device, sizeof(device), "."); - 709 : - 710 4349 : if (stat(device, &st) == 0) { - 711 4344 : dev = st.st_dev; - 712 : } else { - 713 : /* if the disk can be skipped */ - 714 5 : if (state->opt.force_device) { - 715 : /* use a fake device, and mark the disk to be skipped */ - 716 4 : dev = 0; - 717 4 : skip_access = 1; - 718 4 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag); - 719 : } else { - 720 : /* LCOV_EXCL_START */ - 721 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line); - 722 : - 723 : /* in "fix" we allow to continue anyway */ - 724 : if (strcmp(state->command, "fix") == 0) { - 725 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 726 : } - 727 : exit(EXIT_FAILURE); - 728 : /* LCOV_EXCL_STOP */ - 729 : } - 730 : } - 731 : } else { - 732 : /* use a fake device */ - 733 736 : dev = 0; - 734 : } - 735 : - 736 5084 : state->parity[level].split_map[s].device = dev; - 737 : } - 738 : - 739 : /* store the global parity skip_access */ - 740 1271 : state->parity[level].skip_access = skip_access; - 741 : - 742 : /* adjust the level */ - 743 1271 : if (state->level < level + 1) - 744 1005 : state->level = level + 1; - 745 4707 : } else if (strcmp(tag, "share") == 0) { - 746 41 : if (*state->share) { - 747 : /* LCOV_EXCL_START */ - 748 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line); - 749 : exit(EXIT_FAILURE); - 750 : /* LCOV_EXCL_STOP */ - 751 : } - 752 : - 753 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 754 41 : if (ret < 0) { - 755 : /* LCOV_EXCL_START */ - 756 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line); - 757 : exit(EXIT_FAILURE); - 758 : /* LCOV_EXCL_STOP */ - 759 : } - 760 : - 761 41 : if (!*buffer) { - 762 : /* LCOV_EXCL_START */ - 763 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line); - 764 : exit(EXIT_FAILURE); - 765 : /* LCOV_EXCL_STOP */ - 766 : } - 767 : - 768 41 : pathimport(state->share, sizeof(state->share), buffer); - 769 4666 : } else if (strcmp(tag, "pool") == 0) { - 770 : struct stat st; - 771 : - 772 41 : if (*state->pool) { - 773 : /* LCOV_EXCL_START */ - 774 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line); - 775 : exit(EXIT_FAILURE); - 776 : /* LCOV_EXCL_STOP */ - 777 : } - 778 : - 779 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 780 41 : if (ret < 0) { - 781 : /* LCOV_EXCL_START */ - 782 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line); - 783 : exit(EXIT_FAILURE); - 784 : /* LCOV_EXCL_STOP */ - 785 : } - 786 : - 787 41 : if (!*buffer) { - 788 : /* LCOV_EXCL_START */ - 789 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line); - 790 : exit(EXIT_FAILURE); - 791 : /* LCOV_EXCL_STOP */ - 792 : } - 793 : - 794 41 : pathimport(state->pool, sizeof(state->pool), buffer); + 687 1272 : split_mac = strsplit(split_map, SPLIT_MAX+1, buffer, ","); + 688 : + 689 1272 : if (split_mac > SPLIT_MAX) { + 690 : /* LCOV_EXCL_START */ + 691 : log_fatal("Too many files in '%s' specification in '%s' at line %u\n", tag, path, line); + 692 : exit(EXIT_FAILURE); + 693 : /* LCOV_EXCL_STOP */ + 694 : } + 695 : + 696 1272 : skip_access = 0; + 697 1272 : state->parity[level].split_mac = split_mac; + 698 6356 : for (s = 0; s < split_mac; ++s) { + 699 5085 : pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]); + 700 : + 701 5085 : if (!state->opt.skip_parity_access) { + 702 : struct stat st; + 703 : + 704 : /* get the device of the directory containing the parity file */ + 705 4349 : pathimport(device, sizeof(device), split_map[s]); + 706 4349 : slash = strrchr(device, '/'); + 707 4349 : if (slash) + 708 4349 : *slash = 0; + 709 : else + 710 0 : pathcpy(device, sizeof(device), "."); + 711 : + 712 4349 : if (stat(device, &st) == 0) { + 713 4344 : dev = st.st_dev; + 714 : } else { + 715 : /* if the disk can be skipped */ + 716 5 : if (state->opt.force_device) { + 717 : /* use a fake device, and mark the disk to be skipped */ + 718 4 : dev = 0; + 719 4 : skip_access = 1; + 720 4 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag); + 721 : } else { + 722 : /* LCOV_EXCL_START */ + 723 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line); + 724 : + 725 : /* in "fix" we allow to continue anyway */ + 726 : if (strcmp(state->command, "fix") == 0) { + 727 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 728 : } + 729 : exit(EXIT_FAILURE); + 730 : /* LCOV_EXCL_STOP */ + 731 : } + 732 : } + 733 : } else { + 734 : /* use a fake device */ + 735 736 : dev = 0; + 736 : } + 737 : + 738 5084 : state->parity[level].split_map[s].device = dev; + 739 : } + 740 : + 741 : /* store the global parity skip_access */ + 742 1271 : state->parity[level].skip_access = skip_access; + 743 : + 744 : /* adjust the level */ + 745 1271 : if (state->level < level + 1) + 746 1005 : state->level = level + 1; + 747 4707 : } else if (strcmp(tag, "share") == 0) { + 748 41 : if (*state->share) { + 749 : /* LCOV_EXCL_START */ + 750 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line); + 751 : exit(EXIT_FAILURE); + 752 : /* LCOV_EXCL_STOP */ + 753 : } + 754 : + 755 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 756 41 : if (ret < 0) { + 757 : /* LCOV_EXCL_START */ + 758 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line); + 759 : exit(EXIT_FAILURE); + 760 : /* LCOV_EXCL_STOP */ + 761 : } + 762 : + 763 41 : if (!*buffer) { + 764 : /* LCOV_EXCL_START */ + 765 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line); + 766 : exit(EXIT_FAILURE); + 767 : /* LCOV_EXCL_STOP */ + 768 : } + 769 : + 770 41 : pathimport(state->share, sizeof(state->share), buffer); + 771 4666 : } else if (strcmp(tag, "pool") == 0) { + 772 : struct stat st; + 773 : + 774 41 : if (*state->pool) { + 775 : /* LCOV_EXCL_START */ + 776 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line); + 777 : exit(EXIT_FAILURE); + 778 : /* LCOV_EXCL_STOP */ + 779 : } + 780 : + 781 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 782 41 : if (ret < 0) { + 783 : /* LCOV_EXCL_START */ + 784 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line); + 785 : exit(EXIT_FAILURE); + 786 : /* LCOV_EXCL_STOP */ + 787 : } + 788 : + 789 41 : if (!*buffer) { + 790 : /* LCOV_EXCL_START */ + 791 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line); + 792 : exit(EXIT_FAILURE); + 793 : /* LCOV_EXCL_STOP */ + 794 : } 795 : - 796 : /* get the device of the directory containing the pool tree */ - 797 41 : if (stat(buffer, &st) != 0) { - 798 : /* LCOV_EXCL_START */ - 799 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); - 800 : exit(EXIT_FAILURE); - 801 : /* LCOV_EXCL_STOP */ - 802 : } - 803 : - 804 41 : state->pool_device = st.st_dev; - 805 4625 : } else if (strcmp(tag, "content") == 0) { - 806 : struct snapraid_content* content; - 807 : char device[PATH_MAX]; - 808 : char* slash; - 809 : struct stat st; - 810 : uint64_t dev; - 811 : - 812 1531 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 813 1531 : if (ret < 0) { - 814 : /* LCOV_EXCL_START */ - 815 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line); - 816 : exit(EXIT_FAILURE); - 817 : /* LCOV_EXCL_STOP */ - 818 : } - 819 : - 820 1531 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { - 821 : /* LCOV_EXCL_START */ - 822 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); - 823 : exit(EXIT_FAILURE); - 824 : /* LCOV_EXCL_STOP */ - 825 : } - 826 : - 827 1531 : if (!*buffer) { - 828 : /* LCOV_EXCL_START */ - 829 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line); - 830 : exit(EXIT_FAILURE); - 831 : /* LCOV_EXCL_STOP */ - 832 : } - 833 : - 834 : /* check if the content file is already specified */ - 835 5724 : for (i = state->contentlist; i != 0; i = i->next) { - 836 4193 : content = i->data; - 837 4193 : if (pathcmp(content->content, buffer) == 0) - 838 0 : break; - 839 : } - 840 1531 : if (i) { - 841 : /* LCOV_EXCL_START */ - 842 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line); - 843 : exit(EXIT_FAILURE); - 844 : /* LCOV_EXCL_STOP */ - 845 : } - 846 : - 847 : /* get the device of the directory containing the content file */ - 848 1531 : pathimport(device, sizeof(device), buffer); - 849 1531 : slash = strrchr(device, '/'); - 850 1531 : if (slash) - 851 1531 : *slash = 0; - 852 : else - 853 0 : pathcpy(device, sizeof(device), "."); - 854 1531 : if (stat(device, &st) == 0) { - 855 1530 : dev = st.st_dev; - 856 : } else { - 857 1 : if (state->opt.skip_content_access) { - 858 : /* use a fake device */ - 859 1 : dev = 0; - 860 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer); - 861 : } else { - 862 : /* LCOV_EXCL_START */ - 863 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line); - 864 : exit(EXIT_FAILURE); - 865 : /* LCOV_EXCL_STOP */ - 866 : } - 867 : } - 868 : - 869 : /* set the lock file at the first accessible content file */ - 870 1531 : if (state->lockfile[0] == 0 && dev != 0) { - 871 265 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); - 872 265 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); - 873 : } - 874 : - 875 1531 : content = content_alloc(buffer, dev); + 796 41 : pathimport(state->pool, sizeof(state->pool), buffer); + 797 : + 798 : /* get the device of the directory containing the pool tree */ + 799 41 : if (stat(buffer, &st) != 0) { + 800 : /* LCOV_EXCL_START */ + 801 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); + 802 : exit(EXIT_FAILURE); + 803 : /* LCOV_EXCL_STOP */ + 804 : } + 805 : + 806 41 : state->pool_device = st.st_dev; + 807 4625 : } else if (strcmp(tag, "content") == 0) { + 808 : struct snapraid_content* content; + 809 : char device[PATH_MAX]; + 810 : char* slash; + 811 : struct stat st; + 812 : uint64_t dev; + 813 : + 814 1531 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 815 1531 : if (ret < 0) { + 816 : /* LCOV_EXCL_START */ + 817 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line); + 818 : exit(EXIT_FAILURE); + 819 : /* LCOV_EXCL_STOP */ + 820 : } + 821 : + 822 1531 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { + 823 : /* LCOV_EXCL_START */ + 824 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); + 825 : exit(EXIT_FAILURE); + 826 : /* LCOV_EXCL_STOP */ + 827 : } + 828 : + 829 1531 : if (!*buffer) { + 830 : /* LCOV_EXCL_START */ + 831 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line); + 832 : exit(EXIT_FAILURE); + 833 : /* LCOV_EXCL_STOP */ + 834 : } + 835 : + 836 : /* check if the content file is already specified */ + 837 5724 : for (i = state->contentlist; i != 0; i = i->next) { + 838 4193 : content = i->data; + 839 4193 : if (pathcmp(content->content, buffer) == 0) + 840 0 : break; + 841 : } + 842 1531 : if (i) { + 843 : /* LCOV_EXCL_START */ + 844 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line); + 845 : exit(EXIT_FAILURE); + 846 : /* LCOV_EXCL_STOP */ + 847 : } + 848 : + 849 : /* get the device of the directory containing the content file */ + 850 1531 : pathimport(device, sizeof(device), buffer); + 851 1531 : slash = strrchr(device, '/'); + 852 1531 : if (slash) + 853 1531 : *slash = 0; + 854 : else + 855 0 : pathcpy(device, sizeof(device), "."); + 856 1531 : if (stat(device, &st) == 0) { + 857 1530 : dev = st.st_dev; + 858 : } else { + 859 1 : if (state->opt.skip_content_access) { + 860 : /* use a fake device */ + 861 1 : dev = 0; + 862 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer); + 863 : } else { + 864 : /* LCOV_EXCL_START */ + 865 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line); + 866 : exit(EXIT_FAILURE); + 867 : /* LCOV_EXCL_STOP */ + 868 : } + 869 : } + 870 : + 871 : /* set the lock file at the first accessible content file */ + 872 1531 : if (state->lockfile[0] == 0 && dev != 0) { + 873 265 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); + 874 265 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); + 875 : } 876 : - 877 1531 : tommy_list_insert_tail(&state->contentlist, &content->node, content); - 878 4679 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) { - 879 : /* "disk" is the deprecated name up to SnapRAID 9.x */ - 880 : char dir[PATH_MAX]; - 881 : char device[PATH_MAX]; - 882 : char uuid[UUID_MAX]; - 883 : struct snapraid_disk* disk; - 884 : uint64_t dev; - 885 : int skip_access; - 886 : - 887 1585 : ret = sgettok(f, buffer, sizeof(buffer)); - 888 1585 : if (ret < 0) { - 889 : /* LCOV_EXCL_START */ - 890 : log_fatal("Invalid 'data' name specification in '%s' at line %u\n", path, line); - 891 : exit(EXIT_FAILURE); - 892 : /* LCOV_EXCL_STOP */ - 893 : } - 894 : - 895 1585 : if (!*buffer) { - 896 : /* LCOV_EXCL_START */ - 897 : log_fatal("Empty 'data' name specification in '%s' at line %u\n", path, line); - 898 : exit(EXIT_FAILURE); - 899 : /* LCOV_EXCL_STOP */ - 900 : } - 901 : - 902 1585 : sgetspace(f); + 877 1531 : content = content_alloc(buffer, dev); + 878 : + 879 1531 : tommy_list_insert_tail(&state->contentlist, &content->node, content); + 880 4679 : } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) { + 881 : /* "disk" is the deprecated name up to SnapRAID 9.x */ + 882 : char dir[PATH_MAX]; + 883 : char device[PATH_MAX]; + 884 : char uuid[UUID_MAX]; + 885 : struct snapraid_disk* disk; + 886 : uint64_t dev; + 887 : int skip_access; + 888 : + 889 1585 : ret = sgettok(f, buffer, sizeof(buffer)); + 890 1585 : if (ret < 0) { + 891 : /* LCOV_EXCL_START */ + 892 : log_fatal("Invalid 'data' name specification in '%s' at line %u\n", path, line); + 893 : exit(EXIT_FAILURE); + 894 : /* LCOV_EXCL_STOP */ + 895 : } + 896 : + 897 1585 : if (!*buffer) { + 898 : /* LCOV_EXCL_START */ + 899 : log_fatal("Empty 'data' name specification in '%s' at line %u\n", path, line); + 900 : exit(EXIT_FAILURE); + 901 : /* LCOV_EXCL_STOP */ + 902 : } 903 : - 904 1585 : ret = sgetlasttok(f, dir, sizeof(dir)); - 905 1585 : if (ret < 0) { - 906 : /* LCOV_EXCL_START */ - 907 : log_fatal("Invalid 'data' dir specification in '%s' at line %u\n", path, line); - 908 : exit(EXIT_FAILURE); - 909 : /* LCOV_EXCL_STOP */ - 910 : } - 911 : - 912 1585 : if (!*dir) { - 913 : /* LCOV_EXCL_START */ - 914 : log_fatal("Empty 'data' dir specification in '%s' at line %u\n", path, line); - 915 : exit(EXIT_FAILURE); - 916 : /* LCOV_EXCL_STOP */ - 917 : } - 918 : - 919 : /* get the device of the dir */ - 920 1585 : pathimport(device, sizeof(device), dir); - 921 : - 922 : /* check if the disk name already exists */ - 923 5535 : for (i = state->disklist; i != 0; i = i->next) { - 924 3950 : disk = i->data; - 925 3950 : if (strcmp(disk->name, buffer) == 0) - 926 0 : break; - 927 : } - 928 1585 : if (i) { - 929 : /* LCOV_EXCL_START */ - 930 : log_fatal("Duplicate 'data' name '%s' at line %u\n", buffer, line); - 931 : exit(EXIT_FAILURE); - 932 : /* LCOV_EXCL_STOP */ - 933 : } - 934 : - 935 : /* if the disk has to be present */ - 936 1585 : skip_access = 0; - 937 1585 : if (!state->opt.skip_disk_access) { - 938 : struct stat st; - 939 : - 940 1423 : if (stat(device, &st) == 0) { - 941 1422 : dev = st.st_dev; - 942 : - 943 : /* read the uuid, if unsupported use an empty one */ - 944 1422 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) { - 945 0 : *uuid = 0; - 946 : } - 947 : - 948 : /* fake a different UUID when testing */ - 949 1422 : if (state->opt.fake_uuid) { - 950 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid); - 951 2 : --state->opt.fake_uuid; - 952 : } - 953 : } else { - 954 : /* if the disk can be skipped */ - 955 1 : if (state->opt.force_device) { - 956 : /* use a fake device, and mark the disk to be skipped */ - 957 1 : dev = 0; - 958 1 : *uuid = 0; - 959 1 : skip_access = 1; - 960 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer); - 961 : } else { - 962 : /* LCOV_EXCL_START */ - 963 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line); - 964 : - 965 : /* in "fix" we allow to continue anyway */ - 966 : if (strcmp(state->command, "fix") == 0) { - 967 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 968 : } - 969 : exit(EXIT_FAILURE); - 970 : /* LCOV_EXCL_STOP */ - 971 : } - 972 : } - 973 : } else { - 974 : /* use a fake device */ - 975 162 : dev = 0; - 976 162 : *uuid = 0; - 977 : } - 978 : - 979 1585 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access); + 904 1585 : sgetspace(f); + 905 : + 906 1585 : ret = sgetlasttok(f, dir, sizeof(dir)); + 907 1585 : if (ret < 0) { + 908 : /* LCOV_EXCL_START */ + 909 : log_fatal("Invalid 'data' dir specification in '%s' at line %u\n", path, line); + 910 : exit(EXIT_FAILURE); + 911 : /* LCOV_EXCL_STOP */ + 912 : } + 913 : + 914 1585 : if (!*dir) { + 915 : /* LCOV_EXCL_START */ + 916 : log_fatal("Empty 'data' dir specification in '%s' at line %u\n", path, line); + 917 : exit(EXIT_FAILURE); + 918 : /* LCOV_EXCL_STOP */ + 919 : } + 920 : + 921 : /* get the device of the dir */ + 922 1585 : pathimport(device, sizeof(device), dir); + 923 : + 924 : /* check if the disk name already exists */ + 925 5535 : for (i = state->disklist; i != 0; i = i->next) { + 926 3950 : disk = i->data; + 927 3950 : if (strcmp(disk->name, buffer) == 0) + 928 0 : break; + 929 : } + 930 1585 : if (i) { + 931 : /* LCOV_EXCL_START */ + 932 : log_fatal("Duplicate 'data' name '%s' at line %u\n", buffer, line); + 933 : exit(EXIT_FAILURE); + 934 : /* LCOV_EXCL_STOP */ + 935 : } + 936 : + 937 : /* if the disk has to be present */ + 938 1585 : skip_access = 0; + 939 1585 : if (!state->opt.skip_disk_access) { + 940 : struct stat st; + 941 : + 942 1423 : if (stat(device, &st) == 0) { + 943 1422 : dev = st.st_dev; + 944 : + 945 : /* read the uuid, if unsupported use an empty one */ + 946 1422 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) { + 947 0 : *uuid = 0; + 948 : } + 949 : + 950 : /* fake a different UUID when testing */ + 951 1422 : if (state->opt.fake_uuid) { + 952 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid); + 953 2 : --state->opt.fake_uuid; + 954 : } + 955 : } else { + 956 : /* if the disk can be skipped */ + 957 1 : if (state->opt.force_device) { + 958 : /* use a fake device, and mark the disk to be skipped */ + 959 1 : dev = 0; + 960 1 : *uuid = 0; + 961 1 : skip_access = 1; + 962 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer); + 963 : } else { + 964 : /* LCOV_EXCL_START */ + 965 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line); + 966 : + 967 : /* in "fix" we allow to continue anyway */ + 968 : if (strcmp(state->command, "fix") == 0) { + 969 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 970 : } + 971 : exit(EXIT_FAILURE); + 972 : /* LCOV_EXCL_STOP */ + 973 : } + 974 : } + 975 : } else { + 976 : /* use a fake device */ + 977 162 : dev = 0; + 978 162 : *uuid = 0; + 979 : } 980 : - 981 1585 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); - 982 1509 : } else if (strcmp(tag, "smartctl") == 0) { - 983 : char custom[PATH_MAX]; - 984 : - 985 366 : ret = sgettok(f, buffer, sizeof(buffer)); - 986 366 : if (ret < 0) { - 987 : /* LCOV_EXCL_START */ - 988 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); - 989 : exit(EXIT_FAILURE); - 990 : /* LCOV_EXCL_STOP */ - 991 : } - 992 : - 993 366 : if (!*buffer) { - 994 : /* LCOV_EXCL_START */ - 995 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); - 996 : exit(EXIT_FAILURE); - 997 : /* LCOV_EXCL_STOP */ - 998 : } - 999 : - 1000 366 : sgetspace(f); + 981 1585 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access); + 982 : + 983 1585 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 984 1509 : } else if (strcmp(tag, "smartctl") == 0) { + 985 : char custom[PATH_MAX]; + 986 : + 987 366 : ret = sgettok(f, buffer, sizeof(buffer)); + 988 366 : if (ret < 0) { + 989 : /* LCOV_EXCL_START */ + 990 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); + 991 : exit(EXIT_FAILURE); + 992 : /* LCOV_EXCL_STOP */ + 993 : } + 994 : + 995 366 : if (!*buffer) { + 996 : /* LCOV_EXCL_START */ + 997 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); + 998 : exit(EXIT_FAILURE); + 999 : /* LCOV_EXCL_STOP */ + 1000 : } 1001 : - 1002 366 : ret = sgetlasttok(f, custom, sizeof(custom)); - 1003 366 : if (ret < 0) { - 1004 : /* LCOV_EXCL_START */ - 1005 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); - 1006 : exit(EXIT_FAILURE); - 1007 : /* LCOV_EXCL_STOP */ - 1008 : } - 1009 : - 1010 366 : if (!*custom) { - 1011 : /* LCOV_EXCL_START */ - 1012 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); - 1013 : exit(EXIT_FAILURE); - 1014 : /* LCOV_EXCL_STOP */ - 1015 : } - 1016 : - 1017 366 : if (validate_smartctl(custom) != 0) { - 1018 : /* LCOV_EXCL_START */ - 1019 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); - 1020 : exit(EXIT_FAILURE); - 1021 : /* LCOV_EXCL_STOP */ - 1022 : } - 1023 : - 1024 : /* search for parity */ - 1025 366 : if (lev_config_scan(buffer, &level, 0) == 0) { - 1026 183 : if (state->parity[level].smartctl[0] != 0) { - 1027 : /* LCOV_EXCL_START */ - 1028 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line); - 1029 : exit(EXIT_FAILURE); - 1030 : /* LCOV_EXCL_STOP */ - 1031 : } - 1032 : - 1033 183 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); - 1034 : } else { - 1035 : struct snapraid_disk* disk; - 1036 : - 1037 : /* search the disk */ - 1038 183 : disk = 0; - 1039 183 : for (i = state->disklist; i != 0; i = i->next) { - 1040 183 : disk = i->data; - 1041 183 : if (strcmp(disk->name, buffer) == 0) - 1042 183 : break; - 1043 : } - 1044 183 : if (!disk) { - 1045 : /* LCOV_EXCL_START */ - 1046 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line); - 1047 : exit(EXIT_FAILURE); - 1048 : /* LCOV_EXCL_STOP */ - 1049 : } - 1050 183 : if (disk->smartctl[0] != 0) { - 1051 : /* LCOV_EXCL_START */ - 1052 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); - 1053 : exit(EXIT_FAILURE); - 1054 : /* LCOV_EXCL_STOP */ - 1055 : } - 1056 : - 1057 183 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); - 1058 : } - 1059 1143 : } else if (strcmp(tag, "nohidden") == 0) { - 1060 0 : state->filter_hidden = 1; - 1061 1143 : } else if (strcmp(tag, "exclude") == 0) { - 1062 : struct snapraid_filter* filter; - 1063 : - 1064 265 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1065 265 : if (ret < 0) { - 1066 : /* LCOV_EXCL_START */ - 1067 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line); - 1068 : exit(EXIT_FAILURE); - 1069 : /* LCOV_EXCL_STOP */ - 1070 : } - 1071 : - 1072 265 : if (!*buffer) { - 1073 : /* LCOV_EXCL_START */ - 1074 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line); - 1075 : exit(EXIT_FAILURE); - 1076 : /* LCOV_EXCL_STOP */ - 1077 : } - 1078 : - 1079 265 : filter = filter_alloc_file(-1, buffer); - 1080 265 : if (!filter) { - 1081 : /* LCOV_EXCL_START */ - 1082 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); - 1083 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); - 1084 : exit(EXIT_FAILURE); - 1085 : /* LCOV_EXCL_STOP */ - 1086 : } - 1087 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 1088 878 : } else if (strcmp(tag, "include") == 0) { - 1089 : struct snapraid_filter* filter; - 1090 : - 1091 265 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1092 265 : if (ret < 0) { - 1093 : /* LCOV_EXCL_START */ - 1094 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line); - 1095 : exit(EXIT_FAILURE); - 1096 : /* LCOV_EXCL_STOP */ - 1097 : } - 1098 : - 1099 265 : if (!*buffer) { - 1100 : /* LCOV_EXCL_START */ - 1101 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line); - 1102 : exit(EXIT_FAILURE); - 1103 : /* LCOV_EXCL_STOP */ - 1104 : } - 1105 : - 1106 265 : filter = filter_alloc_file(1, buffer); - 1107 265 : if (!filter) { - 1108 : /* LCOV_EXCL_START */ - 1109 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line); - 1110 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); - 1111 : exit(EXIT_FAILURE); - 1112 : /* LCOV_EXCL_STOP */ - 1113 : } - 1114 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 1115 613 : } else if (strcmp(tag, "autosave") == 0) { - 1116 : char* e; - 1117 : - 1118 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1119 41 : if (ret < 0) { - 1120 : /* LCOV_EXCL_START */ - 1121 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); - 1122 : exit(EXIT_FAILURE); - 1123 : /* LCOV_EXCL_STOP */ - 1124 : } - 1125 : - 1126 41 : if (!*buffer) { - 1127 : /* LCOV_EXCL_START */ - 1128 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line); - 1129 : exit(EXIT_FAILURE); - 1130 : /* LCOV_EXCL_STOP */ - 1131 : } - 1132 : - 1133 41 : state->autosave = strtoul(buffer, &e, 0); + 1002 366 : sgetspace(f); + 1003 : + 1004 366 : ret = sgetlasttok(f, custom, sizeof(custom)); + 1005 366 : if (ret < 0) { + 1006 : /* LCOV_EXCL_START */ + 1007 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + 1008 : exit(EXIT_FAILURE); + 1009 : /* LCOV_EXCL_STOP */ + 1010 : } + 1011 : + 1012 366 : if (!*custom) { + 1013 : /* LCOV_EXCL_START */ + 1014 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); + 1015 : exit(EXIT_FAILURE); + 1016 : /* LCOV_EXCL_STOP */ + 1017 : } + 1018 : + 1019 366 : if (validate_smartctl(custom) != 0) { + 1020 : /* LCOV_EXCL_START */ + 1021 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + 1022 : exit(EXIT_FAILURE); + 1023 : /* LCOV_EXCL_STOP */ + 1024 : } + 1025 : + 1026 : /* search for parity */ + 1027 366 : if (lev_config_scan(buffer, &level, 0) == 0) { + 1028 183 : if (state->parity[level].smartctl[0] != 0) { + 1029 : /* LCOV_EXCL_START */ + 1030 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line); + 1031 : exit(EXIT_FAILURE); + 1032 : /* LCOV_EXCL_STOP */ + 1033 : } + 1034 : + 1035 183 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); + 1036 : } else { + 1037 : struct snapraid_disk* disk; + 1038 : + 1039 : /* search the disk */ + 1040 183 : disk = 0; + 1041 183 : for (i = state->disklist; i != 0; i = i->next) { + 1042 183 : disk = i->data; + 1043 183 : if (strcmp(disk->name, buffer) == 0) + 1044 183 : break; + 1045 : } + 1046 183 : if (!disk) { + 1047 : /* LCOV_EXCL_START */ + 1048 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line); + 1049 : exit(EXIT_FAILURE); + 1050 : /* LCOV_EXCL_STOP */ + 1051 : } + 1052 183 : if (disk->smartctl[0] != 0) { + 1053 : /* LCOV_EXCL_START */ + 1054 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); + 1055 : exit(EXIT_FAILURE); + 1056 : /* LCOV_EXCL_STOP */ + 1057 : } + 1058 : + 1059 183 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); + 1060 : } + 1061 1143 : } else if (strcmp(tag, "nohidden") == 0) { + 1062 0 : state->filter_hidden = 1; + 1063 1143 : } else if (strcmp(tag, "exclude") == 0) { + 1064 : struct snapraid_filter* filter; + 1065 : + 1066 265 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1067 265 : if (ret < 0) { + 1068 : /* LCOV_EXCL_START */ + 1069 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line); + 1070 : exit(EXIT_FAILURE); + 1071 : /* LCOV_EXCL_STOP */ + 1072 : } + 1073 : + 1074 265 : if (!*buffer) { + 1075 : /* LCOV_EXCL_START */ + 1076 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line); + 1077 : exit(EXIT_FAILURE); + 1078 : /* LCOV_EXCL_STOP */ + 1079 : } + 1080 : + 1081 265 : filter = filter_alloc_file(-1, buffer); + 1082 265 : if (!filter) { + 1083 : /* LCOV_EXCL_START */ + 1084 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); + 1085 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + 1086 : exit(EXIT_FAILURE); + 1087 : /* LCOV_EXCL_STOP */ + 1088 : } + 1089 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + 1090 878 : } else if (strcmp(tag, "include") == 0) { + 1091 : struct snapraid_filter* filter; + 1092 : + 1093 265 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1094 265 : if (ret < 0) { + 1095 : /* LCOV_EXCL_START */ + 1096 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line); + 1097 : exit(EXIT_FAILURE); + 1098 : /* LCOV_EXCL_STOP */ + 1099 : } + 1100 : + 1101 265 : if (!*buffer) { + 1102 : /* LCOV_EXCL_START */ + 1103 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line); + 1104 : exit(EXIT_FAILURE); + 1105 : /* LCOV_EXCL_STOP */ + 1106 : } + 1107 : + 1108 265 : filter = filter_alloc_file(1, buffer); + 1109 265 : if (!filter) { + 1110 : /* LCOV_EXCL_START */ + 1111 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line); + 1112 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + 1113 : exit(EXIT_FAILURE); + 1114 : /* LCOV_EXCL_STOP */ + 1115 : } + 1116 265 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + 1117 613 : } else if (strcmp(tag, "autosave") == 0) { + 1118 : char* e; + 1119 : + 1120 41 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1121 41 : if (ret < 0) { + 1122 : /* LCOV_EXCL_START */ + 1123 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + 1124 : exit(EXIT_FAILURE); + 1125 : /* LCOV_EXCL_STOP */ + 1126 : } + 1127 : + 1128 41 : if (!*buffer) { + 1129 : /* LCOV_EXCL_START */ + 1130 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line); + 1131 : exit(EXIT_FAILURE); + 1132 : /* LCOV_EXCL_STOP */ + 1133 : } 1134 : - 1135 41 : if (!e || *e) { - 1136 : /* LCOV_EXCL_START */ - 1137 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); - 1138 : exit(EXIT_FAILURE); - 1139 : /* LCOV_EXCL_STOP */ - 1140 : } - 1141 : - 1142 : /* convert to GB */ - 1143 41 : state->autosave *= GIGA; - 1144 572 : } else if (tag[0] == 0) { - 1145 : /* allow empty lines */ - 1146 41 : } else if (tag[0] == '#') { - 1147 41 : ret = sgetline(f, buffer, sizeof(buffer)); - 1148 41 : if (ret < 0) { - 1149 : /* LCOV_EXCL_START */ - 1150 : log_fatal("Invalid comment in '%s' at line %u\n", path, line); - 1151 : exit(EXIT_FAILURE); - 1152 : /* LCOV_EXCL_STOP */ - 1153 : } - 1154 : } else { - 1155 : /* LCOV_EXCL_START */ - 1156 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); - 1157 : exit(EXIT_FAILURE); - 1158 : /* LCOV_EXCL_STOP */ - 1159 : } - 1160 : - 1161 : /* skip final spaces */ - 1162 6244 : sgetspace(f); - 1163 : - 1164 : /* next line */ - 1165 6244 : c = sgeteol(f); - 1166 6244 : if (c == EOF) { - 1167 265 : break; - 1168 : } - 1169 5979 : if (c != '\n') { - 1170 : /* LCOV_EXCL_START */ - 1171 : log_fatal("Extra data in '%s' at line %u\n", path, line); - 1172 : exit(EXIT_FAILURE); - 1173 : /* LCOV_EXCL_STOP */ - 1174 : } - 1175 5979 : ++line; - 1176 5979 : } - 1177 : - 1178 265 : if (serror(f)) { - 1179 : /* LCOV_EXCL_START */ - 1180 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); - 1181 : exit(EXIT_FAILURE); - 1182 : /* LCOV_EXCL_STOP */ - 1183 : } - 1184 : - 1185 265 : sclose(f); + 1135 41 : state->autosave = strtoul(buffer, &e, 0); + 1136 : + 1137 41 : if (!e || *e) { + 1138 : /* LCOV_EXCL_START */ + 1139 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + 1140 : exit(EXIT_FAILURE); + 1141 : /* LCOV_EXCL_STOP */ + 1142 : } + 1143 : + 1144 : /* convert to GB */ + 1145 41 : state->autosave *= GIGA; + 1146 572 : } else if (tag[0] == 0) { + 1147 : /* allow empty lines */ + 1148 41 : } else if (tag[0] == '#') { + 1149 41 : ret = sgetline(f, buffer, sizeof(buffer)); + 1150 41 : if (ret < 0) { + 1151 : /* LCOV_EXCL_START */ + 1152 : log_fatal("Invalid comment in '%s' at line %u\n", path, line); + 1153 : exit(EXIT_FAILURE); + 1154 : /* LCOV_EXCL_STOP */ + 1155 : } + 1156 : } else { + 1157 : /* LCOV_EXCL_START */ + 1158 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); + 1159 : exit(EXIT_FAILURE); + 1160 : /* LCOV_EXCL_STOP */ + 1161 : } + 1162 : + 1163 : /* skip final spaces */ + 1164 6244 : sgetspace(f); + 1165 : + 1166 : /* next line */ + 1167 6244 : c = sgeteol(f); + 1168 6244 : if (c == EOF) { + 1169 265 : break; + 1170 : } + 1171 5979 : if (c != '\n') { + 1172 : /* LCOV_EXCL_START */ + 1173 : log_fatal("Extra data in '%s' at line %u\n", path, line); + 1174 : exit(EXIT_FAILURE); + 1175 : /* LCOV_EXCL_STOP */ + 1176 : } + 1177 5979 : ++line; + 1178 5979 : } + 1179 : + 1180 265 : if (serror(f)) { + 1181 : /* LCOV_EXCL_START */ + 1182 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); + 1183 : exit(EXIT_FAILURE); + 1184 : /* LCOV_EXCL_STOP */ + 1185 : } 1186 : - 1187 265 : state_config_check(state, path, filterlist_disk); + 1187 265 : sclose(f); 1188 : - 1189 : /* select the default hash */ - 1190 265 : if (state->opt.force_murmur3) { - 1191 1 : state->besthash = HASH_MURMUR3; - 1192 264 : } else if (state->opt.force_spooky2) { - 1193 1 : state->besthash = HASH_SPOOKY2; - 1194 : } else { - 1195 : #ifdef CONFIG_X86 - 1196 263 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) - 1197 263 : state->besthash = HASH_MURMUR3; - 1198 : else - 1199 0 : state->besthash = HASH_SPOOKY2; - 1200 : #else - 1201 : if (sizeof(void*) == 4) - 1202 : state->besthash = HASH_MURMUR3; - 1203 : else - 1204 : state->besthash = HASH_SPOOKY2; - 1205 : #endif - 1206 : } - 1207 : - 1208 : /* by default use the best hash */ - 1209 265 : state->hash = state->besthash; - 1210 : - 1211 : /* by default use a random hash seed */ - 1212 265 : if (randomize(state->hashseed, HASH_MAX) != 0) { - 1213 : /* LCOV_EXCL_START */ - 1214 : log_fatal("Failed to get random values.\n"); - 1215 : exit(EXIT_FAILURE); - 1216 : /* LCOV_EXCL_STOP */ - 1217 : } - 1218 : - 1219 : /* no previous hash by default */ - 1220 265 : state->prevhash = HASH_UNDEFINED; - 1221 : - 1222 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + 1189 265 : state_config_check(state, path, filterlist_disk); + 1190 : + 1191 : /* select the default hash */ + 1192 265 : if (state->opt.force_murmur3) { + 1193 1 : state->besthash = HASH_MURMUR3; + 1194 264 : } else if (state->opt.force_spooky2) { + 1195 1 : state->besthash = HASH_SPOOKY2; + 1196 : } else { + 1197 : #ifdef CONFIG_X86 + 1198 263 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) + 1199 263 : state->besthash = HASH_MURMUR3; + 1200 : else + 1201 0 : state->besthash = HASH_SPOOKY2; + 1202 : #else + 1203 : if (sizeof(void*) == 4) + 1204 : state->besthash = HASH_MURMUR3; + 1205 : else + 1206 : state->besthash = HASH_SPOOKY2; + 1207 : #endif + 1208 : } + 1209 : + 1210 : /* by default use the best hash */ + 1211 265 : state->hash = state->besthash; + 1212 : + 1213 : /* by default use a random hash seed */ + 1214 265 : if (randomize(state->hashseed, HASH_MAX) != 0) { + 1215 : /* LCOV_EXCL_START */ + 1216 : log_fatal("Failed to get random values.\n"); + 1217 : exit(EXIT_FAILURE); + 1218 : /* LCOV_EXCL_STOP */ + 1219 : } + 1220 : + 1221 : /* no previous hash by default */ + 1222 265 : state->prevhash = HASH_UNDEFINED; 1223 : - 1224 265 : log_tag("blocksize:%u\n", state->block_size); - 1225 1850 : for (i = state->disklist; i != 0; i = i->next) { - 1226 1585 : struct snapraid_disk* disk = i->data; - 1227 1585 : log_tag("data:%s:%s\n", disk->name, disk->dir); - 1228 : } - 1229 : - 1230 265 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); - 1231 1531 : for (l = 0; l < state->level; ++l) - 1232 6330 : for (s = 0; s < state->parity[l].split_mac; ++s) - 1233 5064 : log_tag("%s:%u:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path); - 1234 265 : if (state->pool[0] != 0) - 1235 41 : log_tag("pool:%s\n", state->pool); - 1236 265 : if (state->share[0] != 0) - 1237 41 : log_tag("share:%s\n", state->share); - 1238 265 : if (state->autosave != 0) - 1239 41 : log_tag("autosave:%" PRIu64 "\n", state->autosave); - 1240 795 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { - 1241 : char out[PATH_MAX]; - 1242 530 : struct snapraid_filter* filter = i->data; - 1243 530 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); - 1244 : } - 1245 265 : if (state->filter_hidden) - 1246 0 : log_tag("filter:nohidden:\n"); - 1247 265 : log_flush(); - 1248 : } - 1249 : - 1250 : /** - 1251 : * Find a disk by name. - 1252 : */ - 1253 7047 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) - 1254 : { - 1255 : tommy_node* i; - 1256 : - 1257 24588 : for (i = state->disklist; i != 0; i = i->next) { - 1258 24580 : struct snapraid_disk* disk = i->data; - 1259 24580 : if (strcmp(disk->name, name) == 0) - 1260 7039 : return disk; - 1261 : } - 1262 : - 1263 8 : if (state->no_conf) { - 1264 : /* without a configuration file, add disks automatically */ - 1265 : struct snapraid_disk* disk; - 1266 : - 1267 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0); + 1224 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + 1225 : + 1226 265 : log_tag("blocksize:%u\n", state->block_size); + 1227 1850 : for (i = state->disklist; i != 0; i = i->next) { + 1228 1585 : struct snapraid_disk* disk = i->data; + 1229 1585 : log_tag("data:%s:%s\n", disk->name, disk->dir); + 1230 : } + 1231 : + 1232 265 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); + 1233 1531 : for (l = 0; l < state->level; ++l) + 1234 6330 : for (s = 0; s < state->parity[l].split_mac; ++s) + 1235 5064 : log_tag("%s:%u:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path); + 1236 265 : if (state->pool[0] != 0) + 1237 41 : log_tag("pool:%s\n", state->pool); + 1238 265 : if (state->share[0] != 0) + 1239 41 : log_tag("share:%s\n", state->share); + 1240 265 : if (state->autosave != 0) + 1241 41 : log_tag("autosave:%" PRIu64 "\n", state->autosave); + 1242 795 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { + 1243 : char out[PATH_MAX]; + 1244 530 : struct snapraid_filter* filter = i->data; + 1245 530 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); + 1246 : } + 1247 265 : if (state->filter_hidden) + 1248 0 : log_tag("filter:nohidden:\n"); + 1249 265 : log_flush(); + 1250 : } + 1251 : + 1252 : /** + 1253 : * Find a disk by name. + 1254 : */ + 1255 7047 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) + 1256 : { + 1257 : tommy_node* i; + 1258 : + 1259 24588 : for (i = state->disklist; i != 0; i = i->next) { + 1260 24580 : struct snapraid_disk* disk = i->data; + 1261 24580 : if (strcmp(disk->name, name) == 0) + 1262 7039 : return disk; + 1263 : } + 1264 : + 1265 8 : if (state->no_conf) { + 1266 : /* without a configuration file, add disks automatically */ + 1267 : struct snapraid_disk* disk; 1268 : - 1269 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 1269 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0); 1270 : - 1271 6 : return disk; - 1272 : } - 1273 : - 1274 2 : return 0; - 1275 : } - 1276 : - 1277 : /** - 1278 : * Find a disk by UUID. - 1279 : */ - 1280 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid) - 1281 : { - 1282 : tommy_node* i; - 1283 2 : struct snapraid_disk* found = 0; - 1284 : - 1285 : /* special test case to find the first matching UUID */ - 1286 : /* when testing UUID are all equal or not supported */ - 1287 : /* and we should handle this case specifically */ - 1288 2 : if (state->opt.match_first_uuid) - 1289 2 : return state->disklist->data; - 1290 : - 1291 : /* LCOV_EXCL_START */ - 1292 : /* never find an empty uuid */ - 1293 : if (!*uuid) - 1294 : return 0; - 1295 : - 1296 : for (i = state->disklist; i != 0; i = i->next) { - 1297 : struct snapraid_disk* disk = i->data; - 1298 : if (strcmp(disk->uuid, uuid) == 0) { - 1299 : /* never match duplicate UUID */ - 1300 : if (found) - 1301 : return 0; - 1302 : found = disk; - 1303 : } - 1304 : } - 1305 : - 1306 : return found; - 1307 : /* LCOV_EXCL_STOP */ - 1308 : } - 1309 : - 1310 : /** - 1311 : * Update the disk mapping if required. - 1312 : */ - 1313 260 : static void state_map(struct snapraid_state* state) - 1314 : { - 1315 : unsigned hole; - 1316 : tommy_node* i; - 1317 : unsigned uuid_mismatch; - 1318 : unsigned diskcount; - 1319 : unsigned l, s; - 1320 : - 1321 : /* remove all the mapping without a disk */ - 1322 : /* this happens when a disk is removed from the configuration file */ - 1323 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ - 1324 : /* when saving the content file, but we keep this code to import older content files. */ - 1325 1917 : for (i = state->maplist; i != 0; ) { - 1326 1397 : struct snapraid_map* map = i->data; - 1327 : struct snapraid_disk* disk; - 1328 : - 1329 1397 : disk = find_disk_by_name(state, map->name); + 1271 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 1272 : + 1273 6 : return disk; + 1274 : } + 1275 : + 1276 2 : return 0; + 1277 : } + 1278 : + 1279 : /** + 1280 : * Find a disk by UUID. + 1281 : */ + 1282 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid) + 1283 : { + 1284 : tommy_node* i; + 1285 2 : struct snapraid_disk* found = 0; + 1286 : + 1287 : /* special test case to find the first matching UUID */ + 1288 : /* when testing UUID are all equal or not supported */ + 1289 : /* and we should handle this case specifically */ + 1290 2 : if (state->opt.match_first_uuid) + 1291 2 : return state->disklist->data; + 1292 : + 1293 : /* LCOV_EXCL_START */ + 1294 : /* never find an empty uuid */ + 1295 : if (!*uuid) + 1296 : return 0; + 1297 : + 1298 : for (i = state->disklist; i != 0; i = i->next) { + 1299 : struct snapraid_disk* disk = i->data; + 1300 : if (strcmp(disk->uuid, uuid) == 0) { + 1301 : /* never match duplicate UUID */ + 1302 : if (found) + 1303 : return 0; + 1304 : found = disk; + 1305 : } + 1306 : } + 1307 : + 1308 : return found; + 1309 : /* LCOV_EXCL_STOP */ + 1310 : } + 1311 : + 1312 : /** + 1313 : * Update the disk mapping if required. + 1314 : */ + 1315 260 : static void state_map(struct snapraid_state* state) + 1316 : { + 1317 : unsigned hole; + 1318 : tommy_node* i; + 1319 : unsigned uuid_mismatch; + 1320 : unsigned diskcount; + 1321 : unsigned l, s; + 1322 : + 1323 : /* remove all the mapping without a disk */ + 1324 : /* this happens when a disk is removed from the configuration file */ + 1325 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ + 1326 : /* when saving the content file, but we keep this code to import older content files. */ + 1327 1917 : for (i = state->maplist; i != 0; ) { + 1328 1397 : struct snapraid_map* map = i->data; + 1329 : struct snapraid_disk* disk; 1330 : - 1331 : /* go to the next mapping before removing */ - 1332 1397 : i = i->next; - 1333 : - 1334 1397 : if (disk == 0) { - 1335 : /* disk not found, remove the mapping */ - 1336 0 : tommy_list_remove_existing(&state->maplist, &map->node); - 1337 0 : map_free(map); - 1338 : } - 1339 : } - 1340 : - 1341 : /* maps each unmapped disk present in the configuration file in the first available hole */ - 1342 : /* this happens when you add disks for the first time in the configuration file */ - 1343 260 : hole = 0; /* first position to try */ - 1344 1815 : for (i = state->disklist; i != 0; i = i->next) { - 1345 1555 : struct snapraid_disk* disk = i->data; - 1346 : struct snapraid_map* map; - 1347 : tommy_node* j; - 1348 : - 1349 : /* check if the disk is already mapped */ - 1350 5430 : for (j = state->maplist; j != 0; j = j->next) { - 1351 5272 : map = j->data; - 1352 5272 : if (strcmp(disk->name, map->name) == 0) { - 1353 : /* mapping found */ - 1354 1397 : break; - 1355 : } - 1356 : } - 1357 1555 : if (j != 0) { - 1358 : /* mapping is present, then copy the free blocks into to disk */ - 1359 1397 : disk->total_blocks = map->total_blocks; - 1360 1397 : disk->free_blocks = map->free_blocks; - 1361 1397 : continue; - 1362 : } - 1363 : - 1364 : /* mapping not found, search for an hole */ - 1365 : while (1) { - 1366 1100 : for (j = state->maplist; j != 0; j = j->next) { - 1367 942 : map = j->data; - 1368 942 : if (map->position == hole) { - 1369 : /* position already used */ - 1370 158 : break; - 1371 : } - 1372 : } - 1373 316 : if (j == 0) { - 1374 : /* hole found */ - 1375 158 : break; - 1376 : } - 1377 : - 1378 : /* try with the next one */ - 1379 158 : ++hole; - 1380 158 : } - 1381 : - 1382 : /* insert the new mapping */ - 1383 158 : map = map_alloc(disk->name, hole, 0, 0, ""); - 1384 : - 1385 158 : tommy_list_insert_tail(&state->maplist, &map->node, map); - 1386 : } - 1387 : - 1388 : /* without configuration don't check for number of data disks or uuid changes */ - 1389 260 : if (state->no_conf) - 1390 261 : return; - 1391 : - 1392 : /* counter for the number of UUID mismatches */ - 1393 259 : uuid_mismatch = 0; - 1394 : - 1395 : /* check if mapping match the disk uuid */ - 1396 259 : if (!state->opt.skip_disk_access) { - 1397 1626 : for (i = state->maplist; i != 0; i = i->next) { - 1398 1393 : struct snapraid_map* map = i->data; - 1399 : struct snapraid_disk* disk; - 1400 : - 1401 1393 : disk = find_disk_by_name(state, map->name); - 1402 1393 : if (disk == 0) { - 1403 : /* LCOV_EXCL_START */ - 1404 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - 1405 : os_abort(); - 1406 : /* LCOV_EXCL_STOP */ - 1407 : } - 1408 : - 1409 1393 : if (disk->has_unsupported_uuid) { - 1410 : /* if uuid is not available, skip this one */ - 1411 1 : continue; - 1412 : } - 1413 : - 1414 : /* if the uuid is changed */ - 1415 1392 : if (strcmp(disk->uuid, map->uuid) != 0) { - 1416 : /* mark the disk as with an UUID change */ - 1417 113 : disk->has_different_uuid = 1; - 1418 : - 1419 : /* if the previous uuid is available */ - 1420 113 : if (map->uuid[0] != 0) { - 1421 : /* count the number of uuid change */ - 1422 4 : ++uuid_mismatch; - 1423 4 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid); - 1424 : } else { - 1425 : /* no message here, because having a disk without */ - 1426 : /* UUID is the normal state of an empty disk */ - 1427 109 : disk->had_empty_uuid = 1; - 1428 : } - 1429 : - 1430 : /* update the uuid in the mapping, */ - 1431 113 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid); - 1432 : - 1433 : /* write the new state with the new uuid */ - 1434 113 : state->need_write = 1; - 1435 : } - 1436 : } - 1437 : } - 1438 : - 1439 : /* check the parity uuid */ - 1440 259 : if (!state->opt.skip_parity_access) { - 1441 1273 : for (l = 0; l < state->level; ++l) { - 1442 5260 : for (s = 0; s < state->parity[l].split_mac; ++s) { - 1443 : char uuid[UUID_MAX]; - 1444 : int ret; - 1445 : - 1446 4208 : ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid)); - 1447 4208 : if (ret != 0) { - 1448 : /* uuid not available, just ignore */ - 1449 4 : continue; - 1450 : } - 1451 : - 1452 : /* if the uuid is changed */ - 1453 4204 : if (strcmp(uuid, state->parity[l].split_map[s].uuid) != 0) { - 1454 : /* if the previous uuid is available */ - 1455 184 : if (state->parity[l].split_map[s].uuid[0] != 0) { - 1456 : /* count the number of uuid change */ - 1457 0 : ++uuid_mismatch; - 1458 0 : log_fatal("UUID change for parity '%s[%u]' from '%s' to '%s'\n", lev_config_name(l), s, state->parity[l].split_map[s].uuid, uuid); - 1459 : } - 1460 : - 1461 : /* update the uuid */ - 1462 184 : pathcpy(state->parity[l].split_map[s].uuid, sizeof(state->parity[l].split_map[s].uuid), uuid); - 1463 : - 1464 : /* write the new state with the new uuid */ - 1465 184 : state->need_write = 1; - 1466 : } - 1467 : } - 1468 : } - 1469 : } - 1470 : - 1471 259 : if (!state->opt.force_uuid && uuid_mismatch > state->level) { - 1472 : /* LCOV_EXCL_START */ - 1473 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n"); - 1474 : log_fatal("If this happens because you really replaced them,\n"); - 1475 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command); - 1476 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n"); - 1477 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n"); - 1478 : exit(EXIT_FAILURE); - 1479 : /* LCOV_EXCL_STOP */ - 1480 : } - 1481 : - 1482 : /* count the number of data disks, including holes left after removing some */ - 1483 259 : diskcount = 0; - 1484 1808 : for (i = state->maplist; i != 0; i = i->next) { - 1485 1549 : struct snapraid_map* map = i->data; - 1486 : - 1487 1549 : if (map->position + 1 > diskcount) - 1488 1367 : diskcount = map->position + 1; - 1489 : } - 1490 : - 1491 : /* ensure to don't go over the limit of the RAID engine */ - 1492 259 : if (diskcount > RAID_DATA_MAX) { - 1493 : /* LCOV_EXCL_START */ - 1494 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX); - 1495 : exit(EXIT_FAILURE); - 1496 : /* LCOV_EXCL_STOP */ - 1497 : } - 1498 : - 1499 : /* now count the real number of data disks, excluding holes left after removing some */ - 1500 259 : diskcount = tommy_list_count(&state->maplist); - 1501 : - 1502 : /* recommend number of parities */ - 1503 259 : if (!state->opt.no_warnings) { - 1504 1 : if (diskcount >= 36 && state->level < 6) { - 1505 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount); - 1506 1 : } else if (diskcount >= 29 && state->level < 5) { - 1507 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount); - 1508 1 : } else if (diskcount >= 22 && state->level < 4) { - 1509 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount); - 1510 1 : } else if (diskcount >= 15 && state->level < 3) { - 1511 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount); - 1512 1 : } else if (diskcount >= 5 && state->level < 2) { - 1513 0 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount); - 1514 : } - 1515 : } - 1516 : } - 1517 : - 1518 173 : void state_refresh(struct snapraid_state* state) - 1519 : { - 1520 : tommy_node* i; - 1521 : unsigned l, s; - 1522 : - 1523 : /* for all disks */ - 1524 1209 : for (i = state->maplist; i != 0; i = i->next) { - 1525 1036 : struct snapraid_map* map = i->data; - 1526 : struct snapraid_disk* disk; - 1527 : uint64_t total_space; - 1528 : uint64_t free_space; - 1529 : int ret; - 1530 : - 1531 1036 : disk = find_disk_by_name(state, map->name); - 1532 1036 : if (disk == 0) { - 1533 : /* LCOV_EXCL_START */ - 1534 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - 1535 : os_abort(); - 1536 : /* LCOV_EXCL_STOP */ - 1537 : } - 1538 : - 1539 1036 : ret = fsinfo(disk->dir, 0, &total_space, &free_space); - 1540 1036 : if (ret != 0) { - 1541 : /* LCOV_EXCL_START */ - 1542 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); - 1543 : exit(EXIT_FAILURE); - 1544 : /* LCOV_EXCL_STOP */ - 1545 : } - 1546 : - 1547 : /* set the new free blocks */ - 1548 1036 : map->total_blocks = total_space / state->block_size; - 1549 1036 : map->free_blocks = free_space / state->block_size; - 1550 : - 1551 : /* also update the disk info */ - 1552 1036 : disk->total_blocks = map->total_blocks; - 1553 1036 : disk->free_blocks = map->free_blocks; - 1554 : } - 1555 : - 1556 : /* for all parities */ - 1557 1141 : for (l = 0; l < state->level; ++l) { - 1558 : /* set the new free blocks */ - 1559 968 : state->parity[l].total_blocks = 0; - 1560 968 : state->parity[l].free_blocks = 0; - 1561 : - 1562 4840 : for (s = 0; s < state->parity[l].split_mac; ++s) { - 1563 : uint64_t total_space; - 1564 : uint64_t free_space; - 1565 : int ret; - 1566 : - 1567 3872 : ret = fsinfo(state->parity[l].split_map[s].path, 0, &total_space, &free_space); - 1568 3872 : if (ret != 0) { - 1569 : /* LCOV_EXCL_START */ - 1570 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno)); - 1571 : exit(EXIT_FAILURE); - 1572 : /* LCOV_EXCL_STOP */ - 1573 : } - 1574 : - 1575 : /* add the new free blocks */ - 1576 3872 : state->parity[l].total_blocks += total_space / state->block_size; - 1577 3872 : state->parity[l].free_blocks += free_space / state->block_size; - 1578 : } - 1579 : } - 1580 : - 1581 : /* note what we don't set need_write = 1, because we don't want */ - 1582 : /* to update the content file only for the free space info. */ - 1583 173 : } - 1584 : - 1585 : /** - 1586 : * Check the content. - 1587 : */ - 1588 253 : static void state_content_check(struct snapraid_state* state, const char* path) - 1589 : { - 1590 : tommy_node* i; - 1591 : - 1592 : /* check that any map has different name and position */ - 1593 1766 : for (i = state->maplist; i != 0; i = i->next) { - 1594 1513 : struct snapraid_map* map = i->data; - 1595 : tommy_node* j; - 1596 5283 : for (j = i->next; j != 0; j = j->next) { - 1597 3770 : struct snapraid_map* other = j->data; - 1598 3770 : if (strcmp(map->name, other->name) == 0) { - 1599 : /* LCOV_EXCL_START */ - 1600 : log_fatal("Colliding 'map' disk specification in '%s'\n", path); - 1601 : exit(EXIT_FAILURE); - 1602 : /* LCOV_EXCL_STOP */ - 1603 : } - 1604 3770 : if (map->position == other->position) { - 1605 : /* LCOV_EXCL_START */ - 1606 : log_fatal("Colliding 'map' index specification in '%s'\n", path); - 1607 : exit(EXIT_FAILURE); - 1608 : /* LCOV_EXCL_STOP */ - 1609 : } - 1610 : } - 1611 : } - 1612 253 : } - 1613 : - 1614 : /** - 1615 : * Check if the position is REQUIRED, or we can completely clear it from the state. - 1616 : * - 1617 : * Note that position with only DELETED blocks are discarged. - 1618 : */ - 1619 756099 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) - 1620 : { - 1621 : tommy_node* i; - 1622 : - 1623 : /* check for each disk */ - 1624 802725 : for (i = state->disklist; i != 0; i = i->next) { - 1625 802725 : struct snapraid_disk* disk = i->data; - 1626 802725 : struct snapraid_block* block = fs_par2block_find(disk, pos); - 1627 : - 1628 : /* if we have at least one file, the position is needed */ - 1629 802725 : if (block_has_file(block)) - 1630 756099 : return 1; - 1631 : } - 1632 : - 1633 0 : return 0; - 1634 : } + 1331 1397 : disk = find_disk_by_name(state, map->name); + 1332 : + 1333 : /* go to the next mapping before removing */ + 1334 1397 : i = i->next; + 1335 : + 1336 1397 : if (disk == 0) { + 1337 : /* disk not found, remove the mapping */ + 1338 0 : tommy_list_remove_existing(&state->maplist, &map->node); + 1339 0 : map_free(map); + 1340 : } + 1341 : } + 1342 : + 1343 : /* maps each unmapped disk present in the configuration file in the first available hole */ + 1344 : /* this happens when you add disks for the first time in the configuration file */ + 1345 260 : hole = 0; /* first position to try */ + 1346 1815 : for (i = state->disklist; i != 0; i = i->next) { + 1347 1555 : struct snapraid_disk* disk = i->data; + 1348 : struct snapraid_map* map; + 1349 : tommy_node* j; + 1350 : + 1351 : /* check if the disk is already mapped */ + 1352 5430 : for (j = state->maplist; j != 0; j = j->next) { + 1353 5272 : map = j->data; + 1354 5272 : if (strcmp(disk->name, map->name) == 0) { + 1355 : /* mapping found */ + 1356 1397 : break; + 1357 : } + 1358 : } + 1359 1555 : if (j != 0) { + 1360 : /* mapping is present, then copy the free blocks into to disk */ + 1361 1397 : disk->total_blocks = map->total_blocks; + 1362 1397 : disk->free_blocks = map->free_blocks; + 1363 1397 : continue; + 1364 : } + 1365 : + 1366 : /* mapping not found, search for an hole */ + 1367 : while (1) { + 1368 1100 : for (j = state->maplist; j != 0; j = j->next) { + 1369 942 : map = j->data; + 1370 942 : if (map->position == hole) { + 1371 : /* position already used */ + 1372 158 : break; + 1373 : } + 1374 : } + 1375 316 : if (j == 0) { + 1376 : /* hole found */ + 1377 158 : break; + 1378 : } + 1379 : + 1380 : /* try with the next one */ + 1381 158 : ++hole; + 1382 158 : } + 1383 : + 1384 : /* insert the new mapping */ + 1385 158 : map = map_alloc(disk->name, hole, 0, 0, ""); + 1386 : + 1387 158 : tommy_list_insert_tail(&state->maplist, &map->node, map); + 1388 : } + 1389 : + 1390 : /* without configuration don't check for number of data disks or uuid changes */ + 1391 260 : if (state->no_conf) + 1392 261 : return; + 1393 : + 1394 : /* counter for the number of UUID mismatches */ + 1395 259 : uuid_mismatch = 0; + 1396 : + 1397 : /* check if mapping match the disk uuid */ + 1398 259 : if (!state->opt.skip_disk_access) { + 1399 1626 : for (i = state->maplist; i != 0; i = i->next) { + 1400 1393 : struct snapraid_map* map = i->data; + 1401 : struct snapraid_disk* disk; + 1402 : + 1403 1393 : disk = find_disk_by_name(state, map->name); + 1404 1393 : if (disk == 0) { + 1405 : /* LCOV_EXCL_START */ + 1406 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + 1407 : os_abort(); + 1408 : /* LCOV_EXCL_STOP */ + 1409 : } + 1410 : + 1411 1393 : if (disk->has_unsupported_uuid) { + 1412 : /* if uuid is not available, skip this one */ + 1413 1 : continue; + 1414 : } + 1415 : + 1416 : /* if the uuid is changed */ + 1417 1392 : if (strcmp(disk->uuid, map->uuid) != 0) { + 1418 : /* mark the disk as with an UUID change */ + 1419 113 : disk->has_different_uuid = 1; + 1420 : + 1421 : /* if the previous uuid is available */ + 1422 113 : if (map->uuid[0] != 0) { + 1423 : /* count the number of uuid change */ + 1424 4 : ++uuid_mismatch; + 1425 4 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid); + 1426 : } else { + 1427 : /* no message here, because having a disk without */ + 1428 : /* UUID is the normal state of an empty disk */ + 1429 109 : disk->had_empty_uuid = 1; + 1430 : } + 1431 : + 1432 : /* update the uuid in the mapping, */ + 1433 113 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid); + 1434 : + 1435 : /* write the new state with the new uuid */ + 1436 113 : state->need_write = 1; + 1437 : } + 1438 : } + 1439 : } + 1440 : + 1441 : /* check the parity uuid */ + 1442 259 : if (!state->opt.skip_parity_access) { + 1443 1273 : for (l = 0; l < state->level; ++l) { + 1444 5260 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 1445 : char uuid[UUID_MAX]; + 1446 : int ret; + 1447 : + 1448 4208 : ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid)); + 1449 4208 : if (ret != 0) { + 1450 : /* uuid not available, just ignore */ + 1451 4 : continue; + 1452 : } + 1453 : + 1454 : /* if the uuid is changed */ + 1455 4204 : if (strcmp(uuid, state->parity[l].split_map[s].uuid) != 0) { + 1456 : /* if the previous uuid is available */ + 1457 184 : if (state->parity[l].split_map[s].uuid[0] != 0) { + 1458 : /* count the number of uuid change */ + 1459 0 : ++uuid_mismatch; + 1460 0 : log_fatal("UUID change for parity '%s[%u]' from '%s' to '%s'\n", lev_config_name(l), s, state->parity[l].split_map[s].uuid, uuid); + 1461 : } + 1462 : + 1463 : /* update the uuid */ + 1464 184 : pathcpy(state->parity[l].split_map[s].uuid, sizeof(state->parity[l].split_map[s].uuid), uuid); + 1465 : + 1466 : /* write the new state with the new uuid */ + 1467 184 : state->need_write = 1; + 1468 : } + 1469 : } + 1470 : } + 1471 : } + 1472 : + 1473 259 : if (!state->opt.force_uuid && uuid_mismatch > state->level) { + 1474 : /* LCOV_EXCL_START */ + 1475 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n"); + 1476 : log_fatal("If this happens because you really replaced them,\n"); + 1477 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command); + 1478 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n"); + 1479 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n"); + 1480 : exit(EXIT_FAILURE); + 1481 : /* LCOV_EXCL_STOP */ + 1482 : } + 1483 : + 1484 : /* count the number of data disks, including holes left after removing some */ + 1485 259 : diskcount = 0; + 1486 1808 : for (i = state->maplist; i != 0; i = i->next) { + 1487 1549 : struct snapraid_map* map = i->data; + 1488 : + 1489 1549 : if (map->position + 1 > diskcount) + 1490 1367 : diskcount = map->position + 1; + 1491 : } + 1492 : + 1493 : /* ensure to don't go over the limit of the RAID engine */ + 1494 259 : if (diskcount > RAID_DATA_MAX) { + 1495 : /* LCOV_EXCL_START */ + 1496 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX); + 1497 : exit(EXIT_FAILURE); + 1498 : /* LCOV_EXCL_STOP */ + 1499 : } + 1500 : + 1501 : /* now count the real number of data disks, excluding holes left after removing some */ + 1502 259 : diskcount = tommy_list_count(&state->maplist); + 1503 : + 1504 : /* recommend number of parities */ + 1505 259 : if (!state->opt.no_warnings) { + 1506 : /* intentionally use log_fatal() instead of log_error() to give more visibility at the warning */ + 1507 1 : if (diskcount >= 36 && state->level < 6) { + 1508 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount); + 1509 1 : } else if (diskcount >= 29 && state->level < 5) { + 1510 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount); + 1511 1 : } else if (diskcount >= 22 && state->level < 4) { + 1512 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount); + 1513 1 : } else if (diskcount >= 15 && state->level < 3) { + 1514 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount); + 1515 1 : } else if (diskcount >= 5 && state->level < 2) { + 1516 0 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount); + 1517 : } + 1518 : } + 1519 : } + 1520 : + 1521 173 : void state_refresh(struct snapraid_state* state) + 1522 : { + 1523 : tommy_node* i; + 1524 : unsigned l, s; + 1525 : + 1526 : /* for all disks */ + 1527 1209 : for (i = state->maplist; i != 0; i = i->next) { + 1528 1036 : struct snapraid_map* map = i->data; + 1529 : struct snapraid_disk* disk; + 1530 : uint64_t total_space; + 1531 : uint64_t free_space; + 1532 : int ret; + 1533 : + 1534 1036 : disk = find_disk_by_name(state, map->name); + 1535 1036 : if (disk == 0) { + 1536 : /* LCOV_EXCL_START */ + 1537 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + 1538 : os_abort(); + 1539 : /* LCOV_EXCL_STOP */ + 1540 : } + 1541 : + 1542 1036 : ret = fsinfo(disk->dir, 0, &total_space, &free_space); + 1543 1036 : if (ret != 0) { + 1544 : /* LCOV_EXCL_START */ + 1545 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + 1546 : exit(EXIT_FAILURE); + 1547 : /* LCOV_EXCL_STOP */ + 1548 : } + 1549 : + 1550 : /* set the new free blocks */ + 1551 1036 : map->total_blocks = total_space / state->block_size; + 1552 1036 : map->free_blocks = free_space / state->block_size; + 1553 : + 1554 : /* also update the disk info */ + 1555 1036 : disk->total_blocks = map->total_blocks; + 1556 1036 : disk->free_blocks = map->free_blocks; + 1557 : } + 1558 : + 1559 : /* for all parities */ + 1560 1141 : for (l = 0; l < state->level; ++l) { + 1561 : /* set the new free blocks */ + 1562 968 : state->parity[l].total_blocks = 0; + 1563 968 : state->parity[l].free_blocks = 0; + 1564 : + 1565 4840 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 1566 : uint64_t total_space; + 1567 : uint64_t free_space; + 1568 : int ret; + 1569 : + 1570 3872 : ret = fsinfo(state->parity[l].split_map[s].path, 0, &total_space, &free_space); + 1571 3872 : if (ret != 0) { + 1572 : /* LCOV_EXCL_START */ + 1573 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno)); + 1574 : exit(EXIT_FAILURE); + 1575 : /* LCOV_EXCL_STOP */ + 1576 : } + 1577 : + 1578 : /* add the new free blocks */ + 1579 3872 : state->parity[l].total_blocks += total_space / state->block_size; + 1580 3872 : state->parity[l].free_blocks += free_space / state->block_size; + 1581 : } + 1582 : } + 1583 : + 1584 : /* note what we don't set need_write = 1, because we don't want */ + 1585 : /* to update the content file only for the free space info. */ + 1586 173 : } + 1587 : + 1588 : /** + 1589 : * Check the content. + 1590 : */ + 1591 253 : static void state_content_check(struct snapraid_state* state, const char* path) + 1592 : { + 1593 : tommy_node* i; + 1594 : + 1595 : /* check that any map has different name and position */ + 1596 1766 : for (i = state->maplist; i != 0; i = i->next) { + 1597 1513 : struct snapraid_map* map = i->data; + 1598 : tommy_node* j; + 1599 5283 : for (j = i->next; j != 0; j = j->next) { + 1600 3770 : struct snapraid_map* other = j->data; + 1601 3770 : if (strcmp(map->name, other->name) == 0) { + 1602 : /* LCOV_EXCL_START */ + 1603 : log_fatal("Colliding 'map' disk specification in '%s'\n", path); + 1604 : exit(EXIT_FAILURE); + 1605 : /* LCOV_EXCL_STOP */ + 1606 : } + 1607 3770 : if (map->position == other->position) { + 1608 : /* LCOV_EXCL_START */ + 1609 : log_fatal("Colliding 'map' index specification in '%s'\n", path); + 1610 : exit(EXIT_FAILURE); + 1611 : /* LCOV_EXCL_STOP */ + 1612 : } + 1613 : } + 1614 : } + 1615 253 : } + 1616 : + 1617 : /** + 1618 : * Check if the position is REQUIRED, or we can completely clear it from the state. + 1619 : * + 1620 : * Note that position with only DELETED blocks are discarged. + 1621 : */ + 1622 756099 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) + 1623 : { + 1624 : tommy_node* i; + 1625 : + 1626 : /* check for each disk */ + 1627 802725 : for (i = state->disklist; i != 0; i = i->next) { + 1628 802725 : struct snapraid_disk* disk = i->data; + 1629 802725 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1630 : + 1631 : /* if we have at least one file, the position is needed */ + 1632 802725 : if (block_has_file(block)) + 1633 756099 : return 1; + 1634 : } 1635 : - 1636 : /** - 1637 : * Check if the info block is REQUIREQ. - 1638 : * - 1639 : * This is used to ensure that we keep the last check used for scrubbing. - 1640 : * and that we add it when importing old context files. + 1636 0 : return 0; + 1637 : } + 1638 : + 1639 : /** + 1640 : * Check if the info block is REQUIREQ. 1641 : * - 1642 : * Note that you can have position without info blocks, for example - 1643 : * if all the blocks are not synced. + 1642 : * This is used to ensure that we keep the last check used for scrubbing. + 1643 : * and that we add it when importing old context files. 1644 : * - 1645 : * Note also that not requiring an info block, doesn't mean that if present it - 1646 : * can be discarded. - 1647 : */ - 1648 1547923 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos) - 1649 : { - 1650 : tommy_node* i; - 1651 : - 1652 : /* check for each disk */ - 1653 2048488 : for (i = state->disklist; i != 0; i = i->next) { - 1654 1989723 : struct snapraid_disk* disk = i->data; - 1655 1989723 : struct snapraid_block* block = fs_par2block_find(disk, pos); - 1656 : - 1657 : /* if we have at least one synced file, the info is required */ - 1658 1989723 : if (block_state_get(block) == BLOCK_STATE_BLK) - 1659 1489158 : return 1; - 1660 : } - 1661 : - 1662 58765 : return 0; - 1663 : } + 1645 : * Note that you can have position without info blocks, for example + 1646 : * if all the blocks are not synced. + 1647 : * + 1648 : * Note also that not requiring an info block, doesn't mean that if present it + 1649 : * can be discarded. + 1650 : */ + 1651 1547923 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos) + 1652 : { + 1653 : tommy_node* i; + 1654 : + 1655 : /* check for each disk */ + 1656 2048488 : for (i = state->disklist; i != 0; i = i->next) { + 1657 1989723 : struct snapraid_disk* disk = i->data; + 1658 1989723 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1659 : + 1660 : /* if we have at least one synced file, the info is required */ + 1661 1989723 : if (block_state_get(block) == BLOCK_STATE_BLK) + 1662 1489158 : return 1; + 1663 : } 1664 : - 1665 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos) - 1666 : { - 1667 : tommy_node* i; - 1668 : - 1669 : /* check for each disk if block is really used */ - 1670 0 : for (i = state->disklist; i != 0; i = i->next) { - 1671 0 : struct snapraid_disk* disk = i->data; - 1672 0 : struct snapraid_block* block = fs_par2block_find(disk, pos); - 1673 : - 1674 : /* if the block is deleted */ - 1675 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) { - 1676 : /* set it to empty */ - 1677 0 : fs_deallocate(disk, pos); - 1678 : } - 1679 : } - 1680 0 : } - 1681 : - 1682 : /** - 1683 : * Check if a block position in a disk is deleted. - 1684 : */ - 1685 4529621 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) - 1686 : { - 1687 4529621 : struct snapraid_block* block = fs_par2block_find(disk, pos); - 1688 : - 1689 4529621 : return block_state_get(block) == BLOCK_STATE_DELETED; - 1690 : } + 1665 58765 : return 0; + 1666 : } + 1667 : + 1668 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos) + 1669 : { + 1670 : tommy_node* i; + 1671 : + 1672 : /* check for each disk if block is really used */ + 1673 0 : for (i = state->disklist; i != 0; i = i->next) { + 1674 0 : struct snapraid_disk* disk = i->data; + 1675 0 : struct snapraid_block* block = fs_par2block_find(disk, pos); + 1676 : + 1677 : /* if the block is deleted */ + 1678 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) { + 1679 : /* set it to empty */ + 1680 0 : fs_deallocate(disk, pos); + 1681 : } + 1682 : } + 1683 0 : } + 1684 : + 1685 : /** + 1686 : * Check if a block position in a disk is deleted. + 1687 : */ + 1688 4529621 : static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) + 1689 : { + 1690 4529621 : struct snapraid_block* block = fs_par2block_find(disk, pos); 1691 : - 1692 : /** - 1693 : * Flush the file checking the final CRC. - 1694 : * We exploit the fact that the CRC is always stored in the last 4 bytes. - 1695 : */ - 1696 1 : static void decoding_error(const char* path, STREAM* f) - 1697 : { - 1698 : unsigned char buf[4]; - 1699 : uint32_t crc_stored; - 1700 : uint32_t crc_computed; - 1701 : - 1702 1 : if (seof(f)) { - 1703 : /* LCOV_EXCL_START */ - 1704 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1705 : log_fatal("This content file is truncated. Use an alternate copy.\n"); - 1706 : exit(EXIT_FAILURE); - 1707 : /* LCOV_EXCL_STOP */ - 1708 : } - 1709 : - 1710 1 : if (serror(f)) { - 1711 : /* LCOV_EXCL_START */ - 1712 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1713 : exit(EXIT_FAILURE); - 1714 : /* LCOV_EXCL_STOP */ - 1715 : } - 1716 : - 1717 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1718 : - 1719 1 : if (sdeplete(f, buf) != 0) { - 1720 : /* LCOV_EXCL_START */ - 1721 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1722 : exit(EXIT_FAILURE); - 1723 : /* LCOV_EXCL_STOP */ - 1724 : } - 1725 : - 1726 : /* get the stored crc from the last four bytes */ - 1727 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + 1692 4529621 : return block_state_get(block) == BLOCK_STATE_DELETED; + 1693 : } + 1694 : + 1695 : /** + 1696 : * Flush the file checking the final CRC. + 1697 : * We exploit the fact that the CRC is always stored in the last 4 bytes. + 1698 : */ + 1699 1 : static void decoding_error(const char* path, STREAM* f) + 1700 : { + 1701 : unsigned char buf[4]; + 1702 : uint32_t crc_stored; + 1703 : uint32_t crc_computed; + 1704 : + 1705 1 : if (seof(f)) { + 1706 : /* LCOV_EXCL_START */ + 1707 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1708 : log_fatal("This content file is truncated. Use an alternate copy.\n"); + 1709 : exit(EXIT_FAILURE); + 1710 : /* LCOV_EXCL_STOP */ + 1711 : } + 1712 : + 1713 1 : if (serror(f)) { + 1714 : /* LCOV_EXCL_START */ + 1715 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1716 : exit(EXIT_FAILURE); + 1717 : /* LCOV_EXCL_STOP */ + 1718 : } + 1719 : + 1720 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1721 : + 1722 1 : if (sdeplete(f, buf) != 0) { + 1723 : /* LCOV_EXCL_START */ + 1724 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1725 : exit(EXIT_FAILURE); + 1726 : /* LCOV_EXCL_STOP */ + 1727 : } 1728 : - 1729 : /* get the computed crc */ - 1730 1 : crc_computed = scrc(f); + 1729 : /* get the stored crc from the last four bytes */ + 1730 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; 1731 : - 1732 : /* adjust the stored crc to include itself */ - 1733 1 : crc_stored = crc32c(crc_stored, buf, 4); + 1732 : /* get the computed crc */ + 1733 1 : crc_computed = scrc(f); 1734 : - 1735 1 : if (crc_computed != crc_stored) { - 1736 1 : log_fatal("Mismatching CRC in '%s'\n", path); - 1737 1 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 1738 1 : exit(EXIT_FAILURE); - 1739 : } else { - 1740 0 : log_fatal("The file CRC is correct!\n"); - 1741 : } - 1742 0 : } - 1743 : - 1744 254 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f) - 1745 : { - 1746 : block_off_t blockmax; - 1747 : unsigned count_file; - 1748 : unsigned count_hardlink; - 1749 : unsigned count_symlink; - 1750 : unsigned count_dir; - 1751 : int crc_checked; - 1752 : char buffer[PATH_MAX]; - 1753 : int ret; - 1754 : tommy_array disk_mapping; - 1755 : uint32_t mapping_max; - 1756 : - 1757 254 : blockmax = 0; - 1758 254 : count_file = 0; - 1759 254 : count_hardlink = 0; - 1760 254 : count_symlink = 0; - 1761 254 : count_dir = 0; - 1762 254 : crc_checked = 0; - 1763 254 : mapping_max = 0; - 1764 254 : tommy_array_init(&disk_mapping); - 1765 : - 1766 254 : ret = sread(f, buffer, 12); - 1767 254 : if (ret < 0) { - 1768 : /* LCOV_EXCL_START */ - 1769 : decoding_error(path, f); - 1770 : log_fatal("Invalid header!\n"); - 1771 : os_abort(); - 1772 : /* LCOV_EXCL_STOP */ - 1773 : } - 1774 : - 1775 : /* - 1776 : * File format versions: - 1777 : * - SNAPCNT1/SnapRAID 4.0 First version. - 1778 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support. - 1779 : * The previous 'm' entry is now deprecated, but supported for importing. - 1780 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'. - 1781 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'y' for hash size. - 1782 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'Q' for multi parity file. - 1783 : * The previous 'P' entry is now deprecated, but supported for importing. - 1784 : */ - 1785 254 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0 - 1786 254 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0 - 1787 254 : && memcmp(buffer, "SNAPCNT3\n\3\0\0", 12) != 0 - 1788 : ) { - 1789 : /* LCOV_EXCL_START */ - 1790 : if (memcmp(buffer, "SNAPCNT", 7) != 0) { - 1791 : decoding_error(path, f); - 1792 : log_fatal("Invalid header!\n"); - 1793 : os_abort(); - 1794 : } else { - 1795 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path); - 1796 : exit(EXIT_FAILURE); - 1797 : } - 1798 : /* LCOV_EXCL_STOP */ - 1799 : } - 1800 : - 1801 : while (1) { - 1802 : int c; + 1735 : /* adjust the stored crc to include itself */ + 1736 1 : crc_stored = crc32c(crc_stored, buf, 4); + 1737 : + 1738 1 : if (crc_computed != crc_stored) { + 1739 1 : log_fatal("Mismatching CRC in '%s'\n", path); + 1740 1 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 1741 1 : exit(EXIT_FAILURE); + 1742 : } else { + 1743 0 : log_fatal("The file CRC is correct!\n"); + 1744 : } + 1745 0 : } + 1746 : + 1747 254 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f) + 1748 : { + 1749 : block_off_t blockmax; + 1750 : unsigned count_file; + 1751 : unsigned count_hardlink; + 1752 : unsigned count_symlink; + 1753 : unsigned count_dir; + 1754 : int crc_checked; + 1755 : char buffer[PATH_MAX]; + 1756 : int ret; + 1757 : tommy_array disk_mapping; + 1758 : uint32_t mapping_max; + 1759 : + 1760 254 : blockmax = 0; + 1761 254 : count_file = 0; + 1762 254 : count_hardlink = 0; + 1763 254 : count_symlink = 0; + 1764 254 : count_dir = 0; + 1765 254 : crc_checked = 0; + 1766 254 : mapping_max = 0; + 1767 254 : tommy_array_init(&disk_mapping); + 1768 : + 1769 254 : ret = sread(f, buffer, 12); + 1770 254 : if (ret < 0) { + 1771 : /* LCOV_EXCL_START */ + 1772 : decoding_error(path, f); + 1773 : log_fatal("Invalid header!\n"); + 1774 : os_abort(); + 1775 : /* LCOV_EXCL_STOP */ + 1776 : } + 1777 : + 1778 : /* + 1779 : * File format versions: + 1780 : * - SNAPCNT1/SnapRAID 4.0 First version. + 1781 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support. + 1782 : * The previous 'm' entry is now deprecated, but supported for importing. + 1783 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'. + 1784 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'y' for hash size. + 1785 : * - SNAPCNT3/SnapRAID 11.0 Adds entry 'Q' for multi parity file. + 1786 : * The previous 'P' entry is now deprecated, but supported for importing. + 1787 : */ + 1788 254 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0 + 1789 254 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0 + 1790 254 : && memcmp(buffer, "SNAPCNT3\n\3\0\0", 12) != 0 + 1791 : ) { + 1792 : /* LCOV_EXCL_START */ + 1793 : if (memcmp(buffer, "SNAPCNT", 7) != 0) { + 1794 : decoding_error(path, f); + 1795 : log_fatal("Invalid header!\n"); + 1796 : os_abort(); + 1797 : } else { + 1798 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path); + 1799 : exit(EXIT_FAILURE); + 1800 : } + 1801 : /* LCOV_EXCL_STOP */ + 1802 : } 1803 : - 1804 : /* read the command */ - 1805 3735612 : c = sgetc(f); - 1806 3735612 : if (c == EOF) { - 1807 253 : break; - 1808 : } - 1809 : - 1810 3735359 : if (c == 'f') { - 1811 : /* file */ - 1812 : char sub[PATH_MAX]; - 1813 : uint64_t v_size; - 1814 : uint64_t v_mtime_sec; - 1815 : uint32_t v_mtime_nsec; - 1816 : uint64_t v_inode; - 1817 : uint32_t v_idx; - 1818 : struct snapraid_file* file; - 1819 : struct snapraid_disk* disk; - 1820 : uint32_t mapping; - 1821 : - 1822 3611762 : ret = sgetb32(f, &mapping); - 1823 3611762 : if (ret < 0 || mapping >= mapping_max) { - 1824 : /* LCOV_EXCL_START */ - 1825 : decoding_error(path, f); - 1826 : log_fatal("Internal inconsistency in mapping index!\n"); - 1827 : os_abort(); - 1828 : /* LCOV_EXCL_STOP */ - 1829 : } - 1830 3611762 : disk = tommy_array_get(&disk_mapping, mapping); - 1831 : - 1832 3611762 : ret = sgetb64(f, &v_size); - 1833 3611762 : if (ret < 0) { - 1834 : /* LCOV_EXCL_START */ - 1835 : decoding_error(path, f); - 1836 : os_abort(); - 1837 : /* LCOV_EXCL_STOP */ - 1838 : } - 1839 : - 1840 3611762 : if (state->block_size == 0) { - 1841 : /* LCOV_EXCL_START */ - 1842 : decoding_error(path, f); - 1843 : log_fatal("Internal incosistency due zero blocksize!\n"); - 1844 : exit(EXIT_FAILURE); - 1845 : /* LCOV_EXCL_STOP */ - 1846 : } - 1847 : - 1848 : /* check for impossible file size to avoid to crash for a too big allocation */ - 1849 3611762 : if (v_size / state->block_size > blockmax) { - 1850 : /* LCOV_EXCL_START */ - 1851 : decoding_error(path, f); - 1852 : log_fatal("Internal inconsistency in file size too big!\n"); - 1853 : os_abort(); - 1854 : /* LCOV_EXCL_STOP */ - 1855 : } - 1856 : - 1857 3611762 : ret = sgetb64(f, &v_mtime_sec); - 1858 3611762 : if (ret < 0) { - 1859 : /* LCOV_EXCL_START */ - 1860 : decoding_error(path, f); - 1861 : os_abort(); - 1862 : /* LCOV_EXCL_STOP */ - 1863 : } - 1864 : - 1865 3611762 : ret = sgetb32(f, &v_mtime_nsec); - 1866 3611762 : if (ret < 0) { - 1867 : /* LCOV_EXCL_START */ - 1868 : decoding_error(path, f); - 1869 : os_abort(); - 1870 : /* LCOV_EXCL_STOP */ - 1871 : } - 1872 : - 1873 : /* STAT_NSEC_INVALID is encoded as 0 */ - 1874 3611762 : if (v_mtime_nsec == 0) - 1875 0 : v_mtime_nsec = STAT_NSEC_INVALID; - 1876 : else - 1877 3611762 : --v_mtime_nsec; - 1878 : - 1879 3611762 : ret = sgetb64(f, &v_inode); - 1880 3611762 : if (ret < 0) { - 1881 : /* LCOV_EXCL_START */ - 1882 : decoding_error(path, f); - 1883 : os_abort(); - 1884 : /* LCOV_EXCL_STOP */ - 1885 : } - 1886 : - 1887 3611762 : ret = sgetbs(f, sub, sizeof(sub)); - 1888 3611762 : if (ret < 0) { - 1889 : /* LCOV_EXCL_START */ - 1890 : decoding_error(path, f); - 1891 : os_abort(); - 1892 : /* LCOV_EXCL_STOP */ - 1893 : } - 1894 3611762 : if (!*sub) { - 1895 : /* LCOV_EXCL_START */ - 1896 : decoding_error(path, f); - 1897 : log_fatal("Internal inconsistency for null file!\n"); - 1898 : os_abort(); - 1899 : /* LCOV_EXCL_STOP */ - 1900 : } - 1901 : - 1902 : /* allocate the file */ - 1903 3611762 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); + 1804 : while (1) { + 1805 : int c; + 1806 : + 1807 : /* read the command */ + 1808 3735613 : c = sgetc(f); + 1809 3735613 : if (c == EOF) { + 1810 253 : break; + 1811 : } + 1812 : + 1813 3735360 : if (c == 'f') { + 1814 : /* file */ + 1815 : char sub[PATH_MAX]; + 1816 : uint64_t v_size; + 1817 : uint64_t v_mtime_sec; + 1818 : uint32_t v_mtime_nsec; + 1819 : uint64_t v_inode; + 1820 : uint32_t v_idx; + 1821 : struct snapraid_file* file; + 1822 : struct snapraid_disk* disk; + 1823 : uint32_t mapping; + 1824 : + 1825 3611762 : ret = sgetb32(f, &mapping); + 1826 3611762 : if (ret < 0 || mapping >= mapping_max) { + 1827 : /* LCOV_EXCL_START */ + 1828 : decoding_error(path, f); + 1829 : log_fatal("Internal inconsistency in mapping index!\n"); + 1830 : os_abort(); + 1831 : /* LCOV_EXCL_STOP */ + 1832 : } + 1833 3611762 : disk = tommy_array_get(&disk_mapping, mapping); + 1834 : + 1835 3611762 : ret = sgetb64(f, &v_size); + 1836 3611762 : if (ret < 0) { + 1837 : /* LCOV_EXCL_START */ + 1838 : decoding_error(path, f); + 1839 : os_abort(); + 1840 : /* LCOV_EXCL_STOP */ + 1841 : } + 1842 : + 1843 3611762 : if (state->block_size == 0) { + 1844 : /* LCOV_EXCL_START */ + 1845 : decoding_error(path, f); + 1846 : log_fatal("Internal incosistency due zero blocksize!\n"); + 1847 : exit(EXIT_FAILURE); + 1848 : /* LCOV_EXCL_STOP */ + 1849 : } + 1850 : + 1851 : /* check for impossible file size to avoid to crash for a too big allocation */ + 1852 3611762 : if (v_size / state->block_size > blockmax) { + 1853 : /* LCOV_EXCL_START */ + 1854 : decoding_error(path, f); + 1855 : log_fatal("Internal inconsistency in file size too big!\n"); + 1856 : os_abort(); + 1857 : /* LCOV_EXCL_STOP */ + 1858 : } + 1859 : + 1860 3611762 : ret = sgetb64(f, &v_mtime_sec); + 1861 3611762 : if (ret < 0) { + 1862 : /* LCOV_EXCL_START */ + 1863 : decoding_error(path, f); + 1864 : os_abort(); + 1865 : /* LCOV_EXCL_STOP */ + 1866 : } + 1867 : + 1868 3611762 : ret = sgetb32(f, &v_mtime_nsec); + 1869 3611762 : if (ret < 0) { + 1870 : /* LCOV_EXCL_START */ + 1871 : decoding_error(path, f); + 1872 : os_abort(); + 1873 : /* LCOV_EXCL_STOP */ + 1874 : } + 1875 : + 1876 : /* STAT_NSEC_INVALID is encoded as 0 */ + 1877 3611762 : if (v_mtime_nsec == 0) + 1878 0 : v_mtime_nsec = STAT_NSEC_INVALID; + 1879 : else + 1880 3611762 : --v_mtime_nsec; + 1881 : + 1882 3611762 : ret = sgetb64(f, &v_inode); + 1883 3611762 : if (ret < 0) { + 1884 : /* LCOV_EXCL_START */ + 1885 : decoding_error(path, f); + 1886 : os_abort(); + 1887 : /* LCOV_EXCL_STOP */ + 1888 : } + 1889 : + 1890 3611762 : ret = sgetbs(f, sub, sizeof(sub)); + 1891 3611762 : if (ret < 0) { + 1892 : /* LCOV_EXCL_START */ + 1893 : decoding_error(path, f); + 1894 : os_abort(); + 1895 : /* LCOV_EXCL_STOP */ + 1896 : } + 1897 3611762 : if (!*sub) { + 1898 : /* LCOV_EXCL_START */ + 1899 : decoding_error(path, f); + 1900 : log_fatal("Internal inconsistency for null file!\n"); + 1901 : os_abort(); + 1902 : /* LCOV_EXCL_STOP */ + 1903 : } 1904 : - 1905 : /* insert the file in the file containers */ - 1906 3611762 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - 1907 3611762 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 1908 3611762 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); - 1909 3611762 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); - 1910 : - 1911 : /* read all the blocks */ - 1912 3611762 : v_idx = 0; - 1913 10855962 : while (v_idx < file->blockmax) { - 1914 : block_off_t v_pos; - 1915 : uint32_t v_count; - 1916 : - 1917 : /* get the "subcommand */ - 1918 3632438 : c = sgetc(f); + 1905 : /* allocate the file */ + 1906 3611762 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); + 1907 : + 1908 : /* insert the file in the file containers */ + 1909 3611762 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 1910 3611762 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 1911 3611762 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 1912 3611762 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 1913 : + 1914 : /* read all the blocks */ + 1915 3611762 : v_idx = 0; + 1916 10855984 : while (v_idx < file->blockmax) { + 1917 : block_off_t v_pos; + 1918 : uint32_t v_count; 1919 : - 1920 3632438 : ret = sgetb32(f, &v_pos); - 1921 3632438 : if (ret < 0) { - 1922 : /* LCOV_EXCL_START */ - 1923 : decoding_error(path, f); - 1924 : os_abort(); - 1925 : /* LCOV_EXCL_STOP */ - 1926 : } - 1927 : - 1928 3632438 : ret = sgetb32(f, &v_count); - 1929 3632438 : if (ret < 0) { - 1930 : /* LCOV_EXCL_START */ - 1931 : decoding_error(path, f); - 1932 : os_abort(); - 1933 : /* LCOV_EXCL_STOP */ - 1934 : } - 1935 : - 1936 3632438 : if (v_idx + v_count > file->blockmax) { - 1937 : /* LCOV_EXCL_START */ - 1938 : decoding_error(path, f); - 1939 : log_fatal("Internal inconsistency in block number!\n"); - 1940 : os_abort(); - 1941 : /* LCOV_EXCL_STOP */ - 1942 : } - 1943 : - 1944 3632438 : if (v_pos + v_count > blockmax) { - 1945 : /* LCOV_EXCL_START */ - 1946 : decoding_error(path, f); - 1947 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); - 1948 : os_abort(); - 1949 : /* LCOV_EXCL_START */ - 1950 : } - 1951 : - 1952 : /* fill the blocks in the run */ - 1953 : while (v_count) { - 1954 : struct snapraid_block* block = fs_file2block_get(file, v_idx); - 1955 : - 1956 : switch (c) { - 1957 : case 'b' : - 1958 : block_state_set(block, BLOCK_STATE_BLK); - 1959 : break; - 1960 : case 'n' : - 1961 : /* deprecated NEW blocks are converted to CHG ones */ - 1962 : block_state_set(block, BLOCK_STATE_CHG); - 1963 : break; - 1964 : case 'g' : + 1920 : /* get the "subcommand */ + 1921 3632460 : c = sgetc(f); + 1922 : + 1923 3632460 : ret = sgetb32(f, &v_pos); + 1924 3632460 : if (ret < 0) { + 1925 : /* LCOV_EXCL_START */ + 1926 : decoding_error(path, f); + 1927 : os_abort(); + 1928 : /* LCOV_EXCL_STOP */ + 1929 : } + 1930 : + 1931 3632460 : ret = sgetb32(f, &v_count); + 1932 3632460 : if (ret < 0) { + 1933 : /* LCOV_EXCL_START */ + 1934 : decoding_error(path, f); + 1935 : os_abort(); + 1936 : /* LCOV_EXCL_STOP */ + 1937 : } + 1938 : + 1939 3632460 : if (v_idx + v_count > file->blockmax) { + 1940 : /* LCOV_EXCL_START */ + 1941 : decoding_error(path, f); + 1942 : log_fatal("Internal inconsistency in block number!\n"); + 1943 : os_abort(); + 1944 : /* LCOV_EXCL_STOP */ + 1945 : } + 1946 : + 1947 3632460 : if (v_pos + v_count > blockmax) { + 1948 : /* LCOV_EXCL_START */ + 1949 : decoding_error(path, f); + 1950 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); + 1951 : os_abort(); + 1952 : /* LCOV_EXCL_START */ + 1953 : } + 1954 : + 1955 : /* fill the blocks in the run */ + 1956 : while (v_count) { + 1957 : struct snapraid_block* block = fs_file2block_get(file, v_idx); + 1958 : + 1959 : switch (c) { + 1960 : case 'b' : + 1961 : block_state_set(block, BLOCK_STATE_BLK); + 1962 : break; + 1963 : case 'n' : + 1964 : /* deprecated NEW blocks are converted to CHG ones */ 1965 : block_state_set(block, BLOCK_STATE_CHG); 1966 : break; - 1967 : case 'p' : - 1968 : block_state_set(block, BLOCK_STATE_REP); + 1967 : case 'g' : + 1968 : block_state_set(block, BLOCK_STATE_CHG); 1969 : break; - 1970 : default : - 1971 : /* LCOV_EXCL_START */ - 1972 : decoding_error(path, f); - 1973 : log_fatal("Invalid block type!\n"); - 1974 : os_abort(); - 1975 : /* LCOV_EXCL_STOP */ - 1976 : } - 1977 : - 1978 : /* read the hash only for 'blk/chg/rep', and not for 'new' */ - 1979 8896100 : if (c != 'n') { - 1980 8896100 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); - 1981 8896100 : if (ret < 0) { - 1982 : /* LCOV_EXCL_START */ - 1983 : decoding_error(path, f); - 1984 : os_abort(); - 1985 : /* LCOV_EXCL_STOP */ - 1986 : } - 1987 : } else { - 1988 : /* set the ZERO hash for deprecated NEW blocks */ - 1989 0 : hash_zero_set(block->hash); - 1990 : } - 1991 : - 1992 : /* if the block contains a hash of past data */ - 1993 : /* and we are clearing such indeterminate hashes */ - 1994 8896100 : if (state->clear_past_hash - 1995 2542004 : && block_has_past_hash(block) - 1996 : ) { - 1997 : /* set the hash value to INVALID */ - 1998 28006 : hash_invalid_set(block->hash); - 1999 : } - 2000 : - 2001 : /* if we are disabling the copy optimization */ - 2002 : /* we want also to clear any already previously stored information */ - 2003 : /* in other sync commands */ - 2004 : /* note that this is required only in sync, and we detect */ - 2005 : /* this using the clear_past_hash flag */ - 2006 8896100 : if (state->clear_past_hash - 2007 2542004 : && state->opt.force_nocopy - 2008 14195 : && block_state_get(block) == BLOCK_STATE_REP - 2009 : ) { - 2010 : /* set the hash value to INVALID */ - 2011 1 : hash_invalid_set(block->hash); - 2012 : /* convert from REP to CHG block */ - 2013 1 : block_state_set(block, BLOCK_STATE_CHG); - 2014 : } - 2015 : - 2016 : /* if we want a full reallocation, marks block as invalid parity */ - 2017 : /* note that we do this after the force_nocopy option */ - 2018 : /* to avoid to mixup the two things */ - 2019 8896100 : if (state->opt.force_realloc - 2020 27826 : && block_state_get(block) == BLOCK_STATE_BLK) { - 2021 : /* convert from BLK to REP */ - 2022 27826 : block_state_set(block, BLOCK_STATE_REP); - 2023 : } - 2024 : - 2025 : /* set the parity association */ - 2026 8896100 : fs_allocate(disk, v_pos, file, v_idx); + 1970 : case 'p' : + 1971 : block_state_set(block, BLOCK_STATE_REP); + 1972 : break; + 1973 : default : + 1974 : /* LCOV_EXCL_START */ + 1975 : decoding_error(path, f); + 1976 : log_fatal("Invalid block type!\n"); + 1977 : os_abort(); + 1978 : /* LCOV_EXCL_STOP */ + 1979 : } + 1980 : + 1981 : /* read the hash only for 'blk/chg/rep', and not for 'new' */ + 1982 8896100 : if (c != 'n') { + 1983 8896100 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); + 1984 8896100 : if (ret < 0) { + 1985 : /* LCOV_EXCL_START */ + 1986 : decoding_error(path, f); + 1987 : os_abort(); + 1988 : /* LCOV_EXCL_STOP */ + 1989 : } + 1990 : } else { + 1991 : /* set the ZERO hash for deprecated NEW blocks */ + 1992 0 : hash_zero_set(block->hash); + 1993 : } + 1994 : + 1995 : /* if the block contains a hash of past data */ + 1996 : /* and we are clearing such indeterminate hashes */ + 1997 8896100 : if (state->clear_past_hash + 1998 2542004 : && block_has_past_hash(block) + 1999 : ) { + 2000 : /* set the hash value to INVALID */ + 2001 28006 : hash_invalid_set(block->hash); + 2002 : } + 2003 : + 2004 : /* if we are disabling the copy optimization */ + 2005 : /* we want also to clear any already previously stored information */ + 2006 : /* in other sync commands */ + 2007 : /* note that this is required only in sync, and we detect */ + 2008 : /* this using the clear_past_hash flag */ + 2009 8896100 : if (state->clear_past_hash + 2010 2542004 : && state->opt.force_nocopy + 2011 14195 : && block_state_get(block) == BLOCK_STATE_REP + 2012 : ) { + 2013 : /* set the hash value to INVALID */ + 2014 1 : hash_invalid_set(block->hash); + 2015 : /* convert from REP to CHG block */ + 2016 1 : block_state_set(block, BLOCK_STATE_CHG); + 2017 : } + 2018 : + 2019 : /* if we want a full reallocation, marks block as invalid parity */ + 2020 : /* note that we do this after the force_nocopy option */ + 2021 : /* to avoid to mixup the two things */ + 2022 8896100 : if (state->opt.force_realloc + 2023 27826 : && block_state_get(block) == BLOCK_STATE_BLK) { + 2024 : /* convert from BLK to REP */ + 2025 27826 : block_state_set(block, BLOCK_STATE_REP); + 2026 : } 2027 : - 2028 : /* go to the next block */ - 2029 8896100 : ++v_idx; - 2030 8896100 : ++v_pos; - 2031 8896100 : --v_count; - 2032 : } - 2033 : } - 2034 : - 2035 : /* stat */ - 2036 3611762 : ++count_file; - 2037 123597 : } else if (c == 'i') { - 2038 : /* "inf" command */ - 2039 : snapraid_info info; - 2040 : uint32_t v_pos; - 2041 : uint32_t v_oldest; - 2042 : - 2043 253 : ret = sgetb32(f, &v_oldest); - 2044 253 : if (ret < 0) { - 2045 : /* LCOV_EXCL_START */ - 2046 : decoding_error(path, f); - 2047 : os_abort(); - 2048 : /* LCOV_EXCL_STOP */ - 2049 : } - 2050 : - 2051 253 : v_pos = 0; - 2052 55893 : while (v_pos < blockmax) { - 2053 : int bad; - 2054 : int rehash; - 2055 : int justsynced; - 2056 : uint32_t t; - 2057 : uint32_t flag; - 2058 : uint32_t v_count; - 2059 : - 2060 55387 : ret = sgetb32(f, &v_count); - 2061 55387 : if (ret < 0) { - 2062 : /* LCOV_EXCL_START */ - 2063 : decoding_error(path, f); - 2064 : os_abort(); - 2065 : /* LCOV_EXCL_STOP */ - 2066 : } - 2067 : - 2068 55387 : if (v_pos + v_count > blockmax) { - 2069 : /* LCOV_EXCL_START */ - 2070 : decoding_error(path, f); - 2071 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); - 2072 : os_abort(); - 2073 : /* LCOV_EXCL_STOP */ - 2074 : } - 2075 : - 2076 55387 : ret = sgetb32(f, &flag); - 2077 55387 : if (ret < 0) { - 2078 : /* LCOV_EXCL_START */ - 2079 : decoding_error(path, f); - 2080 : os_abort(); - 2081 : /* LCOV_EXCL_STOP */ - 2082 : } - 2083 : - 2084 : /* if there is an info */ - 2085 55387 : if ((flag & 1) != 0) { - 2086 : /* read the time */ - 2087 55372 : ret = sgetb32(f, &t); - 2088 55372 : if (ret < 0) { - 2089 : /* LCOV_EXCL_START */ - 2090 : decoding_error(path, f); - 2091 : os_abort(); - 2092 : /* LCOV_EXCL_STOP */ - 2093 : } - 2094 : - 2095 : /* analyze the flags */ - 2096 55372 : bad = (flag & 2) != 0; - 2097 55372 : rehash = (flag & 4) != 0; - 2098 55372 : justsynced = (flag & 8) != 0; - 2099 : - 2100 55372 : if (rehash && state->prevhash == HASH_UNDEFINED) { - 2101 : /* LCOV_EXCL_START */ - 2102 : decoding_error(path, f); - 2103 : log_fatal("Internal inconsistency for missing previous checksum!\n"); - 2104 : os_abort(); - 2105 : /* LCOV_EXCL_STOP */ - 2106 : } - 2107 : - 2108 55372 : info = info_make(t + v_oldest, bad, rehash, justsynced); - 2109 : } else { - 2110 15 : info = 0; - 2111 : } - 2112 : - 2113 1658697 : while (v_count) { - 2114 : /* insert the info in the array */ - 2115 1547923 : info_set(&state->infoarr, v_pos, info); - 2116 : - 2117 : /* ensure that an info is present only for used positions */ - 2118 1547923 : if (fs_info_is_required(state, v_pos)) { - 2119 1489158 : if (!info) { - 2120 : /* LCOV_EXCL_START */ - 2121 : decoding_error(path, f); - 2122 : log_fatal("Internal inconsistency for missing info!\n"); - 2123 : os_abort(); - 2124 : /* LCOV_EXCL_STOP */ - 2125 : } - 2126 : } else { - 2127 : /* extra info are accepted for backward compatibility */ - 2128 : /* they are discarded at the first write */ - 2129 : } - 2130 : - 2131 : /* go to next block */ - 2132 1547923 : ++v_pos; - 2133 1547923 : --v_count; - 2134 : } - 2135 : } - 2136 123344 : } else if (c == 'h') { - 2137 : /* hole */ - 2138 : uint32_t v_pos; - 2139 : struct snapraid_disk* disk; - 2140 : uint32_t mapping; - 2141 : - 2142 1397 : ret = sgetb32(f, &mapping); - 2143 1397 : if (ret < 0 || mapping >= mapping_max) { - 2144 : /* LCOV_EXCL_START */ - 2145 : decoding_error(path, f); - 2146 : log_fatal("Internal inconsistency in mapping index!\n"); - 2147 : os_abort(); - 2148 : /* LCOV_EXCL_STOP */ - 2149 : } - 2150 1397 : disk = tommy_array_get(&disk_mapping, mapping); - 2151 : - 2152 1397 : v_pos = 0; - 2153 4257 : while (v_pos < blockmax) { - 2154 : uint32_t v_idx; - 2155 : uint32_t v_count; - 2156 : struct snapraid_file* deleted; - 2157 : - 2158 1463 : ret = sgetb32(f, &v_count); - 2159 1463 : if (ret < 0) { - 2160 : /* LCOV_EXCL_START */ - 2161 : decoding_error(path, f); - 2162 : os_abort(); - 2163 : /* LCOV_EXCL_STOP */ - 2164 : } - 2165 : - 2166 1463 : if (v_pos + v_count > blockmax) { - 2167 : /* LCOV_EXCL_START */ - 2168 : decoding_error(path, f); - 2169 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); - 2170 : os_abort(); - 2171 : /* LCOV_EXCL_STOP */ - 2172 : } - 2173 : - 2174 : /* get the sub-command */ - 2175 1463 : c = sgetc(f); + 2028 : /* set the parity association */ + 2029 8896100 : fs_allocate(disk, v_pos, file, v_idx); + 2030 : + 2031 : /* go to the next block */ + 2032 8896100 : ++v_idx; + 2033 8896100 : ++v_pos; + 2034 8896100 : --v_count; + 2035 : } + 2036 : } + 2037 : + 2038 : /* stat */ + 2039 3611762 : ++count_file; + 2040 123598 : } else if (c == 'i') { + 2041 : /* "inf" command */ + 2042 : snapraid_info info; + 2043 : uint32_t v_pos; + 2044 : uint32_t v_oldest; + 2045 : + 2046 253 : ret = sgetb32(f, &v_oldest); + 2047 253 : if (ret < 0) { + 2048 : /* LCOV_EXCL_START */ + 2049 : decoding_error(path, f); + 2050 : os_abort(); + 2051 : /* LCOV_EXCL_STOP */ + 2052 : } + 2053 : + 2054 253 : v_pos = 0; + 2055 55856 : while (v_pos < blockmax) { + 2056 : int bad; + 2057 : int rehash; + 2058 : int justsynced; + 2059 : uint32_t t; + 2060 : uint32_t flag; + 2061 : uint32_t v_count; + 2062 : + 2063 55350 : ret = sgetb32(f, &v_count); + 2064 55350 : if (ret < 0) { + 2065 : /* LCOV_EXCL_START */ + 2066 : decoding_error(path, f); + 2067 : os_abort(); + 2068 : /* LCOV_EXCL_STOP */ + 2069 : } + 2070 : + 2071 55350 : if (v_pos + v_count > blockmax) { + 2072 : /* LCOV_EXCL_START */ + 2073 : decoding_error(path, f); + 2074 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); + 2075 : os_abort(); + 2076 : /* LCOV_EXCL_STOP */ + 2077 : } + 2078 : + 2079 55350 : ret = sgetb32(f, &flag); + 2080 55350 : if (ret < 0) { + 2081 : /* LCOV_EXCL_START */ + 2082 : decoding_error(path, f); + 2083 : os_abort(); + 2084 : /* LCOV_EXCL_STOP */ + 2085 : } + 2086 : + 2087 : /* if there is an info */ + 2088 55350 : if ((flag & 1) != 0) { + 2089 : /* read the time */ + 2090 55335 : ret = sgetb32(f, &t); + 2091 55335 : if (ret < 0) { + 2092 : /* LCOV_EXCL_START */ + 2093 : decoding_error(path, f); + 2094 : os_abort(); + 2095 : /* LCOV_EXCL_STOP */ + 2096 : } + 2097 : + 2098 : /* analyze the flags */ + 2099 55335 : bad = (flag & 2) != 0; + 2100 55335 : rehash = (flag & 4) != 0; + 2101 55335 : justsynced = (flag & 8) != 0; + 2102 : + 2103 55335 : if (rehash && state->prevhash == HASH_UNDEFINED) { + 2104 : /* LCOV_EXCL_START */ + 2105 : decoding_error(path, f); + 2106 : log_fatal("Internal inconsistency for missing previous checksum!\n"); + 2107 : os_abort(); + 2108 : /* LCOV_EXCL_STOP */ + 2109 : } + 2110 : + 2111 55335 : info = info_make(t + v_oldest, bad, rehash, justsynced); + 2112 : } else { + 2113 15 : info = 0; + 2114 : } + 2115 : + 2116 1658623 : while (v_count) { + 2117 : /* insert the info in the array */ + 2118 1547923 : info_set(&state->infoarr, v_pos, info); + 2119 : + 2120 : /* ensure that an info is present only for used positions */ + 2121 1547923 : if (fs_info_is_required(state, v_pos)) { + 2122 1489158 : if (!info) { + 2123 : /* LCOV_EXCL_START */ + 2124 : decoding_error(path, f); + 2125 : log_fatal("Internal inconsistency for missing info!\n"); + 2126 : os_abort(); + 2127 : /* LCOV_EXCL_STOP */ + 2128 : } + 2129 : } else { + 2130 : /* extra info are accepted for backward compatibility */ + 2131 : /* they are discarded at the first write */ + 2132 : } + 2133 : + 2134 : /* go to next block */ + 2135 1547923 : ++v_pos; + 2136 1547923 : --v_count; + 2137 : } + 2138 : } + 2139 123345 : } else if (c == 'h') { + 2140 : /* hole */ + 2141 : uint32_t v_pos; + 2142 : struct snapraid_disk* disk; + 2143 : uint32_t mapping; + 2144 : + 2145 1397 : ret = sgetb32(f, &mapping); + 2146 1397 : if (ret < 0 || mapping >= mapping_max) { + 2147 : /* LCOV_EXCL_START */ + 2148 : decoding_error(path, f); + 2149 : log_fatal("Internal inconsistency in mapping index!\n"); + 2150 : os_abort(); + 2151 : /* LCOV_EXCL_STOP */ + 2152 : } + 2153 1397 : disk = tommy_array_get(&disk_mapping, mapping); + 2154 : + 2155 1397 : v_pos = 0; + 2156 4257 : while (v_pos < blockmax) { + 2157 : uint32_t v_idx; + 2158 : uint32_t v_count; + 2159 : struct snapraid_file* deleted; + 2160 : + 2161 1463 : ret = sgetb32(f, &v_count); + 2162 1463 : if (ret < 0) { + 2163 : /* LCOV_EXCL_START */ + 2164 : decoding_error(path, f); + 2165 : os_abort(); + 2166 : /* LCOV_EXCL_STOP */ + 2167 : } + 2168 : + 2169 1463 : if (v_pos + v_count > blockmax) { + 2170 : /* LCOV_EXCL_START */ + 2171 : decoding_error(path, f); + 2172 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); + 2173 : os_abort(); + 2174 : /* LCOV_EXCL_STOP */ + 2175 : } 2176 : - 2177 1463 : switch (c) { - 2178 : case 'o' : - 2179 : /* if it's a run of deleted blocks */ - 2180 : - 2181 : /* allocate a fake deleted file */ - 2182 35 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0); + 2177 : /* get the sub-command */ + 2178 1463 : c = sgetc(f); + 2179 : + 2180 1463 : switch (c) { + 2181 : case 'o' : + 2182 : /* if it's a run of deleted blocks */ 2183 : - 2184 : /* mark the file as deleted */ - 2185 35 : file_flag_set(deleted, FILE_IS_DELETED); + 2184 : /* allocate a fake deleted file */ + 2185 35 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0); 2186 : - 2187 : /* insert it in the list of deleted files */ - 2188 35 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted); + 2187 : /* mark the file as deleted */ + 2188 35 : file_flag_set(deleted, FILE_IS_DELETED); 2189 : - 2190 : /* process all blocks */ - 2191 35 : v_idx = 0; - 2192 27956 : while (v_count) { - 2193 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx); - 2194 : - 2195 : /* set the block as deleted */ - 2196 27886 : block_state_set(block, BLOCK_STATE_DELETED); + 2190 : /* insert it in the list of deleted files */ + 2191 35 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted); + 2192 : + 2193 : /* process all blocks */ + 2194 35 : v_idx = 0; + 2195 27956 : while (v_count) { + 2196 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx); 2197 : - 2198 : /* read the hash */ - 2199 27886 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); - 2200 27886 : if (ret < 0) { - 2201 : /* LCOV_EXCL_START */ - 2202 : decoding_error(path, f); - 2203 : os_abort(); - 2204 : /* LCOV_EXCL_STOP */ - 2205 : } - 2206 : - 2207 : /* if we are clearing indeterminate hashes */ - 2208 27886 : if (state->clear_past_hash) { - 2209 : /* set the hash value to INVALID */ - 2210 9432 : hash_invalid_set(block->hash); - 2211 : } - 2212 : - 2213 : /* insert the block in the block array */ - 2214 27886 : fs_allocate(disk, v_pos, deleted, v_idx); + 2198 : /* set the block as deleted */ + 2199 27886 : block_state_set(block, BLOCK_STATE_DELETED); + 2200 : + 2201 : /* read the hash */ + 2202 27886 : ret = sread(f, block->hash, BLOCK_HASH_SIZE); + 2203 27886 : if (ret < 0) { + 2204 : /* LCOV_EXCL_START */ + 2205 : decoding_error(path, f); + 2206 : os_abort(); + 2207 : /* LCOV_EXCL_STOP */ + 2208 : } + 2209 : + 2210 : /* if we are clearing indeterminate hashes */ + 2211 27886 : if (state->clear_past_hash) { + 2212 : /* set the hash value to INVALID */ + 2213 9432 : hash_invalid_set(block->hash); + 2214 : } 2215 : - 2216 : /* go to next block */ - 2217 27886 : ++v_pos; - 2218 27886 : ++v_idx; - 2219 27886 : --v_count; - 2220 : } - 2221 35 : break; - 2222 : case 'O' : - 2223 : /* go to the next run */ - 2224 1428 : v_pos += v_count; - 2225 1428 : break; - 2226 : default : - 2227 : /* LCOV_EXCL_START */ - 2228 : decoding_error(path, f); - 2229 : log_fatal("Invalid hole type!\n"); - 2230 : os_abort(); - 2231 : /* LCOV_EXCL_STOP */ - 2232 : } - 2233 : } - 2234 121947 : } else if (c == 's') { - 2235 : /* symlink */ - 2236 : char sub[PATH_MAX]; - 2237 : char linkto[PATH_MAX]; - 2238 : struct snapraid_link* slink; - 2239 : struct snapraid_disk* disk; - 2240 : uint32_t mapping; - 2241 : - 2242 116468 : ret = sgetb32(f, &mapping); - 2243 116468 : if (ret < 0 || mapping >= mapping_max) { - 2244 : /* LCOV_EXCL_START */ - 2245 : decoding_error(path, f); - 2246 : log_fatal("Internal inconsistency in mapping index!\n"); - 2247 : os_abort(); - 2248 : /* LCOV_EXCL_STOP */ - 2249 : } - 2250 116468 : disk = tommy_array_get(&disk_mapping, mapping); - 2251 : - 2252 116468 : ret = sgetbs(f, sub, sizeof(sub)); - 2253 116468 : if (ret < 0) { - 2254 : /* LCOV_EXCL_START */ - 2255 : decoding_error(path, f); - 2256 : os_abort(); - 2257 : /* LCOV_EXCL_STOP */ - 2258 : } - 2259 : - 2260 116468 : if (!*sub) { - 2261 : /* LCOV_EXCL_START */ - 2262 : decoding_error(path, f); - 2263 : log_fatal("Internal inconsistency for null symlink!\n"); - 2264 : os_abort(); - 2265 : /* LCOV_EXCL_STOP */ - 2266 : } - 2267 : - 2268 116468 : ret = sgetbs(f, linkto, sizeof(linkto)); - 2269 116468 : if (ret < 0) { - 2270 : /* LCOV_EXCL_START */ - 2271 : decoding_error(path, f); - 2272 : os_abort(); - 2273 : /* LCOV_EXCL_STOP */ - 2274 : } - 2275 : - 2276 : /* allocate the link as symbolic link */ - 2277 116468 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK); + 2216 : /* insert the block in the block array */ + 2217 27886 : fs_allocate(disk, v_pos, deleted, v_idx); + 2218 : + 2219 : /* go to next block */ + 2220 27886 : ++v_pos; + 2221 27886 : ++v_idx; + 2222 27886 : --v_count; + 2223 : } + 2224 35 : break; + 2225 : case 'O' : + 2226 : /* go to the next run */ + 2227 1428 : v_pos += v_count; + 2228 1428 : break; + 2229 : default : + 2230 : /* LCOV_EXCL_START */ + 2231 : decoding_error(path, f); + 2232 : log_fatal("Invalid hole type!\n"); + 2233 : os_abort(); + 2234 : /* LCOV_EXCL_STOP */ + 2235 : } + 2236 : } + 2237 121948 : } else if (c == 's') { + 2238 : /* symlink */ + 2239 : char sub[PATH_MAX]; + 2240 : char linkto[PATH_MAX]; + 2241 : struct snapraid_link* slink; + 2242 : struct snapraid_disk* disk; + 2243 : uint32_t mapping; + 2244 : + 2245 116468 : ret = sgetb32(f, &mapping); + 2246 116468 : if (ret < 0 || mapping >= mapping_max) { + 2247 : /* LCOV_EXCL_START */ + 2248 : decoding_error(path, f); + 2249 : log_fatal("Internal inconsistency in mapping index!\n"); + 2250 : os_abort(); + 2251 : /* LCOV_EXCL_STOP */ + 2252 : } + 2253 116468 : disk = tommy_array_get(&disk_mapping, mapping); + 2254 : + 2255 116468 : ret = sgetbs(f, sub, sizeof(sub)); + 2256 116468 : if (ret < 0) { + 2257 : /* LCOV_EXCL_START */ + 2258 : decoding_error(path, f); + 2259 : os_abort(); + 2260 : /* LCOV_EXCL_STOP */ + 2261 : } + 2262 : + 2263 116468 : if (!*sub) { + 2264 : /* LCOV_EXCL_START */ + 2265 : decoding_error(path, f); + 2266 : log_fatal("Internal inconsistency for null symlink!\n"); + 2267 : os_abort(); + 2268 : /* LCOV_EXCL_STOP */ + 2269 : } + 2270 : + 2271 116468 : ret = sgetbs(f, linkto, sizeof(linkto)); + 2272 116468 : if (ret < 0) { + 2273 : /* LCOV_EXCL_START */ + 2274 : decoding_error(path, f); + 2275 : os_abort(); + 2276 : /* LCOV_EXCL_STOP */ + 2277 : } 2278 : - 2279 : /* insert the link in the link containers */ - 2280 116468 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); - 2281 116468 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); - 2282 : - 2283 : /* stat */ - 2284 116468 : ++count_symlink; - 2285 5479 : } else if (c == 'a') { - 2286 : /* hardlink */ - 2287 : char sub[PATH_MAX]; - 2288 : char linkto[PATH_MAX]; - 2289 : struct snapraid_link* slink; - 2290 : struct snapraid_disk* disk; - 2291 : uint32_t mapping; - 2292 : - 2293 597 : ret = sgetb32(f, &mapping); - 2294 597 : if (ret < 0 || mapping >= mapping_max) { - 2295 : /* LCOV_EXCL_START */ - 2296 : decoding_error(path, f); - 2297 : log_fatal("Internal inconsistency in mapping index!\n"); - 2298 : os_abort(); - 2299 : /* LCOV_EXCL_STOP */ - 2300 : } - 2301 597 : disk = tommy_array_get(&disk_mapping, mapping); - 2302 : - 2303 597 : ret = sgetbs(f, sub, sizeof(sub)); - 2304 597 : if (ret < 0) { - 2305 : /* LCOV_EXCL_START */ - 2306 : decoding_error(path, f); - 2307 : os_abort(); - 2308 : /* LCOV_EXCL_STOP */ - 2309 : } - 2310 : - 2311 597 : if (!*sub) { - 2312 : /* LCOV_EXCL_START */ - 2313 : decoding_error(path, f); - 2314 : log_fatal("Internal inconsistency for null hardlink!\n"); - 2315 : os_abort(); - 2316 : /* LCOV_EXCL_STOP */ - 2317 : } - 2318 : - 2319 597 : ret = sgetbs(f, linkto, sizeof(linkto)); - 2320 597 : if (ret < 0) { - 2321 : /* LCOV_EXCL_START */ - 2322 : decoding_error(path, f); - 2323 : os_abort(); - 2324 : /* LCOV_EXCL_STOP */ - 2325 : } - 2326 : - 2327 597 : if (!*linkto) { - 2328 : /* LCOV_EXCL_START */ - 2329 : decoding_error(path, f); - 2330 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub); - 2331 : os_abort(); - 2332 : /* LCOV_EXCL_STOP */ - 2333 : } - 2334 : - 2335 : /* allocate the link as hard link */ - 2336 597 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK); + 2279 : /* allocate the link as symbolic link */ + 2280 116468 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK); + 2281 : + 2282 : /* insert the link in the link containers */ + 2283 116468 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + 2284 116468 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + 2285 : + 2286 : /* stat */ + 2287 116468 : ++count_symlink; + 2288 5480 : } else if (c == 'a') { + 2289 : /* hardlink */ + 2290 : char sub[PATH_MAX]; + 2291 : char linkto[PATH_MAX]; + 2292 : struct snapraid_link* slink; + 2293 : struct snapraid_disk* disk; + 2294 : uint32_t mapping; + 2295 : + 2296 597 : ret = sgetb32(f, &mapping); + 2297 597 : if (ret < 0 || mapping >= mapping_max) { + 2298 : /* LCOV_EXCL_START */ + 2299 : decoding_error(path, f); + 2300 : log_fatal("Internal inconsistency in mapping index!\n"); + 2301 : os_abort(); + 2302 : /* LCOV_EXCL_STOP */ + 2303 : } + 2304 597 : disk = tommy_array_get(&disk_mapping, mapping); + 2305 : + 2306 597 : ret = sgetbs(f, sub, sizeof(sub)); + 2307 597 : if (ret < 0) { + 2308 : /* LCOV_EXCL_START */ + 2309 : decoding_error(path, f); + 2310 : os_abort(); + 2311 : /* LCOV_EXCL_STOP */ + 2312 : } + 2313 : + 2314 597 : if (!*sub) { + 2315 : /* LCOV_EXCL_START */ + 2316 : decoding_error(path, f); + 2317 : log_fatal("Internal inconsistency for null hardlink!\n"); + 2318 : os_abort(); + 2319 : /* LCOV_EXCL_STOP */ + 2320 : } + 2321 : + 2322 597 : ret = sgetbs(f, linkto, sizeof(linkto)); + 2323 597 : if (ret < 0) { + 2324 : /* LCOV_EXCL_START */ + 2325 : decoding_error(path, f); + 2326 : os_abort(); + 2327 : /* LCOV_EXCL_STOP */ + 2328 : } + 2329 : + 2330 597 : if (!*linkto) { + 2331 : /* LCOV_EXCL_START */ + 2332 : decoding_error(path, f); + 2333 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub); + 2334 : os_abort(); + 2335 : /* LCOV_EXCL_STOP */ + 2336 : } 2337 : - 2338 : /* insert the link in the link containers */ - 2339 597 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); - 2340 597 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); - 2341 : - 2342 : /* stat */ - 2343 597 : ++count_hardlink; - 2344 4882 : } else if (c == 'r') { - 2345 : /* dir */ - 2346 : char sub[PATH_MAX]; - 2347 : struct snapraid_dir* dir; - 2348 : struct snapraid_disk* disk; - 2349 : uint32_t mapping; - 2350 : - 2351 790 : ret = sgetb32(f, &mapping); - 2352 790 : if (ret < 0 || mapping >= mapping_max) { - 2353 : /* LCOV_EXCL_START */ - 2354 : decoding_error(path, f); - 2355 : log_fatal("Internal inconsistency in mapping index!\n"); - 2356 : os_abort(); - 2357 : /* LCOV_EXCL_STOP */ - 2358 : } - 2359 790 : disk = tommy_array_get(&disk_mapping, mapping); - 2360 : - 2361 790 : ret = sgetbs(f, sub, sizeof(sub)); - 2362 790 : if (ret < 0) { - 2363 : /* LCOV_EXCL_START */ - 2364 : decoding_error(path, f); - 2365 : os_abort(); - 2366 : /* LCOV_EXCL_STOP */ - 2367 : } - 2368 : - 2369 790 : if (!*sub) { - 2370 : /* LCOV_EXCL_START */ - 2371 : decoding_error(path, f); - 2372 : log_fatal("Internal inconsistency for null dir!\n"); - 2373 : os_abort(); - 2374 : /* LCOV_EXCL_STOP */ - 2375 : } - 2376 : - 2377 : /* allocate the dir */ - 2378 790 : dir = dir_alloc(sub); + 2338 : /* allocate the link as hard link */ + 2339 597 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK); + 2340 : + 2341 : /* insert the link in the link containers */ + 2342 597 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + 2343 597 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + 2344 : + 2345 : /* stat */ + 2346 597 : ++count_hardlink; + 2347 4883 : } else if (c == 'r') { + 2348 : /* dir */ + 2349 : char sub[PATH_MAX]; + 2350 : struct snapraid_dir* dir; + 2351 : struct snapraid_disk* disk; + 2352 : uint32_t mapping; + 2353 : + 2354 790 : ret = sgetb32(f, &mapping); + 2355 790 : if (ret < 0 || mapping >= mapping_max) { + 2356 : /* LCOV_EXCL_START */ + 2357 : decoding_error(path, f); + 2358 : log_fatal("Internal inconsistency in mapping index!\n"); + 2359 : os_abort(); + 2360 : /* LCOV_EXCL_STOP */ + 2361 : } + 2362 790 : disk = tommy_array_get(&disk_mapping, mapping); + 2363 : + 2364 790 : ret = sgetbs(f, sub, sizeof(sub)); + 2365 790 : if (ret < 0) { + 2366 : /* LCOV_EXCL_START */ + 2367 : decoding_error(path, f); + 2368 : os_abort(); + 2369 : /* LCOV_EXCL_STOP */ + 2370 : } + 2371 : + 2372 790 : if (!*sub) { + 2373 : /* LCOV_EXCL_START */ + 2374 : decoding_error(path, f); + 2375 : log_fatal("Internal inconsistency for null dir!\n"); + 2376 : os_abort(); + 2377 : /* LCOV_EXCL_STOP */ + 2378 : } 2379 : - 2380 : /* insert the dir in the dir containers */ - 2381 790 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); - 2382 790 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); - 2383 : - 2384 : /* stat */ - 2385 790 : ++count_dir; - 2386 4092 : } else if (c == 'c') { - 2387 : /* get the subcommand */ - 2388 254 : c = sgetc(f); - 2389 : - 2390 254 : switch (c) { - 2391 : case 'u' : - 2392 166 : state->hash = HASH_MURMUR3; - 2393 166 : break; - 2394 : case 'k' : - 2395 88 : state->hash = HASH_SPOOKY2; - 2396 88 : break; - 2397 : default : - 2398 : /* LCOV_EXCL_START */ - 2399 : decoding_error(path, f); - 2400 : log_fatal("Invalid checksum!\n"); - 2401 : os_abort(); - 2402 : /* LCOV_EXCL_STOP */ - 2403 : } - 2404 : - 2405 : /* read the seed */ - 2406 254 : ret = sread(f, state->hashseed, HASH_MAX); - 2407 254 : if (ret < 0) { - 2408 : /* LCOV_EXCL_START */ - 2409 : decoding_error(path, f); - 2410 : os_abort(); - 2411 : /* LCOV_EXCL_STOP */ - 2412 : } - 2413 3838 : } else if (c == 'C') { - 2414 : /* get the sub-command */ - 2415 4 : c = sgetc(f); - 2416 : - 2417 4 : switch (c) { - 2418 : case 'u' : - 2419 4 : state->prevhash = HASH_MURMUR3; - 2420 4 : break; - 2421 : case 'k' : - 2422 0 : state->prevhash = HASH_SPOOKY2; - 2423 0 : break; - 2424 : default : - 2425 : /* LCOV_EXCL_START */ - 2426 : decoding_error(path, f); - 2427 : log_fatal("Invalid checksum!\n"); - 2428 : os_abort(); - 2429 : /* LCOV_EXCL_STOP */ - 2430 : } - 2431 : - 2432 : /* read the seed */ - 2433 4 : ret = sread(f, state->prevhashseed, HASH_MAX); - 2434 4 : if (ret < 0) { - 2435 : /* LCOV_EXCL_START */ - 2436 : decoding_error(path, f); - 2437 : os_abort(); - 2438 : /* LCOV_EXCL_STOP */ - 2439 : } - 2440 3834 : } else if (c == 'z') { - 2441 : uint32_t block_size; - 2442 : - 2443 254 : ret = sgetb32(f, &block_size); - 2444 254 : if (ret < 0) { - 2445 : /* LCOV_EXCL_START */ - 2446 : decoding_error(path, f); - 2447 : os_abort(); - 2448 : /* LCOV_EXCL_STOP */ - 2449 : } - 2450 : - 2451 254 : if (block_size == 0) { - 2452 : /* LCOV_EXCL_START */ - 2453 : decoding_error(path, f); - 2454 : log_fatal("Zero 'blocksize' specification in the content file!\n"); - 2455 : exit(EXIT_FAILURE); - 2456 : /* LCOV_EXCL_STOP */ - 2457 : } - 2458 : - 2459 : /* without configuration, auto assign the block size */ - 2460 254 : if (state->no_conf) { - 2461 1 : state->block_size = block_size; - 2462 : } - 2463 : - 2464 254 : if (block_size != state->block_size) { - 2465 : /* LCOV_EXCL_START */ - 2466 : decoding_error(path, f); - 2467 : log_fatal("Mismatching 'blocksize' specification in the content file!\n"); - 2468 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", block_size / KIBI); - 2469 : exit(EXIT_FAILURE); - 2470 : /* LCOV_EXCL_STOP */ - 2471 : } - 2472 3580 : } else if (c == 'y') { - 2473 : uint32_t hash_size; - 2474 : - 2475 254 : ret = sgetb32(f, &hash_size); - 2476 254 : if (ret < 0) { - 2477 : /* LCOV_EXCL_START */ - 2478 : decoding_error(path, f); - 2479 : os_abort(); - 2480 : /* LCOV_EXCL_STOP */ - 2481 : } - 2482 : - 2483 254 : if (hash_size < 2 || hash_size > HASH_MAX) { - 2484 : /* LCOV_EXCL_START */ - 2485 : decoding_error(path, f); - 2486 : log_fatal("Invalid 'hashsize' specification in the content file!\n"); - 2487 : exit(EXIT_FAILURE); - 2488 : /* LCOV_EXCL_STOP */ - 2489 : } - 2490 : - 2491 : /* without configuration, auto assign the block size */ - 2492 254 : if (state->no_conf) { - 2493 1 : BLOCK_HASH_SIZE = hash_size; - 2494 : } - 2495 : - 2496 254 : if ((int)hash_size != BLOCK_HASH_SIZE) { - 2497 : /* LCOV_EXCL_START */ - 2498 : decoding_error(path, f); - 2499 : log_fatal("Mismatching 'hashsize' specification in the content file!\n"); - 2500 : log_fatal("Please restore the 'hashsize' value in the configuration file to '%u'\n", hash_size); - 2501 : exit(EXIT_FAILURE); - 2502 : /* LCOV_EXCL_STOP */ - 2503 : } - 2504 3326 : } else if (c == 'x') { - 2505 254 : ret = sgetb32(f, &blockmax); - 2506 254 : if (ret < 0) { - 2507 : /* LCOV_EXCL_START */ - 2508 : decoding_error(path, f); - 2509 : os_abort(); - 2510 : /* LCOV_EXCL_STOP */ - 2511 : } - 2512 4475 : } else if (c == 'm' || c == 'M') { - 2513 : struct snapraid_map* map; - 2514 : char uuid[UUID_MAX]; - 2515 : uint32_t v_pos; - 2516 : uint32_t v_total_blocks; - 2517 : uint32_t v_free_blocks; - 2518 : struct snapraid_disk* disk; - 2519 : - 2520 1403 : ret = sgetbs(f, buffer, sizeof(buffer)); - 2521 1403 : if (ret < 0) { - 2522 : /* LCOV_EXCL_START */ - 2523 : decoding_error(path, f); - 2524 : os_abort(); - 2525 : /* LCOV_EXCL_STOP */ - 2526 : } - 2527 : - 2528 1403 : ret = sgetb32(f, &v_pos); - 2529 1403 : if (ret < 0) { - 2530 : /* LCOV_EXCL_START */ - 2531 : decoding_error(path, f); - 2532 : os_abort(); - 2533 : /* LCOV_EXCL_STOP */ - 2534 : } - 2535 : - 2536 : /* from SnapRAID 7.0 the 'M' command includes the free space */ - 2537 1403 : if (c == 'M') { - 2538 1403 : ret = sgetb32(f, &v_total_blocks); - 2539 1403 : if (ret < 0) { - 2540 : /* LCOV_EXCL_START */ - 2541 : decoding_error(path, f); - 2542 : os_abort(); - 2543 : /* LCOV_EXCL_STOP */ - 2544 : } - 2545 : - 2546 1403 : ret = sgetb32(f, &v_free_blocks); - 2547 1403 : if (ret < 0) { - 2548 : /* LCOV_EXCL_START */ - 2549 : decoding_error(path, f); - 2550 : os_abort(); - 2551 : /* LCOV_EXCL_STOP */ - 2552 : } - 2553 : } else { - 2554 0 : v_total_blocks = 0; - 2555 0 : v_free_blocks = 0; - 2556 : } - 2557 : - 2558 : /* read the uuid */ - 2559 1403 : ret = sgetbs(f, uuid, sizeof(uuid)); - 2560 1403 : if (ret < 0) { - 2561 : /* LCOV_EXCL_START */ - 2562 : decoding_error(path, f); - 2563 : os_abort(); - 2564 : /* LCOV_EXCL_STOP */ - 2565 : } - 2566 : - 2567 : /* find the disk */ - 2568 1403 : disk = find_disk_by_name(state, buffer); - 2569 1403 : if (!disk) { - 2570 : /* search by UUID if renamed */ - 2571 2 : disk = find_disk_by_uuid(state, uuid); - 2572 2 : if (disk) { - 2573 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name); - 2574 : - 2575 : /* write the new state with the new name */ - 2576 2 : state->need_write = 1; - 2577 : } - 2578 : } - 2579 1403 : if (!disk) { - 2580 : /* LCOV_EXCL_START */ - 2581 : decoding_error(path, f); - 2582 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid); - 2583 : log_fatal("If you have removed it from the configuration file, please restore it\n"); - 2584 : /* if it's a command without UUID, it cannot autorename using UUID */ - 2585 : if (state->opt.skip_disk_access) - 2586 : log_fatal("If you have renamed it, run 'sync' to update the new name\n"); - 2587 : exit(EXIT_FAILURE); - 2588 : /* LCOV_EXCL_STOP */ - 2589 : } - 2590 : - 2591 1403 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid); - 2592 : - 2593 1403 : tommy_list_insert_tail(&state->maplist, &map->node, map); - 2594 : - 2595 : /* insert in the mapping vector */ - 2596 1403 : tommy_array_grow(&disk_mapping, mapping_max + 1); - 2597 1403 : tommy_array_set(&disk_mapping, mapping_max, disk); - 2598 1403 : ++mapping_max; - 2599 1669 : } else if (c == 'P') { - 2600 : /* from SnapRAID 7.0 the 'P' command includes the free space */ - 2601 : /* from SnapRAID 11.0 the 'P' command is deprecated by 'Q' */ - 2602 : char v_uuid[UUID_MAX]; - 2603 : uint32_t v_level; - 2604 : uint32_t v_total_blocks; - 2605 : uint32_t v_free_blocks; - 2606 : - 2607 0 : ret = sgetb32(f, &v_level); - 2608 0 : if (ret < 0) { - 2609 : /* LCOV_EXCL_START */ - 2610 : decoding_error(path, f); - 2611 : os_abort(); - 2612 : /* LCOV_EXCL_STOP */ - 2613 : } - 2614 : - 2615 0 : ret = sgetb32(f, &v_total_blocks); - 2616 0 : if (ret < 0) { - 2617 : /* LCOV_EXCL_START */ - 2618 : decoding_error(path, f); - 2619 : os_abort(); - 2620 : /* LCOV_EXCL_STOP */ - 2621 : } - 2622 : - 2623 0 : ret = sgetb32(f, &v_free_blocks); - 2624 0 : if (ret < 0) { - 2625 : /* LCOV_EXCL_START */ - 2626 : decoding_error(path, f); - 2627 : os_abort(); - 2628 : /* LCOV_EXCL_STOP */ - 2629 : } - 2630 : - 2631 0 : ret = sgetbs(f, v_uuid, sizeof(v_uuid)); - 2632 0 : if (ret < 0) { - 2633 : /* LCOV_EXCL_START */ - 2634 : decoding_error(path, f); - 2635 : os_abort(); - 2636 : /* LCOV_EXCL_STOP */ - 2637 : } - 2638 : - 2639 0 : if (v_level >= LEV_MAX) { - 2640 : /* LCOV_EXCL_START */ - 2641 : decoding_error(path, f); - 2642 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); - 2643 : exit(EXIT_FAILURE); - 2644 : /* LCOV_EXCL_STOP */ - 2645 : } - 2646 : - 2647 : /* auto configure if configuration is missing */ - 2648 0 : if (state->no_conf) { - 2649 0 : if (v_level >= state->level) - 2650 0 : state->level = v_level + 1; - 2651 : } - 2652 : - 2653 : /* if we use this parity entry */ - 2654 0 : if (v_level < state->level) { - 2655 : /* set the parity info */ - 2656 0 : state->parity[v_level].split_mac = 1; - 2657 0 : pathcpy(state->parity[v_level].split_map[0].uuid, sizeof(state->parity[v_level].split_map[0].uuid), v_uuid); - 2658 0 : state->parity[v_level].total_blocks = v_total_blocks; - 2659 0 : state->parity[v_level].free_blocks = v_free_blocks; - 2660 : } - 2661 1669 : } else if (c == 'Q') { - 2662 : /* from SnapRAID 11.0 the 'Q' command include size info and multi file support */ - 2663 : uint32_t v_level; - 2664 : uint32_t v_total_blocks; - 2665 : uint32_t v_free_blocks; - 2666 : uint32_t v_split_mac; - 2667 : unsigned s; - 2668 : - 2669 1415 : ret = sgetb32(f, &v_level); - 2670 1415 : if (ret < 0) { - 2671 : /* LCOV_EXCL_START */ - 2672 : decoding_error(path, f); - 2673 : os_abort(); - 2674 : /* LCOV_EXCL_STOP */ - 2675 : } - 2676 : - 2677 1415 : ret = sgetb32(f, &v_total_blocks); - 2678 1415 : if (ret < 0) { - 2679 : /* LCOV_EXCL_START */ - 2680 : decoding_error(path, f); - 2681 : os_abort(); - 2682 : /* LCOV_EXCL_STOP */ - 2683 : } - 2684 : - 2685 1415 : ret = sgetb32(f, &v_free_blocks); - 2686 1415 : if (ret < 0) { - 2687 : /* LCOV_EXCL_START */ - 2688 : decoding_error(path, f); - 2689 : os_abort(); - 2690 : /* LCOV_EXCL_STOP */ - 2691 : } - 2692 : - 2693 1415 : ret = sgetb32(f, &v_split_mac); - 2694 1415 : if (ret < 0) { - 2695 : /* LCOV_EXCL_START */ - 2696 : decoding_error(path, f); - 2697 : os_abort(); - 2698 : /* LCOV_EXCL_STOP */ - 2699 : } - 2700 : - 2701 1415 : if (v_level >= LEV_MAX) { - 2702 : /* LCOV_EXCL_START */ - 2703 : decoding_error(path, f); - 2704 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); - 2705 : exit(EXIT_FAILURE); - 2706 : /* LCOV_EXCL_STOP */ - 2707 : } - 2708 : - 2709 : /* auto configure if configuration is missing */ - 2710 1415 : if (state->no_conf) { - 2711 6 : if (v_level >= state->level) - 2712 5 : state->level = v_level + 1; - 2713 6 : if (state->parity[v_level].split_mac < v_split_mac) - 2714 6 : state->parity[v_level].split_mac = v_split_mac; - 2715 : } - 2716 : - 2717 : /* if we use this parity entry */ - 2718 1415 : if (v_level < state->level) { - 2719 : /* set the parity info */ - 2720 1156 : state->parity[v_level].total_blocks = v_total_blocks; - 2721 1156 : state->parity[v_level].free_blocks = v_free_blocks; - 2722 : } - 2723 : - 2724 7075 : for (s = 0; s < v_split_mac; ++s) { - 2725 : char v_path[PATH_MAX]; - 2726 : char v_uuid[UUID_MAX]; - 2727 : uint64_t v_size; + 2380 : /* allocate the dir */ + 2381 790 : dir = dir_alloc(sub); + 2382 : + 2383 : /* insert the dir in the dir containers */ + 2384 790 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); + 2385 790 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); + 2386 : + 2387 : /* stat */ + 2388 790 : ++count_dir; + 2389 4093 : } else if (c == 'c') { + 2390 : /* get the subcommand */ + 2391 254 : c = sgetc(f); + 2392 : + 2393 254 : switch (c) { + 2394 : case 'u' : + 2395 166 : state->hash = HASH_MURMUR3; + 2396 166 : break; + 2397 : case 'k' : + 2398 88 : state->hash = HASH_SPOOKY2; + 2399 88 : break; + 2400 : default : + 2401 : /* LCOV_EXCL_START */ + 2402 : decoding_error(path, f); + 2403 : log_fatal("Invalid checksum!\n"); + 2404 : os_abort(); + 2405 : /* LCOV_EXCL_STOP */ + 2406 : } + 2407 : + 2408 : /* read the seed */ + 2409 254 : ret = sread(f, state->hashseed, HASH_MAX); + 2410 254 : if (ret < 0) { + 2411 : /* LCOV_EXCL_START */ + 2412 : decoding_error(path, f); + 2413 : os_abort(); + 2414 : /* LCOV_EXCL_STOP */ + 2415 : } + 2416 3839 : } else if (c == 'C') { + 2417 : /* get the sub-command */ + 2418 4 : c = sgetc(f); + 2419 : + 2420 4 : switch (c) { + 2421 : case 'u' : + 2422 4 : state->prevhash = HASH_MURMUR3; + 2423 4 : break; + 2424 : case 'k' : + 2425 0 : state->prevhash = HASH_SPOOKY2; + 2426 0 : break; + 2427 : default : + 2428 : /* LCOV_EXCL_START */ + 2429 : decoding_error(path, f); + 2430 : log_fatal("Invalid checksum!\n"); + 2431 : os_abort(); + 2432 : /* LCOV_EXCL_STOP */ + 2433 : } + 2434 : + 2435 : /* read the seed */ + 2436 4 : ret = sread(f, state->prevhashseed, HASH_MAX); + 2437 4 : if (ret < 0) { + 2438 : /* LCOV_EXCL_START */ + 2439 : decoding_error(path, f); + 2440 : os_abort(); + 2441 : /* LCOV_EXCL_STOP */ + 2442 : } + 2443 3835 : } else if (c == 'z') { + 2444 : uint32_t block_size; + 2445 : + 2446 254 : ret = sgetb32(f, &block_size); + 2447 254 : if (ret < 0) { + 2448 : /* LCOV_EXCL_START */ + 2449 : decoding_error(path, f); + 2450 : os_abort(); + 2451 : /* LCOV_EXCL_STOP */ + 2452 : } + 2453 : + 2454 254 : if (block_size == 0) { + 2455 : /* LCOV_EXCL_START */ + 2456 : decoding_error(path, f); + 2457 : log_fatal("Zero 'blocksize' specification in the content file!\n"); + 2458 : exit(EXIT_FAILURE); + 2459 : /* LCOV_EXCL_STOP */ + 2460 : } + 2461 : + 2462 : /* without configuration, auto assign the block size */ + 2463 254 : if (state->no_conf) { + 2464 1 : state->block_size = block_size; + 2465 : } + 2466 : + 2467 254 : if (block_size != state->block_size) { + 2468 : /* LCOV_EXCL_START */ + 2469 : decoding_error(path, f); + 2470 : log_fatal("Mismatching 'blocksize' specification in the content file!\n"); + 2471 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", block_size / KIBI); + 2472 : exit(EXIT_FAILURE); + 2473 : /* LCOV_EXCL_STOP */ + 2474 : } + 2475 3581 : } else if (c == 'y') { + 2476 : uint32_t hash_size; + 2477 : + 2478 254 : ret = sgetb32(f, &hash_size); + 2479 254 : if (ret < 0) { + 2480 : /* LCOV_EXCL_START */ + 2481 : decoding_error(path, f); + 2482 : os_abort(); + 2483 : /* LCOV_EXCL_STOP */ + 2484 : } + 2485 : + 2486 254 : if (hash_size < 2 || hash_size > HASH_MAX) { + 2487 : /* LCOV_EXCL_START */ + 2488 : decoding_error(path, f); + 2489 : log_fatal("Invalid 'hashsize' specification in the content file!\n"); + 2490 : exit(EXIT_FAILURE); + 2491 : /* LCOV_EXCL_STOP */ + 2492 : } + 2493 : + 2494 : /* without configuration, auto assign the block size */ + 2495 254 : if (state->no_conf) { + 2496 1 : BLOCK_HASH_SIZE = hash_size; + 2497 : } + 2498 : + 2499 254 : if ((int)hash_size != BLOCK_HASH_SIZE) { + 2500 : /* LCOV_EXCL_START */ + 2501 : decoding_error(path, f); + 2502 : log_fatal("Mismatching 'hashsize' specification in the content file!\n"); + 2503 : log_fatal("Please restore the 'hashsize' value in the configuration file to '%u'\n", hash_size); + 2504 : exit(EXIT_FAILURE); + 2505 : /* LCOV_EXCL_STOP */ + 2506 : } + 2507 3327 : } else if (c == 'x') { + 2508 254 : ret = sgetb32(f, &blockmax); + 2509 254 : if (ret < 0) { + 2510 : /* LCOV_EXCL_START */ + 2511 : decoding_error(path, f); + 2512 : os_abort(); + 2513 : /* LCOV_EXCL_STOP */ + 2514 : } + 2515 4476 : } else if (c == 'm' || c == 'M') { + 2516 : struct snapraid_map* map; + 2517 : char uuid[UUID_MAX]; + 2518 : uint32_t v_pos; + 2519 : uint32_t v_total_blocks; + 2520 : uint32_t v_free_blocks; + 2521 : struct snapraid_disk* disk; + 2522 : + 2523 1403 : ret = sgetbs(f, buffer, sizeof(buffer)); + 2524 1403 : if (ret < 0) { + 2525 : /* LCOV_EXCL_START */ + 2526 : decoding_error(path, f); + 2527 : os_abort(); + 2528 : /* LCOV_EXCL_STOP */ + 2529 : } + 2530 : + 2531 1403 : ret = sgetb32(f, &v_pos); + 2532 1403 : if (ret < 0) { + 2533 : /* LCOV_EXCL_START */ + 2534 : decoding_error(path, f); + 2535 : os_abort(); + 2536 : /* LCOV_EXCL_STOP */ + 2537 : } + 2538 : + 2539 : /* from SnapRAID 7.0 the 'M' command includes the free space */ + 2540 1403 : if (c == 'M') { + 2541 1403 : ret = sgetb32(f, &v_total_blocks); + 2542 1403 : if (ret < 0) { + 2543 : /* LCOV_EXCL_START */ + 2544 : decoding_error(path, f); + 2545 : os_abort(); + 2546 : /* LCOV_EXCL_STOP */ + 2547 : } + 2548 : + 2549 1403 : ret = sgetb32(f, &v_free_blocks); + 2550 1403 : if (ret < 0) { + 2551 : /* LCOV_EXCL_START */ + 2552 : decoding_error(path, f); + 2553 : os_abort(); + 2554 : /* LCOV_EXCL_STOP */ + 2555 : } + 2556 : } else { + 2557 0 : v_total_blocks = 0; + 2558 0 : v_free_blocks = 0; + 2559 : } + 2560 : + 2561 : /* read the uuid */ + 2562 1403 : ret = sgetbs(f, uuid, sizeof(uuid)); + 2563 1403 : if (ret < 0) { + 2564 : /* LCOV_EXCL_START */ + 2565 : decoding_error(path, f); + 2566 : os_abort(); + 2567 : /* LCOV_EXCL_STOP */ + 2568 : } + 2569 : + 2570 : /* find the disk */ + 2571 1403 : disk = find_disk_by_name(state, buffer); + 2572 1403 : if (!disk) { + 2573 : /* search by UUID if renamed */ + 2574 2 : disk = find_disk_by_uuid(state, uuid); + 2575 2 : if (disk) { + 2576 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name); + 2577 : + 2578 : /* write the new state with the new name */ + 2579 2 : state->need_write = 1; + 2580 : } + 2581 : } + 2582 1403 : if (!disk) { + 2583 : /* LCOV_EXCL_START */ + 2584 : decoding_error(path, f); + 2585 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid); + 2586 : log_fatal("If you have removed it from the configuration file, please restore it\n"); + 2587 : /* if it's a command without UUID, it cannot autorename using UUID */ + 2588 : if (state->opt.skip_disk_access) + 2589 : log_fatal("If you have renamed it, run 'sync' to update the new name\n"); + 2590 : exit(EXIT_FAILURE); + 2591 : /* LCOV_EXCL_STOP */ + 2592 : } + 2593 : + 2594 1403 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid); + 2595 : + 2596 1403 : tommy_list_insert_tail(&state->maplist, &map->node, map); + 2597 : + 2598 : /* insert in the mapping vector */ + 2599 1403 : tommy_array_grow(&disk_mapping, mapping_max + 1); + 2600 1403 : tommy_array_set(&disk_mapping, mapping_max, disk); + 2601 1403 : ++mapping_max; + 2602 1670 : } else if (c == 'P') { + 2603 : /* from SnapRAID 7.0 the 'P' command includes the free space */ + 2604 : /* from SnapRAID 11.0 the 'P' command is deprecated by 'Q' */ + 2605 : char v_uuid[UUID_MAX]; + 2606 : uint32_t v_level; + 2607 : uint32_t v_total_blocks; + 2608 : uint32_t v_free_blocks; + 2609 : + 2610 0 : ret = sgetb32(f, &v_level); + 2611 0 : if (ret < 0) { + 2612 : /* LCOV_EXCL_START */ + 2613 : decoding_error(path, f); + 2614 : os_abort(); + 2615 : /* LCOV_EXCL_STOP */ + 2616 : } + 2617 : + 2618 0 : ret = sgetb32(f, &v_total_blocks); + 2619 0 : if (ret < 0) { + 2620 : /* LCOV_EXCL_START */ + 2621 : decoding_error(path, f); + 2622 : os_abort(); + 2623 : /* LCOV_EXCL_STOP */ + 2624 : } + 2625 : + 2626 0 : ret = sgetb32(f, &v_free_blocks); + 2627 0 : if (ret < 0) { + 2628 : /* LCOV_EXCL_START */ + 2629 : decoding_error(path, f); + 2630 : os_abort(); + 2631 : /* LCOV_EXCL_STOP */ + 2632 : } + 2633 : + 2634 0 : ret = sgetbs(f, v_uuid, sizeof(v_uuid)); + 2635 0 : if (ret < 0) { + 2636 : /* LCOV_EXCL_START */ + 2637 : decoding_error(path, f); + 2638 : os_abort(); + 2639 : /* LCOV_EXCL_STOP */ + 2640 : } + 2641 : + 2642 0 : if (v_level >= LEV_MAX) { + 2643 : /* LCOV_EXCL_START */ + 2644 : decoding_error(path, f); + 2645 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); + 2646 : exit(EXIT_FAILURE); + 2647 : /* LCOV_EXCL_STOP */ + 2648 : } + 2649 : + 2650 : /* auto configure if configuration is missing */ + 2651 0 : if (state->no_conf) { + 2652 0 : if (v_level >= state->level) + 2653 0 : state->level = v_level + 1; + 2654 : } + 2655 : + 2656 : /* if we use this parity entry */ + 2657 0 : if (v_level < state->level) { + 2658 : /* if the configuration has more splits, keep them */ + 2659 0 : if (state->parity[v_level].split_mac < 1) + 2660 0 : state->parity[v_level].split_mac = 1; + 2661 : /* set the parity info */ + 2662 0 : pathcpy(state->parity[v_level].split_map[0].uuid, sizeof(state->parity[v_level].split_map[0].uuid), v_uuid); + 2663 0 : state->parity[v_level].total_blocks = v_total_blocks; + 2664 0 : state->parity[v_level].free_blocks = v_free_blocks; + 2665 : } + 2666 1670 : } else if (c == 'Q') { + 2667 : /* from SnapRAID 11.0 the 'Q' command include size info and multi file support */ + 2668 : uint32_t v_level; + 2669 : uint32_t v_total_blocks; + 2670 : uint32_t v_free_blocks; + 2671 : uint32_t v_split_mac; + 2672 : unsigned s; + 2673 : + 2674 1417 : ret = sgetb32(f, &v_level); + 2675 1417 : if (ret < 0) { + 2676 : /* LCOV_EXCL_START */ + 2677 : decoding_error(path, f); + 2678 : os_abort(); + 2679 : /* LCOV_EXCL_STOP */ + 2680 : } + 2681 : + 2682 1417 : ret = sgetb32(f, &v_total_blocks); + 2683 1417 : if (ret < 0) { + 2684 : /* LCOV_EXCL_START */ + 2685 : decoding_error(path, f); + 2686 : os_abort(); + 2687 : /* LCOV_EXCL_STOP */ + 2688 : } + 2689 : + 2690 1417 : ret = sgetb32(f, &v_free_blocks); + 2691 1417 : if (ret < 0) { + 2692 : /* LCOV_EXCL_START */ + 2693 : decoding_error(path, f); + 2694 : os_abort(); + 2695 : /* LCOV_EXCL_STOP */ + 2696 : } + 2697 : + 2698 1417 : ret = sgetb32(f, &v_split_mac); + 2699 1417 : if (ret < 0) { + 2700 : /* LCOV_EXCL_START */ + 2701 : decoding_error(path, f); + 2702 : os_abort(); + 2703 : /* LCOV_EXCL_STOP */ + 2704 : } + 2705 : + 2706 1417 : if (v_level >= LEV_MAX) { + 2707 : /* LCOV_EXCL_START */ + 2708 : decoding_error(path, f); + 2709 : log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); + 2710 : exit(EXIT_FAILURE); + 2711 : /* LCOV_EXCL_STOP */ + 2712 : } + 2713 : + 2714 : /* auto configure if configuration is missing */ + 2715 1417 : if (state->no_conf) { + 2716 6 : if (v_level >= state->level) + 2717 5 : state->level = v_level + 1; + 2718 6 : if (state->parity[v_level].split_mac < v_split_mac) + 2719 6 : state->parity[v_level].split_mac = v_split_mac; + 2720 : } + 2721 : + 2722 : /* if we use this parity entry */ + 2723 1417 : if (v_level < state->level) { + 2724 : /* set the parity info */ + 2725 1158 : state->parity[v_level].total_blocks = v_total_blocks; + 2726 1158 : state->parity[v_level].free_blocks = v_free_blocks; + 2727 : } 2728 : - 2729 5660 : ret = sgetbs(f, v_path, sizeof(v_path)); - 2730 5660 : if (ret < 0) { - 2731 : /* LCOV_EXCL_START */ - 2732 : decoding_error(path, f); - 2733 : os_abort(); - 2734 : /* LCOV_EXCL_STOP */ - 2735 : } - 2736 : - 2737 5660 : ret = sgetbs(f, v_uuid, sizeof(v_uuid)); - 2738 5660 : if (ret < 0) { - 2739 : /* LCOV_EXCL_START */ - 2740 : decoding_error(path, f); - 2741 : os_abort(); - 2742 : /* LCOV_EXCL_STOP */ - 2743 : } - 2744 : - 2745 5660 : ret = sgetb64(f, &v_size); - 2746 5660 : if (ret < 0) { - 2747 : /* LCOV_EXCL_START */ - 2748 : decoding_error(path, f); - 2749 : os_abort(); - 2750 : /* LCOV_EXCL_STOP */ - 2751 : } - 2752 : - 2753 : /* if we use this parity entry */ - 2754 5660 : if (v_level < state->level) { - 2755 : /* if this split was removed from the configuration */ - 2756 4624 : if (s >= state->parity[v_level].split_mac) { - 2757 : /* if the file is used, we really need it */ - 2758 0 : if (v_size != 0) { - 2759 : /* LCOV_EXCL_START */ - 2760 : decoding_error(path, f); - 2761 : log_fatal("Parity '%s' misses used file '%u'!\n", lev_config_name(v_level), s); - 2762 : log_fatal("If you have removed it from the configuration file, please restore it\n"); - 2763 : exit(EXIT_FAILURE); - 2764 : /* LCOV_EXCL_STOP */ - 2765 : } - 2766 : - 2767 : /* otherwise we can drop it */ - 2768 0 : log_fatal("WARNING! Dropping from '%s' unused split '%u'\n", lev_config_name(v_level), s); - 2769 : } else { - 2770 : /* we copy the path only if without configuration file */ - 2771 4624 : if (state->no_conf) - 2772 24 : pathcpy(state->parity[v_level].split_map[s].path, sizeof(state->parity[v_level].split_map[s].path), v_path); - 2773 : - 2774 : /* set the split info */ - 2775 4624 : pathcpy(state->parity[v_level].split_map[s].uuid, sizeof(state->parity[v_level].split_map[s].uuid), v_uuid); - 2776 4624 : state->parity[v_level].split_map[s].size = v_size; - 2777 : - 2778 : /* log the info read from the content file */ - 2779 9248 : log_tag("content:%s:%u:%s:%s:%" PRIi64 "\n", lev_config_name(v_level), s, - 2780 4624 : state->parity[v_level].split_map[s].path, - 2781 4624 : state->parity[v_level].split_map[s].uuid, - 2782 : state->parity[v_level].split_map[s].size); - 2783 : } - 2784 : } - 2785 : } - 2786 254 : } else if (c == 'N') { - 2787 : uint32_t crc_stored; - 2788 : uint32_t crc_computed; - 2789 : - 2790 : /* get the crc before reading it from the file */ - 2791 253 : crc_computed = scrc(f); - 2792 : - 2793 253 : ret = sgetble32(f, &crc_stored); - 2794 253 : if (ret < 0) { - 2795 : /* LCOV_EXCL_START */ - 2796 : /* here don't call decoding_error() because it's too late to get the crc */ - 2797 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f)); - 2798 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 2799 : exit(EXIT_FAILURE); - 2800 : /* LCOV_EXCL_STOP */ - 2801 : } - 2802 : - 2803 253 : if (crc_stored != crc_computed) { - 2804 : /* LCOV_EXCL_START */ - 2805 : /* here don't call decoding_error() because it's too late to get the crc */ - 2806 : log_fatal("Mismatching CRC in '%s'\n", path); - 2807 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 2808 : exit(EXIT_FAILURE); - 2809 : /* LCOV_EXCL_STOP */ - 2810 : } - 2811 : - 2812 253 : crc_checked = 1; - 2813 : } else { - 2814 : /* LCOV_EXCL_START */ - 2815 : decoding_error(path, f); - 2816 : log_fatal("Invalid command '%c'!\n", (char)c); - 2817 : os_abort(); - 2818 : /* LCOV_EXCL_STOP */ - 2819 : } - 2820 3735358 : } - 2821 : - 2822 253 : tommy_array_done(&disk_mapping); - 2823 : - 2824 253 : if (serror(f)) { - 2825 : /* LCOV_EXCL_START */ - 2826 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 2827 : exit(EXIT_FAILURE); - 2828 : /* LCOV_EXCL_STOP */ - 2829 : } - 2830 : - 2831 253 : if (!crc_checked) { - 2832 : /* LCOV_EXCL_START */ - 2833 : log_fatal("Finished reading '%s' without finding the CRC\n", path); - 2834 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n"); - 2835 : exit(EXIT_FAILURE); - 2836 : /* LCOV_EXCL_STOP */ - 2837 : } - 2838 : - 2839 : /* check the file-system on all disks */ - 2840 253 : state_fscheck(state, "after read"); - 2841 : - 2842 : /* check that the stored parity size matches the loaded state */ - 2843 253 : if (blockmax != parity_allocated_size(state)) { - 2844 : /* LCOV_EXCL_START */ - 2845 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f)); - 2846 : if (state->opt.skip_content_check) { - 2847 : log_fatal("Overriding.\n"); - 2848 : blockmax = parity_allocated_size(state); - 2849 : } else { - 2850 : exit(EXIT_FAILURE); - 2851 : } - 2852 : /* LCOV_EXCL_STOP */ - 2853 : } - 2854 : - 2855 253 : msg_verbose("%8u files\n", count_file); - 2856 253 : msg_verbose("%8u hardlinks\n", count_hardlink); - 2857 253 : msg_verbose("%8u symlinks\n", count_symlink); - 2858 253 : msg_verbose("%8u empty dirs\n", count_dir); - 2859 253 : } - 2860 : - 2861 : struct state_write_thread_context { - 2862 : struct snapraid_state* state; - 2863 : #if HAVE_MT_WRITE - 2864 : pthread_t thread; - 2865 : #endif - 2866 : /* input */ - 2867 : block_off_t blockmax; - 2868 : time_t info_oldest; - 2869 : int info_has_rehash; - 2870 : STREAM* f; - 2871 : /* output */ - 2872 : uint32_t crc; - 2873 : unsigned count_file; - 2874 : unsigned count_hardlink; - 2875 : unsigned count_symlink; - 2876 : unsigned count_dir; - 2877 : }; - 2878 : - 2879 151 : static void* state_write_thread(void* arg) - 2880 : { - 2881 151 : struct state_write_thread_context* context = arg; - 2882 151 : struct snapraid_state* state = context->state; - 2883 151 : block_off_t blockmax = context->blockmax; - 2884 151 : time_t info_oldest = context->info_oldest; - 2885 151 : int info_has_rehash = context->info_has_rehash; - 2886 151 : STREAM* f = context->f; - 2887 : uint32_t crc; - 2888 : unsigned count_file; - 2889 : unsigned count_hardlink; - 2890 : unsigned count_symlink; - 2891 : unsigned count_dir; - 2892 : tommy_node* i; - 2893 : block_off_t idx; - 2894 : block_off_t begin; - 2895 : unsigned l, s; - 2896 : int version; - 2897 : - 2898 151 : count_file = 0; - 2899 151 : count_hardlink = 0; - 2900 151 : count_symlink = 0; - 2901 151 : count_dir = 0; + 2729 7083 : for (s = 0; s < v_split_mac; ++s) { + 2730 : char v_path[PATH_MAX]; + 2731 : char v_uuid[UUID_MAX]; + 2732 : uint64_t v_size; + 2733 : + 2734 5667 : ret = sgetbs(f, v_path, sizeof(v_path)); + 2735 5667 : if (ret < 0) { + 2736 : /* LCOV_EXCL_START */ + 2737 : decoding_error(path, f); + 2738 : os_abort(); + 2739 : /* LCOV_EXCL_STOP */ + 2740 : } + 2741 : + 2742 5666 : ret = sgetbs(f, v_uuid, sizeof(v_uuid)); + 2743 5666 : if (ret < 0) { + 2744 : /* LCOV_EXCL_START */ + 2745 : decoding_error(path, f); + 2746 : os_abort(); + 2747 : /* LCOV_EXCL_STOP */ + 2748 : } + 2749 : + 2750 5666 : ret = sgetb64(f, &v_size); + 2751 5666 : if (ret < 0) { + 2752 : /* LCOV_EXCL_START */ + 2753 : decoding_error(path, f); + 2754 : os_abort(); + 2755 : /* LCOV_EXCL_STOP */ + 2756 : } + 2757 : + 2758 : /* if we use this parity entry */ + 2759 5666 : if (v_level < state->level) { + 2760 : /* if this split was removed from the configuration */ + 2761 4630 : if (s >= state->parity[v_level].split_mac) { + 2762 : /* if the file is used, we really need it */ + 2763 0 : if (v_size != 0) { + 2764 : /* LCOV_EXCL_START */ + 2765 : decoding_error(path, f); + 2766 : log_fatal("Parity '%s' misses used file '%u'!\n", lev_config_name(v_level), s); + 2767 : log_fatal("If you have removed it from the configuration file, please restore it\n"); + 2768 : exit(EXIT_FAILURE); + 2769 : /* LCOV_EXCL_STOP */ + 2770 : } + 2771 : + 2772 : /* otherwise we can drop it */ + 2773 0 : log_fatal("WARNING! Dropping from '%s' unused split '%u'\n", lev_config_name(v_level), s); + 2774 : } else { + 2775 : /* we copy the path only if without configuration file */ + 2776 4630 : if (state->no_conf) + 2777 24 : pathcpy(state->parity[v_level].split_map[s].path, sizeof(state->parity[v_level].split_map[s].path), v_path); + 2778 : + 2779 : /* set the split info */ + 2780 4630 : pathcpy(state->parity[v_level].split_map[s].uuid, sizeof(state->parity[v_level].split_map[s].uuid), v_uuid); + 2781 4630 : state->parity[v_level].split_map[s].size = v_size; + 2782 : + 2783 : /* log the info read from the content file */ + 2784 9260 : log_tag("content:%s:%u:%s:%s:%" PRIi64 "\n", lev_config_name(v_level), s, + 2785 4630 : state->parity[v_level].split_map[s].path, + 2786 4630 : state->parity[v_level].split_map[s].uuid, + 2787 : state->parity[v_level].split_map[s].size); + 2788 : } + 2789 : } + 2790 : } + 2791 253 : } else if (c == 'N') { + 2792 : uint32_t crc_stored; + 2793 : uint32_t crc_computed; + 2794 : + 2795 : /* get the crc before reading it from the file */ + 2796 253 : crc_computed = scrc(f); + 2797 : + 2798 253 : ret = sgetble32(f, &crc_stored); + 2799 253 : if (ret < 0) { + 2800 : /* LCOV_EXCL_START */ + 2801 : /* here don't call decoding_error() because it's too late to get the crc */ + 2802 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f)); + 2803 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 2804 : exit(EXIT_FAILURE); + 2805 : /* LCOV_EXCL_STOP */ + 2806 : } + 2807 : + 2808 253 : if (crc_stored != crc_computed) { + 2809 : /* LCOV_EXCL_START */ + 2810 : /* here don't call decoding_error() because it's too late to get the crc */ + 2811 : log_fatal("Mismatching CRC in '%s'\n", path); + 2812 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 2813 : exit(EXIT_FAILURE); + 2814 : /* LCOV_EXCL_STOP */ + 2815 : } + 2816 : + 2817 253 : crc_checked = 1; + 2818 : } else { + 2819 : /* LCOV_EXCL_START */ + 2820 : decoding_error(path, f); + 2821 : log_fatal("Invalid command '%c'!\n", (char)c); + 2822 : os_abort(); + 2823 : /* LCOV_EXCL_STOP */ + 2824 : } + 2825 3735359 : } + 2826 : + 2827 253 : tommy_array_done(&disk_mapping); + 2828 : + 2829 253 : if (serror(f)) { + 2830 : /* LCOV_EXCL_START */ + 2831 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 2832 : exit(EXIT_FAILURE); + 2833 : /* LCOV_EXCL_STOP */ + 2834 : } + 2835 : + 2836 253 : if (!crc_checked) { + 2837 : /* LCOV_EXCL_START */ + 2838 : log_fatal("Finished reading '%s' without finding the CRC\n", path); + 2839 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n"); + 2840 : exit(EXIT_FAILURE); + 2841 : /* LCOV_EXCL_STOP */ + 2842 : } + 2843 : + 2844 : /* check the file-system on all disks */ + 2845 253 : state_fscheck(state, "after read"); + 2846 : + 2847 : /* check that the stored parity size matches the loaded state */ + 2848 253 : if (blockmax != parity_allocated_size(state)) { + 2849 : /* LCOV_EXCL_START */ + 2850 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f)); + 2851 : if (state->opt.skip_content_check) { + 2852 : log_fatal("Overriding.\n"); + 2853 : blockmax = parity_allocated_size(state); + 2854 : } else { + 2855 : exit(EXIT_FAILURE); + 2856 : } + 2857 : /* LCOV_EXCL_STOP */ + 2858 : } + 2859 : + 2860 253 : msg_verbose("%8u files\n", count_file); + 2861 253 : msg_verbose("%8u hardlinks\n", count_hardlink); + 2862 253 : msg_verbose("%8u symlinks\n", count_symlink); + 2863 253 : msg_verbose("%8u empty dirs\n", count_dir); + 2864 253 : } + 2865 : + 2866 : struct state_write_thread_context { + 2867 : struct snapraid_state* state; + 2868 : #if HAVE_MT_WRITE + 2869 : pthread_t thread; + 2870 : #endif + 2871 : /* input */ + 2872 : block_off_t blockmax; + 2873 : time_t info_oldest; + 2874 : int info_has_rehash; + 2875 : STREAM* f; + 2876 : /* output */ + 2877 : uint32_t crc; + 2878 : unsigned count_file; + 2879 : unsigned count_hardlink; + 2880 : unsigned count_symlink; + 2881 : unsigned count_dir; + 2882 : }; + 2883 : + 2884 151 : static void* state_write_thread(void* arg) + 2885 : { + 2886 151 : struct state_write_thread_context* context = arg; + 2887 151 : struct snapraid_state* state = context->state; + 2888 151 : block_off_t blockmax = context->blockmax; + 2889 151 : time_t info_oldest = context->info_oldest; + 2890 151 : int info_has_rehash = context->info_has_rehash; + 2891 151 : STREAM* f = context->f; + 2892 : uint32_t crc; + 2893 : unsigned count_file; + 2894 : unsigned count_hardlink; + 2895 : unsigned count_symlink; + 2896 : unsigned count_dir; + 2897 : tommy_node* i; + 2898 : block_off_t idx; + 2899 : block_off_t begin; + 2900 : unsigned l, s; + 2901 : int version; 2902 : - 2903 : /* check what version to use */ - 2904 151 : version = 2; - 2905 1012 : for (l = 0; l < state->level; ++l) { - 2906 861 : if (state->parity[l].split_mac > 1) - 2907 861 : version = 3; - 2908 : } - 2909 151 : if (BLOCK_HASH_SIZE != 16) - 2910 0 : version = 3; - 2911 : - 2912 : /* write header */ - 2913 151 : if (version == 3) - 2914 151 : swrite("SNAPCNT3\n\3\0\0", 12, f); - 2915 : else - 2916 0 : swrite("SNAPCNT2\n\3\0\0", 12, f); - 2917 : - 2918 : /* write block size and block max */ - 2919 151 : sputc('z', f); - 2920 151 : sputb32(state->block_size, f); - 2921 151 : sputc('x', f); - 2922 151 : sputb32(blockmax, f); - 2923 : - 2924 : /* hash size */ - 2925 151 : if (version == 3) { - 2926 151 : sputc('y', f); - 2927 151 : sputb32(BLOCK_HASH_SIZE, f); - 2928 : } - 2929 : - 2930 151 : if (serror(f)) { - 2931 : /* LCOV_EXCL_START */ - 2932 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2933 : return context; - 2934 : /* LCOV_EXCL_STOP */ - 2935 : } - 2936 : - 2937 151 : sputc('c', f); - 2938 151 : if (state->hash == HASH_MURMUR3) { - 2939 122 : sputc('u', f); - 2940 29 : } else if (state->hash == HASH_SPOOKY2) { - 2941 29 : sputc('k', f); - 2942 : } else { - 2943 : /* LCOV_EXCL_START */ - 2944 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); - 2945 : return context; - 2946 : /* LCOV_EXCL_STOP */ - 2947 : } - 2948 151 : swrite(state->hashseed, HASH_MAX, f); - 2949 151 : if (serror(f)) { - 2950 : /* LCOV_EXCL_START */ - 2951 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2952 : return context; - 2953 : /* LCOV_EXCL_STOP */ - 2954 : } - 2955 : - 2956 : /* previous hash only present */ - 2957 151 : if (state->prevhash != HASH_UNDEFINED) { - 2958 : /* if at least one rehash tag found, we have to save the previous hash */ - 2959 3 : if (info_has_rehash) { - 2960 2 : sputc('C', f); - 2961 2 : if (state->prevhash == HASH_MURMUR3) { - 2962 2 : sputc('u', f); - 2963 0 : } else if (state->prevhash == HASH_SPOOKY2) { - 2964 0 : sputc('k', f); - 2965 : } else { - 2966 : /* LCOV_EXCL_START */ - 2967 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); - 2968 : return context; - 2969 : /* LCOV_EXCL_STOP */ - 2970 : } - 2971 2 : swrite(state->prevhashseed, HASH_MAX, f); - 2972 2 : if (serror(f)) { - 2973 : /* LCOV_EXCL_START */ - 2974 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2975 : return context; - 2976 : /* LCOV_EXCL_STOP */ - 2977 : } - 2978 : } - 2979 : } - 2980 : - 2981 : /* for each map */ - 2982 1057 : for (i = state->maplist; i != 0; i = i->next) { - 2983 906 : struct snapraid_map* map = i->data; - 2984 : struct snapraid_disk* disk; + 2903 151 : count_file = 0; + 2904 151 : count_hardlink = 0; + 2905 151 : count_symlink = 0; + 2906 151 : count_dir = 0; + 2907 : + 2908 : /* check what version to use */ + 2909 151 : version = 2; + 2910 1012 : for (l = 0; l < state->level; ++l) { + 2911 861 : if (state->parity[l].split_mac > 1) + 2912 861 : version = 3; + 2913 : } + 2914 151 : if (BLOCK_HASH_SIZE != 16) + 2915 0 : version = 3; + 2916 : + 2917 : /* write header */ + 2918 151 : if (version == 3) + 2919 151 : swrite("SNAPCNT3\n\3\0\0", 12, f); + 2920 : else + 2921 0 : swrite("SNAPCNT2\n\3\0\0", 12, f); + 2922 : + 2923 : /* write block size and block max */ + 2924 151 : sputc('z', f); + 2925 151 : sputb32(state->block_size, f); + 2926 151 : sputc('x', f); + 2927 151 : sputb32(blockmax, f); + 2928 : + 2929 : /* hash size */ + 2930 151 : if (version == 3) { + 2931 151 : sputc('y', f); + 2932 151 : sputb32(BLOCK_HASH_SIZE, f); + 2933 : } + 2934 : + 2935 151 : if (serror(f)) { + 2936 : /* LCOV_EXCL_START */ + 2937 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2938 : return context; + 2939 : /* LCOV_EXCL_STOP */ + 2940 : } + 2941 : + 2942 151 : sputc('c', f); + 2943 151 : if (state->hash == HASH_MURMUR3) { + 2944 122 : sputc('u', f); + 2945 29 : } else if (state->hash == HASH_SPOOKY2) { + 2946 29 : sputc('k', f); + 2947 : } else { + 2948 : /* LCOV_EXCL_START */ + 2949 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); + 2950 : return context; + 2951 : /* LCOV_EXCL_STOP */ + 2952 : } + 2953 151 : swrite(state->hashseed, HASH_MAX, f); + 2954 151 : if (serror(f)) { + 2955 : /* LCOV_EXCL_START */ + 2956 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2957 : return context; + 2958 : /* LCOV_EXCL_STOP */ + 2959 : } + 2960 : + 2961 : /* previous hash only present */ + 2962 151 : if (state->prevhash != HASH_UNDEFINED) { + 2963 : /* if at least one rehash tag found, we have to save the previous hash */ + 2964 3 : if (info_has_rehash) { + 2965 2 : sputc('C', f); + 2966 2 : if (state->prevhash == HASH_MURMUR3) { + 2967 2 : sputc('u', f); + 2968 0 : } else if (state->prevhash == HASH_SPOOKY2) { + 2969 0 : sputc('k', f); + 2970 : } else { + 2971 : /* LCOV_EXCL_START */ + 2972 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); + 2973 : return context; + 2974 : /* LCOV_EXCL_STOP */ + 2975 : } + 2976 2 : swrite(state->prevhashseed, HASH_MAX, f); + 2977 2 : if (serror(f)) { + 2978 : /* LCOV_EXCL_START */ + 2979 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2980 : return context; + 2981 : /* LCOV_EXCL_STOP */ + 2982 : } + 2983 : } + 2984 : } 2985 : - 2986 : /* find the disk for this mapping */ - 2987 906 : disk = find_disk_by_name(state, map->name); - 2988 906 : if (!disk) { - 2989 : /* LCOV_EXCL_START */ - 2990 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - 2991 : return context; - 2992 : /* LCOV_EXCL_STOP */ - 2993 : } - 2994 : - 2995 : /* save the mapping only if disk is mapped */ - 2996 906 : if (disk->mapping_idx != -1) { - 2997 814 : sputc('M', f); - 2998 814 : sputbs(map->name, f); - 2999 814 : sputb32(map->position, f); - 3000 814 : sputb32(map->total_blocks, f); - 3001 814 : sputb32(map->free_blocks, f); - 3002 814 : sputbs(map->uuid, f); - 3003 814 : if (serror(f)) { - 3004 : /* LCOV_EXCL_START */ - 3005 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3006 : return context; - 3007 : /* LCOV_EXCL_STOP */ - 3008 : } - 3009 : } - 3010 : } - 3011 : - 3012 : /* for each parity */ - 3013 1012 : for (l = 0; l < state->level; ++l) { - 3014 861 : if (version == 3) { - 3015 861 : sputc('Q', f); - 3016 861 : sputb32(l, f); - 3017 861 : sputb32(state->parity[l].total_blocks, f); - 3018 861 : sputb32(state->parity[l].free_blocks, f); - 3019 861 : sputb32(state->parity[l].split_mac, f); - 3020 4305 : for (s = 0; s < state->parity[l].split_mac; ++s) { - 3021 3444 : sputbs(state->parity[l].split_map[s].path, f); - 3022 3444 : sputbs(state->parity[l].split_map[s].uuid, f); - 3023 3444 : sputb64(state->parity[l].split_map[s].size, f); - 3024 : } - 3025 : } else { - 3026 0 : sputc('P', f); - 3027 0 : sputb32(l, f); - 3028 0 : sputb32(state->parity[l].total_blocks, f); - 3029 0 : sputb32(state->parity[l].free_blocks, f); - 3030 0 : sputbs(state->parity[l].split_map[0].uuid, f); - 3031 : } - 3032 861 : if (serror(f)) { - 3033 : /* LCOV_EXCL_START */ - 3034 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3035 : return context; - 3036 : /* LCOV_EXCL_STOP */ - 3037 : } - 3038 : } - 3039 : - 3040 : /* for each disk */ - 3041 1057 : for (i = state->disklist; i != 0; i = i->next) { - 3042 : tommy_node* j; - 3043 906 : struct snapraid_disk* disk = i->data; + 2986 : /* for each map */ + 2987 1057 : for (i = state->maplist; i != 0; i = i->next) { + 2988 906 : struct snapraid_map* map = i->data; + 2989 : struct snapraid_disk* disk; + 2990 : + 2991 : /* find the disk for this mapping */ + 2992 906 : disk = find_disk_by_name(state, map->name); + 2993 906 : if (!disk) { + 2994 : /* LCOV_EXCL_START */ + 2995 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + 2996 : return context; + 2997 : /* LCOV_EXCL_STOP */ + 2998 : } + 2999 : + 3000 : /* save the mapping only if disk is mapped */ + 3001 906 : if (disk->mapping_idx != -1) { + 3002 814 : sputc('M', f); + 3003 814 : sputbs(map->name, f); + 3004 814 : sputb32(map->position, f); + 3005 814 : sputb32(map->total_blocks, f); + 3006 814 : sputb32(map->free_blocks, f); + 3007 814 : sputbs(map->uuid, f); + 3008 814 : if (serror(f)) { + 3009 : /* LCOV_EXCL_START */ + 3010 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3011 : return context; + 3012 : /* LCOV_EXCL_STOP */ + 3013 : } + 3014 : } + 3015 : } + 3016 : + 3017 : /* for each parity */ + 3018 1012 : for (l = 0; l < state->level; ++l) { + 3019 861 : if (version == 3) { + 3020 861 : sputc('Q', f); + 3021 861 : sputb32(l, f); + 3022 861 : sputb32(state->parity[l].total_blocks, f); + 3023 861 : sputb32(state->parity[l].free_blocks, f); + 3024 861 : sputb32(state->parity[l].split_mac, f); + 3025 4305 : for (s = 0; s < state->parity[l].split_mac; ++s) { + 3026 3444 : sputbs(state->parity[l].split_map[s].path, f); + 3027 3444 : sputbs(state->parity[l].split_map[s].uuid, f); + 3028 3444 : sputb64(state->parity[l].split_map[s].size, f); + 3029 : } + 3030 : } else { + 3031 0 : sputc('P', f); + 3032 0 : sputb32(l, f); + 3033 0 : sputb32(state->parity[l].total_blocks, f); + 3034 0 : sputb32(state->parity[l].free_blocks, f); + 3035 0 : sputbs(state->parity[l].split_map[0].uuid, f); + 3036 : } + 3037 861 : if (serror(f)) { + 3038 : /* LCOV_EXCL_START */ + 3039 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3040 : return context; + 3041 : /* LCOV_EXCL_STOP */ + 3042 : } + 3043 : } 3044 : - 3045 : /* if the disk is not mapped, skip it */ - 3046 906 : if (disk->mapping_idx < 0) - 3047 92 : continue; - 3048 : - 3049 : /* for each file */ - 3050 1771698 : for (j = disk->filelist; j != 0; j = j->next) { - 3051 1770884 : struct snapraid_file* file = j->data; - 3052 : uint64_t size; - 3053 : uint64_t mtime_sec; - 3054 : int32_t mtime_nsec; - 3055 : uint64_t inode; - 3056 : - 3057 1770884 : size = file->size; - 3058 1770884 : mtime_sec = file->mtime_sec; - 3059 1770884 : mtime_nsec = file->mtime_nsec; - 3060 1770884 : inode = file->inode; + 3045 : /* for each disk */ + 3046 1057 : for (i = state->disklist; i != 0; i = i->next) { + 3047 : tommy_node* j; + 3048 906 : struct snapraid_disk* disk = i->data; + 3049 : + 3050 : /* if the disk is not mapped, skip it */ + 3051 906 : if (disk->mapping_idx < 0) + 3052 92 : continue; + 3053 : + 3054 : /* for each file */ + 3055 1771698 : for (j = disk->filelist; j != 0; j = j->next) { + 3056 1770884 : struct snapraid_file* file = j->data; + 3057 : uint64_t size; + 3058 : uint64_t mtime_sec; + 3059 : int32_t mtime_nsec; + 3060 : uint64_t inode; 3061 : - 3062 1770884 : sputc('f', f); - 3063 1770884 : sputb32(disk->mapping_idx, f); - 3064 1770884 : sputb64(size, f); - 3065 1770884 : sputb64(mtime_sec, f); - 3066 : /* encode STAT_NSEC_INVALID as 0 */ - 3067 1770884 : if (mtime_nsec == STAT_NSEC_INVALID) - 3068 0 : sputb32(0, f); - 3069 : else - 3070 1770884 : sputb32(mtime_nsec + 1, f); - 3071 1770884 : sputb64(inode, f); - 3072 1770884 : sputbs(file->sub, f); - 3073 1770884 : if (serror(f)) { - 3074 : /* LCOV_EXCL_START */ - 3075 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3076 : return context; - 3077 : /* LCOV_EXCL_STOP */ - 3078 : } - 3079 : - 3080 : /* for all the blocks of the file */ - 3081 1770884 : begin = 0; - 3082 5322967 : while (begin < file->blockmax) { - 3083 1781199 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); - 3084 1781199 : block_off_t v_pos = fs_file2par_get(disk, file, begin); - 3085 : uint32_t v_count; - 3086 : - 3087 : block_off_t end; - 3088 : - 3089 : /* find the end of run of blocks */ - 3090 1781199 : end = begin + 1; - 3091 6146339 : while (end < file->blockmax) { - 3092 2596728 : if (v_state != block_state_get(fs_file2block_get(file, end))) - 3093 12 : break; - 3094 2596716 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end)) - 3095 12775 : break; - 3096 2583941 : ++end; - 3097 : } - 3098 : - 3099 1781199 : switch (v_state) { - 3100 : case BLOCK_STATE_BLK : - 3101 1678540 : sputc('b', f); - 3102 1678540 : break; - 3103 : case BLOCK_STATE_CHG : - 3104 67741 : sputc('g', f); - 3105 67741 : break; - 3106 : case BLOCK_STATE_REP : - 3107 34918 : sputc('p', f); - 3108 34918 : break; - 3109 : default : - 3110 : /* LCOV_EXCL_START */ - 3111 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state); - 3112 : return context; - 3113 : /* LCOV_EXCL_STOP */ - 3114 : } - 3115 : - 3116 1781199 : sputb32(v_pos, f); - 3117 : - 3118 1781199 : v_count = end - begin; - 3119 1781199 : sputb32(v_count, f); + 3062 1770884 : size = file->size; + 3063 1770884 : mtime_sec = file->mtime_sec; + 3064 1770884 : mtime_nsec = file->mtime_nsec; + 3065 1770884 : inode = file->inode; + 3066 : + 3067 1770884 : sputc('f', f); + 3068 1770884 : sputb32(disk->mapping_idx, f); + 3069 1770884 : sputb64(size, f); + 3070 1770884 : sputb64(mtime_sec, f); + 3071 : /* encode STAT_NSEC_INVALID as 0 */ + 3072 1770884 : if (mtime_nsec == STAT_NSEC_INVALID) + 3073 0 : sputb32(0, f); + 3074 : else + 3075 1770884 : sputb32(mtime_nsec + 1, f); + 3076 1770884 : sputb64(inode, f); + 3077 1770884 : sputbs(file->sub, f); + 3078 1770884 : if (serror(f)) { + 3079 : /* LCOV_EXCL_START */ + 3080 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3081 : return context; + 3082 : /* LCOV_EXCL_STOP */ + 3083 : } + 3084 : + 3085 : /* for all the blocks of the file */ + 3086 1770884 : begin = 0; + 3087 5323011 : while (begin < file->blockmax) { + 3088 1781243 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); + 3089 1781243 : block_off_t v_pos = fs_file2par_get(disk, file, begin); + 3090 : uint32_t v_count; + 3091 : + 3092 : block_off_t end; + 3093 : + 3094 : /* find the end of run of blocks */ + 3095 1781243 : end = begin + 1; + 3096 6146383 : while (end < file->blockmax) { + 3097 2596728 : if (v_state != block_state_get(fs_file2block_get(file, end))) + 3098 12 : break; + 3099 2596716 : if (v_pos + (end - begin) != fs_file2par_get(disk, file, end)) + 3100 12819 : break; + 3101 2583897 : ++end; + 3102 : } + 3103 : + 3104 1781243 : switch (v_state) { + 3105 : case BLOCK_STATE_BLK : + 3106 1678566 : sputc('b', f); + 3107 1678566 : break; + 3108 : case BLOCK_STATE_CHG : + 3109 67759 : sputc('g', f); + 3110 67759 : break; + 3111 : case BLOCK_STATE_REP : + 3112 34918 : sputc('p', f); + 3113 34918 : break; + 3114 : default : + 3115 : /* LCOV_EXCL_START */ + 3116 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state); + 3117 : return context; + 3118 : /* LCOV_EXCL_STOP */ + 3119 : } 3120 : - 3121 : /* write hashes */ - 3122 6146339 : for (idx = begin; idx < end; ++idx) { - 3123 4365140 : struct snapraid_block* block = fs_file2block_get(file, idx); - 3124 : - 3125 4365140 : swrite(block->hash, BLOCK_HASH_SIZE, f); - 3126 : } - 3127 : - 3128 1781199 : if (serror(f)) { - 3129 : /* LCOV_EXCL_START */ - 3130 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3131 : return context; - 3132 : /* LCOV_EXCL_STOP */ - 3133 : } - 3134 : - 3135 : /* next begin position */ - 3136 1781199 : begin = end; - 3137 : } - 3138 : - 3139 1770884 : ++count_file; - 3140 : } - 3141 : - 3142 : /* for each link */ - 3143 58887 : for (j = disk->linklist; j != 0; j = j->next) { - 3144 58073 : struct snapraid_link* slink = j->data; - 3145 : - 3146 58073 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { - 3147 : case FILE_IS_HARDLINK : - 3148 321 : sputc('a', f); - 3149 321 : ++count_hardlink; - 3150 321 : break; - 3151 : case FILE_IS_SYMLINK : - 3152 57752 : sputc('s', f); - 3153 57752 : ++count_symlink; - 3154 57752 : break; - 3155 : } - 3156 : - 3157 58073 : sputb32(disk->mapping_idx, f); - 3158 58073 : sputbs(slink->sub, f); - 3159 58073 : sputbs(slink->linkto, f); - 3160 58073 : if (serror(f)) { - 3161 : /* LCOV_EXCL_START */ - 3162 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3163 : return context; - 3164 : /* LCOV_EXCL_STOP */ - 3165 : } - 3166 : } - 3167 : - 3168 : /* for each dir */ - 3169 1241 : for (j = disk->dirlist; j != 0; j = j->next) { - 3170 427 : struct snapraid_dir* dir = j->data; - 3171 : - 3172 427 : sputc('r', f); - 3173 427 : sputb32(disk->mapping_idx, f); - 3174 427 : sputbs(dir->sub, f); - 3175 427 : if (serror(f)) { - 3176 : /* LCOV_EXCL_START */ - 3177 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3178 : return context; - 3179 : /* LCOV_EXCL_STOP */ - 3180 : } - 3181 : - 3182 427 : ++count_dir; - 3183 : } - 3184 : - 3185 : /* deleted blocks of the disk */ - 3186 814 : sputc('h', f); - 3187 814 : sputb32(disk->mapping_idx, f); - 3188 814 : if (serror(f)) { - 3189 : /* LCOV_EXCL_START */ - 3190 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3191 : return context; - 3192 : /* LCOV_EXCL_STOP */ - 3193 : } - 3194 814 : begin = 0; - 3195 2516 : while (begin < blockmax) { - 3196 : int is_deleted; - 3197 : block_off_t end; - 3198 : - 3199 888 : is_deleted = fs_is_block_deleted(disk, begin); - 3200 : - 3201 : /* find the end of run of blocks */ - 3202 888 : end = begin + 1; - 3203 4530435 : while (end < blockmax - 3204 4528733 : && is_deleted == fs_is_block_deleted(disk, end) - 3205 : ) { - 3206 4528659 : ++end; - 3207 : } - 3208 : - 3209 888 : sputb32(end - begin, f); - 3210 : - 3211 888 : if (is_deleted) { - 3212 : /* write the run of deleted blocks with hash */ - 3213 47 : sputc('o', f); - 3214 : - 3215 : /* write all the hash */ - 3216 15961 : while (begin < end) { - 3217 15867 : struct snapraid_block* block = fs_par2block_get(disk, begin); - 3218 : - 3219 15867 : swrite(block->hash, BLOCK_HASH_SIZE, f); - 3220 : - 3221 15867 : ++begin; - 3222 : } - 3223 : } else { - 3224 : /* write the run of blocks without hash */ - 3225 : /* they can be either used or empty blocks */ - 3226 841 : sputc('O', f); - 3227 : - 3228 : /* next begin position */ - 3229 841 : begin = end; - 3230 : } - 3231 : - 3232 888 : if (serror(f)) { - 3233 : /* LCOV_EXCL_START */ - 3234 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3235 : return context; - 3236 : /* LCOV_EXCL_STOP */ - 3237 : } - 3238 : } - 3239 : } - 3240 : - 3241 : /* write the info for each block */ - 3242 151 : sputc('i', f); - 3243 151 : sputb32(info_oldest, f); - 3244 151 : begin = 0; - 3245 19777 : while (begin < blockmax) { - 3246 : snapraid_info info; - 3247 : block_off_t end; - 3248 : time_t t; - 3249 : unsigned flag; - 3250 : - 3251 19475 : info = info_get(&state->infoarr, begin); - 3252 : - 3253 : /* find the end of run of blocks */ - 3254 19475 : end = begin + 1; - 3255 775574 : while (end < blockmax - 3256 755951 : && info == info_get(&state->infoarr, end) - 3257 : ) { - 3258 736624 : ++end; - 3259 : } - 3260 : - 3261 19475 : sputb32(end - begin, f); - 3262 : - 3263 : /* if there is info */ - 3264 19475 : if (info) { - 3265 : /* other flags */ - 3266 19452 : flag = 1; /* info is present */ - 3267 19452 : if (info_get_bad(info)) - 3268 1330 : flag |= 2; - 3269 19452 : if (info_get_rehash(info)) - 3270 5212 : flag |= 4; - 3271 19452 : if (info_get_justsynced(info)) - 3272 12082 : flag |= 8; - 3273 19452 : sputb32(flag, f); - 3274 : - 3275 19452 : t = info_get_time(info) - info_oldest; - 3276 19452 : sputb32(t, f); - 3277 : } else { - 3278 : /* write a special 0 flag to mark missing info */ - 3279 23 : sputb32(0, f); - 3280 : } - 3281 : - 3282 19475 : if (serror(f)) { - 3283 : /* LCOV_EXCL_START */ - 3284 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3285 : return context; - 3286 : /* LCOV_EXCL_STOP */ - 3287 : } - 3288 : - 3289 : /* next begin position */ - 3290 19475 : begin = end; - 3291 : } - 3292 : - 3293 151 : sputc('N', f); - 3294 : - 3295 : /* flush data written to the disk */ - 3296 151 : if (sflush(f)) { - 3297 : /* LCOV_EXCL_START */ - 3298 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); - 3299 : return context; - 3300 : /* LCOV_EXCL_STOP */ - 3301 : } - 3302 : - 3303 : /* get the file crc */ - 3304 151 : crc = scrc(f); - 3305 : - 3306 : /* compare the crc of the data written to file */ - 3307 : /* with the one of the data written to the stream */ - 3308 151 : if (crc != scrc_stream(f)) { - 3309 : /* LCOV_EXCL_START */ - 3310 : log_fatal("CRC mismatch writing the content stream.\n"); - 3311 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); - 3312 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); - 3313 : return context; - 3314 : /* LCOV_EXCL_STOP */ - 3315 : } - 3316 : - 3317 151 : sputble32(crc, f); - 3318 151 : if (serror(f)) { - 3319 : /* LCOV_EXCL_START */ - 3320 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3321 : return context; - 3322 : /* LCOV_EXCL_STOP */ - 3323 : } - 3324 : - 3325 : /* set output variables */ - 3326 151 : context->crc = crc; - 3327 151 : context->count_file = count_file; - 3328 151 : context->count_hardlink = count_hardlink; - 3329 151 : context->count_symlink = count_symlink; - 3330 151 : context->count_dir = count_dir; - 3331 : - 3332 151 : return 0; - 3333 : } - 3334 : - 3335 151 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) - 3336 : { - 3337 : #if HAVE_MT_WRITE - 3338 : int fail; - 3339 : int first; - 3340 : #else - 3341 : STREAM* f; - 3342 : unsigned count_content; - 3343 : unsigned k; - 3344 : struct state_write_thread_context* context; - 3345 : void* retval; - 3346 : #endif - 3347 : tommy_node* i; - 3348 : block_off_t blockmax; - 3349 : time_t info_oldest; - 3350 : int info_has_rehash; - 3351 : int mapping_idx; - 3352 : block_off_t idx; - 3353 : uint32_t crc; - 3354 : unsigned count_file; - 3355 : unsigned count_hardlink; - 3356 : unsigned count_symlink; - 3357 : unsigned count_dir; - 3358 : - 3359 : /* blocks of all array */ - 3360 151 : blockmax = parity_allocated_size(state); - 3361 : - 3362 : /* check the file-system on all disks */ - 3363 151 : state_fscheck(state, "before write"); - 3364 : - 3365 : /* clear the info for unused blocks */ - 3366 : /* and get some other info */ - 3367 151 : info_oldest = 0; /* oldest time in info */ - 3368 151 : info_has_rehash = 0; /* if there is a rehash info */ - 3369 756250 : for (idx = 0; idx < blockmax; ++idx) { - 3370 : /* if the position is used */ - 3371 756099 : if (fs_position_is_required(state, idx)) { - 3372 756099 : snapraid_info info = info_get(&state->infoarr, idx); - 3373 : - 3374 : /* only if there is some info to store */ - 3375 756099 : if (info) { - 3376 711614 : time_t info_time = info_get_time(info); - 3377 : - 3378 711614 : if (!info_oldest || info_time < info_oldest) - 3379 154 : info_oldest = info_time; - 3380 : - 3381 711614 : if (info_get_rehash(info)) - 3382 13822 : info_has_rehash = 1; - 3383 : } - 3384 : } else { - 3385 : /* clear any previous info */ - 3386 0 : info_set(&state->infoarr, idx, 0); - 3387 : - 3388 : /* and clear any deleted blocks */ - 3389 0 : fs_position_clear_deleted(state, idx); - 3390 : } - 3391 : } + 3121 1781243 : sputb32(v_pos, f); + 3122 : + 3123 1781243 : v_count = end - begin; + 3124 1781243 : sputb32(v_count, f); + 3125 : + 3126 : /* write hashes */ + 3127 6146383 : for (idx = begin; idx < end; ++idx) { + 3128 4365140 : struct snapraid_block* block = fs_file2block_get(file, idx); + 3129 : + 3130 4365140 : swrite(block->hash, BLOCK_HASH_SIZE, f); + 3131 : } + 3132 : + 3133 1781243 : if (serror(f)) { + 3134 : /* LCOV_EXCL_START */ + 3135 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3136 : return context; + 3137 : /* LCOV_EXCL_STOP */ + 3138 : } + 3139 : + 3140 : /* next begin position */ + 3141 1781243 : begin = end; + 3142 : } + 3143 : + 3144 1770884 : ++count_file; + 3145 : } + 3146 : + 3147 : /* for each link */ + 3148 58887 : for (j = disk->linklist; j != 0; j = j->next) { + 3149 58073 : struct snapraid_link* slink = j->data; + 3150 : + 3151 58073 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { + 3152 : case FILE_IS_HARDLINK : + 3153 321 : sputc('a', f); + 3154 321 : ++count_hardlink; + 3155 321 : break; + 3156 : case FILE_IS_SYMLINK : + 3157 57752 : sputc('s', f); + 3158 57752 : ++count_symlink; + 3159 57752 : break; + 3160 : } + 3161 : + 3162 58073 : sputb32(disk->mapping_idx, f); + 3163 58073 : sputbs(slink->sub, f); + 3164 58073 : sputbs(slink->linkto, f); + 3165 58073 : if (serror(f)) { + 3166 : /* LCOV_EXCL_START */ + 3167 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3168 : return context; + 3169 : /* LCOV_EXCL_STOP */ + 3170 : } + 3171 : } + 3172 : + 3173 : /* for each dir */ + 3174 1241 : for (j = disk->dirlist; j != 0; j = j->next) { + 3175 427 : struct snapraid_dir* dir = j->data; + 3176 : + 3177 427 : sputc('r', f); + 3178 427 : sputb32(disk->mapping_idx, f); + 3179 427 : sputbs(dir->sub, f); + 3180 427 : if (serror(f)) { + 3181 : /* LCOV_EXCL_START */ + 3182 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3183 : return context; + 3184 : /* LCOV_EXCL_STOP */ + 3185 : } + 3186 : + 3187 427 : ++count_dir; + 3188 : } + 3189 : + 3190 : /* deleted blocks of the disk */ + 3191 814 : sputc('h', f); + 3192 814 : sputb32(disk->mapping_idx, f); + 3193 814 : if (serror(f)) { + 3194 : /* LCOV_EXCL_START */ + 3195 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3196 : return context; + 3197 : /* LCOV_EXCL_STOP */ + 3198 : } + 3199 814 : begin = 0; + 3200 2516 : while (begin < blockmax) { + 3201 : int is_deleted; + 3202 : block_off_t end; + 3203 : + 3204 888 : is_deleted = fs_is_block_deleted(disk, begin); + 3205 : + 3206 : /* find the end of run of blocks */ + 3207 888 : end = begin + 1; + 3208 4530435 : while (end < blockmax + 3209 4528733 : && is_deleted == fs_is_block_deleted(disk, end) + 3210 : ) { + 3211 4528659 : ++end; + 3212 : } + 3213 : + 3214 888 : sputb32(end - begin, f); + 3215 : + 3216 888 : if (is_deleted) { + 3217 : /* write the run of deleted blocks with hash */ + 3218 47 : sputc('o', f); + 3219 : + 3220 : /* write all the hash */ + 3221 15961 : while (begin < end) { + 3222 15867 : struct snapraid_block* block = fs_par2block_get(disk, begin); + 3223 : + 3224 15867 : swrite(block->hash, BLOCK_HASH_SIZE, f); + 3225 : + 3226 15867 : ++begin; + 3227 : } + 3228 : } else { + 3229 : /* write the run of blocks without hash */ + 3230 : /* they can be either used or empty blocks */ + 3231 841 : sputc('O', f); + 3232 : + 3233 : /* next begin position */ + 3234 841 : begin = end; + 3235 : } + 3236 : + 3237 888 : if (serror(f)) { + 3238 : /* LCOV_EXCL_START */ + 3239 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3240 : return context; + 3241 : /* LCOV_EXCL_STOP */ + 3242 : } + 3243 : } + 3244 : } + 3245 : + 3246 : /* write the info for each block */ + 3247 151 : sputc('i', f); + 3248 151 : sputb32(info_oldest, f); + 3249 151 : begin = 0; + 3250 19719 : while (begin < blockmax) { + 3251 : snapraid_info info; + 3252 : block_off_t end; + 3253 : time_t t; + 3254 : unsigned flag; + 3255 : + 3256 19417 : info = info_get(&state->infoarr, begin); + 3257 : + 3258 : /* find the end of run of blocks */ + 3259 19417 : end = begin + 1; + 3260 775516 : while (end < blockmax + 3261 755951 : && info == info_get(&state->infoarr, end) + 3262 : ) { + 3263 736682 : ++end; + 3264 : } + 3265 : + 3266 19417 : sputb32(end - begin, f); + 3267 : + 3268 : /* if there is info */ + 3269 19417 : if (info) { + 3270 : /* other flags */ + 3271 19394 : flag = 1; /* info is present */ + 3272 19394 : if (info_get_bad(info)) + 3273 1348 : flag |= 2; + 3274 19394 : if (info_get_rehash(info)) + 3275 5212 : flag |= 4; + 3276 19394 : if (info_get_justsynced(info)) + 3277 12059 : flag |= 8; + 3278 19394 : sputb32(flag, f); + 3279 : + 3280 19394 : t = info_get_time(info) - info_oldest; + 3281 19394 : sputb32(t, f); + 3282 : } else { + 3283 : /* write a special 0 flag to mark missing info */ + 3284 23 : sputb32(0, f); + 3285 : } + 3286 : + 3287 19417 : if (serror(f)) { + 3288 : /* LCOV_EXCL_START */ + 3289 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3290 : return context; + 3291 : /* LCOV_EXCL_STOP */ + 3292 : } + 3293 : + 3294 : /* next begin position */ + 3295 19417 : begin = end; + 3296 : } + 3297 : + 3298 151 : sputc('N', f); + 3299 : + 3300 : /* flush data written to the disk */ + 3301 151 : if (sflush(f)) { + 3302 : /* LCOV_EXCL_START */ + 3303 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); + 3304 : return context; + 3305 : /* LCOV_EXCL_STOP */ + 3306 : } + 3307 : + 3308 : /* get the file crc */ + 3309 151 : crc = scrc(f); + 3310 : + 3311 : /* compare the crc of the data written to file */ + 3312 : /* with the one of the data written to the stream */ + 3313 151 : if (crc != scrc_stream(f)) { + 3314 : /* LCOV_EXCL_START */ + 3315 : log_fatal("CRC mismatch writing the content stream.\n"); + 3316 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + 3317 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + 3318 : return context; + 3319 : /* LCOV_EXCL_STOP */ + 3320 : } + 3321 : + 3322 151 : sputble32(crc, f); + 3323 151 : if (serror(f)) { + 3324 : /* LCOV_EXCL_START */ + 3325 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3326 : return context; + 3327 : /* LCOV_EXCL_STOP */ + 3328 : } + 3329 : + 3330 : /* set output variables */ + 3331 151 : context->crc = crc; + 3332 151 : context->count_file = count_file; + 3333 151 : context->count_hardlink = count_hardlink; + 3334 151 : context->count_symlink = count_symlink; + 3335 151 : context->count_dir = count_dir; + 3336 : + 3337 151 : return 0; + 3338 : } + 3339 : + 3340 151 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) + 3341 : { + 3342 : #if HAVE_MT_WRITE + 3343 : int fail; + 3344 : int first; + 3345 : #else + 3346 : STREAM* f; + 3347 : unsigned count_content; + 3348 : unsigned k; + 3349 : struct state_write_thread_context* context; + 3350 : void* retval; + 3351 : #endif + 3352 : tommy_node* i; + 3353 : block_off_t blockmax; + 3354 : time_t info_oldest; + 3355 : int info_has_rehash; + 3356 : int mapping_idx; + 3357 : block_off_t idx; + 3358 : uint32_t crc; + 3359 : unsigned count_file; + 3360 : unsigned count_hardlink; + 3361 : unsigned count_symlink; + 3362 : unsigned count_dir; + 3363 : + 3364 : /* blocks of all array */ + 3365 151 : blockmax = parity_allocated_size(state); + 3366 : + 3367 : /* check the file-system on all disks */ + 3368 151 : state_fscheck(state, "before write"); + 3369 : + 3370 : /* clear the info for unused blocks */ + 3371 : /* and get some other info */ + 3372 151 : info_oldest = 0; /* oldest time in info */ + 3373 151 : info_has_rehash = 0; /* if there is a rehash info */ + 3374 756250 : for (idx = 0; idx < blockmax; ++idx) { + 3375 : /* if the position is used */ + 3376 756099 : if (fs_position_is_required(state, idx)) { + 3377 756099 : snapraid_info info = info_get(&state->infoarr, idx); + 3378 : + 3379 : /* only if there is some info to store */ + 3380 756099 : if (info) { + 3381 711614 : time_t info_time = info_get_time(info); + 3382 : + 3383 711614 : if (!info_oldest || info_time < info_oldest) + 3384 151 : info_oldest = info_time; + 3385 : + 3386 711614 : if (info_get_rehash(info)) + 3387 13822 : info_has_rehash = 1; + 3388 : } + 3389 : } else { + 3390 : /* clear any previous info */ + 3391 0 : info_set(&state->infoarr, idx, 0); 3392 : - 3393 : /* map disks */ - 3394 151 : mapping_idx = 0; - 3395 1057 : for (i = state->maplist; i != 0; i = i->next) { - 3396 906 : struct snapraid_map* map = i->data; - 3397 : struct snapraid_disk* disk; - 3398 : - 3399 : /* find the disk for this mapping */ - 3400 906 : disk = find_disk_by_name(state, map->name); - 3401 906 : if (!disk) { - 3402 : /* LCOV_EXCL_START */ - 3403 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - 3404 : os_abort(); - 3405 : /* LCOV_EXCL_STOP */ - 3406 : } - 3407 : - 3408 : /* save the mapping only for not empty disks */ - 3409 906 : if (!fs_is_empty(disk, blockmax)) { - 3410 : /* assign the mapping index used to identify disks */ - 3411 814 : disk->mapping_idx = mapping_idx; - 3412 814 : ++mapping_idx; - 3413 : } else { - 3414 : /* mark the disk as without mapping */ - 3415 92 : disk->mapping_idx = -1; - 3416 : } - 3417 : } - 3418 : - 3419 : #if HAVE_MT_WRITE - 3420 : /* start all writing threads */ - 3421 : i = tommy_list_head(&state->contentlist); - 3422 : while (i) { - 3423 : struct snapraid_content* content = i->data; - 3424 : struct state_write_thread_context* context; - 3425 : char tmp[PATH_MAX]; - 3426 : STREAM* f; - 3427 : - 3428 : msg_progress("Saving state to %s...\n", content->content); - 3429 : - 3430 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3431 : f = sopen_write(tmp); - 3432 : if (f == 0) { - 3433 : /* LCOV_EXCL_START */ - 3434 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); - 3435 : exit(EXIT_FAILURE); - 3436 : /* LCOV_EXCL_STOP */ - 3437 : } - 3438 : - 3439 : /* allocate the thread context */ - 3440 : context = malloc_nofail(sizeof(struct state_write_thread_context)); - 3441 : content->context = context; - 3442 : - 3443 : /* initialize */ - 3444 : context->state = state; - 3445 : context->blockmax = blockmax; - 3446 : context->info_oldest = info_oldest; - 3447 : context->info_has_rehash = info_has_rehash; - 3448 : context->f = f; - 3449 : - 3450 : thread_create(&context->thread, 0, state_write_thread, context); - 3451 : - 3452 : i = i->next; - 3453 : } + 3393 : /* and clear any deleted blocks */ + 3394 0 : fs_position_clear_deleted(state, idx); + 3395 : } + 3396 : } + 3397 : + 3398 : /* map disks */ + 3399 151 : mapping_idx = 0; + 3400 1057 : for (i = state->maplist; i != 0; i = i->next) { + 3401 906 : struct snapraid_map* map = i->data; + 3402 : struct snapraid_disk* disk; + 3403 : + 3404 : /* find the disk for this mapping */ + 3405 906 : disk = find_disk_by_name(state, map->name); + 3406 906 : if (!disk) { + 3407 : /* LCOV_EXCL_START */ + 3408 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + 3409 : os_abort(); + 3410 : /* LCOV_EXCL_STOP */ + 3411 : } + 3412 : + 3413 : /* save the mapping only for not empty disks */ + 3414 906 : if (!fs_is_empty(disk, blockmax)) { + 3415 : /* assign the mapping index used to identify disks */ + 3416 814 : disk->mapping_idx = mapping_idx; + 3417 814 : ++mapping_idx; + 3418 : } else { + 3419 : /* mark the disk as without mapping */ + 3420 92 : disk->mapping_idx = -1; + 3421 : } + 3422 : } + 3423 : + 3424 : #if HAVE_MT_WRITE + 3425 : /* start all writing threads */ + 3426 : i = tommy_list_head(&state->contentlist); + 3427 : while (i) { + 3428 : struct snapraid_content* content = i->data; + 3429 : struct state_write_thread_context* context; + 3430 : char tmp[PATH_MAX]; + 3431 : STREAM* f; + 3432 : + 3433 : msg_progress("Saving state to %s...\n", content->content); + 3434 : + 3435 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3436 : f = sopen_write(tmp); + 3437 : if (f == 0) { + 3438 : /* LCOV_EXCL_START */ + 3439 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3440 : exit(EXIT_FAILURE); + 3441 : /* LCOV_EXCL_STOP */ + 3442 : } + 3443 : + 3444 : /* allocate the thread context */ + 3445 : context = malloc_nofail(sizeof(struct state_write_thread_context)); + 3446 : content->context = context; + 3447 : + 3448 : /* initialize */ + 3449 : context->state = state; + 3450 : context->blockmax = blockmax; + 3451 : context->info_oldest = info_oldest; + 3452 : context->info_has_rehash = info_has_rehash; + 3453 : context->f = f; 3454 : - 3455 : /* join all thread */ - 3456 : fail = 0; - 3457 : first = 1; - 3458 : crc = 0; - 3459 : count_file = 0; - 3460 : count_hardlink = 0; - 3461 : count_symlink = 0; - 3462 : count_dir = 0; - 3463 : i = tommy_list_head(&state->contentlist); - 3464 : while (i) { - 3465 : struct snapraid_content* content = i->data; - 3466 : struct state_write_thread_context* context = content->context; - 3467 : void* retval; - 3468 : - 3469 : thread_join(context->thread, &retval); - 3470 : - 3471 : if (retval) { - 3472 : /* LCOV_EXCL_START */ - 3473 : fail = 1; - 3474 : /* LCOV_EXCL_STOP */ - 3475 : } else { - 3476 : STREAM* f = context->f; - 3477 : - 3478 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ - 3479 : /* than even in a system crash event we have one valid copy of the file. */ - 3480 : if (sflush(f) != 0) { - 3481 : /* LCOV_EXCL_START */ - 3482 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); - 3483 : exit(EXIT_FAILURE); - 3484 : /* LCOV_EXCL_STOP */ - 3485 : } - 3486 : - 3487 : #if HAVE_FSYNC - 3488 : if (ssync(f) != 0) { - 3489 : /* LCOV_EXCL_START */ - 3490 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); - 3491 : exit(EXIT_FAILURE); - 3492 : /* LCOV_EXCL_STOP */ - 3493 : } - 3494 : #endif - 3495 : - 3496 : if (sclose(f) != 0) { - 3497 : /* LCOV_EXCL_START */ - 3498 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); - 3499 : exit(EXIT_FAILURE); - 3500 : /* LCOV_EXCL_STOP */ - 3501 : } - 3502 : - 3503 : if (first) { - 3504 : first = 0; - 3505 : crc = context->crc; - 3506 : count_file = context->count_file; - 3507 : count_hardlink = context->count_hardlink; - 3508 : count_symlink = context->count_symlink; - 3509 : count_dir = context->count_dir; - 3510 : } else { - 3511 : if (crc != context->crc) { - 3512 : /* LCOV_EXCL_START */ - 3513 : log_fatal("Different CRCs writing content streams.\n"); - 3514 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); - 3515 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); - 3516 : exit(EXIT_FAILURE); - 3517 : /* LCOV_EXCL_STOP */ - 3518 : } - 3519 : } - 3520 : } - 3521 : - 3522 : free(context); - 3523 : - 3524 : i = i->next; - 3525 : } + 3455 : thread_create(&context->thread, 0, state_write_thread, context); + 3456 : + 3457 : i = i->next; + 3458 : } + 3459 : + 3460 : /* join all thread */ + 3461 : fail = 0; + 3462 : first = 1; + 3463 : crc = 0; + 3464 : count_file = 0; + 3465 : count_hardlink = 0; + 3466 : count_symlink = 0; + 3467 : count_dir = 0; + 3468 : i = tommy_list_head(&state->contentlist); + 3469 : while (i) { + 3470 : struct snapraid_content* content = i->data; + 3471 : struct state_write_thread_context* context = content->context; + 3472 : void* retval; + 3473 : + 3474 : thread_join(context->thread, &retval); + 3475 : + 3476 : if (retval) { + 3477 : /* LCOV_EXCL_START */ + 3478 : fail = 1; + 3479 : /* LCOV_EXCL_STOP */ + 3480 : } else { + 3481 : STREAM* f = context->f; + 3482 : + 3483 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + 3484 : /* than even in a system crash event we have one valid copy of the file. */ + 3485 : if (sflush(f) != 0) { + 3486 : /* LCOV_EXCL_START */ + 3487 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + 3488 : exit(EXIT_FAILURE); + 3489 : /* LCOV_EXCL_STOP */ + 3490 : } + 3491 : + 3492 : #if HAVE_FSYNC + 3493 : if (ssync(f) != 0) { + 3494 : /* LCOV_EXCL_START */ + 3495 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + 3496 : exit(EXIT_FAILURE); + 3497 : /* LCOV_EXCL_STOP */ + 3498 : } + 3499 : #endif + 3500 : + 3501 : if (sclose(f) != 0) { + 3502 : /* LCOV_EXCL_START */ + 3503 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3504 : exit(EXIT_FAILURE); + 3505 : /* LCOV_EXCL_STOP */ + 3506 : } + 3507 : + 3508 : if (first) { + 3509 : first = 0; + 3510 : crc = context->crc; + 3511 : count_file = context->count_file; + 3512 : count_hardlink = context->count_hardlink; + 3513 : count_symlink = context->count_symlink; + 3514 : count_dir = context->count_dir; + 3515 : } else { + 3516 : if (crc != context->crc) { + 3517 : /* LCOV_EXCL_START */ + 3518 : log_fatal("Different CRCs writing content streams.\n"); + 3519 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + 3520 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + 3521 : exit(EXIT_FAILURE); + 3522 : /* LCOV_EXCL_STOP */ + 3523 : } + 3524 : } + 3525 : } 3526 : - 3527 : /* abort on failure */ - 3528 : if (fail) { - 3529 : /* LCOV_EXCL_START */ - 3530 : exit(EXIT_FAILURE); - 3531 : /* LCOV_EXCL_STOP */ - 3532 : } - 3533 : #else - 3534 : /* count the content files */ - 3535 151 : count_content = 0; - 3536 151 : i = tommy_list_head(&state->contentlist); - 3537 1314 : while (i) { - 3538 1012 : struct snapraid_content* content = i->data; - 3539 1012 : msg_progress("Saving state to %s...\n", content->content); - 3540 1012 : ++count_content; - 3541 1012 : i = i->next; - 3542 : } - 3543 : - 3544 : /* open all the content files */ - 3545 151 : f = sopen_multi_write(count_content); - 3546 151 : if (!f) { - 3547 : /* LCOV_EXCL_START */ - 3548 : log_fatal("Error opening the content files.\n"); - 3549 : exit(EXIT_FAILURE); - 3550 : /* LCOV_EXCL_STOP */ - 3551 : } - 3552 : - 3553 151 : k = 0; - 3554 151 : i = tommy_list_head(&state->contentlist); - 3555 1314 : while (i) { - 3556 1012 : struct snapraid_content* content = i->data; - 3557 : char tmp[PATH_MAX]; - 3558 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3559 1012 : if (sopen_multi_file(f, k, tmp) != 0) { - 3560 : /* LCOV_EXCL_START */ - 3561 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); - 3562 : exit(EXIT_FAILURE); - 3563 : /* LCOV_EXCL_STOP */ - 3564 : } - 3565 1012 : ++k; - 3566 1012 : i = i->next; - 3567 : } - 3568 : - 3569 : /* allocate the thread context */ - 3570 151 : context = malloc_nofail(sizeof(struct state_write_thread_context)); - 3571 : - 3572 : /* initialize */ - 3573 151 : context->state = state; - 3574 151 : context->blockmax = blockmax; - 3575 151 : context->info_oldest = info_oldest; - 3576 151 : context->info_has_rehash = info_has_rehash; - 3577 151 : context->f = f; - 3578 : - 3579 151 : retval = state_write_thread(context); - 3580 : - 3581 : /* abort on failure */ - 3582 151 : if (retval) { - 3583 : /* LCOV_EXCL_START */ - 3584 : exit(EXIT_FAILURE); - 3585 : /* LCOV_EXCL_STOP */ - 3586 : } - 3587 : - 3588 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ - 3589 : /* than even in a system crash event we have one valid copy of the file. */ - 3590 151 : if (sflush(f) != 0) { - 3591 : /* LCOV_EXCL_START */ - 3592 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); - 3593 : exit(EXIT_FAILURE); - 3594 : /* LCOV_EXCL_STOP */ - 3595 : } - 3596 : - 3597 : #if HAVE_FSYNC - 3598 151 : if (ssync(f) != 0) { - 3599 : /* LCOV_EXCL_START */ - 3600 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); - 3601 : exit(EXIT_FAILURE); - 3602 : /* LCOV_EXCL_STOP */ - 3603 : } - 3604 : #endif - 3605 : - 3606 151 : if (sclose(f) != 0) { - 3607 : /* LCOV_EXCL_START */ - 3608 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); - 3609 : exit(EXIT_FAILURE); - 3610 : /* LCOV_EXCL_STOP */ - 3611 : } - 3612 : - 3613 151 : crc = context->crc; - 3614 151 : count_file = context->count_file; - 3615 151 : count_hardlink = context->count_hardlink; - 3616 151 : count_symlink = context->count_symlink; - 3617 151 : count_dir = context->count_dir; - 3618 : - 3619 151 : free(context); - 3620 : #endif - 3621 : - 3622 151 : msg_verbose("%8u files\n", count_file); - 3623 151 : msg_verbose("%8u hardlinks\n", count_hardlink); - 3624 151 : msg_verbose("%8u symlinks\n", count_symlink); - 3625 151 : msg_verbose("%8u empty dirs\n", count_dir); + 3527 : free(context); + 3528 : + 3529 : i = i->next; + 3530 : } + 3531 : + 3532 : /* abort on failure */ + 3533 : if (fail) { + 3534 : /* LCOV_EXCL_START */ + 3535 : exit(EXIT_FAILURE); + 3536 : /* LCOV_EXCL_STOP */ + 3537 : } + 3538 : #else + 3539 : /* count the content files */ + 3540 151 : count_content = 0; + 3541 151 : i = tommy_list_head(&state->contentlist); + 3542 1314 : while (i) { + 3543 1012 : struct snapraid_content* content = i->data; + 3544 1012 : msg_progress("Saving state to %s...\n", content->content); + 3545 1012 : ++count_content; + 3546 1012 : i = i->next; + 3547 : } + 3548 : + 3549 : /* open all the content files */ + 3550 151 : f = sopen_multi_write(count_content); + 3551 151 : if (!f) { + 3552 : /* LCOV_EXCL_START */ + 3553 : log_fatal("Error opening the content files.\n"); + 3554 : exit(EXIT_FAILURE); + 3555 : /* LCOV_EXCL_STOP */ + 3556 : } + 3557 : + 3558 151 : k = 0; + 3559 151 : i = tommy_list_head(&state->contentlist); + 3560 1314 : while (i) { + 3561 1012 : struct snapraid_content* content = i->data; + 3562 : char tmp[PATH_MAX]; + 3563 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3564 1012 : if (sopen_multi_file(f, k, tmp) != 0) { + 3565 : /* LCOV_EXCL_START */ + 3566 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3567 : exit(EXIT_FAILURE); + 3568 : /* LCOV_EXCL_STOP */ + 3569 : } + 3570 1012 : ++k; + 3571 1012 : i = i->next; + 3572 : } + 3573 : + 3574 : /* allocate the thread context */ + 3575 151 : context = malloc_nofail(sizeof(struct state_write_thread_context)); + 3576 : + 3577 : /* initialize */ + 3578 151 : context->state = state; + 3579 151 : context->blockmax = blockmax; + 3580 151 : context->info_oldest = info_oldest; + 3581 151 : context->info_has_rehash = info_has_rehash; + 3582 151 : context->f = f; + 3583 : + 3584 151 : retval = state_write_thread(context); + 3585 : + 3586 : /* abort on failure */ + 3587 151 : if (retval) { + 3588 : /* LCOV_EXCL_START */ + 3589 : exit(EXIT_FAILURE); + 3590 : /* LCOV_EXCL_STOP */ + 3591 : } + 3592 : + 3593 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + 3594 : /* than even in a system crash event we have one valid copy of the file. */ + 3595 151 : if (sflush(f) != 0) { + 3596 : /* LCOV_EXCL_START */ + 3597 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + 3598 : exit(EXIT_FAILURE); + 3599 : /* LCOV_EXCL_STOP */ + 3600 : } + 3601 : + 3602 : #if HAVE_FSYNC + 3603 151 : if (ssync(f) != 0) { + 3604 : /* LCOV_EXCL_START */ + 3605 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + 3606 : exit(EXIT_FAILURE); + 3607 : /* LCOV_EXCL_STOP */ + 3608 : } + 3609 : #endif + 3610 : + 3611 151 : if (sclose(f) != 0) { + 3612 : /* LCOV_EXCL_START */ + 3613 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3614 : exit(EXIT_FAILURE); + 3615 : /* LCOV_EXCL_STOP */ + 3616 : } + 3617 : + 3618 151 : crc = context->crc; + 3619 151 : count_file = context->count_file; + 3620 151 : count_hardlink = context->count_hardlink; + 3621 151 : count_symlink = context->count_symlink; + 3622 151 : count_dir = context->count_dir; + 3623 : + 3624 151 : free(context); + 3625 : #endif 3626 : - 3627 151 : *out_crc = crc; - 3628 151 : } - 3629 : - 3630 261 : void state_read(struct snapraid_state* state) - 3631 : { - 3632 : STREAM* f; - 3633 : char path[PATH_MAX]; - 3634 : struct stat st; - 3635 : tommy_node* node; - 3636 : int ret; - 3637 : int c; - 3638 : - 3639 : /* iterate over all the available content files and load the first one present */ - 3640 261 : f = 0; - 3641 261 : node = tommy_list_head(&state->contentlist); - 3642 572 : while (node) { - 3643 304 : struct snapraid_content* content = node->data; - 3644 304 : pathcpy(path, sizeof(path), content->content); - 3645 : - 3646 304 : if (!state->no_conf) { - 3647 303 : log_tag("content:%s\n", path); - 3648 303 : log_flush(); - 3649 : } - 3650 304 : msg_progress("Loading state from %s...\n", path); - 3651 : - 3652 304 : f = sopen_read(path); - 3653 304 : if (f != 0) { - 3654 : /* if opened stop the search */ - 3655 254 : break; - 3656 : } else { - 3657 : /* if it's real error of an existing file, abort */ - 3658 50 : if (errno != ENOENT) { - 3659 : /* LCOV_EXCL_START */ - 3660 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno)); - 3661 : exit(EXIT_FAILURE); - 3662 : /* LCOV_EXCL_STOP */ - 3663 : } - 3664 : - 3665 : /* otherwise continue */ - 3666 50 : if (node->next) { - 3667 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path); - 3668 : - 3669 : /* ensure to rewrite all the content files */ - 3670 43 : state->need_write = 1; - 3671 : } - 3672 : } + 3627 151 : msg_verbose("%8u files\n", count_file); + 3628 151 : msg_verbose("%8u hardlinks\n", count_hardlink); + 3629 151 : msg_verbose("%8u symlinks\n", count_symlink); + 3630 151 : msg_verbose("%8u empty dirs\n", count_dir); + 3631 : + 3632 151 : *out_crc = crc; + 3633 151 : } + 3634 : + 3635 261 : void state_read(struct snapraid_state* state) + 3636 : { + 3637 : STREAM* f; + 3638 : char path[PATH_MAX]; + 3639 : struct stat st; + 3640 : tommy_node* node; + 3641 : int ret; + 3642 : int c; + 3643 : + 3644 : /* iterate over all the available content files and load the first one present */ + 3645 261 : f = 0; + 3646 261 : node = tommy_list_head(&state->contentlist); + 3647 572 : while (node) { + 3648 304 : struct snapraid_content* content = node->data; + 3649 304 : pathcpy(path, sizeof(path), content->content); + 3650 : + 3651 304 : if (!state->no_conf) { + 3652 303 : log_tag("content:%s\n", path); + 3653 303 : log_flush(); + 3654 : } + 3655 304 : msg_progress("Loading state from %s...\n", path); + 3656 : + 3657 304 : f = sopen_read(path); + 3658 304 : if (f != 0) { + 3659 : /* if opened stop the search */ + 3660 254 : break; + 3661 : } else { + 3662 : /* if it's real error of an existing file, abort */ + 3663 50 : if (errno != ENOENT) { + 3664 : /* LCOV_EXCL_START */ + 3665 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno)); + 3666 : exit(EXIT_FAILURE); + 3667 : /* LCOV_EXCL_STOP */ + 3668 : } + 3669 : + 3670 : /* otherwise continue */ + 3671 50 : if (node->next) { + 3672 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path); 3673 : - 3674 : /* next content file */ - 3675 50 : node = node->next; - 3676 : } - 3677 : - 3678 : /* if not found, assume empty */ - 3679 261 : if (!f) { - 3680 7 : log_fatal("No content file found. Assuming empty.\n"); - 3681 : - 3682 : /* create the initial mapping */ - 3683 7 : state_map(state); - 3684 267 : return; - 3685 : } + 3674 : /* ensure to rewrite all the content files */ + 3675 43 : state->need_write = 1; + 3676 : } + 3677 : } + 3678 : + 3679 : /* next content file */ + 3680 50 : node = node->next; + 3681 : } + 3682 : + 3683 : /* if not found, assume empty */ + 3684 261 : if (!f) { + 3685 7 : log_fatal("No content file found. Assuming empty.\n"); 3686 : - 3687 : /* get the stat of the content file */ - 3688 254 : ret = fstat(shandle(f), &st); - 3689 254 : if (ret != 0) { - 3690 : /* LCOV_EXCL_START */ - 3691 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno)); - 3692 : exit(EXIT_FAILURE); - 3693 : /* LCOV_EXCL_STOP */ - 3694 : } - 3695 : - 3696 : /* go further to check other content files */ - 3697 1955 : while (node) { - 3698 : char other_path[PATH_MAX]; - 3699 : struct stat other_st; - 3700 1447 : struct snapraid_content* content = node->data; - 3701 1447 : pathcpy(other_path, sizeof(other_path), content->content); - 3702 : - 3703 1447 : ret = stat(other_path, &other_st); - 3704 1447 : if (ret != 0) { - 3705 : /* allow missing content files, but not any other kind of error */ - 3706 1 : if (errno != ENOENT) { - 3707 : /* LCOV_EXCL_START */ - 3708 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno)); - 3709 : exit(EXIT_FAILURE); - 3710 : /* LCOV_EXCL_STOP */ - 3711 : } - 3712 : - 3713 : /* ensure to rewrite all the content files */ - 3714 1 : state->need_write = 1; - 3715 : } else { - 3716 : /* if the size is different */ - 3717 1446 : if (other_st.st_size != st.st_size) { - 3718 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path); - 3719 39 : log_fatal("Likely one of the two is broken!\n"); - 3720 : - 3721 : /* ensure to rewrite all the content files */ - 3722 39 : state->need_write = 1; - 3723 : } - 3724 : } + 3687 : /* create the initial mapping */ + 3688 7 : state_map(state); + 3689 267 : return; + 3690 : } + 3691 : + 3692 : /* get the stat of the content file */ + 3693 254 : ret = fstat(shandle(f), &st); + 3694 254 : if (ret != 0) { + 3695 : /* LCOV_EXCL_START */ + 3696 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno)); + 3697 : exit(EXIT_FAILURE); + 3698 : /* LCOV_EXCL_STOP */ + 3699 : } + 3700 : + 3701 : /* go further to check other content files */ + 3702 1955 : while (node) { + 3703 : char other_path[PATH_MAX]; + 3704 : struct stat other_st; + 3705 1447 : struct snapraid_content* content = node->data; + 3706 1447 : pathcpy(other_path, sizeof(other_path), content->content); + 3707 : + 3708 1447 : ret = stat(other_path, &other_st); + 3709 1447 : if (ret != 0) { + 3710 : /* allow missing content files, but not any other kind of error */ + 3711 1 : if (errno != ENOENT) { + 3712 : /* LCOV_EXCL_START */ + 3713 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno)); + 3714 : exit(EXIT_FAILURE); + 3715 : /* LCOV_EXCL_STOP */ + 3716 : } + 3717 : + 3718 : /* ensure to rewrite all the content files */ + 3719 1 : state->need_write = 1; + 3720 : } else { + 3721 : /* if the size is different */ + 3722 1446 : if (other_st.st_size != st.st_size) { + 3723 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path); + 3724 39 : log_fatal("Likely one of the two is broken!\n"); 3725 : - 3726 : /* next content file */ - 3727 1447 : node = node->next; - 3728 : } - 3729 : - 3730 : /* start with a undefined default. */ - 3731 : /* it's for compatibility with version 1.0 where MD5 was implicit. */ - 3732 254 : state->hash = HASH_UNDEFINED; - 3733 : - 3734 : /* start with a zero seed, it was the default in old versions */ - 3735 254 : memset(state->hashseed, 0, HASH_MAX); - 3736 : - 3737 : /* previous hash, start with an undefined value */ - 3738 254 : state->prevhash = HASH_UNDEFINED; - 3739 : - 3740 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + 3726 : /* ensure to rewrite all the content files */ + 3727 39 : state->need_write = 1; + 3728 : } + 3729 : } + 3730 : + 3731 : /* next content file */ + 3732 1447 : node = node->next; + 3733 : } + 3734 : + 3735 : /* start with a undefined default. */ + 3736 : /* it's for compatibility with version 1.0 where MD5 was implicit. */ + 3737 254 : state->hash = HASH_UNDEFINED; + 3738 : + 3739 : /* start with a zero seed, it was the default in old versions */ + 3740 254 : memset(state->hashseed, 0, HASH_MAX); 3741 : - 3742 : /* get the first char to detect the file type */ - 3743 254 : c = sgetc(f); - 3744 254 : sungetc(c, f); - 3745 : - 3746 : /* guess the file type from the first char */ - 3747 254 : if (c == 'S') { - 3748 254 : state_read_content(state, path, f); - 3749 : } else { - 3750 : /* LCOV_EXCL_START */ - 3751 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n"); - 3752 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n"); - 3753 : exit(EXIT_FAILURE); - 3754 : /* LCOV_EXCL_STOP */ - 3755 : } - 3756 : - 3757 253 : sclose(f); - 3758 : - 3759 253 : if (state->hash == HASH_UNDEFINED) { - 3760 : /* LCOV_EXCL_START */ - 3761 : log_fatal("The checksum to use is not specified.\n"); - 3762 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n"); - 3763 : log_fatal("To use a new SnapRAID you must restart from scratch,\n"); - 3764 : log_fatal("deleting all the content and parity files.\n"); - 3765 : exit(EXIT_FAILURE); - 3766 : /* LCOV_EXCL_STOP */ - 3767 : } - 3768 : - 3769 : /* update the mapping */ - 3770 253 : state_map(state); - 3771 : - 3772 253 : state_content_check(state, path); + 3742 : /* previous hash, start with an undefined value */ + 3743 254 : state->prevhash = HASH_UNDEFINED; + 3744 : + 3745 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + 3746 : + 3747 : /* get the first char to detect the file type */ + 3748 254 : c = sgetc(f); + 3749 254 : sungetc(c, f); + 3750 : + 3751 : /* guess the file type from the first char */ + 3752 254 : if (c == 'S') { + 3753 254 : state_read_content(state, path, f); + 3754 : } else { + 3755 : /* LCOV_EXCL_START */ + 3756 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n"); + 3757 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n"); + 3758 : exit(EXIT_FAILURE); + 3759 : /* LCOV_EXCL_STOP */ + 3760 : } + 3761 : + 3762 253 : sclose(f); + 3763 : + 3764 253 : if (state->hash == HASH_UNDEFINED) { + 3765 : /* LCOV_EXCL_START */ + 3766 : log_fatal("The checksum to use is not specified.\n"); + 3767 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n"); + 3768 : log_fatal("To use a new SnapRAID you must restart from scratch,\n"); + 3769 : log_fatal("deleting all the content and parity files.\n"); + 3770 : exit(EXIT_FAILURE); + 3771 : /* LCOV_EXCL_STOP */ + 3772 : } 3773 : - 3774 : /* mark that we read the content file, and it passed all the checks */ - 3775 253 : state->checked_read = 1; - 3776 : } - 3777 : - 3778 : struct state_verify_thread_context { - 3779 : struct snapraid_state* state; - 3780 : struct snapraid_content* content; - 3781 : #if HAVE_MT_VERIFY - 3782 : pthread_t thread; - 3783 : #else - 3784 : void* retval; - 3785 : #endif - 3786 : /* input */ - 3787 : uint32_t crc; - 3788 : STREAM* f; - 3789 : }; - 3790 : - 3791 1012 : static void* state_verify_thread(void* arg) - 3792 : { - 3793 1012 : struct state_verify_thread_context* context = arg; - 3794 1012 : STREAM* f = context->f; - 3795 : unsigned char buf[4]; - 3796 : uint32_t crc_stored; - 3797 : uint32_t crc_computed; - 3798 : - 3799 1012 : if (sdeplete(f, buf) != 0) { - 3800 : /* LCOV_EXCL_START */ - 3801 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 3802 : return context; - 3803 : /* LCOV_EXCL_STOP */ - 3804 : } - 3805 : - 3806 : /* get the stored crc from the last four bytes */ - 3807 1012 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; - 3808 : - 3809 1012 : if (crc_stored != context->crc) { - 3810 : /* LCOV_EXCL_START */ - 3811 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f)); - 3812 : return context; - 3813 : /* LCOV_EXCL_STOP */ - 3814 : } - 3815 : - 3816 : /* get the computed crc */ - 3817 1012 : crc_computed = scrc(f); - 3818 : - 3819 : /* adjust the stored crc to include itself */ - 3820 1012 : crc_stored = crc32c(crc_stored, buf, 4); - 3821 : - 3822 1012 : if (crc_computed != crc_stored) { - 3823 : /* LCOV_EXCL_START */ - 3824 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f)); - 3825 : return context; - 3826 : /* LCOV_EXCL_STOP */ - 3827 : } - 3828 : - 3829 1012 : return 0; - 3830 : } - 3831 : - 3832 151 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) - 3833 : { - 3834 : tommy_node* i; - 3835 : int fail; + 3774 : /* update the mapping */ + 3775 253 : state_map(state); + 3776 : + 3777 253 : state_content_check(state, path); + 3778 : + 3779 : /* mark that we read the content file, and it passed all the checks */ + 3780 253 : state->checked_read = 1; + 3781 : } + 3782 : + 3783 : struct state_verify_thread_context { + 3784 : struct snapraid_state* state; + 3785 : struct snapraid_content* content; + 3786 : #if HAVE_MT_VERIFY + 3787 : pthread_t thread; + 3788 : #else + 3789 : void* retval; + 3790 : #endif + 3791 : /* input */ + 3792 : uint32_t crc; + 3793 : STREAM* f; + 3794 : }; + 3795 : + 3796 1009 : static void* state_verify_thread(void* arg) + 3797 : { + 3798 1009 : struct state_verify_thread_context* context = arg; + 3799 1009 : STREAM* f = context->f; + 3800 : unsigned char buf[4]; + 3801 : uint32_t crc_stored; + 3802 : uint32_t crc_computed; + 3803 : + 3804 1009 : if (sdeplete(f, buf) != 0) { + 3805 : /* LCOV_EXCL_START */ + 3806 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3807 : return context; + 3808 : /* LCOV_EXCL_STOP */ + 3809 : } + 3810 : + 3811 : /* get the stored crc from the last four bytes */ + 3812 1012 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + 3813 : + 3814 1012 : if (crc_stored != context->crc) { + 3815 : /* LCOV_EXCL_START */ + 3816 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f)); + 3817 : return context; + 3818 : /* LCOV_EXCL_STOP */ + 3819 : } + 3820 : + 3821 : /* get the computed crc */ + 3822 1012 : crc_computed = scrc(f); + 3823 : + 3824 : /* adjust the stored crc to include itself */ + 3825 1012 : crc_stored = crc32c(crc_stored, buf, 4); + 3826 : + 3827 1012 : if (crc_computed != crc_stored) { + 3828 : /* LCOV_EXCL_START */ + 3829 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f)); + 3830 : return context; + 3831 : /* LCOV_EXCL_STOP */ + 3832 : } + 3833 : + 3834 1012 : return 0; + 3835 : } 3836 : - 3837 : /* start all reading threads */ - 3838 151 : i = tommy_list_head(&state->contentlist); - 3839 1314 : while (i) { - 3840 1012 : struct snapraid_content* content = i->data; - 3841 : struct state_verify_thread_context* context; - 3842 : char tmp[PATH_MAX]; - 3843 : STREAM* f; - 3844 : - 3845 1012 : msg_progress("Verifying %s...\n", content->content); - 3846 : - 3847 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3848 : - 3849 1012 : f = sopen_read(tmp); - 3850 1012 : if (f == 0) { - 3851 : /* LCOV_EXCL_START */ - 3852 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno)); - 3853 : exit(EXIT_FAILURE); - 3854 : /* LCOV_EXCL_STOP */ - 3855 : } - 3856 : - 3857 : /* allocate the thread context */ - 3858 1012 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); - 3859 1012 : content->context = context; - 3860 : - 3861 : /* initialize */ - 3862 1012 : context->state = state; - 3863 1012 : context->content = content; - 3864 1012 : context->crc = crc; - 3865 1012 : context->f = f; - 3866 : - 3867 : #if HAVE_MT_VERIFY - 3868 1012 : thread_create(&context->thread, 0, state_verify_thread, context); - 3869 : #else - 3870 : context->retval = state_verify_thread(context); - 3871 : #endif - 3872 : - 3873 1012 : i = i->next; - 3874 : } - 3875 : - 3876 : /* join all thread */ - 3877 151 : fail = 0; - 3878 151 : i = tommy_list_head(&state->contentlist); - 3879 1314 : while (i) { - 3880 1012 : struct snapraid_content* content = i->data; - 3881 1012 : struct state_verify_thread_context* context = content->context; - 3882 : void* retval; - 3883 : - 3884 : #if HAVE_MT_VERIFY - 3885 1012 : thread_join(context->thread, &retval); - 3886 : #else - 3887 : retval = context->retval; - 3888 : #endif - 3889 1012 : if (retval) { - 3890 : /* LCOV_EXCL_START */ - 3891 : fail = 1; - 3892 : /* LCOV_EXCL_STOP */ - 3893 : } else { - 3894 1012 : STREAM* f = context->f; - 3895 : - 3896 1012 : if (sclose(f) != 0) { - 3897 : /* LCOV_EXCL_START */ - 3898 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); - 3899 : exit(EXIT_FAILURE); - 3900 : /* LCOV_EXCL_STOP */ - 3901 : } - 3902 : } - 3903 : - 3904 1012 : free(context); - 3905 : - 3906 1012 : i = i->next; - 3907 : } + 3837 151 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) + 3838 : { + 3839 : tommy_node* i; + 3840 : int fail; + 3841 : + 3842 : /* start all reading threads */ + 3843 151 : i = tommy_list_head(&state->contentlist); + 3844 1314 : while (i) { + 3845 1012 : struct snapraid_content* content = i->data; + 3846 : struct state_verify_thread_context* context; + 3847 : char tmp[PATH_MAX]; + 3848 : STREAM* f; + 3849 : + 3850 1012 : msg_progress("Verifying %s...\n", content->content); + 3851 : + 3852 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3853 : + 3854 1012 : f = sopen_read(tmp); + 3855 1012 : if (f == 0) { + 3856 : /* LCOV_EXCL_START */ + 3857 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3858 : exit(EXIT_FAILURE); + 3859 : /* LCOV_EXCL_STOP */ + 3860 : } + 3861 : + 3862 : /* allocate the thread context */ + 3863 1012 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); + 3864 1012 : content->context = context; + 3865 : + 3866 : /* initialize */ + 3867 1012 : context->state = state; + 3868 1012 : context->content = content; + 3869 1012 : context->crc = crc; + 3870 1012 : context->f = f; + 3871 : + 3872 : #if HAVE_MT_VERIFY + 3873 1012 : thread_create(&context->thread, 0, state_verify_thread, context); + 3874 : #else + 3875 : context->retval = state_verify_thread(context); + 3876 : #endif + 3877 : + 3878 1012 : i = i->next; + 3879 : } + 3880 : + 3881 : /* join all thread */ + 3882 151 : fail = 0; + 3883 151 : i = tommy_list_head(&state->contentlist); + 3884 1314 : while (i) { + 3885 1012 : struct snapraid_content* content = i->data; + 3886 1012 : struct state_verify_thread_context* context = content->context; + 3887 : void* retval; + 3888 : + 3889 : #if HAVE_MT_VERIFY + 3890 1012 : thread_join(context->thread, &retval); + 3891 : #else + 3892 : retval = context->retval; + 3893 : #endif + 3894 1012 : if (retval) { + 3895 : /* LCOV_EXCL_START */ + 3896 : fail = 1; + 3897 : /* LCOV_EXCL_STOP */ + 3898 : } else { + 3899 1012 : STREAM* f = context->f; + 3900 : + 3901 1012 : if (sclose(f) != 0) { + 3902 : /* LCOV_EXCL_START */ + 3903 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3904 : exit(EXIT_FAILURE); + 3905 : /* LCOV_EXCL_STOP */ + 3906 : } + 3907 : } 3908 : - 3909 : /* abort on failure */ - 3910 151 : if (fail) { - 3911 : /* LCOV_EXCL_START */ - 3912 : exit(EXIT_FAILURE); - 3913 : /* LCOV_EXCL_STOP */ - 3914 : } - 3915 151 : } - 3916 : - 3917 151 : static void state_rename_content(struct snapraid_state* state) - 3918 : { - 3919 : tommy_node* i; - 3920 : - 3921 151 : i = tommy_list_head(&state->contentlist); - 3922 1314 : while (i) { - 3923 1012 : struct snapraid_content* content = i->data; - 3924 : char tmp[PATH_MAX]; + 3909 1012 : free(context); + 3910 : + 3911 1012 : i = i->next; + 3912 : } + 3913 : + 3914 : /* abort on failure */ + 3915 151 : if (fail) { + 3916 : /* LCOV_EXCL_START */ + 3917 : exit(EXIT_FAILURE); + 3918 : /* LCOV_EXCL_STOP */ + 3919 : } + 3920 151 : } + 3921 : + 3922 151 : static void state_rename_content(struct snapraid_state* state) + 3923 : { + 3924 : tommy_node* i; 3925 : - 3926 : /* now renames the just written copy with the correct name */ - 3927 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3928 1012 : if (rename(tmp, content->content) != 0) { - 3929 : /* LCOV_EXCL_START */ - 3930 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); - 3931 : exit(EXIT_FAILURE); - 3932 : /* LCOV_EXCL_STOP */ - 3933 : } - 3934 : - 3935 1012 : i = i->next; - 3936 : } - 3937 151 : } - 3938 : - 3939 151 : void state_write(struct snapraid_state* state) - 3940 : { - 3941 : uint32_t crc; - 3942 : - 3943 : /* write all the content files */ - 3944 151 : state_write_content(state, &crc); - 3945 : - 3946 : /* verify the just written files */ - 3947 151 : state_verify_content(state, crc); - 3948 : - 3949 : /* rename the new files, over the old ones */ - 3950 151 : state_rename_content(state); - 3951 : - 3952 151 : state->need_write = 0; /* no write needed anymore */ - 3953 151 : state->checked_read = 0; /* what we wrote is not checked in read */ - 3954 151 : } - 3955 : - 3956 122 : void state_skip(struct snapraid_state* state) - 3957 : { - 3958 : tommy_node* i; - 3959 : - 3960 : /* for each disk */ - 3961 850 : for (i = state->disklist; i != 0; i = i->next) { - 3962 : tommy_node* j; - 3963 728 : struct snapraid_disk* disk = i->data; + 3926 151 : i = tommy_list_head(&state->contentlist); + 3927 1314 : while (i) { + 3928 1012 : struct snapraid_content* content = i->data; + 3929 : char tmp[PATH_MAX]; + 3930 : + 3931 : /* now renames the just written copy with the correct name */ + 3932 1012 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3933 1012 : if (rename(tmp, content->content) != 0) { + 3934 : /* LCOV_EXCL_START */ + 3935 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); + 3936 : exit(EXIT_FAILURE); + 3937 : /* LCOV_EXCL_STOP */ + 3938 : } + 3939 : + 3940 1012 : i = i->next; + 3941 : } + 3942 151 : } + 3943 : + 3944 151 : void state_write(struct snapraid_state* state) + 3945 : { + 3946 : uint32_t crc; + 3947 : + 3948 : /* write all the content files */ + 3949 151 : state_write_content(state, &crc); + 3950 : + 3951 : /* verify the just written files */ + 3952 151 : state_verify_content(state, crc); + 3953 : + 3954 : /* rename the new files, over the old ones */ + 3955 151 : state_rename_content(state); + 3956 : + 3957 151 : state->need_write = 0; /* no write needed anymore */ + 3958 151 : state->checked_read = 0; /* what we wrote is not checked in read */ + 3959 151 : } + 3960 : + 3961 122 : void state_skip(struct snapraid_state* state) + 3962 : { + 3963 : tommy_node* i; 3964 : - 3965 728 : if (!disk->skip_access) - 3966 727 : continue; - 3967 : - 3968 : /* for each file */ - 3969 1885 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { - 3970 1884 : struct snapraid_file* file = j->data; - 3971 1884 : file_flag_set(file, FILE_IS_EXCLUDED); - 3972 : } - 3973 : - 3974 : /* for each link */ - 3975 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { - 3976 56 : struct snapraid_link* slink = j->data; - 3977 56 : link_flag_set(slink, FILE_IS_EXCLUDED); - 3978 : } - 3979 : - 3980 : /* for each dir */ - 3981 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { - 3982 0 : struct snapraid_dir* dir = j->data; - 3983 0 : dir_flag_set(dir, FILE_IS_EXCLUDED); - 3984 : } - 3985 : } - 3986 122 : } - 3987 : - 3988 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) - 3989 : { - 3990 : tommy_node* i; - 3991 : unsigned l; + 3965 : /* for each disk */ + 3966 850 : for (i = state->disklist; i != 0; i = i->next) { + 3967 : tommy_node* j; + 3968 728 : struct snapraid_disk* disk = i->data; + 3969 : + 3970 728 : if (!disk->skip_access) + 3971 727 : continue; + 3972 : + 3973 : /* for each file */ + 3974 1885 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + 3975 1884 : struct snapraid_file* file = j->data; + 3976 1884 : file_flag_set(file, FILE_IS_EXCLUDED); + 3977 : } + 3978 : + 3979 : /* for each link */ + 3980 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + 3981 56 : struct snapraid_link* slink = j->data; + 3982 56 : link_flag_set(slink, FILE_IS_EXCLUDED); + 3983 : } + 3984 : + 3985 : /* for each dir */ + 3986 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + 3987 0 : struct snapraid_dir* dir = j->data; + 3988 0 : dir_flag_set(dir, FILE_IS_EXCLUDED); + 3989 : } + 3990 : } + 3991 122 : } 3992 : - 3993 : /* if no filter, include all */ - 3994 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) - 3995 235 : return; - 3996 : - 3997 9 : msg_progress("Filtering...\n"); - 3998 : - 3999 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { - 4000 8 : struct snapraid_filter* filter = i->data; - 4001 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : ""); - 4002 : } - 4003 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) { - 4004 3 : struct snapraid_filter* filter = i->data; - 4005 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : ""); - 4006 : } - 4007 9 : if (filter_missing) - 4008 2 : msg_verbose("\t<missing>\n"); - 4009 9 : if (filter_error) - 4010 2 : msg_verbose("\t<error>\n"); - 4011 : - 4012 : /* for each disk */ - 4013 63 : for (i = state->disklist; i != 0; i = i->next) { - 4014 : tommy_node* j; - 4015 54 : struct snapraid_disk* disk = i->data; + 3993 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) + 3994 : { + 3995 : tommy_node* i; + 3996 : unsigned l; + 3997 : + 3998 : /* if no filter, include all */ + 3999 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) + 4000 235 : return; + 4001 : + 4002 9 : msg_progress("Filtering...\n"); + 4003 : + 4004 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + 4005 8 : struct snapraid_filter* filter = i->data; + 4006 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : ""); + 4007 : } + 4008 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) { + 4009 3 : struct snapraid_filter* filter = i->data; + 4010 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : ""); + 4011 : } + 4012 9 : if (filter_missing) + 4013 2 : msg_verbose("\t<missing>\n"); + 4014 9 : if (filter_error) + 4015 2 : msg_verbose("\t<error>\n"); 4016 : - 4017 : /* if we filter for presence, we have to access the disk, so better to print something */ - 4018 54 : if (filter_missing) - 4019 12 : msg_progress("Scanning disk %s...\n", disk->name); - 4020 : - 4021 : /* for each file */ - 4022 133944 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { - 4023 133890 : struct snapraid_file* file = j->data; - 4024 : - 4025 133890 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0 - 4026 80982 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0 - 4027 78138 : || filter_existence(filter_missing, disk->dir, file->sub) != 0 - 4028 38646 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 - 4029 : ) { - 4030 109490 : file_flag_set(file, FILE_IS_EXCLUDED); - 4031 : } - 4032 : } - 4033 : - 4034 : /* for each link */ - 4035 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { - 4036 4360 : struct snapraid_link* slink = j->data; - 4037 : - 4038 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0 - 4039 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0 - 4040 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0 - 4041 : ) { - 4042 3221 : link_flag_set(slink, FILE_IS_EXCLUDED); - 4043 : } - 4044 : } - 4045 : - 4046 : /* for each empty dir */ - 4047 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { - 4048 28 : struct snapraid_dir* dir = j->data; - 4049 : - 4050 28 : if (filter_emptydir(filterlist_disk, 0, disk->name, dir->sub) != 0 - 4051 17 : || filter_emptydir(filterlist_file, 0, disk->name, dir->sub) != 0 - 4052 17 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0 - 4053 : ) { - 4054 19 : dir_flag_set(dir, FILE_IS_EXCLUDED); - 4055 : } - 4056 : } - 4057 : } - 4058 : - 4059 : /* if we are filtering by disk */ - 4060 9 : if (!tommy_list_empty(filterlist_disk)) { - 4061 : /* for each parity disk */ - 4062 20 : for (l = 0; l < state->level; ++l) { - 4063 : /* check if the parity is excluded by name */ - 4064 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) { - 4065 : /* excluded the parity from further operation */ - 4066 11 : state->parity[l].is_excluded = 1; - 4067 : } - 4068 : } - 4069 : } else { - 4070 : /* if we are filtering by file, exclude all parity */ - 4071 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) { - 4072 : /* for each parity disk */ - 4073 16 : for (l = 0; l < state->level; ++l) { - 4074 13 : state->parity[l].is_excluded = 1; - 4075 : } - 4076 : } - 4077 : } - 4078 : } - 4079 : - 4080 221 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax) - 4081 : { - 4082 : time_t now; - 4083 : - 4084 221 : if (state->opt.gui) { - 4085 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax); - 4086 5 : log_flush(); - 4087 : } + 4017 : /* for each disk */ + 4018 63 : for (i = state->disklist; i != 0; i = i->next) { + 4019 : tommy_node* j; + 4020 54 : struct snapraid_disk* disk = i->data; + 4021 : + 4022 : /* if we filter for presence, we have to access the disk, so better to print something */ + 4023 54 : if (filter_missing) + 4024 12 : msg_progress("Scanning disk %s...\n", disk->name); + 4025 : + 4026 : /* for each file */ + 4027 133944 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + 4028 133890 : struct snapraid_file* file = j->data; + 4029 : + 4030 133890 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0 + 4031 80982 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0 + 4032 78138 : || filter_existence(filter_missing, disk->dir, file->sub) != 0 + 4033 38646 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 + 4034 : ) { + 4035 109458 : file_flag_set(file, FILE_IS_EXCLUDED); + 4036 : } + 4037 : } + 4038 : + 4039 : /* for each link */ + 4040 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + 4041 4360 : struct snapraid_link* slink = j->data; + 4042 : + 4043 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0 + 4044 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0 + 4045 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0 + 4046 : ) { + 4047 3221 : link_flag_set(slink, FILE_IS_EXCLUDED); + 4048 : } + 4049 : } + 4050 : + 4051 : /* for each empty dir */ + 4052 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + 4053 28 : struct snapraid_dir* dir = j->data; + 4054 : + 4055 28 : if (filter_emptydir(filterlist_disk, 0, disk->name, dir->sub) != 0 + 4056 17 : || filter_emptydir(filterlist_file, 0, disk->name, dir->sub) != 0 + 4057 17 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0 + 4058 : ) { + 4059 19 : dir_flag_set(dir, FILE_IS_EXCLUDED); + 4060 : } + 4061 : } + 4062 : } + 4063 : + 4064 : /* if we are filtering by disk, exclude any parity not explicitely included */ + 4065 9 : if (!tommy_list_empty(filterlist_disk)) { + 4066 : /* for each parity disk */ + 4067 20 : for (l = 0; l < state->level; ++l) { + 4068 : /* check if the parity is excluded by name */ + 4069 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) { + 4070 : /* excluded the parity from further operation */ + 4071 11 : state->parity[l].is_excluded_by_filter = 1; + 4072 : } + 4073 : } + 4074 : } else { + 4075 : /* if we are filtering by file, exclude all parity */ + 4076 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) { + 4077 : /* for each parity disk */ + 4078 16 : for (l = 0; l < state->level; ++l) { + 4079 13 : state->parity[l].is_excluded_by_filter = 1; + 4080 : } + 4081 : } + 4082 : } + 4083 : } + 4084 : + 4085 221 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax) + 4086 : { + 4087 : time_t now; 4088 : - 4089 221 : now = time(0); - 4090 : - 4091 221 : state->progress_whole_start = now; - 4092 : - 4093 221 : state->progress_tick = 0; - 4094 221 : state->progress_ptr = 0; - 4095 221 : state->progress_wasted = 0; - 4096 : - 4097 : /* stop if requested */ - 4098 221 : if (global_interrupt) { - 4099 : /* LCOV_EXCL_START */ - 4100 : if (!state->opt.gui) { - 4101 : msg_status("Not starting for interruption\n"); - 4102 : } - 4103 : log_tag("sigint:0: SIGINT received\n"); - 4104 : log_flush(); - 4105 : return 0; - 4106 : /* LCOV_EXCL_STOP */ - 4107 : } - 4108 : - 4109 221 : return 1; - 4110 : } - 4111 : - 4112 221 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize) - 4113 : { - 4114 221 : if (state->opt.gui) { - 4115 5 : log_tag("run:end\n"); - 4116 5 : log_flush(); - 4117 216 : } else if (countmax == 0) { - 4118 19 : msg_status("Nothing to do\n"); - 4119 : } else { - 4120 : time_t now; - 4121 : time_t elapsed; - 4122 : - 4123 197 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; - 4124 : - 4125 197 : now = time(0); - 4126 : - 4127 197 : elapsed = now - state->progress_whole_start - state->progress_wasted; - 4128 : - 4129 197 : msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB); - 4130 197 : if (elapsed >= 60) - 4131 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); - 4132 197 : msg_bar("\n"); - 4133 197 : msg_flush(); - 4134 : } - 4135 221 : } - 4136 : - 4137 1 : void state_progress_stop(struct snapraid_state* state) - 4138 : { - 4139 : time_t now; + 4089 221 : if (state->opt.gui) { + 4090 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax); + 4091 5 : log_flush(); + 4092 : } + 4093 : + 4094 221 : now = time(0); + 4095 : + 4096 221 : state->progress_whole_start = now; + 4097 : + 4098 221 : state->progress_tick = 0; + 4099 221 : state->progress_ptr = 0; + 4100 221 : state->progress_wasted = 0; + 4101 : + 4102 : /* stop if requested */ + 4103 221 : if (global_interrupt) { + 4104 : /* LCOV_EXCL_START */ + 4105 : if (!state->opt.gui) { + 4106 : msg_status("Not starting for interruption\n"); + 4107 : } + 4108 : log_tag("sigint:0: SIGINT received\n"); + 4109 : log_flush(); + 4110 : return 0; + 4111 : /* LCOV_EXCL_STOP */ + 4112 : } + 4113 : + 4114 221 : return 1; + 4115 : } + 4116 : + 4117 221 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize) + 4118 : { + 4119 221 : if (state->opt.gui) { + 4120 5 : log_tag("run:end\n"); + 4121 5 : log_flush(); + 4122 216 : } else if (countmax == 0) { + 4123 19 : msg_status("Nothing to do\n"); + 4124 : } else { + 4125 : time_t now; + 4126 : time_t elapsed; + 4127 : + 4128 197 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; + 4129 : + 4130 197 : now = time(0); + 4131 : + 4132 197 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 4133 : + 4134 197 : msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB); + 4135 : + 4136 197 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); + 4137 : + 4138 : /* some extra spaces to ensure to overwrite the latest status line */ + 4139 197 : msg_bar(" "); 4140 : - 4141 1 : now = time(0); - 4142 : - 4143 1 : if (!state->opt.gui) { - 4144 1 : msg_bar("\n"); - 4145 1 : msg_flush(); - 4146 : } - 4147 : - 4148 1 : state->progress_interruption = now; - 4149 1 : } - 4150 : - 4151 1 : void state_progress_restart(struct snapraid_state* state) - 4152 : { - 4153 : time_t now; - 4154 : - 4155 1 : now = time(0); + 4141 197 : msg_bar("\n"); + 4142 197 : msg_flush(); + 4143 : } + 4144 221 : } + 4145 : + 4146 1 : void state_progress_stop(struct snapraid_state* state) + 4147 : { + 4148 : time_t now; + 4149 : + 4150 1 : now = time(0); + 4151 : + 4152 1 : if (!state->opt.gui) { + 4153 1 : msg_bar("\n"); + 4154 1 : msg_flush(); + 4155 : } 4156 : - 4157 : /* reset the progress counter */ - 4158 1 : state->progress_tick = 0; - 4159 1 : state->progress_ptr = 0; - 4160 : - 4161 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ - 4162 1 : state->progress_wasted += now - state->progress_interruption; - 4163 1 : } - 4164 : - 4165 : #define PROGRESS_CLEAR " " - 4166 : - 4167 : /** - 4168 : * Set the latest tick data in the progress vector. - 4169 : */ - 4170 532 : static void state_progress_latest(struct snapraid_state* state) - 4171 : { - 4172 : tommy_node* i; - 4173 : unsigned l; - 4174 : - 4175 532 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc; - 4176 532 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched; - 4177 532 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid; - 4178 532 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash; - 4179 532 : state->progress_tick_io[state->progress_ptr] = state->tick_io; - 4180 3716 : for (i = state->disklist; i != 0; i = i->next) { - 4181 3184 : struct snapraid_disk* disk = i->data; - 4182 3184 : disk->progress_tick[state->progress_ptr] = disk->tick; - 4183 : } - 4184 2946 : for (l = 0; l < state->level; ++l) - 4185 2414 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick; - 4186 532 : } - 4187 : - 4188 : /** - 4189 : * Number of columns - 4190 : */ - 4191 : #define GRAPH_COLUMN 68 - 4192 : - 4193 : /** - 4194 : * Get the reference value, 0 if index is PROGRESS_MAX - 4195 : */ - 4196 : #define ref(map, index) (index < PROGRESS_MAX ? map[index] : 0) - 4197 : - 4198 2 : static void state_progress_graph(struct snapraid_state* state, struct snapraid_io* io, unsigned current, unsigned oldest) - 4199 : { - 4200 : uint64_t v; - 4201 : uint64_t tick_total; - 4202 : unsigned bar; - 4203 : tommy_node* i; - 4204 : unsigned l; - 4205 : size_t pad; + 4157 1 : state->progress_interruption = now; + 4158 1 : } + 4159 : + 4160 1 : void state_progress_restart(struct snapraid_state* state) + 4161 : { + 4162 : time_t now; + 4163 : + 4164 1 : now = time(0); + 4165 : + 4166 : /* reset the progress counter */ + 4167 1 : state->progress_tick = 0; + 4168 1 : state->progress_ptr = 0; + 4169 : + 4170 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ + 4171 1 : state->progress_wasted += now - state->progress_interruption; + 4172 1 : } + 4173 : + 4174 : #define PROGRESS_CLEAR " " + 4175 : + 4176 : /** + 4177 : * Set the latest tick data in the progress vector. + 4178 : */ + 4179 478 : static void state_progress_latest(struct snapraid_state* state) + 4180 : { + 4181 : tommy_node* i; + 4182 : unsigned l; + 4183 : + 4184 478 : state->progress_tick_misc[state->progress_ptr] = state->tick_misc; + 4185 478 : state->progress_tick_sched[state->progress_ptr] = state->tick_sched; + 4186 478 : state->progress_tick_raid[state->progress_ptr] = state->tick_raid; + 4187 478 : state->progress_tick_hash[state->progress_ptr] = state->tick_hash; + 4188 478 : state->progress_tick_io[state->progress_ptr] = state->tick_io; + 4189 3338 : for (i = state->disklist; i != 0; i = i->next) { + 4190 2860 : struct snapraid_disk* disk = i->data; + 4191 2860 : disk->progress_tick[state->progress_ptr] = disk->tick; + 4192 : } + 4193 2711 : for (l = 0; l < state->level; ++l) + 4194 2233 : state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick; + 4195 478 : } + 4196 : + 4197 : /** + 4198 : * Number of columns + 4199 : */ + 4200 : #define GRAPH_COLUMN 68 + 4201 : + 4202 : /** + 4203 : * Get the reference value, 0 if index is PROGRESS_MAX + 4204 : */ + 4205 : #define ref(map, index) (index < PROGRESS_MAX ? map[index] : 0) 4206 : - 4207 2 : tick_total = 0; - 4208 : - 4209 2 : tick_total += state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); - 4210 2 : tick_total += state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); - 4211 2 : tick_total += state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); - 4212 2 : tick_total += state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); - 4213 2 : tick_total += state->progress_tick_io[current] - ref(state->progress_tick_io, oldest); - 4214 2 : if (!tick_total) - 4215 2 : return; - 4216 : - 4217 2 : pad = 4; - 4218 14 : for (i = state->disklist; i != 0; i = i->next) { - 4219 12 : struct snapraid_disk* disk = i->data; - 4220 12 : size_t len = strlen(disk->name); - 4221 12 : if (pad < len) - 4222 2 : pad = len; - 4223 : } - 4224 9 : for (l = 0; l < state->level; ++l) { - 4225 7 : size_t len = strlen(lev_config_name(l)); - 4226 7 : if (pad < len) - 4227 3 : pad = len; - 4228 : } - 4229 : - 4230 : /* extra space */ - 4231 2 : pad += 1; - 4232 : - 4233 2 : if (pad + 30 < GRAPH_COLUMN) - 4234 2 : bar = GRAPH_COLUMN - pad; - 4235 : else - 4236 0 : bar = 30; - 4237 : - 4238 2 : if (io) { - 4239 1 : const char* legend = "cached blocks (instant, more is better)"; - 4240 : - 4241 : /* refresh the cached blocks info */ - 4242 1 : io_refresh(io); - 4243 : - 4244 1 : printf("\n"); - 4245 : - 4246 7 : for (i = state->disklist; i != 0; i = i->next) { - 4247 6 : struct snapraid_disk* disk = i->data; - 4248 6 : v = disk->cached; - 4249 6 : printr(disk->name, pad); - 4250 6 : printf("%4" PRIu64 " | ", v); - 4251 6 : printc('o', v * bar / io->io_max); - 4252 6 : printf("\n"); - 4253 : } + 4207 1 : static void state_progress_graph(struct snapraid_state* state, struct snapraid_io* io, unsigned current, unsigned oldest) + 4208 : { + 4209 : uint64_t v; + 4210 : uint64_t tick_total; + 4211 : unsigned bar; + 4212 : tommy_node* i; + 4213 : unsigned l; + 4214 : size_t pad; + 4215 : + 4216 1 : tick_total = 0; + 4217 : + 4218 1 : tick_total += state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); + 4219 1 : tick_total += state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); + 4220 1 : tick_total += state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); + 4221 1 : tick_total += state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); + 4222 1 : tick_total += state->progress_tick_io[current] - ref(state->progress_tick_io, oldest); + 4223 1 : if (!tick_total) + 4224 1 : return; + 4225 : + 4226 1 : pad = 4; + 4227 7 : for (i = state->disklist; i != 0; i = i->next) { + 4228 6 : struct snapraid_disk* disk = i->data; + 4229 6 : size_t len = strlen(disk->name); + 4230 6 : if (pad < len) + 4231 1 : pad = len; + 4232 : } + 4233 7 : for (l = 0; l < state->level; ++l) { + 4234 6 : size_t len = strlen(lev_config_name(l)); + 4235 6 : if (pad < len) + 4236 2 : pad = len; + 4237 : } + 4238 : + 4239 : /* extra space */ + 4240 1 : pad += 1; + 4241 : + 4242 1 : if (pad + 30 < GRAPH_COLUMN) + 4243 1 : bar = GRAPH_COLUMN - pad; + 4244 : else + 4245 0 : bar = 30; + 4246 : + 4247 1 : if (io) { + 4248 0 : const char* legend = "cached blocks (instant, more is better)"; + 4249 : + 4250 : /* refresh the cached blocks info */ + 4251 0 : io_refresh(io); + 4252 : + 4253 0 : printf("\n"); 4254 : - 4255 2 : for (l = 0; l < state->level; ++l) { - 4256 1 : v = state->parity[l].cached; - 4257 1 : printr(lev_config_name(l), pad); - 4258 1 : printf("%4" PRIu64 " | ", v); - 4259 1 : printc('o', v * bar / io->io_max); - 4260 1 : printf("\n"); - 4261 : } - 4262 : - 4263 1 : printc(' ', pad); - 4264 1 : printf(" |_"); - 4265 1 : printc('_', bar); - 4266 1 : printf("\n"); - 4267 : - 4268 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); - 4269 1 : printf("%s", legend); - 4270 1 : printf("\n"); - 4271 : } - 4272 : - 4273 2 : printf("\n"); - 4274 : - 4275 14 : for (i = state->disklist; i != 0; i = i->next) { - 4276 12 : struct snapraid_disk* disk = i->data; - 4277 12 : v = disk->progress_tick[current] - ref(disk->progress_tick, oldest); - 4278 12 : printr(disk->name, pad); - 4279 12 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4280 12 : printc('*', v * bar / tick_total); - 4281 12 : printf("\n"); - 4282 : } + 4255 0 : for (i = state->disklist; i != 0; i = i->next) { + 4256 0 : struct snapraid_disk* disk = i->data; + 4257 0 : v = disk->cached; + 4258 0 : printr(disk->name, pad); + 4259 0 : printf("%4" PRIu64 " | ", v); + 4260 0 : printc('o', v * bar / io->io_max); + 4261 0 : printf("\n"); + 4262 : } + 4263 : + 4264 0 : for (l = 0; l < state->level; ++l) { + 4265 0 : v = state->parity[l].cached; + 4266 0 : printr(lev_config_name(l), pad); + 4267 0 : printf("%4" PRIu64 " | ", v); + 4268 0 : printc('o', v * bar / io->io_max); + 4269 0 : printf("\n"); + 4270 : } + 4271 : + 4272 0 : printc(' ', pad); + 4273 0 : printf(" |_"); + 4274 0 : printc('_', bar); + 4275 0 : printf("\n"); + 4276 : + 4277 0 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); + 4278 0 : printf("%s", legend); + 4279 0 : printf("\n"); + 4280 : } + 4281 : + 4282 1 : printf("\n"); 4283 : - 4284 9 : for (l = 0; l < state->level; ++l) { - 4285 7 : v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest); - 4286 7 : printr(lev_config_name(l), pad); - 4287 7 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4288 7 : printc('*', v * bar / tick_total); - 4289 7 : printf("\n"); - 4290 : } - 4291 : - 4292 2 : v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); - 4293 2 : printr("raid", pad); - 4294 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4295 2 : printc('*', v * bar / tick_total); - 4296 2 : printf("\n"); - 4297 : - 4298 2 : v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); - 4299 2 : printr("hash", pad); - 4300 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4301 2 : printc('*', v * bar / tick_total); - 4302 2 : printf("\n"); - 4303 : - 4304 2 : v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); - 4305 2 : printr("sched", pad); - 4306 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4307 2 : printc('*', v * bar / tick_total); - 4308 2 : printf("\n"); - 4309 : - 4310 2 : v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); - 4311 2 : printr("misc", pad); - 4312 2 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); - 4313 2 : printc('*', v * bar / tick_total); - 4314 2 : printf("\n"); - 4315 : - 4316 2 : printc(' ', pad); - 4317 2 : printf(" |_"); - 4318 2 : printc('_', bar); - 4319 2 : printf("\n"); - 4320 : - 4321 2 : if (oldest == PROGRESS_MAX) { - 4322 1 : const char* legend = "wait time (total, less is better)"; - 4323 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); - 4324 1 : printf("%s", legend); - 4325 1 : printf("\n"); - 4326 : } else { - 4327 1 : const char* legend_d = "wait time (last %d secs, less is better)"; - 4328 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend_d) / 2); - 4329 1 : printf(legend_d, PROGRESS_MAX); - 4330 1 : printf("\n"); - 4331 : } - 4332 : - 4333 2 : printf("\n"); - 4334 : } - 4335 : - 4336 1073436 : int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) - 4337 : { - 4338 : time_t now; - 4339 : int pred; - 4340 : - 4341 1073436 : now = time(0); - 4342 : - 4343 : /* previous position */ - 4344 1073436 : pred = state->progress_ptr + PROGRESS_MAX - 1; - 4345 1073436 : if (pred >= PROGRESS_MAX) - 4346 1073237 : pred -= PROGRESS_MAX; - 4347 : - 4348 : /* if the previous measure is different */ - 4349 1073436 : if (state->progress_tick == 0 - 4350 1073237 : || state->progress_time[pred] != now - 4351 : ) { - 4352 : time_t elapsed; - 4353 436 : unsigned out_perc = 0; - 4354 436 : unsigned out_speed = 0; - 4355 436 : unsigned out_cpu = 0; - 4356 436 : unsigned out_eta = 0; - 4357 436 : int out_computed = 0; - 4358 : - 4359 : /* store the new measure */ - 4360 436 : state->progress_time[state->progress_ptr] = now; - 4361 436 : state->progress_pos[state->progress_ptr] = countpos; - 4362 436 : state->progress_size[state->progress_ptr] = countsize; - 4363 436 : state_progress_latest(state); - 4364 : - 4365 436 : elapsed = now - state->progress_whole_start - state->progress_wasted; - 4366 : - 4367 : /* completion percentage */ - 4368 436 : if (countmax) - 4369 436 : out_perc = countpos * 100 / countmax; - 4370 : - 4371 : /* if we have at least 5 measures */ - 4372 436 : if (state->progress_tick >= 5 - 4373 : /* or if we are running in test mode, with at least one measure */ - 4374 397 : || (state->opt.force_progress && state->progress_tick >= 1) - 4375 : ) { - 4376 : int oldest; - 4377 : int past; - 4378 : time_t delta_time; - 4379 : block_off_t delta_pos; - 4380 : data_off_t delta_size; - 4381 : uint64_t tick_cpu; - 4382 : uint64_t tick_total; - 4383 : uint64_t delta_tick_cpu; - 4384 : uint64_t delta_tick_total; - 4385 : uint64_t oldest_tick_cpu; - 4386 : uint64_t oldest_tick_total; - 4387 : - 4388 : /* number of past measures */ - 4389 237 : past = state->progress_tick; - 4390 : - 4391 : /* drop the oldest ones, to promptly */ - 4392 : /* skip the startup phase */ - 4393 237 : past -= past / 5; - 4394 : - 4395 : /* check how much we can go in the past */ - 4396 237 : if (past >= PROGRESS_MAX - 1) { - 4397 : /* the vector is filled, so we are already in position */ - 4398 : /* to get the possible oldest one */ - 4399 0 : oldest = state->progress_ptr + 1; - 4400 : } else { - 4401 : /* go backward the number of positions selected */ - 4402 237 : oldest = state->progress_ptr + PROGRESS_MAX - past; - 4403 : } - 4404 237 : if (oldest >= PROGRESS_MAX) - 4405 237 : oldest -= PROGRESS_MAX; - 4406 : - 4407 474 : tick_cpu = state->progress_tick_misc[state->progress_ptr] - 4408 237 : + state->progress_tick_sched[state->progress_ptr] - 4409 237 : + state->progress_tick_raid[state->progress_ptr] - 4410 237 : + state->progress_tick_hash[state->progress_ptr]; - 4411 237 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr]; - 4412 : - 4413 474 : oldest_tick_cpu = state->progress_tick_misc[oldest] - 4414 237 : + state->progress_tick_sched[oldest] - 4415 237 : + state->progress_tick_raid[oldest] - 4416 237 : + state->progress_tick_hash[oldest]; - 4417 237 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest]; - 4418 : - 4419 237 : delta_time = now - state->progress_time[oldest]; - 4420 237 : delta_pos = countpos - state->progress_pos[oldest]; - 4421 237 : delta_size = countsize - state->progress_size[oldest]; - 4422 237 : delta_tick_cpu = tick_cpu - oldest_tick_cpu; - 4423 237 : delta_tick_total = tick_total - oldest_tick_total; - 4424 : - 4425 : /* estimate the speed in MB/s */ - 4426 237 : if (delta_time != 0) - 4427 237 : out_speed = (unsigned)(delta_size / MEGA / delta_time); - 4428 : - 4429 : /* estimate the cpu usage percentage */ - 4430 237 : if (delta_tick_total != 0) - 4431 95 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total); - 4432 : - 4433 : /* estimate the remaining time in minutes */ - 4434 237 : if (delta_pos != 0) - 4435 237 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos); - 4436 : - 4437 237 : if (state->opt.force_stats) { - 4438 1 : os_clear(); - 4439 1 : state_progress_graph(state, io, state->progress_ptr, oldest); - 4440 : } + 4284 7 : for (i = state->disklist; i != 0; i = i->next) { + 4285 6 : struct snapraid_disk* disk = i->data; + 4286 6 : v = disk->progress_tick[current] - ref(disk->progress_tick, oldest); + 4287 6 : printr(disk->name, pad); + 4288 6 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4289 6 : printc('*', v * bar / tick_total); + 4290 6 : printf("\n"); + 4291 : } + 4292 : + 4293 7 : for (l = 0; l < state->level; ++l) { + 4294 6 : v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest); + 4295 6 : printr(lev_config_name(l), pad); + 4296 6 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4297 6 : printc('*', v * bar / tick_total); + 4298 6 : printf("\n"); + 4299 : } + 4300 : + 4301 1 : v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); + 4302 1 : printr("raid", pad); + 4303 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4304 1 : printc('*', v * bar / tick_total); + 4305 1 : printf("\n"); + 4306 : + 4307 1 : v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); + 4308 1 : printr("hash", pad); + 4309 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4310 1 : printc('*', v * bar / tick_total); + 4311 1 : printf("\n"); + 4312 : + 4313 1 : v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); + 4314 1 : printr("sched", pad); + 4315 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4316 1 : printc('*', v * bar / tick_total); + 4317 1 : printf("\n"); + 4318 : + 4319 1 : v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); + 4320 1 : printr("misc", pad); + 4321 1 : printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + 4322 1 : printc('*', v * bar / tick_total); + 4323 1 : printf("\n"); + 4324 : + 4325 1 : printc(' ', pad); + 4326 1 : printf(" |_"); + 4327 1 : printc('_', bar); + 4328 1 : printf("\n"); + 4329 : + 4330 1 : if (oldest == PROGRESS_MAX) { + 4331 1 : const char* legend = "wait time (total, less is better)"; + 4332 1 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); + 4333 1 : printf("%s", legend); + 4334 1 : printf("\n"); + 4335 : } else { + 4336 0 : const char* legend_d = "wait time (last %d secs, less is better)"; + 4337 0 : printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend_d) / 2); + 4338 0 : printf(legend_d, PROGRESS_MAX); + 4339 0 : printf("\n"); + 4340 : } + 4341 : + 4342 1 : printf("\n"); + 4343 : } + 4344 : + 4345 1073492 : int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) + 4346 : { + 4347 : time_t now; + 4348 : int pred; + 4349 : + 4350 1073492 : now = time(0); + 4351 : + 4352 : /* previous position */ + 4353 1073492 : pred = state->progress_ptr + PROGRESS_MAX - 1; + 4354 1073492 : if (pred >= PROGRESS_MAX) + 4355 1073293 : pred -= PROGRESS_MAX; + 4356 : + 4357 : /* if the previous measure is different */ + 4358 1073492 : if (state->progress_tick == 0 + 4359 1073293 : || state->progress_time[pred] != now + 4360 : ) { + 4361 : time_t elapsed; + 4362 382 : unsigned out_perc = 0; + 4363 382 : unsigned out_speed = 0; + 4364 382 : unsigned out_cpu = 0; + 4365 382 : unsigned out_eta = 0; + 4366 382 : int out_computed = 0; + 4367 : + 4368 : /* store the new measure */ + 4369 382 : state->progress_time[state->progress_ptr] = now; + 4370 382 : state->progress_pos[state->progress_ptr] = countpos; + 4371 382 : state->progress_size[state->progress_ptr] = countsize; + 4372 382 : state_progress_latest(state); + 4373 : + 4374 382 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 4375 : + 4376 : /* completion percentage */ + 4377 382 : if (countmax) + 4378 382 : out_perc = countpos * 100 / countmax; + 4379 : + 4380 : /* if we have at least 5 measures */ + 4381 382 : if (state->progress_tick >= 5 + 4382 : /* or if we are running in test mode, with at least one measure */ + 4383 365 : || (state->opt.force_progress && state->progress_tick >= 1) + 4384 : ) { + 4385 : int oldest; + 4386 : int past; + 4387 : time_t delta_time; + 4388 : block_off_t delta_pos; + 4389 : data_off_t delta_size; + 4390 : uint64_t tick_cpu; + 4391 : uint64_t tick_total; + 4392 : uint64_t delta_tick_cpu; + 4393 : uint64_t delta_tick_total; + 4394 : uint64_t oldest_tick_cpu; + 4395 : uint64_t oldest_tick_total; + 4396 : + 4397 : /* number of past measures */ + 4398 183 : past = state->progress_tick; + 4399 : + 4400 : /* drop the oldest ones, to promptly */ + 4401 : /* skip the startup phase */ + 4402 183 : past -= past / 5; + 4403 : + 4404 : /* check how much we can go in the past */ + 4405 183 : if (past >= PROGRESS_MAX - 1) { + 4406 : /* the vector is filled, so we are already in position */ + 4407 : /* to get the possible oldest one */ + 4408 0 : oldest = state->progress_ptr + 1; + 4409 : } else { + 4410 : /* go backward the number of positions selected */ + 4411 183 : oldest = state->progress_ptr + PROGRESS_MAX - past; + 4412 : } + 4413 183 : if (oldest >= PROGRESS_MAX) + 4414 183 : oldest -= PROGRESS_MAX; + 4415 : + 4416 366 : tick_cpu = state->progress_tick_misc[state->progress_ptr] + 4417 183 : + state->progress_tick_sched[state->progress_ptr] + 4418 183 : + state->progress_tick_raid[state->progress_ptr] + 4419 183 : + state->progress_tick_hash[state->progress_ptr]; + 4420 183 : tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr]; + 4421 : + 4422 366 : oldest_tick_cpu = state->progress_tick_misc[oldest] + 4423 183 : + state->progress_tick_sched[oldest] + 4424 183 : + state->progress_tick_raid[oldest] + 4425 183 : + state->progress_tick_hash[oldest]; + 4426 183 : oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest]; + 4427 : + 4428 183 : delta_time = now - state->progress_time[oldest]; + 4429 183 : delta_pos = countpos - state->progress_pos[oldest]; + 4430 183 : delta_size = countsize - state->progress_size[oldest]; + 4431 183 : delta_tick_cpu = tick_cpu - oldest_tick_cpu; + 4432 183 : delta_tick_total = tick_total - oldest_tick_total; + 4433 : + 4434 : /* estimate the speed in MB/s */ + 4435 183 : if (delta_time != 0) + 4436 183 : out_speed = (unsigned)(delta_size / MEGA / delta_time); + 4437 : + 4438 : /* estimate the cpu usage percentage */ + 4439 183 : if (delta_tick_total != 0) + 4440 77 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total); 4441 : - 4442 : /* we have the output value */ - 4443 237 : out_computed = 1; - 4444 : } + 4442 : /* estimate the remaining time in minutes */ + 4443 183 : if (delta_pos != 0) + 4444 183 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos); 4445 : - 4446 436 : if (state->opt.gui) { - 4447 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed); - 4448 7 : log_flush(); - 4449 : } else { - 4450 429 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA)); - 4451 429 : if (out_computed) { - 4452 235 : msg_bar(", %u MB/s", out_speed); - 4453 235 : msg_bar(", CPU %u%%", out_cpu); - 4454 235 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60); - 4455 : } - 4456 429 : msg_bar("%s\r", PROGRESS_CLEAR); - 4457 429 : msg_flush(); - 4458 : } - 4459 : - 4460 : /* next position to fill */ - 4461 436 : ++state->progress_ptr; - 4462 436 : if (state->progress_ptr >= PROGRESS_MAX) - 4463 0 : state->progress_ptr -= PROGRESS_MAX; - 4464 : - 4465 : /* one more measure */ - 4466 436 : ++state->progress_tick; - 4467 : } + 4446 183 : if (state->opt.force_stats) { + 4447 0 : os_clear(); + 4448 0 : state_progress_graph(state, io, state->progress_ptr, oldest); + 4449 : } + 4450 : + 4451 : /* we have the output value */ + 4452 183 : out_computed = 1; + 4453 : } + 4454 : + 4455 382 : if (state->opt.gui) { + 4456 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed); + 4457 7 : log_flush(); + 4458 : } else { + 4459 375 : msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA)); + 4460 375 : if (out_computed) { + 4461 181 : msg_bar(", %u MB/s", out_speed); + 4462 181 : msg_bar(", CPU %u%%", out_cpu); + 4463 181 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60); + 4464 : } + 4465 375 : msg_bar("%s\r", PROGRESS_CLEAR); + 4466 375 : msg_flush(); + 4467 : } 4468 : - 4469 : /* stop if requested */ - 4470 1073436 : if (global_interrupt) { - 4471 : /* LCOV_EXCL_START */ - 4472 : if (!state->opt.gui) { - 4473 : log_fatal("\n"); - 4474 : log_fatal("Stopping for interruption at block %u\n", blockpos); - 4475 : } - 4476 : log_tag("sigint:%u: SIGINT received\n", blockpos); - 4477 : log_flush(); - 4478 : return 1; - 4479 : /* LCOV_EXCL_STOP */ - 4480 : } - 4481 : - 4482 1073436 : return 0; - 4483 : } - 4484 : - 4485 104 : void state_usage_waste(struct snapraid_state* state) - 4486 : { - 4487 104 : uint64_t now = tick(); - 4488 : - 4489 104 : state->tick_last = now; - 4490 104 : } - 4491 : - 4492 1063244 : void state_usage_misc(struct snapraid_state* state) - 4493 : { - 4494 1063244 : uint64_t now = tick(); - 4495 1063244 : uint64_t delta = now - state->tick_last; - 4496 : - 4497 : /* increment the time spent in computations */ - 4498 1063244 : state->tick_misc += delta; - 4499 : - 4500 1063244 : state->tick_last = now; - 4501 1063244 : } - 4502 : - 4503 149863 : void state_usage_sched(struct snapraid_state* state) - 4504 : { - 4505 149863 : uint64_t now = tick(); - 4506 149863 : uint64_t delta = now - state->tick_last; - 4507 : - 4508 : /* increment the time spent in computations */ - 4509 149863 : state->tick_sched += delta; - 4510 : - 4511 149863 : state->tick_last = now; - 4512 149863 : } - 4513 : - 4514 140402 : void state_usage_raid(struct snapraid_state* state) - 4515 : { - 4516 140402 : uint64_t now = tick(); - 4517 140402 : uint64_t delta = now - state->tick_last; - 4518 : - 4519 : /* increment the time spent in computations */ - 4520 140402 : state->tick_raid += delta; - 4521 : - 4522 140402 : state->tick_last = now; - 4523 140402 : } - 4524 : - 4525 776953 : void state_usage_hash(struct snapraid_state* state) - 4526 : { - 4527 776953 : uint64_t now = tick(); - 4528 776953 : uint64_t delta = now - state->tick_last; - 4529 : - 4530 : /* increment the time spent in computations */ - 4531 776953 : state->tick_hash += delta; - 4532 : - 4533 776953 : state->tick_last = now; - 4534 776953 : } - 4535 : - 4536 912519 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac) - 4537 : { - 4538 912519 : uint64_t now = tick(); - 4539 912519 : uint64_t delta = now - state->tick_last; - 4540 : unsigned i; + 4469 : /* next position to fill */ + 4470 382 : ++state->progress_ptr; + 4471 382 : if (state->progress_ptr >= PROGRESS_MAX) + 4472 0 : state->progress_ptr -= PROGRESS_MAX; + 4473 : + 4474 : /* one more measure */ + 4475 382 : ++state->progress_tick; + 4476 : } + 4477 : + 4478 : /* stop if requested */ + 4479 1073492 : if (global_interrupt) { + 4480 : /* LCOV_EXCL_START */ + 4481 : if (!state->opt.gui) { + 4482 : log_fatal("\n"); + 4483 : log_fatal("Stopping for interruption at block %u\n", blockpos); + 4484 : } + 4485 : log_tag("sigint:%u: SIGINT received\n", blockpos); + 4486 : log_flush(); + 4487 : return 1; + 4488 : /* LCOV_EXCL_STOP */ + 4489 : } + 4490 : + 4491 1073492 : return 0; + 4492 : } + 4493 : + 4494 104 : void state_usage_waste(struct snapraid_state* state) + 4495 : { + 4496 104 : uint64_t now = tick(); + 4497 : + 4498 104 : state->tick_last = now; + 4499 104 : } + 4500 : + 4501 1063636 : void state_usage_misc(struct snapraid_state* state) + 4502 : { + 4503 1063636 : uint64_t now = tick(); + 4504 1063636 : uint64_t delta = now - state->tick_last; + 4505 : + 4506 : /* increment the time spent in computations */ + 4507 1063636 : state->tick_misc += delta; + 4508 : + 4509 1063636 : state->tick_last = now; + 4510 1063636 : } + 4511 : + 4512 149919 : void state_usage_sched(struct snapraid_state* state) + 4513 : { + 4514 149919 : uint64_t now = tick(); + 4515 149919 : uint64_t delta = now - state->tick_last; + 4516 : + 4517 : /* increment the time spent in computations */ + 4518 149919 : state->tick_sched += delta; + 4519 : + 4520 149919 : state->tick_last = now; + 4521 149919 : } + 4522 : + 4523 140474 : void state_usage_raid(struct snapraid_state* state) + 4524 : { + 4525 140474 : uint64_t now = tick(); + 4526 140474 : uint64_t delta = now - state->tick_last; + 4527 : + 4528 : /* increment the time spent in computations */ + 4529 140474 : state->tick_raid += delta; + 4530 : + 4531 140474 : state->tick_last = now; + 4532 140474 : } + 4533 : + 4534 777321 : void state_usage_hash(struct snapraid_state* state) + 4535 : { + 4536 777321 : uint64_t now = tick(); + 4537 777321 : uint64_t delta = now - state->tick_last; + 4538 : + 4539 : /* increment the time spent in computations */ + 4540 777321 : state->tick_hash += delta; 4541 : - 4542 : /* increment the time spent in the data disks */ - 4543 957179 : for (i = 0; i < waiting_mac; ++i) { - 4544 44660 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk; - 4545 : - 4546 44660 : if (!disk) - 4547 10 : continue; - 4548 : - 4549 44650 : disk->tick += delta; - 4550 : } - 4551 912519 : state->tick_io += delta; - 4552 : - 4553 912519 : state->tick_last = now; - 4554 912519 : } - 4555 : - 4556 774185 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac) - 4557 : { - 4558 774185 : uint64_t now = tick(); - 4559 774185 : uint64_t delta = now - state->tick_last; - 4560 : unsigned i; + 4542 777321 : state->tick_last = now; + 4543 777321 : } + 4544 : + 4545 912855 : void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac) + 4546 : { + 4547 912855 : uint64_t now = tick(); + 4548 912855 : uint64_t delta = now - state->tick_last; + 4549 : unsigned i; + 4550 : + 4551 : /* increment the time spent in the data disks */ + 4552 955269 : for (i = 0; i < waiting_mac; ++i) { + 4553 42414 : struct snapraid_disk* disk = handle_map[waiting_map[i]].disk; + 4554 : + 4555 42414 : if (!disk) + 4556 0 : continue; + 4557 : + 4558 42414 : disk->tick += delta; + 4559 : } + 4560 912855 : state->tick_io += delta; 4561 : - 4562 : /* increment the time spent in the parity disk */ - 4563 854258 : for (i = 0; i < waiting_mac; ++i) - 4564 80073 : state->parity[waiting_map[i]].tick += delta; - 4565 774185 : state->tick_io += delta; - 4566 : - 4567 774185 : state->tick_last = now; - 4568 774185 : } - 4569 : - 4570 96 : void state_usage_print(struct snapraid_state* state) - 4571 : { - 4572 : /* set the latest data */ - 4573 96 : state_progress_latest(state); - 4574 : - 4575 96 : if (msg_level < MSG_PROGRESS) - 4576 191 : return; - 4577 : - 4578 : /* print a graph for it */ - 4579 1 : state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX); - 4580 : } - 4581 : - 4582 499 : void state_fscheck(struct snapraid_state* state, const char* ope) - 4583 : { - 4584 : tommy_node* i; - 4585 : - 4586 : /* check the file-system on all disks */ - 4587 3487 : for (i = state->disklist; i != 0; i = i->next) { - 4588 2988 : struct snapraid_disk* disk = i->data; - 4589 : - 4590 2988 : if (fs_check(disk) != 0) { - 4591 : /* LCOV_EXCL_START */ - 4592 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope); - 4593 : os_abort(); - 4594 : /* LCOV_EXCL_STOP */ - 4595 : } - 4596 : } - 4597 499 : } + 4562 912855 : state->tick_last = now; + 4563 912855 : } + 4564 : + 4565 774521 : void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac) + 4566 : { + 4567 774521 : uint64_t now = tick(); + 4568 774521 : uint64_t delta = now - state->tick_last; + 4569 : unsigned i; + 4570 : + 4571 : /* increment the time spent in the parity disk */ + 4572 854191 : for (i = 0; i < waiting_mac; ++i) + 4573 79670 : state->parity[waiting_map[i]].tick += delta; + 4574 774521 : state->tick_io += delta; + 4575 : + 4576 774521 : state->tick_last = now; + 4577 774521 : } + 4578 : + 4579 96 : void state_usage_print(struct snapraid_state* state) + 4580 : { + 4581 : /* set the latest data */ + 4582 96 : state_progress_latest(state); + 4583 : + 4584 96 : if (msg_level < MSG_PROGRESS) + 4585 191 : return; + 4586 : + 4587 : /* print a graph for it */ + 4588 1 : state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX); + 4589 : } + 4590 : + 4591 499 : void state_fscheck(struct snapraid_state* state, const char* ope) + 4592 : { + 4593 : tommy_node* i; + 4594 : + 4595 : /* check the file-system on all disks */ + 4596 3487 : for (i = state->disklist; i != 0; i = i->next) { + 4597 2988 : struct snapraid_disk* disk = i->data; 4598 : - 4599 1 : void generate_configuration(const char* path) - 4600 : { - 4601 : struct snapraid_state state; - 4602 : struct snapraid_content* content; - 4603 : char esc_buffer[ESC_MAX]; - 4604 : unsigned l, s; - 4605 : tommy_node* j; - 4606 : - 4607 1 : state_init(&state); - 4608 : - 4609 : /* mark that we are without a configuration file */ - 4610 1 : state.no_conf = 1; - 4611 : - 4612 : /* create the dummy content entry */ - 4613 1 : content = content_alloc(path, -1); - 4614 : - 4615 : /* adds the content entry */ - 4616 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content); + 4599 2988 : if (fs_check(disk) != 0) { + 4600 : /* LCOV_EXCL_START */ + 4601 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope); + 4602 : os_abort(); + 4603 : /* LCOV_EXCL_STOP */ + 4604 : } + 4605 : } + 4606 499 : } + 4607 : + 4608 1 : void generate_configuration(const char* path) + 4609 : { + 4610 : struct snapraid_state state; + 4611 : struct snapraid_content* content; + 4612 : char esc_buffer[ESC_MAX]; + 4613 : unsigned l, s; + 4614 : tommy_node* j; + 4615 : + 4616 1 : state_init(&state); 4617 : - 4618 : /* read the content file */ - 4619 1 : state_read(&state); + 4618 : /* mark that we are without a configuration file */ + 4619 1 : state.no_conf = 1; 4620 : - 4621 : /* output a dummy configuration file */ - 4622 1 : printf("# Configuration file generated from %s\n", path); - 4623 1 : printf("\n"); - 4624 1 : printf("# Use this blocksize\n"); - 4625 1 : printf("blocksize %u\n", state.block_size / KIBI); - 4626 1 : printf("\n"); - 4627 1 : printf("# Use this hashsize\n"); - 4628 1 : printf("hashsize %u\n", BLOCK_HASH_SIZE); - 4629 1 : printf("\n"); - 4630 7 : for (l = 0; l < state.level; ++l) { - 4631 6 : printf("# Set the correct path for the %s files\n", lev_name(l)); - 4632 6 : printf("# You had %u of them:\n", state.parity[l].split_mac); - 4633 30 : for (s = 0; s < state.parity[l].split_mac; ++s) { - 4634 24 : printf("# %u:\n", s); - 4635 24 : printf("# PATH:"); - 4636 24 : if (state.parity[l].split_map[s].path[0]) - 4637 24 : printf("%s", state.parity[l].split_map[s].path); - 4638 : else - 4639 0 : printf("?"); - 4640 24 : printf("\n"); - 4641 24 : printf("# SIZE:"); - 4642 24 : if (state.parity[l].split_map[s].size != PARITY_SIZE_INVALID) - 4643 24 : printf("%" PRIu64, state.parity[l].split_map[s].size); - 4644 : else - 4645 0 : printf("?"); - 4646 24 : printf("\n"); - 4647 24 : printf("# UUID:"); - 4648 24 : if (state.parity[l].split_map[s].uuid[0]) - 4649 24 : printf("%s", state.parity[l].split_map[s].uuid); - 4650 : else - 4651 0 : printf("?"); - 4652 24 : printf("\n"); - 4653 24 : printf("#\n"); - 4654 : } - 4655 6 : printf("%s ENTER_HERE_THE_PARITY_FILES_COMMA_SEPARATED\n", lev_config_name(l)); - 4656 6 : printf("\n"); - 4657 : } - 4658 1 : printf("# Add any other content file\n"); - 4659 1 : printf("content %s\n", path); - 4660 1 : printf("\n"); - 4661 7 : for (j = state.maplist; j; j = j->next) { - 4662 6 : struct snapraid_map* map = j->data; - 4663 : struct snapraid_disk* disk; - 4664 6 : printf("# Set the correct dir for disk '%s'\n", map->name); - 4665 6 : if (map->uuid[0]) - 4666 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid); - 4667 6 : disk = find_disk_by_name(&state, map->name); - 4668 6 : if (disk && disk->filelist) { - 4669 6 : struct snapraid_file* file = disk->filelist->data; - 4670 6 : if (file) { - 4671 6 : printf("# and containing: %s\n", fmt_poll(disk, file->sub, esc_buffer)); - 4672 : } - 4673 : } - 4674 6 : printf("data %s ENTER_HERE_THE_DIR\n", map->name); - 4675 6 : printf("\n"); - 4676 : } - 4677 : - 4678 1 : state_done(&state); - 4679 1 : } - 4680 : + 4621 : /* create the dummy content entry */ + 4622 1 : content = content_alloc(path, -1); + 4623 : + 4624 : /* adds the content entry */ + 4625 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content); + 4626 : + 4627 : /* read the content file */ + 4628 1 : state_read(&state); + 4629 : + 4630 : /* output a dummy configuration file */ + 4631 1 : printf("# Configuration file generated from %s\n", path); + 4632 1 : printf("\n"); + 4633 1 : printf("# Use this blocksize\n"); + 4634 1 : printf("blocksize %u\n", state.block_size / KIBI); + 4635 1 : printf("\n"); + 4636 1 : printf("# Use this hashsize\n"); + 4637 1 : printf("hashsize %u\n", BLOCK_HASH_SIZE); + 4638 1 : printf("\n"); + 4639 7 : for (l = 0; l < state.level; ++l) { + 4640 6 : printf("# Set the correct path for the %s files\n", lev_name(l)); + 4641 6 : printf("# You had %u of them:\n", state.parity[l].split_mac); + 4642 30 : for (s = 0; s < state.parity[l].split_mac; ++s) { + 4643 24 : printf("# %u:\n", s); + 4644 24 : printf("# PATH:"); + 4645 24 : if (state.parity[l].split_map[s].path[0]) + 4646 24 : printf("%s", state.parity[l].split_map[s].path); + 4647 : else + 4648 0 : printf("?"); + 4649 24 : printf("\n"); + 4650 24 : printf("# SIZE:"); + 4651 24 : if (state.parity[l].split_map[s].size != PARITY_SIZE_INVALID) + 4652 24 : printf("%" PRIu64, state.parity[l].split_map[s].size); + 4653 : else + 4654 0 : printf("?"); + 4655 24 : printf("\n"); + 4656 24 : printf("# UUID:"); + 4657 24 : if (state.parity[l].split_map[s].uuid[0]) + 4658 24 : printf("%s", state.parity[l].split_map[s].uuid); + 4659 : else + 4660 0 : printf("?"); + 4661 24 : printf("\n"); + 4662 24 : printf("#\n"); + 4663 : } + 4664 6 : printf("%s ENTER_HERE_THE_PARITY_FILES_COMMA_SEPARATED\n", lev_config_name(l)); + 4665 6 : printf("\n"); + 4666 : } + 4667 1 : printf("# Add any other content file\n"); + 4668 1 : printf("content %s\n", path); + 4669 1 : printf("\n"); + 4670 7 : for (j = state.maplist; j; j = j->next) { + 4671 6 : struct snapraid_map* map = j->data; + 4672 : struct snapraid_disk* disk; + 4673 6 : printf("# Set the correct dir for disk '%s'\n", map->name); + 4674 6 : if (map->uuid[0]) + 4675 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid); + 4676 6 : disk = find_disk_by_name(&state, map->name); + 4677 6 : if (disk && disk->filelist) { + 4678 6 : struct snapraid_file* file = disk->filelist->data; + 4679 6 : if (file) { + 4680 6 : printf("# and containing: %s\n", fmt_poll(disk, file->sub, esc_buffer)); + 4681 : } + 4682 : } + 4683 6 : printf("data %s ENTER_HERE_THE_DIR\n", map->name); + 4684 6 : printf("\n"); + 4685 : } + 4686 : + 4687 1 : state_done(&state); + 4688 1 : } + 4689 : diff --git a/cov/cmdline/status.c.func-sort-c.html b/cov/cmdline/status.c.func-sort-c.html index e86aad6d..6f1e8aea 100644 --- a/cov/cmdline/status.c.func-sort-c.html +++ b/cov/cmdline/status.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 diff --git a/cov/cmdline/status.c.func.html b/cov/cmdline/status.c.func.html index 7976d962..4efc9d69 100644 --- a/cov/cmdline/status.c.func.html +++ b/cov/cmdline/status.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 diff --git a/cov/cmdline/status.c.gcov.html b/cov/cmdline/status.c.gcov.html index 689bae52..4da3101e 100644 --- a/cov/cmdline/status.c.gcov.html +++ b/cov/cmdline/status.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -395,10 +395,10 @@ 333 39808 : scrub_time = info_get_time(info); 334 : 335 39808 : if (info_get_justsynced(info)) { - 336 20516 : ++unscrubbed_blocks; + 336 20520 : ++unscrubbed_blocks; 337 : 338 : /* mark the time as not scrubbed */ - 339 20516 : scrub_time |= TIME_NEW; + 339 20520 : scrub_time |= TIME_NEW; 340 : } 341 : 342 39808 : timemap[count++] = scrub_time; @@ -430,16 +430,16 @@ 368 : /* output the info map */ 369 9 : i = 0; 370 9 : log_tag("info_count:%u\n", count); - 371 40 : while (i < count) { - 372 22 : unsigned j = i + 1; - 373 39830 : while (j < count && timemap[i] == timemap[j]) - 374 39786 : ++j; - 375 22 : if ((timemap[i] & TIME_NEW) == 0) { - 376 8 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i); + 371 39 : while (i < count) { + 372 21 : unsigned j = i + 1; + 373 39829 : while (j < count && timemap[i] == timemap[j]) + 374 39787 : ++j; + 375 21 : if ((timemap[i] & TIME_NEW) == 0) { + 376 7 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i); 377 : } else { 378 14 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i); 379 : } - 380 22 : i = j; + 380 21 : i = j; 381 : } 382 : 383 9 : oldest = timemap[0]; @@ -462,9 +462,9 @@ 400 630 : step_new = 0; 401 41068 : while (barpos < count && timemap[barpos] <= limit) { 402 39808 : if ((timemap[barpos] & TIME_NEW) != 0) - 403 20516 : ++step_new; + 403 20520 : ++step_new; 404 : else - 405 19292 : ++step_scrubbed; + 405 19288 : ++step_scrubbed; 406 39808 : ++barpos; 407 : } 408 : @@ -494,20 +494,20 @@ 432 9450 : unsigned scrubbed = bar_scrubbed[x]; 433 : 434 9450 : if (both > pivot_upper) { - 435 162 : if (scrubbed > pivot_lower) - 436 71 : printf("*"); + 435 159 : if (scrubbed > pivot_lower) + 436 63 : printf("*"); 437 : else - 438 91 : printf("o"); - 439 9288 : } else if (both > pivot_lower) { + 438 96 : printf("o"); + 439 9291 : } else if (both > pivot_lower) { 440 21 : if (scrubbed == both) 441 7 : printf("*"); 442 : else 443 14 : printf("o"); 444 : } else { - 445 9267 : if (y == GRAPH_ROW - 1) + 445 9270 : if (y == GRAPH_ROW - 1) 446 609 : printf("_"); 447 : else - 448 8658 : printf(" "); + 448 8661 : printf(" "); 449 : } 450 : } 451 135 : printf("\n"); diff --git a/cov/cmdline/stream.c.func-sort-c.html b/cov/cmdline/stream.c.func-sort-c.html index 1cce3c59..f28a34b9 100644 --- a/cov/cmdline/stream.c.func-sort-c.html +++ b/cov/cmdline/stream.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 27 @@ -61,23 +61,23 @@ swrite - 20725404 + 20725318 sgetb32 - 18667305 + 18667259 sread - 12810007 + 12810019 sgetb64 - 10849138 + 10849144 sputb32 - 9127777 + 9127691 sputb64 @@ -85,7 +85,7 @@ sgetbs - 3877064 + 3877077 sputbs diff --git a/cov/cmdline/stream.c.func.html b/cov/cmdline/stream.c.func.html index c096336a..595ba5db 100644 --- a/cov/cmdline/stream.c.func.html +++ b/cov/cmdline/stream.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 27 @@ -85,11 +85,11 @@ sgetb32 - 18667305 + 18667259 sgetb64 - 10849138 + 10849144 sgetble32 @@ -97,7 +97,7 @@ sgetbs - 3877064 + 3877077 sgetc_uncached @@ -141,7 +141,7 @@ sputb32 - 9127777 + 9127691 sputb64 @@ -157,7 +157,7 @@ sread - 12810007 + 12810019 ssync @@ -169,7 +169,7 @@ swrite - 20725404 + 20725318
diff --git a/cov/cmdline/stream.c.gcov.html b/cov/cmdline/stream.c.gcov.html index 8a1438fc..64e49810 100644 --- a/cov/cmdline/stream.c.gcov.html +++ b/cov/cmdline/stream.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 27 @@ -275,29 +275,29 @@ 213 : 214 606069 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE); 215 : - 216 606069 : if (ret < 0) { + 216 606067 : if (ret < 0) { 217 : /* LCOV_EXCL_START */ 218 : s->state = STREAM_STATE_ERROR; 219 : return EOF; 220 : /* LCOV_EXCL_STOP */ 221 : } - 222 606069 : if (ret == 0) { + 222 606067 : if (ret == 0) { 223 1659 : s->state = STREAM_STATE_EOF; 224 1659 : return EOF; 225 : } 226 : 227 : /* update the crc */ - 228 604410 : s->crc_uncached = s->crc; - 229 604410 : s->crc = crc32c(s->crc, s->buffer, ret); + 228 604408 : s->crc_uncached = s->crc; + 229 604408 : s->crc = crc32c(s->crc, s->buffer, ret); 230 : 231 : /* update the offset */ - 232 604409 : s->offset_uncached = s->offset; - 233 604409 : s->offset += ret; + 232 604410 : s->offset_uncached = s->offset; + 233 604410 : s->offset += ret; 234 : - 235 604409 : s->pos = s->buffer; - 236 604409 : s->end = s->buffer + ret; + 235 604410 : s->pos = s->buffer; + 236 604410 : s->end = s->buffer + ret; 237 : - 238 604409 : return 0; + 238 604410 : return 0; 239 : } 240 : 241 1142 : int sdeplete(STREAM* s, unsigned char* last) @@ -314,11 +314,11 @@ 252 148389 : s->pos = s->end - 4; 253 : 254 : /* insert the last 4 bytes */ - 255 1469855 : while (s->pos < s->end) { - 256 853323 : last[0] = last[1]; - 257 853323 : last[1] = last[2]; - 258 853323 : last[2] = last[3]; - 259 853323 : last[3] = *s->pos++; + 255 1469857 : while (s->pos < s->end) { + 256 853325 : last[0] = last[1]; + 257 853325 : last[1] = last[2]; + 258 853325 : last[2] = last[3]; + 259 853325 : last[3] = *s->pos++; 260 : } 261 : 262 : /* fill again the buffer until the end of the file */ @@ -445,35 +445,35 @@ 383 8196 : return i - str; 384 : } 385 : - 386 12810007 : int sread(STREAM* f, void* void_data, unsigned size) + 386 12810019 : int sread(STREAM* f, void* void_data, unsigned size) 387 : { - 388 12810007 : unsigned char* data = void_data; + 388 12810019 : unsigned char* data = void_data; 389 : 390 : /* if there is enough space in memory */ - 391 12810007 : if (sptrlookup(f, size)) { + 391 12810019 : if (sptrlookup(f, size)) { 392 : /* optimized version with all the data in memory */ - 393 12783678 : unsigned char* pos = sptrget(f); + 393 12783673 : unsigned char* pos = sptrget(f); 394 : 395 : /* copy it */ - 396 217717015 : while (size--) - 397 192149659 : *data++ = *pos++; + 396 217716910 : while (size--) + 397 192149564 : *data++ = *pos++; 398 : - 399 12783678 : sptrset(f, pos); + 399 12783673 : sptrset(f, pos); 400 : } else { 401 : /* standard version using sgetc() */ - 402 1378240 : while (size--) { - 403 1325582 : int c = sgetc(f); - 404 1325582 : if (c == EOF) { + 402 1378641 : while (size--) { + 403 1325949 : int c = sgetc(f); + 404 1325949 : if (c == EOF) { 405 : /* LCOV_EXCL_START */ 406 : return -1; 407 : /* LCOV_EXCL_STOP */ 408 : } 409 : - 410 1325582 : *data++ = c; + 410 1325949 : *data++ = c; 411 : } 412 : } 413 : - 414 12810007 : return 0; + 414 12810019 : return 0; 415 : } 416 : 417 5448 : int sgetline(STREAM* f, char* str, int size) @@ -586,76 +586,76 @@ 524 : } 525 : } 526 : - 527 18667305 : int sgetb32(STREAM* f, uint32_t* value) + 527 18667259 : int sgetb32(STREAM* f, uint32_t* value) 528 : { 529 : uint32_t v; 530 : unsigned char b; 531 : unsigned char s; 532 : int c; 533 : - 534 18667305 : v = 0; - 535 18667305 : s = 0; + 534 18667259 : v = 0; + 535 18667259 : s = 0; 536 : loop: - 537 36513909 : c = sgetc(f); - 538 36513909 : if (c == EOF) { + 537 35261143 : c = sgetc(f); + 538 35261143 : if (c == EOF) { 539 : /* LCOV_EXCL_START */ 540 : return -1; 541 : /* LCOV_EXCL_STOP */ 542 : } 543 : - 544 36513909 : b = (unsigned char)c; - 545 36513909 : if ((b & 0x80) == 0) { - 546 17846604 : v |= (uint32_t)b << s; - 547 17846604 : s += 7; - 548 17846604 : if (s >= 32) { + 544 35261143 : b = (unsigned char)c; + 545 35261143 : if ((b & 0x80) == 0) { + 546 16593884 : v |= (uint32_t)b << s; + 547 16593884 : s += 7; + 548 16593884 : if (s >= 32) { 549 : /* LCOV_EXCL_START */ 550 : return -1; 551 : /* LCOV_EXCL_STOP */ 552 : } - 553 17846604 : goto loop; + 553 16593884 : goto loop; 554 : } 555 : - 556 18667305 : v |= (uint32_t)(b & 0x7f) << s; + 556 18667259 : v |= (uint32_t)(b & 0x7f) << s; 557 : - 558 18667305 : *value = v; + 558 18667259 : *value = v; 559 : - 560 18667305 : return 0; + 560 18667259 : return 0; 561 : } 562 : - 563 10849138 : int sgetb64(STREAM* f, uint64_t* value) + 563 10849144 : int sgetb64(STREAM* f, uint64_t* value) 564 : { 565 : uint64_t v; 566 : unsigned char b; 567 : unsigned char s; 568 : int c; 569 : - 570 10849138 : v = 0; - 571 10849138 : s = 0; + 570 10849144 : v = 0; + 571 10849144 : s = 0; 572 : loop: - 573 39665269 : c = sgetc(f); - 574 39665269 : if (c == EOF) { + 573 39665284 : c = sgetc(f); + 574 39665284 : if (c == EOF) { 575 : /* LCOV_EXCL_START */ 576 : return -1; 577 : /* LCOV_EXCL_STOP */ 578 : } 579 : - 580 39665269 : b = (unsigned char)c; - 581 39665269 : if ((b & 0x80) == 0) { - 582 28816131 : v |= (uint64_t)b << s; - 583 28816131 : s += 7; - 584 28816131 : if (s >= 64) { + 580 39665284 : b = (unsigned char)c; + 581 39665284 : if ((b & 0x80) == 0) { + 582 28816140 : v |= (uint64_t)b << s; + 583 28816140 : s += 7; + 584 28816140 : if (s >= 64) { 585 : /* LCOV_EXCL_START */ 586 : return -1; 587 : /* LCOV_EXCL_STOP */ 588 : } - 589 28816131 : goto loop; + 589 28816140 : goto loop; 590 : } 591 : - 592 10849138 : v |= (uint64_t)(b & 0x7f) << s; + 592 10849144 : v |= (uint64_t)(b & 0x7f) << s; 593 : - 594 10849138 : *value = v; + 594 10849144 : *value = v; 595 : - 596 10849138 : return 0; + 596 10849144 : return 0; 597 : } 598 : 599 381 : int sgetble32(STREAM* f, uint32_t* value) @@ -673,35 +673,35 @@ 611 381 : return 0; 612 : } 613 : - 614 3877064 : int sgetbs(STREAM* f, char* str, int size) + 614 3877077 : int sgetbs(STREAM* f, char* str, int size) 615 : { 616 : uint32_t len; 617 : - 618 3877064 : if (sgetb32(f, &len) < 0) { + 618 3877077 : if (sgetb32(f, &len) < 0) { 619 : /* LCOV_EXCL_START */ 620 : return -1; 621 : /* LCOV_EXCL_STOP */ 622 : } 623 : - 624 3877064 : if (len + 1 > (uint32_t)size) { + 624 3877077 : if (len + 1 > (uint32_t)size) { 625 : /* LCOV_EXCL_START */ 626 : return -1; 627 : /* LCOV_EXCL_STOP */ 628 : } 629 : - 630 3877064 : str[len] = 0; + 630 3877076 : str[len] = 0; 631 : - 632 3877064 : return sread(f, str, (int)len); + 632 3877076 : return sread(f, str, (int)len); 633 : } 634 : - 635 20725404 : int swrite(const void* void_data, unsigned size, STREAM* f) + 635 20725318 : int swrite(const void* void_data, unsigned size, STREAM* f) 636 : { - 637 20725404 : const unsigned char* data = void_data; + 637 20725318 : const unsigned char* data = void_data; 638 : 639 : /* if there is enough space in memory */ - 640 20725404 : if (sptrlookup(f, size)) { + 640 20725318 : if (sptrlookup(f, size)) { 641 : /* optimized version with all the data in memory */ - 642 20719227 : unsigned char* pos = sptrget(f); + 642 20719138 : unsigned char* pos = sptrget(f); 643 : 644 : /** 645 : * Update the crc *before* writing the data in the buffer @@ -710,17 +710,17 @@ 648 : * to be able to detect memory errors on the buffer, 649 : * happening before we write it on the file. 650 : */ - 651 20719227 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); + 651 20719138 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); 652 : 653 : /* copy it */ - 654 173052917 : while (size--) - 655 131614463 : *pos++ = *data++; + 654 172416299 : while (size--) + 655 130978023 : *pos++ = *data++; 656 : - 657 20719227 : sptrset(f, pos); + 657 20719138 : sptrset(f, pos); 658 : } else { 659 : /* standard version using sputc() */ - 660 201663 : while (size--) { - 661 189309 : if (sputc(*data++, f) != 0) { + 660 201861 : while (size--) { + 661 189501 : if (sputc(*data++, f) != 0) { 662 : /* LCOV_EXCL_START */ 663 : return -1; 664 : /* LCOV_EXCL_STOP */ @@ -728,28 +728,28 @@ 666 : } 667 : } 668 : - 669 20725404 : return 0; + 669 20725318 : return 0; 670 : } 671 : - 672 9127777 : int sputb32(uint32_t value, STREAM* s) + 672 9127691 : int sputb32(uint32_t value, STREAM* s) 673 : { 674 : unsigned char b; 675 : unsigned char buf[16]; 676 : unsigned i; 677 : - 678 9127777 : i = 0; + 678 9127691 : i = 0; 679 : loop: - 680 17895036 : b = value & 0x7f; - 681 17895036 : value >>= 7; + 680 17258788 : b = value & 0x7f; + 681 17258788 : value >>= 7; 682 : - 683 17895036 : if (value) { - 684 8767259 : buf[i++] = b; - 685 8767259 : goto loop; + 683 17258788 : if (value) { + 684 8131097 : buf[i++] = b; + 685 8131097 : goto loop; 686 : } 687 : - 688 9127777 : buf[i++] = b | 0x80; + 688 9127691 : buf[i++] = b | 0x80; 689 : - 690 9127777 : return swrite(buf, i, s); + 690 9127691 : return swrite(buf, i, s); 691 : } 692 : 693 5317120 : int sputb64(uint64_t value, STREAM* s) diff --git a/cov/cmdline/stream.h.func-sort-c.html b/cov/cmdline/stream.h.func-sort-c.html index 5cdb940a..175f0770 100644 --- a/cov/cmdline/stream.h.func-sort-c.html +++ b/cov/cmdline/stream.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 10 @@ -61,27 +61,27 @@ sgetc - 85137242 + 83884881 sptrlookup - 33540859 + 33540785 sptrset - 33502905 + 33502811 sptrget - 33502905 + 33502811 sputc - 3808426 + 3808662 serror - 3635550 + 3635536 sungetc diff --git a/cov/cmdline/stream.h.func.html b/cov/cmdline/stream.h.func.html index 73c97b0d..93a566f5 100644 --- a/cov/cmdline/stream.h.func.html +++ b/cov/cmdline/stream.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 10 @@ -65,7 +65,7 @@ serror - 3635550 + 3635536 serrorfile @@ -73,7 +73,7 @@ sgetc - 85137242 + 83884881 sgeteol @@ -85,19 +85,19 @@ sptrget - 33502905 + 33502811 sptrlookup - 33540859 + 33540785 sptrset - 33502905 + 33502811 sputc - 3808426 + 3808662 sungetc diff --git a/cov/cmdline/stream.h.gcov.html b/cov/cmdline/stream.h.gcov.html index 0d7947f7..9d4d3fb2 100644 --- a/cov/cmdline/stream.h.gcov.html +++ b/cov/cmdline/stream.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 10 @@ -221,33 +221,33 @@ 159 : /** 160 : * Check if the buffer has enough data loaded. 161 : */ - 162 33540859 : static inline int sptrlookup(STREAM* s, int size) + 162 33540785 : static inline int sptrlookup(STREAM* s, int size) 163 : { - 164 33540859 : return s->pos + size <= s->end; + 164 33540785 : return s->pos + size <= s->end; 165 : } 166 : 167 : /** 168 : * Get the current stream ptr. 169 : */ - 170 33502905 : static inline unsigned char* sptrget(STREAM* s) + 170 33502811 : static inline unsigned char* sptrget(STREAM* s) 171 : { - 172 33502905 : return s->pos; + 172 33502811 : return s->pos; 173 : } 174 : 175 : /** 176 : * Set the current stream ptr. 177 : */ - 178 33502905 : static inline void sptrset(STREAM* s, unsigned char* ptr) + 178 33502811 : static inline void sptrset(STREAM* s, unsigned char* ptr) 179 : { - 180 33502905 : s->pos = ptr; - 181 33502905 : } + 180 33502811 : s->pos = ptr; + 181 33502811 : } 182 : 183 : /** 184 : * Check the error status. Like ferror(). 185 : */ - 186 3635550 : static inline int serror(STREAM* s) + 186 3635536 : static inline int serror(STREAM* s) 187 : { - 188 3635550 : return s->state == STREAM_STATE_ERROR; + 188 3635536 : return s->state == STREAM_STATE_ERROR; 189 : } 190 : 191 : /** @@ -291,11 +291,11 @@ 229 : /** 230 : * Read a char. Like fgetc(). 231 : */ - 232 85137242 : static inline int sgetc(STREAM* s) + 232 83884881 : static inline int sgetc(STREAM* s) 233 : { - 234 85137242 : if (tommy_unlikely(s->pos == s->end)) + 234 83884881 : if (tommy_unlikely(s->pos == s->end)) 235 298863 : return sgetc_uncached(s); - 236 84838379 : return *s->pos++; + 236 83586018 : return *s->pos++; 237 : } 238 : 239 : /** @@ -407,9 +407,9 @@ 345 : * Write a char. Like fputc(). 346 : * Return 0 on success or -1 on error. 347 : */ - 348 3808426 : static inline int sputc(int c, STREAM* s) + 348 3808662 : static inline int sputc(int c, STREAM* s) 349 : { - 350 3808426 : if (s->pos == s->end) { + 350 3808662 : if (s->pos == s->end) { 351 38580 : if (sflush(s) != 0) 352 0 : return -1; 353 : } @@ -421,11 +421,11 @@ 359 : * to be able to detect memory errors on the buffer, 360 : * happening before we write it on the file. 361 : */ - 362 3808426 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); + 362 3808662 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); 363 : - 364 3808426 : *s->pos++ = c; + 364 3808662 : *s->pos++ = c; 365 : - 366 3808426 : return 0; + 366 3808662 : return 0; 367 : } 368 : 369 : /** diff --git a/cov/cmdline/support.c.func-sort-c.html b/cov/cmdline/support.c.func-sort-c.html index cf4f03cd..566856c4 100644 --- a/cov/cmdline/support.c.func-sort-c.html +++ b/cov/cmdline/support.c.func-sort-c.html @@ -31,17 +31,17 @@ lcov.info Lines: - 441 - 550 - 80.2 % + 449 + 559 + 80.3 % Date: - 2016-11-21 + 2017-05-13 Functions: - 60 - 62 + 61 + 63 96.8 % @@ -60,131 +60,135 @@ Hit count Sort by hit count - thread_mutex_unlock - 80858701 + thread_mutex_unlock + 80868352 - thread_mutex_lock - 80857668 + thread_mutex_lock + 80853862 - pathcmp - 51890261 + pathcmp + 51889301 - pathprint - 51564160 + pathprint + 51562646 unlock_memory - 20173887 + 20173439 lock_memory - 20173887 + 20173439 - malloc_counter_inc - 20173411 + malloc_counter_inc + 20172963 - malloc_nofail - 14363921 + malloc_nofail + 14363716 - advise_read - 8903631 + advise_read + 8897480 - pathcpy - 7892123 + pathcpy + 7884434 - strdup_nofail - 5799401 - - - lock_msg - 3887334 + strdup_nofail + 5799158 unlock_msg - 3887334 + 3895151 + + + lock_msg + 3895147 log_tag - 2907727 + 2915010 - advise_flags - 2494965 + advise_flags + 2494636 - advise_init - 2494910 + advise_init + 2494292 esc_tag - 2428312 + 2435456 - advise_open - 2416366 + advise_open + 2412565 - thread_cond_wait - 1037153 + thread_cond_wait + 1125039 - advise_write - 900358 + advise_write + 900744 - mkancestor - 793073 + mkancestor + 793100 log_error - 536048 + 536168 esc_shell_multi - 355914 + 356152 msg_info - 295689 + 295927 - thread_cond_broadcast - 255503 + thread_cond_broadcast + 255615 - thread_cond_broadcast_and_unlock - 255313 + thread_cond_broadcast_and_unlock + 255425 msg_verbose - 126943 + 127041 - fmtime - 119580 + fmtime + 119636 - thread_cond_signal - 85887 + thread_cond_signal + 87081 - thread_cond_signal_and_unlock - 85887 + thread_cond_signal_and_unlock + 87081 - pathexport + pathexport 17589 - pathimport + lmtime + 17000 + + + pathimport 16572 @@ -192,11 +196,11 @@ 11259 - calloc_nofail + calloc_nofail 10089 - pathslash + pathslash 7705 @@ -204,27 +208,27 @@ 4449 - thread_mutex_init + thread_mutex_init 2284 - thread_create + thread_create 2200 - thread_join + thread_join 2200 - thread_mutex_destroy + thread_mutex_destroy 2082 msg_bar - 1958 + 2082 - strsplit + strsplit 1472 @@ -236,27 +240,27 @@ 809 - pathcatc + pathcatc 788 - - msg_flush - 627 - msg_status - 625 + 622 - malloc_counter_get + msg_flush + 573 + + + malloc_counter_get 476 - thread_cond_init + thread_cond_init 380 - thread_cond_destroy + thread_cond_destroy 380 @@ -264,7 +268,7 @@ 299 - pathcat + pathcat 267 @@ -272,39 +276,39 @@ 264 - printc - 106 + pathcut + 100 - pathcut - 100 + printc + 64 printl 52 - smartctl_attribute + smartctl_attribute 43 - - printr - 34 - printp 18 - smartctl_flush + printr + 16 + + + smartctl_flush 5 - strpolish + strpolish 0 - smatch + smatch 0 diff --git a/cov/cmdline/support.c.func.html b/cov/cmdline/support.c.func.html index 883dd715..117789b2 100644 --- a/cov/cmdline/support.c.func.html +++ b/cov/cmdline/support.c.func.html @@ -31,17 +31,17 @@ lcov.info Lines: - 441 - 550 - 80.2 % + 449 + 559 + 80.3 % Date: - 2016-11-21 + 2017-05-13 Functions: - 60 - 62 + 61 + 63 96.8 % @@ -60,40 +60,44 @@ Hit count Sort by hit count - advise_flags - 2494965 + advise_flags + 2494636 - advise_init - 2494910 + advise_init + 2494292 - advise_open - 2416366 + advise_open + 2412565 - advise_read - 8903631 + advise_read + 8897480 - advise_write - 900358 + advise_write + 900744 - calloc_nofail + calloc_nofail 10089 esc_shell_multi - 355914 + 356152 esc_tag - 2428312 + 2435456 - fmtime - 119580 + fmtime + 119636 + + + lmtime + 17000 lock_done @@ -105,15 +109,15 @@ lock_memory - 20173887 + 20173439 lock_msg - 3887334 + 3895147 log_error - 536048 + 536168 log_expected @@ -129,35 +133,35 @@ log_tag - 2907727 + 2915010 - malloc_counter_get + malloc_counter_get 476 - malloc_counter_inc - 20173411 + malloc_counter_inc + 20172963 - malloc_nofail - 14363921 + malloc_nofail + 14363716 - mkancestor - 793073 + mkancestor + 793100 msg_bar - 1958 + 2082 msg_flush - 627 + 573 msg_info - 295689 + 295927 msg_progress @@ -165,51 +169,51 @@ msg_status - 625 + 622 msg_verbose - 126943 + 127041 - pathcat + pathcat 267 - pathcatc + pathcatc 788 - pathcmp - 51890261 + pathcmp + 51889301 - pathcpy - 7892123 + pathcpy + 7884434 - pathcut + pathcut 100 - pathexport + pathexport 17589 - pathimport + pathimport 16572 - pathprint - 51564160 + pathprint + 51562646 - pathslash + pathslash 7705 printc - 106 + 64 printl @@ -221,91 +225,91 @@ printr - 34 + 16 - smartctl_attribute + smartctl_attribute 43 - smartctl_flush + smartctl_flush 5 - smatch + smatch 0 - strdup_nofail - 5799401 + strdup_nofail + 5799158 - strpolish + strpolish 0 - strsplit + strsplit 1472 - thread_cond_broadcast - 255503 + thread_cond_broadcast + 255615 - thread_cond_broadcast_and_unlock - 255313 + thread_cond_broadcast_and_unlock + 255425 - thread_cond_destroy + thread_cond_destroy 380 - thread_cond_init + thread_cond_init 380 - thread_cond_signal - 85887 + thread_cond_signal + 87081 - thread_cond_signal_and_unlock - 85887 + thread_cond_signal_and_unlock + 87081 - thread_cond_wait - 1037153 + thread_cond_wait + 1125039 - thread_create + thread_create 2200 - thread_join + thread_join 2200 - thread_mutex_destroy + thread_mutex_destroy 2082 - thread_mutex_init + thread_mutex_init 2284 - thread_mutex_lock - 80857668 + thread_mutex_lock + 80853862 - thread_mutex_unlock - 80858701 + thread_mutex_unlock + 80868352 unlock_memory - 20173887 + 20173439 unlock_msg - 3887334 + 3895151
diff --git a/cov/cmdline/support.c.gcov.html b/cov/cmdline/support.c.gcov.html index d72968c8..bfdab4e2 100644 --- a/cov/cmdline/support.c.gcov.html +++ b/cov/cmdline/support.c.gcov.html @@ -31,17 +31,17 @@ lcov.info Lines: - 441 - 550 - 80.2 % + 449 + 559 + 80.3 % Date: - 2016-11-21 + 2017-05-13 Functions: - 60 - 62 + 61 + 63 96.8 % @@ -92,33 +92,33 @@ 30 : static pthread_mutex_t memory_lock; 31 : #endif 32 : - 33 3887334 : void lock_msg(void) + 33 3895147 : void lock_msg(void) 34 : { 35 : #if HAVE_PTHREAD - 36 3887334 : thread_mutex_lock(&msg_lock); + 36 3895147 : thread_mutex_lock(&msg_lock); 37 : #endif - 38 3887334 : } + 38 3895151 : } 39 : - 40 3887334 : void unlock_msg(void) + 40 3895151 : void unlock_msg(void) 41 : { 42 : #if HAVE_PTHREAD - 43 3887334 : thread_mutex_unlock(&msg_lock); + 43 3895151 : thread_mutex_unlock(&msg_lock); 44 : #endif - 45 3887334 : } + 45 3895151 : } 46 : - 47 20173887 : void lock_memory(void) + 47 20173439 : void lock_memory(void) 48 : { 49 : #if HAVE_PTHREAD - 50 20173887 : thread_mutex_lock(&memory_lock); + 50 20173439 : thread_mutex_lock(&memory_lock); 51 : #endif - 52 20173887 : } + 52 20173439 : } 53 : - 54 20173887 : void unlock_memory(void) + 54 20173439 : void unlock_memory(void) 55 : { 56 : #if HAVE_PTHREAD - 57 20173887 : thread_mutex_unlock(&memory_lock); + 57 20173439 : thread_mutex_unlock(&memory_lock); 58 : #endif - 59 20173887 : } + 59 20173439 : } 60 : 61 299 : void lock_init(void) 62 : { @@ -176,18 +176,18 @@ 114 809 : unlock_msg(); 115 809 : } 116 : - 117 536048 : void log_error(const char* format, ...) + 117 536168 : void log_error(const char* format, ...) 118 : { 119 : va_list ap; 120 : - 121 536048 : lock_msg(); + 121 536168 : lock_msg(); 122 : - 123 536048 : if (stdlog) { - 124 534168 : va_start(ap, format); - 125 534168 : fprintf(stdlog, "msg:error: "); - 126 534168 : vfprintf(stdlog, format, ap); - 127 534168 : fflush(stdlog); - 128 534168 : va_end(ap); + 123 536168 : if (stdlog) { + 124 534288 : va_start(ap, format); + 125 534288 : fprintf(stdlog, "msg:error: "); + 126 534288 : vfprintf(stdlog, format, ap); + 127 534288 : fflush(stdlog); + 128 534288 : va_end(ap); 129 : } else { 130 1880 : va_start(ap, format); 131 1880 : vfprintf(stderr, format, ap); @@ -195,8 +195,8 @@ 133 1880 : va_end(ap); 134 : } 135 : - 136 536048 : unlock_msg(); - 137 536048 : } + 136 536168 : unlock_msg(); + 137 536168 : } 138 : 139 11259 : void log_expected(const char* format, ...) 140 : { @@ -215,22 +215,22 @@ 153 11259 : unlock_msg(); 154 11259 : } 155 : - 156 2907727 : void log_tag(const char* format, ...) + 156 2915010 : void log_tag(const char* format, ...) 157 : { 158 : va_list ap; 159 : - 160 2907727 : lock_msg(); + 160 2915010 : lock_msg(); 161 : - 162 2907727 : if (stdlog) { - 163 2571717 : va_start(ap, format); - 164 2571717 : vfprintf(stdlog, format, ap); + 162 2915018 : if (stdlog) { + 163 2573287 : va_start(ap, format); + 164 2573287 : vfprintf(stdlog, format, ap); 165 : /* here we intentionally don't flush */ 166 : /* to make the output faster */ - 167 2571717 : va_end(ap); + 167 2573287 : va_end(ap); 168 : } 169 : - 170 2907727 : unlock_msg(); - 171 2907727 : } + 170 2915018 : unlock_msg(); + 171 2915018 : } 172 : 173 1200 : void log_flush(void) 174 : { @@ -244,11 +244,11 @@ 182 1200 : unlock_msg(); 183 1200 : } 184 : - 185 625 : void msg_status(const char* format, ...) + 185 622 : void msg_status(const char* format, ...) 186 : { 187 : va_list ap; 188 : - 189 625 : lock_msg(); + 189 622 : lock_msg(); 190 : 191 625 : if (stdlog) { 192 275 : va_start(ap, format); @@ -268,24 +268,24 @@ 206 625 : unlock_msg(); 207 625 : } 208 : - 209 295689 : void msg_info(const char* format, ...) + 209 295927 : void msg_info(const char* format, ...) 210 : { 211 : va_list ap; 212 : - 213 295689 : lock_msg(); + 213 295927 : lock_msg(); 214 : 215 : /* don't output in stdlog as these messages */ 216 : /* are always paired with a msg_tag() call */ 217 : - 218 295689 : if (msg_level >= MSG_INFO) { - 219 28811 : va_start(ap, format); - 220 28811 : vfprintf(stdout, format, ap); - 221 28811 : fflush(stdout); - 222 28811 : va_end(ap); + 218 295927 : if (msg_level >= MSG_INFO) { + 219 28853 : va_start(ap, format); + 220 28853 : vfprintf(stdout, format, ap); + 221 28853 : fflush(stdout); + 222 28853 : va_end(ap); 223 : } 224 : - 225 295689 : unlock_msg(); - 226 295689 : } + 225 295927 : unlock_msg(); + 226 295927 : } 227 : 228 4449 : void msg_progress(const char* format, ...) 229 : { @@ -311,89 +311,89 @@ 249 4449 : unlock_msg(); 250 4449 : } 251 : - 252 1958 : void msg_bar(const char* format, ...) + 252 2082 : void msg_bar(const char* format, ...) 253 : { 254 : va_list ap; 255 : - 256 1958 : lock_msg(); + 256 2082 : lock_msg(); 257 : 258 : /* don't output in stdlog as these messages */ 259 : /* are intended for screen only */ 260 : /* also don't flush stdout as they are intended to be partial messages */ 261 : - 262 1958 : if (msg_level >= MSG_BAR) { + 262 2082 : if (msg_level >= MSG_BAR) { 263 0 : va_start(ap, format); 264 0 : vfprintf(stdout, format, ap); 265 0 : va_end(ap); 266 : } 267 : - 268 1958 : unlock_msg(); - 269 1958 : } + 268 2082 : unlock_msg(); + 269 2082 : } 270 : - 271 126943 : void msg_verbose(const char* format, ...) + 271 127041 : void msg_verbose(const char* format, ...) 272 : { 273 : va_list ap; 274 : - 275 126943 : lock_msg(); + 275 127041 : lock_msg(); 276 : - 277 126943 : if (stdlog) { - 278 125077 : va_start(ap, format); - 279 125077 : fprintf(stdlog, "msg:verbose: "); - 280 125077 : vfprintf(stdlog, format, ap); - 281 125077 : fflush(stdlog); - 282 125077 : va_end(ap); + 277 127041 : if (stdlog) { + 278 125175 : va_start(ap, format); + 279 125175 : fprintf(stdlog, "msg:verbose: "); + 280 125175 : vfprintf(stdlog, format, ap); + 281 125175 : fflush(stdlog); + 282 125175 : va_end(ap); 283 : } 284 : - 285 126943 : if (msg_level >= MSG_VERBOSE) { + 285 127041 : if (msg_level >= MSG_VERBOSE) { 286 91 : va_start(ap, format); 287 91 : vfprintf(stdout, format, ap); 288 91 : fflush(stdout); 289 91 : va_end(ap); 290 : } 291 : - 292 126943 : unlock_msg(); - 293 126943 : } + 292 127041 : unlock_msg(); + 293 127041 : } 294 : - 295 627 : void msg_flush(void) + 295 573 : void msg_flush(void) 296 : { - 297 627 : lock_msg(); + 297 573 : lock_msg(); 298 : - 299 627 : fflush(stdout); - 300 627 : fflush(stderr); + 299 573 : fflush(stdout); + 300 573 : fflush(stderr); 301 : - 302 627 : unlock_msg(); - 303 627 : } + 302 573 : unlock_msg(); + 303 573 : } 304 : - 305 106 : void printc(char c, size_t pad) + 305 64 : void printc(char c, size_t pad) 306 : { - 307 304 : while (pad) { + 307 180 : while (pad) { 308 : /* group writes in long pieces */ 309 : char buf[128]; - 310 92 : size_t len = pad; + 310 52 : size_t len = pad; 311 : - 312 92 : if (len >= sizeof(buf)) + 312 52 : if (len >= sizeof(buf)) 313 0 : len = sizeof(buf) - 1; 314 : - 315 92 : memset(buf, c, len); - 316 92 : buf[len] = 0; + 315 52 : memset(buf, c, len); + 316 52 : buf[len] = 0; 317 : - 318 92 : fputs(buf, stdout); + 318 52 : fputs(buf, stdout); 319 : - 320 92 : pad -= len; + 320 52 : pad -= len; 321 : } - 322 106 : } + 322 64 : } 323 : - 324 34 : void printr(const char* str, size_t pad) + 324 16 : void printr(const char* str, size_t pad) 325 : { 326 : size_t len; 327 : - 328 34 : len = strlen(str); + 328 16 : len = strlen(str); 329 : - 330 34 : if (len < pad) - 331 34 : printc(' ', pad - len); + 330 16 : if (len < pad) + 331 16 : printc(' ', pad - len); 332 : - 333 34 : fputs(str, stdout); - 334 34 : } + 333 16 : fputs(str, stdout); + 334 16 : } 335 : 336 52 : void printl(const char* str, size_t pad) 337 : { @@ -451,17 +451,17 @@ 389 : *p++ = to; \ 390 : break 391 : - 392 2428312 : const char* esc_tag(const char* str, char* buffer) + 392 2435456 : const char* esc_tag(const char* str, char* buffer) 393 : { - 394 2428312 : char* begin = buffer; - 395 2428312 : char* end = begin + ESC_MAX; - 396 2428312 : char* p = begin; + 394 2435456 : char* begin = buffer; + 395 2435456 : char* end = begin + ESC_MAX; + 396 2435456 : char* p = begin; 397 : 398 : /* copy string with escaping */ - 399 36387237 : while (*str) { - 400 31530613 : char c = *str; + 399 36481551 : while (*str) { + 400 31610639 : char c = *str; 401 : - 402 31530613 : switch (c) { + 402 31610639 : switch (c) { 403 : 404 0 : ESCAPE('\n', '\\', 'n'); 405 0 : ESCAPE('\r', '\\', 'r'); @@ -469,21 +469,21 @@ 407 0 : ESCAPE('\\', '\\', '\\'); 408 : 409 : default: - 410 31530613 : if (p == end) + 410 31610639 : if (p == end) 411 0 : goto bail; - 412 31530613 : *p++ = c; - 413 31530613 : break; + 412 31610639 : *p++ = c; + 413 31610639 : break; 414 : } 415 : - 416 31530613 : ++str; + 416 31610639 : ++str; 417 : } 418 : 419 : /* put final 0 */ - 420 2428312 : if (p == end) + 420 2435456 : if (p == end) 421 0 : goto bail; - 422 2428312 : *p = 0; + 422 2435456 : *p = 0; 423 : - 424 4856624 : return begin; + 424 4870912 : return begin; 425 : 426 : bail: 427 : /* LCOV_EXCL_START */ @@ -492,11 +492,11 @@ 430 : /* LCOV_EXCL_STOP */ 431 : } 432 : - 433 355914 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) + 433 356152 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) 434 : { - 435 355914 : char* begin = buffer; - 436 355914 : char* end = begin + ESC_MAX; - 437 355914 : char* p = begin; + 435 356152 : char* begin = buffer; + 436 356152 : char* end = begin + ESC_MAX; + 437 356152 : char* p = begin; 438 : unsigned str_mac; 439 : const char* str; 440 : @@ -517,24 +517,24 @@ 455 : #endif 456 : 457 : /* copy string with escaping */ - 458 355914 : str_mac = 0; - 459 355914 : str = str_map[str_mac]; + 458 356152 : str_mac = 0; + 459 356152 : str = str_map[str_mac]; 460 : while (1) { 461 : /* get the next char */ - 462 5122618 : char c = *str; + 462 5124343 : char c = *str; 463 : 464 : /* if one string is finished, go to the next */ - 465 10281326 : while (c == 0 && str_mac + 1 < str_max) { + 465 10284776 : while (c == 0 && str_mac + 1 < str_max) { 466 36090 : ++str_mac; 467 36090 : str = str_map[str_mac]; 468 36090 : c = *str; 469 : } 470 : 471 : /* if we read all the strings, stop */ - 472 5122618 : if (!c) - 473 355914 : break; + 472 5124343 : if (!c) + 473 356152 : break; 474 : - 475 4766704 : switch (c) { + 475 4768191 : switch (c) { 476 : #ifdef _WIN32 477 : /* 478 : * Windows shell escape @@ -589,1144 +589,1193 @@ 527 : *p++ = c; 528 : } 529 : break; - 530 : default : - 531 : /* unquoted */ - 532 : if (p == end) - 533 : goto bail; - 534 : *p++ = c; - 535 : break; - 536 : #else - 537 : case 'a' ... 'z' : - 538 : case 'A' ... 'Z' : - 539 : case '0' ... '9' : - 540 : case ',' : - 541 : case '.' : - 542 : case '_' : - 543 : case '+' : - 544 : case ':' : - 545 : case '@' : - 546 : case '%' : - 547 : case '/' : - 548 : case '-' : - 549 : /* safe chars for all shells, unquoted */ - 550 4687726 : if (p == end) - 551 0 : goto bail; - 552 4687726 : *p++ = c; - 553 4687726 : break; - 554 : default : - 555 : /* all the others are quoted with \ */ - 556 78978 : if (p == end) + 530 : #else + 531 : /* special chars that need to be quoted */ + 532 : case ' ' : /* space */ + 533 : case '~' : /* home */ + 534 : case '`' : /* command */ + 535 : case '#' : /* comment */ + 536 : case '$' : /* variable */ + 537 : case '&' : /* background job */ + 538 : case '*' : /* wildcard */ + 539 : case '(' : /* shell */ + 540 : case ')' : /* shell */ + 541 : case '\\': /* quote */ + 542 : case '|' : /* pipe */ + 543 : case '[' : /* wildcard */ + 544 : case ']' : /* wildcard */ + 545 : case '{' : /* code */ + 546 : case '}' : /* code */ + 547 : case ';' : /* separator */ + 548 : case '\'': /* quote */ + 549 : case '"' : /* quote */ + 550 : case '<' : /* redirect */ + 551 : case '>' : /* redirect */ + 552 : case '?' : /* wildcard */ + 553 79129 : if (p == end) + 554 0 : goto bail; + 555 79129 : *p++ = '\\'; + 556 79129 : if (p == end) 557 0 : goto bail; - 558 78978 : *p++ = '\\'; - 559 78978 : if (p == end) - 560 0 : goto bail; - 561 78978 : *p++ = c; - 562 78978 : break; - 563 : #endif - 564 : } - 565 : - 566 4766704 : ++str; - 567 4766704 : } + 558 79129 : *p++ = c; + 559 79129 : break; + 560 : #endif + 561 : default : + 562 : /* unquoted */ + 563 4689062 : if (p == end) + 564 0 : goto bail; + 565 4689062 : *p++ = c; + 566 4689062 : break; + 567 : } 568 : - 569 : #ifdef _WIN32 - 570 : if (has_quote) { - 571 : if (p == end) - 572 : goto bail; - 573 : *p++ = '"'; - 574 : } - 575 : #endif - 576 : - 577 : /* put final 0 */ - 578 355914 : if (p == end) - 579 0 : goto bail; - 580 355914 : *p = 0; - 581 : - 582 711828 : return begin; - 583 : - 584 : bail: - 585 : /* LCOV_EXCL_START */ - 586 : log_fatal("Escape for shell too long\n"); - 587 : exit(EXIT_FAILURE); - 588 : /* LCOV_EXCL_STOP */ - 589 : } - 590 : - 591 0 : char* strpolish(char* s) - 592 : { - 593 0 : char* i = s; - 594 : - 595 0 : while (*i) { - 596 0 : if (isspace(*i) || !isprint(*i)) - 597 0 : *i = ' '; - 598 0 : ++i; - 599 : } - 600 : - 601 0 : return s; - 602 : } + 569 4768191 : ++str; + 570 4768191 : } + 571 : + 572 : #ifdef _WIN32 + 573 : if (has_quote) { + 574 : if (p == end) + 575 : goto bail; + 576 : *p++ = '"'; + 577 : } + 578 : #endif + 579 : + 580 : /* put final 0 */ + 581 356152 : if (p == end) + 582 0 : goto bail; + 583 356152 : *p = 0; + 584 : + 585 712304 : return begin; + 586 : + 587 : bail: + 588 : /* LCOV_EXCL_START */ + 589 : log_fatal("Escape for shell too long\n"); + 590 : exit(EXIT_FAILURE); + 591 : /* LCOV_EXCL_STOP */ + 592 : } + 593 : + 594 0 : char* strpolish(char* s) + 595 : { + 596 0 : char* i = s; + 597 : + 598 0 : while (*i) { + 599 0 : if (isspace(*i) || !isprint(*i)) + 600 0 : *i = ' '; + 601 0 : ++i; + 602 : } 603 : - 604 1472 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters) - 605 : { - 606 1472 : unsigned mac = 0; - 607 : - 608 : /* skip initial delimiters */ - 609 1472 : str += strspn(str, delimiters); + 604 0 : return s; + 605 : } + 606 : + 607 1472 : unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters) + 608 : { + 609 1472 : unsigned mac = 0; 610 : - 611 8932 : while (*str != 0 || mac == split_max) { - 612 : /* start of the token */ - 613 5988 : split_map[mac] = str; - 614 5988 : ++mac; - 615 : - 616 : /* find the first delimiter or the end of the string */ - 617 5988 : str += strcspn(str, delimiters); + 611 : /* skip initial delimiters */ + 612 1472 : str += strspn(str, delimiters); + 613 : + 614 8932 : while (*str != 0 || mac == split_max) { + 615 : /* start of the token */ + 616 5988 : split_map[mac] = str; + 617 5988 : ++mac; 618 : - 619 : /* put the final terminator if missing */ - 620 5988 : if (*str != 0) - 621 4616 : *str++ = 0; - 622 : - 623 : /* skip trailing delimiters */ - 624 5988 : str += strspn(str, delimiters); - 625 : } - 626 : - 627 1472 : return mac; - 628 : } + 619 : /* find the first delimiter or the end of the string */ + 620 5988 : str += strcspn(str, delimiters); + 621 : + 622 : /* put the final terminator if missing */ + 623 5988 : if (*str != 0) + 624 4616 : *str++ = 0; + 625 : + 626 : /* skip trailing delimiters */ + 627 5988 : str += strspn(str, delimiters); + 628 : } 629 : - 630 : /****************************************************************************/ - 631 : /* path */ + 630 1472 : return mac; + 631 : } 632 : - 633 7892123 : void pathcpy(char* dst, size_t size, const char* src) - 634 : { - 635 7892123 : size_t len = strlen(src); - 636 : - 637 7892123 : if (len + 1 > size) { - 638 : /* LCOV_EXCL_START */ - 639 : log_fatal("Path too long '%s'\n", src); - 640 : os_abort(); - 641 : /* LCOV_EXCL_STOP */ - 642 : } - 643 : - 644 7892123 : memcpy(dst, src, len + 1); - 645 7892123 : } + 633 : /****************************************************************************/ + 634 : /* path */ + 635 : + 636 7884434 : void pathcpy(char* dst, size_t size, const char* src) + 637 : { + 638 7884434 : size_t len = strlen(src); + 639 : + 640 7884434 : if (len + 1 > size) { + 641 : /* LCOV_EXCL_START */ + 642 : log_fatal("Path too long '%s'\n", src); + 643 : os_abort(); + 644 : /* LCOV_EXCL_STOP */ + 645 : } 646 : - 647 267 : void pathcat(char* dst, size_t size, const char* src) - 648 : { - 649 267 : size_t dst_len = strlen(dst); - 650 267 : size_t src_len = strlen(src); - 651 : - 652 267 : if (dst_len + src_len + 1 > size) { - 653 : /* LCOV_EXCL_START */ - 654 : log_fatal("Path too long '%s%s'\n", dst, src); - 655 : os_abort(); - 656 : /* LCOV_EXCL_STOP */ - 657 : } - 658 : - 659 267 : memcpy(dst + dst_len, src, src_len + 1); - 660 267 : } + 647 7884434 : memcpy(dst, src, len + 1); + 648 7884434 : } + 649 : + 650 267 : void pathcat(char* dst, size_t size, const char* src) + 651 : { + 652 267 : size_t dst_len = strlen(dst); + 653 267 : size_t src_len = strlen(src); + 654 : + 655 267 : if (dst_len + src_len + 1 > size) { + 656 : /* LCOV_EXCL_START */ + 657 : log_fatal("Path too long '%s%s'\n", dst, src); + 658 : os_abort(); + 659 : /* LCOV_EXCL_STOP */ + 660 : } 661 : - 662 788 : void pathcatc(char* dst, size_t size, char c) - 663 : { - 664 788 : size_t dst_len = strlen(dst); - 665 : - 666 788 : if (dst_len + 2 > size) { - 667 : /* LCOV_EXCL_START */ - 668 : log_fatal("Path too long '%s%c'\n", dst, c); - 669 : os_abort(); - 670 : /* LCOV_EXCL_STOP */ - 671 : } - 672 : - 673 788 : dst[dst_len] = c; - 674 788 : dst[dst_len + 1] = 0; - 675 788 : } - 676 : - 677 16572 : void pathimport(char* dst, size_t size, const char* src) - 678 : { - 679 16572 : pathcpy(dst, size, src); - 680 : - 681 : #ifdef _WIN32 - 682 : /* convert the Windows dir separator '\' to C '/', */ - 683 : /* and the Windows escaping char '^' to the fnmatch '\' */ - 684 : while (*dst) { - 685 : switch (*dst) { - 686 : case '\\' : - 687 : *dst = '/'; - 688 : break; - 689 : case '^' : - 690 : *dst = '\\'; + 662 267 : memcpy(dst + dst_len, src, src_len + 1); + 663 267 : } + 664 : + 665 788 : void pathcatc(char* dst, size_t size, char c) + 666 : { + 667 788 : size_t dst_len = strlen(dst); + 668 : + 669 788 : if (dst_len + 2 > size) { + 670 : /* LCOV_EXCL_START */ + 671 : log_fatal("Path too long '%s%c'\n", dst, c); + 672 : os_abort(); + 673 : /* LCOV_EXCL_STOP */ + 674 : } + 675 : + 676 788 : dst[dst_len] = c; + 677 788 : dst[dst_len + 1] = 0; + 678 788 : } + 679 : + 680 16572 : void pathimport(char* dst, size_t size, const char* src) + 681 : { + 682 16572 : pathcpy(dst, size, src); + 683 : + 684 : #ifdef _WIN32 + 685 : /* convert the Windows dir separator '\' to C '/', */ + 686 : /* and the Windows escaping char '^' to the fnmatch '\' */ + 687 : while (*dst) { + 688 : switch (*dst) { + 689 : case '\\' : + 690 : *dst = '/'; 691 : break; - 692 : } - 693 : ++dst; - 694 : } - 695 : #endif - 696 16572 : } - 697 : - 698 17589 : void pathexport(char* dst, size_t size, const char* src) - 699 : { - 700 17589 : pathcpy(dst, size, src); - 701 : - 702 : #ifdef _WIN32 - 703 : /* invert the import */ - 704 : while (*dst) { - 705 : switch (*dst) { - 706 : case '/' : - 707 : *dst = '\\'; - 708 : break; - 709 : case '\\' : - 710 : *dst = '^'; + 692 : case '^' : + 693 : *dst = '\\'; + 694 : break; + 695 : } + 696 : ++dst; + 697 : } + 698 : #endif + 699 16572 : } + 700 : + 701 17589 : void pathexport(char* dst, size_t size, const char* src) + 702 : { + 703 17589 : pathcpy(dst, size, src); + 704 : + 705 : #ifdef _WIN32 + 706 : /* invert the import */ + 707 : while (*dst) { + 708 : switch (*dst) { + 709 : case '/' : + 710 : *dst = '\\'; 711 : break; - 712 : } - 713 : ++dst; - 714 : } - 715 : #endif - 716 17589 : } - 717 : - 718 51564160 : void pathprint(char* dst, size_t size, const char* format, ...) - 719 : { - 720 : size_t len; - 721 : va_list ap; - 722 : - 723 51564160 : va_start(ap, format); - 724 51564160 : len = vsnprintf(dst, size, format, ap); - 725 51564160 : va_end(ap); - 726 : - 727 51564160 : if (len >= size) { - 728 : /* LCOV_EXCL_START */ - 729 : if (size > 0) { - 730 : dst[size - 1] = 0; - 731 : log_fatal("Path too long '%s...'\n", dst); - 732 : } else { - 733 : log_fatal("Path too long for empty size'\n"); - 734 : } - 735 : os_abort(); - 736 : /* LCOV_EXCL_STOP */ - 737 : } - 738 51564160 : } - 739 : - 740 7705 : void pathslash(char* dst, size_t size) - 741 : { - 742 7705 : size_t len = strlen(dst); - 743 : - 744 7705 : if (len > 0 && dst[len - 1] != '/') { - 745 6114 : if (len + 2 >= size) { - 746 : /* LCOV_EXCL_START */ - 747 : log_fatal("Path too long '%s/'\n", dst); - 748 : os_abort(); - 749 : /* LCOV_EXCL_STOP */ - 750 : } - 751 : - 752 6114 : dst[len] = '/'; - 753 6114 : dst[len + 1] = 0; - 754 : } - 755 7705 : } - 756 : - 757 100 : void pathcut(char* dst) - 758 : { - 759 100 : char* slash = strrchr(dst, '/'); - 760 : - 761 100 : if (slash) - 762 100 : slash[1] = 0; - 763 : else - 764 0 : dst[0] = 0; - 765 100 : } - 766 : - 767 51890261 : int pathcmp(const char* a, const char* b) - 768 : { - 769 : #ifdef _WIN32 - 770 : char ai[PATH_MAX]; - 771 : char bi[PATH_MAX]; - 772 : - 773 : /* import to convert \ to / */ - 774 : pathimport(ai, sizeof(ai), a); - 775 : pathimport(bi, sizeof(bi), b); - 776 : - 777 : /* case insensitive compare in Windows */ - 778 : return stricmp(ai, bi); - 779 : #else - 780 51890261 : return strcmp(a, b); - 781 : #endif - 782 : } - 783 : - 784 : /****************************************************************************/ - 785 : /* file-system */ + 712 : case '\\' : + 713 : *dst = '^'; + 714 : break; + 715 : } + 716 : ++dst; + 717 : } + 718 : #endif + 719 17589 : } + 720 : + 721 51562646 : void pathprint(char* dst, size_t size, const char* format, ...) + 722 : { + 723 : size_t len; + 724 : va_list ap; + 725 : + 726 51562646 : va_start(ap, format); + 727 51562646 : len = vsnprintf(dst, size, format, ap); + 728 51562646 : va_end(ap); + 729 : + 730 51562646 : if (len >= size) { + 731 : /* LCOV_EXCL_START */ + 732 : if (size > 0) { + 733 : dst[size - 1] = 0; + 734 : log_fatal("Path too long '%s...'\n", dst); + 735 : } else { + 736 : log_fatal("Path too long for empty size'\n"); + 737 : } + 738 : os_abort(); + 739 : /* LCOV_EXCL_STOP */ + 740 : } + 741 51562646 : } + 742 : + 743 7705 : void pathslash(char* dst, size_t size) + 744 : { + 745 7705 : size_t len = strlen(dst); + 746 : + 747 7705 : if (len > 0 && dst[len - 1] != '/') { + 748 6114 : if (len + 2 >= size) { + 749 : /* LCOV_EXCL_START */ + 750 : log_fatal("Path too long '%s/'\n", dst); + 751 : os_abort(); + 752 : /* LCOV_EXCL_STOP */ + 753 : } + 754 : + 755 6114 : dst[len] = '/'; + 756 6114 : dst[len + 1] = 0; + 757 : } + 758 7705 : } + 759 : + 760 100 : void pathcut(char* dst) + 761 : { + 762 100 : char* slash = strrchr(dst, '/'); + 763 : + 764 100 : if (slash) + 765 100 : slash[1] = 0; + 766 : else + 767 0 : dst[0] = 0; + 768 100 : } + 769 : + 770 51889301 : int pathcmp(const char* a, const char* b) + 771 : { + 772 : #ifdef _WIN32 + 773 : char ai[PATH_MAX]; + 774 : char bi[PATH_MAX]; + 775 : + 776 : /* import to convert \ to / */ + 777 : pathimport(ai, sizeof(ai), a); + 778 : pathimport(bi, sizeof(bi), b); + 779 : + 780 : /* case insensitive compare in Windows */ + 781 : return stricmp(ai, bi); + 782 : #else + 783 51889301 : return strcmp(a, b); + 784 : #endif + 785 : } 786 : - 787 793073 : int mkancestor(const char* file) - 788 : { - 789 : char dir[PATH_MAX]; - 790 : struct stat st; - 791 : char* c; - 792 : - 793 793073 : pathcpy(dir, sizeof(dir), file); - 794 : - 795 793073 : c = strrchr(dir, '/'); - 796 793073 : if (!c) { - 797 : /* no ancestor */ - 798 0 : return 0; - 799 : } - 800 : - 801 : /* clear the file */ - 802 793073 : *c = 0; + 787 : /****************************************************************************/ + 788 : /* file-system */ + 789 : + 790 793100 : int mkancestor(const char* file) + 791 : { + 792 : char dir[PATH_MAX]; + 793 : struct stat st; + 794 : char* c; + 795 : + 796 793100 : pathcpy(dir, sizeof(dir), file); + 797 : + 798 793100 : c = strrchr(dir, '/'); + 799 793100 : if (!c) { + 800 : /* no ancestor */ + 801 0 : return 0; + 802 : } 803 : - 804 : /* if it's the root dir */ - 805 793073 : if (*dir == 0) { - 806 : /* nothing more to do */ - 807 0 : return 0; - 808 : } - 809 : - 810 : #ifdef _WIN32 - 811 : /* if it's a drive specificaion like "C:" */ - 812 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { - 813 : /* nothing more to do */ - 814 : return 0; - 815 : } - 816 : #endif - 817 : - 818 : /* - 819 : * Check if the dir already exists using lstat(). - 820 : * - 821 : * Note that in Windows when dealing with read-only media - 822 : * you cannot try to create the directory, and expecting - 823 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. - 824 : * - 825 : * Also in Windows it's better to use lstat() than stat() because it - 826 : * doesn't need to open the dir with CreateFile(). - 827 : */ - 828 793073 : if (lstat(dir, &st) == 0) { - 829 : /* it already exists */ - 830 792993 : return 0; - 831 : } - 832 : - 833 : /* recursively create them all */ - 834 80 : if (mkancestor(dir) != 0) { - 835 : /* LCOV_EXCL_START */ - 836 : return -1; - 837 : /* LCOV_EXCL_STOP */ - 838 : } - 839 : - 840 : /* create it */ - 841 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { - 842 : /* LCOV_EXCL_START */ - 843 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno)); - 844 : return -1; - 845 : /* LCOV_EXCL_STOP */ - 846 : } - 847 : - 848 80 : return 0; - 849 : } + 804 : /* clear the file */ + 805 793100 : *c = 0; + 806 : + 807 : /* if it's the root dir */ + 808 793100 : if (*dir == 0) { + 809 : /* nothing more to do */ + 810 0 : return 0; + 811 : } + 812 : + 813 : #ifdef _WIN32 + 814 : /* if it's a drive specificaion like "C:" */ + 815 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { + 816 : /* nothing more to do */ + 817 : return 0; + 818 : } + 819 : #endif + 820 : + 821 : /* + 822 : * Check if the dir already exists using lstat(). + 823 : * + 824 : * Note that in Windows when dealing with read-only media + 825 : * you cannot try to create the directory, and expecting + 826 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. + 827 : * + 828 : * Also in Windows it's better to use lstat() than stat() because it + 829 : * doesn't need to open the dir with CreateFile(). + 830 : */ + 831 793100 : if (lstat(dir, &st) == 0) { + 832 : /* it already exists */ + 833 793020 : return 0; + 834 : } + 835 : + 836 : /* recursively create them all */ + 837 80 : if (mkancestor(dir) != 0) { + 838 : /* LCOV_EXCL_START */ + 839 : return -1; + 840 : /* LCOV_EXCL_STOP */ + 841 : } + 842 : + 843 : /* create it */ + 844 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + 845 : /* LCOV_EXCL_START */ + 846 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno)); + 847 : return -1; + 848 : /* LCOV_EXCL_STOP */ + 849 : } 850 : - 851 119580 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) - 852 : { - 853 : #if HAVE_FUTIMENS - 854 : struct timespec tv[2]; - 855 : #else - 856 : struct timeval tv[2]; - 857 : #endif - 858 : int ret; - 859 : - 860 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ - 861 119580 : tv[0].tv_sec = mtime_sec; - 862 119580 : if (mtime_nsec != STAT_NSEC_INVALID) - 863 119580 : tv[0].tv_nsec = mtime_nsec; - 864 : else - 865 0 : tv[0].tv_nsec = 0; - 866 119580 : tv[1].tv_sec = tv[0].tv_sec; - 867 119580 : tv[1].tv_nsec = tv[0].tv_nsec; - 868 : - 869 119580 : ret = futimens(f, tv); - 870 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ - 871 : tv[0].tv_sec = mtime_sec; - 872 : if (mtime_nsec != STAT_NSEC_INVALID) - 873 : tv[0].tv_usec = mtime_nsec / 1000; - 874 : else - 875 : tv[0].tv_usec = 0; - 876 : tv[1].tv_sec = tv[0].tv_sec; - 877 : tv[1].tv_usec = tv[0].tv_usec; - 878 : - 879 : ret = futimes(f, tv); - 880 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ - 881 : tv[0].tv_sec = mtime_sec; - 882 : if (mtime_nsec != STAT_NSEC_INVALID) - 883 : tv[0].tv_usec = mtime_nsec / 1000; - 884 : else - 885 : tv[0].tv_usec = 0; - 886 : tv[1].tv_sec = tv[0].tv_sec; - 887 : tv[1].tv_usec = tv[0].tv_usec; - 888 : - 889 : ret = futimesat(f, 0, tv); - 890 : #else - 891 : #error No function available to set file timestamps with sub-second precision - 892 : #endif - 893 : - 894 119580 : return ret; - 895 : } + 851 80 : return 0; + 852 : } + 853 : + 854 119636 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) + 855 : { + 856 : #if HAVE_FUTIMENS + 857 : struct timespec tv[2]; + 858 : #else + 859 : struct timeval tv[2]; + 860 : #endif + 861 : int ret; + 862 : + 863 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ + 864 119636 : tv[0].tv_sec = mtime_sec; + 865 119636 : if (mtime_nsec != STAT_NSEC_INVALID) + 866 119636 : tv[0].tv_nsec = mtime_nsec; + 867 : else + 868 0 : tv[0].tv_nsec = 0; + 869 119636 : tv[1].tv_sec = tv[0].tv_sec; + 870 119636 : tv[1].tv_nsec = tv[0].tv_nsec; + 871 : + 872 119636 : ret = futimens(f, tv); + 873 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ + 874 : tv[0].tv_sec = mtime_sec; + 875 : if (mtime_nsec != STAT_NSEC_INVALID) + 876 : tv[0].tv_usec = mtime_nsec / 1000; + 877 : else + 878 : tv[0].tv_usec = 0; + 879 : tv[1].tv_sec = tv[0].tv_sec; + 880 : tv[1].tv_usec = tv[0].tv_usec; + 881 : + 882 : ret = futimes(f, tv); + 883 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + 884 : tv[0].tv_sec = mtime_sec; + 885 : if (mtime_nsec != STAT_NSEC_INVALID) + 886 : tv[0].tv_usec = mtime_nsec / 1000; + 887 : else + 888 : tv[0].tv_usec = 0; + 889 : tv[1].tv_sec = tv[0].tv_sec; + 890 : tv[1].tv_usec = tv[0].tv_usec; + 891 : + 892 : ret = futimesat(f, 0, tv); + 893 : #else + 894 : #error No function available to set file timestamps with sub-second precision + 895 : #endif 896 : - 897 : /****************************************************************************/ - 898 : /* advise */ + 897 119636 : return ret; + 898 : } 899 : - 900 2494910 : void advise_init(struct advise_struct* advise, int mode) + 900 17000 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec) 901 : { - 902 2494910 : advise->mode = mode; - 903 2494910 : advise->dirty_begin = 0; - 904 2494910 : advise->dirty_end = 0; - 905 2494910 : } - 906 : - 907 2494965 : int advise_flags(struct advise_struct* advise) - 908 : { - 909 2494965 : int flags = 0; - 910 : - 911 2494965 : if (advise->mode == ADVISE_SEQUENTIAL - 912 2483621 : || advise->mode == ADVISE_FLUSH - 913 34020 : || advise->mode == ADVISE_FLUSH_WINDOW - 914 22682 : || advise->mode == ADVISE_DISCARD - 915 22682 : || advise->mode == ADVISE_DISCARD_WINDOW - 916 : ) - 917 2483614 : flags |= O_SEQUENTIAL; - 918 : - 919 : #if HAVE_DIRECT_IO - 920 2494965 : if (advise->mode == ADVISE_DIRECT) - 921 0 : flags |= O_DIRECT; - 922 : #endif - 923 : - 924 2494965 : return flags; - 925 : } - 926 : - 927 2416366 : int advise_open(struct advise_struct* advise, int f) - 928 : { - 929 : (void)advise; - 930 : (void)f; - 931 : - 932 : #if HAVE_POSIX_FADVISE - 933 2416366 : if (advise->mode == ADVISE_SEQUENTIAL - 934 2405026 : || advise->mode == ADVISE_FLUSH - 935 34021 : || advise->mode == ADVISE_FLUSH_WINDOW - 936 22682 : || advise->mode == ADVISE_DISCARD - 937 22682 : || advise->mode == ADVISE_DISCARD_WINDOW - 938 : ) { - 939 : int ret; - 940 : - 941 : /* advise sequential access */ - 942 2405029 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); - 943 2405059 : if (ret == ENOSYS) { - 944 : /* call is not supported, like in armhf, see posix_fadvise manpage */ - 945 0 : ret = 0; - 946 : } - 947 2405059 : if (ret != 0) { - 948 : /* LCOV_EXCL_START */ - 949 : errno = ret; /* posix_fadvise return the error code */ - 950 : return -1; - 951 : /* LCOV_EXCL_STOP */ - 952 : } - 953 : } - 954 : #endif + 902 : #if HAVE_UTIMENSAT + 903 : struct timespec tv[2]; + 904 : #else + 905 : struct timeval tv[2]; + 906 : #endif + 907 : int ret; + 908 : + 909 : #if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */ + 910 17000 : tv[0].tv_sec = mtime_sec; + 911 17000 : if (mtime_nsec != STAT_NSEC_INVALID) + 912 17000 : tv[0].tv_nsec = mtime_nsec; + 913 : else + 914 0 : tv[0].tv_nsec = 0; + 915 17000 : tv[1].tv_sec = tv[0].tv_sec; + 916 17000 : tv[1].tv_nsec = tv[0].tv_nsec; + 917 : + 918 17000 : ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW); + 919 : #elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */ + 920 : tv[0].tv_sec = mtime_sec; + 921 : if (mtime_nsec != STAT_NSEC_INVALID) + 922 : tv[0].tv_usec = mtime_nsec / 1000; + 923 : else + 924 : tv[0].tv_usec = 0; + 925 : tv[1].tv_sec = tv[0].tv_sec; + 926 : tv[1].tv_usec = tv[0].tv_usec; + 927 : + 928 : ret = lutimes(path, tv); + 929 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + 930 : tv[0].tv_sec = mtime_sec; + 931 : if (mtime_nsec != STAT_NSEC_INVALID) + 932 : tv[0].tv_usec = mtime_nsec / 1000; + 933 : else + 934 : tv[0].tv_usec = 0; + 935 : tv[1].tv_sec = tv[0].tv_sec; + 936 : tv[1].tv_usec = tv[0].tv_usec; + 937 : + 938 : ret = futimesat(AT_FDCWD, path, tv); + 939 : #else + 940 : #error No function available to set file timestamps with sub-second precision + 941 : #endif + 942 : + 943 17000 : return ret; + 944 : } + 945 : + 946 : /****************************************************************************/ + 947 : /* advise */ + 948 : + 949 2494292 : void advise_init(struct advise_struct* advise, int mode) + 950 : { + 951 2494292 : advise->mode = mode; + 952 2494292 : advise->dirty_begin = 0; + 953 2494292 : advise->dirty_end = 0; + 954 2494292 : } 955 : - 956 2416396 : return 0; - 957 : } - 958 : - 959 900358 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) - 960 : { - 961 : data_off_t flush_offset; - 962 : data_off_t flush_size; - 963 : data_off_t discard_offset; - 964 : data_off_t discard_size; - 965 : - 966 : (void)f; - 967 : (void)flush_offset; - 968 : (void)flush_size; - 969 : (void)discard_offset; - 970 : (void)discard_size; - 971 : - 972 900358 : flush_offset = 0; - 973 900358 : flush_size = 0; - 974 900358 : discard_offset = 0; - 975 900358 : discard_size = 0; - 976 : - 977 : /* - 978 : * Follow Linus recommendations about fast writes. - 979 : * - 980 : * Linus "Unexpected splice "always copy" behavior observed" - 981 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070 - 982 : * --- - 983 : * I have had _very_ good experiences with even a rather trivial - 984 : * file writer that basically used (iirc) 8MB windows, and the logic was very - 985 : * trivial: - 986 : * - 987 : * - before writing a new 8M window, do "start writeback" - 988 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do - 989 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that. - 990 : * - 991 : * in fact, in its simplest form, you can do it like this (this is from my - 992 : * "overwrite disk images" program that I use on old disks): - 993 : * - 994 : * for (index = 0; index < max_index ;index++) { - 995 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE) - 996 : * break; - 997 : * // This won't block, but will start writeout asynchronously - 998 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE); - 999 : * // This does a blocking write-and-wait on any old ranges - 1000 : * if (index) - 1001 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); - 1002 : * } - 1003 : * - 1004 : * and even if you don't actually do a discard (maybe we should add a - 1005 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate - 1006 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty - 1007 : * nice, because the heavy writer gets good IO performance _and_ leaves only - 1008 : * easy-to-free pages around after itself. - 1009 : * --- - 1010 : * - 1011 : * Linus "Unexpected splice "always copy" behavior observed" - 1012 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176 - 1013 : * --- - 1014 : * The behavior for dirty page writeback is _not_ well defined, and - 1015 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that - 1016 : * writeback logic, ie you do it only on ranges that you have just waited on. - 1017 : * - 1018 : * IOW, in my example, you'd couple the - 1019 : * - 1020 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); - 1021 : * - 1022 : * with a - 1023 : * - 1024 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED); - 1025 : * - 1026 : * afterwards to throw out the pages that you just waited for. - 1027 : * --- - 1028 : */ - 1029 : - 1030 900358 : switch (advise->mode) { - 1031 : case ADVISE_FLUSH : - 1032 881613 : flush_offset = offset; - 1033 881613 : flush_size = size; - 1034 881613 : break; - 1035 : case ADVISE_DISCARD : - 1036 0 : discard_offset = offset; - 1037 0 : discard_size = size; - 1038 0 : break; - 1039 : case ADVISE_FLUSH_WINDOW : - 1040 : /* if the dirty range can be extended */ - 1041 4687 : if (advise->dirty_end == offset) { - 1042 : /* extent the dirty range */ - 1043 4687 : advise->dirty_end += size; - 1044 : - 1045 : /* if we reached the window size */ - 1046 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) { - 1047 : /* flush the window */ - 1048 0 : flush_offset = advise->dirty_begin; - 1049 0 : flush_size = ADVISE_WINDOW_SIZE; - 1050 : - 1051 : /* remove it from the dirty range */ - 1052 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; - 1053 : } - 1054 : } else { - 1055 : /* otherwise flush the existing dirty */ - 1056 0 : flush_offset = advise->dirty_begin; - 1057 0 : flush_size = advise->dirty_end - advise->dirty_begin; - 1058 : - 1059 : /* and set the new range as dirty */ - 1060 0 : advise->dirty_begin = offset; - 1061 0 : advise->dirty_end = offset + size; - 1062 : } - 1063 4687 : break; - 1064 : case ADVISE_DISCARD_WINDOW : - 1065 : /* if the dirty range can be extended */ - 1066 4687 : if (advise->dirty_end == offset) { - 1067 : /* extent the dirty range */ - 1068 4687 : advise->dirty_end += size; - 1069 : - 1070 : /* if we reached the double window size */ - 1071 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) { - 1072 : /* discard the first window */ - 1073 0 : discard_offset = advise->dirty_begin; - 1074 0 : discard_size = ADVISE_WINDOW_SIZE; - 1075 : - 1076 : /* remove it from the dirty range */ - 1077 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; + 956 2494636 : int advise_flags(struct advise_struct* advise) + 957 : { + 958 2494636 : int flags = 0; + 959 : + 960 2494636 : if (advise->mode == ADVISE_SEQUENTIAL + 961 2482812 : || advise->mode == ADVISE_FLUSH + 962 33993 : || advise->mode == ADVISE_FLUSH_WINDOW + 963 22671 : || advise->mode == ADVISE_DISCARD + 964 22680 : || advise->mode == ADVISE_DISCARD_WINDOW + 965 : ) + 966 2482844 : flags |= O_SEQUENTIAL; + 967 : + 968 : #if HAVE_DIRECT_IO + 969 2494636 : if (advise->mode == ADVISE_DIRECT) + 970 0 : flags |= O_DIRECT; + 971 : #endif + 972 : + 973 2494636 : return flags; + 974 : } + 975 : + 976 2412565 : int advise_open(struct advise_struct* advise, int f) + 977 : { + 978 : (void)advise; + 979 : (void)f; + 980 : + 981 : #if HAVE_POSIX_FADVISE + 982 2412565 : if (advise->mode == ADVISE_SEQUENTIAL + 983 2402846 : || advise->mode == ADVISE_FLUSH + 984 33966 : || advise->mode == ADVISE_FLUSH_WINDOW + 985 22656 : || advise->mode == ADVISE_DISCARD + 986 22664 : || advise->mode == ADVISE_DISCARD_WINDOW + 987 : ) { + 988 : int ret; + 989 : + 990 : /* advise sequential access */ + 991 2403737 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + 992 2403635 : if (ret == ENOSYS) { + 993 : /* call is not supported, like in armhf, see posix_fadvise manpage */ + 994 0 : ret = 0; + 995 : } + 996 2403635 : if (ret != 0) { + 997 : /* LCOV_EXCL_START */ + 998 : errno = ret; /* posix_fadvise return the error code */ + 999 : return -1; + 1000 : /* LCOV_EXCL_STOP */ + 1001 : } + 1002 : } + 1003 : #endif + 1004 : + 1005 2412463 : return 0; + 1006 : } + 1007 : + 1008 900744 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) + 1009 : { + 1010 : data_off_t flush_offset; + 1011 : data_off_t flush_size; + 1012 : data_off_t discard_offset; + 1013 : data_off_t discard_size; + 1014 : + 1015 : (void)f; + 1016 : (void)flush_offset; + 1017 : (void)flush_size; + 1018 : (void)discard_offset; + 1019 : (void)discard_size; + 1020 : + 1021 900744 : flush_offset = 0; + 1022 900744 : flush_size = 0; + 1023 900744 : discard_offset = 0; + 1024 900744 : discard_size = 0; + 1025 : + 1026 : /* + 1027 : * Follow Linus recommendations about fast writes. + 1028 : * + 1029 : * Linus "Unexpected splice "always copy" behavior observed" + 1030 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070 + 1031 : * --- + 1032 : * I have had _very_ good experiences with even a rather trivial + 1033 : * file writer that basically used (iirc) 8MB windows, and the logic was very + 1034 : * trivial: + 1035 : * + 1036 : * - before writing a new 8M window, do "start writeback" + 1037 : * (SYNC_FILE_RANGE_WRITE) on the previous window, and do + 1038 : * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that. + 1039 : * + 1040 : * in fact, in its simplest form, you can do it like this (this is from my + 1041 : * "overwrite disk images" program that I use on old disks): + 1042 : * + 1043 : * for (index = 0; index < max_index ;index++) { + 1044 : * if (write(fd, buffer, BUFSIZE) != BUFSIZE) + 1045 : * break; + 1046 : * // This won't block, but will start writeout asynchronously + 1047 : * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE); + 1048 : * // This does a blocking write-and-wait on any old ranges + 1049 : * if (index) + 1050 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + 1051 : * } + 1052 : * + 1053 : * and even if you don't actually do a discard (maybe we should add a + 1054 : * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate + 1055 : * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty + 1056 : * nice, because the heavy writer gets good IO performance _and_ leaves only + 1057 : * easy-to-free pages around after itself. + 1058 : * --- + 1059 : * + 1060 : * Linus "Unexpected splice "always copy" behavior observed" + 1061 : * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176 + 1062 : * --- + 1063 : * The behavior for dirty page writeback is _not_ well defined, and + 1064 : * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that + 1065 : * writeback logic, ie you do it only on ranges that you have just waited on. + 1066 : * + 1067 : * IOW, in my example, you'd couple the + 1068 : * + 1069 : * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + 1070 : * + 1071 : * with a + 1072 : * + 1073 : * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED); + 1074 : * + 1075 : * afterwards to throw out the pages that you just waited for. + 1076 : * --- + 1077 : */ 1078 : - 1079 : /* flush the second window */ - 1080 0 : flush_offset = advise->dirty_begin; - 1081 0 : flush_size = ADVISE_WINDOW_SIZE; - 1082 : } - 1083 : } else { - 1084 : /* otherwise discard the existing dirty */ - 1085 0 : discard_offset = advise->dirty_begin; - 1086 0 : discard_size = advise->dirty_end - advise->dirty_begin; - 1087 : - 1088 : /* and set the new range as dirty */ - 1089 0 : advise->dirty_begin = offset; - 1090 0 : advise->dirty_end = offset + size; - 1091 : } - 1092 4687 : break; - 1093 : } - 1094 : - 1095 : #if HAVE_SYNC_FILE_RANGE - 1096 900358 : if (flush_size != 0) { - 1097 : int ret; - 1098 : - 1099 : /* start writing immediately */ - 1100 881612 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); - 1101 881612 : if (ret != 0) { - 1102 : /* LCOV_EXCL_START */ - 1103 : return -1; - 1104 : /* LCOV_EXCL_STOP */ - 1105 : } - 1106 : } - 1107 : #endif - 1108 : - 1109 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE - 1110 900358 : if (discard_size != 0) { - 1111 : int ret; - 1112 : - 1113 : /* send the data to the disk and wait until it's written */ - 1114 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); - 1115 0 : if (ret != 0) { - 1116 : /* LCOV_EXCL_START */ - 1117 : return -1; - 1118 : /* LCOV_EXCL_STOP */ - 1119 : } - 1120 : - 1121 : /* flush the data from the cache */ - 1122 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); - 1123 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ - 1124 0 : if (ret != 0) { - 1125 : /* LCOV_EXCL_START */ - 1126 : errno = ret; /* posix_fadvise return the error code */ - 1127 : return -1; - 1128 : /* LCOV_EXCL_STOP */ - 1129 : } - 1130 : } - 1131 : #endif - 1132 : - 1133 900358 : return 0; - 1134 : } - 1135 : - 1136 8903631 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) - 1137 : { - 1138 : (void)advise; - 1139 : (void)f; - 1140 : (void)offset; - 1141 : (void)size; - 1142 : - 1143 : #if HAVE_POSIX_FADVISE - 1144 8903631 : if (advise->mode == ADVISE_DISCARD - 1145 8903983 : || advise->mode == ADVISE_DISCARD_WINDOW - 1146 : ) { - 1147 : int ret; - 1148 : - 1149 : /* flush the data from the cache */ - 1150 27482 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED); - 1151 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ - 1152 27825 : if (ret != 0) { - 1153 : /* LCOV_EXCL_START */ - 1154 : errno = ret; /* posix_fadvise return the error code */ - 1155 : return -1; - 1156 : /* LCOV_EXCL_STOP */ - 1157 : } - 1158 : } - 1159 : #endif - 1160 : - 1161 : /* - 1162 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block - 1163 : * because it may be blocking. - 1164 : * - 1165 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?" - 1166 : * https://lkml.org/lkml/2010/12/6/122 - 1167 : * --- - 1168 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same - 1169 : * way, and in fact share mostly the same code path (see - 1170 : * force_page_cache_readahead() in mm/readahead.c). - 1171 : * - 1172 : * They are asynchronous in that there is no guarantee the pages will be - 1173 : * in the page cache by the time they return. But at the same time, they - 1174 : * are not guaranteed to be non-blocking. That is, the work of doing the - 1175 : * readahead does not take place in a kernel thread. So if you try to - 1176 : * request I/O than will fit in the request queue, the system call will - 1177 : * block until some I/O is completed so that more I/O requested cam be - 1178 : * loaded onto the request queue. - 1179 : * - 1180 : * The only way to fix this would be to either put the work on a kernel - 1181 : * thread (i.e., some kind of workqueue) or in a userspace thread. For - 1182 : * ion programmer wondering what to do today, I'd suggest the - 1183 : * latter since it will be more portable across various kernel versions. - 1184 : * - 1185 : * This does leave the question about whether we should change the kernel - 1186 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be - 1187 : * non-blocking and do this work in a workqueue (or via some kind of - 1188 : * callback/continuation scheme). My worry is just doing this if a user - 1189 : * application does something crazy, like request gigabytes and gigabytes - 1190 : * of readahead, and then repents of their craziness, there should be a - 1191 : * way of cancelling the readahead request. Today, the user can just - 1192 : * kill the application. But if we simply shove the work to a kernel - 1193 : * thread, it becomes a lot harder to cancel the readahead request. We'd - 1194 : * have to invent a new API, and then have a way to know whether the user - 1195 : * has access to kill a particular readahead request, etc. - 1196 : * --- - 1197 : */ - 1198 : - 1199 8903974 : return 0; - 1200 : } - 1201 : - 1202 : /****************************************************************************/ - 1203 : /* memory */ - 1204 : - 1205 : /** - 1206 : * Total amount of memory allocated. - 1207 : */ - 1208 : static size_t mcounter; + 1079 900744 : switch (advise->mode) { + 1080 : case ADVISE_FLUSH : + 1081 882011 : flush_offset = offset; + 1082 882011 : flush_size = size; + 1083 882011 : break; + 1084 : case ADVISE_DISCARD : + 1085 0 : discard_offset = offset; + 1086 0 : discard_size = size; + 1087 0 : break; + 1088 : case ADVISE_FLUSH_WINDOW : + 1089 : /* if the dirty range can be extended */ + 1090 4687 : if (advise->dirty_end == offset) { + 1091 : /* extent the dirty range */ + 1092 4687 : advise->dirty_end += size; + 1093 : + 1094 : /* if we reached the window size */ + 1095 4687 : if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) { + 1096 : /* flush the window */ + 1097 0 : flush_offset = advise->dirty_begin; + 1098 0 : flush_size = ADVISE_WINDOW_SIZE; + 1099 : + 1100 : /* remove it from the dirty range */ + 1101 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; + 1102 : } + 1103 : } else { + 1104 : /* otherwise flush the existing dirty */ + 1105 0 : flush_offset = advise->dirty_begin; + 1106 0 : flush_size = advise->dirty_end - advise->dirty_begin; + 1107 : + 1108 : /* and set the new range as dirty */ + 1109 0 : advise->dirty_begin = offset; + 1110 0 : advise->dirty_end = offset + size; + 1111 : } + 1112 4687 : break; + 1113 : case ADVISE_DISCARD_WINDOW : + 1114 : /* if the dirty range can be extended */ + 1115 4687 : if (advise->dirty_end == offset) { + 1116 : /* extent the dirty range */ + 1117 4687 : advise->dirty_end += size; + 1118 : + 1119 : /* if we reached the double window size */ + 1120 4687 : if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) { + 1121 : /* discard the first window */ + 1122 0 : discard_offset = advise->dirty_begin; + 1123 0 : discard_size = ADVISE_WINDOW_SIZE; + 1124 : + 1125 : /* remove it from the dirty range */ + 1126 0 : advise->dirty_begin += ADVISE_WINDOW_SIZE; + 1127 : + 1128 : /* flush the second window */ + 1129 0 : flush_offset = advise->dirty_begin; + 1130 0 : flush_size = ADVISE_WINDOW_SIZE; + 1131 : } + 1132 : } else { + 1133 : /* otherwise discard the existing dirty */ + 1134 0 : discard_offset = advise->dirty_begin; + 1135 0 : discard_size = advise->dirty_end - advise->dirty_begin; + 1136 : + 1137 : /* and set the new range as dirty */ + 1138 0 : advise->dirty_begin = offset; + 1139 0 : advise->dirty_end = offset + size; + 1140 : } + 1141 4687 : break; + 1142 : } + 1143 : + 1144 : #if HAVE_SYNC_FILE_RANGE + 1145 900744 : if (flush_size != 0) { + 1146 : int ret; + 1147 : + 1148 : /* start writing immediately */ + 1149 882058 : ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); + 1150 881885 : if (ret != 0) { + 1151 : /* LCOV_EXCL_START */ + 1152 : return -1; + 1153 : /* LCOV_EXCL_STOP */ + 1154 : } + 1155 : } + 1156 : #endif + 1157 : + 1158 : #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE + 1159 900571 : if (discard_size != 0) { + 1160 : int ret; + 1161 : + 1162 : /* send the data to the disk and wait until it's written */ + 1163 0 : ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); + 1164 0 : if (ret != 0) { + 1165 : /* LCOV_EXCL_START */ + 1166 : return -1; + 1167 : /* LCOV_EXCL_STOP */ + 1168 : } + 1169 : + 1170 : /* flush the data from the cache */ + 1171 0 : ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); + 1172 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + 1173 0 : if (ret != 0) { + 1174 : /* LCOV_EXCL_START */ + 1175 : errno = ret; /* posix_fadvise return the error code */ + 1176 : return -1; + 1177 : /* LCOV_EXCL_STOP */ + 1178 : } + 1179 : } + 1180 : #endif + 1181 : + 1182 900571 : return 0; + 1183 : } + 1184 : + 1185 8897480 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) + 1186 : { + 1187 : (void)advise; + 1188 : (void)f; + 1189 : (void)offset; + 1190 : (void)size; + 1191 : + 1192 : #if HAVE_POSIX_FADVISE + 1193 8897480 : if (advise->mode == ADVISE_DISCARD + 1194 8901398 : || advise->mode == ADVISE_DISCARD_WINDOW + 1195 : ) { + 1196 : int ret; + 1197 : + 1198 : /* flush the data from the cache */ + 1199 23941 : ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED); + 1200 : /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + 1201 27801 : if (ret != 0) { + 1202 : /* LCOV_EXCL_START */ + 1203 : errno = ret; /* posix_fadvise return the error code */ + 1204 : return -1; + 1205 : /* LCOV_EXCL_STOP */ + 1206 : } + 1207 : } + 1208 : #endif 1209 : - 1210 476 : size_t malloc_counter_get(void) - 1211 : { - 1212 : size_t ret; - 1213 : - 1214 476 : lock_memory(); - 1215 : - 1216 476 : ret = mcounter; - 1217 : - 1218 476 : unlock_memory(); - 1219 : - 1220 476 : return ret; - 1221 : } - 1222 : - 1223 20173411 : void malloc_counter_inc(size_t inc) - 1224 : { - 1225 20173411 : lock_memory(); - 1226 : - 1227 20173411 : mcounter += inc; - 1228 : - 1229 20173411 : unlock_memory(); - 1230 20173411 : } - 1231 : - 1232 : /* LCOV_EXCL_START */ - 1233 : static ssize_t malloc_print(int f, const char* str) - 1234 : { - 1235 : ssize_t len = 0; - 1236 : - 1237 : while (str[len]) - 1238 : ++len; - 1239 : return write(f, str, len); - 1240 : } - 1241 : /* LCOV_EXCL_STOP */ - 1242 : - 1243 : /* LCOV_EXCL_START */ - 1244 : static ssize_t malloc_printn(int f, size_t value) - 1245 : { - 1246 : char buf[32]; - 1247 : int i; - 1248 : - 1249 : if (!value) - 1250 : return write(f, "0", 1); - 1251 : - 1252 : i = sizeof(buf); - 1253 : while (value) { - 1254 : buf[--i] = (value % 10) + '0'; - 1255 : value /= 10; - 1256 : } - 1257 : - 1258 : return write(f, buf + i, sizeof(buf) - i); - 1259 : } - 1260 : /* LCOV_EXCL_STOP */ - 1261 : - 1262 : /* LCOV_EXCL_START */ - 1263 : void malloc_fail(size_t size) - 1264 : { - 1265 : /* don't use printf to avoid any possible extra allocation */ - 1266 : int f = 2; /* stderr */ - 1267 : - 1268 : malloc_print(f, "Failed for Low Memory!\n"); - 1269 : malloc_print(f, "Allocating "); - 1270 : malloc_printn(f, size); - 1271 : malloc_print(f, " bytes.\n"); - 1272 : malloc_print(f, "Already allocated "); - 1273 : malloc_printn(f, malloc_counter_get()); - 1274 : malloc_print(f, " bytes.\n"); - 1275 : if (sizeof(void*) == 4) { - 1276 : malloc_print(f, "You are currently using a 32 bits executable.\n"); - 1277 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); - 1278 : } - 1279 : } - 1280 : /* LCOV_EXCL_STOP */ - 1281 : - 1282 14363921 : void* malloc_nofail(size_t size) + 1210 : /* + 1211 : * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block + 1212 : * because it may be blocking. + 1213 : * + 1214 : * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?" + 1215 : * https://lkml.org/lkml/2010/12/6/122 + 1216 : * --- + 1217 : * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same + 1218 : * way, and in fact share mostly the same code path (see + 1219 : * force_page_cache_readahead() in mm/readahead.c). + 1220 : * + 1221 : * They are asynchronous in that there is no guarantee the pages will be + 1222 : * in the page cache by the time they return. But at the same time, they + 1223 : * are not guaranteed to be non-blocking. That is, the work of doing the + 1224 : * readahead does not take place in a kernel thread. So if you try to + 1225 : * request I/O than will fit in the request queue, the system call will + 1226 : * block until some I/O is completed so that more I/O requested cam be + 1227 : * loaded onto the request queue. + 1228 : * + 1229 : * The only way to fix this would be to either put the work on a kernel + 1230 : * thread (i.e., some kind of workqueue) or in a userspace thread. For + 1231 : * ion programmer wondering what to do today, I'd suggest the + 1232 : * latter since it will be more portable across various kernel versions. + 1233 : * + 1234 : * This does leave the question about whether we should change the kernel + 1235 : * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be + 1236 : * non-blocking and do this work in a workqueue (or via some kind of + 1237 : * callback/continuation scheme). My worry is just doing this if a user + 1238 : * application does something crazy, like request gigabytes and gigabytes + 1239 : * of readahead, and then repents of their craziness, there should be a + 1240 : * way of cancelling the readahead request. Today, the user can just + 1241 : * kill the application. But if we simply shove the work to a kernel + 1242 : * thread, it becomes a lot harder to cancel the readahead request. We'd + 1243 : * have to invent a new API, and then have a way to know whether the user + 1244 : * has access to kill a particular readahead request, etc. + 1245 : * --- + 1246 : */ + 1247 : + 1248 8901340 : return 0; + 1249 : } + 1250 : + 1251 : /****************************************************************************/ + 1252 : /* memory */ + 1253 : + 1254 : /** + 1255 : * Total amount of memory allocated. + 1256 : */ + 1257 : static size_t mcounter; + 1258 : + 1259 476 : size_t malloc_counter_get(void) + 1260 : { + 1261 : size_t ret; + 1262 : + 1263 476 : lock_memory(); + 1264 : + 1265 476 : ret = mcounter; + 1266 : + 1267 476 : unlock_memory(); + 1268 : + 1269 476 : return ret; + 1270 : } + 1271 : + 1272 20172963 : void malloc_counter_inc(size_t inc) + 1273 : { + 1274 20172963 : lock_memory(); + 1275 : + 1276 20172963 : mcounter += inc; + 1277 : + 1278 20172963 : unlock_memory(); + 1279 20172963 : } + 1280 : + 1281 : /* LCOV_EXCL_START */ + 1282 : static ssize_t malloc_print(int f, const char* str) 1283 : { - 1284 14363921 : void* ptr = malloc(size); + 1284 : ssize_t len = 0; 1285 : - 1286 14363921 : if (!ptr) { - 1287 : /* LCOV_EXCL_START */ - 1288 : malloc_fail(size); - 1289 : exit(EXIT_FAILURE); - 1290 : /* LCOV_EXCL_STOP */ - 1291 : } - 1292 : - 1293 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ - 1294 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ - 1295 : /* and not only reserving the addressable space. */ - 1296 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ - 1297 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ - 1298 : /* get a real error from malloc() instead than a process killed. */ - 1299 : /* Note that calloc() doesn't have the same effect. */ - 1300 14363921 : memset(ptr, 0xA5, size); - 1301 : #endif - 1302 : - 1303 14363921 : malloc_counter_inc(size); - 1304 : - 1305 14363921 : return ptr; - 1306 : } - 1307 : - 1308 10089 : void* calloc_nofail(size_t count, size_t size) - 1309 : { - 1310 : void* ptr; - 1311 : - 1312 10089 : size *= count; - 1313 : - 1314 : /* see the note in malloc_nofail() of why we don't use calloc() */ - 1315 10089 : ptr = malloc(size); + 1286 : while (str[len]) + 1287 : ++len; + 1288 : return write(f, str, len); + 1289 : } + 1290 : /* LCOV_EXCL_STOP */ + 1291 : + 1292 : /* LCOV_EXCL_START */ + 1293 : static ssize_t malloc_printn(int f, size_t value) + 1294 : { + 1295 : char buf[32]; + 1296 : int i; + 1297 : + 1298 : if (!value) + 1299 : return write(f, "0", 1); + 1300 : + 1301 : i = sizeof(buf); + 1302 : while (value) { + 1303 : buf[--i] = (value % 10) + '0'; + 1304 : value /= 10; + 1305 : } + 1306 : + 1307 : return write(f, buf + i, sizeof(buf) - i); + 1308 : } + 1309 : /* LCOV_EXCL_STOP */ + 1310 : + 1311 : /* LCOV_EXCL_START */ + 1312 : void malloc_fail(size_t size) + 1313 : { + 1314 : /* don't use printf to avoid any possible extra allocation */ + 1315 : int f = 2; /* stderr */ 1316 : - 1317 10089 : if (!ptr) { - 1318 : /* LCOV_EXCL_START */ - 1319 : malloc_fail(size); - 1320 : exit(EXIT_FAILURE); - 1321 : /* LCOV_EXCL_STOP */ - 1322 : } - 1323 : - 1324 10089 : memset(ptr, 0, size); - 1325 : - 1326 10089 : malloc_counter_inc(size); - 1327 : - 1328 10089 : return ptr; - 1329 : } + 1317 : malloc_print(f, "Failed for Low Memory!\n"); + 1318 : malloc_print(f, "Allocating "); + 1319 : malloc_printn(f, size); + 1320 : malloc_print(f, " bytes.\n"); + 1321 : malloc_print(f, "Already allocated "); + 1322 : malloc_printn(f, malloc_counter_get()); + 1323 : malloc_print(f, " bytes.\n"); + 1324 : if (sizeof(void*) == 4) { + 1325 : malloc_print(f, "You are currently using a 32 bits executable.\n"); + 1326 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); + 1327 : } + 1328 : } + 1329 : /* LCOV_EXCL_STOP */ 1330 : - 1331 5799401 : char* strdup_nofail(const char* str) + 1331 14363716 : void* malloc_nofail(size_t size) 1332 : { - 1333 : size_t size; - 1334 : char* ptr; - 1335 : - 1336 5799401 : size = strlen(str) + 1; - 1337 : - 1338 5799401 : ptr = malloc(size); - 1339 : - 1340 5799401 : if (!ptr) { - 1341 : /* LCOV_EXCL_START */ - 1342 : malloc_fail(size); - 1343 : exit(EXIT_FAILURE); - 1344 : /* LCOV_EXCL_STOP */ - 1345 : } - 1346 : - 1347 5799401 : memcpy(ptr, str, size); - 1348 : - 1349 5799401 : malloc_counter_inc(size); - 1350 : - 1351 5799401 : return ptr; - 1352 : } + 1333 14363716 : void* ptr = malloc(size); + 1334 : + 1335 14363716 : if (!ptr) { + 1336 : /* LCOV_EXCL_START */ + 1337 : malloc_fail(size); + 1338 : exit(EXIT_FAILURE); + 1339 : /* LCOV_EXCL_STOP */ + 1340 : } + 1341 : + 1342 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ + 1343 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ + 1344 : /* and not only reserving the addressable space. */ + 1345 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ + 1346 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ + 1347 : /* get a real error from malloc() instead than a process killed. */ + 1348 : /* Note that calloc() doesn't have the same effect. */ + 1349 14363716 : memset(ptr, 0xA5, size); + 1350 : #endif + 1351 : + 1352 14363716 : malloc_counter_inc(size); 1353 : - 1354 : /****************************************************************************/ - 1355 : /* smartctl */ + 1354 14363716 : return ptr; + 1355 : } 1356 : - 1357 : /** - 1358 : * Match a string with the specified pattern. - 1359 : * Like sscanf() a space match any sequence of spaces. - 1360 : * Return 0 if it matches. - 1361 : */ - 1362 0 : static int smatch(const char* str, const char* pattern) - 1363 : { - 1364 0 : while (*pattern) { - 1365 0 : if (isspace(*pattern)) { - 1366 0 : ++pattern; - 1367 0 : while (isspace(*str)) - 1368 0 : ++str; - 1369 0 : } else if (*pattern == *str) { - 1370 0 : ++pattern; - 1371 0 : ++str; - 1372 : } else - 1373 0 : return -1; - 1374 : } - 1375 : - 1376 0 : return 0; - 1377 : } - 1378 : - 1379 43 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model) - 1380 : { - 1381 : unsigned i; - 1382 : int inside; - 1383 : - 1384 : /* preclear attribute */ - 1385 43 : *serial = 0; - 1386 11223 : for (i = 0; i < SMART_COUNT; ++i) - 1387 11180 : smart[i] = SMART_UNASSIGNED; + 1357 10089 : void* calloc_nofail(size_t count, size_t size) + 1358 : { + 1359 : void* ptr; + 1360 : + 1361 10089 : size *= count; + 1362 : + 1363 : /* see the note in malloc_nofail() of why we don't use calloc() */ + 1364 10089 : ptr = malloc(size); + 1365 : + 1366 10089 : if (!ptr) { + 1367 : /* LCOV_EXCL_START */ + 1368 : malloc_fail(size); + 1369 : exit(EXIT_FAILURE); + 1370 : /* LCOV_EXCL_STOP */ + 1371 : } + 1372 : + 1373 10089 : memset(ptr, 0, size); + 1374 : + 1375 10089 : malloc_counter_inc(size); + 1376 : + 1377 10089 : return ptr; + 1378 : } + 1379 : + 1380 5799158 : char* strdup_nofail(const char* str) + 1381 : { + 1382 : size_t size; + 1383 : char* ptr; + 1384 : + 1385 5799158 : size = strlen(str) + 1; + 1386 : + 1387 5799158 : ptr = malloc(size); 1388 : - 1389 : /* read the file */ - 1390 43 : inside = 0; - 1391 : while (1) { - 1392 : char buf[256]; - 1393 : unsigned id; - 1394 : uint64_t raw; - 1395 : char* s; - 1396 : - 1397 43 : s = fgets(buf, sizeof(buf), f); - 1398 43 : if (s == 0) - 1399 43 : break; - 1400 : - 1401 : /* remove extraneous chars */ - 1402 0 : s = strpolish(buf); - 1403 : - 1404 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 1389 5799158 : if (!ptr) { + 1390 : /* LCOV_EXCL_START */ + 1391 : malloc_fail(size); + 1392 : exit(EXIT_FAILURE); + 1393 : /* LCOV_EXCL_STOP */ + 1394 : } + 1395 : + 1396 5799158 : memcpy(ptr, str, size); + 1397 : + 1398 5799158 : malloc_counter_inc(size); + 1399 : + 1400 5799158 : return ptr; + 1401 : } + 1402 : + 1403 : /****************************************************************************/ + 1404 : /* smartctl */ 1405 : - 1406 : /* skip initial spaces */ - 1407 0 : while (isspace(*s)) - 1408 0 : ++s; - 1409 : - 1410 0 : if (*s == 0) { - 1411 0 : inside = 0; - 1412 : /* common */ - 1413 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { - 1414 0 : smart[SMART_ROTATION_RATE] = 0; - 1415 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) { - 1416 0 : } else if (smatch(s, "User Capacity:") == 0) { - 1417 0 : char* begin = strchr(s, ':'); - 1418 0 : char* end = strstr(s, "bytes"); - 1419 0 : if (begin != 0 && end != 0 && begin < end) { - 1420 : char* p; - 1421 0 : smart[SMART_SIZE] = 0; - 1422 0 : for (p = begin; p != end; ++p) { - 1423 0 : if (isdigit(*p)) { - 1424 0 : smart[SMART_SIZE] *= 10; - 1425 0 : smart[SMART_SIZE] += *p - '0'; - 1426 : } - 1427 : } - 1428 : } - 1429 0 : } else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) { - 1430 0 : } else if (sscanf(s, "Device Model: %63s", model) == 1) { - 1431 : /* SCSI */ - 1432 0 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */ - 1433 0 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) { - 1434 0 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) { - 1435 0 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) { - 1436 0 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) { - 1437 0 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) { - 1438 0 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) { - 1439 : /* ATA */ - 1440 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { - 1441 0 : } else if (smatch(s, "ID#") == 0) { - 1442 0 : inside = 1; - 1443 0 : } else if (smatch(s, "No Errors Logged") == 0) { - 1444 0 : smart[SMART_ERROR] = 0; - 1445 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - 1446 0 : smart[SMART_ERROR] = raw; - 1447 0 : } else if (inside) { - 1448 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { - 1449 : /* LCOV_EXCL_START */ - 1450 : log_fatal("Invalid smartctl line '%s'.\n", s); - 1451 : return -1; - 1452 : /* LCOV_EXCL_STOP */ - 1453 : } + 1406 : /** + 1407 : * Match a string with the specified pattern. + 1408 : * Like sscanf() a space match any sequence of spaces. + 1409 : * Return 0 if it matches. + 1410 : */ + 1411 0 : static int smatch(const char* str, const char* pattern) + 1412 : { + 1413 0 : while (*pattern) { + 1414 0 : if (isspace(*pattern)) { + 1415 0 : ++pattern; + 1416 0 : while (isspace(*str)) + 1417 0 : ++str; + 1418 0 : } else if (*pattern == *str) { + 1419 0 : ++pattern; + 1420 0 : ++str; + 1421 : } else + 1422 0 : return -1; + 1423 : } + 1424 : + 1425 0 : return 0; + 1426 : } + 1427 : + 1428 43 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model) + 1429 : { + 1430 : unsigned i; + 1431 : int inside; + 1432 : + 1433 : /* preclear attribute */ + 1434 43 : *serial = 0; + 1435 11223 : for (i = 0; i < SMART_COUNT; ++i) + 1436 11180 : smart[i] = SMART_UNASSIGNED; + 1437 : + 1438 : /* read the file */ + 1439 43 : inside = 0; + 1440 : while (1) { + 1441 : char buf[256]; + 1442 : unsigned id; + 1443 : uint64_t raw; + 1444 : char* s; + 1445 : + 1446 43 : s = fgets(buf, sizeof(buf), f); + 1447 42 : if (s == 0) + 1448 42 : break; + 1449 : + 1450 : /* remove extraneous chars */ + 1451 0 : s = strpolish(buf); + 1452 : + 1453 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); 1454 : - 1455 0 : if (id >= 256) { - 1456 : /* LCOV_EXCL_START */ - 1457 : log_fatal("Invalid SMART id '%u'.\n", id); - 1458 : return -1; - 1459 : /* LCOV_EXCL_STOP */ - 1460 : } - 1461 : - 1462 0 : smart[id] = raw; - 1463 : } - 1464 0 : } - 1465 : - 1466 43 : return 0; - 1467 : } - 1468 : - 1469 5 : int smartctl_flush(FILE* f, const char* file, const char* name) - 1470 : { - 1471 : /* read the file */ - 1472 : while (1) { - 1473 : char buf[256]; - 1474 : char* s; - 1475 : - 1476 5 : s = fgets(buf, sizeof(buf), f); - 1477 5 : if (s == 0) - 1478 5 : break; - 1479 : - 1480 : /* remove extraneous chars */ - 1481 0 : s = strpolish(buf); - 1482 : - 1483 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); - 1484 0 : } - 1485 : - 1486 10 : return 0; - 1487 : } - 1488 : - 1489 : /****************************************************************************/ - 1490 : /* thread */ - 1491 : - 1492 : #if HAVE_PTHREAD - 1493 2284 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr) - 1494 : { - 1495 2284 : if (pthread_mutex_init(mutex, attr) != 0) { - 1496 : /* LCOV_EXCL_START */ - 1497 : log_fatal("Failed call to pthread_mutex_init().\n"); - 1498 : os_abort(); - 1499 : /* LCOV_EXCL_STOP */ - 1500 : } - 1501 2284 : } - 1502 : - 1503 2082 : void thread_mutex_destroy(pthread_mutex_t* mutex) - 1504 : { - 1505 2082 : if (pthread_mutex_destroy(mutex) != 0) { - 1506 : /* LCOV_EXCL_START */ - 1507 : log_fatal("Failed call to pthread_mutex_destroy().\n"); - 1508 : os_abort(); - 1509 : /* LCOV_EXCL_STOP */ - 1510 : } - 1511 2082 : } - 1512 : - 1513 80857668 : void thread_mutex_lock(pthread_mutex_t* mutex) - 1514 : { - 1515 80857668 : if (pthread_mutex_lock(mutex) != 0) { - 1516 : /* LCOV_EXCL_START */ - 1517 : log_fatal("Failed call to pthread_mutex_lock().\n"); - 1518 : os_abort(); - 1519 : /* LCOV_EXCL_STOP */ - 1520 : } - 1521 80860507 : } - 1522 : - 1523 80858701 : void thread_mutex_unlock(pthread_mutex_t* mutex) - 1524 : { - 1525 80858701 : if (pthread_mutex_unlock(mutex) != 0) { - 1526 : /* LCOV_EXCL_START */ - 1527 : log_fatal("Failed call to pthread_mutex_unlock().\n"); - 1528 : os_abort(); - 1529 : /* LCOV_EXCL_STOP */ - 1530 : } - 1531 80861909 : } - 1532 : - 1533 380 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr) - 1534 : { - 1535 380 : if (pthread_cond_init(cond, attr) != 0) { - 1536 : /* LCOV_EXCL_START */ - 1537 : log_fatal("Failed call to pthread_cond_init().\n"); - 1538 : os_abort(); - 1539 : /* LCOV_EXCL_STOP */ - 1540 : } - 1541 380 : } - 1542 : - 1543 380 : void thread_cond_destroy(pthread_cond_t* cond) - 1544 : { - 1545 380 : if (pthread_cond_destroy(cond) != 0) { - 1546 : /* LCOV_EXCL_START */ - 1547 : log_fatal("Failed call to pthread_cond_destroy().\n"); - 1548 : os_abort(); - 1549 : /* LCOV_EXCL_STOP */ - 1550 : } - 1551 380 : } - 1552 : - 1553 85887 : void thread_cond_signal(pthread_cond_t* cond) - 1554 : { - 1555 85887 : if (pthread_cond_signal(cond) != 0) { - 1556 : /* LCOV_EXCL_START */ - 1557 : log_fatal("Failed call to pthread_cond_signal().\n"); - 1558 : os_abort(); - 1559 : /* LCOV_EXCL_STOP */ - 1560 : } - 1561 85887 : } - 1562 : - 1563 255503 : void thread_cond_broadcast(pthread_cond_t* cond) - 1564 : { - 1565 255503 : if (pthread_cond_broadcast(cond) != 0) { - 1566 : /* LCOV_EXCL_START */ - 1567 : log_fatal("Failed call to pthread_cond_broadcast().\n"); - 1568 : os_abort(); - 1569 : /* LCOV_EXCL_STOP */ - 1570 : } - 1571 255503 : } - 1572 : - 1573 1037153 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) - 1574 : { - 1575 1037153 : if (pthread_cond_wait(cond, mutex) != 0) { - 1576 : /* LCOV_EXCL_START */ - 1577 : log_fatal("Failed call to pthread_cond_wait().\n"); - 1578 : os_abort(); - 1579 : /* LCOV_EXCL_STOP */ - 1580 : } - 1581 1037153 : } - 1582 : - 1583 : /** - 1584 : * Implementation note about conditional variables. - 1585 : * - 1586 : * The conditional variables can be signaled inside or ouside the mutex, - 1587 : * what is better it's debatable but in general doing that ouside the mutex, - 1588 : * reduces the number of context switches. - 1589 : * - 1590 : * But when when testing with helgrind and drd, this disallows such tools to - 1591 : * to see the dependency between the signal and the wait. - 1592 : * - 1593 : * To avoid it we signal everything inside the mutex. And we do this in both - 1594 : * test mode (with CHERCKER defined) and release mode (CHECKER not defined), - 1595 : * to be on the safe side and avoid any difference in beaviour between test and - 1596 : * release. - 1597 : * - 1598 : * Here some interesting discussion: - 1599 : * - 1600 : * Condvars: signal with mutex locked or not? - 1601 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ - 1602 : * - 1603 : * Calling pthread_cond_signal without locking mutex - 1604 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494 - 1605 : */ - 1606 : - 1607 : /** - 1608 : * Control when to signal the condition variables. - 1609 : */ - 1610 : int thread_cond_signal_outside = 0; + 1455 : /* skip initial spaces */ + 1456 0 : while (isspace(*s)) + 1457 0 : ++s; + 1458 : + 1459 0 : if (*s == 0) { + 1460 0 : inside = 0; + 1461 : /* common */ + 1462 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { + 1463 0 : smart[SMART_ROTATION_RATE] = 0; + 1464 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) { + 1465 0 : } else if (smatch(s, "User Capacity:") == 0) { + 1466 0 : char* begin = strchr(s, ':'); + 1467 0 : char* end = strstr(s, "bytes"); + 1468 0 : if (begin != 0 && end != 0 && begin < end) { + 1469 : char* p; + 1470 0 : smart[SMART_SIZE] = 0; + 1471 0 : for (p = begin; p != end; ++p) { + 1472 0 : if (isdigit(*p)) { + 1473 0 : smart[SMART_SIZE] *= 10; + 1474 0 : smart[SMART_SIZE] += *p - '0'; + 1475 : } + 1476 : } + 1477 : } + 1478 0 : } else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) { + 1479 0 : } else if (sscanf(s, "Device Model: %63s", model) == 1) { + 1480 : /* SCSI */ + 1481 0 : } else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */ + 1482 0 : } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) { + 1483 0 : } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) { + 1484 0 : } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) { + 1485 0 : } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) { + 1486 0 : } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) { + 1487 0 : } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) { + 1488 : /* ATA */ + 1489 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { + 1490 0 : } else if (smatch(s, "ID#") == 0) { + 1491 0 : inside = 1; + 1492 0 : } else if (smatch(s, "No Errors Logged") == 0) { + 1493 0 : smart[SMART_ERROR] = 0; + 1494 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { + 1495 0 : smart[SMART_ERROR] = raw; + 1496 0 : } else if (inside) { + 1497 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { + 1498 : /* LCOV_EXCL_START */ + 1499 : log_fatal("Invalid smartctl line '%s'.\n", s); + 1500 : return -1; + 1501 : /* LCOV_EXCL_STOP */ + 1502 : } + 1503 : + 1504 0 : if (id >= 256) { + 1505 : /* LCOV_EXCL_START */ + 1506 : log_fatal("Invalid SMART id '%u'.\n", id); + 1507 : return -1; + 1508 : /* LCOV_EXCL_STOP */ + 1509 : } + 1510 : + 1511 0 : smart[id] = raw; + 1512 : } + 1513 0 : } + 1514 : + 1515 42 : return 0; + 1516 : } + 1517 : + 1518 5 : int smartctl_flush(FILE* f, const char* file, const char* name) + 1519 : { + 1520 : /* read the file */ + 1521 : while (1) { + 1522 : char buf[256]; + 1523 : char* s; + 1524 : + 1525 5 : s = fgets(buf, sizeof(buf), f); + 1526 5 : if (s == 0) + 1527 5 : break; + 1528 : + 1529 : /* remove extraneous chars */ + 1530 0 : s = strpolish(buf); + 1531 : + 1532 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 1533 0 : } + 1534 : + 1535 10 : return 0; + 1536 : } + 1537 : + 1538 : /****************************************************************************/ + 1539 : /* thread */ + 1540 : + 1541 : #if HAVE_PTHREAD + 1542 2284 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr) + 1543 : { + 1544 2284 : if (pthread_mutex_init(mutex, attr) != 0) { + 1545 : /* LCOV_EXCL_START */ + 1546 : log_fatal("Failed call to pthread_mutex_init().\n"); + 1547 : os_abort(); + 1548 : /* LCOV_EXCL_STOP */ + 1549 : } + 1550 2284 : } + 1551 : + 1552 2082 : void thread_mutex_destroy(pthread_mutex_t* mutex) + 1553 : { + 1554 2082 : if (pthread_mutex_destroy(mutex) != 0) { + 1555 : /* LCOV_EXCL_START */ + 1556 : log_fatal("Failed call to pthread_mutex_destroy().\n"); + 1557 : os_abort(); + 1558 : /* LCOV_EXCL_STOP */ + 1559 : } + 1560 2082 : } + 1561 : + 1562 80853862 : void thread_mutex_lock(pthread_mutex_t* mutex) + 1563 : { + 1564 80853862 : if (pthread_mutex_lock(mutex) != 0) { + 1565 : /* LCOV_EXCL_START */ + 1566 : log_fatal("Failed call to pthread_mutex_lock().\n"); + 1567 : os_abort(); + 1568 : /* LCOV_EXCL_STOP */ + 1569 : } + 1570 80869808 : } + 1571 : + 1572 80868352 : void thread_mutex_unlock(pthread_mutex_t* mutex) + 1573 : { + 1574 80868352 : if (pthread_mutex_unlock(mutex) != 0) { + 1575 : /* LCOV_EXCL_START */ + 1576 : log_fatal("Failed call to pthread_mutex_unlock().\n"); + 1577 : os_abort(); + 1578 : /* LCOV_EXCL_STOP */ + 1579 : } + 1580 80867931 : } + 1581 : + 1582 380 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr) + 1583 : { + 1584 380 : if (pthread_cond_init(cond, attr) != 0) { + 1585 : /* LCOV_EXCL_START */ + 1586 : log_fatal("Failed call to pthread_cond_init().\n"); + 1587 : os_abort(); + 1588 : /* LCOV_EXCL_STOP */ + 1589 : } + 1590 380 : } + 1591 : + 1592 380 : void thread_cond_destroy(pthread_cond_t* cond) + 1593 : { + 1594 380 : if (pthread_cond_destroy(cond) != 0) { + 1595 : /* LCOV_EXCL_START */ + 1596 : log_fatal("Failed call to pthread_cond_destroy().\n"); + 1597 : os_abort(); + 1598 : /* LCOV_EXCL_STOP */ + 1599 : } + 1600 380 : } + 1601 : + 1602 87081 : void thread_cond_signal(pthread_cond_t* cond) + 1603 : { + 1604 87081 : if (pthread_cond_signal(cond) != 0) { + 1605 : /* LCOV_EXCL_START */ + 1606 : log_fatal("Failed call to pthread_cond_signal().\n"); + 1607 : os_abort(); + 1608 : /* LCOV_EXCL_STOP */ + 1609 : } + 1610 87081 : } 1611 : - 1612 85887 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) + 1612 255615 : void thread_cond_broadcast(pthread_cond_t* cond) 1613 : { - 1614 85887 : if (thread_cond_signal_outside) { - 1615 : /* without the thread checker unlock before signaling, */ - 1616 : /* this reduces the number of context switches */ - 1617 0 : thread_mutex_unlock(mutex); - 1618 : } - 1619 : - 1620 85887 : thread_cond_signal(cond); + 1614 255615 : if (pthread_cond_broadcast(cond) != 0) { + 1615 : /* LCOV_EXCL_START */ + 1616 : log_fatal("Failed call to pthread_cond_broadcast().\n"); + 1617 : os_abort(); + 1618 : /* LCOV_EXCL_STOP */ + 1619 : } + 1620 255615 : } 1621 : - 1622 85887 : if (!thread_cond_signal_outside) { - 1623 : /* with the thread checker unlock after signaling */ - 1624 : /* to make explicit the condition and mutex relation */ - 1625 85887 : thread_mutex_unlock(mutex); - 1626 : } - 1627 85887 : } - 1628 : - 1629 255313 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) - 1630 : { - 1631 255313 : if (thread_cond_signal_outside) { - 1632 : /* without the thread checker unlock before signaling, */ - 1633 : /* this reduces the number of context switches */ - 1634 0 : thread_mutex_unlock(mutex); - 1635 : } - 1636 : - 1637 255313 : thread_cond_broadcast(cond); - 1638 : - 1639 255313 : if (!thread_cond_signal_outside) { - 1640 : /* with the thread checker unlock after signaling */ - 1641 : /* to make explicit the condition and mutex relation */ - 1642 255313 : thread_mutex_unlock(mutex); - 1643 : } - 1644 255313 : } - 1645 : - 1646 2200 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg) - 1647 : { - 1648 2200 : if (pthread_create(thread, attr, func, arg) != 0) { - 1649 : /* LCOV_EXCL_START */ - 1650 : log_fatal("Failed call to pthread_create().\n"); - 1651 : os_abort(); - 1652 : /* LCOV_EXCL_STOP */ - 1653 : } - 1654 2200 : } + 1622 1125039 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) + 1623 : { + 1624 1125039 : if (pthread_cond_wait(cond, mutex) != 0) { + 1625 : /* LCOV_EXCL_START */ + 1626 : log_fatal("Failed call to pthread_cond_wait().\n"); + 1627 : os_abort(); + 1628 : /* LCOV_EXCL_STOP */ + 1629 : } + 1630 1125039 : } + 1631 : + 1632 : /** + 1633 : * Implementation note about conditional variables. + 1634 : * + 1635 : * The conditional variables can be signaled inside or ouside the mutex, + 1636 : * what is better it's debatable but in general doing that ouside the mutex, + 1637 : * reduces the number of context switches. + 1638 : * + 1639 : * But when when testing with helgrind and drd, this disallows such tools to + 1640 : * to see the dependency between the signal and the wait. + 1641 : * + 1642 : * To avoid it we signal everything inside the mutex. And we do this in both + 1643 : * test mode (with CHERCKER defined) and release mode (CHECKER not defined), + 1644 : * to be on the safe side and avoid any difference in beaviour between test and + 1645 : * release. + 1646 : * + 1647 : * Here some interesting discussion: + 1648 : * + 1649 : * Condvars: signal with mutex locked or not? + 1650 : * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ + 1651 : * + 1652 : * Calling pthread_cond_signal without locking mutex + 1653 : * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494 + 1654 : */ 1655 : - 1656 2200 : void thread_join(pthread_t thread, void** retval) - 1657 : { - 1658 2200 : if (pthread_join(thread, retval) != 0) { - 1659 : /* LCOV_EXCL_START */ - 1660 : log_fatal("Failed call to pthread_join().\n"); - 1661 : os_abort(); - 1662 : /* LCOV_EXCL_STOP */ - 1663 : } - 1664 2200 : } - 1665 : - 1666 : #endif - 1667 : + 1656 : /** + 1657 : * Control when to signal the condition variables. + 1658 : */ + 1659 : int thread_cond_signal_outside = 0; + 1660 : + 1661 87081 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) + 1662 : { + 1663 87081 : if (thread_cond_signal_outside) { + 1664 : /* without the thread checker unlock before signaling, */ + 1665 : /* this reduces the number of context switches */ + 1666 0 : thread_mutex_unlock(mutex); + 1667 : } + 1668 : + 1669 87081 : thread_cond_signal(cond); + 1670 : + 1671 87081 : if (!thread_cond_signal_outside) { + 1672 : /* with the thread checker unlock after signaling */ + 1673 : /* to make explicit the condition and mutex relation */ + 1674 87081 : thread_mutex_unlock(mutex); + 1675 : } + 1676 87081 : } + 1677 : + 1678 255425 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) + 1679 : { + 1680 255425 : if (thread_cond_signal_outside) { + 1681 : /* without the thread checker unlock before signaling, */ + 1682 : /* this reduces the number of context switches */ + 1683 0 : thread_mutex_unlock(mutex); + 1684 : } + 1685 : + 1686 255425 : thread_cond_broadcast(cond); + 1687 : + 1688 255425 : if (!thread_cond_signal_outside) { + 1689 : /* with the thread checker unlock after signaling */ + 1690 : /* to make explicit the condition and mutex relation */ + 1691 255425 : thread_mutex_unlock(mutex); + 1692 : } + 1693 255425 : } + 1694 : + 1695 2200 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg) + 1696 : { + 1697 2200 : if (pthread_create(thread, attr, func, arg) != 0) { + 1698 : /* LCOV_EXCL_START */ + 1699 : log_fatal("Failed call to pthread_create().\n"); + 1700 : os_abort(); + 1701 : /* LCOV_EXCL_STOP */ + 1702 : } + 1703 2200 : } + 1704 : + 1705 2200 : void thread_join(pthread_t thread, void** retval) + 1706 : { + 1707 2200 : if (pthread_join(thread, retval) != 0) { + 1708 : /* LCOV_EXCL_START */ + 1709 : log_fatal("Failed call to pthread_join().\n"); + 1710 : os_abort(); + 1711 : /* LCOV_EXCL_STOP */ + 1712 : } + 1713 2200 : } + 1714 : + 1715 : #endif + 1716 : diff --git a/cov/cmdline/support.h.func-sort-c.html b/cov/cmdline/support.h.func-sort-c.html index 72186336..6a3d8670 100644 --- a/cov/cmdline/support.h.func-sort-c.html +++ b/cov/cmdline/support.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ esc_shell - 331854 + 332092
diff --git a/cov/cmdline/support.h.func.html b/cov/cmdline/support.h.func.html index 4d39d629..5d667b6c 100644 --- a/cov/cmdline/support.h.func.html +++ b/cov/cmdline/support.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ esc_shell - 331854 + 332092
diff --git a/cov/cmdline/support.h.gcov.html b/cov/cmdline/support.h.gcov.html index 48fbc42d..2951cbc8 100644 --- a/cov/cmdline/support.h.gcov.html +++ b/cov/cmdline/support.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -291,9 +291,9 @@ 229 : * \param buffer Preallocated buffer of ESC_MAX size. 230 : */ 231 : const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer); - 232 331854 : static inline const char* esc_shell(const char* str, char* buffer) + 232 332092 : static inline const char* esc_shell(const char* str, char* buffer) 233 : { - 234 331854 : return esc_shell_multi(&str, 1, buffer); + 234 332092 : return esc_shell_multi(&str, 1, buffer); 235 : } 236 : 237 : /** @@ -384,113 +384,119 @@ 322 : */ 323 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec); 324 : - 325 : /****************************************************************************/ - 326 : /* advise */ - 327 : - 328 : /** - 329 : * Advise modes. - 330 : */ - 331 : #define ADVISE_DEFAULT 0 /**< Default mode. */ - 332 : #define ADVISE_NONE 1 /**< Bare read/write mode. */ - 333 : #define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */ - 334 : #define ADVISE_FLUSH 3 /**< Flush mode. */ - 335 : #define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */ - 336 : #define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */ - 337 : #define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */ - 338 : #define ADVISE_DIRECT 7 /**< Direct mode. */ - 339 : - 340 : #define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */ - 341 : - 342 : struct advise_struct { - 343 : int mode; - 344 : data_off_t dirty_begin; - 345 : data_off_t dirty_end; - 346 : }; + 325 : /** + 326 : * Change the modification time of a file or link. + 327 : * Note that links are NOT deferenced. + 328 : */ + 329 : int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec); + 330 : + 331 : /****************************************************************************/ + 332 : /* advise */ + 333 : + 334 : /** + 335 : * Advise modes. + 336 : */ + 337 : #define ADVISE_DEFAULT 0 /**< Default mode. */ + 338 : #define ADVISE_NONE 1 /**< Bare read/write mode. */ + 339 : #define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */ + 340 : #define ADVISE_FLUSH 3 /**< Flush mode. */ + 341 : #define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */ + 342 : #define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */ + 343 : #define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */ + 344 : #define ADVISE_DIRECT 7 /**< Direct mode. */ + 345 : + 346 : #define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */ 347 : - 348 : void advise_init(struct advise_struct* advise, int mode); - 349 : int advise_flags(struct advise_struct* advise); - 350 : int advise_open(struct advise_struct* advise, int f); - 351 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); - 352 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); + 348 : struct advise_struct { + 349 : int mode; + 350 : data_off_t dirty_begin; + 351 : data_off_t dirty_end; + 352 : }; 353 : - 354 : /****************************************************************************/ - 355 : /* memory */ - 356 : - 357 : /** - 358 : * Return the size of the allocated memory. - 359 : */ - 360 : size_t malloc_counter_get(void); - 361 : - 362 : /** - 363 : * Safe malloc. - 364 : * If no memory is available, it aborts. + 354 : void advise_init(struct advise_struct* advise, int mode); + 355 : int advise_flags(struct advise_struct* advise); + 356 : int advise_open(struct advise_struct* advise, int f); + 357 : int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); + 358 : int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); + 359 : + 360 : /****************************************************************************/ + 361 : /* memory */ + 362 : + 363 : /** + 364 : * Return the size of the allocated memory. 365 : */ - 366 : void* malloc_nofail(size_t size); + 366 : size_t malloc_counter_get(void); 367 : 368 : /** - 369 : * Safe cmalloc. + 369 : * Safe malloc. 370 : * If no memory is available, it aborts. 371 : */ - 372 : void* calloc_nofail(size_t count, size_t size); + 372 : void* malloc_nofail(size_t size); 373 : 374 : /** - 375 : * Safe strdup. + 375 : * Safe cmalloc. 376 : * If no memory is available, it aborts. 377 : */ - 378 : char* strdup_nofail(const char* str); + 378 : void* calloc_nofail(size_t count, size_t size); 379 : 380 : /** - 381 : * Helper for printing an error about a failed allocation. - 382 : */ - 383 : void malloc_fail(size_t size); - 384 : - 385 : /****************************************************************************/ - 386 : /* smartctl */ - 387 : - 388 : /** - 389 : * Read smartctl attributes from a stream. - 390 : * Return 0 on success. - 391 : */ - 392 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model); + 381 : * Safe strdup. + 382 : * If no memory is available, it aborts. + 383 : */ + 384 : char* strdup_nofail(const char* str); + 385 : + 386 : /** + 387 : * Helper for printing an error about a failed allocation. + 388 : */ + 389 : void malloc_fail(size_t size); + 390 : + 391 : /****************************************************************************/ + 392 : /* smartctl */ 393 : 394 : /** - 395 : * Flush smartctl output from a stream. - 396 : */ - 397 : int smartctl_flush(FILE* f, const char* file, const char* name); - 398 : - 399 : /****************************************************************************/ - 400 : /* thread */ - 401 : - 402 : #if HAVE_PTHREAD - 403 : /** - 404 : * Control when to signal the condition variables. - 405 : * - 406 : * Default is inside the mutex. - 407 : * - 408 : * Ensure to change that before starting any thread. - 409 : */ - 410 : int thread_cond_signal_outside; - 411 : - 412 : /** - 413 : * Thread wrappers to handle error conditions. - 414 : */ - 415 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr); - 416 : void thread_mutex_destroy(pthread_mutex_t* mutex); - 417 : void thread_mutex_lock(pthread_mutex_t* mutex); - 418 : void thread_mutex_unlock(pthread_mutex_t* mutex); - 419 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr); - 420 : void thread_cond_destroy(pthread_cond_t* cond); - 421 : void thread_cond_signal(pthread_cond_t* cond); - 422 : void thread_cond_broadcast(pthread_cond_t* cond); - 423 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex); - 424 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); - 425 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); - 426 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg); - 427 : void thread_join(pthread_t thread, void** retval); - 428 : #endif - 429 : - 430 : #endif - 431 : + 395 : * Read smartctl attributes from a stream. + 396 : * Return 0 on success. + 397 : */ + 398 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model); + 399 : + 400 : /** + 401 : * Flush smartctl output from a stream. + 402 : */ + 403 : int smartctl_flush(FILE* f, const char* file, const char* name); + 404 : + 405 : /****************************************************************************/ + 406 : /* thread */ + 407 : + 408 : #if HAVE_PTHREAD + 409 : /** + 410 : * Control when to signal the condition variables. + 411 : * + 412 : * Default is inside the mutex. + 413 : * + 414 : * Ensure to change that before starting any thread. + 415 : */ + 416 : int thread_cond_signal_outside; + 417 : + 418 : /** + 419 : * Thread wrappers to handle error conditions. + 420 : */ + 421 : void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr); + 422 : void thread_mutex_destroy(pthread_mutex_t* mutex); + 423 : void thread_mutex_lock(pthread_mutex_t* mutex); + 424 : void thread_mutex_unlock(pthread_mutex_t* mutex); + 425 : void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr); + 426 : void thread_cond_destroy(pthread_cond_t* cond); + 427 : void thread_cond_signal(pthread_cond_t* cond); + 428 : void thread_cond_broadcast(pthread_cond_t* cond); + 429 : void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex); + 430 : void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); + 431 : void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); + 432 : void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg); + 433 : void thread_join(pthread_t thread, void** retval); + 434 : #endif + 435 : + 436 : #endif + 437 : diff --git a/cov/cmdline/sync.c.func-sort-c.html b/cov/cmdline/sync.c.func-sort-c.html index ed4b5461..f39e3139 100644 --- a/cov/cmdline/sync.c.func-sort-c.html +++ b/cov/cmdline/sync.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 501 + 499 546 - 91.8 % + 91.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -65,11 +65,11 @@ sync_data_reader - 688232 + 688270 sync_parity_writer - 544522 + 544910 failed_compare_by_index diff --git a/cov/cmdline/sync.c.func.html b/cov/cmdline/sync.c.func.html index 0c8a6dfb..c356fd8c 100644 --- a/cov/cmdline/sync.c.func.html +++ b/cov/cmdline/sync.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 501 + 499 546 - 91.8 % + 91.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -81,11 +81,11 @@ sync_data_reader - 688232 + 688270 sync_parity_writer - 544522 + 544910
diff --git a/cov/cmdline/sync.c.gcov.html b/cov/cmdline/sync.c.gcov.html index 465c441c..56bab884 100644 --- a/cov/cmdline/sync.c.gcov.html +++ b/cov/cmdline/sync.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 501 + 499 546 - 91.8 % + 91.4 % Date: - 2016-11-21 + 2017-05-13 Functions: 7 @@ -483,9 +483,9 @@ 421 852 : const struct failed_struct* b = void_b; 422 : 423 852 : if (a->index < b->index) - 424 850 : return -1; - 425 2 : if (a->index > b->index) - 426 2 : return 1; + 424 852 : return -1; + 425 0 : if (a->index > b->index) + 426 0 : return 1; 427 0 : return 0; 428 : } 429 : @@ -524,56 +524,56 @@ 462 4688742 : one_valid = 1; 463 : 464 4911646 : if (block_has_invalid_parity(block) || plan->force_full) - 465 753240 : one_invalid = 1; + 465 753392 : one_invalid = 1; 466 : } 467 : 468 : /* if none valid or none invalid, we don't need to update */ 469 820170 : if (!one_invalid || !one_valid) - 470 590712 : return 0; + 470 590600 : return 0; 471 : - 472 229458 : return 1; + 472 229570 : return 1; 473 : } 474 : - 475 688232 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) + 475 688270 : static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) 476 : { - 477 688232 : struct snapraid_io* io = worker->io; - 478 688232 : struct snapraid_state* state = io->state; - 479 688232 : struct snapraid_handle* handle = worker->handle; - 480 688232 : struct snapraid_disk* disk = handle->disk; - 481 688232 : block_off_t blockcur = task->position; - 482 688232 : unsigned char* buffer = task->buffer; + 477 688270 : struct snapraid_io* io = worker->io; + 478 688270 : struct snapraid_state* state = io->state; + 479 688270 : struct snapraid_handle* handle = worker->handle; + 480 688270 : struct snapraid_disk* disk = handle->disk; + 481 688270 : block_off_t blockcur = task->position; + 482 688270 : unsigned char* buffer = task->buffer; 483 : int ret; 484 : char esc_buffer[ESC_MAX]; 485 : 486 : /* if the disk position is not used */ - 487 688232 : if (!disk) { + 487 688270 : if (!disk) { 488 : /* use an empty block */ 489 0 : memset(buffer, 0, state->block_size); 490 0 : task->state = TASK_STATE_DONE; - 491 92183 : return; + 491 92084 : return; 492 : } 493 : 494 : /* get the block */ - 495 688237 : task->block = fs_par2block_find(disk, blockcur); + 495 688275 : task->block = fs_par2block_find(disk, blockcur); 496 : 497 : /* if the block has no file, meaning that it's EMPTY or DELETED, */ 498 : /* it doesn't participate in the new parity computation */ - 499 688177 : if (!block_has_file(task->block)) { + 499 688010 : if (!block_has_file(task->block)) { 500 : /* use an empty block */ - 501 92175 : memset(buffer, 0, state->block_size); - 502 92175 : task->state = TASK_STATE_DONE; - 503 92175 : return; + 501 92076 : memset(buffer, 0, state->block_size); + 502 92076 : task->state = TASK_STATE_DONE; + 503 92076 : return; 504 : } 505 : 506 : /* get the file of this block */ - 507 595953 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + 507 595621 : task->file = fs_par2file_get(disk, blockcur, &task->file_pos); 508 : 509 : /* if the file is different than the current one, close it */ - 510 596099 : if (handle->file != 0 && handle->file != task->file) { + 510 596270 : if (handle->file != 0 && handle->file != task->file) { 511 : /* keep a pointer at the file we are going to close for error reporting */ - 512 246100 : struct snapraid_file* report = handle->file; - 513 246100 : ret = handle_close(handle); - 514 246014 : if (ret == -1) { + 512 246082 : struct snapraid_file* report = handle->file; + 513 246082 : ret = handle_close(handle); + 514 245642 : if (ret == -1) { 515 : /* LCOV_EXCL_START */ 516 : /* This one is really an unexpected error, because we are only reading */ 517 : /* and closing a descriptor should never fail */ @@ -596,8 +596,8 @@ 534 : } 535 : } 536 : - 537 596013 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); - 538 596027 : if (ret == -1) { + 537 595830 : ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + 538 591402 : if (ret == -1) { 539 12 : if (errno == EIO) { 540 : /* LCOV_EXCL_START */ 541 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); @@ -641,10 +641,10 @@ 579 : } 580 : 581 : /* check if the file is changed */ - 582 596015 : if (handle->st.st_size != task->file->size - 583 596023 : || handle->st.st_mtime != task->file->mtime_sec - 584 596052 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec - 585 596047 : || handle->st.st_ino != task->file->inode + 582 591390 : if (handle->st.st_size != task->file->size + 583 592816 : || handle->st.st_mtime != task->file->mtime_sec + 584 594857 : || STAT_NSEC(&handle->st) != task->file->mtime_nsec + 585 595324 : || handle->st.st_ino != task->file->inode 586 : ) { 587 0 : log_tag("error:%u:%s:%s: Unexpected attribute change\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer)); 588 6 : if (handle->st.st_size != task->file->size) { @@ -663,8 +663,8 @@ 601 6 : return; 602 : } 603 : - 604 596041 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); - 605 595681 : if (task->read_size == -1) { + 604 594859 : task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + 605 592671 : if (task->read_size == -1) { 606 : /* LCOV_EXCL_START */ 607 : if (errno == EIO) { 608 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); @@ -683,24 +683,24 @@ 621 : } 622 : 623 : /* store the path of the opened file */ - 624 595681 : pathcpy(task->path, sizeof(task->path), handle->path); + 624 592671 : pathcpy(task->path, sizeof(task->path), handle->path); 625 : - 626 595979 : task->state = TASK_STATE_DONE; + 626 588699 : task->state = TASK_STATE_DONE; 627 : } 628 : - 629 544522 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task) + 629 544910 : static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task) 630 : { - 631 544522 : struct snapraid_io* io = worker->io; - 632 544522 : struct snapraid_state* state = io->state; - 633 544522 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; - 634 544522 : unsigned level = parity_handle->level; - 635 544522 : block_off_t blockcur = task->position; - 636 544522 : unsigned char* buffer = task->buffer; + 631 544910 : struct snapraid_io* io = worker->io; + 632 544910 : struct snapraid_state* state = io->state; + 633 544910 : struct snapraid_parity_handle* parity_handle = worker->parity_handle; + 634 544910 : unsigned level = parity_handle->level; + 635 544910 : block_off_t blockcur = task->position; + 636 544910 : unsigned char* buffer = task->buffer; 637 : int ret; 638 : 639 : /* write parity */ - 640 544522 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size); - 641 544519 : if (ret == -1) { + 640 544910 : ret = parity_write(parity_handle, blockcur, buffer, state->block_size); + 641 544712 : if (ret == -1) { 642 : /* LCOV_EXCL_START */ 643 : if (errno == EIO) { 644 : log_tag("parity_error:%u:%s: Write EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); @@ -718,7 +718,7 @@ 656 : /* LCOV_EXCL_STOP */ 657 : } 658 : - 659 544519 : task->state = TASK_STATE_DONE; + 659 544712 : task->state = TASK_STATE_DONE; 660 : } 661 : 662 83 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax) @@ -799,8 +799,8 @@ 737 83 : plan.force_full = state->opt.force_full; 738 410168 : for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { 739 410085 : if (!block_is_enabled(&plan, blockcur)) - 740 295356 : continue; - 741 114729 : ++countmax; + 740 295300 : continue; + 741 114785 : ++countmax; 742 : } 743 : 744 : /* compute the autosave size for all disk, even if not read */ @@ -836,31 +836,31 @@ 774 : int writer_error[IO_WRITER_ERROR_MAX]; 775 : 776 : /* go to the next block */ - 777 114812 : blockcur = io_read_next(&io, &buffer); - 778 114812 : if (blockcur >= blockmax) + 777 114868 : blockcur = io_read_next(&io, &buffer); + 778 114868 : if (blockcur >= blockmax) 779 166 : break; 780 : 781 : /* until now is scheduling */ - 782 114729 : state_usage_sched(state); + 782 114785 : state_usage_sched(state); 783 : 784 : /* one more block processed for autosave */ - 785 114729 : ++autosavedone; - 786 114729 : --autosavemissing; + 785 114785 : ++autosavedone; + 786 114785 : --autosavemissing; 787 : 788 : /* by default process the block, and skip it if something goes wrong */ - 789 114729 : error_on_this_block = 0; - 790 114729 : silent_error_on_this_block = 0; - 791 114729 : io_error_on_this_block = 0; - 792 114729 : fixed_error_on_this_block = 0; + 789 114785 : error_on_this_block = 0; + 790 114785 : silent_error_on_this_block = 0; + 791 114785 : io_error_on_this_block = 0; + 792 114785 : fixed_error_on_this_block = 0; 793 : 794 : /* keep track of the number of failed blocks */ - 795 114729 : failed_count = 0; + 795 114785 : failed_count = 0; 796 : 797 : /* get block specific info */ - 798 114729 : info = info_get(&state->infoarr, blockcur); + 798 114785 : info = info_get(&state->infoarr, blockcur); 799 : 800 : /* if we have to use the old hash */ - 801 114729 : rehash = info_get_rehash(info); + 801 114785 : rehash = info_get_rehash(info); 802 : 803 : /* if the parity requires to be updated */ 804 : /* It could happens that all the blocks are EMPTY/BLK and CHG but with the hash */ @@ -869,18 +869,18 @@ 807 : /* Note that CHG/DELETED blocks already present in the content file loaded */ 808 : /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */ 809 : /* We are treating only CHG blocks created at runtime. */ - 810 114729 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update; + 810 114785 : parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update; 811 : 812 : /* if the parity is going to be updated */ - 813 114729 : parity_going_to_be_updated = 0; + 813 114785 : parity_going_to_be_updated = 0; 814 : 815 : /* if the block is marked as bad, we force the parity update */ 816 : /* because the bad block may be the result of a wrong parity */ - 817 114729 : if (info_get_bad(info)) + 817 114785 : if (info_get_bad(info)) 818 0 : parity_needs_to_be_updated = 1; 819 : 820 : /* for each disk, process the block */ - 821 803103 : for (j = 0; j < diskmax; ++j) { + 821 803495 : for (j = 0; j < diskmax; ++j) { 822 : struct snapraid_task* task; 823 : int read_size; 824 : unsigned char hash[HASH_MAX]; @@ -892,45 +892,45 @@ 830 : unsigned diskcur; 831 : 832 : /* until now is misc */ - 833 688374 : state_usage_misc(state); + 833 688710 : state_usage_misc(state); 834 : - 835 688374 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); + 835 688710 : task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); 836 : 837 : /* until now is disk */ - 838 688374 : state_usage_disk(state, handle, waiting_map, waiting_mac); + 838 688710 : state_usage_disk(state, handle, waiting_map, waiting_mac); 839 : 840 : /* get the results */ - 841 688374 : disk = task->disk; - 842 688374 : block = task->block; - 843 688374 : file = task->file; - 844 688374 : file_pos = task->file_pos; - 845 688374 : read_size = task->read_size; + 841 688710 : disk = task->disk; + 842 688710 : block = task->block; + 843 688710 : file = task->file; + 844 688710 : file_pos = task->file_pos; + 845 688710 : read_size = task->read_size; 846 : 847 : /* by default no rehash in case of "continue" */ - 848 688374 : rehandle[diskcur].block = 0; + 848 688710 : rehandle[diskcur].block = 0; 849 : 850 : /* if the disk position is not used */ - 851 688374 : if (!disk) - 852 93074 : continue; + 851 688710 : if (!disk) + 852 93042 : continue; 853 : 854 : /* get the state of the block */ - 855 688374 : block_state = block_state_get(block); + 855 688710 : block_state = block_state_get(block); 856 : 857 : /* if the block has invalid parity, */ 858 : /* we have to take care of it in case of recover */ - 859 688374 : if (block_has_invalid_parity(block)) { + 859 688710 : if (block_has_invalid_parity(block)) { 860 : /* store it in the failed set, because */ 861 : /* the parity may be still computed with the previous content */ - 862 182822 : failed[failed_count].index = diskcur; - 863 182822 : failed[failed_count].size = state->block_size; - 864 182822 : failed[failed_count].block = block; - 865 182822 : ++failed_count; + 862 182898 : failed[failed_count].index = diskcur; + 863 182898 : failed[failed_count].size = state->block_size; + 864 182898 : failed[failed_count].block = block; + 865 182898 : ++failed_count; 866 : 867 : /* if the block has invalid parity, we have to update the parity */ 868 : /* to include this block change */ 869 : /* This also apply to CHG blocks, but we are going to handle */ 870 : /* later this case to do the updates only if really needed */ - 871 182822 : if (block_state != BLOCK_STATE_CHG) + 871 182898 : if (block_state != BLOCK_STATE_CHG) 872 88225 : parity_needs_to_be_updated = 1; 873 : 874 : /* note that DELETE blocks are skipped in the next check */ @@ -941,28 +941,28 @@ 879 : } 880 : 881 : /* if the block is not used */ - 882 688374 : if (!block_has_file(block)) - 883 92203 : continue; + 882 688710 : if (!block_has_file(block)) + 883 92171 : continue; 884 : 885 : /* handle error conditions */ - 886 596171 : if (task->state == TASK_STATE_IOERROR) { + 886 596539 : if (task->state == TASK_STATE_IOERROR) { 887 : /* LCOV_EXCL_START */ 888 : ++io_error; 889 : goto bail; 890 : /* LCOV_EXCL_STOP */ 891 : } - 892 596171 : if (task->state == TASK_STATE_ERROR) { + 892 596539 : if (task->state == TASK_STATE_ERROR) { 893 : /* LCOV_EXCL_START */ 894 : ++error; 895 : goto bail; 896 : /* LCOV_EXCL_STOP */ 897 : } - 898 596171 : if (task->state == TASK_STATE_ERROR_CONTINUE) { + 898 596539 : if (task->state == TASK_STATE_ERROR_CONTINUE) { 899 18 : ++error; 900 18 : error_on_this_block = 1; 901 18 : continue; 902 : } - 903 596153 : if (task->state == TASK_STATE_IOERROR_CONTINUE) { + 903 596521 : if (task->state == TASK_STATE_IOERROR_CONTINUE) { 904 0 : ++io_error; 905 0 : if (io_error >= state->opt.io_error_limit) { 906 : /* LCOV_EXCL_START */ @@ -977,32 +977,32 @@ 915 0 : io_error_on_this_block = 1; 916 0 : continue; 917 : } - 918 596153 : if (task->state != TASK_STATE_DONE) { + 918 596521 : if (task->state != TASK_STATE_DONE) { 919 : /* LCOV_EXCL_START */ 920 : log_fatal("Internal inconsistency in task state\n"); 921 : os_abort(); 922 : /* LCOV_EXCL_STOP */ 923 : } 924 : - 925 596153 : countsize += read_size; + 925 596521 : countsize += read_size; 926 : 927 : /* now compute the hash */ - 928 596153 : if (rehash) { + 928 596521 : if (rehash) { 929 27243 : memhash(state->prevhash, state->prevhashseed, hash, buffer[diskcur], read_size); 930 : 931 : /* compute the new hash, and store it */ 932 27243 : rehandle[diskcur].block = block; 933 27243 : memhash(state->hash, state->hashseed, rehandle[diskcur].hash, buffer[diskcur], read_size); 934 : } else { - 935 568910 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); + 935 569278 : memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); 936 : } 937 : 938 : /* until now is hash */ - 939 596153 : state_usage_hash(state); + 939 596521 : state_usage_hash(state); 940 : - 941 596153 : if (block_has_updated_hash(block)) { + 941 596521 : if (block_has_updated_hash(block)) { 942 : /* compare the hash */ - 943 501574 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 943 501866 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { 944 : /* if the file has invalid parity, it's a REP changed during the sync */ 945 853 : if (block_has_invalid_parity(block)) { 946 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer)); @@ -1026,8 +1026,8 @@ 964 1 : continue; 965 : } else { /* otherwise it's a BLK with silent error */ 966 852 : unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); - 967 852 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff); - 968 852 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", task->path, file_pos, diff); + 967 852 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE*8); + 968 852 : log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE*8); 969 : 970 : /* save the failed block for the fix */ 971 852 : failed[failed_count].index = diskcur; @@ -1045,28 +1045,28 @@ 983 : } 984 : } else { 985 : /* if until now the parity doesn't need to be updated */ - 986 94579 : if (!parity_needs_to_be_updated) { + 986 94655 : if (!parity_needs_to_be_updated) { 987 : /* for sure it's a CHG block, because EMPTY are processed before with "continue" */ 988 : /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */ 989 : /* have "parity_needs_to_be_updated" already at 1 */ - 990 35226 : assert(block_state_get(block) == BLOCK_STATE_CHG); + 990 35282 : assert(block_state_get(block) == BLOCK_STATE_CHG); 991 : 992 : /* if the hash represents the data unequivocally */ - 993 35226 : if (hash_is_unique(block->hash)) { + 993 35282 : if (hash_is_unique(block->hash)) { 994 : /* check if the hash is changed */ - 995 8551 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + 995 8608 : if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { 996 : /* the block is different, and we must update parity */ - 997 6039 : parity_needs_to_be_updated = 1; + 997 6111 : parity_needs_to_be_updated = 1; 998 : } 999 : } else { 1000 : /* if the hash is already invalid, we update parity */ - 1001 26675 : parity_needs_to_be_updated = 1; + 1001 26674 : parity_needs_to_be_updated = 1; 1002 : } 1003 : } 1004 : 1005 : /* copy the hash in the block, but doesn't mark the block as hashed */ 1006 : /* this allow in case of skipped block to do not save the failed computation */ - 1007 94579 : memcpy(block->hash, hash, BLOCK_HASH_SIZE); + 1007 94655 : memcpy(block->hash, hash, BLOCK_HASH_SIZE); 1008 : 1009 : /* note that in case of rehash, this is the wrong hash, */ 1010 : /* but it will be overwritten later */ @@ -1076,7 +1076,7 @@ 1014 : /* if we have only silent errors we can try to fix them on-the-fly */ 1015 : /* note the the fix is not written to disk, but used only to */ 1016 : /* compute the new parity */ - 1017 114729 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { + 1017 114785 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { 1018 : unsigned failed_mac; 1019 852 : int something_to_recover = 0; 1020 : @@ -1213,44 +1213,44 @@ 1151 : } 1152 : 1153 : /* if we have read all the data required and it's correct, proceed with the parity */ - 1154 114729 : if (!error_on_this_block && !io_error_on_this_block - 1155 114710 : && (!silent_error_on_this_block || fixed_error_on_this_block) + 1154 114785 : if (!error_on_this_block && !io_error_on_this_block + 1155 114766 : && (!silent_error_on_this_block || fixed_error_on_this_block) 1156 : ) { 1157 : /* update the parity only if really needed */ - 1158 114710 : if (parity_needs_to_be_updated) { + 1158 114766 : if (parity_needs_to_be_updated) { 1159 : /* compute the parity */ - 1160 112438 : raid_gen(diskmax, state->level, state->block_size, buffer); + 1160 112510 : raid_gen(diskmax, state->level, state->block_size, buffer); 1161 : 1162 : /* until now is raid */ - 1163 112438 : state_usage_raid(state); + 1163 112510 : state_usage_raid(state); 1164 : 1165 : /* mark that the parity is going to be written */ - 1166 112438 : parity_going_to_be_updated = 1; + 1166 112510 : parity_going_to_be_updated = 1; 1167 : } 1168 : 1169 : /* for each disk, mark the blocks as processed */ - 1170 802970 : for (j = 0; j < diskmax; ++j) { + 1170 803362 : for (j = 0; j < diskmax; ++j) { 1171 : struct snapraid_block* block; 1172 : - 1173 688260 : if (!handle[j].disk) + 1173 688596 : if (!handle[j].disk) 1174 0 : continue; 1175 : - 1176 688260 : block = fs_par2block_find(handle[j].disk, blockcur); + 1176 688596 : block = fs_par2block_find(handle[j].disk, blockcur); 1177 : - 1178 688260 : if (block == BLOCK_NULL) { + 1178 688596 : if (block == BLOCK_NULL) { 1179 : /* nothing to do */ - 1180 81248 : continue; + 1180 81216 : continue; 1181 : } 1182 : 1183 : /* if it's a deleted block */ - 1184 607012 : if (block_state_get(block) == BLOCK_STATE_DELETED) { + 1184 607380 : if (block_state_get(block) == BLOCK_STATE_DELETED) { 1185 : /* the parity is now updated without this block, so it's now empty */ 1186 10953 : fs_deallocate(handle[j].disk, blockcur); 1187 10953 : continue; 1188 : } 1189 : 1190 : /* now all the blocks have the hash and the parity computed */ - 1191 596059 : block_state_set(block, BLOCK_STATE_BLK); + 1191 596427 : block_state_set(block, BLOCK_STATE_BLK); 1192 : } 1193 : 1194 : /* we update the info block only if we really have updated the parity */ @@ -1258,11 +1258,11 @@ 1196 : /* wrote the parity at this time */ 1197 : /* we also update the info block only if no silent error was found */ 1198 : /* because has no sense to refresh the time for data that we know bad */ - 1199 114710 : if (parity_needs_to_be_updated - 1200 112438 : && !silent_error_on_this_block + 1199 114766 : if (parity_needs_to_be_updated + 1200 112510 : && !silent_error_on_this_block 1201 : ) { 1202 : /* if rehash is needed */ - 1203 112099 : if (rehash) { + 1203 112174 : if (rehash) { 1204 : /* store all the new hash already computed */ 1205 32249 : for (j = 0; j < diskmax; ++j) { 1206 27642 : if (rehandle[j].block) @@ -1272,14 +1272,14 @@ 1210 : 1211 : /* update the time info of the block */ 1212 : /* we are also clearing any previous bad and rehash flag */ - 1213 112099 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1)); + 1213 112174 : info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1)); 1214 : } 1215 : } 1216 : 1217 : /* if a silent (even if corrected) or input/output error was found */ 1218 : /* mark the block as bad to have check/fix to handle it */ 1219 : /* because our correction is in memory only and not yet written */ - 1220 114729 : if (silent_error_on_this_block || io_error_on_this_block) { + 1220 114785 : if (silent_error_on_this_block || io_error_on_this_block) { 1221 : /* set the error status keeping the other info */ 1222 852 : info_set(&state->infoarr, blockcur, info_set_bad(info)); 1223 : } @@ -1288,27 +1288,27 @@ 1226 : /* Note that the calls to io_parity_write() are mandatory */ 1227 : /* even if the parity doesn't need to be updated */ 1228 : /* This because we want to keep track of the time usage */ - 1229 114729 : state_usage_misc(state); + 1229 114785 : state_usage_misc(state); 1230 : 1231 : /* write start */ - 1232 114729 : io_write_preset(&io, blockcur, !parity_going_to_be_updated); + 1232 114785 : io_write_preset(&io, blockcur, !parity_going_to_be_updated); 1233 : 1234 : /* write the parity */ - 1235 672998 : for (l = 0; l < state->level; ++l) { + 1235 673390 : for (l = 0; l < state->level; ++l) { 1236 : unsigned levcur; 1237 : - 1238 558269 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac); + 1238 558605 : io_parity_write(&io, &levcur, waiting_map, &waiting_mac); 1239 : 1240 : /* until now is parity */ - 1241 558269 : state_usage_parity(state, waiting_map, waiting_mac); + 1241 558605 : state_usage_parity(state, waiting_map, waiting_mac); 1242 : } 1243 : 1244 : /* write finished */ - 1245 114729 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error); + 1245 114785 : io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error); 1246 : 1247 : /* handle errors reported */ - 1248 573645 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) { - 1249 458916 : if (writer_error[j]) { + 1248 573925 : for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) { + 1249 459140 : if (writer_error[j]) { 1250 0 : switch (j + IO_WRITER_ERROR_BASE) { 1251 : case TASK_STATE_IOERROR_CONTINUE : 1252 0 : ++io_error; @@ -1338,24 +1338,24 @@ 1276 : } 1277 : 1278 : /* mark the state as needing write */ - 1279 114729 : state->need_write = 1; + 1279 114785 : state->need_write = 1; 1280 : 1281 : /* count the number of processed block */ - 1282 114729 : ++countpos; + 1282 114785 : ++countpos; 1283 : 1284 : /* progress */ - 1285 114729 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { + 1285 114785 : if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { 1286 : /* LCOV_EXCL_START */ 1287 : break; 1288 : /* LCOV_EXCL_STOP */ 1289 : } 1290 : 1291 : /* autosave */ - 1292 114729 : if ((state->autosave != 0 + 1292 114785 : if ((state->autosave != 0 1293 26021 : && autosavedone >= autosavelimit /* if we have reached the limit */ 1294 0 : && autosavemissing >= autosavelimit) /* if we have at least a full step to do */ 1295 : /* or if we have a forced autosave at the specified block */ - 1296 114729 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur) + 1296 114785 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur) 1297 : ) { 1298 1 : autosavedone = 0; /* restart the counter */ 1299 : @@ -1390,7 +1390,7 @@ 1328 : /* drop until now */ 1329 1 : state_usage_waste(state); 1330 : } - 1331 114729 : } + 1331 114785 : } 1332 : 1333 : end: 1334 83 : state_progress_end(state, countpos, countmax, countsize); diff --git a/cov/cmdline/touch.c.func-sort-c.html b/cov/cmdline/touch.c.func-sort-c.html index 29e46e34..5c8c1624 100644 --- a/cov/cmdline/touch.c.func-sort-c.html +++ b/cov/cmdline/touch.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/touch.c.func.html b/cov/cmdline/touch.c.func.html index 7ca70d61..bc6ad4e6 100644 --- a/cov/cmdline/touch.c.func.html +++ b/cov/cmdline/touch.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/touch.c.gcov.html b/cov/cmdline/touch.c.gcov.html index 8d7eeb65..caa75c8d 100644 --- a/cov/cmdline/touch.c.gcov.html +++ b/cov/cmdline/touch.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/cmdline/unix.c.func-sort-c.html b/cov/cmdline/unix.c.func-sort-c.html index 470599c4..56a88b91 100644 --- a/cov/cmdline/unix.c.func-sort-c.html +++ b/cov/cmdline/unix.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 320 - 442 - 72.4 % + 314 + 447 + 70.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 28 + 27 31 - 90.3 % + 87.1 % @@ -60,91 +60,91 @@ Hit count Sort by hit count - tick - 3817537 + tick + 3819097 open_noatime - 1719437 + 1718110 - filephy + filephy 11432 - devuuid + devuuid 5630 - devuuid_dev + devuuid_dev 5626 - fsinfo + fsinfo 5483 - randomize + randomize 282 - os_init + os_init 271 - os_done + os_done 248 - tagread + tagread 191 - devresolve + devresolve_sys 191 - devresolve_sys - 191 + devresolve + 190 - devread + devread 144 - devtree + devtree 130 - tick_ms + tick_ms 65 - thread_smart - 43 + thread_smart + 42 - devsmart - 43 + devsmart + 42 - devup + devup 30 - thread_spinup + thread_spinup 30 - direct_size + direct_size 7 - thread_spindown + thread_spindown 5 - devdown + devdown 5 @@ -152,33 +152,33 @@ 4 - devdereference + devdereference 4 - devquery + devquery 4 - device_thread + device_thread 3 - devscan + devscan 1 - os_clear - 1 - - - devuuid_blkid + devuuid_blkid 0 dirent_hidden 0 + + os_clear + 0 + stat_desc 0 diff --git a/cov/cmdline/unix.c.func.html b/cov/cmdline/unix.c.func.html index e5db4a7b..acc9ff99 100644 --- a/cov/cmdline/unix.c.func.html +++ b/cov/cmdline/unix.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 320 - 442 - 72.4 % + 314 + 447 + 70.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 28 + 27 31 - 90.3 % + 87.1 % @@ -60,67 +60,67 @@ Hit count Sort by hit count - devdereference + devdereference 4 - devdown + devdown 5 - device_thread + device_thread 3 - devquery + devquery 4 - devread + devread 144 - devresolve - 191 + devresolve + 190 devresolve_proc 4 - devresolve_sys + devresolve_sys 191 - devscan + devscan 1 - devsmart - 43 + devsmart + 42 - devtree + devtree 130 - devup + devup 30 - devuuid + devuuid 5630 - devuuid_blkid + devuuid_blkid 0 - devuuid_dev + devuuid_dev 5626 - direct_size + direct_size 7 @@ -128,31 +128,31 @@ 0 - filephy + filephy 11432 - fsinfo + fsinfo 5483 open_noatime - 1719437 + 1718110 - os_clear - 1 + os_clear + 0 - os_done + os_done 248 - os_init + os_init 271 - randomize + randomize 282 @@ -160,27 +160,27 @@ 0 - tagread + tagread 191 - thread_smart - 43 + thread_smart + 42 - thread_spindown + thread_spindown 5 - thread_spinup + thread_spinup 30 - tick - 3817537 + tick + 3819097 - tick_ms + tick_ms 65 diff --git a/cov/cmdline/unix.c.gcov.html b/cov/cmdline/unix.c.gcov.html index 1299a964..cc72535d 100644 --- a/cov/cmdline/unix.c.gcov.html +++ b/cov/cmdline/unix.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 320 - 442 - 72.4 % + 314 + 447 + 70.2 % Date: - 2016-11-21 + 2017-05-13 Functions: - 28 + 27 31 - 90.3 % + 87.1 % @@ -90,15 +90,15 @@ 28 : int exit_failure = 1; 29 : int exit_sync_needed = 2; 30 : - 31 1719437 : int open_noatime(const char* file, int flags) + 31 1718110 : int open_noatime(const char* file, int flags) 32 : { 33 : #ifdef O_NOATIME - 34 1719437 : int f = open(file, flags | O_NOATIME); + 34 1718110 : int f = open(file, flags | O_NOATIME); 35 : 36 : /* only root is allowed to use O_NOATIME, in case retry without it */ - 37 1719500 : if (f == -1 && errno == EPERM) + 37 1718988 : if (f == -1 && errno == EPERM) 38 0 : f = open(file, flags); - 39 1719484 : return f; + 39 1717923 : return f; 40 : #else 41 : return open(file, flags); 42 : #endif @@ -176,1416 +176,1435 @@ 114 : char* separator; 115 : char* majorminor; 116 : char* mountpoint; - 117 : char* mountsource; - 118 : - 119 104 : s = fgets(buf, sizeof(buf), f); - 120 104 : if (s == 0) - 121 4 : break; - 122 : - 123 : /* find the separator position */ - 124 100 : separator = strstr(s, " - "); - 125 100 : if (!separator) - 126 32 : continue; - 127 : - 128 : /* skip the separator */ - 129 100 : *separator = 0; - 130 100 : separator += 3; - 131 : - 132 : /* split the line */ - 133 100 : first_mac = strsplit(first_map, 8, s, " \t\r\n"); - 134 100 : second_mac = strsplit(second_map, 8, separator, " \t\r\n"); - 135 : - 136 : /* if too short, it's the wrong line */ - 137 100 : if (first_mac < 5) - 138 0 : continue; - 139 100 : if (second_mac < 2) - 140 0 : continue; - 141 : - 142 100 : majorminor = first_map[2]; - 143 100 : mountpoint = first_map[4]; - 144 100 : mountsource = second_map[1]; - 145 : - 146 : /* accept only /dev/... mountsource */ - 147 : /* this excludes ZFS that has the bare label, like "tank" */ - 148 100 : if (strncmp(mountsource, "/dev/", 5) != 0) - 149 32 : continue; - 150 : - 151 : /* compare major:minor from mountinfo */ - 152 68 : if (strcmp(majorminor, match) == 0) { - 153 0 : pathcpy(path, path_size, mountsource); - 154 : - 155 0 : log_tag("resolve:proc:%u:%u:%s: found mountinfo device %s\n", major(device), minor(device), path, match); - 156 : - 157 0 : fclose(f); - 158 0 : return 0; - 159 : } - 160 : - 161 : /* get the device of the mount point */ - 162 : /* in Btrfs it could be different than the one in mountinfo */ - 163 68 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) { - 164 0 : pathcpy(path, path_size, mountsource); - 165 : - 166 0 : log_tag("resolve:proc:%u:%u:%s: found mountpoint %s\n", major(device), minor(device), path, mountpoint); - 167 : - 168 0 : fclose(f); - 169 0 : return 0; - 170 : } - 171 100 : } - 172 : - 173 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device)); + 117 : char* fs; + 118 : char* mountsource; + 119 : + 120 104 : s = fgets(buf, sizeof(buf), f); + 121 104 : if (s == 0) + 122 4 : break; + 123 : + 124 : /* find the separator position */ + 125 100 : separator = strstr(s, " - "); + 126 100 : if (!separator) + 127 0 : continue; + 128 : + 129 : /* skip the separator */ + 130 100 : *separator = 0; + 131 100 : separator += 3; + 132 : + 133 : /* split the line */ + 134 100 : first_mac = strsplit(first_map, 8, s, " \t\r\n"); + 135 100 : second_mac = strsplit(second_map, 8, separator, " \t\r\n"); + 136 : + 137 : /* if too short, it's the wrong line */ + 138 100 : if (first_mac < 5) + 139 0 : continue; + 140 100 : if (second_mac < 2) + 141 0 : continue; + 142 : + 143 100 : majorminor = first_map[2]; + 144 100 : mountpoint = first_map[4]; + 145 100 : fs = second_map[0]; + 146 100 : mountsource = second_map[1]; + 147 : + 148 : /* compare major:minor from mountinfo */ + 149 100 : if (strcmp(majorminor, match) == 0) { + 150 : /* + 151 : * Accept only /dev/... mountsource + 152 : * + 153 : * This excludes ZFS that uses a bare label for mountsource, like "tank". + 154 : * + 155 : * 410 408 0:193 / /XXX rw,relatime shared:217 - zfs tank/system/data/var/lib/docker/XXX rw,xattr,noacl + 156 : * + 157 : * Also excludes AUTOFS unmounted devices that point to a fake filesystem + 158 : * used to remount them at the first use. + 159 : * + 160 : * 97 25 0:42 / /XXX rw,relatime shared:76 - autofs /etc/auto.seed rw,fd=6,pgrp=952,timeout=30,minproto=5,maxproto=5,indirect + 161 : */ + 162 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { + 163 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + 164 0 : continue; + 165 : } + 166 : + 167 0 : pathcpy(path, path_size, mountsource); + 168 : + 169 0 : log_tag("resolve:proc:%u:%u: found device %s matching device %s\n", major(device), minor(device), path, match); + 170 : + 171 0 : fclose(f); + 172 0 : return 0; + 173 : } 174 : - 175 4 : fclose(f); - 176 4 : return -1; - 177 : } - 178 : #endif - 179 : - 180 : /** - 181 : * Get the device of a virtual superblock. - 182 : * - 183 : * This is intended to resolve the case of Btrfs filesystems that - 184 : * create a virtual superblock (major==0) not backed by any low - 185 : * level device. - 186 : * - 187 : * See: - 188 : * Bug 711881 - too funny btrfs st_dev numbers - 189 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881 - 190 : */ - 191 : #if HAVE_LINUX_DEVICE - 192 4 : static int devdereference(uint64_t device, uint64_t* new_device) - 193 : { - 194 : char path[PATH_MAX]; - 195 : struct stat st; - 196 : - 197 : /* use the proc interface to get the device containing the filesystem */ - 198 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) { - 199 : /* LCOV_EXCL_START */ - 200 : return -1; - 201 : /* LCOV_EXCL_STOP */ - 202 : } - 203 : - 204 : /* check the device */ - 205 0 : if (stat(path, &st) != 0) { - 206 : /* LCOV_EXCL_START */ - 207 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path); - 208 : return -1; - 209 : /* LCOV_EXCL_STOP */ - 210 : } - 211 : - 212 0 : if (major(st.st_rdev) == 0) { - 213 : /* LCOV_EXCL_START */ - 214 : log_tag("dereference:%u:%u: still null device %s -> %u:%u\n", major(device), minor(device), path, major(st.st_rdev), minor(st.st_rdev)); - 215 : return -1; - 216 : /* LCOV_EXCL_STOP */ - 217 : } - 218 : - 219 0 : *new_device = st.st_rdev; - 220 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev)); - 221 0 : return 0; - 222 : } - 223 : #endif - 224 : - 225 : /** - 226 : * Read a file extracting the specified tag TAG=VALUE format. - 227 : * Return !=0 on error. - 228 : */ - 229 : #if HAVE_LINUX_DEVICE - 230 191 : static int tagread(const char* path, const char* tag, char* value, size_t value_size) - 231 : { - 232 : int f; - 233 : int ret; - 234 : int len; - 235 : char buf[512]; - 236 : size_t tag_len; - 237 : char* i; - 238 : char* e; - 239 : - 240 191 : f = open(path, O_RDONLY); - 241 191 : if (f == -1) { - 242 : /* LCOV_EXCL_START */ - 243 : log_fatal("Failed to open '%s'.\n", path); - 244 : return 0; - 245 : /* LCOV_EXCL_STOP */ - 246 : } - 247 : - 248 191 : len = read(f, buf, sizeof(buf)); - 249 191 : if (len < 0) { - 250 : /* LCOV_EXCL_START */ - 251 : close(f); - 252 : log_fatal("Failed to read '%s'.\n", path); - 253 : return -1; - 254 : /* LCOV_EXCL_STOP */ - 255 : } - 256 191 : if (len == sizeof(buf)) { - 257 : /* LCOV_EXCL_START */ - 258 : close(f); - 259 : log_fatal("Too long read '%s'.\n", path); - 260 : return -1; - 261 : /* LCOV_EXCL_STOP */ - 262 : } - 263 : - 264 191 : ret = close(f); - 265 191 : if (ret != 0) { - 266 : /* LCOV_EXCL_START */ - 267 : log_fatal("Failed to close '%s'.\n", path); - 268 : return -1; - 269 : /* LCOV_EXCL_STOP */ - 270 : } - 271 : - 272 191 : buf[len] = 0; - 273 191 : tag_len = strlen(tag); - 274 : - 275 3324 : for (i = buf; *i; ++i) { - 276 3324 : char* p = i; - 277 : - 278 : /* start with a space */ - 279 3324 : if (p != buf) { - 280 3133 : if (!isspace(*p)) - 281 2751 : continue; - 282 382 : ++p; - 283 : } - 284 : - 285 573 : if (strncmp(p, tag, tag_len) != 0) - 286 382 : continue; - 287 191 : p += tag_len; - 288 : - 289 : /* end with a = */ - 290 191 : if (*p != '=') - 291 0 : continue; - 292 191 : ++p; + 175 : /* get the device of the mount point */ + 176 : /* in Btrfs it could be different than the one in mountinfo */ + 177 100 : if (stat(mountpoint, &st) == 0 && st.st_dev == device) { + 178 0 : if (strncmp(mountsource, "/dev/", 5) != 0) { + 179 0 : log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + 180 0 : continue; + 181 : } + 182 : + 183 0 : pathcpy(path, path_size, mountsource); + 184 : + 185 0 : log_tag("resolve:proc:%u:%u: found device %s matching mountpoint %s\n", major(device), minor(device), path, mountpoint); + 186 : + 187 0 : fclose(f); + 188 0 : return 0; + 189 : } + 190 100 : } + 191 : + 192 4 : log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device)); + 193 : + 194 4 : fclose(f); + 195 4 : return -1; + 196 : } + 197 : #endif + 198 : + 199 : /** + 200 : * Get the device of a virtual superblock. + 201 : * + 202 : * This is intended to resolve the case of Btrfs filesystems that + 203 : * create a virtual superblock (major==0) not backed by any low + 204 : * level device. + 205 : * + 206 : * See: + 207 : * Bug 711881 - too funny btrfs st_dev numbers + 208 : * https://bugzilla.redhat.com/show_bug.cgi?id=711881 + 209 : */ + 210 : #if HAVE_LINUX_DEVICE + 211 4 : static int devdereference(uint64_t device, uint64_t* new_device) + 212 : { + 213 : char path[PATH_MAX]; + 214 : struct stat st; + 215 : + 216 : /* use the proc interface to get the device containing the filesystem */ + 217 4 : if (devresolve_proc(device, path, sizeof(path)) != 0) { + 218 : /* LCOV_EXCL_START */ + 219 : return -1; + 220 : /* LCOV_EXCL_STOP */ + 221 : } + 222 : + 223 : /* check the device */ + 224 0 : if (stat(path, &st) != 0) { + 225 : /* LCOV_EXCL_START */ + 226 : log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path); + 227 : return -1; + 228 : /* LCOV_EXCL_STOP */ + 229 : } + 230 : + 231 0 : if (major(st.st_rdev) == 0) { + 232 : /* LCOV_EXCL_START */ + 233 : log_tag("dereference:%u:%u: still null device %s -> %u:%u\n", major(device), minor(device), path, major(st.st_rdev), minor(st.st_rdev)); + 234 : return -1; + 235 : /* LCOV_EXCL_STOP */ + 236 : } + 237 : + 238 0 : *new_device = st.st_rdev; + 239 0 : log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev)); + 240 0 : return 0; + 241 : } + 242 : #endif + 243 : + 244 : /** + 245 : * Read a file extracting the specified tag TAG=VALUE format. + 246 : * Return !=0 on error. + 247 : */ + 248 : #if HAVE_LINUX_DEVICE + 249 191 : static int tagread(const char* path, const char* tag, char* value, size_t value_size) + 250 : { + 251 : int f; + 252 : int ret; + 253 : int len; + 254 : char buf[512]; + 255 : size_t tag_len; + 256 : char* i; + 257 : char* e; + 258 : + 259 191 : f = open(path, O_RDONLY); + 260 191 : if (f == -1) { + 261 : /* LCOV_EXCL_START */ + 262 : log_fatal("Failed to open '%s'.\n", path); + 263 : return 0; + 264 : /* LCOV_EXCL_STOP */ + 265 : } + 266 : + 267 191 : len = read(f, buf, sizeof(buf)); + 268 190 : if (len < 0) { + 269 : /* LCOV_EXCL_START */ + 270 : close(f); + 271 : log_fatal("Failed to read '%s'.\n", path); + 272 : return -1; + 273 : /* LCOV_EXCL_STOP */ + 274 : } + 275 190 : if (len == sizeof(buf)) { + 276 : /* LCOV_EXCL_START */ + 277 : close(f); + 278 : log_fatal("Too long read '%s'.\n", path); + 279 : return -1; + 280 : /* LCOV_EXCL_STOP */ + 281 : } + 282 : + 283 190 : ret = close(f); + 284 195 : if (ret != 0) { + 285 : /* LCOV_EXCL_START */ + 286 : log_fatal("Failed to close '%s'.\n", path); + 287 : return -1; + 288 : /* LCOV_EXCL_STOP */ + 289 : } + 290 : + 291 195 : buf[len] = 0; + 292 195 : tag_len = strlen(tag); 293 : - 294 : /* found */ - 295 191 : i = p; - 296 191 : break; - 297 : } - 298 191 : if (!*i) { - 299 : /* LCOV_EXCL_START */ - 300 : log_fatal("Missing tag '%s' for '%s'.\n", tag, path); - 301 : return -1; - 302 : /* LCOV_EXCL_STOP */ - 303 : } - 304 : - 305 : /* terminate at the first space */ - 306 191 : e = i; - 307 1020 : while (*e != 0 && !isspace(*e)) - 308 638 : ++e; - 309 191 : *e = 0; - 310 : - 311 191 : if (!*i) { - 312 : /* LCOV_EXCL_START */ - 313 : log_fatal("Empty tag '%s' for '%s'.\n", tag, path); - 314 : return -1; - 315 : /* LCOV_EXCL_STOP */ + 294 3319 : for (i = buf; *i; ++i) { + 295 3320 : char* p = i; + 296 : + 297 : /* start with a space */ + 298 3320 : if (p != buf) { + 299 3129 : if (!isspace(*p)) + 300 2743 : continue; + 301 381 : ++p; + 302 : } + 303 : + 304 572 : if (strncmp(p, tag, tag_len) != 0) + 305 381 : continue; + 306 191 : p += tag_len; + 307 : + 308 : /* end with a = */ + 309 191 : if (*p != '=') + 310 0 : continue; + 311 191 : ++p; + 312 : + 313 : /* found */ + 314 191 : i = p; + 315 191 : break; 316 : } - 317 : - 318 191 : pathprint(value, value_size, "%s", i); - 319 : - 320 191 : return 0; - 321 : } - 322 : #endif + 317 190 : if (!*i) { + 318 : /* LCOV_EXCL_START */ + 319 : log_fatal("Missing tag '%s' for '%s'.\n", tag, path); + 320 : return -1; + 321 : /* LCOV_EXCL_STOP */ + 322 : } 323 : - 324 : /** - 325 : * Get the device file from the device number. - 326 : * - 327 : * It uses /sys/dev/block/.../uevent. - 328 : * - 329 : * For null device (major==0) it fails. - 330 : */ - 331 : #if HAVE_LINUX_DEVICE - 332 191 : static int devresolve_sys(dev_t device, char* path, size_t path_size) - 333 : { - 334 : struct stat st; - 335 : char buf[PATH_MAX]; + 324 : /* terminate at the first space */ + 325 190 : e = i; + 326 1017 : while (*e != 0 && !isspace(*e)) + 327 637 : ++e; + 328 191 : *e = 0; + 329 : + 330 191 : if (!*i) { + 331 : /* LCOV_EXCL_START */ + 332 : log_fatal("Empty tag '%s' for '%s'.\n", tag, path); + 333 : return -1; + 334 : /* LCOV_EXCL_STOP */ + 335 : } 336 : - 337 : /* default device path from device number */ - 338 191 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device)); - 339 : - 340 191 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) { - 341 : /* LCOV_EXCL_START */ - 342 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path); - 343 : return -1; - 344 : /* LCOV_EXCL_STOP */ - 345 : } - 346 : - 347 : /* set the real device path */ - 348 191 : pathprint(path, path_size, "/dev/%s", buf); - 349 : - 350 : /* check the device */ - 351 191 : if (stat(path, &st) != 0) { - 352 : /* LCOV_EXCL_START */ - 353 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path); - 354 : return -1; - 355 : /* LCOV_EXCL_STOP */ - 356 : } - 357 191 : if (st.st_rdev != device) { - 358 : /* LCOV_EXCL_START */ - 359 : log_tag("resolve:sys:%u:%u: unexpected device '%u:%u' for '%s'.\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev), path); - 360 : return -1; - 361 : /* LCOV_EXCL_STOP */ - 362 : } - 363 : - 364 191 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path); + 337 191 : pathprint(value, value_size, "%s", i); + 338 : + 339 190 : return 0; + 340 : } + 341 : #endif + 342 : + 343 : /** + 344 : * Get the device file from the device number. + 345 : * + 346 : * It uses /sys/dev/block/.../uevent. + 347 : * + 348 : * For null device (major==0) it fails. + 349 : */ + 350 : #if HAVE_LINUX_DEVICE + 351 191 : static int devresolve_sys(dev_t device, char* path, size_t path_size) + 352 : { + 353 : struct stat st; + 354 : char buf[PATH_MAX]; + 355 : + 356 : /* default device path from device number */ + 357 191 : pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device)); + 358 : + 359 191 : if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) { + 360 : /* LCOV_EXCL_START */ + 361 : log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path); + 362 : return -1; + 363 : /* LCOV_EXCL_STOP */ + 364 : } 365 : - 366 191 : return 0; - 367 : } - 368 : #endif - 369 : - 370 : /** - 371 : * Get the device file from the device number. - 372 : */ - 373 : #if HAVE_LINUX_DEVICE - 374 191 : static int devresolve(uint64_t device, char* path, size_t path_size) - 375 : { - 376 191 : if (devresolve_sys(device, path, path_size) == 0) - 377 191 : return 0; - 378 : - 379 0 : return -1; - 380 : } - 381 : #endif + 366 : /* set the real device path */ + 367 190 : pathprint(path, path_size, "/dev/%s", buf); + 368 : + 369 : /* check the device */ + 370 191 : if (stat(path, &st) != 0) { + 371 : /* LCOV_EXCL_START */ + 372 : log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path); + 373 : return -1; + 374 : /* LCOV_EXCL_STOP */ + 375 : } + 376 190 : if (st.st_rdev != device) { + 377 : /* LCOV_EXCL_START */ + 378 : log_tag("resolve:sys:%u:%u: unexpected device '%u:%u' for '%s'.\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev), path); + 379 : return -1; + 380 : /* LCOV_EXCL_STOP */ + 381 : } 382 : - 383 : /** - 384 : * Cache used by blkid. - 385 : */ - 386 : #if HAVE_BLKID - 387 : static blkid_cache cache = 0; - 388 : #endif - 389 : - 390 : /** - 391 : * Get the UUID using the /dev/disk/by-uuid/ links. - 392 : * It doesn't require root permission, and the uuid are always updated. - 393 : * It doesn't work with Btrfs file-systems that don't export the main UUID - 394 : * in /dev/disk/by-uuid/. - 395 : */ - 396 : #if HAVE_LINUX_DEVICE - 397 5626 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) - 398 : { - 399 : int ret; - 400 : DIR* d; - 401 : struct dirent* dd; - 402 : struct stat st; - 403 : - 404 : /* scan the UUID directory searching for the device */ - 405 5626 : d = opendir("/dev/disk/by-uuid"); - 406 5626 : if (!d) { - 407 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); - 408 : /* directory missing?, likely we are not in Linux */ - 409 0 : return -1; - 410 : } - 411 : - 412 95642 : while ((dd = readdir(d)) != 0) { - 413 : /* skip "." and ".." files, UUIDs never start with '.' */ - 414 90016 : if (dd->d_name[0] == '.') - 415 11252 : continue; - 416 : - 417 78764 : ret = fstatat(dirfd(d), dd->d_name, &st, 0); - 418 78764 : if (ret != 0) { - 419 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); - 420 : /* generic error, ignore and continue the search */ - 421 0 : continue; - 422 : } - 423 : - 424 : /* if it matches, we have the uuid */ - 425 78764 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { - 426 : char buf[PATH_MAX]; - 427 : char path[PATH_MAX]; - 428 : - 429 : /* resolve the link */ - 430 5626 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); - 431 5626 : ret = readlink(path, buf, sizeof(buf)); - 432 5626 : if (ret < 0 || ret == sizeof(buf)) { - 433 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); - 434 : /* generic error, ignore and continue the search */ - 435 0 : continue; - 436 : } - 437 5626 : buf[ret] = 0; - 438 : - 439 : /* found */ - 440 5626 : pathcpy(uuid, uuid_size, dd->d_name); - 441 : - 442 5626 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); - 443 : - 444 5626 : closedir(d); - 445 5626 : return 0; - 446 : } - 447 : } - 448 : - 449 0 : log_tag("uuid:by-uuidd:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device)); - 450 : - 451 : /* not found */ - 452 0 : closedir(d); - 453 0 : return -1; - 454 : } - 455 : #endif - 456 : - 457 : /** - 458 : * Get the UUID using liblkid. - 459 : * It uses a cache to work without root permission, resulting in UUID - 460 : * not necessarily recent. - 461 : * We could call blkid_probe_all() to refresh the UUID, but it would - 462 : * require root permission to read the superblocks, and resulting in - 463 : * all the disks spinning. - 464 : */ - 465 : #if HAVE_BLKID - 466 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) - 467 : { - 468 : char* devname; - 469 : char* uuidname; - 470 : - 471 0 : devname = blkid_devno_to_devname(device); - 472 0 : if (!devname) { - 473 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); - 474 : /* device mapping failed */ - 475 0 : return -1; - 476 : } - 477 : - 478 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname); - 479 0 : if (!uuidname) { - 480 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); - 481 : /* uuid mapping failed */ - 482 0 : free(devname); - 483 0 : return -1; - 484 : } - 485 : - 486 0 : pathcpy(uuid, uuid_size, uuidname); - 487 : - 488 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); + 383 190 : log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path); + 384 : + 385 191 : return 0; + 386 : } + 387 : #endif + 388 : + 389 : /** + 390 : * Get the device file from the device number. + 391 : */ + 392 : #if HAVE_LINUX_DEVICE + 393 190 : static int devresolve(uint64_t device, char* path, size_t path_size) + 394 : { + 395 190 : if (devresolve_sys(device, path, path_size) == 0) + 396 191 : return 0; + 397 : + 398 0 : return -1; + 399 : } + 400 : #endif + 401 : + 402 : /** + 403 : * Cache used by blkid. + 404 : */ + 405 : #if HAVE_BLKID + 406 : static blkid_cache cache = 0; + 407 : #endif + 408 : + 409 : /** + 410 : * Get the UUID using the /dev/disk/by-uuid/ links. + 411 : * It doesn't require root permission, and the uuid are always updated. + 412 : * It doesn't work with Btrfs file-systems that don't export the main UUID + 413 : * in /dev/disk/by-uuid/. + 414 : */ + 415 : #if HAVE_LINUX_DEVICE + 416 5626 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) + 417 : { + 418 : int ret; + 419 : DIR* d; + 420 : struct dirent* dd; + 421 : struct stat st; + 422 : + 423 : /* scan the UUID directory searching for the device */ + 424 5626 : d = opendir("/dev/disk/by-uuid"); + 425 5626 : if (!d) { + 426 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); + 427 : /* directory missing?, likely we are not in Linux */ + 428 0 : return -1; + 429 : } + 430 : + 431 95642 : while ((dd = readdir(d)) != 0) { + 432 : /* skip "." and ".." files, UUIDs never start with '.' */ + 433 90016 : if (dd->d_name[0] == '.') + 434 11252 : continue; + 435 : + 436 78764 : ret = fstatat(dirfd(d), dd->d_name, &st, 0); + 437 78764 : if (ret != 0) { + 438 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + 439 : /* generic error, ignore and continue the search */ + 440 0 : continue; + 441 : } + 442 : + 443 : /* if it matches, we have the uuid */ + 444 78764 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { + 445 : char buf[PATH_MAX]; + 446 : char path[PATH_MAX]; + 447 : + 448 : /* resolve the link */ + 449 5626 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); + 450 5626 : ret = readlink(path, buf, sizeof(buf)); + 451 5626 : if (ret < 0 || ret == sizeof(buf)) { + 452 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + 453 : /* generic error, ignore and continue the search */ + 454 0 : continue; + 455 : } + 456 5626 : buf[ret] = 0; + 457 : + 458 : /* found */ + 459 5626 : pathcpy(uuid, uuid_size, dd->d_name); + 460 : + 461 5626 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); + 462 : + 463 5626 : closedir(d); + 464 5626 : return 0; + 465 : } + 466 : } + 467 : + 468 0 : log_tag("uuid:by-uuidd:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device)); + 469 : + 470 : /* not found */ + 471 0 : closedir(d); + 472 0 : return -1; + 473 : } + 474 : #endif + 475 : + 476 : /** + 477 : * Get the UUID using liblkid. + 478 : * It uses a cache to work without root permission, resulting in UUID + 479 : * not necessarily recent. + 480 : * We could call blkid_probe_all() to refresh the UUID, but it would + 481 : * require root permission to read the superblocks, and resulting in + 482 : * all the disks spinning. + 483 : */ + 484 : #if HAVE_BLKID + 485 0 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) + 486 : { + 487 : char* devname; + 488 : char* uuidname; 489 : - 490 0 : free(devname); - 491 0 : free(uuidname); - 492 0 : return 0; - 493 : } - 494 : #endif - 495 : - 496 5630 : int devuuid(uint64_t device, char* uuid, size_t uuid_size) - 497 : { - 498 : #if HAVE_LINUX_DEVICE - 499 : /* if the major is the null device */ - 500 5630 : if (major(device) == 0) { - 501 : /* obtain the real device */ - 502 4 : if (devdereference(device, &device) != 0) { - 503 : /* LCOV_EXCL_START */ - 504 : return -1; - 505 : /* LCOV_EXCL_STOP */ - 506 : } - 507 : } - 508 : #endif - 509 : - 510 : /* first try with the /dev/disk/by-uuid version */ - 511 : #if HAVE_LINUX_DEVICE - 512 5626 : if (devuuid_dev(device, uuid, uuid_size) == 0) - 513 5626 : return 0; - 514 : #else - 515 : log_tag("uuid:by-uuidd:%u:%u: by-uuid not supported\n", major(device), minor(device)); - 516 : #endif - 517 : - 518 : /* fall back to blkid for other cases */ - 519 : #if HAVE_BLKID - 520 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0) - 521 0 : return 0; - 522 : #else - 523 : log_tag("uuid:blkid:%u:%u: blkid not supported\n", major(device), minor(device)); - 524 : #endif - 525 : - 526 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); - 527 : - 528 : /* not supported */ - 529 : (void)uuid; - 530 : (void)uuid_size; - 531 0 : return -1; - 532 : } - 533 : - 534 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) - 535 : { - 536 : #if HAVE_LINUX_FIEMAP_H - 537 : /* In Linux get the real physical address of the file */ - 538 : /* Note that FIEMAP doesn't require root permission */ - 539 : int f; - 540 : struct { - 541 : struct fiemap fiemap; - 542 : struct fiemap_extent extent; - 543 : } fm; - 544 : unsigned int blknum; - 545 : - 546 11432 : f = open(path, O_RDONLY); - 547 11432 : if (f == -1) { - 548 0 : return -1; - 549 : } - 550 : - 551 : /* first try with FIEMAP */ - 552 : /* if works for ext2, ext3, ext4, xfs, btrfs */ - 553 11432 : memset(&fm, 0, sizeof(fm)); - 554 11432 : fm.fiemap.fm_start = 0; - 555 11432 : fm.fiemap.fm_length = ~0ULL; - 556 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ - 557 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */ - 558 : - 559 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) { - 560 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags; - 561 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical; - 562 : - 563 : /* check some condition for validating the offset */ - 564 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) { - 565 : /* if the data is inline, we don't have an offset to report */ - 566 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 567 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) { - 568 : /* if the offset is unknown, we don't have an offset to report */ - 569 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 570 11432 : } else if (offset == 0) { - 571 : /* 0 is the general fallback for file-systems when */ - 572 : /* they don't have an offset to report */ - 573 14 : *physical = FILEPHY_WITHOUT_OFFSET; - 574 : } else { - 575 : /* finally report the real offset */ - 576 11418 : *physical = offset + FILEPHY_REAL_OFFSET; - 577 : } - 578 : - 579 11432 : if (close(f) == -1) - 580 0 : return -1; - 581 11432 : return 0; - 582 : } - 583 : - 584 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ - 585 0 : if (size == 0) { - 586 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 587 0 : if (close(f) == -1) - 588 0 : return -1; - 589 0 : return 0; - 590 : } - 591 : - 592 : /* then try with FIBMAP */ - 593 : /* it works for jfs, reiserfs, ntfs-3g */ - 594 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ - 595 0 : blknum = 0; /* first block */ - 596 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { - 597 0 : *physical = blknum + FILEPHY_REAL_OFFSET; - 598 0 : if (close(f) == -1) + 490 0 : devname = blkid_devno_to_devname(device); + 491 0 : if (!devname) { + 492 0 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); + 493 : /* device mapping failed */ + 494 0 : return -1; + 495 : } + 496 : + 497 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname); + 498 0 : if (!uuidname) { + 499 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); + 500 : /* uuid mapping failed */ + 501 0 : free(devname); + 502 0 : return -1; + 503 : } + 504 : + 505 0 : pathcpy(uuid, uuid_size, uuidname); + 506 : + 507 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); + 508 : + 509 0 : free(devname); + 510 0 : free(uuidname); + 511 0 : return 0; + 512 : } + 513 : #endif + 514 : + 515 5630 : int devuuid(uint64_t device, char* uuid, size_t uuid_size) + 516 : { + 517 : #if HAVE_LINUX_DEVICE + 518 : /* if the major is the null device */ + 519 5630 : if (major(device) == 0) { + 520 : /* obtain the real device */ + 521 4 : if (devdereference(device, &device) != 0) { + 522 : /* LCOV_EXCL_START */ + 523 : return -1; + 524 : /* LCOV_EXCL_STOP */ + 525 : } + 526 : } + 527 : #endif + 528 : + 529 : /* first try with the /dev/disk/by-uuid version */ + 530 : #if HAVE_LINUX_DEVICE + 531 5626 : if (devuuid_dev(device, uuid, uuid_size) == 0) + 532 5626 : return 0; + 533 : #else + 534 : log_tag("uuid:by-uuidd:%u:%u: by-uuid not supported\n", major(device), minor(device)); + 535 : #endif + 536 : + 537 : /* fall back to blkid for other cases */ + 538 : #if HAVE_BLKID + 539 0 : if (devuuid_blkid(device, uuid, uuid_size) == 0) + 540 0 : return 0; + 541 : #else + 542 : log_tag("uuid:blkid:%u:%u: blkid not supported\n", major(device), minor(device)); + 543 : #endif + 544 : + 545 0 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); + 546 : + 547 : /* not supported */ + 548 : (void)uuid; + 549 : (void)uuid_size; + 550 0 : return -1; + 551 : } + 552 : + 553 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) + 554 : { + 555 : #if HAVE_LINUX_FIEMAP_H + 556 : /* In Linux get the real physical address of the file */ + 557 : /* Note that FIEMAP doesn't require root permission */ + 558 : int f; + 559 : struct { + 560 : struct fiemap fiemap; + 561 : struct fiemap_extent extent; + 562 : } fm; + 563 : unsigned int blknum; + 564 : + 565 11432 : f = open(path, O_RDONLY); + 566 11432 : if (f == -1) { + 567 0 : return -1; + 568 : } + 569 : + 570 : /* first try with FIEMAP */ + 571 : /* if works for ext2, ext3, ext4, xfs, btrfs */ + 572 11432 : memset(&fm, 0, sizeof(fm)); + 573 11432 : fm.fiemap.fm_start = 0; + 574 11432 : fm.fiemap.fm_length = ~0ULL; + 575 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ + 576 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */ + 577 : + 578 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) { + 579 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags; + 580 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical; + 581 : + 582 : /* check some condition for validating the offset */ + 583 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) { + 584 : /* if the data is inline, we don't have an offset to report */ + 585 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 586 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) { + 587 : /* if the offset is unknown, we don't have an offset to report */ + 588 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 589 11432 : } else if (offset == 0) { + 590 : /* 0 is the general fallback for file-systems when */ + 591 : /* they don't have an offset to report */ + 592 14 : *physical = FILEPHY_WITHOUT_OFFSET; + 593 : } else { + 594 : /* finally report the real offset */ + 595 11418 : *physical = offset + FILEPHY_REAL_OFFSET; + 596 : } + 597 : + 598 11432 : if (close(f) == -1) 599 0 : return -1; - 600 0 : return 0; + 600 11432 : return 0; 601 : } 602 : - 603 : /* otherwise don't use anything, and keep the directory traversal order */ - 604 : /* at now this should happen only for vfat */ - 605 : /* and it's surely better than using fake inodes */ - 606 0 : *physical = FILEPHY_UNREPORTED_OFFSET; - 607 0 : if (close(f) == -1) - 608 0 : return -1; - 609 : #else - 610 : /* In a generic Unix use a dummy value for all the files */ - 611 : /* We don't want to risk to use the inode without knowing */ - 612 : /* if it really improves performance. */ - 613 : /* In this way we keep them in the directory traversal order */ - 614 : /* that at least keeps files in the same directory together. */ - 615 : /* Note also that in newer file-system with snapshot, like ZFS, */ - 616 : /* the inode doesn't represent evenmore the disk position, because files */ - 617 : /* are not overwritten in place, but rewritten in another location */ - 618 : /* of the disk. */ - 619 : *physical = FILEPHY_UNREPORTED_OFFSET; - 620 : - 621 : (void)path; /* not used here */ - 622 : (void)size; - 623 : #endif - 624 : - 625 0 : return 0; - 626 : } - 627 : - 628 5483 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space) - 629 : { - 630 : char type[64]; - 631 : const char* ptype; - 632 : - 633 : #if HAVE_STATFS - 634 : struct statfs st; - 635 : - 636 5483 : if (statfs(path, &st) != 0) { - 637 : char dir[PATH_MAX]; - 638 : char* slash; + 603 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ + 604 0 : if (size == 0) { + 605 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 606 0 : if (close(f) == -1) + 607 0 : return -1; + 608 0 : return 0; + 609 : } + 610 : + 611 : /* then try with FIBMAP */ + 612 : /* it works for jfs, reiserfs, ntfs-3g */ + 613 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ + 614 0 : blknum = 0; /* first block */ + 615 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { + 616 0 : *physical = blknum + FILEPHY_REAL_OFFSET; + 617 0 : if (close(f) == -1) + 618 0 : return -1; + 619 0 : return 0; + 620 : } + 621 : + 622 : /* otherwise don't use anything, and keep the directory traversal order */ + 623 : /* at now this should happen only for vfat */ + 624 : /* and it's surely better than using fake inodes */ + 625 0 : *physical = FILEPHY_UNREPORTED_OFFSET; + 626 0 : if (close(f) == -1) + 627 0 : return -1; + 628 : #else + 629 : /* In a generic Unix use a dummy value for all the files */ + 630 : /* We don't want to risk to use the inode without knowing */ + 631 : /* if it really improves performance. */ + 632 : /* In this way we keep them in the directory traversal order */ + 633 : /* that at least keeps files in the same directory together. */ + 634 : /* Note also that in newer file-system with snapshot, like ZFS, */ + 635 : /* the inode doesn't represent evenmore the disk position, because files */ + 636 : /* are not overwritten in place, but rewritten in another location */ + 637 : /* of the disk. */ + 638 : *physical = FILEPHY_UNREPORTED_OFFSET; 639 : - 640 24 : if (errno != ENOENT) { - 641 0 : return -1; - 642 : } + 640 : (void)path; /* not used here */ + 641 : (void)size; + 642 : #endif 643 : - 644 : /* if it doesn't exist, we assume a file */ - 645 : /* and we check for the containing dir */ - 646 24 : if (strlen(path) + 1 > sizeof(dir)) { - 647 0 : errno = ENAMETOOLONG; - 648 0 : return -1; - 649 : } - 650 : - 651 24 : strcpy(dir, path); - 652 : - 653 24 : slash = strrchr(dir, '/'); - 654 24 : if (!slash) - 655 0 : return -1; - 656 : - 657 24 : *slash = 0; - 658 24 : if (statfs(dir, &st) != 0) - 659 0 : return -1; - 660 : } - 661 : #endif + 644 0 : return 0; + 645 : } + 646 : + 647 5483 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space) + 648 : { + 649 : char type[64]; + 650 : const char* ptype; + 651 : + 652 : #if HAVE_STATFS + 653 : struct statfs st; + 654 : + 655 5483 : if (statfs(path, &st) != 0) { + 656 : char dir[PATH_MAX]; + 657 : char* slash; + 658 : + 659 24 : if (errno != ENOENT) { + 660 0 : return -1; + 661 : } 662 : - 663 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ - 664 5483 : if (has_persistent_inode) { - 665 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 666 575 : switch (st.f_type) { - 667 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */ - 668 : case 0x4d44 : /* VFAT, "msdos" in the stat command */ - 669 0 : *has_persistent_inode = 0; - 670 0 : break; - 671 : default : - 672 : /* by default assume yes */ - 673 575 : *has_persistent_inode = 1; - 674 575 : break; - 675 : } - 676 : #else - 677 : /* by default assume yes */ - 678 : *has_persistent_inode = 1; - 679 : #endif - 680 : } + 663 : /* if it doesn't exist, we assume a file */ + 664 : /* and we check for the containing dir */ + 665 24 : if (strlen(path) + 1 > sizeof(dir)) { + 666 0 : errno = ENAMETOOLONG; + 667 0 : return -1; + 668 : } + 669 : + 670 24 : strcpy(dir, path); + 671 : + 672 24 : slash = strrchr(dir, '/'); + 673 24 : if (!slash) + 674 0 : return -1; + 675 : + 676 24 : *slash = 0; + 677 24 : if (statfs(dir, &st) != 0) + 678 0 : return -1; + 679 : } + 680 : #endif 681 : - 682 5483 : if (total_space) { - 683 : #if HAVE_STATFS - 684 4908 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; - 685 : #else - 686 : *total_space = 0; - 687 : #endif - 688 : } - 689 : - 690 5483 : if (free_space) { - 691 : #if HAVE_STATFS - 692 4908 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; - 693 : #else - 694 : *free_space = 0; - 695 : #endif - 696 : } - 697 : - 698 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME - 699 : /* get the filesystem type directly from the struct (Mac OS X) */ - 700 : (void)type; - 701 : ptype = st.f_fstypename; - 702 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 703 : /* get the filesystem type from f_type (Linux) */ - 704 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */ - 705 5483 : switch (st.f_type) { - 706 0 : case 0x65735546 : ptype = "fuseblk"; break; - 707 0 : case 0x4D44 : ptype = "vfat/msdos"; break; - 708 5483 : case 0xEF53 : ptype = "ext2/3/4"; break; - 709 0 : case 0x6969 : ptype = "nfs"; break; /* remote */ - 710 0 : case 0x6E667364 : ptype = "nfsd"; break; /* remote */ - 711 0 : case 0x517B : ptype = "smb"; break; /* remote */ - 712 0 : case 0x5346544E : ptype = "ntfs"; break; - 713 0 : case 0x52654973 : ptype = "reiserfs"; break; - 714 0 : case 0x3153464A : ptype = "jfs"; break; - 715 0 : case 0x58465342 : ptype = "xfs"; break; - 716 0 : case 0x9123683E : ptype = "btrfs"; break; - 717 0 : case 0x2FC12FC1 : ptype = "zfs"; break; - 718 : default : - 719 0 : snprintf(type, sizeof(type), "0x%X", (unsigned)st.f_type); - 720 0 : ptype = type; - 721 : } - 722 : #else - 723 : (void)type; - 724 : ptype = "unknown"; - 725 : #endif - 726 : - 727 5483 : log_tag("statfs:%s: %s \n", ptype, path); - 728 : - 729 5483 : return 0; - 730 : } - 731 : - 732 3817537 : uint64_t tick(void) - 733 : { - 734 : #if HAVE_MACH_ABSOLUTE_TIME - 735 : /* for Mac OS X */ - 736 : return mach_absolute_time(); - 737 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) - 738 : /* for Linux */ - 739 : struct timespec tv; - 740 : - 741 : /* nanosecond precision with clock_gettime() */ - 742 : #if defined(CLOCK_MONOTONIC_RAW) - 743 3817537 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { - 744 : #else - 745 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { - 746 : #endif - 747 0 : return 0; - 748 : } - 749 : - 750 3817537 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; - 751 : #else - 752 : /* other platforms */ - 753 : struct timeval tv; - 754 : - 755 : /* microsecond precision with gettimeofday() */ - 756 : if (gettimeofday(&tv, 0) != 0) { - 757 : return 0; - 758 : } + 682 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ + 683 5483 : if (has_persistent_inode) { + 684 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 685 575 : switch (st.f_type) { + 686 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */ + 687 : case 0x4d44 : /* VFAT, "msdos" in the stat command */ + 688 0 : *has_persistent_inode = 0; + 689 0 : break; + 690 : default : + 691 : /* by default assume yes */ + 692 575 : *has_persistent_inode = 1; + 693 575 : break; + 694 : } + 695 : #else + 696 : /* by default assume yes */ + 697 : *has_persistent_inode = 1; + 698 : #endif + 699 : } + 700 : + 701 5483 : if (total_space) { + 702 : #if HAVE_STATFS + 703 4908 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; + 704 : #else + 705 : *total_space = 0; + 706 : #endif + 707 : } + 708 : + 709 5483 : if (free_space) { + 710 : #if HAVE_STATFS + 711 4908 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; + 712 : #else + 713 : *free_space = 0; + 714 : #endif + 715 : } + 716 : + 717 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME + 718 : /* get the filesystem type directly from the struct (Mac OS X) */ + 719 : (void)type; + 720 : ptype = st.f_fstypename; + 721 : #elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 722 : /* get the filesystem type from f_type (Linux) */ + 723 : /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */ + 724 5483 : switch (st.f_type) { + 725 0 : case 0x65735546 : ptype = "fuseblk"; break; + 726 0 : case 0x4D44 : ptype = "vfat/msdos"; break; + 727 5483 : case 0xEF53 : ptype = "ext2/3/4"; break; + 728 0 : case 0x6969 : ptype = "nfs"; break; /* remote */ + 729 0 : case 0x6E667364 : ptype = "nfsd"; break; /* remote */ + 730 0 : case 0x517B : ptype = "smb"; break; /* remote */ + 731 0 : case 0x5346544E : ptype = "ntfs"; break; + 732 0 : case 0x52654973 : ptype = "reiserfs"; break; + 733 0 : case 0x3153464A : ptype = "jfs"; break; + 734 0 : case 0x58465342 : ptype = "xfs"; break; + 735 0 : case 0x9123683E : ptype = "btrfs"; break; + 736 0 : case 0x2FC12FC1 : ptype = "zfs"; break; + 737 : default : + 738 0 : snprintf(type, sizeof(type), "0x%X", (unsigned)st.f_type); + 739 0 : ptype = type; + 740 : } + 741 : #else + 742 : (void)type; + 743 : ptype = "unknown"; + 744 : #endif + 745 : + 746 5483 : log_tag("statfs:%s: %s \n", ptype, path); + 747 : + 748 5483 : return 0; + 749 : } + 750 : + 751 3819097 : uint64_t tick(void) + 752 : { + 753 : #if HAVE_MACH_ABSOLUTE_TIME + 754 : /* for Mac OS X */ + 755 : return mach_absolute_time(); + 756 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) + 757 : /* for Linux */ + 758 : struct timespec tv; 759 : - 760 : return tv.tv_sec * 1000000ULL + tv.tv_usec; - 761 : #endif - 762 : } - 763 : - 764 65 : uint64_t tick_ms(void) - 765 : { - 766 : struct timeval tv; - 767 : - 768 65 : if (gettimeofday(&tv, 0) != 0) - 769 0 : return 0; - 770 : - 771 65 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; - 772 : } + 760 : /* nanosecond precision with clock_gettime() */ + 761 : #if defined(CLOCK_MONOTONIC_RAW) + 762 3819097 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { + 763 : #else + 764 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { + 765 : #endif + 766 0 : return 0; + 767 : } + 768 : + 769 3819097 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; + 770 : #else + 771 : /* other platforms */ + 772 : struct timeval tv; 773 : - 774 282 : int randomize(void* ptr, size_t size) - 775 : { - 776 : int f; - 777 : ssize_t ret; + 774 : /* microsecond precision with gettimeofday() */ + 775 : if (gettimeofday(&tv, 0) != 0) { + 776 : return 0; + 777 : } 778 : - 779 282 : f = open("/dev/urandom", O_RDONLY); - 780 282 : if (f == -1) - 781 0 : return -1; + 779 : return tv.tv_sec * 1000000ULL + tv.tv_usec; + 780 : #endif + 781 : } 782 : - 783 282 : ret = read(f, ptr, size); - 784 282 : if (ret < 0 || (size_t)ret != size) { - 785 0 : close(f); - 786 0 : return -1; - 787 : } - 788 : - 789 282 : if (close(f) != 0) - 790 0 : return -1; - 791 : - 792 282 : return 0; - 793 : } - 794 : - 795 : /** - 796 : * Read a file extracting the contained device number in %u:%u format. - 797 : * Return 0 on error. - 798 : */ - 799 : #if HAVE_LINUX_DEVICE - 800 144 : static dev_t devread(const char* path) - 801 : { - 802 : int f; - 803 : int ret; - 804 : int len; - 805 : char buf[64]; - 806 : char* e; - 807 : unsigned ma; - 808 : unsigned mi; - 809 : - 810 144 : f = open(path, O_RDONLY); - 811 144 : if (f == -1) { - 812 : /* LCOV_EXCL_START */ - 813 : log_fatal("Failed to open '%s'.\n", path); - 814 : return 0; - 815 : /* LCOV_EXCL_STOP */ - 816 : } - 817 : - 818 144 : len = read(f, buf, sizeof(buf)); - 819 144 : if (len < 0) { - 820 : /* LCOV_EXCL_START */ - 821 : close(f); - 822 : log_fatal("Failed to read '%s'.\n", path); - 823 : return 0; - 824 : /* LCOV_EXCL_STOP */ - 825 : } - 826 144 : if (len == sizeof(buf)) { - 827 : /* LCOV_EXCL_START */ - 828 : close(f); - 829 : log_fatal("Too long read '%s'.\n", path); - 830 : return 0; - 831 : /* LCOV_EXCL_STOP */ - 832 : } - 833 : - 834 144 : ret = close(f); - 835 144 : if (ret != 0) { - 836 : /* LCOV_EXCL_START */ - 837 : log_fatal("Failed to close '%s'.\n", path); - 838 : return 0; - 839 : /* LCOV_EXCL_STOP */ - 840 : } - 841 : - 842 144 : buf[len] = 0; - 843 : - 844 144 : ma = strtoul(buf, &e, 10); - 845 144 : if (*e != ':') { + 783 65 : uint64_t tick_ms(void) + 784 : { + 785 : struct timeval tv; + 786 : + 787 65 : if (gettimeofday(&tv, 0) != 0) + 788 0 : return 0; + 789 : + 790 63 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; + 791 : } + 792 : + 793 282 : int randomize(void* ptr, size_t size) + 794 : { + 795 : int f; + 796 : ssize_t ret; + 797 : + 798 282 : f = open("/dev/urandom", O_RDONLY); + 799 282 : if (f == -1) + 800 0 : return -1; + 801 : + 802 282 : ret = read(f, ptr, size); + 803 282 : if (ret < 0 || (size_t)ret != size) { + 804 0 : close(f); + 805 0 : return -1; + 806 : } + 807 : + 808 282 : if (close(f) != 0) + 809 0 : return -1; + 810 : + 811 282 : return 0; + 812 : } + 813 : + 814 : /** + 815 : * Read a file extracting the contained device number in %u:%u format. + 816 : * Return 0 on error. + 817 : */ + 818 : #if HAVE_LINUX_DEVICE + 819 144 : static dev_t devread(const char* path) + 820 : { + 821 : int f; + 822 : int ret; + 823 : int len; + 824 : char buf[64]; + 825 : char* e; + 826 : unsigned ma; + 827 : unsigned mi; + 828 : + 829 144 : f = open(path, O_RDONLY); + 830 144 : if (f == -1) { + 831 : /* LCOV_EXCL_START */ + 832 : log_fatal("Failed to open '%s'.\n", path); + 833 : return 0; + 834 : /* LCOV_EXCL_STOP */ + 835 : } + 836 : + 837 144 : len = read(f, buf, sizeof(buf)); + 838 144 : if (len < 0) { + 839 : /* LCOV_EXCL_START */ + 840 : close(f); + 841 : log_fatal("Failed to read '%s'.\n", path); + 842 : return 0; + 843 : /* LCOV_EXCL_STOP */ + 844 : } + 845 144 : if (len == sizeof(buf)) { 846 : /* LCOV_EXCL_START */ - 847 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); - 848 : return 0; - 849 : /* LCOV_EXCL_STOP */ - 850 : } - 851 : - 852 144 : mi = strtoul(e + 1, &e, 10); - 853 144 : if (*e != 0 && !isspace(*e)) { - 854 : /* LCOV_EXCL_START */ - 855 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); - 856 : return 0; - 857 : /* LCOV_EXCL_STOP */ - 858 : } - 859 : - 860 144 : return makedev(ma, mi); - 861 : } - 862 : #endif - 863 : - 864 : /** - 865 : * Read a device tree filling the specified list of disk_t entries. - 866 : */ - 867 : #if HAVE_LINUX_DEVICE - 868 130 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) - 869 : { - 870 : char path[PATH_MAX]; - 871 : DIR* d; - 872 130 : int slaves = 0; - 873 : - 874 130 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); - 875 : - 876 : /* check if there is a slaves list */ - 877 130 : d = opendir(path); - 878 130 : if (d != 0) { - 879 : struct dirent* dd; - 880 : - 881 325 : while ((dd = readdir(d)) != 0) { - 882 195 : if (dd->d_name[0] != '.') { - 883 : /* for each slave, expand the full potential tree */ - 884 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); - 885 : - 886 65 : device = devread(path); - 887 65 : if (!device) { - 888 : /* LCOV_EXCL_START */ - 889 : closedir(d); - 890 : return -1; - 891 : /* LCOV_EXCL_STOP */ - 892 : } - 893 : - 894 65 : if (devtree(name, custom, device, parent, list) != 0) { - 895 : /* LCOV_EXCL_START */ - 896 : closedir(d); - 897 : return -1; - 898 : /* LCOV_EXCL_STOP */ - 899 : } - 900 : - 901 65 : ++slaves; - 902 : } - 903 : } + 847 : close(f); + 848 : log_fatal("Too long read '%s'.\n", path); + 849 : return 0; + 850 : /* LCOV_EXCL_STOP */ + 851 : } + 852 : + 853 144 : ret = close(f); + 854 144 : if (ret != 0) { + 855 : /* LCOV_EXCL_START */ + 856 : log_fatal("Failed to close '%s'.\n", path); + 857 : return 0; + 858 : /* LCOV_EXCL_STOP */ + 859 : } + 860 : + 861 144 : buf[len] = 0; + 862 : + 863 144 : ma = strtoul(buf, &e, 10); + 864 144 : if (*e != ':') { + 865 : /* LCOV_EXCL_START */ + 866 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + 867 : return 0; + 868 : /* LCOV_EXCL_STOP */ + 869 : } + 870 : + 871 144 : mi = strtoul(e + 1, &e, 10); + 872 144 : if (*e != 0 && !isspace(*e)) { + 873 : /* LCOV_EXCL_START */ + 874 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + 875 : return 0; + 876 : /* LCOV_EXCL_STOP */ + 877 : } + 878 : + 879 144 : return makedev(ma, mi); + 880 : } + 881 : #endif + 882 : + 883 : /** + 884 : * Read a device tree filling the specified list of disk_t entries. + 885 : */ + 886 : #if HAVE_LINUX_DEVICE + 887 130 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) + 888 : { + 889 : char path[PATH_MAX]; + 890 : DIR* d; + 891 130 : int slaves = 0; + 892 : + 893 130 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); + 894 : + 895 : /* check if there is a slaves list */ + 896 130 : d = opendir(path); + 897 130 : if (d != 0) { + 898 : struct dirent* dd; + 899 : + 900 325 : while ((dd = readdir(d)) != 0) { + 901 195 : if (dd->d_name[0] != '.') { + 902 : /* for each slave, expand the full potential tree */ + 903 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); 904 : - 905 65 : closedir(d); - 906 : } - 907 : - 908 : /* if no slaves found */ - 909 130 : if (!slaves) { - 910 : /* this is a raw device */ - 911 : devinfo_t* devinfo; + 905 65 : device = devread(path); + 906 65 : if (!device) { + 907 : /* LCOV_EXCL_START */ + 908 : closedir(d); + 909 : return -1; + 910 : /* LCOV_EXCL_STOP */ + 911 : } 912 : - 913 : /* check if it's a real device */ - 914 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); - 915 65 : if (access(path, F_OK) != 0) { - 916 : /* get the parent device */ - 917 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); - 918 : - 919 65 : device = devread(path); - 920 65 : if (!device) { - 921 : /* LCOV_EXCL_START */ - 922 : return -1; - 923 : /* LCOV_EXCL_STOP */ - 924 : } - 925 : } + 913 65 : if (devtree(name, custom, device, parent, list) != 0) { + 914 : /* LCOV_EXCL_START */ + 915 : closedir(d); + 916 : return -1; + 917 : /* LCOV_EXCL_STOP */ + 918 : } + 919 : + 920 65 : ++slaves; + 921 : } + 922 : } + 923 : + 924 65 : closedir(d); + 925 : } 926 : - 927 : /* get the device file */ - 928 65 : if (devresolve(device, path, sizeof(path)) != 0) { - 929 : /* LCOV_EXCL_START */ - 930 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 931 : return -1; - 932 : /* LCOV_EXCL_STOP */ - 933 : } - 934 : - 935 65 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); - 936 : - 937 65 : devinfo->device = device; - 938 65 : pathcpy(devinfo->name, sizeof(devinfo->name), name); - 939 65 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); - 940 65 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 941 65 : devinfo->parent = parent; - 942 : - 943 : /* insert in the list */ - 944 65 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 945 : } - 946 : - 947 130 : return 0; - 948 : } - 949 : #endif - 950 : - 951 : /** - 952 : * Scan all the devices. - 953 : * - 954 : * If a device is already in, it's not added again. - 955 : */ - 956 : #if HAVE_LINUX_DEVICE - 957 1 : static int devscan(tommy_list* list) - 958 : { - 959 : char dir[PATH_MAX]; - 960 : DIR* d; - 961 : struct dirent* dd; - 962 : - 963 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); - 964 : - 965 : /* check if there is a slaves list */ - 966 1 : d = opendir(dir); - 967 1 : if (d == 0) { - 968 : /* LCOV_EXCL_START */ - 969 : log_fatal("Failed to open dir '%s'.\n", dir); - 970 : return -1; - 971 : /* LCOV_EXCL_STOP */ - 972 : } - 973 : - 974 74 : while ((dd = readdir(d)) != 0) { - 975 : char path[PATH_MAX]; - 976 : tommy_node* i; - 977 : dev_t device; - 978 : devinfo_t* devinfo; - 979 : - 980 72 : if (dd->d_name[0] == '.') - 981 61 : continue; - 982 : - 983 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); - 984 : - 985 : /* check if it's a real device */ - 986 70 : if (access(path, F_OK) != 0) - 987 56 : continue; - 988 : - 989 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); - 990 : - 991 14 : device = devread(path); - 992 14 : if (!device) { - 993 : /* LCOV_EXCL_START */ - 994 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name); - 995 : continue; - 996 : /* LCOV_EXCL_STOP */ - 997 : } + 927 : /* if no slaves found */ + 928 130 : if (!slaves) { + 929 : /* this is a raw device */ + 930 : devinfo_t* devinfo; + 931 : + 932 : /* check if it's a real device */ + 933 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); + 934 65 : if (access(path, F_OK) != 0) { + 935 : /* get the parent device */ + 936 65 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); + 937 : + 938 65 : device = devread(path); + 939 65 : if (!device) { + 940 : /* LCOV_EXCL_START */ + 941 : return -1; + 942 : /* LCOV_EXCL_STOP */ + 943 : } + 944 : } + 945 : + 946 : /* get the device file */ + 947 65 : if (devresolve(device, path, sizeof(path)) != 0) { + 948 : /* LCOV_EXCL_START */ + 949 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 950 : return -1; + 951 : /* LCOV_EXCL_STOP */ + 952 : } + 953 : + 954 65 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 955 : + 956 65 : devinfo->device = device; + 957 65 : pathcpy(devinfo->name, sizeof(devinfo->name), name); + 958 65 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); + 959 65 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 960 65 : devinfo->parent = parent; + 961 : + 962 : /* insert in the list */ + 963 65 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 964 : } + 965 : + 966 130 : return 0; + 967 : } + 968 : #endif + 969 : + 970 : /** + 971 : * Scan all the devices. + 972 : * + 973 : * If a device is already in, it's not added again. + 974 : */ + 975 : #if HAVE_LINUX_DEVICE + 976 1 : static int devscan(tommy_list* list) + 977 : { + 978 : char dir[PATH_MAX]; + 979 : DIR* d; + 980 : struct dirent* dd; + 981 : + 982 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); + 983 : + 984 : /* check if there is a slaves list */ + 985 1 : d = opendir(dir); + 986 1 : if (d == 0) { + 987 : /* LCOV_EXCL_START */ + 988 : log_fatal("Failed to open dir '%s'.\n", dir); + 989 : return -1; + 990 : /* LCOV_EXCL_STOP */ + 991 : } + 992 : + 993 74 : while ((dd = readdir(d)) != 0) { + 994 : char path[PATH_MAX]; + 995 : tommy_node* i; + 996 : dev_t device; + 997 : devinfo_t* devinfo; 998 : - 999 : /* check if already present */ - 1000 482 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 1001 469 : devinfo = i->data; - 1002 469 : if (devinfo->device == device) - 1003 1 : break; - 1004 : } - 1005 : - 1006 : /* if already present */ - 1007 14 : if (i != 0) - 1008 1 : continue; + 999 72 : if (dd->d_name[0] == '.') + 1000 61 : continue; + 1001 : + 1002 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); + 1003 : + 1004 : /* check if it's a real device */ + 1005 70 : if (access(path, F_OK) != 0) + 1006 56 : continue; + 1007 : + 1008 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); 1009 : - 1010 : /* get the device file */ - 1011 13 : if (devresolve(device, path, sizeof(path)) != 0) { + 1010 14 : device = devread(path); + 1011 14 : if (!device) { 1012 : /* LCOV_EXCL_START */ - 1013 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device)); + 1013 : log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name); 1014 : continue; 1015 : /* LCOV_EXCL_STOP */ 1016 : } 1017 : - 1018 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); - 1019 : - 1020 13 : devinfo->device = device; - 1021 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 1022 : - 1023 : /* insert in the list */ - 1024 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 1025 : } - 1026 : - 1027 1 : closedir(d); - 1028 1 : return 0; - 1029 : } - 1030 : #endif - 1031 : - 1032 : /** - 1033 : * Get SMART attributes. - 1034 : */ - 1035 : #if HAVE_LINUX_DEVICE - 1036 43 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model) - 1037 : { - 1038 : char cmd[128]; - 1039 : char file[128]; - 1040 : FILE* f; - 1041 : int ret; - 1042 : - 1043 43 : if (devresolve(device, file, sizeof(file)) != 0) { - 1044 : /* LCOV_EXCL_START */ - 1045 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1046 : return -1; - 1047 : /* LCOV_EXCL_STOP */ - 1048 : } - 1049 : - 1050 : /* if there is a custom command */ - 1051 43 : if (custom[0]) { - 1052 : char option[128]; - 1053 5 : snprintf(option, sizeof(option), custom, file); - 1054 5 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); - 1055 : } else { - 1056 38 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); - 1057 : } - 1058 : - 1059 43 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 1060 : - 1061 43 : f = popen(cmd, "r"); - 1062 43 : if (!f) { + 1018 : /* check if already present */ + 1019 482 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1020 469 : devinfo = i->data; + 1021 469 : if (devinfo->device == device) + 1022 1 : break; + 1023 : } + 1024 : + 1025 : /* if already present */ + 1026 14 : if (i != 0) + 1027 1 : continue; + 1028 : + 1029 : /* get the device file */ + 1030 13 : if (devresolve(device, path, sizeof(path)) != 0) { + 1031 : /* LCOV_EXCL_START */ + 1032 : log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device)); + 1033 : continue; + 1034 : /* LCOV_EXCL_STOP */ + 1035 : } + 1036 : + 1037 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 1038 : + 1039 13 : devinfo->device = device; + 1040 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 1041 : + 1042 : /* insert in the list */ + 1043 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 1044 : } + 1045 : + 1046 1 : closedir(d); + 1047 1 : return 0; + 1048 : } + 1049 : #endif + 1050 : + 1051 : /** + 1052 : * Get SMART attributes. + 1053 : */ + 1054 : #if HAVE_LINUX_DEVICE + 1055 42 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model) + 1056 : { + 1057 : char cmd[128]; + 1058 : char file[128]; + 1059 : FILE* f; + 1060 : int ret; + 1061 : + 1062 42 : if (devresolve(device, file, sizeof(file)) != 0) { 1063 : /* LCOV_EXCL_START */ - 1064 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 1064 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); 1065 : return -1; 1066 : /* LCOV_EXCL_STOP */ 1067 : } 1068 : - 1069 43 : if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) { - 1070 : /* LCOV_EXCL_START */ - 1071 : pclose(f); - 1072 : return -1; - 1073 : /* LCOV_EXCL_STOP */ - 1074 : } - 1075 : - 1076 43 : ret = pclose(f); + 1069 : /* if there is a custom command */ + 1070 43 : if (custom[0]) { + 1071 : char option[128]; + 1072 5 : snprintf(option, sizeof(option), custom, file); + 1073 5 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); + 1074 : } else { + 1075 38 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); + 1076 : } 1077 : - 1078 43 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1078 43 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); 1079 : - 1080 43 : if (!WIFEXITED(ret)) { - 1081 : /* LCOV_EXCL_START */ - 1082 : log_fatal("Failed to run '%s' (not exited).\n", cmd); - 1083 : return -1; - 1084 : /* LCOV_EXCL_STOP */ - 1085 : } - 1086 43 : if (WEXITSTATUS(ret) == 127) { - 1087 : /* LCOV_EXCL_START */ - 1088 : log_fatal("Failed to run '%s' (from sh).\n", cmd); - 1089 : return -1; - 1090 : /* LCOV_EXCL_STOP */ - 1091 : } - 1092 : - 1093 : /* store the return smartctl return value */ - 1094 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret); - 1095 : - 1096 0 : return 0; - 1097 : } - 1098 : #endif - 1099 : - 1100 : /** - 1101 : * Spin down a specific device. - 1102 : */ - 1103 : #if HAVE_LINUX_DEVICE - 1104 5 : static int devdown(dev_t device, const char* name, const char* custom) - 1105 : { - 1106 : char cmd[128]; - 1107 : char file[128]; - 1108 : FILE* f; - 1109 : int ret; - 1110 : - 1111 5 : if (devresolve(device, file, sizeof(file)) != 0) { - 1112 : /* LCOV_EXCL_START */ - 1113 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1114 : return -1; - 1115 : /* LCOV_EXCL_STOP */ - 1116 : } - 1117 : - 1118 : /* if there is a custom command */ - 1119 5 : if (custom[0]) { - 1120 : char option[128]; - 1121 5 : snprintf(option, sizeof(option), custom, file); - 1122 5 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option); - 1123 : } else { - 1124 0 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file); - 1125 : } - 1126 : - 1127 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 1128 : - 1129 5 : f = popen(cmd, "r"); - 1130 5 : if (!f) { + 1080 43 : f = popen(cmd, "r"); + 1081 42 : if (!f) { + 1082 : /* LCOV_EXCL_START */ + 1083 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 1084 : return -1; + 1085 : /* LCOV_EXCL_STOP */ + 1086 : } + 1087 : + 1088 42 : if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) { + 1089 : /* LCOV_EXCL_START */ + 1090 : pclose(f); + 1091 : return -1; + 1092 : /* LCOV_EXCL_STOP */ + 1093 : } + 1094 : + 1095 42 : ret = pclose(f); + 1096 : + 1097 43 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1098 : + 1099 43 : if (!WIFEXITED(ret)) { + 1100 : /* LCOV_EXCL_START */ + 1101 : log_fatal("Failed to run '%s' (not exited).\n", cmd); + 1102 : return -1; + 1103 : /* LCOV_EXCL_STOP */ + 1104 : } + 1105 43 : if (WEXITSTATUS(ret) == 127) { + 1106 : /* LCOV_EXCL_START */ + 1107 : log_fatal("Failed to run '%s' (from sh).\n", cmd); + 1108 : return -1; + 1109 : /* LCOV_EXCL_STOP */ + 1110 : } + 1111 : + 1112 : /* store the return smartctl return value */ + 1113 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret); + 1114 : + 1115 0 : return 0; + 1116 : } + 1117 : #endif + 1118 : + 1119 : /** + 1120 : * Spin down a specific device. + 1121 : */ + 1122 : #if HAVE_LINUX_DEVICE + 1123 5 : static int devdown(dev_t device, const char* name, const char* custom) + 1124 : { + 1125 : char cmd[128]; + 1126 : char file[128]; + 1127 : FILE* f; + 1128 : int ret; + 1129 : + 1130 5 : if (devresolve(device, file, sizeof(file)) != 0) { 1131 : /* LCOV_EXCL_START */ - 1132 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 1132 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); 1133 : return -1; 1134 : /* LCOV_EXCL_STOP */ 1135 : } 1136 : - 1137 5 : if (smartctl_flush(f, file, name) != 0) { - 1138 : /* LCOV_EXCL_START */ - 1139 : pclose(f); - 1140 : return -1; - 1141 : /* LCOV_EXCL_STOP */ - 1142 : } - 1143 : - 1144 5 : ret = pclose(f); + 1137 : /* if there is a custom command */ + 1138 5 : if (custom[0]) { + 1139 : char option[128]; + 1140 5 : snprintf(option, sizeof(option), custom, file); + 1141 5 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option); + 1142 : } else { + 1143 0 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file); + 1144 : } 1145 : - 1146 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 1146 5 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); 1147 : - 1148 5 : if (!WIFEXITED(ret)) { - 1149 : /* LCOV_EXCL_START */ - 1150 : log_fatal("Failed to run '%s' (not exited).\n", cmd); - 1151 : return -1; - 1152 : /* LCOV_EXCL_STOP */ - 1153 : } - 1154 5 : if (WEXITSTATUS(ret) == 127) { - 1155 : /* LCOV_EXCL_START */ - 1156 : log_fatal("Failed to run '%s' (from sh).\n", cmd); - 1157 : return -1; - 1158 : /* LCOV_EXCL_STOP */ - 1159 : } - 1160 0 : if (WEXITSTATUS(ret) != 0) { - 1161 : /* LCOV_EXCL_START */ - 1162 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); - 1163 : return -1; - 1164 : /* LCOV_EXCL_STOP */ - 1165 : } + 1148 5 : f = popen(cmd, "r"); + 1149 5 : if (!f) { + 1150 : /* LCOV_EXCL_START */ + 1151 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 1152 : return -1; + 1153 : /* LCOV_EXCL_STOP */ + 1154 : } + 1155 : + 1156 5 : if (smartctl_flush(f, file, name) != 0) { + 1157 : /* LCOV_EXCL_START */ + 1158 : pclose(f); + 1159 : return -1; + 1160 : /* LCOV_EXCL_STOP */ + 1161 : } + 1162 : + 1163 5 : ret = pclose(f); + 1164 : + 1165 5 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); 1166 : - 1167 0 : return 0; - 1168 : } - 1169 : #endif - 1170 : - 1171 : /** - 1172 : * Spin up a device. - 1173 : * - 1174 : * There isn't a defined way to spin up a device, - 1175 : * so we just do a generic write. - 1176 : */ - 1177 30 : static int devup(const char* mountpoint) - 1178 : { - 1179 : int ret; - 1180 : char path[PATH_MAX]; - 1181 : - 1182 : /* add a temporary name used for writing */ - 1183 30 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint); - 1184 : - 1185 : /* do a generic write, and immediately undo it */ - 1186 30 : ret = mkdir(path, 0); - 1187 30 : if (ret != 0 && errno != EEXIST) { - 1188 : /* LCOV_EXCL_START */ - 1189 : log_fatal("Failed to create dir '%s'.\n", path); - 1190 : return -1; - 1191 : /* LCOV_EXCL_STOP */ - 1192 : } - 1193 : - 1194 : /* remove the just created dir */ - 1195 30 : rmdir(path); - 1196 : - 1197 30 : return 0; - 1198 : } - 1199 : - 1200 : /** - 1201 : * Thread for spinning up. - 1202 : * - 1203 : * Note that filling up the devinfo object is done inside this thread, - 1204 : * to avoid to block the main thread if the device need to be spin up - 1205 : * to handle stat/resolve requests. - 1206 : */ - 1207 30 : static void* thread_spinup(void* arg) - 1208 : { - 1209 30 : devinfo_t* devinfo = arg; - 1210 : struct stat st; - 1211 : uint64_t start; + 1167 5 : if (!WIFEXITED(ret)) { + 1168 : /* LCOV_EXCL_START */ + 1169 : log_fatal("Failed to run '%s' (not exited).\n", cmd); + 1170 : return -1; + 1171 : /* LCOV_EXCL_STOP */ + 1172 : } + 1173 5 : if (WEXITSTATUS(ret) == 127) { + 1174 : /* LCOV_EXCL_START */ + 1175 : log_fatal("Failed to run '%s' (from sh).\n", cmd); + 1176 : return -1; + 1177 : /* LCOV_EXCL_STOP */ + 1178 : } + 1179 0 : if (WEXITSTATUS(ret) != 0) { + 1180 : /* LCOV_EXCL_START */ + 1181 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); + 1182 : return -1; + 1183 : /* LCOV_EXCL_STOP */ + 1184 : } + 1185 : + 1186 0 : return 0; + 1187 : } + 1188 : #endif + 1189 : + 1190 : /** + 1191 : * Spin up a device. + 1192 : * + 1193 : * There isn't a defined way to spin up a device, + 1194 : * so we just do a generic write. + 1195 : */ + 1196 30 : static int devup(const char* mountpoint) + 1197 : { + 1198 : int ret; + 1199 : char path[PATH_MAX]; + 1200 : + 1201 : /* add a temporary name used for writing */ + 1202 30 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint); + 1203 : + 1204 : /* do a generic write, and immediately undo it */ + 1205 30 : ret = mkdir(path, 0); + 1206 30 : if (ret != 0 && errno != EEXIST) { + 1207 : /* LCOV_EXCL_START */ + 1208 : log_fatal("Failed to create dir '%s'.\n", path); + 1209 : return -1; + 1210 : /* LCOV_EXCL_STOP */ + 1211 : } 1212 : - 1213 30 : start = tick_ms(); - 1214 : - 1215 : /* first get the device number, this usually doesn't trigger a thread_spinup */ - 1216 30 : if (stat(devinfo->mount, &st) != 0) { - 1217 : /* LCOV_EXCL_START */ - 1218 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount); - 1219 : return (void*)-1; - 1220 : /* LCOV_EXCL_STOP */ - 1221 : } - 1222 : - 1223 : /* set the device number for printing */ - 1224 30 : devinfo->device = st.st_dev; - 1225 : - 1226 30 : if (devup(devinfo->mount) != 0) { - 1227 : /* LCOV_EXCL_START */ - 1228 : return (void*)-1; - 1229 : /* LCOV_EXCL_STOP */ - 1230 : } + 1213 : /* remove the just created dir */ + 1214 30 : rmdir(path); + 1215 : + 1216 30 : return 0; + 1217 : } + 1218 : + 1219 : /** + 1220 : * Thread for spinning up. + 1221 : * + 1222 : * Note that filling up the devinfo object is done inside this thread, + 1223 : * to avoid to block the main thread if the device need to be spin up + 1224 : * to handle stat/resolve requests. + 1225 : */ + 1226 30 : static void* thread_spinup(void* arg) + 1227 : { + 1228 30 : devinfo_t* devinfo = arg; + 1229 : struct stat st; + 1230 : uint64_t start; 1231 : - 1232 30 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); + 1232 30 : start = tick_ms(); 1233 : - 1234 30 : return 0; - 1235 : } - 1236 : - 1237 : /** - 1238 : * Thread for spinning down. - 1239 : */ - 1240 5 : static void* thread_spindown(void* arg) - 1241 : { - 1242 : #if HAVE_LINUX_DEVICE - 1243 5 : devinfo_t* devinfo = arg; - 1244 : uint64_t start; - 1245 : - 1246 5 : start = tick_ms(); - 1247 : - 1248 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { - 1249 : /* LCOV_EXCL_START */ - 1250 : return (void*)-1; - 1251 : /* LCOV_EXCL_STOP */ - 1252 : } - 1253 : - 1254 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 1234 : /* first get the device number, this usually doesn't trigger a thread_spinup */ + 1235 30 : if (stat(devinfo->mount, &st) != 0) { + 1236 : /* LCOV_EXCL_START */ + 1237 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount); + 1238 : return (void*)-1; + 1239 : /* LCOV_EXCL_STOP */ + 1240 : } + 1241 : + 1242 : /* set the device number for printing */ + 1243 30 : devinfo->device = st.st_dev; + 1244 : + 1245 30 : if (devup(devinfo->mount) != 0) { + 1246 : /* LCOV_EXCL_START */ + 1247 : return (void*)-1; + 1248 : /* LCOV_EXCL_STOP */ + 1249 : } + 1250 : + 1251 30 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); + 1252 : + 1253 30 : return 0; + 1254 : } 1255 : - 1256 0 : return 0; - 1257 : #else - 1258 : (void)arg; - 1259 : return (void*)-1; - 1260 : #endif - 1261 : } - 1262 : - 1263 : /** - 1264 : * Thread for getting smart info. - 1265 : */ - 1266 43 : static void* thread_smart(void* arg) - 1267 : { - 1268 : #if HAVE_LINUX_DEVICE - 1269 43 : devinfo_t* devinfo = arg; - 1270 : - 1271 43 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) { - 1272 : /* LCOV_EXCL_START */ - 1273 : return (void*)-1; - 1274 : /* LCOV_EXCL_STOP */ - 1275 : } - 1276 : - 1277 0 : return 0; - 1278 : #else - 1279 : (void)arg; - 1280 : return (void*)-1; - 1281 : #endif - 1282 : } - 1283 : - 1284 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) - 1285 : { - 1286 3 : int fail = 0; - 1287 : tommy_node* i; - 1288 : - 1289 : #if HAVE_PTHREAD - 1290 : /* start all threads */ - 1291 81 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 1292 78 : devinfo_t* devinfo = i->data; - 1293 : - 1294 78 : thread_create(&devinfo->thread, 0, func, devinfo); - 1295 : } - 1296 : - 1297 : /* join all threads */ - 1298 81 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 1299 78 : devinfo_t* devinfo = i->data; - 1300 : void* retval; - 1301 : - 1302 78 : thread_join(devinfo->thread, &retval); - 1303 : - 1304 78 : if (retval != 0) - 1305 48 : ++fail; - 1306 : } - 1307 : #else - 1308 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 1309 : devinfo_t* devinfo = i->data; - 1310 : - 1311 : if (func(devinfo) != 0) - 1312 : ++fail; - 1313 : } - 1314 : #endif - 1315 3 : if (fail != 0) { - 1316 : /* LCOV_EXCL_START */ - 1317 : return -1; - 1318 : /* LCOV_EXCL_STOP */ - 1319 : } + 1256 : /** + 1257 : * Thread for spinning down. + 1258 : */ + 1259 5 : static void* thread_spindown(void* arg) + 1260 : { + 1261 : #if HAVE_LINUX_DEVICE + 1262 5 : devinfo_t* devinfo = arg; + 1263 : uint64_t start; + 1264 : + 1265 5 : start = tick_ms(); + 1266 : + 1267 5 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { + 1268 : /* LCOV_EXCL_START */ + 1269 : return (void*)-1; + 1270 : /* LCOV_EXCL_STOP */ + 1271 : } + 1272 : + 1273 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 1274 : + 1275 0 : return 0; + 1276 : #else + 1277 : (void)arg; + 1278 : return (void*)-1; + 1279 : #endif + 1280 : } + 1281 : + 1282 : /** + 1283 : * Thread for getting smart info. + 1284 : */ + 1285 42 : static void* thread_smart(void* arg) + 1286 : { + 1287 : #if HAVE_LINUX_DEVICE + 1288 42 : devinfo_t* devinfo = arg; + 1289 : + 1290 42 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) { + 1291 : /* LCOV_EXCL_START */ + 1292 : return (void*)-1; + 1293 : /* LCOV_EXCL_STOP */ + 1294 : } + 1295 : + 1296 0 : return 0; + 1297 : #else + 1298 : (void)arg; + 1299 : return (void*)-1; + 1300 : #endif + 1301 : } + 1302 : + 1303 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) + 1304 : { + 1305 3 : int fail = 0; + 1306 : tommy_node* i; + 1307 : + 1308 : #if HAVE_PTHREAD + 1309 : /* start all threads */ + 1310 81 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1311 78 : devinfo_t* devinfo = i->data; + 1312 : + 1313 78 : thread_create(&devinfo->thread, 0, func, devinfo); + 1314 : } + 1315 : + 1316 : /* join all threads */ + 1317 81 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1318 78 : devinfo_t* devinfo = i->data; + 1319 : void* retval; 1320 : - 1321 1 : return 0; - 1322 : } - 1323 : - 1324 4 : int devquery(tommy_list* high, tommy_list* low, int operation, int others) - 1325 : { - 1326 : tommy_node* i; - 1327 4 : void* (*func)(void* arg) = 0; - 1328 : - 1329 : #if HAVE_LINUX_DEVICE - 1330 4 : if (operation != DEVICE_UP) { - 1331 : struct stat st; - 1332 : /* sysfs interface is required */ - 1333 3 : if (stat("/sys/dev/block", &st) != 0) { - 1334 : /* LCOV_EXCL_START */ - 1335 : log_fatal("Missing interface /sys/dev/block.\n"); - 1336 : return -1; - 1337 : /* LCOV_EXCL_STOP */ - 1338 : } + 1321 78 : thread_join(devinfo->thread, &retval); + 1322 : + 1323 78 : if (retval != 0) + 1324 48 : ++fail; + 1325 : } + 1326 : #else + 1327 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1328 : devinfo_t* devinfo = i->data; + 1329 : + 1330 : if (func(devinfo) != 0) + 1331 : ++fail; + 1332 : } + 1333 : #endif + 1334 3 : if (fail != 0) { + 1335 : /* LCOV_EXCL_START */ + 1336 : return -1; + 1337 : /* LCOV_EXCL_STOP */ + 1338 : } 1339 : - 1340 : /* for each device */ - 1341 136 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 1342 65 : devinfo_t* devinfo = i->data; - 1343 65 : uint64_t device = devinfo->device; - 1344 : - 1345 : /* if the major is the null device, find the real one */ - 1346 65 : if (major(device) == 0) { - 1347 : /* obtain the real device */ - 1348 0 : if (devdereference(device, &device) != 0) { - 1349 : /* LCOV_EXCL_START */ - 1350 : log_fatal("Failed to dereference device '%u:%u'.\n", major(device), minor(device)); - 1351 : return -1; - 1352 : /* LCOV_EXCL_STOP */ - 1353 : } - 1354 : } - 1355 : - 1356 : /* get the device file */ - 1357 65 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { - 1358 : /* LCOV_EXCL_START */ - 1359 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); - 1360 : return -1; - 1361 : /* LCOV_EXCL_STOP */ - 1362 : } + 1340 1 : return 0; + 1341 : } + 1342 : + 1343 4 : int devquery(tommy_list* high, tommy_list* low, int operation, int others) + 1344 : { + 1345 : tommy_node* i; + 1346 4 : void* (*func)(void* arg) = 0; + 1347 : + 1348 : #if HAVE_LINUX_DEVICE + 1349 4 : if (operation != DEVICE_UP) { + 1350 : struct stat st; + 1351 : /* sysfs interface is required */ + 1352 3 : if (stat("/sys/dev/block", &st) != 0) { + 1353 : /* LCOV_EXCL_START */ + 1354 : log_fatal("Missing interface /sys/dev/block.\n"); + 1355 : return -1; + 1356 : /* LCOV_EXCL_STOP */ + 1357 : } + 1358 : + 1359 : /* for each device */ + 1360 136 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 1361 65 : devinfo_t* devinfo = i->data; + 1362 65 : uint64_t device = devinfo->device; 1363 : - 1364 : /* expand the tree of devices */ - 1365 65 : if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) { - 1366 : /* LCOV_EXCL_START */ - 1367 : log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device)); - 1368 : return -1; - 1369 : /* LCOV_EXCL_STOP */ - 1370 : } - 1371 : } - 1372 : } - 1373 : #endif + 1364 : /* if the major is the null device, find the real one */ + 1365 65 : if (major(device) == 0) { + 1366 : /* obtain the real device */ + 1367 0 : if (devdereference(device, &device) != 0) { + 1368 : /* LCOV_EXCL_START */ + 1369 : log_fatal("Failed to dereference device '%u:%u'.\n", major(device), minor(device)); + 1370 : return -1; + 1371 : /* LCOV_EXCL_STOP */ + 1372 : } + 1373 : } 1374 : - 1375 4 : if (operation == DEVICE_UP) { - 1376 : /* duplicate the high */ - 1377 31 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 1378 30 : devinfo_t* devinfo = i->data; - 1379 : devinfo_t* entry; - 1380 : - 1381 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 1375 : /* get the device file */ + 1376 65 : if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { + 1377 : /* LCOV_EXCL_START */ + 1378 : log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + 1379 : return -1; + 1380 : /* LCOV_EXCL_STOP */ + 1381 : } 1382 : - 1383 30 : entry->device = devinfo->device; - 1384 30 : pathcpy(entry->name, sizeof(entry->name), devinfo->name); - 1385 30 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); - 1386 : - 1387 : /* insert in the high */ - 1388 30 : tommy_list_insert_tail(low, &entry->node, entry); - 1389 : } - 1390 : } - 1391 : - 1392 : #if HAVE_LINUX_DEVICE - 1393 : /* add other devices */ - 1394 4 : if (others) { - 1395 1 : if (devscan(low) != 0) { - 1396 : /* LCOV_EXCL_START */ - 1397 : log_fatal("Failed to list other devices.\n"); - 1398 : return -1; - 1399 : /* LCOV_EXCL_STOP */ - 1400 : } - 1401 : } - 1402 : #else - 1403 : (void)others; - 1404 : #endif + 1383 : /* expand the tree of devices */ + 1384 65 : if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) { + 1385 : /* LCOV_EXCL_START */ + 1386 : log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device)); + 1387 : return -1; + 1388 : /* LCOV_EXCL_STOP */ + 1389 : } + 1390 : } + 1391 : } + 1392 : #endif + 1393 : + 1394 4 : if (operation == DEVICE_UP) { + 1395 : /* duplicate the high */ + 1396 31 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 1397 30 : devinfo_t* devinfo = i->data; + 1398 : devinfo_t* entry; + 1399 : + 1400 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 1401 : + 1402 30 : entry->device = devinfo->device; + 1403 30 : pathcpy(entry->name, sizeof(entry->name), devinfo->name); + 1404 30 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); 1405 : - 1406 4 : switch (operation) { - 1407 1 : case DEVICE_UP : func = thread_spinup; break; - 1408 1 : case DEVICE_DOWN : func = thread_spindown; break; - 1409 1 : case DEVICE_SMART : func = thread_smart; break; - 1410 : } - 1411 : - 1412 4 : if (!func) - 1413 1 : return 0; - 1414 : - 1415 3 : return device_thread(low, func); - 1416 : } - 1417 : - 1418 271 : void os_init(int opt) - 1419 : { - 1420 : #if HAVE_BLKID - 1421 : int ret; - 1422 271 : ret = blkid_get_cache(&cache, NULL); - 1423 271 : if (ret != 0) { - 1424 : /* LCOV_EXCL_START */ - 1425 : log_fatal("WARNING Failed to get blkid cache\n"); - 1426 : /* LCOV_EXCL_STOP */ - 1427 : } - 1428 : #endif - 1429 : - 1430 : (void)opt; - 1431 271 : } - 1432 : - 1433 248 : void os_done(void) - 1434 : { - 1435 : #if HAVE_BLKID - 1436 248 : if (cache != 0) - 1437 248 : blkid_put_cache(cache); - 1438 : #endif - 1439 248 : } - 1440 : - 1441 : /* LCOV_EXCL_START */ - 1442 : void os_abort(void) - 1443 : { - 1444 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS - 1445 : void* stack[32]; - 1446 : char** messages; - 1447 : size_t size; - 1448 : unsigned i; - 1449 : #endif - 1450 : - 1451 : printf("Stacktrace of " PACKAGE " v" VERSION); - 1452 : #ifdef _linux - 1453 : printf(", linux"); - 1454 : #endif - 1455 : #ifdef __GNUC__ - 1456 : printf(", gcc " __VERSION__); + 1406 : /* insert in the high */ + 1407 30 : tommy_list_insert_tail(low, &entry->node, entry); + 1408 : } + 1409 : } + 1410 : + 1411 : #if HAVE_LINUX_DEVICE + 1412 : /* add other devices */ + 1413 4 : if (others) { + 1414 1 : if (devscan(low) != 0) { + 1415 : /* LCOV_EXCL_START */ + 1416 : log_fatal("Failed to list other devices.\n"); + 1417 : return -1; + 1418 : /* LCOV_EXCL_STOP */ + 1419 : } + 1420 : } + 1421 : #else + 1422 : (void)others; + 1423 : #endif + 1424 : + 1425 4 : switch (operation) { + 1426 1 : case DEVICE_UP : func = thread_spinup; break; + 1427 1 : case DEVICE_DOWN : func = thread_spindown; break; + 1428 1 : case DEVICE_SMART : func = thread_smart; break; + 1429 : } + 1430 : + 1431 4 : if (!func) + 1432 1 : return 0; + 1433 : + 1434 3 : return device_thread(low, func); + 1435 : } + 1436 : + 1437 271 : void os_init(int opt) + 1438 : { + 1439 : #if HAVE_BLKID + 1440 : int ret; + 1441 271 : ret = blkid_get_cache(&cache, NULL); + 1442 271 : if (ret != 0) { + 1443 : /* LCOV_EXCL_START */ + 1444 : log_fatal("WARNING Failed to get blkid cache\n"); + 1445 : /* LCOV_EXCL_STOP */ + 1446 : } + 1447 : #endif + 1448 : + 1449 : (void)opt; + 1450 271 : } + 1451 : + 1452 248 : void os_done(void) + 1453 : { + 1454 : #if HAVE_BLKID + 1455 248 : if (cache != 0) + 1456 248 : blkid_put_cache(cache); 1457 : #endif - 1458 : printf(", %d-bit", (int)sizeof(void *) * 8); - 1459 : printf(", PATH_MAX=%d", PATH_MAX); - 1460 : printf("\n"); - 1461 : - 1462 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS - 1463 : size = backtrace(stack, 32); - 1464 : - 1465 : messages = backtrace_symbols(stack, size); - 1466 : - 1467 : for (i = 1; i < size; ++i) { - 1468 : const char* msg; + 1458 248 : } + 1459 : + 1460 : /* LCOV_EXCL_START */ + 1461 : void os_abort(void) + 1462 : { + 1463 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 1464 : void* stack[32]; + 1465 : char** messages; + 1466 : size_t size; + 1467 : unsigned i; + 1468 : #endif 1469 : - 1470 : if (messages) - 1471 : msg = messages[i]; - 1472 : else - 1473 : msg = "<unknown>"; - 1474 : - 1475 : printf("[bt] %02u: %s\n", i, msg); - 1476 : - 1477 : if (messages) { - 1478 : int ret; - 1479 : char addr2line[1024]; - 1480 : size_t j = 0; - 1481 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) - 1482 : ++j; + 1470 : printf("Stacktrace of " PACKAGE " v" VERSION); + 1471 : #ifdef _linux + 1472 : printf(", linux"); + 1473 : #endif + 1474 : #ifdef __GNUC__ + 1475 : printf(", gcc " __VERSION__); + 1476 : #endif + 1477 : printf(", %d-bit", (int)sizeof(void *) * 8); + 1478 : printf(", PATH_MAX=%d", PATH_MAX); + 1479 : printf("\n"); + 1480 : + 1481 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 1482 : size = backtrace(stack, 32); 1483 : - 1484 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); + 1484 : messages = backtrace_symbols(stack, size); 1485 : - 1486 : ret = system(addr2line); - 1487 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) - 1488 : printf("exit:%d\n", WEXITSTATUS(ret)); - 1489 : if (WIFSIGNALED(ret)) - 1490 : printf("signal:%d\n", WTERMSIG(ret)); - 1491 : } - 1492 : } - 1493 : #endif - 1494 : - 1495 : printf("Please report this error to the SnapRAID Forum:\n"); - 1496 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); - 1497 : - 1498 : abort(); - 1499 : } - 1500 : /* LCOV_EXCL_STOP */ - 1501 : - 1502 1 : void os_clear(void) - 1503 : { - 1504 : /* ANSI codes */ - 1505 1 : printf("\033[H"); /* cursor at topleft */ - 1506 1 : printf("\033[2J"); /* clear screen */ - 1507 1 : } - 1508 : - 1509 7 : size_t direct_size(void) - 1510 : { - 1511 : long size; - 1512 : - 1513 7 : size = sysconf(_SC_PAGESIZE); - 1514 : - 1515 7 : if (size == -1) { - 1516 : /* LCOV_EXCL_START */ - 1517 : log_fatal("No page size\n"); - 1518 : exit(EXIT_FAILURE); - 1519 : /* LCOV_EXCL_STOP */ - 1520 : } - 1521 : - 1522 7 : return size; - 1523 : } - 1524 : - 1525 : #endif - 1526 : + 1486 : for (i = 1; i < size; ++i) { + 1487 : const char* msg; + 1488 : + 1489 : if (messages) + 1490 : msg = messages[i]; + 1491 : else + 1492 : msg = "<unknown>"; + 1493 : + 1494 : printf("[bt] %02u: %s\n", i, msg); + 1495 : + 1496 : if (messages) { + 1497 : int ret; + 1498 : char addr2line[1024]; + 1499 : size_t j = 0; + 1500 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) + 1501 : ++j; + 1502 : + 1503 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); + 1504 : + 1505 : ret = system(addr2line); + 1506 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) + 1507 : printf("exit:%d\n", WEXITSTATUS(ret)); + 1508 : if (WIFSIGNALED(ret)) + 1509 : printf("signal:%d\n", WTERMSIG(ret)); + 1510 : } + 1511 : } + 1512 : #endif + 1513 : + 1514 : printf("Please report this error to the SnapRAID Forum:\n"); + 1515 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); + 1516 : + 1517 : abort(); + 1518 : } + 1519 : /* LCOV_EXCL_STOP */ + 1520 : + 1521 0 : void os_clear(void) + 1522 : { + 1523 : /* ANSI codes */ + 1524 0 : printf("\033[H"); /* cursor at topleft */ + 1525 0 : printf("\033[2J"); /* clear screen */ + 1526 0 : } + 1527 : + 1528 7 : size_t direct_size(void) + 1529 : { + 1530 : long size; + 1531 : + 1532 7 : size = sysconf(_SC_PAGESIZE); + 1533 : + 1534 7 : if (size == -1) { + 1535 : /* LCOV_EXCL_START */ + 1536 : log_fatal("No page size\n"); + 1537 : exit(EXIT_FAILURE); + 1538 : /* LCOV_EXCL_STOP */ + 1539 : } + 1540 : + 1541 7 : return size; + 1542 : } + 1543 : + 1544 : #endif + 1545 : diff --git a/cov/cmdline/util.c.func-sort-c.html b/cov/cmdline/util.c.func-sort-c.html index 6587372f..fc4ec072 100644 --- a/cov/cmdline/util.c.func-sort-c.html +++ b/cov/cmdline/util.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 20 @@ -61,39 +61,39 @@ util_rotl32 - 854122150 + 854124441 util_rotl64 - 510718872 + 511238832 util_read32 - 8307408 + 8307428 util_write32 - 8307408 + 8307428 util_write64 - 7722914 + 7722984 util_read64 - 7722914 + 7722984 memhash - 5938309 + 5938349 crc32c_x86 - 646603 + 646616 memdiff - 93220 + 93324 malloc_nofail_vector_align diff --git a/cov/cmdline/util.c.func.html b/cov/cmdline/util.c.func.html index 34c06e88..6c534ef4 100644 --- a/cov/cmdline/util.c.func.html +++ b/cov/cmdline/util.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 20 @@ -69,7 +69,7 @@ crc32c_x86 - 646603 + 646616 fast_mtest_vector @@ -109,11 +109,11 @@ memdiff - 93220 + 93324 memhash - 5938309 + 5938349 mtest_vector @@ -121,27 +121,27 @@ util_read32 - 8307408 + 8307428 util_read64 - 7722914 + 7722984 util_rotl32 - 854122150 + 854124441 util_rotl64 - 510718872 + 511238832 util_write32 - 8307408 + 8307428 util_write64 - 7722914 + 7722984
diff --git a/cov/cmdline/util.c.gcov.html b/cov/cmdline/util.c.gcov.html index e731c931..3ff495b0 100644 --- a/cov/cmdline/util.c.gcov.html +++ b/cov/cmdline/util.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 20 @@ -490,15 +490,15 @@ 428 : } 429 : 430 : #if HAVE_SSE42 - 431 646603 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) + 431 646616 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) 432 : { - 433 646603 : crc ^= CRC_IV; + 433 646616 : crc ^= CRC_IV; 434 : - 435 646603 : crc = crc32c_x86_plain(crc, ptr, size); + 435 646616 : crc = crc32c_x86_plain(crc, ptr, size); 436 : - 437 646602 : crc ^= CRC_IV; + 437 646618 : crc ^= CRC_IV; 438 : - 439 646602 : return crc; + 439 646618 : return crc; 440 : } 441 : #endif 442 : @@ -522,14 +522,14 @@ 460 : * Rotate left. 461 : * In x86/x64 they are optimized with a single assembler instruction. 462 : */ - 463 854122150 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) + 463 854124441 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) 464 : { - 465 854122150 : return (x << r) | (x >> (32 - r)); + 465 854124441 : return (x << r) | (x >> (32 - r)); 466 : } 467 : - 468 510718872 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) + 468 511238832 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) 469 : { - 470 510718872 : return (x << r) | (x >> (64 - r)); + 470 511238832 : return (x << r) | (x >> (64 - r)); 471 : } 472 : 473 : /** @@ -564,41 +564,41 @@ 502 : } 503 : #endif 504 : - 505 8307408 : static inline uint32_t util_read32(const void* ptr) + 505 8307428 : static inline uint32_t util_read32(const void* ptr) 506 : { 507 : uint32_t v; - 508 8307408 : memcpy(&v, ptr, sizeof(v)); + 508 8307428 : memcpy(&v, ptr, sizeof(v)); 509 : #if WORDS_BIGENDIAN 510 : v = util_swap32(v); 511 : #endif - 512 8307408 : return v; + 512 8307428 : return v; 513 : } 514 : - 515 7722914 : static inline uint64_t util_read64(const void* ptr) + 515 7722984 : static inline uint64_t util_read64(const void* ptr) 516 : { 517 : uint64_t v; - 518 7722914 : memcpy(&v, ptr, sizeof(v)); + 518 7722984 : memcpy(&v, ptr, sizeof(v)); 519 : #if WORDS_BIGENDIAN 520 : v = util_swap64(v); 521 : #endif - 522 7722914 : return v; + 522 7722984 : return v; 523 : } 524 : - 525 8307408 : static inline void util_write32(void* ptr, uint32_t v) + 525 8307428 : static inline void util_write32(void* ptr, uint32_t v) 526 : { 527 : #if WORDS_BIGENDIAN 528 : v = util_swap32(v); 529 : #endif - 530 8307408 : memcpy(ptr, &v, sizeof(v)); - 531 8307408 : } + 530 8307428 : memcpy(ptr, &v, sizeof(v)); + 531 8307428 : } 532 : - 533 7722914 : static inline void util_write64(void* ptr, uint64_t v) + 533 7722984 : static inline void util_write64(void* ptr, uint64_t v) 534 : { 535 : #if WORDS_BIGENDIAN 536 : v = util_swap64(v); 537 : #endif - 538 7722914 : memcpy(ptr, &v, sizeof(v)); - 539 7722914 : } + 538 7722984 : memcpy(ptr, &v, sizeof(v)); + 539 7722984 : } 540 : 541 : /****************************************************************************/ 542 : /* hash */ @@ -606,15 +606,15 @@ 544 : #include "murmur3.c" 545 : #include "spooky2.c" 546 : - 547 5938309 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) + 547 5938349 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) 548 : { - 549 5938309 : switch (kind) { + 549 5938349 : switch (kind) { 550 : case HASH_MURMUR3 : - 551 2076852 : MurmurHash3_x86_128(src, size, seed, digest); - 552 2076852 : break; + 551 2076857 : MurmurHash3_x86_128(src, size, seed, digest); + 552 2076857 : break; 553 : case HASH_SPOOKY2 : - 554 3861457 : SpookyHash128(src, size, seed, digest); - 555 3861457 : break; + 554 3861492 : SpookyHash128(src, size, seed, digest); + 555 3861492 : break; 556 : default : 557 : /* LCOV_EXCL_START */ 558 : log_fatal("Internal inconsistency in hash function %u\n", kind); @@ -622,7 +622,7 @@ 560 : break; 561 : /* LCOV_EXCL_STOP */ 562 : } - 563 5938309 : } + 563 5938349 : } 564 : 565 45 : const char* hash_config_name(unsigned kind) 566 : { @@ -637,23 +637,23 @@ 575 : } 576 : } 577 : - 578 93220 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) + 578 93324 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) 579 : { 580 : size_t i; 581 : unsigned count; 582 : - 583 93220 : count = 0; - 584 80894180 : for (i = 0; i < size; ++i) { + 583 93324 : count = 0; + 584 80906028 : for (i = 0; i < size; ++i) { 585 : unsigned j; - 586 80800960 : unsigned char diff = data1[i] ^ data2[i]; - 587 727208640 : for (j = 0; j < 8; ++j) { - 588 646407680 : if ((diff & 1) != 0) - 589 311424980 : ++count; - 590 646407680 : diff >>= 1; + 586 80812704 : unsigned char diff = data1[i] ^ data2[i]; + 587 727314336 : for (j = 0; j < 8; ++j) { + 588 646501632 : if ((diff & 1) != 0) + 589 311419223 : ++count; + 590 646501632 : diff >>= 1; 591 : } 592 : } 593 : - 594 93220 : return count; + 594 93324 : return count; 595 : } 596 : 597 : /****************************************************************************/ diff --git a/cov/cmdline/util.h.func-sort-c.html b/cov/cmdline/util.h.func-sort-c.html index be791415..71470ec6 100644 --- a/cov/cmdline/util.h.func-sort-c.html +++ b/cov/cmdline/util.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -61,15 +61,15 @@ crc32c_x86_plain - 21365830 + 21365757 crc32c_plain - 20719227 + 20719138 crc32c_plain_char - 3808426 + 3808662 crc32c_gen_plain diff --git a/cov/cmdline/util.h.func.html b/cov/cmdline/util.h.func.html index bb76f47b..e22c16ef 100644 --- a/cov/cmdline/util.h.func.html +++ b/cov/cmdline/util.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -65,15 +65,15 @@ crc32c_plain - 20719227 + 20719138 crc32c_plain_char - 3808426 + 3808662 crc32c_x86_plain - 21365830 + 21365757
diff --git a/cov/cmdline/util.h.gcov.html b/cov/cmdline/util.h.gcov.html index 1d87b293..58272aab 100644 --- a/cov/cmdline/util.h.gcov.html +++ b/cov/cmdline/util.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -144,12 +144,12 @@ 82 : /** 83 : * Compute CRC-32 (Castagnoli) for a single byte without the IV. 84 : */ - 85 3808426 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) + 85 3808662 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) 86 : { 87 : #if HAVE_SSE42 - 88 3808426 : if (tommy_likely(crc_x86)) { - 89 3808426 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); - 90 3808426 : return crc; + 88 3808662 : if (tommy_likely(crc_x86)) { + 89 3808662 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); + 90 3808662 : return crc; 91 : } 92 : #endif 93 0 : return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8); @@ -180,7 +180,7 @@ 118 : * Compute the CRC-32 (Castagnoli) without the IV. 119 : */ 120 : #if HAVE_SSE42 - 121 21365830 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 121 21365757 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 122 : { 123 : #ifdef CONFIG_X86_64 124 : uint64_t crc64 = crc; @@ -191,30 +191,30 @@ 129 : } 130 : crc = crc64; 131 : #else - 132 392452749 : while (size >= 4) { - 133 349721089 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); - 134 349721089 : ptr += 4; - 135 349721089 : size -= 4; + 132 349127638 : while (size >= 4) { + 133 306396124 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); + 134 306396124 : ptr += 4; + 135 306396124 : size -= 4; 136 : } 137 : #endif - 138 62466405 : while (size) { - 139 19734745 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); - 140 19734745 : ++ptr; - 141 19734745 : --size; + 138 61840849 : while (size) { + 139 19109335 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); + 140 19109335 : ++ptr; + 141 19109335 : --size; 142 : } 143 : - 144 21365830 : return crc; + 144 21365757 : return crc; 145 : } 146 : #endif 147 : 148 : /** 149 : * Compute CRC-32 (Castagnoli) without the IV. 150 : */ - 151 20719227 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 151 20719138 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 152 : { 153 : #if HAVE_SSE42 - 154 20719227 : if (tommy_likely(crc_x86)) { - 155 20719227 : return crc32c_x86_plain(crc, ptr, size); + 154 20719138 : if (tommy_likely(crc_x86)) { + 155 20719138 : return crc32c_x86_plain(crc, ptr, size); 156 : } 157 : #endif 158 0 : return crc32c_gen_plain(crc, ptr, size); diff --git a/cov/index-sort-f.html b/cov/index-sort-f.html index ba99cdd3..d8a55378 100644 --- a/cov/index-sort-f.html +++ b/cov/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 11014 - 11905 - 92.5 % + 10971 + 11927 + 92.0 % Date: - 2016-11-21 + 2017-05-13 Functions: - 649 - 664 - 97.7 % + 648 + 665 + 97.4 % @@ -72,12 +72,12 @@ cmdline -
90.8%90.8%
+
90.2%90.2%
- 90.8 % - 8683 / 9562 - 97.0 % - 488 / 503 + 90.2 % + 8640 / 9584 + 96.6 % + 487 / 504 tommyds diff --git a/cov/index-sort-l.html b/cov/index-sort-l.html index 6732e9e4..d4c07db2 100644 --- a/cov/index-sort-l.html +++ b/cov/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 11014 - 11905 - 92.5 % + 10971 + 11927 + 92.0 % Date: - 2016-11-21 + 2017-05-13 Functions: - 649 - 664 - 97.7 % + 648 + 665 + 97.4 % @@ -72,12 +72,12 @@ cmdline -
90.8%90.8%
+
90.2%90.2%
- 90.8 % - 8683 / 9562 - 97.0 % - 488 / 503 + 90.2 % + 8640 / 9584 + 96.6 % + 487 / 504 raid diff --git a/cov/index.html b/cov/index.html index d8000377..8b39adef 100644 --- a/cov/index.html +++ b/cov/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 11014 - 11905 - 92.5 % + 10971 + 11927 + 92.0 % Date: - 2016-11-21 + 2017-05-13 Functions: - 649 - 664 - 97.7 % + 648 + 665 + 97.4 % @@ -72,12 +72,12 @@ cmdline -
90.8%90.8%
+
90.2%90.2%
- 90.8 % - 8683 / 9562 - 97.0 % - 488 / 503 + 90.2 % + 8640 / 9584 + 96.6 % + 487 / 504 raid diff --git a/cov/raid/check.c.func-sort-c.html b/cov/raid/check.c.func-sort-c.html index 359f4f99..a2ddca2f 100644 --- a/cov/raid/check.c.func-sort-c.html +++ b/cov/raid/check.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 diff --git a/cov/raid/check.c.func.html b/cov/raid/check.c.func.html index a3e6f425..2f97978e 100644 --- a/cov/raid/check.c.func.html +++ b/cov/raid/check.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 diff --git a/cov/raid/check.c.gcov.html b/cov/raid/check.c.gcov.html index 3e42bb82..fc0d4901 100644 --- a/cov/raid/check.c.gcov.html +++ b/cov/raid/check.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 diff --git a/cov/raid/combo.h.func-sort-c.html b/cov/raid/combo.h.func-sort-c.html index 8f7c071c..62280165 100644 --- a/cov/raid/combo.h.func-sort-c.html +++ b/cov/raid/combo.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/combo.h.func.html b/cov/raid/combo.h.func.html index e0b37946..be1c4a51 100644 --- a/cov/raid/combo.h.func.html +++ b/cov/raid/combo.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/combo.h.gcov.html b/cov/raid/combo.h.gcov.html index c9aec85c..ce38279e 100644 --- a/cov/raid/combo.h.gcov.html +++ b/cov/raid/combo.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 @@ -170,10 +170,10 @@ 108 : int i; 109 : 110 : (void)n; /* unused, but kept for clarity */ - 111 207740 : assert(0 < r && r <= n); + 111 207883 : assert(0 < r && r <= n); 112 : - 113 688823 : for (i = 0; i < r; ++i) - 114 481083 : c[i] = i; + 113 689228 : for (i = 0; i < r; ++i) + 114 481345 : c[i] = i; 115 : } 116 : 117 : /** @@ -182,19 +182,19 @@ 120 : */ 121 : static __always_inline int combination_next(int r, int n, int *c) 122 : { - 123 52213 : int i = r - 1; /* present position */ - 124 52213 : int h = n; /* high limit for this position */ + 123 52183 : int i = r - 1; /* present position */ + 124 52183 : int h = n; /* high limit for this position */ 125 : 126 : recurse: 127 : /* next element at position i */ - 128 85086 : ++c[i]; + 128 85056 : ++c[i]; 129 : 130 : /* if the position has reached the max */ - 131 85086 : if (c[i] >= h) { + 131 85056 : if (c[i] >= h) { 132 : 133 : /* if we are at the first level, we have finished */ - 134 45038 : if (i == 0) - 135 12165 : return 0; + 134 45028 : if (i == 0) + 135 12155 : return 0; 136 : 137 : /* increase the previous position */ 138 32873 : --i; @@ -202,16 +202,16 @@ 140 : goto recurse; 141 : } 142 : - 143 40048 : ++i; + 143 40028 : ++i; 144 : 145 : /* initialize all the next positions, if any */ - 146 62593 : while (i < r) { + 146 62573 : while (i < r) { 147 : /* each position start at the next value of the previous one */ 148 22545 : c[i] = c[i - 1] + 1; 149 22545 : ++i; 150 : } 151 : - 152 40048 : return 1; + 152 40028 : return 1; 153 : } 154 : #endif 155 : diff --git a/cov/raid/cpu.h.func-sort-c.html b/cov/raid/cpu.h.func-sort-c.html index 1ff1626d..2ffcbc83 100644 --- a/cov/raid/cpu.h.func-sort-c.html +++ b/cov/raid/cpu.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 12 diff --git a/cov/raid/cpu.h.func.html b/cov/raid/cpu.h.func.html index 72ccd3b3..a3056ec6 100644 --- a/cov/raid/cpu.h.func.html +++ b/cov/raid/cpu.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 12 diff --git a/cov/raid/cpu.h.gcov.html b/cov/raid/cpu.h.gcov.html index f5a1e826..5684fca8 100644 --- a/cov/raid/cpu.h.gcov.html +++ b/cov/raid/cpu.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 12 diff --git a/cov/raid/gf.h.func-sort-c.html b/cov/raid/gf.h.func-sort-c.html index 87a1b765..2caf4886 100644 --- a/cov/raid/gf.h.func-sort-c.html +++ b/cov/raid/gf.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/gf.h.func.html b/cov/raid/gf.h.func.html index fa1b1d4c..9c2e0fae 100644 --- a/cov/raid/gf.h.func.html +++ b/cov/raid/gf.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/gf.h.gcov.html b/cov/raid/gf.h.gcov.html index 51d692be..c61b4bc0 100644 --- a/cov/raid/gf.h.gcov.html +++ b/cov/raid/gf.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 @@ -88,7 +88,7 @@ 26 : */ 27 : static __always_inline uint8_t mul(uint8_t a, uint8_t b) 28 : { - 29 23791770 : return gfmul[a][b]; + 29 23793674 : return gfmul[a][b]; 30 : } 31 : 32 : /* @@ -97,9 +97,9 @@ 35 : */ 36 : static __always_inline uint8_t inv(uint8_t v) 37 : { - 38 635424 : BUG_ON(v == 0); /* division by zero */ + 38 635642 : BUG_ON(v == 0); /* division by zero */ 39 : - 40 635424 : return gfinv[v]; + 40 635642 : return gfinv[v]; 41 : } 42 : 43 : /* @@ -125,7 +125,7 @@ 63 : */ 64 : static __always_inline uint8_t A(int p, int d) 65 : { - 66 2604422 : return gfgen[p][d]; + 66 2604878 : return gfgen[p][d]; 67 : } 68 : 69 : /* @@ -148,12 +148,12 @@ 86 : */ 87 : static __always_inline uint32_t x2_32(uint32_t v) 88 : { - 89 32577344 : uint32_t mask = v & 0x80808080U; + 89 33036096 : uint32_t mask = v & 0x80808080U; 90 : - 91 32577344 : mask = (mask << 1) - (mask >> 7); - 92 32577344 : v = (v << 1) & 0xfefefefeU; - 93 32577344 : v ^= mask & 0x1d1d1d1dU; - 94 32577344 : return v; + 91 33036096 : mask = (mask << 1) - (mask >> 7); + 92 33036096 : v = (v << 1) & 0xfefefefeU; + 93 33036096 : v ^= mask & 0x1d1d1d1dU; + 94 33036096 : return v; 95 : } 96 : 97 : /* @@ -161,12 +161,12 @@ 99 : */ 100 : static __always_inline uint64_t x2_64(uint64_t v) 101 : { - 102 16288672 : uint64_t mask = v & 0x8080808080808080ULL; + 102 16518048 : uint64_t mask = v & 0x8080808080808080ULL; 103 : - 104 16288672 : mask = (mask << 1) - (mask >> 7); - 105 16288672 : v = (v << 1) & 0xfefefefefefefefeULL; - 106 16288672 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL; - 107 16288672 : return v; + 104 16518048 : mask = (mask << 1) - (mask >> 7); + 105 16518048 : v = (v << 1) & 0xfefefefefefefefeULL; + 106 16518048 : v ^= mask & 0x1d1d1d1d1d1d1d1dULL; + 107 16518048 : return v; 108 : } 109 : 110 : /* diff --git a/cov/raid/helper.c.func-sort-c.html b/cov/raid/helper.c.func-sort-c.html index 5f219c44..7e1a23ed 100644 --- a/cov/raid/helper.c.func-sort-c.html +++ b/cov/raid/helper.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/helper.c.func.html b/cov/raid/helper.c.func.html index 4f2ba325..07048a48 100644 --- a/cov/raid/helper.c.func.html +++ b/cov/raid/helper.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/helper.c.gcov.html b/cov/raid/helper.c.gcov.html index 7807e32c..638b18f0 100644 --- a/cov/raid/helper.c.gcov.html +++ b/cov/raid/helper.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/index-sort-f.html b/cov/raid/index-sort-f.html index f76853ec..8b8326d2 100644 --- a/cov/raid/index-sort-f.html +++ b/cov/raid/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 85 diff --git a/cov/raid/index-sort-l.html b/cov/raid/index-sort-l.html index b0f2e8de..a8835134 100644 --- a/cov/raid/index-sort-l.html +++ b/cov/raid/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 85 diff --git a/cov/raid/index.html b/cov/raid/index.html index 05eee1e7..c48051ef 100644 --- a/cov/raid/index.html +++ b/cov/raid/index.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 85 diff --git a/cov/raid/int.c.func-sort-c.html b/cov/raid/int.c.func-sort-c.html index 3f2b190f..2d550ad5 100644 --- a/cov/raid/int.c.func-sort-c.html +++ b/cov/raid/int.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -69,7 +69,7 @@ raid_gen1_int64 - 180 + 183 raid_rec1_int8 @@ -77,15 +77,15 @@ raid_gen1_int32 - 113 + 118 raid_gen2_int64 - 46 + 47 raid_gen2_int32 - 46 + 47 raid_gen3_int8 @@ -101,7 +101,7 @@ raid_gen6_int8 - 15 + 18
diff --git a/cov/raid/int.c.func.html b/cov/raid/int.c.func.html index 9510bc38..39f17525 100644 --- a/cov/raid/int.c.func.html +++ b/cov/raid/int.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -61,19 +61,19 @@ raid_gen1_int32 - 113 + 118 raid_gen1_int64 - 180 + 183 raid_gen2_int32 - 46 + 47 raid_gen2_int64 - 46 + 47 raid_gen3_int8 @@ -89,7 +89,7 @@ raid_gen6_int8 - 15 + 18 raid_rec1_int8 diff --git a/cov/raid/int.c.gcov.html b/cov/raid/int.c.gcov.html index 3ef0c5f6..42a08e4c 100644 --- a/cov/raid/int.c.gcov.html +++ b/cov/raid/int.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -80,9 +80,9 @@ 18 : /* 19 : * GEN1 (RAID5 with xor) 32bit C implementation 20 : */ - 21 113 : void raid_gen1_int32(int nd, size_t size, void **vv) + 21 118 : void raid_gen1_int32(int nd, size_t size, void **vv) 22 : { - 23 113 : uint8_t **v = (uint8_t **)vv; + 23 118 : uint8_t **v = (uint8_t **)vv; 24 : uint8_t *p; 25 : int d, l; 26 : size_t i; @@ -90,27 +90,27 @@ 28 : uint32_t p0; 29 : uint32_t p1; 30 : - 31 113 : l = nd - 1; - 32 113 : p = v[nd]; + 31 118 : l = nd - 1; + 32 118 : p = v[nd]; 33 : - 34 3604689 : for (i = 0; i < size; i += 8) { - 35 3604576 : p0 = v_32(v[l][i]); - 36 3604576 : p1 = v_32(v[l][i + 4]); - 37 28837920 : for (d = l - 1; d >= 0; --d) { - 38 25233344 : p0 ^= v_32(v[d][i]); - 39 25233344 : p1 ^= v_32(v[d][i + 4]); + 34 3768534 : for (i = 0; i < size; i += 8) { + 35 3768416 : p0 = v_32(v[l][i]); + 36 3768416 : p1 = v_32(v[l][i + 4]); + 37 30148640 : for (d = l - 1; d >= 0; --d) { + 38 26380224 : p0 ^= v_32(v[d][i]); + 39 26380224 : p1 ^= v_32(v[d][i + 4]); 40 : } - 41 3604576 : v_32(p[i]) = p0; - 42 3604576 : v_32(p[i + 4]) = p1; + 41 3768416 : v_32(p[i]) = p0; + 42 3768416 : v_32(p[i + 4]) = p1; 43 : } - 44 113 : } + 44 118 : } 45 : 46 : /* 47 : * GEN1 (RAID5 with xor) 64bit C implementation 48 : */ - 49 180 : void raid_gen1_int64(int nd, size_t size, void **vv) + 49 183 : void raid_gen1_int64(int nd, size_t size, void **vv) 50 : { - 51 180 : uint8_t **v = (uint8_t **)vv; + 51 183 : uint8_t **v = (uint8_t **)vv; 52 : uint8_t *p; 53 : int d, l; 54 : size_t i; @@ -118,27 +118,27 @@ 56 : uint64_t p0; 57 : uint64_t p1; 58 : - 59 180 : l = nd - 1; - 60 180 : p = v[nd]; + 59 183 : l = nd - 1; + 60 183 : p = v[nd]; 61 : - 62 2900196 : for (i = 0; i < size; i += 16) { - 63 2900016 : p0 = v_64(v[l][i]); - 64 2900016 : p1 = v_64(v[l][i + 8]); - 65 23200784 : for (d = l - 1; d >= 0; --d) { - 66 20300768 : p0 ^= v_64(v[d][i]); - 67 20300768 : p1 ^= v_64(v[d][i + 8]); + 62 2949351 : for (i = 0; i < size; i += 16) { + 63 2949168 : p0 = v_64(v[l][i]); + 64 2949168 : p1 = v_64(v[l][i + 8]); + 65 23594000 : for (d = l - 1; d >= 0; --d) { + 66 20644832 : p0 ^= v_64(v[d][i]); + 67 20644832 : p1 ^= v_64(v[d][i + 8]); 68 : } - 69 2900016 : v_64(p[i]) = p0; - 70 2900016 : v_64(p[i + 8]) = p1; + 69 2949168 : v_64(p[i]) = p0; + 70 2949168 : v_64(p[i + 8]) = p1; 71 : } - 72 180 : } + 72 183 : } 73 : 74 : /* 75 : * GEN2 (RAID6 with powers of 2) 32bit C implementation 76 : */ - 77 46 : void raid_gen2_int32(int nd, size_t size, void **vv) + 77 47 : void raid_gen2_int32(int nd, size_t size, void **vv) 78 : { - 79 46 : uint8_t **v = (uint8_t **)vv; + 79 47 : uint8_t **v = (uint8_t **)vv; 80 : uint8_t *p; 81 : uint8_t *q; 82 : int d, l; @@ -147,39 +147,39 @@ 85 : uint32_t d0, q0, p0; 86 : uint32_t d1, q1, p1; 87 : - 88 46 : l = nd - 1; - 89 46 : p = v[nd]; - 90 46 : q = v[nd + 1]; + 88 47 : l = nd - 1; + 89 47 : p = v[nd]; + 90 47 : q = v[nd + 1]; 91 : - 92 1409166 : for (i = 0; i < size; i += 8) { - 93 1409120 : q0 = p0 = v_32(v[l][i]); - 94 1409120 : q1 = p1 = v_32(v[l][i + 4]); - 95 11274272 : for (d = l - 1; d >= 0; --d) { - 96 9865152 : d0 = v_32(v[d][i]); - 97 9865152 : d1 = v_32(v[d][i + 4]); + 92 1441935 : for (i = 0; i < size; i += 8) { + 93 1441888 : q0 = p0 = v_32(v[l][i]); + 94 1441888 : q1 = p1 = v_32(v[l][i + 4]); + 95 11536416 : for (d = l - 1; d >= 0; --d) { + 96 10094528 : d0 = v_32(v[d][i]); + 97 10094528 : d1 = v_32(v[d][i + 4]); 98 : - 99 9865152 : p0 ^= d0; - 100 9865152 : p1 ^= d1; + 99 10094528 : p0 ^= d0; + 100 10094528 : p1 ^= d1; 101 : - 102 9865152 : q0 = x2_32(q0); - 103 9865152 : q1 = x2_32(q1); + 102 10094528 : q0 = x2_32(q0); + 103 10094528 : q1 = x2_32(q1); 104 : - 105 9865152 : q0 ^= d0; - 106 9865152 : q1 ^= d1; + 105 10094528 : q0 ^= d0; + 106 10094528 : q1 ^= d1; 107 : } - 108 1409120 : v_32(p[i]) = p0; - 109 1409120 : v_32(p[i + 4]) = p1; - 110 1409120 : v_32(q[i]) = q0; - 111 1409120 : v_32(q[i + 4]) = q1; + 108 1441888 : v_32(p[i]) = p0; + 109 1441888 : v_32(p[i + 4]) = p1; + 110 1441888 : v_32(q[i]) = q0; + 111 1441888 : v_32(q[i + 4]) = q1; 112 : } - 113 46 : } + 113 47 : } 114 : 115 : /* 116 : * GEN2 (RAID6 with powers of 2) 64bit C implementation 117 : */ - 118 46 : void raid_gen2_int64(int nd, size_t size, void **vv) + 118 47 : void raid_gen2_int64(int nd, size_t size, void **vv) 119 : { - 120 46 : uint8_t **v = (uint8_t **)vv; + 120 47 : uint8_t **v = (uint8_t **)vv; 121 : uint8_t *p; 122 : uint8_t *q; 123 : int d, l; @@ -188,32 +188,32 @@ 126 : uint64_t d0, q0, p0; 127 : uint64_t d1, q1, p1; 128 : - 129 46 : l = nd - 1; - 130 46 : p = v[nd]; - 131 46 : q = v[nd + 1]; + 129 47 : l = nd - 1; + 130 47 : p = v[nd]; + 131 47 : q = v[nd + 1]; 132 : - 133 704606 : for (i = 0; i < size; i += 16) { - 134 704560 : q0 = p0 = v_64(v[l][i]); - 135 704560 : q1 = p1 = v_64(v[l][i + 8]); - 136 5637136 : for (d = l - 1; d >= 0; --d) { - 137 4932576 : d0 = v_64(v[d][i]); - 138 4932576 : d1 = v_64(v[d][i + 8]); + 133 720991 : for (i = 0; i < size; i += 16) { + 134 720944 : q0 = p0 = v_64(v[l][i]); + 135 720944 : q1 = p1 = v_64(v[l][i + 8]); + 136 5768208 : for (d = l - 1; d >= 0; --d) { + 137 5047264 : d0 = v_64(v[d][i]); + 138 5047264 : d1 = v_64(v[d][i + 8]); 139 : - 140 4932576 : p0 ^= d0; - 141 4932576 : p1 ^= d1; + 140 5047264 : p0 ^= d0; + 141 5047264 : p1 ^= d1; 142 : - 143 4932576 : q0 = x2_64(q0); - 144 4932576 : q1 = x2_64(q1); + 143 5047264 : q0 = x2_64(q0); + 144 5047264 : q1 = x2_64(q1); 145 : - 146 4932576 : q0 ^= d0; - 147 4932576 : q1 ^= d1; + 146 5047264 : q0 ^= d0; + 147 5047264 : q1 ^= d1; 148 : } - 149 704560 : v_64(p[i]) = p0; - 150 704560 : v_64(p[i + 8]) = p1; - 151 704560 : v_64(q[i]) = q0; - 152 704560 : v_64(q[i + 8]) = q1; + 149 720944 : v_64(p[i]) = p0; + 150 720944 : v_64(p[i + 8]) = p1; + 151 720944 : v_64(q[i]) = q0; + 152 720944 : v_64(q[i + 8]) = q1; 153 : } - 154 46 : } + 154 47 : } 155 : 156 : /* 157 : * GEN3 (triple parity with Cauchy matrix) 8bit C implementation @@ -379,9 +379,9 @@ 317 : * But this is only a kind of reference function, and we are not really 318 : * interested in speed. 319 : */ - 320 15 : void raid_gen6_int8(int nd, size_t size, void **vv) + 320 18 : void raid_gen6_int8(int nd, size_t size, void **vv) 321 : { - 322 15 : uint8_t **v = (uint8_t **)vv; + 322 18 : uint8_t **v = (uint8_t **)vv; 323 : uint8_t *p; 324 : uint8_t *q; 325 : uint8_t *r; @@ -393,45 +393,45 @@ 331 : 332 : uint8_t d0, u0, t0, s0, r0, q0, p0; 333 : - 334 15 : l = nd - 1; - 335 15 : p = v[nd]; - 336 15 : q = v[nd + 1]; - 337 15 : r = v[nd + 2]; - 338 15 : s = v[nd + 3]; - 339 15 : t = v[nd + 4]; - 340 15 : u = v[nd + 5]; + 334 18 : l = nd - 1; + 335 18 : p = v[nd]; + 336 18 : q = v[nd + 1]; + 337 18 : r = v[nd + 2]; + 338 18 : s = v[nd + 3]; + 339 18 : t = v[nd + 4]; + 340 18 : u = v[nd + 5]; 341 : - 342 3408399 : for (i = 0; i < size; i += 1) { - 343 3408384 : p0 = q0 = r0 = s0 = t0 = u0 = 0; - 344 27271424 : for (d = l; d > 0; --d) { - 345 23863040 : d0 = v_8(v[d][i]); + 342 4194834 : for (i = 0; i < size; i += 1) { + 343 4194816 : p0 = q0 = r0 = s0 = t0 = u0 = 0; + 344 33562880 : for (d = l; d > 0; --d) { + 345 29368064 : d0 = v_8(v[d][i]); 346 : - 347 23863040 : p0 ^= d0; - 348 23863040 : q0 ^= gfmul[d0][gfgen[1][d]]; - 349 23863040 : r0 ^= gfmul[d0][gfgen[2][d]]; - 350 23863040 : s0 ^= gfmul[d0][gfgen[3][d]]; - 351 23863040 : t0 ^= gfmul[d0][gfgen[4][d]]; - 352 23863040 : u0 ^= gfmul[d0][gfgen[5][d]]; + 347 29368064 : p0 ^= d0; + 348 29368064 : q0 ^= gfmul[d0][gfgen[1][d]]; + 349 29368064 : r0 ^= gfmul[d0][gfgen[2][d]]; + 350 29368064 : s0 ^= gfmul[d0][gfgen[3][d]]; + 351 29368064 : t0 ^= gfmul[d0][gfgen[4][d]]; + 352 29368064 : u0 ^= gfmul[d0][gfgen[5][d]]; 353 : } 354 : 355 : /* first disk with all coefficients at 1 */ - 356 3408384 : d0 = v_8(v[0][i]); + 356 4194816 : d0 = v_8(v[0][i]); 357 : - 358 3408384 : p0 ^= d0; - 359 3408384 : q0 ^= d0; - 360 3408384 : r0 ^= d0; - 361 3408384 : s0 ^= d0; - 362 3408384 : t0 ^= d0; - 363 3408384 : u0 ^= d0; + 358 4194816 : p0 ^= d0; + 359 4194816 : q0 ^= d0; + 360 4194816 : r0 ^= d0; + 361 4194816 : s0 ^= d0; + 362 4194816 : t0 ^= d0; + 363 4194816 : u0 ^= d0; 364 : - 365 3408384 : v_8(p[i]) = p0; - 366 3408384 : v_8(q[i]) = q0; - 367 3408384 : v_8(r[i]) = r0; - 368 3408384 : v_8(s[i]) = s0; - 369 3408384 : v_8(t[i]) = t0; - 370 3408384 : v_8(u[i]) = u0; + 365 4194816 : v_8(p[i]) = p0; + 366 4194816 : v_8(q[i]) = q0; + 367 4194816 : v_8(r[i]) = r0; + 368 4194816 : v_8(s[i]) = s0; + 369 4194816 : v_8(t[i]) = t0; + 370 4194816 : v_8(u[i]) = u0; 371 : } - 372 15 : } + 372 18 : } 373 : 374 : /* 375 : * Recover failure of one data block at index id[0] using parity at index diff --git a/cov/raid/internal.h.func-sort-c.html b/cov/raid/internal.h.func-sort-c.html index 52c3bb25..df4ad79b 100644 --- a/cov/raid/internal.h.func-sort-c.html +++ b/cov/raid/internal.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/internal.h.func.html b/cov/raid/internal.h.func.html index 45ac5440..e8311124 100644 --- a/cov/raid/internal.h.func.html +++ b/cov/raid/internal.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 diff --git a/cov/raid/internal.h.gcov.html b/cov/raid/internal.h.gcov.html index 8958d14c..c3981909 100644 --- a/cov/raid/internal.h.gcov.html +++ b/cov/raid/internal.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 0 @@ -169,11 +169,11 @@ 107 : */ 108 : static __always_inline void *__align_ptr(void *ptr, uintptr_t size) 109 : { - 110 711884 : uintptr_t offset = (uintptr_t)ptr; + 110 711958 : uintptr_t offset = (uintptr_t)ptr; 111 : - 112 711884 : offset = (offset + size - 1U) & ~(size - 1U); + 112 711958 : offset = (offset + size - 1U) & ~(size - 1U); 113 : - 114 711884 : return (void *)offset; + 114 711958 : return (void *)offset; 115 : } 116 : 117 : /* @@ -294,7 +294,7 @@ 232 : /* that use a weak memory model. To ensure that other processors */ 233 : /* see correctly the data written, we use a store-store memory */ 234 : /* barrier at the end of the asm code */ - 235 1388567 : asm volatile ("sfence" : : : "memory"); + 235 1388797 : asm volatile ("sfence" : : : "memory"); 236 : 237 : /* clobbers registers used in the asm code */ 238 : /* this is required because in the Windows ABI, */ @@ -327,7 +327,7 @@ 265 : /* reset the upper part of the ymm registers */ 266 : /* to avoid the 70 clocks penality on the next */ 267 : /* xmm register use */ - 268 19674 : asm volatile ("vzeroupper" : : : "memory"); + 268 19675 : asm volatile ("vzeroupper" : : : "memory"); 269 : } 270 : #endif 271 : #endif /* CONFIG_X86 */ diff --git a/cov/raid/intz.c.func-sort-c.html b/cov/raid/intz.c.func-sort-c.html index 18ef6699..80d5021d 100644 --- a/cov/raid/intz.c.func-sort-c.html +++ b/cov/raid/intz.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/intz.c.func.html b/cov/raid/intz.c.func.html index 55de5b7d..b2ed069a 100644 --- a/cov/raid/intz.c.func.html +++ b/cov/raid/intz.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/intz.c.gcov.html b/cov/raid/intz.c.gcov.html index cde048b4..0a8d7573 100644 --- a/cov/raid/intz.c.gcov.html +++ b/cov/raid/intz.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/raid/memory.c.func-sort-c.html b/cov/raid/memory.c.func-sort-c.html index e5414239..0ece055a 100644 --- a/cov/raid/memory.c.func-sort-c.html +++ b/cov/raid/memory.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 diff --git a/cov/raid/memory.c.func.html b/cov/raid/memory.c.func.html index c41407b0..43bb1d27 100644 --- a/cov/raid/memory.c.func.html +++ b/cov/raid/memory.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 diff --git a/cov/raid/memory.c.gcov.html b/cov/raid/memory.c.gcov.html index f256592a..51354524 100644 --- a/cov/raid/memory.c.gcov.html +++ b/cov/raid/memory.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 6 @@ -94,7 +94,7 @@ 32 12558 : offset = ((uintptr_t)ptr) % align_size; 33 : 34 12558 : if (offset != 0) - 35 12172 : ptr += align_size - offset; + 35 12173 : ptr += align_size - offset; 36 : 37 12558 : return ptr; 38 : } diff --git a/cov/raid/module.c.func-sort-c.html b/cov/raid/module.c.func-sort-c.html index ec79fad3..9dc89c58 100644 --- a/cov/raid/module.c.func-sort-c.html +++ b/cov/raid/module.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/module.c.func.html b/cov/raid/module.c.func.html index dea2069a..e8155122 100644 --- a/cov/raid/module.c.func.html +++ b/cov/raid/module.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/module.c.gcov.html b/cov/raid/module.c.gcov.html index 5da7dd67..5c10a8e3 100644 --- a/cov/raid/module.c.gcov.html +++ b/cov/raid/module.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/raid.c.func-sort-c.html b/cov/raid/raid.c.func-sort-c.html index 05da72d1..9b412bbd 100644 --- a/cov/raid/raid.c.func-sort-c.html +++ b/cov/raid/raid.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -61,23 +61,23 @@ raid_gen - 1235650 + 1235764 raid_data - 214670 + 214793 raid_invert - 172489 + 172608 raid_delta_gen - 171491 + 171590 raid_rec1of1 - 101560 + 101584 raid_rec diff --git a/cov/raid/raid.c.func.html b/cov/raid/raid.c.func.html index 217f6747..ce892751 100644 --- a/cov/raid/raid.c.func.html +++ b/cov/raid/raid.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -61,19 +61,19 @@ raid_data - 214670 + 214793 raid_delta_gen - 171491 + 171590 raid_gen - 1235650 + 1235764 raid_invert - 172489 + 172608 raid_mode @@ -85,7 +85,7 @@ raid_rec1of1 - 101560 + 101584 raid_rec2of2_int8 diff --git a/cov/raid/raid.c.gcov.html b/cov/raid/raid.c.gcov.html index 918df0e1..35498747 100644 --- a/cov/raid/raid.c.gcov.html +++ b/cov/raid/raid.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 9 @@ -282,17 +282,17 @@ 220 : void (*raid_gen3_ptr)(int nd, size_t size, void **vv); 221 : void (*raid_genz_ptr)(int nd, size_t size, void **vv); 222 : - 223 1235650 : void raid_gen(int nd, int np, size_t size, void **v) + 223 1235764 : void raid_gen(int nd, int np, size_t size, void **v) 224 : { 225 : /* enforce limit on size */ - 226 1235650 : BUG_ON(size % 64 != 0); + 226 1235764 : BUG_ON(size % 64 != 0); 227 : 228 : /* enforce limit on number of failures */ - 229 1235650 : BUG_ON(np < 1); - 230 1235650 : BUG_ON(np > RAID_PARITY_MAX); + 229 1235764 : BUG_ON(np < 1); + 230 1235764 : BUG_ON(np > RAID_PARITY_MAX); 231 : - 232 1235650 : raid_gen_ptr[np - 1](nd, size, v); - 233 1235650 : } + 232 1235764 : raid_gen_ptr[np - 1](nd, size, v); + 233 1235764 : } 234 : 235 : /** 236 : * Inverts the square matrix M of size nxn into V. @@ -305,44 +305,44 @@ 243 : * @V Destination matrix where the result is put. 244 : * @n Number of rows and columns of the matrix. 245 : */ - 246 172489 : void raid_invert(uint8_t *M, uint8_t *V, int n) + 246 172608 : void raid_invert(uint8_t *M, uint8_t *V, int n) 247 : { 248 : int i, j, k; 249 : 250 : /* set the identity matrix in V */ - 251 797524 : for (i = 0; i < n; ++i) - 252 3219332 : for (j = 0; j < n; ++j) - 253 2594297 : V[i * n + j] = i == j; + 251 797881 : for (i = 0; i < n; ++i) + 252 3220046 : for (j = 0; j < n; ++j) + 253 2594773 : V[i * n + j] = i == j; 254 : 255 : /* for each element in the diagonal */ - 256 797524 : for (k = 0; k < n; ++k) { + 256 797881 : for (k = 0; k < n; ++k) { 257 : uint8_t f; 258 : 259 : /* the diagonal element cannot be 0 because */ 260 : /* we are inverting matrices with all the square */ 261 : /* submatrices not singular */ - 262 625035 : BUG_ON(M[k * n + k] == 0); + 262 625273 : BUG_ON(M[k * n + k] == 0); 263 : 264 : /* make the diagonal element to be 1 */ - 265 1250070 : f = inv(M[k * n + k]); - 266 3219332 : for (j = 0; j < n; ++j) { - 267 5188594 : M[k * n + j] = mul(f, M[k * n + j]); - 268 5188594 : V[k * n + j] = mul(f, V[k * n + j]); + 265 1250546 : f = inv(M[k * n + k]); + 266 3220046 : for (j = 0; j < n; ++j) { + 267 5189546 : M[k * n + j] = mul(f, M[k * n + j]); + 268 5189546 : V[k * n + j] = mul(f, V[k * n + j]); 269 : } 270 : 271 : /* make all the elements over and under the diagonal */ 272 : /* to be zero */ - 273 3219332 : for (i = 0; i < n; ++i) { - 274 2594297 : if (i == k) - 275 625035 : continue; - 276 1969262 : f = M[i * n + k]; - 277 11270850 : for (j = 0; j < n; ++j) { - 278 18603176 : M[i * n + j] ^= mul(f, M[k * n + j]); - 279 18603176 : V[i * n + j] ^= mul(f, V[k * n + j]); + 273 3220046 : for (i = 0; i < n; ++i) { + 274 2594773 : if (i == k) + 275 625273 : continue; + 276 1969500 : f = M[i * n + k]; + 277 11271564 : for (j = 0; j < n; ++j) { + 278 18604128 : M[i * n + j] ^= mul(f, M[k * n + j]); + 279 18604128 : V[i * n + j] ^= mul(f, V[k * n + j]); 280 : } 281 : } 282 : } - 283 172489 : } + 283 172608 : } 284 : 285 : /** 286 : * Computes the parity without the missing data blocks @@ -350,7 +350,7 @@ 288 : * 289 : * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua in the equations. 290 : */ - 291 171491 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) + 291 171590 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) 292 : { 293 : void *p[RAID_PARITY_MAX]; 294 : void *pa[RAID_PARITY_MAX]; @@ -360,17 +360,17 @@ 298 : 299 : /* total number of parities we are going to process */ 300 : /* they are both the used and the unused ones */ - 301 171491 : np = ip[nr - 1] + 1; + 301 171590 : np = ip[nr - 1] + 1; 302 : 303 : /* latest missing data block */ - 304 171491 : latest = v[id[nr - 1]]; + 304 171590 : latest = v[id[nr - 1]]; 305 : 306 : /* setup pointers for delta computation */ - 307 873017 : for (i = 0, j = 0; i < np; ++i) { + 307 873314 : for (i = 0, j = 0; i < np; ++i) { 308 : /* keep a copy of the original parity vector */ - 309 701526 : p[i] = v[nd + i]; + 309 701724 : p[i] = v[nd + i]; 310 : - 311 701526 : if (ip[j] == i) { + 311 701724 : if (ip[j] == i) { 312 : /* 313 : * Set used parities to point to the missing 314 : * data blocks. @@ -381,19 +381,19 @@ 319 : 320 : /* the latest parity to use ends the for loop and */ 321 : /* then it cannot happen to process more of them */ - 322 605363 : BUG_ON(j >= nr); + 322 605581 : BUG_ON(j >= nr); 323 : 324 : /* buffer for missing data blocks */ - 325 605363 : pa[j] = v[id[j]]; + 325 605581 : pa[j] = v[id[j]]; 326 : 327 : /* set at zero the missing data blocks */ - 328 605363 : v[id[j]] = raid_zero_block; + 328 605581 : v[id[j]] = raid_zero_block; 329 : 330 : /* compute the parity over the missing data blocks */ - 331 605363 : v[nd + i] = pa[j]; + 331 605581 : v[nd + i] = pa[j]; 332 : 333 : /* check for the next used entry */ - 334 605363 : ++j; + 334 605581 : ++j; 335 : } else { 336 : /* 337 : * Unused parities are going to be rewritten with @@ -413,25 +413,25 @@ 351 : * multiple times and only the latest write will 352 : * contain the correct data. 353 : */ - 354 96163 : v[nd + i] = latest; + 354 96143 : v[nd + i] = latest; 355 : } 356 : } 357 : 358 : /* all the parities have to be processed */ - 359 171491 : BUG_ON(j != nr); + 359 171590 : BUG_ON(j != nr); 360 : 361 : /* recompute the parity, note that np may be smaller than the */ 362 : /* total number of parities available */ - 363 171491 : raid_gen(nd, np, size, v); + 363 171590 : raid_gen(nd, np, size, v); 364 : 365 : /* restore data buffers as before */ - 366 776854 : for (j = 0; j < nr; ++j) - 367 605363 : v[id[j]] = pa[j]; + 366 777171 : for (j = 0; j < nr; ++j) + 367 605581 : v[id[j]] = pa[j]; 368 : 369 : /* restore parity buffers as before */ - 370 873017 : for (i = 0; i < np; ++i) - 371 701526 : v[nd + i] = p[i]; - 372 171491 : } + 370 873314 : for (i = 0; i < np; ++i) + 371 701724 : v[nd + i] = p[i]; + 372 171590 : } 373 : 374 : /** 375 : * Recover failure of one data block for PAR1. @@ -444,29 +444,29 @@ 382 : * 383 : * Dx = Pd 384 : */ - 385 101560 : void raid_rec1of1(int *id, int nd, size_t size, void **v) + 385 101584 : void raid_rec1of1(int *id, int nd, size_t size, void **v) 386 : { 387 : void *p; 388 : void *pa; 389 : 390 : /* for PAR1 we can directly compute the missing block */ 391 : /* and we don't need to use the zero buffer */ - 392 101560 : p = v[nd]; - 393 101560 : pa = v[id[0]]; + 392 101584 : p = v[nd]; + 393 101584 : pa = v[id[0]]; 394 : 395 : /* use the parity as missing data block */ - 396 101560 : v[id[0]] = p; + 396 101584 : v[id[0]] = p; 397 : 398 : /* compute the parity over the missing data block */ - 399 101560 : v[nd] = pa; + 399 101584 : v[nd] = pa; 400 : 401 : /* compute */ - 402 101560 : raid_gen(nd, 1, size, v); + 402 101584 : raid_gen(nd, 1, size, v); 403 : 404 : /* restore as before */ - 405 101560 : v[id[0]] = pa; - 406 101560 : v[nd] = p; - 407 101560 : } + 405 101584 : v[id[0]] = pa; + 406 101584 : v[nd] = p; + 407 101584 : } 408 : 409 : /** 410 : * Recover failure of two data blocks for PAR2. @@ -615,36 +615,36 @@ 553 12 : raid_gen(nd, ir[nr - 1] - nd + 1, size, v); 554 870 : } 555 : - 556 214670 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) + 556 214793 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) 557 : { 558 : /* enforce limit on size */ - 559 214670 : BUG_ON(size % 64 != 0); + 559 214793 : BUG_ON(size % 64 != 0); 560 : 561 : /* enforce limit on number of failures */ - 562 214670 : BUG_ON(nr > nd); - 563 214670 : BUG_ON(nr > RAID_PARITY_MAX); + 562 214793 : BUG_ON(nr > nd); + 563 214793 : BUG_ON(nr > RAID_PARITY_MAX); 564 : 565 : /* enforce order in index vector for data */ - 566 214670 : BUG_ON(nr >= 2 && id[0] >= id[1]); - 567 214670 : BUG_ON(nr >= 3 && id[1] >= id[2]); - 568 214670 : BUG_ON(nr >= 4 && id[2] >= id[3]); - 569 214670 : BUG_ON(nr >= 5 && id[3] >= id[4]); - 570 214670 : BUG_ON(nr >= 6 && id[4] >= id[5]); + 566 214793 : BUG_ON(nr >= 2 && id[0] >= id[1]); + 567 214793 : BUG_ON(nr >= 3 && id[1] >= id[2]); + 568 214793 : BUG_ON(nr >= 4 && id[2] >= id[3]); + 569 214793 : BUG_ON(nr >= 5 && id[3] >= id[4]); + 570 214793 : BUG_ON(nr >= 6 && id[4] >= id[5]); 571 : 572 : /* enforce limit on index vector for data */ - 573 214670 : BUG_ON(nr > 0 && id[nr-1] >= nd); + 573 214793 : BUG_ON(nr > 0 && id[nr-1] >= nd); 574 : 575 : /* enforce order in index vector for parity */ - 576 214670 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); - 577 214670 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); - 578 214670 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); - 579 214670 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); - 580 214670 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); + 576 214793 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); + 577 214793 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); + 578 214793 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); + 579 214793 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); + 580 214793 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); 581 : 582 : /* if failed data is present */ - 583 214670 : if (nr != 0) - 584 214668 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); - 585 214670 : } + 583 214793 : if (nr != 0) + 584 214791 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); + 585 214793 : } 586 : diff --git a/cov/raid/tag.c.func-sort-c.html b/cov/raid/tag.c.func-sort-c.html index 1f9b9cc9..5886f163 100644 --- a/cov/raid/tag.c.func-sort-c.html +++ b/cov/raid/tag.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 diff --git a/cov/raid/tag.c.func.html b/cov/raid/tag.c.func.html index ed516e06..ac6d52b3 100644 --- a/cov/raid/tag.c.func.html +++ b/cov/raid/tag.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 diff --git a/cov/raid/tag.c.gcov.html b/cov/raid/tag.c.gcov.html index c32dfdec..5fc80304 100644 --- a/cov/raid/tag.c.gcov.html +++ b/cov/raid/tag.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 diff --git a/cov/raid/test.c.func-sort-c.html b/cov/raid/test.c.func-sort-c.html index f0ff52fe..c06e625f 100644 --- a/cov/raid/test.c.func-sort-c.html +++ b/cov/raid/test.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/test.c.func.html b/cov/raid/test.c.func.html index f1adbb5b..b49cc7a1 100644 --- a/cov/raid/test.c.func.html +++ b/cov/raid/test.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/test.c.gcov.html b/cov/raid/test.c.gcov.html index f06db169..bf8c0609 100644 --- a/cov/raid/test.c.gcov.html +++ b/cov/raid/test.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 7 diff --git a/cov/raid/x86.c.func-sort-c.html b/cov/raid/x86.c.func-sort-c.html index d8bd9c3e..9c4f11bc 100644 --- a/cov/raid/x86.c.func-sort-c.html +++ b/cov/raid/x86.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 14 @@ -61,19 +61,19 @@ raid_gen6_ssse3 - 564177 + 564249 raid_gen1_sse2 - 288948 + 288895 raid_gen2_sse2 - 268716 + 268822 raid_rec1_ssse3 - 111395 + 111399 raid_recX_ssse3 @@ -81,11 +81,11 @@ raid_gen5_ssse3 - 50654 + 50656 raid_rec2_ssse3 - 44038 + 44157 raid_gen4_ssse3 @@ -93,7 +93,7 @@ raid_gen3_ssse3 - 29542 + 29541 raid_recX_avx2 @@ -113,7 +113,7 @@ raid_gen1_avx2 - 97 + 98
diff --git a/cov/raid/x86.c.func.html b/cov/raid/x86.c.func.html index 80a9bfea..4b7e9dd9 100644 --- a/cov/raid/x86.c.func.html +++ b/cov/raid/x86.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 14 @@ -61,11 +61,11 @@ raid_gen1_avx2 - 97 + 98 raid_gen1_sse2 - 288948 + 288895 raid_gen2_avx2 @@ -73,11 +73,11 @@ raid_gen2_sse2 - 268716 + 268822 raid_gen3_ssse3 - 29542 + 29541 raid_gen4_ssse3 @@ -85,11 +85,11 @@ raid_gen5_ssse3 - 50654 + 50656 raid_gen6_ssse3 - 564177 + 564249 raid_rec1_avx2 @@ -97,7 +97,7 @@ raid_rec1_ssse3 - 111395 + 111399 raid_rec2_avx2 @@ -105,7 +105,7 @@ raid_rec2_ssse3 - 44038 + 44157 raid_recX_avx2 diff --git a/cov/raid/x86.c.gcov.html b/cov/raid/x86.c.gcov.html index 7c8a2e85..35b792da 100644 --- a/cov/raid/x86.c.gcov.html +++ b/cov/raid/x86.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 14 @@ -95,37 +95,37 @@ 33 : * cache block, and processing 128 bytes doesn't increase performance, and in 34 : * some cases it even decreases it. 35 : */ - 36 288948 : void raid_gen1_sse2(int nd, size_t size, void **vv) + 36 288895 : void raid_gen1_sse2(int nd, size_t size, void **vv) 37 : { - 38 288948 : uint8_t **v = (uint8_t **)vv; + 38 288895 : uint8_t **v = (uint8_t **)vv; 39 : uint8_t *p; 40 : int d, l; 41 : size_t i; 42 : - 43 288948 : l = nd - 1; - 44 288948 : p = v[nd]; + 43 288895 : l = nd - 1; + 44 288895 : p = v[nd]; 45 : 46 : raid_sse_begin(); 47 : - 48 6140160 : for (i = 0; i < size; i += 64) { - 49 5851212 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 50 5851212 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 51 5851212 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); - 52 5851212 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); - 53 37573252 : for (d = l - 1; d >= 0; --d) { - 54 31722040 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); - 55 31722040 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); - 56 31722040 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); - 57 31722040 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); + 48 6155579 : for (i = 0; i < size; i += 64) { + 49 5866684 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 50 5866684 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 51 5866684 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + 52 5866684 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + 53 37698852 : for (d = l - 1; d >= 0; --d) { + 54 31832168 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); + 55 31832168 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); + 56 31832168 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); + 57 31832168 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); 58 : } - 59 5851212 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 60 5851212 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 61 5851212 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); - 62 5851212 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + 59 5866684 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 60 5866684 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 61 5866684 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + 62 5866684 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); 63 : } 64 : 65 : raid_sse_end(); - 66 288948 : } + 66 288895 : } 67 : #endif 68 : 69 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2) @@ -136,31 +136,31 @@ 74 : * cache block, and processing 128 bytes doesn't increase performance, and in 75 : * some cases it even decreases it. 76 : */ - 77 97 : void raid_gen1_avx2(int nd, size_t size, void **vv) + 77 98 : void raid_gen1_avx2(int nd, size_t size, void **vv) 78 : { - 79 97 : uint8_t **v = (uint8_t **)vv; + 79 98 : uint8_t **v = (uint8_t **)vv; 80 : uint8_t *p; 81 : int d, l; 82 : size_t i; 83 : - 84 97 : l = nd - 1; - 85 97 : p = v[nd]; + 84 98 : l = nd - 1; + 85 98 : p = v[nd]; 86 : 87 : raid_avx_begin(); 88 : - 89 50189 : for (i = 0; i < size; i += 64) { - 90 50092 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); - 91 50092 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); - 92 407172 : for (d = l - 1; d >= 0; --d) { - 93 357080 : asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i])); - 94 357080 : asm volatile ("vpxor %0,%%ymm1,%%ymm1" : : "m" (v[d][i + 32])); + 89 54286 : for (i = 0; i < size; i += 64) { + 90 54188 : asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + 91 54188 : asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); + 92 439940 : for (d = l - 1; d >= 0; --d) { + 93 385752 : asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i])); + 94 385752 : asm volatile ("vpxor %0,%%ymm1,%%ymm1" : : "m" (v[d][i + 32])); 95 : } - 96 50092 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); - 97 50092 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); + 96 54188 : asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + 97 54188 : asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); 98 : } 99 : 100 : raid_avx_end(); - 101 97 : } + 101 98 : } 102 : #endif 103 : 104 : #if defined(CONFIG_X86) && defined(CONFIG_SSE2) @@ -183,54 +183,54 @@ 121 : /* 122 : * GEN2 (RAID6 with powers of 2) SSE2 implementation 123 : */ - 124 268716 : void raid_gen2_sse2(int nd, size_t size, void **vv) + 124 268822 : void raid_gen2_sse2(int nd, size_t size, void **vv) 125 : { - 126 268716 : uint8_t **v = (uint8_t **)vv; + 126 268822 : uint8_t **v = (uint8_t **)vv; 127 : uint8_t *p; 128 : uint8_t *q; 129 : int d, l; 130 : size_t i; 131 : - 132 268716 : l = nd - 1; - 133 268716 : p = v[nd]; - 134 268716 : q = v[nd + 1]; + 132 268822 : l = nd - 1; + 133 268822 : p = v[nd]; + 134 268822 : q = v[nd + 1]; 135 : 136 : raid_sse_begin(); 137 : - 138 268716 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 138 268822 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 139 : - 140 10785156 : for (i = 0; i < size; i += 32) { - 141 10516440 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 142 10516440 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 143 10516440 : asm volatile ("movdqa %xmm0,%xmm2"); - 144 10516440 : asm volatile ("movdqa %xmm1,%xmm3"); - 145 66949256 : for (d = l - 1; d >= 0; --d) { - 146 56432816 : asm volatile ("pxor %xmm4,%xmm4"); - 147 56432816 : asm volatile ("pxor %xmm5,%xmm5"); - 148 56432816 : asm volatile ("pcmpgtb %xmm2,%xmm4"); - 149 56432816 : asm volatile ("pcmpgtb %xmm3,%xmm5"); - 150 56432816 : asm volatile ("paddb %xmm2,%xmm2"); - 151 56432816 : asm volatile ("paddb %xmm3,%xmm3"); - 152 56432816 : asm volatile ("pand %xmm7,%xmm4"); - 153 56432816 : asm volatile ("pand %xmm7,%xmm5"); - 154 56432816 : asm volatile ("pxor %xmm4,%xmm2"); - 155 56432816 : asm volatile ("pxor %xmm5,%xmm3"); + 140 10845774 : for (i = 0; i < size; i += 32) { + 141 10576952 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 142 10576952 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 143 10576952 : asm volatile ("movdqa %xmm0,%xmm2"); + 144 10576952 : asm volatile ("movdqa %xmm1,%xmm3"); + 145 67427016 : for (d = l - 1; d >= 0; --d) { + 146 56850064 : asm volatile ("pxor %xmm4,%xmm4"); + 147 56850064 : asm volatile ("pxor %xmm5,%xmm5"); + 148 56850064 : asm volatile ("pcmpgtb %xmm2,%xmm4"); + 149 56850064 : asm volatile ("pcmpgtb %xmm3,%xmm5"); + 150 56850064 : asm volatile ("paddb %xmm2,%xmm2"); + 151 56850064 : asm volatile ("paddb %xmm3,%xmm3"); + 152 56850064 : asm volatile ("pand %xmm7,%xmm4"); + 153 56850064 : asm volatile ("pand %xmm7,%xmm5"); + 154 56850064 : asm volatile ("pxor %xmm4,%xmm2"); + 155 56850064 : asm volatile ("pxor %xmm5,%xmm3"); 156 : - 157 56432816 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 158 56432816 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16])); - 159 56432816 : asm volatile ("pxor %xmm4,%xmm0"); - 160 56432816 : asm volatile ("pxor %xmm5,%xmm1"); - 161 56432816 : asm volatile ("pxor %xmm4,%xmm2"); - 162 56432816 : asm volatile ("pxor %xmm5,%xmm3"); + 157 56850064 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 158 56850064 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16])); + 159 56850064 : asm volatile ("pxor %xmm4,%xmm0"); + 160 56850064 : asm volatile ("pxor %xmm5,%xmm1"); + 161 56850064 : asm volatile ("pxor %xmm4,%xmm2"); + 162 56850064 : asm volatile ("pxor %xmm5,%xmm3"); 163 : } - 164 10516440 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 165 10516440 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 166 10516440 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i])); - 167 10516440 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16])); + 164 10576952 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 165 10576952 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 166 10576952 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i])); + 167 10576952 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16])); 168 : } 169 : 170 : raid_sse_end(); - 171 268716 : } + 171 268822 : } 172 : #endif 173 : 174 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2) @@ -370,93 +370,93 @@ 308 : /* 309 : * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation 310 : */ - 311 29542 : void raid_gen3_ssse3(int nd, size_t size, void **vv) + 311 29541 : void raid_gen3_ssse3(int nd, size_t size, void **vv) 312 : { - 313 29542 : uint8_t **v = (uint8_t **)vv; + 313 29541 : uint8_t **v = (uint8_t **)vv; 314 : uint8_t *p; 315 : uint8_t *q; 316 : uint8_t *r; 317 : int d, l; 318 : size_t i; 319 : - 320 29542 : l = nd - 1; - 321 29542 : p = v[nd]; - 322 29542 : q = v[nd + 1]; - 323 29542 : r = v[nd + 2]; + 320 29541 : l = nd - 1; + 321 29541 : p = v[nd]; + 322 29541 : q = v[nd + 1]; + 323 29541 : r = v[nd + 2]; 324 : 325 : /* special case with only one data disk */ - 326 29542 : if (l == 0) { + 326 29541 : if (l == 0) { 327 4 : for (i = 0; i < 3; ++i) 328 3 : memcpy(v[1 + i], v[0], size); - 329 29543 : return; + 329 29542 : return; 330 : } 331 : 332 : raid_sse_begin(); 333 : 334 : /* generic case with at least two data disks */ - 335 29541 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); - 336 29541 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 335 29540 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); + 336 29540 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 337 : - 338 4888821 : for (i = 0; i < size; i += 16) { + 338 4872436 : for (i = 0; i < size; i += 16) { 339 : /* last disk without the by two multiplication */ - 340 4859280 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 340 4842896 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 341 : - 342 4859280 : asm volatile ("movdqa %xmm4,%xmm0"); - 343 4859280 : asm volatile ("movdqa %xmm4,%xmm1"); + 342 4842896 : asm volatile ("movdqa %xmm4,%xmm0"); + 343 4842896 : asm volatile ("movdqa %xmm4,%xmm1"); 344 : - 345 4859280 : asm volatile ("movdqa %xmm4,%xmm5"); - 346 4859280 : asm volatile ("psrlw $4,%xmm5"); - 347 4859280 : asm volatile ("pand %xmm7,%xmm4"); - 348 4859280 : asm volatile ("pand %xmm7,%xmm5"); + 345 4842896 : asm volatile ("movdqa %xmm4,%xmm5"); + 346 4842896 : asm volatile ("psrlw $4,%xmm5"); + 347 4842896 : asm volatile ("pand %xmm7,%xmm4"); + 348 4842896 : asm volatile ("pand %xmm7,%xmm5"); 349 : - 350 4859280 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); - 351 4859280 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); - 352 4859280 : asm volatile ("pshufb %xmm4,%xmm2"); - 353 4859280 : asm volatile ("pshufb %xmm5,%xmm6"); - 354 4859280 : asm volatile ("pxor %xmm6,%xmm2"); + 350 4842896 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + 351 4842896 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); + 352 4842896 : asm volatile ("pshufb %xmm4,%xmm2"); + 353 4842896 : asm volatile ("pshufb %xmm5,%xmm6"); + 354 4842896 : asm volatile ("pxor %xmm6,%xmm2"); 355 : 356 : /* intermediate disks */ - 357 30489328 : for (d = l - 1; d > 0; --d) { - 358 25630048 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 357 30374640 : for (d = l - 1; d > 0; --d) { + 358 25531744 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 359 : - 360 25630048 : asm volatile ("pxor %xmm5,%xmm5"); - 361 25630048 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 362 25630048 : asm volatile ("paddb %xmm1,%xmm1"); - 363 25630048 : asm volatile ("pand %xmm3,%xmm5"); - 364 25630048 : asm volatile ("pxor %xmm5,%xmm1"); + 360 25531744 : asm volatile ("pxor %xmm5,%xmm5"); + 361 25531744 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 362 25531744 : asm volatile ("paddb %xmm1,%xmm1"); + 363 25531744 : asm volatile ("pand %xmm3,%xmm5"); + 364 25531744 : asm volatile ("pxor %xmm5,%xmm1"); 365 : - 366 25630048 : asm volatile ("pxor %xmm4,%xmm0"); - 367 25630048 : asm volatile ("pxor %xmm4,%xmm1"); + 366 25531744 : asm volatile ("pxor %xmm4,%xmm0"); + 367 25531744 : asm volatile ("pxor %xmm4,%xmm1"); 368 : - 369 25630048 : asm volatile ("movdqa %xmm4,%xmm5"); - 370 25630048 : asm volatile ("psrlw $4,%xmm5"); - 371 25630048 : asm volatile ("pand %xmm7,%xmm4"); - 372 25630048 : asm volatile ("pand %xmm7,%xmm5"); + 369 25531744 : asm volatile ("movdqa %xmm4,%xmm5"); + 370 25531744 : asm volatile ("psrlw $4,%xmm5"); + 371 25531744 : asm volatile ("pand %xmm7,%xmm4"); + 372 25531744 : asm volatile ("pand %xmm7,%xmm5"); 373 : - 374 25630048 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 375 25630048 : asm volatile ("pshufb %xmm4,%xmm6"); - 376 25630048 : asm volatile ("pxor %xmm6,%xmm2"); - 377 25630048 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); - 378 25630048 : asm volatile ("pshufb %xmm5,%xmm6"); - 379 25630048 : asm volatile ("pxor %xmm6,%xmm2"); + 374 25531744 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 375 25531744 : asm volatile ("pshufb %xmm4,%xmm6"); + 376 25531744 : asm volatile ("pxor %xmm6,%xmm2"); + 377 25531744 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); + 378 25531744 : asm volatile ("pshufb %xmm5,%xmm6"); + 379 25531744 : asm volatile ("pxor %xmm6,%xmm2"); 380 : } 381 : 382 : /* first disk with all coefficients at 1 */ - 383 4859280 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 383 4842896 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); 384 : - 385 4859280 : asm volatile ("pxor %xmm5,%xmm5"); - 386 4859280 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 387 4859280 : asm volatile ("paddb %xmm1,%xmm1"); - 388 4859280 : asm volatile ("pand %xmm3,%xmm5"); - 389 4859280 : asm volatile ("pxor %xmm5,%xmm1"); + 385 4842896 : asm volatile ("pxor %xmm5,%xmm5"); + 386 4842896 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 387 4842896 : asm volatile ("paddb %xmm1,%xmm1"); + 388 4842896 : asm volatile ("pand %xmm3,%xmm5"); + 389 4842896 : asm volatile ("pxor %xmm5,%xmm1"); 390 : - 391 4859280 : asm volatile ("pxor %xmm4,%xmm0"); - 392 4859280 : asm volatile ("pxor %xmm4,%xmm1"); - 393 4859280 : asm volatile ("pxor %xmm4,%xmm2"); + 391 4842896 : asm volatile ("pxor %xmm4,%xmm0"); + 392 4842896 : asm volatile ("pxor %xmm4,%xmm1"); + 393 4842896 : asm volatile ("pxor %xmm4,%xmm2"); 394 : - 395 4859280 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 396 4859280 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 397 4859280 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 395 4842896 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 396 4842896 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 397 4842896 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 398 : } 399 : 400 : raid_sse_end(); @@ -1191,9 +1191,9 @@ 1129 : /* 1130 : * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation 1131 : */ - 1132 50654 : void raid_gen5_ssse3(int nd, size_t size, void **vv) + 1132 50656 : void raid_gen5_ssse3(int nd, size_t size, void **vv) 1133 : { - 1134 50654 : uint8_t **v = (uint8_t **)vv; + 1134 50656 : uint8_t **v = (uint8_t **)vv; 1135 : uint8_t *p; 1136 : uint8_t *q; 1137 : uint8_t *r; @@ -1202,122 +1202,122 @@ 1140 : int d, l; 1141 : size_t i; 1142 : uint8_t buffer[16+16]; - 1143 50654 : uint8_t *pd = __align_ptr(buffer, 16); + 1143 50656 : uint8_t *pd = __align_ptr(buffer, 16); 1144 : - 1145 50654 : l = nd - 1; - 1146 50654 : p = v[nd]; - 1147 50654 : q = v[nd + 1]; - 1148 50654 : r = v[nd + 2]; - 1149 50654 : s = v[nd + 3]; - 1150 50654 : t = v[nd + 4]; + 1145 50656 : l = nd - 1; + 1146 50656 : p = v[nd]; + 1147 50656 : q = v[nd + 1]; + 1148 50656 : r = v[nd + 2]; + 1149 50656 : s = v[nd + 3]; + 1150 50656 : t = v[nd + 4]; 1151 : 1152 : /* special case with only one data disk */ - 1153 50654 : if (l == 0) { + 1153 50656 : if (l == 0) { 1154 6 : for (i = 0; i < 5; ++i) 1155 5 : memcpy(v[1 + i], v[0], size); - 1156 50655 : return; + 1156 50657 : return; 1157 : } 1158 : 1159 : raid_sse_begin(); 1160 : 1161 : /* generic case with at least two data disks */ - 1162 3937517 : for (i = 0; i < size; i += 16) { + 1162 3970287 : for (i = 0; i < size; i += 16) { 1163 : /* last disk without the by two multiplication */ - 1164 3886864 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 1164 3919632 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 1165 : - 1166 3886864 : asm volatile ("movdqa %xmm4,%xmm0"); - 1167 3886864 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + 1166 3919632 : asm volatile ("movdqa %xmm4,%xmm0"); + 1167 3919632 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); 1168 : - 1169 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1170 3886864 : asm volatile ("movdqa %xmm4,%xmm5"); - 1171 3886864 : asm volatile ("psrlw $4,%xmm5"); - 1172 3886864 : asm volatile ("pand %xmm7,%xmm4"); - 1173 3886864 : asm volatile ("pand %xmm7,%xmm5"); + 1169 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1170 3919632 : asm volatile ("movdqa %xmm4,%xmm5"); + 1171 3919632 : asm volatile ("psrlw $4,%xmm5"); + 1172 3919632 : asm volatile ("pand %xmm7,%xmm4"); + 1173 3919632 : asm volatile ("pand %xmm7,%xmm5"); 1174 : - 1175 3886864 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0])); - 1176 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); - 1177 3886864 : asm volatile ("pshufb %xmm4,%xmm1"); - 1178 3886864 : asm volatile ("pshufb %xmm5,%xmm7"); - 1179 3886864 : asm volatile ("pxor %xmm7,%xmm1"); + 1175 3919632 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0])); + 1176 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + 1177 3919632 : asm volatile ("pshufb %xmm4,%xmm1"); + 1178 3919632 : asm volatile ("pshufb %xmm5,%xmm7"); + 1179 3919632 : asm volatile ("pxor %xmm7,%xmm1"); 1180 : - 1181 3886864 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0])); - 1182 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); - 1183 3886864 : asm volatile ("pshufb %xmm4,%xmm2"); - 1184 3886864 : asm volatile ("pshufb %xmm5,%xmm7"); - 1185 3886864 : asm volatile ("pxor %xmm7,%xmm2"); + 1181 3919632 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0])); + 1182 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + 1183 3919632 : asm volatile ("pshufb %xmm4,%xmm2"); + 1184 3919632 : asm volatile ("pshufb %xmm5,%xmm7"); + 1185 3919632 : asm volatile ("pxor %xmm7,%xmm2"); 1186 : - 1187 3886864 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0])); - 1188 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); - 1189 3886864 : asm volatile ("pshufb %xmm4,%xmm3"); - 1190 3886864 : asm volatile ("pshufb %xmm5,%xmm7"); - 1191 3886864 : asm volatile ("pxor %xmm7,%xmm3"); + 1187 3919632 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0])); + 1188 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + 1189 3919632 : asm volatile ("pshufb %xmm4,%xmm3"); + 1190 3919632 : asm volatile ("pshufb %xmm5,%xmm7"); + 1191 3919632 : asm volatile ("pxor %xmm7,%xmm3"); 1192 : 1193 : /* intermediate disks */ - 1194 23263984 : for (d = l - 1; d > 0; --d) { - 1195 19377120 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 1196 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); - 1197 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1194 23493360 : for (d = l - 1; d > 0; --d) { + 1195 19573728 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 1196 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + 1197 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1198 : - 1199 19377120 : asm volatile ("pxor %xmm5,%xmm5"); - 1200 19377120 : asm volatile ("pcmpgtb %xmm0,%xmm5"); - 1201 19377120 : asm volatile ("paddb %xmm0,%xmm0"); - 1202 19377120 : asm volatile ("pand %xmm7,%xmm5"); - 1203 19377120 : asm volatile ("pxor %xmm5,%xmm0"); + 1199 19573728 : asm volatile ("pxor %xmm5,%xmm5"); + 1200 19573728 : asm volatile ("pcmpgtb %xmm0,%xmm5"); + 1201 19573728 : asm volatile ("paddb %xmm0,%xmm0"); + 1202 19573728 : asm volatile ("pand %xmm7,%xmm5"); + 1203 19573728 : asm volatile ("pxor %xmm5,%xmm0"); 1204 : - 1205 19377120 : asm volatile ("pxor %xmm4,%xmm0"); - 1206 19377120 : asm volatile ("pxor %xmm4,%xmm6"); - 1207 19377120 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0])); + 1205 19573728 : asm volatile ("pxor %xmm4,%xmm0"); + 1206 19573728 : asm volatile ("pxor %xmm4,%xmm6"); + 1207 19573728 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0])); 1208 : - 1209 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1210 19377120 : asm volatile ("movdqa %xmm4,%xmm5"); - 1211 19377120 : asm volatile ("psrlw $4,%xmm5"); - 1212 19377120 : asm volatile ("pand %xmm7,%xmm4"); - 1213 19377120 : asm volatile ("pand %xmm7,%xmm5"); + 1209 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1210 19573728 : asm volatile ("movdqa %xmm4,%xmm5"); + 1211 19573728 : asm volatile ("psrlw $4,%xmm5"); + 1212 19573728 : asm volatile ("pand %xmm7,%xmm4"); + 1213 19573728 : asm volatile ("pand %xmm7,%xmm5"); 1214 : - 1215 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 1216 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); - 1217 19377120 : asm volatile ("pshufb %xmm4,%xmm6"); - 1218 19377120 : asm volatile ("pshufb %xmm5,%xmm7"); - 1219 19377120 : asm volatile ("pxor %xmm6,%xmm1"); - 1220 19377120 : asm volatile ("pxor %xmm7,%xmm1"); + 1215 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 1216 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + 1217 19573728 : asm volatile ("pshufb %xmm4,%xmm6"); + 1218 19573728 : asm volatile ("pshufb %xmm5,%xmm7"); + 1219 19573728 : asm volatile ("pxor %xmm6,%xmm1"); + 1220 19573728 : asm volatile ("pxor %xmm7,%xmm1"); 1221 : - 1222 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); - 1223 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); - 1224 19377120 : asm volatile ("pshufb %xmm4,%xmm6"); - 1225 19377120 : asm volatile ("pshufb %xmm5,%xmm7"); - 1226 19377120 : asm volatile ("pxor %xmm6,%xmm2"); - 1227 19377120 : asm volatile ("pxor %xmm7,%xmm2"); + 1222 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + 1223 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + 1224 19573728 : asm volatile ("pshufb %xmm4,%xmm6"); + 1225 19573728 : asm volatile ("pshufb %xmm5,%xmm7"); + 1226 19573728 : asm volatile ("pxor %xmm6,%xmm2"); + 1227 19573728 : asm volatile ("pxor %xmm7,%xmm2"); 1228 : - 1229 19377120 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); - 1230 19377120 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); - 1231 19377120 : asm volatile ("pshufb %xmm4,%xmm6"); - 1232 19377120 : asm volatile ("pshufb %xmm5,%xmm7"); - 1233 19377120 : asm volatile ("pxor %xmm6,%xmm3"); - 1234 19377120 : asm volatile ("pxor %xmm7,%xmm3"); + 1229 19573728 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + 1230 19573728 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + 1231 19573728 : asm volatile ("pshufb %xmm4,%xmm6"); + 1232 19573728 : asm volatile ("pshufb %xmm5,%xmm7"); + 1233 19573728 : asm volatile ("pxor %xmm6,%xmm3"); + 1234 19573728 : asm volatile ("pxor %xmm7,%xmm3"); 1235 : } 1236 : 1237 : /* first disk with all coefficients at 1 */ - 1238 3886864 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); - 1239 3886864 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); - 1240 3886864 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1238 3919632 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 1239 3919632 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + 1240 3919632 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1241 : - 1242 3886864 : asm volatile ("pxor %xmm5,%xmm5"); - 1243 3886864 : asm volatile ("pcmpgtb %xmm0,%xmm5"); - 1244 3886864 : asm volatile ("paddb %xmm0,%xmm0"); - 1245 3886864 : asm volatile ("pand %xmm7,%xmm5"); - 1246 3886864 : asm volatile ("pxor %xmm5,%xmm0"); + 1242 3919632 : asm volatile ("pxor %xmm5,%xmm5"); + 1243 3919632 : asm volatile ("pcmpgtb %xmm0,%xmm5"); + 1244 3919632 : asm volatile ("paddb %xmm0,%xmm0"); + 1245 3919632 : asm volatile ("pand %xmm7,%xmm5"); + 1246 3919632 : asm volatile ("pxor %xmm5,%xmm0"); 1247 : - 1248 3886864 : asm volatile ("pxor %xmm4,%xmm0"); - 1249 3886864 : asm volatile ("pxor %xmm4,%xmm1"); - 1250 3886864 : asm volatile ("pxor %xmm4,%xmm2"); - 1251 3886864 : asm volatile ("pxor %xmm4,%xmm3"); - 1252 3886864 : asm volatile ("pxor %xmm4,%xmm6"); + 1248 3919632 : asm volatile ("pxor %xmm4,%xmm0"); + 1249 3919632 : asm volatile ("pxor %xmm4,%xmm1"); + 1250 3919632 : asm volatile ("pxor %xmm4,%xmm2"); + 1251 3919632 : asm volatile ("pxor %xmm4,%xmm3"); + 1252 3919632 : asm volatile ("pxor %xmm4,%xmm6"); 1253 : - 1254 3886864 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i])); - 1255 3886864 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i])); - 1256 3886864 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i])); - 1257 3886864 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i])); - 1258 3886864 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i])); + 1254 3919632 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i])); + 1255 3919632 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i])); + 1256 3919632 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i])); + 1257 3919632 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i])); + 1258 3919632 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i])); 1259 : } 1260 : 1261 : raid_sse_end(); @@ -1591,9 +1591,9 @@ 1529 : /* 1530 : * GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation 1531 : */ - 1532 564177 : void raid_gen6_ssse3(int nd, size_t size, void **vv) + 1532 564249 : void raid_gen6_ssse3(int nd, size_t size, void **vv) 1533 : { - 1534 564177 : uint8_t **v = (uint8_t **)vv; + 1534 564249 : uint8_t **v = (uint8_t **)vv; 1535 : uint8_t *p; 1536 : uint8_t *q; 1537 : uint8_t *r; @@ -1603,142 +1603,142 @@ 1541 : int d, l; 1542 : size_t i; 1543 : uint8_t buffer[2*16+16]; - 1544 564177 : uint8_t *pd = __align_ptr(buffer, 16); + 1544 564249 : uint8_t *pd = __align_ptr(buffer, 16); 1545 : - 1546 564177 : l = nd - 1; - 1547 564177 : p = v[nd]; - 1548 564177 : q = v[nd + 1]; - 1549 564177 : r = v[nd + 2]; - 1550 564177 : s = v[nd + 3]; - 1551 564177 : t = v[nd + 4]; - 1552 564177 : u = v[nd + 5]; + 1546 564249 : l = nd - 1; + 1547 564249 : p = v[nd]; + 1548 564249 : q = v[nd + 1]; + 1549 564249 : r = v[nd + 2]; + 1550 564249 : s = v[nd + 3]; + 1551 564249 : t = v[nd + 4]; + 1552 564249 : u = v[nd + 5]; 1553 : 1554 : /* special case with only one data disk */ - 1555 564177 : if (l == 0) { + 1555 564249 : if (l == 0) { 1556 7 : for (i = 0; i < 6; ++i) 1557 6 : memcpy(v[1 + i], v[0], size); - 1558 564178 : return; + 1558 564250 : return; 1559 : } 1560 : 1561 : raid_sse_begin(); 1562 : 1563 : /* generic case with at least two data disks */ - 1564 36098080 : for (i = 0; i < size; i += 16) { + 1564 36102760 : for (i = 0; i < size; i += 16) { 1565 : /* last disk without the by two multiplication */ - 1566 35533904 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 1566 35538512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 1567 : - 1568 35533904 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); - 1569 35533904 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16])); + 1568 35538512 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + 1569 35538512 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16])); 1570 : - 1571 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1572 35533904 : asm volatile ("movdqa %xmm4,%xmm5"); - 1573 35533904 : asm volatile ("psrlw $4,%xmm5"); - 1574 35533904 : asm volatile ("pand %xmm7,%xmm4"); - 1575 35533904 : asm volatile ("pand %xmm7,%xmm5"); + 1571 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1572 35538512 : asm volatile ("movdqa %xmm4,%xmm5"); + 1573 35538512 : asm volatile ("psrlw $4,%xmm5"); + 1574 35538512 : asm volatile ("pand %xmm7,%xmm4"); + 1575 35538512 : asm volatile ("pand %xmm7,%xmm5"); 1576 : - 1577 35533904 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0])); - 1578 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); - 1579 35533904 : asm volatile ("pshufb %xmm4,%xmm0"); - 1580 35533904 : asm volatile ("pshufb %xmm5,%xmm7"); - 1581 35533904 : asm volatile ("pxor %xmm7,%xmm0"); + 1577 35538512 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0])); + 1578 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + 1579 35538512 : asm volatile ("pshufb %xmm4,%xmm0"); + 1580 35538512 : asm volatile ("pshufb %xmm5,%xmm7"); + 1581 35538512 : asm volatile ("pxor %xmm7,%xmm0"); 1582 : - 1583 35533904 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0])); - 1584 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); - 1585 35533904 : asm volatile ("pshufb %xmm4,%xmm1"); - 1586 35533904 : asm volatile ("pshufb %xmm5,%xmm7"); - 1587 35533904 : asm volatile ("pxor %xmm7,%xmm1"); + 1583 35538512 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0])); + 1584 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + 1585 35538512 : asm volatile ("pshufb %xmm4,%xmm1"); + 1586 35538512 : asm volatile ("pshufb %xmm5,%xmm7"); + 1587 35538512 : asm volatile ("pxor %xmm7,%xmm1"); 1588 : - 1589 35533904 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0])); - 1590 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); - 1591 35533904 : asm volatile ("pshufb %xmm4,%xmm2"); - 1592 35533904 : asm volatile ("pshufb %xmm5,%xmm7"); - 1593 35533904 : asm volatile ("pxor %xmm7,%xmm2"); + 1589 35538512 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0])); + 1590 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + 1591 35538512 : asm volatile ("pshufb %xmm4,%xmm2"); + 1592 35538512 : asm volatile ("pshufb %xmm5,%xmm7"); + 1593 35538512 : asm volatile ("pxor %xmm7,%xmm2"); 1594 : - 1595 35533904 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0])); - 1596 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0])); - 1597 35533904 : asm volatile ("pshufb %xmm4,%xmm3"); - 1598 35533904 : asm volatile ("pshufb %xmm5,%xmm7"); - 1599 35533904 : asm volatile ("pxor %xmm7,%xmm3"); + 1595 35538512 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0])); + 1596 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0])); + 1597 35538512 : asm volatile ("pshufb %xmm4,%xmm3"); + 1598 35538512 : asm volatile ("pshufb %xmm5,%xmm7"); + 1599 35538512 : asm volatile ("pxor %xmm7,%xmm3"); 1600 : 1601 : /* intermediate disks */ - 1602 183674416 : for (d = l - 1; d > 0; --d) { - 1603 148140512 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); - 1604 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); - 1605 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1602 183697456 : for (d = l - 1; d > 0; --d) { + 1603 148158944 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + 1604 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + 1605 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1606 : - 1607 148140512 : asm volatile ("pxor %xmm4,%xmm4"); - 1608 148140512 : asm volatile ("pcmpgtb %xmm6,%xmm4"); - 1609 148140512 : asm volatile ("paddb %xmm6,%xmm6"); - 1610 148140512 : asm volatile ("pand %xmm7,%xmm4"); - 1611 148140512 : asm volatile ("pxor %xmm4,%xmm6"); + 1607 148158944 : asm volatile ("pxor %xmm4,%xmm4"); + 1608 148158944 : asm volatile ("pcmpgtb %xmm6,%xmm4"); + 1609 148158944 : asm volatile ("paddb %xmm6,%xmm6"); + 1610 148158944 : asm volatile ("pand %xmm7,%xmm4"); + 1611 148158944 : asm volatile ("pxor %xmm4,%xmm6"); 1612 : - 1613 148140512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 1613 148158944 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 1614 : - 1615 148140512 : asm volatile ("pxor %xmm4,%xmm5"); - 1616 148140512 : asm volatile ("pxor %xmm4,%xmm6"); - 1617 148140512 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0])); - 1618 148140512 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16])); + 1615 148158944 : asm volatile ("pxor %xmm4,%xmm5"); + 1616 148158944 : asm volatile ("pxor %xmm4,%xmm6"); + 1617 148158944 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0])); + 1618 148158944 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16])); 1619 : - 1620 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1621 148140512 : asm volatile ("movdqa %xmm4,%xmm5"); - 1622 148140512 : asm volatile ("psrlw $4,%xmm5"); - 1623 148140512 : asm volatile ("pand %xmm7,%xmm4"); - 1624 148140512 : asm volatile ("pand %xmm7,%xmm5"); + 1620 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1621 148158944 : asm volatile ("movdqa %xmm4,%xmm5"); + 1622 148158944 : asm volatile ("psrlw $4,%xmm5"); + 1623 148158944 : asm volatile ("pand %xmm7,%xmm4"); + 1624 148158944 : asm volatile ("pand %xmm7,%xmm5"); 1625 : - 1626 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 1627 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); - 1628 148140512 : asm volatile ("pshufb %xmm4,%xmm6"); - 1629 148140512 : asm volatile ("pshufb %xmm5,%xmm7"); - 1630 148140512 : asm volatile ("pxor %xmm6,%xmm0"); - 1631 148140512 : asm volatile ("pxor %xmm7,%xmm0"); + 1626 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 1627 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + 1628 148158944 : asm volatile ("pshufb %xmm4,%xmm6"); + 1629 148158944 : asm volatile ("pshufb %xmm5,%xmm7"); + 1630 148158944 : asm volatile ("pxor %xmm6,%xmm0"); + 1631 148158944 : asm volatile ("pxor %xmm7,%xmm0"); 1632 : - 1633 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); - 1634 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); - 1635 148140512 : asm volatile ("pshufb %xmm4,%xmm6"); - 1636 148140512 : asm volatile ("pshufb %xmm5,%xmm7"); - 1637 148140512 : asm volatile ("pxor %xmm6,%xmm1"); - 1638 148140512 : asm volatile ("pxor %xmm7,%xmm1"); + 1633 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + 1634 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + 1635 148158944 : asm volatile ("pshufb %xmm4,%xmm6"); + 1636 148158944 : asm volatile ("pshufb %xmm5,%xmm7"); + 1637 148158944 : asm volatile ("pxor %xmm6,%xmm1"); + 1638 148158944 : asm volatile ("pxor %xmm7,%xmm1"); 1639 : - 1640 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); - 1641 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); - 1642 148140512 : asm volatile ("pshufb %xmm4,%xmm6"); - 1643 148140512 : asm volatile ("pshufb %xmm5,%xmm7"); - 1644 148140512 : asm volatile ("pxor %xmm6,%xmm2"); - 1645 148140512 : asm volatile ("pxor %xmm7,%xmm2"); + 1640 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + 1641 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + 1642 148158944 : asm volatile ("pshufb %xmm4,%xmm6"); + 1643 148158944 : asm volatile ("pshufb %xmm5,%xmm7"); + 1644 148158944 : asm volatile ("pxor %xmm6,%xmm2"); + 1645 148158944 : asm volatile ("pxor %xmm7,%xmm2"); 1646 : - 1647 148140512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0])); - 1648 148140512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0])); - 1649 148140512 : asm volatile ("pshufb %xmm4,%xmm6"); - 1650 148140512 : asm volatile ("pshufb %xmm5,%xmm7"); - 1651 148140512 : asm volatile ("pxor %xmm6,%xmm3"); - 1652 148140512 : asm volatile ("pxor %xmm7,%xmm3"); + 1647 148158944 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0])); + 1648 148158944 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0])); + 1649 148158944 : asm volatile ("pshufb %xmm4,%xmm6"); + 1650 148158944 : asm volatile ("pshufb %xmm5,%xmm7"); + 1651 148158944 : asm volatile ("pxor %xmm6,%xmm3"); + 1652 148158944 : asm volatile ("pxor %xmm7,%xmm3"); 1653 : } 1654 : 1655 : /* first disk with all coefficients at 1 */ - 1656 35533904 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); - 1657 35533904 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); - 1658 35533904 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1656 35538512 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + 1657 35538512 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + 1658 35538512 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1659 : - 1660 35533904 : asm volatile ("pxor %xmm4,%xmm4"); - 1661 35533904 : asm volatile ("pcmpgtb %xmm6,%xmm4"); - 1662 35533904 : asm volatile ("paddb %xmm6,%xmm6"); - 1663 35533904 : asm volatile ("pand %xmm7,%xmm4"); - 1664 35533904 : asm volatile ("pxor %xmm4,%xmm6"); + 1660 35538512 : asm volatile ("pxor %xmm4,%xmm4"); + 1661 35538512 : asm volatile ("pcmpgtb %xmm6,%xmm4"); + 1662 35538512 : asm volatile ("paddb %xmm6,%xmm6"); + 1663 35538512 : asm volatile ("pand %xmm7,%xmm4"); + 1664 35538512 : asm volatile ("pxor %xmm4,%xmm6"); 1665 : - 1666 35533904 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); - 1667 35533904 : asm volatile ("pxor %xmm4,%xmm0"); - 1668 35533904 : asm volatile ("pxor %xmm4,%xmm1"); - 1669 35533904 : asm volatile ("pxor %xmm4,%xmm2"); - 1670 35533904 : asm volatile ("pxor %xmm4,%xmm3"); - 1671 35533904 : asm volatile ("pxor %xmm4,%xmm5"); - 1672 35533904 : asm volatile ("pxor %xmm4,%xmm6"); + 1666 35538512 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 1667 35538512 : asm volatile ("pxor %xmm4,%xmm0"); + 1668 35538512 : asm volatile ("pxor %xmm4,%xmm1"); + 1669 35538512 : asm volatile ("pxor %xmm4,%xmm2"); + 1670 35538512 : asm volatile ("pxor %xmm4,%xmm3"); + 1671 35538512 : asm volatile ("pxor %xmm4,%xmm5"); + 1672 35538512 : asm volatile ("pxor %xmm4,%xmm6"); 1673 : - 1674 35533904 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i])); - 1675 35533904 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i])); - 1676 35533904 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i])); - 1677 35533904 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i])); - 1678 35533904 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i])); - 1679 35533904 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i])); + 1674 35538512 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i])); + 1675 35538512 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i])); + 1676 35538512 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i])); + 1677 35538512 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i])); + 1678 35538512 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i])); + 1679 35538512 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i])); 1680 : } 1681 : 1682 : raid_sse_end(); @@ -2046,9 +2046,9 @@ 1984 : /* 1985 : * RAID recovering for one disk SSSE3 implementation 1986 : */ - 1987 111395 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 1987 111399 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 1988 : { - 1989 111395 : uint8_t **v = (uint8_t **)vv; + 1989 111399 : uint8_t **v = (uint8_t **)vv; 1990 : uint8_t *p; 1991 : uint8_t *pa; 1992 : uint8_t G; @@ -2058,43 +2058,43 @@ 1996 : (void)nr; /* unused, it's always 1 */ 1997 : 1998 : /* if it's RAID5 uses the faster function */ - 1999 111395 : if (ip[0] == 0) { - 2000 101506 : raid_rec1of1(id, nd, size, vv); - 2001 212901 : return; + 1999 111399 : if (ip[0] == 0) { + 2000 101530 : raid_rec1of1(id, nd, size, vv); + 2001 212929 : return; 2002 : } 2003 : 2004 : /* setup the coefficients matrix */ - 2005 19778 : G = A(ip[0], id[0]); + 2005 19738 : G = A(ip[0], id[0]); 2006 : 2007 : /* invert it to solve the system of linear equations */ - 2008 19778 : V = inv(G); + 2008 19738 : V = inv(G); 2009 : 2010 : /* compute delta parity */ - 2011 9889 : raid_delta_gen(1, id, ip, nd, size, vv); + 2011 9869 : raid_delta_gen(1, id, ip, nd, size, vv); 2012 : - 2013 9889 : p = v[nd + ip[0]]; - 2014 9889 : pa = v[id[0]]; + 2013 9869 : p = v[nd + ip[0]]; + 2014 9869 : pa = v[id[0]]; 2015 : 2016 : raid_sse_begin(); 2017 : - 2018 9889 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 2019 9889 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); - 2020 9889 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); + 2018 9869 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2019 9869 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); + 2020 9869 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); 2021 : - 2022 1552673 : for (i = 0; i < size; i += 16) { - 2023 1542784 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); - 2024 1542784 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); - 2025 1542784 : asm volatile ("movdqa %xmm4,%xmm2"); - 2026 1542784 : asm volatile ("movdqa %xmm5,%xmm3"); - 2027 1542784 : asm volatile ("pxor %xmm0,%xmm1"); - 2028 1542784 : asm volatile ("movdqa %xmm1,%xmm0"); - 2029 1542784 : asm volatile ("psrlw $4,%xmm1"); - 2030 1542784 : asm volatile ("pand %xmm7,%xmm0"); - 2031 1542784 : asm volatile ("pand %xmm7,%xmm1"); - 2032 1542784 : asm volatile ("pshufb %xmm0,%xmm2"); - 2033 1542784 : asm volatile ("pshufb %xmm1,%xmm3"); - 2034 1542784 : asm volatile ("pxor %xmm3,%xmm2"); - 2035 1542784 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); + 2022 1551373 : for (i = 0; i < size; i += 16) { + 2023 1541504 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); + 2024 1541504 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); + 2025 1541504 : asm volatile ("movdqa %xmm4,%xmm2"); + 2026 1541504 : asm volatile ("movdqa %xmm5,%xmm3"); + 2027 1541504 : asm volatile ("pxor %xmm0,%xmm1"); + 2028 1541504 : asm volatile ("movdqa %xmm1,%xmm0"); + 2029 1541504 : asm volatile ("psrlw $4,%xmm1"); + 2030 1541504 : asm volatile ("pand %xmm7,%xmm0"); + 2031 1541504 : asm volatile ("pand %xmm7,%xmm1"); + 2032 1541504 : asm volatile ("pshufb %xmm0,%xmm2"); + 2033 1541504 : asm volatile ("pshufb %xmm1,%xmm3"); + 2034 1541504 : asm volatile ("pxor %xmm3,%xmm2"); + 2035 1541504 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); 2036 : } 2037 : 2038 : raid_sse_end(); @@ -2105,106 +2105,106 @@ 2043 : /* 2044 : * RAID recovering for two disks SSSE3 implementation 2045 : */ - 2046 44038 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 2046 44157 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 2047 : { - 2048 44038 : uint8_t **v = (uint8_t **)vv; - 2049 44038 : const int N = 2; - 2050 44038 : uint8_t *p[N]; - 2051 44038 : uint8_t *pa[N]; - 2052 44038 : uint8_t G[N * N]; - 2053 44038 : uint8_t V[N * N]; + 2048 44157 : uint8_t **v = (uint8_t **)vv; + 2049 44157 : const int N = 2; + 2050 44157 : uint8_t *p[N]; + 2051 44157 : uint8_t *pa[N]; + 2052 44157 : uint8_t G[N * N]; + 2053 44157 : uint8_t V[N * N]; 2054 : size_t i; 2055 : int j, k; 2056 : 2057 : (void)nr; /* unused, it's always 2 */ 2058 : 2059 : /* setup the coefficients matrix */ - 2060 132114 : for (j = 0; j < N; ++j) - 2061 264228 : for (k = 0; k < N; ++k) - 2062 352304 : G[j * N + k] = A(ip[j], id[k]); + 2060 132471 : for (j = 0; j < N; ++j) + 2061 264942 : for (k = 0; k < N; ++k) + 2062 353256 : G[j * N + k] = A(ip[j], id[k]); 2063 : 2064 : /* invert it to solve the system of linear equations */ - 2065 44038 : raid_invert(G, V, N); + 2065 44157 : raid_invert(G, V, N); 2066 : 2067 : /* compute delta parity */ - 2068 44038 : raid_delta_gen(N, id, ip, nd, size, vv); + 2068 44157 : raid_delta_gen(N, id, ip, nd, size, vv); 2069 : - 2070 132114 : for (j = 0; j < N; ++j) { - 2071 88076 : p[j] = v[nd + ip[j]]; - 2072 88076 : pa[j] = v[id[j]]; + 2070 132471 : for (j = 0; j < N; ++j) { + 2071 88314 : p[j] = v[nd + ip[j]]; + 2072 88314 : pa[j] = v[id[j]]; 2073 : } 2074 : 2075 : raid_sse_begin(); 2076 : - 2077 44038 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2077 44157 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 2078 : - 2079 3588806 : for (i = 0; i < size; i += 16) { - 2080 3544768 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); - 2081 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); - 2082 3544768 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); - 2083 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); - 2084 3544768 : asm volatile ("pxor %xmm2,%xmm0"); - 2085 3544768 : asm volatile ("pxor %xmm3,%xmm1"); + 2079 3596541 : for (i = 0; i < size; i += 16) { + 2080 3552384 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); + 2081 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); + 2082 3552384 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); + 2083 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); + 2084 3552384 : asm volatile ("pxor %xmm2,%xmm0"); + 2085 3552384 : asm volatile ("pxor %xmm3,%xmm1"); 2086 : - 2087 3544768 : asm volatile ("pxor %xmm6,%xmm6"); + 2087 3552384 : asm volatile ("pxor %xmm6,%xmm6"); 2088 : - 2089 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); - 2090 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); - 2091 3544768 : asm volatile ("movdqa %xmm0,%xmm4"); - 2092 3544768 : asm volatile ("movdqa %xmm0,%xmm5"); - 2093 3544768 : asm volatile ("psrlw $4,%xmm5"); - 2094 3544768 : asm volatile ("pand %xmm7,%xmm4"); - 2095 3544768 : asm volatile ("pand %xmm7,%xmm5"); - 2096 3544768 : asm volatile ("pshufb %xmm4,%xmm2"); - 2097 3544768 : asm volatile ("pshufb %xmm5,%xmm3"); - 2098 3544768 : asm volatile ("pxor %xmm2,%xmm6"); - 2099 3544768 : asm volatile ("pxor %xmm3,%xmm6"); + 2089 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); + 2090 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); + 2091 3552384 : asm volatile ("movdqa %xmm0,%xmm4"); + 2092 3552384 : asm volatile ("movdqa %xmm0,%xmm5"); + 2093 3552384 : asm volatile ("psrlw $4,%xmm5"); + 2094 3552384 : asm volatile ("pand %xmm7,%xmm4"); + 2095 3552384 : asm volatile ("pand %xmm7,%xmm5"); + 2096 3552384 : asm volatile ("pshufb %xmm4,%xmm2"); + 2097 3552384 : asm volatile ("pshufb %xmm5,%xmm3"); + 2098 3552384 : asm volatile ("pxor %xmm2,%xmm6"); + 2099 3552384 : asm volatile ("pxor %xmm3,%xmm6"); 2100 : - 2101 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); - 2102 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); - 2103 3544768 : asm volatile ("movdqa %xmm1,%xmm4"); - 2104 3544768 : asm volatile ("movdqa %xmm1,%xmm5"); - 2105 3544768 : asm volatile ("psrlw $4,%xmm5"); - 2106 3544768 : asm volatile ("pand %xmm7,%xmm4"); - 2107 3544768 : asm volatile ("pand %xmm7,%xmm5"); - 2108 3544768 : asm volatile ("pshufb %xmm4,%xmm2"); - 2109 3544768 : asm volatile ("pshufb %xmm5,%xmm3"); - 2110 3544768 : asm volatile ("pxor %xmm2,%xmm6"); - 2111 3544768 : asm volatile ("pxor %xmm3,%xmm6"); + 2101 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); + 2102 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); + 2103 3552384 : asm volatile ("movdqa %xmm1,%xmm4"); + 2104 3552384 : asm volatile ("movdqa %xmm1,%xmm5"); + 2105 3552384 : asm volatile ("psrlw $4,%xmm5"); + 2106 3552384 : asm volatile ("pand %xmm7,%xmm4"); + 2107 3552384 : asm volatile ("pand %xmm7,%xmm5"); + 2108 3552384 : asm volatile ("pshufb %xmm4,%xmm2"); + 2109 3552384 : asm volatile ("pshufb %xmm5,%xmm3"); + 2110 3552384 : asm volatile ("pxor %xmm2,%xmm6"); + 2111 3552384 : asm volatile ("pxor %xmm3,%xmm6"); 2112 : - 2113 3544768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); + 2113 3552384 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); 2114 : - 2115 3544768 : asm volatile ("pxor %xmm6,%xmm6"); + 2115 3552384 : asm volatile ("pxor %xmm6,%xmm6"); 2116 : - 2117 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); - 2118 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); - 2119 3544768 : asm volatile ("movdqa %xmm0,%xmm4"); - 2120 3544768 : asm volatile ("movdqa %xmm0,%xmm5"); - 2121 3544768 : asm volatile ("psrlw $4,%xmm5"); - 2122 3544768 : asm volatile ("pand %xmm7,%xmm4"); - 2123 3544768 : asm volatile ("pand %xmm7,%xmm5"); - 2124 3544768 : asm volatile ("pshufb %xmm4,%xmm2"); - 2125 3544768 : asm volatile ("pshufb %xmm5,%xmm3"); - 2126 3544768 : asm volatile ("pxor %xmm2,%xmm6"); - 2127 3544768 : asm volatile ("pxor %xmm3,%xmm6"); + 2117 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); + 2118 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); + 2119 3552384 : asm volatile ("movdqa %xmm0,%xmm4"); + 2120 3552384 : asm volatile ("movdqa %xmm0,%xmm5"); + 2121 3552384 : asm volatile ("psrlw $4,%xmm5"); + 2122 3552384 : asm volatile ("pand %xmm7,%xmm4"); + 2123 3552384 : asm volatile ("pand %xmm7,%xmm5"); + 2124 3552384 : asm volatile ("pshufb %xmm4,%xmm2"); + 2125 3552384 : asm volatile ("pshufb %xmm5,%xmm3"); + 2126 3552384 : asm volatile ("pxor %xmm2,%xmm6"); + 2127 3552384 : asm volatile ("pxor %xmm3,%xmm6"); 2128 : - 2129 3544768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); - 2130 3544768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); - 2131 3544768 : asm volatile ("movdqa %xmm1,%xmm4"); - 2132 3544768 : asm volatile ("movdqa %xmm1,%xmm5"); - 2133 3544768 : asm volatile ("psrlw $4,%xmm5"); - 2134 3544768 : asm volatile ("pand %xmm7,%xmm4"); - 2135 3544768 : asm volatile ("pand %xmm7,%xmm5"); - 2136 3544768 : asm volatile ("pshufb %xmm4,%xmm2"); - 2137 3544768 : asm volatile ("pshufb %xmm5,%xmm3"); - 2138 3544768 : asm volatile ("pxor %xmm2,%xmm6"); - 2139 3544768 : asm volatile ("pxor %xmm3,%xmm6"); + 2129 3552384 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); + 2130 3552384 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); + 2131 3552384 : asm volatile ("movdqa %xmm1,%xmm4"); + 2132 3552384 : asm volatile ("movdqa %xmm1,%xmm5"); + 2133 3552384 : asm volatile ("psrlw $4,%xmm5"); + 2134 3552384 : asm volatile ("pand %xmm7,%xmm4"); + 2135 3552384 : asm volatile ("pand %xmm7,%xmm5"); + 2136 3552384 : asm volatile ("pshufb %xmm4,%xmm2"); + 2137 3552384 : asm volatile ("pshufb %xmm5,%xmm3"); + 2138 3552384 : asm volatile ("pxor %xmm2,%xmm6"); + 2139 3552384 : asm volatile ("pxor %xmm3,%xmm6"); 2140 : - 2141 3544768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); + 2141 3552384 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); 2142 : } 2143 : 2144 : raid_sse_end(); - 2145 44038 : } + 2145 44157 : } 2146 : #endif 2147 : 2148 : #if defined(CONFIG_X86) && defined(CONFIG_SSSE3) diff --git a/cov/raid/x86z.c.func-sort-c.html b/cov/raid/x86z.c.func-sort-c.html index 4b3634ae..f1021661 100644 --- a/cov/raid/x86z.c.func-sort-c.html +++ b/cov/raid/x86z.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ raid_genz_sse2 - 1176 + 1180
diff --git a/cov/raid/x86z.c.func.html b/cov/raid/x86z.c.func.html index b6fdb7c1..a4138197 100644 --- a/cov/raid/x86z.c.func.html +++ b/cov/raid/x86z.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -61,7 +61,7 @@ raid_genz_sse2 - 1176 + 1180
diff --git a/cov/raid/x86z.c.gcov.html b/cov/raid/x86z.c.gcov.html index 6a1f08a2..c32bcabf 100644 --- a/cov/raid/x86z.c.gcov.html +++ b/cov/raid/x86z.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 @@ -102,58 +102,58 @@ 40 : /* 41 : * GENz (triple parity with powers of 2^-1) SSE2 implementation 42 : */ - 43 1176 : void raid_genz_sse2(int nd, size_t size, void **vv) + 43 1180 : void raid_genz_sse2(int nd, size_t size, void **vv) 44 : { - 45 1176 : uint8_t **v = (uint8_t**)vv; + 45 1180 : uint8_t **v = (uint8_t**)vv; 46 : uint8_t *p; 47 : uint8_t *q; 48 : uint8_t *r; 49 : int d, l; 50 : size_t i; 51 : - 52 1176 : l = nd - 1; - 53 1176 : p = v[nd]; - 54 1176 : q = v[nd + 1]; - 55 1176 : r = v[nd + 2]; + 52 1180 : l = nd - 1; + 53 1180 : p = v[nd]; + 54 1180 : q = v[nd + 1]; + 55 1180 : r = v[nd + 2]; 56 : 57 : raid_sse_begin(); 58 : - 59 1176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); - 60 1176 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); - 61 1176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); + 59 1180 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); + 60 1180 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); + 61 1180 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); 62 : - 63 1378536 : for (i = 0; i < size; i += 16) { - 64 1377360 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 65 1377360 : asm volatile ("movdqa %xmm0,%xmm1"); - 66 1377360 : asm volatile ("movdqa %xmm0,%xmm2"); - 67 11089152 : for (d = l - 1; d >= 0; --d) { - 68 9711792 : asm volatile ("pxor %xmm4,%xmm4"); - 69 9711792 : asm volatile ("pcmpgtb %xmm1,%xmm4"); - 70 9711792 : asm volatile ("paddb %xmm1,%xmm1"); - 71 9711792 : asm volatile ("pand %xmm7,%xmm4"); - 72 9711792 : asm volatile ("pxor %xmm4,%xmm1"); + 63 1444076 : for (i = 0; i < size; i += 16) { + 64 1442896 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 65 1442896 : asm volatile ("movdqa %xmm0,%xmm1"); + 66 1442896 : asm volatile ("movdqa %xmm0,%xmm2"); + 67 11613440 : for (d = l - 1; d >= 0; --d) { + 68 10170544 : asm volatile ("pxor %xmm4,%xmm4"); + 69 10170544 : asm volatile ("pcmpgtb %xmm1,%xmm4"); + 70 10170544 : asm volatile ("paddb %xmm1,%xmm1"); + 71 10170544 : asm volatile ("pand %xmm7,%xmm4"); + 72 10170544 : asm volatile ("pxor %xmm4,%xmm1"); 73 : - 74 9711792 : asm volatile ("movdqa %xmm2,%xmm4"); - 75 9711792 : asm volatile ("pxor %xmm5,%xmm5"); - 76 9711792 : asm volatile ("psllw $7,%xmm4"); - 77 9711792 : asm volatile ("psrlw $1,%xmm2"); - 78 9711792 : asm volatile ("pcmpgtb %xmm4,%xmm5"); - 79 9711792 : asm volatile ("pand %xmm6,%xmm2"); - 80 9711792 : asm volatile ("pand %xmm3,%xmm5"); - 81 9711792 : asm volatile ("pxor %xmm5,%xmm2"); + 74 10170544 : asm volatile ("movdqa %xmm2,%xmm4"); + 75 10170544 : asm volatile ("pxor %xmm5,%xmm5"); + 76 10170544 : asm volatile ("psllw $7,%xmm4"); + 77 10170544 : asm volatile ("psrlw $1,%xmm2"); + 78 10170544 : asm volatile ("pcmpgtb %xmm4,%xmm5"); + 79 10170544 : asm volatile ("pand %xmm6,%xmm2"); + 80 10170544 : asm volatile ("pand %xmm3,%xmm5"); + 81 10170544 : asm volatile ("pxor %xmm5,%xmm2"); 82 : - 83 9711792 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 84 9711792 : asm volatile ("pxor %xmm4,%xmm0"); - 85 9711792 : asm volatile ("pxor %xmm4,%xmm1"); - 86 9711792 : asm volatile ("pxor %xmm4,%xmm2"); + 83 10170544 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 84 10170544 : asm volatile ("pxor %xmm4,%xmm0"); + 85 10170544 : asm volatile ("pxor %xmm4,%xmm1"); + 86 10170544 : asm volatile ("pxor %xmm4,%xmm2"); 87 : } - 88 1377360 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 89 1377360 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 90 1377360 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 88 1442896 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 89 1442896 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 90 1442896 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 91 : } 92 : 93 : raid_sse_end(); - 94 1176 : } + 94 1180 : } 95 : #endif 96 : 97 : #if defined(CONFIG_X86_64) && defined(CONFIG_SSE2) diff --git a/cov/tommyds/index-sort-f.html b/cov/tommyds/index-sort-f.html index 1aac10bb..c57172c1 100644 --- a/cov/tommyds/index-sort-f.html +++ b/cov/tommyds/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 76 diff --git a/cov/tommyds/index-sort-l.html b/cov/tommyds/index-sort-l.html index 85809ff9..c06f93f9 100644 --- a/cov/tommyds/index-sort-l.html +++ b/cov/tommyds/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 76 diff --git a/cov/tommyds/index.html b/cov/tommyds/index.html index ad75eb65..7aa8cb14 100644 --- a/cov/tommyds/index.html +++ b/cov/tommyds/index.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 76 diff --git a/cov/tommyds/tommyarray.c.func-sort-c.html b/cov/tommyds/tommyarray.c.func-sort-c.html index 5a3f8371..f0719a77 100644 --- a/cov/tommyds/tommyarray.c.func-sort-c.html +++ b/cov/tommyds/tommyarray.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 diff --git a/cov/tommyds/tommyarray.c.func.html b/cov/tommyds/tommyarray.c.func.html index 945e89e6..dce97b64 100644 --- a/cov/tommyds/tommyarray.c.func.html +++ b/cov/tommyds/tommyarray.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 diff --git a/cov/tommyds/tommyarray.c.gcov.html b/cov/tommyds/tommyarray.c.gcov.html index 19d8f82f..965bc4aa 100644 --- a/cov/tommyds/tommyarray.c.gcov.html +++ b/cov/tommyds/tommyarray.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 diff --git a/cov/tommyds/tommyarray.h.func-sort-c.html b/cov/tommyds/tommyarray.h.func-sort-c.html index 1969ed9c..5a7f3eba 100644 --- a/cov/tommyds/tommyarray.h.func-sort-c.html +++ b/cov/tommyds/tommyarray.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -61,11 +61,11 @@ tommy_array_ref - 10268668 + 10268805 tommy_array_get - 10266454 + 10266591 tommy_array_size diff --git a/cov/tommyds/tommyarray.h.func.html b/cov/tommyds/tommyarray.h.func.html index 4b216f81..fdcaddab 100644 --- a/cov/tommyds/tommyarray.h.func.html +++ b/cov/tommyds/tommyarray.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -61,7 +61,7 @@ tommy_array_get - 10266454 + 10266591 tommy_array_insert @@ -69,7 +69,7 @@ tommy_array_ref - 10268668 + 10268805 tommy_array_set diff --git a/cov/tommyds/tommyarray.h.gcov.html b/cov/tommyds/tommyarray.h.gcov.html index 41939361..200e23cc 100644 --- a/cov/tommyds/tommyarray.h.gcov.html +++ b/cov/tommyds/tommyarray.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -152,16 +152,16 @@ 90 : * You must be sure that space for this position is already 91 : * allocated calling tommy_array_grow(). 92 : */ - 93 10268668 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos) + 93 10268805 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos) 94 : { 95 : tommy_uint_t bsr; 96 : - 97 10268668 : assert(pos < array->count); + 97 10268805 : assert(pos < array->count); 98 : 99 : /* get the highest bit set, in case of all 0, return 0 */ - 100 10268668 : bsr = tommy_ilog2_u32(pos | 1); + 100 10268805 : bsr = tommy_ilog2_u32(pos | 1); 101 : - 102 10268668 : return &array->bucket[bsr][pos]; + 102 10268805 : return &array->bucket[bsr][pos]; 103 : } 104 : 105 : /** @@ -179,9 +179,9 @@ 117 : * You must be sure that space for this position is already 118 : * allocated calling tommy_array_grow(). 119 : */ - 120 10266454 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos) + 120 10266591 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos) 121 : { - 122 10266454 : return *tommy_array_ref(array, pos); + 122 10266591 : return *tommy_array_ref(array, pos); 123 : } 124 : 125 : /** diff --git a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html index ca7ec51f..12188e51 100644 --- a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -61,7 +61,7 @@ tommy_arrayblkof_grow - 1698377 + 1698452 tommy_arrayblkof_init diff --git a/cov/tommyds/tommyarrayblkof.c.func.html b/cov/tommyds/tommyarrayblkof.c.func.html index a2043ce2..11789fbc 100644 --- a/cov/tommyds/tommyarrayblkof.c.func.html +++ b/cov/tommyds/tommyarrayblkof.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -65,7 +65,7 @@ tommy_arrayblkof_grow - 1698377 + 1698452 tommy_arrayblkof_init diff --git a/cov/tommyds/tommyarrayblkof.c.gcov.html b/cov/tommyds/tommyarrayblkof.c.gcov.html index 7c6784d6..52aae83d 100644 --- a/cov/tommyds/tommyarrayblkof.c.gcov.html +++ b/cov/tommyds/tommyarrayblkof.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -110,13 +110,13 @@ 48 245 : tommy_array_done(&array->block); 49 245 : } 50 : - 51 1698377 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count) + 51 1698452 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count) 52 : { 53 : tommy_count_t block_max; 54 : tommy_count_t block_mac; 55 : - 56 1698377 : if (array->count >= count) - 57 1821747 : return; + 56 1698452 : if (array->count >= count) + 57 1821897 : return; 58 1575007 : array->count = count; 59 : 60 1575007 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE; diff --git a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html index f0445720..0d9c497b 100644 --- a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_ref - 6534659 + 6534796 tommy_arrayblkof_size - 5098669 + 5098731
diff --git a/cov/tommyds/tommyarrayblkof.h.func.html b/cov/tommyds/tommyarrayblkof.h.func.html index 63d16647..ba44229b 100644 --- a/cov/tommyds/tommyarrayblkof.h.func.html +++ b/cov/tommyds/tommyarrayblkof.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_ref - 6534659 + 6534796 tommy_arrayblkof_size - 5098669 + 5098731
diff --git a/cov/tommyds/tommyarrayblkof.h.gcov.html b/cov/tommyds/tommyarrayblkof.h.gcov.html index 93bf2682..3349dc0c 100644 --- a/cov/tommyds/tommyarrayblkof.h.gcov.html +++ b/cov/tommyds/tommyarrayblkof.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 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 6534659 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos) + 89 6534796 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos) 90 : { 91 : unsigned char* base; 92 : - 93 6534659 : assert(pos < array->count); + 93 6534796 : assert(pos < array->count); 94 : - 95 6534659 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); + 95 6534796 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); 96 : - 97 6534659 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; + 97 6534796 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; 98 : } 99 : 100 : /** 101 : * Gets the initialized size of the array. 102 : */ - 103 5098669 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array) + 103 5098731 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array) 104 : { - 105 5098669 : return array->count; + 105 5098731 : return array->count; 106 : } 107 : 108 : /** diff --git a/cov/tommyds/tommychain.h.func-sort-c.html b/cov/tommyds/tommychain.h.func-sort-c.html index e2cfdd86..ecb8e710 100644 --- a/cov/tommyds/tommychain.h.func-sort-c.html +++ b/cov/tommyds/tommychain.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -61,19 +61,19 @@ tommy_chain_splice - 4491318 + 4493802 tommy_chain_merge_degenerated - 1283280 + 1283278 tommy_chain_concat - 1276623 + 1276615 tommy_chain_merge - 470639 + 471147 tommy_chain_mergesort diff --git a/cov/tommyds/tommychain.h.func.html b/cov/tommyds/tommychain.h.func.html index 094728af..c92eb3c5 100644 --- a/cov/tommyds/tommychain.h.func.html +++ b/cov/tommyds/tommychain.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -61,15 +61,15 @@ tommy_chain_concat - 1276623 + 1276615 tommy_chain_merge - 470639 + 471147 tommy_chain_merge_degenerated - 1283280 + 1283278 tommy_chain_mergesort @@ -77,7 +77,7 @@ tommy_chain_splice - 4491318 + 4493802
diff --git a/cov/tommyds/tommychain.h.gcov.html b/cov/tommyds/tommychain.h.gcov.html index 0438c98f..a9b05b5c 100644 --- a/cov/tommyds/tommychain.h.gcov.html +++ b/cov/tommyds/tommychain.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 5 @@ -119,83 +119,83 @@ 57 : /** 58 : * Splices a chain in the middle of another chain. 59 : */ - 60 4491318 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) + 60 4493802 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) 61 : { 62 : /* set the prev list */ - 63 4491318 : first_after->prev = second_tail; - 64 4491318 : second_head->prev = first_before; + 63 4493802 : first_after->prev = second_tail; + 64 4493802 : second_head->prev = first_before; 65 : 66 : /* set the next list */ - 67 4491318 : first_before->next = second_head; - 68 4491318 : second_tail->next = first_after; - 69 4491318 : } + 67 4493802 : first_before->next = second_head; + 68 4493802 : second_tail->next = first_after; + 69 4493802 : } 70 : 71 : /** 72 : * Concats two chains. 73 : */ - 74 1276623 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) + 74 1276615 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) 75 : { 76 : /* set the prev list */ - 77 1276623 : second_head->prev = first_tail; + 77 1276615 : second_head->prev = first_tail; 78 : 79 : /* set the next list */ - 80 1276623 : first_tail->next = second_head; - 81 1276623 : } + 80 1276615 : first_tail->next = second_head; + 81 1276615 : } 82 : 83 : /** 84 : * Merges two chains. 85 : */ - 86 470639 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 86 471147 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 87 : { - 88 470639 : tommy_node* first_i = first->head; - 89 470639 : tommy_node* second_i = second->head; + 88 471147 : tommy_node* first_i = first->head; + 89 471147 : tommy_node* second_i = second->head; 90 : 91 : /* merge */ 92 : while (1) { - 93 9777914 : if (cmp(first_i->data, second_i->data) > 0) { - 94 4723551 : tommy_node* next = second_i->next; - 95 4723551 : if (first_i == first->head) { - 96 232233 : tommy_chain_concat(second_i, first_i); - 97 232233 : first->head = second_i; + 93 9786940 : if (cmp(first_i->data, second_i->data) > 0) { + 94 4726143 : tommy_node* next = second_i->next; + 95 4726143 : if (first_i == first->head) { + 96 232341 : tommy_chain_concat(second_i, first_i); + 97 232341 : first->head = second_i; 98 : } else { - 99 4491318 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); + 99 4493802 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); 100 : } - 101 4723551 : if (second_i == second->tail) - 102 238890 : break; - 103 4484661 : second_i = next; + 101 4726143 : if (second_i == second->tail) + 102 239004 : break; + 103 4487139 : second_i = next; 104 : } else { - 105 5054363 : if (first_i == first->tail) { - 106 231749 : tommy_chain_concat(first_i, second_i); - 107 231749 : first->tail = second->tail; - 108 231749 : break; + 105 5060797 : if (first_i == first->tail) { + 106 232143 : tommy_chain_concat(first_i, second_i); + 107 232143 : first->tail = second->tail; + 108 232143 : break; 109 : } - 110 4822614 : first_i = first_i->next; + 110 4828654 : first_i = first_i->next; 111 : } - 112 9307275 : } - 113 470639 : } + 112 9315793 : } + 113 471147 : } 114 : 115 : /** 116 : * Merges two chains managing special degenerated cases. 117 : * It's funtionally equivalent at tommy_chain_merge() but faster with already ordered chains. 118 : */ - 119 1283280 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 119 1283278 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 120 : { 121 : /* identify the condition first <= second */ - 122 1283280 : if (cmp(first->tail->data, second->head->data) <= 0) { - 123 477942 : tommy_chain_concat(first->tail, second->head); - 124 477942 : first->tail = second->tail; - 125 477942 : return; + 122 1283278 : if (cmp(first->tail->data, second->head->data) <= 0) { + 123 477266 : tommy_chain_concat(first->tail, second->head); + 124 477266 : first->tail = second->tail; + 125 477266 : return; 126 : } 127 : 128 : /* identify the condition second < first */ 129 : /* here we must be strict on comparison to keep the sort stable */ - 130 805338 : if (cmp(second->tail->data, first->head->data) < 0) { - 131 334699 : tommy_chain_concat(second->tail, first->head); - 132 334699 : first->head = second->head; - 133 334699 : return; + 130 806012 : if (cmp(second->tail->data, first->head->data) < 0) { + 131 334865 : tommy_chain_concat(second->tail, first->head); + 132 334865 : first->head = second->head; + 133 334865 : return; 134 : } 135 : - 136 470639 : tommy_chain_merge(first, second, cmp); + 136 471147 : tommy_chain_merge(first, second, cmp); 137 : } 138 : 139 : /** @@ -241,42 +241,42 @@ 179 : tommy_chain* last; 180 : 181 : /* carry bit to add */ - 182 1284973 : last = &bit[TOMMY_CHAIN_BIT_MAX]; - 183 1284973 : bit[TOMMY_CHAIN_BIT_MAX].head = node; - 184 1284973 : bit[TOMMY_CHAIN_BIT_MAX].tail = node; - 185 1284973 : next = node->next; + 182 1284971 : last = &bit[TOMMY_CHAIN_BIT_MAX]; + 183 1284971 : bit[TOMMY_CHAIN_BIT_MAX].head = node; + 184 1284971 : bit[TOMMY_CHAIN_BIT_MAX].tail = node; + 185 1284971 : next = node->next; 186 : 187 : /* add the bit, propagating the carry */ - 188 1284973 : i = 0; - 189 1284973 : mask = counter; - 190 3847173 : while ((mask & 1) != 0) { - 191 1277227 : tommy_chain_merge_degenerated(&bit[i], last, cmp); - 192 1277227 : mask >>= 1; - 193 1277227 : last = &bit[i]; - 194 1277227 : ++i; + 188 1284971 : i = 0; + 189 1284971 : mask = counter; + 190 3847168 : while ((mask & 1) != 0) { + 191 1277226 : tommy_chain_merge_degenerated(&bit[i], last, cmp); + 192 1277226 : mask >>= 1; + 193 1277226 : last = &bit[i]; + 194 1277226 : ++i; 195 : } 196 : 197 : /* copy the carry in the first empty bit */ - 198 1284973 : bit[i] = *last; + 198 1284971 : bit[i] = *last; 199 : 200 : /* add the carry in the counter */ - 201 1284973 : ++counter; + 201 1284971 : ++counter; 202 : - 203 1284973 : if (node == tail) + 203 1284971 : if (node == tail) 204 1693 : break; - 205 1283280 : node = next; - 206 1283280 : } + 205 1283278 : node = next; + 206 1283278 : } 207 : 208 : /* merge the buckets */ 209 1693 : i = tommy_ctz_u32(counter); 210 1693 : mask = counter >> i; - 211 12416 : while (mask != 1) { - 212 9030 : mask >>= 1; - 213 9030 : if (mask & 1) - 214 6053 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); + 211 12415 : while (mask != 1) { + 212 9029 : mask >>= 1; + 213 9029 : if (mask & 1) + 214 6052 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); 215 : else 216 2977 : bit[i + 1] = bit[i]; - 217 9030 : ++i; + 217 9029 : ++i; 218 : } 219 : 220 1693 : *chain = bit[i]; diff --git a/cov/tommyds/tommyhash.c.func-sort-c.html b/cov/tommyds/tommyhash.c.func-sort-c.html index df6507f4..1b2f6d83 100644 --- a/cov/tommyds/tommyhash.c.func-sort-c.html +++ b/cov/tommyds/tommyhash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -61,11 +61,11 @@ tommy_le_uint32_read - 11588009 + 11604375 tommy_hash_u32 - 4059942 + 4065657 tommy_strhash_u32 diff --git a/cov/tommyds/tommyhash.c.func.html b/cov/tommyds/tommyhash.c.func.html index 54128f24..a8f382e5 100644 --- a/cov/tommyds/tommyhash.c.func.html +++ b/cov/tommyds/tommyhash.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -61,7 +61,7 @@ tommy_hash_u32 - 4059942 + 4065657 tommy_hash_u64 @@ -69,7 +69,7 @@ tommy_le_uint32_read - 11588009 + 11604375 tommy_strhash_u32 diff --git a/cov/tommyds/tommyhash.c.gcov.html b/cov/tommyds/tommyhash.c.gcov.html index 68119537..16bf6da2 100644 --- a/cov/tommyds/tommyhash.c.gcov.html +++ b/cov/tommyds/tommyhash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 4 @@ -92,12 +92,12 @@ 30 : /******************************************************************************/ 31 : /* hash */ 32 : - 33 11588009 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) + 33 11604375 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) 34 : { 35 : /* allow unaligned read on Intel x86 and x86_64 platforms */ 36 : #if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__x86_64__) || defined(_M_X64) 37 : /* defines from http://predef.sourceforge.net/ */ - 38 11588009 : return *(const tommy_uint32_t*)ptr; + 38 11604375 : return *(const tommy_uint32_t*)ptr; 39 : #else 40 : const unsigned char* ptr8 = tommy_cast(const unsigned char*, ptr); 41 : return ptr8[0] + ((tommy_uint32_t)ptr8[1] << 8) + ((tommy_uint32_t)ptr8[2] << 16) + ((tommy_uint32_t)ptr8[3] << 24); @@ -128,53 +128,53 @@ 66 : c ^= b; c -= tommy_rot(b, 24); \ 67 : } while (0) 68 : - 69 4059942 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) + 69 4065657 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) 70 : { - 71 4059942 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); + 71 4065657 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); 72 : tommy_uint32_t a, b, c; 73 : - 74 4059942 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; + 74 4065657 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; 75 : - 76 10240213 : while (key_len > 12) { - 77 2120329 : a += tommy_le_uint32_read(key + 0); - 78 2120329 : b += tommy_le_uint32_read(key + 4); - 79 2120329 : c += tommy_le_uint32_read(key + 8); + 76 10254604 : while (key_len > 12) { + 77 2123290 : a += tommy_le_uint32_read(key + 0); + 78 2123290 : b += tommy_le_uint32_read(key + 4); + 79 2123290 : c += tommy_le_uint32_read(key + 8); 80 : - 81 2120329 : tommy_mix(a, b, c); + 81 2123290 : tommy_mix(a, b, c); 82 : - 83 2120329 : key_len -= 12; - 84 2120329 : key += 12; + 83 2123290 : key_len -= 12; + 84 2123290 : key += 12; 85 : } 86 : - 87 4059942 : switch (key_len) { + 87 4065657 : switch (key_len) { 88 : case 0 : 89 1 : return c; /* used only when called with a zero length */ 90 : case 12 : - 91 207744 : c += tommy_le_uint32_read(key + 8); - 92 207744 : b += tommy_le_uint32_read(key + 4); - 93 207744 : a += tommy_le_uint32_read(key + 0); - 94 207744 : break; - 95 217371 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; - 96 640231 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; - 97 1059969 : case 9 : c += key[8]; + 91 208009 : c += tommy_le_uint32_read(key + 8); + 92 208009 : b += tommy_le_uint32_read(key + 4); + 93 208009 : a += tommy_le_uint32_read(key + 0); + 94 208009 : break; + 95 217656 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; + 96 641102 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; + 97 1061522 : case 9 : c += key[8]; 98 : case 8 : - 99 1470946 : b += tommy_le_uint32_read(key + 4); - 100 1470946 : a += tommy_le_uint32_read(key + 0); - 101 1470946 : break; - 102 413133 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; - 103 812960 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; - 104 1229671 : case 5 : b += key[4]; + 99 1473120 : b += tommy_le_uint32_read(key + 4); + 100 1473120 : a += tommy_le_uint32_read(key + 0); + 101 1473120 : break; + 102 413650 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; + 103 814028 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; + 104 1231376 : case 5 : b += key[4]; 105 : case 4 : - 106 1661764 : a += tommy_le_uint32_read(key + 0); - 107 1661764 : break; - 108 301721 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; - 109 509505 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; - 110 719487 : case 1 : a += key[0]; + 106 1664104 : a += tommy_le_uint32_read(key + 0); + 107 1664104 : break; + 108 302114 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; + 109 510191 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; + 110 720423 : case 1 : a += key[0]; 111 : } 112 : - 113 4059941 : tommy_final(a, b, c); + 113 4065656 : tommy_final(a, b, c); 114 : - 115 4059941 : return c; + 115 4065656 : return c; 116 : } 117 : 118 19 : tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) diff --git a/cov/tommyds/tommyhash.h.func-sort-c.html b/cov/tommyds/tommyhash.h.func-sort-c.html index e16f4c74..16d6d836 100644 --- a/cov/tommyds/tommyhash.h.func-sort-c.html +++ b/cov/tommyds/tommyhash.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u32 - 18826263 + 18826860 tommy_inthash_u64 - 5042449 + 5055357
diff --git a/cov/tommyds/tommyhash.h.func.html b/cov/tommyds/tommyhash.h.func.html index c3f3a49c..efa2bd47 100644 --- a/cov/tommyds/tommyhash.h.func.html +++ b/cov/tommyds/tommyhash.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u32 - 18826263 + 18826860 tommy_inthash_u64 - 5042449 + 5055357
diff --git a/cov/tommyds/tommyhash.h.gcov.html b/cov/tommyds/tommyhash.h.gcov.html index 86c2762a..6ea87a53 100644 --- a/cov/tommyds/tommyhash.h.gcov.html +++ b/cov/tommyds/tommyhash.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 @@ -167,17 +167,17 @@ 105 : * Implementation of the Robert Jenkins "4-byte Integer Hashing", 106 : * from http://burtleburtle.net/bob/hash/integer.html 107 : */ - 108 18826263 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) + 108 18826860 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) 109 : { - 110 18826263 : key -= key << 6; - 111 18826263 : key ^= key >> 17; - 112 18826263 : key -= key << 9; - 113 18826263 : key ^= key << 4; - 114 18826263 : key -= key << 3; - 115 18826263 : key ^= key << 10; - 116 18826263 : key ^= key >> 15; + 110 18826860 : key -= key << 6; + 111 18826860 : key ^= key >> 17; + 112 18826860 : key -= key << 9; + 113 18826860 : key ^= key << 4; + 114 18826860 : key -= key << 3; + 115 18826860 : key ^= key << 10; + 116 18826860 : key ^= key >> 15; 117 : - 118 18826263 : return key; + 118 18826860 : return key; 119 : } 120 : 121 : /** @@ -185,17 +185,17 @@ 123 : * Implementation of the Thomas Wang "Integer Hash Function", 124 : * from http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm 125 : */ - 126 5042449 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) + 126 5055357 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) 127 : { - 128 5042449 : key = ~key + (key << 21); - 129 5042449 : key = key ^ (key >> 24); - 130 5042449 : key = key + (key << 3) + (key << 8); - 131 5042449 : key = key ^ (key >> 14); - 132 5042449 : key = key + (key << 2) + (key << 4); - 133 5042449 : key = key ^ (key >> 28); - 134 5042449 : key = key + (key << 31); + 128 5055357 : key = ~key + (key << 21); + 129 5055357 : key = key ^ (key >> 24); + 130 5055357 : key = key + (key << 3) + (key << 8); + 131 5055357 : key = key ^ (key >> 14); + 132 5055357 : key = key + (key << 2) + (key << 4); + 133 5055357 : key = key ^ (key >> 28); + 134 5055357 : key = key + (key << 31); 135 : - 136 5042449 : return key; + 136 5055357 : return key; 137 : } 138 : 139 : #endif diff --git a/cov/tommyds/tommyhashdyn.c.func-sort-c.html b/cov/tommyds/tommyhashdyn.c.func-sort-c.html index 9c360eb3..24828b7c 100644 --- a/cov/tommyds/tommyhashdyn.c.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -61,19 +61,19 @@ hashdyn_grow_step - 13231522 + 13244128 tommy_hashdyn_insert - 13231522 + 13244128 hashdyn_shrink_step - 276876 + 289723 tommy_hashdyn_remove_existing - 276748 + 289595 tommy_hashdyn_resize diff --git a/cov/tommyds/tommyhashdyn.c.func.html b/cov/tommyds/tommyhashdyn.c.func.html index f2525885..93a5b706 100644 --- a/cov/tommyds/tommyhashdyn.c.func.html +++ b/cov/tommyds/tommyhashdyn.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -61,11 +61,11 @@ hashdyn_grow_step - 13231522 + 13244128 hashdyn_shrink_step - 276876 + 289723 tommy_hashdyn_done @@ -85,7 +85,7 @@ tommy_hashdyn_insert - 13231522 + 13244128 tommy_hashdyn_memory_usage @@ -97,7 +97,7 @@ tommy_hashdyn_remove_existing - 276748 + 289595 tommy_hashdyn_resize diff --git a/cov/tommyds/tommyhashdyn.c.gcov.html b/cov/tommyds/tommyhashdyn.c.gcov.html index f6e08f05..c2738e4a 100644 --- a/cov/tommyds/tommyhashdyn.c.gcov.html +++ b/cov/tommyds/tommyhashdyn.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -148,9 +148,9 @@ 86 16077016 : tommy_hashdyn_node* j_next = j->next; 87 16077016 : tommy_count_t pos = j->key & new_bucket_mask; 88 16077016 : if (new_bucket[pos]) - 89 1915511 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); + 89 1895759 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); 90 : else - 91 14161505 : tommy_list_insert_first(&new_bucket[pos], j); + 91 14181257 : tommy_list_insert_first(&new_bucket[pos], j); 92 16077016 : j = j_next; 93 : } 94 : } @@ -179,47 +179,47 @@ 117 : /** 118 : * Grow. 119 : */ - 120 13231522 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) + 120 13244128 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) 121 : { 122 : /* grow if more than 50% full */ - 123 13231522 : if (hashdyn->count >= hashdyn->bucket_max / 2) + 123 13244128 : if (hashdyn->count >= hashdyn->bucket_max / 2) 124 41474 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); - 125 13231522 : } + 125 13244128 : } 126 : 127 : /** 128 : * Shrink. 129 : */ - 130 276876 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) + 130 289723 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) 131 : { 132 : /* shrink if less than 12.5% full */ - 133 276876 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) + 133 289723 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) 134 49 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1); - 135 276876 : } + 135 289723 : } 136 : - 137 13231522 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) + 137 13244128 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) 138 : { - 139 13231522 : tommy_count_t pos = hash & hashdyn->bucket_mask; + 139 13244128 : tommy_count_t pos = hash & hashdyn->bucket_mask; 140 : - 141 13231522 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); + 141 13244128 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); 142 : - 143 13231522 : node->key = hash; + 143 13244128 : node->key = hash; 144 : - 145 13231522 : ++hashdyn->count; + 145 13244128 : ++hashdyn->count; 146 : - 147 13231522 : hashdyn_grow_step(hashdyn); - 148 13231522 : } + 147 13244128 : hashdyn_grow_step(hashdyn); + 148 13244128 : } 149 : - 150 276748 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) + 150 289595 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) 151 : { - 152 276748 : tommy_count_t pos = node->key & hashdyn->bucket_mask; + 152 289595 : tommy_count_t pos = node->key & hashdyn->bucket_mask; 153 : - 154 276748 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); + 154 289595 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); 155 : - 156 276748 : --hashdyn->count; + 156 289595 : --hashdyn->count; 157 : - 158 276748 : hashdyn_shrink_step(hashdyn); + 158 289595 : hashdyn_shrink_step(hashdyn); 159 : - 160 276748 : return node->data; + 160 289595 : return node->data; 161 : } 162 : 163 256 : void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) @@ -253,10 +253,10 @@ 191 5812552 : for (pos = 0; pos < bucket_max; ++pos) { 192 5812304 : tommy_hashdyn_node* node = bucket[pos]; 193 : - 194 13485790 : while (node) { - 195 1861182 : void* data = node->data; - 196 1861182 : node = node->next; - 197 1861182 : func(data); + 194 13485549 : while (node) { + 195 1860941 : void* data = node->data; + 196 1860941 : node = node->next; + 197 1860941 : func(data); 198 : } 199 : } 200 248 : } diff --git a/cov/tommyds/tommyhashdyn.h.func-sort-c.html b/cov/tommyds/tommyhashdyn.h.func-sort-c.html index 6937e5cf..a26eea91 100644 --- a/cov/tommyds/tommyhashdyn.h.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -61,11 +61,11 @@ tommy_hashdyn_bucket - 3108747 + 3115397 tommy_hashdyn_search - 3108747 + 3115397 tommy_hashdyn_count diff --git a/cov/tommyds/tommyhashdyn.h.func.html b/cov/tommyds/tommyhashdyn.h.func.html index 60527ed5..c815da55 100644 --- a/cov/tommyds/tommyhashdyn.h.func.html +++ b/cov/tommyds/tommyhashdyn.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -61,7 +61,7 @@ tommy_hashdyn_bucket - 3108747 + 3115397 tommy_hashdyn_count @@ -69,7 +69,7 @@ tommy_hashdyn_search - 3108747 + 3115397
diff --git a/cov/tommyds/tommyhashdyn.h.gcov.html b/cov/tommyds/tommyhashdyn.h.gcov.html index b5142826..9fc9fbf8 100644 --- a/cov/tommyds/tommyhashdyn.h.gcov.html +++ b/cov/tommyds/tommyhashdyn.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 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 3108747 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) + 208 3115397 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) 209 : { - 210 3108747 : return hashdyn->bucket[hash & hashdyn->bucket_mask]; + 210 3115397 : return hashdyn->bucket[hash & hashdyn->bucket_mask]; 211 : } 212 : 213 : /** @@ -282,17 +282,17 @@ 220 : * \param hash Hash of the element to find. 221 : * \return The first element found, or 0 if none. 222 : */ - 223 3108747 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) + 223 3115397 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) 224 : { - 225 3108747 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); + 225 3115397 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); 226 : - 227 6892825 : while (i) { + 227 6906900 : while (i) { 228 : /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ - 229 1828483 : if (i->key == hash && cmp(cmp_arg, i->data) == 0) - 230 1153152 : return i->data; - 231 675331 : i = i->next; + 229 1847113 : if (i->key == hash && cmp(cmp_arg, i->data) == 0) + 230 1171007 : return i->data; + 231 676106 : i = i->next; 232 : } - 233 1955595 : return 0; + 233 1944390 : return 0; 234 : } 235 : 236 : /** diff --git a/cov/tommyds/tommylist.c.func-sort-c.html b/cov/tommyds/tommylist.c.func-sort-c.html index 0839d722..7805d5dc 100644 --- a/cov/tommyds/tommylist.c.func-sort-c.html +++ b/cov/tommyds/tommylist.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/tommyds/tommylist.c.func.html b/cov/tommyds/tommylist.c.func.html index 1dfa43e9..78e520bf 100644 --- a/cov/tommyds/tommylist.c.func.html +++ b/cov/tommyds/tommylist.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/tommyds/tommylist.c.gcov.html b/cov/tommyds/tommylist.c.gcov.html index ff470829..15db502b 100644 --- a/cov/tommyds/tommylist.c.gcov.html +++ b/cov/tommyds/tommylist.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 2 diff --git a/cov/tommyds/tommylist.h.func-sort-c.html b/cov/tommyds/tommylist.h.func-sort-c.html index 59514e63..2a1dad02 100644 --- a/cov/tommyds/tommylist.h.func-sort-c.html +++ b/cov/tommyds/tommylist.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -61,23 +61,23 @@ tommy_list_head - 25304133 + 25329368 tommy_list_insert_first - 23374774 + 23404491 tommy_list_insert_tail - 18376886 + 18389486 tommy_list_insert_tail_not_empty - 11079128 + 11062011 tommy_list_remove_existing - 334849 + 347694 tommy_list_concat diff --git a/cov/tommyds/tommylist.h.func.html b/cov/tommyds/tommylist.h.func.html index 665f8a95..3ededb05 100644 --- a/cov/tommyds/tommylist.h.func.html +++ b/cov/tommyds/tommylist.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -77,7 +77,7 @@ tommy_list_head - 25304133 + 25329368 tommy_list_init @@ -85,19 +85,19 @@ tommy_list_insert_first - 23374774 + 23404491 tommy_list_insert_tail - 18376886 + 18389486 tommy_list_insert_tail_not_empty - 11079128 + 11062011 tommy_list_remove_existing - 334849 + 347694 tommy_list_tail diff --git a/cov/tommyds/tommylist.h.gcov.html b/cov/tommyds/tommylist.h.gcov.html index 600cc1c4..097181a6 100644 --- a/cov/tommyds/tommylist.h.gcov.html +++ b/cov/tommyds/tommylist.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 11 @@ -182,9 +182,9 @@ 120 : * Gets the head of the list. 121 : * \return The head node. For empty lists 0 is returned. 122 : */ - 123 25304133 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) + 123 25329368 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) 124 : { - 125 25304133 : return *list; + 125 25329368 : return *list; 126 : } 127 : 128 : /** @@ -206,16 +206,16 @@ 144 : * \param list The list to initialize. 145 : * \param node The node to insert. 146 : */ - 147 23374774 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) + 147 23404491 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) 148 : { 149 : /* one element "circular" prev list */ - 150 23374774 : node->prev = node; + 150 23404491 : node->prev = node; 151 : 152 : /* one element "0 terminated" next list */ - 153 23374774 : node->next = 0; + 153 23404491 : node->next = 0; 154 : - 155 23374774 : *list = node; - 156 23374774 : } + 155 23404491 : *list = node; + 156 23404491 : } 157 : 158 : /** \internal 159 : * Inserts an element at the head of a not empty list. @@ -243,16 +243,16 @@ 181 : * \param head The node at the list head. It cannot be 0. 182 : * \param node The node to insert. 183 : */ - 184 11079128 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) + 184 11062011 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) 185 : { 186 : /* insert in the "circular" prev list */ - 187 11079128 : node->prev = head->prev; - 188 11079128 : head->prev = node; + 187 11062011 : node->prev = head->prev; + 188 11062011 : head->prev = node; 189 : 190 : /* insert in the "0 terminated" next list */ - 191 11079128 : node->next = 0; - 192 11079128 : node->prev->next = node; - 193 11079128 : } + 191 11062011 : node->next = 0; + 192 11062011 : node->prev->next = node; + 193 11062011 : } 194 : 195 : /** 196 : * Inserts an element at the head of a list. @@ -276,17 +276,17 @@ 214 : * \param node The node to insert. 215 : * \param data The object containing the node. It's used to set the tommy_node::data field of the node. 216 : */ - 217 18376886 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) + 217 18389486 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) 218 : { - 219 18376886 : tommy_node* head = tommy_list_head(list); + 219 18389486 : tommy_node* head = tommy_list_head(list); 220 : - 221 18376886 : if (head) - 222 9163617 : tommy_list_insert_tail_not_empty(head, node); + 221 18389486 : if (head) + 222 9166252 : tommy_list_insert_tail_not_empty(head, node); 223 : else - 224 9213269 : tommy_list_insert_first(list, node); + 224 9223234 : tommy_list_insert_first(list, node); 225 : - 226 18376886 : node->data = data; - 227 18376886 : } + 226 18389486 : node->data = data; + 227 18389486 : } 228 : 229 : /** \internal 230 : * Removes an element from the head of a not empty list. @@ -314,23 +314,23 @@ 252 : * \param node The node to remove. The node must be in the list. 253 : * \return The tommy_node::data field of the node removed. 254 : */ - 255 334849 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) + 255 347694 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) 256 : { - 257 334849 : tommy_node* head = tommy_list_head(list); + 257 347694 : tommy_node* head = tommy_list_head(list); 258 : 259 : /* remove from the "circular" prev list */ - 260 334849 : if (node->next) - 261 116893 : node->next->prev = node->prev; + 260 347694 : if (node->next) + 261 117955 : node->next->prev = node->prev; 262 : else - 263 217956 : head->prev = node->prev; /* the last */ + 263 229739 : head->prev = node->prev; /* the last */ 264 : 265 : /* remove from the "0 terminated" next list */ - 266 334849 : if (head == node) - 267 234397 : *list = node->next; /* the new head, in case 0 */ + 266 347694 : if (head == node) + 267 244534 : *list = node->next; /* the new head, in case 0 */ 268 : else - 269 100452 : node->prev->next = node->next; + 269 103160 : node->prev->next = node->next; 270 : - 271 334849 : return node->data; + 271 347694 : return node->data; 272 : } 273 : 274 : /** @@ -349,24 +349,24 @@ 287 : /* if the second is empty, nothing to do */ 288 63152 : second_head = tommy_list_head(second); 289 63152 : if (second_head == 0) - 290 55882 : return; + 290 55787 : return; 291 : 292 : /* if the first is empty, copy the second */ - 293 7270 : first_head = tommy_list_head(first); - 294 7270 : if (first_head == 0) { - 295 6382 : *first = *second; - 296 6382 : return; + 293 7365 : first_head = tommy_list_head(first); + 294 7365 : if (first_head == 0) { + 295 6478 : *first = *second; + 296 6478 : return; 297 : } 298 : 299 : /* tail of the first list */ - 300 888 : first_tail = first_head->prev; + 300 887 : first_tail = first_head->prev; 301 : 302 : /* set the "circular" prev list */ - 303 888 : first_head->prev = second_head->prev; - 304 888 : second_head->prev = first_tail; + 303 887 : first_head->prev = second_head->prev; + 304 887 : second_head->prev = first_tail; 305 : 306 : /* set the "0 terminated" next list */ - 307 888 : first_tail->next = second_head; + 307 887 : first_tail->next = second_head; 308 : } 309 : 310 : /** @@ -436,10 +436,10 @@ 374 : { 375 7645 : tommy_node* node = tommy_list_head(list); 376 : - 377 3679931 : while (node) { - 378 3664641 : void* data = node->data; - 379 3664641 : node = node->next; - 380 3664641 : func(data); + 377 3679929 : while (node) { + 378 3664639 : void* data = node->data; + 379 3664639 : node = node->next; + 380 3664639 : func(data); 381 : } 382 7645 : } 383 : diff --git a/cov/tommyds/tommytree.c.func-sort-c.html b/cov/tommyds/tommytree.c.func-sort-c.html index 82ebea9a..0a34d3a4 100644 --- a/cov/tommyds/tommytree.c.func-sort-c.html +++ b/cov/tommyds/tommytree.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 19 @@ -61,55 +61,55 @@ tommy_tree_search_node - 137516004 + 136358907 tommy_tree_delta - 112385081 + 112386346 tommy_tree_balance - 104878675 + 104880543 tommy_tree_insert_node - 96198722 + 96201724 tommy_tree_foreach_arg_node - 26344381 + 26344733 tommy_tree_search_compare - 12374066 + 12265513 tommy_tree_rotate_left - 7494967 + 7494292 tommy_tree_insert - 7470835 + 7470915 tommy_tree_foreach_node - 7052386 + 7052474 tommy_tree_remove_node - 791513 + 791997 tommy_tree_move_right - 187087 + 186993 tommy_tree_rotate_right - 170763 + 170708 tommy_tree_remove - 79700 + 79692 tommy_tree_foreach_arg diff --git a/cov/tommyds/tommytree.c.func.html b/cov/tommyds/tommytree.c.func.html index d5863abc..4fbf0ecc 100644 --- a/cov/tommyds/tommytree.c.func.html +++ b/cov/tommyds/tommytree.c.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 19 @@ -61,11 +61,11 @@ tommy_tree_balance - 104878675 + 104880543 tommy_tree_delta - 112385081 + 112386346 tommy_tree_foreach @@ -77,11 +77,11 @@ tommy_tree_foreach_arg_node - 26344381 + 26344733 tommy_tree_foreach_node - 7052386 + 7052474 tommy_tree_init @@ -89,11 +89,11 @@ tommy_tree_insert - 7470835 + 7470915 tommy_tree_insert_node - 96198722 + 96201724 tommy_tree_memory_usage @@ -101,11 +101,11 @@ tommy_tree_move_right - 187087 + 186993 tommy_tree_remove - 79700 + 79692 tommy_tree_remove_existing @@ -113,15 +113,15 @@ tommy_tree_remove_node - 791513 + 791997 tommy_tree_rotate_left - 7494967 + 7494292 tommy_tree_rotate_right - 170763 + 170708 tommy_tree_search @@ -129,11 +129,11 @@ tommy_tree_search_compare - 12374066 + 12265513 tommy_tree_search_node - 137516004 + 136358907
diff --git a/cov/tommyds/tommytree.c.gcov.html b/cov/tommyds/tommytree.c.gcov.html index cf93057e..2ff1395c 100644 --- a/cov/tommyds/tommytree.c.gcov.html +++ b/cov/tommyds/tommytree.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 19 @@ -101,97 +101,97 @@ 39 3183 : tree->cmp = cmp; 40 3183 : } 41 : - 42 112385081 : static int tommy_tree_delta(tommy_tree_node* root) + 42 112386346 : static int tommy_tree_delta(tommy_tree_node* root) 43 : { - 44 112385081 : int left_height = root->prev ? root->prev->key : 0; - 45 112385081 : int right_height = root->next ? root->next->key : 0; + 44 112386346 : int left_height = root->prev ? root->prev->key : 0; + 45 112386346 : int right_height = root->next ? root->next->key : 0; 46 : - 47 112385081 : return left_height - right_height; + 47 112386346 : return left_height - right_height; 48 : } 49 : 50 : /* AVL tree operations */ 51 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*); 52 : - 53 7494967 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) + 53 7494292 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) 54 : { - 55 7494967 : tommy_tree_node* next = root->next; + 55 7494292 : tommy_tree_node* next = root->next; 56 : - 57 7494967 : root->next = next->prev; + 57 7494292 : root->next = next->prev; 58 : - 59 7494967 : next->prev = tommy_tree_balance(root); + 59 7494292 : next->prev = tommy_tree_balance(root); 60 : - 61 7494967 : return tommy_tree_balance(next); + 61 7494292 : return tommy_tree_balance(next); 62 : } 63 : - 64 170763 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) + 64 170708 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) 65 : { - 66 170763 : tommy_tree_node* prev = root->prev; + 66 170708 : tommy_tree_node* prev = root->prev; 67 : - 68 170763 : root->prev = prev->next; + 68 170708 : root->prev = prev->next; 69 : - 70 170763 : prev->next = tommy_tree_balance(root); + 70 170708 : prev->next = tommy_tree_balance(root); 71 : - 72 170763 : return tommy_tree_balance(prev); + 72 170708 : return tommy_tree_balance(prev); 73 : } 74 : - 75 187087 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) + 75 186993 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) 76 : { - 77 187087 : if (!root) - 78 79572 : return node; + 77 186993 : if (!root) + 78 79564 : return node; 79 : - 80 107515 : root->next = tommy_tree_move_right(root->next, node); + 80 107429 : root->next = tommy_tree_move_right(root->next, node); 81 : - 82 107515 : return tommy_tree_balance(root); + 82 107429 : return tommy_tree_balance(root); 83 : } 84 : - 85 104878675 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) + 85 104880543 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) 86 : { - 87 104878675 : int delta = tommy_tree_delta(root); + 87 104880543 : int delta = tommy_tree_delta(root); 88 : - 89 104878675 : if (delta < -1) { - 90 7378499 : if (tommy_tree_delta(root->next) > 0) - 91 42856 : root->next = tommy_tree_rotate_right(root->next); - 92 7378499 : return tommy_tree_rotate_left(root); + 89 104880543 : if (delta < -1) { + 90 7378061 : if (tommy_tree_delta(root->next) > 0) + 91 42966 : root->next = tommy_tree_rotate_right(root->next); + 92 7378061 : return tommy_tree_rotate_left(root); 93 : } 94 : - 95 97500176 : if (delta > 1) { - 96 127907 : if (tommy_tree_delta(root->prev) < 0) - 97 116468 : root->prev = tommy_tree_rotate_left(root->prev); - 98 127907 : return tommy_tree_rotate_right(root); + 95 97502482 : if (delta > 1) { + 96 127742 : if (tommy_tree_delta(root->prev) < 0) + 97 116231 : root->prev = tommy_tree_rotate_left(root->prev); + 98 127742 : return tommy_tree_rotate_right(root); 99 : } 100 : 101 : /* recompute key */ - 102 97372269 : root->key = 0; + 102 97374740 : root->key = 0; 103 : - 104 97372269 : if (root->prev && root->prev->key > root->key) - 105 78769557 : root->key = root->prev->key; + 104 97374740 : if (root->prev && root->prev->key > root->key) + 105 78772370 : root->key = root->prev->key; 106 : - 107 97372269 : if (root->next && root->next->key > root->key) - 108 44908478 : root->key = root->next->key; + 107 97374740 : if (root->next && root->next->key > root->key) + 108 44910466 : root->key = root->next->key; 109 : 110 : /* count itself */ - 111 97372269 : root->key += 1; + 111 97374740 : root->key += 1; 112 : - 113 97372269 : return root; + 113 97374740 : return root; 114 : } 115 : - 116 96198722 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) + 116 96201724 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) 117 : { 118 : int c; 119 : - 120 96198722 : if (!root) - 121 7470834 : return *let; + 120 96201724 : if (!root) + 121 7470914 : return *let; 122 : - 123 88727888 : c = cmp((*let)->data, root->data); + 123 88730810 : c = cmp((*let)->data, root->data); 124 : - 125 88727888 : if (c < 0) { - 126 1533765 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); - 127 1533765 : return tommy_tree_balance(root); + 125 88730810 : if (c < 0) { + 126 1533509 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); + 127 1533509 : return tommy_tree_balance(root); 128 : } 129 : - 130 87194123 : if (c > 0) { - 131 87194122 : root->next = tommy_tree_insert_node(cmp, root->next, let); - 132 87194122 : return tommy_tree_balance(root); + 130 87197301 : if (c > 0) { + 131 87197300 : root->next = tommy_tree_insert_node(cmp, root->next, let); + 132 87197300 : return tommy_tree_balance(root); 133 : } 134 : 135 : /* already present, set the return pointer */ @@ -200,78 +200,78 @@ 138 1 : return root; 139 : } 140 : - 141 7470835 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) + 141 7470915 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) 142 : { - 143 7470835 : tommy_tree_node* insert = node; + 143 7470915 : tommy_tree_node* insert = node; 144 : - 145 7470835 : insert->data = data; - 146 7470835 : insert->prev = 0; - 147 7470835 : insert->next = 0; - 148 7470835 : insert->key = 0; + 145 7470915 : insert->data = data; + 146 7470915 : insert->prev = 0; + 147 7470915 : insert->next = 0; + 148 7470915 : insert->key = 0; 149 : - 150 7470835 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); + 150 7470915 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); 151 : - 152 7470835 : if (insert == node) - 153 7470834 : ++tree->count; + 152 7470915 : if (insert == node) + 153 7470914 : ++tree->count; 154 : - 155 7470835 : return insert->data; + 155 7470915 : return insert->data; 156 : } 157 : - 158 791513 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) + 158 791997 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) 159 : { 160 : int c; 161 : - 162 791513 : if (!root) + 162 791997 : if (!root) 163 128 : return 0; 164 : - 165 791385 : c = cmp(data, root->data); + 165 791869 : c = cmp(data, root->data); 166 : - 167 791385 : if (c < 0) { - 168 304173 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); - 169 304173 : return tommy_tree_balance(root); + 167 791869 : if (c < 0) { + 168 304676 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); + 169 304676 : return tommy_tree_balance(root); 170 : } 171 : - 172 487212 : if (c > 0) { - 173 407640 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); - 174 407640 : return tommy_tree_balance(root); + 172 487193 : if (c > 0) { + 173 407629 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); + 174 407629 : return tommy_tree_balance(root); 175 : } 176 : 177 : /* found */ - 178 79572 : *let = root; + 178 79564 : *let = root; 179 : - 180 79572 : return tommy_tree_move_right(root->prev, root->next); + 180 79564 : return tommy_tree_move_right(root->prev, root->next); 181 : } 182 : - 183 79700 : void* tommy_tree_remove(tommy_tree* tree, void* data) + 183 79692 : void* tommy_tree_remove(tommy_tree* tree, void* data) 184 : { - 185 79700 : tommy_tree_node* node = 0; + 185 79692 : tommy_tree_node* node = 0; 186 : - 187 79700 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); + 187 79692 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); 188 : - 189 79700 : if (!node) + 189 79692 : if (!node) 190 128 : return 0; 191 : - 192 79572 : --tree->count; + 192 79564 : --tree->count; 193 : - 194 79572 : return node->data; + 194 79564 : return node->data; 195 : } 196 : - 197 137516004 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) + 197 136358907 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) 198 : { 199 : int c; 200 : - 201 137516004 : if (!root) - 202 1589078 : return 0; + 201 136358907 : if (!root) + 202 1589052 : return 0; 203 : - 204 135926926 : c = cmp(data, root->data); + 204 134769855 : c = cmp(data, root->data); 205 : - 206 135935261 : if (c < 0) - 207 49441744 : return tommy_tree_search_node(cmp, root->prev, data); + 206 134778932 : if (c < 0) + 207 48960881 : return tommy_tree_search_node(cmp, root->prev, data); 208 : - 209 86493517 : if (c > 0) - 210 75708858 : return tommy_tree_search_node(cmp, root->next, data); + 209 85818051 : if (c > 0) + 210 75141540 : return tommy_tree_search_node(cmp, root->next, data); 211 : - 212 10784659 : return root; + 212 10676511 : return root; 213 : } 214 : 215 2 : void* tommy_tree_search(tommy_tree* tree, void* data) @@ -284,14 +284,14 @@ 222 1 : return node->data; 223 : } 224 : - 225 12374066 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) + 225 12265513 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) 226 : { - 227 12374066 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); + 227 12265513 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); 228 : - 229 12373755 : if (!node) - 230 1589128 : return 0; + 229 12265527 : if (!node) + 230 1589090 : return 0; 231 : - 232 10784627 : return node->data; + 232 10676437 : return node->data; 233 : } 234 : 235 128 : void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) @@ -303,21 +303,21 @@ 241 128 : return data; 242 : } 243 : - 244 7052386 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) + 244 7052474 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) 245 : { 246 : tommy_tree_node* next; 247 : - 248 7052386 : if (!root) - 249 10579309 : return; + 248 7052474 : if (!root) + 249 10579441 : return; 250 : - 251 3525463 : tommy_tree_foreach_node(root->prev, func); + 251 3525507 : tommy_tree_foreach_node(root->prev, func); 252 : 253 : /* make a copy in case func is free() */ - 254 3525463 : next = root->next; + 254 3525507 : next = root->next; 255 : - 256 3525463 : func(root->data); + 256 3525507 : func(root->data); 257 : - 258 3525463 : tommy_tree_foreach_node(next, func); + 258 3525507 : tommy_tree_foreach_node(next, func); 259 : } 260 : 261 1460 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) @@ -325,21 +325,21 @@ 263 1460 : tommy_tree_foreach_node(tree->root, func); 264 1460 : } 265 : - 266 26344381 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) + 266 26344733 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) 267 : { 268 : tommy_tree_node* next; 269 : - 270 26344381 : if (!root) - 271 39519560 : return; + 270 26344733 : if (!root) + 271 39520088 : return; 272 : - 273 13169202 : tommy_tree_foreach_arg_node(root->prev, func, arg); + 273 13169378 : tommy_tree_foreach_arg_node(root->prev, func, arg); 274 : 275 : /* make a copy in case func is free() */ - 276 13169202 : next = root->next; + 276 13169378 : next = root->next; 277 : - 278 13169202 : func(arg, root->data); + 278 13169378 : func(arg, root->data); 279 : - 280 13169202 : tommy_tree_foreach_arg_node(next, func, arg); + 280 13169378 : tommy_tree_foreach_arg_node(next, func, arg); 281 : } 282 : 283 5977 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) diff --git a/cov/tommyds/tommytree.h.func-sort-c.html b/cov/tommyds/tommytree.h.func-sort-c.html index ff624258..0baf7714 100644 --- a/cov/tommyds/tommytree.h.func-sort-c.html +++ b/cov/tommyds/tommytree.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/tommyds/tommytree.h.func.html b/cov/tommyds/tommytree.h.func.html index 1d42fad9..a637aeda 100644 --- a/cov/tommyds/tommytree.h.func.html +++ b/cov/tommyds/tommytree.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/tommyds/tommytree.h.gcov.html b/cov/tommyds/tommytree.h.gcov.html index d11ce0f8..840efecf 100644 --- a/cov/tommyds/tommytree.h.gcov.html +++ b/cov/tommyds/tommytree.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 1 diff --git a/cov/tommyds/tommytypes.h.func-sort-c.html b/cov/tommyds/tommytypes.h.func-sort-c.html index a9485641..5fe44624 100644 --- a/cov/tommyds/tommytypes.h.func-sort-c.html +++ b/cov/tommyds/tommytypes.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -61,7 +61,7 @@ tommy_ilog2_u32 - 10268668 + 10268805 tommy_ctz_u32 diff --git a/cov/tommyds/tommytypes.h.func.html b/cov/tommyds/tommytypes.h.func.html index b4d67947..06c03883 100644 --- a/cov/tommyds/tommytypes.h.func.html +++ b/cov/tommyds/tommytypes.h.func.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -69,7 +69,7 @@ tommy_ilog2_u32 - 10268668 + 10268805
diff --git a/cov/tommyds/tommytypes.h.gcov.html b/cov/tommyds/tommytypes.h.gcov.html index feca1864..8dfc33bc 100644 --- a/cov/tommyds/tommytypes.h.gcov.html +++ b/cov/tommyds/tommytypes.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2016-11-21 + 2017-05-13 Functions: 3 @@ -390,7 +390,7 @@ 328 : * \param value Value to scan. 0 is not allowed. 329 : * \return The index of the most significant bit set. 330 : */ - 331 10268668 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value) + 331 10268805 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value) 332 : { 333 : #if defined(_MSC_VER) 334 : unsigned long count; @@ -406,7 +406,7 @@ 344 : * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)", 345 : * to allow the double xor to be optimized out. 346 : */ - 347 10268668 : return __builtin_clz(value) ^ 31; + 347 10268805 : return __builtin_clz(value) ^ 31; 348 : #else 349 : /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */ 350 : /* from http://graphics.stanford.edu/~seander/bithacks.html */