From 493a91f0c64154628d0c60a1ff9826fe5059ce7d Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 9 Jan 2016 17:18:05 +0100 Subject: [PATCH] Auto update --- cov/cmdline/check.c.func-sort-c.html | 26 +- cov/cmdline/check.c.func.html | 20 +- cov/cmdline/check.c.gcov.html | 954 +- cov/cmdline/device.c.func-sort-c.html | 18 +- cov/cmdline/device.c.func.html | 18 +- cov/cmdline/device.c.gcov.html | 874 +- cov/cmdline/dry.c.func-sort-c.html | 2 +- cov/cmdline/dry.c.func.html | 2 +- cov/cmdline/dry.c.gcov.html | 56 +- cov/cmdline/dup.c.func-sort-c.html | 16 +- cov/cmdline/dup.c.func.html | 10 +- cov/cmdline/dup.c.gcov.html | 72 +- cov/cmdline/elem.c.func-sort-c.html | 224 +- cov/cmdline/elem.c.func.html | 166 +- cov/cmdline/elem.c.gcov.html | 1801 ++-- cov/cmdline/elem.h.func-sort-c.html | 156 +- cov/cmdline/elem.h.func.html | 156 +- cov/cmdline/elem.h.gcov.html | 2074 ++--- cov/cmdline/handle.c.func-sort-c.html | 22 +- cov/cmdline/handle.c.func.html | 22 +- cov/cmdline/handle.c.gcov.html | 277 +- cov/cmdline/import.c.func-sort-c.html | 34 +- cov/cmdline/import.c.func.html | 28 +- cov/cmdline/import.c.gcov.html | 579 +- cov/cmdline/index-sort-f.html | 124 +- cov/cmdline/index-sort-l.html | 162 +- cov/cmdline/index.html | 104 +- cov/cmdline/list.c.func-sort-c.html | 2 +- cov/cmdline/list.c.func.html | 2 +- cov/cmdline/list.c.gcov.html | 30 +- 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 | 28 +- cov/cmdline/mktest.c.func.html | 22 +- cov/cmdline/mktest.c.gcov.html | 172 +- 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/nano.c.func-sort-c.html | 2 +- cov/cmdline/nano.c.func.html | 2 +- cov/cmdline/nano.c.gcov.html | 10 +- cov/cmdline/parity.c.func-sort-c.html | 24 +- cov/cmdline/parity.c.func.html | 18 +- cov/cmdline/parity.c.gcov.html | 182 +- cov/cmdline/pool.c.func-sort-c.html | 4 +- cov/cmdline/pool.c.func.html | 4 +- cov/cmdline/pool.c.gcov.html | 54 +- cov/cmdline/portable.h.func-sort-c.html | 4 +- cov/cmdline/portable.h.func.html | 4 +- cov/cmdline/portable.h.gcov.html | 702 +- cov/cmdline/rehash.c.func-sort-c.html | 2 +- cov/cmdline/rehash.c.func.html | 2 +- cov/cmdline/rehash.c.gcov.html | 16 +- cov/cmdline/scan.c.func-sort-c.html | 56 +- cov/cmdline/scan.c.func.html | 50 +- cov/cmdline/scan.c.gcov.html | 1598 ++-- cov/cmdline/scrub.c.func-sort-c.html | 4 +- cov/cmdline/scrub.c.func.html | 4 +- cov/cmdline/scrub.c.gcov.html | 210 +- cov/cmdline/search.c.func-sort-c.html | 14 +- cov/cmdline/search.c.func.html | 14 +- cov/cmdline/search.c.gcov.html | 140 +- cov/cmdline/selftest.c.func-sort-c.html | 8 +- cov/cmdline/selftest.c.func.html | 8 +- cov/cmdline/selftest.c.gcov.html | 469 +- cov/cmdline/snapraid.c.func-sort-c.html | 24 +- cov/cmdline/snapraid.c.func.html | 24 +- cov/cmdline/snapraid.c.gcov.html | 2134 ++--- cov/cmdline/speed.c.func-sort-c.html | 4 +- cov/cmdline/speed.c.func.html | 4 +- cov/cmdline/speed.c.gcov.html | 70 +- 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 | 148 +- cov/cmdline/state.c.func.html | 200 +- cov/cmdline/state.c.gcov.html | 7814 +++++++++-------- cov/cmdline/state.h.func-sort-c.html | 18 +- cov/cmdline/state.h.func.html | 18 +- cov/cmdline/state.h.gcov.html | 594 +- cov/cmdline/status.c.func-sort-c.html | 2 +- cov/cmdline/status.c.func.html | 2 +- cov/cmdline/status.c.gcov.html | 156 +- cov/cmdline/stream.c.func-sort-c.html | 118 +- cov/cmdline/stream.c.func.html | 64 +- cov/cmdline/stream.c.gcov.html | 522 +- cov/cmdline/stream.h.func-sort-c.html | 32 +- cov/cmdline/stream.h.func.html | 20 +- cov/cmdline/stream.h.gcov.html | 76 +- cov/cmdline/support.c.func-sort-c.html | 92 +- cov/cmdline/support.c.func.html | 92 +- cov/cmdline/support.c.gcov.html | 1117 +-- cov/cmdline/sync.c.func-sort-c.html | 8 +- cov/cmdline/sync.c.func.html | 8 +- cov/cmdline/sync.c.gcov.html | 538 +- cov/cmdline/unix.c.func-sort-c.html | 76 +- cov/cmdline/unix.c.func.html | 76 +- cov/cmdline/unix.c.gcov.html | 2027 +++-- cov/cmdline/util.c.func-sort-c.html | 28 +- cov/cmdline/util.c.func.html | 28 +- cov/cmdline/util.c.gcov.html | 120 +- cov/cmdline/util.h.func-sort-c.html | 10 +- cov/cmdline/util.h.func.html | 10 +- cov/cmdline/util.h.gcov.html | 52 +- 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 | 22 +- cov/raid/cpu.h.func.html | 38 +- cov/raid/cpu.h.gcov.html | 130 +- cov/raid/gf.h.func-sort-c.html | 2 +- cov/raid/gf.h.func.html | 2 +- cov/raid/gf.h.gcov.html | 10 +- 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 | 8 +- cov/raid/int.c.func.html | 8 +- cov/raid/int.c.gcov.html | 120 +- cov/raid/internal.h.func-sort-c.html | 2 +- cov/raid/internal.h.func.html | 2 +- cov/raid/internal.h.gcov.html | 10 +- 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 | 8 +- cov/raid/memory.c.func.html | 8 +- cov/raid/memory.c.gcov.html | 86 +- cov/raid/module.c.func-sort-c.html | 16 +- cov/raid/module.c.func.html | 16 +- cov/raid/module.c.gcov.html | 787 +- cov/raid/raid.c.func-sort-c.html | 18 +- cov/raid/raid.c.func.html | 18 +- cov/raid/raid.c.gcov.html | 206 +- 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 | 20 +- cov/raid/x86.c.func.html | 20 +- cov/raid/x86.c.gcov.html | 1014 +-- 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 | 8 +- cov/tommyds/tommyarray.c.func.html | 8 +- cov/tommyds/tommyarray.c.gcov.html | 36 +- cov/tommyds/tommyarray.h.func-sort-c.html | 14 +- cov/tommyds/tommyarray.h.func.html | 10 +- cov/tommyds/tommyarray.h.gcov.html | 24 +- cov/tommyds/tommyarrayblk.c.func-sort-c.html | 2 +- cov/tommyds/tommyarrayblk.c.func.html | 2 +- cov/tommyds/tommyarrayblk.c.gcov.html | 2 +- cov/tommyds/tommyarrayblk.h.func-sort-c.html | 2 +- cov/tommyds/tommyarrayblk.h.func.html | 2 +- cov/tommyds/tommyarrayblk.h.gcov.html | 2 +- .../tommyarrayblkof.c.func-sort-c.html | 8 +- cov/tommyds/tommyarrayblkof.c.func.html | 8 +- cov/tommyds/tommyarrayblkof.c.gcov.html | 46 +- .../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 | 12 +- cov/tommyds/tommychain.h.func.html | 12 +- cov/tommyds/tommychain.h.gcov.html | 142 +- 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 | 18 +- cov/tommyds/tommyhashdyn.c.func.html | 18 +- cov/tommyds/tommyhashdyn.c.gcov.html | 130 +- 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 | 6 +- cov/tommyds/tommylist.c.func.html | 6 +- cov/tommyds/tommylist.c.gcov.html | 48 +- cov/tommyds/tommylist.h.func-sort-c.html | 22 +- cov/tommyds/tommylist.h.func.html | 22 +- cov/tommyds/tommylist.h.gcov.html | 106 +- cov/tommyds/tommytree.c.func-sort-c.html | 48 +- cov/tommyds/tommytree.c.func.html | 34 +- cov/tommyds/tommytree.c.gcov.html | 226 +- 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 | 6 +- cov/tommyds/tommytypes.h.func.html | 6 +- cov/tommyds/tommytypes.h.gcov.html | 10 +- 207 files changed, 16507 insertions(+), 15922 deletions(-) diff --git a/cov/cmdline/check.c.func-sort-c.html b/cov/cmdline/check.c.func-sort-c.html index 9d707518..2de16b5f 100644 --- a/cov/cmdline/check.c.func-sort-c.html +++ b/cov/cmdline/check.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 713 + 712 781 - 91.3 % + 91.2 % Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -61,31 +61,27 @@ block_is_enabled - 1866664 + 1869102 file_post - 933332 + 934551 repair - 869089 + 870166 blockcmp - 468172 + 469276 repair_step - 260805 + 254143 is_hash_matching - 209449 - - - is_parity_matching - 8386 + 211335 state_check @@ -95,6 +91,10 @@ state_check_process 118 + + is_parity_matching + 8 +
diff --git a/cov/cmdline/check.c.func.html b/cov/cmdline/check.c.func.html index 9544066b..b46f8731 100644 --- a/cov/cmdline/check.c.func.html +++ b/cov/cmdline/check.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 713 + 712 781 - 91.3 % + 91.2 % Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -61,31 +61,31 @@ block_is_enabled - 1866664 + 1869102 blockcmp - 468172 + 469276 file_post - 933332 + 934551 is_hash_matching - 209449 + 211335 is_parity_matching - 8386 + 8 repair - 869089 + 870166 repair_step - 260805 + 254143 state_check diff --git a/cov/cmdline/check.c.gcov.html b/cov/cmdline/check.c.gcov.html index d2e357c6..2e56b65e 100644 --- a/cov/cmdline/check.c.gcov.html +++ b/cov/cmdline/check.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 713 + 712 781 - 91.3 % + 91.2 % Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -129,64 +129,64 @@ 67 : * Check if a block hash matches the specified buffer. 68 : * Return ==0 if equal 69 : */ - 70 468172 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) + 70 469276 : static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) 71 : { 72 : unsigned char hash[HASH_SIZE]; 73 : 74 : /* now compute the hash of the valid part */ - 75 468172 : if (rehash) { - 76 22270 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size); + 75 469276 : if (rehash) { + 76 0 : memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size); 77 : } else { - 78 445902 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); + 78 469276 : memhash(state->hash, state->hashseed, hash, buffer, pos_size); 79 : } 80 : 81 : /* compare the hash */ - 82 468172 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { - 83 13872 : return -1; + 82 469276 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 83 13920 : return -1; 84 : } 85 : 86 : /* compare to the end of the block */ - 87 454300 : if (pos_size < state->block_size) { - 88 187749 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { - 89 24 : return -1; + 87 455356 : if (pos_size < state->block_size) { + 88 188035 : if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { + 89 18 : return -1; 90 : } 91 : } 92 : - 93 454276 : return 0; + 93 455338 : return 0; 94 : } 95 : 96 : /** 97 : * Check if the hash of all the failed block we are expecting to recover are now matching. 98 : */ - 99 209449 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero) + 99 211335 : static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero) 100 : { 101 : unsigned j; 102 : int hash_checked; 103 : - 104 209449 : hash_checked = 0; /* keep track if we check at least one block */ + 104 211335 : hash_checked = 0; /* keep track if we check at least one block */ 105 : 106 : /* check if the recovered blocks are OK */ - 107 668247 : for (j = 0; j < failed_count; ++j) { + 107 671195 : for (j = 0; j < failed_count; ++j) { 108 : /* if we are expected to recover this block */ - 109 472694 : if (!failed[failed_map[j]].is_outofdate + 109 473798 : if (!failed[failed_map[j]].is_outofdate 110 : /* if the block has a hash to check */ - 111 468172 : && block_has_updated_hash(failed[failed_map[j]].block) + 111 469276 : && block_has_updated_hash(failed[failed_map[j]].block) 112 : ) { 113 : /* if a hash doesn't match, fail the check */ - 114 468172 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); - 115 468172 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { - 116 13896 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]); - 117 13896 : return 0; + 114 469276 : unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); + 115 469276 : if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { + 116 13938 : log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]); + 117 13938 : return 0; 118 : } 119 : - 120 454276 : hash_checked = 1; + 120 455338 : hash_checked = 1; 121 : } 122 : } 123 : 124 : /* if nothing checked, we reject it */ 125 : /* note that we are excluding this case at upper level */ 126 : /* but checking again doesn't hurt */ - 127 195553 : if (!hash_checked) { + 127 197397 : if (!hash_checked) { 128 : /* LCOV_EXCL_START */ 129 : return 0; 130 : /* LCOV_EXCL_STOP */ @@ -194,23 +194,23 @@ 132 : 133 : /* if we checked something, and no block failed the check */ 134 : /* recompute all the redundancy information */ - 135 195553 : raid_gen(diskmax, state->level, state->block_size, buffer); - 136 195553 : return 1; + 135 197397 : raid_gen(diskmax, state->level, state->block_size, buffer); + 136 197397 : return 1; 137 : } 138 : 139 : /** 140 : * Check if specified parity is now matching with a recomputed one. 141 : */ - 142 8386 : static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, void** buffer, void** buffer_recov) + 142 8 : static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, void** buffer, void** buffer_recov) 143 : { 144 : /* recompute parity, note that we don't need parity over i */ - 145 8386 : raid_gen(diskmax, i + 1, state->block_size, buffer); + 145 8 : raid_gen(diskmax, i + 1, state->block_size, buffer); 146 : 147 : /* if the recovered parity block matches */ - 148 8386 : if (memcmp(buffer[diskmax + i], buffer_recov[i], state->block_size) == 0) { + 148 8 : if (memcmp(buffer[diskmax + i], buffer_recov[i], state->block_size) == 0) { 149 : /* recompute all the redundancy information */ - 150 8386 : raid_gen(diskmax, state->level, state->block_size, buffer); - 151 8386 : return 1; + 150 8 : raid_gen(diskmax, state->level, state->block_size, buffer); + 151 8 : return 1; 152 : } 153 : 154 0 : return 0; @@ -221,7 +221,7 @@ 159 : * Return <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. 160 : * If success, the parity are computed in the buffer variable. 161 : */ - 162 260805 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) + 162 254143 : static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) 163 : { 164 : unsigned i, n; 165 : int error; @@ -230,7 +230,7 @@ 168 : int ip[LEV_MAX]; 169 : 170 : /* no fix required, already checked at higher level, but just to be sure */ - 171 260805 : if (failed_count == 0) { + 171 254143 : if (failed_count == 0) { 172 : /* LCOV_EXCL_START */ 173 : /* recompute only the parity */ 174 : raid_gen(diskmax, state->level, state->block_size, buffer); @@ -238,52 +238,52 @@ 176 : /* LCOV_EXCL_STOP */ 177 : } 178 : - 179 260805 : n = state->level; - 180 260805 : error = 0; + 179 254143 : n = state->level; + 180 254143 : error = 0; 181 : 182 : /* setup vector of failed disk indexes */ - 183 908349 : for (i = 0; i < failed_count; ++i) - 184 647544 : id[i] = failed[failed_map[i]].index; + 183 894073 : for (i = 0; i < failed_count; ++i) + 184 639930 : id[i] = failed[failed_map[i]].index; 185 : 186 : /* check if there is at least a failed block that can be checked for correctness using the hash */ 187 : /* if there isn't, we have to sacrifice a parity block to check that the result is correct */ - 188 260805 : has_hash = 0; - 189 908349 : for (i = 0; i < failed_count; ++i) { + 188 254143 : has_hash = 0; + 189 894073 : for (i = 0; i < failed_count; ++i) { 190 : /* if we are expected to recover this block */ - 191 647544 : if (!failed[failed_map[i]].is_outofdate + 191 639930 : if (!failed[failed_map[i]].is_outofdate 192 : /* if the block has a hash to check */ - 193 638500 : && block_has_updated_hash(failed[failed_map[i]].block) + 193 630886 : && block_has_updated_hash(failed[failed_map[i]].block) 194 : ) - 195 630114 : has_hash = 1; + 195 630878 : has_hash = 1; 196 : } 197 : 198 : /* if we don't have a hash, but we have an extra parity */ 199 : /* (strictly-less failures than number of parities) */ - 200 260805 : if (!has_hash && failed_count < n) { + 200 254143 : if (!has_hash && failed_count < n) { 201 : /* number of parity to use, one more to check the recovering */ - 202 8386 : unsigned r = failed_count + 1; + 202 8 : unsigned r = failed_count + 1; 203 : 204 : /* all combinations (r of n) parities */ - 205 8386 : combination_first(r, n, ip); + 205 8 : combination_first(r, n, ip); 206 : do { 207 : /* if a parity is missing, do nothing */ - 208 25158 : for (i = 0; i < r; ++i) { - 209 16772 : if (buffer_recov[ip[i]] == 0) + 208 24 : for (i = 0; i < r; ++i) { + 209 16 : if (buffer_recov[ip[i]] == 0) 210 0 : break; 211 : } - 212 8386 : if (i != r) + 212 8 : if (i != r) 213 0 : continue; 214 : 215 : /* copy the parities to use, one less because the last is used for checking */ - 216 16772 : for (i = 0; i < r - 1; ++i) - 217 8386 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + 216 16 : for (i = 0; i < r - 1; ++i) + 217 8 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); 218 : 219 : /* recover using one less parity, the ip[r-1] one */ - 220 8386 : raid_data(r - 1, id, ip, diskmax, state->block_size, buffer); + 220 8 : raid_data(r - 1, id, ip, diskmax, state->block_size, buffer); 221 : 222 : /* use the remaining ip[r-1] parity to check the result */ - 223 8386 : if (is_parity_matching(state, diskmax, ip[r - 1], buffer, buffer_recov)) - 224 8386 : return 0; + 223 8 : if (is_parity_matching(state, diskmax, ip[r - 1], buffer, buffer_recov)) + 224 8 : return 0; 225 : 226 : /* log */ 227 0 : log_tag("parity_error:%u:", pos); @@ -299,54 +299,54 @@ 237 : 238 : /* if we have a hash, and enough parities */ 239 : /* (less-or-equal failures than number of parities) */ - 240 252419 : if (has_hash && failed_count <= n) { + 240 254135 : if (has_hash && failed_count <= n) { 241 : /* number of parities to use equal at the number of failures */ - 242 204707 : unsigned r = failed_count; + 242 206565 : unsigned r = failed_count; 243 : 244 : /* all combinations (r of n) parities */ - 245 204707 : combination_first(r, n, ip); + 245 206565 : combination_first(r, n, ip); 246 : do { 247 : /* if a parity is missing, do nothing */ - 248 686792 : for (i = 0; i < r; ++i) { - 249 477343 : if (buffer_recov[ip[i]] == 0) + 248 689782 : for (i = 0; i < r; ++i) { + 249 478447 : if (buffer_recov[ip[i]] == 0) 250 4649 : break; 251 : } - 252 214098 : if (i != r) + 252 215984 : if (i != r) 253 4649 : continue; 254 : 255 : /* copy the parities to use */ - 256 682143 : for (i = 0; i < r; ++i) - 257 472694 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + 256 685133 : for (i = 0; i < r; ++i) + 257 473798 : memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); 258 : 259 : /* recover */ - 260 209449 : raid_data(r, id, ip, diskmax, state->block_size, buffer); + 260 211335 : raid_data(r, id, ip, diskmax, state->block_size, buffer); 261 : 262 : /* use the hash to check the result */ - 263 209449 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) - 264 195553 : return 0; + 263 211335 : if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) + 264 197397 : return 0; 265 : 266 : /* log */ - 267 13896 : log_tag("parity_error:%u:", pos); - 268 27792 : for (i = 0; i < r; ++i) { - 269 13896 : if (i != 0) + 267 13938 : log_tag("parity_error:%u:", pos); + 268 27876 : for (i = 0; i < r; ++i) { + 269 13938 : if (i != 0) 270 0 : log_tag("/"); - 271 13896 : log_tag("%s", lev_config_name(ip[i])); + 271 13938 : log_tag("%s", lev_config_name(ip[i])); 272 : } - 273 13896 : log_tag(":hash: Hash mismatch\n"); - 274 13896 : ++error; - 275 37090 : } while (combination_next(r, n, ip)); + 273 13938 : log_tag(":hash: Hash mismatch\n"); + 274 13938 : ++error; + 275 37174 : } while (combination_next(r, n, ip)); 276 : } 277 : 278 : /* return the number of failed attempts, or -1 if no strategy */ - 279 56866 : if (error) - 280 9154 : return error; + 279 56738 : if (error) + 280 9168 : return error; 281 : - 282 47712 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", + 282 47570 : log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", 283 : pos, failed_count, n, has_hash ? "with" : "without"); - 284 47712 : return -1; + 284 47570 : return -1; 285 : } 286 : - 287 869089 : static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) + 287 870166 : static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) 288 : { 289 : int ret; 290 : int error; @@ -355,51 +355,51 @@ 293 : int something_to_recover; 294 : int something_unsynced; 295 : - 296 869089 : error = 0; + 296 870166 : error = 0; 297 : 298 : /* if nothing failed, just recompute the parity */ - 299 869089 : if (failed_count == 0) { - 300 581432 : raid_gen(diskmax, state->level, state->block_size, buffer); - 301 581432 : return 0; + 299 870166 : if (failed_count == 0) { + 300 580935 : raid_gen(diskmax, state->level, state->block_size, buffer); + 301 580935 : return 0; 302 : } 303 : 304 : /* logs the status */ - 305 1016720 : for (j = 0; j < failed_count; ++j) { + 305 1019108 : for (j = 0; j < failed_count; ++j) { 306 : const char* desc; 307 : const char* hash; 308 : const char* data; - 309 729063 : struct snapraid_block* block = failed[j].block; - 310 729063 : unsigned block_state = block_state_get(block); + 309 729877 : struct snapraid_block* block = failed[j].block; + 310 729877 : unsigned block_state = block_state_get(block); 311 : - 312 729063 : switch (block_state) { + 312 729877 : switch (block_state) { 313 18454 : case BLOCK_STATE_DELETED : desc = "delete"; break; - 314 52081 : case BLOCK_STATE_CHG : desc = "change"; break; - 315 24042 : case BLOCK_STATE_REP : desc = "replace"; break; - 316 634486 : case BLOCK_STATE_BLK : desc = "block"; break; + 314 13851 : case BLOCK_STATE_CHG : desc = "change"; break; + 315 62282 : case BLOCK_STATE_REP : desc = "replace"; break; + 316 635290 : case BLOCK_STATE_BLK : desc = "block"; break; 317 : /* LCOV_EXCL_START */ 318 : default : desc = "unknown"; break; 319 : /* LCOV_EXCL_STOP */ 320 : } 321 : - 322 729063 : if (hash_is_invalid(block->hash)) { - 323 13841 : hash = "lost"; - 324 715222 : } else if (hash_is_zero(block->hash)) { - 325 29602 : hash = "zero"; + 322 729877 : if (hash_is_invalid(block->hash)) { + 323 13843 : hash = "lost"; + 324 716034 : } else if (hash_is_zero(block->hash)) { + 325 8 : hash = "zero"; 326 : } else { - 327 685620 : hash = "known"; + 327 716026 : hash = "known"; 328 : } 329 : - 330 729063 : if (failed[j].is_bad) - 331 643340 : data = "bad"; + 330 729877 : if (failed[j].is_bad) + 331 644152 : data = "bad"; 332 : else - 333 85723 : data = "good"; + 333 85725 : data = "good"; 334 : - 335 729063 : if (failed[j].file) { - 336 710609 : struct snapraid_disk* disk = failed[j].disk; - 337 710609 : struct snapraid_file* file = failed[j].file; - 338 710609 : block_off_t file_pos = failed[j].file_pos; + 335 729877 : if (failed[j].file) { + 336 711423 : struct snapraid_disk* disk = failed[j].disk; + 337 711423 : struct snapraid_file* file = failed[j].file; + 338 711423 : block_off_t file_pos = failed[j].file_pos; 339 : - 340 710609 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc(file->sub), file_pos); + 340 711423 : log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc(file->sub), file_pos); 341 : } else { 342 18454 : log_tag("entry:%u:%s:%s:%s:\n", j, desc, hash, data); 343 : } @@ -421,58 +421,58 @@ 359 : /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */ 360 : /* but we are not interested in DELETED ones. */ 361 : - 362 287657 : n = 0; - 363 287657 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 364 1016720 : for (j = 0; j < failed_count; ++j) { - 365 729063 : if (failed[j].is_bad) { - 366 643340 : unsigned block_state = block_state_get(failed[j].block); + 362 289231 : n = 0; + 363 289231 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 364 1019108 : for (j = 0; j < failed_count; ++j) { + 365 729877 : if (failed[j].is_bad) { + 366 644152 : unsigned block_state = block_state_get(failed[j].block); 367 : - 368 643340 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ + 368 644152 : assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ 369 : 370 : /* if we have the hash for it */ - 371 643340 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) + 371 644152 : if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) 372 : /* try to fetch the block using the known hash */ - 373 634954 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 - 374 630482 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) + 373 644144 : && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 + 374 639672 : || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) 375 : ) { 376 : /* we already have corrected it! */ - 377 13884 : log_tag("hash_import: Fixed entry %u\n", j); + 377 22310 : log_tag("hash_import: Fixed entry %u\n", j); 378 : } else { 379 : /* otherwise try to recover it */ - 380 629456 : failed_map[n] = j; - 381 629456 : ++n; + 380 621842 : failed_map[n] = j; + 381 621842 : ++n; 382 : 383 : /* we have something to try to recover */ - 384 629456 : something_to_recover = 1; + 384 621842 : something_to_recover = 1; 385 : } 386 : } 387 : } 388 : 389 : /* if nothing to fix */ - 390 287657 : if (!something_to_recover) { - 391 35896 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n); + 390 289231 : if (!something_to_recover) { + 391 44132 : log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n); 392 : 393 : /* recompute only the parity */ - 394 35896 : raid_gen(diskmax, state->level, state->block_size, buffer); - 395 35896 : return 0; + 394 44132 : raid_gen(diskmax, state->level, state->block_size, buffer); + 395 44132 : return 0; 396 : } 397 : - 398 251761 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); - 399 251761 : if (ret == 0) { + 398 245099 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); + 399 245099 : if (ret == 0) { 400 : /* reprocess the CHG blocks, for which we don't have a hash to check */ - 401 : /* if they were BAD we have to use some euristics to ensure that we have recovered */ + 401 : /* if they were BAD we have to use some heuristics to ensure that we have recovered */ 402 : /* the state after the sync. If unsure, we assume the worst case */ 403 : - 404 683858 : for (j = 0; j < failed_count; ++j) { + 404 670084 : for (j = 0; j < failed_count; ++j) { 405 : /* we take care only of BAD blocks we have to write back */ - 406 484441 : if (failed[j].is_bad) { - 407 470929 : unsigned block_state = block_state_get(failed[j].block); + 406 477201 : if (failed[j].is_bad) { + 407 463729 : unsigned block_state = block_state_get(failed[j].block); 408 : 409 : /* BLK and REP blocks are always OK, because at this point */ 410 : /* we have already checked their hash */ - 411 470929 : if (block_state != BLOCK_STATE_CHG) { - 412 462543 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); - 413 462543 : continue; + 411 463729 : if (block_state != BLOCK_STATE_CHG) { + 412 463721 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 413 463721 : continue; 414 : } 415 : 416 : /* for CHG blocks we have to 'guess' if they are correct or not */ @@ -480,22 +480,22 @@ 418 : /* if the hash is invalid we cannot check the result */ 419 : /* this could happen if we have lost this information */ 420 : /* after an aborted sync */ - 421 8386 : if (hash_is_invalid(failed[j].block->hash)) { + 421 8 : if (hash_is_invalid(failed[j].block->hash)) { 422 : /* it may contain garbage */ 423 0 : failed[j].is_outofdate = 1; 424 : 425 0 : log_tag("hash_unknown: Unknown hash on entry %u\n", j); - 426 8386 : } else if (hash_is_zero(failed[j].block->hash)) { + 426 8 : } else if (hash_is_zero(failed[j].block->hash)) { 427 : /* if the block is not filled with 0, we are sure to have */ 428 : /* restored it to the state after the 'sync' */ 429 : /* instead, if the block is filled with 0, it could be either that the */ 430 : /* block after the sync is really filled by 0, or that */ 431 : /* we restored the block before the 'sync'. */ - 432 8386 : if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) == 0) { + 432 8 : if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) == 0) { 433 : /* it may contain garbage */ - 434 4192 : failed[j].is_outofdate = 1; + 434 8 : failed[j].is_outofdate = 1; 435 : - 436 4192 : log_tag("hash_unknown: Maybe old zero on entry %u\n", j); + 436 8 : log_tag("hash_unknown: Maybe old zero on entry %u\n", j); 437 : } 438 : } else { 439 : /* if the hash is different than the previous one, we are sure to have */ @@ -514,15 +514,15 @@ 452 : } 453 : } 454 : - 455 199417 : return 0; + 455 192883 : return 0; 456 : } - 457 52344 : if (ret > 0) - 458 9154 : error += ret; + 457 52216 : if (ret > 0) + 458 9168 : error += ret; 459 : - 460 52344 : if (ret < 0) - 461 43190 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); + 460 52216 : if (ret < 0) + 461 43048 : log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); 462 : else - 463 9154 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); + 463 9168 : log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); 464 : 465 : /* Now assume that the parity IS NOT updated at the current state, */ 466 : /* but still represent the state before the last 'sync' process. */ @@ -532,15 +532,15 @@ 470 : /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */ 471 : /* even if marked as bad, because we don't have parity for them and it's just impossible, */ 472 : /* and we are not interested to recover DELETED ones. */ - 473 52344 : n = 0; - 474 52344 : something_to_recover = 0; /* keep track if there is at least one block to fix */ - 475 52344 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ - 476 232704 : for (j = 0; j < failed_count; ++j) { - 477 180360 : unsigned block_state = block_state_get(failed[j].block); + 473 52216 : n = 0; + 474 52216 : something_to_recover = 0; /* keep track if there is at least one block to fix */ + 475 52216 : something_unsynced = 0; /* keep track if we have some unsynced info to process */ + 476 232278 : for (j = 0; j < failed_count; ++j) { + 477 180062 : unsigned block_state = block_state_get(failed[j].block); 478 : - 479 180360 : if (block_state == BLOCK_STATE_DELETED - 480 171316 : || block_state == BLOCK_STATE_CHG - 481 171316 : || block_state == BLOCK_STATE_REP + 479 180062 : if (block_state == BLOCK_STATE_DELETED + 480 171018 : || block_state == BLOCK_STATE_CHG + 481 171018 : || block_state == BLOCK_STATE_REP 482 : ) { 483 : /* If the block is CHG, REP or DELETED, we don't have the original content of block, */ 484 : /* and we must try to recover it. */ @@ -580,26 +580,26 @@ 518 : /* this applies to REP blocks because we are going to recover the old state */ 519 : /* and the REP hash represent the new one */ 520 : /* it also applies to CHG and DELETE blocks because we want to have */ - 521 : /* a succesful recovering only if a BLK one is matching */ + 521 : /* a successful recovering only if a BLK one is matching */ 522 9044 : failed[j].is_outofdate = 1; - 523 171316 : } else if (failed[j].is_bad) { + 523 171018 : } else if (failed[j].is_bad) { 524 : /* If the block is bad we don't know its content, and we try to recover it */ 525 : /* At this point, we can have only BLK ones */ 526 : - 527 171316 : assert(block_state == BLOCK_STATE_BLK); + 527 171018 : assert(block_state == BLOCK_STATE_BLK); 528 : 529 : /* we have something we are interested to recover */ - 530 171316 : something_to_recover = 1; + 530 171018 : something_to_recover = 1; 531 : 532 : /* we try to recover it */ - 533 171316 : failed_map[n] = j; - 534 171316 : ++n; + 533 171018 : failed_map[n] = j; + 534 171018 : ++n; 535 : } 536 : } 537 : 538 : /* if nothing to fix, we just don't try */ 539 : /* if nothing unsynced we also don't retry, because it's the same try as before */ - 540 52344 : if (something_to_recover && something_unsynced) { + 540 52216 : if (something_to_recover && something_unsynced) { 541 9044 : ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); 542 9044 : if (ret == 0) { 543 : /* reprocess the REP and CHG blocks, for which we have recovered and old state */ @@ -633,17 +633,17 @@ 571 : else 572 0 : log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret); 573 : } else { - 574 43300 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, + 574 43172 : log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, 575 : !something_to_recover ? " nothing to recover" : "", 576 : !something_unsynced ? " nothing unsynched" : "" 577 : ); 578 : } 579 : 580 : /* return the number of failed attempts, or -1 if no strategy */ - 581 47822 : if (error) - 582 4632 : return error; + 581 47694 : if (error) + 582 4646 : return error; 583 : else - 584 43190 : return -1; + 584 43048 : return -1; 585 : } 586 : 587 : /** @@ -655,19 +655,19 @@ 593 : * fix. This assumption is not always correct, and in such case we have to 594 : * skip the whole postprocessing. And example, is when fixing only bad blocks. 595 : */ - 596 933332 : static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax) + 596 934551 : static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax) 597 : { 598 : unsigned j; 599 : int ret; 600 : - 601 : /* if we are processing only bad blocks, we don't have to do any postprocessing */ + 601 : /* if we are processing only bad blocks, we don't have to do any post-processing */ 602 : /* as we don't have any guarantee to process the last block of the fixed files */ - 603 933332 : if (state->opt.badonly) - 604 9342 : return 0; + 603 934551 : if (state->opt.badonly) + 604 9358 : return 0; 605 : 606 : /* for all the files print the final status, and does the final time fix */ 607 : /* we also ensure to close files after processing the last block */ - 608 6467930 : for (j = 0; j < diskmax; ++j) { + 608 6476351 : for (j = 0; j < diskmax; ++j) { 609 : struct snapraid_block* block; 610 : struct snapraid_disk* disk; 611 : struct snapraid_file* collide_file; @@ -676,51 +676,51 @@ 614 : char path[PATH_MAX]; 615 : uint64_t inode; 616 : - 617 5543940 : disk = handle[j].disk; - 618 5543940 : if (!disk) { + 617 5551158 : disk = handle[j].disk; + 618 5551158 : if (!disk) { 619 : /* if no disk, nothing to do */ - 620 3396852 : continue; + 620 3403281 : continue; 621 : } 622 : - 623 5529927 : block = fs_par2block_get(disk, i); - 624 5529927 : if (!block_has_file(block)) { + 623 5537121 : block = fs_par2block_get(disk, i); + 624 5537121 : if (!block_has_file(block)) { 625 : /* if no file, nothing to do */ - 626 210017 : continue; + 626 210707 : continue; 627 : } 628 : - 629 5319910 : file = fs_par2file_get(disk, i, &file_pos); - 630 5319910 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + 629 5326414 : file = fs_par2file_get(disk, i, &file_pos); + 630 5326414 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); 631 : 632 : /* if it isn't the last block in the file */ - 633 5319910 : if (!file_block_is_last(file, file_pos)) { + 633 5326414 : if (!file_block_is_last(file, file_pos)) { 634 : /* nothing to do */ - 635 3158809 : continue; + 635 3164500 : continue; 636 : } 637 : 638 : /* if the file is excluded, we have nothing to adjust as the file is never written */ - 639 2161101 : if (file_flag_has(file, FILE_IS_EXCLUDED) - 640 2064360 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) { + 639 2161914 : if (file_flag_has(file, FILE_IS_EXCLUDED) + 640 2065035 : || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) { 641 : /* nothing to do, but close the file */ 642 : goto close_and_continue; 643 : } 644 : 645 : /* finish the fix process if it's the last block of the files */ - 646 2064360 : if (fix) { + 646 2065035 : if (fix) { 647 : /* mark that we finished with this file */ 648 : /* to identify later any NOT finished ones */ - 649 757042 : file_flag_set(file, FILE_IS_FINISHED); + 649 757215 : file_flag_set(file, FILE_IS_FINISHED); 650 : 651 : /* if the file is damaged, meaning that a fix failed */ - 652 757042 : if (file_flag_has(file, FILE_IS_DAMAGED)) { + 652 757215 : if (file_flag_has(file, FILE_IS_DAMAGED)) { 653 : /* rename it to .unrecoverable */ 654 : char path_to[PATH_MAX]; 655 : - 656 64972 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); + 656 63364 : pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); 657 : 658 : /* ensure to close the file before renaming */ - 659 64972 : if (handle[j].file == file) { - 660 64972 : ret = handle_close(&handle[j]); - 661 64972 : if (ret != 0) { + 659 63364 : if (handle[j].file == file) { + 660 63364 : ret = handle_close(&handle[j]); + 661 63364 : if (ret != 0) { 662 : /* LCOV_EXCL_START */ 663 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); 664 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -729,8 +729,8 @@ 667 : } 668 : } 669 : - 670 64972 : ret = rename(path, path_to); - 671 64972 : if (ret != 0) { + 670 63364 : ret = rename(path, path_to); + 671 63364 : if (ret != 0) { 672 : /* LCOV_EXCL_START */ 673 : log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno)); 674 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); @@ -738,22 +738,22 @@ 676 : /* LCOV_EXCL_STOP */ 677 : } 678 : - 679 64972 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub)); - 680 64972 : msg_info("unrecoverable %s\n", path); + 679 63364 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub)); + 680 63364 : msg_info("unrecoverable %s\n", path); 681 : 682 : /* and do not set the time if damaged */ - 683 64972 : goto close_and_continue; + 683 63364 : goto close_and_continue; 684 : } 685 : 686 : /* if the file is not fixed, meaning that it is untouched */ - 687 692070 : if (!file_flag_has(file, FILE_IS_FIXED)) { + 687 693851 : if (!file_flag_has(file, FILE_IS_FIXED)) { 688 : /* nothing to do, but close the file */ - 689 574306 : goto close_and_continue; + 689 574395 : goto close_and_continue; 690 : } 691 : 692 : /* if the file is closed or different than the one expected, reopen it */ 693 : /* a different open file could happen when filtering for bad blocks */ - 694 117764 : if (handle[j].file != file) { + 694 119456 : if (handle[j].file != file) { 695 : /* close a potential different file */ 696 0 : ret = handle_close(&handle[j]); 697 0 : if (ret != 0) { @@ -776,13 +776,13 @@ 714 : } 715 : } 716 : - 717 117764 : log_tag("status:recovered:%s:%s\n", disk->name, esc(file->sub)); - 718 117764 : msg_info("recovered %s\n", path); + 717 119456 : log_tag("status:recovered:%s:%s\n", disk->name, esc(file->sub)); + 718 119456 : msg_info("recovered %s\n", path); 719 : - 720 117764 : inode = handle[j].st.st_ino; + 720 119456 : inode = handle[j].st.st_ino; 721 : 722 : /* search for the corresponding inode */ - 723 117764 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + 723 119456 : collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); 724 : 725 : /* if the inode is already in the database and it refers at a different file name, */ 726 : /* we can fix the file time ONLY if the time and size allow to differentiate */ @@ -792,15 +792,15 @@ 730 : /* when recreating them the inodes may be reused in a different order, */ 731 : /* and at the next sync some files may have matching inode/size/time even if different name */ 732 : /* not allowing sync to detect that the file is changed and not renamed */ - 733 117764 : if (!collide_file /* if not in the database, there is no collision */ - 734 29250 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ - 735 27741 : || collide_file->size != file->size /* if the size is different, the collision is identified */ - 736 5 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ - 737 3 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ + 733 119456 : if (!collide_file /* if not in the database, there is no collision */ + 734 37496 : || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ + 735 35757 : || collide_file->size != file->size /* if the size is different, the collision is identified */ + 736 10 : || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ + 737 5 : || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ 738 : ) { 739 : /* set the original modification time */ - 740 117763 : ret = handle_utime(&handle[j]); - 741 235526 : if (ret == -1) { + 740 119455 : ret = handle_utime(&handle[j]); + 741 238910 : if (ret == -1) { 742 : /* LCOV_EXCL_START */ 743 : /* mark the file as damaged */ 744 : file_flag_set(file, FILE_IS_DAMAGED); @@ -814,22 +814,22 @@ 752 : } else { 753 : /* we are not fixing, but only checking */ 754 : /* print just the final status */ - 755 1307318 : if (file_flag_has(file, FILE_IS_DAMAGED)) { - 756 9389 : if (state->opt.auditonly) { - 757 2806 : log_tag("status:damaged:%s:%s\n", disk->name, esc(file->sub)); - 758 2806 : msg_info("damaged %s\n", path); + 755 1307820 : if (file_flag_has(file, FILE_IS_DAMAGED)) { + 756 9087 : if (state->opt.auditonly) { + 757 2758 : log_tag("status:damaged:%s:%s\n", disk->name, esc(file->sub)); + 758 2758 : msg_info("damaged %s\n", path); 759 : } else { - 760 6583 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub)); - 761 6583 : msg_info("unrecoverable %s\n", path); + 760 6329 : log_tag("status:unrecoverable:%s:%s\n", disk->name, esc(file->sub)); + 761 6329 : msg_info("unrecoverable %s\n", path); 762 : } - 763 1297929 : } else if (file_flag_has(file, FILE_IS_FIXED)) { - 764 76370 : log_tag("status:recoverable:%s:%s\n", disk->name, esc(file->sub)); - 765 76370 : msg_info("recoverable %s\n", path); + 763 1298733 : } else if (file_flag_has(file, FILE_IS_FIXED)) { + 764 76728 : log_tag("status:recoverable:%s:%s\n", disk->name, esc(file->sub)); + 765 76728 : msg_info("recoverable %s\n", path); 766 : } else { - 767 1221559 : log_tag("status:correct:%s:%s\n", disk->name, esc(file->sub)); + 767 1222005 : log_tag("status:correct:%s:%s\n", disk->name, esc(file->sub)); 768 : /* we don't use msg_verbose() because it also goes into the log */ - 769 1221559 : if (msg_level >= MSG_VERBOSE) - 770 23233 : msg_info("correct %s\n", path); + 769 1222005 : if (msg_level >= MSG_VERBOSE) + 770 23203 : msg_info("correct %s\n", path); 771 : } 772 : } 773 : @@ -837,11 +837,11 @@ 775 : /* if the opened file is the correct one, close it */ 776 : /* in case of excluded and fragmented files it's possible */ 777 : /* that the opened file is not the current one */ - 778 2161101 : if (handle[j].file == file) { + 778 2161914 : if (handle[j].file == file) { 779 : /* ensure to close the file just after finishing with it */ 780 : /* to avoid to keep it open without any possible use */ - 781 1975748 : ret = handle_close(&handle[j]); - 782 1975748 : if (ret != 0) { + 781 1978155 : ret = handle_close(&handle[j]); + 782 1978155 : if (ret != 0) { 783 : /* LCOV_EXCL_START */ 784 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); 785 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -851,56 +851,56 @@ 789 : } 790 : } 791 : - 792 923990 : return 0; + 792 925193 : return 0; 793 : } 794 : 795 : /** 796 : * Check if we have to process the specified block index ::i. 797 : */ - 798 1866664 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax) + 798 1869102 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax) 799 : { 800 : snapraid_info info; 801 : unsigned j; 802 : unsigned l; 803 : 804 : /* get block specific info */ - 805 1866664 : info = info_get(&state->infoarr, i); + 805 1869102 : info = info_get(&state->infoarr, i); 806 : 807 : /* if we filter for only bad blocks */ - 808 1866664 : if (state->opt.badonly) { + 808 1869102 : if (state->opt.badonly) { 809 : /* skip if this is not bad */ - 810 18684 : if (!info_get_bad(info)) - 811 15080 : return 0; + 810 18716 : if (!info_get_bad(info)) + 811 15174 : return 0; 812 : } 813 : 814 : /* for each parity */ - 815 2120448 : for (l = 0; l < state->level; ++l) { - 816 2037332 : if (!state->parity[l].is_excluded) { - 817 1768468 : return 1; + 815 2123608 : for (l = 0; l < state->level; ++l) { + 816 2040324 : if (!state->parity[l].is_excluded) { + 817 1770644 : return 1; 818 : } 819 : } 820 : 821 : /* for each disk */ - 822 384812 : for (j = 0; j < diskmax; ++j) { + 822 385562 : for (j = 0; j < diskmax; ++j) { 823 : struct snapraid_block* block; 824 : 825 : /* if no disk, nothing to check */ - 826 349760 : if (!handle[j].disk) + 826 350436 : if (!handle[j].disk) 827 0 : continue; 828 : - 829 349760 : block = fs_par2block_get(handle[j].disk, i); + 829 350436 : block = fs_par2block_get(handle[j].disk, i); 830 : 831 : /* try to recover all files, even the ones without hash */ 832 : /* because in some cases we can recover also them */ - 833 349760 : if (block_has_file(block)) { - 834 343338 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); - 835 343338 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ - 836 48064 : return 1; + 833 350436 : if (block_has_file(block)) { + 834 343994 : struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); + 835 343994 : if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ + 836 48158 : return 1; 837 : } 838 : } 839 : } 840 : - 841 35052 : return 0; + 841 35126 : return 0; 842 : } 843 : 844 118 : static int state_check_process(struct snapraid_state* state, int fix, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) @@ -945,33 +945,33 @@ 883 : 884 : /* first count the number of blocks to process */ 885 118 : countmax = 0; - 886 933450 : for (i = blockstart; i < blockmax; ++i) { - 887 933332 : if (!block_is_enabled(state, i, handle, diskmax)) - 888 25066 : continue; - 889 908266 : ++countmax; + 886 934669 : for (i = blockstart; i < blockmax; ++i) { + 887 934551 : if (!block_is_enabled(state, i, handle, diskmax)) + 888 25150 : continue; + 889 909401 : ++countmax; 890 : } 891 : 892 : /* check all the blocks in files */ 893 118 : countsize = 0; 894 118 : countpos = 0; 895 118 : state_progress_begin(state, blockstart, blockmax, countmax); - 896 933450 : for (i = blockstart; i < blockmax; ++i) { + 896 934669 : for (i = blockstart; i < blockmax; ++i) { 897 : unsigned failed_count; 898 : int valid_parity; 899 : snapraid_info info; 900 : int rehash; 901 : - 902 933332 : if (!block_is_enabled(state, i, handle, diskmax)) { + 902 934551 : if (!block_is_enabled(state, i, handle, diskmax)) { 903 : /* post process the files */ - 904 25066 : ret = file_post(state, fix, i, handle, diskmax); - 905 25066 : if (ret == -1) { + 904 25150 : ret = file_post(state, fix, i, handle, diskmax); + 905 25150 : if (ret == -1) { 906 0 : log_fatal("Stopping at block %u\n", i); 907 0 : ++unrecoverable_error; 908 0 : goto bail; 909 : } 910 : 911 : /* and now continue with the next block */ - 912 25066 : continue; + 912 25150 : continue; 913 : } 914 : 915 : /* If we have valid parity, and it makes sense to check its content. */ @@ -979,19 +979,19 @@ 917 : /* but we don't report parity errors */ 918 : /* Note that with auditonly, we anyway skip the full parity check, */ 919 : /* because we also don't read it at all */ - 920 908266 : valid_parity = 1; + 920 909401 : valid_parity = 1; 921 : 922 : /* keep track of the number of failed blocks */ - 923 908266 : failed_count = 0; + 923 909401 : failed_count = 0; 924 : 925 : /* get block specific info */ - 926 908266 : info = info_get(&state->infoarr, i); + 926 909401 : info = info_get(&state->infoarr, i); 927 : 928 : /* if we have to use the old hash */ - 929 908266 : rehash = info_get_rehash(info); + 929 909401 : rehash = info_get_rehash(info); 930 : 931 : /* for each disk, process the block */ - 932 6357862 : for (j = 0; j < diskmax; ++j) { + 932 6365807 : for (j = 0; j < diskmax; ++j) { 933 : int read_size; 934 : unsigned char hash[HASH_SIZE]; 935 : struct snapraid_disk* disk; @@ -1001,34 +1001,34 @@ 939 : unsigned block_state; 940 : 941 : /* if the disk position is not used */ - 942 5449596 : disk = handle[j].disk; - 943 5449596 : if (!disk) { + 942 5456406 : disk = handle[j].disk; + 943 5456406 : if (!disk) { 944 : /* use an empty block */ - 945 14013 : memset(buffer[j], 0, state->block_size); - 946 951802 : continue; + 945 14037 : memset(buffer[j], 0, state->block_size); + 946 953296 : continue; 947 : } 948 : 949 : /* if the disk block is not used */ - 950 5435583 : block = fs_par2block_get(disk, i); - 951 5435583 : if (block == BLOCK_EMPTY) { + 950 5442369 : block = fs_par2block_get(disk, i); + 951 5442369 : if (block == BLOCK_EMPTY) { 952 : /* use an empty block */ - 953 188862 : memset(buffer[j], 0, state->block_size); - 954 188862 : continue; + 953 189495 : memset(buffer[j], 0, state->block_size); + 954 189495 : continue; 955 : } 956 : 957 : /* get the state of the block */ - 958 5246721 : block_state = block_state_get(block); + 958 5252874 : block_state = block_state_get(block); 959 : 960 : /* if the parity is not valid */ - 961 5246721 : if (block_has_invalid_parity(block)) { + 961 5252874 : if (block_has_invalid_parity(block)) { 962 : /* mark the parity as invalid, and don't try to check/fix it */ 963 : /* because it will be recomputed at the next sync */ - 964 94577 : valid_parity = 0; + 964 94587 : valid_parity = 0; 965 : /* follow */ 966 : } 967 : 968 : /* if the block is DELETED */ - 969 5246721 : if (block_state == BLOCK_STATE_DELETED) { + 969 5252874 : if (block_state == BLOCK_STATE_DELETED) { 970 : /* use an empty block */ 971 18454 : memset(buffer[j], 0, state->block_size); 972 : @@ -1047,22 +1047,22 @@ 985 : } 986 : 987 : /* get the file of this block */ - 988 5228267 : file = fs_par2file_get(disk, i, &file_pos); + 988 5234420 : file = fs_par2file_get(disk, i, &file_pos); 989 : 990 : /* if we are only hashing, we can skip excluded files and don't even read them */ - 991 5228267 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) { + 991 5234420 : if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) { 992 : /* use an empty block */ - 993 : /* in true, this is unnecessary, becase we are not checking any parity */ + 993 : /* in true, this is unnecessary, because we are not checking any parity */ 994 : /* but we keep it for completeness */ 995 0 : memset(buffer[j], 0, state->block_size); 996 0 : continue; 997 : } 998 : 999 : /* if the file is closed or different than the current one */ - 1000 5228267 : if (handle[j].file == 0 || handle[j].file != file) { + 1000 5234420 : if (handle[j].file == 0 || handle[j].file != file) { 1001 : /* close the old one, if any */ - 1002 2258931 : ret = handle_close(&handle[j]); - 1003 2258931 : if (ret == -1) { + 1002 2259919 : ret = handle_close(&handle[j]); + 1003 2259919 : if (ret == -1) { 1004 : /* LCOV_EXCL_START */ 1005 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(handle[j].file->sub), strerror(errno)); 1006 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -1073,10 +1073,10 @@ 1011 : } 1012 : 1013 : /* if fixing, and the file is not excluded, we must open for writing */ - 1014 2258931 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1014 2259919 : if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { 1015 : /* if fixing, create the file, open for writing and resize if required */ - 1016 771210 : ret = handle_create(&handle[j], file, state->file_mode); - 1017 771210 : if (ret == -1) { + 1016 771290 : ret = handle_create(&handle[j], file, state->file_mode); + 1017 771290 : if (ret == -1) { 1018 : /* LCOV_EXCL_START */ 1019 : if (errno == EACCES) { 1020 : log_fatal("WARNING! Please give write permission to the file.\n"); @@ -1090,69 +1090,69 @@ 1028 : } 1029 : 1030 : /* check if the file was just created */ - 1031 1542420 : if (handle[j].created != 0) { + 1031 1542580 : if (handle[j].created != 0) { 1032 : /* if fragmented, it may be reopened, so remember that the file */ 1033 : /* was originally missing */ - 1034 113024 : file_flag_set(file, FILE_IS_CREATED); + 1034 113107 : file_flag_set(file, FILE_IS_CREATED); 1035 : } 1036 : } else { 1037 : /* open the file only for reading */ - 1038 1487721 : if (!file_flag_has(file, FILE_IS_MISSING)) - 1039 1372062 : ret = handle_open(&handle[j], file, state->file_mode, - 1040 1372062 : log_error, state->opt.expected_missing ? log_expected : 0); + 1038 1488629 : if (!file_flag_has(file, FILE_IS_MISSING)) + 1039 1372724 : ret = handle_open(&handle[j], file, state->file_mode, + 1040 1372724 : log_error, state->opt.expected_missing ? log_expected : 0); 1041 : else - 1042 115659 : ret = -1; /* if the file is missing, we cannot open it */ - 1043 1487721 : if (ret == -1) { + 1042 115905 : ret = -1; /* if the file is missing, we cannot open it */ + 1043 1488629 : if (ret == -1) { 1044 : /* save the failed block for the check/fix */ - 1045 194418 : failed[failed_count].is_bad = 1; - 1046 194418 : failed[failed_count].is_outofdate = 0; - 1047 194418 : failed[failed_count].index = j; - 1048 194418 : failed[failed_count].block = block; - 1049 194418 : failed[failed_count].disk = disk; - 1050 194418 : failed[failed_count].file = file; - 1051 194418 : failed[failed_count].file_pos = file_pos; - 1052 194418 : failed[failed_count].handle = &handle[j]; - 1053 194418 : ++failed_count; + 1045 194668 : failed[failed_count].is_bad = 1; + 1046 194668 : failed[failed_count].is_outofdate = 0; + 1047 194668 : failed[failed_count].index = j; + 1048 194668 : failed[failed_count].block = block; + 1049 194668 : failed[failed_count].disk = disk; + 1050 194668 : failed[failed_count].file = file; + 1051 194668 : failed[failed_count].file_pos = file_pos; + 1052 194668 : failed[failed_count].handle = &handle[j]; + 1053 194668 : ++failed_count; 1054 : - 1055 194418 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc(file->sub), file_pos); - 1056 194418 : ++error; + 1055 194668 : log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc(file->sub), file_pos); + 1056 194668 : ++error; 1057 : 1058 : /* mark the file as missing, to avoid to retry to open it again */ 1059 : /* note that this can be done only if we are not fixing it */ 1060 : /* otherwise, it could be recreated */ - 1061 194418 : file_flag_set(file, FILE_IS_MISSING); - 1062 194418 : continue; + 1061 194668 : file_flag_set(file, FILE_IS_MISSING); + 1062 194668 : continue; 1063 : } 1064 : } 1065 : 1066 : /* if it's the first open, and not excluded */ - 1067 2064513 : if (!file_flag_has(file, FILE_IS_OPENED) - 1068 2049148 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { + 1067 2065251 : if (!file_flag_has(file, FILE_IS_OPENED) + 1068 2049859 : && !file_flag_has(file, FILE_IS_EXCLUDED)) { 1069 : 1070 : /* check if the file is changed */ - 1071 1997793 : if (handle[j].st.st_size != file->size - 1072 1804861 : || handle[j].st.st_mtime != file->mtime_sec - 1073 1780308 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec - 1074 : /* don't check the inode to support filesystem without persistent inodes */ + 1071 1998374 : if (handle[j].st.st_size != file->size + 1072 1805527 : || handle[j].st.st_mtime != file->mtime_sec + 1073 1781193 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec + 1074 : /* don't check the inode to support file-system without persistent inodes */ 1075 : ) { 1076 : /* report that the file is not synced */ - 1077 217485 : file_flag_set(file, FILE_IS_UNSYNCED); + 1077 217181 : file_flag_set(file, FILE_IS_UNSYNCED); 1078 : } 1079 : } 1080 : 1081 : /* if it's the first open, and not excluded and larger */ - 1082 2064513 : if (!file_flag_has(file, FILE_IS_OPENED) - 1083 2049148 : && !file_flag_has(file, FILE_IS_EXCLUDED) - 1084 1997793 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) - 1085 1997793 : && handle[j].st.st_size > file->size + 1082 2065251 : if (!file_flag_has(file, FILE_IS_OPENED) + 1083 2049859 : && !file_flag_has(file, FILE_IS_EXCLUDED) + 1084 1998374 : && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) + 1085 1998374 : && handle[j].st.st_size > file->size 1086 : ) { - 1087 8781 : log_error("File '%s' is larger than expected.\n", handle[j].path); - 1088 8781 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc(file->sub)); - 1089 8781 : ++error; + 1087 8640 : log_error("File '%s' is larger than expected.\n", handle[j].path); + 1088 8640 : log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc(file->sub)); + 1089 8640 : ++error; 1090 : - 1091 8781 : if (fix) { - 1092 3249 : ret = handle_truncate(&handle[j], file); - 1093 3249 : if (ret == -1) { + 1091 8640 : if (fix) { + 1092 3187 : ret = handle_truncate(&handle[j], file); + 1093 3187 : if (ret == -1) { 1094 : /* LCOV_EXCL_START */ 1095 : log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n"); 1096 : log_fatal("Stopping at block %u\n", i); @@ -1161,202 +1161,202 @@ 1099 : /* LCOV_EXCL_STOP */ 1100 : } 1101 : - 1102 3249 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc(file->sub)); - 1103 3249 : ++recovered_error; + 1102 3187 : log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc(file->sub)); + 1103 3187 : ++recovered_error; 1104 : } 1105 : } 1106 : 1107 : /* mark the file as opened at least one time */ 1108 : /* this is used to avoid to check the unsynced and size */ 1109 : /* more than one time, in case the file is reopened later */ - 1110 2064513 : file_flag_set(file, FILE_IS_OPENED); + 1110 2065251 : file_flag_set(file, FILE_IS_OPENED); 1111 : } 1112 : 1113 : /* read from the file */ - 1114 5033849 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, - 1115 5033849 : log_error, state->opt.expected_missing ? log_expected : 0); - 1116 5033849 : if (read_size == -1) { + 1114 5039752 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, + 1115 5039752 : log_error, state->opt.expected_missing ? log_expected : 0); + 1116 5039752 : if (read_size == -1) { 1117 : /* save the failed block for the check/fix */ - 1118 442025 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ - 1119 442025 : failed[failed_count].is_outofdate = 0; - 1120 442025 : failed[failed_count].index = j; - 1121 442025 : failed[failed_count].block = block; - 1122 442025 : failed[failed_count].disk = disk; - 1123 442025 : failed[failed_count].file = file; - 1124 442025 : failed[failed_count].file_pos = file_pos; - 1125 442025 : failed[failed_count].handle = &handle[j]; - 1126 442025 : ++failed_count; + 1118 442526 : failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ + 1119 442526 : failed[failed_count].is_outofdate = 0; + 1120 442526 : failed[failed_count].index = j; + 1121 442526 : failed[failed_count].block = block; + 1122 442526 : failed[failed_count].disk = disk; + 1123 442526 : failed[failed_count].file = file; + 1124 442526 : failed[failed_count].file_pos = file_pos; + 1125 442526 : failed[failed_count].handle = &handle[j]; + 1126 442526 : ++failed_count; 1127 : - 1128 442025 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos); - 1129 442025 : ++error; - 1130 442025 : continue; + 1128 442526 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos); + 1129 442526 : ++error; + 1130 442526 : continue; 1131 : } 1132 : - 1133 4591824 : countsize += read_size; + 1133 4597226 : countsize += read_size; 1134 : 1135 : /* always insert CHG blocks, the repair functions needs all of them */ 1136 : /* because the parity may be still referring at the old state */ 1137 : /* and the repair must be aware of it */ - 1138 4591824 : if (block_state == BLOCK_STATE_CHG) { + 1138 4597226 : if (block_state == BLOCK_STATE_CHG) { 1139 : /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */ 1140 : /* if we don't have a hash, we always assume the first read of the block correct. */ - 1141 43695 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ - 1142 43695 : failed[failed_count].is_outofdate = 0; - 1143 43695 : failed[failed_count].index = j; - 1144 43695 : failed[failed_count].block = block; - 1145 43695 : failed[failed_count].disk = disk; - 1146 43695 : failed[failed_count].file = file; - 1147 43695 : failed[failed_count].file_pos = file_pos; - 1148 43695 : failed[failed_count].handle = &handle[j]; - 1149 43695 : ++failed_count; - 1150 43695 : continue; + 1141 13843 : failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ + 1142 13843 : failed[failed_count].is_outofdate = 0; + 1143 13843 : failed[failed_count].index = j; + 1144 13843 : failed[failed_count].block = block; + 1145 13843 : failed[failed_count].disk = disk; + 1146 13843 : failed[failed_count].file = file; + 1147 13843 : failed[failed_count].file_pos = file_pos; + 1148 13843 : failed[failed_count].handle = &handle[j]; + 1149 13843 : ++failed_count; + 1150 13843 : continue; 1151 : } 1152 : - 1153 4548129 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + 1153 4583383 : assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); 1154 : 1155 : /* compute the hash of the block just read */ - 1156 4548129 : if (rehash) { - 1157 286660 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); + 1156 4583383 : if (rehash) { + 1157 27231 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); 1158 : } else { - 1159 4261469 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 1159 4556152 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); 1160 : } 1161 : 1162 : /* compare the hash */ - 1163 4548129 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { - 1164 12748 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE); + 1163 4583383 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 1164 12808 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE); 1165 : 1166 : /* save the failed block for the check/fix */ - 1167 12748 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ - 1168 12748 : failed[failed_count].is_outofdate = 0; - 1169 12748 : failed[failed_count].index = j; - 1170 12748 : failed[failed_count].block = block; - 1171 12748 : failed[failed_count].disk = disk; - 1172 12748 : failed[failed_count].file = file; - 1173 12748 : failed[failed_count].file_pos = file_pos; - 1174 12748 : failed[failed_count].handle = &handle[j]; - 1175 12748 : ++failed_count; + 1167 12808 : failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ + 1168 12808 : failed[failed_count].is_outofdate = 0; + 1169 12808 : failed[failed_count].index = j; + 1170 12808 : failed[failed_count].block = block; + 1171 12808 : failed[failed_count].disk = disk; + 1172 12808 : failed[failed_count].file = file; + 1173 12808 : failed[failed_count].file_pos = file_pos; + 1174 12808 : failed[failed_count].handle = &handle[j]; + 1175 12808 : ++failed_count; 1176 : - 1177 12748 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff); - 1178 12748 : ++error; - 1179 12748 : continue; + 1177 12808 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff); + 1178 12808 : ++error; + 1179 12808 : continue; 1180 : } 1181 : 1182 : /* always insert REP blocks, the repair functions needs all of them */ 1183 : /* because the parity may be still referring at the old state */ 1184 : /* and the repair must be aware of it */ - 1185 4535381 : if (block_state == BLOCK_STATE_REP) { - 1186 23574 : failed[failed_count].is_bad = 0; /* it's not bad */ - 1187 23574 : failed[failed_count].is_outofdate = 0; - 1188 23574 : failed[failed_count].index = j; - 1189 23574 : failed[failed_count].block = block; - 1190 23574 : failed[failed_count].disk = disk; - 1191 23574 : failed[failed_count].file = file; - 1192 23574 : failed[failed_count].file_pos = file_pos; - 1193 23574 : failed[failed_count].handle = &handle[j]; - 1194 23574 : ++failed_count; - 1195 23574 : continue; + 1185 4570575 : if (block_state == BLOCK_STATE_REP) { + 1186 53428 : failed[failed_count].is_bad = 0; /* it's not bad */ + 1187 53428 : failed[failed_count].is_outofdate = 0; + 1188 53428 : failed[failed_count].index = j; + 1189 53428 : failed[failed_count].block = block; + 1190 53428 : failed[failed_count].disk = disk; + 1191 53428 : failed[failed_count].file = file; + 1192 53428 : failed[failed_count].file_pos = file_pos; + 1193 53428 : failed[failed_count].handle = &handle[j]; + 1194 53428 : ++failed_count; + 1195 53428 : continue; 1196 : } 1197 : } 1198 : 1199 : /* now read and check the parity if requested */ - 1200 908266 : if (!state->opt.auditonly) { + 1200 909401 : if (!state->opt.auditonly) { 1201 : void* buffer_recov[LEV_MAX]; 1202 : void* buffer_zero; 1203 : 1204 : /* buffers for parity read and not computed */ - 1205 4161698 : for (l = 0; l < state->level; ++l) - 1206 3292609 : buffer_recov[l] = buffer[diskmax + state->level + l]; - 1207 2791014 : for (; l < LEV_MAX; ++l) - 1208 1921925 : buffer_recov[l] = 0; + 1205 4166971 : for (l = 0; l < state->level; ++l) + 1206 3296805 : buffer_recov[l] = buffer[diskmax + state->level + l]; + 1207 2794357 : for (; l < LEV_MAX; ++l) + 1208 1924191 : buffer_recov[l] = 0; 1209 : 1210 : /* the zero buffer is the last one */ - 1211 869089 : buffer_zero = buffer[buffermax - 1]; + 1211 870166 : buffer_zero = buffer[buffermax - 1]; 1212 : 1213 : /* read the parity */ - 1214 4161698 : for (l = 0; l < state->level; ++l) { - 1215 3292609 : if (parity[l]) { - 1216 3278739 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); - 1217 3278739 : if (ret == -1) { - 1218 90275 : buffer_recov[l] = 0; /* no parity to use */ + 1214 4166971 : for (l = 0; l < state->level; ++l) { + 1215 3296805 : if (parity[l]) { + 1216 3282919 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); + 1217 3282919 : if (ret == -1) { + 1218 90295 : buffer_recov[l] = 0; /* no parity to use */ 1219 : - 1220 90275 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); - 1221 90275 : ++error; + 1220 90295 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); + 1221 90295 : ++error; 1222 : } 1223 : } else { - 1224 13870 : buffer_recov[l] = 0; + 1224 13886 : buffer_recov[l] = 0; 1225 : } 1226 : } 1227 : 1228 : /* try all the recovering strategies */ - 1229 869089 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); - 1230 869089 : if (ret != 0) { + 1229 870166 : ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); + 1230 870166 : if (ret != 0) { 1231 : /* increment the number of errors */ - 1232 47822 : if (ret > 0) - 1233 4632 : error += ret; - 1234 47822 : ++unrecoverable_error; + 1232 47694 : if (ret > 0) + 1233 4646 : error += ret; + 1234 47694 : ++unrecoverable_error; 1235 : 1236 : /* print a list of all the errors in files */ - 1237 219138 : for (j = 0; j < failed_count; ++j) { - 1238 171316 : if (failed[j].is_bad) - 1239 166794 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); + 1237 218712 : for (j = 0; j < failed_count; ++j) { + 1238 171018 : if (failed[j].is_bad) + 1239 166496 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); 1240 : } 1241 : 1242 : /* keep track of damaged files */ - 1243 219138 : for (j = 0; j < failed_count; ++j) { - 1244 171316 : if (failed[j].is_bad) - 1245 166794 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1243 218712 : for (j = 0; j < failed_count; ++j) { + 1244 171018 : if (failed[j].is_bad) + 1245 166496 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); 1246 : } 1247 : } else { 1248 : /* now counts partial recovers */ 1249 : /* note that this could happen only when we have an incomplete 'sync' */ 1250 : /* and that we have recovered is the state before the 'sync' */ - 1251 821267 : int partial_recover_error = 0; + 1251 822472 : int partial_recover_error = 0; 1252 : 1253 : /* print a list of all the errors in files */ - 1254 1379014 : for (j = 0; j < failed_count; ++j) { - 1255 557747 : if (failed[j].is_bad && failed[j].is_outofdate) { - 1256 4192 : ++partial_recover_error; - 1257 4192 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); + 1254 1381331 : for (j = 0; j < failed_count; ++j) { + 1255 558859 : if (failed[j].is_bad && failed[j].is_outofdate) { + 1256 8 : ++partial_recover_error; + 1257 8 : log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); 1258 : } 1259 : } - 1260 821267 : if (partial_recover_error != 0) { - 1261 4192 : error += partial_recover_error; - 1262 4192 : ++unrecoverable_error; + 1260 822472 : if (partial_recover_error != 0) { + 1261 8 : error += partial_recover_error; + 1262 8 : ++unrecoverable_error; 1263 : } 1264 : 1265 : /* now check parities, but only if all the blocks have it computed */ 1266 : /* if you check/fix after a partial sync, it's OK to have parity errors on the blocks with invalid parity */ 1267 : /* and doesn't make sense to try to fix it */ - 1268 821267 : if (valid_parity) { + 1268 822472 : if (valid_parity) { 1269 : /* check the parity */ - 1270 3719151 : for (l = 0; l < state->level; ++l) { - 1271 2959573 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { - 1272 10640 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); + 1270 3725482 : for (l = 0; l < state->level; ++l) { + 1271 2964593 : if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { + 1272 10750 : unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); 1273 : 1274 : /* mark that the read parity is wrong, setting ptr to 0 */ - 1275 10640 : buffer_recov[l] = 0; + 1275 10750 : buffer_recov[l] = 0; 1276 : - 1277 10640 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff); - 1278 10640 : ++error; + 1277 10750 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff); + 1278 10750 : ++error; 1279 : } 1280 : } 1281 : } 1282 : 1283 : /* now write recovered files */ - 1284 821267 : if (fix) { + 1284 822472 : if (fix) { 1285 : /* update the fixed files */ - 1286 651810 : for (j = 0; j < failed_count; ++j) { + 1286 652441 : for (j = 0; j < failed_count; ++j) { 1287 : /* nothing to do if it doesn't need recovering */ - 1288 337787 : if (!failed[j].is_bad) + 1288 338114 : if (!failed[j].is_bad) 1289 40318 : continue; 1290 : 1291 : /* do not fix if the file is excluded */ - 1292 297469 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) - 1293 288205 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) + 1292 297796 : if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) + 1293 288532 : || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) 1294 9264 : continue; 1295 : - 1296 288205 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); - 1297 288205 : if (ret == -1) { + 1296 288532 : ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); + 1297 288532 : if (ret == -1) { 1298 : /* LCOV_EXCL_START */ 1299 : /* mark the file as damaged */ 1300 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); @@ -1374,35 +1374,35 @@ 1312 : } 1313 : 1314 : /* if we are not sure that the recovered content is uptodate */ - 1315 288205 : if (failed[j].is_outofdate) { + 1315 288532 : if (failed[j].is_outofdate) { 1316 : /* mark the file as damaged */ - 1317 4192 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); - 1318 4192 : continue; + 1317 8 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1318 8 : continue; 1319 : } 1320 : 1321 : /* mark the file as containing some fixes */ 1322 : /* note that it could be also marked as damaged in other iterations */ - 1323 284013 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1323 288524 : file_flag_set(failed[j].file, FILE_IS_FIXED); 1324 : - 1325 284013 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); - 1326 284013 : ++recovered_error; + 1325 288524 : log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc(failed[j].file->sub), failed[j].file_pos); + 1326 288524 : ++recovered_error; 1327 : } 1328 : 1329 : /* update parity only if all the blocks have it computed */ 1330 : /* if you check/fix after a partial sync, you do not want to fix parity */ 1331 : /* for blocks that are going to have it computed in the sync completion */ - 1332 314023 : if (valid_parity) { + 1332 314327 : if (valid_parity) { 1333 : /* update the parity */ - 1334 961782 : for (l = 0; l < state->level; ++l) { + 1334 962923 : for (l = 0; l < state->level; ++l) { 1335 : /* if the parity on disk is wrong */ - 1336 696931 : if (buffer_recov[l] == 0 + 1336 697776 : if (buffer_recov[l] == 0 1337 : /* and we have access at the parity */ - 1338 67199 : && parity[l] != 0 + 1338 67218 : && parity[l] != 0 1339 : /* and the parity is not excluded */ - 1340 62528 : && !state->parity[l].is_excluded + 1340 62539 : && !state->parity[l].is_excluded 1341 : ) { - 1342 62528 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); - 1343 62528 : if (ret == -1) { + 1342 62539 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); + 1343 62539 : if (ret == -1) { 1344 : /* LCOV_EXCL_START */ 1345 : /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ 1346 : log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l)); @@ -1412,17 +1412,17 @@ 1350 : /* LCOV_EXCL_STOP */ 1351 : } 1352 : - 1353 62528 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); - 1354 62528 : ++recovered_error; + 1353 62539 : log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); + 1354 62539 : ++recovered_error; 1355 : } 1356 : } 1357 : } 1358 : } else { 1359 : /* if we are not fixing, we just set the FIXED flag */ 1360 : /* meaning that we could fix this file if we try */ - 1361 727204 : for (j = 0; j < failed_count; ++j) { - 1362 219960 : if (failed[j].is_bad) { - 1363 179077 : file_flag_set(failed[j].file, FILE_IS_FIXED); + 1361 728890 : for (j = 0; j < failed_count; ++j) { + 1362 220745 : if (failed[j].is_bad) { + 1363 179860 : file_flag_set(failed[j].file, FILE_IS_FIXED); 1364 : } 1365 : } 1366 : } @@ -1430,26 +1430,26 @@ 1368 : } else { 1369 : /* if we are not checking, we just set the DAMAGED flag */ 1370 : /* to report that the file is damaged, and we don't know if we can fix it */ - 1371 45028 : for (j = 0; j < failed_count; ++j) { - 1372 5851 : if (failed[j].is_bad) { - 1373 5851 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); + 1371 45085 : for (j = 0; j < failed_count; ++j) { + 1372 5850 : if (failed[j].is_bad) { + 1373 5850 : file_flag_set(failed[j].file, FILE_IS_DAMAGED); 1374 : } 1375 : } 1376 : } 1377 : 1378 : /* post process the files */ - 1379 908266 : ret = file_post(state, fix, i, handle, diskmax); - 1380 908266 : if (ret == -1) { + 1379 909401 : ret = file_post(state, fix, i, handle, diskmax); + 1380 909401 : if (ret == -1) { 1381 0 : log_fatal("Stopping at block %u\n", i); 1382 0 : ++unrecoverable_error; 1383 0 : goto bail; 1384 : } 1385 : 1386 : /* count the number of processed block */ - 1387 908266 : ++countpos; + 1387 909401 : ++countpos; 1388 : 1389 : /* progress */ - 1390 908266 : if (state_progress(state, i, countpos, countmax, countsize)) { + 1390 909401 : if (state_progress(state, i, countpos, countmax, countsize)) { 1391 : /* LCOV_EXCL_START */ 1392 : break; 1393 : /* LCOV_EXCL_STOP */ @@ -1467,18 +1467,18 @@ 1405 : /* for each empty file in the disk */ 1406 705 : disk = handle[i].disk; 1407 705 : node = disk->filelist; - 1408 2187957 : while (node) { + 1408 2188784 : while (node) { 1409 : char path[PATH_MAX]; 1410 : struct stat st; 1411 : struct snapraid_file* file; - 1412 2186547 : int unsuccesful = 0; + 1412 2187374 : int unsuccesful = 0; 1413 : - 1414 2186547 : file = node->data; - 1415 2186547 : node = node->next; /* next node */ + 1414 2187374 : file = node->data; + 1415 2187374 : node = node->next; /* next node */ 1416 : 1417 : /* if not empty, it's already checked and continue to the next one */ - 1418 2186547 : if (file->size != 0) { - 1419 4367359 : continue; + 1418 2187374 : if (file->size != 0) { + 1419 4369013 : continue; 1420 : } 1421 : 1422 : /* if excluded continue to the next one */ @@ -1490,21 +1490,21 @@ 1428 2783 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); 1429 2783 : ret = stat(path, &st); 1430 2783 : if (ret == -1) { - 1431 173 : unsuccesful = 1; + 1431 169 : unsuccesful = 1; 1432 : - 1433 173 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); - 1434 173 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc(file->sub)); - 1435 173 : ++error; - 1436 2610 : } else if (!S_ISREG(st.st_mode)) { + 1433 169 : log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); + 1434 169 : log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc(file->sub)); + 1435 169 : ++error; + 1436 2614 : } else if (!S_ISREG(st.st_mode)) { 1437 0 : unsuccesful = 1; 1438 : 1439 0 : log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc(file->sub)); 1440 0 : ++error; - 1441 2610 : } else if (st.st_size != 0) { - 1442 8 : unsuccesful = 1; + 1441 2614 : } else if (st.st_size != 0) { + 1442 14 : unsuccesful = 1; 1443 : - 1444 8 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc(file->sub), st.st_size); - 1445 8 : ++error; + 1444 14 : log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc(file->sub), st.st_size); + 1445 14 : ++error; 1446 : } 1447 : 1448 2783 : if (fix && unsuccesful) { @@ -1650,33 +1650,33 @@ 1588 66532 : pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); 1589 66532 : ret = readlink(path, linkto, sizeof(linkto)); 1590 66532 : if (ret < 0) { - 1591 4337 : unsuccesful = 1; + 1591 4273 : unsuccesful = 1; 1592 : - 1593 4337 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); - 1594 4337 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub)); - 1595 4337 : ++error; - 1596 62195 : } else if (ret >= PATH_MAX) { + 1593 4273 : log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); + 1594 4273 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub)); + 1595 4273 : ++error; + 1596 62259 : } else if (ret >= PATH_MAX) { 1597 0 : unsuccesful = 1; 1598 : 1599 0 : log_error("Error reading symlink '%s'. Symlink too long.\n", path); 1600 0 : log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc(slink->sub)); 1601 0 : ++error; 1602 : } else { - 1603 62195 : linkto[ret] = 0; + 1603 62259 : linkto[ret] = 0; 1604 : - 1605 62195 : if (strcmp(linkto, slink->linkto) != 0) { - 1606 493 : unsuccesful = 1; + 1605 62259 : if (strcmp(linkto, slink->linkto) != 0) { + 1606 561 : unsuccesful = 1; 1607 : - 1608 493 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc(slink->sub), linkto, slink->linkto); - 1609 493 : ++error; + 1608 561 : log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc(slink->sub), linkto, slink->linkto); + 1609 561 : ++error; 1610 : } 1611 : } 1612 : } 1613 : 1614 66850 : if (fix && unsuccesful && !unrecoverable) { 1615 : /* create the ancestor directories */ - 1616 3940 : ret = mkancestor(path); - 1617 3940 : if (ret != 0) { + 1616 3941 : ret = mkancestor(path); + 1617 3941 : if (ret != 0) { 1618 : /* LCOV_EXCL_START */ 1619 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); 1620 : log_fatal("Stopping\n"); @@ -1686,8 +1686,8 @@ 1624 : } 1625 : 1626 : /* if it exists, it must be deleted before recreating */ - 1627 3940 : ret = remove(path); - 1628 3940 : if (ret != 0 && errno != ENOENT) { + 1627 3941 : ret = remove(path); + 1628 3941 : if (ret != 0 && errno != ENOENT) { 1629 : /* LCOV_EXCL_START */ 1630 : log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); 1631 : log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); @@ -1698,7 +1698,7 @@ 1636 : } 1637 : 1638 : /* create it */ - 1639 3940 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { + 1639 3941 : if (link_flag_has(slink, FILE_IS_HARDLINK)) { 1640 12 : ret = hardlink(pathto, path); 1641 12 : if (ret != 0) { 1642 : /* LCOV_EXCL_START */ @@ -1718,8 +1718,8 @@ 1656 12 : log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc(slink->sub)); 1657 12 : ++recovered_error; 1658 : } else { - 1659 3928 : ret = symlink(slink->linkto, path); - 1660 3928 : if (ret != 0) { + 1659 3929 : ret = symlink(slink->linkto, path); + 1660 3929 : if (ret != 0) { 1661 : /* LCOV_EXCL_START */ 1662 : log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno)); 1663 : if (errno == EACCES) { @@ -1734,12 +1734,12 @@ 1672 : /* LCOV_EXCL_STOP */ 1673 : } 1674 : - 1675 3928 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc(slink->sub)); - 1676 3928 : ++recovered_error; + 1675 3929 : log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc(slink->sub)); + 1676 3929 : ++recovered_error; 1677 : } 1678 : - 1679 3940 : log_tag("status:recovered:%s:%s\n", disk->name, esc(slink->sub)); - 1680 3940 : msg_info("recovered %s%s\n", disk->dir, slink->sub); + 1679 3941 : log_tag("status:recovered:%s:%s\n", disk->name, esc(slink->sub)); + 1680 3941 : msg_info("recovered %s%s\n", disk->dir, slink->sub); 1681 : } 1682 : } 1683 : @@ -1846,23 +1846,23 @@ 1784 : /* for each file in the disk */ 1785 269 : disk = handle[i].disk; 1786 269 : node = disk->filelist; - 1787 870399 : while (node) { + 1787 870715 : while (node) { 1788 : char path[PATH_MAX]; 1789 : struct snapraid_file* file; 1790 : - 1791 869861 : file = node->data; - 1792 869861 : node = node->next; /* next node */ + 1791 870177 : file = node->data; + 1792 870177 : node = node->next; /* next node */ 1793 : 1794 : /* if the file was not created, meaning that it was already existing */ - 1795 869861 : if (!file_flag_has(file, FILE_IS_CREATED)) { + 1795 870177 : if (!file_flag_has(file, FILE_IS_CREATED)) { 1796 : /* nothing to do */ - 1797 1626698 : continue; + 1797 1627247 : continue; 1798 : } 1799 : 1800 : /* if processing was finished */ - 1801 113024 : if (file_flag_has(file, FILE_IS_FINISHED)) { + 1801 113107 : if (file_flag_has(file, FILE_IS_FINISHED)) { 1802 : /* nothing to do */ - 1803 113024 : continue; + 1803 113107 : continue; 1804 : } 1805 : 1806 : /* if the file was originally missing, and processing not yet finished */ diff --git a/cov/cmdline/device.c.func-sort-c.html b/cov/cmdline/device.c.func-sort-c.html index 566e5929..df63bf7b 100644 --- a/cov/cmdline/device.c.func-sort-c.html +++ b/cov/cmdline/device.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 300 - 318 - 94.3 % + 301 + 320 + 94.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -64,7 +64,7 @@ 72 - printl + printl 52 @@ -84,7 +84,7 @@ 18 - printp + printp 18 @@ -92,15 +92,15 @@ 13 - state_device + state_device 5 - state_smart + state_smart 1 - devtest + devtest 1 diff --git a/cov/cmdline/device.c.func.html b/cov/cmdline/device.c.func.html index b0da8a8b..9ffc7cc5 100644 --- a/cov/cmdline/device.c.func.html +++ b/cov/cmdline/device.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 300 - 318 - 94.3 % + 301 + 320 + 94.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -60,7 +60,7 @@ Hit count Sort by hit count - devtest + devtest 1 @@ -76,11 +76,11 @@ 31 - printl + printl 52 - printp + printp 18 @@ -96,11 +96,11 @@ 72 - state_device + state_device 5 - state_smart + state_smart 1 diff --git a/cov/cmdline/device.c.gcov.html b/cov/cmdline/device.c.gcov.html index 1014045d..8b590e26 100644 --- a/cov/cmdline/device.c.gcov.html +++ b/cov/cmdline/device.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 300 - 318 - 94.3 % + 301 + 320 + 94.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -100,7 +100,7 @@ 38 : * they really fail, not counting as a failure. 39 : * 40 : * The following tables are computed using the data from 2014-02-14 to 2014-12-31 - 41 : * becasue it's the period when more SMART attributes were gathered. + 41 : * because it's the period when more SMART attributes were gathered. 42 : * 43 : * In this period there are 47322 disk seen, with 1988 removed because failed, 44 : * and with 4121 removed because predicted to fail. @@ -632,451 +632,455 @@ 570 : * Garth Alan Gibson, "Redundant Disk Arrays: Reliable, Parallel Secondary Storage", 1990 571 : */ 572 : - 573 : /* get the Mean Time Between Failure of a single disk */ - 574 : /* from the array failure rate */ - 575 18 : MTBF = n / array_failure_rate; + 573 : /* avoid division by zero */ + 574 18 : if (array_failure_rate == 0) + 575 0 : return 0; 576 : - 577 : /* get the Mean Time Between Repair (the time that a failed disk is replaced) */ - 578 : /* from the repair rate */ - 579 18 : MTTR = 1.0 / replace_rate; + 577 : /* get the Mean Time Between Failure of a single disk */ + 578 : /* from the array failure rate */ + 579 18 : MTBF = n / array_failure_rate; 580 : - 581 : /* use the approximated MTTDL equation */ - 582 18 : MTTDL = pow(MTBF, redundancy + 1) / pow(MTTR, redundancy); - 583 99 : for (i = 0; i < redundancy + 1; ++i) - 584 81 : MTTDL /= n - i; - 585 : - 586 : /* the raid failure rate is just the inverse of the MTTDL */ - 587 18 : raid_failure_rate = 1.0 / MTTDL; - 588 : - 589 : /* probability of at least one RAID failure */ - 590 : /* note that is almost equal at the probabilty of */ - 591 : /* the first failure. */ - 592 18 : return poisson_prob_n_or_more_failures(raid_failure_rate, 1); - 593 : } - 594 : - 595 : /** - 596 : * Print a string with space padding. - 597 : */ - 598 52 : static void printl(const char* str, size_t pad) - 599 : { - 600 : size_t len; - 601 : - 602 52 : printf("%s", str); - 603 : - 604 52 : len = strlen(str); + 581 : /* get the Mean Time Between Repair (the time that a failed disk is replaced) */ + 582 : /* from the repair rate */ + 583 18 : MTTR = 1.0 / replace_rate; + 584 : + 585 : /* use the approximated MTTDL equation */ + 586 18 : MTTDL = pow(MTBF, redundancy + 1) / pow(MTTR, redundancy); + 587 99 : for (i = 0; i < redundancy + 1; ++i) + 588 81 : MTTDL /= n - i; + 589 : + 590 : /* the raid failure rate is just the inverse of the MTTDL */ + 591 18 : raid_failure_rate = 1.0 / MTTDL; + 592 : + 593 : /* probability of at least one RAID failure */ + 594 : /* note that is almost equal at the probability of */ + 595 : /* the first failure. */ + 596 18 : return poisson_prob_n_or_more_failures(raid_failure_rate, 1); + 597 : } + 598 : + 599 : /** + 600 : * Print a string with space padding. + 601 : */ + 602 52 : static void printl(const char* str, size_t pad) + 603 : { + 604 : size_t len; 605 : - 606 245 : while (len < pad) { - 607 141 : printf(" "); - 608 141 : ++len; - 609 : } - 610 52 : } - 611 : - 612 : /** - 613 : * Print a probability with space padding. - 614 : */ - 615 18 : static void printp(double v, size_t pad) - 616 : { - 617 : char buf[64]; - 618 18 : const char* s = "%"; - 619 : - 620 18 : if (v > 0.1) - 621 4 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s); - 622 14 : else if (v > 0.01) - 623 2 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s); - 624 12 : else if (v > 0.001) - 625 3 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s); - 626 9 : else if (v > 0.0001) - 627 2 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s); - 628 7 : else if (v > 0.00001) - 629 2 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s); - 630 5 : else if (v > 0.000001) - 631 1 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s); - 632 4 : else if (v > 0.0000001) - 633 1 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s); - 634 3 : else if (v > 0.00000001) - 635 1 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s); - 636 2 : else if (v > 0.000000001) - 637 1 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s); - 638 1 : else if (v > 0.0000000001) - 639 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s); - 640 1 : else if (v > 0.00000000001) - 641 1 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s); - 642 0 : else if (v > 0.000000000001) - 643 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s); - 644 : else - 645 0 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s); - 646 18 : printl(buf, pad); - 647 18 : } - 648 : - 649 1 : static void state_smart(unsigned n, tommy_list* low) - 650 : { - 651 : tommy_node* i; - 652 : unsigned j; - 653 : size_t device_pad; - 654 : size_t serial_pad; - 655 : int have_parent; - 656 : double array_failure_rate; - 657 : double p_at_least_one_failure; - 658 1 : int make_it_fail = 0; - 659 1 : uint64_t mask32 = 0xffffffffU; - 660 1 : uint64_t mask16 = 0xffffU; - 661 : - 662 : /* compute lengths for padding */ - 663 1 : device_pad = 0; - 664 1 : serial_pad = 0; - 665 1 : have_parent = 0; - 666 17 : for (i = tommy_list_head(low); i != 0; i = i->next) { - 667 : size_t len; - 668 16 : devinfo_t* devinfo = i->data; - 669 : - 670 16 : len = strlen(devinfo->file); - 671 16 : if (len > device_pad) - 672 1 : device_pad = len; + 606 52 : printf("%s", str); + 607 : + 608 52 : len = strlen(str); + 609 : + 610 245 : while (len < pad) { + 611 141 : printf(" "); + 612 141 : ++len; + 613 : } + 614 52 : } + 615 : + 616 : /** + 617 : * Print a probability with space padding. + 618 : */ + 619 18 : static void printp(double v, size_t pad) + 620 : { + 621 : char buf[64]; + 622 18 : const char* s = "%"; + 623 : + 624 18 : if (v > 0.1) + 625 4 : snprintf(buf, sizeof(buf), "%5.2f%s", v, s); + 626 14 : else if (v > 0.01) + 627 2 : snprintf(buf, sizeof(buf), "%6.3f%s", v, s); + 628 12 : else if (v > 0.001) + 629 3 : snprintf(buf, sizeof(buf), "%7.4f%s", v, s); + 630 9 : else if (v > 0.0001) + 631 2 : snprintf(buf, sizeof(buf), "%8.5f%s", v, s); + 632 7 : else if (v > 0.00001) + 633 2 : snprintf(buf, sizeof(buf), "%9.6f%s", v, s); + 634 5 : else if (v > 0.000001) + 635 1 : snprintf(buf, sizeof(buf), "%10.7f%s", v, s); + 636 4 : else if (v > 0.0000001) + 637 1 : snprintf(buf, sizeof(buf), "%11.8f%s", v, s); + 638 3 : else if (v > 0.00000001) + 639 1 : snprintf(buf, sizeof(buf), "%12.9f%s", v, s); + 640 2 : else if (v > 0.000000001) + 641 1 : snprintf(buf, sizeof(buf), "%13.10f%s", v, s); + 642 1 : else if (v > 0.0000000001) + 643 0 : snprintf(buf, sizeof(buf), "%14.11f%s", v, s); + 644 1 : else if (v > 0.00000000001) + 645 1 : snprintf(buf, sizeof(buf), "%15.12f%s", v, s); + 646 0 : else if (v > 0.000000000001) + 647 0 : snprintf(buf, sizeof(buf), "%16.13f%s", v, s); + 648 : else + 649 0 : snprintf(buf, sizeof(buf), "%17.14f%s", v, s); + 650 18 : printl(buf, pad); + 651 18 : } + 652 : + 653 1 : static void state_smart(unsigned n, tommy_list* low) + 654 : { + 655 : tommy_node* i; + 656 : unsigned j; + 657 : size_t device_pad; + 658 : size_t serial_pad; + 659 : int have_parent; + 660 : double array_failure_rate; + 661 : double p_at_least_one_failure; + 662 1 : int make_it_fail = 0; + 663 1 : uint64_t mask32 = 0xffffffffU; + 664 1 : uint64_t mask16 = 0xffffU; + 665 : + 666 : /* compute lengths for padding */ + 667 1 : device_pad = 0; + 668 1 : serial_pad = 0; + 669 1 : have_parent = 0; + 670 17 : for (i = tommy_list_head(low); i != 0; i = i->next) { + 671 : size_t len; + 672 16 : devinfo_t* devinfo = i->data; 673 : - 674 16 : len = strlen(devinfo->smart_serial); - 675 16 : if (len > serial_pad) - 676 2 : serial_pad = len; + 674 16 : len = strlen(devinfo->file); + 675 16 : if (len > device_pad) + 676 1 : device_pad = len; 677 : - 678 16 : if (devinfo->parent != 0) - 679 0 : have_parent = 1; - 680 : } + 678 16 : len = strlen(devinfo->smart_serial); + 679 16 : if (len > serial_pad) + 680 2 : serial_pad = len; 681 : - 682 1 : printf("SnapRAID SMART report:\n"); - 683 1 : printf("\n"); - 684 1 : printf(" Temp"); - 685 1 : printf(" Power"); - 686 1 : printf(" Error"); - 687 1 : printf(" FP"); - 688 1 : printf(" Size"); - 689 1 : printf("\n"); - 690 1 : printf(" C"); - 691 1 : printf(" OnDays"); - 692 1 : printf(" Count"); - 693 1 : printf(" "); - 694 1 : printf(" TB"); - 695 1 : printf(" "); printl("Serial", serial_pad); - 696 1 : printf(" "); printl("Device", device_pad); - 697 1 : printf(" Disk"); - 698 1 : printf("\n"); - 699 : /* |<##################################################################72>|####80>| */ - 700 1 : printf(" -----------------------------------------------------------------------\n"); - 701 : - 702 1 : array_failure_rate = 0; - 703 17 : for (i = tommy_list_head(low); i != 0; i = i->next) { - 704 16 : devinfo_t* devinfo = i->data; - 705 : double afr; - 706 : uint64_t flag; - 707 : - 708 16 : if (devinfo->smart[194] != SMART_UNASSIGNED) - 709 15 : printf("%7" PRIu64, devinfo->smart[194] & mask16); - 710 1 : else if (devinfo->smart[190] != SMART_UNASSIGNED) - 711 0 : printf("%7" PRIu64, devinfo->smart[190] & mask16); - 712 : else - 713 1 : printf(" -"); - 714 : - 715 16 : if (devinfo->smart[9] != SMART_UNASSIGNED) - 716 15 : printf("%7" PRIu64, (devinfo->smart[9] & mask32) / 24); - 717 : else - 718 1 : printf(" -"); - 719 : - 720 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) - 721 8 : flag = devinfo->smart[SMART_FLAGS]; - 722 : else - 723 8 : flag = 0; - 724 16 : if (flag & SMARTCTL_FLAG_FAIL) - 725 1 : printf(" FAIL"); - 726 15 : else if (flag & SMARTCTL_FLAG_PREFAIL) - 727 1 : printf(" PREFAIL"); - 728 14 : else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED) - 729 1 : printf(" logfail"); - 730 13 : else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED - 731 13 : && devinfo->smart[SMART_ERROR] != 0) - 732 1 : printf("%8" PRIu64, devinfo->smart[SMART_ERROR]); - 733 12 : else if (flag & SMARTCTL_FLAG_ERROR) - 734 1 : printf(" logerr"); - 735 11 : else if (flag & SMARTCTL_FLAG_ERROR_LOGGED) - 736 1 : printf(" selferr"); - 737 10 : else if (devinfo->smart[SMART_ERROR] == 0) - 738 10 : printf(" 0"); - 739 : else - 740 0 : printf(" -"); - 741 : - 742 : /* if some fail/prefail attribute, make the command to fail */ - 743 16 : if (flag & (SMARTCTL_FLAG_FAIL | SMARTCTL_FLAG_PREFAIL)) - 744 2 : make_it_fail = 1; + 682 16 : if (devinfo->parent != 0) + 683 0 : have_parent = 1; + 684 : } + 685 : + 686 1 : printf("SnapRAID SMART report:\n"); + 687 1 : printf("\n"); + 688 1 : printf(" Temp"); + 689 1 : printf(" Power"); + 690 1 : printf(" Error"); + 691 1 : printf(" FP"); + 692 1 : printf(" Size"); + 693 1 : printf("\n"); + 694 1 : printf(" C"); + 695 1 : printf(" OnDays"); + 696 1 : printf(" Count"); + 697 1 : printf(" "); + 698 1 : printf(" TB"); + 699 1 : printf(" "); printl("Serial", serial_pad); + 700 1 : printf(" "); printl("Device", device_pad); + 701 1 : printf(" Disk"); + 702 1 : printf("\n"); + 703 : /* |<##################################################################72>|####80>| */ + 704 1 : printf(" -----------------------------------------------------------------------\n"); + 705 : + 706 1 : array_failure_rate = 0; + 707 17 : for (i = tommy_list_head(low); i != 0; i = i->next) { + 708 16 : devinfo_t* devinfo = i->data; + 709 : double afr; + 710 : uint64_t flag; + 711 : + 712 16 : if (devinfo->smart[194] != SMART_UNASSIGNED) + 713 15 : printf("%7" PRIu64, devinfo->smart[194] & mask16); + 714 1 : else if (devinfo->smart[190] != SMART_UNASSIGNED) + 715 0 : printf("%7" PRIu64, devinfo->smart[190] & mask16); + 716 : else + 717 1 : printf(" -"); + 718 : + 719 16 : if (devinfo->smart[9] != SMART_UNASSIGNED) + 720 15 : printf("%7" PRIu64, (devinfo->smart[9] & mask32) / 24); + 721 : else + 722 1 : printf(" -"); + 723 : + 724 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) + 725 8 : flag = devinfo->smart[SMART_FLAGS]; + 726 : else + 727 8 : flag = 0; + 728 16 : if (flag & SMARTCTL_FLAG_FAIL) + 729 1 : printf(" FAIL"); + 730 15 : else if (flag & SMARTCTL_FLAG_PREFAIL) + 731 1 : printf(" PREFAIL"); + 732 14 : else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED) + 733 1 : printf(" logfail"); + 734 13 : else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED + 735 13 : && devinfo->smart[SMART_ERROR] != 0) + 736 1 : printf("%8" PRIu64, devinfo->smart[SMART_ERROR]); + 737 12 : else if (flag & SMARTCTL_FLAG_ERROR) + 738 1 : printf(" logerr"); + 739 11 : else if (flag & SMARTCTL_FLAG_ERROR_LOGGED) + 740 1 : printf(" selferr"); + 741 10 : else if (devinfo->smart[SMART_ERROR] == 0) + 742 10 : printf(" 0"); + 743 : else + 744 0 : printf(" -"); 745 : - 746 : /* note that in older smartmontools, like 5.x, rotation rate is not present */ - 747 : /* and then it could remain unassigned */ - 748 : - 749 16 : if (flag & (SMARTCTL_FLAG_UNSUPPORTED | SMARTCTL_FLAG_OPEN)) { - 750 : /* if error running smartctl, skip AFR estimation */ - 751 2 : afr = 0; - 752 2 : printf(" n/a"); - 753 14 : } else if (devinfo->smart[SMART_ROTATION_RATE] == 0) { - 754 : /* if SSD, skip AFR estimation as data is from not SSD disks */ - 755 1 : afr = 0; - 756 1 : printf(" SSD"); - 757 : } else { - 758 13 : afr = smart_afr(devinfo->smart); - 759 : - 760 13 : if (afr == 0) { - 761 : /* this happens only if no data */ - 762 1 : printf(" -"); - 763 : } else { - 764 : /* use only the disks in the array */ - 765 12 : if (devinfo->parent != 0 || !have_parent) - 766 12 : array_failure_rate += afr; - 767 : - 768 12 : printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100); - 769 : } - 770 : } + 746 : /* if some fail/prefail attribute, make the command to fail */ + 747 16 : if (flag & (SMARTCTL_FLAG_FAIL | SMARTCTL_FLAG_PREFAIL)) + 748 2 : make_it_fail = 1; + 749 : + 750 : /* note that in older smartmontools, like 5.x, rotation rate is not present */ + 751 : /* and then it could remain unassigned */ + 752 : + 753 16 : if (flag & (SMARTCTL_FLAG_UNSUPPORTED | SMARTCTL_FLAG_OPEN)) { + 754 : /* if error running smartctl, skip AFR estimation */ + 755 2 : afr = 0; + 756 2 : printf(" n/a"); + 757 14 : } else if (devinfo->smart[SMART_ROTATION_RATE] == 0) { + 758 : /* if SSD, skip AFR estimation as data is from not SSD disks */ + 759 1 : afr = 0; + 760 1 : printf(" SSD"); + 761 : } else { + 762 13 : afr = smart_afr(devinfo->smart); + 763 : + 764 13 : if (afr == 0) { + 765 : /* this happens only if no data */ + 766 1 : printf(" -"); + 767 : } else { + 768 : /* use only the disks in the array */ + 769 12 : if (devinfo->parent != 0 || !have_parent) + 770 12 : array_failure_rate += afr; 771 : - 772 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) - 773 15 : printf(" %4.1f", devinfo->smart[SMART_SIZE] / 1E12); - 774 : else - 775 1 : printf(" -"); - 776 : - 777 16 : printf(" "); - 778 16 : if (*devinfo->smart_serial) - 779 15 : printl(devinfo->smart_serial, serial_pad); - 780 : else - 781 1 : printl("-", serial_pad); - 782 : - 783 16 : printf(" "); - 784 16 : if (*devinfo->file) - 785 15 : printl(devinfo->file, device_pad); - 786 : else - 787 1 : printl("-", device_pad); - 788 : - 789 16 : printf(" "); - 790 16 : if (*devinfo->name) - 791 15 : printf("%s", devinfo->name); - 792 : else - 793 1 : printf("-"); - 794 : - 795 16 : printf("\n"); - 796 : - 797 16 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); - 798 16 : if (devinfo->smart_serial[0]) - 799 15 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc(devinfo->smart_serial)); - 800 16 : if (afr != 0) - 801 12 : log_tag("attr:%s:%s:afr:%g\n", devinfo->file, devinfo->name, afr); - 802 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) - 803 15 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_SIZE]); - 804 16 : if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED) - 805 16 : log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]); - 806 16 : if (devinfo->smart[SMART_ROTATION_RATE] != SMART_UNASSIGNED) - 807 16 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ROTATION_RATE]); - 808 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) - 809 8 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]); - 810 4112 : for (j = 0; j < 256; ++j) - 811 4096 : if (devinfo->smart[j] != SMART_UNASSIGNED) - 812 3840 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]); - 813 : } - 814 : - 815 1 : printf("\n"); - 816 : - 817 : /* |<##################################################################72>|####80>| */ - 818 1 : printf("The FP column is the estimated probability (in percentage) that the disk\n"); - 819 1 : printf("is going to fail in the next year.\n"); - 820 1 : printf("\n"); - 821 : - 822 : /* - 823 : * The probability of one and of at least one failure is computed assuming - 824 : * a Poisson distribution with the estimated array failure rate. - 825 : */ - 826 1 : p_at_least_one_failure = poisson_prob_n_or_more_failures(array_failure_rate, 1); - 827 : - 828 1 : printf("Probability that at least one disk is going to fail in the next year is %.0f%%.\n", p_at_least_one_failure * 100); - 829 1 : log_tag("summary:array_failure:%g:%g\n", array_failure_rate, p_at_least_one_failure); - 830 : - 831 : /* print extra stats only in verbose mode */ - 832 1 : if (msg_level < MSG_VERBOSE) - 833 0 : goto bail; + 772 12 : printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100); + 773 : } + 774 : } + 775 : + 776 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) + 777 15 : printf(" %4.1f", devinfo->smart[SMART_SIZE] / 1E12); + 778 : else + 779 1 : printf(" -"); + 780 : + 781 16 : printf(" "); + 782 16 : if (*devinfo->smart_serial) + 783 15 : printl(devinfo->smart_serial, serial_pad); + 784 : else + 785 1 : printl("-", serial_pad); + 786 : + 787 16 : printf(" "); + 788 16 : if (*devinfo->file) + 789 15 : printl(devinfo->file, device_pad); + 790 : else + 791 1 : printl("-", device_pad); + 792 : + 793 16 : printf(" "); + 794 16 : if (*devinfo->name) + 795 15 : printf("%s", devinfo->name); + 796 : else + 797 1 : printf("-"); + 798 : + 799 16 : printf("\n"); + 800 : + 801 16 : log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); + 802 16 : if (devinfo->smart_serial[0]) + 803 15 : log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc(devinfo->smart_serial)); + 804 16 : if (afr != 0) + 805 12 : log_tag("attr:%s:%s:afr:%g\n", devinfo->file, devinfo->name, afr); + 806 16 : if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) + 807 15 : log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_SIZE]); + 808 16 : if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED) + 809 16 : log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]); + 810 16 : if (devinfo->smart[SMART_ROTATION_RATE] != SMART_UNASSIGNED) + 811 16 : log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ROTATION_RATE]); + 812 16 : if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) + 813 8 : log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]); + 814 4112 : for (j = 0; j < 256; ++j) + 815 4096 : if (devinfo->smart[j] != SMART_UNASSIGNED) + 816 3840 : log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]); + 817 : } + 818 : + 819 1 : printf("\n"); + 820 : + 821 : /* |<##################################################################72>|####80>| */ + 822 1 : printf("The FP column is the estimated probability (in percentage) that the disk\n"); + 823 1 : printf("is going to fail in the next year.\n"); + 824 1 : printf("\n"); + 825 : + 826 : /* + 827 : * The probability of one and of at least one failure is computed assuming + 828 : * a Poisson distribution with the estimated array failure rate. + 829 : */ + 830 1 : p_at_least_one_failure = poisson_prob_n_or_more_failures(array_failure_rate, 1); + 831 : + 832 1 : printf("Probability that at least one disk is going to fail in the next year is %.0f%%.\n", p_at_least_one_failure * 100); + 833 1 : log_tag("summary:array_failure:%g:%g\n", array_failure_rate, p_at_least_one_failure); 834 : - 835 : /* |<##################################################################72>|####80>| */ - 836 1 : printf("\n"); - 837 1 : printf("Probability of data loss in the next year for different parity and\n"); - 838 1 : printf("combined scrub and repair time:\n"); - 839 1 : printf("\n"); - 840 1 : printf(" Parity 1 Week 1 Month 3 Months\n"); - 841 1 : printf(" -----------------------------------------------------------------------\n"); - 842 7 : for (j = 0; j < RAID_PARITY_MAX; ++j) { - 843 6 : printf("%6u", j + 1); - 844 6 : printf(" "); - 845 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 7, n, j + 1) * 100, 19); - 846 6 : printf(" "); - 847 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 30, n, j + 1) * 100, 17); + 835 : /* print extra stats only in verbose mode */ + 836 1 : if (msg_level < MSG_VERBOSE) + 837 0 : goto bail; + 838 : + 839 : /* |<##################################################################72>|####80>| */ + 840 1 : printf("\n"); + 841 1 : printf("Probability of data loss in the next year for different parity and\n"); + 842 1 : printf("combined scrub and repair time:\n"); + 843 1 : printf("\n"); + 844 1 : printf(" Parity 1 Week 1 Month 3 Months\n"); + 845 1 : printf(" -----------------------------------------------------------------------\n"); + 846 7 : for (j = 0; j < RAID_PARITY_MAX; ++j) { + 847 6 : printf("%6u", j + 1); 848 6 : printf(" "); - 849 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 90, n, j + 1) * 100, 13); - 850 6 : printf("\n"); - 851 : } - 852 : - 853 1 : printf("\n"); - 854 : - 855 : /* |<##################################################################72>|####80>| */ - 856 1 : printf("These values are the probabilities that in the next year you'll have a\n"); - 857 1 : printf("sequence of failures that the parity WONT be able to recover, assuming\n"); - 858 1 : printf("that you regularly scrub, and in case repair, the array in the specified\n"); - 859 1 : printf("time.\n"); - 860 : - 861 : bail: - 862 1 : if (make_it_fail) { - 863 1 : printf("\n"); - 864 1 : printf("DANGER! SMART is reporting that one or more disks are FAILING!\n"); - 865 1 : printf("Please take immediate action!\n"); - 866 1 : exit(EXIT_FAILURE); - 867 : } - 868 0 : } - 869 : - 870 : /** - 871 : * Fill with fake data the device list. - 872 : */ - 873 1 : static int devtest(tommy_list* low, int operation) - 874 : { - 875 : unsigned c; - 876 : - 877 1 : if (operation != DEVICE_SMART) - 878 0 : return -1; - 879 : - 880 : /* add some fake data */ - 881 17 : for (c = 0; c < 16; ++c) { - 882 : devinfo_t* entry; - 883 : int j; - 884 : - 885 16 : entry = calloc_nofail(1, sizeof(devinfo_t)); - 886 : - 887 16 : entry->device = c; + 849 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 7, n, j + 1) * 100, 19); + 850 6 : printf(" "); + 851 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 30, n, j + 1) * 100, 17); + 852 6 : printf(" "); + 853 6 : printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 90, n, j + 1) * 100, 13); + 854 6 : printf("\n"); + 855 : } + 856 : + 857 1 : printf("\n"); + 858 : + 859 : /* |<##################################################################72>|####80>| */ + 860 1 : printf("These values are the probabilities that in the next year you'll have a\n"); + 861 1 : printf("sequence of failures that the parity WONT be able to recover, assuming\n"); + 862 1 : printf("that you regularly scrub, and in case repair, the array in the specified\n"); + 863 1 : printf("time.\n"); + 864 : + 865 : bail: + 866 1 : if (make_it_fail) { + 867 1 : printf("\n"); + 868 1 : printf("DANGER! SMART is reporting that one or more disks are FAILING!\n"); + 869 1 : printf("Please take immediate action!\n"); + 870 1 : exit(EXIT_FAILURE); + 871 : } + 872 0 : } + 873 : + 874 : /** + 875 : * Fill with fake data the device list. + 876 : */ + 877 1 : static int devtest(tommy_list* low, int operation) + 878 : { + 879 : unsigned c; + 880 : + 881 1 : if (operation != DEVICE_SMART) + 882 0 : return -1; + 883 : + 884 : /* add some fake data */ + 885 17 : for (c = 0; c < 16; ++c) { + 886 : devinfo_t* entry; + 887 : int j; 888 : - 889 16 : tommy_list_insert_tail(low, &entry->node, entry); + 889 16 : entry = calloc_nofail(1, sizeof(devinfo_t)); 890 : - 891 4112 : for (j = 0; j < 256; ++j) { - 892 4096 : switch (c) { - 893 256 : case 0 : entry->smart[j] = 0; break; - 894 256 : case 1 : entry->smart[j] = SMART_UNASSIGNED; break; - 895 : default: - 896 3584 : if (j == 193) - 897 14 : entry->smart[j] = c - 2; - 898 : else - 899 3570 : entry->smart[j] = 0; - 900 3584 : break; - 901 : } - 902 : } - 903 : - 904 16 : if (c == 0) { - 905 1 : entry->smart_serial[0] = 0; - 906 1 : entry->file[0] = 0; - 907 1 : entry->name[0] = 0; - 908 1 : entry->smart[SMART_SIZE] = SMART_UNASSIGNED; - 909 1 : entry->smart[SMART_ROTATION_RATE] = 0; - 910 : } else { - 911 15 : snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c); - 912 15 : pathcpy(entry->file, sizeof(entry->name), "file"); - 913 15 : pathcpy(entry->name, sizeof(entry->name), "name"); - 914 15 : entry->smart[SMART_SIZE] = c * TERA; - 915 15 : entry->smart[SMART_ROTATION_RATE] = 7200; - 916 : } - 917 : - 918 16 : entry->smart[SMART_ERROR] = 0; - 919 16 : entry->smart[SMART_FLAGS] = SMART_UNASSIGNED; - 920 : - 921 16 : switch (c) { - 922 1 : case 3 : entry->smart[SMART_ERROR] = 1; break; - 923 1 : case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break; - 924 1 : case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break; - 925 1 : case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break; - 926 1 : case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break; - 927 1 : case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break; - 928 1 : case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break; - 929 1 : case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break; - 930 1 : case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break; - 931 : } - 932 : } - 933 : - 934 1 : return 0; - 935 : } - 936 : - 937 5 : void state_device(struct snapraid_state* state, int operation) - 938 : { - 939 : tommy_node* i; - 940 : unsigned j; - 941 : tommy_list high; - 942 : tommy_list low; - 943 : int ret; - 944 : - 945 5 : switch (operation) { - 946 1 : case DEVICE_UP : msg_progress("Spinup...\n"); break; - 947 1 : case DEVICE_DOWN : msg_progress("Spindown...\n"); break; - 948 : } - 949 : - 950 5 : tommy_list_init(&high); - 951 5 : tommy_list_init(&low); - 952 : - 953 : /* for all disks */ - 954 35 : for (i = state->disklist; i != 0; i = i->next) { - 955 30 : struct snapraid_disk* disk = i->data; - 956 : devinfo_t* entry; - 957 : - 958 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); - 959 : - 960 30 : entry->device = disk->device; - 961 30 : pathcpy(entry->name, sizeof(entry->name), disk->name); - 962 30 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir); - 963 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); - 964 : - 965 30 : tommy_list_insert_tail(&high, &entry->node, entry); - 966 : } - 967 : - 968 : /* for all parities */ - 969 35 : for (j = 0; j < state->level; ++j) { - 970 : devinfo_t* entry; + 891 16 : entry->device = c; + 892 : + 893 16 : tommy_list_insert_tail(low, &entry->node, entry); + 894 : + 895 4112 : for (j = 0; j < 256; ++j) { + 896 4096 : switch (c) { + 897 256 : case 0 : entry->smart[j] = 0; break; + 898 256 : case 1 : entry->smart[j] = SMART_UNASSIGNED; break; + 899 : default: + 900 3584 : if (j == 193) + 901 14 : entry->smart[j] = c - 2; + 902 : else + 903 3570 : entry->smart[j] = 0; + 904 3584 : break; + 905 : } + 906 : } + 907 : + 908 16 : if (c == 0) { + 909 1 : entry->smart_serial[0] = 0; + 910 1 : entry->file[0] = 0; + 911 1 : entry->name[0] = 0; + 912 1 : entry->smart[SMART_SIZE] = SMART_UNASSIGNED; + 913 1 : entry->smart[SMART_ROTATION_RATE] = 0; + 914 : } else { + 915 15 : snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c); + 916 15 : pathcpy(entry->file, sizeof(entry->name), "file"); + 917 15 : pathcpy(entry->name, sizeof(entry->name), "name"); + 918 15 : entry->smart[SMART_SIZE] = c * TERA; + 919 15 : entry->smart[SMART_ROTATION_RATE] = 7200; + 920 : } + 921 : + 922 16 : entry->smart[SMART_ERROR] = 0; + 923 16 : entry->smart[SMART_FLAGS] = SMART_UNASSIGNED; + 924 : + 925 16 : switch (c) { + 926 1 : case 3 : entry->smart[SMART_ERROR] = 1; break; + 927 1 : case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break; + 928 1 : case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break; + 929 1 : case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break; + 930 1 : case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break; + 931 1 : case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break; + 932 1 : case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break; + 933 1 : case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break; + 934 1 : case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break; + 935 : } + 936 : } + 937 : + 938 1 : return 0; + 939 : } + 940 : + 941 5 : void state_device(struct snapraid_state* state, int operation) + 942 : { + 943 : tommy_node* i; + 944 : unsigned j; + 945 : tommy_list high; + 946 : tommy_list low; + 947 : int ret; + 948 : + 949 5 : switch (operation) { + 950 1 : case DEVICE_UP : msg_progress("Spinup...\n"); break; + 951 1 : case DEVICE_DOWN : msg_progress("Spindown...\n"); break; + 952 : } + 953 : + 954 5 : tommy_list_init(&high); + 955 5 : tommy_list_init(&low); + 956 : + 957 : /* for all disks */ + 958 35 : for (i = state->disklist; i != 0; i = i->next) { + 959 30 : struct snapraid_disk* disk = i->data; + 960 : devinfo_t* entry; + 961 : + 962 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 963 : + 964 30 : entry->device = disk->device; + 965 30 : pathcpy(entry->name, sizeof(entry->name), disk->name); + 966 30 : pathcpy(entry->mount, sizeof(entry->mount), disk->dir); + 967 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); + 968 : + 969 30 : tommy_list_insert_tail(&high, &entry->node, entry); + 970 : } 971 : - 972 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); - 973 : - 974 30 : entry->device = state->parity[j].device; - 975 30 : pathcpy(entry->name, sizeof(entry->name), lev_config_name(j)); - 976 30 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path); - 977 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); - 978 30 : pathcut(entry->mount); /* remove the parity file */ - 979 : - 980 30 : tommy_list_insert_tail(&high, &entry->node, entry); - 981 : } - 982 : - 983 5 : if (state->opt.fake_device) - 984 1 : ret = devtest(&low, operation); - 985 : else - 986 4 : ret = devquery(&high, &low, operation); - 987 : - 988 5 : if (ret != 0) { - 989 2 : const char* ope = 0; - 990 2 : switch (operation) { - 991 0 : case DEVICE_UP : ope = "Spinup"; break; - 992 1 : case DEVICE_DOWN : ope = "Spindown"; break; - 993 0 : case DEVICE_LIST : ope = "List"; break; - 994 1 : case DEVICE_SMART : ope = "SMART"; break; - 995 : } - 996 2 : log_fatal("%s unsupported in this platform.\n", ope); - 997 : } else { - 998 3 : if (operation == DEVICE_LIST) { - 999 13 : for (i = tommy_list_head(&low); i != 0; i = i->next) { - 1000 12 : devinfo_t* devinfo = i->data; - 1001 12 : devinfo_t* parent = devinfo->parent; - 1002 : #ifdef _WIN32 - 1003 : printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name); - 1004 : #else - 1005 12 : printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name); - 1006 : #endif - 1007 : } - 1008 : } - 1009 : - 1010 3 : if (operation == DEVICE_SMART) - 1011 1 : state_smart(state->level + tommy_list_count(&state->disklist), &low); - 1012 : } + 972 : /* for all parities */ + 973 35 : for (j = 0; j < state->level; ++j) { + 974 : devinfo_t* entry; + 975 : + 976 30 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 977 : + 978 30 : entry->device = state->parity[j].device; + 979 30 : pathcpy(entry->name, sizeof(entry->name), lev_config_name(j)); + 980 30 : pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path); + 981 30 : pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); + 982 30 : pathcut(entry->mount); /* remove the parity file */ + 983 : + 984 30 : tommy_list_insert_tail(&high, &entry->node, entry); + 985 : } + 986 : + 987 5 : if (state->opt.fake_device) + 988 1 : ret = devtest(&low, operation); + 989 : else + 990 4 : ret = devquery(&high, &low, operation); + 991 : + 992 5 : if (ret != 0) { + 993 2 : const char* ope = 0; + 994 2 : switch (operation) { + 995 0 : case DEVICE_UP : ope = "Spinup"; break; + 996 1 : case DEVICE_DOWN : ope = "Spindown"; break; + 997 0 : case DEVICE_LIST : ope = "List"; break; + 998 1 : case DEVICE_SMART : ope = "SMART"; break; + 999 : } + 1000 2 : log_fatal("%s unsupported in this platform.\n", ope); + 1001 : } else { + 1002 3 : if (operation == DEVICE_LIST) { + 1003 13 : for (i = tommy_list_head(&low); i != 0; i = i->next) { + 1004 12 : devinfo_t* devinfo = i->data; + 1005 12 : devinfo_t* parent = devinfo->parent; + 1006 : #ifdef _WIN32 + 1007 : printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name); + 1008 : #else + 1009 12 : printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name); + 1010 : #endif + 1011 : } + 1012 : } 1013 : - 1014 4 : tommy_list_foreach(&high, free); - 1015 4 : tommy_list_foreach(&low, free); - 1016 4 : } + 1014 3 : if (operation == DEVICE_SMART) + 1015 1 : state_smart(state->level + tommy_list_count(&state->disklist), &low); + 1016 : } 1017 : + 1018 4 : tommy_list_foreach(&high, free); + 1019 4 : tommy_list_foreach(&low, free); + 1020 4 : } + 1021 : diff --git a/cov/cmdline/dry.c.func-sort-c.html b/cov/cmdline/dry.c.func-sort-c.html index ac636230..fd89714e 100644 --- a/cov/cmdline/dry.c.func-sort-c.html +++ b/cov/cmdline/dry.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/cmdline/dry.c.func.html b/cov/cmdline/dry.c.func.html index 05c93ac8..318ac87c 100644 --- a/cov/cmdline/dry.c.func.html +++ b/cov/cmdline/dry.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/cmdline/dry.c.gcov.html b/cov/cmdline/dry.c.gcov.html index 52891e1b..6886148c 100644 --- a/cov/cmdline/dry.c.gcov.html +++ b/cov/cmdline/dry.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -116,38 +116,38 @@ 54 2 : countsize = 0; 55 2 : countpos = 0; 56 2 : state_progress_begin(state, blockstart, blockmax, countmax); - 57 7054 : for (i = blockstart; i < blockmax; ++i) { + 57 7088 : for (i = blockstart; i < blockmax; ++i) { 58 : /* for each disk, process the block */ - 59 49364 : for (j = 0; j < diskmax; ++j) { + 59 49602 : for (j = 0; j < diskmax; ++j) { 60 : int read_size; 61 : struct snapraid_block* block; - 62 42312 : struct snapraid_disk* disk = handle[j].disk; + 62 42516 : struct snapraid_disk* disk = handle[j].disk; 63 : struct snapraid_file* file; 64 : block_off_t file_pos; 65 : - 66 42312 : if (!disk) { + 66 42516 : if (!disk) { 67 : /* if no disk, nothing to do */ - 68 9755 : continue; + 68 9855 : continue; 69 : } 70 : - 71 37641 : block = fs_par2block_get(disk, i); + 71 37837 : block = fs_par2block_get(disk, i); 72 : - 73 37641 : if (!block_has_file(block)) { + 73 37837 : if (!block_has_file(block)) { 74 : /* if no file, nothing to do */ - 75 413 : continue; + 75 497 : continue; 76 : } 77 : 78 : /* get the file of this block */ - 79 37228 : file = fs_par2file_get(disk, i, &file_pos); + 79 37340 : file = fs_par2file_get(disk, i, &file_pos); 80 : 81 : /* until now is CPU */ - 82 37228 : state_usage_cpu(state); + 82 37340 : state_usage_cpu(state); 83 : 84 : /* if the file is closed or different than the current one */ - 85 37228 : if (handle[j].file == 0 || handle[j].file != file) { + 85 37340 : if (handle[j].file == 0 || handle[j].file != file) { 86 : /* close the old one, if any */ - 87 15082 : ret = handle_close(&handle[j]); - 88 15082 : if (ret == -1) { + 87 15096 : ret = handle_close(&handle[j]); + 88 15096 : if (ret == -1) { 89 : /* LCOV_EXCL_START */ 90 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(handle[j].file->sub), strerror(errno)); 91 : log_fatal("DANGER! Unexpected close error in a data disk, it isn't possible to dry.\n"); @@ -158,8 +158,8 @@ 96 : } 97 : 98 : /* open the file only for reading */ - 99 15082 : ret = handle_open(&handle[j], file, state->file_mode, log_fatal, 0); - 100 15082 : if (ret == -1) { + 99 15096 : ret = handle_open(&handle[j], file, state->file_mode, log_fatal, 0); + 100 15096 : if (ret == -1) { 101 : /* LCOV_EXCL_START */ 102 : log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); 103 : log_fatal("DANGER! Unexpected open error in a data disk, it isn't possible to dry.\n"); @@ -171,41 +171,41 @@ 109 : } 110 : 111 : /* read from the file */ - 112 37228 : read_size = handle_read(&handle[j], file_pos, buffer_aligned, state->block_size, log_error, 0); - 113 37228 : if (read_size == -1) { + 112 37340 : read_size = handle_read(&handle[j], file_pos, buffer_aligned, state->block_size, log_error, 0); + 113 37340 : if (read_size == -1) { 114 0 : log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc(file->sub), file_pos); 115 0 : ++error; 116 0 : continue; 117 : } 118 : 119 : /* until now is disk */ - 120 37228 : state_usage_disk(state, disk); + 120 37340 : state_usage_disk(state, disk); 121 : - 122 37228 : countsize += read_size; + 122 37340 : countsize += read_size; 123 : } 124 : 125 : /* read the parity */ - 126 49364 : for (l = 0; l < state->level; ++l) { - 127 42312 : if (parity[l]) { + 126 49602 : for (l = 0; l < state->level; ++l) { + 127 42516 : if (parity[l]) { 128 : /* until now is CPU */ - 129 42312 : state_usage_cpu(state); + 129 42516 : state_usage_cpu(state); 130 : - 131 42312 : ret = parity_read(parity[l], i, buffer_aligned, state->block_size, log_error); - 132 42312 : if (ret == -1) { + 131 42516 : ret = parity_read(parity[l], i, buffer_aligned, state->block_size, log_error); + 132 42516 : if (ret == -1) { 133 0 : log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); 134 0 : ++error; 135 : } 136 : 137 : /* until now is parity */ - 138 42312 : state_usage_parity(state, l); + 138 42516 : state_usage_parity(state, l); 139 : } 140 : } 141 : 142 : /* count the number of processed block */ - 143 7052 : ++countpos; + 143 7086 : ++countpos; 144 : 145 : /* progress */ - 146 7052 : if (state_progress(state, i, countpos, countmax, countsize)) { + 146 7086 : if (state_progress(state, i, countpos, countmax, countsize)) { 147 : /* LCOV_EXCL_START */ 148 : break; 149 : /* LCOV_EXCL_STOP */ diff --git a/cov/cmdline/dup.c.func-sort-c.html b/cov/cmdline/dup.c.func-sort-c.html index 0817fb38..bf95ff92 100644 --- a/cov/cmdline/dup.c.func-sort-c.html +++ b/cov/cmdline/dup.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -61,24 +61,24 @@ hash_alloc - 16956 + 16970 hash_free - 16956 + 16970 hash_hash - 16956 + 16970 + + + hash_compare + 14 state_dup 3 - - hash_compare - 2 -
diff --git a/cov/cmdline/dup.c.func.html b/cov/cmdline/dup.c.func.html index 90e3eb0b..3dd795c3 100644 --- a/cov/cmdline/dup.c.func.html +++ b/cov/cmdline/dup.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -61,19 +61,19 @@ hash_alloc - 16956 + 16970 hash_compare - 2 + 14 hash_free - 16956 + 16970 hash_hash - 16956 + 16970 state_dup diff --git a/cov/cmdline/dup.c.gcov.html b/cov/cmdline/dup.c.gcov.html index 628d41b2..2be2ce52 100644 --- a/cov/cmdline/dup.c.gcov.html +++ b/cov/cmdline/dup.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -98,54 +98,54 @@ 36 : tommy_hashdyn_node node; 37 : }; 38 : - 39 16956 : struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 39 16970 : struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 40 : { 41 : struct snapraid_hash* hash; 42 : block_off_t i; 43 : unsigned char* buf; 44 : - 45 16956 : hash = malloc_nofail(sizeof(struct snapraid_hash)); - 46 16956 : hash->disk = disk; - 47 16956 : hash->file = file; + 45 16970 : hash = malloc_nofail(sizeof(struct snapraid_hash)); + 46 16970 : hash->disk = disk; + 47 16970 : hash->file = file; 48 : - 49 16956 : buf = malloc_nofail(file->blockmax * HASH_SIZE); + 49 16970 : buf = malloc_nofail(file->blockmax * HASH_SIZE); 50 : 51 : /* set the back pointer */ - 52 58816 : for (i = 0; i < file->blockmax; ++i) { - 53 41860 : struct snapraid_block* block = fs_file2block_get(file, i); + 52 58942 : for (i = 0; i < file->blockmax; ++i) { + 53 41972 : struct snapraid_block* block = fs_file2block_get(file, i); 54 : - 55 41860 : memcpy(buf + i * HASH_SIZE, block->hash, HASH_SIZE); + 55 41972 : memcpy(buf + i * HASH_SIZE, block->hash, HASH_SIZE); 56 : - 57 41860 : if (!block_has_updated_hash(block)) { + 57 41972 : if (!block_has_updated_hash(block)) { 58 0 : free(buf); 59 0 : free(hash); 60 0 : return 0; 61 : } 62 : } 63 : - 64 16956 : memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * HASH_SIZE); + 64 16970 : memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * HASH_SIZE); 65 : - 66 16956 : free(buf); + 66 16970 : free(buf); 67 : - 68 16956 : return hash; + 68 16970 : return hash; 69 : } 70 : - 71 16956 : static inline tommy_uint32_t hash_hash(struct snapraid_hash* hash) + 71 16970 : static inline tommy_uint32_t hash_hash(struct snapraid_hash* hash) 72 : { - 73 16956 : return tommy_hash_u32(0, hash->hash, HASH_SIZE); + 73 16970 : return tommy_hash_u32(0, hash->hash, HASH_SIZE); 74 : } 75 : - 76 16956 : void hash_free(struct snapraid_hash* hash) + 76 16970 : void hash_free(struct snapraid_hash* hash) 77 : { - 78 16956 : free(hash); - 79 16956 : } + 78 16970 : free(hash); + 79 16970 : } 80 : - 81 2 : int hash_compare(const void* void_arg, const void* void_data) + 81 14 : int hash_compare(const void* void_arg, const void* void_data) 82 : { - 83 2 : const char* arg = void_arg; - 84 2 : const struct snapraid_hash* hash = void_data; + 83 14 : const char* arg = void_arg; + 84 14 : const struct snapraid_hash* hash = void_data; 85 : - 86 2 : return memcmp(arg, hash->hash, HASH_SIZE); + 86 14 : return memcmp(arg, hash->hash, HASH_SIZE); 87 : } 88 : 89 3 : void state_dup(struct snapraid_state* state) @@ -168,32 +168,32 @@ 106 18 : struct snapraid_disk* disk = i->data; 107 : 108 : /* for each file */ - 109 16998 : for (j = disk->filelist; j != 0; j = j->next) { - 110 16980 : struct snapraid_file* file = j->data; + 109 17012 : for (j = disk->filelist; j != 0; j = j->next) { + 110 16994 : struct snapraid_file* file = j->data; 111 : struct snapraid_hash* hash; 112 : tommy_hash_t hash32; 113 : 114 : /* if empty, skip it */ - 115 16980 : if (file->size == 0) + 115 16994 : if (file->size == 0) 116 24 : continue; 117 : - 118 16956 : hash = hash_alloc(state, disk, file); + 118 16970 : hash = hash_alloc(state, disk, file); 119 : 120 : /* if no hash, skip it */ - 121 16956 : if (!hash) + 121 16970 : if (!hash) 122 0 : continue; 123 : - 124 16956 : hash32 = hash_hash(hash); + 124 16970 : hash32 = hash_hash(hash); 125 : - 126 16956 : struct snapraid_hash* found = tommy_hashdyn_search(&hashset, hash_compare, hash->hash, hash32); - 127 16956 : if (found) { - 128 2 : ++count; - 129 2 : size += found->file->size; - 130 2 : log_tag("dup:%s:%s:%s:%s:%" PRIu64 ": dup\n", disk->name, esc(file->sub), found->disk->name, esc(found->file->sub), found->file->size); - 131 2 : printf("%12" PRIu64 " %s%s = %s%s\n", file->size, disk->dir, file->sub, found->disk->dir, found->file->sub); - 132 2 : hash_free(hash); + 126 16970 : struct snapraid_hash* found = tommy_hashdyn_search(&hashset, hash_compare, hash->hash, hash32); + 127 16970 : if (found) { + 128 14 : ++count; + 129 14 : size += found->file->size; + 130 14 : log_tag("dup:%s:%s:%s:%s:%" PRIu64 ": dup\n", disk->name, esc(file->sub), found->disk->name, esc(found->file->sub), found->file->size); + 131 14 : printf("%12" PRIu64 " %s%s = %s%s\n", file->size, disk->dir, file->sub, found->disk->dir, found->file->sub); + 132 14 : hash_free(hash); 133 : } else { - 134 16954 : tommy_hashdyn_insert(&hashset, &hash->node, hash, hash32); + 134 16956 : tommy_hashdyn_insert(&hashset, &hash->node, hash, hash32); 135 : } 136 : } 137 : } diff --git a/cov/cmdline/elem.c.func-sort-c.html b/cov/cmdline/elem.c.func-sort-c.html index ad72c590..fdcb8ada 100644 --- a/cov/cmdline/elem.c.func-sort-c.html +++ b/cov/cmdline/elem.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 545 - 581 + 546 + 582 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 62 @@ -60,248 +60,248 @@ Hit count Sort by hit count - chunk_parity_inside_compare - 211700412 - - - chunk_file_inside_compare - 123424429 - - - fs_file2block_get - 112904165 - - - fs_par2file_get_ts - 62671366 - - - fs_par2chunk_get_ts - 62562730 - - - fs_par2block_get_ts - 51148943 + chunk_parity_inside_compare + 102351431 chunk_file_compare - 43527418 + 44153325 + + + fs_file2block_get + 44106216 chunk_parity_compare - 43029600 + 43351652 - fs_file2chunk_get_ts - 34157182 + fs_par2chunk_get_ts + 38418652 - fs_file2par_get_ts - 28740730 + fs_par2file_get_ts + 38311850 + + + fs_par2block_get_ts + 26733115 + + + chunk_file_inside_compare + 21495373 filter_apply - 12035450 + 12222233 - fs_allocate - 8849850 + fs_file2chunk_get_ts + 10223247 + + + fs_allocate + 8975787 file_block_size - 6610122 + 6677441 - chunk_file_check_foreach - 6291380 + chunk_file_check_foreach + 6441048 - chunk_parity_check_foreach - 6291380 + chunk_parity_check_foreach + 6441048 filter_recurse - 6023667 + 6118464 file_block_is_last - 5319910 + 5326414 + + + fs_file2par_get_ts + 4878725 chunk_alloc - 3607761 + 3657427 file_alloc - 3565141 + 3611495 chunk_free - 3437520 + 3486903 file_free - 3417248 + 3466242 filter_element - 3226232 + 3273724 filter_path - 3223260 + 3270701 filter_content - 3066852 + 3114300 file_inode_compare_to_arg - 866983 + 927047 - time_compare - 743492 + time_compare + 707506 file_path_compare - 126356 + 129121 filter_type - 125437 + 125387 link_alloc - 115419 + 116876 link_free - 109621 + 111078 + + + fs_deallocate + 106802 file_path_compare_to_arg - 105104 - - - fs_deallocate - 104155 + 104908 filter_existence - 80654 - - - file_name - 47908 - - - chunk_disk_size_compare - 47779 - - - filter_correctness - 38806 + 80688 file_physical_compare - 34618 + 49676 + + + chunk_disk_size_compare + 48702 + + + file_name + 47994 + + + filter_correctness + 38732 link_name_compare_to_arg - 30380 - - - file_namestamp_compare - 23954 - - - file_name_compare - 23954 - - - file_stamp_compare - 23659 + 31837 file_dup - 21785 + 24707 + + + file_namestamp_compare + 23997 + + + file_name_compare + 23997 + + + file_stamp_compare + 23661 file_copy - 6209 + 23633 - disk_size - 3955 + disk_size + 4165 filter_dir - 2972 + 3023 - fs_check - 2676 + fs_check + 2838 disk_alloc - 1477 + 1525 - map_alloc - 1447 + map_alloc + 1495 content_alloc - 1434 + 1490 - disk_free - 1351 + disk_free + 1399 - map_free - 1327 + map_free + 1375 content_free - 1297 + 1353 link_alpha_compare 1249 - disk_is_empty - 804 + disk_is_empty + 870 dir_alloc - 760 + 772 dir_free - 712 + 724 filter_alloc_file - 498 + 514 filter_free - 461 + 477 dir_name_compare - 217 + 229 file_rename 155 - chunk_disk_empty_compare - 10 + chunk_disk_empty_compare + 13 filter_alloc_disk diff --git a/cov/cmdline/elem.c.func.html b/cov/cmdline/elem.c.func.html index a43507ef..b00e3681 100644 --- a/cov/cmdline/elem.c.func.html +++ b/cov/cmdline/elem.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 545 - 581 + 546 + 582 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 62 @@ -61,103 +61,103 @@ chunk_alloc - 3607761 + 3657427 - chunk_disk_empty_compare - 10 + chunk_disk_empty_compare + 13 - chunk_disk_size_compare - 47779 + chunk_disk_size_compare + 48702 - chunk_file_check_foreach - 6291380 + chunk_file_check_foreach + 6441048 chunk_file_compare - 43527418 + 44153325 - chunk_file_inside_compare - 123424429 + chunk_file_inside_compare + 21495373 chunk_free - 3437520 + 3486903 - chunk_parity_check_foreach - 6291380 + chunk_parity_check_foreach + 6441048 chunk_parity_compare - 43029600 + 43351652 - chunk_parity_inside_compare - 211700412 + chunk_parity_inside_compare + 102351431 content_alloc - 1434 + 1490 content_free - 1297 + 1353 dir_alloc - 760 + 772 dir_free - 712 + 724 dir_name_compare - 217 + 229 disk_alloc - 1477 + 1525 - disk_free - 1351 + disk_free + 1399 - disk_is_empty - 804 + disk_is_empty + 870 - disk_size - 3955 + disk_size + 4165 file_alloc - 3565141 + 3611495 file_block_is_last - 5319910 + 5326414 file_block_size - 6610122 + 6677441 file_copy - 6209 + 23633 file_dup - 21785 + 24707 file_free - 3417248 + 3466242 file_inode_compare @@ -165,27 +165,27 @@ file_inode_compare_to_arg - 866983 + 927047 file_name - 47908 + 47994 file_name_compare - 23954 + 23997 file_namestamp_compare - 23954 + 23997 file_path_compare - 126356 + 129121 file_path_compare_to_arg - 105104 + 104908 file_pathstamp_compare @@ -193,7 +193,7 @@ file_physical_compare - 34618 + 49676 file_rename @@ -201,7 +201,7 @@ file_stamp_compare - 23659 + 23661 filter_alloc_disk @@ -209,87 +209,87 @@ filter_alloc_file - 498 + 514 filter_apply - 12035450 + 12222233 filter_content - 3066852 + 3114300 filter_correctness - 38806 + 38732 filter_dir - 2972 + 3023 filter_element - 3226232 + 3273724 filter_existence - 80654 + 80688 filter_free - 461 + 477 filter_path - 3223260 + 3270701 filter_recurse - 6023667 + 6118464 filter_type - 125437 + 125387 - fs_allocate - 8849850 + fs_allocate + 8975787 - fs_check - 2676 + fs_check + 2838 - fs_deallocate - 104155 + fs_deallocate + 106802 - fs_file2block_get - 112904165 + fs_file2block_get + 44106216 - fs_file2chunk_get_ts - 34157182 + fs_file2chunk_get_ts + 10223247 - fs_file2par_get_ts - 28740730 + fs_file2par_get_ts + 4878725 - fs_par2block_get_ts - 51148943 + fs_par2block_get_ts + 26733115 - fs_par2chunk_get_ts - 62562730 + fs_par2chunk_get_ts + 38418652 - fs_par2file_get_ts - 62671366 + fs_par2file_get_ts + 38311850 link_alloc - 115419 + 116876 link_alpha_compare @@ -297,23 +297,23 @@ link_free - 109621 + 111078 link_name_compare_to_arg - 30380 + 31837 - map_alloc - 1447 + map_alloc + 1495 - map_free - 1327 + map_free + 1375 - time_compare - 743492 + time_compare + 707506
diff --git a/cov/cmdline/elem.c.gcov.html b/cov/cmdline/elem.c.gcov.html index 0121811d..647e3a16 100644 --- a/cov/cmdline/elem.c.gcov.html +++ b/cov/cmdline/elem.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 545 - 581 + 546 + 582 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 62 @@ -86,23 +86,23 @@ 24 : /****************************************************************************/ 25 : /* snapraid */ 26 : - 27 1434 : struct snapraid_content* content_alloc(const char* path, uint64_t dev) + 27 1490 : struct snapraid_content* content_alloc(const char* path, uint64_t dev) 28 : { 29 : struct snapraid_content* content; 30 : - 31 1434 : content = malloc_nofail(sizeof(struct snapraid_content)); - 32 1434 : pathimport(content->content, sizeof(content->content), path); - 33 1434 : content->device = dev; + 31 1490 : content = malloc_nofail(sizeof(struct snapraid_content)); + 32 1490 : pathimport(content->content, sizeof(content->content), path); + 33 1490 : content->device = dev; 34 : - 35 1434 : return content; + 35 1490 : return content; 36 : } 37 : - 38 1297 : void content_free(struct snapraid_content* content) + 38 1353 : void content_free(struct snapraid_content* content) 39 : { - 40 1297 : free(content); - 41 1297 : } + 40 1353 : free(content); + 41 1353 : } 42 : - 43 498 : struct snapraid_filter* filter_alloc_file(int direction, const char* pattern) + 43 514 : struct snapraid_filter* filter_alloc_file(int direction, const char* pattern) 44 : { 45 : struct snapraid_filter* filter; 46 : char* i; @@ -111,18 +111,18 @@ 49 : int token_is_valid; 50 : int token_is_filled; 51 : - 52 498 : filter = malloc_nofail(sizeof(struct snapraid_filter)); - 53 498 : pathimport(filter->pattern, sizeof(filter->pattern), pattern); - 54 498 : filter->direction = direction; + 52 514 : filter = malloc_nofail(sizeof(struct snapraid_filter)); + 53 514 : pathimport(filter->pattern, sizeof(filter->pattern), pattern); + 54 514 : filter->direction = direction; 55 : 56 : /* find first and last slash */ - 57 498 : first = 0; - 58 498 : last = 0; + 57 514 : first = 0; + 58 514 : last = 0; 59 : /* reject invalid tokens, like "<empty>", ".", ".." and more dots */ - 60 498 : token_is_valid = 0; - 61 498 : token_is_filled = 0; - 62 6172 : for (i = filter->pattern; *i; ++i) { - 63 5675 : if (*i == '/') { + 60 514 : token_is_valid = 0; + 61 514 : token_is_filled = 0; + 62 6372 : for (i = filter->pattern; *i; ++i) { + 63 5859 : if (*i == '/') { 64 : /* reject invalid tokens, but accept an empty one as first */ 65 5 : if (!token_is_valid && (first != 0 || token_is_filled)) { 66 1 : free(filter); @@ -135,27 +135,27 @@ 73 4 : if (!first) 74 3 : first = i; 75 4 : last = i; - 76 5670 : } else if (*i != '.') { - 77 5176 : token_is_valid = 1; - 78 5176 : token_is_filled = 1; + 76 5854 : } else if (*i != '.') { + 77 5344 : token_is_valid = 1; + 78 5344 : token_is_filled = 1; 79 : } else { - 80 494 : token_is_filled = 1; + 80 510 : token_is_filled = 1; 81 : } 82 : } 83 : 84 : /* reject invalid tokens, but accept an empty one as last, but not if it's the only one */ - 85 497 : if (!token_is_valid && (first == 0 || token_is_filled)) { + 85 513 : if (!token_is_valid && (first == 0 || token_is_filled)) { 86 1 : free(filter); 87 1 : return 0; 88 : } 89 : 90 : /* it's a file filter */ - 91 496 : filter->is_disk = 0; + 91 512 : filter->is_disk = 0; 92 : - 93 496 : if (first == 0) { + 93 512 : if (first == 0) { 94 : /* no slash */ - 95 493 : filter->is_path = 0; - 96 493 : filter->is_dir = 0; + 95 509 : filter->is_path = 0; + 96 509 : filter->is_dir = 0; 97 3 : } else if (first == last && last[1] == 0) { 98 : /* one slash at the end */ 99 1 : filter->is_path = 0; @@ -178,7 +178,7 @@ 116 : } 117 : } 118 : - 119 495 : return filter; + 119 511 : return filter; 120 : } 121 : 122 8 : struct snapraid_filter* filter_alloc_disk(int direction, const char* pattern) @@ -205,162 +205,162 @@ 143 8 : return filter; 144 : } 145 : - 146 461 : void filter_free(struct snapraid_filter* filter) + 146 477 : void filter_free(struct snapraid_filter* filter) 147 : { - 148 461 : free(filter); - 149 461 : } + 148 477 : free(filter); + 149 477 : } 150 : - 151 125437 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) + 151 125387 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) 152 : { 153 : const char* direction; - 154 125437 : if (filter->direction < 0) - 155 125191 : direction = "exclude"; + 154 125387 : if (filter->direction < 0) + 155 125133 : direction = "exclude"; 156 : else - 157 246 : direction = "include"; + 157 254 : direction = "include"; 158 : - 159 125437 : if (filter->is_disk) + 159 125387 : if (filter->is_disk) 160 0 : pathprint(out, out_size, "%s %s:", direction, filter->pattern); - 161 125437 : else if (filter->is_dir) + 161 125387 : else if (filter->is_dir) 162 0 : pathprint(out, out_size, "%s %s/", direction, filter->pattern); 163 : else - 164 125437 : pathprint(out, out_size, "%s %s", direction, filter->pattern); + 164 125387 : pathprint(out, out_size, "%s %s", direction, filter->pattern); 165 : - 166 125437 : return out; + 166 125387 : return out; 167 : } 168 : - 169 12035450 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir) + 169 12222233 : static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir) 170 : { - 171 12035450 : int ret = 0; + 171 12222233 : int ret = 0; 172 : 173 : /* match dirs with dirs and files with files */ - 174 12035450 : if (filter->is_dir && !is_dir) - 175 2939 : return 0; - 176 12032511 : if (!filter->is_dir && is_dir) - 177 6014680 : return 0; + 174 12222233 : if (filter->is_dir && !is_dir) + 175 2946 : return 0; + 176 12219287 : if (!filter->is_dir && is_dir) + 177 6106768 : return 0; 178 : - 179 6017831 : if (filter->is_path) { + 179 6112519 : if (filter->is_path) { 180 : /* skip initial slash, as always missing from the path */ - 181 2939 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 181 2946 : if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0) 182 0 : ret = filter->direction; 183 : } else { - 184 6014892 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) - 185 127935 : ret = filter->direction; + 184 6109573 : if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 185 127869 : ret = filter->direction; 186 : } 187 : - 188 6017831 : if (reason != 0 && ret < 0) - 189 124945 : *reason = filter; + 188 6112519 : if (reason != 0 && ret < 0) + 189 124879 : *reason = filter; 190 : - 191 6017831 : return ret; + 191 6112519 : return ret; 192 : } 193 : - 194 6023667 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir) + 194 6118464 : static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir) 195 : { 196 : char path[PATH_MAX]; 197 : char* name; 198 : unsigned i; 199 : - 200 6023667 : pathcpy(path, sizeof(path), const_path); + 200 6118464 : pathcpy(path, sizeof(path), const_path); 201 : 202 : /* filter for all the directories */ - 203 6023667 : name = path; - 204 86942366 : for (i = 0; path[i] != 0; ++i) { - 205 80921689 : if (path[i] == '/') { + 203 6118464 : name = path; + 204 88222216 : for (i = 0; path[i] != 0; ++i) { + 205 82106742 : if (path[i] == '/') { 206 : /* set a terminator */ - 207 6014773 : path[i] = 0; + 207 6106759 : path[i] = 0; 208 : 209 : /* filter the directory */ - 210 6014773 : if (filter_apply(filter, reason, path, name, 1) != 0) + 210 6106759 : if (filter_apply(filter, reason, path, name, 1) != 0) 211 2990 : return filter->direction; 212 : 213 : /* restore the slash */ - 214 6011783 : path[i] = '/'; + 214 6103769 : path[i] = '/'; 215 : 216 : /* next name */ - 217 6011783 : name = path + i + 1; + 217 6103769 : name = path + i + 1; 218 : } 219 : } 220 : 221 : /* filter the final file */ - 222 6020677 : if (filter_apply(filter, reason, path, name, is_dir) != 0) - 223 124945 : return filter->direction; + 222 6115474 : if (filter_apply(filter, reason, path, name, is_dir) != 0) + 223 124879 : return filter->direction; 224 : - 225 5895732 : return 0; + 225 5990595 : return 0; 226 : } 227 : - 228 3226232 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir) + 228 3273724 : static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir) 229 : { 230 : tommy_node* i; 231 : - 232 3226232 : int direction = 1; /* by default include all */ + 232 3273724 : int direction = 1; /* by default include all */ 233 : 234 : /* for each filter */ - 235 9223179 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { + 235 9365584 : for (i = tommy_list_head(filterlist); i != 0; i = i->next) { 236 : int ret; - 237 6133552 : struct snapraid_filter* filter = i->data; + 237 6228405 : struct snapraid_filter* filter = i->data; 238 : - 239 6133552 : if (filter->is_disk) { - 240 109885 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0) - 241 8670 : ret = filter->direction; + 239 6228405 : if (filter->is_disk) { + 240 109941 : if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 241 8676 : ret = filter->direction; 242 : else - 243 101215 : ret = 0; - 244 109885 : if (reason != 0 && ret < 0) + 243 101265 : ret = 0; + 244 109941 : if (reason != 0 && ret < 0) 245 0 : *reason = filter; 246 : } else { - 247 6023667 : ret = filter_recurse(filter, reason, sub, is_dir); + 247 6118464 : ret = filter_recurse(filter, reason, sub, is_dir); 248 : } 249 : - 250 6133552 : if (ret > 0) { + 250 6228405 : if (ret > 0) { 251 : /* include the file */ - 252 11660 : return 0; - 253 6121892 : } else if (ret < 0) { + 252 11666 : return 0; + 253 6216739 : } else if (ret < 0) { 254 : /* exclude the file */ - 255 124945 : return -1; + 255 124879 : return -1; 256 : } else { 257 : /* default is opposite of the last filter */ - 258 5996947 : direction = -filter->direction; - 259 5996947 : if (reason != 0 && direction < 0) - 260 3004435 : *reason = filter; + 258 6091860 : direction = -filter->direction; + 259 6091860 : if (reason != 0 && direction < 0) + 260 3051823 : *reason = filter; 261 : /* continue with the next one */ 262 : } 263 : } 264 : 265 : /* directories are always included by default, otherwise we cannot apply rules */ 266 : /* to the contained files */ - 267 3089627 : if (is_dir) - 268 2971 : return 0; + 267 3137179 : if (is_dir) + 268 3022 : return 0; 269 : 270 : /* files are excluded/included depending of the last rule processed */ - 271 3086656 : if (direction < 0) - 272 57545 : return -1; + 271 3134157 : if (direction < 0) + 272 57574 : return -1; 273 : - 274 3029111 : return 0; + 274 3076583 : return 0; 275 : } 276 : - 277 3223260 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) + 277 3270701 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) 278 : { - 279 3223260 : return filter_element(filterlist, reason, disk, sub, 0); + 279 3270701 : return filter_element(filterlist, reason, disk, sub, 0); 280 : } 281 : - 282 2972 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) + 282 3023 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) 283 : { - 284 2972 : return filter_element(filterlist, reason, disk, sub, 1); + 284 3023 : return filter_element(filterlist, reason, disk, sub, 1); 285 : } 286 : - 287 80654 : int filter_existence(int filter_missing, const char* dir, const char* sub) + 287 80688 : int filter_existence(int filter_missing, const char* dir, const char* sub) 288 : { 289 : char path[PATH_MAX]; 290 : struct stat st; 291 : - 292 80654 : if (!filter_missing) - 293 34958 : return 0; + 292 80688 : if (!filter_missing) + 293 34978 : return 0; 294 : 295 : /* we directly check if in the disk the file is present or not */ - 296 45696 : pathprint(path, sizeof(path), "%s%s", dir, sub); + 296 45710 : pathprint(path, sizeof(path), "%s%s", dir, sub); 297 : - 298 45696 : if (lstat(path, &st) != 0) { + 298 45710 : if (lstat(path, &st) != 0) { 299 : /* if the file doesn't exist, we don't filter it out */ - 300 5007 : if (errno == ENOENT) - 301 5007 : return 0; + 300 4913 : if (errno == ENOENT) + 301 4913 : return 0; 302 : /* LCOV_EXCL_START */ 303 : log_fatal("Error in stat file '%s'. %s.\n", path, strerror(errno)); 304 : exit(EXIT_FAILURE); @@ -368,111 +368,111 @@ 306 : } 307 : 308 : /* the file is present, so we filter it out */ - 309 40689 : return 1; + 309 40797 : return 1; 310 : } 311 : - 312 38806 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file) + 312 38732 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file) 313 : { 314 : unsigned i; 315 : - 316 38806 : if (!filter_error) - 317 16278 : return 0; + 316 38732 : if (!filter_error) + 317 16190 : return 0; 318 : 319 : /* check each block of the file */ - 320 60231 : for (i = 0; i < file->blockmax; ++i) { - 321 46123 : block_off_t parity_pos = fs_file2par_get(disk, file, i); - 322 46123 : snapraid_info info = info_get(infoarr, parity_pos); + 320 60567 : for (i = 0; i < file->blockmax; ++i) { + 321 46357 : block_off_t parity_pos = fs_file2par_get(disk, file, i); + 322 46357 : snapraid_info info = info_get(infoarr, parity_pos); 323 : 324 : /* if the file has a bad block, don't exclude it */ - 325 46123 : if (info_get_bad(info)) - 326 8420 : return 0; + 325 46357 : if (info_get_bad(info)) + 326 8332 : return 0; 327 : } 328 : 329 : /* the file is correct, so we filter it out */ - 330 14108 : return 1; + 330 14210 : return 1; 331 : } 332 : - 333 3066852 : int filter_content(tommy_list* contentlist, const char* path) + 333 3114300 : int filter_content(tommy_list* contentlist, const char* path) 334 : { 335 : tommy_node* i; 336 : - 337 39681406 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { - 338 16773851 : struct snapraid_content* content = i->data; + 337 40437716 : for (i = tommy_list_head(contentlist); i != 0; i = i->next) { + 338 17104558 : struct snapraid_content* content = i->data; 339 : char tmp[PATH_MAX]; 340 : - 341 16773851 : if (pathcmp(content->content, path) == 0) + 341 17104558 : if (pathcmp(content->content, path) == 0) 342 0 : return -1; 343 : 344 : /* exclude also the ".tmp" copy used to save it */ - 345 16773851 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 346 16773851 : if (pathcmp(tmp, path) == 0) + 345 17104558 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 346 17104558 : if (pathcmp(tmp, path) == 0) 347 0 : return -1; 348 : 349 : /* exclude also the ".lock" file */ - 350 16773851 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); - 351 16773851 : if (pathcmp(tmp, path) == 0) + 350 17104558 : pathprint(tmp, sizeof(tmp), "%s.lock", content->content); + 351 17104558 : if (pathcmp(tmp, path) == 0) 352 0 : return -1; 353 : } 354 : - 355 3066852 : return 0; + 355 3114300 : return 0; 356 : } 357 : - 358 3565141 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical) + 358 3611495 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical) 359 : { 360 : struct snapraid_file* file; 361 : block_off_t i; 362 : - 363 3565141 : file = malloc_nofail(sizeof(struct snapraid_file)); - 364 3565141 : file->sub = strdup_nofail(sub); - 365 3565141 : file->size = size; - 366 3565141 : file->blockmax = (size + block_size - 1) / block_size; - 367 3565141 : file->mtime_sec = mtime_sec; - 368 3565141 : file->mtime_nsec = mtime_nsec; - 369 3565141 : file->inode = inode; - 370 3565141 : file->physical = physical; - 371 3565141 : file->flag = 0; - 372 3565141 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block)); + 363 3611495 : file = malloc_nofail(sizeof(struct snapraid_file)); + 364 3611495 : file->sub = strdup_nofail(sub); + 365 3611495 : file->size = size; + 366 3611495 : file->blockmax = (size + block_size - 1) / block_size; + 367 3611495 : file->mtime_sec = mtime_sec; + 368 3611495 : file->mtime_nsec = mtime_nsec; + 369 3611495 : file->inode = inode; + 370 3611495 : file->physical = physical; + 371 3611495 : file->flag = 0; + 372 3611495 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block)); 373 : - 374 12361356 : for (i = 0; i < file->blockmax; ++i) { - 375 8796215 : block_state_set(&file->blockvec[i], BLOCK_STATE_CHG); - 376 8796215 : hash_invalid_set(file->blockvec[i].hash); + 374 12530604 : for (i = 0; i < file->blockmax; ++i) { + 375 8919109 : block_state_set(&file->blockvec[i], BLOCK_STATE_CHG); + 376 8919109 : hash_invalid_set(file->blockvec[i].hash); 377 : } 378 : - 379 3565141 : return file; + 379 3611495 : return file; 380 : } 381 : - 382 21785 : struct snapraid_file* file_dup(struct snapraid_file* copy) + 382 24707 : struct snapraid_file* file_dup(struct snapraid_file* copy) 383 : { 384 : struct snapraid_file* file; 385 : block_off_t i; 386 : - 387 21785 : file = malloc_nofail(sizeof(struct snapraid_file)); - 388 21785 : file->sub = strdup_nofail(copy->sub); - 389 21785 : file->size = copy->size; - 390 21785 : file->blockmax = copy->blockmax; - 391 21785 : file->mtime_sec = copy->mtime_sec; - 392 21785 : file->mtime_nsec = copy->mtime_nsec; - 393 21785 : file->inode = copy->inode; - 394 21785 : file->physical = copy->physical; - 395 21785 : file->flag = copy->flag; - 396 21785 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block)); + 387 24707 : file = malloc_nofail(sizeof(struct snapraid_file)); + 388 24707 : file->sub = strdup_nofail(copy->sub); + 389 24707 : file->size = copy->size; + 390 24707 : file->blockmax = copy->blockmax; + 391 24707 : file->mtime_sec = copy->mtime_sec; + 392 24707 : file->mtime_nsec = copy->mtime_nsec; + 393 24707 : file->inode = copy->inode; + 394 24707 : file->physical = copy->physical; + 395 24707 : file->flag = copy->flag; + 396 24707 : file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block)); 397 : - 398 75420 : for (i = 0; i < file->blockmax; ++i) { - 399 53635 : file->blockvec[i].state = copy->blockvec[i].state; - 400 53635 : memcpy(file->blockvec[i].hash, copy->blockvec[i].hash, HASH_SIZE); + 398 81385 : for (i = 0; i < file->blockmax; ++i) { + 399 56678 : file->blockvec[i].state = copy->blockvec[i].state; + 400 56678 : memcpy(file->blockvec[i].hash, copy->blockvec[i].hash, HASH_SIZE); 401 : } 402 : - 403 21785 : return file; + 403 24707 : return file; 404 : } 405 : - 406 3417248 : void file_free(struct snapraid_file* file) + 406 3466242 : void file_free(struct snapraid_file* file) 407 : { - 408 3417248 : free(file->sub); - 409 3417248 : file->sub = 0; - 410 3417248 : free(file->blockvec); - 411 3417248 : file->blockvec = 0; - 412 3417248 : free(file); - 413 3417248 : } + 408 3466242 : free(file->sub); + 409 3466242 : file->sub = 0; + 410 3466242 : free(file->blockvec); + 411 3466242 : file->blockvec = 0; + 412 3466242 : free(file); + 413 3466242 : } 414 : 415 155 : void file_rename(struct snapraid_file* file, const char* sub) 416 : { @@ -480,94 +480,94 @@ 418 155 : file->sub = strdup_nofail(sub); 419 155 : } 420 : - 421 6209 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file) + 421 23633 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file) 422 : { 423 : block_off_t i; 424 : - 425 6209 : if (src_file->size != dst_file->size) { + 425 23633 : if (src_file->size != dst_file->size) { 426 : /* LCOV_EXCL_START */ 427 : log_fatal("Internal inconsistency in copy file with different size\n"); - 428 : exit(EXIT_FAILURE); + 428 : os_abort(); 429 : /* LCOV_EXCL_STOP */ 430 : } 431 : - 432 6209 : if (src_file->mtime_sec != dst_file->mtime_sec) { + 432 23633 : if (src_file->mtime_sec != dst_file->mtime_sec) { 433 : /* LCOV_EXCL_START */ 434 : log_fatal("Internal inconsistency in copy file with different mtime_sec\n"); - 435 : exit(EXIT_FAILURE); + 435 : os_abort(); 436 : /* LCOV_EXCL_STOP */ 437 : } 438 : - 439 6209 : if (src_file->mtime_nsec != dst_file->mtime_nsec) { + 439 23633 : if (src_file->mtime_nsec != dst_file->mtime_nsec) { 440 : /* LCOV_EXCL_START */ 441 : log_fatal("Internal inconsistency in copy file with different mtime_nsec\n"); - 442 : exit(EXIT_FAILURE); + 442 : os_abort(); 443 : /* LCOV_EXCL_STOP */ 444 : } 445 : - 446 17910 : for (i = 0; i < dst_file->blockmax; ++i) { + 446 81852 : for (i = 0; i < dst_file->blockmax; ++i) { 447 : /* set a block with hash computed but without parity */ - 448 11701 : block_state_set(&dst_file->blockvec[i], BLOCK_STATE_REP); + 448 58219 : block_state_set(&dst_file->blockvec[i], BLOCK_STATE_REP); 449 : 450 : /* copy the hash */ - 451 11701 : memcpy(dst_file->blockvec[i].hash, src_file->blockvec[i].hash, HASH_SIZE); + 451 58219 : memcpy(dst_file->blockvec[i].hash, src_file->blockvec[i].hash, HASH_SIZE); 452 : } 453 : - 454 6209 : file_flag_set(dst_file, FILE_IS_COPY); - 455 6209 : } + 454 23633 : file_flag_set(dst_file, FILE_IS_COPY); + 455 23633 : } 456 : - 457 47908 : const char* file_name(const struct snapraid_file* file) + 457 47994 : const char* file_name(const struct snapraid_file* file) 458 : { - 459 47908 : const char* r = strrchr(file->sub, '/'); + 459 47994 : const char* r = strrchr(file->sub, '/'); 460 : - 461 47908 : if (!r) - 462 8 : r = file->sub; + 461 47994 : if (!r) + 462 60 : r = file->sub; 463 : else - 464 47900 : ++r; - 465 47908 : return r; + 464 47934 : ++r; + 465 47994 : return r; 466 : } 467 : - 468 6610122 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) + 468 6677441 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) 469 : { 470 : /* if it's the last block */ - 471 6610122 : if (file_pos + 1 == file->blockmax) { + 471 6677441 : if (file_pos + 1 == file->blockmax) { 472 : unsigned block_remainder; - 473 2692717 : if (file->size == 0) + 473 2717238 : if (file->size == 0) 474 0 : return 0; - 475 2692717 : block_remainder = file->size % block_size; - 476 2692717 : if (block_remainder == 0) - 477 1544 : block_remainder = block_size; - 478 2692717 : return block_remainder; + 475 2717238 : block_remainder = file->size % block_size; + 476 2717238 : if (block_remainder == 0) + 477 2543 : block_remainder = block_size; + 478 2717238 : return block_remainder; 479 : } 480 : - 481 3917405 : return block_size; + 481 3960203 : return block_size; 482 : } 483 : - 484 5319910 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) + 484 5326414 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) 485 : { - 486 5319910 : if (file_pos == 0 && file->blockmax == 0) + 486 5326414 : if (file_pos == 0 && file->blockmax == 0) 487 0 : return 1; 488 : - 489 5319910 : if (file_pos >= file->blockmax) { + 489 5326414 : if (file_pos >= file->blockmax) { 490 : /* LCOV_EXCL_START */ 491 : log_fatal("Internal inconsistency in file block position\n"); - 492 : exit(EXIT_FAILURE); + 492 : os_abort(); 493 : /* LCOV_EXCL_STOP */ 494 : } 495 : - 496 5319910 : return file_pos == file->blockmax - 1; + 496 5326414 : return file_pos == file->blockmax - 1; 497 : } 498 : - 499 866983 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) + 499 927047 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data) 500 : { - 501 866983 : const uint64_t* arg = void_arg; - 502 866983 : const struct snapraid_file* file = void_data; + 501 927047 : const uint64_t* arg = void_arg; + 502 927047 : const struct snapraid_file* file = void_data; 503 : - 504 866983 : if (*arg < file->inode) + 504 927047 : if (*arg < file->inode) 505 0 : return -1; - 506 866983 : if (*arg > file->inode) + 506 927047 : if (*arg > file->inode) 507 0 : return 1; - 508 866983 : return 0; + 508 927047 : return 0; 509 : } 510 : 511 0 : int file_inode_compare(const void* void_a, const void* void_b) @@ -582,76 +582,76 @@ 520 0 : return 0; 521 : } 522 : - 523 126356 : int file_path_compare(const void* void_a, const void* void_b) + 523 129121 : int file_path_compare(const void* void_a, const void* void_b) 524 : { - 525 126356 : const struct snapraid_file* file_a = void_a; - 526 126356 : const struct snapraid_file* file_b = void_b; + 525 129121 : const struct snapraid_file* file_a = void_a; + 526 129121 : const struct snapraid_file* file_b = void_b; 527 : - 528 126356 : return strcmp(file_a->sub, file_b->sub); + 528 129121 : return strcmp(file_a->sub, file_b->sub); 529 : } 530 : - 531 34618 : int file_physical_compare(const void* void_a, const void* void_b) + 531 49676 : int file_physical_compare(const void* void_a, const void* void_b) 532 : { - 533 34618 : const struct snapraid_file* file_a = void_a; - 534 34618 : const struct snapraid_file* file_b = void_b; + 533 49676 : const struct snapraid_file* file_a = void_a; + 534 49676 : const struct snapraid_file* file_b = void_b; 535 : - 536 34618 : if (file_a->physical < file_b->physical) - 537 26412 : return -1; - 538 8206 : if (file_a->physical > file_b->physical) - 539 8204 : return 1; + 536 49676 : if (file_a->physical < file_b->physical) + 537 34678 : return -1; + 538 14998 : if (file_a->physical > file_b->physical) + 539 14996 : return 1; 540 2 : return 0; 541 : } 542 : - 543 105104 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) + 543 104908 : int file_path_compare_to_arg(const void* void_arg, const void* void_data) 544 : { - 545 105104 : const char* arg = void_arg; - 546 105104 : const struct snapraid_file* file = void_data; + 545 104908 : const char* arg = void_arg; + 546 104908 : const struct snapraid_file* file = void_data; 547 : - 548 105104 : return strcmp(arg, file->sub); + 548 104908 : return strcmp(arg, file->sub); 549 : } 550 : - 551 23954 : int file_name_compare(const void* void_a, const void* void_b) + 551 23997 : int file_name_compare(const void* void_a, const void* void_b) 552 : { - 553 23954 : const struct snapraid_file* file_a = void_a; - 554 23954 : const struct snapraid_file* file_b = void_b; - 555 23954 : const char* name_a = file_name(file_a); - 556 23954 : const char* name_b = file_name(file_b); + 553 23997 : const struct snapraid_file* file_a = void_a; + 554 23997 : const struct snapraid_file* file_b = void_b; + 555 23997 : const char* name_a = file_name(file_a); + 556 23997 : const char* name_b = file_name(file_b); 557 : - 558 23954 : return strcmp(name_a, name_b); + 558 23997 : return strcmp(name_a, name_b); 559 : } 560 : - 561 23659 : int file_stamp_compare(const void* void_a, const void* void_b) + 561 23661 : int file_stamp_compare(const void* void_a, const void* void_b) 562 : { - 563 23659 : const struct snapraid_file* file_a = void_a; - 564 23659 : const struct snapraid_file* file_b = void_b; + 563 23661 : const struct snapraid_file* file_a = void_a; + 564 23661 : const struct snapraid_file* file_b = void_b; 565 : - 566 23659 : if (file_a->size < file_b->size) + 566 23661 : if (file_a->size < file_b->size) 567 0 : return -1; - 568 23659 : if (file_a->size > file_b->size) + 568 23661 : if (file_a->size > file_b->size) 569 0 : return 1; 570 : - 571 23659 : if (file_a->mtime_sec < file_b->mtime_sec) + 571 23661 : if (file_a->mtime_sec < file_b->mtime_sec) 572 0 : return -1; - 573 23659 : if (file_a->mtime_sec > file_b->mtime_sec) + 573 23661 : if (file_a->mtime_sec > file_b->mtime_sec) 574 0 : return 1; 575 : - 576 23659 : if (file_a->mtime_nsec < file_b->mtime_nsec) + 576 23661 : if (file_a->mtime_nsec < file_b->mtime_nsec) 577 0 : return -1; - 578 23659 : if (file_a->mtime_nsec > file_b->mtime_nsec) + 578 23661 : if (file_a->mtime_nsec > file_b->mtime_nsec) 579 0 : return 1; 580 : - 581 23659 : return 0; + 581 23661 : return 0; 582 : } 583 : - 584 23954 : int file_namestamp_compare(const void* void_a, const void* void_b) + 584 23997 : int file_namestamp_compare(const void* void_a, const void* void_b) 585 : { 586 : int ret; 587 : - 588 23954 : ret = file_name_compare(void_a, void_b); - 589 23954 : if (ret != 0) - 590 295 : return ret; + 588 23997 : ret = file_name_compare(void_a, void_b); + 589 23997 : if (ret != 0) + 590 336 : return ret; 591 : - 592 23659 : return file_stamp_compare(void_a, void_b); + 592 23661 : return file_stamp_compare(void_a, void_b); 593 : } 594 : 595 0 : int file_pathstamp_compare(const void* void_a, const void* void_b) @@ -665,93 +665,93 @@ 603 0 : return file_stamp_compare(void_a, void_b); 604 : } 605 : - 606 3607761 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) + 606 3657427 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) 607 : { 608 : struct snapraid_chunk* chunk; 609 : - 610 3607761 : if (count == 0) { + 610 3657427 : if (count == 0) { 611 : /* LCOV_EXCL_START */ 612 : log_fatal("Internal inconsistency when allocating empty chunk for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); - 613 : exit(EXIT_FAILURE); + 613 : os_abort(); 614 : /* LCOV_EXCL_STOP */ 615 : } - 616 3607761 : if (file_pos + count > file->blockmax) { + 616 3657427 : if (file_pos + count > file->blockmax) { 617 : /* LCOV_EXCL_START */ 618 : log_fatal("Internal inconsistency when allocating overflowing chunk for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax); - 619 : exit(EXIT_FAILURE); + 619 : os_abort(); 620 : /* LCOV_EXCL_STOP */ 621 : } 622 : - 623 3607761 : chunk = malloc_nofail(sizeof(struct snapraid_chunk)); - 624 3607761 : chunk->parity_pos = parity_pos; - 625 3607761 : chunk->file = file; - 626 3607761 : chunk->file_pos = file_pos; - 627 3607761 : chunk->count = count; + 623 3657427 : chunk = malloc_nofail(sizeof(struct snapraid_chunk)); + 624 3657427 : chunk->parity_pos = parity_pos; + 625 3657427 : chunk->file = file; + 626 3657427 : chunk->file_pos = file_pos; + 627 3657427 : chunk->count = count; 628 : - 629 3607761 : return chunk; + 629 3657427 : return chunk; 630 : } 631 : - 632 3437520 : void chunk_free(struct snapraid_chunk* chunk) + 632 3486903 : void chunk_free(struct snapraid_chunk* chunk) 633 : { - 634 3437520 : free(chunk); - 635 3437520 : } + 634 3486903 : free(chunk); + 635 3486903 : } 636 : - 637 43029600 : int chunk_parity_compare(const void* void_a, const void* void_b) + 637 43351652 : int chunk_parity_compare(const void* void_a, const void* void_b) 638 : { - 639 43029600 : const struct snapraid_chunk* arg_a = void_a; - 640 43029600 : const struct snapraid_chunk* arg_b = void_b; + 639 43351652 : const struct snapraid_chunk* arg_a = void_a; + 640 43351652 : const struct snapraid_chunk* arg_b = void_b; 641 : - 642 43029600 : if (arg_a->parity_pos < arg_b->parity_pos) - 643 932908 : return -1; - 644 42096692 : if (arg_a->parity_pos > arg_b->parity_pos) - 645 42057855 : return 1; + 642 43351652 : if (arg_a->parity_pos < arg_b->parity_pos) + 643 2220745 : return -1; + 644 41130907 : if (arg_a->parity_pos > arg_b->parity_pos) + 645 41089282 : return 1; 646 : - 647 38837 : return 0; + 647 41625 : return 0; 648 : } 649 : - 650 43527418 : int chunk_file_compare(const void* void_a, const void* void_b) + 650 44153325 : int chunk_file_compare(const void* void_a, const void* void_b) 651 : { - 652 43527418 : const struct snapraid_chunk* arg_a = void_a; - 653 43527418 : const struct snapraid_chunk* arg_b = void_b; + 652 44153325 : const struct snapraid_chunk* arg_a = void_a; + 653 44153325 : const struct snapraid_chunk* arg_b = void_b; 654 : - 655 43527418 : if (arg_a->file < arg_b->file) - 656 856585 : return -1; - 657 42670833 : if (arg_a->file > arg_b->file) - 658 42601978 : return 1; + 655 44153325 : if (arg_a->file < arg_b->file) + 656 875219 : return -1; + 657 43278106 : if (arg_a->file > arg_b->file) + 658 43205895 : return 1; 659 : - 660 68855 : if (arg_a->file_pos < arg_b->file_pos) - 661 192 : return -1; - 662 68663 : if (arg_a->file_pos > arg_b->file_pos) - 663 29826 : return 1; + 660 72211 : if (arg_a->file_pos < arg_b->file_pos) + 661 194 : return -1; + 662 72017 : if (arg_a->file_pos > arg_b->file_pos) + 663 30392 : return 1; 664 : - 665 38837 : return 0; + 665 41625 : return 0; 666 : } 667 : - 668 115419 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag) + 668 116876 : struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag) 669 : { 670 : struct snapraid_link* slink; 671 : - 672 115419 : slink = malloc_nofail(sizeof(struct snapraid_link)); - 673 115419 : slink->sub = strdup_nofail(sub); - 674 115419 : slink->linkto = strdup_nofail(linkto); - 675 115419 : slink->flag = link_flag; + 672 116876 : slink = malloc_nofail(sizeof(struct snapraid_link)); + 673 116876 : slink->sub = strdup_nofail(sub); + 674 116876 : slink->linkto = strdup_nofail(linkto); + 675 116876 : slink->flag = link_flag; 676 : - 677 115419 : return slink; + 677 116876 : return slink; 678 : } 679 : - 680 109621 : void link_free(struct snapraid_link* slink) + 680 111078 : void link_free(struct snapraid_link* slink) 681 : { - 682 109621 : free(slink->sub); - 683 109621 : free(slink->linkto); - 684 109621 : free(slink); - 685 109621 : } + 682 111078 : free(slink->sub); + 683 111078 : free(slink->linkto); + 684 111078 : free(slink); + 685 111078 : } 686 : - 687 30380 : int link_name_compare_to_arg(const void* void_arg, const void* void_data) + 687 31837 : int link_name_compare_to_arg(const void* void_arg, const void* void_data) 688 : { - 689 30380 : const char* arg = void_arg; - 690 30380 : const struct snapraid_link* slink = void_data; + 689 31837 : const char* arg = void_arg; + 690 31837 : const struct snapraid_link* slink = void_data; 691 : - 692 30380 : return strcmp(arg, slink->sub); + 692 31837 : return strcmp(arg, slink->sub); 693 : } 694 : 695 1249 : int link_alpha_compare(const void* void_a, const void* void_b) @@ -762,643 +762,644 @@ 700 1249 : return strcmp(slink_a->sub, slink_b->sub); 701 : } 702 : - 703 760 : struct snapraid_dir* dir_alloc(const char* sub) + 703 772 : struct snapraid_dir* dir_alloc(const char* sub) 704 : { 705 : struct snapraid_dir* dir; 706 : - 707 760 : dir = malloc_nofail(sizeof(struct snapraid_dir)); - 708 760 : dir->sub = strdup_nofail(sub); - 709 760 : dir->flag = 0; + 707 772 : dir = malloc_nofail(sizeof(struct snapraid_dir)); + 708 772 : dir->sub = strdup_nofail(sub); + 709 772 : dir->flag = 0; 710 : - 711 760 : return dir; + 711 772 : return dir; 712 : } 713 : - 714 712 : void dir_free(struct snapraid_dir* dir) + 714 724 : void dir_free(struct snapraid_dir* dir) 715 : { - 716 712 : free(dir->sub); - 717 712 : free(dir); - 718 712 : } + 716 724 : free(dir->sub); + 717 724 : free(dir); + 718 724 : } 719 : - 720 217 : int dir_name_compare(const void* void_arg, const void* void_data) + 720 229 : int dir_name_compare(const void* void_arg, const void* void_data) 721 : { - 722 217 : const char* arg = void_arg; - 723 217 : const struct snapraid_dir* dir = void_data; + 722 229 : const char* arg = void_arg; + 723 229 : const struct snapraid_dir* dir = void_data; 724 : - 725 217 : return strcmp(arg, dir->sub); + 725 229 : return strcmp(arg, dir->sub); 726 : } 727 : - 728 1477 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip) + 728 1525 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip) 729 : { 730 : struct snapraid_disk* disk; 731 : - 732 1477 : disk = malloc_nofail(sizeof(struct snapraid_disk)); - 733 1477 : pathcpy(disk->name, sizeof(disk->name), name); - 734 1477 : pathimport(disk->dir, sizeof(disk->dir), dir); - 735 : - 736 : /* ensure that the dir terminate with "/" if it isn't empty */ - 737 1477 : pathslash(disk->dir, sizeof(disk->dir)); - 738 : - 739 1477 : disk->smartctl[0] = 0; - 740 1477 : disk->device = dev; - 741 1477 : disk->tick = 0; - 742 1477 : disk->total_blocks = 0; - 743 1477 : disk->free_blocks = 0; - 744 1477 : disk->first_free_block = 0; - 745 1477 : disk->has_volatile_inodes = 0; - 746 1477 : disk->has_unreliable_physical = 0; - 747 1477 : disk->has_different_uuid = 0; - 748 1477 : disk->has_unsupported_uuid = 0; - 749 1477 : disk->had_empty_uuid = 0; - 750 1477 : disk->mapping_idx = -1; - 751 1477 : disk->skip_access = skip; - 752 1477 : tommy_list_init(&disk->filelist); - 753 1477 : tommy_list_init(&disk->deletedlist); - 754 1477 : tommy_hashdyn_init(&disk->inodeset); - 755 1477 : tommy_hashdyn_init(&disk->pathset); - 756 1477 : tommy_hashdyn_init(&disk->stampset); - 757 1477 : tommy_list_init(&disk->linklist); - 758 1477 : tommy_hashdyn_init(&disk->linkset); - 759 1477 : tommy_list_init(&disk->dirlist); - 760 1477 : tommy_hashdyn_init(&disk->dirset); - 761 1477 : tommy_tree_init(&disk->fs_parity, chunk_parity_compare); - 762 1477 : tommy_tree_init(&disk->fs_file, chunk_file_compare); - 763 1477 : disk->fs_last = 0; - 764 : - 765 1477 : return disk; - 766 : } - 767 : - 768 1351 : void disk_free(struct snapraid_disk* disk) - 769 : { - 770 1351 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free); - 771 1351 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free); - 772 1351 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)chunk_free); - 773 1351 : tommy_hashdyn_done(&disk->inodeset); - 774 1351 : tommy_hashdyn_done(&disk->pathset); - 775 1351 : tommy_hashdyn_done(&disk->stampset); - 776 1351 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free); - 777 1351 : tommy_hashdyn_done(&disk->linkset); - 778 1351 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); - 779 1351 : tommy_hashdyn_done(&disk->dirset); - 780 1351 : free(disk); - 781 1351 : } - 782 : - 783 : struct chunk_disk_empty { - 784 : block_off_t blockmax; - 785 : }; - 786 : - 787 : /** - 788 : * Compare the chunk if inside the specified blockmax. - 789 : */ - 790 10 : static int chunk_disk_empty_compare(const void* void_a, const void* void_b) - 791 : { - 792 10 : const struct chunk_disk_empty* arg_a = void_a; - 793 10 : const struct snapraid_chunk* arg_b = void_b; - 794 : - 795 : /* if the block is inside the specified blockmax, it's found */ - 796 10 : if (arg_a->blockmax > arg_b->parity_pos) - 797 5 : return 0; - 798 : - 799 : /* otherwise search for a smaller one */ - 800 5 : return -1; - 801 : } - 802 : - 803 804 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax) - 804 : { - 805 804 : struct chunk_disk_empty arg = { blockmax }; - 806 : - 807 : /* if there is an element, it's not empty */ - 808 : /* even if links and dirs have no block allocation */ - 809 804 : if (!tommy_list_empty(&disk->filelist)) - 810 736 : return 0; - 811 68 : if (!tommy_list_empty(&disk->linklist)) - 812 0 : return 0; - 813 68 : if (!tommy_list_empty(&disk->dirlist)) - 814 0 : return 0; - 815 : - 816 : /* search for any chunk inside blockmax */ - 817 68 : if (tommy_tree_search_compare(&disk->fs_parity, chunk_disk_empty_compare, &arg) != 0) - 818 5 : return 0; - 819 : - 820 : /* finally, it's empty */ - 821 63 : return 1; - 822 : } - 823 : - 824 : struct chunk_disk_size { - 825 : block_off_t size; - 826 : }; - 827 : - 828 : /** - 829 : * Compare the chunk by highest parity position. - 830 : * - 831 : * The maximum parity position is stored as size. - 832 : */ - 833 47779 : static int chunk_disk_size_compare(const void* void_a, const void* void_b) - 834 : { - 835 47779 : struct chunk_disk_size* arg_a = (void*)void_a; - 836 47779 : const struct snapraid_chunk* arg_b = void_b; - 837 : - 838 : /* get the maximum size */ - 839 47779 : if (arg_a->size < arg_b->parity_pos + arg_b->count) - 840 47779 : arg_a->size = arg_b->parity_pos + arg_b->count; - 841 : - 842 : /* search always for a bigger one */ - 843 47779 : return 1; - 844 : } - 845 : - 846 3955 : block_off_t disk_size(struct snapraid_disk* disk) - 847 : { - 848 3955 : struct chunk_disk_size arg = { 0 }; - 849 3955 : tommy_tree_search_compare(&disk->fs_parity, chunk_disk_size_compare, &arg); - 850 3955 : return arg.size; - 851 : } - 852 : - 853 : struct chunk_check { - 854 : const struct snapraid_chunk* prev; - 855 : int result; - 856 : }; - 857 : - 858 6291380 : void chunk_parity_check_foreach(void* void_arg, void* void_obj) - 859 : { - 860 6291380 : struct chunk_check* arg = void_arg; - 861 6291380 : const struct snapraid_chunk* obj = void_obj; - 862 6291380 : const struct snapraid_chunk* prev = arg->prev; - 863 : - 864 : /* set the next previous block */ - 865 6291380 : arg->prev = obj; - 866 : - 867 : /* stop reporting if too many errors */ - 868 6291380 : if (arg->result > 100) { - 869 : /* LCOV_EXCL_START */ - 870 : return; - 871 : /* LCOV_EXCL_STOP */ - 872 : } - 873 : - 874 6291380 : if (obj->count == 0) { - 875 : /* LCOV_EXCL_START */ - 876 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n", - 877 : obj->file->sub, obj->parity_pos); - 878 : ++arg->result; - 879 : return; - 880 : /* LCOV_EXCL_STOP */ - 881 : } - 882 : - 883 : /* check only if there is a previous block */ - 884 6291380 : if (!prev) - 885 2473 : return; - 886 : - 887 : /* check the order */ - 888 6288907 : if (prev->parity_pos >= obj->parity_pos) { - 889 : /* LCOV_EXCL_START */ - 890 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", - 891 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); - 892 : ++arg->result; - 893 : return; - 894 : /* LCOV_EXCL_STOP */ - 895 : } - 896 : - 897 : /* check that the chunks don't overlap */ - 898 6288907 : if (prev->parity_pos + prev->count > obj->parity_pos) { - 899 : /* LCOV_EXCL_START */ - 900 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", - 901 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); - 902 : ++arg->result; - 903 : return; - 904 : /* LCOV_EXCL_STOP */ - 905 : } - 906 : } - 907 : - 908 6291380 : void chunk_file_check_foreach(void* void_arg, void* void_obj) - 909 : { - 910 6291380 : struct chunk_check* arg = void_arg; - 911 6291380 : const struct snapraid_chunk* obj = void_obj; - 912 6291380 : const struct snapraid_chunk* prev = arg->prev; - 913 : - 914 : /* set the next previous block */ - 915 6291380 : arg->prev = obj; - 916 : - 917 : /* stop reporting if too many errors */ - 918 6291380 : if (arg->result > 100) { - 919 : /* LCOV_EXCL_START */ - 920 : return; - 921 : /* LCOV_EXCL_STOP */ - 922 : } - 923 : - 924 6291380 : if (obj->count == 0) { - 925 : /* LCOV_EXCL_START */ - 926 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n", - 927 : obj->file->sub, obj->file_pos); - 928 : ++arg->result; - 929 : return; - 930 : /* LCOV_EXCL_STOP */ - 931 : } - 932 : - 933 : /* note that for deleted files, some chunks may be missing */ - 934 : - 935 : /* if the files are different */ - 936 6291380 : if (!prev || prev->file != obj->file) { - 937 6247390 : if (prev != 0) { - 938 6244917 : if (file_flag_has(prev->file, FILE_IS_DELETED)) { - 939 : /* check that the chunk doesn't overflow the file */ - 940 59701 : if (prev->file_pos + prev->count > prev->file->blockmax) { - 941 : /* LCOV_EXCL_START */ - 942 : log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n", - 943 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); - 944 : ++arg->result; - 945 : return; - 946 : /* LCOV_EXCL_STOP */ - 947 : } - 948 : } else { - 949 : /* check that the chunk ends the file */ - 950 6185216 : if (prev->file_pos + prev->count != prev->file->blockmax) { - 951 : /* LCOV_EXCL_START */ - 952 : log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n", - 953 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); - 954 : ++arg->result; - 955 : return; - 956 : /* LCOV_EXCL_STOP */ - 957 : } - 958 : } - 959 : } - 960 : - 961 12494780 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { - 962 : /* check that the chunk doesn't overflow the file */ - 963 59776 : if (obj->file_pos + obj->count > obj->file->blockmax) { - 964 : /* LCOV_EXCL_START */ - 965 : log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n", - 966 : obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax); - 967 : ++arg->result; - 968 : return; - 969 : /* LCOV_EXCL_STOP */ - 970 : } - 971 : } else { - 972 : /* check that the chunk starts the file */ - 973 6187614 : if (obj->file_pos != 0) { - 974 : /* LCOV_EXCL_START */ - 975 : log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n", - 976 : obj->file->sub, obj->file_pos, obj->count); - 977 : ++arg->result; - 978 : return; - 979 : /* LCOV_EXCL_STOP */ - 980 : } - 981 : } - 982 : } else { - 983 : /* check the order */ - 984 43990 : if (prev->file_pos >= obj->file_pos) { - 985 : /* LCOV_EXCL_START */ - 986 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n", - 987 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); - 988 : ++arg->result; - 989 : return; - 990 : /* LCOV_EXCL_STOP */ - 991 : } - 992 : - 993 43990 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { - 994 : /* check that the chunks don't overlap */ - 995 27 : if (prev->file_pos + prev->count > obj->file_pos) { - 996 : /* LCOV_EXCL_START */ - 997 : log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n", - 998 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); - 999 : ++arg->result; - 1000 : return; - 1001 : /* LCOV_EXCL_STOP */ - 1002 : } - 1003 : } else { - 1004 : /* check that the chunks are sequential */ - 1005 43963 : if (prev->file_pos + prev->count != obj->file_pos) { - 1006 : /* LCOV_EXCL_START */ - 1007 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n", - 1008 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); - 1009 : ++arg->result; - 1010 : return; - 1011 : /* LCOV_EXCL_STOP */ - 1012 : } - 1013 : } - 1014 : } - 1015 : } - 1016 : - 1017 2676 : int fs_check(struct snapraid_disk* disk) - 1018 : { - 1019 : struct chunk_check arg; - 1020 : - 1021 : /* error count starts from 0 */ - 1022 2676 : arg.result = 0; - 1023 : - 1024 : /* check parity sequence */ - 1025 2676 : arg.prev = 0; - 1026 2676 : tommy_tree_foreach_arg(&disk->fs_parity, chunk_parity_check_foreach, &arg); - 1027 : - 1028 : /* check file sequence */ - 1029 2676 : arg.prev = 0; - 1030 2676 : tommy_tree_foreach_arg(&disk->fs_file, chunk_file_check_foreach, &arg); - 1031 : - 1032 2676 : if (arg.result != 0) - 1033 0 : return -1; - 1034 : - 1035 2676 : return 0; - 1036 : } - 1037 : - 1038 : struct chunk_parity_inside { - 1039 : block_off_t parity_pos; - 1040 : }; - 1041 : - 1042 : /** - 1043 : * Compare the chunk if containing the specified parity position. - 1044 : */ - 1045 211700412 : static int chunk_parity_inside_compare(const void* void_a, const void* void_b) - 1046 : { - 1047 211700412 : const struct chunk_parity_inside* arg_a = void_a; - 1048 211700412 : const struct snapraid_chunk* arg_b = void_b; - 1049 : - 1050 211700412 : if (arg_a->parity_pos < arg_b->parity_pos) - 1051 78963776 : return -1; - 1052 132736636 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) - 1053 115362811 : return 1; - 1054 : - 1055 17373825 : return 0; - 1056 : } - 1057 : - 1058 : /** - 1059 : * Seach the chunk at the specified parity position. - 1060 : * The search is optimized for sequential accesses. - 1061 : * \return If not found return 0 - 1062 : */ - 1063 62562730 : static struct snapraid_chunk* fs_par2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos) - 1064 : { - 1065 : struct snapraid_chunk* chunk; - 1066 : - 1067 : /* check if the last accessed chunk matches */ - 1068 62562730 : if (*fs_last - 1069 62828537 : && parity_pos >= (*fs_last)->parity_pos - 1070 62678201 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count - 1071 : ) { - 1072 43113171 : chunk = *fs_last; - 1073 : } else { - 1074 19449559 : struct chunk_parity_inside arg = { parity_pos }; - 1075 19449559 : chunk = tommy_tree_search_compare(&disk->fs_parity, chunk_parity_inside_compare, &arg); - 1076 : } - 1077 : - 1078 62800800 : if (!chunk) - 1079 2351363 : return 0; - 1080 : - 1081 : /* store the last accessed chunk */ - 1082 60449437 : *fs_last = chunk; - 1083 : - 1084 60449437 : return chunk; - 1085 : } - 1086 : - 1087 : struct chunk_file_inside { - 1088 : struct snapraid_file* file; - 1089 : block_off_t file_pos; - 1090 : }; - 1091 : - 1092 : /** - 1093 : * Compare the chunk if containing the specified file position. - 1094 : */ - 1095 123424429 : static int chunk_file_inside_compare(const void* void_a, const void* void_b) - 1096 : { - 1097 123424429 : const struct chunk_file_inside* arg_a = void_a; - 1098 123424429 : const struct snapraid_chunk* arg_b = void_b; - 1099 : - 1100 123424429 : if (arg_a->file < arg_b->file) - 1101 52876931 : return -1; - 1102 70547498 : if (arg_a->file > arg_b->file) - 1103 58630297 : return 1; - 1104 : - 1105 11917201 : if (arg_a->file_pos < arg_b->file_pos) - 1106 49120 : return -1; - 1107 11868081 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) - 1108 44006 : return 1; - 1109 : - 1110 11824075 : return 0; - 1111 : } - 1112 : - 1113 : /** - 1114 : * Seach the chunk at the specified file position. - 1115 : * The search is optimized for sequential accesses. - 1116 : * \return If not found return 0 - 1117 : */ - 1118 34157182 : static struct snapraid_chunk* fs_file2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos) - 1119 : { - 1120 : struct snapraid_chunk* chunk; - 1121 : - 1122 : /* check if the last accessed chunk matches */ - 1123 34157182 : if (*fs_last - 1124 34107260 : && file == (*fs_last)->file - 1125 22496891 : && file_pos >= (*fs_last)->file_pos - 1126 22481340 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count - 1127 : ) { - 1128 22376150 : chunk = *fs_last; - 1129 : } else { - 1130 11781032 : struct chunk_file_inside arg = { file, file_pos }; - 1131 11781032 : chunk = tommy_tree_search_compare(&disk->fs_file, chunk_file_inside_compare, &arg); - 1132 : } - 1133 : - 1134 34132437 : if (!chunk) - 1135 0 : return 0; - 1136 : - 1137 : /* store the last accessed chunk */ - 1138 34132437 : *fs_last = chunk; - 1139 : - 1140 34132437 : return chunk; - 1141 : } - 1142 : - 1143 62671366 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos) - 1144 : { - 1145 : struct snapraid_chunk* chunk; - 1146 : - 1147 62671366 : chunk = fs_par2chunk_get_ts(disk, fs_last, parity_pos); - 1148 62750330 : if (!chunk) - 1149 2351221 : return 0; - 1150 : - 1151 60399109 : if (file_pos) - 1152 59839728 : *file_pos = chunk->file_pos + (parity_pos - chunk->parity_pos); - 1153 : - 1154 60399109 : return chunk->file; - 1155 : } - 1156 : - 1157 28740730 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos) - 1158 : { - 1159 : struct snapraid_chunk* chunk; - 1160 : - 1161 28740730 : chunk = fs_file2chunk_get_ts(disk, fs_last, file, file_pos); - 1162 28850478 : if (!chunk) { - 1163 : /* LCOV_EXCL_START */ - 1164 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); - 1165 : exit(EXIT_FAILURE); - 1166 : /* LCOV_EXCL_STOP */ - 1167 : } - 1168 : - 1169 28850478 : return chunk->parity_pos + (file_pos - chunk->file_pos); - 1170 : } - 1171 : - 1172 8849850 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) - 1173 : { - 1174 : struct snapraid_chunk* chunk; - 1175 : struct snapraid_chunk* parity_chunk; - 1176 : struct snapraid_chunk* file_chunk; - 1177 : - 1178 8849850 : if (file_pos > 0) { - 1179 : /* search an existing chunk for the previous file_pos */ - 1180 5267799 : chunk = fs_file2chunk_get_ts(disk, &disk->fs_last, file, file_pos - 1); - 1181 : - 1182 5267799 : if (chunk != 0 && parity_pos == chunk->parity_pos + chunk->count) { - 1183 : /* ensure that we are extending the chunk at the end */ - 1184 5242090 : if (file_pos != chunk->file_pos + chunk->count) { - 1185 : /* LCOV_EXCL_START */ - 1186 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); - 1187 : exit(EXIT_FAILURE); - 1188 : /* LCOV_EXCL_STOP */ - 1189 : } - 1190 : - 1191 : /* extend the existing chunk */ - 1192 5242090 : ++chunk->count; - 1193 : - 1194 14091940 : return; - 1195 : } - 1196 : } - 1197 : - 1198 : /* a chunk doesn't exist, and we have to create a new one */ - 1199 3607760 : chunk = chunk_alloc(parity_pos, file, file_pos, 1); - 1200 : - 1201 : /* insert the chunk in the trees */ - 1202 3607760 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &chunk->parity_node, chunk); - 1203 3607760 : file_chunk = tommy_tree_insert(&disk->fs_file, &chunk->file_node, chunk); - 1204 : - 1205 3607760 : if (parity_chunk != chunk || file_chunk != chunk) { - 1206 : /* LCOV_EXCL_START */ - 1207 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); - 1208 : exit(EXIT_FAILURE); - 1209 : /* LCOV_EXCL_STOP */ - 1210 : } - 1211 : - 1212 : /* store the last accessed chunk */ - 1213 3607760 : disk->fs_last = chunk; - 1214 : } - 1215 : - 1216 104155 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) - 1217 : { - 1218 : struct snapraid_chunk* chunk; - 1219 : struct snapraid_chunk* second_chunk; - 1220 : struct snapraid_chunk* parity_chunk; - 1221 : struct snapraid_chunk* file_chunk; - 1222 : block_off_t first_count, second_count; - 1223 : - 1224 104155 : chunk = fs_par2chunk_get_ts(disk, &disk->fs_last, parity_pos); - 1225 104155 : if (!chunk) { - 1226 : /* LCOV_EXCL_START */ - 1227 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name); - 1228 : exit(EXIT_FAILURE); - 1229 : /* LCOV_EXCL_STOP */ - 1230 : } - 1231 : - 1232 : /* if it's the only block of the chunk, delete it */ - 1233 104155 : if (chunk->count == 1) { - 1234 : /* remove from the trees */ - 1235 38837 : tommy_tree_remove(&disk->fs_parity, chunk); - 1236 38837 : tommy_tree_remove(&disk->fs_file, chunk); - 1237 : - 1238 : /* deallocate */ - 1239 38837 : chunk_free(chunk); - 1240 : - 1241 : /* clear the last accessed chunk */ - 1242 38837 : disk->fs_last = 0; - 1243 38837 : return; - 1244 : } - 1245 : - 1246 : /* if it's at the start of the chunk, shrink the chunk */ - 1247 65318 : if (parity_pos == chunk->parity_pos) { - 1248 65316 : ++chunk->parity_pos; - 1249 65316 : ++chunk->file_pos; - 1250 65316 : --chunk->count; - 1251 65316 : return; - 1252 : } - 1253 : - 1254 : /* if it's at the end of the chunk, shrink the chunk */ - 1255 2 : if (parity_pos == chunk->parity_pos + chunk->count - 1) { - 1256 1 : --chunk->count; - 1257 1 : return; - 1258 : } - 1259 : - 1260 : /* otherwise it's in the middle */ - 1261 1 : first_count = parity_pos - chunk->parity_pos; - 1262 1 : second_count = chunk->count - first_count - 1; - 1263 : - 1264 : /* adjust the first chunk */ - 1265 1 : chunk->count = first_count; - 1266 : - 1267 : /* allocate the second chunk */ - 1268 1 : second_chunk = chunk_alloc(chunk->parity_pos + first_count + 1, chunk->file, chunk->file_pos + first_count + 1, second_count); - 1269 : - 1270 : /* insert the chunk in the trees */ - 1271 1 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &second_chunk->parity_node, second_chunk); - 1272 1 : file_chunk = tommy_tree_insert(&disk->fs_file, &second_chunk->file_node, second_chunk); - 1273 : - 1274 1 : if (parity_chunk != second_chunk || file_chunk != second_chunk) { - 1275 : /* LCOV_EXCL_START */ - 1276 : log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name); - 1277 : exit(EXIT_FAILURE); - 1278 : /* LCOV_EXCL_STOP */ - 1279 : } - 1280 : - 1281 : /* store the last accessed chunk */ - 1282 1 : disk->fs_last = second_chunk; - 1283 : } - 1284 : - 1285 112904165 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) - 1286 : { - 1287 112904165 : if (file_pos >= file->blockmax) { - 1288 : /* LCOV_EXCL_START */ - 1289 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); - 1290 : exit(EXIT_FAILURE); - 1291 : /* LCOV_EXCL_STOP */ - 1292 : } - 1293 : - 1294 112904165 : return &file->blockvec[file_pos]; - 1295 : } - 1296 : - 1297 51148943 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos) - 1298 : { - 1299 : struct snapraid_file* file; - 1300 : block_off_t file_pos; - 1301 : - 1302 51148943 : file = fs_par2file_get_ts(disk, fs_last, parity_pos, &file_pos); - 1303 : - 1304 51044271 : if (!file) - 1305 2337947 : return BLOCK_EMPTY; - 1306 : - 1307 48706324 : return fs_file2block_get(file, file_pos); - 1308 : } - 1309 : - 1310 1447 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid) - 1311 : { - 1312 : struct snapraid_map* map; - 1313 : - 1314 1447 : map = malloc_nofail(sizeof(struct snapraid_map)); - 1315 1447 : pathcpy(map->name, sizeof(map->name), name); - 1316 1447 : map->position = position; - 1317 1447 : map->total_blocks = total_blocks; - 1318 1447 : map->free_blocks = free_blocks; - 1319 1447 : pathcpy(map->uuid, sizeof(map->uuid), uuid); - 1320 : - 1321 1447 : return map; - 1322 : } - 1323 : - 1324 1327 : void map_free(struct snapraid_map* map) - 1325 : { - 1326 1327 : free(map); - 1327 1327 : } - 1328 : - 1329 743492 : int time_compare(const void* void_a, const void* void_b) - 1330 : { - 1331 743492 : const time_t* time_a = void_a; - 1332 743492 : const time_t* time_b = void_b; - 1333 : - 1334 743492 : if (*time_a < *time_b) - 1335 28996 : return -1; - 1336 714496 : if (*time_a > *time_b) - 1337 185655 : return 1; - 1338 528841 : return 0; - 1339 : } + 732 1525 : disk = malloc_nofail(sizeof(struct snapraid_disk)); + 733 1525 : pathcpy(disk->name, sizeof(disk->name), name); + 734 1525 : pathimport(disk->dir, sizeof(disk->dir), dir); + 735 1525 : pathcpy(disk->uuid, sizeof(disk->uuid), uuid); + 736 : + 737 : /* ensure that the dir terminate with "/" if it isn't empty */ + 738 1525 : pathslash(disk->dir, sizeof(disk->dir)); + 739 : + 740 1525 : disk->smartctl[0] = 0; + 741 1525 : disk->device = dev; + 742 1525 : disk->tick = 0; + 743 1525 : disk->total_blocks = 0; + 744 1525 : disk->free_blocks = 0; + 745 1525 : disk->first_free_block = 0; + 746 1525 : disk->has_volatile_inodes = 0; + 747 1525 : disk->has_unreliable_physical = 0; + 748 1525 : disk->has_different_uuid = 0; + 749 1525 : disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */ + 750 1525 : disk->had_empty_uuid = 0; + 751 1525 : disk->mapping_idx = -1; + 752 1525 : disk->skip_access = skip; + 753 1525 : tommy_list_init(&disk->filelist); + 754 1525 : tommy_list_init(&disk->deletedlist); + 755 1525 : tommy_hashdyn_init(&disk->inodeset); + 756 1525 : tommy_hashdyn_init(&disk->pathset); + 757 1525 : tommy_hashdyn_init(&disk->stampset); + 758 1525 : tommy_list_init(&disk->linklist); + 759 1525 : tommy_hashdyn_init(&disk->linkset); + 760 1525 : tommy_list_init(&disk->dirlist); + 761 1525 : tommy_hashdyn_init(&disk->dirset); + 762 1525 : tommy_tree_init(&disk->fs_parity, chunk_parity_compare); + 763 1525 : tommy_tree_init(&disk->fs_file, chunk_file_compare); + 764 1525 : disk->fs_last = 0; + 765 : + 766 1525 : return disk; + 767 : } + 768 : + 769 1399 : void disk_free(struct snapraid_disk* disk) + 770 : { + 771 1399 : tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free); + 772 1399 : tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free); + 773 1399 : tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)chunk_free); + 774 1399 : tommy_hashdyn_done(&disk->inodeset); + 775 1399 : tommy_hashdyn_done(&disk->pathset); + 776 1399 : tommy_hashdyn_done(&disk->stampset); + 777 1399 : tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free); + 778 1399 : tommy_hashdyn_done(&disk->linkset); + 779 1399 : tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); + 780 1399 : tommy_hashdyn_done(&disk->dirset); + 781 1399 : free(disk); + 782 1399 : } + 783 : + 784 : struct chunk_disk_empty { + 785 : block_off_t blockmax; + 786 : }; + 787 : + 788 : /** + 789 : * Compare the chunk if inside the specified blockmax. + 790 : */ + 791 13 : static int chunk_disk_empty_compare(const void* void_a, const void* void_b) + 792 : { + 793 13 : const struct chunk_disk_empty* arg_a = void_a; + 794 13 : const struct snapraid_chunk* arg_b = void_b; + 795 : + 796 : /* if the block is inside the specified blockmax, it's found */ + 797 13 : if (arg_a->blockmax > arg_b->parity_pos) + 798 8 : return 0; + 799 : + 800 : /* otherwise search for a smaller one */ + 801 5 : return -1; + 802 : } + 803 : + 804 870 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax) + 805 : { + 806 870 : struct chunk_disk_empty arg = { blockmax }; + 807 : + 808 : /* if there is an element, it's not empty */ + 809 : /* even if links and dirs have no block allocation */ + 810 870 : if (!tommy_list_empty(&disk->filelist)) + 811 778 : return 0; + 812 92 : if (!tommy_list_empty(&disk->linklist)) + 813 0 : return 0; + 814 92 : if (!tommy_list_empty(&disk->dirlist)) + 815 0 : return 0; + 816 : + 817 : /* search for any chunk inside blockmax */ + 818 92 : if (tommy_tree_search_compare(&disk->fs_parity, chunk_disk_empty_compare, &arg) != 0) + 819 8 : return 0; + 820 : + 821 : /* finally, it's empty */ + 822 84 : return 1; + 823 : } + 824 : + 825 : struct chunk_disk_size { + 826 : block_off_t size; + 827 : }; + 828 : + 829 : /** + 830 : * Compare the chunk by highest parity position. + 831 : * + 832 : * The maximum parity position is stored as size. + 833 : */ + 834 48702 : static int chunk_disk_size_compare(const void* void_a, const void* void_b) + 835 : { + 836 48702 : struct chunk_disk_size* arg_a = (void*)void_a; + 837 48702 : const struct snapraid_chunk* arg_b = void_b; + 838 : + 839 : /* get the maximum size */ + 840 48702 : if (arg_a->size < arg_b->parity_pos + arg_b->count) + 841 48702 : arg_a->size = arg_b->parity_pos + arg_b->count; + 842 : + 843 : /* search always for a bigger one */ + 844 48702 : return 1; + 845 : } + 846 : + 847 4165 : block_off_t disk_size(struct snapraid_disk* disk) + 848 : { + 849 4165 : struct chunk_disk_size arg = { 0 }; + 850 4165 : tommy_tree_search_compare(&disk->fs_parity, chunk_disk_size_compare, &arg); + 851 4165 : return arg.size; + 852 : } + 853 : + 854 : struct chunk_check { + 855 : const struct snapraid_chunk* prev; + 856 : int result; + 857 : }; + 858 : + 859 6441048 : void chunk_parity_check_foreach(void* void_arg, void* void_obj) + 860 : { + 861 6441048 : struct chunk_check* arg = void_arg; + 862 6441048 : const struct snapraid_chunk* obj = void_obj; + 863 6441048 : const struct snapraid_chunk* prev = arg->prev; + 864 : + 865 : /* set the next previous block */ + 866 6441048 : arg->prev = obj; + 867 : + 868 : /* stop reporting if too many errors */ + 869 6441048 : if (arg->result > 100) { + 870 : /* LCOV_EXCL_START */ + 871 : return; + 872 : /* LCOV_EXCL_STOP */ + 873 : } + 874 : + 875 6441048 : if (obj->count == 0) { + 876 : /* LCOV_EXCL_START */ + 877 : log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n", + 878 : obj->file->sub, obj->parity_pos); + 879 : ++arg->result; + 880 : return; + 881 : /* LCOV_EXCL_STOP */ + 882 : } + 883 : + 884 : /* check only if there is a previous block */ + 885 6441048 : if (!prev) + 886 2588 : return; + 887 : + 888 : /* check the order */ + 889 6438460 : if (prev->parity_pos >= obj->parity_pos) { + 890 : /* LCOV_EXCL_START */ + 891 : log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", + 892 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); + 893 : ++arg->result; + 894 : return; + 895 : /* LCOV_EXCL_STOP */ + 896 : } + 897 : + 898 : /* check that the chunks don't overlap */ + 899 6438460 : if (prev->parity_pos + prev->count > obj->parity_pos) { + 900 : /* LCOV_EXCL_START */ + 901 : log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", + 902 : prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); + 903 : ++arg->result; + 904 : return; + 905 : /* LCOV_EXCL_STOP */ + 906 : } + 907 : } + 908 : + 909 6441048 : void chunk_file_check_foreach(void* void_arg, void* void_obj) + 910 : { + 911 6441048 : struct chunk_check* arg = void_arg; + 912 6441048 : const struct snapraid_chunk* obj = void_obj; + 913 6441048 : const struct snapraid_chunk* prev = arg->prev; + 914 : + 915 : /* set the next previous block */ + 916 6441048 : arg->prev = obj; + 917 : + 918 : /* stop reporting if too many errors */ + 919 6441048 : if (arg->result > 100) { + 920 : /* LCOV_EXCL_START */ + 921 : return; + 922 : /* LCOV_EXCL_STOP */ + 923 : } + 924 : + 925 6441048 : if (obj->count == 0) { + 926 : /* LCOV_EXCL_START */ + 927 : log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n", + 928 : obj->file->sub, obj->file_pos); + 929 : ++arg->result; + 930 : return; + 931 : /* LCOV_EXCL_STOP */ + 932 : } + 933 : + 934 : /* note that for deleted files, some chunks may be missing */ + 935 : + 936 : /* if the files are different */ + 937 6441048 : if (!prev || prev->file != obj->file) { + 938 6395699 : if (prev != 0) { + 939 6393111 : if (file_flag_has(prev->file, FILE_IS_DELETED)) { + 940 : /* check that the chunk doesn't overflow the file */ + 941 59771 : if (prev->file_pos + prev->count > prev->file->blockmax) { + 942 : /* LCOV_EXCL_START */ + 943 : log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n", + 944 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); + 945 : ++arg->result; + 946 : return; + 947 : /* LCOV_EXCL_STOP */ + 948 : } + 949 : } else { + 950 : /* check that the chunk ends the file */ + 951 6333340 : if (prev->file_pos + prev->count != prev->file->blockmax) { + 952 : /* LCOV_EXCL_START */ + 953 : log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n", + 954 : prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); + 955 : ++arg->result; + 956 : return; + 957 : /* LCOV_EXCL_STOP */ + 958 : } + 959 : } + 960 : } + 961 : + 962 12791398 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { + 963 : /* check that the chunk doesn't overflow the file */ + 964 59854 : if (obj->file_pos + obj->count > obj->file->blockmax) { + 965 : /* LCOV_EXCL_START */ + 966 : log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n", + 967 : obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax); + 968 : ++arg->result; + 969 : return; + 970 : /* LCOV_EXCL_STOP */ + 971 : } + 972 : } else { + 973 : /* check that the chunk starts the file */ + 974 6335845 : if (obj->file_pos != 0) { + 975 : /* LCOV_EXCL_START */ + 976 : log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n", + 977 : obj->file->sub, obj->file_pos, obj->count); + 978 : ++arg->result; + 979 : return; + 980 : /* LCOV_EXCL_STOP */ + 981 : } + 982 : } + 983 : } else { + 984 : /* check the order */ + 985 45349 : if (prev->file_pos >= obj->file_pos) { + 986 : /* LCOV_EXCL_START */ + 987 : log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n", + 988 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + 989 : ++arg->result; + 990 : return; + 991 : /* LCOV_EXCL_STOP */ + 992 : } + 993 : + 994 45349 : if (file_flag_has(obj->file, FILE_IS_DELETED)) { + 995 : /* check that the chunks don't overlap */ + 996 27 : if (prev->file_pos + prev->count > obj->file_pos) { + 997 : /* LCOV_EXCL_START */ + 998 : log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n", + 999 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + 1000 : ++arg->result; + 1001 : return; + 1002 : /* LCOV_EXCL_STOP */ + 1003 : } + 1004 : } else { + 1005 : /* check that the chunks are sequential */ + 1006 45322 : if (prev->file_pos + prev->count != obj->file_pos) { + 1007 : /* LCOV_EXCL_START */ + 1008 : log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n", + 1009 : prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + 1010 : ++arg->result; + 1011 : return; + 1012 : /* LCOV_EXCL_STOP */ + 1013 : } + 1014 : } + 1015 : } + 1016 : } + 1017 : + 1018 2838 : int fs_check(struct snapraid_disk* disk) + 1019 : { + 1020 : struct chunk_check arg; + 1021 : + 1022 : /* error count starts from 0 */ + 1023 2838 : arg.result = 0; + 1024 : + 1025 : /* check parity sequence */ + 1026 2838 : arg.prev = 0; + 1027 2838 : tommy_tree_foreach_arg(&disk->fs_parity, chunk_parity_check_foreach, &arg); + 1028 : + 1029 : /* check file sequence */ + 1030 2838 : arg.prev = 0; + 1031 2838 : tommy_tree_foreach_arg(&disk->fs_file, chunk_file_check_foreach, &arg); + 1032 : + 1033 2838 : if (arg.result != 0) + 1034 0 : return -1; + 1035 : + 1036 2838 : return 0; + 1037 : } + 1038 : + 1039 : struct chunk_parity_inside { + 1040 : block_off_t parity_pos; + 1041 : }; + 1042 : + 1043 : /** + 1044 : * Compare the chunk if containing the specified parity position. + 1045 : */ + 1046 102351431 : static int chunk_parity_inside_compare(const void* void_a, const void* void_b) + 1047 : { + 1048 102351431 : const struct chunk_parity_inside* arg_a = void_a; + 1049 102351431 : const struct snapraid_chunk* arg_b = void_b; + 1050 : + 1051 102351431 : if (arg_a->parity_pos < arg_b->parity_pos) + 1052 35386523 : return -1; + 1053 66964908 : if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) + 1054 59326333 : return 1; + 1055 : + 1056 7638575 : return 0; + 1057 : } + 1058 : + 1059 : /** + 1060 : * Seach the chunk at the specified parity position. + 1061 : * The search is optimized for sequential accesses. + 1062 : * \return If not found return 0 + 1063 : */ + 1064 38418652 : static struct snapraid_chunk* fs_par2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos) + 1065 : { + 1066 : struct snapraid_chunk* chunk; + 1067 : + 1068 : /* check if the last accessed chunk matches */ + 1069 38418652 : if (*fs_last + 1070 38399475 : && parity_pos >= (*fs_last)->parity_pos + 1071 38241144 : && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count + 1072 : ) { + 1073 29222600 : chunk = *fs_last; + 1074 : } else { + 1075 9196052 : struct chunk_parity_inside arg = { parity_pos }; + 1076 9196052 : chunk = tommy_tree_search_compare(&disk->fs_parity, chunk_parity_inside_compare, &arg); + 1077 : } + 1078 : + 1079 38418652 : if (!chunk) + 1080 1557477 : return 0; + 1081 : + 1082 : /* store the last accessed chunk */ + 1083 36861175 : *fs_last = chunk; + 1084 : + 1085 36861175 : return chunk; + 1086 : } + 1087 : + 1088 : struct chunk_file_inside { + 1089 : struct snapraid_file* file; + 1090 : block_off_t file_pos; + 1091 : }; + 1092 : + 1093 : /** + 1094 : * Compare the chunk if containing the specified file position. + 1095 : */ + 1096 21495373 : static int chunk_file_inside_compare(const void* void_a, const void* void_b) + 1097 : { + 1098 21495373 : const struct chunk_file_inside* arg_a = void_a; + 1099 21495373 : const struct snapraid_chunk* arg_b = void_b; + 1100 : + 1101 21495373 : if (arg_a->file < arg_b->file) + 1102 8992026 : return -1; + 1103 12503347 : if (arg_a->file > arg_b->file) + 1104 10470075 : return 1; + 1105 : + 1106 2033272 : if (arg_a->file_pos < arg_b->file_pos) + 1107 7395 : return -1; + 1108 2025877 : if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) + 1109 9044 : return 1; + 1110 : + 1111 2016833 : return 0; + 1112 : } + 1113 : + 1114 : /** + 1115 : * Search the chunk at the specified file position. + 1116 : * The search is optimized for sequential accesses. + 1117 : * \return If not found return 0 + 1118 : */ + 1119 10223247 : static struct snapraid_chunk* fs_file2chunk_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos) + 1120 : { + 1121 : struct snapraid_chunk* chunk; + 1122 : + 1123 : /* check if the last accessed chunk matches */ + 1124 10223247 : if (*fs_last + 1125 10199301 : && file == (*fs_last)->file + 1126 8220750 : && file_pos >= (*fs_last)->file_pos + 1127 8220750 : && file_pos < (*fs_last)->file_pos + (*fs_last)->count + 1128 : ) { + 1129 8206414 : chunk = *fs_last; + 1130 : } else { + 1131 2016833 : struct chunk_file_inside arg = { file, file_pos }; + 1132 2016833 : chunk = tommy_tree_search_compare(&disk->fs_file, chunk_file_inside_compare, &arg); + 1133 : } + 1134 : + 1135 10223247 : if (!chunk) + 1136 0 : return 0; + 1137 : + 1138 : /* store the last accessed chunk */ + 1139 10223247 : *fs_last = chunk; + 1140 : + 1141 10223247 : return chunk; + 1142 : } + 1143 : + 1144 38311850 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos) + 1145 : { + 1146 : struct snapraid_chunk* chunk; + 1147 : + 1148 38311850 : chunk = fs_par2chunk_get_ts(disk, fs_last, parity_pos); + 1149 38311850 : if (!chunk) + 1150 1557477 : return 0; + 1151 : + 1152 36754373 : if (file_pos) + 1153 36410379 : *file_pos = chunk->file_pos + (parity_pos - chunk->parity_pos); + 1154 : + 1155 36754373 : return chunk->file; + 1156 : } + 1157 : + 1158 4878725 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos) + 1159 : { + 1160 : struct snapraid_chunk* chunk; + 1161 : + 1162 4878725 : chunk = fs_file2chunk_get_ts(disk, fs_last, file, file_pos); + 1163 4878725 : if (!chunk) { + 1164 : /* LCOV_EXCL_START */ + 1165 : log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); + 1166 : os_abort(); + 1167 : /* LCOV_EXCL_STOP */ + 1168 : } + 1169 : + 1170 4878725 : return chunk->parity_pos + (file_pos - chunk->file_pos); + 1171 : } + 1172 : + 1173 8975787 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) + 1174 : { + 1175 : struct snapraid_chunk* chunk; + 1176 : struct snapraid_chunk* parity_chunk; + 1177 : struct snapraid_chunk* file_chunk; + 1178 : + 1179 8975787 : if (file_pos > 0) { + 1180 : /* search an existing chunk for the previous file_pos */ + 1181 5344522 : chunk = fs_file2chunk_get_ts(disk, &disk->fs_last, file, file_pos - 1); + 1182 : + 1183 5344522 : if (chunk != 0 && parity_pos == chunk->parity_pos + chunk->count) { + 1184 : /* ensure that we are extending the chunk at the end */ + 1185 5318361 : if (file_pos != chunk->file_pos + chunk->count) { + 1186 : /* LCOV_EXCL_START */ + 1187 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); + 1188 : os_abort(); + 1189 : /* LCOV_EXCL_STOP */ + 1190 : } + 1191 : + 1192 : /* extend the existing chunk */ + 1193 5318361 : ++chunk->count; + 1194 : + 1195 14294148 : return; + 1196 : } + 1197 : } + 1198 : + 1199 : /* a chunk doesn't exist, and we have to create a new one */ + 1200 3657426 : chunk = chunk_alloc(parity_pos, file, file_pos, 1); + 1201 : + 1202 : /* insert the chunk in the trees */ + 1203 3657426 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &chunk->parity_node, chunk); + 1204 3657426 : file_chunk = tommy_tree_insert(&disk->fs_file, &chunk->file_node, chunk); + 1205 : + 1206 3657426 : if (parity_chunk != chunk || file_chunk != chunk) { + 1207 : /* LCOV_EXCL_START */ + 1208 : log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); + 1209 : os_abort(); + 1210 : /* LCOV_EXCL_STOP */ + 1211 : } + 1212 : + 1213 : /* store the last accessed chunk */ + 1214 3657426 : disk->fs_last = chunk; + 1215 : } + 1216 : + 1217 106802 : void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) + 1218 : { + 1219 : struct snapraid_chunk* chunk; + 1220 : struct snapraid_chunk* second_chunk; + 1221 : struct snapraid_chunk* parity_chunk; + 1222 : struct snapraid_chunk* file_chunk; + 1223 : block_off_t first_count, second_count; + 1224 : + 1225 106802 : chunk = fs_par2chunk_get_ts(disk, &disk->fs_last, parity_pos); + 1226 106802 : if (!chunk) { + 1227 : /* LCOV_EXCL_START */ + 1228 : log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name); + 1229 : os_abort(); + 1230 : /* LCOV_EXCL_STOP */ + 1231 : } + 1232 : + 1233 : /* if it's the only block of the chunk, delete it */ + 1234 106802 : if (chunk->count == 1) { + 1235 : /* remove from the trees */ + 1236 41625 : tommy_tree_remove(&disk->fs_parity, chunk); + 1237 41625 : tommy_tree_remove(&disk->fs_file, chunk); + 1238 : + 1239 : /* deallocate */ + 1240 41625 : chunk_free(chunk); + 1241 : + 1242 : /* clear the last accessed chunk */ + 1243 41625 : disk->fs_last = 0; + 1244 41625 : return; + 1245 : } + 1246 : + 1247 : /* if it's at the start of the chunk, shrink the chunk */ + 1248 65177 : if (parity_pos == chunk->parity_pos) { + 1249 65175 : ++chunk->parity_pos; + 1250 65175 : ++chunk->file_pos; + 1251 65175 : --chunk->count; + 1252 65175 : return; + 1253 : } + 1254 : + 1255 : /* if it's at the end of the chunk, shrink the chunk */ + 1256 2 : if (parity_pos == chunk->parity_pos + chunk->count - 1) { + 1257 1 : --chunk->count; + 1258 1 : return; + 1259 : } + 1260 : + 1261 : /* otherwise it's in the middle */ + 1262 1 : first_count = parity_pos - chunk->parity_pos; + 1263 1 : second_count = chunk->count - first_count - 1; + 1264 : + 1265 : /* adjust the first chunk */ + 1266 1 : chunk->count = first_count; + 1267 : + 1268 : /* allocate the second chunk */ + 1269 1 : second_chunk = chunk_alloc(chunk->parity_pos + first_count + 1, chunk->file, chunk->file_pos + first_count + 1, second_count); + 1270 : + 1271 : /* insert the chunk in the trees */ + 1272 1 : parity_chunk = tommy_tree_insert(&disk->fs_parity, &second_chunk->parity_node, second_chunk); + 1273 1 : file_chunk = tommy_tree_insert(&disk->fs_file, &second_chunk->file_node, second_chunk); + 1274 : + 1275 1 : if (parity_chunk != second_chunk || file_chunk != second_chunk) { + 1276 : /* LCOV_EXCL_START */ + 1277 : log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name); + 1278 : os_abort(); + 1279 : /* LCOV_EXCL_STOP */ + 1280 : } + 1281 : + 1282 : /* store the last accessed chunk */ + 1283 1 : disk->fs_last = second_chunk; + 1284 : } + 1285 : + 1286 44106216 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) + 1287 : { + 1288 44106216 : if (file_pos >= file->blockmax) { + 1289 : /* LCOV_EXCL_START */ + 1290 : log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); + 1291 : os_abort(); + 1292 : /* LCOV_EXCL_STOP */ + 1293 : } + 1294 : + 1295 44106216 : return &file->blockvec[file_pos]; + 1296 : } + 1297 : + 1298 26733115 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos) + 1299 : { + 1300 : struct snapraid_file* file; + 1301 : block_off_t file_pos; + 1302 : + 1303 26733115 : file = fs_par2file_get_ts(disk, fs_last, parity_pos, &file_pos); + 1304 : + 1305 26733115 : if (!file) + 1306 1557477 : return BLOCK_EMPTY; + 1307 : + 1308 25175638 : return fs_file2block_get(file, file_pos); + 1309 : } + 1310 : + 1311 1495 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid) + 1312 : { + 1313 : struct snapraid_map* map; + 1314 : + 1315 1495 : map = malloc_nofail(sizeof(struct snapraid_map)); + 1316 1495 : pathcpy(map->name, sizeof(map->name), name); + 1317 1495 : map->position = position; + 1318 1495 : map->total_blocks = total_blocks; + 1319 1495 : map->free_blocks = free_blocks; + 1320 1495 : pathcpy(map->uuid, sizeof(map->uuid), uuid); + 1321 : + 1322 1495 : return map; + 1323 : } + 1324 : + 1325 1375 : void map_free(struct snapraid_map* map) + 1326 : { + 1327 1375 : free(map); + 1328 1375 : } + 1329 : + 1330 707506 : int time_compare(const void* void_a, const void* void_b) + 1331 : { + 1332 707506 : const time_t* time_a = void_a; + 1333 707506 : const time_t* time_b = void_b; + 1334 : + 1335 707506 : if (*time_a < *time_b) + 1336 26871 : return -1; + 1337 680635 : if (*time_a > *time_b) + 1338 146878 : return 1; + 1339 533757 : return 0; + 1340 : } diff --git a/cov/cmdline/elem.h.func-sort-c.html b/cov/cmdline/elem.h.func-sort-c.html index 2a9ac818..8bc953ab 100644 --- a/cov/cmdline/elem.h.func-sort-c.html +++ b/cov/cmdline/elem.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 39 @@ -60,159 +60,159 @@ Hit count Sort by hit count - block_state_get - 96735410 + block_state_get + 49967196 - file_flag_has - 33299459 + file_flag_has + 33706389 - fs_par2block_get - 21727310 + fs_par2block_get + 22209416 - block_state_set - 18242161 + block_state_set + 18633161 - block_has_file - 12929086 + block_has_file + 13243669 - fs_par2file_get - 11514087 + block_has_invalid_parity + 11837218 - block_has_invalid_parity - 11489174 + fs_par2file_get + 11578735 - info_get - 10573034 + hash_invalid_set + 9036734 - hash_invalid_set - 8910831 + file_stamp_hash + 6198269 - file_stamp_hash - 6139138 + file_flag_set + 5250833 - file_flag_set - 5176917 + info_get + 5104110 - file_inode_hash - 4822298 + file_inode_hash + 4924816 - file_path_hash - 3766623 + file_path_hash + 3815727 - info_get_rehash - 3312725 + filter_hidden + 3114300 - filter_hidden - 3066852 + block_has_past_hash + 2401624 - block_has_past_hash - 2287366 + block_has_updated_hash + 2075259 - info_get_time - 2258078 + info_get_rehash + 2058338 - block_has_updated_hash - 2005171 + info_set + 1639782 - info_get_bad - 1725704 + info_get_time + 890086 - info_set - 1609485 + hash_is_zero + 761026 - info_get_justsynced - 1474627 + hash_is_invalid + 759605 - hash_is_zero - 790275 + fs_file2par_get + 519510 - hash_is_invalid - 776042 + info_get_bad + 338860 - fs_file2par_get - 464306 + block_has_file_and_valid_parity + 257893 - link_flag_get - 410820 + link_flag_has + 205548 - info_make - 394996 + info_make + 174394 - block_has_file_and_valid_parity - 221100 + link_name_hash + 151170 - link_flag_has - 202633 + hash_zero_set + 115487 - hash_zero_set - 153288 + link_flag_get + 89637 - link_name_hash - 148256 + info_get_justsynced + 79285 - hash_is_real - 65785 + hash_is_real + 44133 - link_flag_set - 36114 + link_flag_set + 37571 - file_flag_clear - 14174 + file_flag_clear + 20621 - info_set_rehash - 9199 + info_set_rehash + 9207 - info_set_bad - 1802 + info_set_bad + 1771 - dir_name_hash - 987 + dir_name_hash + 1011 - dir_flag_has - 876 + dir_flag_has + 900 - dir_flag_set - 235 + dir_flag_set + 247 - link_flag_let + link_flag_let 6 diff --git a/cov/cmdline/elem.h.func.html b/cov/cmdline/elem.h.func.html index 8e76d216..d9c2ba6e 100644 --- a/cov/cmdline/elem.h.func.html +++ b/cov/cmdline/elem.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 39 @@ -60,160 +60,160 @@ Hit count Sort by hit count - block_has_file - 12929086 + block_has_file + 13243669 - block_has_file_and_valid_parity - 221100 + block_has_file_and_valid_parity + 257893 - block_has_invalid_parity - 11489174 + block_has_invalid_parity + 11837218 - block_has_past_hash - 2287366 + block_has_past_hash + 2401624 - block_has_updated_hash - 2005171 + block_has_updated_hash + 2075259 - block_state_get - 96735410 + block_state_get + 49967196 - block_state_set - 18242161 + block_state_set + 18633161 - dir_flag_has - 876 + dir_flag_has + 900 - dir_flag_set - 235 + dir_flag_set + 247 - dir_name_hash - 987 + dir_name_hash + 1011 - file_flag_clear - 14174 + file_flag_clear + 20621 - file_flag_has - 33299459 + file_flag_has + 33706389 - file_flag_set - 5176917 + file_flag_set + 5250833 - file_inode_hash - 4822298 + file_inode_hash + 4924816 - file_path_hash - 3766623 + file_path_hash + 3815727 - file_stamp_hash - 6139138 + file_stamp_hash + 6198269 - filter_hidden - 3066852 + filter_hidden + 3114300 - fs_file2par_get - 464306 + fs_file2par_get + 519510 - fs_par2block_get - 21727310 + fs_par2block_get + 22209416 - fs_par2file_get - 11514087 + fs_par2file_get + 11578735 - hash_invalid_set - 8910831 + hash_invalid_set + 9036734 - hash_is_invalid - 776042 + hash_is_invalid + 759605 - hash_is_real - 65785 + hash_is_real + 44133 - hash_is_zero - 790275 + hash_is_zero + 761026 - hash_zero_set - 153288 + hash_zero_set + 115487 - info_get - 10573034 + info_get + 5104110 - info_get_bad - 1725704 + info_get_bad + 338860 - info_get_justsynced - 1474627 + info_get_justsynced + 79285 - info_get_rehash - 3312725 + info_get_rehash + 2058338 - info_get_time - 2258078 + info_get_time + 890086 - info_make - 394996 + info_make + 174394 - info_set - 1609485 + info_set + 1639782 - info_set_bad - 1802 + info_set_bad + 1771 - info_set_rehash - 9199 + info_set_rehash + 9207 - link_flag_get - 410820 + link_flag_get + 89637 - link_flag_has - 202633 + link_flag_has + 205548 - link_flag_let + link_flag_let 6 - link_flag_set - 36114 + link_flag_set + 37571 - link_name_hash - 148256 + link_name_hash + 151170
diff --git a/cov/cmdline/elem.h.gcov.html b/cov/cmdline/elem.h.gcov.html index c8f25c02..e99f6062 100644 --- a/cov/cmdline/elem.h.gcov.html +++ b/cov/cmdline/elem.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 39 @@ -94,1057 +94,1059 @@ 32 : /* snapraid */ 33 : 34 : /** - 35 : * Invalid position. + 35 : * Max UUID length. 36 : */ - 37 : #define POS_INVALID ((block_off_t)-1) + 37 : #define UUID_MAX 128 38 : 39 : /** - 40 : * Basic block position type. - 41 : * With 32 bits and 128k blocks you can address 256 TB. - 42 : */ - 43 : typedef uint32_t block_off_t; - 44 : - 45 : /** - 46 : * Basic data position type. - 47 : * It's signed as file size and offset are usually signed. - 48 : */ - 49 : typedef int64_t data_off_t; - 50 : - 51 : /** - 52 : * Content file specification. + 40 : * Invalid position. + 41 : */ + 42 : #define POS_INVALID ((block_off_t)-1) + 43 : + 44 : /** + 45 : * Basic block position type. + 46 : * With 32 bits and 128k blocks you can address 256 TB. + 47 : */ + 48 : typedef uint32_t block_off_t; + 49 : + 50 : /** + 51 : * Basic data position type. + 52 : * It's signed as file size and offset are usually signed. 53 : */ - 54 : struct snapraid_content { - 55 : char content[PATH_MAX]; /**< Path of the content file. */ - 56 : uint64_t device; /**< Device identifier. */ - 57 : void* context; /**< Context used for multithread operations. */ - 58 : tommy_node node; /**< Next node in the list. */ - 59 : }; - 60 : - 61 : /** - 62 : * Filter for paths. - 63 : */ - 64 : struct snapraid_filter { - 65 : char pattern[PATH_MAX]; /**< Filter pattern. */ - 66 : int is_disk; /**< If the pattern is a disk one. */ - 67 : int is_path; /**< If the pattern is only for the complete path. */ - 68 : int is_dir; /**< If the pattern is only for dir. */ - 69 : int direction; /**< If it's an inclusion (=1) or an exclusion (=-1). */ - 70 : tommy_node node; /**< Next node in the list. */ - 71 : }; - 72 : - 73 : /** - 74 : * Block pointer used to represent unused blocks. - 75 : */ - 76 : #define BLOCK_EMPTY 0 + 54 : typedef int64_t data_off_t; + 55 : + 56 : /** + 57 : * Content file specification. + 58 : */ + 59 : struct snapraid_content { + 60 : char content[PATH_MAX]; /**< Path of the content file. */ + 61 : uint64_t device; /**< Device identifier. */ + 62 : void* context; /**< Context used for multithread operations. */ + 63 : tommy_node node; /**< Next node in the list. */ + 64 : }; + 65 : + 66 : /** + 67 : * Filter for paths. + 68 : */ + 69 : struct snapraid_filter { + 70 : char pattern[PATH_MAX]; /**< Filter pattern. */ + 71 : int is_disk; /**< If the pattern is a disk one. */ + 72 : int is_path; /**< If the pattern is only for the complete path. */ + 73 : int is_dir; /**< If the pattern is only for dir. */ + 74 : int direction; /**< If it's an inclusion (=1) or an exclusion (=-1). */ + 75 : tommy_node node; /**< Next node in the list. */ + 76 : }; 77 : 78 : /** - 79 : * This block is an empty one. - 80 : * Note that an empty block is represent with ::BLOCK_EMPTY. - 81 : */ - 82 : #define BLOCK_STATE_EMPTY 0 - 83 : - 84 : /** - 85 : * The block has both the hash and the parity computed. - 86 : * This is the normal state of a saved block. - 87 : * - 88 : * The block hash field IS set. - 89 : * The parity for this disk is updated. - 90 : */ - 91 : #define BLOCK_STATE_BLK 1 - 92 : - 93 : /** - 94 : * The block is new and not yet hashed. - 95 : * This happens when a new block overwrite a just removed block, or an empty space. - 96 : * - 97 : * The block hash field MAY be set and it represents the hash of the OLD data. - 98 : * The hash may be also INVALID or ZERO. - 99 : * - 100 : * If the OLD block was empty, the hash is set to the special ZERO value. - 101 : * If the OLD block was lost, the hash is set to the special INVALID value. - 102 : * - 103 : * The parity for this disk is not updated, but it contains the old data referenced by the hash. + 79 : * Block pointer used to represent unused blocks. + 80 : */ + 81 : #define BLOCK_EMPTY 0 + 82 : + 83 : /** + 84 : * This block is an empty one. + 85 : * Note that an empty block is represent with ::BLOCK_EMPTY. + 86 : */ + 87 : #define BLOCK_STATE_EMPTY 0 + 88 : + 89 : /** + 90 : * The block has both the hash and the parity computed. + 91 : * This is the normal state of a saved block. + 92 : * + 93 : * The block hash field IS set. + 94 : * The parity for this disk is updated. + 95 : */ + 96 : #define BLOCK_STATE_BLK 1 + 97 : + 98 : /** + 99 : * The block is new and not yet hashed. + 100 : * This happens when a new block overwrite a just removed block, or an empty space. + 101 : * + 102 : * The block hash field MAY be set and it represents the hash of the OLD data. + 103 : * The hash may be also INVALID or ZERO. 104 : * - 105 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the - 106 : * data used to compute the parity, because the sync process was interrupted at an unknown point, - 107 : * and the parity may or may not be updated. - 108 : * - 109 : * For this reson we clear all such hashes when reading the state from an incomplete sync before - 110 : * starting a new sync, because sync is affected by such hashes, as sync updates the parity, only - 111 : * if the new data read for CHG blocks has a mismatching hash. - 112 : * Clearing is done setting the ::clear_past_hash flag before reading the state. - 113 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced - 114 : * hashes, and scrub ignores CHG/DELETED blocks. - 115 : */ - 116 : #define BLOCK_STATE_CHG 2 - 117 : - 118 : /** - 119 : * The block is new and hashed. - 120 : * This happens when a new block overwrite a just removed block, or an empty space. - 121 : * - 122 : * Note that when the file copy heuristic is enabled, the REP blocks may be set - 123 : * using this euristic, meaning that the hash may be wrong. - 124 : * - 125 : * For this reason, when the ::force_nocopy flag is enabled in sync, we convert all the REP blocks - 126 : * to CHG, invalidating the stored hash. - 127 : * Clearing is done setting the ::clear_past_hash flag before reading the state. - 128 : * No clearing is done in other commands, as they don't stop the process like in sync - 129 : * when there is a false silent error. - 130 : * - 131 : * The block hash field IS set, and it represents the hash of the new data. - 132 : * The parity for this disk is not updated. - 133 : */ - 134 : #define BLOCK_STATE_REP 3 - 135 : - 136 : /** - 137 : * This block is a deleted one. - 138 : * This happens when a file is deleted. - 139 : * - 140 : * The block hash field IS set, and it represents the hash of the previous data, - 141 : * but only if it's different by all 0. - 142 : * The parity for this disk is not updated, but it contains the old data referenced by the hash. - 143 : * - 144 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the - 145 : * data used to compute the parity, because the sync process was interrupted at an unknown point, - 146 : * and the parity may or may not be updated. - 147 : * - 148 : * A now the sync process is not affected by DELETED hash, so clearing won't be really needed, - 149 : * but considering that we have to do it for CHG blocks, we do it also for DELETED ones, - 150 : * clearing all the past hashes. - 151 : * Clearing is done setting the ::clear_past_hash flag before reading the state. - 152 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced - 153 : * hashes, and scrub ignores CHG/DELETED blocks. - 154 : */ - 155 : #define BLOCK_STATE_DELETED 4 - 156 : - 157 : /** - 158 : * Block of a file. + 105 : * If the OLD block was empty, the hash is set to the special ZERO value. + 106 : * If the OLD block was lost, the hash is set to the special INVALID value. + 107 : * + 108 : * The parity for this disk is not updated, but it contains the old data referenced by the hash. + 109 : * + 110 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the + 111 : * data used to compute the parity, because the sync process was interrupted at an unknown point, + 112 : * and the parity may or may not be updated. + 113 : * + 114 : * For this reason we clear all such hashes when reading the state from an incomplete sync before + 115 : * starting a new sync, because sync is affected by such hashes, as sync updates the parity, only + 116 : * if the new data read for CHG blocks has a mismatching hash. + 117 : * Clearing is done setting the ::clear_past_hash flag before reading the state. + 118 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced + 119 : * hashes, and scrub ignores CHG/DELETED blocks. + 120 : */ + 121 : #define BLOCK_STATE_CHG 2 + 122 : + 123 : /** + 124 : * The block is new and hashed. + 125 : * This happens when a new block overwrite a just removed block, or an empty space. + 126 : * + 127 : * Note that when the file copy heuristic is enabled, the REP blocks may be set + 128 : * using this heuristic, meaning that the hash may be wrong. + 129 : * + 130 : * For this reason, when the ::force_nocopy flag is enabled in sync, we convert all the REP blocks + 131 : * to CHG, invalidating the stored hash. + 132 : * Clearing is done setting the ::clear_past_hash flag before reading the state. + 133 : * No clearing is done in other commands, as they don't stop the process like in sync + 134 : * when there is a false silent error. + 135 : * + 136 : * The block hash field IS set, and it represents the hash of the new data. + 137 : * The parity for this disk is not updated. + 138 : */ + 139 : #define BLOCK_STATE_REP 3 + 140 : + 141 : /** + 142 : * This block is a deleted one. + 143 : * This happens when a file is deleted. + 144 : * + 145 : * The block hash field IS set, and it represents the hash of the previous data, + 146 : * but only if it's different by all 0. + 147 : * The parity for this disk is not updated, but it contains the old data referenced by the hash. + 148 : * + 149 : * If the state is read from an incomplete sync, we don't really know if the hash is referring at the + 150 : * data used to compute the parity, because the sync process was interrupted at an unknown point, + 151 : * and the parity may or may not be updated. + 152 : * + 153 : * A now the sync process is not affected by DELETED hash, so clearing won't be really needed, + 154 : * but considering that we have to do it for CHG blocks, we do it also for DELETED ones, + 155 : * clearing all the past hashes. + 156 : * Clearing is done setting the ::clear_past_hash flag before reading the state. + 157 : * No clearing is done in other commands, as check and fix are instead able to work with unsynced + 158 : * hashes, and scrub ignores CHG/DELETED blocks. 159 : */ - 160 : struct snapraid_block { - 161 : unsigned char hash[HASH_SIZE]; /**< Hash of the block. */ - 162 : unsigned char state; /**< State of the block. */ - 163 : }; - 164 : - 165 : /** - 166 : * If a file is present in the disk. - 167 : * It's used only in scan to detect present and missing files. - 168 : */ - 169 : #define FILE_IS_PRESENT 0x01 - 170 : - 171 : /** - 172 : * If it's an excluded file from the processing. - 173 : * It's used in both check and fix to mark files to exclude from the processing. - 174 : */ - 175 : #define FILE_IS_EXCLUDED 0x02 - 176 : - 177 : /** - 178 : * If a fix was attempted but it failed. - 179 : * It's used only in fix to mark that some data is unrecoverable. - 180 : */ - 181 : #define FILE_IS_DAMAGED 0x04 - 182 : - 183 : /** - 184 : * If a fix was done. - 185 : * It's used only in fix to mark that some data was recovered. - 186 : */ - 187 : #define FILE_IS_FIXED 0x08 - 188 : - 189 : /** - 190 : * If the file was originally missing, and it was created in the fix process. - 191 : * It's used only in fix to mark files recovered from scratch, - 192 : * meaning that they don't have any previous content. - 193 : * This is important because it means that deleting them, you are not going - 194 : * to lose something that cannot be recovered. - 195 : * Note that excluded files won't ever get this flag. - 196 : */ - 197 : #define FILE_IS_CREATED 0x10 - 198 : - 199 : /** - 200 : * If the file has completed its processing, meaning that it won't be opened anymore. - 201 : * It's used only in fix to mark when we finish processing one file. - 202 : * Note that excluded files won't ever get this flag. - 203 : */ - 204 : #define FILE_IS_FINISHED 0x20 - 205 : - 206 : /** - 207 : * If the file hash was obtained from a file copy - 208 : * identified by the same name, size and stamp. - 209 : */ - 210 : #define FILE_IS_COPY 0x40 - 211 : - 212 : /** - 213 : * If the file was opened. - 214 : * It's used in fix to detect if it's the first time a file is opened. - 215 : */ - 216 : #define FILE_IS_OPENED 0x80 - 217 : - 218 : /** - 219 : * If the file is modified from the latest sync. - 220 : * It's used in fix to store if the state of the file before being modified. - 221 : */ - 222 : #define FILE_IS_UNSYNCED 0x100 - 223 : - 224 : /** - 225 : * If the file is without inode. - 226 : * It could happen in filesystem where inodes are not persistent, - 227 : * or when restoring a full disk with "fix". - 228 : * In such cases we have to clear any stored duplicate inode. - 229 : * After the scan process completes, no file should have this flag set. - 230 : */ - 231 : #define FILE_IS_WITHOUT_INODE 0x200 - 232 : - 233 : /** - 234 : * The file is deleted. - 235 : * This happens when a file is deleted from the array, - 236 : * but it's keep inside the parity until the next sync. - 237 : * - 238 : * During the filesystem check we needs this information, - 239 : * because deleted files may be present only partially. - 240 : */ - 241 : #define FILE_IS_DELETED 0x400 - 242 : - 243 : /** - 244 : * The file is missing. - 245 : * This happens in fix/check when a file is cannot be opened, - 246 : * and marking it as such prevents to retry to open it again. - 247 : */ - 248 : #define FILE_IS_MISSING 0x800 - 249 : - 250 : #define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */ - 251 : #define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */ - 252 : #define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */ - 253 : #define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */ - 254 : #define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */ - 255 : - 256 : /** - 257 : * File. - 258 : */ - 259 : struct snapraid_file { - 260 : int64_t mtime_sec; /**< Modification time. */ - 261 : uint64_t inode; /**< Inode. */ - 262 : uint64_t physical; /**< Physical offset of the file. */ - 263 : data_off_t size; /**< Size of the file. */ - 264 : struct snapraid_block* blockvec; /**< All the blocks of the file. */ - 265 : int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */ - 266 : block_off_t blockmax; /**< Number of blocks. */ - 267 : unsigned flag; /**< FILE_IS_* flags. */ - 268 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ - 269 : - 270 : /* nodes for data structures */ - 271 : tommy_node nodelist; - 272 : tommy_hashdyn_node nodeset; - 273 : tommy_hashdyn_node pathset; - 274 : tommy_hashdyn_node stampset; - 275 : }; - 276 : - 277 : /** - 278 : * Symbolic Link. - 279 : */ - 280 : struct snapraid_link { - 281 : unsigned flag; /**< FILE_IS_* flags. */ - 282 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ - 283 : char* linkto; /**< Link to. */ - 284 : - 285 : /* nodes for data structures */ - 286 : tommy_node nodelist; - 287 : tommy_hashdyn_node nodeset; - 288 : }; + 160 : #define BLOCK_STATE_DELETED 4 + 161 : + 162 : /** + 163 : * Block of a file. + 164 : */ + 165 : struct snapraid_block { + 166 : unsigned char hash[HASH_SIZE]; /**< Hash of the block. */ + 167 : unsigned char state; /**< State of the block. */ + 168 : }; + 169 : + 170 : /** + 171 : * If a file is present in the disk. + 172 : * It's used only in scan to detect present and missing files. + 173 : */ + 174 : #define FILE_IS_PRESENT 0x01 + 175 : + 176 : /** + 177 : * If it's an excluded file from the processing. + 178 : * It's used in both check and fix to mark files to exclude from the processing. + 179 : */ + 180 : #define FILE_IS_EXCLUDED 0x02 + 181 : + 182 : /** + 183 : * If a fix was attempted but it failed. + 184 : * It's used only in fix to mark that some data is unrecoverable. + 185 : */ + 186 : #define FILE_IS_DAMAGED 0x04 + 187 : + 188 : /** + 189 : * If a fix was done. + 190 : * It's used only in fix to mark that some data was recovered. + 191 : */ + 192 : #define FILE_IS_FIXED 0x08 + 193 : + 194 : /** + 195 : * If the file was originally missing, and it was created in the fix process. + 196 : * It's used only in fix to mark files recovered from scratch, + 197 : * meaning that they don't have any previous content. + 198 : * This is important because it means that deleting them, you are not going + 199 : * to lose something that cannot be recovered. + 200 : * Note that excluded files won't ever get this flag. + 201 : */ + 202 : #define FILE_IS_CREATED 0x10 + 203 : + 204 : /** + 205 : * If the file has completed its processing, meaning that it won't be opened anymore. + 206 : * It's used only in fix to mark when we finish processing one file. + 207 : * Note that excluded files won't ever get this flag. + 208 : */ + 209 : #define FILE_IS_FINISHED 0x20 + 210 : + 211 : /** + 212 : * If the file hash was obtained from a file copy + 213 : * identified by the same name, size and stamp. + 214 : */ + 215 : #define FILE_IS_COPY 0x40 + 216 : + 217 : /** + 218 : * If the file was opened. + 219 : * It's used in fix to detect if it's the first time a file is opened. + 220 : */ + 221 : #define FILE_IS_OPENED 0x80 + 222 : + 223 : /** + 224 : * If the file is modified from the latest sync. + 225 : * It's used in fix to store if the state of the file before being modified. + 226 : */ + 227 : #define FILE_IS_UNSYNCED 0x100 + 228 : + 229 : /** + 230 : * If the file is without inode. + 231 : * It could happen in file-system where inodes are not persistent, + 232 : * or when restoring a full disk with "fix". + 233 : * In such cases we have to clear any stored duplicate inode. + 234 : * After the scan process completes, no file should have this flag set. + 235 : */ + 236 : #define FILE_IS_WITHOUT_INODE 0x200 + 237 : + 238 : /** + 239 : * The file is deleted. + 240 : * This happens when a file is deleted from the array, + 241 : * but it's keep inside the parity until the next sync. + 242 : * + 243 : * During the file-system check we needs this information, + 244 : * because deleted files may be present only partially. + 245 : */ + 246 : #define FILE_IS_DELETED 0x400 + 247 : + 248 : /** + 249 : * The file is missing. + 250 : * This happens in fix/check when a file is cannot be opened, + 251 : * and marking it as such prevents to retry to open it again. + 252 : */ + 253 : #define FILE_IS_MISSING 0x800 + 254 : + 255 : #define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */ + 256 : #define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */ + 257 : #define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */ + 258 : #define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */ + 259 : #define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */ + 260 : + 261 : /** + 262 : * File. + 263 : */ + 264 : struct snapraid_file { + 265 : int64_t mtime_sec; /**< Modification time. */ + 266 : uint64_t inode; /**< Inode. */ + 267 : uint64_t physical; /**< Physical offset of the file. */ + 268 : data_off_t size; /**< Size of the file. */ + 269 : struct snapraid_block* blockvec; /**< All the blocks of the file. */ + 270 : int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */ + 271 : block_off_t blockmax; /**< Number of blocks. */ + 272 : unsigned flag; /**< FILE_IS_* flags. */ + 273 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ + 274 : + 275 : /* nodes for data structures */ + 276 : tommy_node nodelist; + 277 : tommy_hashdyn_node nodeset; + 278 : tommy_hashdyn_node pathset; + 279 : tommy_hashdyn_node stampset; + 280 : }; + 281 : + 282 : /** + 283 : * Symbolic Link. + 284 : */ + 285 : struct snapraid_link { + 286 : unsigned flag; /**< FILE_IS_* flags. */ + 287 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ + 288 : char* linkto; /**< Link to. */ 289 : - 290 : /** - 291 : * Dir. - 292 : */ - 293 : struct snapraid_dir { - 294 : unsigned flag; /**< FILE_IS_* flags. */ - 295 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ - 296 : - 297 : /* nodes for data structures */ - 298 : tommy_node nodelist; - 299 : tommy_hashdyn_node nodeset; - 300 : }; + 290 : /* nodes for data structures */ + 291 : tommy_node nodelist; + 292 : tommy_hashdyn_node nodeset; + 293 : }; + 294 : + 295 : /** + 296 : * Dir. + 297 : */ + 298 : struct snapraid_dir { + 299 : unsigned flag; /**< FILE_IS_* flags. */ + 300 : char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ 301 : - 302 : /** - 303 : * Chunk. - 304 : * - 305 : * A chunk represents a fragment of a file mapped into the parity. - 306 : */ - 307 : struct snapraid_chunk { - 308 : struct snapraid_file* file; /* File containing this chunk. */ - 309 : block_off_t parity_pos; /**< Parity position. */ - 310 : block_off_t file_pos; /**< Position in the file. */ - 311 : block_off_t count; /**< Number of sequential blocks in the file and parity. */ - 312 : tommy_tree_node parity_node; /**< Tree sorted by <parity_pos>. */ - 313 : tommy_tree_node file_node; /**< Tree sorter by <file,file_pos>. */ - 314 : }; - 315 : - 316 : /** - 317 : * Disk. - 318 : */ - 319 : struct snapraid_disk { - 320 : char name[PATH_MAX]; /**< Name of the disk. */ - 321 : char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */ - 322 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ - 323 : uint64_t device; /**< Device identifier. */ - 324 : uint64_t tick; /**< Usage time of the disk. */ - 325 : block_off_t total_blocks; /**< Number of total blocks. */ - 326 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */ - 327 : - 328 : /** - 329 : * First free searching block. - 330 : * Note that it doesn't necessarely point at the first free block, - 331 : * but it just tell you that no free block is present before this position. - 332 : */ - 333 : block_off_t first_free_block; + 302 : /* nodes for data structures */ + 303 : tommy_node nodelist; + 304 : tommy_hashdyn_node nodeset; + 305 : }; + 306 : + 307 : /** + 308 : * Chunk. + 309 : * + 310 : * A chunk represents a fragment of a file mapped into the parity. + 311 : */ + 312 : struct snapraid_chunk { + 313 : struct snapraid_file* file; /**< File containing this chunk. */ + 314 : block_off_t parity_pos; /**< Parity position. */ + 315 : block_off_t file_pos; /**< Position in the file. */ + 316 : block_off_t count; /**< Number of sequential blocks in the file and parity. */ + 317 : tommy_tree_node parity_node; /**< Tree sorted by <parity_pos>. */ + 318 : tommy_tree_node file_node; /**< Tree sorter by <file,file_pos>. */ + 319 : }; + 320 : + 321 : /** + 322 : * Disk. + 323 : */ + 324 : struct snapraid_disk { + 325 : char name[PATH_MAX]; /**< Name of the disk. */ + 326 : char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */ + 327 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ + 328 : char uuid[UUID_MAX]; /**< UUID of the disk. */ + 329 : + 330 : uint64_t device; /**< Device identifier. */ + 331 : uint64_t tick; /**< Usage time of the disk. */ + 332 : block_off_t total_blocks; /**< Number of total blocks. */ + 333 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */ 334 : - 335 : int has_volatile_inodes; /**< If the underline filesystem has not persistent inodes. */ - 336 : int has_unreliable_physical; /**< If the physical offset of files has duplicates. */ - 337 : int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same filesystem. */ - 338 : int has_unsupported_uuid; /**< If the disk doesn't report UUID, meaning it's not supported. */ - 339 : int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */ - 340 : int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */ - 341 : int skip_access; /**< If the disk is unaccessible and it should be skipped. */ - 342 : - 343 : /** - 344 : * Mapping of chunks in the parity. - 345 : * Sorted by <parity_pos> and by <file,file_pos> - 346 : */ - 347 : tommy_tree fs_parity; - 348 : tommy_tree fs_file; + 335 : /** + 336 : * First free searching block. + 337 : * Note that it doesn't necessarily point at the first free block, + 338 : * but it just tell you that no free block is present before this position. + 339 : */ + 340 : block_off_t first_free_block; + 341 : + 342 : int has_volatile_inodes; /**< If the underline file-system has not persistent inodes. */ + 343 : int has_unreliable_physical; /**< If the physical offset of files has duplicates. */ + 344 : int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same file-system. */ + 345 : int has_unsupported_uuid; /**< If the disk doesn't report UUID, meaning it's not supported. */ + 346 : int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */ + 347 : int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */ + 348 : int skip_access; /**< If the disk is inaccessible and it should be skipped. */ 349 : 350 : /** - 351 : * Last chunk we accessed. - 352 : * It's used to optimize access of sequential blocks. + 351 : * Mapping of chunks in the parity. + 352 : * Sorted by <parity_pos> and by <file,file_pos> 353 : */ - 354 : struct snapraid_chunk* fs_last; - 355 : - 356 : /** - 357 : * List of all the snapraid_file for the disk. - 358 : */ - 359 : tommy_list filelist; - 360 : - 361 : /** - 362 : * List of all the deleted file for the disk. - 363 : * - 364 : * These files are kept allocated, because the blocks are still referenced in - 365 : * the ::blockarr. - 366 : */ - 367 : tommy_list deletedlist; - 368 : - 369 : tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */ - 370 : tommy_hashdyn pathset; /**< Hashtable by path of all the files. */ - 371 : tommy_hashdyn stampset; /**< Hashtable by stamp (size and time) of all the files. */ - 372 : tommy_list linklist; /**< List of all the links. */ - 373 : tommy_hashdyn linkset; /**< Hashtable by name of all the links. */ - 374 : tommy_list dirlist; /**< List of all the dirs. */ - 375 : tommy_hashdyn dirset; /**< Hashtable by name of all the dirs. */ - 376 : - 377 : /* nodes for data structures */ - 378 : tommy_node node; - 379 : }; - 380 : - 381 : /** - 382 : * Max UUID length. - 383 : */ - 384 : #define UUID_MAX 128 - 385 : - 386 : /** - 387 : * Disk mapping. - 388 : */ - 389 : struct snapraid_map { - 390 : char name[PATH_MAX]; /**< Name of the disk. */ - 391 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ - 392 : block_off_t total_blocks; /**< Number of total blocks. */ - 393 : block_off_t free_blocks; /**< Number of free blocks at last 'sync'. */ - 394 : unsigned position; /**< Position of the disk in the parity. */ - 395 : - 396 : /* nodes for data structures */ - 397 : tommy_node node; - 398 : }; - 399 : - 400 : /** - 401 : * Parity. - 402 : */ - 403 : struct snapraid_parity { - 404 : char path[PATH_MAX]; /**< Path of the parity file. */ - 405 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ - 406 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ - 407 : uint64_t device; /**< Device identifier of the parity. */ - 408 : block_off_t total_blocks; /**< Number of total blocks. */ - 409 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */ - 410 : int skip_access; /**< If the disk is unaccessible and it should be skipped. */ - 411 : int is_excluded; /**< If the parity is excluded by disk filter. */ - 412 : - 413 : /** - 414 : * Cumulative time used for parity disks. - 415 : */ - 416 : uint64_t tick; - 417 : }; - 418 : - 419 : /** - 420 : * Info. - 421 : */ - 422 : typedef uint32_t snapraid_info; - 423 : - 424 : /** - 425 : * Allocate a content. - 426 : */ - 427 : struct snapraid_content* content_alloc(const char* path, uint64_t dev); - 428 : - 429 : /** - 430 : * Deallocate a content. - 431 : */ - 432 : void content_free(struct snapraid_content* content); - 433 : - 434 : /** - 435 : * Allocate a filter pattern for files and directories. - 436 : */ - 437 : struct snapraid_filter* filter_alloc_file(int is_include, const char* pattern); - 438 : - 439 : /** - 440 : * Allocate a filter pattern for disks. - 441 : */ - 442 : struct snapraid_filter* filter_alloc_disk(int is_include, const char* pattern); - 443 : - 444 : /** - 445 : * Deallocate an exclusion. - 446 : */ - 447 : void filter_free(struct snapraid_filter* filter); - 448 : - 449 : /** - 450 : * Filter type description. - 451 : */ - 452 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size); - 453 : - 454 : /** - 455 : * Filter hidden files. - 456 : * Return !=0 if it matches and it should be excluded. - 457 : */ - 458 3066852 : static inline int filter_hidden(int enable, struct dirent* dd) - 459 : { - 460 3066852 : if (enable && dirent_hidden(dd)) { - 461 0 : return 1; /* filter out */ - 462 : } - 463 : - 464 3066852 : return 0; - 465 : } - 466 : - 467 : /** - 468 : * Filter a path using a list of filters. - 469 : * For each element of the path all the filters are applied, until the first one that matches. - 470 : * Return !=0 if it should be excluded. - 471 : */ - 472 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); - 473 : - 474 : /** - 475 : * Filter a file/link/dir if missing. - 476 : * This call imply a disk check for the file presence. - 477 : * Return !=0 if the file is present and it should be excluded. - 478 : */ - 479 : int filter_existence(int filter_missing, const char* dir, const char* sub); - 480 : - 481 : /** - 482 : * Filter a file if bad. - 483 : * Return !=0 if the file is correct and it should be excluded. - 484 : */ - 485 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file); - 486 : - 487 : /** - 488 : * Filter a dir using a list of filters. - 489 : * For each element of the path all the filters are applied, until the first one that matches. - 490 : * Return !=0 if should be excluded. - 491 : */ - 492 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); - 493 : - 494 : /** - 495 : * Filter a path if it's a content file. - 496 : * Return !=0 if should be excluded. - 497 : */ - 498 : int filter_content(tommy_list* contentlist, const char* path); - 499 : - 500 : /** - 501 : * Check if the specified hash is invalid. - 502 : * - 503 : * An invalid hash is represented with all bytes at 0x00. - 504 : */ - 505 776042 : static inline int hash_is_invalid(const unsigned char* hash) - 506 : { - 507 : unsigned i; - 508 : - 509 1264688 : for (i = 0; i < HASH_SIZE; ++i) - 510 1234312 : if (hash[i] != 0x00) - 511 745666 : return 0; - 512 : - 513 30376 : return 1; - 514 : } - 515 : - 516 : /** - 517 : * Check if the specified hash represent the zero block. - 518 : * - 519 : * A zero hash is represented with all bytes at 0xFF. - 520 : */ - 521 790275 : static inline int hash_is_zero(const unsigned char* hash) - 522 : { - 523 : unsigned i; - 524 : - 525 1835799 : for (i = 0; i < HASH_SIZE; ++i) - 526 1770619 : if (hash[i] != 0xFF) - 527 725095 : return 0; - 528 : - 529 65180 : return 1; - 530 : } - 531 : - 532 : /** - 533 : * Check if the specified hash is a real hash. - 534 : */ - 535 65785 : static inline int hash_is_real(const unsigned char* hash) - 536 : { - 537 65785 : return !hash_is_zero(hash) && !hash_is_invalid(hash); - 538 : } - 539 : - 540 : /** - 541 : * Set the hash to the special INVALID value. - 542 : */ - 543 8910831 : static inline void hash_invalid_set(unsigned char* hash) - 544 : { - 545 8910831 : memset(hash, 0x00, HASH_SIZE); - 546 8910831 : } - 547 : - 548 : /** - 549 : * Set the hash to the special ZERO value. - 550 : */ - 551 153288 : static inline void hash_zero_set(unsigned char* hash) - 552 : { - 553 153288 : memset(hash, 0xFF, HASH_SIZE); - 554 153288 : } - 555 : - 556 : /** - 557 : * Get the state of the block. - 558 : * - 559 : * For this function, it's allowed to pass a NULL block - 560 : * pointer than results in the BLOCK_STATE_EMPTY state. - 561 : */ - 562 96735410 : static inline unsigned block_state_get(const struct snapraid_block* block) - 563 : { - 564 96735410 : if (block == BLOCK_EMPTY) - 565 2427201 : return BLOCK_STATE_EMPTY; - 566 : - 567 94308209 : return block->state; - 568 : } - 569 : - 570 : /** - 571 : * Set the state of the block. - 572 : */ - 573 18242161 : static inline void block_state_set(struct snapraid_block* block, unsigned state) - 574 : { - 575 18242161 : block->state = state; - 576 18242161 : } - 577 : - 578 : /** - 579 : * Check if the specified block has an updated hash. - 580 : * - 581 : * Note that EMPTY / CHG / DELETED return 0. - 582 : */ - 583 2005171 : static inline int block_has_updated_hash(const struct snapraid_block* block) - 584 : { - 585 2005171 : unsigned state = block_state_get(block); - 586 : - 587 2005171 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; - 588 : } - 589 : - 590 : /** - 591 : * Check if the specified block has a past hash, - 592 : * i.e. the hash of the data that it's now overwritten or lost. - 593 : * - 594 : * Note that EMPTY / BLK / REP return 0. - 595 : */ - 596 2287366 : static inline int block_has_past_hash(const struct snapraid_block* block) - 597 : { - 598 2287366 : unsigned state = block_state_get(block); - 599 : - 600 2287366 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED; - 601 : } - 602 : - 603 : /** - 604 : * Check if the specified block is part of a file. - 605 : * - 606 : * Note that EMPTY / DELETED return 0. - 607 : */ - 608 12929086 : static inline int block_has_file(const struct snapraid_block* block) - 609 : { - 610 12929086 : unsigned state = block_state_get(block); - 611 : - 612 12929086 : return state == BLOCK_STATE_BLK - 613 12929086 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; - 614 : } - 615 : - 616 : /** - 617 : * Check if the block has an invalid parity than needs to be updated. - 618 : * - 619 : * Note that EMPTY / BLK return 0. - 620 : */ - 621 11489174 : static inline int block_has_invalid_parity(const struct snapraid_block* block) - 622 : { - 623 11489174 : unsigned state = block_state_get(block); - 624 : - 625 11489174 : return state == BLOCK_STATE_DELETED - 626 11489174 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; - 627 : } - 628 : - 629 : /** - 630 : * Check if the block is part of a file with valid parity. - 631 : * - 632 : * Note that anything different than BLK return 0. - 633 : */ - 634 221100 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) - 635 : { - 636 221100 : unsigned state = block_state_get(block); - 637 : - 638 221100 : return state == BLOCK_STATE_BLK; - 639 : } - 640 : - 641 33299459 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) - 642 : { - 643 33299459 : return (file->flag & mask) == mask; - 644 : } - 645 : - 646 5176917 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) - 647 : { - 648 5176917 : file->flag |= mask; - 649 5176917 : } - 650 : - 651 14174 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) - 652 : { - 653 14174 : file->flag &= ~mask; - 654 14174 : } - 655 : - 656 : /** - 657 : * Allocate a file. - 658 : */ - 659 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical); - 660 : - 661 : /** - 662 : * Duplicate a file. - 663 : */ - 664 : struct snapraid_file* file_dup(struct snapraid_file* copy); - 665 : - 666 : /** - 667 : * Deallocate a file. - 668 : */ - 669 : void file_free(struct snapraid_file* file); - 670 : - 671 : /** - 672 : * Rename a file. - 673 : */ - 674 : void file_rename(struct snapraid_file* file, const char* sub); - 675 : - 676 : /** - 677 : * Copy a file. - 678 : */ - 679 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file); - 680 : - 681 : /** - 682 : * Return the name of the file, without the dir. - 683 : */ - 684 : const char* file_name(const struct snapraid_file* file); - 685 : - 686 : /** - 687 : * Check if the block is the last in the file. - 688 : */ - 689 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos); - 690 : - 691 : /** - 692 : * Get the size in bytes of the block. - 693 : * If it's the last block of a file it could be less than block_size. - 694 : */ - 695 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size); - 696 : - 697 : /** - 698 : * Compare a file with an inode. - 699 : */ - 700 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data); - 701 : - 702 : /** - 703 : * Compare files by inode. - 704 : */ - 705 : int file_inode_compare(const void* void_a, const void* void_b); - 706 : - 707 : /** - 708 : * Compare files by path. - 709 : */ - 710 : int file_path_compare(const void* void_a, const void* void_b); - 711 : - 712 : /** - 713 : * Compare files by physical address. - 714 : */ - 715 : int file_physical_compare(const void* void_a, const void* void_b); - 716 : - 717 : /** - 718 : * Compute the hash of a file inode. - 719 : */ - 720 4822298 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) - 721 : { - 722 4822298 : return (tommy_uint32_t)tommy_inthash_u64(inode); - 723 : } - 724 : - 725 : /** - 726 : * Compare a file with a path. - 727 : */ - 728 : int file_path_compare_to_arg(const void* void_arg, const void* void_data); - 729 : - 730 : /** - 731 : * Compare a file with another file for name, stamp, and both. - 732 : */ - 733 : int file_name_compare(const void* void_a, const void* void_b); - 734 : int file_stamp_compare(const void* void_a, const void* void_b); - 735 : int file_namestamp_compare(const void* void_a, const void* void_b); - 736 : int file_pathstamp_compare(const void* void_a, const void* void_b); - 737 : - 738 : /** - 739 : * Compute the hash of a file path. - 740 : */ - 741 3766623 : static inline tommy_uint32_t file_path_hash(const char* sub) - 742 : { - 743 3766623 : return tommy_hash_u32(0, sub, strlen(sub)); - 744 : } - 745 : - 746 : /** - 747 : * Compute the hash of a file stamp. - 748 : */ - 749 6139138 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) - 750 : { - 751 6139138 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); - 752 : } - 753 : - 754 : /** - 755 : * Allocate a chunk. - 756 : */ - 757 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count); - 758 : - 759 : /** - 760 : * Deallocate a chunk. - 761 : */ - 762 : void chunk_free(struct snapraid_chunk* chunk); - 763 : - 764 : /** - 765 : * Compare chunk by parity position. - 766 : */ - 767 : int chunk_parity_compare(const void* void_a, const void* void_b); - 768 : - 769 : /** - 770 : * Compare chunk by file and file position. - 771 : */ - 772 : int chunk_file_compare(const void* void_a, const void* void_b); - 773 : - 774 202633 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask) - 775 : { - 776 202633 : return (slink->flag & mask) == mask; - 777 : } - 778 : - 779 36114 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask) - 780 : { - 781 36114 : slink->flag |= mask; - 782 36114 : } - 783 : - 784 : static inline void link_flag_clear(struct snapraid_link* slink, unsigned mask) - 785 : { - 786 : slink->flag &= ~mask; - 787 : } - 788 : - 789 6 : static inline void link_flag_let(struct snapraid_link* slink, unsigned flag, unsigned mask) - 790 : { - 791 6 : slink->flag &= ~mask; - 792 6 : slink->flag |= flag & mask; - 793 6 : } - 794 : - 795 410820 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask) - 796 : { - 797 410820 : return slink->flag & mask; - 798 : } - 799 : - 800 : /** - 801 : * Allocate a link. - 802 : */ - 803 : struct snapraid_link* link_alloc(const char* name, const char* slink, unsigned link_flag); - 804 : - 805 : /** - 806 : * Deallocate a link. - 807 : */ - 808 : void link_free(struct snapraid_link* slink); - 809 : - 810 : /** - 811 : * Compare a link with a name. - 812 : */ - 813 : int link_name_compare_to_arg(const void* void_arg, const void* void_data); - 814 : - 815 : /** - 816 : * Compare links by path. - 817 : */ - 818 : int link_alpha_compare(const void* void_a, const void* void_b); - 819 : - 820 : /** - 821 : * Compute the hash of a link name. - 822 : */ - 823 148256 : static inline tommy_uint32_t link_name_hash(const char* name) - 824 : { - 825 148256 : return tommy_hash_u32(0, name, strlen(name)); - 826 : } - 827 : - 828 876 : static inline int dir_flag_has(const struct snapraid_dir* dir, unsigned mask) - 829 : { - 830 876 : return (dir->flag & mask) == mask; - 831 : } - 832 : - 833 235 : static inline void dir_flag_set(struct snapraid_dir* dir, unsigned mask) - 834 : { - 835 235 : dir->flag |= mask; - 836 235 : } - 837 : - 838 : static inline void dir_flag_clear(struct snapraid_dir* dir, unsigned mask) - 839 : { - 840 : dir->flag &= ~mask; - 841 : } - 842 : - 843 : /** - 844 : * Allocate a dir. - 845 : */ - 846 : struct snapraid_dir* dir_alloc(const char* name); - 847 : - 848 : /** - 849 : * Deallocate a dir. - 850 : */ - 851 : void dir_free(struct snapraid_dir* dir); - 852 : - 853 : /** - 854 : * Compare a dir with a name. - 855 : */ - 856 : int dir_name_compare(const void* void_arg, const void* void_data); - 857 : - 858 : /** - 859 : * Compute the hash of a dir name. - 860 : */ - 861 987 : static inline tommy_uint32_t dir_name_hash(const char* name) - 862 : { - 863 987 : return tommy_hash_u32(0, name, strlen(name)); - 864 : } - 865 : - 866 : /** - 867 : * Allocate a disk. - 868 : */ - 869 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip); - 870 : - 871 : /** - 872 : * Deallocate a disk. - 873 : */ - 874 : void disk_free(struct snapraid_disk* disk); - 875 : - 876 : /** - 877 : * Get the size of the disk in blocks. - 878 : */ - 879 : block_off_t disk_size(struct snapraid_disk* disk); - 880 : - 881 : /** - 882 : * Check if a disk is totally empty and can be discarded from the content file. - 883 : * A disk is empty if it doesn't contain any file, symlink, hardlink or dir - 884 : * and without any DELETED block. - 885 : * The blockmax is used to limit the search of DELETED block up to blockmax. - 886 : */ - 887 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax); - 888 : - 889 : /** - 890 : * Check the filesystem for errors. - 891 : * Return 0 if it's OK. - 892 : */ - 893 : int fs_check(struct snapraid_disk* disk); - 894 : - 895 : /** - 896 : * Allocate a parity position for the specified file position. - 897 : * - 898 : * After this call you can use the par2file/par2block operations - 899 : * to query the relation. - 900 : * - 901 : * \note This function is NOT thread-safe as it uses the the disk cache. + - 902 : */ - 903 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos); - 904 : - 905 : /** - 906 : * Deallocate the parity position. - 907 : * - 908 : * After this call the par2file/par2block operations - 909 : * won't find anymore the parity association. - 910 : * - 911 : * \note This function is NOT thread-safe as it uses the the disk cache. - 912 : */ - 913 : void fs_deallocate(struct snapraid_disk* disk, block_off_t pos); - 914 : - 915 : /** - 916 : * Get the block from the file position. - 917 : */ - 918 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos); - 919 : - 920 : /** - 921 : * Like fs_file2par_get() but thread-safe. - 922 : */ - 923 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos); - 924 : - 925 : /** - 926 : * Get the file position from the parity position. - 927 : * Return 0 if no file is using it. - 928 : * \note This function is NOT thread-safe as it uses the the disk cache. - 929 : */ - 930 11514087 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) - 931 : { - 932 11514087 : return fs_par2file_get_ts(disk, &disk->fs_last, parity_pos, file_pos); - 933 : } - 934 : - 935 : /** - 936 : * Like fs_file2par_get() but thread-safe. - 937 : */ - 938 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos); - 939 : - 940 : /** - 941 : * Get the parity position from the file position. - 942 : * \note This function is NOT thread-safe as it uses the the disk cache. - 943 : */ - 944 464306 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) - 945 : { - 946 464306 : return fs_file2par_get_ts(disk, &disk->fs_last, file, file_pos); - 947 : } - 948 : - 949 : /** - 950 : * Like fs_par2block_get() but thread-safe. - 951 : */ - 952 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos); - 953 : - 954 : /** - 955 : * Get the block from the parity position. - 956 : * Return BLOCK_EMPTY==0 if the block is over the end of the disk or not used. - 957 : * \note This function is NOT thread-safe as it uses the the disk cache. - 958 : */ - 959 21727310 : static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk, block_off_t parity_pos) - 960 : { - 961 21727310 : return fs_par2block_get_ts(disk, &disk->fs_last, parity_pos); - 962 : } - 963 : - 964 : /** - 965 : * Allocate a disk mapping. - 966 : * Uses uuid="" if not available. - 967 : */ - 968 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid); - 969 : - 970 : /** - 971 : * Deallocate a disk mapping. - 972 : */ - 973 : void map_free(struct snapraid_map* map); - 974 : - 975 : /** - 976 : * Mask used to store additional information in the info bits. - 977 : * - 978 : * These bits reduce the granurality of the time in the memory representation. - 979 : */ - 980 : #define INFO_MASK 0x7 - 981 : - 982 : /** - 983 : * Make an info. - 984 : */ - 985 394996 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) - 986 : { - 987 : /* clear the lowest bits as reserved for other information */ - 988 394996 : snapraid_info info = last_access & ~INFO_MASK; - 989 : - 990 394996 : if (error != 0) - 991 5460 : info |= 0x1; - 992 394996 : if (rehash != 0) - 993 127410 : info |= 0x2; - 994 394996 : if (justsynced != 0) - 995 226412 : info |= 0x4; - 996 394996 : return info; - 997 : } - 998 : - 999 : /** - 1000 : * Extract the time information. - 1001 : * This is the last time when the block was know to be correct. - 1002 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub. - 1003 : */ - 1004 2258078 : static inline time_t info_get_time(snapraid_info info) - 1005 : { - 1006 2258078 : return info & ~INFO_MASK; - 1007 : } - 1008 : - 1009 : /** - 1010 : * Extract the error information. - 1011 : * Report if the block address had some problem. - 1012 : */ - 1013 1725704 : static inline int info_get_bad(snapraid_info info) - 1014 : { - 1015 1725704 : return (info & 0x1) != 0; - 1016 : } - 1017 : - 1018 : /** - 1019 : * Extract the rehash information. - 1020 : * Report if the block address is using the old hash and needs to be rehashed. - 1021 : */ - 1022 3312725 : static inline int info_get_rehash(snapraid_info info) - 1023 : { - 1024 3312725 : return (info & 0x2) != 0; - 1025 : } - 1026 : - 1027 : /** - 1028 : * Extract the scrubbed information. - 1029 : * Report if the block address was never scrubbed. - 1030 : */ - 1031 1474627 : static inline int info_get_justsynced(snapraid_info info) - 1032 : { - 1033 1474627 : return (info & 0x4) != 0; - 1034 : } - 1035 : - 1036 : /** - 1037 : * Mark the block address as with error. - 1038 : */ - 1039 1802 : static inline snapraid_info info_set_bad(snapraid_info info) - 1040 : { - 1041 1802 : return info | 0x1; - 1042 : } - 1043 : - 1044 : /** - 1045 : * Mark the block address as with rehash. - 1046 : */ - 1047 9199 : static inline snapraid_info info_set_rehash(snapraid_info info) - 1048 : { - 1049 9199 : return info | 0x2; - 1050 : } - 1051 : - 1052 : /** - 1053 : * Set the info at the specified position. - 1054 : * The position is allocated if not yet done. - 1055 : */ - 1056 1609485 : static inline void info_set(tommy_arrayblkof* array, unsigned pos, snapraid_info info) - 1057 : { - 1058 1609485 : tommy_arrayblkof_grow(array, pos + 1); - 1059 : - 1060 1609485 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); - 1061 1609485 : } - 1062 : - 1063 : /** - 1064 : * Get the info at the specified position. - 1065 : * For not allocated position, 0 is returned. - 1066 : */ - 1067 10573034 : static inline snapraid_info info_get(tommy_arrayblkof* array, unsigned pos) - 1068 : { - 1069 : snapraid_info info; - 1070 : - 1071 10573034 : if (pos >= tommy_arrayblkof_size(array)) - 1072 474047 : return 0; - 1073 : - 1074 10073489 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); + 354 : tommy_tree fs_parity; + 355 : tommy_tree fs_file; + 356 : + 357 : /** + 358 : * Last chunk we accessed. + 359 : * It's used to optimize access of sequential blocks. + 360 : */ + 361 : struct snapraid_chunk* fs_last; + 362 : + 363 : /** + 364 : * List of all the snapraid_file for the disk. + 365 : */ + 366 : tommy_list filelist; + 367 : + 368 : /** + 369 : * List of all the deleted file for the disk. + 370 : * + 371 : * These files are kept allocated, because the blocks are still referenced in + 372 : * the ::blockarr. + 373 : */ + 374 : tommy_list deletedlist; + 375 : + 376 : tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */ + 377 : tommy_hashdyn pathset; /**< Hashtable by path of all the files. */ + 378 : tommy_hashdyn stampset; /**< Hashtable by stamp (size and time) of all the files. */ + 379 : tommy_list linklist; /**< List of all the links. */ + 380 : tommy_hashdyn linkset; /**< Hashtable by name of all the links. */ + 381 : tommy_list dirlist; /**< List of all the dirs. */ + 382 : tommy_hashdyn dirset; /**< Hashtable by name of all the dirs. */ + 383 : + 384 : /* nodes for data structures */ + 385 : tommy_node node; + 386 : }; + 387 : + 388 : /** + 389 : * Disk mapping. + 390 : */ + 391 : struct snapraid_map { + 392 : char name[PATH_MAX]; /**< Name of the disk. */ + 393 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ + 394 : block_off_t total_blocks; /**< Number of total blocks. */ + 395 : block_off_t free_blocks; /**< Number of free blocks at last 'sync'. */ + 396 : unsigned position; /**< Position of the disk in the parity. */ + 397 : + 398 : /* nodes for data structures */ + 399 : tommy_node node; + 400 : }; + 401 : + 402 : /** + 403 : * Parity. + 404 : */ + 405 : struct snapraid_parity { + 406 : char path[PATH_MAX]; /**< Path of the parity file. */ + 407 : char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ + 408 : char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ + 409 : uint64_t device; /**< Device identifier of the parity. */ + 410 : block_off_t total_blocks; /**< Number of total blocks. */ + 411 : block_off_t free_blocks; /**< Number of free blocks at the last sync. */ + 412 : int skip_access; /**< If the disk is inaccessible and it should be skipped. */ + 413 : int is_excluded; /**< If the parity is excluded by disk filter. */ + 414 : + 415 : /** + 416 : * Cumulative time used for parity disks. + 417 : */ + 418 : uint64_t tick; + 419 : }; + 420 : + 421 : /** + 422 : * Info. + 423 : */ + 424 : typedef uint32_t snapraid_info; + 425 : + 426 : /** + 427 : * Allocate a content. + 428 : */ + 429 : struct snapraid_content* content_alloc(const char* path, uint64_t dev); + 430 : + 431 : /** + 432 : * Deallocate a content. + 433 : */ + 434 : void content_free(struct snapraid_content* content); + 435 : + 436 : /** + 437 : * Allocate a filter pattern for files and directories. + 438 : */ + 439 : struct snapraid_filter* filter_alloc_file(int is_include, const char* pattern); + 440 : + 441 : /** + 442 : * Allocate a filter pattern for disks. + 443 : */ + 444 : struct snapraid_filter* filter_alloc_disk(int is_include, const char* pattern); + 445 : + 446 : /** + 447 : * Deallocate an exclusion. + 448 : */ + 449 : void filter_free(struct snapraid_filter* filter); + 450 : + 451 : /** + 452 : * Filter type description. + 453 : */ + 454 : const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size); + 455 : + 456 : /** + 457 : * Filter hidden files. + 458 : * Return !=0 if it matches and it should be excluded. + 459 : */ + 460 3114300 : static inline int filter_hidden(int enable, struct dirent* dd) + 461 : { + 462 3114300 : if (enable && dirent_hidden(dd)) { + 463 0 : return 1; /* filter out */ + 464 : } + 465 : + 466 3114300 : return 0; + 467 : } + 468 : + 469 : /** + 470 : * Filter a path using a list of filters. + 471 : * For each element of the path all the filters are applied, until the first one that matches. + 472 : * Return !=0 if it should be excluded. + 473 : */ + 474 : int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); + 475 : + 476 : /** + 477 : * Filter a file/link/dir if missing. + 478 : * This call imply a disk check for the file presence. + 479 : * Return !=0 if the file is present and it should be excluded. + 480 : */ + 481 : int filter_existence(int filter_missing, const char* dir, const char* sub); + 482 : + 483 : /** + 484 : * Filter a file if bad. + 485 : * Return !=0 if the file is correct and it should be excluded. + 486 : */ + 487 : int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file); + 488 : + 489 : /** + 490 : * Filter a dir using a list of filters. + 491 : * For each element of the path all the filters are applied, until the first one that matches. + 492 : * Return !=0 if should be excluded. + 493 : */ + 494 : int filter_dir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); + 495 : + 496 : /** + 497 : * Filter a path if it's a content file. + 498 : * Return !=0 if should be excluded. + 499 : */ + 500 : int filter_content(tommy_list* contentlist, const char* path); + 501 : + 502 : /** + 503 : * Check if the specified hash is invalid. + 504 : * + 505 : * An invalid hash is represented with all bytes at 0x00. + 506 : */ + 507 759605 : static inline int hash_is_invalid(const unsigned char* hash) + 508 : { + 509 : unsigned i; + 510 : + 511 1179159 : for (i = 0; i < HASH_SIZE; ++i) + 512 1153105 : if (hash[i] != 0x00) + 513 733551 : return 0; + 514 : + 515 26054 : return 1; + 516 : } + 517 : + 518 : /** + 519 : * Check if the specified hash represent the zero block. + 520 : * + 521 : * A zero hash is represented with all bytes at 0xFF. + 522 : */ + 523 761026 : static inline int hash_is_zero(const unsigned char* hash) + 524 : { + 525 : unsigned i; + 526 : + 527 994627 : for (i = 0; i < HASH_SIZE; ++i) + 528 980198 : if (hash[i] != 0xFF) + 529 746597 : return 0; + 530 : + 531 14429 : return 1; + 532 : } + 533 : + 534 : /** + 535 : * Check if the specified hash is a real hash. + 536 : */ + 537 44133 : static inline int hash_is_real(const unsigned char* hash) + 538 : { + 539 44133 : return !hash_is_zero(hash) && !hash_is_invalid(hash); + 540 : } + 541 : + 542 : /** + 543 : * Set the hash to the special INVALID value. + 544 : */ + 545 9036734 : static inline void hash_invalid_set(unsigned char* hash) + 546 : { + 547 9036734 : memset(hash, 0x00, HASH_SIZE); + 548 9036734 : } + 549 : + 550 : /** + 551 : * Set the hash to the special ZERO value. + 552 : */ + 553 115487 : static inline void hash_zero_set(unsigned char* hash) + 554 : { + 555 115487 : memset(hash, 0xFF, HASH_SIZE); + 556 115487 : } + 557 : + 558 : /** + 559 : * Get the state of the block. + 560 : * + 561 : * For this function, it's allowed to pass a NULL block + 562 : * pointer than results in the BLOCK_STATE_EMPTY state. + 563 : */ + 564 49967196 : static inline unsigned block_state_get(const struct snapraid_block* block) + 565 : { + 566 49967196 : if (block == BLOCK_EMPTY) + 567 1604566 : return BLOCK_STATE_EMPTY; + 568 : + 569 48362630 : return block->state; + 570 : } + 571 : + 572 : /** + 573 : * Set the state of the block. + 574 : */ + 575 18633161 : static inline void block_state_set(struct snapraid_block* block, unsigned state) + 576 : { + 577 18633161 : block->state = state; + 578 18633161 : } + 579 : + 580 : /** + 581 : * Check if the specified block has an updated hash. + 582 : * + 583 : * Note that EMPTY / CHG / DELETED return 0. + 584 : */ + 585 2075259 : static inline int block_has_updated_hash(const struct snapraid_block* block) + 586 : { + 587 2075259 : unsigned state = block_state_get(block); + 588 : + 589 2075259 : return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; + 590 : } + 591 : + 592 : /** + 593 : * Check if the specified block has a past hash, + 594 : * i.e. the hash of the data that it's now overwritten or lost. + 595 : * + 596 : * Note that EMPTY / BLK / REP return 0. + 597 : */ + 598 2401624 : static inline int block_has_past_hash(const struct snapraid_block* block) + 599 : { + 600 2401624 : unsigned state = block_state_get(block); + 601 : + 602 2401624 : return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED; + 603 : } + 604 : + 605 : /** + 606 : * Check if the specified block is part of a file. + 607 : * + 608 : * Note that EMPTY / DELETED return 0. + 609 : */ + 610 13243669 : static inline int block_has_file(const struct snapraid_block* block) + 611 : { + 612 13243669 : unsigned state = block_state_get(block); + 613 : + 614 13243669 : return state == BLOCK_STATE_BLK + 615 13243669 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 616 : } + 617 : + 618 : /** + 619 : * Check if the block has an invalid parity than needs to be updated. + 620 : * + 621 : * Note that EMPTY / BLK return 0. + 622 : */ + 623 11837218 : static inline int block_has_invalid_parity(const struct snapraid_block* block) + 624 : { + 625 11837218 : unsigned state = block_state_get(block); + 626 : + 627 11837218 : return state == BLOCK_STATE_DELETED + 628 11837218 : || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; + 629 : } + 630 : + 631 : /** + 632 : * Check if the block is part of a file with valid parity. + 633 : * + 634 : * Note that anything different than BLK return 0. + 635 : */ + 636 257893 : static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) + 637 : { + 638 257893 : unsigned state = block_state_get(block); + 639 : + 640 257893 : return state == BLOCK_STATE_BLK; + 641 : } + 642 : + 643 33706389 : static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) + 644 : { + 645 33706389 : return (file->flag & mask) == mask; + 646 : } + 647 : + 648 5250833 : static inline void file_flag_set(struct snapraid_file* file, unsigned mask) + 649 : { + 650 5250833 : file->flag |= mask; + 651 5250833 : } + 652 : + 653 20621 : static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) + 654 : { + 655 20621 : file->flag &= ~mask; + 656 20621 : } + 657 : + 658 : /** + 659 : * Allocate a file. + 660 : */ + 661 : struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical); + 662 : + 663 : /** + 664 : * Duplicate a file. + 665 : */ + 666 : struct snapraid_file* file_dup(struct snapraid_file* copy); + 667 : + 668 : /** + 669 : * Deallocate a file. + 670 : */ + 671 : void file_free(struct snapraid_file* file); + 672 : + 673 : /** + 674 : * Rename a file. + 675 : */ + 676 : void file_rename(struct snapraid_file* file, const char* sub); + 677 : + 678 : /** + 679 : * Copy a file. + 680 : */ + 681 : void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file); + 682 : + 683 : /** + 684 : * Return the name of the file, without the dir. + 685 : */ + 686 : const char* file_name(const struct snapraid_file* file); + 687 : + 688 : /** + 689 : * Check if the block is the last in the file. + 690 : */ + 691 : int file_block_is_last(struct snapraid_file* file, block_off_t file_pos); + 692 : + 693 : /** + 694 : * Get the size in bytes of the block. + 695 : * If it's the last block of a file it could be less than block_size. + 696 : */ + 697 : unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size); + 698 : + 699 : /** + 700 : * Compare a file with an inode. + 701 : */ + 702 : int file_inode_compare_to_arg(const void* void_arg, const void* void_data); + 703 : + 704 : /** + 705 : * Compare files by inode. + 706 : */ + 707 : int file_inode_compare(const void* void_a, const void* void_b); + 708 : + 709 : /** + 710 : * Compare files by path. + 711 : */ + 712 : int file_path_compare(const void* void_a, const void* void_b); + 713 : + 714 : /** + 715 : * Compare files by physical address. + 716 : */ + 717 : int file_physical_compare(const void* void_a, const void* void_b); + 718 : + 719 : /** + 720 : * Compute the hash of a file inode. + 721 : */ + 722 4924816 : static inline tommy_uint32_t file_inode_hash(uint64_t inode) + 723 : { + 724 4924816 : return (tommy_uint32_t)tommy_inthash_u64(inode); + 725 : } + 726 : + 727 : /** + 728 : * Compare a file with a path. + 729 : */ + 730 : int file_path_compare_to_arg(const void* void_arg, const void* void_data); + 731 : + 732 : /** + 733 : * Compare a file with another file for name, stamp, and both. + 734 : */ + 735 : int file_name_compare(const void* void_a, const void* void_b); + 736 : int file_stamp_compare(const void* void_a, const void* void_b); + 737 : int file_namestamp_compare(const void* void_a, const void* void_b); + 738 : int file_pathstamp_compare(const void* void_a, const void* void_b); + 739 : + 740 : /** + 741 : * Compute the hash of a file path. + 742 : */ + 743 3815727 : static inline tommy_uint32_t file_path_hash(const char* sub) + 744 : { + 745 3815727 : return tommy_hash_u32(0, sub, strlen(sub)); + 746 : } + 747 : + 748 : /** + 749 : * Compute the hash of a file stamp. + 750 : */ + 751 6198269 : static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) + 752 : { + 753 6198269 : return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); + 754 : } + 755 : + 756 : /** + 757 : * Allocate a chunk. + 758 : */ + 759 : struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count); + 760 : + 761 : /** + 762 : * Deallocate a chunk. + 763 : */ + 764 : void chunk_free(struct snapraid_chunk* chunk); + 765 : + 766 : /** + 767 : * Compare chunk by parity position. + 768 : */ + 769 : int chunk_parity_compare(const void* void_a, const void* void_b); + 770 : + 771 : /** + 772 : * Compare chunk by file and file position. + 773 : */ + 774 : int chunk_file_compare(const void* void_a, const void* void_b); + 775 : + 776 205548 : static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask) + 777 : { + 778 205548 : return (slink->flag & mask) == mask; + 779 : } + 780 : + 781 37571 : static inline void link_flag_set(struct snapraid_link* slink, unsigned mask) + 782 : { + 783 37571 : slink->flag |= mask; + 784 37571 : } + 785 : + 786 : static inline void link_flag_clear(struct snapraid_link* slink, unsigned mask) + 787 : { + 788 : slink->flag &= ~mask; + 789 : } + 790 : + 791 6 : static inline void link_flag_let(struct snapraid_link* slink, unsigned flag, unsigned mask) + 792 : { + 793 6 : slink->flag &= ~mask; + 794 6 : slink->flag |= flag & mask; + 795 6 : } + 796 : + 797 89637 : static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask) + 798 : { + 799 89637 : return slink->flag & mask; + 800 : } + 801 : + 802 : /** + 803 : * Allocate a link. + 804 : */ + 805 : struct snapraid_link* link_alloc(const char* name, const char* slink, unsigned link_flag); + 806 : + 807 : /** + 808 : * Deallocate a link. + 809 : */ + 810 : void link_free(struct snapraid_link* slink); + 811 : + 812 : /** + 813 : * Compare a link with a name. + 814 : */ + 815 : int link_name_compare_to_arg(const void* void_arg, const void* void_data); + 816 : + 817 : /** + 818 : * Compare links by path. + 819 : */ + 820 : int link_alpha_compare(const void* void_a, const void* void_b); + 821 : + 822 : /** + 823 : * Compute the hash of a link name. + 824 : */ + 825 151170 : static inline tommy_uint32_t link_name_hash(const char* name) + 826 : { + 827 151170 : return tommy_hash_u32(0, name, strlen(name)); + 828 : } + 829 : + 830 900 : static inline int dir_flag_has(const struct snapraid_dir* dir, unsigned mask) + 831 : { + 832 900 : return (dir->flag & mask) == mask; + 833 : } + 834 : + 835 247 : static inline void dir_flag_set(struct snapraid_dir* dir, unsigned mask) + 836 : { + 837 247 : dir->flag |= mask; + 838 247 : } + 839 : + 840 : static inline void dir_flag_clear(struct snapraid_dir* dir, unsigned mask) + 841 : { + 842 : dir->flag &= ~mask; + 843 : } + 844 : + 845 : /** + 846 : * Allocate a dir. + 847 : */ + 848 : struct snapraid_dir* dir_alloc(const char* name); + 849 : + 850 : /** + 851 : * Deallocate a dir. + 852 : */ + 853 : void dir_free(struct snapraid_dir* dir); + 854 : + 855 : /** + 856 : * Compare a dir with a name. + 857 : */ + 858 : int dir_name_compare(const void* void_arg, const void* void_data); + 859 : + 860 : /** + 861 : * Compute the hash of a dir name. + 862 : */ + 863 1011 : static inline tommy_uint32_t dir_name_hash(const char* name) + 864 : { + 865 1011 : return tommy_hash_u32(0, name, strlen(name)); + 866 : } + 867 : + 868 : /** + 869 : * Allocate a disk. + 870 : */ + 871 : struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip); + 872 : + 873 : /** + 874 : * Deallocate a disk. + 875 : */ + 876 : void disk_free(struct snapraid_disk* disk); + 877 : + 878 : /** + 879 : * Get the size of the disk in blocks. + 880 : */ + 881 : block_off_t disk_size(struct snapraid_disk* disk); + 882 : + 883 : /** + 884 : * Check if a disk is totally empty and can be discarded from the content file. + 885 : * A disk is empty if it doesn't contain any file, symlink, hardlink or dir + 886 : * and without any DELETED block. + 887 : * The blockmax is used to limit the search of DELETED block up to blockmax. + 888 : */ + 889 : int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax); + 890 : + 891 : /** + 892 : * Check the file-system for errors. + 893 : * Return 0 if it's OK. + 894 : */ + 895 : int fs_check(struct snapraid_disk* disk); + 896 : + 897 : /** + 898 : * Allocate a parity position for the specified file position. + 899 : * + 900 : * After this call you can use the par2file/par2block operations + 901 : * to query the relation. + 902 : * + 903 : * \note This function is NOT thread-safe as it uses the the disk cache. + + 904 : */ + 905 : void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos); + 906 : + 907 : /** + 908 : * Deallocate the parity position. + 909 : * + 910 : * After this call the par2file/par2block operations + 911 : * won't find anymore the parity association. + 912 : * + 913 : * \note This function is NOT thread-safe as it uses the the disk cache. + 914 : */ + 915 : void fs_deallocate(struct snapraid_disk* disk, block_off_t pos); + 916 : + 917 : /** + 918 : * Get the block from the file position. + 919 : */ + 920 : struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos); + 921 : + 922 : /** + 923 : * Like fs_file2par_get() but thread-safe. + 924 : */ + 925 : struct snapraid_file* fs_par2file_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos, block_off_t* file_pos); + 926 : + 927 : /** + 928 : * Get the file position from the parity position. + 929 : * Return 0 if no file is using it. + 930 : * \note This function is NOT thread-safe as it uses the the disk cache. + 931 : */ + 932 11578735 : static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) + 933 : { + 934 11578735 : return fs_par2file_get_ts(disk, &disk->fs_last, parity_pos, file_pos); + 935 : } + 936 : + 937 : /** + 938 : * Like fs_file2par_get() but thread-safe. + 939 : */ + 940 : block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, struct snapraid_file* file, block_off_t file_pos); + 941 : + 942 : /** + 943 : * Get the parity position from the file position. + 944 : * \note This function is NOT thread-safe as it uses the the disk cache. + 945 : */ + 946 519510 : static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) + 947 : { + 948 519510 : return fs_file2par_get_ts(disk, &disk->fs_last, file, file_pos); + 949 : } + 950 : + 951 : /** + 952 : * Like fs_par2block_get() but thread-safe. + 953 : */ + 954 : struct snapraid_block* fs_par2block_get_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t parity_pos); + 955 : + 956 : /** + 957 : * Get the block from the parity position. + 958 : * Return BLOCK_EMPTY==0 if the block is over the end of the disk or not used. + 959 : * \note This function is NOT thread-safe as it uses the the disk cache. + 960 : */ + 961 22209416 : static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk, block_off_t parity_pos) + 962 : { + 963 22209416 : return fs_par2block_get_ts(disk, &disk->fs_last, parity_pos); + 964 : } + 965 : + 966 : /** + 967 : * Allocate a disk mapping. + 968 : * Uses uuid="" if not available. + 969 : */ + 970 : struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid); + 971 : + 972 : /** + 973 : * Deallocate a disk mapping. + 974 : */ + 975 : void map_free(struct snapraid_map* map); + 976 : + 977 : /** + 978 : * Mask used to store additional information in the info bits. + 979 : * + 980 : * These bits reduce the granularity of the time in the memory representation. + 981 : */ + 982 : #define INFO_MASK 0x7 + 983 : + 984 : /** + 985 : * Make an info. + 986 : */ + 987 174394 : static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) + 988 : { + 989 : /* clear the lowest bits as reserved for other information */ + 990 174394 : snapraid_info info = last_access & ~INFO_MASK; + 991 : + 992 174394 : if (error != 0) + 993 5365 : info |= 0x1; + 994 174394 : if (rehash != 0) + 995 14409 : info |= 0x2; + 996 174394 : if (justsynced != 0) + 997 122709 : info |= 0x4; + 998 174394 : return info; + 999 : } + 1000 : + 1001 : /** + 1002 : * Extract the time information. + 1003 : * This is the last time when the block was know to be correct. + 1004 : * The "scrubbed" info tells if the time is referreing at the latest sync or scrub. + 1005 : */ + 1006 890086 : static inline time_t info_get_time(snapraid_info info) + 1007 : { + 1008 890086 : return info & ~INFO_MASK; + 1009 : } + 1010 : + 1011 : /** + 1012 : * Extract the error information. + 1013 : * Report if the block address had some problem. + 1014 : */ + 1015 338860 : static inline int info_get_bad(snapraid_info info) + 1016 : { + 1017 338860 : return (info & 0x1) != 0; + 1018 : } + 1019 : + 1020 : /** + 1021 : * Extract the rehash information. + 1022 : * Report if the block address is using the old hash and needs to be rehashed. + 1023 : */ + 1024 2058338 : static inline int info_get_rehash(snapraid_info info) + 1025 : { + 1026 2058338 : return (info & 0x2) != 0; + 1027 : } + 1028 : + 1029 : /** + 1030 : * Extract the scrubbed information. + 1031 : * Report if the block address was never scrubbed. + 1032 : */ + 1033 79285 : static inline int info_get_justsynced(snapraid_info info) + 1034 : { + 1035 79285 : return (info & 0x4) != 0; + 1036 : } + 1037 : + 1038 : /** + 1039 : * Mark the block address as with error. + 1040 : */ + 1041 1771 : static inline snapraid_info info_set_bad(snapraid_info info) + 1042 : { + 1043 1771 : return info | 0x1; + 1044 : } + 1045 : + 1046 : /** + 1047 : * Mark the block address as with rehash. + 1048 : */ + 1049 9207 : static inline snapraid_info info_set_rehash(snapraid_info info) + 1050 : { + 1051 9207 : return info | 0x2; + 1052 : } + 1053 : + 1054 : /** + 1055 : * Set the info at the specified position. + 1056 : * The position is allocated if not yet done. + 1057 : */ + 1058 1639782 : static inline void info_set(tommy_arrayblkof* array, unsigned pos, snapraid_info info) + 1059 : { + 1060 1639782 : tommy_arrayblkof_grow(array, pos + 1); + 1061 : + 1062 1639782 : memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); + 1063 1639782 : } + 1064 : + 1065 : /** + 1066 : * Get the info at the specified position. + 1067 : * For not allocated position, 0 is returned. + 1068 : */ + 1069 5104110 : static inline snapraid_info info_get(tommy_arrayblkof* array, unsigned pos) + 1070 : { + 1071 : snapraid_info info; + 1072 : + 1073 5104110 : if (pos >= tommy_arrayblkof_size(array)) + 1074 262738 : return 0; 1075 : - 1076 10085303 : return info; - 1077 : } - 1078 : - 1079 : /** - 1080 : * Compare times - 1081 : */ - 1082 : int time_compare(const void* void_a, const void* void_b); - 1083 : - 1084 : #endif + 1076 4841372 : memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); + 1077 : + 1078 4841372 : return info; + 1079 : } + 1080 : + 1081 : /** + 1082 : * Compare times + 1083 : */ + 1084 : int time_compare(const void* void_a, const void* void_b); 1085 : + 1086 : #endif + 1087 : diff --git a/cov/cmdline/handle.c.func-sort-c.html b/cov/cmdline/handle.c.func-sort-c.html index 364aeee3..2444eacb 100644 --- a/cov/cmdline/handle.c.func-sort-c.html +++ b/cov/cmdline/handle.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 125 - 128 + 126 + 129 97.7 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -61,35 +61,35 @@ handle_read - 5656394 + 5713632 handle_close - 4568631 + 4590919 handle_open - 1972488 + 2024387 handle_create - 771210 + 771290 handle_write - 288205 + 288532 handle_utime - 117763 + 119455 handle_truncate - 3249 + 3187 handle_map - 206 + 214
diff --git a/cov/cmdline/handle.c.func.html b/cov/cmdline/handle.c.func.html index f0a579bc..cb35a7e7 100644 --- a/cov/cmdline/handle.c.func.html +++ b/cov/cmdline/handle.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 125 - 128 + 126 + 129 97.7 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -61,35 +61,35 @@ handle_close - 4568631 + 4590919 handle_create - 771210 + 771290 handle_map - 206 + 214 handle_open - 1972488 + 2024387 handle_read - 5656394 + 5713632 handle_truncate - 3249 + 3187 handle_utime - 117763 + 119455 handle_write - 288205 + 288532
diff --git a/cov/cmdline/handle.c.gcov.html b/cov/cmdline/handle.c.gcov.html index 72e13a47..84f0dbae 100644 --- a/cov/cmdline/handle.c.gcov.html +++ b/cov/cmdline/handle.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 125 - 128 + 126 + 129 97.7 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -86,66 +86,66 @@ 24 : /****************************************************************************/ 25 : /* handle */ 26 : - 27 771210 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) + 27 771290 : int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) 28 : { 29 : int ret; 30 : int flags; 31 : 32 : /* if it's the same file, and already opened, nothing to do */ - 33 771210 : if (handle->file == file && handle->f != -1) { + 33 771290 : if (handle->file == file && handle->f != -1) { 34 0 : return 0; 35 : } 36 : - 37 771210 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 37 771290 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 38 : - 39 771210 : ret = mkancestor(handle->path); - 40 771210 : if (ret != 0) { + 39 771290 : ret = mkancestor(handle->path); + 40 771290 : if (ret != 0) { 41 : /* LCOV_EXCL_START */ 42 : return -1; 43 : /* LCOV_EXCL_STOP */ 44 : } 45 : 46 : /* initial values, changed later if required */ - 47 771210 : handle->created = 0; + 47 771290 : handle->created = 0; 48 : 49 : /* flags for opening */ 50 : /* O_BINARY: open as binary file (Windows only) */ 51 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ 52 : /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */ - 53 771210 : flags = O_BINARY | O_NOFOLLOW; - 54 771210 : if ((mode & MODE_SEQUENTIAL) != 0) - 55 771210 : flags |= O_SEQUENTIAL; + 53 771290 : flags = O_BINARY | O_NOFOLLOW; + 54 771290 : if ((mode & MODE_SEQUENTIAL) != 0) + 55 771290 : flags |= O_SEQUENTIAL; 56 : 57 : /* open for read write */ - 58 771210 : handle->f = open(handle->path, flags | O_RDWR); + 58 771290 : handle->f = open(handle->path, flags | O_RDWR); 59 : 60 : /* if failed for missing write permission */ - 61 771210 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { + 61 771290 : if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { 62 : /* open for real-only */ 63 0 : handle->f = open(handle->path, flags | O_RDONLY); 64 : } 65 : 66 : /* if failed for missing file */ - 67 771210 : if (handle->f == -1 && errno == ENOENT) { + 67 771290 : if (handle->f == -1 && errno == ENOENT) { 68 : char path_from[PATH_MAX]; 69 : 70 : /* check if exists a .unrecoverable copy, and rename to the real one */ - 71 176420 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); + 71 176470 : pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); 72 : - 73 176420 : if (rename(path_from, handle->path) == 0) { + 73 176470 : if (rename(path_from, handle->path) == 0) { 74 : /* open for read write */ - 75 63396 : handle->f = open(handle->path, flags | O_RDWR); + 75 63363 : handle->f = open(handle->path, flags | O_RDWR); 76 : } else { 77 : /* create it */ - 78 113024 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); - 79 113024 : if (handle->f != -1) { + 78 113107 : handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); + 79 113107 : if (handle->f != -1) { 80 : /* mark it as created if really done */ - 81 113024 : handle->created = 1; + 81 113107 : handle->created = 1; 82 : } 83 : } 84 : } 85 : - 86 771210 : if (handle->f == -1) { + 86 771290 : if (handle->f == -1) { 87 : /* LCOV_EXCL_START */ 88 : /* invalidate for error */ 89 : handle->file = 0; @@ -158,11 +158,11 @@ 96 : } 97 : 98 : /* just opened */ - 99 771210 : handle->file = file; + 99 771290 : handle->file = file; 100 : 101 : /* get the stat info */ - 102 771210 : ret = fstat(handle->f, &handle->st); - 103 771210 : if (ret != 0) { + 102 771290 : ret = fstat(handle->f, &handle->st); + 103 771290 : if (ret != 0) { 104 : /* LCOV_EXCL_START */ 105 : log_fatal("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); 106 : return -1; @@ -170,13 +170,13 @@ 108 : } 109 : 110 : /* get the size of the existing data */ - 111 771210 : handle->valid_size = handle->st.st_size; + 111 771290 : handle->valid_size = handle->st.st_size; 112 : 113 : #if HAVE_POSIX_FADVISE - 114 771210 : if ((mode & MODE_SEQUENTIAL) != 0) { + 114 771290 : if ((mode & MODE_SEQUENTIAL) != 0) { 115 : /* advise sequential access */ - 116 771210 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); - 117 771210 : if (ret != 0) { + 116 771290 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); + 117 771290 : if (ret != 0) { 118 : /* LCOV_EXCL_START */ 119 : log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(ret)); 120 : return -1; @@ -185,15 +185,15 @@ 123 : } 124 : #endif 125 : - 126 771210 : return 0; + 126 771290 : return 0; 127 : } 128 : - 129 3249 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) + 129 3187 : int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) 130 : { 131 : int ret; 132 : - 133 3249 : ret = ftruncate(handle->f, file->size); - 134 3249 : if (ret != 0) { + 133 3187 : ret = ftruncate(handle->f, file->size); + 134 3187 : if (ret != 0) { 135 : /* LCOV_EXCL_START */ 136 : if (errno == EACCES) { 137 : log_fatal("Failed to truncate file '%s' for missing write permission.\n", handle->path); @@ -205,58 +205,58 @@ 143 : } 144 : 145 : /* adjust the size to the truncated size */ - 146 3249 : handle->valid_size = file->size; + 146 3187 : handle->valid_size = file->size; 147 : - 148 3249 : return 0; + 148 3187 : return 0; 149 : } 150 : - 151 1972488 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing) + 151 2024387 : int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing) 152 : { 153 : int ret; 154 : int flags; 155 : - 156 1972488 : if (!out_missing) - 157 1971972 : out_missing = out; + 156 2024387 : if (!out_missing) + 157 2023815 : out_missing = out; 158 : 159 : /* if already opened, nothing to do */ - 160 1972488 : if (handle->file == file && handle->f != -1) { - 161 332290 : return 0; + 160 2024387 : if (handle->file == file && handle->f != -1) { + 161 363056 : return 0; 162 : } 163 : - 164 1640198 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + 164 1661331 : pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); 165 : 166 : /* for sure not created */ - 167 1640198 : handle->created = 0; + 167 1661331 : handle->created = 0; 168 : 169 : /* flags for opening */ 170 : /* O_BINARY: open as binary file (Windows only) */ 171 : /* O_NOFOLLOW: do not follow links to ensure to open the real file */ 172 : /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */ - 173 1640198 : flags = O_BINARY | O_NOFOLLOW; - 174 1640198 : if ((mode & MODE_SEQUENTIAL) != 0) - 175 1628870 : flags |= O_SEQUENTIAL; + 173 1661331 : flags = O_BINARY | O_NOFOLLOW; + 174 1661331 : if ((mode & MODE_SEQUENTIAL) != 0) + 175 1649996 : flags |= O_SEQUENTIAL; 176 : 177 : /* open for read */ - 178 1640198 : handle->f = open_noatime(handle->path, flags | O_RDONLY); - 179 1640198 : if (handle->f == -1) { + 178 1661331 : handle->f = open_noatime(handle->path, flags | O_RDONLY); + 179 1661331 : if (handle->f == -1) { 180 : /* invalidate for error */ - 181 78777 : handle->file = 0; - 182 78777 : handle->f = -1; - 183 78777 : handle->valid_size = 0; + 181 78781 : handle->file = 0; + 182 78781 : handle->f = -1; + 183 78781 : handle->valid_size = 0; 184 : - 185 78777 : if (errno == ENOENT) - 186 78765 : out_missing("Missing file '%s'.\n", handle->path); + 185 78781 : if (errno == ENOENT) + 186 78769 : out_missing("Missing file '%s'.\n", handle->path); 187 : else 188 12 : out("Error opening file '%s'. %s.\n", handle->path, strerror(errno)); - 189 78777 : return -1; + 189 78781 : return -1; 190 : } 191 : 192 : /* just opened */ - 193 1561421 : handle->file = file; + 193 1582550 : handle->file = file; 194 : 195 : /* get the stat info */ - 196 1561421 : ret = fstat(handle->f, &handle->st); - 197 1561421 : if (ret != 0) { + 196 1582550 : ret = fstat(handle->f, &handle->st); + 197 1582550 : if (ret != 0) { 198 : /* LCOV_EXCL_START */ 199 : out("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); 200 : return -1; @@ -264,13 +264,13 @@ 202 : } 203 : 204 : /* get the size of the existing data */ - 205 1561421 : handle->valid_size = handle->st.st_size; + 205 1582550 : handle->valid_size = handle->st.st_size; 206 : 207 : #if HAVE_POSIX_FADVISE - 208 1561421 : if ((mode & MODE_SEQUENTIAL) != 0) { + 208 1582550 : if ((mode & MODE_SEQUENTIAL) != 0) { 209 : /* advise sequential access */ - 210 1550093 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); - 211 1550093 : if (ret != 0) { + 210 1571215 : ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); + 211 1571215 : if (ret != 0) { 212 : /* LCOV_EXCL_START */ 213 : out("Error advising file '%s'. %s.\n", handle->path, strerror(ret)); 214 : return -1; @@ -279,17 +279,17 @@ 217 : } 218 : #endif 219 : - 220 1561421 : return 0; + 220 1582550 : return 0; 221 : } 222 : - 223 4568631 : int handle_close(struct snapraid_handle* handle) + 223 4590919 : int handle_close(struct snapraid_handle* handle) 224 : { 225 : int ret; 226 : 227 : /* close if open */ - 228 4568631 : if (handle->f != -1) { - 229 2332631 : ret = close(handle->f); - 230 2332631 : if (ret != 0) { + 228 4590919 : if (handle->f != -1) { + 229 2353840 : ret = close(handle->f); + 230 2353840 : if (ret != 0) { 231 : /* LCOV_EXCL_START */ 232 : log_fatal("Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 233 : @@ -303,36 +303,36 @@ 241 : } 242 : 243 : /* reset the descriptor */ - 244 4568631 : handle->file = 0; - 245 4568631 : handle->f = -1; - 246 4568631 : handle->valid_size = 0; + 244 4590919 : handle->file = 0; + 245 4590919 : handle->f = -1; + 246 4590919 : handle->valid_size = 0; 247 : - 248 4568631 : return 0; + 248 4590919 : return 0; 249 : } 250 : - 251 5656394 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing) + 251 5713632 : int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing) 252 : { 253 : ssize_t read_ret; 254 : data_off_t offset; 255 : unsigned read_size; 256 : unsigned count; 257 : - 258 5656394 : offset = file_pos * (data_off_t)block_size; + 258 5713632 : offset = file_pos * (data_off_t)block_size; 259 : - 260 5656394 : if (!out_missing) - 261 5642993 : out_missing = out; + 260 5713632 : if (!out_missing) + 261 5700398 : out_missing = out; 262 : 263 : /* check if we are going to read only not initialized data */ - 264 5656394 : if (offset >= handle->valid_size) { + 264 5713632 : if (offset >= handle->valid_size) { 265 : /* if the file is missing, it's at 0 size, or it's rebuilt while reading */ - 266 433131 : if (offset == handle->valid_size || handle->valid_size == 0) - 267 431906 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 266 433671 : if (offset == handle->valid_size || handle->valid_size == 0) + 267 432378 : out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset); 268 : else - 269 1225 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); - 270 433131 : return -1; + 269 1293 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + 270 433671 : return -1; 271 : } 272 : - 273 5223263 : read_size = file_block_size(handle->file, file_pos, block_size); + 273 5279961 : read_size = file_block_size(handle->file, file_pos, block_size); 274 : 275 : #if !HAVE_PREAD 276 : if (lseek(handle->f, offset, SEEK_SET) != offset) { @@ -343,32 +343,32 @@ 281 : } 282 : #endif 283 : - 284 5223263 : count = 0; + 284 5279961 : count = 0; 285 : do { 286 : 287 : #if HAVE_PREAD - 288 5232157 : read_ret = pread(handle->f, block_buffer + count, read_size - count, offset + count); + 288 5288816 : read_ret = pread(handle->f, block_buffer + count, read_size - count, offset + count); 289 : #else 290 : read_ret = read(handle->f, block_buffer + count, read_size - count); 291 : #endif 292 : - 293 5232157 : if (read_ret < 0) { + 293 5288816 : if (read_ret < 0) { 294 : /* LCOV_EXCL_START */ 295 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, read_size - count, strerror(errno)); 296 : return -1; 297 : /* LCOV_EXCL_STOP */ 298 : } - 299 5232157 : if (read_ret == 0) { - 300 8894 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno)); - 301 8894 : return -1; + 299 5288816 : if (read_ret == 0) { + 300 8855 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno)); + 301 8855 : return -1; 302 : } 303 : - 304 5223263 : count += read_ret; - 305 5223263 : } while (count < read_size); + 304 5279961 : count += read_ret; + 305 5279961 : } while (count < read_size); 306 : 307 : /* pad with 0 */ - 308 5214369 : if (read_size < block_size) { - 309 2112031 : memset(block_buffer + read_size, 0, block_size - read_size); + 308 5271106 : if (read_size < block_size) { + 309 2132322 : memset(block_buffer + read_size, 0, block_size - read_size); 310 : } 311 : 312 : /* Here isn't needed to call posix_fadvise(..., POSIX_FADV_DONTNEED) */ @@ -382,21 +382,21 @@ 320 : /* at: https://lkml.org/lkml/2010/12/6/122 */ 321 : /* We relay only on the automatic readahead triggered by POSIX_FADV_SEQUENTIAL. */ 322 : - 323 5214369 : return read_size; + 323 5271106 : return read_size; 324 : } 325 : - 326 288205 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) + 326 288532 : int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) 327 : { 328 : ssize_t write_ret; 329 : data_off_t offset; 330 : unsigned write_size; 331 : - 332 288205 : offset = file_pos * (data_off_t)block_size; + 332 288532 : offset = file_pos * (data_off_t)block_size; 333 : - 334 288205 : write_size = file_block_size(handle->file, file_pos, block_size); + 334 288532 : write_size = file_block_size(handle->file, file_pos, block_size); 335 : 336 : #if HAVE_PWRITE - 337 288205 : write_ret = pwrite(handle->f, block_buffer, write_size, offset); + 337 288532 : write_ret = pwrite(handle->f, block_buffer, write_size, offset); 338 : #else 339 : if (lseek(handle->f, offset, SEEK_SET) != offset) { 340 : /* LCOV_EXCL_START */ @@ -407,7 +407,7 @@ 345 : 346 : write_ret = write(handle->f, block_buffer, write_size); 347 : #endif - 348 288205 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */ + 348 288532 : if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */ 349 : /* LCOV_EXCL_START */ 350 : log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno)); 351 : return -1; @@ -415,88 +415,89 @@ 353 : } 354 : 355 : /* adjust the size of the valid data */ - 356 288205 : if (handle->valid_size < offset + write_size) { - 357 282174 : handle->valid_size = offset + write_size; + 356 288532 : if (handle->valid_size < offset + write_size) { + 357 282422 : handle->valid_size = offset + write_size; 358 : } 359 : 360 : /* Here doesn't make sense to call posix_fadvise(..., POSIX_FADV_DONTNEED) because */ 361 : /* at this time the data is still not yet written and it cannot be discharged. */ 362 : - 363 288205 : return 0; + 363 288532 : return 0; 364 : } 365 : - 366 117763 : int handle_utime(struct snapraid_handle* handle) + 366 119455 : int handle_utime(struct snapraid_handle* handle) 367 : { 368 : int ret; 369 : 370 : /* do nothing if not opened */ - 371 117763 : if (handle->f == -1) + 371 119455 : if (handle->f == -1) 372 0 : return 0; 373 : - 374 117763 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); + 374 119455 : ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); 375 : - 376 117763 : if (ret != 0) { + 376 119455 : if (ret != 0) { 377 : /* LCOV_EXCL_START */ 378 : log_fatal("Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno)); 379 : return -1; 380 : /* LCOV_EXCL_STOP */ 381 : } 382 : - 383 117763 : return 0; + 383 119455 : return 0; 384 : } 385 : - 386 206 : struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax) + 386 214 : struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax) 387 : { 388 : tommy_node* i; 389 : unsigned j; - 390 206 : unsigned size = 0; + 390 214 : unsigned size = 0; 391 : struct snapraid_handle* handle; 392 : 393 : /* get the size of the mapping */ - 394 206 : size = 0; - 395 1437 : for (i = state->maplist; i != 0; i = i->next) { - 396 1231 : struct snapraid_map* map = i->data; - 397 1231 : if (map->position > size) - 398 895 : size = map->position; + 394 214 : size = 0; + 395 1493 : for (i = state->maplist; i != 0; i = i->next) { + 396 1279 : struct snapraid_map* map = i->data; + 397 1279 : if (map->position > size) + 398 925 : size = map->position; 399 : } - 400 206 : ++size; /* size is one more than the max */ + 400 214 : ++size; /* size is one more than the max */ 401 : - 402 206 : handle = malloc_nofail(size * sizeof(struct snapraid_handle)); + 402 214 : handle = malloc_nofail(size * sizeof(struct snapraid_handle)); 403 : - 404 1442 : for (j = 0; j < size; ++j) { + 404 1498 : for (j = 0; j < size; ++j) { 405 : /* default for empty position */ - 406 1236 : handle[j].disk = 0; - 407 1236 : handle[j].file = 0; - 408 1236 : handle[j].f = -1; - 409 1236 : handle[j].valid_size = 0; + 406 1284 : handle[j].disk = 0; + 407 1284 : handle[j].file = 0; + 408 1284 : handle[j].f = -1; + 409 1284 : handle[j].valid_size = 0; 410 : } 411 : 412 : /* set the vector */ - 413 1437 : for (i = state->disklist; i != 0; i = i->next) { + 413 1493 : for (i = state->disklist; i != 0; i = i->next) { 414 : struct snapraid_map* map; - 415 1231 : struct snapraid_disk* disk = i->data; + 415 1279 : struct snapraid_disk* disk = i->data; 416 : tommy_node* k; 417 : 418 : /* search the mapping for this disk */ - 419 4296 : for (k = state->maplist; k != 0; k = k->next) { - 420 4296 : map = k->data; - 421 4296 : if (strcmp(disk->name, map->name) == 0) - 422 1231 : break; - 423 : } - 424 1231 : if (k == 0) { - 425 : /* LCOV_EXCL_START */ - 426 : log_fatal("Internal error for inconsistent disk mapping.\n"); - 427 : exit(EXIT_FAILURE); - 428 : /* LCOV_EXCL_STOP */ - 429 : } - 430 : - 431 1231 : handle[map->position].disk = disk; - 432 : } - 433 : - 434 206 : *handlemax = size; - 435 206 : return handle; - 436 : } - 437 : + 419 1279 : map = 0; + 420 4464 : for (k = state->maplist; k != 0; k = k->next) { + 421 4464 : map = k->data; + 422 4464 : if (strcmp(disk->name, map->name) == 0) + 423 1279 : break; + 424 : } + 425 1279 : if (!map) { + 426 : /* LCOV_EXCL_START */ + 427 : log_fatal("Internal error for inconsistent disk mapping.\n"); + 428 : os_abort(); + 429 : /* LCOV_EXCL_STOP */ + 430 : } + 431 : + 432 1279 : handle[map->position].disk = disk; + 433 : } + 434 : + 435 214 : *handlemax = size; + 436 214 : return handle; + 437 : } + 438 : diff --git a/cov/cmdline/import.c.func-sort-c.html b/cov/cmdline/import.c.func-sort-c.html index 4ed3e003..fc384422 100644 --- a/cov/cmdline/import.c.func-sort-c.html +++ b/cov/cmdline/import.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 103 + 95 105 - 98.1 % + 90.5 % Date: - 2015-11-20 + 2016-01-09 Functions: + 7 8 - 8 - 100.0 % + 87.5 % @@ -61,36 +61,36 @@ import_block_hash - 652942 + 657660 - state_import_fetch - 643998 - - - import_block_prevhash_compare - 2238 + state_import_fetch + 653188 import_block_hash_compare - 2234 + 4472 - import_file + import_file 1750 - import_file_free + import_file_free 1750 - state_import + state_import 1 - import_dir + import_dir 1 + + import_block_prevhash_compare + 0 +
diff --git a/cov/cmdline/import.c.func.html b/cov/cmdline/import.c.func.html index 00f16958..c081b511 100644 --- a/cov/cmdline/import.c.func.html +++ b/cov/cmdline/import.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 103 + 95 105 - 98.1 % + 90.5 % Date: - 2015-11-20 + 2016-01-09 Functions: + 7 8 - 8 - 100.0 % + 87.5 % @@ -61,35 +61,35 @@ import_block_hash - 652942 + 657660 import_block_hash_compare - 2234 + 4472 import_block_prevhash_compare - 2238 + 0 - import_dir + import_dir 1 - import_file + import_file 1750 - import_file_free + import_file_free 1750 - state_import + state_import 1 - state_import_fetch - 643998 + state_import_fetch + 653188
diff --git a/cov/cmdline/import.c.gcov.html b/cov/cmdline/import.c.gcov.html index 0cec9c66..a3d12909 100644 --- a/cov/cmdline/import.c.gcov.html +++ b/cov/cmdline/import.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 103 + 95 105 - 98.1 % + 90.5 % Date: - 2015-11-20 + 2016-01-09 Functions: + 7 8 - 8 - 100.0 % + 87.5 % @@ -88,303 +88,304 @@ 26 : /** 27 : * Compare the hash of two import blocks. 28 : */ - 29 2234 : int import_block_hash_compare(const void* void_arg, const void* void_data) + 29 4472 : int import_block_hash_compare(const void* void_arg, const void* void_data) 30 : { - 31 2234 : const unsigned char* arg = void_arg; - 32 2234 : const struct snapraid_import_block* block = void_data; + 31 4472 : const unsigned char* arg = void_arg; + 32 4472 : const struct snapraid_import_block* block = void_data; 33 : - 34 2234 : return memcmp(arg, block->hash, HASH_SIZE); + 34 4472 : return memcmp(arg, block->hash, HASH_SIZE); 35 : } 36 : - 37 2238 : int import_block_prevhash_compare(const void* void_arg, const void* void_data) + 37 0 : int import_block_prevhash_compare(const void* void_arg, const void* void_data) 38 : { - 39 2238 : const unsigned char* arg = void_arg; - 40 2238 : const struct snapraid_import_block* block = void_data; + 39 0 : const unsigned char* arg = void_arg; + 40 0 : const struct snapraid_import_block* block = void_data; 41 : - 42 2238 : return memcmp(arg, block->prevhash, HASH_SIZE); + 42 0 : return memcmp(arg, block->prevhash, HASH_SIZE); 43 : } 44 : 45 : /** 46 : * Compute the hash of the hash for an import block. 47 : * We just use the first 32 bit of the hash itself. 48 : */ - 49 652942 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash) + 49 657660 : static inline tommy_uint32_t import_block_hash(const unsigned char* hash) 50 : { - 51 652942 : return *(const tommy_uint32_t*)hash; - 52 : } - 53 : - 54 1750 : static void import_file(struct snapraid_state* state, const char* path, uint64_t size) - 55 : { - 56 : struct snapraid_import_file* file; - 57 : block_off_t i; - 58 : data_off_t offset; - 59 : void* buffer; - 60 : int ret; - 61 : int f; - 62 : int flags; - 63 1750 : unsigned block_size = state->block_size; - 64 : - 65 1750 : file = malloc_nofail(sizeof(struct snapraid_import_file)); - 66 1750 : file->path = strdup_nofail(path); - 67 1750 : file->size = size; - 68 1750 : file->blockmax = (size + block_size - 1) / block_size; - 69 1750 : file->blockimp = malloc_nofail(file->blockmax * sizeof(struct snapraid_import_block)); - 70 : - 71 1750 : buffer = malloc_nofail(block_size); - 72 : - 73 : /* open for read */ - 74 : /* O_SEQUENTIAL: opening in sequential mode in Windows */ - 75 1750 : flags = O_RDONLY | O_BINARY; - 76 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) - 77 1750 : flags |= O_SEQUENTIAL; - 78 1750 : f = open(path, flags); - 79 1750 : if (f == -1) { - 80 : /* LCOV_EXCL_START */ - 81 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); - 82 : exit(EXIT_FAILURE); - 83 : /* LCOV_EXCL_STOP */ - 84 : } - 85 : - 86 : #if HAVE_POSIX_FADVISE - 87 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) { - 88 : /* advise sequential access */ - 89 1750 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); - 90 1750 : if (ret != 0) { - 91 : /* LCOV_EXCL_START */ - 92 : log_fatal("Error advising file '%s'. %s.\n", path, strerror(ret)); - 93 : exit(EXIT_FAILURE); - 94 : /* LCOV_EXCL_STOP */ - 95 : } - 96 : } - 97 : #endif - 98 : - 99 1750 : offset = 0; - 100 6222 : for (i = 0; i < file->blockmax; ++i) { - 101 4472 : struct snapraid_import_block* block = &file->blockimp[i]; - 102 4472 : unsigned read_size = block_size; - 103 4472 : if (read_size > size) - 104 1745 : read_size = size; - 105 : - 106 4472 : ret = read(f, buffer, read_size); - 107 4472 : if (ret < 0 || (unsigned)ret != read_size) { - 108 : /* LCOV_EXCL_START */ - 109 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); - 110 : exit(EXIT_FAILURE); - 111 : /* LCOV_EXCL_STOP */ - 112 : } - 113 : - 114 4472 : block->file = file; - 115 4472 : block->offset = offset; - 116 4472 : block->size = read_size; - 117 : - 118 4472 : memhash(state->hash, state->hashseed, block->hash, buffer, read_size); - 119 4472 : tommy_hashdyn_insert(&state->importset, &block->nodeset, block, import_block_hash(block->hash)); - 120 : - 121 : /* if we are in a rehash state */ - 122 4472 : if (state->prevhash != HASH_UNDEFINED) { - 123 : /* compute also the previous hash */ - 124 4472 : memhash(state->prevhash, state->prevhashseed, block->prevhash, buffer, read_size); - 125 4472 : tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash)); - 126 : } - 127 : - 128 4472 : offset += read_size; - 129 4472 : size -= read_size; - 130 : } - 131 : - 132 1750 : ret = close(f); - 133 1750 : if (ret != 0) { - 134 : /* LCOV_EXCL_START */ - 135 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); - 136 : exit(EXIT_FAILURE); - 137 : /* LCOV_EXCL_STOP */ - 138 : } - 139 : - 140 1750 : tommy_list_insert_tail(&state->importlist, &file->nodelist, file); - 141 : - 142 1750 : free(buffer); - 143 1750 : } - 144 : - 145 1750 : void import_file_free(struct snapraid_import_file* file) - 146 : { - 147 1750 : free(file->path); - 148 1750 : free(file->blockimp); - 149 1750 : free(file); - 150 1750 : } - 151 : - 152 643998 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) - 153 : { - 154 : struct snapraid_import_block* block; - 155 : int ret; - 156 : int f; - 157 643998 : const unsigned char* hash = missing_block->hash; - 158 643998 : unsigned block_size = state->block_size; - 159 : unsigned read_size; - 160 : unsigned char buffer_hash[HASH_SIZE]; - 161 : const char* path; - 162 : - 163 643998 : if (rehash) { - 164 28986 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash)); - 165 : } else { - 166 615012 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); - 167 : } - 168 643998 : if (!block) - 169 639526 : return -1; - 170 : - 171 4472 : path = block->file->path; - 172 4472 : read_size = block->size; - 173 : - 174 4472 : f = open(path, O_RDONLY | O_BINARY); - 175 4472 : if (f == -1) { - 176 : /* LCOV_EXCL_START */ - 177 : if (errno == ENOENT) { - 178 : log_fatal("DANGER! file '%s' disappeared.\n", path); - 179 : log_fatal("If you moved it, please rerun the same command.\n"); - 180 : } else { - 181 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); - 182 : } - 183 : exit(EXIT_FAILURE); - 184 : /* LCOV_EXCL_STOP */ - 185 : } - 186 : - 187 4472 : if (lseek(f, block->offset, SEEK_SET) != block->offset) { - 188 : /* LCOV_EXCL_START */ - 189 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno)); - 190 : exit(EXIT_FAILURE); - 191 : /* LCOV_EXCL_STOP */ - 192 : } - 193 : - 194 4472 : ret = read(f, buffer, read_size); - 195 4472 : if (ret < 0 || (unsigned)ret != read_size) { - 196 : /* LCOV_EXCL_START */ - 197 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); - 198 : exit(EXIT_FAILURE); - 199 : /* LCOV_EXCL_STOP */ - 200 : } - 201 : - 202 4472 : ret = close(f); - 203 4472 : if (ret != 0) { - 204 : /* LCOV_EXCL_START */ - 205 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); - 206 : exit(EXIT_FAILURE); - 207 : /* LCOV_EXCL_STOP */ - 208 : } - 209 : - 210 4472 : if (read_size != block_size) { - 211 : /* fill the remaining with 0 */ - 212 1745 : memset(buffer + read_size, 0, block_size - read_size); - 213 : } - 214 : - 215 : /* recheck the hash */ - 216 4472 : if (rehash) - 217 2238 : memhash(state->prevhash, state->prevhashseed, buffer_hash, buffer, read_size); - 218 : else - 219 2234 : memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size); - 220 : - 221 4472 : if (memcmp(buffer_hash, hash, HASH_SIZE) != 0) { - 222 : /* LCOV_EXCL_START */ - 223 : log_fatal("Error in data reading file '%s'.\n", path); - 224 : log_fatal("Please don't change imported files while running.\n"); - 225 : exit(EXIT_FAILURE); - 226 : /* LCOV_EXCL_STOP */ - 227 : } - 228 : - 229 4472 : return 0; - 230 : } - 231 : - 232 1 : static void import_dir(struct snapraid_state* state, const char* dir) - 233 : { - 234 : DIR* d; - 235 : - 236 1 : d = opendir(dir); - 237 1 : if (!d) { - 238 : /* LCOV_EXCL_START */ - 239 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); - 240 : exit(EXIT_FAILURE); - 241 : /* LCOV_EXCL_STOP */ - 242 : } - 243 : - 244 : while (1) { - 245 : char path_next[PATH_MAX]; - 246 : struct stat st; - 247 : const char* name; - 248 : struct dirent* dd; - 249 : - 250 : /* clear errno to detect erroneous conditions */ - 251 1812 : errno = 0; - 252 1812 : dd = readdir(d); - 253 1812 : if (dd == 0 && errno != 0) { - 254 : /* LCOV_EXCL_START */ - 255 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); - 256 : exit(EXIT_FAILURE); - 257 : /* LCOV_EXCL_STOP */ - 258 : } - 259 1812 : if (dd == 0) { - 260 1 : break; /* finished */ - 261 : } - 262 : - 263 : /* skip "." and ".." files */ - 264 1811 : name = dd->d_name; - 265 1811 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) - 266 2 : continue; - 267 : - 268 1809 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 269 : - 270 : #if HAVE_STRUCT_DIRENT_D_STAT - 271 : /* convert dirent to lstat result */ - 272 : dirent_lstat(dd, &st); - 273 : - 274 : /* if the st_mode field is missing, takes care to fill it using normal lstat() */ - 275 : /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */ - 276 : /* because we use a directory reading method that doesn't read info about ReparsePoint. */ - 277 : /* Note that here we cannot call here lstat_sync(), because we don't know what kind */ - 278 : /* of file is it, and lstat_sync() doesn't always work */ - 279 : if (st.st_mode == 0) { - 280 : if (lstat(path_next, &st) != 0) { - 281 : /* LCOV_EXCL_START */ - 282 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); - 283 : exit(EXIT_FAILURE); - 284 : /* LCOV_EXCL_STOP */ - 285 : } - 286 : } - 287 : #else - 288 : /* get lstat info about the file */ - 289 1809 : if (lstat(path_next, &st) != 0) { - 290 : /* LCOV_EXCL_START */ - 291 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); - 292 : exit(EXIT_FAILURE); - 293 : /* LCOV_EXCL_STOP */ - 294 : } - 295 : #endif - 296 : - 297 1809 : if (S_ISREG(st.st_mode)) { - 298 1750 : import_file(state, path_next, st.st_size); - 299 59 : } else if (S_ISDIR(st.st_mode)) { - 300 0 : pathslash(path_next, sizeof(path_next)); - 301 0 : import_dir(state, path_next); - 302 : } - 303 1811 : } - 304 : - 305 1 : if (closedir(d) != 0) { - 306 : /* LCOV_EXCL_START */ - 307 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); - 308 : exit(EXIT_FAILURE); - 309 : /* LCOV_EXCL_STOP */ - 310 : } - 311 1 : } - 312 : - 313 1 : void state_import(struct snapraid_state* state, const char* dir) - 314 : { - 315 : char path[PATH_MAX]; - 316 : - 317 1 : msg_progress("Importing...\n"); - 318 : - 319 : /* add the final slash */ - 320 1 : pathimport(path, sizeof(path), dir); - 321 1 : pathslash(path, sizeof(path)); - 322 : - 323 1 : import_dir(state, path); - 324 1 : } - 325 : + 51 : /* the hash data is not aligned, and we cannot access it with a direct cast */ + 52 657660 : return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24); + 53 : } + 54 : + 55 1750 : static void import_file(struct snapraid_state* state, const char* path, uint64_t size) + 56 : { + 57 : struct snapraid_import_file* file; + 58 : block_off_t i; + 59 : data_off_t offset; + 60 : void* buffer; + 61 : int ret; + 62 : int f; + 63 : int flags; + 64 1750 : unsigned block_size = state->block_size; + 65 : + 66 1750 : file = malloc_nofail(sizeof(struct snapraid_import_file)); + 67 1750 : file->path = strdup_nofail(path); + 68 1750 : file->size = size; + 69 1750 : file->blockmax = (size + block_size - 1) / block_size; + 70 1750 : file->blockimp = malloc_nofail(file->blockmax * sizeof(struct snapraid_import_block)); + 71 : + 72 1750 : buffer = malloc_nofail(block_size); + 73 : + 74 : /* open for read */ + 75 : /* O_SEQUENTIAL: opening in sequential mode in Windows */ + 76 1750 : flags = O_RDONLY | O_BINARY; + 77 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) + 78 1750 : flags |= O_SEQUENTIAL; + 79 1750 : f = open(path, flags); + 80 1750 : if (f == -1) { + 81 : /* LCOV_EXCL_START */ + 82 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + 83 : exit(EXIT_FAILURE); + 84 : /* LCOV_EXCL_STOP */ + 85 : } + 86 : + 87 : #if HAVE_POSIX_FADVISE + 88 1750 : if ((state->file_mode & MODE_SEQUENTIAL) != 0) { + 89 : /* advise sequential access */ + 90 1750 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + 91 1750 : if (ret != 0) { + 92 : /* LCOV_EXCL_START */ + 93 : log_fatal("Error advising file '%s'. %s.\n", path, strerror(ret)); + 94 : exit(EXIT_FAILURE); + 95 : /* LCOV_EXCL_STOP */ + 96 : } + 97 : } + 98 : #endif + 99 : + 100 1750 : offset = 0; + 101 6222 : for (i = 0; i < file->blockmax; ++i) { + 102 4472 : struct snapraid_import_block* block = &file->blockimp[i]; + 103 4472 : unsigned read_size = block_size; + 104 4472 : if (read_size > size) + 105 1745 : read_size = size; + 106 : + 107 4472 : ret = read(f, buffer, read_size); + 108 4472 : if (ret < 0 || (unsigned)ret != read_size) { + 109 : /* LCOV_EXCL_START */ + 110 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); + 111 : exit(EXIT_FAILURE); + 112 : /* LCOV_EXCL_STOP */ + 113 : } + 114 : + 115 4472 : block->file = file; + 116 4472 : block->offset = offset; + 117 4472 : block->size = read_size; + 118 : + 119 4472 : memhash(state->hash, state->hashseed, block->hash, buffer, read_size); + 120 4472 : tommy_hashdyn_insert(&state->importset, &block->nodeset, block, import_block_hash(block->hash)); + 121 : + 122 : /* if we are in a rehash state */ + 123 4472 : if (state->prevhash != HASH_UNDEFINED) { + 124 : /* compute also the previous hash */ + 125 0 : memhash(state->prevhash, state->prevhashseed, block->prevhash, buffer, read_size); + 126 0 : tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash)); + 127 : } + 128 : + 129 4472 : offset += read_size; + 130 4472 : size -= read_size; + 131 : } + 132 : + 133 1750 : ret = close(f); + 134 1750 : if (ret != 0) { + 135 : /* LCOV_EXCL_START */ + 136 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + 137 : exit(EXIT_FAILURE); + 138 : /* LCOV_EXCL_STOP */ + 139 : } + 140 : + 141 1750 : tommy_list_insert_tail(&state->importlist, &file->nodelist, file); + 142 : + 143 1750 : free(buffer); + 144 1750 : } + 145 : + 146 1750 : void import_file_free(struct snapraid_import_file* file) + 147 : { + 148 1750 : free(file->path); + 149 1750 : free(file->blockimp); + 150 1750 : free(file); + 151 1750 : } + 152 : + 153 653188 : int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) + 154 : { + 155 : struct snapraid_import_block* block; + 156 : int ret; + 157 : int f; + 158 653188 : const unsigned char* hash = missing_block->hash; + 159 653188 : unsigned block_size = state->block_size; + 160 : unsigned read_size; + 161 : unsigned char buffer_hash[HASH_SIZE]; + 162 : const char* path; + 163 : + 164 653188 : if (rehash) { + 165 0 : block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash)); + 166 : } else { + 167 653188 : block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); + 168 : } + 169 653188 : if (!block) + 170 648716 : return -1; + 171 : + 172 4472 : path = block->file->path; + 173 4472 : read_size = block->size; + 174 : + 175 4472 : f = open(path, O_RDONLY | O_BINARY); + 176 4472 : if (f == -1) { + 177 : /* LCOV_EXCL_START */ + 178 : if (errno == ENOENT) { + 179 : log_fatal("DANGER! file '%s' disappeared.\n", path); + 180 : log_fatal("If you moved it, please rerun the same command.\n"); + 181 : } else { + 182 : log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + 183 : } + 184 : exit(EXIT_FAILURE); + 185 : /* LCOV_EXCL_STOP */ + 186 : } + 187 : + 188 4472 : if (lseek(f, block->offset, SEEK_SET) != block->offset) { + 189 : /* LCOV_EXCL_START */ + 190 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno)); + 191 : exit(EXIT_FAILURE); + 192 : /* LCOV_EXCL_STOP */ + 193 : } + 194 : + 195 4472 : ret = read(f, buffer, read_size); + 196 4472 : if (ret < 0 || (unsigned)ret != read_size) { + 197 : /* LCOV_EXCL_START */ + 198 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); + 199 : exit(EXIT_FAILURE); + 200 : /* LCOV_EXCL_STOP */ + 201 : } + 202 : + 203 4472 : ret = close(f); + 204 4472 : if (ret != 0) { + 205 : /* LCOV_EXCL_START */ + 206 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + 207 : exit(EXIT_FAILURE); + 208 : /* LCOV_EXCL_STOP */ + 209 : } + 210 : + 211 4472 : if (read_size != block_size) { + 212 : /* fill the remaining with 0 */ + 213 1745 : memset(buffer + read_size, 0, block_size - read_size); + 214 : } + 215 : + 216 : /* recheck the hash */ + 217 4472 : if (rehash) + 218 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, buffer, read_size); + 219 : else + 220 4472 : memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size); + 221 : + 222 4472 : if (memcmp(buffer_hash, hash, HASH_SIZE) != 0) { + 223 : /* LCOV_EXCL_START */ + 224 : log_fatal("Error in data reading file '%s'.\n", path); + 225 : log_fatal("Please don't change imported files while running.\n"); + 226 : exit(EXIT_FAILURE); + 227 : /* LCOV_EXCL_STOP */ + 228 : } + 229 : + 230 4472 : return 0; + 231 : } + 232 : + 233 1 : static void import_dir(struct snapraid_state* state, const char* dir) + 234 : { + 235 : DIR* d; + 236 : + 237 1 : d = opendir(dir); + 238 1 : if (!d) { + 239 : /* LCOV_EXCL_START */ + 240 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); + 241 : exit(EXIT_FAILURE); + 242 : /* LCOV_EXCL_STOP */ + 243 : } + 244 : + 245 : while (1) { + 246 : char path_next[PATH_MAX]; + 247 : struct stat st; + 248 : const char* name; + 249 : struct dirent* dd; + 250 : + 251 : /* clear errno to detect erroneous conditions */ + 252 1812 : errno = 0; + 253 1812 : dd = readdir(d); + 254 1812 : if (dd == 0 && errno != 0) { + 255 : /* LCOV_EXCL_START */ + 256 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); + 257 : exit(EXIT_FAILURE); + 258 : /* LCOV_EXCL_STOP */ + 259 : } + 260 1812 : if (dd == 0) { + 261 1 : break; /* finished */ + 262 : } + 263 : + 264 : /* skip "." and ".." files */ + 265 1811 : name = dd->d_name; + 266 1811 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 267 2 : continue; + 268 : + 269 1809 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 270 : + 271 : #if HAVE_STRUCT_DIRENT_D_STAT + 272 : /* convert dirent to lstat result */ + 273 : dirent_lstat(dd, &st); + 274 : + 275 : /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + 276 : /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */ + 277 : /* because we use a directory reading method that doesn't read info about ReparsePoint. */ + 278 : /* Note that here we cannot call here lstat_sync(), because we don't know what kind */ + 279 : /* of file is it, and lstat_sync() doesn't always work */ + 280 : if (st.st_mode == 0) { + 281 : if (lstat(path_next, &st) != 0) { + 282 : /* LCOV_EXCL_START */ + 283 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + 284 : exit(EXIT_FAILURE); + 285 : /* LCOV_EXCL_STOP */ + 286 : } + 287 : } + 288 : #else + 289 : /* get lstat info about the file */ + 290 1809 : if (lstat(path_next, &st) != 0) { + 291 : /* LCOV_EXCL_START */ + 292 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + 293 : exit(EXIT_FAILURE); + 294 : /* LCOV_EXCL_STOP */ + 295 : } + 296 : #endif + 297 : + 298 1809 : if (S_ISREG(st.st_mode)) { + 299 1750 : import_file(state, path_next, st.st_size); + 300 59 : } else if (S_ISDIR(st.st_mode)) { + 301 0 : pathslash(path_next, sizeof(path_next)); + 302 0 : import_dir(state, path_next); + 303 : } + 304 1811 : } + 305 : + 306 1 : if (closedir(d) != 0) { + 307 : /* LCOV_EXCL_START */ + 308 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); + 309 : exit(EXIT_FAILURE); + 310 : /* LCOV_EXCL_STOP */ + 311 : } + 312 1 : } + 313 : + 314 1 : void state_import(struct snapraid_state* state, const char* dir) + 315 : { + 316 : char path[PATH_MAX]; + 317 : + 318 1 : msg_progress("Importing...\n"); + 319 : + 320 : /* add the final slash */ + 321 1 : pathimport(path, sizeof(path), dir); + 322 1 : pathslash(path, sizeof(path)); + 323 : + 324 1 : import_dir(state, path); + 325 1 : } + 326 : diff --git a/cov/cmdline/index-sort-f.html b/cov/cmdline/index-sort-f.html index 7e050b55..4610da17 100644 --- a/cov/cmdline/index-sort-f.html +++ b/cov/cmdline/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 7344 - 8033 - 91.4 % + 7401 + 8084 + 91.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 388 - 397 - 97.7 % + 390 + 401 + 97.3 % @@ -69,6 +69,16 @@ Line Coverage Sort by line coverage Functions Sort by function coverage + + import.c + +
90.5%90.5%
+ + 90.5 % + 95 / 105 + 87.5 % + 7 / 8 + parity.c @@ -92,22 +102,32 @@ unix.c -
79.2%79.2%
+
76.8%76.8%
- 79.2 % - 229 / 289 - 91.3 % - 21 / 23 + 76.8 % + 255 / 332 + 92.0 % + 23 / 25 support.c -
79.2%79.2%
+
79.7%79.7%
- 79.2 % - 232 / 293 - 93.5 % - 29 / 31 + 79.7 % + 240 / 301 + 93.8 % + 30 / 32 + + + stream.c + +
91.8%91.8%
+ + 91.8 % + 257 / 280 + 96.4 % + 27 / 28 elem.c @@ -115,19 +135,19 @@
93.8%93.8%
93.8 % - 545 / 581 + 546 / 582 96.9 % 62 / 64 state.c -
92.4%92.4%
+
92.6%92.6%
- 92.4 % - 1248 / 1351 - 97.2 % - 35 / 36 + 92.6 % + 1262 / 1363 + 97.3 % + 36 / 37 nano.c @@ -292,70 +312,60 @@ search.c -
92.0%92.0%
+
91.0%91.0%
- 92.0 % - 92 / 100 + 91.0 % + 91 / 100 100.0 % 7 / 7 - - import.c - -
98.1%98.1%
- - 98.1 % - 103 / 105 - 100.0 % - 8 / 8 - handle.c
97.7%97.7%
97.7 % - 125 / 128 + 126 / 129 100.0 % 8 / 8 selftest.c -
83.7%83.7%
+
100.0%
- 83.7 % - 144 / 172 + 100.0 % + 144 / 144 100.0 % 8 / 8 snapraid.c -
94.1%94.1%
+
93.8%93.8%
- 94.1 % - 446 / 474 + 93.8 % + 454 / 484 100.0 % 8 / 8 check.c -
91.3%91.3%
+
91.2%91.2%
- 91.3 % - 713 / 781 + 91.2 % + 712 / 781 100.0 % 9 / 9 device.c -
94.3%94.3%
+
94.1%94.1%
- 94.3 % - 300 / 318 + 94.1 % + 301 / 320 100.0 % 11 / 11 @@ -382,23 +392,13 @@ scan.c -
87.4%87.4%
+
89.1%89.1%
- 87.4 % - 542 / 620 + 89.1 % + 554 / 622 100.0 % 23 / 23 - - stream.c - -
93.2%93.2%
- - 93.2 % - 261 / 280 - 100.0 % - 28 / 28 - elem.h diff --git a/cov/cmdline/index-sort-l.html b/cov/cmdline/index-sort-l.html index 8aa34497..e8ea2475 100644 --- a/cov/cmdline/index-sort-l.html +++ b/cov/cmdline/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 7344 - 8033 - 91.4 % + 7401 + 8084 + 91.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 388 - 397 - 97.7 % + 390 + 401 + 97.3 % @@ -70,14 +70,14 @@ Functions Sort by function coverage - support.c + unix.c -
79.2%79.2%
+
76.8%76.8%
- 79.2 % - 232 / 293 - 93.5 % - 29 / 31 + 76.8 % + 255 / 332 + 92.0 % + 23 / 25 parity.c @@ -89,16 +89,6 @@ 90.9 % 10 / 11 - - unix.c - -
79.2%79.2%
- - 79.2 % - 229 / 289 - 91.3 % - 21 / 23 - scrub.c @@ -110,14 +100,14 @@ 4 / 4 - selftest.c + support.c -
83.7%83.7%
+
79.7%79.7%
- 83.7 % - 144 / 172 - 100.0 % - 8 / 8 + 79.7 % + 240 / 301 + 93.8 % + 30 / 32 dry.c @@ -132,10 +122,10 @@ scan.c -
87.4%87.4%
+
89.1%89.1%
- 87.4 % - 542 / 620 + 89.1 % + 554 / 622 100.0 % 23 / 23 @@ -150,34 +140,54 @@ 10 / 11 - check.c + import.c -
91.3%91.3%
+
90.5%90.5%
- 91.3 % - 713 / 781 - 100.0 % - 9 / 9 + 90.5 % + 95 / 105 + 87.5 % + 7 / 8 search.c -
92.0%92.0%
+
91.0%91.0%
- 92.0 % - 92 / 100 + 91.0 % + 91 / 100 100.0 % 7 / 7 + + check.c + +
91.2%91.2%
+ + 91.2 % + 712 / 781 + 100.0 % + 9 / 9 + + + stream.c + +
91.8%91.8%
+ + 91.8 % + 257 / 280 + 96.4 % + 27 / 28 + state.c -
92.4%92.4%
+
92.6%92.6%
- 92.4 % - 1248 / 1351 - 97.2 % - 35 / 36 + 92.6 % + 1262 / 1363 + 97.3 % + 36 / 37 sync.c @@ -199,16 +209,6 @@ 100.0 % 18 / 18 - - stream.c - -
93.2%93.2%
- - 93.2 % - 261 / 280 - 100.0 % - 28 / 28 - util.h @@ -229,25 +229,35 @@ 100.0 % 5 / 5 + + snapraid.c + +
93.8%93.8%
+ + 93.8 % + 454 / 484 + 100.0 % + 8 / 8 + elem.c
93.8%93.8%
93.8 % - 545 / 581 + 546 / 582 96.9 % 62 / 64 - snapraid.c + device.c
94.1%94.1%
94.1 % - 446 / 474 + 301 / 320 100.0 % - 8 / 8 + 11 / 11 pool.c @@ -259,16 +269,6 @@ 100.0 % 3 / 3 - - device.c - -
94.3%94.3%
- - 94.3 % - 300 / 318 - 100.0 % - 11 / 11 - rehash.c @@ -305,17 +305,7 @@
97.7%97.7%
97.7 % - 125 / 128 - 100.0 % - 8 / 8 - - - import.c - -
98.1%98.1%
- - 98.1 % - 103 / 105 + 126 / 129 100.0 % 8 / 8 @@ -409,6 +399,16 @@ 100.0 % 2 / 2 + + selftest.c + +
100.0%
+ + 100.0 % + 144 / 144 + 100.0 % + 8 / 8 +
diff --git a/cov/cmdline/index.html b/cov/cmdline/index.html index 8449d375..852332c6 100644 --- a/cov/cmdline/index.html +++ b/cov/cmdline/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 7344 - 8033 - 91.4 % + 7401 + 8084 + 91.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 388 - 397 - 97.7 % + 390 + 401 + 97.3 % @@ -72,20 +72,20 @@ check.c -
91.3%91.3%
+
91.2%91.2%
- 91.3 % - 713 / 781 + 91.2 % + 712 / 781 100.0 % 9 / 9 device.c -
94.3%94.3%
+
94.1%94.1%
- 94.3 % - 300 / 318 + 94.1 % + 301 / 320 100.0 % 11 / 11 @@ -115,7 +115,7 @@
93.8%93.8%
93.8 % - 545 / 581 + 546 / 582 96.9 % 62 / 64 @@ -135,19 +135,19 @@
97.7%97.7%
97.7 % - 125 / 128 + 126 / 129 100.0 % 8 / 8 import.c -
98.1%98.1%
+
90.5%90.5%
- 98.1 % - 103 / 105 - 100.0 % - 8 / 8 + 90.5 % + 95 / 105 + 87.5 % + 7 / 8 list.c @@ -242,10 +242,10 @@ scan.c -
87.4%87.4%
+
89.1%89.1%
- 87.4 % - 542 / 620 + 89.1 % + 554 / 622 100.0 % 23 / 23 @@ -262,30 +262,30 @@ search.c -
92.0%92.0%
+
91.0%91.0%
- 92.0 % - 92 / 100 + 91.0 % + 91 / 100 100.0 % 7 / 7 selftest.c -
83.7%83.7%
+
100.0%
- 83.7 % - 144 / 172 + 100.0 % + 144 / 144 100.0 % 8 / 8 snapraid.c -
94.1%94.1%
+
93.8%93.8%
- 94.1 % - 446 / 474 + 93.8 % + 454 / 484 100.0 % 8 / 8 @@ -312,12 +312,12 @@ state.c -
92.4%92.4%
+
92.6%92.6%
- 92.4 % - 1248 / 1351 - 97.2 % - 35 / 36 + 92.6 % + 1262 / 1363 + 97.3 % + 36 / 37 state.h @@ -342,12 +342,12 @@ stream.c -
93.2%93.2%
+
91.8%91.8%
- 93.2 % - 261 / 280 - 100.0 % - 28 / 28 + 91.8 % + 257 / 280 + 96.4 % + 27 / 28 stream.h @@ -362,12 +362,12 @@ support.c -
79.2%79.2%
+
79.7%79.7%
- 79.2 % - 232 / 293 - 93.5 % - 29 / 31 + 79.7 % + 240 / 301 + 93.8 % + 30 / 32 sync.c @@ -382,12 +382,12 @@ unix.c -
79.2%79.2%
+
76.8%76.8%
- 79.2 % - 229 / 289 - 91.3 % - 21 / 23 + 76.8 % + 255 / 332 + 92.0 % + 23 / 25 util.c diff --git a/cov/cmdline/list.c.func-sort-c.html b/cov/cmdline/list.c.func-sort-c.html index 8a842797..a1d33ff3 100644 --- a/cov/cmdline/list.c.func-sort-c.html +++ b/cov/cmdline/list.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/list.c.func.html b/cov/cmdline/list.c.func.html index 6de816a4..77720432 100644 --- a/cov/cmdline/list.c.func.html +++ b/cov/cmdline/list.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/list.c.gcov.html b/cov/cmdline/list.c.gcov.html index 6d26e742..41e63009 100644 --- a/cov/cmdline/list.c.gcov.html +++ b/cov/cmdline/list.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -110,34 +110,34 @@ 48 18 : tommy_list_sort(&disk->filelist, file_path_compare); 49 : 50 : /* for each file */ - 51 16998 : for (j = disk->filelist; j != 0; j = j->next) { - 52 16980 : struct snapraid_file* file = j->data; + 51 17012 : for (j = disk->filelist; j != 0; j = j->next) { + 52 16994 : struct snapraid_file* file = j->data; 53 : #if HAVE_LOCALTIME_R 54 : struct tm tm_res; 55 : #endif 56 : struct tm* tm; 57 : time_t t; 58 : - 59 16980 : ++file_count; - 60 16980 : file_size += file->size; + 59 16994 : ++file_count; + 60 16994 : file_size += file->size; 61 : - 62 16980 : log_tag("file:%s:%s:%" PRIu64 ":%" PRIi64 ":%u:%" PRIi64 "\n", disk->name, esc(file->sub), file->size, file->mtime_sec, file->mtime_nsec, file->inode); + 62 16994 : log_tag("file:%s:%s:%" PRIu64 ":%" PRIi64 ":%u:%" PRIi64 "\n", disk->name, esc(file->sub), file->size, file->mtime_sec, file->mtime_nsec, file->inode); 63 : - 64 16980 : t = file->mtime_sec; + 64 16994 : t = file->mtime_sec; 65 : #if HAVE_LOCALTIME_R - 66 16980 : tm = localtime_r(&t, &tm_res); + 66 16994 : tm = localtime_r(&t, &tm_res); 67 : #else 68 : tm = localtime(&t); 69 : #endif 70 : - 71 16980 : printf("%12" PRIu64 " ", file->size); - 72 16980 : if (tm) { - 73 16980 : printf("%04u/%02u/%02u %02u:%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min); - 74 16980 : if (msg_level >= MSG_VERBOSE) - 75 16980 : printf(":%02u.%03u", tm->tm_sec, file->mtime_nsec / 1000000); - 76 16980 : printf(" "); + 71 16994 : printf("%12" PRIu64 " ", file->size); + 72 16994 : if (tm) { + 73 16994 : printf("%04u/%02u/%02u %02u:%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min); + 74 16994 : if (msg_level >= MSG_VERBOSE) + 75 16994 : printf(":%02u.%03u", tm->tm_sec, file->mtime_nsec / 1000000); + 76 16994 : printf(" "); 77 : } - 78 16980 : printf("%s%s\n", disk->dir, file->sub); + 78 16994 : printf("%s%s\n", disk->dir, file->sub); 79 : } 80 : 81 : /* sort by name */ diff --git a/cov/cmdline/mkstream.c.func-sort-c.html b/cov/cmdline/mkstream.c.func-sort-c.html index 0ef05fdf..e22bee50 100644 --- a/cov/cmdline/mkstream.c.func-sort-c.html +++ b/cov/cmdline/mkstream.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/cmdline/mkstream.c.func.html b/cov/cmdline/mkstream.c.func.html index bd99773d..5b87fdd6 100644 --- a/cov/cmdline/mkstream.c.func.html +++ b/cov/cmdline/mkstream.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/cmdline/mkstream.c.gcov.html b/cov/cmdline/mkstream.c.gcov.html index f02e9bf5..7c9b10f2 100644 --- a/cov/cmdline/mkstream.c.gcov.html +++ b/cov/cmdline/mkstream.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/cmdline/mktest.c.func-sort-c.html b/cov/cmdline/mktest.c.func-sort-c.html index 60c06d2d..2268a650 100644 --- a/cov/cmdline/mktest.c.func-sort-c.html +++ b/cov/cmdline/mktest.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 18 @@ -61,23 +61,23 @@ rnd - 50988385 + 50969532 rndnz - 50578180 + 50559223 file_cmp - 146608 + 146593 rndnz_range - 31195 + 31151 rnd_name - 26824 + 26849 cmd_generate @@ -93,19 +93,19 @@ cmd_write - 4703 - - - cmd_append - 3252 + 4719 cmd_delete - 3155 + 3209 + + + cmd_append + 3192 cmd_truncate - 3151 + 3139 cmd_damage @@ -121,7 +121,7 @@ cmd_generate_symlink - 915 + 940 main diff --git a/cov/cmdline/mktest.c.func.html b/cov/cmdline/mktest.c.func.html index 96c88f25..3b8f65ae 100644 --- a/cov/cmdline/mktest.c.func.html +++ b/cov/cmdline/mktest.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 18 @@ -61,7 +61,7 @@ cmd_append - 3252 + 3192 cmd_change @@ -73,7 +73,7 @@ cmd_delete - 3155 + 3209 cmd_generate @@ -85,15 +85,15 @@ cmd_generate_symlink - 915 + 940 cmd_truncate - 3151 + 3139 cmd_write - 4703 + 4719 fallback @@ -101,7 +101,7 @@ file_cmp - 146608 + 146593 help @@ -113,15 +113,15 @@ rnd - 50988385 + 50969532 rnd_name - 26824 + 26849 rndnz - 50578180 + 50559223 rndnz_damage @@ -129,7 +129,7 @@ rndnz_range - 31195 + 31151
diff --git a/cov/cmdline/mktest.c.gcov.html b/cov/cmdline/mktest.c.gcov.html index 501823e9..2f63044d 100644 --- a/cov/cmdline/mktest.c.gcov.html +++ b/cov/cmdline/mktest.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 18 @@ -89,28 +89,28 @@ 27 : */ 28 : unsigned long long seed = 0; 29 : - 30 50988385 : unsigned rnd(unsigned max) + 30 50969532 : unsigned rnd(unsigned max) 31 : { - 32 50988385 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; + 32 50969532 : seed = seed * 6364136223846793005LL + 1442695040888963407LL; 33 : - 34 50988385 : return (seed >> 32) % max; + 34 50969532 : return (seed >> 32) % max; 35 : } 36 : - 37 50578180 : unsigned rndnz(unsigned max) + 37 50559223 : unsigned rndnz(unsigned max) 38 : { - 39 50578180 : if (max <= 1) + 39 50559223 : if (max <= 1) 40 2831 : return 1; 41 : else - 42 50575349 : return rnd(max - 1) + 1; + 42 50556392 : return rnd(max - 1) + 1; 43 : } 44 : - 45 31195 : void rndnz_range(unsigned char* data, int size) + 45 31151 : void rndnz_range(unsigned char* data, int size) 46 : { 47 : int i; 48 : - 49 50604116 : for (i = 0; i < size; ++i) - 50 50572921 : data[i] = rndnz(256); - 51 31195 : } + 49 50585115 : for (i = 0; i < size; ++i) + 50 50553964 : data[i] = rndnz(256); + 51 31151 : } 52 : 53 1821 : void rndnz_damage(unsigned char* data, int size) 54 : { @@ -131,23 +131,23 @@ 69 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+"; 70 : #define CHARSET_LEN (sizeof(CHARSET) - 1) 71 : - 72 26824 : void rnd_name(char* file) + 72 26849 : void rnd_name(char* file) 73 : { - 74 26824 : int l = 1 + rnd(20); + 74 26849 : int l = 1 + rnd(20); 75 : - 76 335360 : while (l) { - 77 281712 : *file++ = CHARSET[rnd(CHARSET_LEN)]; - 78 281712 : --l; + 76 335469 : while (l) { + 77 281771 : *file++ = CHARSET[rnd(CHARSET_LEN)]; + 78 281771 : --l; 79 : } - 80 26824 : *file = 0; - 81 26824 : } + 80 26849 : *file = 0; + 81 26849 : } 82 : 83 : /****************************************************************************/ 84 : /* file */ 85 : - 86 146608 : int file_cmp(const void* a, const void* b) + 86 146593 : int file_cmp(const void* a, const void* b) 87 : { - 88 146608 : return strcmp(a, b); + 88 146593 : return strcmp(a, b); 89 : } 90 : 91 1821 : int fallback(int f, struct stat* st) @@ -259,11 +259,11 @@ 197 : * Create a symlink. 198 : * - If the file already exists, it's removed. 199 : */ - 200 915 : void cmd_generate_symlink(const char* path, const char* linkto) + 200 940 : void cmd_generate_symlink(const char* path, const char* linkto) 201 : { 202 : /* remove the existing file/symlink if any */ - 203 915 : if (remove(path) != 0) { - 204 894 : if (errno != ENOENT) { + 203 940 : if (remove(path) != 0) { + 204 919 : if (errno != ENOENT) { 205 : /* LCOV_EXCL_START */ 206 : log_fatal("Error removing file %s\n", path); 207 : exit(EXIT_FAILURE); @@ -271,13 +271,13 @@ 209 : } 210 : } 211 : - 212 915 : if (symlink(linkto, path) != 0) { + 212 940 : if (symlink(linkto, path) != 0) { 213 : /* LCOV_EXCL_START */ 214 : log_fatal("Error writing symlink %s\n", path); 215 : exit(EXIT_FAILURE); 216 : /* LCOV_EXCL_STOP */ 217 : } - 218 915 : } + 218 940 : } 219 : 220 : /** 221 : * Create a file or a symlink with a random name. @@ -350,68 +350,68 @@ 288 : * - The written data may be equal or not at the already existing one. 289 : * - If it's a symlink nothing is done. 290 : */ - 291 4703 : void cmd_write(const char* path, int size) + 291 4719 : void cmd_write(const char* path, int size) 292 : { 293 : struct stat st; 294 : - 295 4703 : if (lstat(path, &st) != 0) { + 295 4719 : if (lstat(path, &st) != 0) { 296 : /* LCOV_EXCL_START */ 297 : log_fatal("Error accessing %s\n", path); 298 : exit(EXIT_FAILURE); 299 : /* LCOV_EXCL_STOP */ 300 : } 301 : - 302 4703 : if (S_ISREG(st.st_mode)) { + 302 4719 : if (S_ISREG(st.st_mode)) { 303 : unsigned char* data; 304 : off_t off; 305 : int f; 306 : 307 : /* not over the end */ - 308 4676 : if (size > st.st_size) - 309 179 : size = st.st_size; + 308 4692 : if (size > st.st_size) + 309 175 : size = st.st_size; 310 : 311 : /* start at random position inside the file */ - 312 4676 : if (size < st.st_size) - 313 4496 : off = rnd(st.st_size - size); + 312 4692 : if (size < st.st_size) + 313 4517 : off = rnd(st.st_size - size); 314 : else - 315 180 : off = 0; + 315 175 : off = 0; 316 : - 317 4676 : data = malloc(size); + 317 4692 : data = malloc(size); 318 : - 319 4676 : rndnz_range(data, size); + 319 4692 : rndnz_range(data, size); 320 : - 321 4676 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 322 4676 : if (f < 0) { + 321 4692 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 322 4692 : if (f < 0) { 323 : /* LCOV_EXCL_START */ 324 : log_fatal("Error creating file %s\n", path); 325 : exit(EXIT_FAILURE); 326 : /* LCOV_EXCL_STOP */ 327 : } 328 : - 329 4676 : if (lseek(f, off, SEEK_SET) != off) { + 329 4692 : if (lseek(f, off, SEEK_SET) != off) { 330 : /* LCOV_EXCL_START */ 331 : log_fatal("Error seeking file %s\n", path); 332 : exit(EXIT_FAILURE); 333 : /* LCOV_EXCL_STOP */ 334 : } 335 : - 336 4676 : if (write(f, data, size) != size) { + 336 4692 : if (write(f, data, size) != size) { 337 : /* LCOV_EXCL_START */ 338 : log_fatal("Error writing file %s\n", path); 339 : exit(EXIT_FAILURE); 340 : /* LCOV_EXCL_STOP */ 341 : } 342 : - 343 4676 : if (close(f) != 0) { + 343 4692 : if (close(f) != 0) { 344 : /* LCOV_EXCL_START */ 345 : log_fatal("Error closing file %s\n", path); 346 : exit(EXIT_FAILURE); 347 : /* LCOV_EXCL_STOP */ 348 : } 349 : - 350 4676 : free(data); + 350 4692 : free(data); 351 : } - 352 4703 : } + 352 4719 : } 353 : 354 : /** 355 : * Damage a file. @@ -518,50 +518,50 @@ 456 : * - The file must exist. 457 : * - If it's a symlink nothing is done. 458 : */ - 459 3252 : void cmd_append(const char* path, int size) + 459 3192 : void cmd_append(const char* path, int size) 460 : { 461 : struct stat st; 462 : - 463 3252 : if (lstat(path, &st) != 0) { + 463 3192 : if (lstat(path, &st) != 0) { 464 : /* LCOV_EXCL_START */ 465 : log_fatal("Error accessing %s\n", path); 466 : exit(EXIT_FAILURE); 467 : /* LCOV_EXCL_STOP */ 468 : } 469 : - 470 3252 : if (S_ISREG(st.st_mode)) { + 470 3192 : if (S_ISREG(st.st_mode)) { 471 : unsigned char* data; 472 : int f; 473 : - 474 3252 : data = malloc(size); + 474 3192 : data = malloc(size); 475 : - 476 3252 : rndnz_range(data, size); + 476 3192 : rndnz_range(data, size); 477 : - 478 3252 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); - 479 3252 : if (f < 0) { + 478 3192 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); + 479 3192 : if (f < 0) { 480 : /* LCOV_EXCL_START */ 481 : log_fatal("Error opening file %s\n", path); 482 : exit(EXIT_FAILURE); 483 : /* LCOV_EXCL_STOP */ 484 : } 485 : - 486 3252 : if (write(f, data, size) != size) { + 486 3192 : if (write(f, data, size) != size) { 487 : /* LCOV_EXCL_START */ 488 : log_fatal("Error writing file %s\n", path); 489 : exit(EXIT_FAILURE); 490 : /* LCOV_EXCL_STOP */ 491 : } 492 : - 493 3252 : if (close(f) != 0) { + 493 3192 : if (close(f) != 0) { 494 : /* LCOV_EXCL_START */ 495 : log_fatal("Error closing file %s\n", path); 496 : exit(EXIT_FAILURE); 497 : /* LCOV_EXCL_STOP */ 498 : } 499 : - 500 3252 : free(data); + 500 3192 : free(data); 501 : } - 502 3252 : } + 502 3192 : } 503 : 504 : /** 505 : * Truncate a file. @@ -569,69 +569,69 @@ 507 : * - The file is NEVER truncated to 0. 508 : * - If it's a symlink nothing is done. 509 : */ - 510 3151 : void cmd_truncate(const char* path, int size) + 510 3139 : void cmd_truncate(const char* path, int size) 511 : { 512 : struct stat st; 513 : - 514 3151 : if (lstat(path, &st) != 0) { + 514 3139 : if (lstat(path, &st) != 0) { 515 : /* LCOV_EXCL_START */ 516 : log_fatal("Error accessing %s\n", path); 517 : exit(EXIT_FAILURE); 518 : /* LCOV_EXCL_STOP */ 519 : } 520 : - 521 3151 : if (S_ISREG(st.st_mode)) { + 521 3139 : if (S_ISREG(st.st_mode)) { 522 : off_t off; 523 : int f; 524 : 525 : /* if file is empty, just rewrite it */ - 526 3151 : if (st.st_size == 0) { - 527 3 : size = 0; + 526 3139 : if (st.st_size == 0) { + 527 4 : size = 0; 528 : } else { 529 : /* don't truncate files to 0 size to avoid ZERO file size protection */ - 530 3148 : if (size >= st.st_size) - 531 193 : size = st.st_size - 1; + 530 3135 : if (size >= st.st_size) + 531 211 : size = st.st_size - 1; 532 : } 533 : - 534 3151 : off = st.st_size - size; + 534 3139 : off = st.st_size - size; 535 : - 536 3151 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); - 537 3151 : if (f < 0) { + 536 3139 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + 537 3139 : if (f < 0) { 538 : /* LCOV_EXCL_START */ 539 : log_fatal("Error opening file %s\n", path); 540 : exit(EXIT_FAILURE); 541 : /* LCOV_EXCL_STOP */ 542 : } 543 : - 544 3151 : if (ftruncate(f, off) != 0) { + 544 3139 : if (ftruncate(f, off) != 0) { 545 : /* LCOV_EXCL_START */ 546 : log_fatal("Error truncating file %s\n", path); 547 : exit(EXIT_FAILURE); 548 : /* LCOV_EXCL_STOP */ 549 : } 550 : - 551 3151 : if (close(f) != 0) { + 551 3139 : if (close(f) != 0) { 552 : /* LCOV_EXCL_START */ 553 : log_fatal("Error closing file %s\n", path); 554 : exit(EXIT_FAILURE); 555 : /* LCOV_EXCL_STOP */ 556 : } 557 : } - 558 3151 : } + 558 3139 : } 559 : 560 : /** 561 : * Delete a file. 562 : * - The file must exist. 563 : */ - 564 3155 : void cmd_delete(const char* path) + 564 3209 : void cmd_delete(const char* path) 565 : { - 566 3155 : if (remove(path) != 0) { + 566 3209 : if (remove(path) != 0) { 567 : /* LCOV_EXCL_START */ 568 : log_fatal("Error removing %s\n", path); 569 : exit(EXIT_FAILURE); 570 : /* LCOV_EXCL_STOP */ 571 : } - 572 3155 : } + 572 3209 : } 573 : 574 : /** 575 : * Change a file. Or deleted/truncated/append/created. @@ -642,20 +642,20 @@ 580 : struct stat st; 581 : 582 13128 : if (!size) - 583 13152 : return; + 583 13153 : return; 584 : - 585 13104 : if (lstat(path, &st) != 0) { + 585 13103 : if (lstat(path, &st) != 0) { 586 : /* LCOV_EXCL_START */ 587 : log_fatal("Error accessing %s\n", path); 588 : exit(EXIT_FAILURE); 589 : /* LCOV_EXCL_STOP */ 590 : } 591 : - 592 13104 : if (S_ISLNK(st.st_mode)) { + 592 13103 : if (S_ISLNK(st.st_mode)) { 593 : /* symlink */ - 594 392 : if (rnd(2) == 0) { + 594 393 : if (rnd(2) == 0) { 595 : /* delete */ - 596 210 : if (remove(path) != 0) { + 596 186 : if (remove(path) != 0) { 597 : /* LCOV_EXCL_START */ 598 : log_fatal("Error removing %s\n", path); 599 : exit(EXIT_FAILURE); @@ -665,30 +665,30 @@ 603 : /* recreate */ 604 : char linkto[PATH_MAX]; 605 : - 606 182 : if (remove(path) != 0) { + 606 207 : if (remove(path) != 0) { 607 : /* LCOV_EXCL_START */ 608 : log_fatal("Error removing %s\n", path); 609 : exit(EXIT_FAILURE); 610 : /* LCOV_EXCL_STOP */ 611 : } 612 : - 613 182 : rnd_name(linkto); + 613 207 : rnd_name(linkto); 614 : - 615 182 : cmd_generate_symlink(path, linkto); + 615 207 : cmd_generate_symlink(path, linkto); 616 : } - 617 12712 : } else if (S_ISREG(st.st_mode)) { + 617 12710 : } else if (S_ISREG(st.st_mode)) { 618 : int r; 619 : - 620 12712 : r = rnd(4); + 620 12710 : r = rnd(4); 621 : - 622 12712 : if (r == 0) { - 623 3154 : cmd_write(path, size); - 624 9558 : } else if (r == 1) { - 625 3252 : cmd_append(path, size); - 626 6306 : } else if (r == 2) { - 627 3151 : cmd_truncate(path, size); + 622 12710 : if (r == 0) { + 623 3170 : cmd_write(path, size); + 624 9540 : } else if (r == 1) { + 625 3192 : cmd_append(path, size); + 626 6348 : } else if (r == 2) { + 627 3139 : cmd_truncate(path, size); 628 : } else { - 629 3155 : cmd_delete(path); + 629 3209 : cmd_delete(path); 630 : } 631 : } 632 : } diff --git a/cov/cmdline/murmur3.c.func-sort-c.html b/cov/cmdline/murmur3.c.func-sort-c.html index 890c3fb1..1f49f399 100644 --- a/cov/cmdline/murmur3.c.func-sort-c.html +++ b/cov/cmdline/murmur3.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ fmix32 - 9010328 + 7745044 MurmurHash3_x86_128 - 2252582 + 1936261
diff --git a/cov/cmdline/murmur3.c.func.html b/cov/cmdline/murmur3.c.func.html index 749722b4..aec58569 100644 --- a/cov/cmdline/murmur3.c.func.html +++ b/cov/cmdline/murmur3.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ MurmurHash3_x86_128 - 2252582 + 1936261 fmix32 - 9010328 + 7745044
diff --git a/cov/cmdline/murmur3.c.gcov.html b/cov/cmdline/murmur3.c.gcov.html index b92c0ea0..75a6add6 100644 --- a/cov/cmdline/murmur3.c.gcov.html +++ b/cov/cmdline/murmur3.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 9010328 : static inline uint32_t fmix32(uint32_t h) + 32 7745044 : static inline uint32_t fmix32(uint32_t h) 33 : { - 34 9010328 : h ^= h >> 16; - 35 9010328 : h *= 0x85ebca6b; - 36 9010328 : h ^= h >> 13; - 37 9010328 : h *= 0xc2b2ae35; - 38 9010328 : h ^= h >> 16; - 39 9010328 : return h; + 34 7745044 : h ^= h >> 16; + 35 7745044 : h *= 0x85ebca6b; + 36 7745044 : h ^= h >> 13; + 37 7745044 : h *= 0xc2b2ae35; + 38 7745044 : h ^= h >> 16; + 39 7745044 : return h; 40 : } 41 : 42 : /* @@ -137,17 +137,17 @@ 75 : uint32_t c3 = 0x38b34ae5; 76 : uint32_t c4 = 0xa1e38b93; 77 : - 78 2252582 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) + 78 1936261 : void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) 79 : { 80 : size_t nblocks; 81 : const uint32_t* blocks; 82 : const uint32_t* end; 83 : size_t size_remainder; 84 : - 85 2252582 : uint32_t h1 = ((const uint32_t*)seed)[0]; - 86 2252582 : uint32_t h2 = ((const uint32_t*)seed)[1]; - 87 2252582 : uint32_t h3 = ((const uint32_t*)seed)[2]; - 88 2252582 : uint32_t h4 = ((const uint32_t*)seed)[3]; + 85 1936261 : uint32_t h1 = ((const uint32_t*)seed)[0]; + 86 1936261 : uint32_t h2 = ((const uint32_t*)seed)[1]; + 87 1936261 : uint32_t h3 = ((const uint32_t*)seed)[2]; + 88 1936261 : uint32_t h4 = ((const uint32_t*)seed)[3]; 89 : 90 : #if WORDS_BIGENDIAN 91 : h1 = util_swap32(h1); @@ -156,16 +156,16 @@ 94 : h4 = util_swap32(h4); 95 : #endif 96 : - 97 2252582 : nblocks = size / 16; - 98 2252582 : blocks = data; - 99 2252582 : end = blocks + nblocks * 4; + 97 1936261 : nblocks = size / 16; + 98 1936261 : blocks = data; + 99 1936261 : end = blocks + nblocks * 4; 100 : 101 : /* body */ - 102 119857435 : while (blocks < end) { - 103 115352271 : uint32_t k1 = blocks[0]; - 104 115352271 : uint32_t k2 = blocks[1]; - 105 115352271 : uint32_t k3 = blocks[2]; - 106 115352271 : uint32_t k4 = blocks[3]; + 102 103248950 : while (blocks < end) { + 103 99376428 : uint32_t k1 = blocks[0]; + 104 99376428 : uint32_t k2 = blocks[1]; + 105 99376428 : uint32_t k3 = blocks[2]; + 106 99376428 : uint32_t k4 = blocks[3]; 107 : 108 : #if WORDS_BIGENDIAN 109 : k1 = util_swap32(k1); @@ -174,71 +174,71 @@ 112 : k4 = util_swap32(k4); 113 : #endif 114 : - 115 115352271 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 115 99376428 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 116 : - 117 115352271 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; + 117 99376428 : h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; 118 : - 119 115352271 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 119 99376428 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; 120 : - 121 115352271 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; + 121 99376428 : h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; 122 : - 123 115352271 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 123 99376428 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; 124 : - 125 115352271 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; + 125 99376428 : h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; 126 : - 127 115352271 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 127 99376428 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; 128 : - 129 115352271 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; + 129 99376428 : h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; 130 : - 131 115352271 : blocks += 4; + 131 99376428 : blocks += 4; 132 : } 133 : 134 : /* tail */ - 135 2252582 : size_remainder = size & 15; - 136 2252582 : if (size_remainder != 0) { - 137 848153 : const uint8_t* tail = (const uint8_t*)blocks; + 135 1936261 : size_remainder = size & 15; + 136 1936261 : if (size_remainder != 0) { + 137 726747 : const uint8_t* tail = (const uint8_t*)blocks; 138 : - 139 848153 : uint32_t k1 = 0; - 140 848153 : uint32_t k2 = 0; - 141 848153 : uint32_t k3 = 0; - 142 848153 : uint32_t k4 = 0; + 139 726747 : uint32_t k1 = 0; + 140 726747 : uint32_t k2 = 0; + 141 726747 : uint32_t k3 = 0; + 142 726747 : uint32_t k4 = 0; 143 : - 144 848153 : switch (size_remainder) { - 145 55834 : case 15 : k4 ^= tail[14] << 16; - 146 112972 : case 14 : k4 ^= tail[13] << 8; - 147 170132 : case 13 : k4 ^= tail[12] << 0; - 148 170132 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; - 149 227529 : case 12 : k3 ^= tail[11] << 24; - 150 284808 : case 11 : k3 ^= tail[10] << 16; - 151 341803 : case 10 : k3 ^= tail[ 9] << 8; - 152 400242 : case 9 : k3 ^= tail[ 8] << 0; - 153 400242 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; - 154 458531 : case 8 : k2 ^= tail[ 7] << 24; - 155 512645 : case 7 : k2 ^= tail[ 6] << 16; - 156 569544 : case 6 : k2 ^= tail[ 5] << 8; - 157 624516 : case 5 : k2 ^= tail[ 4] << 0; - 158 624516 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; - 159 680502 : case 4 : k1 ^= tail[ 3] << 24; - 160 735518 : case 3 : k1 ^= tail[ 2] << 16; - 161 791435 : case 2 : k1 ^= tail[ 1] << 8; - 162 848153 : case 1 : k1 ^= tail[ 0] << 0; - 163 848153 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + 144 726747 : switch (size_remainder) { + 145 47814 : case 15 : k4 ^= (uint32_t)tail[14] << 16; + 146 97089 : case 14 : k4 ^= (uint32_t)tail[13] << 8; + 147 145774 : case 13 : k4 ^= (uint32_t)tail[12] << 0; + 148 145774 : k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + 149 194991 : case 12 : k3 ^= (uint32_t)tail[11] << 24; + 150 244008 : case 11 : k3 ^= (uint32_t)tail[10] << 16; + 151 292626 : case 10 : k3 ^= (uint32_t)tail[ 9] << 8; + 152 342276 : case 9 : k3 ^= (uint32_t)tail[ 8] << 0; + 153 342276 : k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + 154 392525 : case 8 : k2 ^= (uint32_t)tail[ 7] << 24; + 155 438669 : case 7 : k2 ^= (uint32_t)tail[ 6] << 16; + 156 487770 : case 6 : k2 ^= (uint32_t)tail[ 5] << 8; + 157 534928 : case 5 : k2 ^= (uint32_t)tail[ 4] << 0; + 158 534928 : k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + 159 583310 : case 4 : k1 ^= (uint32_t)tail[ 3] << 24; + 160 630301 : case 3 : k1 ^= (uint32_t)tail[ 2] << 16; + 161 678080 : case 2 : k1 ^= (uint32_t)tail[ 1] << 8; + 162 726747 : case 1 : k1 ^= (uint32_t)tail[ 0] << 0; + 163 726747 : k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; 164 : } 165 : } 166 : 167 : /* finalization */ - 168 2252582 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; + 168 1936261 : h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; 169 : - 170 2252582 : h1 += h2; h1 += h3; h1 += h4; - 171 2252582 : h2 += h1; h3 += h1; h4 += h1; + 170 1936261 : h1 += h2; h1 += h3; h1 += h4; + 171 1936261 : h2 += h1; h3 += h1; h4 += h1; 172 : - 173 2252582 : h1 = fmix32(h1); - 174 2252582 : h2 = fmix32(h2); - 175 2252582 : h3 = fmix32(h3); - 176 2252582 : h4 = fmix32(h4); + 173 1936261 : h1 = fmix32(h1); + 174 1936261 : h2 = fmix32(h2); + 175 1936261 : h3 = fmix32(h3); + 176 1936261 : h4 = fmix32(h4); 177 : - 178 2252582 : h1 += h2; h1 += h3; h1 += h4; - 179 2252582 : h2 += h1; h3 += h1; h4 += h1; + 178 1936261 : h1 += h2; h1 += h3; h1 += h4; + 179 1936261 : h2 += h1; h3 += h1; h4 += h1; 180 : 181 : #if WORDS_BIGENDIAN 182 : h1 = util_swap32(h1); @@ -247,11 +247,11 @@ 185 : h4 = util_swap32(h4); 186 : #endif 187 : - 188 2252582 : ((uint32_t*)digest)[0] = h1; - 189 2252582 : ((uint32_t*)digest)[1] = h2; - 190 2252582 : ((uint32_t*)digest)[2] = h3; - 191 2252582 : ((uint32_t*)digest)[3] = h4; - 192 2252582 : } + 188 1936261 : ((uint32_t*)digest)[0] = h1; + 189 1936261 : ((uint32_t*)digest)[1] = h2; + 190 1936261 : ((uint32_t*)digest)[2] = h3; + 191 1936261 : ((uint32_t*)digest)[3] = h4; + 192 1936261 : } 193 : diff --git a/cov/cmdline/nano.c.func-sort-c.html b/cov/cmdline/nano.c.func-sort-c.html index 86954774..9a6e5795 100644 --- a/cov/cmdline/nano.c.func-sort-c.html +++ b/cov/cmdline/nano.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/nano.c.func.html b/cov/cmdline/nano.c.func.html index 0a3357e1..40cd8921 100644 --- a/cov/cmdline/nano.c.func.html +++ b/cov/cmdline/nano.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/nano.c.gcov.html b/cov/cmdline/nano.c.gcov.html index 931ad05d..6c81a29b 100644 --- a/cov/cmdline/nano.c.gcov.html +++ b/cov/cmdline/nano.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -96,13 +96,13 @@ 34 : tommy_node* j; 35 : 36 : /* for all files */ - 37 5724 : for (j = disk->filelist; j != 0; j = j->next) { - 38 5718 : struct snapraid_file* file = j->data; + 37 5731 : for (j = disk->filelist; j != 0; j = j->next) { + 38 5725 : struct snapraid_file* file = j->data; 39 : 40 : /* if the file has a zero nanosecond timestamp */ 41 : /* note that symbolic links are not in the file list */ 42 : /* and then are not processed */ - 43 5718 : if (file->mtime_nsec == 0) { + 43 5725 : if (file->mtime_nsec == 0) { 44 : char path[PATH_MAX]; 45 : struct stat st; 46 : int f; @@ -180,7 +180,7 @@ 118 : 119 : /* set the same nanosecond value in the content file */ 120 : /* note that if the seconds value is already matching */ - 121 : /* the file won't be synched because the content file will */ + 121 : /* the file won't be synced because the content file will */ 122 : /* contain the new updated timestamp */ 123 16 : file->mtime_nsec = STAT_NSEC(&st); 124 : diff --git a/cov/cmdline/parity.c.func-sort-c.html b/cov/cmdline/parity.c.func-sort-c.html index 862a0682..9234472e 100644 --- a/cov/cmdline/parity.c.func-sort-c.html +++ b/cov/cmdline/parity.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -61,39 +61,39 @@ parity_read - 3488577 + 3492991 parity_write - 506040 + 559380 parity_close - 952 + 1000 parity_allocated_size - 589 + 616 parity_create - 551 + 599 parity_chsize - 551 + 599 + + + parity_sync + 447 parity_open 402 - - parity_sync - 399 - parity_used_size - 72 + 80 parity_is_invalid diff --git a/cov/cmdline/parity.c.func.html b/cov/cmdline/parity.c.func.html index 700c0fe6..72656e05 100644 --- a/cov/cmdline/parity.c.func.html +++ b/cov/cmdline/parity.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -61,19 +61,19 @@ parity_allocated_size - 589 + 616 parity_chsize - 551 + 599 parity_close - 952 + 1000 parity_create - 551 + 599 parity_is_invalid @@ -89,19 +89,19 @@ parity_read - 3488577 + 3492991 parity_sync - 399 + 447 parity_used_size - 72 + 80 parity_write - 506040 + 559380
diff --git a/cov/cmdline/parity.c.gcov.html b/cov/cmdline/parity.c.gcov.html index 6ebacc6b..ac06a6d2 100644 --- a/cov/cmdline/parity.c.gcov.html +++ b/cov/cmdline/parity.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -88,56 +88,56 @@ 26 : /****************************************************************************/ 27 : /* parity */ 28 : - 29 589 : block_off_t parity_allocated_size(struct snapraid_state* state) + 29 616 : block_off_t parity_allocated_size(struct snapraid_state* state) 30 : { 31 : block_off_t parity_block; 32 : tommy_node* i; 33 : 34 : /* compute the size of the parity file */ - 35 589 : parity_block = 0; - 36 4113 : for (i = state->disklist; i != 0; i = i->next) { - 37 3524 : struct snapraid_disk* disk = i->data; + 35 616 : parity_block = 0; + 36 4302 : for (i = state->disklist; i != 0; i = i->next) { + 37 3686 : struct snapraid_disk* disk = i->data; 38 : 39 : /* start from the declared size */ - 40 3524 : block_off_t block = disk_size(disk); + 40 3686 : block_off_t block = disk_size(disk); 41 : 42 : /* decrease the block until an allocated one, but part of a file */ 43 : /* we don't stop at deleted blocks, because we want to have them cleared */ 44 : /* if they are at the end of the parity */ - 45 189514 : while (block > parity_block && !block_has_file(fs_par2block_get(disk, block - 1))) - 46 182466 : --block; + 45 128726 : while (block > parity_block && !block_has_file(fs_par2block_get(disk, block - 1))) + 46 121354 : --block; 47 : 48 : /* get the highest value */ - 49 3524 : if (block > parity_block) - 50 2273 : parity_block = block; + 49 3686 : if (block > parity_block) + 50 2201 : parity_block = block; 51 : } 52 : - 53 589 : return parity_block; + 53 616 : return parity_block; 54 : } 55 : - 56 72 : block_off_t parity_used_size(struct snapraid_state* state) + 56 80 : block_off_t parity_used_size(struct snapraid_state* state) 57 : { 58 : block_off_t parity_block; 59 : tommy_node* i; 60 : 61 : /* compute the size of the parity file */ - 62 72 : parity_block = 0; - 63 503 : for (i = state->disklist; i != 0; i = i->next) { - 64 431 : struct snapraid_disk* disk = i->data; + 62 80 : parity_block = 0; + 63 559 : for (i = state->disklist; i != 0; i = i->next) { + 64 479 : struct snapraid_disk* disk = i->data; 65 : 66 : /* start from the declared size */ - 67 431 : block_off_t block = disk_size(disk); + 67 479 : block_off_t block = disk_size(disk); 68 : 69 : /* decrease the block until an used one */ - 70 221700 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_get(disk, block - 1))) - 71 220838 : --block; + 70 258592 : while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_get(disk, block - 1))) + 71 257634 : --block; 72 : 73 : /* get the highest value */ - 74 431 : if (block > parity_block) - 75 262 : parity_block = block; + 74 479 : if (block > parity_block) + 75 259 : parity_block = block; 76 : } 77 : - 78 72 : return parity_block; + 78 80 : return parity_block; 79 : } 80 : 81 1 : int parity_is_invalid(struct snapraid_state* state) @@ -211,20 +211,20 @@ 149 : } 150 : } 151 : - 152 551 : int parity_create(struct snapraid_parity_handle* parity, const char* path, data_off_t* out_size, int mode) + 152 599 : int parity_create(struct snapraid_parity_handle* parity, const char* path, data_off_t* out_size, int mode) 153 : { 154 : int ret; 155 : int flags; 156 : - 157 551 : pathcpy(parity->path, sizeof(parity->path), path); + 157 599 : pathcpy(parity->path, sizeof(parity->path), path); 158 : 159 : /* opening in sequential mode in Windows */ 160 : /* O_SEQUENTIAL: opening in sequential mode in Windows */ - 161 551 : flags = O_RDWR | O_CREAT | O_BINARY; - 162 551 : if ((mode & MODE_SEQUENTIAL) != 0) - 163 551 : flags |= O_SEQUENTIAL; - 164 551 : parity->f = open(parity->path, flags, 0600); - 165 551 : if (parity->f == -1) { + 161 599 : flags = O_RDWR | O_CREAT | O_BINARY; + 162 599 : if ((mode & MODE_SEQUENTIAL) != 0) + 163 599 : flags |= O_SEQUENTIAL; + 164 599 : parity->f = open(parity->path, flags, 0600); + 165 599 : if (parity->f == -1) { 166 : /* LCOV_EXCL_START */ 167 : log_fatal("Error opening parity file '%s'. %s.\n", parity->path, strerror(errno)); 168 : return -1; @@ -232,8 +232,8 @@ 170 : } 171 : 172 : /* get the stat info */ - 173 551 : ret = fstat(parity->f, &parity->st); - 174 551 : if (ret != 0) { + 173 599 : ret = fstat(parity->f, &parity->st); + 174 599 : if (ret != 0) { 175 : /* LCOV_EXCL_START */ 176 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno)); 177 : goto bail; @@ -241,10 +241,10 @@ 179 : } 180 : 181 : #if HAVE_POSIX_FADVISE - 182 551 : if ((mode & MODE_SEQUENTIAL) != 0) { + 182 599 : if ((mode & MODE_SEQUENTIAL) != 0) { 183 : /* advise sequential access */ - 184 551 : ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL); - 185 551 : if (ret != 0) { + 184 599 : ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL); + 185 599 : if (ret != 0) { 186 : /* LCOV_EXCL_START */ 187 : log_fatal("Error advising parity file '%s'. %s.\n", parity->path, strerror(ret)); 188 : goto bail; @@ -254,10 +254,10 @@ 192 : #endif 193 : 194 : /* get the size of the existing data */ - 195 551 : parity->valid_size = parity->st.st_size; - 196 551 : *out_size = parity->st.st_size; + 195 599 : parity->valid_size = parity->st.st_size; + 196 599 : *out_size = parity->st.st_size; 197 : - 198 551 : return 0; + 198 599 : return 0; 199 : 200 : bail: 201 : /* LCOV_EXCL_START */ @@ -268,28 +268,28 @@ 206 : /* LCOV_EXCL_STOP */ 207 : } 208 : - 209 551 : int parity_chsize(struct snapraid_parity_handle* parity, data_off_t size, data_off_t* out_size, int skip_fallocate) + 209 599 : int parity_chsize(struct snapraid_parity_handle* parity, data_off_t size, data_off_t* out_size, int skip_fallocate) 210 : { 211 : int ret; 212 : - 213 551 : if (parity->st.st_size < size) { + 213 599 : if (parity->st.st_size < size) { 214 : int f_ret; 215 : int f_errno; 216 : const char* call; 217 : 218 : #if HAVE_FALLOCATE - 219 83 : call = "fallocate"; - 220 83 : if (!skip_fallocate) { + 219 95 : call = "fallocate"; + 220 95 : if (!skip_fallocate) { 221 : /* allocate real space using the specific Linux fallocate() operation. */ - 222 : /* If the underline filesystem doesn't support it, this operation fails, */ + 222 : /* If the underline file-system doesn't support it, this operation fails, */ 223 : /* instead posix_fallocate() fallbacks to write the whole file. */ - 224 82 : ret = fallocate(parity->f, 0, 0, size); + 224 94 : ret = fallocate(parity->f, 0, 0, size); 225 : 226 : /* fallocate() returns the error number as positive integer, */ 227 : /* and in this case it doesn't set errno, just like posix_fallocate() */ 228 : /* Checking the glibc code (2.11.1 and 2.14.1) it seems that ENOSYS */ 229 : /* may be returned in errno, so we support both the return way */ - 230 82 : if (ret > 0) { /* if a positive error is returned, convert it to errno */ + 230 94 : if (ret > 0) { /* if a positive error is returned, convert it to errno */ 231 : /* LCOV_EXCL_START */ 232 : errno = ret; 233 : ret = -1; @@ -302,7 +302,7 @@ 240 : 241 : /* we get EOPNOTSUPP if the operation is not supported, like in ext3/ext2 */ 242 : /* or ENOSYS with kernel before 2.6.23 */ - 243 83 : if (errno == EOPNOTSUPP || errno == ENOSYS) { + 243 95 : if (errno == EOPNOTSUPP || errno == ENOSYS) { 244 : /* fallback using ftruncate() */ 245 1 : call = "ftruncate"; 246 1 : ret = ftruncate(parity->f, size); @@ -315,12 +315,12 @@ 253 : ret = ftruncate(parity->f, size); 254 : #endif 255 : /* save the state of the grow operation */ - 256 83 : f_ret = ret; - 257 83 : f_errno = errno; + 256 95 : f_ret = ret; + 257 95 : f_errno = errno; 258 : 259 : /* get the stat info */ - 260 83 : ret = fstat(parity->f, &parity->st); - 261 83 : if (ret != 0) { + 260 95 : ret = fstat(parity->f, &parity->st); + 261 95 : if (ret != 0) { 262 : /* LCOV_EXCL_START */ 263 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno)); 264 : goto bail; @@ -328,10 +328,10 @@ 266 : } 267 : 268 : /* return the new size */ - 269 83 : *out_size = parity->st.st_size; + 269 95 : *out_size = parity->st.st_size; 270 : 271 : /* now check the error */ - 272 83 : if (f_ret != 0) { + 272 95 : if (f_ret != 0) { 273 : /* LCOV_EXCL_START */ 274 : if (f_errno == ENOSPC) { 275 : log_fatal("Failed to grow parity file '%s' to size %" PRIu64 " using %s due lack of space.\n", parity->path, size, call); @@ -341,20 +341,20 @@ 279 : goto bail; 280 : /* LCOV_EXCL_STOP */ 281 : } - 282 468 : } else if (parity->st.st_size > size) { + 282 504 : } else if (parity->st.st_size > size) { 283 : int f_ret; 284 : int f_errno; 285 : 286 : /* truncate the parity file */ - 287 48 : ret = ftruncate(parity->f, size); + 287 72 : ret = ftruncate(parity->f, size); 288 : 289 : /* save the state of the shrink operation */ - 290 48 : f_ret = ret; - 291 48 : f_errno = errno; + 290 72 : f_ret = ret; + 291 72 : f_errno = errno; 292 : 293 : /* get the stat info */ - 294 48 : ret = fstat(parity->f, &parity->st); - 295 48 : if (ret != 0) { + 294 72 : ret = fstat(parity->f, &parity->st); + 295 72 : if (ret != 0) { 296 : /* LCOV_EXCL_START */ 297 : log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno)); 298 : goto bail; @@ -362,10 +362,10 @@ 300 : } 301 : 302 : /* return the new size */ - 303 48 : *out_size = parity->st.st_size; + 303 72 : *out_size = parity->st.st_size; 304 : 305 : /* now check the error */ - 306 48 : if (f_ret != 0) { + 306 72 : if (f_ret != 0) { 307 : /* LCOV_EXCL_START */ 308 : log_fatal("Error truncating parity file '%s' to size %" PRIu64 ". %s.\n", parity->path, size, strerror(f_errno)); 309 : goto bail; @@ -373,10 +373,10 @@ 311 : } 312 : 313 : /* adjust the valid to the new size */ - 314 48 : parity->valid_size = size; + 314 72 : parity->valid_size = size; 315 : } 316 : - 317 551 : return 0; + 317 599 : return 0; 318 : 319 : bail: 320 : /* LCOV_EXCL_START */ @@ -413,7 +413,7 @@ 351 : /* LCOV_EXCL_STOP */ 352 : } 353 : - 354 : /* get the size of the exising data */ + 354 : /* get the size of the existing data */ 355 401 : parity->valid_size = parity->st.st_size; 356 : 357 : #if HAVE_POSIX_FADVISE @@ -440,7 +440,7 @@ 378 : /* LCOV_EXCL_STOP */ 379 : } 380 : - 381 399 : int parity_sync(struct snapraid_parity_handle* parity) + 381 447 : int parity_sync(struct snapraid_parity_handle* parity) 382 : { 383 : #if HAVE_FSYNC 384 : int ret; @@ -448,8 +448,8 @@ 386 : /* Ensure that data changes are written to disk. */ 387 : /* This is required to ensure that parity is more updated than content */ 388 : /* in case of a system crash. */ - 389 399 : ret = fsync(parity->f); - 390 399 : if (ret != 0) { + 389 447 : ret = fsync(parity->f); + 390 447 : if (ret != 0) { 391 : /* LCOV_EXCL_START */ 392 : log_fatal("Error synching parity file '%s'. %s.\n", parity->path, strerror(errno)); 393 : return -1; @@ -457,15 +457,15 @@ 395 : } 396 : #endif 397 : - 398 399 : return 0; + 398 447 : return 0; 399 : } 400 : - 401 952 : int parity_close(struct snapraid_parity_handle* parity) + 401 1000 : int parity_close(struct snapraid_parity_handle* parity) 402 : { 403 : int ret; 404 : - 405 952 : ret = close(parity->f); - 406 952 : if (ret != 0) { + 405 1000 : ret = close(parity->f); + 406 1000 : if (ret != 0) { 407 : /* LCOV_EXCL_START */ 408 : /* invalidate for error */ 409 : parity->f = -1; @@ -473,28 +473,28 @@ 411 : 412 : /* This is a serious error, as it may be the result of a failed write */ 413 : /* identified at later time. */ - 414 : /* In a normal filesystem (not NFS) it should never happen */ + 414 : /* In a normal file-system (not NFS) it should never happen */ 415 : log_fatal("Error closing parity file '%s'. %s.\n", parity->path, strerror(errno)); 416 : return -1; 417 : /* LCOV_EXCL_STOP */ 418 : } 419 : 420 : /* reset the descriptor */ - 421 952 : parity->f = -1; - 422 952 : parity->valid_size = 0; + 421 1000 : parity->f = -1; + 422 1000 : parity->valid_size = 0; 423 : - 424 952 : return 0; + 424 1000 : return 0; 425 : } 426 : - 427 506040 : int parity_write(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size) + 427 559380 : int parity_write(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size) 428 : { 429 : ssize_t write_ret; 430 : data_off_t offset; 431 : - 432 506040 : offset = pos * (data_off_t)block_size; + 432 559380 : offset = pos * (data_off_t)block_size; 433 : 434 : #if HAVE_PWRITE - 435 506040 : write_ret = pwrite(parity->f, block_buffer, block_size, offset); + 435 559380 : write_ret = pwrite(parity->f, block_buffer, block_size, offset); 436 : #else 437 : if (lseek(parity->f, offset, SEEK_SET) != offset) { 438 : /* LCOV_EXCL_START */ @@ -509,7 +509,7 @@ 447 : 448 : write_ret = write(parity->f, block_buffer, block_size); 449 : #endif - 450 506040 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */ + 450 559380 : if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */ 451 : /* LCOV_EXCL_START */ 452 : if (errno == ENOSPC) { 453 : log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", parity->path); @@ -521,28 +521,28 @@ 459 : } 460 : 461 : /* adjust the size of the valid data */ - 462 506040 : if (parity->valid_size < offset + block_size) { - 463 170559 : parity->valid_size = offset + block_size; + 462 559380 : if (parity->valid_size < offset + block_size) { + 463 171021 : parity->valid_size = offset + block_size; 464 : } 465 : 466 : /* Here doesn't make sense to call posix_fadvise(..., POSIX_FADV_DONTNEED) because */ 467 : /* at this time the data is still in not yet written and it cannot be discharged. */ 468 : - 469 506040 : return 0; + 469 559380 : return 0; 470 : } 471 : - 472 3488577 : int parity_read(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out) + 472 3492991 : int parity_read(struct snapraid_parity_handle* parity, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out) 473 : { 474 : ssize_t read_ret; 475 : data_off_t offset; 476 : unsigned count; 477 : - 478 3488577 : offset = pos * (data_off_t)block_size; + 478 3492991 : offset = pos * (data_off_t)block_size; 479 : 480 : /* check if we are going to read only not initialized data */ - 481 3488577 : if (offset >= parity->valid_size) { - 482 90275 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", parity->path, offset); - 483 90275 : return -1; + 481 3492991 : if (offset >= parity->valid_size) { + 482 90295 : out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", parity->path, offset); + 483 90295 : return -1; 484 : } 485 : 486 : #if !HAVE_PREAD @@ -554,36 +554,36 @@ 492 : } 493 : #endif 494 : - 495 3398302 : count = 0; + 495 3402696 : count = 0; 496 : do { 497 : 498 : #if HAVE_PREAD - 499 3398302 : read_ret = pread(parity->f, block_buffer + count, block_size - count, offset + count); + 499 3402696 : read_ret = pread(parity->f, block_buffer + count, block_size - count, offset + count); 500 : #else 501 : read_ret = read(parity->f, block_buffer + count, block_size - count); 502 : #endif - 503 3398302 : if (read_ret < 0) { + 503 3402696 : if (read_ret < 0) { 504 : /* LCOV_EXCL_START */ 505 : out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", parity->path, offset + count, block_size - count, strerror(errno)); 506 : return -1; 507 : /* LCOV_EXCL_STOP */ 508 : } - 509 3398302 : if (read_ret == 0) { + 509 3402696 : if (read_ret == 0) { 510 : /* LCOV_EXCL_START */ 511 : out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", parity->path, offset, strerror(errno)); 512 : return -1; 513 : /* LCOV_EXCL_STOP */ 514 : } 515 : - 516 3398302 : count += read_ret; - 517 3398302 : } while (count < block_size); + 516 3402696 : count += read_ret; + 517 3402696 : } while (count < block_size); 518 : 519 : /* Here isn't needed to call posix_fadvise(..., POSIX_FADV_DONTNEED) */ 520 : /* because we already advised sequential access with POSIX_FADV_SEQUENTIAL. */ 521 : /* In Linux 2.6.33 it's enough to ensure that data is not kept in the cache. */ 522 : /* Better to do nothing and save a syscall for each block. */ 523 : - 524 3398302 : return block_size; + 524 3402696 : return block_size; 525 : } 526 : diff --git a/cov/cmdline/pool.c.func-sort-c.html b/cov/cmdline/pool.c.func-sort-c.html index 745f72a1..227f106b 100644 --- a/cov/cmdline/pool.c.func-sort-c.html +++ b/cov/cmdline/pool.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -61,7 +61,7 @@ make_link - 17569 + 17583 clean_dir diff --git a/cov/cmdline/pool.c.func.html b/cov/cmdline/pool.c.func.html index 6a1d2ec3..a874cb8a 100644 --- a/cov/cmdline/pool.c.func.html +++ b/cov/cmdline/pool.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -65,7 +65,7 @@ make_link - 17569 + 17583 state_pool diff --git a/cov/cmdline/pool.c.gcov.html b/cov/cmdline/pool.c.gcov.html index 233bc037..3172ab70 100644 --- a/cov/cmdline/pool.c.gcov.html +++ b/cov/cmdline/pool.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -107,24 +107,24 @@ 45 : struct dirent* dd; 46 : 47 : /* clear errno to detect erroneous conditions */ - 48 5760 : errno = 0; - 49 5760 : dd = readdir(d); - 50 5760 : if (dd == 0 && errno != 0) { + 48 5767 : errno = 0; + 49 5767 : dd = readdir(d); + 50 5767 : if (dd == 0 && errno != 0) { 51 : /* LCOV_EXCL_START */ 52 : log_fatal("Error reading pool directory '%s'. %s.\n", dir, strerror(errno)); 53 : exit(EXIT_FAILURE); 54 : /* LCOV_EXCL_STOP */ 55 : } - 56 5760 : if (dd == 0 && errno == 0) { + 56 5767 : if (dd == 0 && errno == 0) { 57 5 : break; /* finished */ 58 : } 59 : 60 : /* skip "." and ".." files */ - 61 5755 : name = dd->d_name; - 62 5755 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 61 5762 : name = dd->d_name; + 62 5762 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 63 10 : continue; 64 : - 65 5745 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 65 5752 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); 66 : 67 : #if HAVE_STRUCT_DIRENT_D_STAT 68 : /* convert dirent to lstat result */ @@ -142,7 +142,7 @@ 80 : } 81 : #else 82 : /* get lstat info about the file */ - 83 5745 : if (lstat(path_next, &st) != 0) { + 83 5752 : if (lstat(path_next, &st) != 0) { 84 : /* LCOV_EXCL_START */ 85 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); 86 : exit(EXIT_FAILURE); @@ -150,12 +150,12 @@ 88 : } 89 : #endif 90 : - 91 5745 : if (S_ISLNK(st.st_mode)) { + 91 5752 : if (S_ISLNK(st.st_mode)) { 92 : int ret; 93 : 94 : /* delete the link */ - 95 5743 : ret = remove(path_next); - 96 5743 : if (ret < 0) { + 95 5750 : ret = remove(path_next); + 96 5750 : if (ret < 0) { 97 : /* LCOV_EXCL_START */ 98 : log_fatal("Error removing symlink '%s'. %s.\n", path_next, strerror(errno)); 99 : exit(EXIT_FAILURE); @@ -194,7 +194,7 @@ 132 0 : ignored = 1; 133 0 : msg_verbose("Ignoring pool file '%s'\n", path_next); 134 : } - 135 5755 : } + 135 5762 : } 136 : 137 5 : if (closedir(d) != 0) { 138 : /* LCOV_EXCL_START */ @@ -209,7 +209,7 @@ 147 : /** 148 : * Create a link to the specified disk entry. 149 : */ - 150 17569 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub) + 150 17583 : static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub) 151 : { 152 : char path[PATH_MAX]; 153 : char linkto[PATH_MAX]; @@ -217,31 +217,31 @@ 155 : int ret; 156 : 157 : /* make the source path */ - 158 17569 : pathprint(path, sizeof(path), "%s%s", pool_dir, sub); + 158 17583 : pathprint(path, sizeof(path), "%s%s", pool_dir, sub); 159 : 160 : /* make the linkto path */ - 161 17569 : if (share_dir[0] != 0) { + 161 17583 : if (share_dir[0] != 0) { 162 : /* with a shared directory, use it */ - 163 17569 : pathprint(linkto, sizeof(linkto), "%s%s/%s", share_dir, disk->name, sub); + 163 17583 : pathprint(linkto, sizeof(linkto), "%s%s/%s", share_dir, disk->name, sub); 164 : } else { 165 : /* without a share directory, use the local disk paths */ 166 0 : pathprint(linkto, sizeof(linkto), "%s%s", disk->dir, sub); 167 : } 168 : 169 : /* create the ancestor directories */ - 170 17569 : ret = mkancestor(path); - 171 17569 : if (ret != 0) { + 170 17583 : ret = mkancestor(path); + 171 17583 : if (ret != 0) { 172 : /* LCOV_EXCL_START */ 173 : exit(EXIT_FAILURE); 174 : /* LCOV_EXCL_STOP */ 175 : } 176 : 177 : /* convert back slashes */ - 178 17569 : pathexport(linkto_exported, sizeof(linkto_exported), linkto); + 178 17583 : pathexport(linkto_exported, sizeof(linkto_exported), linkto); 179 : 180 : /* create the symlink */ - 181 17569 : ret = symlink(linkto_exported, path); - 182 17569 : if (ret != 0) { + 181 17583 : ret = symlink(linkto_exported, path); + 182 17583 : if (ret != 0) { 183 517 : if (errno == EEXIST) { 184 517 : log_fatal("WARNING! Duplicate pooling for '%s'\n", path); 185 : #ifdef _WIN32 @@ -258,7 +258,7 @@ 196 : /* LCOV_EXCL_STOP */ 197 : } 198 : } - 199 17569 : } + 199 17583 : } 200 : 201 3 : void state_pool(struct snapraid_state* state) 202 : { @@ -296,10 +296,10 @@ 234 18 : struct snapraid_disk* disk = i->data; 235 : 236 : /* for each file */ - 237 16998 : for (j = disk->filelist; j != 0; j = j->next) { - 238 16980 : struct snapraid_file* file = j->data; - 239 16980 : make_link(pool_dir, share_dir, disk, file->sub); - 240 16980 : ++count; + 237 17012 : for (j = disk->filelist; j != 0; j = j->next) { + 238 16994 : struct snapraid_file* file = j->data; + 239 16994 : make_link(pool_dir, share_dir, disk, file->sub); + 240 16994 : ++count; 241 : } 242 : 243 : /* for each link */ diff --git a/cov/cmdline/portable.h.func-sort-c.html b/cov/cmdline/portable.h.func-sort-c.html index 4b66bf09..5265a465 100644 --- a/cov/cmdline/portable.h.func-sort-c.html +++ b/cov/cmdline/portable.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 ee3455ec..c83d5fe3 100644 --- a/cov/cmdline/portable.h.func.html +++ b/cov/cmdline/portable.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 5cb42125..c75de15a 100644 --- a/cov/cmdline/portable.h.gcov.html +++ b/cov/cmdline/portable.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -131,357 +131,385 @@ 69 : #define __always_inline inline __attribute__((always_inline)) 70 : #endif 71 : - 72 : /** - 73 : * Architecture. - 74 : */ - 75 : #if defined(__i386__) - 76 : #define CONFIG_X86 1 - 77 : #define CONFIG_X86_32 1 - 78 : #endif - 79 : - 80 : #if defined(__x86_64__) + 72 : #ifndef __noreturn + 73 : #define __noreturn __attribute__((noreturn)) + 74 : #endif + 75 : + 76 : + 77 : /** + 78 : * Architecture. + 79 : */ + 80 : #if defined(__i386__) 81 : #define CONFIG_X86 1 - 82 : #define CONFIG_X86_64 1 + 82 : #define CONFIG_X86_32 1 83 : #endif 84 : - 85 : /** - 86 : * Includes some platform specific headers. - 87 : */ - 88 : #if HAVE_SYS_PARAM_H - 89 : #include <sys/param.h> - 90 : #endif - 91 : - 92 : #if HAVE_SYS_MOUNT_H - 93 : #include <sys/mount.h> - 94 : #endif - 95 : - 96 : #if HAVE_SYS_VFS_H - 97 : #include <sys/vfs.h> - 98 : #endif - 99 : - 100 : #if HAVE_SYS_STATFS_H - 101 : #include <sys/statfs.h> - 102 : #endif - 103 : - 104 : #if HAVE_SYS_FILE_H - 105 : #include <sys/file.h> - 106 : #endif - 107 : - 108 : #if HAVE_SYS_IOCTL_H - 109 : #include <sys/ioctl.h> - 110 : #endif - 111 : - 112 : #if HAVE_LINUX_FS_H - 113 : #include <linux/fs.h> - 114 : #endif - 115 : - 116 : #if HAVE_LINUX_FIEMAP_H - 117 : #include <linux/fiemap.h> - 118 : #endif - 119 : - 120 : /** - 121 : * Includes some standard headers. - 122 : */ - 123 : #include <stdio.h> - 124 : #include <stdlib.h> /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */ - 125 : #include <stdarg.h> - 126 : #include <string.h> - 127 : #include <ctype.h> - 128 : #include <fcntl.h> - 129 : #include <assert.h> - 130 : #include <errno.h> - 131 : #include <signal.h> - 132 : #include <limits.h> - 133 : - 134 : #if HAVE_STDINT_H - 135 : #include <stdint.h> - 136 : #endif - 137 : - 138 : #if HAVE_INTTYPES_H - 139 : #include <inttypes.h> - 140 : #endif - 141 : - 142 : #if HAVE_UNISTD_H - 143 : #include <unistd.h> - 144 : #endif + 85 : #if defined(__x86_64__) + 86 : #define CONFIG_X86 1 + 87 : #define CONFIG_X86_64 1 + 88 : #endif + 89 : + 90 : /** + 91 : * Includes some platform specific headers. + 92 : */ + 93 : #if HAVE_SYS_PARAM_H + 94 : #include <sys/param.h> + 95 : #endif + 96 : + 97 : #if HAVE_SYS_MOUNT_H + 98 : #include <sys/mount.h> + 99 : #endif + 100 : + 101 : #if HAVE_SYS_VFS_H + 102 : #include <sys/vfs.h> + 103 : #endif + 104 : + 105 : #if HAVE_SYS_STATFS_H + 106 : #include <sys/statfs.h> + 107 : #endif + 108 : + 109 : #if HAVE_SYS_FILE_H + 110 : #include <sys/file.h> + 111 : #endif + 112 : + 113 : #if HAVE_SYS_IOCTL_H + 114 : #include <sys/ioctl.h> + 115 : #endif + 116 : + 117 : #if HAVE_LINUX_FS_H + 118 : #include <linux/fs.h> + 119 : #endif + 120 : + 121 : #if HAVE_LINUX_FIEMAP_H + 122 : #include <linux/fiemap.h> + 123 : #endif + 124 : + 125 : #if HAVE_BLKID_BLKID_H + 126 : #include <blkid/blkid.h> + 127 : #if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE + 128 : #define HAVE_BLKID 1 + 129 : #endif + 130 : #endif + 131 : + 132 : /** + 133 : * Includes some standard headers. + 134 : */ + 135 : #include <stdio.h> + 136 : #include <stdlib.h> /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */ + 137 : #include <stdarg.h> + 138 : #include <string.h> + 139 : #include <ctype.h> + 140 : #include <fcntl.h> + 141 : #include <assert.h> + 142 : #include <errno.h> + 143 : #include <signal.h> + 144 : #include <limits.h> 145 : - 146 : #if TIME_WITH_SYS_TIME - 147 : #include <sys/time.h> - 148 : #include <time.h> - 149 : #else - 150 : #if HAVE_SYS_TIME_H - 151 : #include <sys/time.h> - 152 : #else - 153 : #include <time.h> - 154 : #endif - 155 : #endif - 156 : - 157 : #if HAVE_MACH_MACH_TIME_H - 158 : #include <mach/mach_time.h> - 159 : #endif - 160 : - 161 : #if HAVE_DIRENT_H - 162 : #include <dirent.h> - 163 : #define NAMLEN(dirent) strlen((dirent)->d_name) + 146 : #if HAVE_STDINT_H + 147 : #include <stdint.h> + 148 : #endif + 149 : + 150 : #if HAVE_INTTYPES_H + 151 : #include <inttypes.h> + 152 : #endif + 153 : + 154 : #if HAVE_UNISTD_H + 155 : #include <unistd.h> + 156 : #endif + 157 : + 158 : #if TIME_WITH_SYS_TIME + 159 : #include <sys/time.h> + 160 : #include <time.h> + 161 : #else + 162 : #if HAVE_SYS_TIME_H + 163 : #include <sys/time.h> 164 : #else - 165 : #define dirent direct - 166 : #define NAMLEN(dirent) (dirent)->d_namlen - 167 : #if HAVE_SYS_NDIR_H - 168 : #include <sys/ndir.h> - 169 : #endif - 170 : #if HAVE_SYS_DIR_H - 171 : #include <sys/dir.h> - 172 : #endif - 173 : #if HAVE_NDIR_H - 174 : #include <ndir.h> - 175 : #endif - 176 : #endif - 177 : - 178 : #if HAVE_SYS_TYPES_H - 179 : #include <sys/types.h> - 180 : #endif - 181 : - 182 : #if HAVE_SYS_STAT_H - 183 : #include <sys/stat.h> + 165 : #include <time.h> + 166 : #endif + 167 : #endif + 168 : + 169 : #if HAVE_MACH_MACH_TIME_H + 170 : #include <mach/mach_time.h> + 171 : #endif + 172 : + 173 : #if HAVE_DIRENT_H + 174 : #include <dirent.h> + 175 : #define NAMLEN(dirent) strlen((dirent)->d_name) + 176 : #else + 177 : #define dirent direct + 178 : #define NAMLEN(dirent) (dirent)->d_namlen + 179 : #if HAVE_SYS_NDIR_H + 180 : #include <sys/ndir.h> + 181 : #endif + 182 : #if HAVE_SYS_DIR_H + 183 : #include <sys/dir.h> 184 : #endif - 185 : - 186 : #if HAVE_SYS_WAIT_H - 187 : #include <sys/wait.h> + 185 : #if HAVE_NDIR_H + 186 : #include <ndir.h> + 187 : #endif 188 : #endif - 189 : #ifndef WEXITSTATUS - 190 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) - 191 : #endif - 192 : #ifndef WIFEXITED - 193 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) - 194 : #endif - 195 : - 196 : #if HAVE_GETOPT_H - 197 : #include <getopt.h> - 198 : #endif - 199 : - 200 : #if HAVE_FNMATCH_H - 201 : #include <fnmatch.h> - 202 : #else - 203 : #include "fnmatch.h" - 204 : #endif - 205 : - 206 : #if HAVE_PTHREAD_H - 207 : #include <pthread.h> - 208 : #endif - 209 : - 210 : #if HAVE_MATH_H - 211 : #include <math.h> - 212 : #endif - 213 : - 214 : /** - 215 : * Disable case check in Windows. - 216 : */ - 217 : #ifdef _WIN32 - 218 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD - 219 : #else - 220 : #define FNM_CASEINSENSITIVE_FOR_WIN 0 - 221 : #endif - 222 : - 223 : #if HAVE_IO_H - 224 : #include <io.h> - 225 : #endif - 226 : - 227 : #if HAVE_GETOPT_LONG - 228 : #define SWITCH_GETOPT_LONG(a, b) a - 229 : #else - 230 : #define SWITCH_GETOPT_LONG(a, b) b - 231 : #endif - 232 : - 233 : /** - 234 : * Enables lock file support. - 235 : */ - 236 : #if HAVE_FLOCK && HAVE_FTRUNCATE - 237 : #define HAVE_LOCKFILE 1 - 238 : #endif - 239 : - 240 : /** - 241 : * Includes specific support for Windows or Linux. - 242 : */ - 243 : #ifdef __MINGW32__ - 244 : #include "mingw.h" - 245 : #else - 246 : #include "unix.h" - 247 : #endif - 248 : - 249 : /** - 250 : * Include list support to have tommy_node. - 251 : */ - 252 : #include "tommyds/tommylist.h" - 253 : - 254 : /** - 255 : * Another name for link() to avoid confusion with local variables called "link". - 256 : */ - 257 12 : static inline int hardlink(const char* a, const char* b) - 258 : { - 259 12 : return link(a, b); - 260 : } - 261 : - 262 : /** - 263 : * Get the device UUID. - 264 : * Return 0 on success. + 189 : + 190 : #if HAVE_SYS_TYPES_H + 191 : #include <sys/types.h> + 192 : #endif + 193 : + 194 : #if HAVE_SYS_STAT_H + 195 : #include <sys/stat.h> + 196 : #endif + 197 : + 198 : #if HAVE_SYS_WAIT_H + 199 : #include <sys/wait.h> + 200 : #endif + 201 : #ifndef WEXITSTATUS + 202 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) + 203 : #endif + 204 : #ifndef WIFEXITED + 205 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) + 206 : #endif + 207 : + 208 : #if HAVE_GETOPT_H + 209 : #include <getopt.h> + 210 : #endif + 211 : + 212 : #if HAVE_FNMATCH_H + 213 : #include <fnmatch.h> + 214 : #else + 215 : #include "fnmatch.h" + 216 : #endif + 217 : + 218 : #if HAVE_PTHREAD_H + 219 : #include <pthread.h> + 220 : #endif + 221 : + 222 : #if HAVE_MATH_H + 223 : #include <math.h> + 224 : #endif + 225 : + 226 : #if HAVE_EXECINFO_H + 227 : #include <execinfo.h> + 228 : #endif + 229 : + 230 : /** + 231 : * Enable thread use. + 232 : */ + 233 : #if HAVE_PTHREAD_H && HAVE_PTHREAD_CREATE + 234 : #define HAVE_PTHREAD 1 + 235 : #endif + 236 : + 237 : /** + 238 : * Disable case check in Windows. + 239 : */ + 240 : #ifdef _WIN32 + 241 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD + 242 : #else + 243 : #define FNM_CASEINSENSITIVE_FOR_WIN 0 + 244 : #endif + 245 : + 246 : #if HAVE_IO_H + 247 : #include <io.h> + 248 : #endif + 249 : + 250 : #if HAVE_GETOPT_LONG + 251 : #define SWITCH_GETOPT_LONG(a, b) a + 252 : #else + 253 : #define SWITCH_GETOPT_LONG(a, b) b + 254 : #endif + 255 : + 256 : /** + 257 : * Enables lock file support. + 258 : */ + 259 : #if HAVE_FLOCK && HAVE_FTRUNCATE + 260 : #define HAVE_LOCKFILE 1 + 261 : #endif + 262 : + 263 : /** + 264 : * Includes specific support for Windows or Linux. 265 : */ - 266 : int devuuid(uint64_t device, char* uuid, size_t size); - 267 : - 268 : /** - 269 : * Physical offset not yet read. - 270 : */ - 271 : #define FILEPHY_UNREAD_OFFSET 0 - 272 : - 273 : /** - 274 : * Special value returned when the filesystem doesn't report any offset for unknown reason. - 275 : */ - 276 : #define FILEPHY_UNREPORTED_OFFSET 1 - 277 : - 278 : /** - 279 : * Special value returned when the file doesn't have a real offset. - 280 : * For example, because it's stored in the NTFS MFT. - 281 : */ - 282 : #define FILEPHY_WITHOUT_OFFSET 2 - 283 : - 284 : /** - 285 : * Value indicating real offsets. All offsets greater or equal at this one are real. - 286 : */ - 287 : #define FILEPHY_REAL_OFFSET 3 - 288 : - 289 : /** - 290 : * Get the physcal address of the specified file. - 291 : * This is expected to be just a hint and not necessarely correct or unique. - 292 : * Return 0 on success. + 266 : #ifdef __MINGW32__ + 267 : #include "mingw.h" + 268 : #else + 269 : #include "unix.h" + 270 : #endif + 271 : + 272 : /** + 273 : * Include list support to have tommy_node. + 274 : */ + 275 : #include "tommyds/tommylist.h" + 276 : + 277 : /** + 278 : * Another name for link() to avoid confusion with local variables called "link". + 279 : */ + 280 12 : static inline int hardlink(const char* a, const char* b) + 281 : { + 282 12 : return link(a, b); + 283 : } + 284 : + 285 : /** + 286 : * Get the device UUID. + 287 : * Return 0 on success. + 288 : */ + 289 : int devuuid(uint64_t device, char* uuid, size_t size); + 290 : + 291 : /** + 292 : * Physical offset not yet read. 293 : */ - 294 : int filephy(const char* path, uint64_t size, uint64_t* physical); + 294 : #define FILEPHY_UNREAD_OFFSET 0 295 : 296 : /** - 297 : * Check if the underline filesystem support persistent inodes. - 298 : * Return -1 on error, 0 on success. - 299 : */ - 300 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space); - 301 : - 302 : /** - 303 : * Get the tick counter value. - 304 : * - 305 : * Note that the frequency is unspecified, because the time measure - 306 : * is meant to be used to compare the ratio between usage times. - 307 : */ - 308 : uint64_t tick(void); - 309 : - 310 : /** - 311 : * Get the tick counter value in millisecond. - 312 : */ - 313 : uint64_t tick_ms(void); - 314 : - 315 : /** - 316 : * Initializes the system. - 317 : */ - 318 : void os_init(int opt); - 319 : - 320 : /** - 321 : * Deintialize the system. + 297 : * Special value returned when the file-system doesn't report any offset for unknown reason. + 298 : */ + 299 : #define FILEPHY_UNREPORTED_OFFSET 1 + 300 : + 301 : /** + 302 : * Special value returned when the file doesn't have a real offset. + 303 : * For example, because it's stored in the NTFS MFT. + 304 : */ + 305 : #define FILEPHY_WITHOUT_OFFSET 2 + 306 : + 307 : /** + 308 : * Value indicating real offsets. All offsets greater or equal at this one are real. + 309 : */ + 310 : #define FILEPHY_REAL_OFFSET 3 + 311 : + 312 : /** + 313 : * Get the physcal address of the specified file. + 314 : * This is expected to be just a hint and not necessarily correct or unique. + 315 : * Return 0 on success. + 316 : */ + 317 : int filephy(const char* path, uint64_t size, uint64_t* physical); + 318 : + 319 : /** + 320 : * Check if the underline file-system support persistent inodes. + 321 : * Return -1 on error, 0 on success. 322 : */ - 323 : void os_done(void); + 323 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space); 324 : 325 : /** - 326 : * Log file. + 326 : * Get the tick counter value. 327 : * - 328 : * This stream if fully buffered. - 329 : * - 330 : * If no log file is selected, it's 0. - 331 : */ - 332 : FILE* stdlog; - 333 : - 334 : /** - 335 : * Exit codes for testing. - 336 : */ - 337 : int exit_success; - 338 : int exit_failure; - 339 : int exit_sync_needed; - 340 : #undef EXIT_SUCCESS - 341 : #undef EXIT_FAILURE - 342 : #define EXIT_SUCCESS exit_success - 343 : #define EXIT_FAILURE exit_failure - 344 : #define EXIT_SYNC_NEEDED exit_sync_needed - 345 : - 346 : /** - 347 : * Fill memory with psudeo-random values. - 348 : */ - 349 : int randomize(void* ptr, size_t size); - 350 : - 351 : /** - 352 : * Additional SMART attributes. - 353 : */ - 354 : #define SMART_ERROR 256 /**< ATA Error count. */ - 355 : #define SMART_SIZE 257 /**< Size in bytes. */ - 356 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ - 357 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ - 358 : - 359 : /** - 360 : * SMART attributes count. - 361 : */ - 362 : #define SMART_COUNT 260 - 363 : - 364 : /** - 365 : * Flags returned by smartctl. - 366 : */ - 367 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ - 368 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ - 369 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ - 370 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ - 371 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ - 372 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */ - 373 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ - 374 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ - 375 : - 376 : /** - 377 : * SMART max attribute length. - 378 : */ - 379 : #define SMART_MAX 64 - 380 : - 381 : /** - 382 : * Value for unassigned SMART attribute. - 383 : */ - 384 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL - 385 : - 386 : /** - 387 : * Device info entry. - 388 : */ - 389 : struct devinfo_struct { - 390 : uint64_t device; /**< Device ID. */ - 391 : char name[PATH_MAX]; /**< Name of the disk. */ - 392 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */ - 393 : char smartctl[PATH_MAX]; /**< Options for smartctl. */ - 394 : char file[PATH_MAX]; /**< File device. */ - 395 : #ifdef _WIN32 - 396 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ - 397 : #endif - 398 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */ - 399 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ - 400 : char smart_serial[SMART_MAX]; /**< SMART serial number. */ - 401 : #if HAVE_PTHREAD_CREATE - 402 : pthread_t thread; - 403 : #endif - 404 : tommy_node node; - 405 : }; - 406 : typedef struct devinfo_struct devinfo_t; - 407 : - 408 : #define DEVICE_LIST 0 - 409 : #define DEVICE_DOWN 1 - 410 : #define DEVICE_UP 2 - 411 : #define DEVICE_SMART 3 - 412 : - 413 : /** - 414 : * Query all the "high" level devices with the specified operation, - 415 : * and produces a list of "low" level devices to operate on. - 416 : * - 417 : * The passed "low" device list must be already initialized. - 418 : */ - 419 : int devquery(tommy_list* high, tommy_list* low, int operation); - 420 : - 421 : #endif - 422 : + 328 : * Note that the frequency is unspecified, because the time measure + 329 : * is meant to be used to compare the ratio between usage times. + 330 : */ + 331 : uint64_t tick(void); + 332 : + 333 : /** + 334 : * Get the tick counter value in millisecond. + 335 : */ + 336 : uint64_t tick_ms(void); + 337 : + 338 : /** + 339 : * Initializes the system. + 340 : */ + 341 : void os_init(int opt); + 342 : + 343 : /** + 344 : * Deinitialize the system. + 345 : */ + 346 : void os_done(void); + 347 : + 348 : /** + 349 : * Abort the process with a stacktrace. + 350 : */ + 351 : void os_abort(void) __noreturn; + 352 : + 353 : /** + 354 : * Log file. + 355 : * + 356 : * This stream if fully buffered. + 357 : * + 358 : * If no log file is selected, it's 0. + 359 : */ + 360 : FILE* stdlog; + 361 : + 362 : /** + 363 : * Exit codes for testing. + 364 : */ + 365 : int exit_success; + 366 : int exit_failure; + 367 : int exit_sync_needed; + 368 : #undef EXIT_SUCCESS + 369 : #undef EXIT_FAILURE + 370 : #define EXIT_SUCCESS exit_success + 371 : #define EXIT_FAILURE exit_failure + 372 : #define EXIT_SYNC_NEEDED exit_sync_needed + 373 : + 374 : /** + 375 : * Fill memory with psudeo-random values. + 376 : */ + 377 : int randomize(void* ptr, size_t size); + 378 : + 379 : /** + 380 : * Additional SMART attributes. + 381 : */ + 382 : #define SMART_ERROR 256 /**< ATA Error count. */ + 383 : #define SMART_SIZE 257 /**< Size in bytes. */ + 384 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ + 385 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ + 386 : + 387 : /** + 388 : * SMART attributes count. + 389 : */ + 390 : #define SMART_COUNT 260 + 391 : + 392 : /** + 393 : * Flags returned by smartctl. + 394 : */ + 395 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ + 396 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ + 397 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ + 398 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ + 399 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ + 400 : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */ + 401 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ + 402 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ + 403 : + 404 : /** + 405 : * SMART max attribute length. + 406 : */ + 407 : #define SMART_MAX 64 + 408 : + 409 : /** + 410 : * Value for unassigned SMART attribute. + 411 : */ + 412 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL + 413 : + 414 : /** + 415 : * Device info entry. + 416 : */ + 417 : struct devinfo_struct { + 418 : uint64_t device; /**< Device ID. */ + 419 : char name[PATH_MAX]; /**< Name of the disk. */ + 420 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */ + 421 : char smartctl[PATH_MAX]; /**< Options for smartctl. */ + 422 : char file[PATH_MAX]; /**< File device. */ + 423 : #ifdef _WIN32 + 424 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ + 425 : #endif + 426 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */ + 427 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ + 428 : char smart_serial[SMART_MAX]; /**< SMART serial number. */ + 429 : #if HAVE_PTHREAD + 430 : pthread_t thread; + 431 : #endif + 432 : tommy_node node; + 433 : }; + 434 : typedef struct devinfo_struct devinfo_t; + 435 : + 436 : #define DEVICE_LIST 0 + 437 : #define DEVICE_DOWN 1 + 438 : #define DEVICE_UP 2 + 439 : #define DEVICE_SMART 3 + 440 : + 441 : /** + 442 : * Query all the "high" level devices with the specified operation, + 443 : * and produces a list of "low" level devices to operate on. + 444 : * + 445 : * The passed "low" device list must be already initialized. + 446 : */ + 447 : int devquery(tommy_list* high, tommy_list* low, int operation); + 448 : + 449 : #endif + 450 : diff --git a/cov/cmdline/rehash.c.func-sort-c.html b/cov/cmdline/rehash.c.func-sort-c.html index 7f91b7d7..4ebb089d 100644 --- a/cov/cmdline/rehash.c.func-sort-c.html +++ b/cov/cmdline/rehash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/rehash.c.func.html b/cov/cmdline/rehash.c.func.html index 4f50c788..66f4b11d 100644 --- a/cov/cmdline/rehash.c.func.html +++ b/cov/cmdline/rehash.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/cmdline/rehash.c.gcov.html b/cov/cmdline/rehash.c.gcov.html index 66b8ba99..a8adc540 100644 --- a/cov/cmdline/rehash.c.gcov.html +++ b/cov/cmdline/rehash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -126,28 +126,28 @@ 64 : } 65 : 66 : /* mark all the block for rehashing */ - 67 9200 : for (i = 0; i < blockmax; ++i) { + 67 9208 : for (i = 0; i < blockmax; ++i) { 68 : snapraid_info info; 69 : 70 : /* if it's unused */ - 71 9199 : info = info_get(&state->infoarr, i); - 72 9199 : if (info == 0) { + 71 9207 : info = info_get(&state->infoarr, i); + 72 9207 : if (info == 0) { 73 : /* skip it */ 74 0 : continue; 75 : } 76 : - 77 9199 : if (info_get_rehash(info)) { + 77 9207 : if (info_get_rehash(info)) { 78 : /* LCOV_EXCL_START */ 79 : log_fatal("Internal inconsistency for a rehash already in progress\n"); - 80 : exit(EXIT_FAILURE); + 80 : os_abort(); 81 : /* LCOV_EXCL_STOP */ 82 : } 83 : 84 : /* enable the rehash */ - 85 9199 : info = info_set_rehash(info); + 85 9207 : info = info_set_rehash(info); 86 : 87 : /* save it */ - 88 9199 : info_set(&state->infoarr, i, info); + 88 9207 : info_set(&state->infoarr, i, info); 89 : } 90 : 91 : /* save the new content file */ diff --git a/cov/cmdline/scan.c.func-sort-c.html b/cov/cmdline/scan.c.func-sort-c.html index c14fca19..c5b96cf3 100644 --- a/cov/cmdline/scan.c.func-sort-c.html +++ b/cov/cmdline/scan.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 542 - 620 - 87.4 % + 554 + 622 + 89.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 23 @@ -61,59 +61,59 @@ dd_name_compare - 10485497 + 10959090 dstat - 1004217 + 1049496 scan_file - 1003082 + 1048310 scan_file_keep - 923721 + 968997 file_is_full_invalid_parity_and_stable - 923721 - - - dd_ino_compare - 103314 + 968997 scan_file_delayed_allocate - 100975 + 103840 scan_file_insert - 100975 + 103840 scan_file_allocate - 100975 + 103840 + + + dd_ino_compare + 103366 scan_file_refresh - 79190 + 79133 scan_file_remove - 56139 + 58983 scan_file_deallocate - 56139 + 58983 scan_link - 32837 + 34294 file_is_full_hashed_and_stable - 23659 + 23661 scan_link_insert @@ -121,7 +121,7 @@ scan_dir - 1614 + 1713 scan_link_remove @@ -129,22 +129,22 @@ scan_emptydir - 227 + 239 - state_diffscan - 80 + state_diffscan + 88 - state_scan - 73 + state_scan + 81 scan_emptydir_insert 10 - state_diff + state_diff 7 diff --git a/cov/cmdline/scan.c.func.html b/cov/cmdline/scan.c.func.html index abe27914..93ca7fe6 100644 --- a/cov/cmdline/scan.c.func.html +++ b/cov/cmdline/scan.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 542 - 620 - 87.4 % + 554 + 622 + 89.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 23 @@ -61,31 +61,31 @@ dd_ino_compare - 103314 + 103366 dd_name_compare - 10485497 + 10959090 dstat - 1004217 + 1049496 file_is_full_hashed_and_stable - 23659 + 23661 file_is_full_invalid_parity_and_stable - 923721 + 968997 scan_dir - 1614 + 1713 scan_emptydir - 227 + 239 scan_emptydir_insert @@ -97,39 +97,39 @@ scan_file - 1003082 + 1048310 scan_file_allocate - 100975 + 103840 scan_file_deallocate - 56139 + 58983 scan_file_delayed_allocate - 100975 + 103840 scan_file_insert - 100975 + 103840 scan_file_keep - 923721 + 968997 scan_file_refresh - 79190 + 79133 scan_file_remove - 56139 + 58983 scan_link - 32837 + 34294 scan_link_insert @@ -140,16 +140,16 @@ 956 - state_diff + state_diff 7 - state_diffscan - 80 + state_diffscan + 88 - state_scan - 73 + state_scan + 81
diff --git a/cov/cmdline/scan.c.gcov.html b/cov/cmdline/scan.c.gcov.html index 28c662b0..6fbcb4f0 100644 --- a/cov/cmdline/scan.c.gcov.html +++ b/cov/cmdline/scan.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 542 - 620 - 87.4 % + 554 + 622 + 89.1 % Date: - 2015-11-20 + 2016-01-09 Functions: 23 @@ -145,32 +145,32 @@ 83 : /** 84 : * Process a symbolic link. 85 : */ - 86 32837 : static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag) + 86 34294 : static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag) 87 : { - 88 32837 : struct snapraid_state* state = scan->state; - 89 32837 : struct snapraid_disk* disk = scan->disk; + 88 34294 : struct snapraid_state* state = scan->state; + 89 34294 : struct snapraid_disk* disk = scan->disk; 90 : struct snapraid_link* slink; 91 : 92 : /* check if the link already exists */ - 93 32837 : slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub)); - 94 32837 : if (slink) { + 93 34294 : slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub)); + 94 34294 : if (slink) { 95 : /* check if multiple files have the same name */ - 96 30380 : if (link_flag_has(slink, FILE_IS_PRESENT)) { + 96 31837 : if (link_flag_has(slink, FILE_IS_PRESENT)) { 97 : /* LCOV_EXCL_START */ 98 : log_fatal("Internal inconsistency for link '%s%s'\n", disk->dir, sub); - 99 : exit(EXIT_FAILURE); + 99 : os_abort(); 100 : /* LCOV_EXCL_STOP */ 101 : } 102 : 103 : /* mark as present */ - 104 30380 : link_flag_set(slink, FILE_IS_PRESENT); + 104 31837 : link_flag_set(slink, FILE_IS_PRESENT); 105 : 106 : /* check if the link is not changed and it's of the same kind */ - 107 30380 : if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) { + 107 31837 : if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) { 108 : /* it's equal */ - 109 30374 : ++scan->count_equal; + 109 31831 : ++scan->count_equal; 110 : - 111 60748 : if (state->opt.gui) { + 111 63662 : if (state->opt.gui) { 112 829 : log_tag("scan:equal:%s:%s\n", disk->name, esc(slink->sub)); 113 : } 114 : } else { @@ -193,7 +193,7 @@ 131 : } 132 : 133 : /* nothing more to do */ - 134 63217 : return; + 134 66131 : return; 135 : } else { 136 : /* create the new link */ 137 2457 : ++scan->count_insert; @@ -219,72 +219,72 @@ 157 : /** 158 : * Insert the specified file in the parity. 159 : */ - 160 100975 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 160 103840 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 161 : { - 162 100975 : struct snapraid_state* state = scan->state; - 163 100975 : struct snapraid_disk* disk = scan->disk; + 162 103840 : struct snapraid_state* state = scan->state; + 163 103840 : struct snapraid_disk* disk = scan->disk; 164 : block_off_t i; 165 : block_off_t parity_pos; 166 : 167 : /* state changed */ - 168 100975 : state->need_write = 1; + 168 103840 : state->need_write = 1; 169 : 170 : /* allocate the blocks of the file */ - 171 100975 : parity_pos = disk->first_free_block; - 172 349689 : for (i = 0; i < file->blockmax; ++i) { + 171 103840 : parity_pos = disk->first_free_block; + 172 355546 : for (i = 0; i < file->blockmax; ++i) { 173 : struct snapraid_block* block; 174 : struct snapraid_block* over_block; 175 : snapraid_info info; 176 : 177 : /* increment the position until the first really free block */ - 178 1013456 : while (block_has_file(fs_par2block_get(disk, parity_pos))) - 179 516028 : ++parity_pos; + 178 1072060 : while (block_has_file(fs_par2block_get(disk, parity_pos))) + 179 568648 : ++parity_pos; 180 : 181 : /* get block we are going to overwrite, if any */ - 182 248714 : over_block = fs_par2block_get(disk, parity_pos); + 182 251706 : over_block = fs_par2block_get(disk, parity_pos); 183 : 184 : /* deallocate it */ - 185 248714 : if (over_block != BLOCK_EMPTY) - 186 93089 : fs_deallocate(disk, parity_pos); + 185 251706 : if (over_block != BLOCK_EMPTY) + 186 95873 : fs_deallocate(disk, parity_pos); 187 : 188 : /* get block specific info */ - 189 248714 : info = info_get(&state->infoarr, parity_pos); + 189 251706 : info = info_get(&state->infoarr, parity_pos); 190 : 191 : /* get the new block we are going to write */ - 192 248714 : block = fs_file2block_get(file, i); + 192 251706 : block = fs_file2block_get(file, i); 193 : 194 : /* if the file block already has an updated hash without rehash */ - 195 248714 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { + 195 251706 : if (block_has_updated_hash(block) && !info_get_rehash(info)) { 196 : /* the only possible case is for REP blocks */ - 197 37269 : assert(block_state_get(block) == BLOCK_STATE_REP); + 197 86941 : assert(block_state_get(block) == BLOCK_STATE_REP); 198 : 199 : /* convert to a REP block */ - 200 37269 : block_state_set(block, BLOCK_STATE_REP); + 200 86941 : block_state_set(block, BLOCK_STATE_REP); 201 : 202 : /* and keep the hash as it's */ 203 : } else { 204 : unsigned over_state; 205 : 206 : /* convert to a CHG block */ - 207 211445 : block_state_set(block, BLOCK_STATE_CHG); + 207 164765 : block_state_set(block, BLOCK_STATE_CHG); 208 : 209 : /* state of the block we are going to overwrite */ - 210 211445 : over_state = block_state_get(over_block); + 210 164765 : over_state = block_state_get(over_block); 211 : 212 : /* if the block is an empty one */ - 213 211445 : if (over_state == BLOCK_STATE_EMPTY) { + 213 164765 : if (over_state == BLOCK_STATE_EMPTY) { 214 : /* the block was empty and filled with zeros */ 215 : /* set the hash to the special ZERO value */ - 216 153288 : hash_zero_set(block->hash); + 216 115487 : hash_zero_set(block->hash); 217 : } else { 218 : /* otherwise it's a DELETED one */ - 219 58157 : assert(over_state == BLOCK_STATE_DELETED); + 219 49278 : assert(over_state == BLOCK_STATE_DELETED); 220 : 221 : /* copy the past hash of the block */ - 222 58157 : memcpy(block->hash, over_block->hash, HASH_SIZE); + 222 49278 : memcpy(block->hash, over_block->hash, HASH_SIZE); 223 : 224 : /* if we have not already cleared the past hash */ - 225 58157 : if (!state->clear_past_hash) { + 225 49278 : if (!state->clear_past_hash) { 226 : /* in this case we don't know if the old state is still the one */ 227 : /* stored inside the parity, because after an aborted sync, the parity */ 228 : /* may be or may be not have been updated with the new data */ @@ -294,22 +294,22 @@ 232 : /* - Sync aborted after, updating the parity to the new state, */ 233 : /* but without saving the content file representing this new state. */ 234 : /* - Another file is added again (exactly here) */ - 235 : /* with the hash of DELETED block not represeting the real parity state */ + 235 : /* with the hash of DELETED block not representing the real parity state */ 236 381 : hash_invalid_set(block->hash); 237 : } 238 : } 239 : } 240 : 241 : /* store in the disk map, after invalidating all the other blocks */ - 242 248714 : fs_allocate(disk, parity_pos, file, i); + 242 251706 : fs_allocate(disk, parity_pos, file, i); 243 : 244 : /* set the new free position */ - 245 248714 : disk->first_free_block = parity_pos + 1; + 245 251706 : disk->first_free_block = parity_pos + 1; 246 : } 247 : 248 : /* insert in the list of contained files */ - 249 100975 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); - 250 100975 : } + 249 103840 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 250 103840 : } 251 : 252 : /** 253 : * Delete the specified file from the parity. @@ -318,44 +318,44 @@ 256 : * The file is then inserted in the deleted set, and it should not be deallocated, 257 : * as the parity still references it. 258 : */ - 259 56139 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) + 259 58983 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) 260 : { - 261 56139 : struct snapraid_state* state = scan->state; - 262 56139 : struct snapraid_disk* disk = scan->disk; + 261 58983 : struct snapraid_state* state = scan->state; + 262 58983 : struct snapraid_disk* disk = scan->disk; 263 : block_off_t i; 264 : 265 : /* remove from the list of contained files */ - 266 56139 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); + 266 58983 : tommy_list_remove_existing(&disk->filelist, &file->nodelist); 267 : 268 : /* state changed */ - 269 56139 : state->need_write = 1; + 269 58983 : state->need_write = 1; 270 : 271 : /* here we are supposed to adjust the ::first_free_block position */ 272 : /* with the parity position we are deleting */ 273 : /* but we also know that we do only delayed insert, after all the deletion, */ 274 : /* so at this point ::first_free_block is always at 0, and we don't need to update it */ - 275 56139 : if (disk->first_free_block != 0) { + 275 58983 : if (disk->first_free_block != 0) { 276 : /* LCOV_EXCL_START */ 277 : log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub); - 278 : exit(EXIT_FAILURE); + 278 : os_abort(); 279 : /* LCOV_EXCL_STOP */ 280 : } 281 : 282 : /* free all the blocks of the file */ - 283 194478 : for (i = 0; i < file->blockmax; ++i) { - 284 138339 : struct snapraid_block* block = fs_file2block_get(file, i); + 283 200146 : for (i = 0; i < file->blockmax; ++i) { + 284 141163 : struct snapraid_block* block = fs_file2block_get(file, i); 285 : unsigned block_state; 286 : 287 : /* in case we scan after an aborted sync, */ 288 : /* we could get also intermediate states */ - 289 138339 : block_state = block_state_get(block); - 290 138339 : switch (block_state) { + 289 141163 : block_state = block_state_get(block); + 290 141163 : switch (block_state) { 291 : case BLOCK_STATE_BLK : 292 : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */ - 293 33544 : break; + 293 33358 : break; 294 : case BLOCK_STATE_CHG : 295 : /* if we have not already cleared the past hash */ - 296 57596 : if (!state->clear_past_hash) { + 296 28000 : if (!state->clear_past_hash) { 297 : /* in these cases we don't know if the old state is still the one */ 298 : /* stored inside the parity, because after an aborted sync, the parity */ 299 : /* may be or may be not have been updated with the data that it's now */ @@ -366,39 +366,39 @@ 304 : /* but without saving the content file representing this new state. */ 305 : /* - File is now deleted after the aborted sync */ 306 : /* - Sync again, deleting the blocks (exactly here) */ - 307 : /* with the hash of CHG block not represeting the real parity state */ + 307 : /* with the hash of CHG block not representing the real parity state */ 308 0 : hash_invalid_set(block->hash); 309 : } - 310 57596 : break; + 310 28000 : break; 311 : case BLOCK_STATE_REP : 312 : /* we just don't know the old hash, and then we set it to invalid */ - 313 47199 : hash_invalid_set(block->hash); - 314 47199 : break; + 313 79805 : hash_invalid_set(block->hash); + 314 79805 : break; 315 : default : 316 : /* LCOV_EXCL_START */ 317 : log_fatal("Internal inconsistency in file '%s' deallocating block '%u:%u' state %u\n", file->sub, i, file->blockmax, block_state); - 318 : exit(EXIT_FAILURE); + 318 : os_abort(); 319 : /* LCOV_EXCL_STOP */ 320 : } 321 : 322 : /* set the block as deleted */ - 323 138339 : block_state_set(block, BLOCK_STATE_DELETED); + 323 141163 : block_state_set(block, BLOCK_STATE_DELETED); 324 : } 325 : 326 : /* mark the file as deleted */ - 327 56139 : file_flag_set(file, FILE_IS_DELETED); + 327 58983 : file_flag_set(file, FILE_IS_DELETED); 328 : 329 : /* insert it in the list of deleted blocks */ - 330 56139 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); - 331 56139 : } + 330 58983 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); + 331 58983 : } 332 : - 333 100975 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) + 333 103840 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) 334 : { - 335 100975 : struct snapraid_state* state = scan->state; - 336 100975 : struct snapraid_disk* disk = scan->disk; + 335 103840 : struct snapraid_state* state = scan->state; + 336 103840 : struct snapraid_disk* disk = scan->disk; 337 : 338 : /* if we sort for physical offsets we have to read them for new files */ - 339 100975 : if (state->opt.force_order == SORT_PHYSICAL + 339 103840 : if (state->opt.force_order == SORT_PHYSICAL 340 11432 : && file->physical == FILEPHY_UNREAD_OFFSET 341 : ) { 342 : char path_next[PATH_MAX]; @@ -414,30 +414,30 @@ 352 : } 353 : 354 : /* insert in the delayed list */ - 355 100975 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); - 356 100975 : } + 355 103840 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); + 356 103840 : } 357 : 358 : /** 359 : * Check if a file is completely formed of blocks with invalid parity, 360 : * and no rehash is tagged, and if it has at least one block. 361 : */ - 362 923721 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 362 968997 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 363 : { 364 : block_off_t i; 365 : 366 : /* with no block, it never has an invalid parity */ - 367 923721 : if (file->blockmax == 0) - 368 1290 : return 0; + 367 968997 : if (file->blockmax == 0) + 368 1354 : return 0; 369 : 370 : /* check all blocks */ - 371 976066 : for (i = 0; i < file->blockmax; ++i) { + 371 1032530 : for (i = 0; i < file->blockmax; ++i) { 372 : snapraid_info info; - 373 954281 : struct snapraid_block* block = fs_file2block_get(file, i); + 373 1007823 : struct snapraid_block* block = fs_file2block_get(file, i); 374 : block_off_t parity_pos; 375 : 376 : /* exclude blocks with parity */ - 377 954281 : if (!block_has_invalid_parity(block)) - 378 900646 : return 0; + 377 1007823 : if (!block_has_invalid_parity(block)) + 378 923696 : return 0; 379 : 380 : /* 381 : * Get the parity position, but only after checking @@ -445,40 +445,40 @@ 383 : * This is not really required, as we are sure 384 : * that 'kept" files are mapped into parity. 385 : */ - 386 53635 : parity_pos = fs_file2par_get(disk, file, i); + 386 84127 : parity_pos = fs_file2par_get(disk, file, i); 387 : 388 : /* get block specific info */ - 389 53635 : info = info_get(&state->infoarr, parity_pos); + 389 84127 : info = info_get(&state->infoarr, parity_pos); 390 : 391 : /* if rehash fails */ - 392 53635 : if (info_get_rehash(info)) - 393 0 : return 0; + 392 84127 : if (info_get_rehash(info)) + 393 19240 : return 0; 394 : } 395 : - 396 21785 : return 1; + 396 24707 : return 1; 397 : } 398 : 399 : /** 400 : * Check if a file is completely formed of blocks with an updated hash, 401 : * and no rehash is tagged, and if it has at least one block. 402 : */ - 403 23659 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) + 403 23661 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) 404 : { 405 : block_off_t i; 406 : 407 : /* with no block, it never has a hash */ - 408 23659 : if (file->blockmax == 0) + 408 23661 : if (file->blockmax == 0) 409 27 : return 0; 410 : 411 : /* check all blocks */ - 412 42158 : for (i = 0; i < file->blockmax; ++i) { + 412 81853 : for (i = 0; i < file->blockmax; ++i) { 413 : snapraid_info info; - 414 35949 : struct snapraid_block* block = fs_file2block_get(file, i); + 414 58220 : struct snapraid_block* block = fs_file2block_get(file, i); 415 : block_off_t parity_pos; 416 : 417 : /* exclude blocks without hash */ - 418 35949 : if (!block_has_updated_hash(block)) - 419 1704 : return 0; + 418 58220 : if (!block_has_updated_hash(block)) + 419 1 : return 0; 420 : 421 : /* 422 : * Get the parity position, but only AFTER checking @@ -492,17 +492,17 @@ 430 : * As just allocated files have only CHG blocks, checking that 431 : * the hash is updated is enough to exclude such cases. 432 : */ - 433 34245 : parity_pos = fs_file2par_get(disk, file, i); + 433 58219 : parity_pos = fs_file2par_get(disk, file, i); 434 : 435 : /* get block specific info */ - 436 34245 : info = info_get(&state->infoarr, parity_pos); + 436 58219 : info = info_get(&state->infoarr, parity_pos); 437 : 438 : /* exclude blocks needing a rehash */ - 439 34245 : if (info_get_rehash(info)) - 440 15719 : return 0; + 439 58219 : if (info_get_rehash(info)) + 440 0 : return 0; 441 : } 442 : - 443 6209 : return 1; + 443 23633 : return 1; 444 : } 445 : 446 : /** @@ -514,7 +514,7 @@ 452 : * 453 : * If this happens, we read also the physical offset, to avoid to read it later. 454 : */ - 455 79190 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) + 455 79133 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) 456 : { 457 : #if HAVE_LSTAT_SYNC 458 : struct snapraid_state* state = scan->state; @@ -586,43 +586,43 @@ 524 : (void)st; 525 : (void)physical; 526 : #endif - 527 79190 : } + 527 79133 : } 528 : 529 : /** 530 : * Insert the file in the data set. 531 : */ - 532 100975 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) + 532 103840 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) 533 : { - 534 100975 : struct snapraid_disk* disk = scan->disk; + 534 103840 : struct snapraid_disk* disk = scan->disk; 535 : 536 : /* insert the file in the containers */ - 537 100975 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 538 100975 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - 539 100975 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 540 100975 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 537 103840 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 538 103840 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 539 103840 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 540 103840 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); 541 : 542 : /* delayed allocation of the parity */ - 543 100975 : scan_file_delayed_allocate(scan, file); - 544 100975 : } + 543 103840 : scan_file_delayed_allocate(scan, file); + 544 103840 : } 545 : 546 : /** 547 : * Remove the file from the data set. 548 : * 549 : * File is then deleted. 550 : */ - 551 56139 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) + 551 58983 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) 552 : { - 553 56139 : struct snapraid_disk* disk = scan->disk; + 553 58983 : struct snapraid_disk* disk = scan->disk; 554 : 555 : /* remove the file from the containers */ - 556 56139 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) - 557 56084 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); - 558 56139 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); - 559 56139 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); + 556 58983 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + 557 58942 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 558 58983 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + 559 58983 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); 560 : 561 : /* deallocate the file from the parity */ - 562 56139 : scan_file_deallocate(scan, file); - 563 56139 : } + 562 58983 : scan_file_deallocate(scan, file); + 563 58983 : } 564 : 565 : /** 566 : * Keep the file as it's (or with only a name/inode modification). @@ -635,29 +635,29 @@ 573 : * This could happen after a failed sync, when some other files are deleted, 574 : * and then new ones can be moved backward to fill the hole created. 575 : */ - 576 923721 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) + 576 968997 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) 577 : { - 578 923721 : struct snapraid_disk* disk = scan->disk; + 578 968997 : struct snapraid_disk* disk = scan->disk; 579 : 580 : /* if the file is full invalid, schedule a reinsert at later stage */ - 581 923721 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { - 582 21785 : struct snapraid_file* copy = file_dup(file); + 581 968997 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { + 582 24707 : struct snapraid_file* copy = file_dup(file); 583 : 584 : /* remove the file */ - 585 21785 : scan_file_remove(scan, file); + 585 24707 : scan_file_remove(scan, file); 586 : 587 : /* reinsert the copy in the delayed list */ - 588 21785 : scan_file_insert(scan, copy); + 588 24707 : scan_file_insert(scan, copy); 589 : } - 590 923721 : } + 590 968997 : } 591 : 592 : /** 593 : * Process a file. 594 : */ - 595 1003082 : static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical) + 595 1048310 : static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical) 596 : { - 597 1003082 : struct snapraid_state* state = scan->state; - 598 1003082 : struct snapraid_disk* disk = scan->disk; + 597 1048310 : struct snapraid_state* state = scan->state; + 598 1048310 : struct snapraid_disk* disk = scan->disk; 599 : struct snapraid_file* file; 600 : tommy_node* i; 601 : int is_original_file_size_different_than_zero; @@ -668,7 +668,7 @@ 606 : * If the disk has persistent inodes and UUID, try a search on the past inodes, 607 : * to detect moved files. 608 : * - 609 : * For persistent inodes we mean inodes that keep their values when the filesystem + 609 : * For persistent inodes we mean inodes that keep their values when the file-system 610 : * is unmounted and remounted. This don't always happen. 611 : * 612 : * Cases found are: @@ -682,55 +682,55 @@ 620 : * file recognition. 621 : * 622 : * For persistent UUID we mean that it has the same UUID as before. - 623 : * Otherwise, if the UUID is changed, likely it's a new recreated filesystem, + 623 : * Otherwise, if the UUID is changed, likely it's a new recreated file-system, 624 : * and then the inode have no meaning. 625 : * - 626 : * Note that to disable the search by past inode, we do this implicitely + 626 : * Note that to disable the search by past inode, we do this implicitly 627 : * removing all the past inode before searching for files. 628 : * This ensures that no file is found with a past inode, but at the same time, 629 : * it allows to find new files with the same inode, to identify them as hardlinks. 630 : */ - 631 1003082 : int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid; + 631 1048310 : int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid; 632 : 633 : /* always search with the new inode, in the all new inodes found until now, */ 634 : /* with the eventual presence of also the past inodes */ - 635 1003082 : uint64_t inode = st->st_ino; + 635 1048310 : uint64_t inode = st->st_ino; 636 : - 637 1003082 : file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + 637 1048310 : file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); 638 : 639 : /* identify moved files with past inodes and hardlinks with the new inodes */ - 640 1003082 : if (file) { + 640 1048310 : if (file) { 641 : /* check if the file is not changed */ - 642 837733 : if (file->size == st->st_size - 643 826569 : && file->mtime_sec == st->st_mtime - 644 823506 : && (file->mtime_nsec == STAT_NSEC(st) + 642 889551 : if (file->size == st->st_size + 643 871917 : && file->mtime_sec == st->st_mtime + 644 868905 : && (file->mtime_nsec == STAT_NSEC(st) 645 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 646 : /* it happens when upgrading from an old version of SnapRAID */ 647 : /* not yet supporting the nanosecond field */ - 648 2 : || file->mtime_nsec == STAT_NSEC_INVALID + 648 6 : || file->mtime_nsec == STAT_NSEC_INVALID 649 : ) 650 : ) { 651 : /* check if multiple files have the same inode */ - 652 823504 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 652 868899 : if (file_flag_has(file, FILE_IS_PRESENT)) { 653 : #if HAVE_STRUCT_STAT_ST_NLINK - 654 171 : if (st->st_nlink <= 1) { + 654 180 : if (st->st_nlink <= 1) { 655 : /* LCOV_EXCL_START */ 656 : log_fatal("Internal inode '%" PRIu64 "' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub); - 657 : exit(EXIT_FAILURE); + 657 : os_abort(); 658 : /* LCOV_EXCL_STOP */ 659 : } 660 : #endif 661 : /* it's a hardlink */ - 662 171 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK); - 663 171 : return; + 662 180 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK); + 663 180 : return; 664 : } 665 : 666 : /* mark as present */ - 667 823333 : file_flag_set(file, FILE_IS_PRESENT); + 667 868719 : file_flag_set(file, FILE_IS_PRESENT); 668 : 669 : /* update the nanoseconds mtime only if different */ 670 : /* to avoid unneeded updates */ - 671 823333 : if (file->mtime_nsec == STAT_NSEC_INVALID + 671 868719 : if (file->mtime_nsec == STAT_NSEC_INVALID 672 0 : && STAT_NSEC(st) != file->mtime_nsec 673 : ) { 674 0 : file->mtime_nsec = STAT_NSEC(st); @@ -739,7 +739,7 @@ 677 0 : state->need_write = 1; 678 : } 679 : - 680 823333 : if (strcmp(file->sub, sub) != 0) { + 680 868719 : if (strcmp(file->sub, sub) != 0) { 681 : /* if the path is different, it means a moved file with the same inode */ 682 155 : ++scan->count_move; 683 : @@ -761,96 +761,96 @@ 699 155 : state->need_write = 1; 700 : } else { 701 : /* otherwise it's equal */ - 702 823178 : ++scan->count_equal; + 702 868564 : ++scan->count_equal; 703 : - 704 823178 : if (state->opt.gui) { - 705 22559 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub)); + 704 868564 : if (state->opt.gui) { + 705 22587 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub)); 706 : } 707 : } 708 : 709 : /* mark the file as kept */ - 710 823333 : scan_file_keep(scan, file); + 710 868719 : scan_file_keep(scan, file); 711 : 712 : /* nothing more to do */ - 713 823333 : return; + 713 868719 : return; 714 : } 715 : 716 : /* here the file matches the inode, but not the other info */ 717 : /* if could be a modified file with the same name, */ 718 : /* or a restored/copied file that get assigned a previously used inode, */ - 719 : /* or a filesystem with not persistent inodes */ + 719 : /* or a file-system with not persistent inodes */ 720 : 721 : /* for sure it cannot be already present */ - 722 14229 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 722 20652 : if (file_flag_has(file, FILE_IS_PRESENT)) { 723 : /* LCOV_EXCL_START */ 724 : log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub); - 725 : exit(EXIT_FAILURE); + 725 : os_abort(); 726 : /* LCOV_EXCL_STOP */ 727 : } 728 : 729 : /* assume a previously used inode, it's the worst case */ 730 : /* and we handle it removing the duplicate stored inode. */ - 731 : /* If the file is found by name (not necessarely in this function call), */ + 731 : /* If the file is found by name (not necessarily in this function call), */ 732 : /* it will have the inode restored, otherwise, it will get removed */ 733 : 734 : /* remove from the inode set */ - 735 14229 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 735 20652 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 736 : 737 : /* clear the inode */ 738 : /* this is not really needed for correct functionality */ 739 : /* because we are going to set FILE_IS_WITHOUT_INODE */ 740 : /* but it's easier for debugging to have invalid inodes set to 0 */ - 741 14229 : file->inode = 0; + 741 20652 : file->inode = 0; 742 : 743 : /* mark as missing inode */ - 744 14229 : file_flag_set(file, FILE_IS_WITHOUT_INODE); + 744 20652 : file_flag_set(file, FILE_IS_WITHOUT_INODE); 745 : 746 : /* go further to find it by name */ 747 : } 748 : 749 : /* initialize for later overwrite */ - 750 179578 : is_file_reported = 0; - 751 179578 : is_original_file_size_different_than_zero = 0; + 750 179411 : is_file_reported = 0; + 751 179411 : is_original_file_size_different_than_zero = 0; 752 : 753 : /* then try finding it by name */ - 754 179578 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); + 754 179411 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); 755 : 756 : /* keep track if the file already exists */ - 757 179578 : is_file_already_present = file != 0; + 757 179411 : is_file_already_present = file != 0; 758 : - 759 179578 : if (is_file_already_present) { + 759 179411 : if (is_file_already_present) { 760 : /* if the file is without an inode */ - 761 105104 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { + 761 104908 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { 762 : /* set it now */ - 763 14174 : file->inode = st->st_ino; + 763 20621 : file->inode = st->st_ino; 764 : 765 : /* insert in the set */ - 766 14174 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 766 20621 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 767 : 768 : /* unmark as missing inode */ - 769 14174 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); + 769 20621 : file_flag_clear(file, FILE_IS_WITHOUT_INODE); 770 : } else { 771 : /* here the inode has to be different, otherwise we would have found it before */ - 772 90930 : if (file->inode == st->st_ino) { + 772 84287 : if (file->inode == st->st_ino) { 773 : /* LCOV_EXCL_START */ 774 : log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub); - 775 : exit(EXIT_FAILURE); + 775 : os_abort(); 776 : /* LCOV_EXCL_STOP */ 777 : } 778 : } 779 : 780 : /* for sure it cannot be already present */ - 781 105104 : if (file_flag_has(file, FILE_IS_PRESENT)) { + 781 104908 : if (file_flag_has(file, FILE_IS_PRESENT)) { 782 : /* LCOV_EXCL_START */ 783 : log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub); - 784 : exit(EXIT_FAILURE); + 784 : os_abort(); 785 : /* LCOV_EXCL_STOP */ 786 : } 787 : 788 : /* check if the file is not changed */ - 789 105104 : if (file->size == st->st_size - 790 104510 : && file->mtime_sec == st->st_mtime - 791 100388 : && (file->mtime_nsec == STAT_NSEC(st) + 789 104908 : if (file->size == st->st_size + 790 104314 : && file->mtime_sec == st->st_mtime + 791 100278 : && (file->mtime_nsec == STAT_NSEC(st) 792 : /* always accept the stored value if it's STAT_NSEC_INVALID */ 793 : /* it happens when upgrading from an old version of SnapRAID */ 794 : /* not yet supporting the nanosecond field */ @@ -858,11 +858,11 @@ 796 : ) 797 : ) { 798 : /* mark as present */ - 799 100388 : file_flag_set(file, FILE_IS_PRESENT); + 799 100278 : file_flag_set(file, FILE_IS_PRESENT); 800 : 801 : /* update the nano seconds mtime only if different */ 802 : /* to avoid unneeded updates */ - 803 100388 : if (file->mtime_nsec == STAT_NSEC_INVALID + 803 100278 : if (file->mtime_nsec == STAT_NSEC_INVALID 804 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID 805 : ) { 806 0 : file->mtime_nsec = STAT_NSEC(st); @@ -872,55 +872,55 @@ 810 : } 811 : 812 : /* if when processing the disk we used the past inodes values */ - 813 100388 : if (has_past_inodes) { + 813 100278 : if (has_past_inodes) { 814 : /* if persistent inodes are supported, we are sure that the inode number */ 815 : /* is now different, because otherwise the file would have been found */ 816 : /* when searching by inode. */ 817 : /* if the inode is different, it means a rewritten file with the same path */ 818 : /* like when restoring a backup that restores also the timestamp */ - 819 100388 : ++scan->count_restore; + 819 100268 : ++scan->count_restore; 820 : - 821 100388 : log_tag("scan:restore:%s:%s\n", disk->name, esc(sub)); - 822 100388 : if (is_diff) { + 821 100268 : log_tag("scan:restore:%s:%s\n", disk->name, esc(sub)); + 822 100268 : if (is_diff) { 823 0 : printf("restore %s%s\n", disk->dir, sub); 824 : } 825 : 826 : /* remove from the inode set */ - 827 100388 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 827 100268 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); 828 : 829 : /* save the new inode */ - 830 100388 : file->inode = st->st_ino; + 830 100268 : file->inode = st->st_ino; 831 : 832 : /* reinsert in the inode set */ - 833 100388 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 833 100268 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); 834 : 835 : /* we have to save the new inode */ - 836 100388 : state->need_write = 1; + 836 100268 : state->need_write = 1; 837 : } else { 838 : /* otherwise it's the case of not persistent inode, where doesn't */ 839 : /* matter if the inode is different or equal, because they have no */ 840 : /* meaning, and then we don't even save them */ - 841 0 : ++scan->count_equal; + 841 10 : ++scan->count_equal; 842 : - 843 0 : if (state->opt.gui) { + 843 10 : if (state->opt.gui) { 844 0 : log_tag("scan:equal:%s:%s\n", disk->name, esc(file->sub)); 845 : } 846 : } 847 : 848 : /* mark the file as kept */ - 849 100388 : scan_file_keep(scan, file); + 849 100278 : scan_file_keep(scan, file); 850 : 851 : /* nothing more to do */ - 852 100388 : return; + 852 100278 : return; 853 : } 854 : 855 : /* here if the file is changed but with the correct name */ 856 : 857 : /* keep track if the original file was not of zero size */ - 858 4716 : is_original_file_size_different_than_zero = file->size != 0; + 858 4630 : is_original_file_size_different_than_zero = file->size != 0; 859 : 860 : /* remove it, and continue to insert it again */ - 861 4716 : scan_file_remove(scan, file); + 861 4630 : scan_file_remove(scan, file); 862 : 863 : /* and continue to insert it again */ 864 : } @@ -928,13 +928,13 @@ 866 : /* refresh the info, to ensure that they are synced, */ 867 : /* note that we refresh only the info of the new or modified files */ 868 : /* because this is slow operation */ - 869 79190 : scan_file_refresh(scan, sub, st, &physical); + 869 79133 : scan_file_refresh(scan, sub, st, &physical); 870 : 871 : #ifndef _WIN32 872 : /* do a safety check to ensure that the common ext4 case of zeroing */ 873 : /* the size of a file after a crash doesn't propagate to the backup */ 874 : /* this check is specific for Linux, so we disable it on Windows */ - 875 79190 : if (is_original_file_size_different_than_zero && st->st_size == 0) { + 875 79133 : if (is_original_file_size_different_than_zero && st->st_size == 0) { 876 0 : if (!state->opt.force_zero) { 877 : /* LCOV_EXCL_START */ 878 : log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub); @@ -953,74 +953,74 @@ 891 : #endif 892 : 893 : /* insert it */ - 894 79190 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); + 894 79133 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); 895 : 896 : /* mark it as present */ - 897 79190 : file_flag_set(file, FILE_IS_PRESENT); + 897 79133 : file_flag_set(file, FILE_IS_PRESENT); 898 : 899 : /* if copy detection is enabled */ 900 : /* note that the copy detection is tried also for updated files */ 901 : /* this makes sense because it may happen to have two different copies */ 902 : /* of the same file, and we move the right one over the wrong one */ 903 : /* in such case we have a "copy" over an "update" */ - 904 79190 : if (!state->opt.force_nocopy) { - 905 79190 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 904 79133 : if (!state->opt.force_nocopy) { + 905 79133 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 906 : 907 : /* search for a file with the same name and stamp in all the disks */ - 908 518611 : for (i = state->disklist; i != 0; i = i->next) { - 909 445630 : struct snapraid_disk* other_disk = i->data; + 908 422996 : for (i = state->disklist; i != 0; i = i->next) { + 909 367496 : struct snapraid_disk* other_disk = i->data; 910 : struct snapraid_file* other_file; 911 : 912 : /* if the nanosecond part of the time stamp is valid, search */ 913 : /* for name and stamp, otherwise for path and stamp */ - 914 445630 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) - 915 445522 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); + 914 367496 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) + 915 367388 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); 916 : else 917 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); 918 : 919 : /* if found, and it's a fully hashed file */ - 920 445630 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { + 920 367496 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { 921 : /* assume that the file is a copy, and reuse the hash */ - 922 6209 : file_copy(other_file, file); + 922 23633 : file_copy(other_file, file); 923 : 924 : /* revert old counter and use the copy one */ - 925 6209 : ++scan->count_copy; + 925 23633 : ++scan->count_copy; 926 : - 927 6209 : log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc(other_file->sub), disk->name, esc(file->sub)); - 928 6209 : if (is_diff) { + 927 23633 : log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc(other_file->sub), disk->name, esc(file->sub)); + 928 23633 : if (is_diff) { 929 31 : printf("copy %s%s -> %s%s\n", other_disk->dir, other_file->sub, disk->dir, file->sub); 930 : } 931 : 932 : /* mark it as reported */ - 933 6209 : is_file_reported = 1; + 933 23633 : is_file_reported = 1; 934 : 935 : /* no need to continue the search */ - 936 6209 : break; + 936 23633 : break; 937 : } 938 : } 939 : } 940 : 941 : /* if not yet reported, do it now */ - 942 79190 : if (!is_file_reported) { - 943 72981 : if (is_file_already_present) { - 944 4716 : ++scan->count_change; + 942 79133 : if (!is_file_reported) { + 943 55500 : if (is_file_already_present) { + 944 4630 : ++scan->count_change; 945 : - 946 4716 : log_tag("scan:update:%s:%s\n", disk->name, esc(sub)); - 947 4716 : if (is_diff) { + 946 4630 : log_tag("scan:update:%s:%s\n", disk->name, esc(sub)); + 947 4630 : if (is_diff) { 948 118 : printf("update %s%s\n", disk->dir, sub); 949 : } 950 : } else { - 951 68265 : ++scan->count_insert; + 951 50870 : ++scan->count_insert; 952 : - 953 68265 : log_tag("scan:add:%s:%s\n", disk->name, esc(sub)); - 954 68265 : if (is_diff) { - 955 17044 : printf("add %s%s\n", disk->dir, sub); + 953 50870 : log_tag("scan:add:%s:%s\n", disk->name, esc(sub)); + 954 50870 : if (is_diff) { + 955 17051 : printf("add %s%s\n", disk->dir, sub); 956 : } 957 : } 958 : } 959 : 960 : /* insert the file in the delayed list */ - 961 79190 : scan_file_insert(scan, file); + 961 79133 : scan_file_insert(scan, file); 962 : } 963 : 964 : /** @@ -1061,27 +1061,27 @@ 999 : /** 1000 : * Process a dir. 1001 : */ - 1002 227 : static void scan_emptydir(struct snapraid_scan* scan, const char* sub) + 1002 239 : static void scan_emptydir(struct snapraid_scan* scan, const char* sub) 1003 : { - 1004 227 : struct snapraid_disk* disk = scan->disk; + 1004 239 : struct snapraid_disk* disk = scan->disk; 1005 : struct snapraid_dir* dir; 1006 : 1007 : /* check if the dir already exists */ - 1008 227 : dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub)); - 1009 227 : if (dir) { + 1008 239 : dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub)); + 1009 239 : if (dir) { 1010 : /* check if multiple files have the same name */ - 1011 217 : if (dir_flag_has(dir, FILE_IS_PRESENT)) { + 1011 229 : if (dir_flag_has(dir, FILE_IS_PRESENT)) { 1012 : /* LCOV_EXCL_START */ 1013 : log_fatal("Internal inconsistency for dir '%s%s'\n", disk->dir, sub); - 1014 : exit(EXIT_FAILURE); + 1014 : os_abort(); 1015 : /* LCOV_EXCL_STOP */ 1016 : } 1017 : 1018 : /* mark as present */ - 1019 217 : dir_flag_set(dir, FILE_IS_PRESENT); + 1019 229 : dir_flag_set(dir, FILE_IS_PRESENT); 1020 : 1021 : /* nothing more to do */ - 1022 444 : return; + 1022 468 : return; 1023 : } else { 1024 : /* and continue to insert it */ 1025 : } @@ -1113,26 +1113,26 @@ 1051 : }; 1052 : 1053 : #if HAVE_STRUCT_DIRENT_D_INO - 1054 103314 : static int dd_ino_compare(const void* void_a, const void* void_b) + 1054 103366 : static int dd_ino_compare(const void* void_a, const void* void_b) 1055 : { - 1056 103314 : const struct dirent_sorted* a = void_a; - 1057 103314 : const struct dirent_sorted* b = void_b; + 1056 103366 : const struct dirent_sorted* a = void_a; + 1057 103366 : const struct dirent_sorted* b = void_b; 1058 : - 1059 103314 : if (a->d_ino < b->d_ino) - 1060 49400 : return -1; - 1061 53914 : if (a->d_ino > b->d_ino) - 1062 53914 : return 1; + 1059 103366 : if (a->d_ino < b->d_ino) + 1060 49430 : return -1; + 1061 53936 : if (a->d_ino > b->d_ino) + 1062 53936 : return 1; 1063 : 1064 0 : return 0; 1065 : } 1066 : #endif 1067 : - 1068 10485497 : static int dd_name_compare(const void* void_a, const void* void_b) + 1068 10959090 : static int dd_name_compare(const void* void_a, const void* void_b) 1069 : { - 1070 10485497 : const struct dirent_sorted* a = void_a; - 1071 10485497 : const struct dirent_sorted* b = void_b; + 1070 10959090 : const struct dirent_sorted* a = void_a; + 1071 10959090 : const struct dirent_sorted* b = void_b; 1072 : - 1073 10485497 : return strcmp(a->d_name, b->d_name); + 1073 10959090 : return strcmp(a->d_name, b->d_name); 1074 : } 1075 : 1076 : /** @@ -1146,15 +1146,15 @@ 1084 : } 1085 : #else 1086 : #define DSTAT(file, dd, buf) dstat(file, buf) - 1087 1004217 : struct stat* dstat(const char* file, struct stat* st) + 1087 1049496 : struct stat* dstat(const char* file, struct stat* st) 1088 : { - 1089 1004217 : if (lstat(file, st) != 0) { + 1089 1049496 : if (lstat(file, st) != 0) { 1090 : /* LCOV_EXCL_START */ 1091 : log_fatal("Error in stat file/directory '%s'. %s.\n", file, strerror(errno)); 1092 : exit(EXIT_FAILURE); 1093 : /* LCOV_EXCL_STOP */ 1094 : } - 1095 1004217 : return st; + 1095 1049496 : return st; 1096 : } 1097 : #endif 1098 : @@ -1162,19 +1162,19 @@ 1100 : * Process a directory. 1101 : * Return != 0 if at least one file or link is processed. 1102 : */ - 1103 1614 : static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub) + 1103 1713 : static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub) 1104 : { - 1105 1614 : struct snapraid_state* state = scan->state; - 1106 1614 : struct snapraid_disk* disk = scan->disk; - 1107 1614 : int processed = 0; + 1105 1713 : struct snapraid_state* state = scan->state; + 1106 1713 : struct snapraid_disk* disk = scan->disk; + 1107 1713 : int processed = 0; 1108 : DIR* d; 1109 : tommy_list list; 1110 : tommy_node* node; 1111 : - 1112 1614 : tommy_list_init(&list); + 1112 1713 : tommy_list_init(&list); 1113 : - 1114 1614 : d = opendir(dir); - 1115 1614 : if (!d) { + 1114 1713 : d = opendir(dir); + 1115 1713 : if (!d) { 1116 : /* LCOV_EXCL_START */ 1117 : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); 1118 : if (level == 0) @@ -1195,29 +1195,29 @@ 1133 : size_t name_len; 1134 : 1135 : /* clear errno to detect erroneous conditions */ - 1136 1041725 : errno = 0; - 1137 1041725 : dd = readdir(d); - 1138 1041725 : if (dd == 0 && errno != 0) { + 1136 1088749 : errno = 0; + 1137 1088749 : dd = readdir(d); + 1138 1088749 : if (dd == 0 && errno != 0) { 1139 : /* LCOV_EXCL_START */ 1140 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); 1141 : log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub); 1142 : exit(EXIT_FAILURE); 1143 : /* LCOV_EXCL_STOP */ 1144 : } - 1145 1041725 : if (dd == 0) { - 1146 1614 : break; /* finished */ + 1145 1088749 : if (dd == 0) { + 1146 1713 : break; /* finished */ 1147 : } 1148 : 1149 : /* skip "." and ".." files */ - 1150 1040111 : name = dd->d_name; - 1151 1040111 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) - 1152 6456 : continue; + 1150 1087036 : name = dd->d_name; + 1151 1087036 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 1152 6852 : continue; 1153 : - 1154 1036883 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 1155 1036883 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + 1154 1083610 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 1155 1083610 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); 1156 : 1157 : /* check for not supported file names */ - 1158 1036883 : if (name[0] == 0) { + 1158 1083610 : if (name[0] == 0) { 1159 : /* LCOV_EXCL_START */ 1160 : log_fatal("Unsupported name '%s' in file '%s'.\n", name, path_next); 1161 : exit(EXIT_FAILURE); @@ -1225,26 +1225,26 @@ 1163 : } 1164 : 1165 : /* exclude hidden files even before calling lstat() */ - 1166 1036883 : if (filter_hidden(state->filter_hidden, dd) != 0) { + 1166 1083610 : if (filter_hidden(state->filter_hidden, dd) != 0) { 1167 0 : msg_verbose("Excluding hidden '%s'\n", path_next); 1168 0 : continue; 1169 : } 1170 : 1171 : /* exclude content files even before calling lstat() */ - 1172 1036883 : if (filter_content(&state->contentlist, path_next) != 0) { + 1172 1083610 : if (filter_content(&state->contentlist, path_next) != 0) { 1173 0 : msg_verbose("Excluding content '%s'\n", path_next); 1174 0 : continue; 1175 : } 1176 : - 1177 1036883 : name_len = strlen(dd->d_name); - 1178 1036883 : entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1); + 1177 1083610 : name_len = strlen(dd->d_name); + 1178 1083610 : entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1); 1179 : 1180 : /* copy the dir entry */ 1181 : #if HAVE_STRUCT_DIRENT_D_INO - 1182 1036883 : entry->d_ino = dd->d_ino; + 1182 1083610 : entry->d_ino = dd->d_ino; 1183 : #endif 1184 : #if HAVE_STRUCT_DIRENT_D_TYPE - 1185 1036883 : entry->d_type = dd->d_type; + 1185 1083610 : entry->d_type = dd->d_type; 1186 : #endif 1187 : #if HAVE_STRUCT_DIRENT_D_STAT 1188 : /* convert dirent to lstat result */ @@ -1252,24 +1252,24 @@ 1190 : 1191 : /* note that at this point the st_mode may be 0 */ 1192 : #endif - 1193 1036883 : memcpy(entry->d_name, dd->d_name, name_len + 1); + 1193 1083610 : memcpy(entry->d_name, dd->d_name, name_len + 1); 1194 : 1195 : /* insert in the list */ - 1196 1036883 : tommy_list_insert_tail(&list, &entry->node, entry); - 1197 1040111 : } + 1196 1083610 : tommy_list_insert_tail(&list, &entry->node, entry); + 1197 1087036 : } 1198 : - 1199 1614 : if (closedir(d) != 0) { + 1199 1713 : if (closedir(d) != 0) { 1200 : /* LCOV_EXCL_START */ 1201 : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); 1202 : exit(EXIT_FAILURE); 1203 : /* LCOV_EXCL_STOP */ 1204 : } 1205 : - 1206 1614 : if (state->opt.force_order == SORT_ALPHA) { + 1206 1713 : if (state->opt.force_order == SORT_ALPHA) { 1207 : /* if requested sort alphabetically */ 1208 : /* this is mainly done for testing to ensure to always */ 1209 : /* process in the same way in different platforms */ - 1210 1578 : tommy_list_sort(&list, dd_name_compare); + 1210 1677 : tommy_list_sort(&list, dd_name_compare); 1211 : } 1212 : #if HAVE_STRUCT_DIRENT_D_INO 1213 36 : else if (!disk->has_volatile_inodes) { @@ -1281,40 +1281,40 @@ 1219 : #endif 1220 : 1221 : /* process the sorted dir entries */ - 1222 1614 : node = list; - 1223 1040111 : while (node != 0) { + 1222 1713 : node = list; + 1223 1087036 : while (node != 0) { 1224 : char path_next[PATH_MAX]; 1225 : char sub_next[PATH_MAX]; 1226 : char out[PATH_MAX]; - 1227 1036883 : struct snapraid_filter* reason = 0; - 1228 1036883 : struct dirent_sorted* dd = node->data; - 1229 1036883 : const char* name = dd->d_name; + 1227 1083610 : struct snapraid_filter* reason = 0; + 1228 1083610 : struct dirent_sorted* dd = node->data; + 1229 1083610 : const char* name = dd->d_name; 1230 : struct stat* st; 1231 : int type; 1232 : #if !HAVE_STRUCT_DIRENT_D_STAT 1233 : struct stat st_buf; 1234 : #endif 1235 : - 1236 1036883 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 1237 1036883 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + 1236 1083610 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 1237 1083610 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); 1238 : 1239 : /* start with an unknown type */ - 1240 1036883 : type = -1; - 1241 1036883 : st = 0; + 1240 1083610 : type = -1; + 1241 1083610 : st = 0; 1242 : 1243 : /* if dirent has the type, use it */ 1244 : #if HAVE_STRUCT_DIRENT_D_TYPE - 1245 1036883 : switch (dd->d_type) { + 1245 1083610 : switch (dd->d_type) { 1246 0 : case DT_UNKNOWN : break; - 1247 1003082 : case DT_REG : type = 0; break; - 1248 32666 : case DT_LNK : type = 1; break; - 1249 1135 : case DT_DIR : type = 2; break; + 1247 1048310 : case DT_REG : type = 0; break; + 1248 34114 : case DT_LNK : type = 1; break; + 1249 1186 : case DT_DIR : type = 2; break; 1250 0 : default : type = 3; break; 1251 : } 1252 : #endif 1253 : 1254 : /* if type is still unknown */ - 1255 1036883 : if (type < 0) { + 1255 1083610 : if (type < 0) { 1256 : /* get the type from stat */ 1257 0 : st = DSTAT(path_next, dd, &st_buf); 1258 : @@ -1344,12 +1344,12 @@ 1282 0 : type = 3; 1283 : } 1284 : - 1285 1036883 : if (type == 0) { /* REG */ - 1286 1003082 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 1285 1083610 : if (type == 0) { /* REG */ + 1286 1048310 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { 1287 : 1288 : /* late stat, if not yet called */ - 1289 1003082 : if (!st) - 1290 1003082 : st = DSTAT(path_next, dd, &st_buf); + 1289 1048310 : if (!st) + 1290 1048310 : st = DSTAT(path_next, dd, &st_buf); 1291 : 1292 : #if HAVE_LSTAT_SYNC 1293 : /* if the st_ino field is missing, takes care to fill it using the extended lstat() */ @@ -1364,539 +1364,545 @@ 1302 : } 1303 : #endif 1304 : - 1305 1003082 : scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET); - 1306 1003082 : processed = 1; + 1305 1048310 : scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET); + 1306 1048310 : processed = 1; 1307 : } else { 1308 0 : msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 1309 : } - 1310 33801 : } else if (type == 1) { /* LNK */ - 1311 32666 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 1310 35300 : } else if (type == 1) { /* LNK */ + 1311 34114 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { 1312 : char subnew[PATH_MAX]; 1313 : int ret; 1314 : - 1315 32666 : ret = readlink(path_next, subnew, sizeof(subnew)); - 1316 32666 : if (ret >= PATH_MAX) { + 1315 34114 : ret = readlink(path_next, subnew, sizeof(subnew)); + 1316 34114 : if (ret >= PATH_MAX) { 1317 : /* LCOV_EXCL_START */ 1318 : log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next); 1319 : exit(EXIT_FAILURE); 1320 : /* LCOV_EXCL_STOP */ 1321 : } - 1322 32666 : if (ret < 0) { + 1322 34114 : if (ret < 0) { 1323 : /* LCOV_EXCL_START */ 1324 : log_fatal("Error in readlink file '%s'. %s.\n", path_next, strerror(errno)); 1325 : exit(EXIT_FAILURE); 1326 : /* LCOV_EXCL_STOP */ 1327 : } - 1328 : - 1329 : /* readlink doesn't put the final 0 */ - 1330 32666 : subnew[ret] = 0; - 1331 : - 1332 : /* process as a symbolic link */ - 1333 32666 : scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK); - 1334 32666 : processed = 1; - 1335 : } else { - 1336 0 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); - 1337 : } - 1338 1135 : } else if (type == 2) { /* DIR */ - 1339 1135 : if (filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) { - 1340 : #ifndef _WIN32 - 1341 : /* late stat, if not yet called */ - 1342 1135 : if (!st) - 1343 1135 : st = DSTAT(path_next, dd, &st_buf); - 1344 : - 1345 : /* in Unix don't follow mount points in different devices */ - 1346 : /* in Windows we are already skipping them reporting them as special files */ - 1347 1135 : if ((uint64_t)st->st_dev != disk->device) { - 1348 0 : log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next); - 1349 : } else - 1350 : #endif - 1351 : { - 1352 : char sub_dir[PATH_MAX]; - 1353 : - 1354 : /* recurse */ - 1355 1135 : pathslash(path_next, sizeof(path_next)); - 1356 1135 : pathcpy(sub_dir, sizeof(sub_dir), sub_next); - 1357 1135 : pathslash(sub_dir, sizeof(sub_dir)); - 1358 1135 : if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) { - 1359 : /* scan the directory as empty dir */ - 1360 227 : scan_emptydir(scan, sub_next); - 1361 : } - 1362 : /* or we processed something internally, or we have added the empty dir */ - 1363 1135 : processed = 1; - 1364 : } - 1365 : } else { - 1366 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); - 1367 : } - 1368 : } else { - 1369 0 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { - 1370 : /* late stat, if not yet called */ - 1371 0 : if (!st) - 1372 0 : st = DSTAT(path_next, dd, &st_buf); - 1373 : - 1374 0 : log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next); - 1375 : } else { - 1376 0 : msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); - 1377 : } - 1378 : } - 1379 : - 1380 : /* next entry */ - 1381 1036883 : node = node->next; - 1382 : - 1383 : /* free the present one */ - 1384 1036883 : free(dd); - 1385 : } - 1386 : - 1387 1614 : return processed; - 1388 : } - 1389 : - 1390 80 : static int state_diffscan(struct snapraid_state* state, int is_diff) - 1391 : { - 1392 : tommy_node* i; - 1393 : tommy_node* j; - 1394 : tommy_list scanlist; - 1395 : int done; - 1396 : fptr* msg; - 1397 : struct snapraid_scan total; - 1398 : int no_difference; - 1399 : - 1400 80 : tommy_list_init(&scanlist); + 1328 34114 : if (ret == 0) + 1329 0 : log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next); + 1330 : + 1331 : /* readlink doesn't put the final 0 */ + 1332 34114 : subnew[ret] = 0; + 1333 : + 1334 : /* process as a symbolic link */ + 1335 34114 : scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK); + 1336 34114 : processed = 1; + 1337 : } else { + 1338 0 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 1339 : } + 1340 1186 : } else if (type == 2) { /* DIR */ + 1341 1186 : if (filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 1342 : #ifndef _WIN32 + 1343 : /* late stat, if not yet called */ + 1344 1186 : if (!st) + 1345 1186 : st = DSTAT(path_next, dd, &st_buf); + 1346 : + 1347 : /* in Unix don't follow mount points in different devices */ + 1348 : /* in Windows we are already skipping them reporting them as special files */ + 1349 1186 : if ((uint64_t)st->st_dev != disk->device) { + 1350 0 : log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next); + 1351 : } else + 1352 : #endif + 1353 : { + 1354 : char sub_dir[PATH_MAX]; + 1355 : + 1356 : /* recurse */ + 1357 1186 : pathslash(path_next, sizeof(path_next)); + 1358 1186 : pathcpy(sub_dir, sizeof(sub_dir), sub_next); + 1359 1186 : pathslash(sub_dir, sizeof(sub_dir)); + 1360 1186 : if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) { + 1361 : /* scan the directory as empty dir */ + 1362 239 : scan_emptydir(scan, sub_next); + 1363 : } + 1364 : /* or we processed something internally, or we have added the empty dir */ + 1365 1186 : processed = 1; + 1366 : } + 1367 : } else { + 1368 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 1369 : } + 1370 : } else { + 1371 0 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 1372 : /* late stat, if not yet called */ + 1373 0 : if (!st) + 1374 0 : st = DSTAT(path_next, dd, &st_buf); + 1375 : + 1376 0 : log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next); + 1377 : } else { + 1378 0 : msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 1379 : } + 1380 : } + 1381 : + 1382 : /* next entry */ + 1383 1083610 : node = node->next; + 1384 : + 1385 : /* free the present one */ + 1386 1083610 : free(dd); + 1387 : } + 1388 : + 1389 1713 : return processed; + 1390 : } + 1391 : + 1392 88 : static int state_diffscan(struct snapraid_state* state, int is_diff) + 1393 : { + 1394 : tommy_node* i; + 1395 : tommy_node* j; + 1396 : tommy_list scanlist; + 1397 : int done; + 1398 : fptr* msg; + 1399 : struct snapraid_scan total; + 1400 : int no_difference; 1401 : - 1402 80 : if (is_diff) - 1403 7 : msg_progress("Comparing...\n"); - 1404 : - 1405 : /* first scan all the directory and find new and deleted files */ - 1406 559 : for (i = state->disklist; i != 0; i = i->next) { - 1407 479 : struct snapraid_disk* disk = i->data; - 1408 : struct snapraid_scan* scan; - 1409 : tommy_node* node; - 1410 : int ret; - 1411 : int has_persistent_inode; - 1412 : - 1413 479 : scan = malloc_nofail(sizeof(struct snapraid_scan)); - 1414 479 : scan->state = state; - 1415 479 : scan->disk = disk; - 1416 479 : scan->count_equal = 0; - 1417 479 : scan->count_move = 0; - 1418 479 : scan->count_copy = 0; - 1419 479 : scan->count_restore = 0; - 1420 479 : scan->count_change = 0; - 1421 479 : scan->count_remove = 0; - 1422 479 : scan->count_insert = 0; - 1423 479 : tommy_list_init(&scan->file_insert_list); - 1424 479 : tommy_list_init(&scan->link_insert_list); - 1425 479 : tommy_list_init(&scan->dir_insert_list); - 1426 : - 1427 479 : tommy_list_insert_tail(&scanlist, &scan->node, scan); + 1402 88 : tommy_list_init(&scanlist); + 1403 : + 1404 88 : if (is_diff) + 1405 7 : msg_progress("Comparing...\n"); + 1406 : + 1407 : /* first scan all the directory and find new and deleted files */ + 1408 615 : for (i = state->disklist; i != 0; i = i->next) { + 1409 527 : struct snapraid_disk* disk = i->data; + 1410 : struct snapraid_scan* scan; + 1411 : tommy_node* node; + 1412 : int ret; + 1413 : int has_persistent_inode; + 1414 : + 1415 527 : scan = malloc_nofail(sizeof(struct snapraid_scan)); + 1416 527 : scan->state = state; + 1417 527 : scan->disk = disk; + 1418 527 : scan->count_equal = 0; + 1419 527 : scan->count_move = 0; + 1420 527 : scan->count_copy = 0; + 1421 527 : scan->count_restore = 0; + 1422 527 : scan->count_change = 0; + 1423 527 : scan->count_remove = 0; + 1424 527 : scan->count_insert = 0; + 1425 527 : tommy_list_init(&scan->file_insert_list); + 1426 527 : tommy_list_init(&scan->link_insert_list); + 1427 527 : tommy_list_init(&scan->dir_insert_list); 1428 : - 1429 479 : if (!is_diff) - 1430 437 : msg_progress("Scanning disk %s...\n", disk->name); - 1431 : - 1432 : /* check if the disk supports persistent inodes */ - 1433 479 : ret = fsinfo(disk->dir, &has_persistent_inode, 0, 0); - 1434 479 : if (ret < 0) { - 1435 : /* LCOV_EXCL_START */ - 1436 : log_fatal("Error accessing disk '%s' to get filesystem info. %s.\n", disk->dir, strerror(errno)); - 1437 : exit(EXIT_FAILURE); - 1438 : /* LCOV_EXCL_STOP */ - 1439 : } - 1440 479 : if (!has_persistent_inode) { - 1441 0 : disk->has_volatile_inodes = 1; - 1442 : } - 1443 : - 1444 : /* if inodes or UUID are not persistent/changed/unsupported */ - 1445 479 : if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) { - 1446 : /* remove all the inodes from the inode collection */ - 1447 : /* if they are not persistent, all of them could be changed now */ - 1448 : /* and we don't want to find false matching ones */ - 1449 : /* see scan_file() for more details */ - 1450 75 : node = disk->filelist; - 1451 150 : while (node) { - 1452 0 : struct snapraid_file* file = node->data; - 1453 : - 1454 0 : node = node->next; + 1429 527 : tommy_list_insert_tail(&scanlist, &scan->node, scan); + 1430 : + 1431 527 : if (!is_diff) + 1432 485 : msg_progress("Scanning disk %s...\n", disk->name); + 1433 : + 1434 : /* check if the disk supports persistent inodes */ + 1435 527 : ret = fsinfo(disk->dir, &has_persistent_inode, 0, 0); + 1436 527 : if (ret < 0) { + 1437 : /* LCOV_EXCL_START */ + 1438 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + 1439 : exit(EXIT_FAILURE); + 1440 : /* LCOV_EXCL_STOP */ + 1441 : } + 1442 527 : if (!has_persistent_inode) { + 1443 0 : disk->has_volatile_inodes = 1; + 1444 : } + 1445 : + 1446 : /* if inodes or UUID are not persistent/changed/unsupported */ + 1447 527 : if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) { + 1448 : /* remove all the inodes from the inode collection */ + 1449 : /* if they are not persistent, all of them could be changed now */ + 1450 : /* and we don't want to find false matching ones */ + 1451 : /* see scan_file() for more details */ + 1452 90 : node = disk->filelist; + 1453 190 : while (node) { + 1454 10 : struct snapraid_file* file = node->data; 1455 : - 1456 : /* remove from the inode set */ - 1457 0 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); - 1458 : - 1459 : /* clear the inode */ - 1460 0 : file->inode = 0; - 1461 : - 1462 : /* mark as missing inode */ - 1463 0 : file_flag_set(file, FILE_IS_WITHOUT_INODE); - 1464 : } - 1465 : } - 1466 : - 1467 479 : scan_dir(scan, 0, is_diff, disk->dir, ""); - 1468 : } - 1469 : - 1470 : /* we split the search in two phases because to detect files */ - 1471 : /* moved from one disk to another we have to start deletion */ - 1472 : /* only when all disks have all the new files found */ - 1473 : - 1474 : /* now process all the new and deleted files */ - 1475 559 : for (i = scanlist; i != 0; i = i->next) { - 1476 479 : struct snapraid_scan* scan = i->data; - 1477 479 : struct snapraid_disk* disk = scan->disk; - 1478 : tommy_node* node; - 1479 : unsigned phy_count; - 1480 : unsigned phy_dup; - 1481 : uint64_t phy_last; - 1482 : struct snapraid_file* phy_file_last; - 1483 : - 1484 : /* check for removed files */ - 1485 479 : node = disk->filelist; - 1486 932532 : while (node) { - 1487 931574 : struct snapraid_file* file = node->data; - 1488 : - 1489 : /* next node */ - 1490 931574 : node = node->next; - 1491 : - 1492 : /* remove if not present */ - 1493 931574 : if (!file_flag_has(file, FILE_IS_PRESENT)) { - 1494 29638 : ++scan->count_remove; - 1495 : - 1496 29638 : log_tag("scan:remove:%s:%s\n", disk->name, esc(file->sub)); - 1497 29638 : if (is_diff) { - 1498 97 : printf("remove %s%s\n", disk->dir, file->sub); - 1499 : } - 1500 : - 1501 29638 : scan_file_remove(scan, file); - 1502 : } - 1503 : } - 1504 : - 1505 : /* check for removed links */ - 1506 479 : node = disk->linklist; - 1507 32294 : while (node) { - 1508 31336 : struct snapraid_link* slink = node->data; - 1509 : - 1510 : /* next node */ - 1511 31336 : node = node->next; - 1512 : - 1513 : /* remove if not present */ - 1514 31336 : if (!link_flag_has(slink, FILE_IS_PRESENT)) { - 1515 956 : ++scan->count_remove; - 1516 : - 1517 956 : log_tag("scan:remove:%s:%s\n", disk->name, esc(slink->sub)); - 1518 956 : if (is_diff) { - 1519 10 : printf("remove %s%s\n", disk->dir, slink->sub); - 1520 : } - 1521 : - 1522 956 : scan_link_remove(scan, slink); - 1523 : } - 1524 : } - 1525 : - 1526 : /* check for removed dirs */ - 1527 479 : node = disk->dirlist; - 1528 1177 : while (node) { - 1529 219 : struct snapraid_dir* dir = node->data; - 1530 : - 1531 : /* next node */ - 1532 219 : node = node->next; - 1533 : - 1534 : /* remove if not present */ - 1535 219 : if (!dir_flag_has(dir, FILE_IS_PRESENT)) { - 1536 2 : scan_emptydir_remove(scan, dir); - 1537 : } - 1538 : } - 1539 : - 1540 : /* sort the files before inserting them */ - 1541 : /* we use a stable sort to ensure that if the reported physical offset/inode */ - 1542 : /* are always 0, we keep at least the directory order */ - 1543 479 : switch (state->opt.force_order) { - 1544 : case SORT_PHYSICAL : - 1545 12 : tommy_list_sort(&scan->file_insert_list, file_physical_compare); - 1546 12 : break; - 1547 : case SORT_INODE : - 1548 0 : tommy_list_sort(&scan->file_insert_list, file_inode_compare); - 1549 0 : break; - 1550 : case SORT_ALPHA : - 1551 467 : tommy_list_sort(&scan->file_insert_list, file_path_compare); - 1552 467 : break; - 1553 : case SORT_DIR : - 1554 : /* already in order */ - 1555 0 : break; - 1556 : } - 1557 : - 1558 : /* insert all the new files, we insert them only after the deletion */ - 1559 : /* to reuse the just freed space */ - 1560 : /* also check if the physical offset reported are fakes or not */ - 1561 479 : node = scan->file_insert_list; - 1562 479 : phy_count = 0; - 1563 479 : phy_dup = 0; - 1564 479 : phy_last = FILEPHY_UNREAD_OFFSET; - 1565 479 : phy_file_last = 0; - 1566 101933 : while (node) { - 1567 100975 : struct snapraid_file* file = node->data; - 1568 : - 1569 : /* if the file is not empty, count duplicate physical offsets */ - 1570 100975 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { - 1571 11418 : if (phy_file_last != 0 && file->physical == phy_last - 1572 : /* files without offset are expected to have duplicates */ - 1573 0 : && phy_last != FILEPHY_WITHOUT_OFFSET - 1574 : ) { - 1575 : /* if verbose, print the list of duplicates real offsets */ - 1576 : /* other cases are for offsets not supported, so we don't need to report them file by file */ - 1577 0 : if (phy_last >= FILEPHY_REAL_OFFSET) { - 1578 0 : log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last); - 1579 : } - 1580 0 : ++phy_dup; - 1581 : } - 1582 11418 : phy_file_last = file; - 1583 11418 : phy_last = file->physical; - 1584 11418 : ++phy_count; - 1585 : } - 1586 : - 1587 : /* next node */ - 1588 100975 : node = node->next; - 1589 : - 1590 : /* insert in the parity */ - 1591 100975 : scan_file_allocate(scan, file); - 1592 : } - 1593 : - 1594 : /* mark the disk without reliable physical offset if it has duplicates */ - 1595 : /* here it should never happen because we already sorted out hardlinks */ - 1596 479 : if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) { - 1597 0 : disk->has_unreliable_physical = 1; - 1598 : } - 1599 : - 1600 : /* insert all the new links */ - 1601 479 : node = scan->link_insert_list; - 1602 3415 : while (node) { - 1603 2457 : struct snapraid_link* slink = node->data; - 1604 : - 1605 : /* next node */ - 1606 2457 : node = node->next; - 1607 : - 1608 : /* insert it */ - 1609 2457 : scan_link_insert(scan, slink); - 1610 : } - 1611 : - 1612 : /* insert all the new dirs */ - 1613 479 : node = scan->dir_insert_list; - 1614 968 : while (node) { - 1615 10 : struct snapraid_dir* dir = node->data; - 1616 : - 1617 : /* next node */ - 1618 10 : node = node->next; - 1619 : - 1620 : /* insert it */ - 1621 10 : scan_emptydir_insert(scan, dir); - 1622 : } - 1623 : } - 1624 : - 1625 : /* check for disks where all the previously existing files where removed */ - 1626 80 : if (!state->opt.force_empty) { - 1627 75 : int all_missing = 0; - 1628 75 : int all_rewritten = 0; - 1629 75 : done = 0; - 1630 524 : for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) { - 1631 449 : struct snapraid_disk* disk = i->data; - 1632 449 : struct snapraid_scan* scan = j->data; - 1633 : - 1634 449 : if (scan->count_equal == 0 - 1635 60 : && scan->count_move == 0 - 1636 60 : && scan->count_restore == 0 - 1637 60 : && (scan->count_remove != 0 || scan->count_change != 0) - 1638 : ) { - 1639 1 : if (!done) { - 1640 1 : done = 1; - 1641 1 : log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir); - 1642 : } else { - 1643 0 : log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir); - 1644 : } - 1645 : - 1646 : /* detect the special condition of all files missing */ - 1647 1 : if (scan->count_change == 0) - 1648 1 : all_missing = 1; - 1649 : - 1650 : /* detect the special condition of all files rewritten */ - 1651 1 : if (scan->count_remove == 0) - 1652 0 : all_rewritten = 1; - 1653 : } - 1654 : } - 1655 75 : if (done) { - 1656 1 : log_fatal("\nare now missing or rewritten!\n"); - 1657 1 : if (all_rewritten) { - 1658 0 : log_fatal("This could happen when restoring a disk with a backup\n"); - 1659 0 : log_fatal("program that is not setting correctly the timestamps.\n"); - 1660 : } - 1661 1 : if (all_missing) { - 1662 1 : log_fatal("This could happen when some disks are not mounted\n"); - 1663 1 : log_fatal("in the expected directory.\n"); - 1664 : } - 1665 1 : if (!is_diff) { - 1666 1 : log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.", state->command, state->command); - 1667 1 : exit(EXIT_FAILURE); - 1668 : } - 1669 : } - 1670 : } - 1671 : - 1672 : /* check for disks without the physical offset support */ - 1673 79 : if (state->opt.force_order == SORT_PHYSICAL) { - 1674 2 : done = 0; - 1675 14 : for (i = state->disklist; i != 0; i = i->next) { - 1676 12 : struct snapraid_disk* disk = i->data; - 1677 : - 1678 12 : if (disk->has_unreliable_physical) { - 1679 0 : if (!done) { - 1680 0 : done = 1; - 1681 0 : log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name); - 1682 : } else { - 1683 0 : log_fatal(", '%s'", disk->name); - 1684 : } - 1685 : } - 1686 : } - 1687 2 : if (done) { - 1688 0 : log_fatal(". Files order won't be optimal.\n"); - 1689 : } - 1690 : } - 1691 : - 1692 : /* check for disks without persistent inodes */ - 1693 79 : done = 0; - 1694 552 : for (i = state->disklist; i != 0; i = i->next) { - 1695 473 : struct snapraid_disk* disk = i->data; - 1696 : - 1697 473 : if (disk->has_volatile_inodes) { - 1698 0 : if (!done) { - 1699 0 : done = 1; - 1700 0 : log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name); - 1701 : } else { - 1702 0 : log_fatal(", '%s'", disk->name); - 1703 : } - 1704 : } - 1705 : } - 1706 79 : if (done) { - 1707 0 : log_fatal(". Move operations won't be optimal.\n"); - 1708 : } - 1709 : - 1710 : /* check for disks with changed UUID */ - 1711 79 : done = 0; - 1712 552 : for (i = state->disklist; i != 0; i = i->next) { - 1713 473 : struct snapraid_disk* disk = i->data; - 1714 : - 1715 : /* don't print the message if the UUID changed because before */ - 1716 : /* it was no set. */ - 1717 : /* this is the normal condition for an empty disk because it */ - 1718 : /* isn't stored */ - 1719 473 : if (disk->has_different_uuid && !disk->had_empty_uuid) { - 1720 0 : if (!done) { - 1721 0 : done = 1; - 1722 0 : log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name); - 1723 : } else { - 1724 0 : log_fatal(", '%s'", disk->name); - 1725 : } - 1726 : } - 1727 : } - 1728 79 : if (done) { - 1729 0 : log_fatal(". Move operations won't be optimal.\n"); - 1730 : } - 1731 : - 1732 : /* check for disks with unsupported UUID */ - 1733 79 : done = 0; - 1734 552 : for (i = state->disklist; i != 0; i = i->next) { - 1735 473 : struct snapraid_disk* disk = i->data; - 1736 : - 1737 473 : if (disk->has_unsupported_uuid) { - 1738 0 : if (!done) { - 1739 0 : done = 1; - 1740 0 : log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name); - 1741 : } else { - 1742 0 : log_fatal(", '%s'", disk->name); - 1743 : } - 1744 : } - 1745 : } - 1746 79 : if (done) { - 1747 0 : log_fatal(". Move operations won't be optimal.\n"); - 1748 : } - 1749 : - 1750 79 : total.count_equal = 0; - 1751 79 : total.count_move = 0; - 1752 79 : total.count_copy = 0; - 1753 79 : total.count_restore = 0; - 1754 79 : total.count_change = 0; - 1755 79 : total.count_remove = 0; - 1756 79 : total.count_insert = 0; - 1757 : - 1758 552 : for (i = scanlist; i != 0; i = i->next) { - 1759 473 : struct snapraid_scan* scan = i->data; - 1760 473 : total.count_equal += scan->count_equal; - 1761 473 : total.count_move += scan->count_move; - 1762 473 : total.count_copy += scan->count_copy; - 1763 473 : total.count_restore += scan->count_restore; - 1764 473 : total.count_change += scan->count_change; - 1765 473 : total.count_remove += scan->count_remove; - 1766 473 : total.count_insert += scan->count_insert; - 1767 : } - 1768 : - 1769 79 : if (is_diff) { - 1770 7 : msg_status("\n"); - 1771 7 : msg = msg_status; - 1772 : } else { - 1773 72 : msg = msg_verbose; - 1774 : } - 1775 : - 1776 79 : msg("%8u equal\n", total.count_equal); - 1777 79 : msg("%8u moved\n", total.count_move); - 1778 79 : msg("%8u copied\n", total.count_copy); - 1779 79 : msg("%8u restored\n", total.count_restore); - 1780 79 : msg("%8u updated\n", total.count_change); - 1781 79 : msg("%8u removed\n", total.count_remove); - 1782 79 : msg("%8u added\n", total.count_insert); - 1783 : - 1784 79 : log_tag("summary:equal:%u\n", total.count_equal); - 1785 79 : log_tag("summary:moved:%u\n", total.count_move); - 1786 79 : log_tag("summary:copied:%u\n", total.count_copy); - 1787 79 : log_tag("summary:restored:%u\n", total.count_restore); - 1788 79 : log_tag("summary:updated:%u\n", total.count_change); - 1789 79 : log_tag("summary:removed:%u\n", total.count_remove); - 1790 79 : log_tag("summary:added:%u\n", total.count_insert); - 1791 : - 1792 236 : no_difference = !total.count_move && !total.count_copy && !total.count_restore - 1793 129 : && !total.count_change && !total.count_remove && !total.count_insert; - 1794 : - 1795 79 : if (is_diff) { - 1796 7 : if (no_difference) { - 1797 1 : msg_status("No differences\n"); - 1798 : } else { - 1799 6 : msg_status("There are differences!\n"); - 1800 : } - 1801 : } - 1802 : - 1803 79 : if (no_difference) { - 1804 9 : log_tag("summary:exit:equal\n"); - 1805 : } else { - 1806 70 : log_tag("summary:exit:diff\n"); + 1456 10 : node = node->next; + 1457 : + 1458 : /* remove from the inode set */ + 1459 10 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + 1460 : + 1461 : /* clear the inode */ + 1462 10 : file->inode = 0; + 1463 : + 1464 : /* mark as missing inode */ + 1465 10 : file_flag_set(file, FILE_IS_WITHOUT_INODE); + 1466 : } + 1467 : } + 1468 : + 1469 527 : scan_dir(scan, 0, is_diff, disk->dir, ""); + 1470 : } + 1471 : + 1472 : /* we split the search in two phases because to detect files */ + 1473 : /* moved from one disk to another we have to start deletion */ + 1474 : /* only when all disks have all the new files found */ + 1475 : + 1476 : /* now process all the new and deleted files */ + 1477 615 : for (i = scanlist; i != 0; i = i->next) { + 1478 527 : struct snapraid_scan* scan = i->data; + 1479 527 : struct snapraid_disk* disk = scan->disk; + 1480 : tommy_node* node; + 1481 : unsigned phy_count; + 1482 : unsigned phy_dup; + 1483 : uint64_t phy_last; + 1484 : struct snapraid_file* phy_file_last; + 1485 : + 1486 : /* check for removed files */ + 1487 527 : node = disk->filelist; + 1488 974990 : while (node) { + 1489 973936 : struct snapraid_file* file = node->data; + 1490 : + 1491 : /* next node */ + 1492 973936 : node = node->next; + 1493 : + 1494 : /* remove if not present */ + 1495 973936 : if (!file_flag_has(file, FILE_IS_PRESENT)) { + 1496 29646 : ++scan->count_remove; + 1497 : + 1498 29646 : log_tag("scan:remove:%s:%s\n", disk->name, esc(file->sub)); + 1499 29646 : if (is_diff) { + 1500 97 : printf("remove %s%s\n", disk->dir, file->sub); + 1501 : } + 1502 : + 1503 29646 : scan_file_remove(scan, file); + 1504 : } + 1505 : } + 1506 : + 1507 : /* check for removed links */ + 1508 527 : node = disk->linklist; + 1509 33847 : while (node) { + 1510 32793 : struct snapraid_link* slink = node->data; + 1511 : + 1512 : /* next node */ + 1513 32793 : node = node->next; + 1514 : + 1515 : /* remove if not present */ + 1516 32793 : if (!link_flag_has(slink, FILE_IS_PRESENT)) { + 1517 956 : ++scan->count_remove; + 1518 : + 1519 956 : log_tag("scan:remove:%s:%s\n", disk->name, esc(slink->sub)); + 1520 956 : if (is_diff) { + 1521 10 : printf("remove %s%s\n", disk->dir, slink->sub); + 1522 : } + 1523 : + 1524 956 : scan_link_remove(scan, slink); + 1525 : } + 1526 : } + 1527 : + 1528 : /* check for removed dirs */ + 1529 527 : node = disk->dirlist; + 1530 1285 : while (node) { + 1531 231 : struct snapraid_dir* dir = node->data; + 1532 : + 1533 : /* next node */ + 1534 231 : node = node->next; + 1535 : + 1536 : /* remove if not present */ + 1537 231 : if (!dir_flag_has(dir, FILE_IS_PRESENT)) { + 1538 2 : scan_emptydir_remove(scan, dir); + 1539 : } + 1540 : } + 1541 : + 1542 : /* sort the files before inserting them */ + 1543 : /* we use a stable sort to ensure that if the reported physical offset/inode */ + 1544 : /* are always 0, we keep at least the directory order */ + 1545 527 : switch (state->opt.force_order) { + 1546 : case SORT_PHYSICAL : + 1547 12 : tommy_list_sort(&scan->file_insert_list, file_physical_compare); + 1548 12 : break; + 1549 : case SORT_INODE : + 1550 0 : tommy_list_sort(&scan->file_insert_list, file_inode_compare); + 1551 0 : break; + 1552 : case SORT_ALPHA : + 1553 515 : tommy_list_sort(&scan->file_insert_list, file_path_compare); + 1554 515 : break; + 1555 : case SORT_DIR : + 1556 : /* already in order */ + 1557 0 : break; + 1558 : } + 1559 : + 1560 : /* insert all the new files, we insert them only after the deletion */ + 1561 : /* to reuse the just freed space */ + 1562 : /* also check if the physical offset reported are fakes or not */ + 1563 527 : node = scan->file_insert_list; + 1564 527 : phy_count = 0; + 1565 527 : phy_dup = 0; + 1566 527 : phy_last = FILEPHY_UNREAD_OFFSET; + 1567 527 : phy_file_last = 0; + 1568 104894 : while (node) { + 1569 103840 : struct snapraid_file* file = node->data; + 1570 : + 1571 : /* if the file is not empty, count duplicate physical offsets */ + 1572 103840 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { + 1573 11418 : if (phy_file_last != 0 && file->physical == phy_last + 1574 : /* files without offset are expected to have duplicates */ + 1575 0 : && phy_last != FILEPHY_WITHOUT_OFFSET + 1576 : ) { + 1577 : /* if verbose, print the list of duplicates real offsets */ + 1578 : /* other cases are for offsets not supported, so we don't need to report them file by file */ + 1579 0 : if (phy_last >= FILEPHY_REAL_OFFSET) { + 1580 0 : log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last); + 1581 : } + 1582 0 : ++phy_dup; + 1583 : } + 1584 11418 : phy_file_last = file; + 1585 11418 : phy_last = file->physical; + 1586 11418 : ++phy_count; + 1587 : } + 1588 : + 1589 : /* next node */ + 1590 103840 : node = node->next; + 1591 : + 1592 : /* insert in the parity */ + 1593 103840 : scan_file_allocate(scan, file); + 1594 : } + 1595 : + 1596 : /* mark the disk without reliable physical offset if it has duplicates */ + 1597 : /* here it should never happen because we already sorted out hardlinks */ + 1598 527 : if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) { + 1599 0 : disk->has_unreliable_physical = 1; + 1600 : } + 1601 : + 1602 : /* insert all the new links */ + 1603 527 : node = scan->link_insert_list; + 1604 3511 : while (node) { + 1605 2457 : struct snapraid_link* slink = node->data; + 1606 : + 1607 : /* next node */ + 1608 2457 : node = node->next; + 1609 : + 1610 : /* insert it */ + 1611 2457 : scan_link_insert(scan, slink); + 1612 : } + 1613 : + 1614 : /* insert all the new dirs */ + 1615 527 : node = scan->dir_insert_list; + 1616 1064 : while (node) { + 1617 10 : struct snapraid_dir* dir = node->data; + 1618 : + 1619 : /* next node */ + 1620 10 : node = node->next; + 1621 : + 1622 : /* insert it */ + 1623 10 : scan_emptydir_insert(scan, dir); + 1624 : } + 1625 : } + 1626 : + 1627 : /* check for disks where all the previously existing files where removed */ + 1628 88 : if (!state->opt.force_empty) { + 1629 82 : int all_missing = 0; + 1630 82 : int all_rewritten = 0; + 1631 82 : done = 0; + 1632 573 : for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) { + 1633 491 : struct snapraid_disk* disk = i->data; + 1634 491 : struct snapraid_scan* scan = j->data; + 1635 : + 1636 491 : if (scan->count_equal == 0 + 1637 71 : && scan->count_move == 0 + 1638 71 : && scan->count_restore == 0 + 1639 71 : && (scan->count_remove != 0 || scan->count_change != 0) + 1640 : ) { + 1641 1 : if (!done) { + 1642 1 : done = 1; + 1643 1 : log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir); + 1644 : } else { + 1645 0 : log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir); + 1646 : } + 1647 : + 1648 : /* detect the special condition of all files missing */ + 1649 1 : if (scan->count_change == 0) + 1650 1 : all_missing = 1; + 1651 : + 1652 : /* detect the special condition of all files rewritten */ + 1653 1 : if (scan->count_remove == 0) + 1654 0 : all_rewritten = 1; + 1655 : } + 1656 : } + 1657 82 : if (done) { + 1658 1 : log_fatal("\nare now missing or rewritten!\n"); + 1659 1 : if (all_rewritten) { + 1660 0 : log_fatal("This could happen when restoring a disk with a backup\n"); + 1661 0 : log_fatal("program that is not setting correctly the timestamps.\n"); + 1662 : } + 1663 1 : if (all_missing) { + 1664 1 : log_fatal("This could happen when some disks are not mounted\n"); + 1665 1 : log_fatal("in the expected directory.\n"); + 1666 : } + 1667 1 : if (!is_diff) { + 1668 1 : log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.\n", state->command, state->command); + 1669 1 : exit(EXIT_FAILURE); + 1670 : } + 1671 : } + 1672 : } + 1673 : + 1674 : /* check for disks without the physical offset support */ + 1675 87 : if (state->opt.force_order == SORT_PHYSICAL) { + 1676 2 : done = 0; + 1677 14 : for (i = state->disklist; i != 0; i = i->next) { + 1678 12 : struct snapraid_disk* disk = i->data; + 1679 : + 1680 12 : if (disk->has_unreliable_physical) { + 1681 0 : if (!done) { + 1682 0 : done = 1; + 1683 0 : log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name); + 1684 : } else { + 1685 0 : log_fatal(", '%s'", disk->name); + 1686 : } + 1687 : } + 1688 : } + 1689 2 : if (done) { + 1690 0 : log_fatal(". Files order won't be optimal.\n"); + 1691 : } + 1692 : } + 1693 : + 1694 : /* check for disks without persistent inodes */ + 1695 87 : done = 0; + 1696 608 : for (i = state->disklist; i != 0; i = i->next) { + 1697 521 : struct snapraid_disk* disk = i->data; + 1698 : + 1699 521 : if (disk->has_volatile_inodes) { + 1700 0 : if (!done) { + 1701 0 : done = 1; + 1702 0 : log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name); + 1703 : } else { + 1704 0 : log_fatal(", '%s'", disk->name); + 1705 : } + 1706 : } + 1707 : } + 1708 87 : if (done) { + 1709 0 : log_fatal(". Move operations won't be optimal.\n"); + 1710 : } + 1711 : + 1712 : /* check for disks with changed UUID */ + 1713 87 : done = 0; + 1714 608 : for (i = state->disklist; i != 0; i = i->next) { + 1715 521 : struct snapraid_disk* disk = i->data; + 1716 : + 1717 : /* don't print the message if the UUID changed because before */ + 1718 : /* it was no set. */ + 1719 : /* this is the normal condition for an empty disk because it */ + 1720 : /* isn't stored */ + 1721 521 : if (disk->has_different_uuid && !disk->had_empty_uuid) { + 1722 2 : if (!done) { + 1723 2 : done = 1; + 1724 2 : log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name); + 1725 : } else { + 1726 0 : log_fatal(", '%s'", disk->name); + 1727 : } + 1728 : } + 1729 : } + 1730 87 : if (done) { + 1731 2 : log_fatal(". Move operations won't be optimal.\n"); + 1732 : } + 1733 : + 1734 : /* check for disks with unsupported UUID */ + 1735 87 : done = 0; + 1736 608 : for (i = state->disklist; i != 0; i = i->next) { + 1737 521 : struct snapraid_disk* disk = i->data; + 1738 : + 1739 521 : if (disk->has_unsupported_uuid) { + 1740 0 : if (!done) { + 1741 0 : done = 1; + 1742 0 : log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name); + 1743 : } else { + 1744 0 : log_fatal(", '%s'", disk->name); + 1745 : } + 1746 : } + 1747 : } + 1748 87 : if (done) { + 1749 0 : log_fatal(". Move operations won't be optimal.\n"); + 1750 : #if defined(_linux) && !HAVE_BLKID + 1751 : log_fatal("The 'blkid' library is not linked in SnapRAID!\n"); + 1752 : log_fatal("Try rebuilding it after installing the libblkid-dev/devel package.\n"); + 1753 : #endif + 1754 : } + 1755 : + 1756 87 : total.count_equal = 0; + 1757 87 : total.count_move = 0; + 1758 87 : total.count_copy = 0; + 1759 87 : total.count_restore = 0; + 1760 87 : total.count_change = 0; + 1761 87 : total.count_remove = 0; + 1762 87 : total.count_insert = 0; + 1763 : + 1764 608 : for (i = scanlist; i != 0; i = i->next) { + 1765 521 : struct snapraid_scan* scan = i->data; + 1766 521 : total.count_equal += scan->count_equal; + 1767 521 : total.count_move += scan->count_move; + 1768 521 : total.count_copy += scan->count_copy; + 1769 521 : total.count_restore += scan->count_restore; + 1770 521 : total.count_change += scan->count_change; + 1771 521 : total.count_remove += scan->count_remove; + 1772 521 : total.count_insert += scan->count_insert; + 1773 : } + 1774 : + 1775 87 : if (is_diff) { + 1776 7 : msg_status("\n"); + 1777 7 : msg = msg_status; + 1778 : } else { + 1779 80 : msg = msg_verbose; + 1780 : } + 1781 : + 1782 87 : msg("%8u equal\n", total.count_equal); + 1783 87 : msg("%8u moved\n", total.count_move); + 1784 87 : msg("%8u copied\n", total.count_copy); + 1785 87 : msg("%8u restored\n", total.count_restore); + 1786 87 : msg("%8u updated\n", total.count_change); + 1787 87 : msg("%8u removed\n", total.count_remove); + 1788 87 : msg("%8u added\n", total.count_insert); + 1789 : + 1790 87 : log_tag("summary:equal:%u\n", total.count_equal); + 1791 87 : log_tag("summary:moved:%u\n", total.count_move); + 1792 87 : log_tag("summary:copied:%u\n", total.count_copy); + 1793 87 : log_tag("summary:restored:%u\n", total.count_restore); + 1794 87 : log_tag("summary:updated:%u\n", total.count_change); + 1795 87 : log_tag("summary:removed:%u\n", total.count_remove); + 1796 87 : log_tag("summary:added:%u\n", total.count_insert); + 1797 : + 1798 260 : no_difference = !total.count_move && !total.count_copy && !total.count_restore + 1799 144 : && !total.count_change && !total.count_remove && !total.count_insert; + 1800 : + 1801 87 : if (is_diff) { + 1802 7 : if (no_difference) { + 1803 1 : msg_status("No differences\n"); + 1804 : } else { + 1805 6 : msg_status("There are differences!\n"); + 1806 : } 1807 : } - 1808 79 : log_flush(); - 1809 : - 1810 79 : tommy_list_foreach(&scanlist, (tommy_foreach_func*)free); - 1811 : - 1812 : /* check the filesystem on all disks */ - 1813 79 : state_fscheck(state, "after scan"); - 1814 : - 1815 79 : if (is_diff) { - 1816 : /* check for file difference */ - 1817 7 : if (!no_difference) - 1818 6 : return 1; - 1819 : - 1820 : /* check also for incomplete "sync" */ - 1821 1 : if (parity_is_invalid(state)) - 1822 0 : return 1; - 1823 : } - 1824 : - 1825 73 : return 0; - 1826 : } - 1827 : - 1828 7 : int state_diff(struct snapraid_state* state) - 1829 : { - 1830 7 : return state_diffscan(state, 1); - 1831 : } - 1832 : - 1833 73 : void state_scan(struct snapraid_state* state) - 1834 : { - 1835 73 : (void)state_diffscan(state, 0); /* ignore return value */ - 1836 72 : } - 1837 : + 1808 : + 1809 87 : if (no_difference) { + 1810 14 : log_tag("summary:exit:equal\n"); + 1811 : } else { + 1812 73 : log_tag("summary:exit:diff\n"); + 1813 : } + 1814 87 : log_flush(); + 1815 : + 1816 87 : tommy_list_foreach(&scanlist, (tommy_foreach_func*)free); + 1817 : + 1818 : /* check the file-system on all disks */ + 1819 87 : state_fscheck(state, "after scan"); + 1820 : + 1821 87 : if (is_diff) { + 1822 : /* check for file difference */ + 1823 7 : if (!no_difference) + 1824 6 : return 1; + 1825 : + 1826 : /* check also for incomplete "sync" */ + 1827 1 : if (parity_is_invalid(state)) + 1828 0 : return 1; + 1829 : } + 1830 : + 1831 81 : return 0; + 1832 : } + 1833 : + 1834 7 : int state_diff(struct snapraid_state* state) + 1835 : { + 1836 7 : return state_diffscan(state, 1); + 1837 : } + 1838 : + 1839 81 : void state_scan(struct snapraid_state* state) + 1840 : { + 1841 81 : (void)state_diffscan(state, 0); /* ignore return value */ + 1842 80 : } + 1843 : diff --git a/cov/cmdline/scrub.c.func-sort-c.html b/cov/cmdline/scrub.c.func-sort-c.html index a40ea5f0..677e4c72 100644 --- a/cov/cmdline/scrub.c.func-sort-c.html +++ b/cov/cmdline/scrub.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,7 +61,7 @@ block_is_enabled - 111818 + 111994 state_scrub_process diff --git a/cov/cmdline/scrub.c.func.html b/cov/cmdline/scrub.c.func.html index 9815b4ce..0a104426 100644 --- a/cov/cmdline/scrub.c.func.html +++ b/cov/cmdline/scrub.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,7 +61,7 @@ block_is_enabled - 111818 + 111994 md diff --git a/cov/cmdline/scrub.c.gcov.html b/cov/cmdline/scrub.c.gcov.html index 751e79a9..d8624e9e 100644 --- a/cov/cmdline/scrub.c.gcov.html +++ b/cov/cmdline/scrub.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -110,55 +110,55 @@ 48 : /** 49 : * Check if we have to process the specified block index ::i. 50 : */ - 51 111818 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_plan* plan) + 51 111994 : static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_plan* plan) 52 : { 53 : time_t blocktime; 54 : snapraid_info info; 55 : 56 : /* don't scrub unused blocks in all plans */ - 57 111818 : info = info_get(&state->infoarr, i); - 58 111818 : if (info == 0) + 57 111994 : info = info_get(&state->infoarr, i); + 58 111994 : if (info == 0) 59 0 : return 0; 60 : 61 : /* bad blocks are always scrubbed in all plans */ - 62 111818 : if (info_get_bad(info)) - 63 3604 : return 1; + 62 111994 : if (info_get_bad(info)) + 63 3542 : return 1; 64 : - 65 108214 : switch (plan->plan) { + 65 108452 : switch (plan->plan) { 66 : case SCRUB_FULL : 67 : /* in 'full' plan everything is scrubbed */ - 68 16920 : return 1; + 68 17014 : return 1; 69 : case SCRUB_EVEN : 70 : /* in 'even' plan, scrub only even blocks */ - 71 18398 : return i % 2 == 0; + 71 18414 : return i % 2 == 0; 72 : case SCRUB_NEW : 73 : /* in 'sync' plan, only blocks never scrubbed */ - 74 9342 : return info_get_justsynced(info); + 74 9358 : return info_get_justsynced(info); 75 : case SCRUB_BAD : 76 : /* in 'bad' plan, only bad blocks (already reported) */ - 77 7502 : return 0; + 77 7518 : return 0; 78 : } 79 : 80 : /* if it's too new */ - 81 56052 : blocktime = info_get_time(info); - 82 56052 : if (blocktime > plan->timelimit) { + 81 56148 : blocktime = info_get_time(info); + 82 56148 : if (blocktime > plan->timelimit) { 83 : /* skip it */ - 84 22506 : return 0; + 84 20662 : return 0; 85 : } 86 : 87 : /* if the time is less than the limit, always include */ 88 : /* otherwise, check if we reached the last limit count */ - 89 33546 : if (blocktime == plan->timelimit) { + 89 35486 : if (blocktime == plan->timelimit) { 90 : /* if we reached the count limit */ - 91 16872 : if (plan->countlast >= plan->lastlimit) { + 91 18980 : if (plan->countlast >= plan->lastlimit) { 92 : /* skip it */ - 93 11882 : return 0; + 93 13790 : return 0; 94 : } 95 : - 96 4990 : ++plan->countlast; + 96 5190 : ++plan->countlast; 97 : } 98 : - 99 21664 : return 1; + 99 21696 : return 1; 100 : } 101 : 102 11 : static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax, struct snapraid_plan* plan, time_t now) @@ -204,11 +204,11 @@ 142 : /* first count the number of blocks to process */ 143 11 : countmax = 0; 144 11 : plan->countlast = 0; - 145 55920 : for (i = blockstart; i < blockmax; ++i) { - 146 55909 : if (!block_is_enabled(state, i, plan)) - 147 27950 : continue; + 145 56008 : for (i = blockstart; i < blockmax; ++i) { + 146 55997 : if (!block_is_enabled(state, i, plan)) + 147 28002 : continue; 148 : - 149 27959 : ++countmax; + 149 27995 : ++countmax; 150 : } 151 : 152 : /* compute the autosave size for all disk, even if not read */ @@ -225,7 +225,7 @@ 163 11 : countpos = 0; 164 11 : plan->countlast = 0; 165 11 : state_progress_begin(state, blockstart, blockmax, countmax); - 166 55920 : for (i = blockstart; i < blockmax; ++i) { + 166 56008 : for (i = blockstart; i < blockmax; ++i) { 167 : snapraid_info info; 168 : int error_on_this_block; 169 : int silent_error_on_this_block; @@ -233,65 +233,65 @@ 171 : int block_is_unsynced; 172 : int rehash; 173 : - 174 55909 : if (!block_is_enabled(state, i, plan)) - 175 27950 : continue; + 174 55997 : if (!block_is_enabled(state, i, plan)) + 175 28002 : continue; 176 : 177 : /* one more block processed for autosave */ - 178 27959 : ++autosavedone; - 179 27959 : --autosavemissing; + 178 27995 : ++autosavedone; + 179 27995 : --autosavemissing; 180 : 181 : /* by default process the block, and skip it if something goes wrong */ - 182 27959 : error_on_this_block = 0; - 183 27959 : silent_error_on_this_block = 0; - 184 27959 : io_error_on_this_block = 0; + 182 27995 : error_on_this_block = 0; + 183 27995 : silent_error_on_this_block = 0; + 184 27995 : io_error_on_this_block = 0; 185 : 186 : /* if all the blocks at this address are synced */ 187 : /* if not, parity is not even checked */ - 188 27959 : block_is_unsynced = 0; + 188 27995 : block_is_unsynced = 0; 189 : 190 : /* get block specific info */ - 191 27959 : info = info_get(&state->infoarr, i); + 191 27995 : info = info_get(&state->infoarr, i); 192 : 193 : /* if we have to use the old hash */ - 194 27959 : rehash = info_get_rehash(info); + 194 27995 : rehash = info_get_rehash(info); 195 : 196 : /* for each disk, process the block */ - 197 195713 : for (j = 0; j < diskmax; ++j) { + 197 195965 : for (j = 0; j < diskmax; ++j) { 198 : int read_size; 199 : unsigned char hash[HASH_SIZE]; 200 : struct snapraid_block* block; 201 : int file_is_unsynced; - 202 167754 : struct snapraid_disk* disk = handle[j].disk; + 202 167970 : struct snapraid_disk* disk = handle[j].disk; 203 : struct snapraid_file* file; 204 : block_off_t file_pos; 205 : 206 : /* if the file on this disk is synced */ 207 : /* if not, silent errors are assumed as expected error */ - 208 167754 : file_is_unsynced = 0; + 208 167970 : file_is_unsynced = 0; 209 : 210 : /* by default no rehash in case of "continue" */ - 211 167754 : rehandle[j].block = 0; + 211 167970 : rehandle[j].block = 0; 212 : 213 : /* if the disk position is not used */ - 214 167754 : if (!disk) { + 214 167970 : if (!disk) { 215 : /* use an empty block */ 216 0 : memset(buffer[j], 0, state->block_size); - 217 2433 : continue; + 217 2397 : continue; 218 : } 219 : 220 : /* if the block is not used */ - 221 167754 : block = fs_par2block_get(disk, i); - 222 167754 : if (!block_has_file(block)) { + 221 167970 : block = fs_par2block_get(disk, i); + 222 167970 : if (!block_has_file(block)) { 223 : /* use an empty block */ - 224 1513 : memset(buffer[j], 0, state->block_size); - 225 1513 : continue; + 224 1477 : memset(buffer[j], 0, state->block_size); + 225 1477 : continue; 226 : } 227 : 228 : /* get the file of this block */ - 229 166241 : file = fs_par2file_get(disk, i, &file_pos); + 229 166493 : file = fs_par2file_get(disk, i, &file_pos); 230 : 231 : /* if the block is unsynced, errors are expected */ - 232 166241 : if (block_has_invalid_parity(block)) { + 232 166493 : if (block_has_invalid_parity(block)) { 233 : /* report that the block and the file are not synced */ 234 0 : block_is_unsynced = 1; 235 0 : file_is_unsynced = 1; @@ -299,14 +299,14 @@ 237 : } 238 : 239 : /* until now is CPU */ - 240 166241 : state_usage_cpu(state); + 240 166493 : state_usage_cpu(state); 241 : 242 : /* if the file is different than the current one, close it */ - 243 166241 : if (handle[j].file != 0 && handle[j].file != file) { + 243 166493 : if (handle[j].file != 0 && handle[j].file != file) { 244 : /* keep a pointer at the file we are going to close for error reporting */ - 245 78552 : struct snapraid_file* report = handle[j].file; - 246 78552 : ret = handle_close(&handle[j]); - 247 78552 : if (ret == -1) { + 245 78228 : struct snapraid_file* report = handle[j].file; + 246 78228 : ret = handle_close(&handle[j]); + 247 78228 : if (ret == -1) { 248 : /* LCOV_EXCL_START */ 249 : /* This one is really an unexpected error, because we are only reading */ 250 : /* and closing a descriptor should never fail */ @@ -329,8 +329,8 @@ 267 : } 268 : } 269 : - 270 166241 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); - 271 166241 : if (ret == -1) { + 270 166493 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); + 271 166493 : if (ret == -1) { 272 0 : if (errno == EIO) { 273 : /* LCOV_EXCL_START */ 274 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); @@ -349,14 +349,14 @@ 287 : } 288 : 289 : /* check if the file is changed */ - 290 166241 : if (handle[j].st.st_size != file->size - 291 166241 : || handle[j].st.st_mtime != file->mtime_sec - 292 160522 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec - 293 : /* don't check the inode to support filesystem without persistent inodes */ + 290 166493 : if (handle[j].st.st_size != file->size + 291 166493 : || handle[j].st.st_mtime != file->mtime_sec + 292 160895 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec + 293 : /* don't check the inode to support file-system without persistent inodes */ 294 : ) { 295 : /* report that the block and the file are not synced */ - 296 5719 : block_is_unsynced = 1; - 297 5719 : file_is_unsynced = 1; + 296 5598 : block_is_unsynced = 1; + 297 5598 : file_is_unsynced = 1; 298 : /* follow */ 299 : } 300 : @@ -364,8 +364,8 @@ 302 : /* from the last sync, as we are expected to return errors if running */ 303 : /* in an unsynced array. This is just like the check command. */ 304 : - 305 166241 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0); - 306 166241 : if (read_size == -1) { + 305 166493 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0); + 306 166493 : if (read_size == -1) { 307 0 : if (errno == EIO) { 308 0 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc(file->sub), file_pos, strerror(errno)); 309 0 : if (io_error >= state->opt.io_error_limit) { @@ -391,24 +391,24 @@ 329 : } 330 : 331 : /* until now is disk */ - 332 166241 : state_usage_disk(state, disk); + 332 166493 : state_usage_disk(state, disk); 333 : - 334 166241 : countsize += read_size; + 334 166493 : countsize += read_size; 335 : 336 : /* now compute the hash */ - 337 166241 : if (rehash) { - 338 27207 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); + 337 166493 : if (rehash) { + 338 27235 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); 339 : 340 : /* compute the new hash, and store it */ - 341 27207 : rehandle[j].block = block; - 342 27207 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size); + 341 27235 : rehandle[j].block = block; + 342 27235 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size); 343 : } else { - 344 139034 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 344 139258 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); 345 : } 346 : - 347 166241 : if (block_has_updated_hash(block)) { + 347 166493 : if (block_has_updated_hash(block)) { 348 : /* compare the hash */ - 349 166241 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 349 166493 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { 350 920 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE); 351 : 352 920 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff); @@ -428,22 +428,22 @@ 366 : } 367 : 368 : /* if we have read all the data required and it's correct, proceed with the parity check */ - 369 27959 : if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) { + 369 27995 : if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) { 370 : unsigned char* buffer_recov[LEV_MAX]; 371 : 372 : /* until now is CPU */ - 373 27039 : state_usage_cpu(state); + 373 27075 : state_usage_cpu(state); 374 : 375 : /* buffers for parity read and not computed */ - 376 189273 : for (l = 0; l < state->level; ++l) - 377 162234 : buffer_recov[l] = buffer[diskmax + state->level + l]; - 378 27039 : for (; l < LEV_MAX; ++l) + 376 189525 : for (l = 0; l < state->level; ++l) + 377 162450 : buffer_recov[l] = buffer[diskmax + state->level + l]; + 378 27075 : for (; l < LEV_MAX; ++l) 379 0 : buffer_recov[l] = 0; 380 : 381 : /* read the parity */ - 382 189273 : for (l = 0; l < state->level; ++l) { - 383 162234 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); - 384 162234 : if (ret == -1) { + 382 189525 : for (l = 0; l < state->level; ++l) { + 383 162450 : ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); + 384 162450 : if (ret == -1) { 385 0 : buffer_recov[l] = 0; 386 : 387 0 : if (errno == EIO) { @@ -471,15 +471,15 @@ 409 : } 410 : 411 : /* until now is parity */ - 412 162234 : state_usage_parity(state, l); + 412 162450 : state_usage_parity(state, l); 413 : } 414 : 415 : /* compute the parity */ - 416 27039 : raid_gen(diskmax, state->level, state->block_size, buffer); + 416 27075 : raid_gen(diskmax, state->level, state->block_size, buffer); 417 : 418 : /* compare the parity */ - 419 189273 : for (l = 0; l < state->level; ++l) { - 420 162234 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { + 419 189525 : for (l = 0; l < state->level; ++l) { + 420 162450 : if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { 421 0 : unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size); 422 : 423 0 : log_tag("parity_error:%u:%s: Data error, diff bits %u\n", i, lev_config_name(l), diff); @@ -497,42 +497,42 @@ 435 : } 436 : } 437 : - 438 27959 : if (silent_error_on_this_block || io_error_on_this_block) { + 438 27995 : if (silent_error_on_this_block || io_error_on_this_block) { 439 : /* set the error status keeping other info */ 440 920 : info_set(&state->infoarr, i, info_set_bad(info)); - 441 27039 : } else if (error_on_this_block) { + 441 27075 : } else if (error_on_this_block) { 442 : /* do nothing, as this is a generic error */ 443 : /* likely caused by a not synced array */ 444 : } else { 445 : /* if rehash is needed */ - 446 27039 : if (rehash) { + 446 27075 : if (rehash) { 447 : /* store all the new hash already computed */ - 448 32200 : for (j = 0; j < diskmax; ++j) { - 449 27600 : if (rehandle[j].block) - 450 27207 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE); + 448 32228 : for (j = 0; j < diskmax; ++j) { + 449 27624 : if (rehandle[j].block) + 450 27235 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE); 451 : } 452 : } 453 : 454 : /* update the time info of the block */ 455 : /* and clear any other flag */ - 456 27039 : info_set(&state->infoarr, i, info_make(now, 0, 0, 0)); + 456 27075 : info_set(&state->infoarr, i, info_make(now, 0, 0, 0)); 457 : } 458 : 459 : /* mark the state as needing write */ - 460 27959 : state->need_write = 1; + 460 27995 : state->need_write = 1; 461 : 462 : /* count the number of processed block */ - 463 27959 : ++countpos; + 463 27995 : ++countpos; 464 : 465 : /* progress */ - 466 27959 : if (state_progress(state, i, countpos, countmax, countsize)) { + 466 27995 : if (state_progress(state, i, countpos, countmax, countsize)) { 467 : /* LCOV_EXCL_START */ 468 : break; 469 : /* LCOV_EXCL_STOP */ 470 : } 471 : 472 : /* autosave */ - 473 27959 : if (state->autosave != 0 + 473 27995 : if (state->autosave != 0 474 0 : && autosavedone >= autosavelimit /* if we have reached the limit */ 475 0 : && autosavemissing >= autosavelimit /* if we have at least a full step to do */ 476 : ) { @@ -705,14 +705,14 @@ 643 : /* copy the info in the temp vector */ 644 11 : count = 0; 645 11 : log_tag("block_count:%u\n", blockmax); - 646 55920 : for (i = 0; i < blockmax; ++i) { - 647 55909 : snapraid_info info = info_get(&state->infoarr, i); + 646 56008 : for (i = 0; i < blockmax; ++i) { + 647 55997 : snapraid_info info = info_get(&state->infoarr, i); 648 : 649 : /* skip unused blocks */ - 650 55909 : if (info == 0) + 650 55997 : if (info == 0) 651 0 : continue; 652 : - 653 55909 : timemap[count++] = info_get_time(info); + 653 55997 : timemap[count++] = info_get_time(info); 654 : } 655 : 656 11 : if (!count) { @@ -728,12 +728,12 @@ 666 : /* output the info map */ 667 11 : i = 0; 668 11 : log_tag("info_count:%u\n", count); - 669 54 : while (i < count) { - 670 32 : unsigned j = i + 1; - 671 55941 : while (j < count && timemap[i] == timemap[j]) - 672 55877 : ++j; - 673 32 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i); - 674 32 : i = j; + 669 49 : while (i < count) { + 670 27 : unsigned j = i + 1; + 671 56024 : while (j < count && timemap[i] == timemap[j]) + 672 55970 : ++j; + 673 27 : log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i); + 674 27 : i = j; 675 : } 676 : 677 : /* compute the limits from count/recentlimit */ @@ -754,8 +754,8 @@ 692 : /* count how many entries for this exact time we have to scrub */ 693 : /* if the blocks have all the same time, we end with countlimit == lastlimit */ 694 5 : ps.lastlimit = 1; - 695 2500 : while (countlimit > ps.lastlimit && timemap[countlimit - ps.lastlimit - 1] == ps.timelimit) - 696 2490 : ++ps.lastlimit; + 695 2600 : while (countlimit > ps.lastlimit && timemap[countlimit - ps.lastlimit - 1] == ps.timelimit) + 696 2590 : ++ps.lastlimit; 697 : } else { 698 : /* if nothing to scrub, disable also other limits */ 699 1 : ps.timelimit = 0; diff --git a/cov/cmdline/search.c.func-sort-c.html b/cov/cmdline/search.c.func-sort-c.html index 29c53774..b4963364 100644 --- a/cov/cmdline/search.c.func-sort-c.html +++ b/cov/cmdline/search.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 92 + 91 100 - 92.0 % + 91.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -61,19 +61,19 @@ search_file - 1842576 + 1843303 search_file_free - 1842576 + 1843303 state_search_fetch - 630482 + 639672 search_file_compare - 11531 + 20073 search_dir diff --git a/cov/cmdline/search.c.func.html b/cov/cmdline/search.c.func.html index 7773723e..bc92b8ca 100644 --- a/cov/cmdline/search.c.func.html +++ b/cov/cmdline/search.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 92 + 91 100 - 92.0 % + 91.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -65,15 +65,15 @@ search_file - 1842576 + 1843303 search_file_compare - 11531 + 20073 search_file_free - 1842576 + 1843303 state_search @@ -85,7 +85,7 @@ state_search_fetch - 630482 + 639672
diff --git a/cov/cmdline/search.c.gcov.html b/cov/cmdline/search.c.gcov.html index ae597b03..06f79786 100644 --- a/cov/cmdline/search.c.gcov.html +++ b/cov/cmdline/search.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 92 + 91 100 - 92.0 % + 91.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -85,27 +85,27 @@ 23 : /****************************************************************************/ 24 : /* search */ 25 : - 26 1842576 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) + 26 1843303 : static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) 27 : { 28 : struct snapraid_search_file* file; 29 : tommy_uint32_t file_hash; 30 : - 31 1842576 : file = malloc_nofail(sizeof(struct snapraid_search_file)); - 32 1842576 : file->path = strdup_nofail(path); - 33 1842576 : file->size = size; - 34 1842576 : file->mtime_sec = mtime_sec; - 35 1842576 : file->mtime_nsec = mtime_nsec; + 31 1843303 : file = malloc_nofail(sizeof(struct snapraid_search_file)); + 32 1843303 : file->path = strdup_nofail(path); + 33 1843303 : file->size = size; + 34 1843303 : file->mtime_sec = mtime_sec; + 35 1843303 : file->mtime_nsec = mtime_nsec; 36 : - 37 1842576 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + 37 1843303 : file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); 38 : - 39 1842576 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); - 40 1842576 : } + 39 1843303 : tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); + 40 1843303 : } 41 : - 42 1842576 : void search_file_free(struct snapraid_search_file* file) + 42 1843303 : void search_file_free(struct snapraid_search_file* file) 43 : { - 44 1842576 : free(file->path); - 45 1842576 : free(file); - 46 1842576 : } + 44 1843303 : free(file->path); + 45 1843303 : free(file); + 46 1843303 : } 47 : 48 : struct search_file_compare_arg { 49 : const struct snapraid_state* state; @@ -117,29 +117,29 @@ 55 : int prevhash; 56 : }; 57 : - 58 11531 : int search_file_compare(const void* void_arg, const void* void_data) + 58 20073 : int search_file_compare(const void* void_arg, const void* void_data) 59 : { - 60 11531 : const struct search_file_compare_arg* arg = void_arg; - 61 11531 : const struct snapraid_search_file* file = void_data; - 62 11531 : const struct snapraid_state* state = arg->state; + 60 20073 : const struct search_file_compare_arg* arg = void_arg; + 61 20073 : const struct snapraid_search_file* file = void_data; + 62 20073 : const struct snapraid_state* state = arg->state; 63 : unsigned char buffer_hash[HASH_SIZE]; - 64 11531 : const char* path = file->path; + 64 20073 : const char* path = file->path; 65 : int f; 66 : ssize_t ret; 67 : 68 : /* compare file info */ - 69 11531 : if (arg->file->size != file->size) + 69 20073 : if (arg->file->size != file->size) 70 0 : return -1; 71 : - 72 11531 : if (arg->file->mtime_sec != file->mtime_sec) + 72 20073 : if (arg->file->mtime_sec != file->mtime_sec) 73 0 : return -1; 74 : - 75 11531 : if (arg->file->mtime_nsec != file->mtime_nsec) + 75 20073 : if (arg->file->mtime_nsec != file->mtime_nsec) 76 0 : return -1; 77 : 78 : /* read the block and compare the hash */ - 79 11531 : f = open(path, O_RDONLY | O_BINARY); - 80 11531 : if (f == -1) { + 79 20073 : f = open(path, O_RDONLY | O_BINARY); + 80 20073 : if (f == -1) { 81 : /* LCOV_EXCL_START */ 82 : if (errno == ENOENT) { 83 : log_fatal("DANGER! file '%s' disappeared.\n", path); @@ -151,23 +151,23 @@ 89 : /* LCOV_EXCL_STOP */ 90 : } 91 : - 92 11531 : if (lseek(f, arg->offset, SEEK_SET) != arg->offset) { + 92 20073 : if (lseek(f, arg->offset, SEEK_SET) != arg->offset) { 93 : /* LCOV_EXCL_START */ 94 : log_fatal("Error seeking file '%s'. %s.\n", path, strerror(errno)); 95 : exit(EXIT_FAILURE); 96 : /* LCOV_EXCL_STOP */ 97 : } 98 : - 99 11531 : ret = read(f, arg->buffer, arg->read_size); - 100 11531 : if (ret < 0 || (unsigned)ret != arg->read_size) { + 99 20073 : ret = read(f, arg->buffer, arg->read_size); + 100 20073 : if (ret < 0 || (unsigned)ret != arg->read_size) { 101 : /* LCOV_EXCL_START */ 102 : log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); 103 : exit(EXIT_FAILURE); 104 : /* LCOV_EXCL_STOP */ 105 : } 106 : - 107 11531 : ret = close(f); - 108 11531 : if (ret != 0) { + 107 20073 : ret = close(f); + 108 20073 : if (ret != 0) { 109 : /* LCOV_EXCL_START */ 110 : log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); 111 : exit(EXIT_FAILURE); @@ -175,46 +175,46 @@ 113 : } 114 : 115 : /* compute the hash */ - 116 11531 : if (arg->prevhash) - 117 4492 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size); + 116 20073 : if (arg->prevhash) + 117 0 : memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size); 118 : else - 119 7039 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); + 119 20073 : memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); 120 : 121 : /* check if the hash is matching */ - 122 11531 : if (memcmp(buffer_hash, arg->block->hash, HASH_SIZE) != 0) - 123 2119 : return -1; + 122 20073 : if (memcmp(buffer_hash, arg->block->hash, HASH_SIZE) != 0) + 123 2235 : return -1; 124 : - 125 9412 : if (arg->read_size != state->block_size) { + 125 17838 : if (arg->read_size != state->block_size) { 126 : /* fill the remaining with 0 */ - 127 3956 : memset(arg->buffer + arg->read_size, 0, state->block_size - arg->read_size); + 127 7108 : memset(arg->buffer + arg->read_size, 0, state->block_size - arg->read_size); 128 : } 129 : - 130 9412 : return 0; + 130 17838 : return 0; 131 : } 132 : - 133 630482 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer) + 133 639672 : int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer) 134 : { 135 : struct snapraid_search_file* file; 136 : tommy_uint32_t file_hash; 137 : struct search_file_compare_arg arg; 138 : - 139 630482 : arg.state = state; - 140 630482 : arg.block = missing_block; - 141 630482 : arg.file = missing_file; - 142 630482 : arg.buffer = buffer; - 143 630482 : arg.offset = state->block_size * (data_off_t)missing_file_pos; - 144 630482 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); - 145 630482 : arg.prevhash = prevhash; + 139 639672 : arg.state = state; + 140 639672 : arg.block = missing_block; + 141 639672 : arg.file = missing_file; + 142 639672 : arg.buffer = buffer; + 143 639672 : arg.offset = state->block_size * (data_off_t)missing_file_pos; + 144 639672 : arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); + 145 639672 : arg.prevhash = prevhash; 146 : - 147 630482 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); + 147 639672 : file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); 148 : 149 : /* search in the hashtable, and also check if the data matches the hash */ - 150 630482 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); - 151 630482 : if (!file) - 152 621070 : return -1; + 150 639672 : file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); + 151 639672 : if (!file) + 152 621834 : return -1; 153 : 154 : /* if found, buffer is already set with data */ - 155 9412 : return 0; + 155 17838 : return 0; 156 : } 157 : 158 2462 : static void search_dir(struct snapraid_state* state, struct snapraid_disk* disk, const char* dir, const char* sub) @@ -233,40 +233,40 @@ 171 : char path_next[PATH_MAX]; 172 : char sub_next[PATH_MAX]; 173 : char out[PATH_MAX]; - 174 2039164 : struct snapraid_filter* reason = 0; + 174 2039885 : struct snapraid_filter* reason = 0; 175 : struct stat st; 176 : const char* name; 177 : struct dirent* dd; 178 : 179 : /* clear errno to detect erroneous conditions */ - 180 2039164 : errno = 0; - 181 2039164 : dd = readdir(d); - 182 2039164 : if (dd == 0 && errno != 0) { + 180 2039885 : errno = 0; + 181 2039885 : dd = readdir(d); + 182 2039885 : if (dd == 0 && errno != 0) { 183 : /* LCOV_EXCL_START */ 184 : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); 185 : exit(EXIT_FAILURE); 186 : /* LCOV_EXCL_STOP */ 187 : } - 188 2039164 : if (dd == 0) { + 188 2039885 : if (dd == 0) { 189 2462 : break; /* finished */ 190 : } 191 : 192 : /* skip "." and ".." files */ - 193 2036702 : name = dd->d_name; - 194 2036702 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + 193 2037423 : name = dd->d_name; + 194 2037423 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 195 9848 : continue; 196 : - 197 2031778 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - 198 2031778 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + 197 2032499 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + 198 2032499 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); 199 : 200 : /* exclude hidden files even before calling lstat() */ - 201 2031778 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { + 201 2032499 : if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { 202 0 : msg_verbose("Excluding hidden '%s'\n", path_next); 203 0 : continue; 204 : } 205 : 206 : /* exclude content files even before calling lstat() */ - 207 2031778 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { + 207 2032499 : if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { 208 0 : msg_verbose("Excluding content '%s'\n", path_next); 209 0 : continue; 210 : } @@ -290,7 +290,7 @@ 228 : } 229 : #else 230 : /* get lstat info about the file */ - 231 2031778 : if (lstat(path_next, &st) != 0) { + 231 2032499 : if (lstat(path_next, &st) != 0) { 232 : /* LCOV_EXCL_START */ 233 : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); 234 : exit(EXIT_FAILURE); @@ -298,13 +298,13 @@ 236 : } 237 : #endif 238 : - 239 2031778 : if (S_ISREG(st.st_mode)) { - 240 1967521 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { - 241 1842576 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); + 239 2032499 : if (S_ISREG(st.st_mode)) { + 240 1968182 : if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + 241 1843303 : search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); 242 : } else { - 243 124945 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + 243 124879 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 244 : } - 245 64257 : } else if (S_ISDIR(st.st_mode)) { + 245 64317 : } else if (S_ISDIR(st.st_mode)) { 246 1781 : if (disk == 0 || filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) { 247 1781 : pathslash(path_next, sizeof(path_next)); 248 1781 : pathslash(sub_next, sizeof(sub_next)); @@ -313,7 +313,7 @@ 251 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); 252 : } 253 : } - 254 2036702 : } + 254 2037423 : } 255 : 256 2462 : if (closedir(d) != 0) { 257 : /* LCOV_EXCL_START */ diff --git a/cov/cmdline/selftest.c.func-sort-c.html b/cov/cmdline/selftest.c.func-sort-c.html index cbbf9134..ef0b6b12 100644 --- a/cov/cmdline/selftest.c.func-sort-c.html +++ b/cov/cmdline/selftest.c.func-sort-c.html @@ -32,12 +32,12 @@ Lines: 144 - 172 - 83.7 % + 144 + 100.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -88,7 +88,7 @@ 1 - selftest + selftest 1 diff --git a/cov/cmdline/selftest.c.func.html b/cov/cmdline/selftest.c.func.html index 7dd73f90..bb9ef14f 100644 --- a/cov/cmdline/selftest.c.func.html +++ b/cov/cmdline/selftest.c.func.html @@ -32,12 +32,12 @@ Lines: 144 - 172 - 83.7 % + 144 + 100.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -60,7 +60,7 @@ Hit count Sort by hit count - selftest + selftest 1 diff --git a/cov/cmdline/selftest.c.gcov.html b/cov/cmdline/selftest.c.gcov.html index c18817e6..31f5f6df 100644 --- a/cov/cmdline/selftest.c.gcov.html +++ b/cov/cmdline/selftest.c.gcov.html @@ -32,12 +32,12 @@ Lines: 144 - 172 - 83.7 % + 144 + 100.0 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -378,207 +378,288 @@ 316 256 : *(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) = i; 317 : } 318 : - 319 1 : if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*)) - 320 0 : goto bail; - 321 1 : if (tommy_arrayblk_memory_usage(&arrayblk) < TOMMY_SIZE * sizeof(void*)) - 322 0 : goto bail; - 323 1 : if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned)) - 324 0 : goto bail; - 325 : - 326 257 : for (i = 0; i < TOMMY_SIZE; ++i) { - 327 256 : if (tommy_array_get(&array, i) != &node[i]) - 328 0 : goto bail; - 329 256 : if (tommy_arrayblk_get(&arrayblk, i) != &node[i]) - 330 0 : goto bail; - 331 256 : if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i) - 332 0 : goto bail; + 319 1 : if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*)) { + 320 : /* LCOV_EXCL_START */ + 321 : goto bail; + 322 : /* LCOV_EXCL_STOP */ + 323 : } + 324 1 : if (tommy_arrayblk_memory_usage(&arrayblk) < TOMMY_SIZE * sizeof(void*)) { + 325 : /* LCOV_EXCL_START */ + 326 : goto bail; + 327 : /* LCOV_EXCL_STOP */ + 328 : } + 329 1 : if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned)) { + 330 : /* LCOV_EXCL_START */ + 331 : goto bail; + 332 : /* LCOV_EXCL_STOP */ 333 : } 334 : - 335 1 : tommy_arrayblkof_done(&arrayblkof); - 336 1 : tommy_arrayblk_done(&arrayblk); - 337 1 : tommy_array_done(&array); - 338 : - 339 1 : tommy_list_init(&list); - 340 : - 341 1 : if (!tommy_list_empty(&list)) - 342 0 : goto bail; - 343 : - 344 1 : if (tommy_list_tail(&list)) - 345 0 : goto bail; - 346 : - 347 1 : if (tommy_list_head(&list)) - 348 0 : goto bail; - 349 : - 350 1 : tommy_hashdyn_init(&hashdyn); - 351 : - 352 257 : for (i = 0; i < TOMMY_SIZE; ++i) - 353 256 : tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64); - 354 : - 355 1 : if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE) - 356 0 : goto bail; - 357 : - 358 1 : if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node)) - 359 0 : goto bail; - 360 : - 361 1 : tommy_test_foreach_count = 0; - 362 1 : tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach); - 363 1 : if (tommy_test_foreach_count != TOMMY_SIZE) - 364 0 : goto bail; - 365 : - 366 1 : tommy_test_foreach_count = 0; - 367 1 : tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count); - 368 1 : if (tommy_test_foreach_count != TOMMY_SIZE) - 369 0 : goto bail; + 335 257 : for (i = 0; i < TOMMY_SIZE; ++i) { + 336 256 : if (tommy_array_get(&array, i) != &node[i]) { + 337 : /* LCOV_EXCL_START */ + 338 : goto bail; + 339 : /* LCOV_EXCL_STOP */ + 340 : } + 341 256 : if (tommy_arrayblk_get(&arrayblk, i) != &node[i]) { + 342 : /* LCOV_EXCL_START */ + 343 : goto bail; + 344 : /* LCOV_EXCL_STOP */ + 345 : } + 346 256 : if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i) { + 347 : /* LCOV_EXCL_START */ + 348 : goto bail; + 349 : /* LCOV_EXCL_STOP */ + 350 : } + 351 : } + 352 : + 353 1 : tommy_arrayblkof_done(&arrayblkof); + 354 1 : tommy_arrayblk_done(&arrayblk); + 355 1 : tommy_array_done(&array); + 356 : + 357 1 : tommy_list_init(&list); + 358 : + 359 1 : if (!tommy_list_empty(&list)) { + 360 : /* LCOV_EXCL_START */ + 361 : goto bail; + 362 : /* LCOV_EXCL_STOP */ + 363 : } + 364 : + 365 1 : if (tommy_list_tail(&list)) { + 366 : /* LCOV_EXCL_START */ + 367 : goto bail; + 368 : /* LCOV_EXCL_STOP */ + 369 : } 370 : - 371 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) - 372 128 : tommy_hashdyn_remove_existing(&hashdyn, &node[i]); - 373 : - 374 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) - 375 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0) - 376 0 : goto bail; - 377 : - 378 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) - 379 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0) - 380 0 : goto bail; + 371 1 : if (tommy_list_head(&list)) { + 372 : /* LCOV_EXCL_START */ + 373 : goto bail; + 374 : /* LCOV_EXCL_STOP */ + 375 : } + 376 : + 377 1 : tommy_hashdyn_init(&hashdyn); + 378 : + 379 257 : for (i = 0; i < TOMMY_SIZE; ++i) + 380 256 : tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64); 381 : - 382 1 : if (tommy_hashdyn_count(&hashdyn) != 0) - 383 0 : goto bail; - 384 : - 385 1 : tommy_hashdyn_done(&hashdyn); - 386 : - 387 1 : tommy_tree_init(&tree, tommy_test_compare); - 388 : - 389 257 : for (i = 0; i < TOMMY_SIZE; ++i) - 390 256 : tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i+1)); - 391 : - 392 : /* try to insert a duplicate, count should not change */ - 393 1 : if (tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)1) != (void*)1) - 394 0 : goto bail; - 395 : - 396 1 : if (tommy_tree_count(&tree) != TOMMY_SIZE) - 397 0 : goto bail; - 398 : - 399 1 : if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node)) - 400 0 : goto bail; + 382 1 : if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE) { + 383 : /* LCOV_EXCL_START */ + 384 : goto bail; + 385 : /* LCOV_EXCL_STOP */ + 386 : } + 387 : + 388 1 : if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node)) { + 389 : /* LCOV_EXCL_START */ + 390 : goto bail; + 391 : /* LCOV_EXCL_STOP */ + 392 : } + 393 : + 394 1 : tommy_test_foreach_count = 0; + 395 1 : tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach); + 396 1 : if (tommy_test_foreach_count != TOMMY_SIZE) { + 397 : /* LCOV_EXCL_START */ + 398 : goto bail; + 399 : /* LCOV_EXCL_STOP */ + 400 : } 401 : - 402 1 : if (tommy_tree_search(&tree, (void*)1) != (void*)1) - 403 0 : goto bail; - 404 : - 405 1 : if (tommy_tree_search(&tree, (void*)-1) != 0) - 406 0 : goto bail; - 407 : - 408 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1) - 409 0 : goto bail; - 410 : - 411 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0) - 412 0 : goto bail; - 413 : - 414 1 : tommy_test_foreach_count = 0; - 415 1 : tommy_tree_foreach(&tree, tommy_test_foreach); - 416 1 : if (tommy_test_foreach_count != TOMMY_SIZE) - 417 0 : goto bail; - 418 : - 419 1 : tommy_test_foreach_count = 0; - 420 1 : tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count); - 421 1 : if (tommy_test_foreach_count != TOMMY_SIZE) - 422 0 : goto bail; - 423 : - 424 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) - 425 128 : tommy_tree_remove_existing(&tree, &node[i]); - 426 : - 427 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) - 428 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) != 0) - 429 0 : goto bail; - 430 : - 431 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) - 432 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) == 0) - 433 0 : goto bail; - 434 : - 435 1 : if (tommy_tree_count(&tree) != 0) - 436 0 : goto bail; + 402 1 : tommy_test_foreach_count = 0; + 403 1 : tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count); + 404 1 : if (tommy_test_foreach_count != TOMMY_SIZE) { + 405 : /* LCOV_EXCL_START */ + 406 : goto bail; + 407 : /* LCOV_EXCL_STOP */ + 408 : } + 409 : + 410 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) + 411 128 : tommy_hashdyn_remove_existing(&hashdyn, &node[i]); + 412 : + 413 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) { + 414 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0) { + 415 : /* LCOV_EXCL_START */ + 416 : goto bail; + 417 : /* LCOV_EXCL_STOP */ + 418 : } + 419 : } + 420 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) { + 421 128 : if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0) { + 422 : /* LCOV_EXCL_START */ + 423 : goto bail; + 424 : /* LCOV_EXCL_STOP */ + 425 : } + 426 : } + 427 : + 428 1 : if (tommy_hashdyn_count(&hashdyn) != 0) { + 429 : /* LCOV_EXCL_START */ + 430 : goto bail; + 431 : /* LCOV_EXCL_STOP */ + 432 : } + 433 : + 434 1 : tommy_hashdyn_done(&hashdyn); + 435 : + 436 1 : tommy_tree_init(&tree, tommy_test_compare); 437 : - 438 2 : return; - 439 : bail: - 440 : /* LCOV_EXCL_START */ - 441 : log_fatal("Failed tommy test\n"); - 442 : exit(EXIT_FAILURE); - 443 : /* LCOV_EXCL_STOP */ - 444 : } - 445 : - 446 1 : void selftest(void) - 447 : { - 448 1 : log_tag("selftest:\n"); - 449 1 : log_flush(); - 450 : - 451 1 : msg_progress("Self test...\n"); - 452 : - 453 : /* large file check */ - 454 : if (sizeof(off_t) < sizeof(uint64_t)) { - 455 : /* LCOV_EXCL_START */ - 456 : log_fatal("Missing support for large files\n"); - 457 : exit(EXIT_FAILURE); - 458 : /* LCOV_EXCL_STOP */ - 459 : } - 460 : - 461 1 : test_hash(); - 462 1 : test_crc32c(); - 463 1 : test_tommy(); - 464 1 : if (raid_selftest() != 0) { - 465 : /* LCOV_EXCL_START */ - 466 : log_fatal("Failed SELF test\n"); - 467 : exit(EXIT_FAILURE); - 468 : /* LCOV_EXCL_STOP */ - 469 : } - 470 1 : if (raid_test_sort() != 0) { - 471 : /* LCOV_EXCL_START */ - 472 : log_fatal("Failed SORT test\n"); - 473 : exit(EXIT_FAILURE); - 474 : /* LCOV_EXCL_STOP */ - 475 : } - 476 1 : if (raid_test_insert() != 0) { - 477 : /* LCOV_EXCL_START */ - 478 : log_fatal("Failed INSERT test\n"); - 479 : exit(EXIT_FAILURE); - 480 : /* LCOV_EXCL_STOP */ - 481 : } - 482 1 : if (raid_test_combo() != 0) { - 483 : /* LCOV_EXCL_START */ - 484 : log_fatal("Failed COMBO test\n"); - 485 : exit(EXIT_FAILURE); - 486 : /* LCOV_EXCL_STOP */ - 487 : } - 488 1 : if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) { + 438 257 : for (i = 0; i < TOMMY_SIZE; ++i) + 439 256 : tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i+1)); + 440 : + 441 : /* try to insert a duplicate, count should not change */ + 442 1 : if (tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)1) != (void*)1) { + 443 : /* LCOV_EXCL_START */ + 444 : goto bail; + 445 : /* LCOV_EXCL_STOP */ + 446 : } + 447 1 : if (tommy_tree_count(&tree) != TOMMY_SIZE) { + 448 : /* LCOV_EXCL_START */ + 449 : goto bail; + 450 : /* LCOV_EXCL_STOP */ + 451 : } + 452 1 : if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node)) { + 453 : /* LCOV_EXCL_START */ + 454 : goto bail; + 455 : /* LCOV_EXCL_STOP */ + 456 : } + 457 1 : if (tommy_tree_search(&tree, (void*)1) != (void*)1) { + 458 : /* LCOV_EXCL_START */ + 459 : goto bail; + 460 : /* LCOV_EXCL_STOP */ + 461 : } + 462 1 : if (tommy_tree_search(&tree, (void*)-1) != 0) { + 463 : /* LCOV_EXCL_START */ + 464 : goto bail; + 465 : /* LCOV_EXCL_STOP */ + 466 : } + 467 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1) { + 468 : /* LCOV_EXCL_START */ + 469 : goto bail; + 470 : /* LCOV_EXCL_STOP */ + 471 : } + 472 1 : if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0) { + 473 : /* LCOV_EXCL_START */ + 474 : goto bail; + 475 : /* LCOV_EXCL_STOP */ + 476 : } + 477 : + 478 1 : tommy_test_foreach_count = 0; + 479 1 : tommy_tree_foreach(&tree, tommy_test_foreach); + 480 1 : if (tommy_test_foreach_count != TOMMY_SIZE) { + 481 : /* LCOV_EXCL_START */ + 482 : goto bail; + 483 : /* LCOV_EXCL_STOP */ + 484 : } + 485 : + 486 1 : tommy_test_foreach_count = 0; + 487 1 : tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count); + 488 1 : if (tommy_test_foreach_count != TOMMY_SIZE) { 489 : /* LCOV_EXCL_START */ - 490 : log_fatal("Failed GEN Vandermonde test\n"); - 491 : exit(EXIT_FAILURE); - 492 : /* LCOV_EXCL_STOP */ - 493 : } - 494 1 : if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) { - 495 : /* LCOV_EXCL_START */ - 496 : log_fatal("Failed REC Vandermonde test\n"); - 497 : exit(EXIT_FAILURE); - 498 : /* LCOV_EXCL_STOP */ - 499 : } - 500 1 : if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) { - 501 : /* LCOV_EXCL_START */ - 502 : log_fatal("Failed GEN Cauchy test\n"); - 503 : exit(EXIT_FAILURE); - 504 : /* LCOV_EXCL_STOP */ - 505 : } - 506 1 : if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) { - 507 : /* LCOV_EXCL_START */ - 508 : log_fatal("Failed REC Cauchy test\n"); - 509 : exit(EXIT_FAILURE); - 510 : /* LCOV_EXCL_STOP */ + 490 : goto bail; + 491 : /* LCOV_EXCL_STOP */ + 492 : } + 493 : + 494 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) + 495 128 : tommy_tree_remove_existing(&tree, &node[i]); + 496 : + 497 129 : for (i = 0; i < TOMMY_SIZE / 2; ++i) { + 498 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) != 0) { + 499 : /* LCOV_EXCL_START */ + 500 : goto bail; + 501 : /* LCOV_EXCL_STOP */ + 502 : } + 503 : } + 504 : + 505 129 : for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) { + 506 128 : if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i+1)) == 0) { + 507 : /* LCOV_EXCL_START */ + 508 : goto bail; + 509 : /* LCOV_EXCL_STOP */ + 510 : } 511 : } - 512 1 : if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) { - 513 : /* LCOV_EXCL_START */ - 514 : log_fatal("Failed GEN Cauchy test sigle data disk\n"); - 515 : exit(EXIT_FAILURE); + 512 : + 513 1 : if (tommy_tree_count(&tree) != 0) { + 514 : /* LCOV_EXCL_START */ + 515 : goto bail; 516 : /* LCOV_EXCL_STOP */ 517 : } - 518 1 : } - 519 : + 518 : + 519 2 : return; + 520 : bail: + 521 : /* LCOV_EXCL_START */ + 522 : log_fatal("Failed tommy test\n"); + 523 : exit(EXIT_FAILURE); + 524 : /* LCOV_EXCL_STOP */ + 525 : } + 526 : + 527 1 : void selftest(void) + 528 : { + 529 1 : log_tag("selftest:\n"); + 530 1 : log_flush(); + 531 : + 532 1 : msg_progress("Self test...\n"); + 533 : + 534 : /* large file check */ + 535 : if (sizeof(off_t) < sizeof(uint64_t)) { + 536 : /* LCOV_EXCL_START */ + 537 : log_fatal("Missing support for large files\n"); + 538 : exit(EXIT_FAILURE); + 539 : /* LCOV_EXCL_STOP */ + 540 : } + 541 : + 542 1 : test_hash(); + 543 1 : test_crc32c(); + 544 1 : test_tommy(); + 545 1 : if (raid_selftest() != 0) { + 546 : /* LCOV_EXCL_START */ + 547 : log_fatal("Failed SELF test\n"); + 548 : exit(EXIT_FAILURE); + 549 : /* LCOV_EXCL_STOP */ + 550 : } + 551 1 : if (raid_test_sort() != 0) { + 552 : /* LCOV_EXCL_START */ + 553 : log_fatal("Failed SORT test\n"); + 554 : exit(EXIT_FAILURE); + 555 : /* LCOV_EXCL_STOP */ + 556 : } + 557 1 : if (raid_test_insert() != 0) { + 558 : /* LCOV_EXCL_START */ + 559 : log_fatal("Failed INSERT test\n"); + 560 : exit(EXIT_FAILURE); + 561 : /* LCOV_EXCL_STOP */ + 562 : } + 563 1 : if (raid_test_combo() != 0) { + 564 : /* LCOV_EXCL_START */ + 565 : log_fatal("Failed COMBO test\n"); + 566 : exit(EXIT_FAILURE); + 567 : /* LCOV_EXCL_STOP */ + 568 : } + 569 1 : if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) { + 570 : /* LCOV_EXCL_START */ + 571 : log_fatal("Failed GEN Vandermonde test\n"); + 572 : exit(EXIT_FAILURE); + 573 : /* LCOV_EXCL_STOP */ + 574 : } + 575 1 : if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) { + 576 : /* LCOV_EXCL_START */ + 577 : log_fatal("Failed REC Vandermonde test\n"); + 578 : exit(EXIT_FAILURE); + 579 : /* LCOV_EXCL_STOP */ + 580 : } + 581 1 : if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) { + 582 : /* LCOV_EXCL_START */ + 583 : log_fatal("Failed GEN Cauchy test\n"); + 584 : exit(EXIT_FAILURE); + 585 : /* LCOV_EXCL_STOP */ + 586 : } + 587 1 : if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) { + 588 : /* LCOV_EXCL_START */ + 589 : log_fatal("Failed REC Cauchy test\n"); + 590 : exit(EXIT_FAILURE); + 591 : /* LCOV_EXCL_STOP */ + 592 : } + 593 1 : if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) { + 594 : /* LCOV_EXCL_START */ + 595 : log_fatal("Failed GEN Cauchy test sigle data disk\n"); + 596 : exit(EXIT_FAILURE); + 597 : /* LCOV_EXCL_STOP */ + 598 : } + 599 1 : } + 600 : diff --git a/cov/cmdline/snapraid.c.func-sort-c.html b/cov/cmdline/snapraid.c.func-sort-c.html index 8601a790..1a663a69 100644 --- a/cov/cmdline/snapraid.c.func-sort-c.html +++ b/cov/cmdline/snapraid.c.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 446 - 474 - 94.1 % + 454 + 484 + 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -60,28 +60,28 @@ Hit count Sort by hit count - main - 257 + main + 265 config - 257 + 265 log_open - 247 + 255 log_close - 225 + 233 memory - 222 + 230 - signal_init - 208 + signal_init + 216 version diff --git a/cov/cmdline/snapraid.c.func.html b/cov/cmdline/snapraid.c.func.html index 5c3cd1ce..ccd27a1f 100644 --- a/cov/cmdline/snapraid.c.func.html +++ b/cov/cmdline/snapraid.c.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 446 - 474 - 94.1 % + 454 + 484 + 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -61,27 +61,27 @@ config - 257 + 265 log_close - 225 + 233 log_open - 247 + 255 - main - 257 + main + 265 memory - 222 + 230 - signal_init - 208 + signal_init + 216 usage diff --git a/cov/cmdline/snapraid.c.gcov.html b/cov/cmdline/snapraid.c.gcov.html index 9efa5568..7343ea06 100644 --- a/cov/cmdline/snapraid.c.gcov.html +++ b/cov/cmdline/snapraid.c.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 446 - 474 - 94.1 % + 454 + 484 + 93.8 % Date: - 2015-11-20 + 2016-01-09 Functions: 8 @@ -103,13 +103,13 @@ 41 1 : printf("\n"); 42 1 : printf("Commands:\n"); 43 1 : printf(" status Print the status of the array\n"); - 44 1 : printf(" diff Show the changes that needs to be syncronized\n"); - 45 1 : printf(" sync Syncronize the state of the array\n"); + 44 1 : printf(" diff Show the changes that needs to be synchronized\n"); + 45 1 : printf(" sync Synchronize the state of the array\n"); 46 1 : printf(" scrub Scrub the array\n"); 47 1 : printf(" list List the array content\n"); 48 1 : printf(" dup Find duplicate files\n"); - 49 1 : printf(" up Spinup the array\n"); - 50 1 : printf(" down Spindown the array\n"); + 49 1 : printf(" up Spin-up the array\n"); + 50 1 : printf(" down Spin-down the array\n"); 51 1 : printf(" smart SMART attributes of the array\n"); 52 1 : printf(" pool Create or update the virtual view of the array\n"); 53 1 : printf(" check Check the array\n"); @@ -126,34 +126,34 @@ 64 1 : printf(" " SWITCH_GETOPT_LONG("-i, --import DIR ", "-i") " Import deleted files\n"); 65 1 : printf(" " SWITCH_GETOPT_LONG("-l, --log FILE ", "-l") " Log file. Default none\n"); 66 1 : printf(" " SWITCH_GETOPT_LONG("-a, --audit-only ", "-a") " Check only file data and not parity\n"); - 67 1 : printf(" " SWITCH_GETOPT_LONG("-h, --pre-hash ", "-h") " Pre hash all the new data\n"); - 68 1 : printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force synching of files that get zero size\n"); - 69 1 : printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force synching of disks that get empty\n"); + 67 1 : printf(" " SWITCH_GETOPT_LONG("-h, --pre-hash ", "-h") " Pre-hash all the new data\n"); + 68 1 : printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force syncing of files that get zero size\n"); + 69 1 : printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force syncing of disks that get empty\n"); 70 1 : printf(" " SWITCH_GETOPT_LONG("-U, --force-uuid ", "-U") " Force commands on disks with uuid changed\n"); - 71 1 : printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands with unaccessible/shared disks\n"); + 71 1 : printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands with inaccessible/shared disks\n"); 72 1 : printf(" " SWITCH_GETOPT_LONG("-N, --force-nocopy ", "-N") " Force commands disabling the copy detection\n"); 73 1 : printf(" " SWITCH_GETOPT_LONG("-F, --force-full ", "-F") " Force commands requiring a full sync\n"); 74 1 : printf(" " SWITCH_GETOPT_LONG("-v, --verbose ", "-v") " Verbose\n"); 75 1 : } 76 : - 77 222 : void memory(void) + 77 230 : void memory(void) 78 : { - 79 222 : log_tag("memory:used:%" PRIu64 "\n", (uint64_t)malloc_counter()); + 79 230 : log_tag("memory:used:%" PRIu64 "\n", (uint64_t)malloc_counter_get()); 80 : 81 : /* size of the block */ - 82 222 : log_tag("memory:block:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_block))); - 83 222 : log_tag("memory:chunk:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_chunk))); - 84 222 : log_tag("memory:file:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_file))); - 85 222 : log_tag("memory:link:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_link))); - 86 222 : log_tag("memory:dir:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_dir))); + 82 230 : log_tag("memory:block:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_block))); + 83 230 : log_tag("memory:chunk:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_chunk))); + 84 230 : log_tag("memory:file:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_file))); + 85 230 : log_tag("memory:link:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_link))); + 86 230 : log_tag("memory:dir:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_dir))); 87 : - 88 222 : msg_progress("Using %u MiB of memory.\n", (unsigned)(malloc_counter() / (1024 * 1024))); - 89 222 : } + 88 230 : msg_progress("Using %u MiB of memory.\n", (unsigned)(malloc_counter_get() / (1024 * 1024))); + 89 230 : } 90 : 91 : /****************************************************************************/ 92 : /* log */ 93 : - 94 247 : void log_open(const char* file) + 94 255 : void log_open(const char* file) 95 : { 96 : char path[PATH_MAX]; 97 : const char* mode; @@ -163,8 +163,8 @@ 101 : struct tm* tm; 102 : 103 : /* leave stdlog at 0 if not specified */ - 104 247 : if (file == 0) - 105 343 : return; + 104 255 : if (file == 0) + 105 359 : return; 106 : 107 77 : t = time(0); 108 77 : tm = localtime(&t); @@ -237,9 +237,9 @@ 175 : } 176 : } 177 : - 178 225 : void log_close(const char* file) + 178 233 : void log_close(const char* file) 179 : { - 180 225 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) { + 180 233 : if (stdlog != stdout && stdlog != stderr && stdlog != 0) { 181 74 : if (fclose(stdlog) != 0) { 182 : /* LCOV_EXCL_START */ 183 : log_fatal("Error closing the log file '%s'. %s.\n", file, strerror(errno)); @@ -248,13 +248,13 @@ 186 : } 187 : } 188 : - 189 225 : stdlog = 0; - 190 225 : } + 189 233 : stdlog = 0; + 190 233 : } 191 : 192 : /****************************************************************************/ 193 : /* config */ 194 : - 195 257 : void config(char* conf, size_t conf_size, const char* argv0) + 195 265 : void config(char* conf, size_t conf_size, const char* argv0) 196 : { 197 : #ifdef _WIN32 198 : char* slash; @@ -271,9 +271,9 @@ 209 : #else 210 : (void)argv0; 211 : - 212 257 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf"); + 212 265 : pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf"); 213 : #endif - 214 257 : } + 214 265 : } 215 : 216 : /****************************************************************************/ 217 : /* main */ @@ -307,1052 +307,1084 @@ 245 : #define OPT_TEST_FORCE_AUTOSAVE_AT 283 246 : #define OPT_TEST_FAKE_DEVICE 284 247 : #define OPT_TEST_EXPECT_NEED_SYNC 285 - 248 : - 249 : #if HAVE_GETOPT_LONG - 250 : struct option long_options[] = { - 251 : { "conf", 1, 0, 'c' }, - 252 : { "filter", 1, 0, 'f' }, - 253 : { "filter-disk", 1, 0, 'd' }, - 254 : { "filter-missing", 0, 0, 'm' }, - 255 : { "filter-error", 0, 0, 'e' }, - 256 : { "percentage", 1, 0, 'p' }, /* legacy name for --plan */ - 257 : { "plan", 1, 0, 'p' }, - 258 : { "older-than", 1, 0, 'o' }, - 259 : { "start", 1, 0, 'S' }, - 260 : { "count", 1, 0, 'B' }, - 261 : { "error-limit", 1, 0, 'L' }, - 262 : { "import", 1, 0, 'i' }, - 263 : { "log", 1, 0, 'l' }, - 264 : { "force-zero", 0, 0, 'Z' }, - 265 : { "force-empty", 0, 0, 'E' }, - 266 : { "force-uuid", 0, 0, 'U' }, - 267 : { "force-device", 0, 0, 'D' }, - 268 : { "force-nocopy", 0, 0, 'N' }, - 269 : { "force-full", 0, 0, 'F' }, - 270 : { "audit-only", 0, 0, 'a' }, - 271 : { "pre-hash", 0, 0, 'h' }, - 272 : { "speed-test", 0, 0, 'T' }, /* undocumented speed test command */ - 273 : { "gen-conf", 1, 0, 'C' }, - 274 : { "verbose", 0, 0, 'v' }, - 275 : { "quiet", 0, 0, 'q' }, /* undocumented quiet option */ - 276 : { "gui", 0, 0, 'G' }, /* undocumented GUI interface option */ - 277 : { "help", 0, 0, 'H' }, - 278 : { "version", 0, 0, 'V' }, - 279 : - 280 : /* The following are test specific options, DO NOT USE! */ - 281 : - 282 : /* After syncing, do not write the new content file */ - 283 : { "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC }, - 284 : - 285 : /* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */ - 286 : { "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE }, - 287 : - 288 : /* Exit with failure if after check/fix there ARE NOT recoverable errors. */ - 289 : { "test-expect-recoverable", 0, 0, OPT_TEST_EXPECT_RECOVERABLE }, - 290 : - 291 : /* Skip the initial self test */ - 292 : { "test-skip-self", 0, 0, OPT_TEST_SKIP_SELF }, - 293 : - 294 : /* Skip the initial sign check when reading the content file */ - 295 : { "test-skip-sign", 0, 0, OPT_TEST_SKIP_SIGN }, - 296 : - 297 : /* Skip the fallocate() when growing the parity files */ - 298 : { "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE }, - 299 : - 300 : /* Skip the sequential hint when reading files */ - 301 : { "test-skip-sequential", 0, 0, OPT_TEST_SKIP_SEQUENTIAL }, - 302 : - 303 : /* Skip the device check */ - 304 : { "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE }, - 305 : - 306 : /* Force Murmur3 hash */ - 307 : { "test-force-murmur3", 0, 0, OPT_TEST_FORCE_MURMUR3 }, - 308 : - 309 : /* Force Spooky2 hash */ - 310 : { "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 }, - 311 : - 312 : /* Skip the use of lock file */ - 313 : { "test-skip-lock", 0, 0, OPT_TEST_SKIP_LOCK }, - 314 : - 315 : /* Force a sort order for files */ - 316 : { "test-force-order-physical", 0, 0, OPT_TEST_FORCE_ORDER_PHYSICAL }, - 317 : { "test-force-order-inode", 0, 0, OPT_TEST_FORCE_ORDER_INODE }, - 318 : { "test-force-order-alpha", 0, 0, OPT_TEST_FORCE_ORDER_ALPHA }, - 319 : { "test-force-order-dir", 0, 0, OPT_TEST_FORCE_ORDER_DIR }, - 320 : - 321 : /* Force scrub of the specified number of blocks */ - 322 : { "test-force-scrub-at", 1, 0, OPT_TEST_FORCE_SCRUB_AT }, - 323 : - 324 : /* Force scrub of all the even blocks. This is really for testing, don't try it */ - 325 : { "test-force-scrub-even", 0, 0, OPT_TEST_FORCE_SCRUB_EVEN }, - 326 : - 327 : /* Force write of the content file even if no modification is done */ - 328 : { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE }, - 329 : - 330 : /* Relax the checks done at the content file */ - 331 : { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK }, - 332 : - 333 : /* Skip the parity access */ - 334 : { "test-skip-parity-access", 0, 0, OPT_TEST_SKIP_PARITY_ACCESS }, - 335 : - 336 : /* Exit generic failure */ - 337 : { "test-expect-failure", 0, 0, OPT_TEST_EXPECT_FAILURE }, - 338 : - 339 : /* Exit generic need sync */ - 340 : { "test-expect-need-sync", 0, 0, OPT_TEST_EXPECT_NEED_SYNC }, - 341 : - 342 : /* Run some command after loading the state and before the command */ - 343 : { "test-run", 1, 0, OPT_TEST_RUN }, - 344 : - 345 : /* Use the FindFirst/Next approach in Windows to list files */ - 346 : { "test-force-scan-winfind", 0, 0, OPT_TEST_FORCE_SCAN_WINFIND }, - 347 : - 348 : /* Alternative import working by data */ - 349 : { "test-import-content", 1, 0, OPT_TEST_IMPORT_CONTENT }, - 350 : - 351 : /* Force immediate progress state update */ - 352 : { "test-force-progress", 0, 0, OPT_TEST_FORCE_PROGRESS }, - 353 : - 354 : /* Skip the disk access */ - 355 : { "test-skip-disk-access", 0, 0, OPT_TEST_SKIP_DISK_ACCESS }, - 356 : - 357 : /* Force autosave at the specified block */ - 358 : { "test-force-autosave-at", 1, 0, OPT_TEST_FORCE_AUTOSAVE_AT }, - 359 : - 360 : /* Fake device data */ - 361 : { "test-fake-device", 0, 0, OPT_TEST_FAKE_DEVICE }, - 362 : - 363 : { 0, 0, 0, 0 } - 364 : }; - 365 : #endif + 248 : #define OPT_NO_WARNINGS 286 + 249 : #define OPT_TEST_FAKE_UUID 287 + 250 : #define OPT_TEST_MATCH_FIRST_UUID 288 + 251 : #define OPT_TEST_FORCE_PARITY_UPDATE 289 + 252 : + 253 : #if HAVE_GETOPT_LONG + 254 : struct option long_options[] = { + 255 : { "conf", 1, 0, 'c' }, + 256 : { "filter", 1, 0, 'f' }, + 257 : { "filter-disk", 1, 0, 'd' }, + 258 : { "filter-missing", 0, 0, 'm' }, + 259 : { "filter-error", 0, 0, 'e' }, + 260 : { "percentage", 1, 0, 'p' }, /* legacy name for --plan */ + 261 : { "plan", 1, 0, 'p' }, + 262 : { "older-than", 1, 0, 'o' }, + 263 : { "start", 1, 0, 'S' }, + 264 : { "count", 1, 0, 'B' }, + 265 : { "error-limit", 1, 0, 'L' }, + 266 : { "import", 1, 0, 'i' }, + 267 : { "log", 1, 0, 'l' }, + 268 : { "force-zero", 0, 0, 'Z' }, + 269 : { "force-empty", 0, 0, 'E' }, + 270 : { "force-uuid", 0, 0, 'U' }, + 271 : { "force-device", 0, 0, 'D' }, + 272 : { "force-nocopy", 0, 0, 'N' }, + 273 : { "force-full", 0, 0, 'F' }, + 274 : { "audit-only", 0, 0, 'a' }, + 275 : { "pre-hash", 0, 0, 'h' }, + 276 : { "speed-test", 0, 0, 'T' }, /* undocumented speed test command */ + 277 : { "gen-conf", 1, 0, 'C' }, + 278 : { "verbose", 0, 0, 'v' }, + 279 : { "quiet", 0, 0, 'q' }, /* undocumented quiet option */ + 280 : { "gui", 0, 0, 'G' }, /* undocumented GUI interface option */ + 281 : { "help", 0, 0, 'H' }, + 282 : { "version", 0, 0, 'V' }, + 283 : + 284 : /* The following are test specific options, DO NOT USE! */ + 285 : + 286 : /* After syncing, do not write the new content file */ + 287 : { "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC }, + 288 : + 289 : /* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */ + 290 : { "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE }, + 291 : + 292 : /* Exit with failure if after check/fix there ARE NOT recoverable errors. */ + 293 : { "test-expect-recoverable", 0, 0, OPT_TEST_EXPECT_RECOVERABLE }, + 294 : + 295 : /* Skip the initial self test */ + 296 : { "test-skip-self", 0, 0, OPT_TEST_SKIP_SELF }, + 297 : + 298 : /* Skip the initial sign check when reading the content file */ + 299 : { "test-skip-sign", 0, 0, OPT_TEST_SKIP_SIGN }, + 300 : + 301 : /* Skip the fallocate() when growing the parity files */ + 302 : { "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE }, + 303 : + 304 : /* Skip the sequential hint when reading files */ + 305 : { "test-skip-sequential", 0, 0, OPT_TEST_SKIP_SEQUENTIAL }, + 306 : + 307 : /* Skip the device check */ + 308 : { "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE }, + 309 : + 310 : /* Force Murmur3 hash */ + 311 : { "test-force-murmur3", 0, 0, OPT_TEST_FORCE_MURMUR3 }, + 312 : + 313 : /* Force Spooky2 hash */ + 314 : { "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 }, + 315 : + 316 : /* Skip the use of lock file */ + 317 : { "test-skip-lock", 0, 0, OPT_TEST_SKIP_LOCK }, + 318 : + 319 : /* Force a sort order for files */ + 320 : { "test-force-order-physical", 0, 0, OPT_TEST_FORCE_ORDER_PHYSICAL }, + 321 : { "test-force-order-inode", 0, 0, OPT_TEST_FORCE_ORDER_INODE }, + 322 : { "test-force-order-alpha", 0, 0, OPT_TEST_FORCE_ORDER_ALPHA }, + 323 : { "test-force-order-dir", 0, 0, OPT_TEST_FORCE_ORDER_DIR }, + 324 : + 325 : /* Force scrub of the specified number of blocks */ + 326 : { "test-force-scrub-at", 1, 0, OPT_TEST_FORCE_SCRUB_AT }, + 327 : + 328 : /* Force scrub of all the even blocks. This is really for testing, don't try it */ + 329 : { "test-force-scrub-even", 0, 0, OPT_TEST_FORCE_SCRUB_EVEN }, + 330 : + 331 : /* Force write of the content file even if no modification is done */ + 332 : { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE }, + 333 : + 334 : /* Relax the checks done at the content file */ + 335 : { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK }, + 336 : + 337 : /* Skip the parity access */ + 338 : { "test-skip-parity-access", 0, 0, OPT_TEST_SKIP_PARITY_ACCESS }, + 339 : + 340 : /* Exit generic failure */ + 341 : { "test-expect-failure", 0, 0, OPT_TEST_EXPECT_FAILURE }, + 342 : + 343 : /* Exit generic need sync */ + 344 : { "test-expect-need-sync", 0, 0, OPT_TEST_EXPECT_NEED_SYNC }, + 345 : + 346 : /* Run some command after loading the state and before the command */ + 347 : { "test-run", 1, 0, OPT_TEST_RUN }, + 348 : + 349 : /* Use the FindFirst/Next approach in Windows to list files */ + 350 : { "test-force-scan-winfind", 0, 0, OPT_TEST_FORCE_SCAN_WINFIND }, + 351 : + 352 : /* Alternative import working by data */ + 353 : { "test-import-content", 1, 0, OPT_TEST_IMPORT_CONTENT }, + 354 : + 355 : /* Force immediate progress state update */ + 356 : { "test-force-progress", 0, 0, OPT_TEST_FORCE_PROGRESS }, + 357 : + 358 : /* Skip the disk access */ + 359 : { "test-skip-disk-access", 0, 0, OPT_TEST_SKIP_DISK_ACCESS }, + 360 : + 361 : /* Force autosave at the specified block */ + 362 : { "test-force-autosave-at", 1, 0, OPT_TEST_FORCE_AUTOSAVE_AT }, + 363 : + 364 : /* Fake device data */ + 365 : { "test-fake-device", 0, 0, OPT_TEST_FAKE_DEVICE }, 366 : - 367 : #define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFahTC:vqHVG" - 368 : - 369 : volatile int global_interrupt = 0; - 370 : - 371 : /* LCOV_EXCL_START */ - 372 : void signal_handler(int signum) - 373 : { - 374 : (void)signum; + 367 : /* Disable annoying warnings */ + 368 : { "no-warnings", 0, 0, OPT_NO_WARNINGS }, + 369 : + 370 : /* Fake UUID */ + 371 : { "test-fake-uuid", 0, 0, OPT_TEST_FAKE_UUID }, + 372 : + 373 : /* Match first UUID */ + 374 : { "test-match-first-uuid", 0, 0, OPT_TEST_MATCH_FIRST_UUID }, 375 : - 376 : /* report the request of interruption */ - 377 : global_interrupt = 1; - 378 : } - 379 : /* LCOV_EXCL_STOP */ - 380 : - 381 208 : void signal_init(void) - 382 : { - 383 : #if HAVE_SIGACTION - 384 : struct sigaction sa; - 385 : - 386 208 : sa.sa_handler = signal_handler; - 387 208 : sigemptyset(&sa.sa_mask); - 388 : - 389 : /* use the SA_RESTART to automatically restart interrupted system calls */ - 390 208 : sa.sa_flags = SA_RESTART; + 376 : /* Force parity update even if all the data is not changed */ + 377 : { "test-force-parity-update", 0, 0, OPT_TEST_FORCE_PARITY_UPDATE }, + 378 : + 379 : { 0, 0, 0, 0 } + 380 : }; + 381 : #endif + 382 : + 383 : #define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFahTC:vqHVG" + 384 : + 385 : volatile int global_interrupt = 0; + 386 : + 387 : /* LCOV_EXCL_START */ + 388 : void signal_handler(int signum) + 389 : { + 390 : (void)signum; 391 : - 392 208 : sigaction(SIGHUP, &sa, 0); - 393 208 : sigaction(SIGTERM, &sa, 0); - 394 208 : sigaction(SIGINT, &sa, 0); - 395 208 : sigaction(SIGQUIT, &sa, 0); - 396 : #else - 397 : signal(SIGINT, signal_handler); - 398 : #endif - 399 208 : } - 400 : - 401 : #define OPERATION_DIFF 0 - 402 : #define OPERATION_SYNC 1 - 403 : #define OPERATION_CHECK 2 - 404 : #define OPERATION_FIX 3 - 405 : #define OPERATION_DRY 4 - 406 : #define OPERATION_DUP 5 - 407 : #define OPERATION_LIST 6 - 408 : #define OPERATION_POOL 7 - 409 : #define OPERATION_REHASH 8 - 410 : #define OPERATION_SCRUB 9 - 411 : #define OPERATION_STATUS 10 - 412 : #define OPERATION_REWRITE 11 - 413 : #define OPERATION_READ 12 - 414 : #define OPERATION_NANO 13 - 415 : #define OPERATION_SPINUP 14 - 416 : #define OPERATION_SPINDOWN 15 - 417 : #define OPERATION_DEVICES 16 - 418 : #define OPERATION_SMART 17 - 419 : - 420 257 : int main(int argc, char* argv[]) - 421 : { - 422 : int c; - 423 : struct snapraid_option opt; - 424 : char conf[PATH_MAX]; - 425 : struct snapraid_state state; - 426 : int operation; - 427 : block_off_t blockstart; - 428 : block_off_t blockcount; - 429 : int ret; - 430 : tommy_list filterlist_file; - 431 : tommy_list filterlist_disk; - 432 : int filter_missing; - 433 : int filter_error; - 434 : int plan; - 435 : int olderthan; - 436 : char* e; - 437 : const char* command; - 438 : const char* import_timestamp; - 439 : const char* import_content; - 440 : const char* log_file; - 441 : int lock; - 442 : const char* gen_conf; - 443 : const char* run; - 444 : int speedtest; - 445 : int period; - 446 : time_t t; - 447 : struct tm* tm; - 448 : int i; - 449 : - 450 : /* defaults */ - 451 257 : config(conf, sizeof(conf), argv[0]); - 452 257 : memset(&opt, 0, sizeof(opt)); - 453 257 : opt.io_error_limit = 100; - 454 257 : blockstart = 0; - 455 257 : blockcount = 0; - 456 257 : tommy_list_init(&filterlist_file); - 457 257 : tommy_list_init(&filterlist_disk); - 458 257 : period = 1000; - 459 257 : filter_missing = 0; - 460 257 : filter_error = 0; - 461 257 : plan = SCRUB_AUTO; - 462 257 : olderthan = SCRUB_AUTO; - 463 257 : import_timestamp = 0; - 464 257 : import_content = 0; - 465 257 : log_file = 0; - 466 257 : lock = 0; - 467 257 : gen_conf = 0; - 468 257 : speedtest = 0; - 469 257 : run = 0; - 470 : - 471 257 : opterr = 0; - 472 2722 : while ((c = - 473 : #if HAVE_GETOPT_LONG - 474 : getopt_long(argc, argv, OPTIONS, long_options, 0)) - 475 : #else - 476 : getopt(argc, argv, OPTIONS)) - 477 : #endif - 478 : != EOF) { - 479 2213 : switch (c) { - 480 : case 'c' : - 481 250 : pathimport(conf, sizeof(conf), optarg); - 482 250 : break; - 483 : case 'f' : { - 484 6 : struct snapraid_filter* filter = filter_alloc_file(1, optarg); - 485 6 : if (!filter) { - 486 : /* LCOV_EXCL_START */ - 487 : log_fatal("Invalid filter specification '%s'\n", optarg); - 488 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); - 489 : exit(EXIT_FAILURE); - 490 : /* LCOV_EXCL_STOP */ - 491 : } - 492 3 : tommy_list_insert_tail(&filterlist_file, &filter->node, filter); - 493 3 : } break; - 494 : case 'd' : { - 495 8 : struct snapraid_filter* filter = filter_alloc_disk(1, optarg); - 496 8 : if (!filter) { - 497 : /* LCOV_EXCL_START */ - 498 : log_fatal("Invalid filter specification '%s'\n", optarg); - 499 : exit(EXIT_FAILURE); - 500 : /* LCOV_EXCL_STOP */ - 501 : } - 502 8 : tommy_list_insert_tail(&filterlist_disk, &filter->node, filter); - 503 8 : } break; - 504 : case 'm' : - 505 2 : filter_missing = 1; - 506 2 : opt.expected_missing = 1; - 507 2 : break; - 508 : case 'e' : - 509 : /* when processing only error, we filter both files and blocks */ - 510 : /* and we apply fixes only to synced ones */ - 511 2 : filter_error = 1; - 512 2 : opt.badonly = 1; - 513 2 : opt.syncedonly = 1; - 514 2 : break; - 515 : case 'p' : - 516 5 : if (strcmp(optarg, "bad") == 0) { - 517 1 : plan = SCRUB_BAD; - 518 4 : } else if (strcmp(optarg, "new") == 0) { - 519 1 : plan = SCRUB_NEW; - 520 3 : } else if (strcmp(optarg, "full") == 0) { - 521 2 : plan = SCRUB_FULL; - 522 : } else { - 523 1 : plan = strtoul(optarg, &e, 10); - 524 1 : if (!e || *e || plan > 100) { - 525 : /* LCOV_EXCL_START */ - 526 : log_fatal("Invalid plan/percentage '%s'\n", optarg); - 527 : exit(EXIT_FAILURE); - 528 : /* LCOV_EXCL_STOP */ - 529 : } - 530 : } - 531 5 : break; - 532 : case 'o' : - 533 1 : olderthan = strtoul(optarg, &e, 10); - 534 1 : if (!e || *e || olderthan > 1000) { - 535 : /* LCOV_EXCL_START */ - 536 : log_fatal("Invalid number of days '%s'\n", optarg); - 537 : exit(EXIT_FAILURE); - 538 : /* LCOV_EXCL_STOP */ - 539 : } - 540 1 : break; - 541 : case 'S' : - 542 2 : blockstart = strtoul(optarg, &e, 0); - 543 2 : if (!e || *e) { - 544 : /* LCOV_EXCL_START */ - 545 : log_fatal("Invalid start position '%s'\n", optarg); - 546 : exit(EXIT_FAILURE); - 547 : /* LCOV_EXCL_STOP */ - 548 : } - 549 2 : break; - 550 : case 'B' : - 551 7 : blockcount = strtoul(optarg, &e, 0); - 552 7 : if (!e || *e) { - 553 : /* LCOV_EXCL_START */ - 554 : log_fatal("Invalid count number '%s'\n", optarg); - 555 : exit(EXIT_FAILURE); - 556 : /* LCOV_EXCL_STOP */ - 557 : } - 558 7 : break; - 559 : case 'L' : - 560 0 : opt.io_error_limit = strtoul(optarg, &e, 0); - 561 0 : if (!e || *e) { - 562 : /* LCOV_EXCL_START */ - 563 : log_fatal("Invalid error limit number '%s'\n", optarg); - 564 : exit(EXIT_FAILURE); - 565 : /* LCOV_EXCL_STOP */ - 566 : } - 567 0 : break; - 568 : case 'i' : - 569 1 : if (import_timestamp) { - 570 : /* LCOV_EXCL_START */ - 571 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp); - 572 : exit(EXIT_FAILURE); - 573 : /* LCOV_EXCL_STOP */ - 574 : } - 575 1 : import_timestamp = optarg; - 576 1 : break; - 577 : case OPT_TEST_IMPORT_CONTENT : - 578 1 : if (import_content) { - 579 : /* LCOV_EXCL_START */ - 580 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content); - 581 : exit(EXIT_FAILURE); - 582 : /* LCOV_EXCL_STOP */ - 583 : } - 584 1 : import_content = optarg; - 585 1 : break; - 586 : case 'l' : - 587 77 : if (log_file) { - 588 : /* LCOV_EXCL_START */ - 589 : log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file); - 590 : exit(EXIT_FAILURE); - 591 : /* LCOV_EXCL_STOP */ - 592 : } - 593 77 : log_file = optarg; - 594 77 : break; - 595 : case 'Z' : - 596 0 : opt.force_zero = 1; - 597 0 : break; - 598 : case 'E' : - 599 5 : opt.force_empty = 1; - 600 5 : break; - 601 : case 'U' : - 602 0 : opt.force_uuid = 1; - 603 0 : break; - 604 : case 'D' : - 605 1 : opt.force_device = 1; - 606 1 : break; - 607 : case 'N' : - 608 1 : opt.force_nocopy = 1; - 609 1 : break; - 610 : case 'F' : - 611 1 : opt.force_full = 1; - 612 1 : break; - 613 : case 'a' : - 614 6 : opt.auditonly = 1; - 615 6 : break; - 616 : case 'h' : - 617 7 : opt.prehash = 1; - 618 7 : break; - 619 : case 'v' : - 620 23 : ++msg_level; - 621 23 : break; - 622 : case 'q' : - 623 681 : --msg_level; - 624 681 : break; - 625 : case 'G' : - 626 23 : opt.gui = 1; - 627 23 : break; - 628 : case 'H' : - 629 1 : usage(); - 630 1 : exit(EXIT_SUCCESS); - 631 : case 'V' : - 632 1 : version(); - 633 1 : exit(EXIT_SUCCESS); - 634 : case 'T' : - 635 4 : speedtest = 1; - 636 4 : break; - 637 : case 'C' : - 638 1 : gen_conf = optarg; - 639 1 : break; - 640 : case OPT_TEST_KILL_AFTER_SYNC : - 641 9 : opt.kill_after_sync = 1; - 642 9 : break; - 643 : case OPT_TEST_EXPECT_UNRECOVERABLE : - 644 13 : opt.expect_unrecoverable = 1; - 645 13 : break; - 646 : case OPT_TEST_EXPECT_RECOVERABLE : - 647 23 : opt.expect_recoverable = 1; - 648 23 : break; - 649 : case OPT_TEST_SKIP_SELF : - 650 250 : opt.skip_self = 1; - 651 250 : break; - 652 : case OPT_TEST_SKIP_SIGN : - 653 0 : opt.skip_sign = 1; - 654 0 : break; - 655 : case OPT_TEST_SKIP_FALLOCATE : - 656 1 : opt.skip_fallocate = 1; - 657 1 : break; - 658 : case OPT_TEST_SKIP_SEQUENTIAL : - 659 1 : opt.skip_sequential = 1; - 660 1 : break; - 661 : case OPT_TEST_SKIP_DEVICE : - 662 257 : opt.skip_device = 1; - 663 257 : period = 50; /* reduce period of the speed test */ - 664 257 : break; - 665 : case OPT_TEST_SKIP_CONTENT_CHECK : - 666 0 : opt.skip_content_check = 1; - 667 0 : break; - 668 : case OPT_TEST_SKIP_PARITY_ACCESS : - 669 0 : opt.skip_parity_access = 1; + 392 : /* report the request of interruption */ + 393 : global_interrupt = 1; + 394 : } + 395 : /* LCOV_EXCL_STOP */ + 396 : + 397 216 : void signal_init(void) + 398 : { + 399 : #if HAVE_SIGACTION + 400 : struct sigaction sa; + 401 : + 402 216 : sa.sa_handler = signal_handler; + 403 216 : sigemptyset(&sa.sa_mask); + 404 : + 405 : /* use the SA_RESTART to automatically restart interrupted system calls */ + 406 216 : sa.sa_flags = SA_RESTART; + 407 : + 408 216 : sigaction(SIGHUP, &sa, 0); + 409 216 : sigaction(SIGTERM, &sa, 0); + 410 216 : sigaction(SIGINT, &sa, 0); + 411 216 : sigaction(SIGQUIT, &sa, 0); + 412 : #else + 413 : signal(SIGINT, signal_handler); + 414 : #endif + 415 216 : } + 416 : + 417 : #define OPERATION_DIFF 0 + 418 : #define OPERATION_SYNC 1 + 419 : #define OPERATION_CHECK 2 + 420 : #define OPERATION_FIX 3 + 421 : #define OPERATION_DRY 4 + 422 : #define OPERATION_DUP 5 + 423 : #define OPERATION_LIST 6 + 424 : #define OPERATION_POOL 7 + 425 : #define OPERATION_REHASH 8 + 426 : #define OPERATION_SCRUB 9 + 427 : #define OPERATION_STATUS 10 + 428 : #define OPERATION_REWRITE 11 + 429 : #define OPERATION_READ 12 + 430 : #define OPERATION_NANO 13 + 431 : #define OPERATION_SPINUP 14 + 432 : #define OPERATION_SPINDOWN 15 + 433 : #define OPERATION_DEVICES 16 + 434 : #define OPERATION_SMART 17 + 435 : + 436 265 : int main(int argc, char* argv[]) + 437 : { + 438 : int c; + 439 : struct snapraid_option opt; + 440 : char conf[PATH_MAX]; + 441 : struct snapraid_state state; + 442 : int operation; + 443 : block_off_t blockstart; + 444 : block_off_t blockcount; + 445 : int ret; + 446 : tommy_list filterlist_file; + 447 : tommy_list filterlist_disk; + 448 : int filter_missing; + 449 : int filter_error; + 450 : int plan; + 451 : int olderthan; + 452 : char* e; + 453 : const char* command; + 454 : const char* import_timestamp; + 455 : const char* import_content; + 456 : const char* log_file; + 457 : int lock; + 458 : const char* gen_conf; + 459 : const char* run; + 460 : int speedtest; + 461 : int period; + 462 : time_t t; + 463 : struct tm* tm; + 464 : int i; + 465 : + 466 : /* defaults */ + 467 265 : config(conf, sizeof(conf), argv[0]); + 468 265 : memset(&opt, 0, sizeof(opt)); + 469 265 : opt.io_error_limit = 100; + 470 265 : blockstart = 0; + 471 265 : blockcount = 0; + 472 265 : tommy_list_init(&filterlist_file); + 473 265 : tommy_list_init(&filterlist_disk); + 474 265 : period = 1000; + 475 265 : filter_missing = 0; + 476 265 : filter_error = 0; + 477 265 : plan = SCRUB_AUTO; + 478 265 : olderthan = SCRUB_AUTO; + 479 265 : import_timestamp = 0; + 480 265 : import_content = 0; + 481 265 : log_file = 0; + 482 265 : lock = 0; + 483 265 : gen_conf = 0; + 484 265 : speedtest = 0; + 485 265 : run = 0; + 486 : + 487 265 : opterr = 0; + 488 2809 : while ((c = + 489 : #if HAVE_GETOPT_LONG + 490 : getopt_long(argc, argv, OPTIONS, long_options, 0)) + 491 : #else + 492 : getopt(argc, argv, OPTIONS)) + 493 : #endif + 494 : != EOF) { + 495 2284 : switch (c) { + 496 : case 'c' : + 497 258 : pathimport(conf, sizeof(conf), optarg); + 498 258 : break; + 499 : case 'f' : { + 500 6 : struct snapraid_filter* filter = filter_alloc_file(1, optarg); + 501 6 : if (!filter) { + 502 : /* LCOV_EXCL_START */ + 503 : log_fatal("Invalid filter specification '%s'\n", optarg); + 504 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + 505 : exit(EXIT_FAILURE); + 506 : /* LCOV_EXCL_STOP */ + 507 : } + 508 3 : tommy_list_insert_tail(&filterlist_file, &filter->node, filter); + 509 3 : } break; + 510 : case 'd' : { + 511 8 : struct snapraid_filter* filter = filter_alloc_disk(1, optarg); + 512 8 : if (!filter) { + 513 : /* LCOV_EXCL_START */ + 514 : log_fatal("Invalid filter specification '%s'\n", optarg); + 515 : exit(EXIT_FAILURE); + 516 : /* LCOV_EXCL_STOP */ + 517 : } + 518 8 : tommy_list_insert_tail(&filterlist_disk, &filter->node, filter); + 519 8 : } break; + 520 : case 'm' : + 521 2 : filter_missing = 1; + 522 2 : opt.expected_missing = 1; + 523 2 : break; + 524 : case 'e' : + 525 : /* when processing only error, we filter both files and blocks */ + 526 : /* and we apply fixes only to synced ones */ + 527 2 : filter_error = 1; + 528 2 : opt.badonly = 1; + 529 2 : opt.syncedonly = 1; + 530 2 : break; + 531 : case 'p' : + 532 5 : if (strcmp(optarg, "bad") == 0) { + 533 1 : plan = SCRUB_BAD; + 534 4 : } else if (strcmp(optarg, "new") == 0) { + 535 1 : plan = SCRUB_NEW; + 536 3 : } else if (strcmp(optarg, "full") == 0) { + 537 2 : plan = SCRUB_FULL; + 538 : } else { + 539 1 : plan = strtoul(optarg, &e, 10); + 540 1 : if (!e || *e || plan > 100) { + 541 : /* LCOV_EXCL_START */ + 542 : log_fatal("Invalid plan/percentage '%s'\n", optarg); + 543 : exit(EXIT_FAILURE); + 544 : /* LCOV_EXCL_STOP */ + 545 : } + 546 : } + 547 5 : break; + 548 : case 'o' : + 549 1 : olderthan = strtoul(optarg, &e, 10); + 550 1 : if (!e || *e || olderthan > 1000) { + 551 : /* LCOV_EXCL_START */ + 552 : log_fatal("Invalid number of days '%s'\n", optarg); + 553 : exit(EXIT_FAILURE); + 554 : /* LCOV_EXCL_STOP */ + 555 : } + 556 1 : break; + 557 : case 'S' : + 558 2 : blockstart = strtoul(optarg, &e, 0); + 559 2 : if (!e || *e) { + 560 : /* LCOV_EXCL_START */ + 561 : log_fatal("Invalid start position '%s'\n", optarg); + 562 : exit(EXIT_FAILURE); + 563 : /* LCOV_EXCL_STOP */ + 564 : } + 565 2 : break; + 566 : case 'B' : + 567 7 : blockcount = strtoul(optarg, &e, 0); + 568 7 : if (!e || *e) { + 569 : /* LCOV_EXCL_START */ + 570 : log_fatal("Invalid count number '%s'\n", optarg); + 571 : exit(EXIT_FAILURE); + 572 : /* LCOV_EXCL_STOP */ + 573 : } + 574 7 : break; + 575 : case 'L' : + 576 0 : opt.io_error_limit = strtoul(optarg, &e, 0); + 577 0 : if (!e || *e) { + 578 : /* LCOV_EXCL_START */ + 579 : log_fatal("Invalid error limit number '%s'\n", optarg); + 580 : exit(EXIT_FAILURE); + 581 : /* LCOV_EXCL_STOP */ + 582 : } + 583 0 : break; + 584 : case 'i' : + 585 1 : if (import_timestamp) { + 586 : /* LCOV_EXCL_START */ + 587 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp); + 588 : exit(EXIT_FAILURE); + 589 : /* LCOV_EXCL_STOP */ + 590 : } + 591 1 : import_timestamp = optarg; + 592 1 : break; + 593 : case OPT_TEST_IMPORT_CONTENT : + 594 1 : if (import_content) { + 595 : /* LCOV_EXCL_START */ + 596 : log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content); + 597 : exit(EXIT_FAILURE); + 598 : /* LCOV_EXCL_STOP */ + 599 : } + 600 1 : import_content = optarg; + 601 1 : break; + 602 : case 'l' : + 603 77 : if (log_file) { + 604 : /* LCOV_EXCL_START */ + 605 : log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file); + 606 : exit(EXIT_FAILURE); + 607 : /* LCOV_EXCL_STOP */ + 608 : } + 609 77 : log_file = optarg; + 610 77 : break; + 611 : case 'Z' : + 612 0 : opt.force_zero = 1; + 613 0 : break; + 614 : case 'E' : + 615 6 : opt.force_empty = 1; + 616 6 : break; + 617 : case 'U' : + 618 0 : opt.force_uuid = 1; + 619 0 : break; + 620 : case 'D' : + 621 1 : opt.force_device = 1; + 622 1 : break; + 623 : case 'N' : + 624 1 : opt.force_nocopy = 1; + 625 1 : break; + 626 : case 'F' : + 627 2 : opt.force_full = 1; + 628 2 : break; + 629 : case 'a' : + 630 6 : opt.auditonly = 1; + 631 6 : break; + 632 : case 'h' : + 633 7 : opt.prehash = 1; + 634 7 : break; + 635 : case 'v' : + 636 23 : ++msg_level; + 637 23 : break; + 638 : case 'q' : + 639 705 : --msg_level; + 640 705 : break; + 641 : case 'G' : + 642 23 : opt.gui = 1; + 643 23 : break; + 644 : case 'H' : + 645 1 : usage(); + 646 1 : exit(EXIT_SUCCESS); + 647 : case 'V' : + 648 1 : version(); + 649 1 : exit(EXIT_SUCCESS); + 650 : case 'T' : + 651 4 : speedtest = 1; + 652 4 : break; + 653 : case 'C' : + 654 1 : gen_conf = optarg; + 655 1 : break; + 656 : case OPT_TEST_KILL_AFTER_SYNC : + 657 10 : opt.kill_after_sync = 1; + 658 10 : break; + 659 : case OPT_TEST_EXPECT_UNRECOVERABLE : + 660 13 : opt.expect_unrecoverable = 1; + 661 13 : break; + 662 : case OPT_TEST_EXPECT_RECOVERABLE : + 663 23 : opt.expect_recoverable = 1; + 664 23 : break; + 665 : case OPT_TEST_SKIP_SELF : + 666 258 : opt.skip_self = 1; + 667 258 : break; + 668 : case OPT_TEST_SKIP_SIGN : + 669 0 : opt.skip_sign = 1; 670 0 : break; - 671 : case OPT_TEST_SKIP_DISK_ACCESS : - 672 0 : opt.skip_disk_access = 1; - 673 0 : break; - 674 : case OPT_TEST_FORCE_MURMUR3 : - 675 1 : opt.force_murmur3 = 1; + 671 : case OPT_TEST_SKIP_FALLOCATE : + 672 1 : opt.skip_fallocate = 1; + 673 1 : break; + 674 : case OPT_TEST_SKIP_SEQUENTIAL : + 675 1 : opt.skip_sequential = 1; 676 1 : break; - 677 : case OPT_TEST_FORCE_SPOOKY2 : - 678 1 : opt.force_spooky2 = 1; - 679 1 : break; - 680 : case OPT_TEST_SKIP_LOCK : - 681 0 : opt.skip_lock = 1; - 682 0 : break; - 683 : case OPT_TEST_FORCE_ORDER_PHYSICAL : - 684 2 : opt.force_order = SORT_PHYSICAL; - 685 2 : break; - 686 : case OPT_TEST_FORCE_ORDER_INODE : - 687 0 : opt.force_order = SORT_INODE; - 688 0 : break; - 689 : case OPT_TEST_FORCE_ORDER_ALPHA : - 690 248 : opt.force_order = SORT_ALPHA; - 691 248 : break; - 692 : case OPT_TEST_FORCE_ORDER_DIR : - 693 0 : opt.force_order = SORT_DIR; - 694 0 : break; - 695 : case OPT_TEST_FORCE_SCRUB_AT : - 696 4 : opt.force_scrub_at = atoi(optarg); - 697 4 : break; - 698 : case OPT_TEST_FORCE_SCRUB_EVEN : - 699 1 : opt.force_scrub_even = 1; - 700 1 : break; - 701 : case OPT_TEST_FORCE_CONTENT_WRITE : - 702 0 : opt.force_content_write = 1; - 703 0 : break; - 704 : case OPT_TEST_EXPECT_FAILURE : - 705 : /* invert the exit codes */ - 706 19 : exit_success = 1; - 707 19 : exit_failure = 0; - 708 19 : break; - 709 : case OPT_TEST_EXPECT_NEED_SYNC : - 710 : /* invert the exit codes */ - 711 6 : exit_success = 1; - 712 6 : exit_sync_needed = 0; - 713 6 : break; - 714 : case OPT_TEST_RUN : - 715 10 : run = optarg; - 716 10 : break; - 717 : case OPT_TEST_FORCE_SCAN_WINFIND : - 718 0 : opt.force_scan_winfind = 1; + 677 : case OPT_TEST_SKIP_DEVICE : + 678 265 : opt.skip_device = 1; + 679 265 : period = 50; /* reduce period of the speed test */ + 680 265 : break; + 681 : case OPT_TEST_SKIP_CONTENT_CHECK : + 682 0 : opt.skip_content_check = 1; + 683 0 : break; + 684 : case OPT_TEST_SKIP_PARITY_ACCESS : + 685 0 : opt.skip_parity_access = 1; + 686 0 : break; + 687 : case OPT_TEST_SKIP_DISK_ACCESS : + 688 0 : opt.skip_disk_access = 1; + 689 0 : break; + 690 : case OPT_TEST_FORCE_MURMUR3 : + 691 1 : opt.force_murmur3 = 1; + 692 1 : break; + 693 : case OPT_TEST_FORCE_SPOOKY2 : + 694 1 : opt.force_spooky2 = 1; + 695 1 : break; + 696 : case OPT_TEST_SKIP_LOCK : + 697 0 : opt.skip_lock = 1; + 698 0 : break; + 699 : case OPT_TEST_FORCE_ORDER_PHYSICAL : + 700 2 : opt.force_order = SORT_PHYSICAL; + 701 2 : break; + 702 : case OPT_TEST_FORCE_ORDER_INODE : + 703 0 : opt.force_order = SORT_INODE; + 704 0 : break; + 705 : case OPT_TEST_FORCE_ORDER_ALPHA : + 706 256 : opt.force_order = SORT_ALPHA; + 707 256 : break; + 708 : case OPT_TEST_FORCE_ORDER_DIR : + 709 0 : opt.force_order = SORT_DIR; + 710 0 : break; + 711 : case OPT_TEST_FORCE_SCRUB_AT : + 712 4 : opt.force_scrub_at = atoi(optarg); + 713 4 : break; + 714 : case OPT_TEST_FORCE_SCRUB_EVEN : + 715 1 : opt.force_scrub_even = 1; + 716 1 : break; + 717 : case OPT_TEST_FORCE_CONTENT_WRITE : + 718 0 : opt.force_content_write = 1; 719 0 : break; - 720 : case OPT_TEST_FORCE_PROGRESS : - 721 248 : opt.force_progress = 1; - 722 248 : break; - 723 : case OPT_TEST_FORCE_AUTOSAVE_AT : - 724 1 : opt.force_autosave_at = atoi(optarg); - 725 1 : break; - 726 : case OPT_TEST_FAKE_DEVICE : - 727 1 : opt.fake_device = 1; - 728 1 : break; - 729 : default : - 730 : /* LCOV_EXCL_START */ - 731 : log_fatal("Unknown option '%c'\n", (char)c); - 732 : exit(EXIT_FAILURE); - 733 : /* LCOV_EXCL_STOP */ - 734 : } - 735 : } - 736 : - 737 252 : os_init(opt.force_scan_winfind); - 738 252 : raid_init(); - 739 252 : crc32c_init(); - 740 : - 741 252 : if (speedtest != 0) { - 742 4 : speed(period); - 743 4 : os_done(); - 744 4 : exit(EXIT_SUCCESS); - 745 : } - 746 : - 747 248 : if (gen_conf != 0) { - 748 1 : generate_configuration(gen_conf); - 749 1 : os_done(); - 750 1 : exit(EXIT_SUCCESS); - 751 : } - 752 : - 753 247 : if (optind + 1 != argc) { - 754 : /* LCOV_EXCL_START */ - 755 : usage(); - 756 : exit(EXIT_FAILURE); - 757 : /* LCOV_EXCL_STOP */ - 758 : } - 759 : - 760 247 : command = argv[optind]; - 761 247 : if (strcmp(command, "diff") == 0) { - 762 7 : operation = OPERATION_DIFF; - 763 240 : } else if (strcmp(argv[optind], "sync") == 0) { - 764 74 : operation = OPERATION_SYNC; - 765 166 : } else if (strcmp(argv[optind], "check") == 0) { - 766 75 : operation = OPERATION_CHECK; - 767 91 : } else if (strcmp(argv[optind], "fix") == 0) { - 768 46 : operation = OPERATION_FIX; - 769 45 : } else if (strcmp(argv[optind], "test-dry") == 0) { - 770 2 : operation = OPERATION_DRY; - 771 43 : } else if (strcmp(argv[optind], "dup") == 0) { - 772 3 : operation = OPERATION_DUP; - 773 40 : } else if (strcmp(argv[optind], "list") == 0) { - 774 3 : operation = OPERATION_LIST; - 775 37 : } else if (strcmp(argv[optind], "pool") == 0) { - 776 3 : operation = OPERATION_POOL; - 777 34 : } else if (strcmp(argv[optind], "rehash") == 0) { - 778 1 : operation = OPERATION_REHASH; - 779 33 : } else if (strcmp(argv[optind], "scrub") == 0) { - 780 11 : operation = OPERATION_SCRUB; - 781 22 : } else if (strcmp(argv[optind], "status") == 0) { - 782 14 : operation = OPERATION_STATUS; - 783 8 : } else if (strcmp(argv[optind], "test-rewrite") == 0) { - 784 1 : operation = OPERATION_REWRITE; - 785 7 : } else if (strcmp(argv[optind], "test-read") == 0) { - 786 1 : operation = OPERATION_READ; - 787 6 : } else if (strcmp(argv[optind], "test-nano") == 0) { - 788 1 : operation = OPERATION_NANO; - 789 5 : } else if (strcmp(argv[optind], "up") == 0) { - 790 1 : operation = OPERATION_SPINUP; - 791 4 : } else if (strcmp(argv[optind], "down") == 0) { - 792 1 : operation = OPERATION_SPINDOWN; - 793 3 : } else if (strcmp(argv[optind], "devices") == 0) { - 794 1 : operation = OPERATION_DEVICES; - 795 2 : } else if (strcmp(argv[optind], "smart") == 0) { - 796 2 : operation = OPERATION_SMART; - 797 : } else { - 798 : /* LCOV_EXCL_START */ - 799 : log_fatal("Unknown command '%s'\n", argv[optind]); - 800 : exit(EXIT_FAILURE); - 801 : /* LCOV_EXCL_STOP */ - 802 : } - 803 : - 804 : /* check options compatibility */ - 805 247 : switch (operation) { - 806 : case OPERATION_CHECK : - 807 75 : break; - 808 : default : - 809 172 : if (opt.auditonly) { - 810 : /* LCOV_EXCL_START */ - 811 : log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command); - 812 : exit(EXIT_FAILURE); - 813 : /* LCOV_EXCL_STOP */ - 814 : } - 815 : } - 816 : - 817 247 : switch (operation) { - 818 : case OPERATION_FIX : - 819 46 : break; - 820 : default : - 821 201 : if (opt.force_device) { - 822 : /* LCOV_EXCL_START */ - 823 : log_fatal("You cannot use -D, --force-device with the '%s' command\n", command); - 824 : exit(EXIT_FAILURE); - 825 : /* LCOV_EXCL_STOP */ - 826 : } - 827 : } - 828 : - 829 247 : switch (operation) { - 830 : case OPERATION_SYNC : - 831 : case OPERATION_CHECK : - 832 : case OPERATION_FIX : - 833 195 : break; - 834 : default : - 835 52 : if (opt.force_nocopy) { - 836 : /* LCOV_EXCL_START */ - 837 : log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command); - 838 : exit(EXIT_FAILURE); - 839 : /* LCOV_EXCL_STOP */ - 840 : } - 841 : } - 842 : - 843 247 : switch (operation) { - 844 : case OPERATION_SYNC : - 845 74 : break; - 846 : default : - 847 173 : if (opt.prehash) { - 848 : /* LCOV_EXCL_START */ - 849 : log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command); - 850 : exit(EXIT_FAILURE); - 851 : /* LCOV_EXCL_STOP */ - 852 : } - 853 : - 854 173 : if (opt.force_full) { - 855 : /* LCOV_EXCL_START */ - 856 : log_fatal("You cannot use -F, --force-full with the '%s' command\n", command); - 857 : exit(EXIT_FAILURE); - 858 : /* LCOV_EXCL_STOP */ - 859 : } - 860 : } - 861 : - 862 247 : if (opt.force_full && opt.force_nocopy) { - 863 : /* LCOV_EXCL_START */ - 864 : log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n"); - 865 : exit(EXIT_FAILURE); - 866 : /* LCOV_EXCL_STOP */ - 867 : } - 868 : - 869 247 : if (opt.prehash && opt.force_nocopy) { - 870 : /* LCOV_EXCL_START */ - 871 : log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n"); - 872 : exit(EXIT_FAILURE); - 873 : /* LCOV_EXCL_STOP */ - 874 : } - 875 : - 876 247 : switch (operation) { - 877 : case OPERATION_CHECK : - 878 : case OPERATION_FIX : - 879 : case OPERATION_DRY : - 880 123 : break; - 881 : default : - 882 124 : if (!tommy_list_empty(&filterlist_file)) { + 720 : case OPT_TEST_EXPECT_FAILURE : + 721 : /* invert the exit codes */ + 722 19 : exit_success = 1; + 723 19 : exit_failure = 0; + 724 19 : break; + 725 : case OPT_TEST_EXPECT_NEED_SYNC : + 726 : /* invert the exit codes */ + 727 6 : exit_success = 1; + 728 6 : exit_sync_needed = 0; + 729 6 : break; + 730 : case OPT_TEST_RUN : + 731 10 : run = optarg; + 732 10 : break; + 733 : case OPT_TEST_FORCE_SCAN_WINFIND : + 734 0 : opt.force_scan_winfind = 1; + 735 0 : break; + 736 : case OPT_TEST_FORCE_PROGRESS : + 737 256 : opt.force_progress = 1; + 738 256 : break; + 739 : case OPT_TEST_FORCE_AUTOSAVE_AT : + 740 1 : opt.force_autosave_at = atoi(optarg); + 741 1 : break; + 742 : case OPT_TEST_FAKE_DEVICE : + 743 1 : opt.fake_device = 1; + 744 1 : break; + 745 : case OPT_NO_WARNINGS : + 746 1 : opt.no_warnings = 1; + 747 1 : break; + 748 : case OPT_TEST_FAKE_UUID : + 749 1 : opt.fake_uuid = 2; + 750 1 : break; + 751 : case OPT_TEST_MATCH_FIRST_UUID : + 752 2 : opt.match_first_uuid = 1; + 753 2 : break; + 754 : case OPT_TEST_FORCE_PARITY_UPDATE : + 755 0 : opt.force_parity_update = 1; + 756 0 : break; + 757 : default : + 758 : /* LCOV_EXCL_START */ + 759 : log_fatal("Unknown option '%c'\n", (char)c); + 760 : exit(EXIT_FAILURE); + 761 : /* LCOV_EXCL_STOP */ + 762 : } + 763 : } + 764 : + 765 260 : os_init(opt.force_scan_winfind); + 766 260 : raid_init(); + 767 260 : crc32c_init(); + 768 : + 769 260 : if (speedtest != 0) { + 770 4 : speed(period); + 771 4 : os_done(); + 772 4 : exit(EXIT_SUCCESS); + 773 : } + 774 : + 775 256 : if (gen_conf != 0) { + 776 1 : generate_configuration(gen_conf); + 777 1 : os_done(); + 778 1 : exit(EXIT_SUCCESS); + 779 : } + 780 : + 781 255 : if (optind + 1 != argc) { + 782 : /* LCOV_EXCL_START */ + 783 : usage(); + 784 : exit(EXIT_FAILURE); + 785 : /* LCOV_EXCL_STOP */ + 786 : } + 787 : + 788 255 : command = argv[optind]; + 789 255 : if (strcmp(command, "diff") == 0) { + 790 7 : operation = OPERATION_DIFF; + 791 248 : } else if (strcmp(argv[optind], "sync") == 0) { + 792 82 : operation = OPERATION_SYNC; + 793 166 : } else if (strcmp(argv[optind], "check") == 0) { + 794 75 : operation = OPERATION_CHECK; + 795 91 : } else if (strcmp(argv[optind], "fix") == 0) { + 796 46 : operation = OPERATION_FIX; + 797 45 : } else if (strcmp(argv[optind], "test-dry") == 0) { + 798 2 : operation = OPERATION_DRY; + 799 43 : } else if (strcmp(argv[optind], "dup") == 0) { + 800 3 : operation = OPERATION_DUP; + 801 40 : } else if (strcmp(argv[optind], "list") == 0) { + 802 3 : operation = OPERATION_LIST; + 803 37 : } else if (strcmp(argv[optind], "pool") == 0) { + 804 3 : operation = OPERATION_POOL; + 805 34 : } else if (strcmp(argv[optind], "rehash") == 0) { + 806 1 : operation = OPERATION_REHASH; + 807 33 : } else if (strcmp(argv[optind], "scrub") == 0) { + 808 11 : operation = OPERATION_SCRUB; + 809 22 : } else if (strcmp(argv[optind], "status") == 0) { + 810 14 : operation = OPERATION_STATUS; + 811 8 : } else if (strcmp(argv[optind], "test-rewrite") == 0) { + 812 1 : operation = OPERATION_REWRITE; + 813 7 : } else if (strcmp(argv[optind], "test-read") == 0) { + 814 1 : operation = OPERATION_READ; + 815 6 : } else if (strcmp(argv[optind], "test-nano") == 0) { + 816 1 : operation = OPERATION_NANO; + 817 5 : } else if (strcmp(argv[optind], "up") == 0) { + 818 1 : operation = OPERATION_SPINUP; + 819 4 : } else if (strcmp(argv[optind], "down") == 0) { + 820 1 : operation = OPERATION_SPINDOWN; + 821 3 : } else if (strcmp(argv[optind], "devices") == 0) { + 822 1 : operation = OPERATION_DEVICES; + 823 2 : } else if (strcmp(argv[optind], "smart") == 0) { + 824 2 : operation = OPERATION_SMART; + 825 : } else { + 826 : /* LCOV_EXCL_START */ + 827 : log_fatal("Unknown command '%s'\n", argv[optind]); + 828 : exit(EXIT_FAILURE); + 829 : /* LCOV_EXCL_STOP */ + 830 : } + 831 : + 832 : /* check options compatibility */ + 833 255 : switch (operation) { + 834 : case OPERATION_CHECK : + 835 75 : break; + 836 : default : + 837 180 : if (opt.auditonly) { + 838 : /* LCOV_EXCL_START */ + 839 : log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command); + 840 : exit(EXIT_FAILURE); + 841 : /* LCOV_EXCL_STOP */ + 842 : } + 843 : } + 844 : + 845 255 : switch (operation) { + 846 : case OPERATION_FIX : + 847 46 : break; + 848 : default : + 849 209 : if (opt.force_device) { + 850 : /* LCOV_EXCL_START */ + 851 : log_fatal("You cannot use -D, --force-device with the '%s' command\n", command); + 852 : exit(EXIT_FAILURE); + 853 : /* LCOV_EXCL_STOP */ + 854 : } + 855 : } + 856 : + 857 255 : switch (operation) { + 858 : case OPERATION_SYNC : + 859 : case OPERATION_CHECK : + 860 : case OPERATION_FIX : + 861 203 : break; + 862 : default : + 863 52 : if (opt.force_nocopy) { + 864 : /* LCOV_EXCL_START */ + 865 : log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command); + 866 : exit(EXIT_FAILURE); + 867 : /* LCOV_EXCL_STOP */ + 868 : } + 869 : } + 870 : + 871 255 : switch (operation) { + 872 : case OPERATION_SYNC : + 873 82 : break; + 874 : default : + 875 173 : if (opt.prehash) { + 876 : /* LCOV_EXCL_START */ + 877 : log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command); + 878 : exit(EXIT_FAILURE); + 879 : /* LCOV_EXCL_STOP */ + 880 : } + 881 : + 882 173 : if (opt.force_full) { 883 : /* LCOV_EXCL_START */ - 884 : log_fatal("You cannot use -f, --filter with the '%s' command\n", command); + 884 : log_fatal("You cannot use -F, --force-full with the '%s' command\n", command); 885 : exit(EXIT_FAILURE); 886 : /* LCOV_EXCL_STOP */ 887 : } - 888 124 : if (!tommy_list_empty(&filterlist_disk)) { - 889 : /* LCOV_EXCL_START */ - 890 : log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command); - 891 : exit(EXIT_FAILURE); - 892 : /* LCOV_EXCL_STOP */ - 893 : } - 894 124 : if (filter_missing != 0) { - 895 : /* LCOV_EXCL_START */ - 896 : log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command); - 897 : exit(EXIT_FAILURE); - 898 : /* LCOV_EXCL_STOP */ - 899 : } - 900 124 : if (filter_error != 0) { - 901 : /* LCOV_EXCL_START */ - 902 : log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command); - 903 : exit(EXIT_FAILURE); - 904 : /* LCOV_EXCL_STOP */ - 905 : } - 906 : } - 907 : - 908 : /* errors must be always fixed on all disks */ - 909 : /* becasue we don't keep the information on what disk is the error */ - 910 247 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) { - 911 : /* LCOV_EXCL_START */ - 912 : log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n"); - 913 : exit(EXIT_FAILURE); - 914 : /* LCOV_EXCL_STOP */ - 915 : } - 916 : - 917 247 : switch (operation) { - 918 : case OPERATION_CHECK : - 919 : case OPERATION_FIX : - 920 121 : break; - 921 : default : - 922 126 : if (import_timestamp != 0 || import_content != 0) { + 888 : } + 889 : + 890 255 : if (opt.force_full && opt.force_nocopy) { + 891 : /* LCOV_EXCL_START */ + 892 : log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n"); + 893 : exit(EXIT_FAILURE); + 894 : /* LCOV_EXCL_STOP */ + 895 : } + 896 : + 897 255 : if (opt.prehash && opt.force_nocopy) { + 898 : /* LCOV_EXCL_START */ + 899 : log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n"); + 900 : exit(EXIT_FAILURE); + 901 : /* LCOV_EXCL_STOP */ + 902 : } + 903 : + 904 255 : switch (operation) { + 905 : case OPERATION_CHECK : + 906 : case OPERATION_FIX : + 907 : case OPERATION_DRY : + 908 123 : break; + 909 : default : + 910 132 : if (!tommy_list_empty(&filterlist_file)) { + 911 : /* LCOV_EXCL_START */ + 912 : log_fatal("You cannot use -f, --filter with the '%s' command\n", command); + 913 : exit(EXIT_FAILURE); + 914 : /* LCOV_EXCL_STOP */ + 915 : } + 916 132 : if (!tommy_list_empty(&filterlist_disk)) { + 917 : /* LCOV_EXCL_START */ + 918 : log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command); + 919 : exit(EXIT_FAILURE); + 920 : /* LCOV_EXCL_STOP */ + 921 : } + 922 132 : if (filter_missing != 0) { 923 : /* LCOV_EXCL_START */ - 924 : log_fatal("You cannot import with the '%s' command\n", command); + 924 : log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command); 925 : exit(EXIT_FAILURE); 926 : /* LCOV_EXCL_STOP */ 927 : } - 928 : } - 929 : - 930 247 : switch (operation) { - 931 : case OPERATION_LIST : - 932 : case OPERATION_DUP : - 933 : case OPERATION_STATUS : - 934 : case OPERATION_REWRITE : - 935 : case OPERATION_READ : - 936 : case OPERATION_REHASH : - 937 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ - 938 : /* avoid to check and access data disks if not needed */ - 939 24 : opt.skip_disk_access = 1; - 940 24 : break; - 941 : } - 942 : - 943 247 : switch (operation) { - 944 : case OPERATION_DIFF : - 945 : case OPERATION_LIST : - 946 : case OPERATION_DUP : - 947 : case OPERATION_POOL : - 948 : case OPERATION_STATUS : - 949 : case OPERATION_REWRITE : - 950 : case OPERATION_READ : - 951 : case OPERATION_REHASH : - 952 : case OPERATION_NANO : - 953 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ - 954 : /* avoid to check and access parity disks if not needed */ - 955 35 : opt.skip_parity_access = 1; - 956 35 : break; - 957 : } - 958 : - 959 247 : switch (operation) { - 960 : case OPERATION_FIX : - 961 : case OPERATION_CHECK : - 962 : /* avoid to stop processing if a content file is not accessible */ - 963 121 : opt.skip_content_access = 1; - 964 121 : break; - 965 : } - 966 : - 967 247 : switch (operation) { - 968 : case OPERATION_DIFF : - 969 : case OPERATION_LIST : - 970 : case OPERATION_DUP : - 971 : case OPERATION_POOL : - 972 : case OPERATION_NANO : - 973 : case OPERATION_SPINUP : - 974 : case OPERATION_SPINDOWN : - 975 : case OPERATION_DEVICES : - 976 : case OPERATION_SMART : - 977 22 : opt.skip_self = 1; - 978 22 : break; - 979 : } - 980 : - 981 247 : switch (operation) { - 982 : case OPERATION_DEVICES : - 983 : case OPERATION_SMART : - 984 : /* we may need to use these commands during operations */ - 985 3 : opt.skip_lock = 1; - 986 3 : break; - 987 : } - 988 : - 989 : /* open the log file */ - 990 247 : log_open(log_file); - 991 : - 992 : /* print generic info into the log */ - 993 247 : t = time(0); - 994 247 : tm = localtime(&t); - 995 247 : log_tag("version:%s\n", PACKAGE_VERSION); - 996 247 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t); - 997 247 : if (tm) { - 998 : char datetime[64]; - 999 247 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm); - 1000 247 : log_tag("time:%s\n", datetime); - 1001 : } - 1002 247 : log_tag("command:%s\n", command); - 1003 3274 : for (i = 0; i < argc; ++i) - 1004 3027 : log_tag("argv:%u:%s\n", i, argv[i]); - 1005 247 : log_flush(); - 1006 : - 1007 247 : if (!opt.skip_self) - 1008 1 : selftest(); - 1009 : - 1010 247 : state_init(&state); - 1011 : - 1012 : /* read the configuration file */ - 1013 247 : state_config(&state, conf, command, &opt, &filterlist_disk); - 1014 : - 1015 : /* set the raid mode */ - 1016 246 : raid_mode(state.raid_mode); - 1017 : - 1018 : #if HAVE_LOCKFILE - 1019 : /* create the lock file */ - 1020 246 : if (!opt.skip_lock && state.lockfile[0]) { - 1021 243 : lock = lock_lock(state.lockfile); - 1022 243 : if (lock == -1) { - 1023 : /* LCOV_EXCL_START */ - 1024 : if (errno != EWOULDBLOCK) { - 1025 : log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); - 1026 : } else { - 1027 : log_fatal("The lock file '%s' is already locked!\n", state.lockfile); - 1028 : log_fatal("SnapRAID is already in use!\n"); - 1029 : } - 1030 : exit(EXIT_FAILURE); - 1031 : /* LCOV_EXCL_STOP */ - 1032 : } - 1033 : } - 1034 : #else - 1035 : (void)lock; - 1036 : #endif + 928 132 : if (filter_error != 0) { + 929 : /* LCOV_EXCL_START */ + 930 : log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command); + 931 : exit(EXIT_FAILURE); + 932 : /* LCOV_EXCL_STOP */ + 933 : } + 934 : } + 935 : + 936 : /* errors must be always fixed on all disks */ + 937 : /* because we don't keep the information on what disk is the error */ + 938 255 : if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) { + 939 : /* LCOV_EXCL_START */ + 940 : log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n"); + 941 : exit(EXIT_FAILURE); + 942 : /* LCOV_EXCL_STOP */ + 943 : } + 944 : + 945 255 : switch (operation) { + 946 : case OPERATION_CHECK : + 947 : case OPERATION_FIX : + 948 121 : break; + 949 : default : + 950 134 : if (import_timestamp != 0 || import_content != 0) { + 951 : /* LCOV_EXCL_START */ + 952 : log_fatal("You cannot import with the '%s' command\n", command); + 953 : exit(EXIT_FAILURE); + 954 : /* LCOV_EXCL_STOP */ + 955 : } + 956 : } + 957 : + 958 255 : switch (operation) { + 959 : case OPERATION_LIST : + 960 : case OPERATION_DUP : + 961 : case OPERATION_STATUS : + 962 : case OPERATION_REWRITE : + 963 : case OPERATION_READ : + 964 : case OPERATION_REHASH : + 965 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ + 966 : /* avoid to check and access data disks if not needed */ + 967 24 : opt.skip_disk_access = 1; + 968 24 : break; + 969 : } + 970 : + 971 255 : switch (operation) { + 972 : case OPERATION_DIFF : + 973 : case OPERATION_LIST : + 974 : case OPERATION_DUP : + 975 : case OPERATION_POOL : + 976 : case OPERATION_STATUS : + 977 : case OPERATION_REWRITE : + 978 : case OPERATION_READ : + 979 : case OPERATION_REHASH : + 980 : case OPERATION_NANO : + 981 : case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ + 982 : /* avoid to check and access parity disks if not needed */ + 983 35 : opt.skip_parity_access = 1; + 984 35 : break; + 985 : } + 986 : + 987 255 : switch (operation) { + 988 : case OPERATION_FIX : + 989 : case OPERATION_CHECK : + 990 : /* avoid to stop processing if a content file is not accessible */ + 991 121 : opt.skip_content_access = 1; + 992 121 : break; + 993 : } + 994 : + 995 255 : switch (operation) { + 996 : case OPERATION_DIFF : + 997 : case OPERATION_LIST : + 998 : case OPERATION_DUP : + 999 : case OPERATION_POOL : + 1000 : case OPERATION_NANO : + 1001 : case OPERATION_SPINUP : + 1002 : case OPERATION_SPINDOWN : + 1003 : case OPERATION_DEVICES : + 1004 : case OPERATION_SMART : + 1005 22 : opt.skip_self = 1; + 1006 22 : break; + 1007 : } + 1008 : + 1009 255 : switch (operation) { + 1010 : case OPERATION_DEVICES : + 1011 : case OPERATION_SMART : + 1012 : /* we may need to use these commands during operations */ + 1013 3 : opt.skip_lock = 1; + 1014 3 : break; + 1015 : } + 1016 : + 1017 : /* open the log file */ + 1018 255 : log_open(log_file); + 1019 : + 1020 : /* print generic info into the log */ + 1021 255 : t = time(0); + 1022 255 : tm = localtime(&t); + 1023 255 : log_tag("version:%s\n", PACKAGE_VERSION); + 1024 255 : log_tag("unixtime:%" PRIi64 "\n", (int64_t)t); + 1025 255 : if (tm) { + 1026 : char datetime[64]; + 1027 255 : strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm); + 1028 255 : log_tag("time:%s\n", datetime); + 1029 : } + 1030 255 : log_tag("command:%s\n", command); + 1031 3377 : for (i = 0; i < argc; ++i) + 1032 3122 : log_tag("argv:%u:%s\n", i, argv[i]); + 1033 255 : log_flush(); + 1034 : + 1035 255 : if (!opt.skip_self) + 1036 1 : selftest(); 1037 : - 1038 246 : if (operation == OPERATION_DIFF) { - 1039 7 : state_read(&state); - 1040 : - 1041 7 : ret = state_diff(&state); + 1038 255 : state_init(&state); + 1039 : + 1040 : /* read the configuration file */ + 1041 255 : state_config(&state, conf, command, &opt, &filterlist_disk); 1042 : - 1043 : /* abort if sync needed */ - 1044 7 : if (ret > 0) - 1045 6 : exit(EXIT_SYNC_NEEDED); - 1046 239 : } else if (operation == OPERATION_SYNC) { - 1047 : - 1048 : /* in the next state read ensures to clear all the past hashes in case */ - 1049 : /* we are reading from an incomplete sync */ - 1050 : /* The undeterminated hash are only for CHG/DELETED blocks for which we don't */ - 1051 : /* know if the previous interrupted sync was able to update or not the parity. */ - 1052 : /* The sync process instead needs to trust this information because it's used */ - 1053 : /* to avoid to recompute the parity if all the input are equals as before. */ - 1054 : - 1055 : /* In these cases we don't know if the old state is still the one */ - 1056 : /* stored inside the parity, because after an aborted sync, the parity */ - 1057 : /* may be or may be not have been updated with the data that may be now */ - 1058 : /* deleted. Then we reset the hash to a bogus value. */ - 1059 : - 1060 : /* An example for CHG blocks is: */ - 1061 : /* - One file is added creating a CHG block with ZERO state */ - 1062 : /* - Sync aborted after updating the parity to the new state, */ - 1063 : /* but without saving the content file representing this new BLK state. */ - 1064 : /* - File is now deleted after the aborted sync */ - 1065 : /* - Sync again, deleting the blocks overt the CHG ones */ - 1066 : /* with the hash of CHG blocks not represeting the real parity state */ - 1067 : - 1068 : /* An example for DELETED blocks is: */ - 1069 : /* - One file is deleted creating DELETED blocks */ - 1070 : /* - Sync aborted after, updating the parity to the new state, */ - 1071 : /* but without saving the content file representing this new EMPTY state. */ - 1072 : /* - Another file is added again over the DELETE ones */ - 1073 : /* with the hash of DELETED blocks not represeting the real parity state */ - 1074 74 : state.clear_past_hash = 1; + 1043 : /* set the raid mode */ + 1044 254 : raid_mode(state.raid_mode); + 1045 : + 1046 : #if HAVE_LOCKFILE + 1047 : /* create the lock file */ + 1048 254 : if (!opt.skip_lock && state.lockfile[0]) { + 1049 251 : lock = lock_lock(state.lockfile); + 1050 251 : if (lock == -1) { + 1051 : /* LCOV_EXCL_START */ + 1052 : if (errno != EWOULDBLOCK) { + 1053 : log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); + 1054 : } else { + 1055 : log_fatal("The lock file '%s' is already locked!\n", state.lockfile); + 1056 : log_fatal("SnapRAID is already in use!\n"); + 1057 : } + 1058 : exit(EXIT_FAILURE); + 1059 : /* LCOV_EXCL_STOP */ + 1060 : } + 1061 : } + 1062 : #else + 1063 : (void)lock; + 1064 : #endif + 1065 : + 1066 254 : if (operation == OPERATION_DIFF) { + 1067 7 : state_read(&state); + 1068 : + 1069 7 : ret = state_diff(&state); + 1070 : + 1071 : /* abort if sync needed */ + 1072 7 : if (ret > 0) + 1073 6 : exit(EXIT_SYNC_NEEDED); + 1074 247 : } else if (operation == OPERATION_SYNC) { 1075 : - 1076 74 : state_read(&state); - 1077 : - 1078 73 : state_scan(&state); - 1079 : - 1080 : /* refresh the size info before the content write */ - 1081 72 : state_refresh(&state); + 1076 : /* in the next state read ensures to clear all the past hashes in case */ + 1077 : /* we are reading from an incomplete sync */ + 1078 : /* The indeterminate hash are only for CHG/DELETED blocks for which we don't */ + 1079 : /* know if the previous interrupted sync was able to update or not the parity. */ + 1080 : /* The sync process instead needs to trust this information because it's used */ + 1081 : /* to avoid to recompute the parity if all the input are equals as before. */ 1082 : - 1083 72 : memory(); - 1084 : - 1085 : /* intercept signals while operating */ - 1086 72 : signal_init(); + 1083 : /* In these cases we don't know if the old state is still the one */ + 1084 : /* stored inside the parity, because after an aborted sync, the parity */ + 1085 : /* may be or may be not have been updated with the data that may be now */ + 1086 : /* deleted. Then we reset the hash to a bogus value. */ 1087 : - 1088 : /* save the new state before the sync */ - 1089 : /* this allow to recover the case of the changes in the array after an aborted sync. */ - 1090 : - 1091 : /* for example, think at this case: */ - 1092 : /* - add some files at the array */ - 1093 : /* - run a sync command, it will recompute the parity adding the new files */ - 1094 : /* - abort the sync command before it stores the new content file */ - 1095 : /* - delete the not yet synced files from the array */ - 1096 : /* - run a new sync command */ - 1097 : - 1098 : /* the new sync command has now way to know that the parity file was modified */ - 1099 : /* because the files triggering these changes are now deleted */ - 1100 : /* and they aren't listed in the content file */ - 1101 : - 1102 72 : if (state.need_write) - 1103 70 : state_write(&state); - 1104 : - 1105 : /* run a test command if required */ - 1106 72 : if (run != 0) { - 1107 10 : ret = system(run); /* ignore error */ - 1108 10 : if (ret != 0) { - 1109 : /* LCOV_EXCL_START */ - 1110 : log_fatal("Error in running command '%s'.\n", run); - 1111 : exit(EXIT_FAILURE); - 1112 : /* LCOV_EXCL_STOP */ - 1113 : } - 1114 : } + 1088 : /* An example for CHG blocks is: */ + 1089 : /* - One file is added creating a CHG block with ZERO state */ + 1090 : /* - Sync aborted after updating the parity to the new state, */ + 1091 : /* but without saving the content file representing this new BLK state. */ + 1092 : /* - File is now deleted after the aborted sync */ + 1093 : /* - Sync again, deleting the blocks over the CHG ones */ + 1094 : /* with the hash of CHG blocks not representing the real parity state */ + 1095 : + 1096 : /* An example for DELETED blocks is: */ + 1097 : /* - One file is deleted creating DELETED blocks */ + 1098 : /* - Sync aborted after, updating the parity to the new state, */ + 1099 : /* but without saving the content file representing this new EMPTY state. */ + 1100 : /* - Another file is added again over the DELETE ones */ + 1101 : /* with the hash of DELETED blocks not representing the real parity state */ + 1102 82 : state.clear_past_hash = 1; + 1103 : + 1104 82 : state_read(&state); + 1105 : + 1106 81 : state_scan(&state); + 1107 : + 1108 : /* refresh the size info before the content write */ + 1109 80 : state_refresh(&state); + 1110 : + 1111 80 : memory(); + 1112 : + 1113 : /* intercept signals while operating */ + 1114 80 : signal_init(); 1115 : - 1116 : /* waits some time to ensure that any concurrent modification done at the files, */ - 1117 : /* using the same mtime read by the scan process, will be read by sync. */ - 1118 : /* Note that any later modification done, potentially not read by sync, will have */ - 1119 : /* a different mtime, and it will be syncronized at the next sync. */ - 1120 : /* The worst case is the FAT filesystem with a two seconds resolution for mtime. */ - 1121 : /* If you don't use FAT, the wait is not needed, because most filesystems have now */ - 1122 : /* at least microseconds resolution, but better to be safe. */ - 1123 72 : if (!opt.skip_self) - 1124 0 : sleep(2); + 1116 : /* save the new state before the sync */ + 1117 : /* this allow to recover the case of the changes in the array after an aborted sync. */ + 1118 : + 1119 : /* for example, think at this case: */ + 1120 : /* - add some files at the array */ + 1121 : /* - run a sync command, it will recompute the parity adding the new files */ + 1122 : /* - abort the sync command before it stores the new content file */ + 1123 : /* - delete the not yet synced files from the array */ + 1124 : /* - run a new sync command */ 1125 : - 1126 72 : ret = state_sync(&state, blockstart, blockcount); - 1127 : - 1128 : /* save the new state if required */ - 1129 72 : if (!opt.kill_after_sync && (state.need_write || state.opt.force_content_write)) - 1130 47 : state_write(&state); - 1131 : - 1132 : /* abort if required */ - 1133 72 : if (ret != 0) { - 1134 : /* LCOV_EXCL_START */ - 1135 : exit(EXIT_FAILURE); - 1136 : /* LCOV_EXCL_STOP */ - 1137 : } - 1138 165 : } else if (operation == OPERATION_DRY) { - 1139 2 : state_read(&state); - 1140 : - 1141 : /* filter */ - 1142 2 : state_skip(&state); - 1143 2 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); - 1144 : - 1145 2 : memory(); - 1146 : - 1147 : /* intercept signals while operating */ - 1148 2 : signal_init(); - 1149 : - 1150 2 : state_dry(&state, blockstart, blockcount); - 1151 163 : } else if (operation == OPERATION_REHASH) { - 1152 1 : state_read(&state); + 1126 : /* the new sync command has now way to know that the parity file was modified */ + 1127 : /* because the files triggering these changes are now deleted */ + 1128 : /* and they aren't listed in the content file */ + 1129 : + 1130 80 : if (state.need_write) + 1131 78 : state_write(&state); + 1132 : + 1133 : /* run a test command if required */ + 1134 80 : if (run != 0) { + 1135 10 : ret = system(run); /* ignore error */ + 1136 10 : if (ret != 0) { + 1137 : /* LCOV_EXCL_START */ + 1138 : log_fatal("Error in running command '%s'.\n", run); + 1139 : exit(EXIT_FAILURE); + 1140 : /* LCOV_EXCL_STOP */ + 1141 : } + 1142 : } + 1143 : + 1144 : /* waits some time to ensure that any concurrent modification done at the files, */ + 1145 : /* using the same mtime read by the scan process, will be read by sync. */ + 1146 : /* Note that any later modification done, potentially not read by sync, will have */ + 1147 : /* a different mtime, and it will be synchronized at the next sync. */ + 1148 : /* The worst case is the FAT file-system with a two seconds resolution for mtime. */ + 1149 : /* If you don't use FAT, the wait is not needed, because most file-systems have now */ + 1150 : /* at least microseconds resolution, but better to be safe. */ + 1151 80 : if (!opt.skip_self) + 1152 0 : sleep(2); 1153 : - 1154 : /* intercept signals while operating */ - 1155 1 : signal_init(); - 1156 : - 1157 1 : state_rehash(&state); - 1158 : - 1159 : /* save the new state if required */ - 1160 1 : if (state.need_write) - 1161 1 : state_write(&state); - 1162 162 : } else if (operation == OPERATION_SCRUB) { - 1163 11 : state_read(&state); - 1164 : - 1165 11 : memory(); - 1166 : - 1167 : /* intercept signals while operating */ - 1168 11 : signal_init(); - 1169 : - 1170 11 : ret = state_scrub(&state, plan, olderthan); - 1171 : - 1172 : /* save the new state if required */ - 1173 11 : if (state.need_write || state.opt.force_content_write) - 1174 10 : state_write(&state); - 1175 : - 1176 : /* abort if required */ - 1177 11 : if (ret != 0) { - 1178 : /* LCOV_EXCL_START */ - 1179 : exit(EXIT_FAILURE); - 1180 : /* LCOV_EXCL_STOP */ - 1181 : } - 1182 151 : } else if (operation == OPERATION_REWRITE) { - 1183 1 : state_read(&state); - 1184 : - 1185 : /* intercept signals while operating */ - 1186 1 : signal_init(); - 1187 : - 1188 1 : state_write(&state); - 1189 : - 1190 1 : memory(); - 1191 150 : } else if (operation == OPERATION_READ) { - 1192 1 : state_read(&state); - 1193 : - 1194 1 : memory(); - 1195 149 : } else if (operation == OPERATION_NANO) { - 1196 1 : state_read(&state); - 1197 : - 1198 1 : state_nano(&state); - 1199 : - 1200 : /* intercept signals while operating */ - 1201 1 : signal_init(); - 1202 : - 1203 1 : state_write(&state); - 1204 : - 1205 1 : memory(); - 1206 148 : } else if (operation == OPERATION_SPINUP) { - 1207 1 : state_device(&state, DEVICE_UP); - 1208 147 : } else if (operation == OPERATION_SPINDOWN) { - 1209 1 : state_device(&state, DEVICE_DOWN); - 1210 146 : } else if (operation == OPERATION_DEVICES) { - 1211 1 : state_device(&state, DEVICE_LIST); - 1212 145 : } else if (operation == OPERATION_SMART) { - 1213 2 : state_device(&state, DEVICE_SMART); - 1214 143 : } else if (operation == OPERATION_STATUS) { - 1215 14 : state_read(&state); + 1154 80 : ret = state_sync(&state, blockstart, blockcount); + 1155 : + 1156 : /* save the new state if required */ + 1157 80 : if (!opt.kill_after_sync) { + 1158 70 : if ((state.need_write || state.opt.force_content_write)) + 1159 51 : state_write(&state); + 1160 : } else { + 1161 10 : log_fatal("WARNING! Skipped state write for --test-kill-after-sync option.\n"); + 1162 : } + 1163 : + 1164 : /* abort if required */ + 1165 80 : if (ret != 0) { + 1166 : /* LCOV_EXCL_START */ + 1167 : exit(EXIT_FAILURE); + 1168 : /* LCOV_EXCL_STOP */ + 1169 : } + 1170 165 : } else if (operation == OPERATION_DRY) { + 1171 2 : state_read(&state); + 1172 : + 1173 : /* filter */ + 1174 2 : state_skip(&state); + 1175 2 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); + 1176 : + 1177 2 : memory(); + 1178 : + 1179 : /* intercept signals while operating */ + 1180 2 : signal_init(); + 1181 : + 1182 2 : state_dry(&state, blockstart, blockcount); + 1183 163 : } else if (operation == OPERATION_REHASH) { + 1184 1 : state_read(&state); + 1185 : + 1186 : /* intercept signals while operating */ + 1187 1 : signal_init(); + 1188 : + 1189 1 : state_rehash(&state); + 1190 : + 1191 : /* save the new state if required */ + 1192 1 : if (state.need_write) + 1193 1 : state_write(&state); + 1194 162 : } else if (operation == OPERATION_SCRUB) { + 1195 11 : state_read(&state); + 1196 : + 1197 11 : memory(); + 1198 : + 1199 : /* intercept signals while operating */ + 1200 11 : signal_init(); + 1201 : + 1202 11 : ret = state_scrub(&state, plan, olderthan); + 1203 : + 1204 : /* save the new state if required */ + 1205 11 : if (state.need_write || state.opt.force_content_write) + 1206 10 : state_write(&state); + 1207 : + 1208 : /* abort if required */ + 1209 11 : if (ret != 0) { + 1210 : /* LCOV_EXCL_START */ + 1211 : exit(EXIT_FAILURE); + 1212 : /* LCOV_EXCL_STOP */ + 1213 : } + 1214 151 : } else if (operation == OPERATION_REWRITE) { + 1215 1 : state_read(&state); 1216 : - 1217 14 : memory(); - 1218 : - 1219 14 : state_status(&state); - 1220 129 : } else if (operation == OPERATION_DUP) { - 1221 3 : state_read(&state); - 1222 : - 1223 3 : state_dup(&state); - 1224 126 : } else if (operation == OPERATION_LIST) { - 1225 3 : state_read(&state); - 1226 : - 1227 3 : state_list(&state); - 1228 123 : } else if (operation == OPERATION_POOL) { - 1229 3 : state_read(&state); - 1230 : - 1231 3 : state_pool(&state); - 1232 : } else { - 1233 120 : state_read(&state); + 1217 : /* intercept signals while operating */ + 1218 1 : signal_init(); + 1219 : + 1220 1 : state_write(&state); + 1221 : + 1222 1 : memory(); + 1223 150 : } else if (operation == OPERATION_READ) { + 1224 1 : state_read(&state); + 1225 : + 1226 1 : memory(); + 1227 149 : } else if (operation == OPERATION_NANO) { + 1228 1 : state_read(&state); + 1229 : + 1230 1 : state_nano(&state); + 1231 : + 1232 : /* intercept signals while operating */ + 1233 1 : signal_init(); 1234 : - 1235 : /* if we are also trying to recover */ - 1236 120 : if (!state.opt.auditonly) { - 1237 : /* import the user specified dirs */ - 1238 114 : if (import_timestamp != 0) - 1239 1 : state_search(&state, import_timestamp); - 1240 114 : if (import_content != 0) - 1241 1 : state_import(&state, import_content); - 1242 : - 1243 : /* import from all the array */ - 1244 114 : if (!state.opt.force_nocopy) - 1245 114 : state_search_array(&state); - 1246 : } - 1247 : - 1248 : /* filter */ - 1249 120 : state_skip(&state); - 1250 120 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); - 1251 : - 1252 120 : memory(); - 1253 : - 1254 : /* intercept signals while operating */ - 1255 120 : signal_init(); - 1256 : - 1257 120 : if (operation == OPERATION_CHECK) { - 1258 75 : ret = state_check(&state, 0, blockstart, blockcount); - 1259 : } else { /* it's fix */ - 1260 45 : ret = state_check(&state, 1, blockstart, blockcount); - 1261 : } + 1235 1 : state_write(&state); + 1236 : + 1237 1 : memory(); + 1238 148 : } else if (operation == OPERATION_SPINUP) { + 1239 1 : state_device(&state, DEVICE_UP); + 1240 147 : } else if (operation == OPERATION_SPINDOWN) { + 1241 1 : state_device(&state, DEVICE_DOWN); + 1242 146 : } else if (operation == OPERATION_DEVICES) { + 1243 1 : state_device(&state, DEVICE_LIST); + 1244 145 : } else if (operation == OPERATION_SMART) { + 1245 2 : state_device(&state, DEVICE_SMART); + 1246 143 : } else if (operation == OPERATION_STATUS) { + 1247 14 : state_read(&state); + 1248 : + 1249 14 : memory(); + 1250 : + 1251 14 : state_status(&state); + 1252 129 : } else if (operation == OPERATION_DUP) { + 1253 3 : state_read(&state); + 1254 : + 1255 3 : state_dup(&state); + 1256 126 : } else if (operation == OPERATION_LIST) { + 1257 3 : state_read(&state); + 1258 : + 1259 3 : state_list(&state); + 1260 123 : } else if (operation == OPERATION_POOL) { + 1261 3 : state_read(&state); 1262 : - 1263 : /* abort if required */ - 1264 120 : if (ret != 0) { - 1265 : /* LCOV_EXCL_START */ - 1266 : exit(EXIT_FAILURE); - 1267 : /* LCOV_EXCL_STOP */ - 1268 : } - 1269 : } - 1270 : - 1271 : /* close log file */ - 1272 225 : log_close(log_file); - 1273 : - 1274 : #if HAVE_LOCKFILE - 1275 225 : if (!opt.skip_lock && state.lockfile[0]) { - 1276 223 : if (lock_unlock(lock) == -1) { - 1277 : /* LCOV_EXCL_START */ - 1278 : log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); - 1279 : exit(EXIT_FAILURE); - 1280 : /* LCOV_EXCL_STOP */ - 1281 : } - 1282 : } - 1283 : #endif - 1284 : - 1285 225 : state_done(&state); - 1286 225 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free); - 1287 225 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free); + 1263 3 : state_pool(&state); + 1264 : } else { + 1265 120 : state_read(&state); + 1266 : + 1267 : /* if we are also trying to recover */ + 1268 120 : if (!state.opt.auditonly) { + 1269 : /* import the user specified dirs */ + 1270 114 : if (import_timestamp != 0) + 1271 1 : state_search(&state, import_timestamp); + 1272 114 : if (import_content != 0) + 1273 1 : state_import(&state, import_content); + 1274 : + 1275 : /* import from all the array */ + 1276 114 : if (!state.opt.force_nocopy) + 1277 114 : state_search_array(&state); + 1278 : } + 1279 : + 1280 : /* filter */ + 1281 120 : state_skip(&state); + 1282 120 : state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); + 1283 : + 1284 120 : memory(); + 1285 : + 1286 : /* intercept signals while operating */ + 1287 120 : signal_init(); 1288 : - 1289 225 : os_done(); - 1290 : - 1291 225 : return EXIT_SUCCESS; - 1292 : } - 1293 : + 1289 120 : if (operation == OPERATION_CHECK) { + 1290 75 : ret = state_check(&state, 0, blockstart, blockcount); + 1291 : } else { /* it's fix */ + 1292 45 : ret = state_check(&state, 1, blockstart, blockcount); + 1293 : } + 1294 : + 1295 : /* abort if required */ + 1296 120 : if (ret != 0) { + 1297 : /* LCOV_EXCL_START */ + 1298 : exit(EXIT_FAILURE); + 1299 : /* LCOV_EXCL_STOP */ + 1300 : } + 1301 : } + 1302 : + 1303 : /* close log file */ + 1304 233 : log_close(log_file); + 1305 : + 1306 : #if HAVE_LOCKFILE + 1307 233 : if (!opt.skip_lock && state.lockfile[0]) { + 1308 231 : if (lock_unlock(lock) == -1) { + 1309 : /* LCOV_EXCL_START */ + 1310 : log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); + 1311 : exit(EXIT_FAILURE); + 1312 : /* LCOV_EXCL_STOP */ + 1313 : } + 1314 : } + 1315 : #endif + 1316 : + 1317 233 : state_done(&state); + 1318 233 : tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free); + 1319 233 : tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free); + 1320 : + 1321 233 : os_done(); + 1322 : + 1323 233 : return EXIT_SUCCESS; + 1324 : } + 1325 : diff --git a/cov/cmdline/speed.c.func-sort-c.html b/cov/cmdline/speed.c.func-sort-c.html index af5d7d8f..4b48a521 100644 --- a/cov/cmdline/speed.c.func-sort-c.html +++ b/cov/cmdline/speed.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,7 +61,7 @@ diffgettimeofday - 1866 + 1878 speed diff --git a/cov/cmdline/speed.c.func.html b/cov/cmdline/speed.c.func.html index eb03f6a4..2ea02544 100644 --- a/cov/cmdline/speed.c.func.html +++ b/cov/cmdline/speed.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,7 +61,7 @@ diffgettimeofday - 1866 + 1878 speed diff --git a/cov/cmdline/speed.c.gcov.html b/cov/cmdline/speed.c.gcov.html index edf49280..3d202c50 100644 --- a/cov/cmdline/speed.c.gcov.html +++ b/cov/cmdline/speed.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -100,14 +100,14 @@ 38 : /** 39 : * Differential us of two timeval. 40 : */ - 41 1866 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) + 41 1878 : static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) 42 : { 43 : int64_t d; 44 : - 45 1866 : d = 1000000LL * (stop->tv_sec - start->tv_sec); - 46 1866 : d += stop->tv_usec - start->tv_usec; + 45 1878 : d = 1000000LL * (stop->tv_sec - start->tv_sec); + 46 1878 : d += stop->tv_usec - start->tv_usec; 47 : - 48 1866 : return d; + 48 1878 : return d; 49 : } 50 : 51 : /** @@ -232,10 +232,10 @@ 170 4 : printf("%8s", "memset"); 171 4 : fflush(stdout); 172 : - 173 385 : SPEED_START { - 174 3429 : for (j = 0; j < nd; ++j) - 175 3048 : memset(v[j], j, size); - 176 381 : } SPEED_STOP + 173 375 : SPEED_START { + 174 3339 : for (j = 0; j < nd; ++j) + 175 2968 : memset(v[j], j, size); + 176 371 : } SPEED_STOP 177 : 178 4 : printf("%8" PRIu64, ds / dt); 179 4 : printf("\n"); @@ -247,10 +247,10 @@ 185 4 : printf("%8s", "table"); 186 4 : fflush(stdout); 187 : - 188 46 : SPEED_START { - 189 378 : for (j = 0; j < nd; ++j) - 190 336 : side_effect += crc32c_gen(0, v[j], size); - 191 42 : } SPEED_STOP + 188 48 : SPEED_START { + 189 396 : for (j = 0; j < nd; ++j) + 190 352 : side_effect += crc32c_gen(0, v[j], size); + 191 44 : } SPEED_STOP 192 : 193 4 : printf("%8" PRIu64, ds / dt); 194 4 : printf("\n"); @@ -302,10 +302,10 @@ 240 4 : printf("%8" PRIu64, ds / dt); 241 4 : fflush(stdout); 242 : - 243 35 : SPEED_START { - 244 279 : for (j = 0; j < nd; ++j) - 245 248 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); - 246 31 : } SPEED_STOP + 243 36 : SPEED_START { + 244 288 : for (j = 0; j < nd; ++j) + 245 256 : memhash(HASH_SPOOKY2, seed, digest, v[j], size); + 246 32 : } SPEED_STOP 247 : 248 4 : printf("%8" PRIu64, ds / dt); 249 4 : printf("\n"); @@ -341,16 +341,16 @@ 279 : 280 4 : printf("%8s", ""); 281 : - 282 118 : SPEED_START { - 283 114 : raid_gen1_int32(nd, size, v); - 284 114 : } SPEED_STOP + 282 120 : SPEED_START { + 283 116 : raid_gen1_int32(nd, size, v); + 284 116 : } SPEED_STOP 285 : 286 4 : printf("%8" PRIu64, ds / dt); 287 4 : fflush(stdout); 288 : - 289 189 : SPEED_START { - 290 185 : raid_gen1_int64(nd, size, v); - 291 185 : } SPEED_STOP + 289 192 : SPEED_START { + 290 188 : raid_gen1_int64(nd, size, v); + 291 188 : } SPEED_STOP 292 : 293 4 : printf("%8" PRIu64, ds / dt); 294 4 : fflush(stdout); @@ -358,9 +358,9 @@ 296 : #ifdef CONFIG_X86 297 : #ifdef CONFIG_SSE2 298 4 : if (raid_cpu_has_sse2()) { - 299 310 : SPEED_START { - 300 306 : raid_gen1_sse2(nd, size, v); - 301 306 : } SPEED_STOP + 299 317 : SPEED_START { + 300 313 : raid_gen1_sse2(nd, size, v); + 301 313 : } SPEED_STOP 302 : 303 4 : printf("%8" PRIu64, ds / dt); 304 4 : fflush(stdout); @@ -411,9 +411,9 @@ 349 : #ifdef CONFIG_X86 350 : #ifdef CONFIG_SSE2 351 4 : if (raid_cpu_has_sse2()) { - 352 147 : SPEED_START { - 353 143 : raid_gen2_sse2(nd, size, v); - 354 143 : } SPEED_STOP + 352 151 : SPEED_START { + 353 147 : raid_gen2_sse2(nd, size, v); + 354 147 : } SPEED_STOP 355 : 356 4 : printf("%8" PRIu64, ds / dt); 357 4 : fflush(stdout); @@ -470,9 +470,9 @@ 408 : #ifdef CONFIG_X86 409 : #ifdef CONFIG_SSE2 410 4 : if (raid_cpu_has_sse2()) { - 411 88 : SPEED_START { - 412 84 : raid_genz_sse2(nd, size, v); - 413 84 : } SPEED_STOP + 411 89 : SPEED_START { + 412 85 : raid_genz_sse2(nd, size, v); + 413 85 : } SPEED_STOP 414 : 415 4 : printf("%8" PRIu64, ds / dt); 416 4 : fflush(stdout); @@ -707,9 +707,9 @@ 645 4 : printf("%8s", raid_gen6_tag()); 646 4 : fflush(stdout); 647 : - 648 10 : SPEED_START { - 649 6 : raid_gen6_int8(nd, size, v); - 650 6 : } SPEED_STOP + 648 12 : SPEED_START { + 649 8 : raid_gen6_int8(nd, size, v); + 650 8 : } SPEED_STOP 651 : 652 4 : printf("%8" PRIu64, ds / dt); 653 4 : fflush(stdout); diff --git a/cov/cmdline/spooky2.c.func-sort-c.html b/cov/cmdline/spooky2.c.func-sort-c.html index d52512e6..8c286716 100644 --- a/cov/cmdline/spooky2.c.func-sort-c.html +++ b/cov/cmdline/spooky2.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3472174 + 3855152
diff --git a/cov/cmdline/spooky2.c.func.html b/cov/cmdline/spooky2.c.func.html index d22d4cbf..6c188d72 100644 --- a/cov/cmdline/spooky2.c.func.html +++ b/cov/cmdline/spooky2.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -61,7 +61,7 @@ SpookyHash128 - 3472174 + 3855152
diff --git a/cov/cmdline/spooky2.c.gcov.html b/cov/cmdline/spooky2.c.gcov.html index 06596abb..8e1b9ebc 100644 --- a/cov/cmdline/spooky2.c.gcov.html +++ b/cov/cmdline/spooky2.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -170,7 +170,7 @@ 108 : // 109 : #define sc_const 0xdeadbeefdeadbeefLL 110 : - 111 3472174 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) + 111 3855152 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) 112 : { 113 : uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11; 114 : uint64_t buf[sc_numVars]; @@ -182,39 +182,39 @@ 120 : unsigned i; 121 : #endif 122 : - 123 3472174 : h9 = ((const uint64_t*)seed)[0]; - 124 3472174 : h10 = ((const uint64_t*)seed)[1]; + 123 3855152 : h9 = ((const uint64_t*)seed)[0]; + 124 3855152 : h10 = ((const uint64_t*)seed)[1]; 125 : 126 : #if WORDS_BIGENDIAN 127 : h9 = util_swap64(h9); 128 : h10 = util_swap64(h10); 129 : #endif 130 : - 131 3472174 : h0 = h3 = h6 = h9; - 132 3472174 : h1 = h4 = h7 = h10; - 133 3472174 : h2 = h5 = h8 = h11 = sc_const; + 131 3855152 : h0 = h3 = h6 = h9; + 132 3855152 : h1 = h4 = h7 = h10; + 133 3855152 : h2 = h5 = h8 = h11 = sc_const; 134 : - 135 3472174 : nblocks = size / sc_blockSize; - 136 3472174 : blocks = data; - 137 3472174 : end = blocks + nblocks * sc_numVars; + 135 3855152 : nblocks = size / sc_blockSize; + 136 3855152 : blocks = data; + 137 3855152 : end = blocks + nblocks * sc_numVars; 138 : 139 : /* body */ - 140 34945798 : while (blocks < end) { + 140 38762369 : while (blocks < end) { 141 : #if WORDS_BIGENDIAN 142 : for (i = 0; i < sc_numVars; ++i) 143 : buf[i] = util_swap64(blocks[i]); 144 : Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 145 : #else - 146 28001450 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 146 31052065 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 147 : #endif - 148 28001450 : blocks += sc_numVars; + 148 31052065 : blocks += sc_numVars; 149 : } 150 : 151 : /* tail */ - 152 3472174 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); - 153 3472174 : memcpy(buf, end, size_remainder); - 154 3472174 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); - 155 3472174 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; + 152 3855152 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); + 153 3855152 : memcpy(buf, end, size_remainder); + 154 3855152 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); + 155 3855152 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; 156 : 157 : /* finalization */ 158 : #if WORDS_BIGENDIAN @@ -222,16 +222,16 @@ 160 : buf[i] = util_swap64(buf[i]); 161 : #endif 162 : - 163 3472174 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + 163 3855152 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); 164 : 165 : #if WORDS_BIGENDIAN 166 : h0 = util_swap64(h0); 167 : h1 = util_swap64(h1); 168 : #endif 169 : - 170 3472174 : ((uint64_t*)digest)[0] = h0; - 171 3472174 : ((uint64_t*)digest)[1] = h1; - 172 3472174 : } + 170 3855152 : ((uint64_t*)digest)[0] = h0; + 171 3855152 : ((uint64_t*)digest)[1] = h1; + 172 3855152 : } 173 : diff --git a/cov/cmdline/state.c.func-sort-c.html b/cov/cmdline/state.c.func-sort-c.html index 7cf9b431..f380d70f 100644 --- a/cov/cmdline/state.c.func-sort-c.html +++ b/cov/cmdline/state.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 1248 - 1351 - 92.4 % + 1262 + 1363 + 92.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 35 36 - 97.2 % + 37 + 97.3 % @@ -60,147 +60,151 @@ Hit count Sort by hit count - fs_is_block_deleted_ts - 29344162 + fs_is_block_deleted_ts + 4507856 - fs_info_is_required - 1491820 + fs_info_is_required + 1513218 - state_progress - 1038958 + state_progress + 1048979 - fs_position_is_required - 729418 + fs_position_is_required + 752491 - lev_config_name - 178766 + lev_config_name + 178997 - find_disk - 11051 + find_disk_by_name + 6723 - lev_config_scan - 5905 + lev_config_scan + 6118 - state_write_thread - 913 + state_verify_thread + 990 - state_verify_thread - 912 + state_fscheck + 474 - state_fscheck - 447 + validate_smartctl + 358 - validate_smartctl - 344 + state_init + 256 - state_init - 248 + state_config + 255 - state_config - 247 + lev_raid_name + 254 - lev_raid_name - 246 + state_config_check + 254 - state_config_check - 246 + state_read + 250 - state_read + state_map + 249 + + + state_read_content + 243 + + + state_content_check 242 - state_map - 241 - - - state_read_content - 235 - - - state_content_check + state_done 234 - state_done - 226 + state_progress_end + 214 - state_progress_end - 206 + state_progress_begin + 214 - state_progress_begin - 206 + state_refresh + 160 - state_refresh - 144 + state_write + 145 - state_write - 134 + state_write_thread + 145 - state_write_content - 134 + state_write_content + 145 - state_verify_content - 134 + state_verify_content + 145 - state_rename_content - 134 + state_rename_content + 145 - state_skip + state_skip 122 - state_filter + state_filter 122 - state_usage_print - 81 + state_usage_print + 89 - lev_name + lev_name 7 - state_progress_restart + find_disk_by_uuid + 2 + + + state_progress_restart 1 - generate_configuration + generate_configuration 1 - decoding_error + decoding_error 1 - state_progress_stop + state_progress_stop 1 - fs_position_clear_deleted + fs_position_clear_deleted 0 diff --git a/cov/cmdline/state.c.func.html b/cov/cmdline/state.c.func.html index c610d3af..912c6cfc 100644 --- a/cov/cmdline/state.c.func.html +++ b/cov/cmdline/state.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 1248 - 1351 - 92.4 % + 1262 + 1363 + 92.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 35 36 - 97.2 % + 37 + 97.3 % @@ -60,148 +60,152 @@ Hit count Sort by hit count - decoding_error + decoding_error 1 - find_disk - 11051 + find_disk_by_name + 6723 - fs_info_is_required - 1491820 + find_disk_by_uuid + 2 - fs_is_block_deleted_ts - 29344162 + fs_info_is_required + 1513218 - fs_position_clear_deleted + fs_is_block_deleted_ts + 4507856 + + + fs_position_clear_deleted 0 - fs_position_is_required - 729418 + fs_position_is_required + 752491 - generate_configuration + generate_configuration 1 - lev_config_name - 178766 + lev_config_name + 178997 - lev_config_scan - 5905 + lev_config_scan + 6118 - lev_name + lev_name 7 - lev_raid_name - 246 + lev_raid_name + 254 - state_config - 247 + state_config + 255 - state_config_check - 246 + state_config_check + 254 - state_content_check - 234 - - - state_done - 226 - - - state_filter - 122 - - - state_fscheck - 447 - - - state_init - 248 - - - state_map - 241 - - - state_progress - 1038958 - - - state_progress_begin - 206 - - - state_progress_end - 206 - - - state_progress_restart - 1 - - - state_progress_stop - 1 - - - state_read + state_content_check 242 - state_read_content - 235 + state_done + 234 - state_refresh - 144 - - - state_rename_content - 134 - - - state_skip + state_filter 122 - state_usage_print - 81 + state_fscheck + 474 - state_verify_content - 134 + state_init + 256 - state_verify_thread - 912 + state_map + 249 - state_write - 134 + state_progress + 1048979 - state_write_content - 134 + state_progress_begin + 214 - state_write_thread - 913 + state_progress_end + 214 - validate_smartctl - 344 + state_progress_restart + 1 + + + state_progress_stop + 1 + + + state_read + 250 + + + state_read_content + 243 + + + state_refresh + 160 + + + state_rename_content + 145 + + + state_skip + 122 + + + state_usage_print + 89 + + + state_verify_content + 145 + + + state_verify_thread + 990 + + + state_write + 145 + + + state_write_content + 145 + + + state_write_thread + 145 + + + validate_smartctl + 358
diff --git a/cov/cmdline/state.c.gcov.html b/cov/cmdline/state.c.gcov.html index 17e83360..f17512ad 100644 --- a/cov/cmdline/state.c.gcov.html +++ b/cov/cmdline/state.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 1248 - 1351 - 92.4 % + 1262 + 1363 + 92.6 % Date: - 2015-11-20 + 2016-01-09 Functions: - 35 36 - 97.2 % + 37 + 97.3 % @@ -87,3948 +87,4120 @@ 25 : #include "parity.h" 26 : #include "stream.h" 27 : #include "raid/raid.h" - 28 : #include "raid/cpu.h" + 28 : #include "raid/cpu.h" 29 : - 30 7 : const char* lev_name(unsigned l) - 31 : { - 32 7 : switch (l) { - 33 2 : case 0 : return "Parity"; - 34 1 : case 1 : return "2-Parity"; - 35 1 : case 2 : return "3-Parity"; - 36 1 : case 3 : return "4-Parity"; - 37 1 : case 4 : return "5-Parity"; - 38 1 : case 5 : return "6-Parity"; - 39 : } - 40 : - 41 0 : return 0; - 42 : } - 43 : - 44 178766 : const char* lev_config_name(unsigned l) - 45 : { - 46 178766 : switch (l) { - 47 70476 : case 0 : return "parity"; - 48 57423 : case 1 : return "2-parity"; - 49 12723 : case 2 : return "3-parity"; - 50 12719 : case 3 : return "4-parity"; - 51 12715 : case 4 : return "5-parity"; - 52 12710 : case 5 : return "6-parity"; - 53 : } - 54 : - 55 0 : return 0; - 56 : } - 57 : - 58 5905 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) - 59 : { - 60 5905 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { - 61 419 : *level = 0; - 62 419 : return 0; - 63 : } - 64 : - 65 5486 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { - 66 213 : *level = 1; - 67 213 : return 0; - 68 : } - 69 : - 70 5273 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { - 71 188 : *level = 2; - 72 188 : return 0; + 30 : /** + 31 : * Configure the multithread support. + 32 : * + 33 : * Multi thread for write could be either faster or slower, depending + 34 : * on the specific conditions. With multithreads it's likely faster + 35 : * writing to disk, but you'll need to access multiple times the same data, + 36 : * being potentially slower. + 37 : * + 38 : * For upcoming SnapRAID version it's planned to add a mutex protection + 39 : * at the file-system structure, slowing down multiple data access, + 40 : * so we disable it. + 41 : * + 42 : * Multi thread for verify is instead always generally faster, + 43 : * so we enable it if possible. + 44 : */ + 45 : #if HAVE_PTHREAD + 46 : /* #define HAVE_MT_WRITE 1 */ + 47 : #define HAVE_MT_VERIFY 1 + 48 : #endif + 49 : + 50 7 : const char* lev_name(unsigned l) + 51 : { + 52 7 : switch (l) { + 53 2 : case 0 : return "Parity"; + 54 1 : case 1 : return "2-Parity"; + 55 1 : case 2 : return "3-Parity"; + 56 1 : case 3 : return "4-Parity"; + 57 1 : case 4 : return "5-Parity"; + 58 1 : case 5 : return "6-Parity"; + 59 : } + 60 : + 61 0 : return 0; + 62 : } + 63 : + 64 178997 : const char* lev_config_name(unsigned l) + 65 : { + 66 178997 : switch (l) { + 67 70574 : case 0 : return "parity"; + 68 57456 : case 1 : return "2-parity"; + 69 12748 : case 2 : return "3-parity"; + 70 12744 : case 3 : return "4-parity"; + 71 12740 : case 4 : return "5-parity"; + 72 12735 : case 5 : return "6-parity"; 73 : } 74 : - 75 5085 : if (strcmp(s, "4-parity") == 0) { - 76 185 : *level = 3; - 77 185 : return 0; - 78 : } - 79 : - 80 4900 : if (strcmp(s, "5-parity") == 0) { - 81 182 : *level = 4; - 82 182 : return 0; + 75 0 : return 0; + 76 : } + 77 : + 78 6118 : static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) + 79 : { + 80 6118 : if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { + 81 434 : *level = 0; + 82 434 : return 0; 83 : } 84 : - 85 4718 : if (strcmp(s, "6-parity") == 0) { - 86 178 : *level = 5; - 87 178 : return 0; + 85 5684 : if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { + 86 221 : *level = 1; + 87 221 : return 0; 88 : } 89 : - 90 4540 : if (strcmp(s, "z-parity") == 0) { - 91 0 : *level = 2; - 92 0 : if (mode) - 93 0 : *mode = RAID_MODE_VANDERMONDE; - 94 0 : return 0; - 95 : } - 96 : - 97 4540 : return -1; - 98 : } + 90 5463 : if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { + 91 196 : *level = 2; + 92 196 : return 0; + 93 : } + 94 : + 95 5267 : if (strcmp(s, "4-parity") == 0) { + 96 193 : *level = 3; + 97 193 : return 0; + 98 : } 99 : - 100 246 : const char* lev_raid_name(unsigned mode, unsigned n) - 101 : { - 102 246 : switch (n) { - 103 34 : case 1 : return "par1"; - 104 25 : case 2 : return "par2"; - 105 3 : case 3 : if (mode == RAID_MODE_CAUCHY) - 106 3 : return "par3"; - 107 : else - 108 0 : return "parz"; - 109 3 : case 4 : return "par4"; - 110 4 : case 5 : return "par5"; - 111 177 : case 6 : return "par6"; - 112 : } - 113 : - 114 0 : return 0; - 115 : } + 100 5074 : if (strcmp(s, "5-parity") == 0) { + 101 190 : *level = 4; + 102 190 : return 0; + 103 : } + 104 : + 105 4884 : if (strcmp(s, "6-parity") == 0) { + 106 186 : *level = 5; + 107 186 : return 0; + 108 : } + 109 : + 110 4698 : if (strcmp(s, "z-parity") == 0) { + 111 0 : *level = 2; + 112 0 : if (mode) + 113 0 : *mode = RAID_MODE_VANDERMONDE; + 114 0 : return 0; + 115 : } 116 : - 117 248 : void state_init(struct snapraid_state* state) - 118 : { - 119 : unsigned l; - 120 : - 121 248 : memset(&state->opt, 0, sizeof(state->opt)); - 122 248 : state->filter_hidden = 0; - 123 248 : state->autosave = 0; - 124 248 : state->need_write = 0; - 125 248 : state->checked_read = 0; - 126 248 : state->block_size = 256 * 1024; /* default 256 KiB */ - 127 248 : state->raid_mode = RAID_MODE_CAUCHY; - 128 248 : state->file_mode = MODE_SEQUENTIAL; - 129 1736 : for (l = 0; l < LEV_MAX; ++l) { - 130 1488 : state->parity[l].path[0] = 0; - 131 1488 : state->parity[l].smartctl[0] = 0; - 132 1488 : state->parity[l].uuid[0] = 0; - 133 1488 : state->parity[l].device = 0; - 134 1488 : state->parity[l].total_blocks = 0; - 135 1488 : state->parity[l].free_blocks = 0; - 136 1488 : state->parity[l].tick = 0; - 137 1488 : state->parity[l].skip_access = 0; - 138 1488 : state->parity[l].is_excluded = 0; - 139 : } - 140 248 : state->tick_io = 0; - 141 248 : state->tick_cpu = 0; - 142 248 : state->tick_last = tick(); - 143 248 : state->share[0] = 0; - 144 248 : state->pool[0] = 0; - 145 248 : state->pool_device = 0; - 146 248 : state->lockfile[0] = 0; - 147 248 : state->level = 1; /* default is the lowest protection */ - 148 248 : state->clear_past_hash = 0; - 149 248 : state->no_conf = 0; - 150 : - 151 248 : tommy_list_init(&state->disklist); - 152 248 : tommy_list_init(&state->maplist); - 153 248 : tommy_list_init(&state->contentlist); - 154 248 : tommy_list_init(&state->filterlist); - 155 248 : tommy_list_init(&state->importlist); - 156 248 : tommy_hashdyn_init(&state->importset); - 157 248 : tommy_hashdyn_init(&state->previmportset); - 158 248 : tommy_hashdyn_init(&state->searchset); - 159 248 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info)); - 160 248 : } - 161 : - 162 226 : void state_done(struct snapraid_state* state) - 163 : { - 164 226 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); - 165 226 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free); - 166 226 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); - 167 226 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); - 168 226 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free); - 169 226 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free); - 170 226 : tommy_hashdyn_done(&state->importset); - 171 226 : tommy_hashdyn_done(&state->previmportset); - 172 226 : tommy_hashdyn_done(&state->searchset); - 173 226 : tommy_arrayblkof_done(&state->infoarr); - 174 226 : } - 175 : - 176 : /** - 177 : * Check the configuration. - 178 : */ - 179 246 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk) - 180 : { - 181 : tommy_node* i; - 182 : unsigned l; - 183 : - 184 : /* check for parity level */ - 185 246 : if (state->raid_mode == RAID_MODE_VANDERMONDE) { - 186 0 : if (state->level > 3) { - 187 : /* LCOV_EXCL_START */ - 188 : log_fatal("If you use the z-parity you cannot have more than 3 parities.\n"); - 189 : exit(EXIT_FAILURE); - 190 : /* LCOV_EXCL_STIO */ - 191 : } - 192 : } - 193 : - 194 : for (l = 0; l < state->level; ++l) { - 195 : if (state->parity[l].path[0] == 0) { - 196 : /* LCOV_EXCL_START */ - 197 : log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path); - 198 : exit(EXIT_FAILURE); - 199 : /* LCOV_EXCL_STOP */ - 200 : } - 201 : } - 202 : - 203 246 : if (tommy_list_empty(&state->contentlist)) { - 204 : /* LCOV_EXCL_START */ - 205 : log_fatal("No 'content' specification in '%s'\n", path); - 206 : exit(EXIT_FAILURE); - 207 : /* LCOV_EXCL_STOP */ - 208 : } - 209 : - 210 : /* check for equal paths */ - 211 1679 : for (i = state->contentlist; i != 0; i = i->next) { - 212 1433 : struct snapraid_content* content = i->data; + 117 4698 : return -1; + 118 : } + 119 : + 120 254 : const char* lev_raid_name(unsigned mode, unsigned n) + 121 : { + 122 254 : switch (n) { + 123 34 : case 1 : return "par1"; + 124 25 : case 2 : return "par2"; + 125 3 : case 3 : if (mode == RAID_MODE_CAUCHY) + 126 3 : return "par3"; + 127 : else + 128 0 : return "parz"; + 129 3 : case 4 : return "par4"; + 130 4 : case 5 : return "par5"; + 131 185 : case 6 : return "par6"; + 132 : } + 133 : + 134 0 : return 0; + 135 : } + 136 : + 137 256 : void state_init(struct snapraid_state* state) + 138 : { + 139 : unsigned l; + 140 : + 141 256 : memset(&state->opt, 0, sizeof(state->opt)); + 142 256 : state->filter_hidden = 0; + 143 256 : state->autosave = 0; + 144 256 : state->need_write = 0; + 145 256 : state->checked_read = 0; + 146 256 : state->block_size = 256 * 1024; /* default 256 KiB */ + 147 256 : state->raid_mode = RAID_MODE_CAUCHY; + 148 256 : state->file_mode = MODE_SEQUENTIAL; + 149 1792 : for (l = 0; l < LEV_MAX; ++l) { + 150 1536 : state->parity[l].path[0] = 0; + 151 1536 : state->parity[l].smartctl[0] = 0; + 152 1536 : state->parity[l].uuid[0] = 0; + 153 1536 : state->parity[l].device = 0; + 154 1536 : state->parity[l].total_blocks = 0; + 155 1536 : state->parity[l].free_blocks = 0; + 156 1536 : state->parity[l].tick = 0; + 157 1536 : state->parity[l].skip_access = 0; + 158 1536 : state->parity[l].is_excluded = 0; + 159 : } + 160 256 : state->tick_io = 0; + 161 256 : state->tick_cpu = 0; + 162 256 : state->tick_last = tick(); + 163 256 : state->share[0] = 0; + 164 256 : state->pool[0] = 0; + 165 256 : state->pool_device = 0; + 166 256 : state->lockfile[0] = 0; + 167 256 : state->level = 1; /* default is the lowest protection */ + 168 256 : state->clear_past_hash = 0; + 169 256 : state->no_conf = 0; + 170 : + 171 256 : tommy_list_init(&state->disklist); + 172 256 : tommy_list_init(&state->maplist); + 173 256 : tommy_list_init(&state->contentlist); + 174 256 : tommy_list_init(&state->filterlist); + 175 256 : tommy_list_init(&state->importlist); + 176 256 : tommy_hashdyn_init(&state->importset); + 177 256 : tommy_hashdyn_init(&state->previmportset); + 178 256 : tommy_hashdyn_init(&state->searchset); + 179 256 : tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info)); + 180 256 : } + 181 : + 182 234 : void state_done(struct snapraid_state* state) + 183 : { + 184 234 : tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); + 185 234 : tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free); + 186 234 : tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); + 187 234 : tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); + 188 234 : tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free); + 189 234 : tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free); + 190 234 : tommy_hashdyn_done(&state->importset); + 191 234 : tommy_hashdyn_done(&state->previmportset); + 192 234 : tommy_hashdyn_done(&state->searchset); + 193 234 : tommy_arrayblkof_done(&state->infoarr); + 194 234 : } + 195 : + 196 : /** + 197 : * Check the configuration. + 198 : */ + 199 254 : static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk) + 200 : { + 201 : tommy_node* i; + 202 : unsigned l; + 203 : + 204 : /* check for parity level */ + 205 254 : if (state->raid_mode == RAID_MODE_VANDERMONDE) { + 206 0 : if (state->level > 3) { + 207 : /* LCOV_EXCL_START */ + 208 : log_fatal("If you use the z-parity you cannot have more than 3 parities.\n"); + 209 : exit(EXIT_FAILURE); + 210 : /* LCOV_EXCL_STIO */ + 211 : } + 212 : } 213 : - 214 9301 : for (l = 0; l < state->level; ++l) { - 215 7868 : if (pathcmp(state->parity[l].path, content->content) == 0) { - 216 : /* LCOV_EXCL_START */ - 217 : log_fatal("Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content); - 218 : exit(EXIT_FAILURE); - 219 : /* LCOV_EXCL_STOP */ - 220 : } - 221 : } - 222 : } - 223 : - 224 : /* check device of data disks */ - 225 246 : if (!state->opt.skip_device && !state->opt.skip_disk_access) { - 226 0 : for (i = state->disklist; i != 0; i = i->next) { - 227 : tommy_node* j; - 228 0 : struct snapraid_disk* disk = i->data; + 214 : for (l = 0; l < state->level; ++l) { + 215 : if (state->parity[l].path[0] == 0) { + 216 : /* LCOV_EXCL_START */ + 217 : log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path); + 218 : exit(EXIT_FAILURE); + 219 : /* LCOV_EXCL_STOP */ + 220 : } + 221 : } + 222 : + 223 254 : if (tommy_list_empty(&state->contentlist)) { + 224 : /* LCOV_EXCL_START */ + 225 : log_fatal("No 'content' specification in '%s'\n", path); + 226 : exit(EXIT_FAILURE); + 227 : /* LCOV_EXCL_STOP */ + 228 : } 229 : - 230 : /* skip data disks that are not accessible */ - 231 0 : if (disk->skip_access) - 232 0 : continue; + 230 : /* check for equal paths */ + 231 1743 : for (i = state->contentlist; i != 0; i = i->next) { + 232 1489 : struct snapraid_content* content = i->data; 233 : - 234 : #ifdef _WIN32 - 235 : if (disk->device == 0) { + 234 9693 : for (l = 0; l < state->level; ++l) { + 235 8204 : if (pathcmp(state->parity[l].path, content->content) == 0) { 236 : /* LCOV_EXCL_START */ - 237 : log_fatal("Disk '%s' has a zero serial number.\n", disk->dir); - 238 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n"); - 239 : log_fatal("it's better to change the serial number of the disk.\n"); - 240 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - 241 : exit(EXIT_FAILURE); - 242 : /* LCOV_EXCL_STOP */ - 243 : } - 244 : #endif - 245 : - 246 0 : for (j = i->next; j != 0; j = j->next) { - 247 0 : struct snapraid_disk* other = j->data; - 248 0 : if (disk->device == other->device) { - 249 0 : if (state->opt.force_device) { - 250 : /* mark disks to be skipped */ - 251 0 : disk->skip_access = 1; - 252 0 : other->skip_access = 1; - 253 0 : log_fatal("DANGER! Ignoring that disks '%s' and '%s' are on the same device\n", disk->name, other->name); - 254 : } else { - 255 : /* LCOV_EXCL_START */ - 256 : log_fatal("Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir); - 257 : #ifdef _WIN32 - 258 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); - 259 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); - 260 : log_fatal("to change one of the disk serial.\n"); - 261 : #endif - 262 : /* in "fix" we allow to continue anyway */ - 263 : if (strcmp(state->command, "fix") == 0) { - 264 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 265 : } - 266 : exit(EXIT_FAILURE); - 267 : /* LCOV_EXCL_STOP */ - 268 : } - 269 : } - 270 : } - 271 : - 272 : /* skip data disks that are not accessible */ - 273 0 : if (disk->skip_access) - 274 0 : continue; - 275 : - 276 0 : if (!state->opt.skip_parity_access) { - 277 0 : for (l = 0; l < state->level; ++l) { - 278 0 : if (disk->device == state->parity[l].device) { - 279 : /* LCOV_EXCL_START */ - 280 : log_fatal("Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity[l].path); - 281 : #ifdef _WIN32 - 282 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); - 283 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); - 284 : log_fatal("to change one of the disk serial.\n"); - 285 : #endif - 286 : exit(EXIT_FAILURE); - 287 : /* LCOV_EXCL_STOP */ - 288 : } - 289 : } - 290 : } - 291 : - 292 0 : if (state->pool[0] != 0 && disk->device == state->pool_device) { - 293 : /* LCOV_EXCL_START */ - 294 : log_fatal("Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool); - 295 : #ifdef _WIN32 - 296 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); - 297 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); - 298 : log_fatal("to change one of the disk serial.\n"); - 299 : #endif - 300 : exit(EXIT_FAILURE); - 301 : /* LCOV_EXCL_STOP */ - 302 : } - 303 : } - 304 : } - 305 : - 306 : /* check device of parity disks */ - 307 246 : if (!state->opt.skip_device && !state->opt.skip_parity_access) { - 308 0 : for (l = 0; l < state->level; ++l) { - 309 : unsigned j; - 310 : - 311 : /* skip parity disks that are not accessible */ - 312 0 : if (state->parity[l].skip_access) - 313 0 : continue; - 314 : - 315 : #ifdef _WIN32 - 316 : if (state->parity[l].device == 0) { - 317 : /* LCOV_EXCL_START */ - 318 : log_fatal("Disk '%s' has a zero serial number.\n", state->parity[l].path); - 319 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n"); - 320 : log_fatal("it's better to change the serial number of the disk.\n"); - 321 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - 322 : exit(EXIT_FAILURE); - 323 : /* LCOV_EXCL_STOP */ - 324 : } - 325 : #endif + 237 : log_fatal("Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content); + 238 : exit(EXIT_FAILURE); + 239 : /* LCOV_EXCL_STOP */ + 240 : } + 241 : } + 242 : } + 243 : + 244 : /* check device of data disks */ + 245 254 : if (!state->opt.skip_device && !state->opt.skip_disk_access) { + 246 0 : for (i = state->disklist; i != 0; i = i->next) { + 247 : tommy_node* j; + 248 0 : struct snapraid_disk* disk = i->data; + 249 : + 250 : /* skip data disks that are not accessible */ + 251 0 : if (disk->skip_access) + 252 0 : continue; + 253 : + 254 : #ifdef _WIN32 + 255 : if (disk->device == 0) { + 256 : /* LCOV_EXCL_START */ + 257 : log_fatal("Disk '%s' has a zero serial number.\n", disk->dir); + 258 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + 259 : log_fatal("it's better to change the serial number of the disk.\n"); + 260 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + 261 : exit(EXIT_FAILURE); + 262 : /* LCOV_EXCL_STOP */ + 263 : } + 264 : #endif + 265 : + 266 0 : for (j = i->next; j != 0; j = j->next) { + 267 0 : struct snapraid_disk* other = j->data; + 268 0 : if (disk->device == other->device) { + 269 0 : if (state->opt.force_device) { + 270 : /* mark disks to be skipped */ + 271 0 : disk->skip_access = 1; + 272 0 : other->skip_access = 1; + 273 0 : if (!state->opt.no_warnings) + 274 0 : log_fatal("DANGER! Ignoring that disks '%s' and '%s' are on the same device\n", disk->name, other->name); + 275 : } else { + 276 : /* LCOV_EXCL_START */ + 277 : log_fatal("Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir); + 278 : #ifdef _WIN32 + 279 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + 280 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + 281 : log_fatal("to change one of the disk serial.\n"); + 282 : #endif + 283 : /* in "fix" we allow to continue anyway */ + 284 : if (strcmp(state->command, "fix") == 0) { + 285 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 286 : } + 287 : exit(EXIT_FAILURE); + 288 : /* LCOV_EXCL_STOP */ + 289 : } + 290 : } + 291 : } + 292 : + 293 : /* skip data disks that are not accessible */ + 294 0 : if (disk->skip_access) + 295 0 : continue; + 296 : + 297 0 : if (!state->opt.skip_parity_access) { + 298 0 : for (l = 0; l < state->level; ++l) { + 299 0 : if (disk->device == state->parity[l].device) { + 300 : /* LCOV_EXCL_START */ + 301 : log_fatal("Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity[l].path); + 302 : #ifdef _WIN32 + 303 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + 304 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + 305 : log_fatal("to change one of the disk serial.\n"); + 306 : #endif + 307 : exit(EXIT_FAILURE); + 308 : /* LCOV_EXCL_STOP */ + 309 : } + 310 : } + 311 : } + 312 : + 313 0 : if (state->pool[0] != 0 && disk->device == state->pool_device) { + 314 : /* LCOV_EXCL_START */ + 315 : log_fatal("Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool); + 316 : #ifdef _WIN32 + 317 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + 318 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + 319 : log_fatal("to change one of the disk serial.\n"); + 320 : #endif + 321 : exit(EXIT_FAILURE); + 322 : /* LCOV_EXCL_STOP */ + 323 : } + 324 : } + 325 : } 326 : - 327 0 : for (j = l + 1; j < state->level; ++j) { - 328 0 : if (state->parity[l].device == state->parity[j].device) { - 329 0 : if (state->opt.force_device) { - 330 : /* mark disks to be skipped */ - 331 0 : state->parity[l].skip_access = 1; - 332 0 : state->parity[j].skip_access = 1; - 333 0 : log_fatal("DANGER! Skipping parities '%s' and '%s' on the same device\n", lev_config_name(l), lev_config_name(j)); - 334 : } else { - 335 : /* LCOV_EXCL_START */ - 336 : log_fatal("Parity '%s' and '%s' are on the same device.\n", state->parity[l].path, state->parity[j].path); - 337 : #ifdef _WIN32 - 338 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->parity[l].device); - 339 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); - 340 : log_fatal("to change one of the disk serial.\n"); - 341 : #endif - 342 : /* in "fix" we allow to continue anyway */ - 343 : if (strcmp(state->command, "fix") == 0) { - 344 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 345 : } - 346 : exit(EXIT_FAILURE); - 347 : /* LCOV_EXCL_STOP */ - 348 : } - 349 : } - 350 : } - 351 : - 352 : /* skip parity disks that are not accessible */ - 353 0 : if (state->parity[l].skip_access) - 354 0 : continue; - 355 : - 356 0 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].device) { - 357 : /* LCOV_EXCL_START */ - 358 : log_fatal("Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].path); + 327 : /* check device of parity disks */ + 328 254 : if (!state->opt.skip_device && !state->opt.skip_parity_access) { + 329 0 : for (l = 0; l < state->level; ++l) { + 330 : unsigned j; + 331 : + 332 : /* skip parity disks that are not accessible */ + 333 0 : if (state->parity[l].skip_access) + 334 0 : continue; + 335 : + 336 : #ifdef _WIN32 + 337 : if (state->parity[l].device == 0) { + 338 : /* LCOV_EXCL_START */ + 339 : log_fatal("Disk '%s' has a zero serial number.\n", state->parity[l].path); + 340 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + 341 : log_fatal("it's better to change the serial number of the disk.\n"); + 342 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + 343 : exit(EXIT_FAILURE); + 344 : /* LCOV_EXCL_STOP */ + 345 : } + 346 : #endif + 347 : + 348 0 : for (j = l + 1; j < state->level; ++j) { + 349 0 : if (state->parity[l].device == state->parity[j].device) { + 350 0 : if (state->opt.force_device) { + 351 : /* mark disks to be skipped */ + 352 0 : state->parity[l].skip_access = 1; + 353 0 : state->parity[j].skip_access = 1; + 354 0 : if (!state->opt.no_warnings) + 355 0 : log_fatal("DANGER! Skipping parities '%s' and '%s' on the same device\n", lev_config_name(l), lev_config_name(j)); + 356 : } else { + 357 : /* LCOV_EXCL_START */ + 358 : log_fatal("Parity '%s' and '%s' are on the same device.\n", state->parity[l].path, state->parity[j].path); 359 : #ifdef _WIN32 - 360 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->pool_device); - 361 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); - 362 : log_fatal("to change one of the disk serial.\n"); + 360 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->parity[l].device); + 361 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + 362 : log_fatal("to change one of the disk serial.\n"); 363 : #endif - 364 : exit(EXIT_FAILURE); - 365 : /* LCOV_EXCL_STOP */ - 366 : } - 367 : } - 368 : } - 369 : - 370 : /* check device of pool disk */ - 371 : #ifdef _WIN32 - 372 : if (!state->opt.skip_device) { - 373 : if (state->pool[0] != 0 && state->pool_device == 0) { - 374 : /* LCOV_EXCL_START */ - 375 : log_fatal("Disk '%s' has a zero serial number.\n", state->pool); - 376 : log_fatal("This is not necessarely wrong, but for using SnapRAID\n"); - 377 : log_fatal("it's better to change the serial number of the disk.\n"); - 378 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); - 379 : exit(EXIT_FAILURE); - 380 : /* LCOV_EXCL_STOP */ - 381 : } - 382 : } - 383 : #endif - 384 : - 385 : /* count the content files */ - 386 246 : if (!state->opt.skip_device && !state->opt.skip_content_access) { - 387 : unsigned content_count; - 388 : - 389 0 : content_count = 0; - 390 0 : for (i = state->contentlist; i != 0; i = i->next) { - 391 : tommy_node* j; - 392 0 : struct snapraid_content* content = i->data; - 393 : - 394 : /* check if there are others in the same disk */ - 395 0 : for (j = i->next; j != 0; j = j->next) { - 396 0 : struct snapraid_content* other = j->data; - 397 0 : if (content->device == other->device) { - 398 0 : break; - 399 : } - 400 : } - 401 0 : if (j != 0) { - 402 : /* skip it */ - 403 0 : continue; - 404 : } - 405 : - 406 0 : ++content_count; - 407 : } - 408 : - 409 0 : if (content_count < state->level + 1) { - 410 : /* LCOV_EXCL_START */ - 411 : log_fatal("You must have at least %d 'content' files in different disks.\n", state->level + 1); - 412 : exit(EXIT_FAILURE); - 413 : /* LCOV_EXCL_STOP */ - 414 : } - 415 : } - 416 : - 417 : /* check for speed */ - 418 : #ifdef CONFIG_X86 - 419 246 : if (!raid_cpu_has_ssse3()) - 420 : #endif - 421 0 : if (state->raid_mode == RAID_MODE_CAUCHY) { - 422 0 : if (state->level == 3) { - 423 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation for triple parity.\n"); - 424 0 : log_fatal("WARNING! It's recommended to switch to 'z-parity' instead than '3-parity'.\n"); - 425 0 : } else if (state->level > 3) { - 426 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n"); - 427 0 : log_fatal("WARNING! It's recommended to reduce the parity levels to triple parity.\n"); - 428 : } - 429 : } + 364 : /* in "fix" we allow to continue anyway */ + 365 : if (strcmp(state->command, "fix") == 0) { + 366 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 367 : } + 368 : exit(EXIT_FAILURE); + 369 : /* LCOV_EXCL_STOP */ + 370 : } + 371 : } + 372 : } + 373 : + 374 : /* skip parity disks that are not accessible */ + 375 0 : if (state->parity[l].skip_access) + 376 0 : continue; + 377 : + 378 0 : if (state->pool[0] != 0 && state->pool_device == state->parity[l].device) { + 379 : /* LCOV_EXCL_START */ + 380 : log_fatal("Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].path); + 381 : #ifdef _WIN32 + 382 : log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->pool_device); + 383 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + 384 : log_fatal("to change one of the disk serial.\n"); + 385 : #endif + 386 : exit(EXIT_FAILURE); + 387 : /* LCOV_EXCL_STOP */ + 388 : } + 389 : } + 390 : } + 391 : + 392 : /* check device of pool disk */ + 393 : #ifdef _WIN32 + 394 : if (!state->opt.skip_device) { + 395 : if (state->pool[0] != 0 && state->pool_device == 0) { + 396 : /* LCOV_EXCL_START */ + 397 : log_fatal("Disk '%s' has a zero serial number.\n", state->pool); + 398 : log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + 399 : log_fatal("it's better to change the serial number of the disk.\n"); + 400 : log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + 401 : exit(EXIT_FAILURE); + 402 : /* LCOV_EXCL_STOP */ + 403 : } + 404 : } + 405 : #endif + 406 : + 407 : /* count the content files */ + 408 254 : if (!state->opt.skip_device && !state->opt.skip_content_access) { + 409 : unsigned content_count; + 410 : + 411 0 : content_count = 0; + 412 0 : for (i = state->contentlist; i != 0; i = i->next) { + 413 : tommy_node* j; + 414 0 : struct snapraid_content* content = i->data; + 415 : + 416 : /* check if there are others in the same disk */ + 417 0 : for (j = i->next; j != 0; j = j->next) { + 418 0 : struct snapraid_content* other = j->data; + 419 0 : if (content->device == other->device) { + 420 0 : break; + 421 : } + 422 : } + 423 0 : if (j != 0) { + 424 : /* skip it */ + 425 0 : continue; + 426 : } + 427 : + 428 0 : ++content_count; + 429 : } 430 : - 431 : /* ensure that specified filter disks are valid ones */ - 432 254 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { - 433 : tommy_node* j; - 434 8 : struct snapraid_filter* filter = i->data; - 435 43 : for (j = state->disklist; j != 0; j = j->next) { - 436 38 : struct snapraid_disk* disk = j->data; - 437 38 : if (fnmatch(filter->pattern, disk->name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) - 438 3 : break; - 439 : } - 440 8 : if (j == 0) { - 441 : /* check matching with parity disks */ - 442 20 : for (l = 0; l < state->level; ++l) - 443 20 : if (fnmatch(filter->pattern, lev_config_name(l), FNM_CASEINSENSITIVE_FOR_WIN) == 0) - 444 5 : break; - 445 5 : if (l == state->level) { - 446 : /* LCOV_EXCL_START */ - 447 : log_fatal("Option -d, --filter-disk %s doesn't match any data or parity disk.\n", filter->pattern); - 448 : exit(EXIT_FAILURE); - 449 : /* LCOV_EXCL_STOP */ - 450 : } - 451 : } - 452 : } - 453 246 : } - 454 : - 455 : /** - 456 : * Validate the smartctl command. - 457 : * - 458 : * It must contains only one %s string, and not other % chars. - 459 : */ - 460 344 : static int validate_smartctl(const char* custom) - 461 : { - 462 344 : const char* s = custom; - 463 344 : int arg = 0; - 464 : - 465 2408 : while (*s) { - 466 1720 : if (s[0] == '%' && s[1] == 's') { - 467 172 : if (arg) { + 431 0 : if (content_count < state->level + 1) { + 432 : /* LCOV_EXCL_START */ + 433 : log_fatal("You must have at least %d 'content' files in different disks.\n", state->level + 1); + 434 : exit(EXIT_FAILURE); + 435 : /* LCOV_EXCL_STOP */ + 436 : } + 437 : } + 438 : + 439 : /* check for speed */ + 440 : #ifdef CONFIG_X86 + 441 254 : if (!raid_cpu_has_ssse3()) + 442 : #endif + 443 0 : if (state->raid_mode == RAID_MODE_CAUCHY && !state->opt.no_warnings) { + 444 0 : if (state->level == 3) { + 445 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation for triple parity.\n"); + 446 0 : log_fatal("WARNING! It's recommended to switch to 'z-parity' instead than '3-parity'.\n"); + 447 0 : } else if (state->level > 3) { + 448 0 : log_fatal("WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n"); + 449 0 : log_fatal("WARNING! It's recommended to reduce the parity levels to triple parity.\n"); + 450 : } + 451 : } + 452 : + 453 : /* ensure that specified filter disks are valid ones */ + 454 262 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + 455 : tommy_node* j; + 456 8 : struct snapraid_filter* filter = i->data; + 457 43 : for (j = state->disklist; j != 0; j = j->next) { + 458 38 : struct snapraid_disk* disk = j->data; + 459 38 : if (fnmatch(filter->pattern, disk->name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 460 3 : break; + 461 : } + 462 8 : if (j == 0) { + 463 : /* check matching with parity disks */ + 464 20 : for (l = 0; l < state->level; ++l) + 465 20 : if (fnmatch(filter->pattern, lev_config_name(l), FNM_CASEINSENSITIVE_FOR_WIN) == 0) + 466 5 : break; + 467 5 : if (l == state->level) { 468 : /* LCOV_EXCL_START */ - 469 : return -1; - 470 : /* LCOV_EXCL_STOP */ - 471 : } - 472 172 : arg = 1; - 473 1548 : } else if (s[0] == '%') { - 474 : /* LCOV_EXCL_START */ - 475 : return -1; - 476 : /* LCOV_EXCL_STOP */ - 477 : } - 478 : - 479 1720 : ++s; - 480 : } - 481 : - 482 344 : return 0; - 483 : } - 484 : - 485 247 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk) - 486 : { - 487 : STREAM* f; - 488 : unsigned line; - 489 : tommy_node* i; - 490 : unsigned l; - 491 : - 492 : /* copy the options */ - 493 247 : state->opt = *opt; - 494 : - 495 : /* if unset, sort by physical order */ - 496 247 : if (!state->opt.force_order) - 497 1 : state->opt.force_order = SORT_PHYSICAL; - 498 : - 499 : /* adjust file mode */ - 500 247 : if (state->opt.skip_sequential) - 501 1 : state->file_mode &= ~MODE_SEQUENTIAL; - 502 : - 503 : /* store current command */ - 504 247 : state->command = command; - 505 : - 506 247 : log_tag("conf:%s\n", path); - 507 : - 508 247 : f = sopen_read(path); - 509 247 : if (!f) { - 510 : /* LCOV_EXCL_START */ - 511 : if (errno == ENOENT) { - 512 : log_fatal("No configuration file found at '%s'\n", path); - 513 : } else if (errno == EACCES) { - 514 : log_fatal("You do not have rights to access the configuration file '%s'\n", path); - 515 : } else { - 516 : log_fatal("Error opening the configuration file '%s'. %s.\n", path, strerror(errno)); - 517 : } - 518 : exit(EXIT_FAILURE); - 519 : /* LCOV_EXCL_STOP */ - 520 : } - 521 : - 522 247 : line = 1; - 523 : while (1) { - 524 : char tag[PATH_MAX]; - 525 : char buffer[PATH_MAX]; - 526 : int ret; - 527 : int c; - 528 : unsigned level; + 469 : log_fatal("Option -d, --filter-disk %s doesn't match any data or parity disk.\n", filter->pattern); + 470 : exit(EXIT_FAILURE); + 471 : /* LCOV_EXCL_STOP */ + 472 : } + 473 : } + 474 : } + 475 254 : } + 476 : + 477 : /** + 478 : * Validate the smartctl command. + 479 : * + 480 : * It must contains only one %s string, and not other % chars. + 481 : */ + 482 358 : static int validate_smartctl(const char* custom) + 483 : { + 484 358 : const char* s = custom; + 485 358 : int arg = 0; + 486 : + 487 2506 : while (*s) { + 488 1790 : if (s[0] == '%' && s[1] == 's') { + 489 179 : if (arg) { + 490 : /* LCOV_EXCL_START */ + 491 : return -1; + 492 : /* LCOV_EXCL_STOP */ + 493 : } + 494 179 : arg = 1; + 495 1611 : } else if (s[0] == '%') { + 496 : /* LCOV_EXCL_START */ + 497 : return -1; + 498 : /* LCOV_EXCL_STOP */ + 499 : } + 500 : + 501 1790 : ++s; + 502 : } + 503 : + 504 358 : return 0; + 505 : } + 506 : + 507 255 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk) + 508 : { + 509 : STREAM* f; + 510 : unsigned line; + 511 : tommy_node* i; + 512 : unsigned l; + 513 : + 514 : /* copy the options */ + 515 255 : state->opt = *opt; + 516 : + 517 : /* if unset, sort by physical order */ + 518 255 : if (!state->opt.force_order) + 519 1 : state->opt.force_order = SORT_PHYSICAL; + 520 : + 521 : /* adjust file mode */ + 522 255 : if (state->opt.skip_sequential) + 523 1 : state->file_mode &= ~MODE_SEQUENTIAL; + 524 : + 525 : /* store current command */ + 526 255 : state->command = command; + 527 : + 528 255 : log_tag("conf:%s\n", path); 529 : - 530 : /* skip initial spaces */ - 531 5808 : sgetspace(f); - 532 : - 533 : /* read the command */ - 534 5808 : ret = sgettok(f, tag, sizeof(tag)); - 535 5808 : if (ret < 0) { - 536 : /* LCOV_EXCL_START */ - 537 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); - 538 : exit(EXIT_FAILURE); - 539 : /* LCOV_EXCL_STOP */ - 540 : } - 541 : - 542 : /* skip spaces after the command */ - 543 5808 : sgetspace(f); - 544 : - 545 5808 : if (strcmp(tag, "blocksize") == 0 - 546 : /* block_size is the old format of the option */ - 547 5561 : || strcmp(tag, "block_size") == 0) { - 548 : - 549 247 : ret = sgetu32(f, &state->block_size); - 550 247 : if (ret < 0) { - 551 : /* LCOV_EXCL_START */ - 552 : log_fatal("Invalid 'blocksize' specification in '%s' at line %u\n", path, line); - 553 : exit(EXIT_FAILURE); - 554 : /* LCOV_EXCL_STOP */ - 555 : } - 556 247 : if (state->block_size < 1) { - 557 : /* LCOV_EXCL_START */ - 558 : log_fatal("Too small 'blocksize' specification in '%s' at line %u\n", path, line); - 559 : exit(EXIT_FAILURE); - 560 : /* LCOV_EXCL_STOP */ - 561 : } - 562 247 : if (state->block_size > 16 * 1024) { - 563 : /* LCOV_EXCL_START */ - 564 : log_fatal("Too big 'blocksize' specification in '%s' at line %u\n", path, line); - 565 : exit(EXIT_FAILURE); - 566 : /* LCOV_EXCL_STOP */ - 567 : } - 568 : /* check if it's a power of 2 */ - 569 247 : if ((state->block_size & (state->block_size - 1)) != 0) { - 570 : /* LCOV_EXCL_START */ - 571 : log_fatal("Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line); - 572 : exit(EXIT_FAILURE); - 573 : /* LCOV_EXCL_STOP */ - 574 : } - 575 247 : state->block_size *= 1024; - 576 5561 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { - 577 : char device[PATH_MAX]; - 578 : char* slash; - 579 : uint64_t dev; - 580 : int skip_access; - 581 : - 582 1193 : if (*state->parity[level].path) { - 583 : /* LCOV_EXCL_START */ - 584 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line); - 585 : exit(EXIT_FAILURE); - 586 : /* LCOV_EXCL_STOP */ - 587 : } - 588 : - 589 1193 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 590 1193 : if (ret < 0) { - 591 : /* LCOV_EXCL_START */ - 592 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - 593 : exit(EXIT_FAILURE); - 594 : /* LCOV_EXCL_STOP */ - 595 : } - 596 : - 597 1193 : if (!*buffer) { - 598 : /* LCOV_EXCL_START */ - 599 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line); - 600 : exit(EXIT_FAILURE); - 601 : /* LCOV_EXCL_STOP */ - 602 : } + 530 255 : f = sopen_read(path); + 531 255 : if (!f) { + 532 : /* LCOV_EXCL_START */ + 533 : if (errno == ENOENT) { + 534 : log_fatal("No configuration file found at '%s'\n", path); + 535 : } else if (errno == EACCES) { + 536 : log_fatal("You do not have rights to access the configuration file '%s'\n", path); + 537 : } else { + 538 : log_fatal("Error opening the configuration file '%s'. %s.\n", path, strerror(errno)); + 539 : } + 540 : exit(EXIT_FAILURE); + 541 : /* LCOV_EXCL_STOP */ + 542 : } + 543 : + 544 255 : line = 1; + 545 : while (1) { + 546 : char tag[PATH_MAX]; + 547 : char buffer[PATH_MAX]; + 548 : int ret; + 549 : int c; + 550 : unsigned level; + 551 : + 552 : /* skip initial spaces */ + 553 6015 : sgetspace(f); + 554 : + 555 : /* read the command */ + 556 6015 : ret = sgettok(f, tag, sizeof(tag)); + 557 6015 : if (ret < 0) { + 558 : /* LCOV_EXCL_START */ + 559 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); + 560 : exit(EXIT_FAILURE); + 561 : /* LCOV_EXCL_STOP */ + 562 : } + 563 : + 564 : /* skip spaces after the command */ + 565 6015 : sgetspace(f); + 566 : + 567 6015 : if (strcmp(tag, "blocksize") == 0 + 568 : /* block_size is the old format of the option */ + 569 5760 : || strcmp(tag, "block_size") == 0) { + 570 : + 571 255 : ret = sgetu32(f, &state->block_size); + 572 255 : if (ret < 0) { + 573 : /* LCOV_EXCL_START */ + 574 : log_fatal("Invalid 'blocksize' specification in '%s' at line %u\n", path, line); + 575 : exit(EXIT_FAILURE); + 576 : /* LCOV_EXCL_STOP */ + 577 : } + 578 255 : if (state->block_size < 1) { + 579 : /* LCOV_EXCL_START */ + 580 : log_fatal("Too small 'blocksize' specification in '%s' at line %u\n", path, line); + 581 : exit(EXIT_FAILURE); + 582 : /* LCOV_EXCL_STOP */ + 583 : } + 584 255 : if (state->block_size > 16 * 1024) { + 585 : /* LCOV_EXCL_START */ + 586 : log_fatal("Too big 'blocksize' specification in '%s' at line %u\n", path, line); + 587 : exit(EXIT_FAILURE); + 588 : /* LCOV_EXCL_STOP */ + 589 : } + 590 : /* check if it's a power of 2 */ + 591 255 : if ((state->block_size & (state->block_size - 1)) != 0) { + 592 : /* LCOV_EXCL_START */ + 593 : log_fatal("Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line); + 594 : exit(EXIT_FAILURE); + 595 : /* LCOV_EXCL_STOP */ + 596 : } + 597 255 : state->block_size *= 1024; + 598 5760 : } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { + 599 : char device[PATH_MAX]; + 600 : char* slash; + 601 : uint64_t dev; + 602 : int skip_access; 603 : - 604 1193 : pathimport(state->parity[level].path, sizeof(state->parity[level].path), buffer); - 605 : - 606 1193 : skip_access = 0; - 607 1193 : if (!state->opt.skip_parity_access) { - 608 : struct stat st; - 609 : - 610 : /* get the device of the directory containing the parity file */ - 611 1018 : pathimport(device, sizeof(device), buffer); - 612 1018 : slash = strrchr(device, '/'); - 613 1018 : if (slash) - 614 1018 : *slash = 0; - 615 : else - 616 0 : pathcpy(device, sizeof(device), "."); - 617 : - 618 1018 : if (stat(device, &st) == 0) { - 619 1016 : dev = st.st_dev; - 620 : } else { - 621 : /* if the disk can be skipped */ - 622 2 : if (state->opt.force_device) { - 623 : /* use a fake device, and mark the disk to be skipped */ - 624 1 : dev = 0; - 625 1 : skip_access = 1; - 626 1 : log_fatal("DANGER! Skipping unaccessible parity disk '%s'...\n", tag); - 627 : } else { - 628 : /* LCOV_EXCL_START */ - 629 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line); - 630 : - 631 : /* in "fix" we allow to continue anyway */ - 632 : if (strcmp(state->command, "fix") == 0) { - 633 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 634 : } - 635 : exit(EXIT_FAILURE); - 636 : /* LCOV_EXCL_STOP */ - 637 : } - 638 : } - 639 : } else { - 640 : /* use a fake device */ - 641 175 : dev = 0; - 642 : } - 643 : - 644 1192 : state->parity[level].device = dev; - 645 1192 : state->parity[level].skip_access = skip_access; - 646 : - 647 : /* adjust the level */ - 648 1192 : if (state->level < level + 1) - 649 945 : state->level = level + 1; - 650 4368 : } else if (strcmp(tag, "share") == 0) { - 651 34 : if (*state->share) { - 652 : /* LCOV_EXCL_START */ - 653 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line); - 654 : exit(EXIT_FAILURE); - 655 : /* LCOV_EXCL_STOP */ - 656 : } - 657 : - 658 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 659 34 : if (ret < 0) { - 660 : /* LCOV_EXCL_START */ - 661 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line); - 662 : exit(EXIT_FAILURE); - 663 : /* LCOV_EXCL_STOP */ + 604 1241 : if (*state->parity[level].path) { + 605 : /* LCOV_EXCL_START */ + 606 : log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line); + 607 : exit(EXIT_FAILURE); + 608 : /* LCOV_EXCL_STOP */ + 609 : } + 610 : + 611 1241 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 612 1241 : if (ret < 0) { + 613 : /* LCOV_EXCL_START */ + 614 : log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); + 615 : exit(EXIT_FAILURE); + 616 : /* LCOV_EXCL_STOP */ + 617 : } + 618 : + 619 1241 : if (!*buffer) { + 620 : /* LCOV_EXCL_START */ + 621 : log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line); + 622 : exit(EXIT_FAILURE); + 623 : /* LCOV_EXCL_STOP */ + 624 : } + 625 : + 626 1241 : pathimport(state->parity[level].path, sizeof(state->parity[level].path), buffer); + 627 : + 628 1241 : skip_access = 0; + 629 1241 : if (!state->opt.skip_parity_access) { + 630 : struct stat st; + 631 : + 632 : /* get the device of the directory containing the parity file */ + 633 1066 : pathimport(device, sizeof(device), buffer); + 634 1066 : slash = strrchr(device, '/'); + 635 1066 : if (slash) + 636 1066 : *slash = 0; + 637 : else + 638 0 : pathcpy(device, sizeof(device), "."); + 639 : + 640 1066 : if (stat(device, &st) == 0) { + 641 1064 : dev = st.st_dev; + 642 : } else { + 643 : /* if the disk can be skipped */ + 644 2 : if (state->opt.force_device) { + 645 : /* use a fake device, and mark the disk to be skipped */ + 646 1 : dev = 0; + 647 1 : skip_access = 1; + 648 1 : log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag); + 649 : } else { + 650 : /* LCOV_EXCL_START */ + 651 : log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line); + 652 : + 653 : /* in "fix" we allow to continue anyway */ + 654 : if (strcmp(state->command, "fix") == 0) { + 655 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 656 : } + 657 : exit(EXIT_FAILURE); + 658 : /* LCOV_EXCL_STOP */ + 659 : } + 660 : } + 661 : } else { + 662 : /* use a fake device */ + 663 175 : dev = 0; 664 : } 665 : - 666 34 : if (!*buffer) { - 667 : /* LCOV_EXCL_START */ - 668 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line); - 669 : exit(EXIT_FAILURE); - 670 : /* LCOV_EXCL_STOP */ - 671 : } - 672 : - 673 34 : pathimport(state->share, sizeof(state->share), buffer); - 674 4334 : } else if (strcmp(tag, "pool") == 0) { - 675 : struct stat st; - 676 : - 677 34 : if (*state->pool) { - 678 : /* LCOV_EXCL_START */ - 679 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line); - 680 : exit(EXIT_FAILURE); - 681 : /* LCOV_EXCL_STOP */ - 682 : } - 683 : - 684 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 685 34 : if (ret < 0) { - 686 : /* LCOV_EXCL_START */ - 687 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line); - 688 : exit(EXIT_FAILURE); - 689 : /* LCOV_EXCL_STOP */ - 690 : } - 691 : - 692 34 : if (!*buffer) { - 693 : /* LCOV_EXCL_START */ - 694 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line); - 695 : exit(EXIT_FAILURE); - 696 : /* LCOV_EXCL_STOP */ - 697 : } + 666 1240 : state->parity[level].device = dev; + 667 1240 : state->parity[level].skip_access = skip_access; + 668 : + 669 : /* adjust the level */ + 670 1240 : if (state->level < level + 1) + 671 985 : state->level = level + 1; + 672 4519 : } else if (strcmp(tag, "share") == 0) { + 673 34 : if (*state->share) { + 674 : /* LCOV_EXCL_START */ + 675 : log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line); + 676 : exit(EXIT_FAILURE); + 677 : /* LCOV_EXCL_STOP */ + 678 : } + 679 : + 680 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 681 34 : if (ret < 0) { + 682 : /* LCOV_EXCL_START */ + 683 : log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line); + 684 : exit(EXIT_FAILURE); + 685 : /* LCOV_EXCL_STOP */ + 686 : } + 687 : + 688 34 : if (!*buffer) { + 689 : /* LCOV_EXCL_START */ + 690 : log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line); + 691 : exit(EXIT_FAILURE); + 692 : /* LCOV_EXCL_STOP */ + 693 : } + 694 : + 695 34 : pathimport(state->share, sizeof(state->share), buffer); + 696 4485 : } else if (strcmp(tag, "pool") == 0) { + 697 : struct stat st; 698 : - 699 34 : pathimport(state->pool, sizeof(state->pool), buffer); - 700 : - 701 : /* get the device of the directory containing the pool tree */ - 702 34 : if (stat(buffer, &st) != 0) { - 703 : /* LCOV_EXCL_START */ - 704 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); - 705 : exit(EXIT_FAILURE); - 706 : /* LCOV_EXCL_STOP */ - 707 : } - 708 : - 709 34 : state->pool_device = st.st_dev; - 710 4300 : } else if (strcmp(tag, "content") == 0) { - 711 : struct snapraid_content* content; - 712 : char device[PATH_MAX]; - 713 : char* slash; - 714 : struct stat st; - 715 : uint64_t dev; - 716 : - 717 1433 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 718 1433 : if (ret < 0) { - 719 : /* LCOV_EXCL_START */ - 720 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line); - 721 : exit(EXIT_FAILURE); - 722 : /* LCOV_EXCL_STOP */ - 723 : } - 724 : - 725 1433 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { - 726 : /* LCOV_EXCL_START */ - 727 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); - 728 : exit(EXIT_FAILURE); - 729 : /* LCOV_EXCL_STOP */ - 730 : } - 731 : - 732 1433 : if (!*buffer) { - 733 : /* LCOV_EXCL_START */ - 734 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line); - 735 : exit(EXIT_FAILURE); - 736 : /* LCOV_EXCL_STOP */ - 737 : } + 699 34 : if (*state->pool) { + 700 : /* LCOV_EXCL_START */ + 701 : log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line); + 702 : exit(EXIT_FAILURE); + 703 : /* LCOV_EXCL_STOP */ + 704 : } + 705 : + 706 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 707 34 : if (ret < 0) { + 708 : /* LCOV_EXCL_START */ + 709 : log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line); + 710 : exit(EXIT_FAILURE); + 711 : /* LCOV_EXCL_STOP */ + 712 : } + 713 : + 714 34 : if (!*buffer) { + 715 : /* LCOV_EXCL_START */ + 716 : log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line); + 717 : exit(EXIT_FAILURE); + 718 : /* LCOV_EXCL_STOP */ + 719 : } + 720 : + 721 34 : pathimport(state->pool, sizeof(state->pool), buffer); + 722 : + 723 : /* get the device of the directory containing the pool tree */ + 724 34 : if (stat(buffer, &st) != 0) { + 725 : /* LCOV_EXCL_START */ + 726 : log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); + 727 : exit(EXIT_FAILURE); + 728 : /* LCOV_EXCL_STOP */ + 729 : } + 730 : + 731 34 : state->pool_device = st.st_dev; + 732 4451 : } else if (strcmp(tag, "content") == 0) { + 733 : struct snapraid_content* content; + 734 : char device[PATH_MAX]; + 735 : char* slash; + 736 : struct stat st; + 737 : uint64_t dev; 738 : - 739 : /* check if the content file is already specified */ - 740 5367 : for (i = state->contentlist; i != 0; i = i->next) { - 741 3934 : content = i->data; - 742 3934 : if (pathcmp(content->content, buffer) == 0) - 743 0 : break; - 744 : } - 745 1433 : if (i) { - 746 : /* LCOV_EXCL_START */ - 747 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line); - 748 : exit(EXIT_FAILURE); - 749 : /* LCOV_EXCL_STOP */ - 750 : } - 751 : - 752 : /* get the device of the directory containing the content file */ - 753 1433 : pathimport(device, sizeof(device), buffer); - 754 1433 : slash = strrchr(device, '/'); - 755 1433 : if (slash) - 756 1433 : *slash = 0; - 757 : else - 758 0 : pathcpy(device, sizeof(device), "."); - 759 1433 : if (stat(device, &st) == 0) { - 760 1432 : dev = st.st_dev; - 761 : } else { - 762 1 : if (state->opt.skip_content_access) { - 763 : /* use a fake device */ - 764 1 : dev = 0; - 765 1 : log_fatal("WARNING! Skipping unaccessible content file '%s'...\n", buffer); - 766 : } else { - 767 : /* LCOV_EXCL_START */ - 768 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line); - 769 : exit(EXIT_FAILURE); - 770 : /* LCOV_EXCL_STOP */ - 771 : } + 739 1489 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 740 1489 : if (ret < 0) { + 741 : /* LCOV_EXCL_START */ + 742 : log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line); + 743 : exit(EXIT_FAILURE); + 744 : /* LCOV_EXCL_STOP */ + 745 : } + 746 : + 747 1489 : if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { + 748 : /* LCOV_EXCL_START */ + 749 : log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); + 750 : exit(EXIT_FAILURE); + 751 : /* LCOV_EXCL_STOP */ + 752 : } + 753 : + 754 1489 : if (!*buffer) { + 755 : /* LCOV_EXCL_START */ + 756 : log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line); + 757 : exit(EXIT_FAILURE); + 758 : /* LCOV_EXCL_STOP */ + 759 : } + 760 : + 761 : /* check if the content file is already specified */ + 762 5591 : for (i = state->contentlist; i != 0; i = i->next) { + 763 4102 : content = i->data; + 764 4102 : if (pathcmp(content->content, buffer) == 0) + 765 0 : break; + 766 : } + 767 1489 : if (i) { + 768 : /* LCOV_EXCL_START */ + 769 : log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line); + 770 : exit(EXIT_FAILURE); + 771 : /* LCOV_EXCL_STOP */ 772 : } 773 : - 774 : /* set the lock file at the first accessible content file */ - 775 1433 : if (state->lockfile[0] == 0 && dev != 0) { - 776 246 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); - 777 246 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); - 778 : } - 779 : - 780 1433 : content = content_alloc(buffer, dev); - 781 : - 782 1433 : tommy_list_insert_tail(&state->contentlist, &content->node, content); - 783 2867 : } else if (strcmp(tag, "disk") == 0) { - 784 : char dir[PATH_MAX]; - 785 : char device[PATH_MAX]; - 786 : struct snapraid_disk* disk; - 787 : uint64_t dev; - 788 : int skip_access; - 789 : - 790 1471 : ret = sgettok(f, buffer, sizeof(buffer)); - 791 1471 : if (ret < 0) { - 792 : /* LCOV_EXCL_START */ - 793 : log_fatal("Invalid 'disk' name specification in '%s' at line %u\n", path, line); - 794 : exit(EXIT_FAILURE); - 795 : /* LCOV_EXCL_STOP */ - 796 : } - 797 : - 798 1471 : if (!*buffer) { - 799 : /* LCOV_EXCL_START */ - 800 : log_fatal("Empty 'disk' name specification in '%s' at line %u\n", path, line); - 801 : exit(EXIT_FAILURE); - 802 : /* LCOV_EXCL_STOP */ - 803 : } - 804 : - 805 1471 : sgetspace(f); - 806 : - 807 1471 : ret = sgetlasttok(f, dir, sizeof(dir)); - 808 1471 : if (ret < 0) { - 809 : /* LCOV_EXCL_START */ - 810 : log_fatal("Invalid 'disk' dir specification in '%s' at line %u\n", path, line); - 811 : exit(EXIT_FAILURE); - 812 : /* LCOV_EXCL_STOP */ - 813 : } - 814 : - 815 1471 : if (!*dir) { - 816 : /* LCOV_EXCL_START */ - 817 : log_fatal("Empty 'disk' dir specification in '%s' at line %u\n", path, line); - 818 : exit(EXIT_FAILURE); - 819 : /* LCOV_EXCL_STOP */ - 820 : } - 821 : - 822 : /* get the device of the dir */ - 823 1471 : pathimport(device, sizeof(device), dir); - 824 : - 825 : /* check if the disk name already exists */ - 826 5136 : for (i = state->disklist; i != 0; i = i->next) { - 827 3665 : disk = i->data; - 828 3665 : if (strcmp(disk->name, buffer) == 0) - 829 0 : break; - 830 : } - 831 1471 : if (i) { + 774 : /* get the device of the directory containing the content file */ + 775 1489 : pathimport(device, sizeof(device), buffer); + 776 1489 : slash = strrchr(device, '/'); + 777 1489 : if (slash) + 778 1489 : *slash = 0; + 779 : else + 780 0 : pathcpy(device, sizeof(device), "."); + 781 1489 : if (stat(device, &st) == 0) { + 782 1488 : dev = st.st_dev; + 783 : } else { + 784 1 : if (state->opt.skip_content_access) { + 785 : /* use a fake device */ + 786 1 : dev = 0; + 787 1 : log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer); + 788 : } else { + 789 : /* LCOV_EXCL_START */ + 790 : log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line); + 791 : exit(EXIT_FAILURE); + 792 : /* LCOV_EXCL_STOP */ + 793 : } + 794 : } + 795 : + 796 : /* set the lock file at the first accessible content file */ + 797 1489 : if (state->lockfile[0] == 0 && dev != 0) { + 798 254 : pathcpy(state->lockfile, sizeof(state->lockfile), buffer); + 799 254 : pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); + 800 : } + 801 : + 802 1489 : content = content_alloc(buffer, dev); + 803 : + 804 1489 : tommy_list_insert_tail(&state->contentlist, &content->node, content); + 805 2962 : } else if (strcmp(tag, "disk") == 0) { + 806 : char dir[PATH_MAX]; + 807 : char device[PATH_MAX]; + 808 : char uuid[UUID_MAX]; + 809 : struct snapraid_disk* disk; + 810 : uint64_t dev; + 811 : int skip_access; + 812 : + 813 1519 : ret = sgettok(f, buffer, sizeof(buffer)); + 814 1519 : if (ret < 0) { + 815 : /* LCOV_EXCL_START */ + 816 : log_fatal("Invalid 'disk' name specification in '%s' at line %u\n", path, line); + 817 : exit(EXIT_FAILURE); + 818 : /* LCOV_EXCL_STOP */ + 819 : } + 820 : + 821 1519 : if (!*buffer) { + 822 : /* LCOV_EXCL_START */ + 823 : log_fatal("Empty 'disk' name specification in '%s' at line %u\n", path, line); + 824 : exit(EXIT_FAILURE); + 825 : /* LCOV_EXCL_STOP */ + 826 : } + 827 : + 828 1519 : sgetspace(f); + 829 : + 830 1519 : ret = sgetlasttok(f, dir, sizeof(dir)); + 831 1519 : if (ret < 0) { 832 : /* LCOV_EXCL_START */ - 833 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); + 833 : log_fatal("Invalid 'disk' dir specification in '%s' at line %u\n", path, line); 834 : exit(EXIT_FAILURE); 835 : /* LCOV_EXCL_STOP */ 836 : } 837 : - 838 : /* if the disk has to be present */ - 839 1471 : skip_access = 0; - 840 1471 : if (!state->opt.skip_disk_access) { - 841 : struct stat st; - 842 : - 843 1327 : if (stat(device, &st) == 0) { - 844 1326 : dev = st.st_dev; - 845 : } else { - 846 : /* if the disk can be skipped */ - 847 1 : if (state->opt.force_device) { - 848 : /* use a fake device, and mark the disk to be skipped */ - 849 1 : dev = 0; - 850 1 : skip_access = 1; - 851 1 : log_fatal("DANGER! Skipping unaccessible data disk '%s'...\n", buffer); - 852 : } else { - 853 : /* LCOV_EXCL_START */ - 854 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line); - 855 : - 856 : /* in "fix" we allow to continue anyway */ - 857 : if (strcmp(state->command, "fix") == 0) { - 858 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); - 859 : } - 860 : exit(EXIT_FAILURE); - 861 : /* LCOV_EXCL_STOP */ - 862 : } - 863 : } - 864 : } else { - 865 : /* use a fake device */ - 866 144 : dev = 0; - 867 : } + 838 1519 : if (!*dir) { + 839 : /* LCOV_EXCL_START */ + 840 : log_fatal("Empty 'disk' dir specification in '%s' at line %u\n", path, line); + 841 : exit(EXIT_FAILURE); + 842 : /* LCOV_EXCL_STOP */ + 843 : } + 844 : + 845 : /* get the device of the dir */ + 846 1519 : pathimport(device, sizeof(device), dir); + 847 : + 848 : /* check if the disk name already exists */ + 849 5304 : for (i = state->disklist; i != 0; i = i->next) { + 850 3785 : disk = i->data; + 851 3785 : if (strcmp(disk->name, buffer) == 0) + 852 0 : break; + 853 : } + 854 1519 : if (i) { + 855 : /* LCOV_EXCL_START */ + 856 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); + 857 : exit(EXIT_FAILURE); + 858 : /* LCOV_EXCL_STOP */ + 859 : } + 860 : + 861 : /* if the disk has to be present */ + 862 1519 : skip_access = 0; + 863 1519 : if (!state->opt.skip_disk_access) { + 864 : struct stat st; + 865 : + 866 1375 : if (stat(device, &st) == 0) { + 867 1374 : dev = st.st_dev; 868 : - 869 1471 : disk = disk_alloc(buffer, dir, dev, skip_access); - 870 : - 871 1471 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); - 872 1396 : } else if (strcmp(tag, "smartctl") == 0) { - 873 : char custom[PATH_MAX]; - 874 : - 875 344 : ret = sgettok(f, buffer, sizeof(buffer)); - 876 344 : if (ret < 0) { - 877 : /* LCOV_EXCL_START */ - 878 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); - 879 : exit(EXIT_FAILURE); - 880 : /* LCOV_EXCL_STOP */ - 881 : } - 882 : - 883 344 : if (!*buffer) { - 884 : /* LCOV_EXCL_START */ - 885 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); - 886 : exit(EXIT_FAILURE); - 887 : /* LCOV_EXCL_STOP */ - 888 : } - 889 : - 890 344 : sgetspace(f); - 891 : - 892 344 : ret = sgetlasttok(f, custom, sizeof(custom)); - 893 344 : if (ret < 0) { - 894 : /* LCOV_EXCL_START */ - 895 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); - 896 : exit(EXIT_FAILURE); - 897 : /* LCOV_EXCL_STOP */ - 898 : } - 899 : - 900 344 : if (!*custom) { - 901 : /* LCOV_EXCL_START */ - 902 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); - 903 : exit(EXIT_FAILURE); - 904 : /* LCOV_EXCL_STOP */ - 905 : } + 869 : /* read the uuid, if unsupported use an empty one */ + 870 1374 : if (devuuid(dev, uuid, sizeof(uuid)) != 0) { + 871 0 : *uuid = 0; + 872 : } + 873 : + 874 : /* fake a different UUID when testing */ + 875 1374 : if (state->opt.fake_uuid) { + 876 2 : snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid); + 877 2 : --state->opt.fake_uuid; + 878 : } + 879 : } else { + 880 : /* if the disk can be skipped */ + 881 1 : if (state->opt.force_device) { + 882 : /* use a fake device, and mark the disk to be skipped */ + 883 1 : dev = 0; + 884 1 : *uuid = 0; + 885 1 : skip_access = 1; + 886 1 : log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer); + 887 : } else { + 888 : /* LCOV_EXCL_START */ + 889 : log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line); + 890 : + 891 : /* in "fix" we allow to continue anyway */ + 892 : if (strcmp(state->command, "fix") == 0) { + 893 : log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + 894 : } + 895 : exit(EXIT_FAILURE); + 896 : /* LCOV_EXCL_STOP */ + 897 : } + 898 : } + 899 : } else { + 900 : /* use a fake device */ + 901 144 : dev = 0; + 902 144 : *uuid = 0; + 903 : } + 904 : + 905 1519 : disk = disk_alloc(buffer, dir, dev, uuid, skip_access); 906 : - 907 344 : if (validate_smartctl(custom) != 0) { - 908 : /* LCOV_EXCL_START */ - 909 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); - 910 : exit(EXIT_FAILURE); - 911 : /* LCOV_EXCL_STOP */ - 912 : } - 913 : - 914 : /* search for parity */ - 915 344 : if (lev_config_scan(buffer, &level, 0) == 0) { - 916 172 : if (state->parity[level].smartctl[0] != 0) { - 917 : /* LCOV_EXCL_START */ - 918 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line); - 919 : exit(EXIT_FAILURE); - 920 : /* LCOV_EXCL_STOP */ - 921 : } - 922 : - 923 172 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); - 924 : } else { - 925 : /* search the disk */ - 926 : struct snapraid_disk* disk; - 927 172 : for (i = state->disklist; i != 0; i = i->next) { - 928 172 : disk = i->data; - 929 172 : if (strcmp(disk->name, buffer) == 0) - 930 172 : break; - 931 : } - 932 172 : if (!i) { - 933 : /* LCOV_EXCL_START */ - 934 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line); - 935 : exit(EXIT_FAILURE); - 936 : /* LCOV_EXCL_STOP */ - 937 : } - 938 172 : if (disk->smartctl[0] != 0) { - 939 : /* LCOV_EXCL_START */ - 940 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); - 941 : exit(EXIT_FAILURE); - 942 : /* LCOV_EXCL_STOP */ - 943 : } - 944 : - 945 172 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); - 946 : } - 947 1052 : } else if (strcmp(tag, "nohidden") == 0) { - 948 0 : state->filter_hidden = 1; - 949 1052 : } else if (strcmp(tag, "exclude") == 0) { - 950 : struct snapraid_filter* filter; - 951 : - 952 246 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 953 246 : if (ret < 0) { - 954 : /* LCOV_EXCL_START */ - 955 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line); - 956 : exit(EXIT_FAILURE); - 957 : /* LCOV_EXCL_STOP */ - 958 : } - 959 : - 960 246 : if (!*buffer) { - 961 : /* LCOV_EXCL_START */ - 962 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line); - 963 : exit(EXIT_FAILURE); - 964 : /* LCOV_EXCL_STOP */ - 965 : } - 966 : - 967 246 : filter = filter_alloc_file(-1, buffer); - 968 246 : if (!filter) { - 969 : /* LCOV_EXCL_START */ - 970 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); - 971 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); - 972 : exit(EXIT_FAILURE); - 973 : /* LCOV_EXCL_STOP */ - 974 : } - 975 246 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 976 806 : } else if (strcmp(tag, "include") == 0) { - 977 : struct snapraid_filter* filter; - 978 : - 979 246 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 980 246 : if (ret < 0) { - 981 : /* LCOV_EXCL_START */ - 982 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line); - 983 : exit(EXIT_FAILURE); - 984 : /* LCOV_EXCL_STOP */ - 985 : } - 986 : - 987 246 : if (!*buffer) { - 988 : /* LCOV_EXCL_START */ - 989 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line); - 990 : exit(EXIT_FAILURE); - 991 : /* LCOV_EXCL_STOP */ - 992 : } - 993 : - 994 246 : filter = filter_alloc_file(1, buffer); - 995 246 : if (!filter) { - 996 : /* LCOV_EXCL_START */ - 997 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line); - 998 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); - 999 : exit(EXIT_FAILURE); - 1000 : /* LCOV_EXCL_STOP */ - 1001 : } - 1002 246 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); - 1003 560 : } else if (strcmp(tag, "autosave") == 0) { - 1004 : char* e; - 1005 : - 1006 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); - 1007 34 : if (ret < 0) { - 1008 : /* LCOV_EXCL_START */ - 1009 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + 907 1519 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 908 1443 : } else if (strcmp(tag, "smartctl") == 0) { + 909 : char custom[PATH_MAX]; + 910 : + 911 358 : ret = sgettok(f, buffer, sizeof(buffer)); + 912 358 : if (ret < 0) { + 913 : /* LCOV_EXCL_START */ + 914 : log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); + 915 : exit(EXIT_FAILURE); + 916 : /* LCOV_EXCL_STOP */ + 917 : } + 918 : + 919 358 : if (!*buffer) { + 920 : /* LCOV_EXCL_START */ + 921 : log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); + 922 : exit(EXIT_FAILURE); + 923 : /* LCOV_EXCL_STOP */ + 924 : } + 925 : + 926 358 : sgetspace(f); + 927 : + 928 358 : ret = sgetlasttok(f, custom, sizeof(custom)); + 929 358 : if (ret < 0) { + 930 : /* LCOV_EXCL_START */ + 931 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + 932 : exit(EXIT_FAILURE); + 933 : /* LCOV_EXCL_STOP */ + 934 : } + 935 : + 936 358 : if (!*custom) { + 937 : /* LCOV_EXCL_START */ + 938 : log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); + 939 : exit(EXIT_FAILURE); + 940 : /* LCOV_EXCL_STOP */ + 941 : } + 942 : + 943 358 : if (validate_smartctl(custom) != 0) { + 944 : /* LCOV_EXCL_START */ + 945 : log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + 946 : exit(EXIT_FAILURE); + 947 : /* LCOV_EXCL_STOP */ + 948 : } + 949 : + 950 : /* search for parity */ + 951 358 : if (lev_config_scan(buffer, &level, 0) == 0) { + 952 179 : if (state->parity[level].smartctl[0] != 0) { + 953 : /* LCOV_EXCL_START */ + 954 : log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line); + 955 : exit(EXIT_FAILURE); + 956 : /* LCOV_EXCL_STOP */ + 957 : } + 958 : + 959 179 : pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); + 960 : } else { + 961 : struct snapraid_disk* disk; + 962 : + 963 : /* search the disk */ + 964 179 : disk = 0; + 965 179 : for (i = state->disklist; i != 0; i = i->next) { + 966 179 : disk = i->data; + 967 179 : if (strcmp(disk->name, buffer) == 0) + 968 179 : break; + 969 : } + 970 179 : if (!disk) { + 971 : /* LCOV_EXCL_START */ + 972 : log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line); + 973 : exit(EXIT_FAILURE); + 974 : /* LCOV_EXCL_STOP */ + 975 : } + 976 179 : if (disk->smartctl[0] != 0) { + 977 : /* LCOV_EXCL_START */ + 978 : log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); + 979 : exit(EXIT_FAILURE); + 980 : /* LCOV_EXCL_STOP */ + 981 : } + 982 : + 983 179 : pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); + 984 : } + 985 1085 : } else if (strcmp(tag, "nohidden") == 0) { + 986 0 : state->filter_hidden = 1; + 987 1085 : } else if (strcmp(tag, "exclude") == 0) { + 988 : struct snapraid_filter* filter; + 989 : + 990 254 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 991 254 : if (ret < 0) { + 992 : /* LCOV_EXCL_START */ + 993 : log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line); + 994 : exit(EXIT_FAILURE); + 995 : /* LCOV_EXCL_STOP */ + 996 : } + 997 : + 998 254 : if (!*buffer) { + 999 : /* LCOV_EXCL_START */ + 1000 : log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line); + 1001 : exit(EXIT_FAILURE); + 1002 : /* LCOV_EXCL_STOP */ + 1003 : } + 1004 : + 1005 254 : filter = filter_alloc_file(-1, buffer); + 1006 254 : if (!filter) { + 1007 : /* LCOV_EXCL_START */ + 1008 : log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); + 1009 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); 1010 : exit(EXIT_FAILURE); 1011 : /* LCOV_EXCL_STOP */ 1012 : } - 1013 : - 1014 34 : if (!*buffer) { - 1015 : /* LCOV_EXCL_START */ - 1016 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line); - 1017 : exit(EXIT_FAILURE); - 1018 : /* LCOV_EXCL_STOP */ - 1019 : } - 1020 : - 1021 34 : state->autosave = strtoul(buffer, &e, 0); - 1022 : - 1023 34 : if (!e || *e) { - 1024 : /* LCOV_EXCL_START */ - 1025 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); - 1026 : exit(EXIT_FAILURE); - 1027 : /* LCOV_EXCL_STOP */ - 1028 : } - 1029 : - 1030 : /* convert to GB */ - 1031 34 : state->autosave *= GIGA; - 1032 526 : } else if (tag[0] == 0) { - 1033 : /* allow empty lines */ - 1034 34 : } else if (tag[0] == '#') { - 1035 34 : ret = sgetline(f, buffer, sizeof(buffer)); - 1036 34 : if (ret < 0) { - 1037 : /* LCOV_EXCL_START */ - 1038 : log_fatal("Invalid comment in '%s' at line %u\n", path, line); - 1039 : exit(EXIT_FAILURE); - 1040 : /* LCOV_EXCL_STOP */ - 1041 : } - 1042 : } else { - 1043 : /* LCOV_EXCL_START */ - 1044 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); - 1045 : exit(EXIT_FAILURE); - 1046 : /* LCOV_EXCL_STOP */ - 1047 : } - 1048 : - 1049 : /* skip final spaces */ - 1050 5807 : sgetspace(f); + 1013 254 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + 1014 831 : } else if (strcmp(tag, "include") == 0) { + 1015 : struct snapraid_filter* filter; + 1016 : + 1017 254 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1018 254 : if (ret < 0) { + 1019 : /* LCOV_EXCL_START */ + 1020 : log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line); + 1021 : exit(EXIT_FAILURE); + 1022 : /* LCOV_EXCL_STOP */ + 1023 : } + 1024 : + 1025 254 : if (!*buffer) { + 1026 : /* LCOV_EXCL_START */ + 1027 : log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line); + 1028 : exit(EXIT_FAILURE); + 1029 : /* LCOV_EXCL_STOP */ + 1030 : } + 1031 : + 1032 254 : filter = filter_alloc_file(1, buffer); + 1033 254 : if (!filter) { + 1034 : /* LCOV_EXCL_START */ + 1035 : log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line); + 1036 : log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + 1037 : exit(EXIT_FAILURE); + 1038 : /* LCOV_EXCL_STOP */ + 1039 : } + 1040 254 : tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + 1041 577 : } else if (strcmp(tag, "autosave") == 0) { + 1042 : char* e; + 1043 : + 1044 34 : ret = sgetlasttok(f, buffer, sizeof(buffer)); + 1045 34 : if (ret < 0) { + 1046 : /* LCOV_EXCL_START */ + 1047 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + 1048 : exit(EXIT_FAILURE); + 1049 : /* LCOV_EXCL_STOP */ + 1050 : } 1051 : - 1052 : /* next line */ - 1053 5807 : c = sgeteol(f); - 1054 5807 : if (c == EOF) { - 1055 246 : break; - 1056 : } - 1057 5561 : if (c != '\n') { - 1058 : /* LCOV_EXCL_START */ - 1059 : log_fatal("Extra data in '%s' at line %u\n", path, line); - 1060 : exit(EXIT_FAILURE); - 1061 : /* LCOV_EXCL_STOP */ - 1062 : } - 1063 5561 : ++line; - 1064 5561 : } - 1065 : - 1066 246 : if (serror(f)) { - 1067 : /* LCOV_EXCL_START */ - 1068 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); - 1069 : exit(EXIT_FAILURE); - 1070 : /* LCOV_EXCL_STOP */ - 1071 : } - 1072 : - 1073 246 : sclose(f); - 1074 : - 1075 246 : state_config_check(state, path, filterlist_disk); - 1076 : - 1077 : /* select the default hash */ - 1078 246 : if (state->opt.force_murmur3) { - 1079 1 : state->besthash = HASH_MURMUR3; - 1080 245 : } else if (state->opt.force_spooky2) { - 1081 1 : state->besthash = HASH_SPOOKY2; - 1082 : } else { - 1083 : #ifdef CONFIG_X86 - 1084 244 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) - 1085 244 : state->besthash = HASH_MURMUR3; - 1086 : else - 1087 0 : state->besthash = HASH_SPOOKY2; - 1088 : #else - 1089 : if (sizeof(void*) == 4) - 1090 : state->besthash = HASH_MURMUR3; - 1091 : else - 1092 : state->besthash = HASH_SPOOKY2; - 1093 : #endif - 1094 : } - 1095 : - 1096 : /* by default use the best hash */ - 1097 246 : state->hash = state->besthash; - 1098 : - 1099 : /* by default use a random hash seed */ - 1100 246 : if (randomize(state->hashseed, HASH_SIZE) != 0) { - 1101 : /* LCOV_EXCL_START */ - 1102 : log_fatal("Failed to get random values.\n"); - 1103 : exit(EXIT_FAILURE); - 1104 : /* LCOV_EXCL_STOP */ - 1105 : } - 1106 : - 1107 : /* no previous hash by default */ - 1108 246 : state->prevhash = HASH_UNDEFINED; - 1109 : - 1110 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ - 1111 : - 1112 246 : log_tag("blocksize:%u\n", state->block_size); - 1113 1717 : for (i = state->disklist; i != 0; i = i->next) { - 1114 1471 : struct snapraid_disk* disk = i->data; - 1115 1471 : log_tag("disk:%s:%s\n", disk->name, disk->dir); - 1116 : } - 1117 : - 1118 246 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); - 1119 1433 : for (l = 0; l < state->level; ++l) - 1120 1187 : log_tag("%s:%s\n", lev_config_name(l), state->parity[l].path); - 1121 246 : if (state->pool[0] != 0) - 1122 34 : log_tag("pool:%s\n", state->pool); - 1123 246 : if (state->share[0] != 0) - 1124 34 : log_tag("share:%s\n", state->share); - 1125 246 : if (state->autosave != 0) - 1126 34 : log_tag("autosave:%" PRIu64 "\n", state->autosave); - 1127 738 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { - 1128 : char out[PATH_MAX]; - 1129 492 : struct snapraid_filter* filter = i->data; - 1130 492 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); - 1131 : } - 1132 246 : if (state->filter_hidden) - 1133 0 : log_tag("filter:nohidden:\n"); - 1134 246 : log_flush(); - 1135 246 : } + 1052 34 : if (!*buffer) { + 1053 : /* LCOV_EXCL_START */ + 1054 : log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line); + 1055 : exit(EXIT_FAILURE); + 1056 : /* LCOV_EXCL_STOP */ + 1057 : } + 1058 : + 1059 34 : state->autosave = strtoul(buffer, &e, 0); + 1060 : + 1061 34 : if (!e || *e) { + 1062 : /* LCOV_EXCL_START */ + 1063 : log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + 1064 : exit(EXIT_FAILURE); + 1065 : /* LCOV_EXCL_STOP */ + 1066 : } + 1067 : + 1068 : /* convert to GB */ + 1069 34 : state->autosave *= GIGA; + 1070 543 : } else if (tag[0] == 0) { + 1071 : /* allow empty lines */ + 1072 34 : } else if (tag[0] == '#') { + 1073 34 : ret = sgetline(f, buffer, sizeof(buffer)); + 1074 34 : if (ret < 0) { + 1075 : /* LCOV_EXCL_START */ + 1076 : log_fatal("Invalid comment in '%s' at line %u\n", path, line); + 1077 : exit(EXIT_FAILURE); + 1078 : /* LCOV_EXCL_STOP */ + 1079 : } + 1080 : } else { + 1081 : /* LCOV_EXCL_START */ + 1082 : log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); + 1083 : exit(EXIT_FAILURE); + 1084 : /* LCOV_EXCL_STOP */ + 1085 : } + 1086 : + 1087 : /* skip final spaces */ + 1088 6014 : sgetspace(f); + 1089 : + 1090 : /* next line */ + 1091 6014 : c = sgeteol(f); + 1092 6014 : if (c == EOF) { + 1093 254 : break; + 1094 : } + 1095 5760 : if (c != '\n') { + 1096 : /* LCOV_EXCL_START */ + 1097 : log_fatal("Extra data in '%s' at line %u\n", path, line); + 1098 : exit(EXIT_FAILURE); + 1099 : /* LCOV_EXCL_STOP */ + 1100 : } + 1101 5760 : ++line; + 1102 5760 : } + 1103 : + 1104 254 : if (serror(f)) { + 1105 : /* LCOV_EXCL_START */ + 1106 : log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); + 1107 : exit(EXIT_FAILURE); + 1108 : /* LCOV_EXCL_STOP */ + 1109 : } + 1110 : + 1111 254 : sclose(f); + 1112 : + 1113 254 : state_config_check(state, path, filterlist_disk); + 1114 : + 1115 : /* select the default hash */ + 1116 254 : if (state->opt.force_murmur3) { + 1117 1 : state->besthash = HASH_MURMUR3; + 1118 253 : } else if (state->opt.force_spooky2) { + 1119 1 : state->besthash = HASH_SPOOKY2; + 1120 : } else { + 1121 : #ifdef CONFIG_X86 + 1122 252 : if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) + 1123 252 : state->besthash = HASH_MURMUR3; + 1124 : else + 1125 0 : state->besthash = HASH_SPOOKY2; + 1126 : #else + 1127 : if (sizeof(void*) == 4) + 1128 : state->besthash = HASH_MURMUR3; + 1129 : else + 1130 : state->besthash = HASH_SPOOKY2; + 1131 : #endif + 1132 : } + 1133 : + 1134 : /* by default use the best hash */ + 1135 254 : state->hash = state->besthash; 1136 : - 1137 : /** - 1138 : * Find a disk by name. - 1139 : */ - 1140 11051 : static struct snapraid_disk* find_disk(struct snapraid_state* state, const char* name) - 1141 : { - 1142 : tommy_node* i; - 1143 : - 1144 38600 : for (i = state->disklist; i != 0; i = i->next) { - 1145 38594 : struct snapraid_disk* disk = i->data; - 1146 38594 : if (strcmp(disk->name, name) == 0) - 1147 11045 : return disk; - 1148 : } + 1137 : /* by default use a random hash seed */ + 1138 254 : if (randomize(state->hashseed, HASH_SIZE) != 0) { + 1139 : /* LCOV_EXCL_START */ + 1140 : log_fatal("Failed to get random values.\n"); + 1141 : exit(EXIT_FAILURE); + 1142 : /* LCOV_EXCL_STOP */ + 1143 : } + 1144 : + 1145 : /* no previous hash by default */ + 1146 254 : state->prevhash = HASH_UNDEFINED; + 1147 : + 1148 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ 1149 : - 1150 6 : if (state->no_conf) { - 1151 : /* without a configuration file, add disks automatically */ - 1152 : struct snapraid_disk* disk; - 1153 : - 1154 6 : disk = disk_alloc(name, "DUMMY/", -1, 0); + 1150 254 : log_tag("blocksize:%u\n", state->block_size); + 1151 1773 : for (i = state->disklist; i != 0; i = i->next) { + 1152 1519 : struct snapraid_disk* disk = i->data; + 1153 1519 : log_tag("disk:%s:%s\n", disk->name, disk->dir); + 1154 : } 1155 : - 1156 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); - 1157 : - 1158 6 : return disk; - 1159 : } - 1160 : - 1161 0 : return 0; - 1162 : } - 1163 : - 1164 : /** - 1165 : * Update the disk mapping if required. - 1166 : */ - 1167 241 : static void state_map(struct snapraid_state* state) - 1168 : { - 1169 : unsigned hole; - 1170 : tommy_node* i; - 1171 : unsigned uuid_mismatch; - 1172 : unsigned diskcount; - 1173 : unsigned l; + 1156 254 : log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); + 1157 1489 : for (l = 0; l < state->level; ++l) + 1158 1235 : log_tag("%s:%s\n", lev_config_name(l), state->parity[l].path); + 1159 254 : if (state->pool[0] != 0) + 1160 34 : log_tag("pool:%s\n", state->pool); + 1161 254 : if (state->share[0] != 0) + 1162 34 : log_tag("share:%s\n", state->share); + 1163 254 : if (state->autosave != 0) + 1164 34 : log_tag("autosave:%" PRIu64 "\n", state->autosave); + 1165 762 : for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { + 1166 : char out[PATH_MAX]; + 1167 508 : struct snapraid_filter* filter = i->data; + 1168 508 : log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); + 1169 : } + 1170 254 : if (state->filter_hidden) + 1171 0 : log_tag("filter:nohidden:\n"); + 1172 254 : log_flush(); + 1173 254 : } 1174 : - 1175 : /* remove all the mapping without a disk */ - 1176 : /* this happens when a disk is removed from the configuration file */ - 1177 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ - 1178 : /* when saving the content file, but we keep this code to import older content files. */ - 1179 1781 : for (i = state->maplist; i != 0; ) { - 1180 1299 : struct snapraid_map* map = i->data; - 1181 : struct snapraid_disk* disk; - 1182 : - 1183 1299 : disk = find_disk(state, map->name); - 1184 : - 1185 : /* go to the next mapping before removing */ - 1186 1299 : i = i->next; + 1175 : /** + 1176 : * Find a disk by name. + 1177 : */ + 1178 6723 : static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) + 1179 : { + 1180 : tommy_node* i; + 1181 : + 1182 23463 : for (i = state->disklist; i != 0; i = i->next) { + 1183 23455 : struct snapraid_disk* disk = i->data; + 1184 23455 : if (strcmp(disk->name, name) == 0) + 1185 6715 : return disk; + 1186 : } 1187 : - 1188 1299 : if (disk == 0) { - 1189 : /* disk not found, remove the mapping */ - 1190 0 : tommy_list_remove_existing(&state->maplist, &map->node); - 1191 0 : map_free(map); - 1192 : } - 1193 : } - 1194 : - 1195 : /* maps each unmapped disk present in the configuration file in the first available hole */ - 1196 : /* this happens when you add disks for the first time in the configuration file */ - 1197 241 : hole = 0; /* first position to try */ - 1198 1682 : for (i = state->disklist; i != 0; i = i->next) { - 1199 1441 : struct snapraid_disk* disk = i->data; - 1200 : struct snapraid_map* map; - 1201 : tommy_node* j; - 1202 : - 1203 : /* check if the disk is already mapped */ - 1204 5031 : for (j = state->maplist; j != 0; j = j->next) { - 1205 4889 : map = j->data; - 1206 4889 : if (strcmp(disk->name, map->name) == 0) { - 1207 : /* mapping found */ - 1208 1299 : break; - 1209 : } - 1210 : } - 1211 1441 : if (j != 0) { - 1212 : /* mapping is present, then copy the free blocks into to disk */ - 1213 1299 : disk->total_blocks = map->total_blocks; - 1214 1299 : disk->free_blocks = map->free_blocks; - 1215 1299 : continue; - 1216 : } - 1217 : - 1218 : /* mapping not found, search for an hole */ - 1219 : while (1) { - 1220 900 : for (j = state->maplist; j != 0; j = j->next) { - 1221 758 : map = j->data; - 1222 758 : if (map->position == hole) { - 1223 : /* position already used */ - 1224 127 : break; - 1225 : } - 1226 : } - 1227 269 : if (j == 0) { - 1228 : /* hole found */ - 1229 142 : break; - 1230 : } - 1231 : - 1232 : /* try with the next one */ - 1233 127 : ++hole; - 1234 127 : } - 1235 : - 1236 : /* insert the new mapping */ - 1237 142 : map = map_alloc(disk->name, hole, 0, 0, ""); - 1238 : - 1239 142 : tommy_list_insert_tail(&state->maplist, &map->node, map); - 1240 : } - 1241 : - 1242 : /* without configuration don't check for number of data disks or uuid changes */ - 1243 241 : if (state->no_conf) - 1244 242 : return; + 1188 8 : if (state->no_conf) { + 1189 : /* without a configuration file, add disks automatically */ + 1190 : struct snapraid_disk* disk; + 1191 : + 1192 6 : disk = disk_alloc(name, "DUMMY/", -1, "", 0); + 1193 : + 1194 6 : tommy_list_insert_tail(&state->disklist, &disk->node, disk); + 1195 : + 1196 6 : return disk; + 1197 : } + 1198 : + 1199 2 : return 0; + 1200 : } + 1201 : + 1202 : /** + 1203 : * Find a disk by UUID. + 1204 : */ + 1205 2 : static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid) + 1206 : { + 1207 : tommy_node* i; + 1208 2 : struct snapraid_disk* found = 0; + 1209 : + 1210 : /* special test case to find the first matching UUID */ + 1211 : /* when testing UUID are all equal or not supported */ + 1212 : /* and we should handle this case specifically */ + 1213 2 : if (state->opt.match_first_uuid) + 1214 2 : return state->disklist->data; + 1215 : + 1216 : /* LCOV_EXCL_START */ + 1217 : /* never find an empty uuid */ + 1218 : if (!*uuid) + 1219 : return 0; + 1220 : + 1221 : for (i = state->disklist; i != 0; i = i->next) { + 1222 : struct snapraid_disk* disk = i->data; + 1223 : if (strcmp(disk->uuid, uuid) == 0) { + 1224 : /* never match duplicate UUID */ + 1225 : if (found) + 1226 : return 0; + 1227 : found = disk; + 1228 : } + 1229 : } + 1230 : + 1231 : return found; + 1232 : /* LCOV_EXCL_STOP */ + 1233 : } + 1234 : + 1235 : /** + 1236 : * Update the disk mapping if required. + 1237 : */ + 1238 249 : static void state_map(struct snapraid_state* state) + 1239 : { + 1240 : unsigned hole; + 1241 : tommy_node* i; + 1242 : unsigned uuid_mismatch; + 1243 : unsigned diskcount; + 1244 : unsigned l; 1245 : - 1246 : /* counter for the number of UUID mismatches */ - 1247 240 : uuid_mismatch = 0; - 1248 : - 1249 : /* check if mapping match the disk uuid */ - 1250 240 : if (!state->opt.skip_disk_access) { - 1251 1514 : for (i = state->maplist; i != 0; i = i->next) { - 1252 1297 : struct snapraid_map* map = i->data; - 1253 : struct snapraid_disk* disk; - 1254 : char uuid[UUID_MAX]; - 1255 : int ret; - 1256 : - 1257 1297 : disk = find_disk(state, map->name); - 1258 1297 : if (disk == 0) { - 1259 : /* LCOV_EXCL_START */ - 1260 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - 1261 : exit(EXIT_FAILURE); - 1262 : /* LCOV_EXCL_STOP */ - 1263 : } - 1264 : - 1265 1297 : ret = devuuid(disk->device, uuid, sizeof(uuid)); - 1266 1297 : if (ret != 0) { - 1267 : /* uuid not available, just ignore but marks the disk with unsupported UUID */ - 1268 1 : disk->has_unsupported_uuid = 1; - 1269 1 : continue; - 1270 : } - 1271 : - 1272 : /* if the uuid is changed */ - 1273 1296 : if (strcmp(uuid, map->uuid) != 0) { - 1274 : /* mark the disk as with an UUID change */ - 1275 94 : disk->has_different_uuid = 1; - 1276 : - 1277 : /* if the previous uuid is available */ - 1278 94 : if (map->uuid[0] != 0) { - 1279 : /* count the number of uuid change */ - 1280 0 : ++uuid_mismatch; - 1281 0 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, uuid); - 1282 : } else { - 1283 : /* no message here, because having a disk without */ - 1284 : /* UUID is the normal state of an empty disk */ - 1285 94 : disk->had_empty_uuid = 1; - 1286 : } - 1287 : - 1288 : /* update the uuid in the mapping, */ - 1289 94 : pathcpy(map->uuid, sizeof(map->uuid), uuid); - 1290 : - 1291 : /* write the new state with the new uuid */ - 1292 94 : state->need_write = 1; - 1293 : } - 1294 : } - 1295 : } - 1296 : - 1297 : /* check the parity uuid */ - 1298 240 : if (!state->opt.skip_parity_access) { - 1299 1188 : for (l = 0; l < state->level; ++l) { - 1300 : char uuid[UUID_MAX]; - 1301 : int ret; + 1246 : /* remove all the mapping without a disk */ + 1247 : /* this happens when a disk is removed from the configuration file */ + 1248 : /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ + 1249 : /* when saving the content file, but we keep this code to import older content files. */ + 1250 1832 : for (i = state->maplist; i != 0; ) { + 1251 1334 : struct snapraid_map* map = i->data; + 1252 : struct snapraid_disk* disk; + 1253 : + 1254 1334 : disk = find_disk_by_name(state, map->name); + 1255 : + 1256 : /* go to the next mapping before removing */ + 1257 1334 : i = i->next; + 1258 : + 1259 1334 : if (disk == 0) { + 1260 : /* disk not found, remove the mapping */ + 1261 0 : tommy_list_remove_existing(&state->maplist, &map->node); + 1262 0 : map_free(map); + 1263 : } + 1264 : } + 1265 : + 1266 : /* maps each unmapped disk present in the configuration file in the first available hole */ + 1267 : /* this happens when you add disks for the first time in the configuration file */ + 1268 249 : hole = 0; /* first position to try */ + 1269 1738 : for (i = state->disklist; i != 0; i = i->next) { + 1270 1489 : struct snapraid_disk* disk = i->data; + 1271 : struct snapraid_map* map; + 1272 : tommy_node* j; + 1273 : + 1274 : /* check if the disk is already mapped */ + 1275 5199 : for (j = state->maplist; j != 0; j = j->next) { + 1276 5044 : map = j->data; + 1277 5044 : if (strcmp(disk->name, map->name) == 0) { + 1278 : /* mapping found */ + 1279 1334 : break; + 1280 : } + 1281 : } + 1282 1489 : if (j != 0) { + 1283 : /* mapping is present, then copy the free blocks into to disk */ + 1284 1334 : disk->total_blocks = map->total_blocks; + 1285 1334 : disk->free_blocks = map->free_blocks; + 1286 1334 : continue; + 1287 : } + 1288 : + 1289 : /* mapping not found, search for an hole */ + 1290 : while (1) { + 1291 1025 : for (j = state->maplist; j != 0; j = j->next) { + 1292 870 : map = j->data; + 1293 870 : if (map->position == hole) { + 1294 : /* position already used */ + 1295 144 : break; + 1296 : } + 1297 : } + 1298 299 : if (j == 0) { + 1299 : /* hole found */ + 1300 155 : break; + 1301 : } 1302 : - 1303 982 : ret = devuuid(state->parity[l].device, uuid, sizeof(uuid)); - 1304 982 : if (ret != 0) { - 1305 : /* uuid not available, just ignore */ - 1306 1 : continue; - 1307 : } - 1308 : - 1309 : /* if the uuid is changed */ - 1310 981 : if (strcmp(uuid, state->parity[l].uuid) != 0) { - 1311 : /* if the previous uuid is available */ - 1312 46 : if (state->parity[l].uuid[0] != 0) { - 1313 : /* count the number of uuid change */ - 1314 0 : ++uuid_mismatch; - 1315 0 : log_fatal("UUID change for parity '%s' from '%s' to '%s'\n", lev_config_name(l), state->parity[l].uuid, uuid); - 1316 : } - 1317 : - 1318 : /* update the uuid */ - 1319 46 : pathcpy(state->parity[l].uuid, sizeof(state->parity[l].uuid), uuid); - 1320 : - 1321 : /* write the new state with the new uuid */ - 1322 46 : state->need_write = 1; - 1323 : } - 1324 : } - 1325 : } - 1326 : - 1327 240 : if (!state->opt.force_uuid && uuid_mismatch > state->level) { - 1328 : /* LCOV_EXCL_START */ - 1329 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n"); - 1330 : log_fatal("If this happens because you really replaced them,\n"); - 1331 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command); - 1332 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n"); - 1333 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n"); - 1334 : exit(EXIT_FAILURE); - 1335 : /* LCOV_EXCL_STOP */ - 1336 : } - 1337 : - 1338 : /* count the number of data disks, including holes left after removing some */ - 1339 240 : diskcount = 0; - 1340 1675 : for (i = state->maplist; i != 0; i = i->next) { - 1341 1435 : struct snapraid_map* map = i->data; - 1342 : - 1343 1435 : if (map->position + 1 > diskcount) - 1344 1304 : diskcount = map->position + 1; - 1345 : } - 1346 : - 1347 : /* ensure to don't go over the limit of the RAID engine */ - 1348 240 : if (diskcount > RAID_DATA_MAX) { - 1349 : /* LCOV_EXCL_START */ - 1350 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX); - 1351 : exit(EXIT_FAILURE); - 1352 : /* LCOV_EXCL_STOP */ - 1353 : } + 1303 : /* try with the next one */ + 1304 144 : ++hole; + 1305 144 : } + 1306 : + 1307 : /* insert the new mapping */ + 1308 155 : map = map_alloc(disk->name, hole, 0, 0, ""); + 1309 : + 1310 155 : tommy_list_insert_tail(&state->maplist, &map->node, map); + 1311 : } + 1312 : + 1313 : /* without configuration don't check for number of data disks or uuid changes */ + 1314 249 : if (state->no_conf) + 1315 250 : return; + 1316 : + 1317 : /* counter for the number of UUID mismatches */ + 1318 248 : uuid_mismatch = 0; + 1319 : + 1320 : /* check if mapping match the disk uuid */ + 1321 248 : if (!state->opt.skip_disk_access) { + 1322 1570 : for (i = state->maplist; i != 0; i = i->next) { + 1323 1345 : struct snapraid_map* map = i->data; + 1324 : struct snapraid_disk* disk; + 1325 : + 1326 1345 : disk = find_disk_by_name(state, map->name); + 1327 1345 : if (disk == 0) { + 1328 : /* LCOV_EXCL_START */ + 1329 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + 1330 : os_abort(); + 1331 : /* LCOV_EXCL_STOP */ + 1332 : } + 1333 : + 1334 1345 : if (disk->has_unsupported_uuid) { + 1335 : /* if uuid is not available, skip this one */ + 1336 1 : continue; + 1337 : } + 1338 : + 1339 : /* if the uuid is changed */ + 1340 1344 : if (strcmp(disk->uuid, map->uuid) != 0) { + 1341 : /* mark the disk as with an UUID change */ + 1342 109 : disk->has_different_uuid = 1; + 1343 : + 1344 : /* if the previous uuid is available */ + 1345 109 : if (map->uuid[0] != 0) { + 1346 : /* count the number of uuid change */ + 1347 2 : ++uuid_mismatch; + 1348 2 : log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid); + 1349 : } else { + 1350 : /* no message here, because having a disk without */ + 1351 : /* UUID is the normal state of an empty disk */ + 1352 107 : disk->had_empty_uuid = 1; + 1353 : } 1354 : - 1355 : /* now count the real number of data disks, excluding holes left after removing some */ - 1356 240 : diskcount = tommy_list_count(&state->maplist); + 1355 : /* update the uuid in the mapping, */ + 1356 109 : pathcpy(map->uuid, sizeof(map->uuid), disk->uuid); 1357 : - 1358 : /* recommend number of parities */ - 1359 240 : if (diskcount >= 36 && state->level < 6) { - 1360 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount); - 1361 240 : } else if (diskcount >= 29 && state->level < 5) { - 1362 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount); - 1363 240 : } else if (diskcount >= 22 && state->level < 4) { - 1364 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount); - 1365 240 : } else if (diskcount >= 15 && state->level < 3) { - 1366 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount); - 1367 240 : } else if (diskcount >= 5 && state->level < 2) { - 1368 34 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount); - 1369 : } - 1370 : } - 1371 : - 1372 144 : void state_refresh(struct snapraid_state* state) - 1373 : { - 1374 : tommy_node* i; - 1375 : unsigned l; - 1376 : - 1377 : /* for all disks */ - 1378 1006 : for (i = state->maplist; i != 0; i = i->next) { - 1379 862 : struct snapraid_map* map = i->data; - 1380 : struct snapraid_disk* disk; - 1381 : uint64_t total_space; - 1382 : uint64_t free_space; - 1383 : int ret; + 1358 : /* write the new state with the new uuid */ + 1359 109 : state->need_write = 1; + 1360 : } + 1361 : } + 1362 : } + 1363 : + 1364 : /* check the parity uuid */ + 1365 248 : if (!state->opt.skip_parity_access) { + 1366 1244 : for (l = 0; l < state->level; ++l) { + 1367 : char uuid[UUID_MAX]; + 1368 : int ret; + 1369 : + 1370 1030 : ret = devuuid(state->parity[l].device, uuid, sizeof(uuid)); + 1371 1030 : if (ret != 0) { + 1372 : /* uuid not available, just ignore */ + 1373 1 : continue; + 1374 : } + 1375 : + 1376 : /* if the uuid is changed */ + 1377 1029 : if (strcmp(uuid, state->parity[l].uuid) != 0) { + 1378 : /* if the previous uuid is available */ + 1379 46 : if (state->parity[l].uuid[0] != 0) { + 1380 : /* count the number of uuid change */ + 1381 0 : ++uuid_mismatch; + 1382 0 : log_fatal("UUID change for parity '%s' from '%s' to '%s'\n", lev_config_name(l), state->parity[l].uuid, uuid); + 1383 : } 1384 : - 1385 862 : disk = find_disk(state, map->name); - 1386 862 : if (disk == 0) { - 1387 : /* LCOV_EXCL_START */ - 1388 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - 1389 : exit(EXIT_FAILURE); - 1390 : /* LCOV_EXCL_STOP */ + 1385 : /* update the uuid */ + 1386 46 : pathcpy(state->parity[l].uuid, sizeof(state->parity[l].uuid), uuid); + 1387 : + 1388 : /* write the new state with the new uuid */ + 1389 46 : state->need_write = 1; + 1390 : } 1391 : } - 1392 : - 1393 862 : ret = fsinfo(disk->dir, 0, &total_space, &free_space); - 1394 862 : if (ret != 0) { - 1395 : /* LCOV_EXCL_START */ - 1396 : log_fatal("Error accessing disk '%s' to get filesystem info. %s.\n", disk->dir, strerror(errno)); - 1397 : exit(EXIT_FAILURE); - 1398 : /* LCOV_EXCL_STOP */ - 1399 : } - 1400 : - 1401 : /* set the new free blocks */ - 1402 862 : map->total_blocks = total_space / state->block_size; - 1403 862 : map->free_blocks = free_space / state->block_size; + 1392 : } + 1393 : + 1394 248 : if (!state->opt.force_uuid && uuid_mismatch > state->level) { + 1395 : /* LCOV_EXCL_START */ + 1396 : log_fatal("Too many disks have UUID changed from the latest 'sync'.\n"); + 1397 : log_fatal("If this happens because you really replaced them,\n"); + 1398 : log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command); + 1399 : log_fatal("Instead, it's possible that you messed up the disk mount points,\n"); + 1400 : log_fatal("and you have to restore the mount points at the state of the latest sync.\n"); + 1401 : exit(EXIT_FAILURE); + 1402 : /* LCOV_EXCL_STOP */ + 1403 : } 1404 : - 1405 : /* also update the disk info */ - 1406 862 : disk->total_blocks = map->total_blocks; - 1407 862 : disk->free_blocks = map->free_blocks; - 1408 : } + 1405 : /* count the number of data disks, including holes left after removing some */ + 1406 248 : diskcount = 0; + 1407 1731 : for (i = state->maplist; i != 0; i = i->next) { + 1408 1483 : struct snapraid_map* map = i->data; 1409 : - 1410 : /* for all parities */ - 1411 978 : for (l = 0; l < state->level; ++l) { - 1412 : uint64_t total_space; - 1413 : uint64_t free_space; - 1414 : int ret; - 1415 : - 1416 834 : ret = fsinfo(state->parity[l].path, 0, &total_space, &free_space); - 1417 834 : if (ret != 0) { - 1418 : /* LCOV_EXCL_START */ - 1419 : log_fatal("Error accessing file '%s' to get filesystem info. %s.\n", state->parity[l].path, strerror(errno)); - 1420 : exit(EXIT_FAILURE); - 1421 : /* LCOV_EXCL_STOP */ - 1422 : } - 1423 : - 1424 : /* set the new free blocks */ - 1425 834 : state->parity[l].total_blocks = total_space / state->block_size; - 1426 834 : state->parity[l].free_blocks = free_space / state->block_size; - 1427 : } - 1428 : - 1429 : /* note what we don't set need_write = 1, because we don't want */ - 1430 : /* to update the content file only for the free space info. */ - 1431 144 : } - 1432 : - 1433 : /** - 1434 : * Check the content. - 1435 : */ - 1436 234 : static void state_content_check(struct snapraid_state* state, const char* path) - 1437 : { - 1438 : tommy_node* i; - 1439 : - 1440 : /* check that any map has different name and position */ - 1441 1633 : for (i = state->maplist; i != 0; i = i->next) { - 1442 1399 : struct snapraid_map* map = i->data; - 1443 : tommy_node* j; - 1444 4884 : for (j = i->next; j != 0; j = j->next) { - 1445 3485 : struct snapraid_map* other = j->data; - 1446 3485 : if (strcmp(map->name, other->name) == 0) { - 1447 : /* LCOV_EXCL_START */ - 1448 : log_fatal("Colliding 'map' disk specification in '%s'\n", path); - 1449 : exit(EXIT_FAILURE); - 1450 : /* LCOV_EXCL_STOP */ - 1451 : } - 1452 3485 : if (map->position == other->position) { - 1453 : /* LCOV_EXCL_START */ - 1454 : log_fatal("Colliding 'map' index specification in '%s'\n", path); - 1455 : exit(EXIT_FAILURE); - 1456 : /* LCOV_EXCL_STOP */ - 1457 : } - 1458 : } - 1459 : } - 1460 234 : } + 1410 1483 : if (map->position + 1 > diskcount) + 1411 1339 : diskcount = map->position + 1; + 1412 : } + 1413 : + 1414 : /* ensure to don't go over the limit of the RAID engine */ + 1415 248 : if (diskcount > RAID_DATA_MAX) { + 1416 : /* LCOV_EXCL_START */ + 1417 : log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX); + 1418 : exit(EXIT_FAILURE); + 1419 : /* LCOV_EXCL_STOP */ + 1420 : } + 1421 : + 1422 : /* now count the real number of data disks, excluding holes left after removing some */ + 1423 248 : diskcount = tommy_list_count(&state->maplist); + 1424 : + 1425 : /* recommend number of parities */ + 1426 248 : if (!state->opt.no_warnings) { + 1427 248 : if (diskcount >= 36 && state->level < 6) { + 1428 0 : log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount); + 1429 248 : } else if (diskcount >= 29 && state->level < 5) { + 1430 0 : log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount); + 1431 248 : } else if (diskcount >= 22 && state->level < 4) { + 1432 0 : log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount); + 1433 248 : } else if (diskcount >= 15 && state->level < 3) { + 1434 0 : log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount); + 1435 248 : } else if (diskcount >= 5 && state->level < 2) { + 1436 34 : log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount); + 1437 : } + 1438 : } + 1439 : } + 1440 : + 1441 160 : void state_refresh(struct snapraid_state* state) + 1442 : { + 1443 : tommy_node* i; + 1444 : unsigned l; + 1445 : + 1446 : /* for all disks */ + 1447 1118 : for (i = state->maplist; i != 0; i = i->next) { + 1448 958 : struct snapraid_map* map = i->data; + 1449 : struct snapraid_disk* disk; + 1450 : uint64_t total_space; + 1451 : uint64_t free_space; + 1452 : int ret; + 1453 : + 1454 958 : disk = find_disk_by_name(state, map->name); + 1455 958 : if (disk == 0) { + 1456 : /* LCOV_EXCL_START */ + 1457 : log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + 1458 : os_abort(); + 1459 : /* LCOV_EXCL_STOP */ + 1460 : } 1461 : - 1462 : /** - 1463 : * Check if the position is REQUIRED, or we can completely clear it from the state. - 1464 : * - 1465 : * Note that position with only DELETED blocks are discarged. - 1466 : */ - 1467 729418 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) - 1468 : { - 1469 : tommy_node* i; - 1470 : - 1471 : /* check for each disk */ - 1472 773475 : for (i = state->disklist; i != 0; i = i->next) { - 1473 773475 : struct snapraid_disk* disk = i->data; - 1474 773475 : struct snapraid_block* block = fs_par2block_get(disk, pos); - 1475 : - 1476 : /* if we have at least one file, the position is needed */ - 1477 773475 : if (block_has_file(block)) - 1478 729418 : return 1; - 1479 : } - 1480 : - 1481 0 : return 0; - 1482 : } - 1483 : - 1484 : /** - 1485 : * Check if the info block is REQUIREQ. - 1486 : * - 1487 : * This is used to ensure that we keep the last check used for scrubbing. - 1488 : * and that we add it when importing old context files. - 1489 : * - 1490 : * Note that you can have position without info blocks, for example - 1491 : * if all the blocks are not synced. - 1492 : * - 1493 : * Note also that not requiring an info block, doesn't mean that if present it - 1494 : * can be discarded. - 1495 : */ - 1496 1491820 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos) - 1497 : { - 1498 : tommy_node* i; - 1499 : - 1500 : /* check for each disk */ - 1501 1985452 : for (i = state->disklist; i != 0; i = i->next) { - 1502 1927007 : struct snapraid_disk* disk = i->data; - 1503 1927007 : struct snapraid_block* block = fs_par2block_get(disk, pos); - 1504 : - 1505 : /* if we have at least one synced file, the info is required */ - 1506 1927007 : if (block_state_get(block) == BLOCK_STATE_BLK) - 1507 1433375 : return 1; - 1508 : } - 1509 : - 1510 58445 : return 0; - 1511 : } - 1512 : - 1513 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos) - 1514 : { - 1515 : tommy_node* i; - 1516 : - 1517 : /* check for each disk if block is really used */ - 1518 0 : for (i = state->disklist; i != 0; i = i->next) { - 1519 0 : struct snapraid_disk* disk = i->data; - 1520 0 : struct snapraid_block* block = fs_par2block_get(disk, pos); - 1521 : - 1522 : /* if the block is deleted */ - 1523 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) { - 1524 : /* set it to empty */ - 1525 0 : fs_deallocate(disk, pos); - 1526 : } - 1527 : } - 1528 0 : } - 1529 : - 1530 : /** - 1531 : * Check if a block position in a disk is deleted. - 1532 : */ - 1533 29344162 : static int fs_is_block_deleted_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t pos) - 1534 : { - 1535 29344162 : struct snapraid_block* block = fs_par2block_get_ts(disk, fs_last, pos); - 1536 : - 1537 29163541 : return block_state_get(block) == BLOCK_STATE_DELETED; - 1538 : } + 1462 958 : ret = fsinfo(disk->dir, 0, &total_space, &free_space); + 1463 958 : if (ret != 0) { + 1464 : /* LCOV_EXCL_START */ + 1465 : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + 1466 : exit(EXIT_FAILURE); + 1467 : /* LCOV_EXCL_STOP */ + 1468 : } + 1469 : + 1470 : /* set the new free blocks */ + 1471 958 : map->total_blocks = total_space / state->block_size; + 1472 958 : map->free_blocks = free_space / state->block_size; + 1473 : + 1474 : /* also update the disk info */ + 1475 958 : disk->total_blocks = map->total_blocks; + 1476 958 : disk->free_blocks = map->free_blocks; + 1477 : } + 1478 : + 1479 : /* for all parities */ + 1480 1090 : for (l = 0; l < state->level; ++l) { + 1481 : uint64_t total_space; + 1482 : uint64_t free_space; + 1483 : int ret; + 1484 : + 1485 930 : ret = fsinfo(state->parity[l].path, 0, &total_space, &free_space); + 1486 930 : if (ret != 0) { + 1487 : /* LCOV_EXCL_START */ + 1488 : log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].path, strerror(errno)); + 1489 : exit(EXIT_FAILURE); + 1490 : /* LCOV_EXCL_STOP */ + 1491 : } + 1492 : + 1493 : /* set the new free blocks */ + 1494 930 : state->parity[l].total_blocks = total_space / state->block_size; + 1495 930 : state->parity[l].free_blocks = free_space / state->block_size; + 1496 : } + 1497 : + 1498 : /* note what we don't set need_write = 1, because we don't want */ + 1499 : /* to update the content file only for the free space info. */ + 1500 160 : } + 1501 : + 1502 : /** + 1503 : * Check the content. + 1504 : */ + 1505 242 : static void state_content_check(struct snapraid_state* state, const char* path) + 1506 : { + 1507 : tommy_node* i; + 1508 : + 1509 : /* check that any map has different name and position */ + 1510 1689 : for (i = state->maplist; i != 0; i = i->next) { + 1511 1447 : struct snapraid_map* map = i->data; + 1512 : tommy_node* j; + 1513 5052 : for (j = i->next; j != 0; j = j->next) { + 1514 3605 : struct snapraid_map* other = j->data; + 1515 3605 : if (strcmp(map->name, other->name) == 0) { + 1516 : /* LCOV_EXCL_START */ + 1517 : log_fatal("Colliding 'map' disk specification in '%s'\n", path); + 1518 : exit(EXIT_FAILURE); + 1519 : /* LCOV_EXCL_STOP */ + 1520 : } + 1521 3605 : if (map->position == other->position) { + 1522 : /* LCOV_EXCL_START */ + 1523 : log_fatal("Colliding 'map' index specification in '%s'\n", path); + 1524 : exit(EXIT_FAILURE); + 1525 : /* LCOV_EXCL_STOP */ + 1526 : } + 1527 : } + 1528 : } + 1529 242 : } + 1530 : + 1531 : /** + 1532 : * Check if the position is REQUIRED, or we can completely clear it from the state. + 1533 : * + 1534 : * Note that position with only DELETED blocks are discarged. + 1535 : */ + 1536 752491 : static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) + 1537 : { + 1538 : tommy_node* i; 1539 : - 1540 : /** - 1541 : * Flush the file checking the final CRC. - 1542 : * We exploit the fact that the CRC is always stored in the last 4 bytes. - 1543 : */ - 1544 1 : static void decoding_error(const char* path, STREAM* f) - 1545 : { - 1546 : unsigned char buf[4]; - 1547 : uint32_t crc_stored; - 1548 : uint32_t crc_computed; + 1540 : /* check for each disk */ + 1541 797220 : for (i = state->disklist; i != 0; i = i->next) { + 1542 797220 : struct snapraid_disk* disk = i->data; + 1543 797220 : struct snapraid_block* block = fs_par2block_get(disk, pos); + 1544 : + 1545 : /* if we have at least one file, the position is needed */ + 1546 797220 : if (block_has_file(block)) + 1547 752491 : return 1; + 1548 : } 1549 : - 1550 1 : if (seof(f)) { - 1551 : /* LCOV_EXCL_START */ - 1552 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1553 : log_fatal("This content file is truncated. Use an alternate copy.\n"); - 1554 : exit(EXIT_FAILURE); - 1555 : /* LCOV_EXCL_STOP */ - 1556 : } - 1557 : - 1558 1 : if (serror(f)) { - 1559 : /* LCOV_EXCL_START */ - 1560 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1561 : exit(EXIT_FAILURE); - 1562 : /* LCOV_EXCL_STOP */ - 1563 : } - 1564 : - 1565 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1566 : - 1567 1 : if (sdeplete(f, buf) != 0) { - 1568 : /* LCOV_EXCL_START */ - 1569 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 1570 : exit(EXIT_FAILURE); - 1571 : /* LCOV_EXCL_STOP */ - 1572 : } + 1550 0 : return 0; + 1551 : } + 1552 : + 1553 : /** + 1554 : * Check if the info block is REQUIREQ. + 1555 : * + 1556 : * This is used to ensure that we keep the last check used for scrubbing. + 1557 : * and that we add it when importing old context files. + 1558 : * + 1559 : * Note that you can have position without info blocks, for example + 1560 : * if all the blocks are not synced. + 1561 : * + 1562 : * Note also that not requiring an info block, doesn't mean that if present it + 1563 : * can be discarded. + 1564 : */ + 1565 1513218 : static int fs_info_is_required(struct snapraid_state* state, block_off_t pos) + 1566 : { + 1567 : tommy_node* i; + 1568 : + 1569 : /* check for each disk */ + 1570 2062203 : for (i = state->disklist; i != 0; i = i->next) { + 1571 1994271 : struct snapraid_disk* disk = i->data; + 1572 1994271 : struct snapraid_block* block = fs_par2block_get(disk, pos); 1573 : - 1574 : /* get the stored crc from the last four bytes */ - 1575 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; - 1576 : - 1577 : /* get the computed crc */ - 1578 1 : crc_computed = scrc(f); - 1579 : - 1580 : /* adjust the stored crc to include itself */ - 1581 1 : crc_stored = crc32c(crc_stored, buf, 4); - 1582 : - 1583 1 : if (crc_computed != crc_stored) { - 1584 1 : log_fatal("Mismatching CRC in '%s'\n", path); - 1585 1 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 1586 1 : exit(EXIT_FAILURE); - 1587 : } else { - 1588 0 : log_fatal("The file CRC is correct!\n"); - 1589 : } - 1590 0 : } - 1591 : - 1592 235 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f) - 1593 : { - 1594 : block_off_t blockmax; - 1595 : unsigned count_file; - 1596 : unsigned count_hardlink; - 1597 : unsigned count_symlink; - 1598 : unsigned count_dir; - 1599 : int crc_checked; - 1600 : char buffer[PATH_MAX]; - 1601 : int ret; - 1602 : tommy_array disk_mapping; - 1603 : uint32_t mapping_max; - 1604 : - 1605 235 : blockmax = 0; - 1606 235 : count_file = 0; - 1607 235 : count_hardlink = 0; - 1608 235 : count_symlink = 0; - 1609 235 : count_dir = 0; - 1610 235 : crc_checked = 0; - 1611 235 : mapping_max = 0; - 1612 235 : tommy_array_init(&disk_mapping); - 1613 : - 1614 235 : ret = sread(f, buffer, 12); - 1615 235 : if (ret < 0) { - 1616 : /* LCOV_EXCL_START */ - 1617 : decoding_error(path, f); - 1618 : log_fatal("Invalid header!\n"); - 1619 : exit(EXIT_FAILURE); - 1620 : /* LCOV_EXCL_STOP */ - 1621 : } - 1622 : - 1623 : /* - 1624 : * File format versions: - 1625 : * - SNAPCNT1/SnapRAID 4.0 First version. - 1626 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support. - 1627 : * The previous 'm' entry is now deprecated, but supported for importing. - 1628 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'. - 1629 : */ - 1630 235 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0 - 1631 235 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0) { - 1632 : /* LCOV_EXCL_START */ - 1633 : if (memcmp(buffer, "SNAPCNT", 7) != 0) { - 1634 : decoding_error(path, f); - 1635 : log_fatal("Invalid header!\n"); - 1636 : } else { - 1637 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path); - 1638 : } + 1574 : /* if we have at least one synced file, the info is required */ + 1575 1994271 : if (block_state_get(block) == BLOCK_STATE_BLK) + 1576 1445286 : return 1; + 1577 : } + 1578 : + 1579 67932 : return 0; + 1580 : } + 1581 : + 1582 0 : static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos) + 1583 : { + 1584 : tommy_node* i; + 1585 : + 1586 : /* check for each disk if block is really used */ + 1587 0 : for (i = state->disklist; i != 0; i = i->next) { + 1588 0 : struct snapraid_disk* disk = i->data; + 1589 0 : struct snapraid_block* block = fs_par2block_get(disk, pos); + 1590 : + 1591 : /* if the block is deleted */ + 1592 0 : if (block_state_get(block) == BLOCK_STATE_DELETED) { + 1593 : /* set it to empty */ + 1594 0 : fs_deallocate(disk, pos); + 1595 : } + 1596 : } + 1597 0 : } + 1598 : + 1599 : /** + 1600 : * Check if a block position in a disk is deleted. + 1601 : */ + 1602 4507856 : static int fs_is_block_deleted_ts(struct snapraid_disk* disk, struct snapraid_chunk** fs_last, block_off_t pos) + 1603 : { + 1604 4507856 : struct snapraid_block* block = fs_par2block_get_ts(disk, fs_last, pos); + 1605 : + 1606 4507856 : return block_state_get(block) == BLOCK_STATE_DELETED; + 1607 : } + 1608 : + 1609 : /** + 1610 : * Flush the file checking the final CRC. + 1611 : * We exploit the fact that the CRC is always stored in the last 4 bytes. + 1612 : */ + 1613 1 : static void decoding_error(const char* path, STREAM* f) + 1614 : { + 1615 : unsigned char buf[4]; + 1616 : uint32_t crc_stored; + 1617 : uint32_t crc_computed; + 1618 : + 1619 1 : if (seof(f)) { + 1620 : /* LCOV_EXCL_START */ + 1621 : log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1622 : log_fatal("This content file is truncated. Use an alternate copy.\n"); + 1623 : exit(EXIT_FAILURE); + 1624 : /* LCOV_EXCL_STOP */ + 1625 : } + 1626 : + 1627 1 : if (serror(f)) { + 1628 : /* LCOV_EXCL_START */ + 1629 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1630 : exit(EXIT_FAILURE); + 1631 : /* LCOV_EXCL_STOP */ + 1632 : } + 1633 : + 1634 1 : log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); + 1635 : + 1636 1 : if (sdeplete(f, buf) != 0) { + 1637 : /* LCOV_EXCL_START */ + 1638 : log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); 1639 : exit(EXIT_FAILURE); 1640 : /* LCOV_EXCL_STOP */ 1641 : } 1642 : - 1643 : while (1) { - 1644 : int c; + 1643 : /* get the stored crc from the last four bytes */ + 1644 1 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; 1645 : - 1646 : /* read the command */ - 1647 3605061 : c = sgetc(f); - 1648 3605061 : if (c == EOF) { - 1649 234 : break; - 1650 : } + 1646 : /* get the computed crc */ + 1647 1 : crc_computed = scrc(f); + 1648 : + 1649 : /* adjust the stored crc to include itself */ + 1650 1 : crc_stored = crc32c(crc_stored, buf, 4); 1651 : - 1652 3604827 : if (c == 'f') { - 1653 : /* file */ - 1654 : char sub[PATH_MAX]; - 1655 : uint64_t v_size; - 1656 : uint64_t v_mtime_sec; - 1657 : uint32_t v_mtime_nsec; - 1658 : uint64_t v_inode; - 1659 : uint32_t v_idx; - 1660 : struct snapraid_file* file; - 1661 : struct snapraid_disk* disk; - 1662 : uint32_t mapping; - 1663 : - 1664 3485915 : ret = sgetb32(f, &mapping); - 1665 3485915 : if (ret < 0 || mapping >= mapping_max) { - 1666 : /* LCOV_EXCL_START */ - 1667 : decoding_error(path, f); - 1668 : log_fatal("Internal inconsistency in mapping index!\n"); - 1669 : exit(EXIT_FAILURE); - 1670 : /* LCOV_EXCL_STOP */ - 1671 : } - 1672 3485915 : disk = tommy_array_get(&disk_mapping, mapping); + 1652 1 : if (crc_computed != crc_stored) { + 1653 1 : log_fatal("Mismatching CRC in '%s'\n", path); + 1654 1 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 1655 1 : exit(EXIT_FAILURE); + 1656 : } else { + 1657 0 : log_fatal("The file CRC is correct!\n"); + 1658 : } + 1659 0 : } + 1660 : + 1661 243 : static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f) + 1662 : { + 1663 : block_off_t blockmax; + 1664 : unsigned count_file; + 1665 : unsigned count_hardlink; + 1666 : unsigned count_symlink; + 1667 : unsigned count_dir; + 1668 : int crc_checked; + 1669 : char buffer[PATH_MAX]; + 1670 : int ret; + 1671 : tommy_array disk_mapping; + 1672 : uint32_t mapping_max; 1673 : - 1674 3485915 : ret = sgetb64(f, &v_size); - 1675 3485915 : if (ret < 0) { - 1676 : /* LCOV_EXCL_START */ - 1677 : decoding_error(path, f); - 1678 : exit(EXIT_FAILURE); - 1679 : /* LCOV_EXCL_STOP */ - 1680 : } - 1681 : - 1682 : /* check for impossible file size to avoid to crash for a too big allocation */ - 1683 3485915 : if (v_size / state->block_size > blockmax) { - 1684 : /* LCOV_EXCL_START */ - 1685 : decoding_error(path, f); - 1686 : log_fatal("Internal inconsistency in file size too big!\n"); - 1687 : exit(EXIT_FAILURE); - 1688 : /* LCOV_EXCL_STOP */ - 1689 : } - 1690 : - 1691 3485915 : ret = sgetb64(f, &v_mtime_sec); - 1692 3485915 : if (ret < 0) { - 1693 : /* LCOV_EXCL_START */ - 1694 : decoding_error(path, f); - 1695 : exit(EXIT_FAILURE); - 1696 : /* LCOV_EXCL_STOP */ - 1697 : } - 1698 : - 1699 3485915 : ret = sgetb32(f, &v_mtime_nsec); - 1700 3485915 : if (ret < 0) { - 1701 : /* LCOV_EXCL_START */ - 1702 : decoding_error(path, f); - 1703 : exit(EXIT_FAILURE); - 1704 : /* LCOV_EXCL_STOP */ - 1705 : } - 1706 : - 1707 : /* STAT_NSEC_INVALID is encoded as 0 */ - 1708 3485915 : if (v_mtime_nsec == 0) - 1709 0 : v_mtime_nsec = STAT_NSEC_INVALID; - 1710 : else - 1711 3485915 : --v_mtime_nsec; + 1674 243 : blockmax = 0; + 1675 243 : count_file = 0; + 1676 243 : count_hardlink = 0; + 1677 243 : count_symlink = 0; + 1678 243 : count_dir = 0; + 1679 243 : crc_checked = 0; + 1680 243 : mapping_max = 0; + 1681 243 : tommy_array_init(&disk_mapping); + 1682 : + 1683 243 : ret = sread(f, buffer, 12); + 1684 243 : if (ret < 0) { + 1685 : /* LCOV_EXCL_START */ + 1686 : decoding_error(path, f); + 1687 : log_fatal("Invalid header!\n"); + 1688 : os_abort(); + 1689 : /* LCOV_EXCL_STOP */ + 1690 : } + 1691 : + 1692 : /* + 1693 : * File format versions: + 1694 : * - SNAPCNT1/SnapRAID 4.0 First version. + 1695 : * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support. + 1696 : * The previous 'm' entry is now deprecated, but supported for importing. + 1697 : * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'. + 1698 : */ + 1699 243 : if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0 + 1700 243 : && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0) { + 1701 : /* LCOV_EXCL_START */ + 1702 : if (memcmp(buffer, "SNAPCNT", 7) != 0) { + 1703 : decoding_error(path, f); + 1704 : log_fatal("Invalid header!\n"); + 1705 : os_abort(); + 1706 : } else { + 1707 : log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path); + 1708 : exit(EXIT_FAILURE); + 1709 : } + 1710 : /* LCOV_EXCL_STOP */ + 1711 : } 1712 : - 1713 3485915 : ret = sgetb64(f, &v_inode); - 1714 3485915 : if (ret < 0) { - 1715 : /* LCOV_EXCL_START */ - 1716 : decoding_error(path, f); - 1717 : exit(EXIT_FAILURE); - 1718 : /* LCOV_EXCL_STOP */ - 1719 : } - 1720 : - 1721 3485915 : ret = sgetbs(f, sub, sizeof(sub)); - 1722 3485915 : if (ret < 0) { - 1723 : /* LCOV_EXCL_START */ - 1724 : decoding_error(path, f); - 1725 : exit(EXIT_FAILURE); - 1726 : /* LCOV_EXCL_STOP */ - 1727 : } - 1728 3485915 : if (!*sub) { - 1729 : /* LCOV_EXCL_START */ - 1730 : decoding_error(path, f); - 1731 : exit(EXIT_FAILURE); - 1732 : /* LCOV_EXCL_STOP */ - 1733 : } - 1734 : - 1735 : /* allocate the file */ - 1736 3485915 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); - 1737 : - 1738 : /* insert the file in the file containers */ - 1739 3485915 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - 1740 3485915 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - 1741 3485915 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); - 1742 3485915 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 1713 : while (1) { + 1714 : int c; + 1715 : + 1716 : /* read the command */ + 1717 3653019 : c = sgetc(f); + 1718 3653019 : if (c == EOF) { + 1719 242 : break; + 1720 : } + 1721 : + 1722 3652777 : if (c == 'f') { + 1723 : /* file */ + 1724 : char sub[PATH_MAX]; + 1725 : uint64_t v_size; + 1726 : uint64_t v_mtime_sec; + 1727 : uint32_t v_mtime_nsec; + 1728 : uint64_t v_inode; + 1729 : uint32_t v_idx; + 1730 : struct snapraid_file* file; + 1731 : struct snapraid_disk* disk; + 1732 : uint32_t mapping; + 1733 : + 1734 3532322 : ret = sgetb32(f, &mapping); + 1735 3532322 : if (ret < 0 || mapping >= mapping_max) { + 1736 : /* LCOV_EXCL_START */ + 1737 : decoding_error(path, f); + 1738 : log_fatal("Internal inconsistency in mapping index!\n"); + 1739 : os_abort(); + 1740 : /* LCOV_EXCL_STOP */ + 1741 : } + 1742 3532322 : disk = tommy_array_get(&disk_mapping, mapping); 1743 : - 1744 : /* read all the blocks */ - 1745 3485915 : v_idx = 0; - 1746 10477653 : while (v_idx < file->blockmax) { - 1747 : block_off_t v_pos; - 1748 : uint32_t v_count; - 1749 : - 1750 : /* get the "subcommand */ - 1751 3505823 : c = sgetc(f); - 1752 : - 1753 3505823 : ret = sgetb32(f, &v_pos); - 1754 3505823 : if (ret < 0) { - 1755 : /* LCOV_EXCL_START */ - 1756 : decoding_error(path, f); - 1757 : exit(EXIT_FAILURE); - 1758 : /* LCOV_EXCL_STOP */ - 1759 : } + 1744 3532322 : ret = sgetb64(f, &v_size); + 1745 3532322 : if (ret < 0) { + 1746 : /* LCOV_EXCL_START */ + 1747 : decoding_error(path, f); + 1748 : os_abort(); + 1749 : /* LCOV_EXCL_STOP */ + 1750 : } + 1751 : + 1752 : /* check for impossible file size to avoid to crash for a too big allocation */ + 1753 3532322 : if (v_size / state->block_size > blockmax) { + 1754 : /* LCOV_EXCL_START */ + 1755 : decoding_error(path, f); + 1756 : log_fatal("Internal inconsistency in file size too big!\n"); + 1757 : os_abort(); + 1758 : /* LCOV_EXCL_STOP */ + 1759 : } 1760 : - 1761 3505823 : ret = sgetb32(f, &v_count); - 1762 3505823 : if (ret < 0) { - 1763 : /* LCOV_EXCL_START */ - 1764 : decoding_error(path, f); - 1765 : exit(EXIT_FAILURE); - 1766 : /* LCOV_EXCL_STOP */ - 1767 : } + 1761 3532322 : ret = sgetb64(f, &v_mtime_sec); + 1762 3532322 : if (ret < 0) { + 1763 : /* LCOV_EXCL_START */ + 1764 : decoding_error(path, f); + 1765 : os_abort(); + 1766 : /* LCOV_EXCL_STOP */ + 1767 : } 1768 : - 1769 3505823 : if (v_idx + v_count > file->blockmax) { - 1770 : /* LCOV_EXCL_START */ - 1771 : decoding_error(path, f); - 1772 : log_fatal("Internal inconsistency in block number!\n"); - 1773 : exit(EXIT_FAILURE); - 1774 : /* LCOV_EXCL_STOP */ - 1775 : } + 1769 3532322 : ret = sgetb32(f, &v_mtime_nsec); + 1770 3532322 : if (ret < 0) { + 1771 : /* LCOV_EXCL_START */ + 1772 : decoding_error(path, f); + 1773 : os_abort(); + 1774 : /* LCOV_EXCL_STOP */ + 1775 : } 1776 : - 1777 3505823 : if (v_pos + v_count > blockmax) { - 1778 : /* LCOV_EXCL_START */ - 1779 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); - 1780 : decoding_error(path, f); - 1781 : exit(EXIT_FAILURE); - 1782 : /* LCOV_EXCL_START */ - 1783 : } - 1784 : - 1785 : /* fill the blocks in the run */ - 1786 : while (v_count) { - 1787 : struct snapraid_block* block = fs_file2block_get(file, v_idx); - 1788 : - 1789 : switch (c) { - 1790 : case 'b' : - 1791 : block_state_set(block, BLOCK_STATE_BLK); - 1792 : break; - 1793 : case 'n' : - 1794 : /* deprecated NEW blocks are converted to CHG ones */ - 1795 : block_state_set(block, BLOCK_STATE_CHG); - 1796 : break; - 1797 : case 'g' : - 1798 : block_state_set(block, BLOCK_STATE_CHG); - 1799 : break; - 1800 : case 'p' : - 1801 : block_state_set(block, BLOCK_STATE_REP); - 1802 : break; - 1803 : default : - 1804 : /* LCOV_EXCL_START */ - 1805 : decoding_error(path, f); - 1806 : log_fatal("Invalid block type!\n"); - 1807 : exit(EXIT_FAILURE); - 1808 : /* LCOV_EXCL_STOP */ - 1809 : } - 1810 : - 1811 : /* read the hash only for 'blk/chg/rep', and not for 'new' */ - 1812 8573249 : if (c != 'n') { - 1813 8573249 : ret = sread(f, block->hash, HASH_SIZE); - 1814 8573249 : if (ret < 0) { - 1815 : /* LCOV_EXCL_START */ - 1816 : decoding_error(path, f); - 1817 : exit(EXIT_FAILURE); - 1818 : /* LCOV_EXCL_STOP */ - 1819 : } - 1820 : } else { - 1821 : /* set the ZERO hash for deprecated NEW blocks */ - 1822 0 : hash_zero_set(block->hash); - 1823 : } - 1824 : - 1825 : /* if the block contains a hash of past data */ - 1826 : /* and we are clearing such undeterminated hashes */ - 1827 8573249 : if (state->clear_past_hash - 1828 2287366 : && block_has_past_hash(block) - 1829 : ) { - 1830 : /* set the hash value to INVALID */ - 1831 57602 : hash_invalid_set(block->hash); - 1832 : } - 1833 : - 1834 : /* if we are disabling the copy optimization */ - 1835 : /* we want also to clear any already previously stored information */ - 1836 : /* in other sync commands */ - 1837 : /* note that this is required only in sync, and we detect */ - 1838 : /* this using the clear_past_hash flag */ - 1839 8573249 : if (state->clear_past_hash - 1840 2287366 : && state->opt.force_nocopy - 1841 14115 : && block_state_get(block) == BLOCK_STATE_REP - 1842 : ) { - 1843 : /* set the hash value to INVALID */ - 1844 1 : hash_invalid_set(block->hash); - 1845 : /* convert from REP to CHG block */ - 1846 1 : block_state_set(block, BLOCK_STATE_CHG); - 1847 : } - 1848 : - 1849 : /* if we want a full sync, marks block as invalid parity */ - 1850 : /* note that we do this after the force_nocopy option */ - 1851 : /* to avoid to mixup the two things */ - 1852 8573249 : if (state->opt.force_full - 1853 27746 : && block_state_get(block) == BLOCK_STATE_BLK) { - 1854 : /* convert from BLK to REP */ - 1855 27746 : block_state_set(block, BLOCK_STATE_REP); - 1856 : } - 1857 : - 1858 : /* set the parity association */ - 1859 8573249 : fs_allocate(disk, v_pos, file, v_idx); - 1860 : - 1861 : /* go to the next block */ - 1862 8573249 : ++v_idx; - 1863 8573249 : ++v_pos; - 1864 8573249 : --v_count; - 1865 : } - 1866 : } - 1867 : - 1868 : /* stat */ - 1869 3485915 : ++count_file; - 1870 118912 : } else if (c == 'i') { - 1871 : /* "inf" command */ - 1872 : snapraid_info info; - 1873 : uint32_t v_pos; - 1874 : uint32_t v_oldest; - 1875 : - 1876 234 : ret = sgetb32(f, &v_oldest); - 1877 234 : if (ret < 0) { - 1878 : /* LCOV_EXCL_START */ - 1879 : decoding_error(path, f); - 1880 : exit(EXIT_FAILURE); - 1881 : /* LCOV_EXCL_STOP */ - 1882 : } - 1883 : - 1884 234 : v_pos = 0; - 1885 288815 : while (v_pos < blockmax) { - 1886 : int bad; - 1887 : int rehash; - 1888 : int justsynced; - 1889 : uint32_t t; - 1890 : uint32_t flag; - 1891 : uint32_t v_count; - 1892 : - 1893 288347 : ret = sgetb32(f, &v_count); - 1894 288347 : if (ret < 0) { - 1895 : /* LCOV_EXCL_START */ - 1896 : decoding_error(path, f); - 1897 : exit(EXIT_FAILURE); - 1898 : /* LCOV_EXCL_STOP */ - 1899 : } - 1900 : - 1901 288347 : if (v_pos + v_count > blockmax) { - 1902 : /* LCOV_EXCL_START */ - 1903 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); - 1904 : decoding_error(path, f); - 1905 : exit(EXIT_FAILURE); - 1906 : /* LCOV_EXCL_STOP */ - 1907 : } - 1908 : - 1909 288347 : ret = sgetb32(f, &flag); - 1910 288347 : if (ret < 0) { - 1911 : /* LCOV_EXCL_START */ - 1912 : decoding_error(path, f); - 1913 : exit(EXIT_FAILURE); - 1914 : /* LCOV_EXCL_STOP */ - 1915 : } - 1916 : - 1917 : /* if there is an info */ - 1918 288347 : if ((flag & 1) != 0) { - 1919 : /* read the time */ - 1920 288332 : ret = sgetb32(f, &t); - 1921 288332 : if (ret < 0) { - 1922 : /* LCOV_EXCL_START */ - 1923 : decoding_error(path, f); - 1924 : exit(EXIT_FAILURE); - 1925 : /* LCOV_EXCL_STOP */ - 1926 : } - 1927 : - 1928 : /* analyze the flags */ - 1929 288332 : bad = (flag & 2) != 0; - 1930 288332 : rehash = (flag & 4) != 0; - 1931 288332 : justsynced = (flag & 8) != 0; - 1932 : - 1933 288332 : if (rehash && state->prevhash == HASH_UNDEFINED) { - 1934 : /* LCOV_EXCL_START */ - 1935 : decoding_error(path, f); - 1936 : log_fatal("Internal inconsistency for missing previous checksum!\n"); - 1937 : exit(EXIT_FAILURE); - 1938 : /* LCOV_EXCL_STOP */ - 1939 : } - 1940 : - 1941 288332 : info = info_make(t + v_oldest, bad, rehash, justsynced); - 1942 : } else { - 1943 15 : info = 0; - 1944 : } - 1945 : - 1946 2068514 : while (v_count) { - 1947 : /* insert the info in the array */ - 1948 1491820 : info_set(&state->infoarr, v_pos, info); - 1949 : - 1950 : /* ensure that an info is present only for used positions */ - 1951 1491820 : if (fs_info_is_required(state, v_pos)) { - 1952 1433375 : if (!info) { - 1953 : /* LCOV_EXCL_START */ - 1954 : decoding_error(path, f); - 1955 : log_fatal("Internal inconsistency for missing info!\n"); - 1956 : exit(EXIT_FAILURE); - 1957 : /* LCOV_EXCL_STOP */ - 1958 : } - 1959 : } else { - 1960 : /* extra info are accepted for backward compatibility */ - 1961 : /* they are discarged at the first write */ - 1962 : } + 1777 : /* STAT_NSEC_INVALID is encoded as 0 */ + 1778 3532322 : if (v_mtime_nsec == 0) + 1779 0 : v_mtime_nsec = STAT_NSEC_INVALID; + 1780 : else + 1781 3532322 : --v_mtime_nsec; + 1782 : + 1783 3532322 : ret = sgetb64(f, &v_inode); + 1784 3532322 : if (ret < 0) { + 1785 : /* LCOV_EXCL_START */ + 1786 : decoding_error(path, f); + 1787 : os_abort(); + 1788 : /* LCOV_EXCL_STOP */ + 1789 : } + 1790 : + 1791 3532322 : ret = sgetbs(f, sub, sizeof(sub)); + 1792 3532322 : if (ret < 0) { + 1793 : /* LCOV_EXCL_START */ + 1794 : decoding_error(path, f); + 1795 : os_abort(); + 1796 : /* LCOV_EXCL_STOP */ + 1797 : } + 1798 3532321 : if (!*sub) { + 1799 : /* LCOV_EXCL_START */ + 1800 : decoding_error(path, f); + 1801 : log_fatal("Internal inconsistency for null file!\n"); + 1802 : os_abort(); + 1803 : /* LCOV_EXCL_STOP */ + 1804 : } + 1805 : + 1806 : /* allocate the file */ + 1807 3532321 : file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); + 1808 : + 1809 : /* insert the file in the file containers */ + 1810 3532321 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + 1811 3532321 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + 1812 3532321 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + 1813 3532321 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + 1814 : + 1815 : /* read all the blocks */ + 1816 3532321 : v_idx = 0; + 1817 10617218 : while (v_idx < file->blockmax) { + 1818 : block_off_t v_pos; + 1819 : uint32_t v_count; + 1820 : + 1821 : /* get the "subcommand */ + 1822 3552576 : c = sgetc(f); + 1823 : + 1824 3552576 : ret = sgetb32(f, &v_pos); + 1825 3552576 : if (ret < 0) { + 1826 : /* LCOV_EXCL_START */ + 1827 : decoding_error(path, f); + 1828 : os_abort(); + 1829 : /* LCOV_EXCL_STOP */ + 1830 : } + 1831 : + 1832 3552576 : ret = sgetb32(f, &v_count); + 1833 3552576 : if (ret < 0) { + 1834 : /* LCOV_EXCL_START */ + 1835 : decoding_error(path, f); + 1836 : os_abort(); + 1837 : /* LCOV_EXCL_STOP */ + 1838 : } + 1839 : + 1840 3552576 : if (v_idx + v_count > file->blockmax) { + 1841 : /* LCOV_EXCL_START */ + 1842 : decoding_error(path, f); + 1843 : log_fatal("Internal inconsistency in block number!\n"); + 1844 : os_abort(); + 1845 : /* LCOV_EXCL_STOP */ + 1846 : } + 1847 : + 1848 3552576 : if (v_pos + v_count > blockmax) { + 1849 : /* LCOV_EXCL_START */ + 1850 : decoding_error(path, f); + 1851 : log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); + 1852 : os_abort(); + 1853 : /* LCOV_EXCL_START */ + 1854 : } + 1855 : + 1856 : /* fill the blocks in the run */ + 1857 : while (v_count) { + 1858 : struct snapraid_block* block = fs_file2block_get(file, v_idx); + 1859 : + 1860 : switch (c) { + 1861 : case 'b' : + 1862 : block_state_set(block, BLOCK_STATE_BLK); + 1863 : break; + 1864 : case 'n' : + 1865 : /* deprecated NEW blocks are converted to CHG ones */ + 1866 : block_state_set(block, BLOCK_STATE_CHG); + 1867 : break; + 1868 : case 'g' : + 1869 : block_state_set(block, BLOCK_STATE_CHG); + 1870 : break; + 1871 : case 'p' : + 1872 : block_state_set(block, BLOCK_STATE_REP); + 1873 : break; + 1874 : default : + 1875 : /* LCOV_EXCL_START */ + 1876 : decoding_error(path, f); + 1877 : log_fatal("Invalid block type!\n"); + 1878 : os_abort(); + 1879 : /* LCOV_EXCL_STOP */ + 1880 : } + 1881 : + 1882 : /* read the hash only for 'blk/chg/rep', and not for 'new' */ + 1883 8696195 : if (c != 'n') { + 1884 8696195 : ret = sread(f, block->hash, HASH_SIZE); + 1885 8696195 : if (ret < 0) { + 1886 : /* LCOV_EXCL_START */ + 1887 : decoding_error(path, f); + 1888 : os_abort(); + 1889 : /* LCOV_EXCL_STOP */ + 1890 : } + 1891 : } else { + 1892 : /* set the ZERO hash for deprecated NEW blocks */ + 1893 0 : hash_zero_set(block->hash); + 1894 : } + 1895 : + 1896 : /* if the block contains a hash of past data */ + 1897 : /* and we are clearing such undeterminated hashes */ + 1898 8696195 : if (state->clear_past_hash + 1899 2401624 : && block_has_past_hash(block) + 1900 : ) { + 1901 : /* set the hash value to INVALID */ + 1902 28006 : hash_invalid_set(block->hash); + 1903 : } + 1904 : + 1905 : /* if we are disabling the copy optimization */ + 1906 : /* we want also to clear any already previously stored information */ + 1907 : /* in other sync commands */ + 1908 : /* note that this is required only in sync, and we detect */ + 1909 : /* this using the clear_past_hash flag */ + 1910 8696195 : if (state->clear_past_hash + 1911 2401624 : && state->opt.force_nocopy + 1912 14171 : && block_state_get(block) == BLOCK_STATE_REP + 1913 : ) { + 1914 : /* set the hash value to INVALID */ + 1915 1 : hash_invalid_set(block->hash); + 1916 : /* convert from REP to CHG block */ + 1917 1 : block_state_set(block, BLOCK_STATE_CHG); + 1918 : } + 1919 : + 1920 : /* if we want a full sync, marks block as invalid parity */ + 1921 : /* note that we do this after the force_nocopy option */ + 1922 : /* to avoid to mixup the two things */ + 1923 8696195 : if (state->opt.force_full + 1924 82268 : && block_state_get(block) == BLOCK_STATE_BLK) { + 1925 : /* convert from BLK to REP */ + 1926 82268 : block_state_set(block, BLOCK_STATE_REP); + 1927 : } + 1928 : + 1929 : /* set the parity association */ + 1930 8696195 : fs_allocate(disk, v_pos, file, v_idx); + 1931 : + 1932 : /* go to the next block */ + 1933 8696195 : ++v_idx; + 1934 8696195 : ++v_pos; + 1935 8696195 : --v_count; + 1936 : } + 1937 : } + 1938 : + 1939 : /* stat */ + 1940 3532321 : ++count_file; + 1941 120455 : } else if (c == 'i') { + 1942 : /* "inf" command */ + 1943 : snapraid_info info; + 1944 : uint32_t v_pos; + 1945 : uint32_t v_oldest; + 1946 : + 1947 242 : ret = sgetb32(f, &v_oldest); + 1948 242 : if (ret < 0) { + 1949 : /* LCOV_EXCL_START */ + 1950 : decoding_error(path, f); + 1951 : os_abort(); + 1952 : /* LCOV_EXCL_STOP */ + 1953 : } + 1954 : + 1955 242 : v_pos = 0; + 1956 59307 : while (v_pos < blockmax) { + 1957 : int bad; + 1958 : int rehash; + 1959 : int justsynced; + 1960 : uint32_t t; + 1961 : uint32_t flag; + 1962 : uint32_t v_count; 1963 : - 1964 : /* go to next block */ - 1965 1491820 : ++v_pos; - 1966 1491820 : --v_count; - 1967 : } - 1968 : } - 1969 118678 : } else if (c == 'h') { - 1970 : /* hole */ - 1971 : uint32_t v_pos; - 1972 : struct snapraid_disk* disk; - 1973 : uint32_t mapping; - 1974 : - 1975 1299 : ret = sgetb32(f, &mapping); - 1976 1299 : if (ret < 0 || mapping >= mapping_max) { - 1977 : /* LCOV_EXCL_START */ - 1978 : decoding_error(path, f); - 1979 : log_fatal("Internal inconsistency in mapping index!\n"); - 1980 : exit(EXIT_FAILURE); - 1981 : /* LCOV_EXCL_STOP */ - 1982 : } - 1983 1299 : disk = tommy_array_get(&disk_mapping, mapping); - 1984 : - 1985 1299 : v_pos = 0; - 1986 3965 : while (v_pos < blockmax) { - 1987 : uint32_t v_idx; - 1988 : uint32_t v_count; - 1989 : struct snapraid_file* deleted; - 1990 : - 1991 1367 : ret = sgetb32(f, &v_count); - 1992 1367 : if (ret < 0) { - 1993 : /* LCOV_EXCL_START */ - 1994 : decoding_error(path, f); - 1995 : exit(EXIT_FAILURE); - 1996 : /* LCOV_EXCL_STOP */ - 1997 : } + 1964 58823 : ret = sgetb32(f, &v_count); + 1965 58823 : if (ret < 0) { + 1966 : /* LCOV_EXCL_START */ + 1967 : decoding_error(path, f); + 1968 : os_abort(); + 1969 : /* LCOV_EXCL_STOP */ + 1970 : } + 1971 : + 1972 58823 : if (v_pos + v_count > blockmax) { + 1973 : /* LCOV_EXCL_START */ + 1974 : decoding_error(path, f); + 1975 : log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); + 1976 : os_abort(); + 1977 : /* LCOV_EXCL_STOP */ + 1978 : } + 1979 : + 1980 58823 : ret = sgetb32(f, &flag); + 1981 58823 : if (ret < 0) { + 1982 : /* LCOV_EXCL_START */ + 1983 : decoding_error(path, f); + 1984 : os_abort(); + 1985 : /* LCOV_EXCL_STOP */ + 1986 : } + 1987 : + 1988 : /* if there is an info */ + 1989 58823 : if ((flag & 1) != 0) { + 1990 : /* read the time */ + 1991 58808 : ret = sgetb32(f, &t); + 1992 58808 : if (ret < 0) { + 1993 : /* LCOV_EXCL_START */ + 1994 : decoding_error(path, f); + 1995 : os_abort(); + 1996 : /* LCOV_EXCL_STOP */ + 1997 : } 1998 : - 1999 1367 : if (v_pos + v_count > blockmax) { - 2000 : /* LCOV_EXCL_START */ - 2001 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); - 2002 : decoding_error(path, f); - 2003 : exit(EXIT_FAILURE); - 2004 : /* LCOV_EXCL_STOP */ - 2005 : } - 2006 : - 2007 : /* get the subcommand */ - 2008 1367 : c = sgetc(f); - 2009 : - 2010 1367 : switch (c) { - 2011 : case 'o' : - 2012 : /* if it's a run of deleted blocks */ - 2013 : - 2014 : /* allocate a fake deleted file */ - 2015 36 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0); + 1999 : /* analyze the flags */ + 2000 58808 : bad = (flag & 2) != 0; + 2001 58808 : rehash = (flag & 4) != 0; + 2002 58808 : justsynced = (flag & 8) != 0; + 2003 : + 2004 58808 : if (rehash && state->prevhash == HASH_UNDEFINED) { + 2005 : /* LCOV_EXCL_START */ + 2006 : decoding_error(path, f); + 2007 : log_fatal("Internal inconsistency for missing previous checksum!\n"); + 2008 : os_abort(); + 2009 : /* LCOV_EXCL_STOP */ + 2010 : } + 2011 : + 2012 58808 : info = info_make(t + v_oldest, bad, rehash, justsynced); + 2013 : } else { + 2014 15 : info = 0; + 2015 : } 2016 : - 2017 : /* mark the file as deleted */ - 2018 36 : file_flag_set(deleted, FILE_IS_DELETED); - 2019 : - 2020 : /* insert it in the list of deleted files */ - 2021 36 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted); - 2022 : - 2023 : /* process all blocks */ - 2024 36 : v_idx = 0; - 2025 27959 : while (v_count) { - 2026 27887 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx); - 2027 : - 2028 : /* set the block as deleted */ - 2029 27887 : block_state_set(block, BLOCK_STATE_DELETED); - 2030 : - 2031 : /* read the hash */ - 2032 27887 : ret = sread(f, block->hash, HASH_SIZE); - 2033 27887 : if (ret < 0) { - 2034 : /* LCOV_EXCL_START */ - 2035 : decoding_error(path, f); - 2036 : exit(EXIT_FAILURE); - 2037 : /* LCOV_EXCL_STOP */ - 2038 : } - 2039 : - 2040 : /* if we are clearing undeterminated hashes */ - 2041 27887 : if (state->clear_past_hash) { - 2042 : /* set the hash value to INVALID */ - 2043 9433 : hash_invalid_set(block->hash); - 2044 : } + 2017 1630864 : while (v_count) { + 2018 : /* insert the info in the array */ + 2019 1513218 : info_set(&state->infoarr, v_pos, info); + 2020 : + 2021 : /* ensure that an info is present only for used positions */ + 2022 1513218 : if (fs_info_is_required(state, v_pos)) { + 2023 1445286 : if (!info) { + 2024 : /* LCOV_EXCL_START */ + 2025 : decoding_error(path, f); + 2026 : log_fatal("Internal inconsistency for missing info!\n"); + 2027 : os_abort(); + 2028 : /* LCOV_EXCL_STOP */ + 2029 : } + 2030 : } else { + 2031 : /* extra info are accepted for backward compatibility */ + 2032 : /* they are discarded at the first write */ + 2033 : } + 2034 : + 2035 : /* go to next block */ + 2036 1513218 : ++v_pos; + 2037 1513218 : --v_count; + 2038 : } + 2039 : } + 2040 120213 : } else if (c == 'h') { + 2041 : /* hole */ + 2042 : uint32_t v_pos; + 2043 : struct snapraid_disk* disk; + 2044 : uint32_t mapping; 2045 : - 2046 : /* insert the block in the block array */ - 2047 27887 : fs_allocate(disk, v_pos, deleted, v_idx); - 2048 : - 2049 : /* go to next block */ - 2050 27887 : ++v_pos; - 2051 27887 : ++v_idx; - 2052 27887 : --v_count; - 2053 : } - 2054 36 : break; - 2055 : case 'O' : - 2056 : /* go to the next run */ - 2057 1331 : v_pos += v_count; - 2058 1331 : break; - 2059 : default : - 2060 : /* LCOV_EXCL_START */ - 2061 : decoding_error(path, f); - 2062 : log_fatal("Invalid hole type!\n"); - 2063 : exit(EXIT_FAILURE); - 2064 : /* LCOV_EXCL_STOP */ - 2065 : } - 2066 : } - 2067 117379 : } else if (c == 's') { - 2068 : /* symlink */ - 2069 : char sub[PATH_MAX]; - 2070 : char linkto[PATH_MAX]; - 2071 : struct snapraid_link* slink; - 2072 : struct snapraid_disk* disk; - 2073 : uint32_t mapping; - 2074 : - 2075 112395 : ret = sgetb32(f, &mapping); - 2076 112395 : if (ret < 0 || mapping >= mapping_max) { - 2077 : /* LCOV_EXCL_START */ - 2078 : decoding_error(path, f); - 2079 : log_fatal("Internal inconsistency in mapping index!\n"); - 2080 : exit(EXIT_FAILURE); - 2081 : /* LCOV_EXCL_STOP */ - 2082 : } - 2083 112395 : disk = tommy_array_get(&disk_mapping, mapping); + 2046 1334 : ret = sgetb32(f, &mapping); + 2047 1334 : if (ret < 0 || mapping >= mapping_max) { + 2048 : /* LCOV_EXCL_START */ + 2049 : decoding_error(path, f); + 2050 : log_fatal("Internal inconsistency in mapping index!\n"); + 2051 : os_abort(); + 2052 : /* LCOV_EXCL_STOP */ + 2053 : } + 2054 1334 : disk = tommy_array_get(&disk_mapping, mapping); + 2055 : + 2056 1334 : v_pos = 0; + 2057 4080 : while (v_pos < blockmax) { + 2058 : uint32_t v_idx; + 2059 : uint32_t v_count; + 2060 : struct snapraid_file* deleted; + 2061 : + 2062 1412 : ret = sgetb32(f, &v_count); + 2063 1412 : if (ret < 0) { + 2064 : /* LCOV_EXCL_START */ + 2065 : decoding_error(path, f); + 2066 : os_abort(); + 2067 : /* LCOV_EXCL_STOP */ + 2068 : } + 2069 : + 2070 1412 : if (v_pos + v_count > blockmax) { + 2071 : /* LCOV_EXCL_START */ + 2072 : decoding_error(path, f); + 2073 : log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); + 2074 : os_abort(); + 2075 : /* LCOV_EXCL_STOP */ + 2076 : } + 2077 : + 2078 : /* get the sub-command */ + 2079 1412 : c = sgetc(f); + 2080 : + 2081 1412 : switch (c) { + 2082 : case 'o' : + 2083 : /* if it's a run of deleted blocks */ 2084 : - 2085 112395 : ret = sgetbs(f, sub, sizeof(sub)); - 2086 112395 : if (ret < 0) { - 2087 : /* LCOV_EXCL_START */ - 2088 : decoding_error(path, f); - 2089 : exit(EXIT_FAILURE); - 2090 : /* LCOV_EXCL_STOP */ - 2091 : } - 2092 : - 2093 112395 : ret = sgetbs(f, linkto, sizeof(linkto)); - 2094 112395 : if (ret < 0) { - 2095 : /* LCOV_EXCL_START */ - 2096 : decoding_error(path, f); - 2097 : exit(EXIT_FAILURE); - 2098 : /* LCOV_EXCL_STOP */ - 2099 : } - 2100 : - 2101 112395 : if (!*sub || !*linkto) { - 2102 : /* LCOV_EXCL_START */ - 2103 : decoding_error(path, f); - 2104 : exit(EXIT_FAILURE); - 2105 : /* LCOV_EXCL_STOP */ - 2106 : } - 2107 : - 2108 : /* allocate the link as symbolic link */ - 2109 112395 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK); + 2085 : /* allocate a fake deleted file */ + 2086 41 : deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0, 0); + 2087 : + 2088 : /* mark the file as deleted */ + 2089 41 : file_flag_set(deleted, FILE_IS_DELETED); + 2090 : + 2091 : /* insert it in the list of deleted files */ + 2092 41 : tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted); + 2093 : + 2094 : /* process all blocks */ + 2095 41 : v_idx = 0; + 2096 27968 : while (v_count) { + 2097 27886 : struct snapraid_block* block = fs_file2block_get(deleted, v_idx); + 2098 : + 2099 : /* set the block as deleted */ + 2100 27886 : block_state_set(block, BLOCK_STATE_DELETED); + 2101 : + 2102 : /* read the hash */ + 2103 27886 : ret = sread(f, block->hash, HASH_SIZE); + 2104 27886 : if (ret < 0) { + 2105 : /* LCOV_EXCL_START */ + 2106 : decoding_error(path, f); + 2107 : os_abort(); + 2108 : /* LCOV_EXCL_STOP */ + 2109 : } 2110 : - 2111 : /* insert the link in the link containers */ - 2112 112395 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); - 2113 112395 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); - 2114 : - 2115 : /* stat */ - 2116 112395 : ++count_symlink; - 2117 4984 : } else if (c == 'a') { - 2118 : /* hardlink */ - 2119 : char sub[PATH_MAX]; - 2120 : char linkto[PATH_MAX]; - 2121 : struct snapraid_link* slink; - 2122 : struct snapraid_disk* disk; - 2123 : uint32_t mapping; - 2124 : - 2125 567 : ret = sgetb32(f, &mapping); - 2126 567 : if (ret < 0 || mapping >= mapping_max) { - 2127 : /* LCOV_EXCL_START */ - 2128 : decoding_error(path, f); - 2129 : log_fatal("Internal inconsistency in mapping index!\n"); - 2130 : exit(EXIT_FAILURE); - 2131 : /* LCOV_EXCL_STOP */ - 2132 : } - 2133 567 : disk = tommy_array_get(&disk_mapping, mapping); - 2134 : - 2135 567 : ret = sgetbs(f, sub, sizeof(sub)); - 2136 567 : if (ret < 0) { - 2137 : /* LCOV_EXCL_START */ - 2138 : decoding_error(path, f); - 2139 : exit(EXIT_FAILURE); - 2140 : /* LCOV_EXCL_STOP */ - 2141 : } - 2142 : - 2143 567 : ret = sgetbs(f, linkto, sizeof(linkto)); - 2144 567 : if (ret < 0) { - 2145 : /* LCOV_EXCL_START */ - 2146 : decoding_error(path, f); - 2147 : exit(EXIT_FAILURE); - 2148 : /* LCOV_EXCL_STOP */ - 2149 : } - 2150 : - 2151 567 : if (!*sub || !*linkto) { - 2152 : /* LCOV_EXCL_START */ - 2153 : decoding_error(path, f); - 2154 : exit(EXIT_FAILURE); - 2155 : /* LCOV_EXCL_STOP */ - 2156 : } - 2157 : - 2158 : /* allocate the link as hard link */ - 2159 567 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK); - 2160 : - 2161 : /* insert the link in the link containers */ - 2162 567 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); - 2163 567 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); - 2164 : - 2165 : /* stat */ - 2166 567 : ++count_hardlink; - 2167 4417 : } else if (c == 'r') { - 2168 : /* dir */ - 2169 : char sub[PATH_MAX]; - 2170 : struct snapraid_dir* dir; - 2171 : struct snapraid_disk* disk; - 2172 : uint32_t mapping; - 2173 : - 2174 750 : ret = sgetb32(f, &mapping); - 2175 750 : if (ret < 0 || mapping >= mapping_max) { - 2176 : /* LCOV_EXCL_START */ - 2177 : decoding_error(path, f); - 2178 : log_fatal("Internal inconsistency in mapping index!\n"); - 2179 : exit(EXIT_FAILURE); - 2180 : /* LCOV_EXCL_STOP */ - 2181 : } - 2182 750 : disk = tommy_array_get(&disk_mapping, mapping); - 2183 : - 2184 750 : ret = sgetbs(f, sub, sizeof(sub)); - 2185 750 : if (ret < 0) { - 2186 : /* LCOV_EXCL_START */ - 2187 : decoding_error(path, f); - 2188 : exit(EXIT_FAILURE); - 2189 : /* LCOV_EXCL_STOP */ - 2190 : } - 2191 : - 2192 750 : if (!*sub) { - 2193 : /* LCOV_EXCL_START */ - 2194 : decoding_error(path, f); - 2195 : exit(EXIT_FAILURE); - 2196 : /* LCOV_EXCL_STOP */ - 2197 : } - 2198 : - 2199 : /* allocate the dir */ - 2200 750 : dir = dir_alloc(sub); - 2201 : - 2202 : /* insert the dir in the dir containers */ - 2203 750 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); - 2204 750 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); - 2205 : - 2206 : /* stat */ - 2207 750 : ++count_dir; - 2208 3667 : } else if (c == 'c') { - 2209 : /* get the subcommand */ - 2210 235 : c = sgetc(f); - 2211 : - 2212 235 : switch (c) { - 2213 : case 'u' : - 2214 148 : state->hash = HASH_MURMUR3; - 2215 148 : break; - 2216 : case 'k' : - 2217 87 : state->hash = HASH_SPOOKY2; - 2218 87 : break; - 2219 : default : - 2220 : /* LCOV_EXCL_START */ - 2221 : decoding_error(path, f); - 2222 : log_fatal("Invalid checksum!\n"); - 2223 : exit(EXIT_FAILURE); - 2224 : /* LCOV_EXCL_STOP */ - 2225 : } - 2226 : - 2227 : /* read the seed */ - 2228 235 : ret = sread(f, state->hashseed, HASH_SIZE); - 2229 235 : if (ret < 0) { - 2230 : /* LCOV_EXCL_START */ - 2231 : decoding_error(path, f); - 2232 : exit(EXIT_FAILURE); - 2233 : /* LCOV_EXCL_STOP */ - 2234 : } - 2235 3432 : } else if (c == 'C') { - 2236 : /* get the subcommand */ - 2237 87 : c = sgetc(f); + 2111 : /* if we are clearing indeterminate hashes */ + 2112 27886 : if (state->clear_past_hash) { + 2113 : /* set the hash value to INVALID */ + 2114 9432 : hash_invalid_set(block->hash); + 2115 : } + 2116 : + 2117 : /* insert the block in the block array */ + 2118 27886 : fs_allocate(disk, v_pos, deleted, v_idx); + 2119 : + 2120 : /* go to next block */ + 2121 27886 : ++v_pos; + 2122 27886 : ++v_idx; + 2123 27886 : --v_count; + 2124 : } + 2125 41 : break; + 2126 : case 'O' : + 2127 : /* go to the next run */ + 2128 1371 : v_pos += v_count; + 2129 1371 : break; + 2130 : default : + 2131 : /* LCOV_EXCL_START */ + 2132 : decoding_error(path, f); + 2133 : log_fatal("Invalid hole type!\n"); + 2134 : os_abort(); + 2135 : /* LCOV_EXCL_STOP */ + 2136 : } + 2137 : } + 2138 118879 : } else if (c == 's') { + 2139 : /* symlink */ + 2140 : char sub[PATH_MAX]; + 2141 : char linkto[PATH_MAX]; + 2142 : struct snapraid_link* slink; + 2143 : struct snapraid_disk* disk; + 2144 : uint32_t mapping; + 2145 : + 2146 113843 : ret = sgetb32(f, &mapping); + 2147 113843 : if (ret < 0 || mapping >= mapping_max) { + 2148 : /* LCOV_EXCL_START */ + 2149 : decoding_error(path, f); + 2150 : log_fatal("Internal inconsistency in mapping index!\n"); + 2151 : os_abort(); + 2152 : /* LCOV_EXCL_STOP */ + 2153 : } + 2154 113843 : disk = tommy_array_get(&disk_mapping, mapping); + 2155 : + 2156 113843 : ret = sgetbs(f, sub, sizeof(sub)); + 2157 113843 : if (ret < 0) { + 2158 : /* LCOV_EXCL_START */ + 2159 : decoding_error(path, f); + 2160 : os_abort(); + 2161 : /* LCOV_EXCL_STOP */ + 2162 : } + 2163 : + 2164 113843 : if (!*sub) { + 2165 : /* LCOV_EXCL_START */ + 2166 : decoding_error(path, f); + 2167 : log_fatal("Internal inconsistency for null symlink!\n"); + 2168 : os_abort(); + 2169 : /* LCOV_EXCL_STOP */ + 2170 : } + 2171 : + 2172 113843 : ret = sgetbs(f, linkto, sizeof(linkto)); + 2173 113843 : if (ret < 0) { + 2174 : /* LCOV_EXCL_START */ + 2175 : decoding_error(path, f); + 2176 : os_abort(); + 2177 : /* LCOV_EXCL_STOP */ + 2178 : } + 2179 : + 2180 : /* allocate the link as symbolic link */ + 2181 113843 : slink = link_alloc(sub, linkto, FILE_IS_SYMLINK); + 2182 : + 2183 : /* insert the link in the link containers */ + 2184 113843 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + 2185 113843 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + 2186 : + 2187 : /* stat */ + 2188 113843 : ++count_symlink; + 2189 5036 : } else if (c == 'a') { + 2190 : /* hardlink */ + 2191 : char sub[PATH_MAX]; + 2192 : char linkto[PATH_MAX]; + 2193 : struct snapraid_link* slink; + 2194 : struct snapraid_disk* disk; + 2195 : uint32_t mapping; + 2196 : + 2197 576 : ret = sgetb32(f, &mapping); + 2198 576 : if (ret < 0 || mapping >= mapping_max) { + 2199 : /* LCOV_EXCL_START */ + 2200 : decoding_error(path, f); + 2201 : log_fatal("Internal inconsistency in mapping index!\n"); + 2202 : os_abort(); + 2203 : /* LCOV_EXCL_STOP */ + 2204 : } + 2205 576 : disk = tommy_array_get(&disk_mapping, mapping); + 2206 : + 2207 576 : ret = sgetbs(f, sub, sizeof(sub)); + 2208 576 : if (ret < 0) { + 2209 : /* LCOV_EXCL_START */ + 2210 : decoding_error(path, f); + 2211 : os_abort(); + 2212 : /* LCOV_EXCL_STOP */ + 2213 : } + 2214 : + 2215 576 : if (!*sub) { + 2216 : /* LCOV_EXCL_START */ + 2217 : decoding_error(path, f); + 2218 : log_fatal("Internal inconsistency for null hardlink!\n"); + 2219 : os_abort(); + 2220 : /* LCOV_EXCL_STOP */ + 2221 : } + 2222 : + 2223 576 : ret = sgetbs(f, linkto, sizeof(linkto)); + 2224 576 : if (ret < 0) { + 2225 : /* LCOV_EXCL_START */ + 2226 : decoding_error(path, f); + 2227 : os_abort(); + 2228 : /* LCOV_EXCL_STOP */ + 2229 : } + 2230 : + 2231 576 : if (!*linkto) { + 2232 : /* LCOV_EXCL_START */ + 2233 : decoding_error(path, f); + 2234 : log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub); + 2235 : os_abort(); + 2236 : /* LCOV_EXCL_STOP */ + 2237 : } 2238 : - 2239 87 : switch (c) { - 2240 : case 'u' : - 2241 87 : state->prevhash = HASH_MURMUR3; - 2242 87 : break; - 2243 : case 'k' : - 2244 0 : state->prevhash = HASH_SPOOKY2; - 2245 0 : break; - 2246 : default : - 2247 : /* LCOV_EXCL_START */ - 2248 : decoding_error(path, f); - 2249 : log_fatal("Invalid checksum!\n"); - 2250 : exit(EXIT_FAILURE); - 2251 : /* LCOV_EXCL_STOP */ - 2252 : } - 2253 : - 2254 : /* read the seed */ - 2255 87 : ret = sread(f, state->prevhashseed, HASH_SIZE); - 2256 87 : if (ret < 0) { + 2239 : /* allocate the link as hard link */ + 2240 576 : slink = link_alloc(sub, linkto, FILE_IS_HARDLINK); + 2241 : + 2242 : /* insert the link in the link containers */ + 2243 576 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + 2244 576 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + 2245 : + 2246 : /* stat */ + 2247 576 : ++count_hardlink; + 2248 4460 : } else if (c == 'r') { + 2249 : /* dir */ + 2250 : char sub[PATH_MAX]; + 2251 : struct snapraid_dir* dir; + 2252 : struct snapraid_disk* disk; + 2253 : uint32_t mapping; + 2254 : + 2255 762 : ret = sgetb32(f, &mapping); + 2256 762 : if (ret < 0 || mapping >= mapping_max) { 2257 : /* LCOV_EXCL_START */ 2258 : decoding_error(path, f); - 2259 : exit(EXIT_FAILURE); - 2260 : /* LCOV_EXCL_STOP */ - 2261 : } - 2262 3345 : } else if (c == 'z') { - 2263 : block_off_t blksize; + 2259 : log_fatal("Internal inconsistency in mapping index!\n"); + 2260 : os_abort(); + 2261 : /* LCOV_EXCL_STOP */ + 2262 : } + 2263 762 : disk = tommy_array_get(&disk_mapping, mapping); 2264 : - 2265 235 : ret = sgetb32(f, &blksize); - 2266 235 : if (ret < 0) { + 2265 762 : ret = sgetbs(f, sub, sizeof(sub)); + 2266 762 : if (ret < 0) { 2267 : /* LCOV_EXCL_START */ 2268 : decoding_error(path, f); - 2269 : exit(EXIT_FAILURE); + 2269 : os_abort(); 2270 : /* LCOV_EXCL_STOP */ 2271 : } 2272 : - 2273 : /* without configuration, auto assign the block size */ - 2274 235 : if (state->no_conf) { - 2275 1 : state->block_size = blksize; - 2276 : } - 2277 : - 2278 235 : if (blksize != state->block_size) { - 2279 : /* LCOV_EXCL_START */ - 2280 : decoding_error(path, f); - 2281 : log_fatal("Mismatching 'blksize' and 'blocksize' specification!\n"); - 2282 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", blksize / 1024); - 2283 : exit(EXIT_FAILURE); - 2284 : /* LCOV_EXCL_STOP */ - 2285 : } - 2286 3110 : } else if (c == 'x') { - 2287 235 : ret = sgetb32(f, &blockmax); - 2288 235 : if (ret < 0) { - 2289 : /* LCOV_EXCL_START */ - 2290 : decoding_error(path, f); - 2291 : exit(EXIT_FAILURE); - 2292 : /* LCOV_EXCL_STOP */ - 2293 : } - 2294 4180 : } else if (c == 'm' || c == 'M') { - 2295 : struct snapraid_map* map; - 2296 : char uuid[UUID_MAX]; - 2297 : uint32_t v_pos; - 2298 : uint32_t v_total_blocks; - 2299 : uint32_t v_free_blocks; - 2300 : struct snapraid_disk* disk; - 2301 : - 2302 1305 : ret = sgetbs(f, buffer, sizeof(buffer)); - 2303 1305 : if (ret < 0) { - 2304 : /* LCOV_EXCL_START */ - 2305 : decoding_error(path, f); - 2306 : exit(EXIT_FAILURE); - 2307 : /* LCOV_EXCL_STOP */ - 2308 : } - 2309 : - 2310 1305 : ret = sgetb32(f, &v_pos); - 2311 1305 : if (ret < 0) { + 2273 762 : if (!*sub) { + 2274 : /* LCOV_EXCL_START */ + 2275 : decoding_error(path, f); + 2276 : log_fatal("Internal inconsistency for null dir!\n"); + 2277 : os_abort(); + 2278 : /* LCOV_EXCL_STOP */ + 2279 : } + 2280 : + 2281 : /* allocate the dir */ + 2282 762 : dir = dir_alloc(sub); + 2283 : + 2284 : /* insert the dir in the dir containers */ + 2285 762 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); + 2286 762 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); + 2287 : + 2288 : /* stat */ + 2289 762 : ++count_dir; + 2290 3698 : } else if (c == 'c') { + 2291 : /* get the subcommand */ + 2292 243 : c = sgetc(f); + 2293 : + 2294 243 : switch (c) { + 2295 : case 'u' : + 2296 155 : state->hash = HASH_MURMUR3; + 2297 155 : break; + 2298 : case 'k' : + 2299 88 : state->hash = HASH_SPOOKY2; + 2300 88 : break; + 2301 : default : + 2302 : /* LCOV_EXCL_START */ + 2303 : decoding_error(path, f); + 2304 : log_fatal("Invalid checksum!\n"); + 2305 : os_abort(); + 2306 : /* LCOV_EXCL_STOP */ + 2307 : } + 2308 : + 2309 : /* read the seed */ + 2310 243 : ret = sread(f, state->hashseed, HASH_SIZE); + 2311 243 : if (ret < 0) { 2312 : /* LCOV_EXCL_START */ 2313 : decoding_error(path, f); - 2314 : exit(EXIT_FAILURE); + 2314 : os_abort(); 2315 : /* LCOV_EXCL_STOP */ 2316 : } - 2317 : - 2318 : /* from SnapRAID 7.0 the 'M' command includes the free space */ - 2319 1305 : if (c == 'M') { - 2320 1305 : ret = sgetb32(f, &v_total_blocks); - 2321 1305 : if (ret < 0) { - 2322 : /* LCOV_EXCL_START */ - 2323 : decoding_error(path, f); - 2324 : exit(EXIT_FAILURE); - 2325 : /* LCOV_EXCL_STOP */ - 2326 : } - 2327 : - 2328 1305 : ret = sgetb32(f, &v_free_blocks); - 2329 1305 : if (ret < 0) { - 2330 : /* LCOV_EXCL_START */ - 2331 : decoding_error(path, f); - 2332 : exit(EXIT_FAILURE); - 2333 : /* LCOV_EXCL_STOP */ - 2334 : } - 2335 : } else { - 2336 0 : v_total_blocks = 0; - 2337 0 : v_free_blocks = 0; - 2338 : } - 2339 : - 2340 : /* read the uuid */ - 2341 1305 : ret = sgetbs(f, uuid, sizeof(uuid)); - 2342 1305 : if (ret < 0) { - 2343 : /* LCOV_EXCL_START */ - 2344 : decoding_error(path, f); - 2345 : exit(EXIT_FAILURE); - 2346 : /* LCOV_EXCL_STOP */ - 2347 : } - 2348 : - 2349 1305 : map = map_alloc(buffer, v_pos, v_total_blocks, v_free_blocks, uuid); - 2350 : - 2351 1305 : tommy_list_insert_tail(&state->maplist, &map->node, map); - 2352 : - 2353 : /* find the disk */ - 2354 1305 : disk = find_disk(state, buffer); - 2355 1305 : if (!disk) { - 2356 : /* LCOV_EXCL_START */ - 2357 : decoding_error(path, f); - 2358 : log_fatal("Disk named '%s' not present in the configuration file!\n", buffer); - 2359 : log_fatal("If you have removed it from the configuration file, please restore it\n"); - 2360 : exit(EXIT_FAILURE); - 2361 : /* LCOV_EXCL_STOP */ - 2362 : } - 2363 : - 2364 : /* insert in the mapping vector */ - 2365 1305 : tommy_array_grow(&disk_mapping, mapping_max + 1); - 2366 1305 : tommy_array_set(&disk_mapping, mapping_max, disk); - 2367 1305 : ++mapping_max; - 2368 1570 : } else if (c == 'P') { - 2369 : /* from SnapRAID 7.0 the 'P' command includes the free space */ - 2370 : char uuid[UUID_MAX]; - 2371 : uint32_t v_level; - 2372 : uint32_t v_total_blocks; - 2373 : uint32_t v_free_blocks; - 2374 : - 2375 1335 : ret = sgetb32(f, &v_level); - 2376 1335 : if (ret < 0) { - 2377 : /* LCOV_EXCL_START */ - 2378 : decoding_error(path, f); - 2379 : exit(EXIT_FAILURE); - 2380 : /* LCOV_EXCL_STOP */ - 2381 : } - 2382 : - 2383 1335 : ret = sgetb32(f, &v_total_blocks); - 2384 1335 : if (ret < 0) { - 2385 : /* LCOV_EXCL_START */ - 2386 : decoding_error(path, f); - 2387 : exit(EXIT_FAILURE); - 2388 : /* LCOV_EXCL_STOP */ - 2389 : } - 2390 : - 2391 1335 : ret = sgetb32(f, &v_free_blocks); - 2392 1335 : if (ret < 0) { - 2393 : /* LCOV_EXCL_START */ - 2394 : decoding_error(path, f); - 2395 : exit(EXIT_FAILURE); - 2396 : /* LCOV_EXCL_STOP */ - 2397 : } - 2398 : - 2399 1335 : ret = sgetbs(f, uuid, sizeof(uuid)); - 2400 1335 : if (ret < 0) { - 2401 : /* LCOV_EXCL_START */ - 2402 : decoding_error(path, f); - 2403 : exit(EXIT_FAILURE); - 2404 : /* LCOV_EXCL_STOP */ - 2405 : } - 2406 : - 2407 : /* auto configure if configuration is missing */ - 2408 1335 : if (state->no_conf && v_level < LEV_MAX && v_level >= state->level) - 2409 5 : state->level = v_level + 1; - 2410 : - 2411 : /* if we use this parity entry */ - 2412 1335 : if (v_level < state->level) { - 2413 : /* set the parity info */ - 2414 1081 : pathcpy(state->parity[v_level].uuid, sizeof(state->parity[v_level].uuid), uuid); - 2415 1081 : state->parity[v_level].total_blocks = v_total_blocks; - 2416 1081 : state->parity[v_level].free_blocks = v_free_blocks; - 2417 : } - 2418 235 : } else if (c == 'N') { - 2419 : uint32_t crc_stored; - 2420 : uint32_t crc_computed; + 2317 3455 : } else if (c == 'C') { + 2318 : /* get the sub-command */ + 2319 4 : c = sgetc(f); + 2320 : + 2321 4 : switch (c) { + 2322 : case 'u' : + 2323 4 : state->prevhash = HASH_MURMUR3; + 2324 4 : break; + 2325 : case 'k' : + 2326 0 : state->prevhash = HASH_SPOOKY2; + 2327 0 : break; + 2328 : default : + 2329 : /* LCOV_EXCL_START */ + 2330 : decoding_error(path, f); + 2331 : log_fatal("Invalid checksum!\n"); + 2332 : os_abort(); + 2333 : /* LCOV_EXCL_STOP */ + 2334 : } + 2335 : + 2336 : /* read the seed */ + 2337 4 : ret = sread(f, state->prevhashseed, HASH_SIZE); + 2338 4 : if (ret < 0) { + 2339 : /* LCOV_EXCL_START */ + 2340 : decoding_error(path, f); + 2341 : os_abort(); + 2342 : /* LCOV_EXCL_STOP */ + 2343 : } + 2344 3451 : } else if (c == 'z') { + 2345 : block_off_t blksize; + 2346 : + 2347 243 : ret = sgetb32(f, &blksize); + 2348 243 : if (ret < 0) { + 2349 : /* LCOV_EXCL_START */ + 2350 : decoding_error(path, f); + 2351 : os_abort(); + 2352 : /* LCOV_EXCL_STOP */ + 2353 : } + 2354 : + 2355 : /* without configuration, auto assign the block size */ + 2356 243 : if (state->no_conf) { + 2357 1 : state->block_size = blksize; + 2358 : } + 2359 : + 2360 243 : if (blksize != state->block_size) { + 2361 : /* LCOV_EXCL_START */ + 2362 : decoding_error(path, f); + 2363 : log_fatal("Mismatching 'blksize' and 'blocksize' specification!\n"); + 2364 : log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", blksize / 1024); + 2365 : exit(EXIT_FAILURE); + 2366 : /* LCOV_EXCL_STOP */ + 2367 : } + 2368 3208 : } else if (c == 'x') { + 2369 243 : ret = sgetb32(f, &blockmax); + 2370 243 : if (ret < 0) { + 2371 : /* LCOV_EXCL_START */ + 2372 : decoding_error(path, f); + 2373 : os_abort(); + 2374 : /* LCOV_EXCL_STOP */ + 2375 : } + 2376 4305 : } else if (c == 'm' || c == 'M') { + 2377 : struct snapraid_map* map; + 2378 : char uuid[UUID_MAX]; + 2379 : uint32_t v_pos; + 2380 : uint32_t v_total_blocks; + 2381 : uint32_t v_free_blocks; + 2382 : struct snapraid_disk* disk; + 2383 : + 2384 1340 : ret = sgetbs(f, buffer, sizeof(buffer)); + 2385 1340 : if (ret < 0) { + 2386 : /* LCOV_EXCL_START */ + 2387 : decoding_error(path, f); + 2388 : os_abort(); + 2389 : /* LCOV_EXCL_STOP */ + 2390 : } + 2391 : + 2392 1340 : ret = sgetb32(f, &v_pos); + 2393 1340 : if (ret < 0) { + 2394 : /* LCOV_EXCL_START */ + 2395 : decoding_error(path, f); + 2396 : os_abort(); + 2397 : /* LCOV_EXCL_STOP */ + 2398 : } + 2399 : + 2400 : /* from SnapRAID 7.0 the 'M' command includes the free space */ + 2401 1340 : if (c == 'M') { + 2402 1340 : ret = sgetb32(f, &v_total_blocks); + 2403 1340 : if (ret < 0) { + 2404 : /* LCOV_EXCL_START */ + 2405 : decoding_error(path, f); + 2406 : os_abort(); + 2407 : /* LCOV_EXCL_STOP */ + 2408 : } + 2409 : + 2410 1340 : ret = sgetb32(f, &v_free_blocks); + 2411 1340 : if (ret < 0) { + 2412 : /* LCOV_EXCL_START */ + 2413 : decoding_error(path, f); + 2414 : os_abort(); + 2415 : /* LCOV_EXCL_STOP */ + 2416 : } + 2417 : } else { + 2418 0 : v_total_blocks = 0; + 2419 0 : v_free_blocks = 0; + 2420 : } 2421 : - 2422 : /* get the crc before reading it from the file */ - 2423 234 : crc_computed = scrc(f); - 2424 : - 2425 234 : ret = sgetble32(f, &crc_stored); - 2426 234 : if (ret < 0) { - 2427 : /* LCOV_EXCL_START */ - 2428 : /* here don't call decoding_error() because it's too late to get the crc */ - 2429 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f)); - 2430 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 2431 : exit(EXIT_FAILURE); - 2432 : /* LCOV_EXCL_STOP */ - 2433 : } - 2434 : - 2435 234 : if (crc_stored != crc_computed) { - 2436 : /* LCOV_EXCL_START */ - 2437 : /* here don't call decoding_error() because it's too late to get the crc */ - 2438 : log_fatal("Mismatching CRC in '%s'\n", path); - 2439 : log_fatal("This content file is damaged! Use an alternate copy.\n"); - 2440 : exit(EXIT_FAILURE); - 2441 : /* LCOV_EXCL_STOP */ + 2422 : /* read the uuid */ + 2423 1340 : ret = sgetbs(f, uuid, sizeof(uuid)); + 2424 1340 : if (ret < 0) { + 2425 : /* LCOV_EXCL_START */ + 2426 : decoding_error(path, f); + 2427 : os_abort(); + 2428 : /* LCOV_EXCL_STOP */ + 2429 : } + 2430 : + 2431 : /* find the disk */ + 2432 1340 : disk = find_disk_by_name(state, buffer); + 2433 1340 : if (!disk) { + 2434 : /* search by UUID if renamed */ + 2435 2 : disk = find_disk_by_uuid(state, uuid); + 2436 2 : if (disk) { + 2437 2 : log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name); + 2438 : + 2439 : /* write the new state with the new name */ + 2440 2 : state->need_write = 1; + 2441 : } 2442 : } - 2443 : - 2444 234 : crc_checked = 1; - 2445 : } else { - 2446 : /* LCOV_EXCL_START */ - 2447 : decoding_error(path, f); - 2448 : log_fatal("Invalid command '%c'!\n", (char)c); - 2449 : exit(EXIT_FAILURE); - 2450 : /* LCOV_EXCL_STOP */ - 2451 : } - 2452 3604826 : } - 2453 : - 2454 234 : tommy_array_done(&disk_mapping); - 2455 : - 2456 234 : if (serror(f)) { - 2457 : /* LCOV_EXCL_START */ - 2458 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); - 2459 : exit(EXIT_FAILURE); - 2460 : /* LCOV_EXCL_STOP */ - 2461 : } - 2462 : - 2463 234 : if (!crc_checked) { - 2464 : /* LCOV_EXCL_START */ - 2465 : log_fatal("Finished reading '%s' without finding the CRC\n", path); - 2466 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n"); - 2467 : exit(EXIT_FAILURE); - 2468 : /* LCOV_EXCL_STOP */ - 2469 : } - 2470 : - 2471 : /* check the filesystem on all disks */ - 2472 234 : state_fscheck(state, "after read"); - 2473 : - 2474 : /* check that the stored parity size matches the loaded state */ - 2475 234 : if (blockmax != parity_allocated_size(state)) { - 2476 : /* LCOV_EXCL_START */ - 2477 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f)); - 2478 : if (state->opt.skip_content_check) { - 2479 : log_fatal("Overriding.\n"); - 2480 : blockmax = parity_allocated_size(state); - 2481 : } else { - 2482 : exit(EXIT_FAILURE); - 2483 : } - 2484 : /* LCOV_EXCL_STOP */ - 2485 : } - 2486 : - 2487 234 : msg_verbose("%8u files\n", count_file); - 2488 234 : msg_verbose("%8u hardlinks\n", count_hardlink); - 2489 234 : msg_verbose("%8u symlinks\n", count_symlink); - 2490 234 : msg_verbose("%8u empty dirs\n", count_dir); - 2491 234 : } - 2492 : - 2493 : struct state_write_thread_context { - 2494 : struct snapraid_state* state; - 2495 : struct snapraid_content* content; - 2496 : #if HAVE_PTHREAD_CREATE - 2497 : pthread_t thread; - 2498 : #else - 2499 : void* retval; - 2500 : #endif - 2501 : /* input */ - 2502 : block_off_t blockmax; - 2503 : time_t info_oldest; - 2504 : int info_has_rehash; - 2505 : /* output */ - 2506 : uint32_t crc; - 2507 : unsigned count_file; - 2508 : unsigned count_hardlink; - 2509 : unsigned count_symlink; - 2510 : unsigned count_dir; - 2511 : }; - 2512 : - 2513 913 : static void* state_write_thread(void* arg) - 2514 : { - 2515 913 : struct state_write_thread_context* context = arg; - 2516 913 : struct snapraid_content* content = context->content; - 2517 913 : struct snapraid_state* state = context->state; - 2518 913 : block_off_t blockmax = context->blockmax; - 2519 913 : time_t info_oldest = context->info_oldest; - 2520 913 : int info_has_rehash = context->info_has_rehash; - 2521 : uint32_t crc; - 2522 : unsigned count_file; - 2523 : unsigned count_hardlink; - 2524 : unsigned count_symlink; - 2525 : unsigned count_dir; - 2526 : char tmp[PATH_MAX]; - 2527 : STREAM* f; - 2528 : tommy_node* i; - 2529 : block_off_t idx; - 2530 : block_off_t begin; - 2531 : unsigned l; - 2532 : - 2533 913 : count_file = 0; - 2534 913 : count_hardlink = 0; - 2535 913 : count_symlink = 0; - 2536 913 : count_dir = 0; - 2537 : - 2538 913 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 2539 904 : f = sopen_write(tmp); - 2540 913 : if (f == 0) { - 2541 : /* LCOV_EXCL_START */ - 2542 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); - 2543 : goto bail; - 2544 : /* LCOV_EXCL_STOP */ - 2545 : } - 2546 : - 2547 : /* write header */ - 2548 913 : swrite("SNAPCNT2\n\3\0\0", 12, f); - 2549 : - 2550 : /* write block size and block max */ - 2551 913 : sputc('z', f); - 2552 913 : sputb32(state->block_size, f); - 2553 913 : sputc('x', f); - 2554 913 : sputb32(blockmax, f); - 2555 913 : if (serror(f)) { - 2556 : /* LCOV_EXCL_START */ - 2557 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2558 : goto bail; - 2559 : /* LCOV_EXCL_STOP */ - 2560 : } - 2561 : - 2562 913 : sputc('c', f); - 2563 913 : if (state->hash == HASH_MURMUR3) { - 2564 715 : sputc('u', f); - 2565 198 : } else if (state->hash == HASH_SPOOKY2) { - 2566 198 : sputc('k', f); - 2567 : } else { - 2568 : /* LCOV_EXCL_START */ - 2569 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); - 2570 : goto bail; - 2571 : /* LCOV_EXCL_STOP */ - 2572 : } - 2573 913 : swrite(state->hashseed, HASH_SIZE, f); - 2574 913 : if (serror(f)) { - 2575 : /* LCOV_EXCL_START */ - 2576 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2577 : goto bail; - 2578 : /* LCOV_EXCL_STOP */ - 2579 : } - 2580 : - 2581 : /* previous hash only present */ - 2582 913 : if (state->prevhash != HASH_UNDEFINED) { - 2583 : /* if at least one rehash tag found, we have to save the previous hash */ - 2584 198 : if (info_has_rehash) { - 2585 198 : sputc('C', f); - 2586 198 : if (state->prevhash == HASH_MURMUR3) { - 2587 198 : sputc('u', f); - 2588 0 : } else if (state->prevhash == HASH_SPOOKY2) { - 2589 0 : sputc('k', f); - 2590 : } else { - 2591 : /* LCOV_EXCL_START */ - 2592 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); - 2593 : goto bail; - 2594 : /* LCOV_EXCL_STOP */ - 2595 : } - 2596 198 : swrite(state->prevhashseed, HASH_SIZE, f); - 2597 198 : if (serror(f)) { - 2598 : /* LCOV_EXCL_START */ - 2599 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2600 : goto bail; - 2601 : /* LCOV_EXCL_STOP */ - 2602 : } - 2603 : } - 2604 : } + 2443 1340 : if (!disk) { + 2444 : /* LCOV_EXCL_START */ + 2445 : decoding_error(path, f); + 2446 : log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid); + 2447 : log_fatal("If you have removed it from the configuration file, please restore it\n"); + 2448 : /* if it's a command without UUID, it cannot autorename using UUID */ + 2449 : if (state->opt.skip_disk_access) + 2450 : log_fatal("If you have renamed it, run 'sync' to update the new name\n"); + 2451 : exit(EXIT_FAILURE); + 2452 : /* LCOV_EXCL_STOP */ + 2453 : } + 2454 : + 2455 1340 : map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid); + 2456 : + 2457 1340 : tommy_list_insert_tail(&state->maplist, &map->node, map); + 2458 : + 2459 : /* insert in the mapping vector */ + 2460 1340 : tommy_array_grow(&disk_mapping, mapping_max + 1); + 2461 1340 : tommy_array_set(&disk_mapping, mapping_max, disk); + 2462 1340 : ++mapping_max; + 2463 1625 : } else if (c == 'P') { + 2464 : /* from SnapRAID 7.0 the 'P' command includes the free space */ + 2465 : char uuid[UUID_MAX]; + 2466 : uint32_t v_level; + 2467 : uint32_t v_total_blocks; + 2468 : uint32_t v_free_blocks; + 2469 : + 2470 1383 : ret = sgetb32(f, &v_level); + 2471 1383 : if (ret < 0) { + 2472 : /* LCOV_EXCL_START */ + 2473 : decoding_error(path, f); + 2474 : os_abort(); + 2475 : /* LCOV_EXCL_STOP */ + 2476 : } + 2477 : + 2478 1383 : ret = sgetb32(f, &v_total_blocks); + 2479 1383 : if (ret < 0) { + 2480 : /* LCOV_EXCL_START */ + 2481 : decoding_error(path, f); + 2482 : os_abort(); + 2483 : /* LCOV_EXCL_STOP */ + 2484 : } + 2485 : + 2486 1383 : ret = sgetb32(f, &v_free_blocks); + 2487 1383 : if (ret < 0) { + 2488 : /* LCOV_EXCL_START */ + 2489 : decoding_error(path, f); + 2490 : os_abort(); + 2491 : /* LCOV_EXCL_STOP */ + 2492 : } + 2493 : + 2494 1383 : ret = sgetbs(f, uuid, sizeof(uuid)); + 2495 1383 : if (ret < 0) { + 2496 : /* LCOV_EXCL_START */ + 2497 : decoding_error(path, f); + 2498 : os_abort(); + 2499 : /* LCOV_EXCL_STOP */ + 2500 : } + 2501 : + 2502 : /* auto configure if configuration is missing */ + 2503 1383 : if (state->no_conf && v_level < LEV_MAX && v_level >= state->level) + 2504 5 : state->level = v_level + 1; + 2505 : + 2506 : /* if we use this parity entry */ + 2507 1383 : if (v_level < state->level) { + 2508 : /* set the parity info */ + 2509 1129 : pathcpy(state->parity[v_level].uuid, sizeof(state->parity[v_level].uuid), uuid); + 2510 1129 : state->parity[v_level].total_blocks = v_total_blocks; + 2511 1129 : state->parity[v_level].free_blocks = v_free_blocks; + 2512 : } + 2513 242 : } else if (c == 'N') { + 2514 : uint32_t crc_stored; + 2515 : uint32_t crc_computed; + 2516 : + 2517 : /* get the crc before reading it from the file */ + 2518 242 : crc_computed = scrc(f); + 2519 : + 2520 242 : ret = sgetble32(f, &crc_stored); + 2521 242 : if (ret < 0) { + 2522 : /* LCOV_EXCL_START */ + 2523 : /* here don't call decoding_error() because it's too late to get the crc */ + 2524 : log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f)); + 2525 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 2526 : exit(EXIT_FAILURE); + 2527 : /* LCOV_EXCL_STOP */ + 2528 : } + 2529 : + 2530 242 : if (crc_stored != crc_computed) { + 2531 : /* LCOV_EXCL_START */ + 2532 : /* here don't call decoding_error() because it's too late to get the crc */ + 2533 : log_fatal("Mismatching CRC in '%s'\n", path); + 2534 : log_fatal("This content file is damaged! Use an alternate copy.\n"); + 2535 : exit(EXIT_FAILURE); + 2536 : /* LCOV_EXCL_STOP */ + 2537 : } + 2538 : + 2539 242 : crc_checked = 1; + 2540 : } else { + 2541 : /* LCOV_EXCL_START */ + 2542 : decoding_error(path, f); + 2543 : log_fatal("Invalid command '%c'!\n", (char)c); + 2544 : os_abort(); + 2545 : /* LCOV_EXCL_STOP */ + 2546 : } + 2547 3652776 : } + 2548 : + 2549 242 : tommy_array_done(&disk_mapping); + 2550 : + 2551 242 : if (serror(f)) { + 2552 : /* LCOV_EXCL_START */ + 2553 : log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + 2554 : exit(EXIT_FAILURE); + 2555 : /* LCOV_EXCL_STOP */ + 2556 : } + 2557 : + 2558 242 : if (!crc_checked) { + 2559 : /* LCOV_EXCL_START */ + 2560 : log_fatal("Finished reading '%s' without finding the CRC\n", path); + 2561 : log_fatal("This content file is truncated or damaged! Use an alternate copy.\n"); + 2562 : exit(EXIT_FAILURE); + 2563 : /* LCOV_EXCL_STOP */ + 2564 : } + 2565 : + 2566 : /* check the file-system on all disks */ + 2567 242 : state_fscheck(state, "after read"); + 2568 : + 2569 : /* check that the stored parity size matches the loaded state */ + 2570 242 : if (blockmax != parity_allocated_size(state)) { + 2571 : /* LCOV_EXCL_START */ + 2572 : log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f)); + 2573 : if (state->opt.skip_content_check) { + 2574 : log_fatal("Overriding.\n"); + 2575 : blockmax = parity_allocated_size(state); + 2576 : } else { + 2577 : exit(EXIT_FAILURE); + 2578 : } + 2579 : /* LCOV_EXCL_STOP */ + 2580 : } + 2581 : + 2582 242 : msg_verbose("%8u files\n", count_file); + 2583 242 : msg_verbose("%8u hardlinks\n", count_hardlink); + 2584 242 : msg_verbose("%8u symlinks\n", count_symlink); + 2585 242 : msg_verbose("%8u empty dirs\n", count_dir); + 2586 242 : } + 2587 : + 2588 : struct state_write_thread_context { + 2589 : struct snapraid_state* state; + 2590 : #if HAVE_MT_WRITE + 2591 : pthread_t thread; + 2592 : #endif + 2593 : /* input */ + 2594 : block_off_t blockmax; + 2595 : time_t info_oldest; + 2596 : int info_has_rehash; + 2597 : STREAM* f; + 2598 : /* output */ + 2599 : uint32_t crc; + 2600 : unsigned count_file; + 2601 : unsigned count_hardlink; + 2602 : unsigned count_symlink; + 2603 : unsigned count_dir; + 2604 : }; 2605 : - 2606 : /* for each map */ - 2607 6391 : for (i = state->maplist; i != 0; i = i->next) { - 2608 5478 : struct snapraid_map* map = i->data; - 2609 : struct snapraid_disk* disk; - 2610 : - 2611 : /* find the disk for this mapping */ - 2612 5478 : disk = find_disk(state, map->name); - 2613 5478 : if (!disk) { - 2614 : /* LCOV_EXCL_START */ - 2615 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - 2616 : goto bail; - 2617 : /* LCOV_EXCL_STOP */ - 2618 : } - 2619 : - 2620 : /* save the mapping only if disk is mapped */ - 2621 5478 : if (disk->mapping_idx != -1) { - 2622 5037 : sputc('M', f); - 2623 5037 : sputbs(map->name, f); - 2624 5037 : sputb32(map->position, f); - 2625 5037 : sputb32(map->total_blocks, f); - 2626 5037 : sputb32(map->free_blocks, f); - 2627 5037 : sputbs(map->uuid, f); - 2628 5037 : if (serror(f)) { - 2629 : /* LCOV_EXCL_START */ - 2630 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2631 : goto bail; - 2632 : /* LCOV_EXCL_STOP */ - 2633 : } - 2634 : } - 2635 : } - 2636 : - 2637 : /* for each parity */ - 2638 6341 : for (l = 0; l < state->level; ++l) { - 2639 5428 : sputc('P', f); - 2640 5428 : sputb32(l, f); - 2641 5428 : sputb32(state->parity[l].total_blocks, f); - 2642 5428 : sputb32(state->parity[l].free_blocks, f); - 2643 5427 : sputbs(state->parity[l].uuid, f); - 2644 5428 : if (serror(f)) { - 2645 : /* LCOV_EXCL_START */ - 2646 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2647 : goto bail; - 2648 : /* LCOV_EXCL_STOP */ - 2649 : } - 2650 : } - 2651 : - 2652 : /* for each disk */ - 2653 6391 : for (i = state->disklist; i != 0; i = i->next) { - 2654 : tommy_node* j; - 2655 5478 : struct snapraid_disk* disk = i->data; - 2656 : struct snapraid_chunk* fs_last; - 2657 : - 2658 : /** - 2659 : * This is the last accessed chunk in the tree operations. - 2660 : * Here we are inside a thread, and we cannot use the - 2661 : * ::disk member to store this information. - 2662 : */ - 2663 5478 : fs_last = 0; - 2664 : - 2665 : /* if the disk is not mapped, skip it */ - 2666 5478 : if (disk->mapping_idx < 0) - 2667 441 : continue; - 2668 : - 2669 : /* for each file */ - 2670 11578188 : for (j = disk->filelist; j != 0; j = j->next) { - 2671 11573152 : struct snapraid_file* file = j->data; - 2672 : uint64_t size; - 2673 : uint64_t mtime_sec; - 2674 : int32_t mtime_nsec; - 2675 : uint64_t inode; - 2676 : - 2677 11573152 : size = file->size; - 2678 11573152 : mtime_sec = file->mtime_sec; - 2679 11573152 : mtime_nsec = file->mtime_nsec; - 2680 11573152 : inode = file->inode; - 2681 : - 2682 11573152 : sputc('f', f); - 2683 11523322 : sputb32(disk->mapping_idx, f); - 2684 11531504 : sputb64(size, f); - 2685 11543059 : sputb64(mtime_sec, f); - 2686 : /* encode STAT_NSEC_INVALID as 0 */ - 2687 11521684 : if (mtime_nsec == STAT_NSEC_INVALID) - 2688 0 : sputb32(0, f); - 2689 : else - 2690 11521684 : sputb32(mtime_nsec + 1, f); - 2691 11530611 : sputb64(inode, f); - 2692 11526825 : sputbs(file->sub, f); - 2693 11546662 : if (serror(f)) { - 2694 : /* LCOV_EXCL_START */ - 2695 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2696 : goto bail; - 2697 : /* LCOV_EXCL_STOP */ - 2698 : } - 2699 : - 2700 : /* for all the blocks of the file */ - 2701 11560751 : begin = 0; - 2702 34754559 : while (begin < file->blockmax) { - 2703 11620657 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); - 2704 11635419 : block_off_t v_pos = fs_file2par_get_ts(disk, &fs_last, file, begin); - 2705 : uint32_t v_count; - 2706 : - 2707 : block_off_t end; - 2708 : - 2709 : /* find the end of run of blocks */ - 2710 11602915 : end = begin + 1; - 2711 40021161 : while (end < file->blockmax) { - 2712 16868038 : if (v_state != block_state_get(fs_file2block_get(file, end))) - 2713 63 : break; - 2714 16887534 : if (v_pos + (end - begin) != fs_file2par_get_ts(disk, &fs_last, file, end)) - 2715 83317 : break; - 2716 16815331 : ++end; - 2717 : } + 2606 145 : static void* state_write_thread(void* arg) + 2607 : { + 2608 145 : struct state_write_thread_context* context = arg; + 2609 145 : struct snapraid_state* state = context->state; + 2610 145 : block_off_t blockmax = context->blockmax; + 2611 145 : time_t info_oldest = context->info_oldest; + 2612 145 : int info_has_rehash = context->info_has_rehash; + 2613 145 : STREAM* f = context->f; + 2614 : uint32_t crc; + 2615 : unsigned count_file; + 2616 : unsigned count_hardlink; + 2617 : unsigned count_symlink; + 2618 : unsigned count_dir; + 2619 : tommy_node* i; + 2620 : block_off_t idx; + 2621 : block_off_t begin; + 2622 : unsigned l; + 2623 : + 2624 145 : count_file = 0; + 2625 145 : count_hardlink = 0; + 2626 145 : count_symlink = 0; + 2627 145 : count_dir = 0; + 2628 : + 2629 : /* write header */ + 2630 145 : swrite("SNAPCNT2\n\3\0\0", 12, f); + 2631 : + 2632 : /* write block size and block max */ + 2633 145 : sputc('z', f); + 2634 145 : sputb32(state->block_size, f); + 2635 145 : sputc('x', f); + 2636 145 : sputb32(blockmax, f); + 2637 145 : if (serror(f)) { + 2638 : /* LCOV_EXCL_START */ + 2639 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2640 : return context; + 2641 : /* LCOV_EXCL_STOP */ + 2642 : } + 2643 : + 2644 145 : sputc('c', f); + 2645 145 : if (state->hash == HASH_MURMUR3) { + 2646 115 : sputc('u', f); + 2647 30 : } else if (state->hash == HASH_SPOOKY2) { + 2648 30 : sputc('k', f); + 2649 : } else { + 2650 : /* LCOV_EXCL_START */ + 2651 : log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); + 2652 : return context; + 2653 : /* LCOV_EXCL_STOP */ + 2654 : } + 2655 145 : swrite(state->hashseed, HASH_SIZE, f); + 2656 145 : if (serror(f)) { + 2657 : /* LCOV_EXCL_START */ + 2658 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2659 : return context; + 2660 : /* LCOV_EXCL_STOP */ + 2661 : } + 2662 : + 2663 : /* previous hash only present */ + 2664 145 : if (state->prevhash != HASH_UNDEFINED) { + 2665 : /* if at least one rehash tag found, we have to save the previous hash */ + 2666 4 : if (info_has_rehash) { + 2667 3 : sputc('C', f); + 2668 3 : if (state->prevhash == HASH_MURMUR3) { + 2669 3 : sputc('u', f); + 2670 0 : } else if (state->prevhash == HASH_SPOOKY2) { + 2671 0 : sputc('k', f); + 2672 : } else { + 2673 : /* LCOV_EXCL_START */ + 2674 : log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); + 2675 : return context; + 2676 : /* LCOV_EXCL_STOP */ + 2677 : } + 2678 3 : swrite(state->prevhashseed, HASH_SIZE, f); + 2679 3 : if (serror(f)) { + 2680 : /* LCOV_EXCL_START */ + 2681 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2682 : return context; + 2683 : /* LCOV_EXCL_STOP */ + 2684 : } + 2685 : } + 2686 : } + 2687 : + 2688 : /* for each map */ + 2689 1015 : for (i = state->maplist; i != 0; i = i->next) { + 2690 870 : struct snapraid_map* map = i->data; + 2691 : struct snapraid_disk* disk; + 2692 : + 2693 : /* find the disk for this mapping */ + 2694 870 : disk = find_disk_by_name(state, map->name); + 2695 870 : if (!disk) { + 2696 : /* LCOV_EXCL_START */ + 2697 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + 2698 : return context; + 2699 : /* LCOV_EXCL_STOP */ + 2700 : } + 2701 : + 2702 : /* save the mapping only if disk is mapped */ + 2703 870 : if (disk->mapping_idx != -1) { + 2704 786 : sputc('M', f); + 2705 786 : sputbs(map->name, f); + 2706 786 : sputb32(map->position, f); + 2707 786 : sputb32(map->total_blocks, f); + 2708 786 : sputb32(map->free_blocks, f); + 2709 786 : sputbs(map->uuid, f); + 2710 786 : if (serror(f)) { + 2711 : /* LCOV_EXCL_START */ + 2712 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2713 : return context; + 2714 : /* LCOV_EXCL_STOP */ + 2715 : } + 2716 : } + 2717 : } 2718 : - 2719 11633588 : switch (v_state) { - 2720 : case BLOCK_STATE_BLK : - 2721 10922665 : sputc('b', f); - 2722 10930254 : break; - 2723 : case BLOCK_STATE_CHG : - 2724 559524 : sputc('g', f); - 2725 559519 : break; - 2726 : case BLOCK_STATE_REP : - 2727 151399 : sputc('p', f); - 2728 151402 : break; - 2729 : default : - 2730 : /* LCOV_EXCL_START */ - 2731 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state); - 2732 : goto bail; - 2733 : /* LCOV_EXCL_STOP */ - 2734 : } - 2735 : - 2736 11641175 : sputb32(v_pos, f); - 2737 : - 2738 11622679 : v_count = end - begin; - 2739 11622679 : sputb32(v_count, f); - 2740 : - 2741 : /* write hashes */ - 2742 39768736 : for (idx = begin; idx < end; ++idx) { - 2743 28155837 : struct snapraid_block* block = fs_file2block_get(file, idx); - 2744 : - 2745 28133584 : swrite(block->hash, HASH_SIZE, f); - 2746 : } - 2747 : - 2748 11612899 : if (serror(f)) { - 2749 : /* LCOV_EXCL_START */ - 2750 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2751 : goto bail; - 2752 : /* LCOV_EXCL_STOP */ - 2753 : } - 2754 : - 2755 : /* next begin position */ - 2756 11633057 : begin = end; - 2757 : } + 2719 : /* for each parity */ + 2720 990 : for (l = 0; l < state->level; ++l) { + 2721 845 : sputc('P', f); + 2722 845 : sputb32(l, f); + 2723 845 : sputb32(state->parity[l].total_blocks, f); + 2724 845 : sputb32(state->parity[l].free_blocks, f); + 2725 845 : sputbs(state->parity[l].uuid, f); + 2726 845 : if (serror(f)) { + 2727 : /* LCOV_EXCL_START */ + 2728 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2729 : return context; + 2730 : /* LCOV_EXCL_STOP */ + 2731 : } + 2732 : } + 2733 : + 2734 : /* for each disk */ + 2735 1015 : for (i = state->disklist; i != 0; i = i->next) { + 2736 : tommy_node* j; + 2737 870 : struct snapraid_disk* disk = i->data; + 2738 : struct snapraid_chunk* fs_last; + 2739 : + 2740 : /** + 2741 : * This is the last accessed chunk in the tree operations. + 2742 : * Here we are inside a thread, and we cannot use the + 2743 : * ::disk member to store this information. + 2744 : */ + 2745 870 : fs_last = 0; + 2746 : + 2747 : /* if the disk is not mapped, skip it */ + 2748 870 : if (disk->mapping_idx < 0) + 2749 84 : continue; + 2750 : + 2751 : /* for each file */ + 2752 1765094 : for (j = disk->filelist; j != 0; j = j->next) { + 2753 1764308 : struct snapraid_file* file = j->data; + 2754 : uint64_t size; + 2755 : uint64_t mtime_sec; + 2756 : int32_t mtime_nsec; + 2757 : uint64_t inode; 2758 : - 2759 11573151 : ++count_file; - 2760 : } - 2761 : - 2762 : /* for each link */ - 2763 385485 : for (j = disk->linklist; j != 0; j = j->next) { - 2764 380448 : struct snapraid_link* slink = j->data; - 2765 : - 2766 380448 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { - 2767 : case FILE_IS_HARDLINK : - 2768 2046 : sputc('a', f); - 2769 2046 : ++count_hardlink; - 2770 2046 : break; - 2771 : case FILE_IS_SYMLINK : - 2772 378402 : sputc('s', f); - 2773 378020 : ++count_symlink; - 2774 378020 : break; - 2775 : } - 2776 : - 2777 380066 : sputb32(disk->mapping_idx, f); - 2778 380422 : sputbs(slink->sub, f); - 2779 380445 : sputbs(slink->linkto, f); - 2780 380449 : if (serror(f)) { - 2781 : /* LCOV_EXCL_START */ - 2782 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2783 : goto bail; - 2784 : /* LCOV_EXCL_STOP */ - 2785 : } - 2786 : } - 2787 : - 2788 : /* for each dir */ - 2789 7758 : for (j = disk->dirlist; j != 0; j = j->next) { - 2790 2721 : struct snapraid_dir* dir = j->data; - 2791 : - 2792 2721 : sputc('r', f); - 2793 2721 : sputb32(disk->mapping_idx, f); - 2794 2721 : sputbs(dir->sub, f); - 2795 2721 : if (serror(f)) { - 2796 : /* LCOV_EXCL_START */ - 2797 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2798 : goto bail; - 2799 : /* LCOV_EXCL_STOP */ - 2800 : } - 2801 : - 2802 2721 : ++count_dir; - 2803 : } - 2804 : - 2805 : /* deleted blocks of the disk */ - 2806 5037 : sputc('h', f); - 2807 5037 : sputb32(disk->mapping_idx, f); - 2808 5037 : if (serror(f)) { - 2809 : /* LCOV_EXCL_START */ - 2810 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2811 : goto bail; - 2812 : /* LCOV_EXCL_STOP */ - 2813 : } - 2814 5037 : begin = 0; - 2815 15643 : while (begin < blockmax) { - 2816 : int is_deleted; - 2817 : block_off_t end; - 2818 : - 2819 5569 : is_deleted = fs_is_block_deleted_ts(disk, &fs_last, begin); - 2820 : - 2821 : /* find the end of run of blocks */ - 2822 5569 : end = begin + 1; - 2823 29396439 : while (end < blockmax - 2824 29341613 : && is_deleted == fs_is_block_deleted_ts(disk, &fs_last, end) - 2825 : ) { - 2826 29385301 : ++end; - 2827 : } - 2828 : - 2829 0 : sputb32(end - begin, f); - 2830 : - 2831 5569 : if (is_deleted) { - 2832 : /* write the run of deleted blocks with hash */ - 2833 329 : sputc('o', f); - 2834 : - 2835 : /* write all the hash */ - 2836 112525 : while (begin < end) { - 2837 111867 : struct snapraid_block* block = fs_par2block_get_ts(disk, &fs_last, begin); - 2838 : - 2839 111867 : swrite(block->hash, HASH_SIZE, f); + 2759 1764308 : size = file->size; + 2760 1764308 : mtime_sec = file->mtime_sec; + 2761 1764308 : mtime_nsec = file->mtime_nsec; + 2762 1764308 : inode = file->inode; + 2763 : + 2764 1764308 : sputc('f', f); + 2765 1764308 : sputb32(disk->mapping_idx, f); + 2766 1764308 : sputb64(size, f); + 2767 1764308 : sputb64(mtime_sec, f); + 2768 : /* encode STAT_NSEC_INVALID as 0 */ + 2769 1764308 : if (mtime_nsec == STAT_NSEC_INVALID) + 2770 0 : sputb32(0, f); + 2771 : else + 2772 1764308 : sputb32(mtime_nsec + 1, f); + 2773 1764308 : sputb64(inode, f); + 2774 1764308 : sputbs(file->sub, f); + 2775 1764308 : if (serror(f)) { + 2776 : /* LCOV_EXCL_START */ + 2777 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2778 : return context; + 2779 : /* LCOV_EXCL_STOP */ + 2780 : } + 2781 : + 2782 : /* for all the blocks of the file */ + 2783 1764308 : begin = 0; + 2784 5303306 : while (begin < file->blockmax) { + 2785 1774690 : unsigned v_state = block_state_get(fs_file2block_get(file, begin)); + 2786 1774690 : block_off_t v_pos = fs_file2par_get_ts(disk, &fs_last, file, begin); + 2787 : uint32_t v_count; + 2788 : + 2789 : block_off_t end; + 2790 : + 2791 : /* find the end of run of blocks */ + 2792 1774690 : end = begin + 1; + 2793 6121077 : while (end < file->blockmax) { + 2794 2584536 : if (v_state != block_state_get(fs_file2block_get(file, end))) + 2795 11 : break; + 2796 2584525 : if (v_pos + (end - begin) != fs_file2par_get_ts(disk, &fs_last, file, end)) + 2797 12828 : break; + 2798 2571697 : ++end; + 2799 : } + 2800 : + 2801 1774690 : switch (v_state) { + 2802 : case BLOCK_STATE_BLK : + 2803 1650586 : sputc('b', f); + 2804 1650586 : break; + 2805 : case BLOCK_STATE_CHG : + 2806 67711 : sputc('g', f); + 2807 67711 : break; + 2808 : case BLOCK_STATE_REP : + 2809 56393 : sputc('p', f); + 2810 56393 : break; + 2811 : default : + 2812 : /* LCOV_EXCL_START */ + 2813 : log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state); + 2814 : return context; + 2815 : /* LCOV_EXCL_STOP */ + 2816 : } + 2817 : + 2818 1774690 : sputb32(v_pos, f); + 2819 : + 2820 1774690 : v_count = end - begin; + 2821 1774690 : sputb32(v_count, f); + 2822 : + 2823 : /* write hashes */ + 2824 6121077 : for (idx = begin; idx < end; ++idx) { + 2825 4346387 : struct snapraid_block* block = fs_file2block_get(file, idx); + 2826 : + 2827 4346387 : swrite(block->hash, HASH_SIZE, f); + 2828 : } + 2829 : + 2830 1774690 : if (serror(f)) { + 2831 : /* LCOV_EXCL_START */ + 2832 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2833 : return context; + 2834 : /* LCOV_EXCL_STOP */ + 2835 : } + 2836 : + 2837 : /* next begin position */ + 2838 1774690 : begin = end; + 2839 : } 2840 : - 2841 111867 : ++begin; - 2842 : } - 2843 : } else { - 2844 : /* write the run of blocks without hash */ - 2845 : /* they can be either used or empty blocks */ - 2846 5240 : sputc('O', f); + 2841 1764308 : ++count_file; + 2842 : } + 2843 : + 2844 : /* for each link */ + 2845 58592 : for (j = disk->linklist; j != 0; j = j->next) { + 2846 57806 : struct snapraid_link* slink = j->data; 2847 : - 2848 : /* next begin position */ - 2849 5240 : begin = end; - 2850 : } - 2851 : - 2852 5569 : if (serror(f)) { - 2853 : /* LCOV_EXCL_START */ - 2854 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2855 : goto bail; - 2856 : /* LCOV_EXCL_STOP */ + 2848 57806 : switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { + 2849 : case FILE_IS_HARDLINK : + 2850 315 : sputc('a', f); + 2851 315 : ++count_hardlink; + 2852 315 : break; + 2853 : case FILE_IS_SYMLINK : + 2854 57491 : sputc('s', f); + 2855 57491 : ++count_symlink; + 2856 57491 : break; 2857 : } - 2858 : } - 2859 : } - 2860 : - 2861 : /* write the info for each block */ - 2862 913 : sputc('i', f); - 2863 913 : sputb32(info_oldest, f); - 2864 929 : begin = 0; - 2865 1427365 : while (begin < blockmax) { - 2866 : snapraid_info info; - 2867 : block_off_t end; - 2868 : time_t t; - 2869 : unsigned flag; - 2870 : - 2871 1425523 : info = info_get(&state->infoarr, begin); - 2872 : - 2873 : /* find the end of run of blocks */ - 2874 1426289 : end = begin + 1; - 2875 6350808 : while (end < blockmax - 2876 4922834 : && info == info_get(&state->infoarr, end) - 2877 : ) { - 2878 3498230 : ++end; - 2879 : } - 2880 : - 2881 1427382 : sputb32(end - begin, f); - 2882 : - 2883 : /* if there is info */ - 2884 1426642 : if (info) { - 2885 : /* other flags */ - 2886 1426512 : flag = 1; /* info is present */ - 2887 1426512 : if (info_get_bad(info)) - 2888 9590 : flag |= 2; - 2889 1425847 : if (info_get_rehash(info)) - 2890 673003 : flag |= 4; - 2891 1425736 : if (info_get_justsynced(info)) - 2892 724485 : flag |= 8; - 2893 1425766 : sputb32(flag, f); - 2894 : - 2895 1425741 : t = info_get_time(info) - info_oldest; - 2896 1425676 : sputb32(t, f); - 2897 : } else { - 2898 : /* write a special 0 flag to mark missing info */ - 2899 130 : sputb32(0, f); - 2900 : } - 2901 : - 2902 1425342 : if (serror(f)) { - 2903 : /* LCOV_EXCL_START */ - 2904 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2905 : goto bail; - 2906 : /* LCOV_EXCL_STOP */ - 2907 : } - 2908 : - 2909 : /* next begin position */ - 2910 1425507 : begin = end; - 2911 : } + 2858 : + 2859 57806 : sputb32(disk->mapping_idx, f); + 2860 57806 : sputbs(slink->sub, f); + 2861 57806 : sputbs(slink->linkto, f); + 2862 57806 : if (serror(f)) { + 2863 : /* LCOV_EXCL_START */ + 2864 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2865 : return context; + 2866 : /* LCOV_EXCL_STOP */ + 2867 : } + 2868 : } + 2869 : + 2870 : /* for each dir */ + 2871 1205 : for (j = disk->dirlist; j != 0; j = j->next) { + 2872 419 : struct snapraid_dir* dir = j->data; + 2873 : + 2874 419 : sputc('r', f); + 2875 419 : sputb32(disk->mapping_idx, f); + 2876 419 : sputbs(dir->sub, f); + 2877 419 : if (serror(f)) { + 2878 : /* LCOV_EXCL_START */ + 2879 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2880 : return context; + 2881 : /* LCOV_EXCL_STOP */ + 2882 : } + 2883 : + 2884 419 : ++count_dir; + 2885 : } + 2886 : + 2887 : /* deleted blocks of the disk */ + 2888 786 : sputc('h', f); + 2889 786 : sputb32(disk->mapping_idx, f); + 2890 786 : if (serror(f)) { + 2891 : /* LCOV_EXCL_START */ + 2892 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2893 : return context; + 2894 : /* LCOV_EXCL_STOP */ + 2895 : } + 2896 786 : begin = 0; + 2897 2435 : while (begin < blockmax) { + 2898 : int is_deleted; + 2899 : block_off_t end; + 2900 : + 2901 863 : is_deleted = fs_is_block_deleted_ts(disk, &fs_last, begin); + 2902 : + 2903 : /* find the end of run of blocks */ + 2904 863 : end = begin + 1; + 2905 4508642 : while (end < blockmax + 2906 4506993 : && is_deleted == fs_is_block_deleted_ts(disk, &fs_last, end) + 2907 : ) { + 2908 4506916 : ++end; + 2909 : } + 2910 : + 2911 863 : sputb32(end - begin, f); 2912 : - 2913 913 : sputc('N', f); - 2914 : - 2915 : /* flush data written to the disk */ - 2916 913 : if (sflush(f)) { - 2917 : /* LCOV_EXCL_START */ - 2918 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); - 2919 : goto bail; - 2920 : /* LCOV_EXCL_STOP */ - 2921 : } + 2913 863 : if (is_deleted) { + 2914 : /* write the run of deleted blocks with hash */ + 2915 49 : sputc('o', f); + 2916 : + 2917 : /* write all the hash */ + 2918 15941 : while (begin < end) { + 2919 15843 : struct snapraid_block* block = fs_par2block_get_ts(disk, &fs_last, begin); + 2920 : + 2921 15843 : swrite(block->hash, HASH_SIZE, f); 2922 : - 2923 : /* get the file crc */ - 2924 913 : crc = scrc(f); - 2925 : - 2926 : /* compare the crc of the data written to file */ - 2927 : /* with the one of the data written to the stream */ - 2928 913 : if (crc != scrc_stream(f)) { - 2929 : /* LCOV_EXCL_START */ - 2930 : log_fatal("CRC mismatch writing the content stream.\n"); - 2931 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); - 2932 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); - 2933 : goto bail; - 2934 : /* LCOV_EXCL_STOP */ - 2935 : } - 2936 : - 2937 913 : sputble32(crc, f); - 2938 913 : if (serror(f)) { - 2939 : /* LCOV_EXCL_START */ - 2940 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - 2941 : goto bail; - 2942 : /* LCOV_EXCL_STOP */ - 2943 : } - 2944 : - 2945 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ - 2946 : /* than even in a system crash event we have one valid copy of the file. */ - 2947 913 : if (sflush(f) != 0) { - 2948 : /* LCOV_EXCL_START */ - 2949 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); - 2950 : goto bail; - 2951 : /* LCOV_EXCL_STOP */ - 2952 : } - 2953 : - 2954 : #if HAVE_FSYNC - 2955 913 : if (ssync(f) != 0) { - 2956 : /* LCOV_EXCL_START */ - 2957 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); - 2958 : goto bail; - 2959 : /* LCOV_EXCL_STOP */ - 2960 : } - 2961 : #endif + 2923 15843 : ++begin; + 2924 : } + 2925 : } else { + 2926 : /* write the run of blocks without hash */ + 2927 : /* they can be either used or empty blocks */ + 2928 814 : sputc('O', f); + 2929 : + 2930 : /* next begin position */ + 2931 814 : begin = end; + 2932 : } + 2933 : + 2934 863 : if (serror(f)) { + 2935 : /* LCOV_EXCL_START */ + 2936 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2937 : return context; + 2938 : /* LCOV_EXCL_STOP */ + 2939 : } + 2940 : } + 2941 : } + 2942 : + 2943 : /* write the info for each block */ + 2944 145 : sputc('i', f); + 2945 145 : sputb32(info_oldest, f); + 2946 145 : begin = 0; + 2947 30551 : while (begin < blockmax) { + 2948 : snapraid_info info; + 2949 : block_off_t end; + 2950 : time_t t; + 2951 : unsigned flag; + 2952 : + 2953 30261 : info = info_get(&state->infoarr, begin); + 2954 : + 2955 : /* find the end of run of blocks */ + 2956 30261 : end = begin + 1; + 2957 782752 : while (end < blockmax + 2958 752349 : && info == info_get(&state->infoarr, end) + 2959 : ) { + 2960 722230 : ++end; + 2961 : } 2962 : - 2963 913 : if (sclose(f) != 0) { - 2964 : /* LCOV_EXCL_START */ - 2965 : f = 0; - 2966 : log_fatal("Error closing the content files. %s.\n", strerror(errno)); - 2967 : goto bail; - 2968 : /* LCOV_EXCL_STOP */ - 2969 : } - 2970 : - 2971 : /* set output variables */ - 2972 913 : context->crc = crc; - 2973 913 : context->count_file = count_file; - 2974 913 : context->count_hardlink = count_hardlink; - 2975 913 : context->count_symlink = count_symlink; - 2976 913 : context->count_dir = count_dir; - 2977 : - 2978 913 : return 0; - 2979 : - 2980 : /* LCOV_EXCL_START */ - 2981 : bail: - 2982 : /* cleanup resources */ - 2983 : if (f != 0) - 2984 : sclose(f); - 2985 : return context; - 2986 : /* LCOV_EXCL_STOP */ - 2987 : } - 2988 : - 2989 134 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) - 2990 : { - 2991 : tommy_node* i; - 2992 : int fail; - 2993 : block_off_t blockmax; - 2994 : time_t info_oldest; - 2995 : int info_has_rehash; - 2996 : int mapping_idx; - 2997 : block_off_t idx; - 2998 : uint32_t crc; - 2999 : unsigned count_file; - 3000 : unsigned count_hardlink; - 3001 : unsigned count_symlink; - 3002 : unsigned count_dir; - 3003 : int first; + 2963 30261 : sputb32(end - begin, f); + 2964 : + 2965 : /* if there is info */ + 2966 30261 : if (info) { + 2967 : /* other flags */ + 2968 30239 : flag = 1; /* info is present */ + 2969 30239 : if (info_get_bad(info)) + 2970 1351 : flag |= 2; + 2971 30239 : if (info_get_rehash(info)) + 2972 9806 : flag |= 4; + 2973 30239 : if (info_get_justsynced(info)) + 2974 18186 : flag |= 8; + 2975 30239 : sputb32(flag, f); + 2976 : + 2977 30239 : t = info_get_time(info) - info_oldest; + 2978 30239 : sputb32(t, f); + 2979 : } else { + 2980 : /* write a special 0 flag to mark missing info */ + 2981 22 : sputb32(0, f); + 2982 : } + 2983 : + 2984 30261 : if (serror(f)) { + 2985 : /* LCOV_EXCL_START */ + 2986 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 2987 : return context; + 2988 : /* LCOV_EXCL_STOP */ + 2989 : } + 2990 : + 2991 : /* next begin position */ + 2992 30261 : begin = end; + 2993 : } + 2994 : + 2995 145 : sputc('N', f); + 2996 : + 2997 : /* flush data written to the disk */ + 2998 145 : if (sflush(f)) { + 2999 : /* LCOV_EXCL_START */ + 3000 : log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); + 3001 : return context; + 3002 : /* LCOV_EXCL_STOP */ + 3003 : } 3004 : - 3005 : /* blocks of all array */ - 3006 134 : blockmax = parity_allocated_size(state); + 3005 : /* get the file crc */ + 3006 145 : crc = scrc(f); 3007 : - 3008 : /* check the filesystem on all disks */ - 3009 134 : state_fscheck(state, "before write"); - 3010 : - 3011 : /* clear the info for unused blocks */ - 3012 : /* and get some other info */ - 3013 134 : info_oldest = 0; /* oldest time in info */ - 3014 134 : info_has_rehash = 0; /* if there is a rehash info */ - 3015 729552 : for (idx = 0; idx < blockmax; ++idx) { - 3016 : /* if the position is used */ - 3017 729418 : if (fs_position_is_required(state, idx)) { - 3018 729418 : snapraid_info info = info_get(&state->infoarr, idx); - 3019 : - 3020 : /* only if there is some info to store */ - 3021 729418 : if (info) { - 3022 680773 : time_t info_time = info_get_time(info); - 3023 : - 3024 680773 : if (!info_oldest || info_time < info_oldest) - 3025 170 : info_oldest = info_time; + 3008 : /* compare the crc of the data written to file */ + 3009 : /* with the one of the data written to the stream */ + 3010 145 : if (crc != scrc_stream(f)) { + 3011 : /* LCOV_EXCL_START */ + 3012 : log_fatal("CRC mismatch writing the content stream.\n"); + 3013 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + 3014 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + 3015 : return context; + 3016 : /* LCOV_EXCL_STOP */ + 3017 : } + 3018 : + 3019 145 : sputble32(crc, f); + 3020 145 : if (serror(f)) { + 3021 : /* LCOV_EXCL_START */ + 3022 : log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3023 : return context; + 3024 : /* LCOV_EXCL_STOP */ + 3025 : } 3026 : - 3027 680773 : if (info_get_rehash(info)) - 3028 108421 : info_has_rehash = 1; - 3029 : } - 3030 : } else { - 3031 : /* clear any previous info */ - 3032 0 : info_set(&state->infoarr, idx, 0); + 3027 : /* set output variables */ + 3028 145 : context->crc = crc; + 3029 145 : context->count_file = count_file; + 3030 145 : context->count_hardlink = count_hardlink; + 3031 145 : context->count_symlink = count_symlink; + 3032 145 : context->count_dir = count_dir; 3033 : - 3034 : /* and clear any deleted blocks */ - 3035 0 : fs_position_clear_deleted(state, idx); - 3036 : } - 3037 : } - 3038 : - 3039 : /* map disks */ - 3040 134 : mapping_idx = 0; - 3041 938 : for (i = state->maplist; i != 0; i = i->next) { - 3042 804 : struct snapraid_map* map = i->data; - 3043 : struct snapraid_disk* disk; - 3044 : - 3045 : /* find the disk for this mapping */ - 3046 804 : disk = find_disk(state, map->name); - 3047 804 : if (!disk) { - 3048 : /* LCOV_EXCL_START */ - 3049 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - 3050 : exit(EXIT_FAILURE); - 3051 : /* LCOV_EXCL_STOP */ - 3052 : } - 3053 : - 3054 : /* save the mapping only for not empty disks */ - 3055 804 : if (!disk_is_empty(disk, blockmax)) { - 3056 : /* assign the mapping index used to identify disks */ - 3057 741 : disk->mapping_idx = mapping_idx; - 3058 741 : ++mapping_idx; - 3059 : } else { - 3060 : /* mark the disk as without mapping */ - 3061 63 : disk->mapping_idx = -1; - 3062 : } - 3063 : } - 3064 : - 3065 : /* start all writing threads */ - 3066 134 : i = tommy_list_head(&state->contentlist); - 3067 1181 : while (i) { - 3068 913 : struct snapraid_content* content = i->data; - 3069 : struct state_write_thread_context* context; - 3070 : - 3071 : /* allocate the thread context */ - 3072 913 : context = malloc_nofail(sizeof(struct state_write_thread_context)); - 3073 913 : content->context = context; - 3074 : - 3075 : /* initialize */ - 3076 913 : context->state = state; - 3077 913 : context->content = content; - 3078 913 : context->blockmax = blockmax; - 3079 913 : context->info_oldest = info_oldest; - 3080 913 : context->info_has_rehash = info_has_rehash; - 3081 : - 3082 913 : msg_progress("Saving state to %s...\n", content->content); - 3083 : - 3084 : #if HAVE_PTHREAD_CREATE - 3085 913 : if (pthread_create(&context->thread, 0, state_write_thread, context) != 0) { - 3086 : /* LCOV_EXCL_START */ - 3087 : log_fatal("Failed to create thread.\n"); - 3088 : exit(EXIT_FAILURE); - 3089 : /* LCOV_EXCL_STOP */ - 3090 : } - 3091 : #else - 3092 : context->retval = state_write_thread(context); - 3093 : #endif + 3034 145 : return 0; + 3035 : } + 3036 : + 3037 145 : static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) + 3038 : { + 3039 : #if HAVE_MT_WRITE + 3040 : int fail; + 3041 : int first; + 3042 : #else + 3043 : STREAM* f; + 3044 : unsigned count_content; + 3045 : unsigned k; + 3046 : struct state_write_thread_context* context; + 3047 : void* retval; + 3048 : #endif + 3049 : tommy_node* i; + 3050 : block_off_t blockmax; + 3051 : time_t info_oldest; + 3052 : int info_has_rehash; + 3053 : int mapping_idx; + 3054 : block_off_t idx; + 3055 : uint32_t crc; + 3056 : unsigned count_file; + 3057 : unsigned count_hardlink; + 3058 : unsigned count_symlink; + 3059 : unsigned count_dir; + 3060 : + 3061 : /* blocks of all array */ + 3062 145 : blockmax = parity_allocated_size(state); + 3063 : + 3064 : /* check the file-system on all disks */ + 3065 145 : state_fscheck(state, "before write"); + 3066 : + 3067 : /* clear the info for unused blocks */ + 3068 : /* and get some other info */ + 3069 145 : info_oldest = 0; /* oldest time in info */ + 3070 145 : info_has_rehash = 0; /* if there is a rehash info */ + 3071 752636 : for (idx = 0; idx < blockmax; ++idx) { + 3072 : /* if the position is used */ + 3073 752491 : if (fs_position_is_required(state, idx)) { + 3074 752491 : snapraid_info info = info_get(&state->infoarr, idx); + 3075 : + 3076 : /* only if there is some info to store */ + 3077 752491 : if (info) { + 3078 708014 : time_t info_time = info_get_time(info); + 3079 : + 3080 708014 : if (!info_oldest || info_time < info_oldest) + 3081 155 : info_oldest = info_time; + 3082 : + 3083 708014 : if (info_get_rehash(info)) + 3084 18413 : info_has_rehash = 1; + 3085 : } + 3086 : } else { + 3087 : /* clear any previous info */ + 3088 0 : info_set(&state->infoarr, idx, 0); + 3089 : + 3090 : /* and clear any deleted blocks */ + 3091 0 : fs_position_clear_deleted(state, idx); + 3092 : } + 3093 : } 3094 : - 3095 913 : i = i->next; - 3096 : } - 3097 : - 3098 : /* join all thread */ - 3099 134 : fail = 0; - 3100 134 : first = 1; - 3101 134 : crc = 0; - 3102 134 : count_file = 0; - 3103 134 : count_hardlink = 0; - 3104 134 : count_symlink = 0; - 3105 134 : count_dir = 0; - 3106 134 : i = tommy_list_head(&state->contentlist); - 3107 1181 : while (i) { - 3108 913 : struct snapraid_content* content = i->data; - 3109 913 : struct state_write_thread_context* context = content->context; - 3110 : void* retval; - 3111 : - 3112 : #if HAVE_PTHREAD_CREATE - 3113 913 : if (pthread_join(context->thread, &retval) != 0) { - 3114 : /* LCOV_EXCL_START */ - 3115 : log_fatal("Failed to join thread.\n"); - 3116 : exit(EXIT_FAILURE); - 3117 : /* LCOV_EXCL_STOP */ + 3095 : /* map disks */ + 3096 145 : mapping_idx = 0; + 3097 1015 : for (i = state->maplist; i != 0; i = i->next) { + 3098 870 : struct snapraid_map* map = i->data; + 3099 : struct snapraid_disk* disk; + 3100 : + 3101 : /* find the disk for this mapping */ + 3102 870 : disk = find_disk_by_name(state, map->name); + 3103 870 : if (!disk) { + 3104 : /* LCOV_EXCL_START */ + 3105 : log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + 3106 : os_abort(); + 3107 : /* LCOV_EXCL_STOP */ + 3108 : } + 3109 : + 3110 : /* save the mapping only for not empty disks */ + 3111 870 : if (!disk_is_empty(disk, blockmax)) { + 3112 : /* assign the mapping index used to identify disks */ + 3113 786 : disk->mapping_idx = mapping_idx; + 3114 786 : ++mapping_idx; + 3115 : } else { + 3116 : /* mark the disk as without mapping */ + 3117 84 : disk->mapping_idx = -1; 3118 : } - 3119 : #else - 3120 : retval = context->retval; - 3121 : #endif - 3122 913 : if (retval) { - 3123 : /* LCOV_EXCL_START */ - 3124 : fail = 1; - 3125 : /* LCOV_EXCL_STOP */ - 3126 : } else { - 3127 913 : if (first) { - 3128 134 : first = 0; - 3129 134 : crc = context->crc; - 3130 134 : count_file = context->count_file; - 3131 134 : count_hardlink = context->count_hardlink; - 3132 134 : count_symlink = context->count_symlink; - 3133 134 : count_dir = context->count_dir; - 3134 : } else { - 3135 779 : if (crc != context->crc) { - 3136 : /* LCOV_EXCL_START */ - 3137 : log_fatal("Different CRCs writing content streams.\n"); - 3138 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); - 3139 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); - 3140 : exit(EXIT_FAILURE); - 3141 : /* LCOV_EXCL_STOP */ - 3142 : } - 3143 : } - 3144 : } - 3145 : - 3146 913 : free(context); - 3147 : - 3148 913 : i = i->next; - 3149 : } - 3150 : - 3151 : /* abort on failure */ - 3152 134 : if (fail) { - 3153 : /* LCOV_EXCL_START */ - 3154 : exit(EXIT_FAILURE); - 3155 : /* LCOV_EXCL_STOP */ - 3156 : } - 3157 : - 3158 134 : msg_verbose("%8u files\n", count_file); - 3159 134 : msg_verbose("%8u hardlinks\n", count_hardlink); - 3160 134 : msg_verbose("%8u symlinks\n", count_symlink); - 3161 134 : msg_verbose("%8u empty dirs\n", count_dir); - 3162 : - 3163 134 : *out_crc = crc; - 3164 134 : } - 3165 : - 3166 242 : void state_read(struct snapraid_state* state) - 3167 : { - 3168 : STREAM* f; - 3169 : char path[PATH_MAX]; - 3170 : struct stat st; - 3171 : tommy_node* node; - 3172 : int ret; - 3173 : int c; - 3174 : - 3175 : /* iterate over all the available content files and load the first one present */ - 3176 242 : f = 0; - 3177 242 : node = tommy_list_head(&state->contentlist); - 3178 534 : while (node) { - 3179 285 : struct snapraid_content* content = node->data; - 3180 285 : pathcpy(path, sizeof(path), content->content); - 3181 : - 3182 285 : if (!state->no_conf) { - 3183 284 : log_tag("content:%s\n", path); - 3184 284 : log_flush(); - 3185 : } - 3186 285 : msg_progress("Loading state from %s...\n", path); - 3187 : - 3188 285 : f = sopen_read(path); - 3189 285 : if (f != 0) { - 3190 : /* if openend stop the search */ - 3191 235 : break; - 3192 : } else { - 3193 : /* if it's real error of an existing file, abort */ - 3194 50 : if (errno != ENOENT) { - 3195 : /* LCOV_EXCL_START */ - 3196 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno)); - 3197 : exit(EXIT_FAILURE); - 3198 : /* LCOV_EXCL_STOP */ - 3199 : } - 3200 : - 3201 : /* otherwise continue */ - 3202 50 : if (node->next) { - 3203 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path); - 3204 : - 3205 : /* ensure to rewrite all the content files */ - 3206 43 : state->need_write = 1; - 3207 : } - 3208 : } - 3209 : - 3210 : /* next content file */ - 3211 50 : node = node->next; - 3212 : } - 3213 : - 3214 : /* if not found, assume empty */ - 3215 242 : if (!f) { - 3216 7 : log_fatal("No content file found. Assuming empty.\n"); - 3217 : - 3218 : /* create the initial mapping */ - 3219 7 : state_map(state); - 3220 248 : return; - 3221 : } - 3222 : - 3223 : /* get the stat of the content file */ - 3224 235 : ret = fstat(shandle(f), &st); - 3225 235 : if (ret != 0) { - 3226 : /* LCOV_EXCL_START */ - 3227 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno)); - 3228 : exit(EXIT_FAILURE); - 3229 : /* LCOV_EXCL_STOP */ - 3230 : } - 3231 : - 3232 : /* go further to check other content files */ - 3233 1819 : while (node) { - 3234 : char other_path[PATH_MAX]; - 3235 : struct stat other_st; - 3236 1349 : struct snapraid_content* content = node->data; - 3237 1349 : pathcpy(other_path, sizeof(other_path), content->content); + 3119 : } + 3120 : + 3121 : #if HAVE_MT_WRITE + 3122 : /* start all writing threads */ + 3123 : i = tommy_list_head(&state->contentlist); + 3124 : while (i) { + 3125 : struct snapraid_content* content = i->data; + 3126 : struct state_write_thread_context* context; + 3127 : char tmp[PATH_MAX]; + 3128 : STREAM* f; + 3129 : + 3130 : msg_progress("Saving state to %s...\n", content->content); + 3131 : + 3132 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3133 : f = sopen_write(tmp); + 3134 : if (f == 0) { + 3135 : /* LCOV_EXCL_START */ + 3136 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3137 : exit(EXIT_FAILURE); + 3138 : /* LCOV_EXCL_STOP */ + 3139 : } + 3140 : + 3141 : /* allocate the thread context */ + 3142 : context = malloc_nofail(sizeof(struct state_write_thread_context)); + 3143 : content->context = context; + 3144 : + 3145 : /* initialize */ + 3146 : context->state = state; + 3147 : context->blockmax = blockmax; + 3148 : context->info_oldest = info_oldest; + 3149 : context->info_has_rehash = info_has_rehash; + 3150 : context->f = f; + 3151 : + 3152 : if (pthread_create(&context->thread, 0, state_write_thread, context) != 0) { + 3153 : /* LCOV_EXCL_START */ + 3154 : log_fatal("Failed to create thread.\n"); + 3155 : exit(EXIT_FAILURE); + 3156 : /* LCOV_EXCL_STOP */ + 3157 : } + 3158 : + 3159 : i = i->next; + 3160 : } + 3161 : + 3162 : /* join all thread */ + 3163 : fail = 0; + 3164 : first = 1; + 3165 : crc = 0; + 3166 : count_file = 0; + 3167 : count_hardlink = 0; + 3168 : count_symlink = 0; + 3169 : count_dir = 0; + 3170 : i = tommy_list_head(&state->contentlist); + 3171 : while (i) { + 3172 : struct snapraid_content* content = i->data; + 3173 : struct state_write_thread_context* context = content->context; + 3174 : void* retval; + 3175 : + 3176 : if (pthread_join(context->thread, &retval) != 0) { + 3177 : /* LCOV_EXCL_START */ + 3178 : log_fatal("Failed to join thread.\n"); + 3179 : exit(EXIT_FAILURE); + 3180 : /* LCOV_EXCL_STOP */ + 3181 : } + 3182 : + 3183 : if (retval) { + 3184 : /* LCOV_EXCL_START */ + 3185 : fail = 1; + 3186 : /* LCOV_EXCL_STOP */ + 3187 : } else { + 3188 : STREAM* f = context->f; + 3189 : + 3190 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + 3191 : /* than even in a system crash event we have one valid copy of the file. */ + 3192 : if (sflush(f) != 0) { + 3193 : /* LCOV_EXCL_START */ + 3194 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + 3195 : exit(EXIT_FAILURE); + 3196 : /* LCOV_EXCL_STOP */ + 3197 : } + 3198 : + 3199 : #if HAVE_FSYNC + 3200 : if (ssync(f) != 0) { + 3201 : /* LCOV_EXCL_START */ + 3202 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + 3203 : exit(EXIT_FAILURE); + 3204 : /* LCOV_EXCL_STOP */ + 3205 : } + 3206 : #endif + 3207 : + 3208 : if (sclose(f) != 0) { + 3209 : /* LCOV_EXCL_START */ + 3210 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3211 : exit(EXIT_FAILURE); + 3212 : /* LCOV_EXCL_STOP */ + 3213 : } + 3214 : + 3215 : if (first) { + 3216 : first = 0; + 3217 : crc = context->crc; + 3218 : count_file = context->count_file; + 3219 : count_hardlink = context->count_hardlink; + 3220 : count_symlink = context->count_symlink; + 3221 : count_dir = context->count_dir; + 3222 : } else { + 3223 : if (crc != context->crc) { + 3224 : /* LCOV_EXCL_START */ + 3225 : log_fatal("Different CRCs writing content streams.\n"); + 3226 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + 3227 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + 3228 : exit(EXIT_FAILURE); + 3229 : /* LCOV_EXCL_STOP */ + 3230 : } + 3231 : } + 3232 : } + 3233 : + 3234 : free(context); + 3235 : + 3236 : i = i->next; + 3237 : } 3238 : - 3239 1349 : ret = stat(other_path, &other_st); - 3240 1349 : if (ret != 0) { - 3241 : /* allow missing content files, but not any other kind of error */ - 3242 1 : if (errno != ENOENT) { - 3243 : /* LCOV_EXCL_START */ - 3244 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno)); - 3245 : exit(EXIT_FAILURE); - 3246 : /* LCOV_EXCL_STOP */ - 3247 : } - 3248 : - 3249 : /* ensure to rewrite all the content files */ - 3250 1 : state->need_write = 1; - 3251 : } else { - 3252 : /* if the size is different */ - 3253 1348 : if (other_st.st_size != st.st_size) { - 3254 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path); - 3255 39 : log_fatal("Likely one of the two is broken!\n"); - 3256 : - 3257 : /* ensure to rewrite all the content files */ - 3258 39 : state->need_write = 1; - 3259 : } - 3260 : } - 3261 : - 3262 : /* next content file */ - 3263 1349 : node = node->next; - 3264 : } - 3265 : - 3266 : /* start with a undefined default. */ - 3267 : /* it's for compatibility with version 1.0 where MD5 was implicit. */ - 3268 235 : state->hash = HASH_UNDEFINED; - 3269 : - 3270 : /* start with a zero seed, it was the default in old versions */ - 3271 235 : memset(state->hashseed, 0, HASH_SIZE); - 3272 : - 3273 : /* previous hash, start with an undefined value */ - 3274 235 : state->prevhash = HASH_UNDEFINED; - 3275 : - 3276 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ - 3277 : - 3278 : /* get the first char to detect the file type */ - 3279 235 : c = sgetc(f); - 3280 235 : sungetc(c, f); - 3281 : - 3282 : /* guess the file type from the first char */ - 3283 235 : if (c == 'S') { - 3284 235 : state_read_content(state, path, f); - 3285 : } else { - 3286 : /* LCOV_EXCL_START */ - 3287 : log_fatal("The text file format is not supported anymore.\n"); - 3288 : exit(EXIT_FAILURE); - 3289 : /* LCOV_EXCL_STOP */ - 3290 : } - 3291 : - 3292 234 : sclose(f); - 3293 : - 3294 234 : if (state->hash == HASH_UNDEFINED) { + 3239 : /* abort on failure */ + 3240 : if (fail) { + 3241 : /* LCOV_EXCL_START */ + 3242 : exit(EXIT_FAILURE); + 3243 : /* LCOV_EXCL_STOP */ + 3244 : } + 3245 : #else + 3246 : /* count the content files */ + 3247 145 : count_content = 0; + 3248 145 : i = tommy_list_head(&state->contentlist); + 3249 1280 : while (i) { + 3250 990 : struct snapraid_content* content = i->data; + 3251 990 : msg_progress("Saving state to %s...\n", content->content); + 3252 990 : ++count_content; + 3253 990 : i = i->next; + 3254 : } + 3255 : + 3256 : /* open all the content files */ + 3257 145 : f = sopen_multi_write(count_content); + 3258 145 : if (!f) { + 3259 : /* LCOV_EXCL_START */ + 3260 : log_fatal("Error opening the content files.\n"); + 3261 : exit(EXIT_FAILURE); + 3262 : /* LCOV_EXCL_STOP */ + 3263 : } + 3264 : + 3265 145 : k = 0; + 3266 145 : i = tommy_list_head(&state->contentlist); + 3267 1280 : while (i) { + 3268 990 : struct snapraid_content* content = i->data; + 3269 : char tmp[PATH_MAX]; + 3270 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3271 990 : if (sopen_multi_file(f, k, tmp) != 0) { + 3272 : /* LCOV_EXCL_START */ + 3273 : log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3274 : exit(EXIT_FAILURE); + 3275 : /* LCOV_EXCL_STOP */ + 3276 : } + 3277 990 : ++k; + 3278 990 : i = i->next; + 3279 : } + 3280 : + 3281 : /* allocate the thread context */ + 3282 145 : context = malloc_nofail(sizeof(struct state_write_thread_context)); + 3283 : + 3284 : /* initialize */ + 3285 145 : context->state = state; + 3286 145 : context->blockmax = blockmax; + 3287 145 : context->info_oldest = info_oldest; + 3288 145 : context->info_has_rehash = info_has_rehash; + 3289 145 : context->f = f; + 3290 : + 3291 145 : retval = state_write_thread(context); + 3292 : + 3293 : /* abort on failure */ + 3294 145 : if (retval) { 3295 : /* LCOV_EXCL_START */ - 3296 : log_fatal("The checksum to use is not specified.\n"); - 3297 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n"); - 3298 : log_fatal("To use a new SnapRAID you must restart from scratch,\n"); - 3299 : log_fatal("deleting all the content and parity files.\n"); - 3300 : exit(EXIT_FAILURE); - 3301 : /* LCOV_EXCL_STOP */ - 3302 : } - 3303 : - 3304 : /* update the mapping */ - 3305 234 : state_map(state); - 3306 : - 3307 234 : state_content_check(state, path); + 3296 : exit(EXIT_FAILURE); + 3297 : /* LCOV_EXCL_STOP */ + 3298 : } + 3299 : + 3300 : /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + 3301 : /* than even in a system crash event we have one valid copy of the file. */ + 3302 145 : if (sflush(f) != 0) { + 3303 : /* LCOV_EXCL_START */ + 3304 : log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + 3305 : exit(EXIT_FAILURE); + 3306 : /* LCOV_EXCL_STOP */ + 3307 : } 3308 : - 3309 : /* mark that we read the content file, and it passed all the checks */ - 3310 234 : state->checked_read = 1; - 3311 : } - 3312 : - 3313 : struct state_verify_thread_context { - 3314 : struct snapraid_state* state; - 3315 : struct snapraid_content* content; - 3316 : #if HAVE_PTHREAD_CREATE - 3317 : pthread_t thread; - 3318 : #else - 3319 : void* retval; - 3320 : #endif - 3321 : /* input */ - 3322 : uint32_t crc; - 3323 : }; + 3309 : #if HAVE_FSYNC + 3310 145 : if (ssync(f) != 0) { + 3311 : /* LCOV_EXCL_START */ + 3312 : log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + 3313 : exit(EXIT_FAILURE); + 3314 : /* LCOV_EXCL_STOP */ + 3315 : } + 3316 : #endif + 3317 : + 3318 145 : if (sclose(f) != 0) { + 3319 : /* LCOV_EXCL_START */ + 3320 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3321 : exit(EXIT_FAILURE); + 3322 : /* LCOV_EXCL_STOP */ + 3323 : } 3324 : - 3325 912 : static void* state_verify_thread(void* arg) - 3326 : { - 3327 912 : struct state_verify_thread_context* context = arg; - 3328 912 : struct snapraid_content* content = context->content; - 3329 : STREAM* f; - 3330 : char tmp[PATH_MAX]; - 3331 : unsigned char buf[4]; - 3332 : uint32_t crc_stored; - 3333 : uint32_t crc_computed; - 3334 : - 3335 912 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3336 : - 3337 913 : f = sopen_read(tmp); - 3338 913 : if (f == 0) { - 3339 : /* LCOV_EXCL_START */ - 3340 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno)); - 3341 : goto bail; - 3342 : /* LCOV_EXCL_STOP */ - 3343 : } - 3344 : - 3345 913 : if (sdeplete(f, buf) != 0) { - 3346 : /* LCOV_EXCL_START */ - 3347 : log_fatal("Error flushing the content file '%s'. %s.\n", tmp, strerror(errno)); - 3348 : goto bail; - 3349 : /* LCOV_EXCL_STOP */ - 3350 : } - 3351 : - 3352 : /* get the stored crc from the last four bytes */ - 3353 913 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; - 3354 : - 3355 913 : if (crc_stored != context->crc) { - 3356 : /* LCOV_EXCL_START */ - 3357 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", tmp); - 3358 : goto bail; - 3359 : /* LCOV_EXCL_STOP */ - 3360 : } - 3361 : - 3362 : /* get the computed crc */ - 3363 913 : crc_computed = scrc(f); - 3364 : - 3365 : /* adjust the stored crc to include itself */ - 3366 913 : crc_stored = crc32c(crc_stored, buf, 4); - 3367 : - 3368 913 : if (crc_computed != crc_stored) { - 3369 : /* LCOV_EXCL_START */ - 3370 : log_fatal("DANGER! Wrong file CRC in '%s'\n", tmp); - 3371 : goto bail; - 3372 : /* LCOV_EXCL_STOP */ - 3373 : } - 3374 : - 3375 913 : if (sclose(f) != 0) { - 3376 : /* LCOV_EXCL_START */ - 3377 : f = 0; - 3378 : log_fatal("Error closing the content file '%s'. %s.\n", tmp, strerror(errno)); - 3379 : goto bail; - 3380 : /* LCOV_EXCL_STOP */ - 3381 : } - 3382 : - 3383 913 : return 0; - 3384 : - 3385 : bail: - 3386 : /* LCOV_EXCL_START */ - 3387 : /* cleanup resources */ - 3388 : if (f != 0) - 3389 : sclose(f); - 3390 : return context; - 3391 : /* LCOV_EXCL_STOP */ - 3392 : } + 3325 145 : crc = context->crc; + 3326 145 : count_file = context->count_file; + 3327 145 : count_hardlink = context->count_hardlink; + 3328 145 : count_symlink = context->count_symlink; + 3329 145 : count_dir = context->count_dir; + 3330 : + 3331 145 : free(context); + 3332 : #endif + 3333 : + 3334 145 : msg_verbose("%8u files\n", count_file); + 3335 145 : msg_verbose("%8u hardlinks\n", count_hardlink); + 3336 145 : msg_verbose("%8u symlinks\n", count_symlink); + 3337 145 : msg_verbose("%8u empty dirs\n", count_dir); + 3338 : + 3339 145 : *out_crc = crc; + 3340 145 : } + 3341 : + 3342 250 : void state_read(struct snapraid_state* state) + 3343 : { + 3344 : STREAM* f; + 3345 : char path[PATH_MAX]; + 3346 : struct stat st; + 3347 : tommy_node* node; + 3348 : int ret; + 3349 : int c; + 3350 : + 3351 : /* iterate over all the available content files and load the first one present */ + 3352 250 : f = 0; + 3353 250 : node = tommy_list_head(&state->contentlist); + 3354 550 : while (node) { + 3355 293 : struct snapraid_content* content = node->data; + 3356 293 : pathcpy(path, sizeof(path), content->content); + 3357 : + 3358 293 : if (!state->no_conf) { + 3359 292 : log_tag("content:%s\n", path); + 3360 292 : log_flush(); + 3361 : } + 3362 293 : msg_progress("Loading state from %s...\n", path); + 3363 : + 3364 293 : f = sopen_read(path); + 3365 293 : if (f != 0) { + 3366 : /* if opened stop the search */ + 3367 243 : break; + 3368 : } else { + 3369 : /* if it's real error of an existing file, abort */ + 3370 50 : if (errno != ENOENT) { + 3371 : /* LCOV_EXCL_START */ + 3372 : log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno)); + 3373 : exit(EXIT_FAILURE); + 3374 : /* LCOV_EXCL_STOP */ + 3375 : } + 3376 : + 3377 : /* otherwise continue */ + 3378 50 : if (node->next) { + 3379 43 : log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path); + 3380 : + 3381 : /* ensure to rewrite all the content files */ + 3382 43 : state->need_write = 1; + 3383 : } + 3384 : } + 3385 : + 3386 : /* next content file */ + 3387 50 : node = node->next; + 3388 : } + 3389 : + 3390 : /* if not found, assume empty */ + 3391 250 : if (!f) { + 3392 7 : log_fatal("No content file found. Assuming empty.\n"); 3393 : - 3394 134 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) - 3395 : { - 3396 : tommy_node* i; - 3397 : int fail; + 3394 : /* create the initial mapping */ + 3395 7 : state_map(state); + 3396 256 : return; + 3397 : } 3398 : - 3399 : /* start all reading threads */ - 3400 134 : i = tommy_list_head(&state->contentlist); - 3401 1181 : while (i) { - 3402 913 : struct snapraid_content* content = i->data; - 3403 : struct state_verify_thread_context* context; - 3404 : - 3405 : /* allocate the thread context */ - 3406 913 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); - 3407 913 : content->context = context; - 3408 : - 3409 : /* initialize */ - 3410 913 : context->state = state; - 3411 913 : context->content = content; - 3412 913 : context->crc = crc; - 3413 : - 3414 913 : msg_progress("Verifying %s...\n", content->content); - 3415 : - 3416 : #if HAVE_PTHREAD_CREATE - 3417 913 : if (pthread_create(&context->thread, 0, state_verify_thread, context) != 0) { - 3418 : /* LCOV_EXCL_START */ - 3419 : log_fatal("Failed to create thread.\n"); - 3420 : exit(EXIT_FAILURE); - 3421 : /* LCOV_EXCL_STOP */ - 3422 : } - 3423 : #else - 3424 : content->retval = state_verify_thread(context); - 3425 : #endif - 3426 : - 3427 913 : i = i->next; - 3428 : } - 3429 : - 3430 : /* join all thread */ - 3431 134 : fail = 0; - 3432 134 : i = tommy_list_head(&state->contentlist); - 3433 1181 : while (i) { - 3434 913 : struct snapraid_content* content = i->data; - 3435 913 : struct state_verify_thread_context* context = content->context; - 3436 : void* retval; + 3399 : /* get the stat of the content file */ + 3400 243 : ret = fstat(shandle(f), &st); + 3401 243 : if (ret != 0) { + 3402 : /* LCOV_EXCL_START */ + 3403 : log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno)); + 3404 : exit(EXIT_FAILURE); + 3405 : /* LCOV_EXCL_STOP */ + 3406 : } + 3407 : + 3408 : /* go further to check other content files */ + 3409 1891 : while (node) { + 3410 : char other_path[PATH_MAX]; + 3411 : struct stat other_st; + 3412 1405 : struct snapraid_content* content = node->data; + 3413 1405 : pathcpy(other_path, sizeof(other_path), content->content); + 3414 : + 3415 1405 : ret = stat(other_path, &other_st); + 3416 1405 : if (ret != 0) { + 3417 : /* allow missing content files, but not any other kind of error */ + 3418 1 : if (errno != ENOENT) { + 3419 : /* LCOV_EXCL_START */ + 3420 : log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno)); + 3421 : exit(EXIT_FAILURE); + 3422 : /* LCOV_EXCL_STOP */ + 3423 : } + 3424 : + 3425 : /* ensure to rewrite all the content files */ + 3426 1 : state->need_write = 1; + 3427 : } else { + 3428 : /* if the size is different */ + 3429 1404 : if (other_st.st_size != st.st_size) { + 3430 39 : log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path); + 3431 39 : log_fatal("Likely one of the two is broken!\n"); + 3432 : + 3433 : /* ensure to rewrite all the content files */ + 3434 39 : state->need_write = 1; + 3435 : } + 3436 : } 3437 : - 3438 : #if HAVE_PTHREAD_CREATE - 3439 913 : if (pthread_join(context->thread, &retval) != 0) { - 3440 : /* LCOV_EXCL_START */ - 3441 : log_fatal("Failed to join thread.\n"); - 3442 : exit(EXIT_FAILURE); - 3443 : /* LCOV_EXCL_STOP */ - 3444 : } - 3445 : #else - 3446 : retval = context->retval; - 3447 : #endif - 3448 913 : if (retval) { - 3449 : /* LCOV_EXCL_START */ - 3450 : fail = 1; - 3451 : /* LCOV_EXCL_STOP */ - 3452 : } + 3438 : /* next content file */ + 3439 1405 : node = node->next; + 3440 : } + 3441 : + 3442 : /* start with a undefined default. */ + 3443 : /* it's for compatibility with version 1.0 where MD5 was implicit. */ + 3444 243 : state->hash = HASH_UNDEFINED; + 3445 : + 3446 : /* start with a zero seed, it was the default in old versions */ + 3447 243 : memset(state->hashseed, 0, HASH_SIZE); + 3448 : + 3449 : /* previous hash, start with an undefined value */ + 3450 243 : state->prevhash = HASH_UNDEFINED; + 3451 : + 3452 : /* intentionally not set the prevhashseed, if used valgrind will warn about it */ 3453 : - 3454 913 : free(context); - 3455 : - 3456 913 : i = i->next; - 3457 : } - 3458 : - 3459 : /* abort on failure */ - 3460 134 : if (fail) { - 3461 : /* LCOV_EXCL_START */ - 3462 : exit(EXIT_FAILURE); - 3463 : /* LCOV_EXCL_STOP */ - 3464 : } - 3465 134 : } - 3466 : - 3467 134 : static void state_rename_content(struct snapraid_state* state) - 3468 : { - 3469 : tommy_node* i; + 3454 : /* get the first char to detect the file type */ + 3455 243 : c = sgetc(f); + 3456 243 : sungetc(c, f); + 3457 : + 3458 : /* guess the file type from the first char */ + 3459 243 : if (c == 'S') { + 3460 243 : state_read_content(state, path, f); + 3461 : } else { + 3462 : /* LCOV_EXCL_START */ + 3463 : log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n"); + 3464 : log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n"); + 3465 : exit(EXIT_FAILURE); + 3466 : /* LCOV_EXCL_STOP */ + 3467 : } + 3468 : + 3469 242 : sclose(f); 3470 : - 3471 134 : i = tommy_list_head(&state->contentlist); - 3472 1181 : while (i) { - 3473 913 : struct snapraid_content* content = i->data; - 3474 : char tmp[PATH_MAX]; - 3475 : - 3476 : /* now renames the just written copy with the correct name */ - 3477 913 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); - 3478 913 : if (rename(tmp, content->content) != 0) { - 3479 : /* LCOV_EXCL_START */ - 3480 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); - 3481 : exit(EXIT_FAILURE); - 3482 : /* LCOV_EXCL_STOP */ - 3483 : } - 3484 : - 3485 913 : i = i->next; - 3486 : } - 3487 134 : } - 3488 : - 3489 134 : void state_write(struct snapraid_state* state) - 3490 : { - 3491 : uint32_t crc; - 3492 : - 3493 : /* write all the content files */ - 3494 134 : state_write_content(state, &crc); - 3495 : - 3496 : /* verify the just written files */ - 3497 134 : state_verify_content(state, crc); - 3498 : - 3499 : /* rename the new files, over the old ones */ - 3500 134 : state_rename_content(state); - 3501 : - 3502 134 : state->need_write = 0; /* no write needed anymore */ - 3503 134 : state->checked_read = 0; /* what we wrote is not checked in read */ - 3504 134 : } - 3505 : - 3506 122 : void state_skip(struct snapraid_state* state) - 3507 : { - 3508 : tommy_node* i; - 3509 : - 3510 : /* for each disk */ - 3511 850 : for (i = state->disklist; i != 0; i = i->next) { - 3512 : tommy_node* j; - 3513 728 : struct snapraid_disk* disk = i->data; - 3514 : - 3515 728 : if (!disk->skip_access) - 3516 727 : continue; + 3471 242 : if (state->hash == HASH_UNDEFINED) { + 3472 : /* LCOV_EXCL_START */ + 3473 : log_fatal("The checksum to use is not specified.\n"); + 3474 : log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n"); + 3475 : log_fatal("To use a new SnapRAID you must restart from scratch,\n"); + 3476 : log_fatal("deleting all the content and parity files.\n"); + 3477 : exit(EXIT_FAILURE); + 3478 : /* LCOV_EXCL_STOP */ + 3479 : } + 3480 : + 3481 : /* update the mapping */ + 3482 242 : state_map(state); + 3483 : + 3484 242 : state_content_check(state, path); + 3485 : + 3486 : /* mark that we read the content file, and it passed all the checks */ + 3487 242 : state->checked_read = 1; + 3488 : } + 3489 : + 3490 : struct state_verify_thread_context { + 3491 : struct snapraid_state* state; + 3492 : struct snapraid_content* content; + 3493 : #if HAVE_MT_VERIFY + 3494 : pthread_t thread; + 3495 : #else + 3496 : void* retval; + 3497 : #endif + 3498 : /* input */ + 3499 : uint32_t crc; + 3500 : STREAM* f; + 3501 : }; + 3502 : + 3503 990 : static void* state_verify_thread(void* arg) + 3504 : { + 3505 990 : struct state_verify_thread_context* context = arg; + 3506 990 : STREAM* f = context->f; + 3507 : unsigned char buf[4]; + 3508 : uint32_t crc_stored; + 3509 : uint32_t crc_computed; + 3510 : + 3511 990 : if (sdeplete(f, buf) != 0) { + 3512 : /* LCOV_EXCL_START */ + 3513 : log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + 3514 : return context; + 3515 : /* LCOV_EXCL_STOP */ + 3516 : } 3517 : - 3518 : /* for each file */ - 3519 1883 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { - 3520 1882 : struct snapraid_file* file = j->data; - 3521 1882 : file_flag_set(file, FILE_IS_EXCLUDED); - 3522 : } - 3523 : - 3524 : /* for each link */ - 3525 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { - 3526 56 : struct snapraid_link* slink = j->data; - 3527 56 : link_flag_set(slink, FILE_IS_EXCLUDED); - 3528 : } - 3529 : - 3530 : /* for each dir */ - 3531 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { - 3532 0 : struct snapraid_dir* dir = j->data; - 3533 0 : dir_flag_set(dir, FILE_IS_EXCLUDED); - 3534 : } - 3535 : } - 3536 122 : } - 3537 : - 3538 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) - 3539 : { - 3540 : tommy_node* i; - 3541 : unsigned l; - 3542 : - 3543 : /* if no filter, include all */ - 3544 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) - 3545 235 : return; - 3546 : - 3547 9 : msg_progress("Filtering...\n"); + 3518 : /* get the stored crc from the last four bytes */ + 3519 990 : crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + 3520 : + 3521 990 : if (crc_stored != context->crc) { + 3522 : /* LCOV_EXCL_START */ + 3523 : log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f)); + 3524 : return context; + 3525 : /* LCOV_EXCL_STOP */ + 3526 : } + 3527 : + 3528 : /* get the computed crc */ + 3529 990 : crc_computed = scrc(f); + 3530 : + 3531 : /* adjust the stored crc to include itself */ + 3532 990 : crc_stored = crc32c(crc_stored, buf, 4); + 3533 : + 3534 990 : if (crc_computed != crc_stored) { + 3535 : /* LCOV_EXCL_START */ + 3536 : log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f)); + 3537 : return context; + 3538 : /* LCOV_EXCL_STOP */ + 3539 : } + 3540 : + 3541 990 : return 0; + 3542 : } + 3543 : + 3544 145 : static void state_verify_content(struct snapraid_state* state, uint32_t crc) + 3545 : { + 3546 : tommy_node* i; + 3547 : int fail; 3548 : - 3549 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { - 3550 8 : struct snapraid_filter* filter = i->data; - 3551 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : ""); - 3552 : } - 3553 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) { - 3554 3 : struct snapraid_filter* filter = i->data; - 3555 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : ""); - 3556 : } - 3557 9 : if (filter_missing) - 3558 2 : msg_verbose("\t<missing>\n"); - 3559 9 : if (filter_error) - 3560 2 : msg_verbose("\t<error>\n"); - 3561 : - 3562 : /* for each disk */ - 3563 63 : for (i = state->disklist; i != 0; i = i->next) { - 3564 : tommy_node* j; - 3565 54 : struct snapraid_disk* disk = i->data; - 3566 : - 3567 : /* if we filter for presence, we have to access the disk, so better to print something */ - 3568 54 : if (filter_missing) - 3569 12 : msg_progress("Scanning disk %s...\n", disk->name); - 3570 : - 3571 : /* for each file */ - 3572 133854 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { - 3573 133800 : struct snapraid_file* file = j->data; - 3574 : - 3575 133800 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0 - 3576 80924 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0 - 3577 78090 : || filter_existence(filter_missing, disk->dir, file->sub) != 0 - 3578 38806 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 - 3579 : ) { - 3580 109102 : file_flag_set(file, FILE_IS_EXCLUDED); - 3581 : } - 3582 : } - 3583 : - 3584 : /* for each link */ - 3585 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { - 3586 4360 : struct snapraid_link* slink = j->data; - 3587 : - 3588 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0 - 3589 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0 - 3590 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0 - 3591 : ) { - 3592 3221 : link_flag_set(slink, FILE_IS_EXCLUDED); - 3593 : } - 3594 : } - 3595 : - 3596 : /* for each dir */ - 3597 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { - 3598 28 : struct snapraid_dir* dir = j->data; - 3599 : - 3600 28 : if (filter_dir(filterlist_disk, 0, disk->name, dir->sub) != 0 - 3601 28 : || filter_dir(filterlist_file, 0, disk->name, dir->sub) != 0 - 3602 28 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0 - 3603 : ) { - 3604 8 : dir_flag_set(dir, FILE_IS_EXCLUDED); - 3605 : } - 3606 : } - 3607 : } - 3608 : - 3609 : /* if we are filtering by disk */ - 3610 9 : if (!tommy_list_empty(filterlist_disk)) { - 3611 : /* for each parity disk */ - 3612 20 : for (l = 0; l < state->level; ++l) { - 3613 : /* check if the parity is excluded by name */ - 3614 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) { - 3615 : /* excluded the parity from further operation */ - 3616 11 : state->parity[l].is_excluded = 1; - 3617 : } - 3618 : } - 3619 : } else { - 3620 : /* if we are filtering by file, exclude all parity */ - 3621 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) { - 3622 : /* for each parity disk */ - 3623 16 : for (l = 0; l < state->level; ++l) { - 3624 13 : state->parity[l].is_excluded = 1; - 3625 : } - 3626 : } - 3627 : } - 3628 : } - 3629 : - 3630 206 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax) - 3631 : { - 3632 : time_t now; - 3633 : - 3634 206 : if (state->opt.gui) { - 3635 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax); - 3636 5 : log_flush(); - 3637 : } + 3549 : /* start all reading threads */ + 3550 145 : i = tommy_list_head(&state->contentlist); + 3551 1280 : while (i) { + 3552 990 : struct snapraid_content* content = i->data; + 3553 : struct state_verify_thread_context* context; + 3554 : char tmp[PATH_MAX]; + 3555 : STREAM* f; + 3556 : + 3557 990 : msg_progress("Verifying %s...\n", content->content); + 3558 : + 3559 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3560 : + 3561 990 : f = sopen_read(tmp); + 3562 990 : if (f == 0) { + 3563 : /* LCOV_EXCL_START */ + 3564 : log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno)); + 3565 : exit(EXIT_FAILURE); + 3566 : /* LCOV_EXCL_STOP */ + 3567 : } + 3568 : + 3569 : /* allocate the thread context */ + 3570 990 : context = malloc_nofail(sizeof(struct state_verify_thread_context)); + 3571 990 : content->context = context; + 3572 : + 3573 : /* initialize */ + 3574 990 : context->state = state; + 3575 990 : context->content = content; + 3576 990 : context->crc = crc; + 3577 990 : context->f = f; + 3578 : + 3579 : #if HAVE_MT_VERIFY + 3580 990 : if (pthread_create(&context->thread, 0, state_verify_thread, context) != 0) { + 3581 : /* LCOV_EXCL_START */ + 3582 : log_fatal("Failed to create thread.\n"); + 3583 : exit(EXIT_FAILURE); + 3584 : /* LCOV_EXCL_STOP */ + 3585 : } + 3586 : #else + 3587 : context->retval = state_verify_thread(context); + 3588 : #endif + 3589 : + 3590 990 : i = i->next; + 3591 : } + 3592 : + 3593 : /* join all thread */ + 3594 145 : fail = 0; + 3595 145 : i = tommy_list_head(&state->contentlist); + 3596 1280 : while (i) { + 3597 990 : struct snapraid_content* content = i->data; + 3598 990 : struct state_verify_thread_context* context = content->context; + 3599 : void* retval; + 3600 : + 3601 : #if HAVE_MT_VERIFY + 3602 990 : if (pthread_join(context->thread, &retval) != 0) { + 3603 : /* LCOV_EXCL_START */ + 3604 : log_fatal("Failed to join thread.\n"); + 3605 : exit(EXIT_FAILURE); + 3606 : /* LCOV_EXCL_STOP */ + 3607 : } + 3608 : #else + 3609 : retval = context->retval; + 3610 : #endif + 3611 990 : if (retval) { + 3612 : /* LCOV_EXCL_START */ + 3613 : fail = 1; + 3614 : /* LCOV_EXCL_STOP */ + 3615 : } else { + 3616 990 : STREAM* f = context->f; + 3617 : + 3618 990 : if (sclose(f) != 0) { + 3619 : /* LCOV_EXCL_START */ + 3620 : log_fatal("Error closing the content file. %s.\n", strerror(errno)); + 3621 : exit(EXIT_FAILURE); + 3622 : /* LCOV_EXCL_STOP */ + 3623 : } + 3624 : } + 3625 : + 3626 990 : free(context); + 3627 : + 3628 990 : i = i->next; + 3629 : } + 3630 : + 3631 : /* abort on failure */ + 3632 145 : if (fail) { + 3633 : /* LCOV_EXCL_START */ + 3634 : exit(EXIT_FAILURE); + 3635 : /* LCOV_EXCL_STOP */ + 3636 : } + 3637 145 : } 3638 : - 3639 206 : now = time(0); - 3640 : - 3641 206 : state->progress_whole_start = now; + 3639 145 : static void state_rename_content(struct snapraid_state* state) + 3640 : { + 3641 : tommy_node* i; 3642 : - 3643 206 : state->progress_tick = 0; - 3644 206 : state->progress_ptr = 0; - 3645 206 : state->progress_wasted = 0; - 3646 : - 3647 : /* stop if requested */ - 3648 206 : if (global_interrupt) { - 3649 : /* LCOV_EXCL_START */ - 3650 : if (!state->opt.gui) { - 3651 : msg_status("Not starting for interruption\n"); - 3652 : } - 3653 : log_tag("sigint:0: SIGINT received\n"); - 3654 : log_flush(); - 3655 : return 0; - 3656 : /* LCOV_EXCL_STOP */ - 3657 : } - 3658 : - 3659 206 : return 1; - 3660 : } - 3661 : - 3662 206 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize) - 3663 : { - 3664 206 : if (state->opt.gui) { - 3665 5 : log_tag("run:end\n"); - 3666 5 : log_flush(); - 3667 201 : } else if (countmax == 0) { - 3668 15 : msg_status("Nothing to do\n"); - 3669 : } else { - 3670 : time_t now; - 3671 : time_t elapsed; - 3672 : - 3673 186 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; - 3674 : - 3675 186 : now = time(0); - 3676 : - 3677 186 : elapsed = now - state->progress_whole_start - state->progress_wasted; - 3678 : - 3679 186 : msg_bar("%u%% completed, %u MB processed", countpos * 100 / countmax, countsize_MB); - 3680 186 : if (elapsed >= 60) - 3681 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); - 3682 186 : msg_bar("\n"); - 3683 186 : msg_flush(); - 3684 : } - 3685 206 : } + 3643 145 : i = tommy_list_head(&state->contentlist); + 3644 1280 : while (i) { + 3645 990 : struct snapraid_content* content = i->data; + 3646 : char tmp[PATH_MAX]; + 3647 : + 3648 : /* now renames the just written copy with the correct name */ + 3649 990 : pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + 3650 990 : if (rename(tmp, content->content) != 0) { + 3651 : /* LCOV_EXCL_START */ + 3652 : log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); + 3653 : exit(EXIT_FAILURE); + 3654 : /* LCOV_EXCL_STOP */ + 3655 : } + 3656 : + 3657 990 : i = i->next; + 3658 : } + 3659 145 : } + 3660 : + 3661 145 : void state_write(struct snapraid_state* state) + 3662 : { + 3663 : uint32_t crc; + 3664 : + 3665 : /* write all the content files */ + 3666 145 : state_write_content(state, &crc); + 3667 : + 3668 : /* verify the just written files */ + 3669 145 : state_verify_content(state, crc); + 3670 : + 3671 : /* rename the new files, over the old ones */ + 3672 145 : state_rename_content(state); + 3673 : + 3674 145 : state->need_write = 0; /* no write needed anymore */ + 3675 145 : state->checked_read = 0; /* what we wrote is not checked in read */ + 3676 145 : } + 3677 : + 3678 122 : void state_skip(struct snapraid_state* state) + 3679 : { + 3680 : tommy_node* i; + 3681 : + 3682 : /* for each disk */ + 3683 850 : for (i = state->disklist; i != 0; i = i->next) { + 3684 : tommy_node* j; + 3685 728 : struct snapraid_disk* disk = i->data; 3686 : - 3687 1 : void state_progress_stop(struct snapraid_state* state) - 3688 : { - 3689 : time_t now; - 3690 : - 3691 1 : now = time(0); - 3692 : - 3693 1 : if (!state->opt.gui) { - 3694 1 : msg_bar("\n"); - 3695 1 : msg_flush(); - 3696 : } - 3697 : - 3698 1 : state->progress_interruption = now; - 3699 1 : } - 3700 : - 3701 1 : void state_progress_restart(struct snapraid_state* state) - 3702 : { - 3703 : time_t now; - 3704 : - 3705 1 : now = time(0); - 3706 : - 3707 : /* reset the progress counter */ - 3708 1 : state->progress_tick = 0; - 3709 1 : state->progress_ptr = 0; - 3710 : - 3711 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ - 3712 1 : state->progress_wasted += now - state->progress_interruption; - 3713 1 : } + 3687 728 : if (!disk->skip_access) + 3688 727 : continue; + 3689 : + 3690 : /* for each file */ + 3691 1884 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + 3692 1883 : struct snapraid_file* file = j->data; + 3693 1883 : file_flag_set(file, FILE_IS_EXCLUDED); + 3694 : } + 3695 : + 3696 : /* for each link */ + 3697 57 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + 3698 56 : struct snapraid_link* slink = j->data; + 3699 56 : link_flag_set(slink, FILE_IS_EXCLUDED); + 3700 : } + 3701 : + 3702 : /* for each dir */ + 3703 1 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + 3704 0 : struct snapraid_dir* dir = j->data; + 3705 0 : dir_flag_set(dir, FILE_IS_EXCLUDED); + 3706 : } + 3707 : } + 3708 122 : } + 3709 : + 3710 122 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) + 3711 : { + 3712 : tommy_node* i; + 3713 : unsigned l; 3714 : - 3715 : #define PROGRESS_CLEAR " " - 3716 : - 3717 1038958 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) - 3718 : { - 3719 : time_t now; - 3720 : int pred; - 3721 : - 3722 1038958 : now = time(0); - 3723 : - 3724 : /* previous position */ - 3725 1038958 : pred = state->progress_ptr + PROGRESS_MAX - 1; - 3726 1038958 : if (pred >= PROGRESS_MAX) - 3727 1038770 : pred -= PROGRESS_MAX; - 3728 : - 3729 : /* if the previous measure is different */ - 3730 1038958 : if (state->progress_tick == 0 - 3731 1038770 : || state->progress_time[pred] != now - 3732 : ) { - 3733 : uint64_t tick_total; - 3734 : uint64_t tick_cpu; - 3735 : time_t elapsed; - 3736 260 : unsigned out_perc = 0; - 3737 260 : unsigned out_speed = 0; - 3738 260 : unsigned out_cpu = 0; - 3739 260 : unsigned out_eta = 0; - 3740 : - 3741 260 : tick_total = state->tick_cpu + state->tick_io; - 3742 260 : tick_cpu = state->tick_cpu; - 3743 260 : elapsed = now - state->progress_whole_start - state->progress_wasted; - 3744 : - 3745 : /* completion percentage */ - 3746 260 : if (countmax) - 3747 260 : out_perc = countpos * 100 / countmax; - 3748 : - 3749 : /* if we have at least 5 measures */ - 3750 260 : if (state->progress_tick >= 5 - 3751 : /* or if we are running in test mode, with at least one measure */ - 3752 260 : || (state->opt.force_progress && state->progress_tick >= 1) - 3753 : ) { - 3754 : int oldest; - 3755 : int past; - 3756 : time_t delta_time; - 3757 : block_off_t delta_pos; - 3758 : data_off_t delta_size; - 3759 : uint64_t delta_tick_total; - 3760 : uint64_t delta_tick_cpu; - 3761 : - 3762 : /* number of past measures */ - 3763 72 : past = state->progress_tick; - 3764 : - 3765 : /* drop the oldest ones, to promptly */ - 3766 : /* skip the startup phase */ - 3767 72 : past -= past / 5; - 3768 : - 3769 : /* check how much we can go in the past */ - 3770 72 : if (past >= PROGRESS_MAX) { - 3771 : /* the vector is filled, so we are already in position */ - 3772 : /* to get the possible oldest one */ - 3773 0 : oldest = state->progress_ptr; - 3774 : } else { - 3775 : /* go backward the number of positions selected */ - 3776 72 : oldest = state->progress_ptr + PROGRESS_MAX - past; - 3777 72 : if (oldest >= PROGRESS_MAX) - 3778 72 : oldest -= PROGRESS_MAX; - 3779 : } + 3715 : /* if no filter, include all */ + 3716 122 : if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) + 3717 235 : return; + 3718 : + 3719 9 : msg_progress("Filtering...\n"); + 3720 : + 3721 17 : for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + 3722 8 : struct snapraid_filter* filter = i->data; + 3723 8 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : ""); + 3724 : } + 3725 12 : for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) { + 3726 3 : struct snapraid_filter* filter = i->data; + 3727 3 : msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : ""); + 3728 : } + 3729 9 : if (filter_missing) + 3730 2 : msg_verbose("\t<missing>\n"); + 3731 9 : if (filter_error) + 3732 2 : msg_verbose("\t<error>\n"); + 3733 : + 3734 : /* for each disk */ + 3735 63 : for (i = state->disklist; i != 0; i = i->next) { + 3736 : tommy_node* j; + 3737 54 : struct snapraid_disk* disk = i->data; + 3738 : + 3739 : /* if we filter for presence, we have to access the disk, so better to print something */ + 3740 54 : if (filter_missing) + 3741 12 : msg_progress("Scanning disk %s...\n", disk->name); + 3742 : + 3743 : /* for each file */ + 3744 133917 : for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + 3745 133863 : struct snapraid_file* file = j->data; + 3746 : + 3747 133863 : if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0 + 3748 80965 : || filter_path(filterlist_file, 0, disk->name, file->sub) != 0 + 3749 78124 : || filter_existence(filter_missing, disk->dir, file->sub) != 0 + 3750 38732 : || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 + 3751 : ) { + 3752 109341 : file_flag_set(file, FILE_IS_EXCLUDED); + 3753 : } + 3754 : } + 3755 : + 3756 : /* for each link */ + 3757 4414 : for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + 3758 4360 : struct snapraid_link* slink = j->data; + 3759 : + 3760 4360 : if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0 + 3761 2641 : || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0 + 3762 2536 : || filter_existence(filter_missing, disk->dir, slink->sub) != 0 + 3763 : ) { + 3764 3221 : link_flag_set(slink, FILE_IS_EXCLUDED); + 3765 : } + 3766 : } + 3767 : + 3768 : /* for each dir */ + 3769 82 : for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + 3770 28 : struct snapraid_dir* dir = j->data; + 3771 : + 3772 28 : if (filter_dir(filterlist_disk, 0, disk->name, dir->sub) != 0 + 3773 28 : || filter_dir(filterlist_file, 0, disk->name, dir->sub) != 0 + 3774 28 : || filter_existence(filter_missing, disk->dir, dir->sub) != 0 + 3775 : ) { + 3776 8 : dir_flag_set(dir, FILE_IS_EXCLUDED); + 3777 : } + 3778 : } + 3779 : } 3780 : - 3781 72 : delta_time = now - state->progress_time[oldest]; - 3782 72 : delta_pos = countpos - state->progress_pos[oldest]; - 3783 72 : delta_size = countsize - state->progress_size[oldest]; - 3784 72 : delta_tick_total = tick_total - state->progress_tick_total[oldest]; - 3785 72 : delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest]; - 3786 : - 3787 : /* estimate the speed in MiB/s */ - 3788 72 : if (delta_time != 0) - 3789 72 : out_speed = (unsigned)(delta_size / MEGA / delta_time); - 3790 : - 3791 : /* estimate the cpu usage percentage */ - 3792 72 : if (delta_tick_total != 0) - 3793 10 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total); - 3794 : - 3795 : /* estimate the remaining time in minutes */ - 3796 72 : if (delta_pos != 0) - 3797 72 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos); + 3781 : /* if we are filtering by disk */ + 3782 9 : if (!tommy_list_empty(filterlist_disk)) { + 3783 : /* for each parity disk */ + 3784 20 : for (l = 0; l < state->level; ++l) { + 3785 : /* check if the parity is excluded by name */ + 3786 16 : if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) { + 3787 : /* excluded the parity from further operation */ + 3788 11 : state->parity[l].is_excluded = 1; + 3789 : } + 3790 : } + 3791 : } else { + 3792 : /* if we are filtering by file, exclude all parity */ + 3793 5 : if (filter_missing || !tommy_list_empty(filterlist_file)) { + 3794 : /* for each parity disk */ + 3795 16 : for (l = 0; l < state->level; ++l) { + 3796 13 : state->parity[l].is_excluded = 1; + 3797 : } 3798 : } - 3799 : - 3800 260 : if (state->opt.gui) { - 3801 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed); - 3802 7 : log_flush(); - 3803 : } else { - 3804 253 : msg_bar("%u%%, %u MiB", out_perc, (unsigned)(countsize / MEGA)); - 3805 253 : if (out_speed) - 3806 63 : msg_bar(", %u MiB/s", out_speed); - 3807 253 : if (out_cpu) - 3808 10 : msg_bar(", CPU %u%%", out_cpu); - 3809 253 : if (out_eta) - 3810 0 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60); - 3811 253 : msg_bar("%s\r", PROGRESS_CLEAR); - 3812 253 : msg_flush(); - 3813 : } + 3799 : } + 3800 : } + 3801 : + 3802 214 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax) + 3803 : { + 3804 : time_t now; + 3805 : + 3806 214 : if (state->opt.gui) { + 3807 5 : log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax); + 3808 5 : log_flush(); + 3809 : } + 3810 : + 3811 214 : now = time(0); + 3812 : + 3813 214 : state->progress_whole_start = now; 3814 : - 3815 : /* store the new measure */ - 3816 260 : state->progress_time[state->progress_ptr] = now; - 3817 260 : state->progress_pos[state->progress_ptr] = countpos; - 3818 260 : state->progress_size[state->progress_ptr] = countsize; - 3819 260 : state->progress_tick_cpu[state->progress_ptr] = tick_cpu; - 3820 260 : state->progress_tick_total[state->progress_ptr] = tick_total; - 3821 : - 3822 : /* next position */ - 3823 260 : ++state->progress_ptr; - 3824 260 : if (state->progress_ptr >= PROGRESS_MAX) - 3825 0 : state->progress_ptr -= PROGRESS_MAX; - 3826 : - 3827 : /* one more measure */ - 3828 260 : ++state->progress_tick; + 3815 214 : state->progress_tick = 0; + 3816 214 : state->progress_ptr = 0; + 3817 214 : state->progress_wasted = 0; + 3818 : + 3819 : /* stop if requested */ + 3820 214 : if (global_interrupt) { + 3821 : /* LCOV_EXCL_START */ + 3822 : if (!state->opt.gui) { + 3823 : msg_status("Not starting for interruption\n"); + 3824 : } + 3825 : log_tag("sigint:0: SIGINT received\n"); + 3826 : log_flush(); + 3827 : return 0; + 3828 : /* LCOV_EXCL_STOP */ 3829 : } 3830 : - 3831 : /* stop if requested */ - 3832 1038958 : if (global_interrupt) { - 3833 : /* LCOV_EXCL_START */ - 3834 : if (!state->opt.gui) { - 3835 : log_fatal("\n"); - 3836 : log_fatal("Stopping for interruption at block %u\n", blockpos); - 3837 : } - 3838 : log_tag("sigint:%u: SIGINT received\n", blockpos); - 3839 : log_flush(); - 3840 : return 1; - 3841 : /* LCOV_EXCL_STOP */ - 3842 : } - 3843 : - 3844 1038958 : return 0; - 3845 : } + 3831 214 : return 1; + 3832 : } + 3833 : + 3834 214 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize) + 3835 : { + 3836 214 : if (state->opt.gui) { + 3837 5 : log_tag("run:end\n"); + 3838 5 : log_flush(); + 3839 209 : } else if (countmax == 0) { + 3840 18 : msg_status("Nothing to do\n"); + 3841 : } else { + 3842 : time_t now; + 3843 : time_t elapsed; + 3844 : + 3845 191 : unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; 3846 : - 3847 81 : void state_usage_print(struct snapraid_state* state) - 3848 : { - 3849 : uint64_t tick_total; - 3850 : uint64_t tick_max; - 3851 : tommy_node* i; - 3852 : unsigned l; - 3853 : - 3854 81 : tick_max = 0; - 3855 81 : tick_total = 0; - 3856 565 : for (i = state->disklist; i != 0; i = i->next) { - 3857 484 : struct snapraid_disk* disk = i->data; - 3858 484 : tick_total += disk->tick; - 3859 484 : if (disk->tick > tick_max) - 3860 99 : tick_max = disk->tick; - 3861 : } - 3862 552 : for (l = 0; l < state->level; ++l) { - 3863 471 : tick_total += state->parity[l].tick; - 3864 471 : if (state->parity[l].tick > tick_max) - 3865 17 : tick_max = state->parity[l].tick; - 3866 : } - 3867 : - 3868 81 : if (!tick_total) - 3869 96 : return; - 3870 : - 3871 66 : if (msg_level >= MSG_PROGRESS) { - 3872 : /* here we don't use msg_progress() because it doesn't allow partial output */ - 3873 1 : printf("Time for disk:"); - 3874 7 : for (i = state->disklist; i != 0; i = i->next) { - 3875 6 : struct snapraid_disk* disk = i->data; - 3876 6 : if (disk->tick == tick_max) - 3877 1 : printf(" %s:", disk->name); - 3878 : else - 3879 5 : printf(" "); - 3880 6 : printf("%" PRIu64 "%%", disk->tick * 100U / tick_total); - 3881 : } - 3882 1 : printf("\n"); - 3883 : - 3884 1 : printf("Time for parity:"); - 3885 7 : for (l = 0; l < state->level; ++l) { - 3886 6 : if (state->parity[l].tick == tick_max) - 3887 0 : printf(" %s:", lev_config_name(l)); - 3888 : else - 3889 6 : printf(" "); - 3890 6 : printf("%" PRIu64 "%%", state->parity[l].tick * 100U / tick_total); - 3891 : } - 3892 1 : printf("\n"); - 3893 : } - 3894 : } + 3847 191 : now = time(0); + 3848 : + 3849 191 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 3850 : + 3851 191 : msg_bar("%u%% completed, %u MB processed", countpos * 100 / countmax, countsize_MB); + 3852 191 : if (elapsed >= 60) + 3853 0 : msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); + 3854 191 : msg_bar("\n"); + 3855 191 : msg_flush(); + 3856 : } + 3857 214 : } + 3858 : + 3859 1 : void state_progress_stop(struct snapraid_state* state) + 3860 : { + 3861 : time_t now; + 3862 : + 3863 1 : now = time(0); + 3864 : + 3865 1 : if (!state->opt.gui) { + 3866 1 : msg_bar("\n"); + 3867 1 : msg_flush(); + 3868 : } + 3869 : + 3870 1 : state->progress_interruption = now; + 3871 1 : } + 3872 : + 3873 1 : void state_progress_restart(struct snapraid_state* state) + 3874 : { + 3875 : time_t now; + 3876 : + 3877 1 : now = time(0); + 3878 : + 3879 : /* reset the progress counter */ + 3880 1 : state->progress_tick = 0; + 3881 1 : state->progress_ptr = 0; + 3882 : + 3883 1 : if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ + 3884 1 : state->progress_wasted += now - state->progress_interruption; + 3885 1 : } + 3886 : + 3887 : #define PROGRESS_CLEAR " " + 3888 : + 3889 1048979 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) + 3890 : { + 3891 : time_t now; + 3892 : int pred; + 3893 : + 3894 1048979 : now = time(0); 3895 : - 3896 447 : void state_fscheck(struct snapraid_state* state, const char* ope) - 3897 : { - 3898 : tommy_node* i; - 3899 : - 3900 : /* check the filesystem on all disks */ - 3901 3123 : for (i = state->disklist; i != 0; i = i->next) { - 3902 2676 : struct snapraid_disk* disk = i->data; - 3903 : - 3904 2676 : if (fs_check(disk) != 0) { - 3905 : /* LCOV_EXCL_START */ - 3906 : log_fatal("Internal inconsistency in filesystem for disk '%s' %s\n", disk->name, ope); - 3907 : exit(EXIT_FAILURE); - 3908 : /* LCOV_EXCL_STOP */ - 3909 : } - 3910 : } - 3911 447 : } + 3896 : /* previous position */ + 3897 1048979 : pred = state->progress_ptr + PROGRESS_MAX - 1; + 3898 1048979 : if (pred >= PROGRESS_MAX) + 3899 1048786 : pred -= PROGRESS_MAX; + 3900 : + 3901 : /* if the previous measure is different */ + 3902 1048979 : if (state->progress_tick == 0 + 3903 1048786 : || state->progress_time[pred] != now + 3904 : ) { + 3905 : uint64_t tick_total; + 3906 : uint64_t tick_cpu; + 3907 : time_t elapsed; + 3908 257 : unsigned out_perc = 0; + 3909 257 : unsigned out_speed = 0; + 3910 257 : unsigned out_cpu = 0; + 3911 257 : unsigned out_eta = 0; 3912 : - 3913 1 : void generate_configuration(const char* path) - 3914 : { - 3915 : struct snapraid_state state; - 3916 : struct snapraid_content* content; - 3917 : unsigned i; - 3918 : tommy_node* j; - 3919 : - 3920 1 : state_init(&state); - 3921 : - 3922 : /* mark that we are without a configuration file */ - 3923 1 : state.no_conf = 1; - 3924 : - 3925 : /* create the dummy content entry */ - 3926 1 : content = content_alloc(path, -1); - 3927 : - 3928 : /* adds the content entry */ - 3929 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content); - 3930 : - 3931 : /* read the content file */ - 3932 1 : state_read(&state); + 3913 257 : tick_total = state->tick_cpu + state->tick_io; + 3914 257 : tick_cpu = state->tick_cpu; + 3915 257 : elapsed = now - state->progress_whole_start - state->progress_wasted; + 3916 : + 3917 : /* completion percentage */ + 3918 257 : if (countmax) + 3919 257 : out_perc = countpos * 100 / countmax; + 3920 : + 3921 : /* if we have at least 5 measures */ + 3922 257 : if (state->progress_tick >= 5 + 3923 : /* or if we are running in test mode, with at least one measure */ + 3924 257 : || (state->opt.force_progress && state->progress_tick >= 1) + 3925 : ) { + 3926 : int oldest; + 3927 : int past; + 3928 : time_t delta_time; + 3929 : block_off_t delta_pos; + 3930 : data_off_t delta_size; + 3931 : uint64_t delta_tick_total; + 3932 : uint64_t delta_tick_cpu; 3933 : - 3934 : /* output a dummy configuration file */ - 3935 1 : printf("# Configuration file generated from %s\n", path); - 3936 1 : printf("\n"); - 3937 1 : printf("# Use this blocksize\n"); - 3938 1 : printf("blocksize %u\n", state.block_size / 1024); - 3939 1 : printf("\n"); - 3940 7 : for (i = 0; i < state.level; ++i) { - 3941 6 : printf("# Set the correct path for the %s file\n", lev_name(i)); - 3942 6 : if (state.parity[i].uuid[0]) - 3943 6 : printf("# The file was in the disk with id '%s'\n", state.parity[i].uuid); - 3944 6 : printf("%s ENTER_HERE_THE_PARITY_FILE\n", lev_config_name(i)); - 3945 6 : printf("\n"); - 3946 : } - 3947 1 : printf("# Add any other content file\n"); - 3948 1 : printf("content %s\n", path); - 3949 1 : printf("\n"); - 3950 7 : for (j = state.maplist; j; j = j->next) { - 3951 6 : struct snapraid_map* map = j->data; - 3952 : struct snapraid_disk* disk; - 3953 6 : printf("# Set the correct dir for disk '%s'\n", map->name); - 3954 6 : if (map->uuid[0]) - 3955 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid); - 3956 6 : disk = find_disk(&state, map->name); - 3957 6 : if (disk && disk->filelist) { - 3958 6 : struct snapraid_file* file = disk->filelist->data; - 3959 6 : if (file) { - 3960 6 : printf("# and containing: %s\n", file->sub); - 3961 : } - 3962 : } - 3963 6 : printf("disk %s ENTER_HERE_THE_DIR\n", map->name); - 3964 6 : printf("\n"); - 3965 : } + 3934 : /* number of past measures */ + 3935 63 : past = state->progress_tick; + 3936 : + 3937 : /* drop the oldest ones, to promptly */ + 3938 : /* skip the startup phase */ + 3939 63 : past -= past / 5; + 3940 : + 3941 : /* check how much we can go in the past */ + 3942 63 : if (past >= PROGRESS_MAX) { + 3943 : /* the vector is filled, so we are already in position */ + 3944 : /* to get the possible oldest one */ + 3945 0 : oldest = state->progress_ptr; + 3946 : } else { + 3947 : /* go backward the number of positions selected */ + 3948 63 : oldest = state->progress_ptr + PROGRESS_MAX - past; + 3949 63 : if (oldest >= PROGRESS_MAX) + 3950 63 : oldest -= PROGRESS_MAX; + 3951 : } + 3952 : + 3953 63 : delta_time = now - state->progress_time[oldest]; + 3954 63 : delta_pos = countpos - state->progress_pos[oldest]; + 3955 63 : delta_size = countsize - state->progress_size[oldest]; + 3956 63 : delta_tick_total = tick_total - state->progress_tick_total[oldest]; + 3957 63 : delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest]; + 3958 : + 3959 : /* estimate the speed in MiB/s */ + 3960 63 : if (delta_time != 0) + 3961 63 : out_speed = (unsigned)(delta_size / MEGA / delta_time); + 3962 : + 3963 : /* estimate the cpu usage percentage */ + 3964 63 : if (delta_tick_total != 0) + 3965 9 : out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total); 3966 : - 3967 1 : state_done(&state); - 3968 1 : } - 3969 : + 3967 : /* estimate the remaining time in minutes */ + 3968 63 : if (delta_pos != 0) + 3969 63 : out_eta = (countmax - countpos) * delta_time / (60 * delta_pos); + 3970 : } + 3971 : + 3972 257 : if (state->opt.gui) { + 3973 7 : log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed); + 3974 7 : log_flush(); + 3975 : } else { + 3976 250 : msg_bar("%u%%, %u MiB", out_perc, (unsigned)(countsize / MEGA)); + 3977 250 : if (out_speed) + 3978 49 : msg_bar(", %u MiB/s", out_speed); + 3979 250 : if (out_cpu) + 3980 9 : msg_bar(", CPU %u%%", out_cpu); + 3981 250 : if (out_eta) + 3982 4 : msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60); + 3983 250 : msg_bar("%s\r", PROGRESS_CLEAR); + 3984 250 : msg_flush(); + 3985 : } + 3986 : + 3987 : /* store the new measure */ + 3988 257 : state->progress_time[state->progress_ptr] = now; + 3989 257 : state->progress_pos[state->progress_ptr] = countpos; + 3990 257 : state->progress_size[state->progress_ptr] = countsize; + 3991 257 : state->progress_tick_cpu[state->progress_ptr] = tick_cpu; + 3992 257 : state->progress_tick_total[state->progress_ptr] = tick_total; + 3993 : + 3994 : /* next position */ + 3995 257 : ++state->progress_ptr; + 3996 257 : if (state->progress_ptr >= PROGRESS_MAX) + 3997 0 : state->progress_ptr -= PROGRESS_MAX; + 3998 : + 3999 : /* one more measure */ + 4000 257 : ++state->progress_tick; + 4001 : } + 4002 : + 4003 : /* stop if requested */ + 4004 1048979 : if (global_interrupt) { + 4005 : /* LCOV_EXCL_START */ + 4006 : if (!state->opt.gui) { + 4007 : log_fatal("\n"); + 4008 : log_fatal("Stopping for interruption at block %u\n", blockpos); + 4009 : } + 4010 : log_tag("sigint:%u: SIGINT received\n", blockpos); + 4011 : log_flush(); + 4012 : return 1; + 4013 : /* LCOV_EXCL_STOP */ + 4014 : } + 4015 : + 4016 1048979 : return 0; + 4017 : } + 4018 : + 4019 89 : void state_usage_print(struct snapraid_state* state) + 4020 : { + 4021 : uint64_t tick_total; + 4022 : uint64_t tick_max; + 4023 : tommy_node* i; + 4024 : unsigned l; + 4025 : + 4026 89 : tick_max = 0; + 4027 89 : tick_total = 0; + 4028 621 : for (i = state->disklist; i != 0; i = i->next) { + 4029 532 : struct snapraid_disk* disk = i->data; + 4030 532 : tick_total += disk->tick; + 4031 532 : if (disk->tick > tick_max) + 4032 100 : tick_max = disk->tick; + 4033 : } + 4034 608 : for (l = 0; l < state->level; ++l) { + 4035 519 : tick_total += state->parity[l].tick; + 4036 519 : if (state->parity[l].tick > tick_max) + 4037 19 : tick_max = state->parity[l].tick; + 4038 : } + 4039 : + 4040 89 : if (!tick_total) + 4041 107 : return; + 4042 : + 4043 71 : if (msg_level >= MSG_PROGRESS) { + 4044 : /* here we don't use msg_progress() because it doesn't allow partial output */ + 4045 1 : printf("Time for disk:"); + 4046 7 : for (i = state->disklist; i != 0; i = i->next) { + 4047 6 : struct snapraid_disk* disk = i->data; + 4048 6 : if (disk->tick == tick_max) + 4049 1 : printf(" %s:", disk->name); + 4050 : else + 4051 5 : printf(" "); + 4052 6 : printf("%" PRIu64 "%%", disk->tick * 100U / tick_total); + 4053 : } + 4054 1 : printf("\n"); + 4055 : + 4056 1 : printf("Time for parity:"); + 4057 7 : for (l = 0; l < state->level; ++l) { + 4058 6 : if (state->parity[l].tick == tick_max) + 4059 0 : printf(" %s:", lev_config_name(l)); + 4060 : else + 4061 6 : printf(" "); + 4062 6 : printf("%" PRIu64 "%%", state->parity[l].tick * 100U / tick_total); + 4063 : } + 4064 1 : printf("\n"); + 4065 : } + 4066 : } + 4067 : + 4068 474 : void state_fscheck(struct snapraid_state* state, const char* ope) + 4069 : { + 4070 : tommy_node* i; + 4071 : + 4072 : /* check the file-system on all disks */ + 4073 3312 : for (i = state->disklist; i != 0; i = i->next) { + 4074 2838 : struct snapraid_disk* disk = i->data; + 4075 : + 4076 2838 : if (fs_check(disk) != 0) { + 4077 : /* LCOV_EXCL_START */ + 4078 : log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope); + 4079 : os_abort(); + 4080 : /* LCOV_EXCL_STOP */ + 4081 : } + 4082 : } + 4083 474 : } + 4084 : + 4085 1 : void generate_configuration(const char* path) + 4086 : { + 4087 : struct snapraid_state state; + 4088 : struct snapraid_content* content; + 4089 : unsigned i; + 4090 : tommy_node* j; + 4091 : + 4092 1 : state_init(&state); + 4093 : + 4094 : /* mark that we are without a configuration file */ + 4095 1 : state.no_conf = 1; + 4096 : + 4097 : /* create the dummy content entry */ + 4098 1 : content = content_alloc(path, -1); + 4099 : + 4100 : /* adds the content entry */ + 4101 1 : tommy_list_insert_tail(&state.contentlist, &content->node, content); + 4102 : + 4103 : /* read the content file */ + 4104 1 : state_read(&state); + 4105 : + 4106 : /* output a dummy configuration file */ + 4107 1 : printf("# Configuration file generated from %s\n", path); + 4108 1 : printf("\n"); + 4109 1 : printf("# Use this blocksize\n"); + 4110 1 : printf("blocksize %u\n", state.block_size / 1024); + 4111 1 : printf("\n"); + 4112 7 : for (i = 0; i < state.level; ++i) { + 4113 6 : printf("# Set the correct path for the %s file\n", lev_name(i)); + 4114 6 : if (state.parity[i].uuid[0]) + 4115 6 : printf("# The file was in the disk with id '%s'\n", state.parity[i].uuid); + 4116 6 : printf("%s ENTER_HERE_THE_PARITY_FILE\n", lev_config_name(i)); + 4117 6 : printf("\n"); + 4118 : } + 4119 1 : printf("# Add any other content file\n"); + 4120 1 : printf("content %s\n", path); + 4121 1 : printf("\n"); + 4122 7 : for (j = state.maplist; j; j = j->next) { + 4123 6 : struct snapraid_map* map = j->data; + 4124 : struct snapraid_disk* disk; + 4125 6 : printf("# Set the correct dir for disk '%s'\n", map->name); + 4126 6 : if (map->uuid[0]) + 4127 6 : printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid); + 4128 6 : disk = find_disk_by_name(&state, map->name); + 4129 6 : if (disk && disk->filelist) { + 4130 6 : struct snapraid_file* file = disk->filelist->data; + 4131 6 : if (file) { + 4132 6 : printf("# and containing: %s\n", file->sub); + 4133 : } + 4134 : } + 4135 6 : printf("disk %s ENTER_HERE_THE_DIR\n", map->name); + 4136 6 : printf("\n"); + 4137 : } + 4138 : + 4139 1 : state_done(&state); + 4140 1 : } + 4141 : diff --git a/cov/cmdline/state.h.func-sort-c.html b/cov/cmdline/state.h.func-sort-c.html index 05fa4cc0..220cc8c0 100644 --- a/cov/cmdline/state.h.func-sort-c.html +++ b/cov/cmdline/state.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -60,20 +60,20 @@ Hit count Sort by hit count - state_usage_cpu - 772778 + state_usage_cpu + 833206 - state_usage_parity - 653350 + state_usage_parity + 706913 - state_usage_disk - 622545 + state_usage_disk + 673880 - state_usage_waste - 89 + state_usage_waste + 97
diff --git a/cov/cmdline/state.h.func.html b/cov/cmdline/state.h.func.html index 37c5849d..2c89482c 100644 --- a/cov/cmdline/state.h.func.html +++ b/cov/cmdline/state.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -60,20 +60,20 @@ Hit count Sort by hit count - state_usage_cpu - 772778 + state_usage_cpu + 833206 - state_usage_disk - 622545 + state_usage_disk + 673880 - state_usage_parity - 653350 + state_usage_parity + 706913 - state_usage_waste - 89 + state_usage_waste + 97
diff --git a/cov/cmdline/state.h.gcov.html b/cov/cmdline/state.h.gcov.html index 0cdf4d7f..6a6fac5f 100644 --- a/cov/cmdline/state.h.gcov.html +++ b/cov/cmdline/state.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -136,11 +136,11 @@ 74 : int syncedonly; /**< In fix, fixes only files that are synced. */ 75 : int prehash; /**< Enables the prehash mode for sync. */ 76 : unsigned io_error_limit; /**< Max number of input/output errors before aborting. */ - 77 : int force_zero; /**< Forced dangerous operations of synching files now with zero size. */ - 78 : int force_empty; /**< Forced dangerous operations of synching disks now empty. */ - 79 : int force_uuid; /**< Forced dangerous operations of synching disks with uuid changed. */ + 77 : int force_zero; /**< Forced dangerous operations of syncing files now with zero size. */ + 78 : int force_empty; /**< Forced dangerous operations of syncing disks now empty. */ + 79 : int force_uuid; /**< Forced dangerous operations of syncing disks with uuid changed. */ 80 : int force_device; /**< Forced dangerous operations of using disks with save device id. */ - 81 : int force_nocopy; /**< Force dangerous operations of synching files without using copy detection. */ + 81 : int force_nocopy; /**< Force dangerous operations of syncing files without using copy detection. */ 82 : int force_full; /**< Force a full sync when using an old content file. */ 83 : int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */ 84 : int expect_recoverable; /**< Expect presence of recoverable error in checking. */ @@ -165,299 +165,303 @@ 103 : int force_progress; /**< Force the use of the progress status. */ 104 : unsigned force_autosave_at; /**< Force autosave at the specified block. */ 105 : int fake_device; /**< Fake device data. */ - 106 : int expected_missing; /**< If missing files are expected and should not be reported. */ - 107 : }; - 108 : - 109 : /** - 110 : * Number of measures of the operation progress. - 111 : */ - 112 : #define PROGRESS_MAX 100 - 113 : - 114 : struct snapraid_state { - 115 : struct snapraid_option opt; /**< Setup options. */ - 116 : int filter_hidden; /**< Filter out hidden files. */ - 117 : uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */ - 118 : int need_write; /**< If the state is changed. */ - 119 : int checked_read; /**< If the state was read and checked. */ - 120 : uint32_t block_size; /**< Block size in bytes. */ - 121 : unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */ - 122 : int file_mode; /**< File access mode. Combination of MODE_* flags. */ - 123 : struct snapraid_parity parity[LEV_MAX]; /**< Parity vector. */ - 124 : char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */ - 125 : char pool[PATH_MAX]; /**< Path of the pool tree. */ - 126 : uint64_t pool_device; /**< Device identifier of the pool. */ - 127 : unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */ - 128 : unsigned char prevhashseed[HASH_SIZE]; /**< Previous hash seed. In case of rehash. */ - 129 : char lockfile[PATH_MAX]; /**< Path of the lock file to use. */ - 130 : unsigned level; /**< Number of parity levels. 1 for PAR1, 2 for PAR2. */ - 131 : unsigned hash; /**< Hash kind used. */ - 132 : unsigned prevhash; /**< Previous hash kind used. In case of rehash. */ - 133 : unsigned besthash; /**< Best hash suggested. */ - 134 : const char* command; /**< Command running. */ - 135 : tommy_list contentlist; /**< List of content files. */ - 136 : tommy_list disklist; /**< List of all the disks. */ - 137 : tommy_list maplist; /**< List of all the disk mappings. */ - 138 : tommy_list filterlist; /**< List of inclusion/exclusion. */ - 139 : tommy_list importlist; /**< List of import file. */ - 140 : tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */ - 141 : tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */ - 142 : tommy_hashdyn searchset; /**< Hashtable by timestamp of all the search files. */ - 143 : tommy_arrayblkof infoarr; /**< Block information array. */ - 144 : - 145 : /** - 146 : * Cumulative time used for computations. - 147 : */ - 148 : uint64_t tick_cpu; - 149 : - 150 : /** - 151 : * Cumulative time used for all io operations of disks. - 152 : */ - 153 : uint64_t tick_io; - 154 : - 155 : /** - 156 : * Last time used for time measure. - 157 : */ - 158 : uint64_t tick_last; - 159 : - 160 : int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */ - 161 : - 162 : time_t progress_whole_start; /**< Initial start of the whole process. */ - 163 : time_t progress_interruption; /**< Time of the start of the progress interruption. */ - 164 : time_t progress_wasted; /**< Time wasted in interruptions. */ + 106 : int no_warnings; /**< Remove some warning messages. */ + 107 : int expected_missing; /**< If missing files are expected and should not be reported. */ + 108 : int fake_uuid; /**< Set fakes UUID for testing. */ + 109 : int match_first_uuid; /**< Force the matching of the first UUID. */ + 110 : int force_parity_update; /**< Force parity update even if data is not changed. */ + 111 : }; + 112 : + 113 : /** + 114 : * Number of measures of the operation progress. + 115 : */ + 116 : #define PROGRESS_MAX 100 + 117 : + 118 : struct snapraid_state { + 119 : struct snapraid_option opt; /**< Setup options. */ + 120 : int filter_hidden; /**< Filter out hidden files. */ + 121 : uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */ + 122 : int need_write; /**< If the state is changed. */ + 123 : int checked_read; /**< If the state was read and checked. */ + 124 : uint32_t block_size; /**< Block size in bytes. */ + 125 : unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */ + 126 : int file_mode; /**< File access mode. Combination of MODE_* flags. */ + 127 : struct snapraid_parity parity[LEV_MAX]; /**< Parity vector. */ + 128 : char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */ + 129 : char pool[PATH_MAX]; /**< Path of the pool tree. */ + 130 : uint64_t pool_device; /**< Device identifier of the pool. */ + 131 : unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */ + 132 : unsigned char prevhashseed[HASH_SIZE]; /**< Previous hash seed. In case of rehash. */ + 133 : char lockfile[PATH_MAX]; /**< Path of the lock file to use. */ + 134 : unsigned level; /**< Number of parity levels. 1 for PAR1, 2 for PAR2. */ + 135 : unsigned hash; /**< Hash kind used. */ + 136 : unsigned prevhash; /**< Previous hash kind used. In case of rehash. */ + 137 : unsigned besthash; /**< Best hash suggested. */ + 138 : const char* command; /**< Command running. */ + 139 : tommy_list contentlist; /**< List of content files. */ + 140 : tommy_list disklist; /**< List of all the disks. */ + 141 : tommy_list maplist; /**< List of all the disk mappings. */ + 142 : tommy_list filterlist; /**< List of inclusion/exclusion. */ + 143 : tommy_list importlist; /**< List of import file. */ + 144 : tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */ + 145 : tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */ + 146 : tommy_hashdyn searchset; /**< Hashtable by timestamp of all the search files. */ + 147 : tommy_arrayblkof infoarr; /**< Block information array. */ + 148 : + 149 : /** + 150 : * Cumulative time used for computations. + 151 : */ + 152 : uint64_t tick_cpu; + 153 : + 154 : /** + 155 : * Cumulative time used for all io operations of disks. + 156 : */ + 157 : uint64_t tick_io; + 158 : + 159 : /** + 160 : * Last time used for time measure. + 161 : */ + 162 : uint64_t tick_last; + 163 : + 164 : int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */ 165 : - 166 : time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */ - 167 : block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */ - 168 : data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */ - 169 : uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */ - 170 : uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */ - 171 : - 172 : int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */ - 173 : int progress_tick; /**< Number of measures done. */ - 174 : - 175 : int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */ - 176 : }; - 177 : - 178 : /** - 179 : * Initialize the state. - 180 : */ - 181 : void state_init(struct snapraid_state* state); - 182 : - 183 : /** - 184 : * Deinitialize the state. - 185 : */ - 186 : void state_done(struct snapraid_state* state); - 187 : - 188 : /** - 189 : * Read the configuration file. - 190 : */ - 191 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk); - 192 : - 193 : /** - 194 : * Read the state. - 195 : */ - 196 : void state_read(struct snapraid_state* state); - 197 : - 198 : /** - 199 : * Write the new state. - 200 : */ - 201 : void state_write(struct snapraid_state* state); - 202 : - 203 : /** - 204 : * Diff all the disks. - 205 : */ - 206 : int state_diff(struct snapraid_state* state); - 207 : - 208 : /** - 209 : * Scan all the disks to update the state. - 210 : */ - 211 : void state_scan(struct snapraid_state* state); - 212 : - 213 : /** - 214 : * Set the nanosecond timestamp of all files that have a zero value. - 215 : */ - 216 : void state_nano(struct snapraid_state* state); - 217 : - 218 : /** - 219 : * Devices operations. - 220 : */ - 221 : void state_device(struct snapraid_state* state, int operation); - 222 : - 223 : /** - 224 : * Sync the parity data. - 225 : */ - 226 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); - 227 : - 228 : /** - 229 : * Check (and fixes) all the files and parity data. - 230 : * \param fix If we have to fix, after checking. - 231 : */ - 232 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount); - 233 : - 234 : /** - 235 : * Dry the files. - 236 : */ - 237 : void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); - 238 : - 239 : /** - 240 : * Rehash the files. - 241 : */ - 242 : void state_rehash(struct snapraid_state* state); - 243 : - 244 : /** - 245 : * Scrub levels. - 246 : */ - 247 : #define SCRUB_AUTO -1 /**< Automatic selection. */ - 248 : #define SCRUB_BAD -2 /**< Scrub only the bad blocks. */ - 249 : #define SCRUB_NEW -3 /**< Scub the new blocks. */ - 250 : #define SCRUB_FULL -4 /**< Scrub everything. */ - 251 : #define SCRUB_EVEN -5 /**< Even blocks. */ - 252 : - 253 : /** - 254 : * Scrub the files. - 255 : */ - 256 : int state_scrub(struct snapraid_state* state, int plan, int olderthan); - 257 : - 258 : /** - 259 : * Print the status. - 260 : */ - 261 : int state_status(struct snapraid_state* state); - 262 : - 263 : /** - 264 : * Find duplicates. - 265 : */ - 266 : void state_dup(struct snapraid_state* state); - 267 : - 268 : /** - 269 : * List content. - 270 : */ - 271 : void state_list(struct snapraid_state* state); - 272 : - 273 : /** - 274 : * Create pool tree. - 275 : */ - 276 : void state_pool(struct snapraid_state* state); - 277 : - 278 : /** - 279 : * Refresh the free space info. - 280 : * - 281 : * Note that it requires disks access. - 282 : */ - 283 : void state_refresh(struct snapraid_state* state); - 284 : - 285 : /** - 286 : * Skip files, symlinks and dirs. - 287 : * Apply any skip access disk. - 288 : */ - 289 : void state_skip(struct snapraid_state* state); - 290 : - 291 : /** - 292 : * Filter files, symlinks and dirs. - 293 : * Apply an additional filter to the list currently loaded. - 294 : */ - 295 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error); - 296 : - 297 : /** - 298 : * Begin the progress visualization. - 299 : */ - 300 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax); - 301 : - 302 : /** - 303 : * End the progress visualization. - 304 : */ - 305 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize); - 306 : - 307 : /** - 308 : * Write the progress. - 309 : */ - 310 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize); - 311 : - 312 : /** - 313 : * Stop temporarely the progress. - 314 : */ - 315 : void state_progress_stop(struct snapraid_state* state); - 316 : - 317 : /** - 318 : * Restart the progress. - 319 : */ - 320 : void state_progress_restart(struct snapraid_state* state); - 321 : - 322 : /** - 323 : * Set the usage time as wasted one not counted. - 324 : */ - 325 89 : static inline void state_usage_waste(struct snapraid_state* state) - 326 : { - 327 89 : uint64_t now = tick(); - 328 : - 329 89 : state->tick_last = now; - 330 89 : } - 331 : - 332 : /** - 333 : * Set the usage time for CPU. - 334 : */ - 335 772778 : static inline void state_usage_cpu(struct snapraid_state* state) - 336 : { - 337 772778 : uint64_t now = tick(); - 338 772778 : uint64_t delta = now - state->tick_last; - 339 : - 340 : /* increment the time spent in computations */ - 341 772778 : state->tick_cpu += delta; - 342 : - 343 772778 : state->tick_last = now; - 344 772778 : } - 345 : - 346 : /** - 347 : * Set the usage time for data disk. - 348 : */ - 349 622545 : static inline void state_usage_disk(struct snapraid_state* state, struct snapraid_disk* disk) - 350 : { - 351 622545 : uint64_t now = tick(); - 352 622545 : uint64_t delta = now - state->tick_last; - 353 : - 354 : /* increment the time spent in the data disk */ - 355 622545 : disk->tick += delta; - 356 622545 : state->tick_io += delta; + 166 : time_t progress_whole_start; /**< Initial start of the whole process. */ + 167 : time_t progress_interruption; /**< Time of the start of the progress interruption. */ + 168 : time_t progress_wasted; /**< Time wasted in interruptions. */ + 169 : + 170 : time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */ + 171 : block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */ + 172 : data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */ + 173 : uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */ + 174 : uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */ + 175 : + 176 : int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */ + 177 : int progress_tick; /**< Number of measures done. */ + 178 : + 179 : int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */ + 180 : }; + 181 : + 182 : /** + 183 : * Initialize the state. + 184 : */ + 185 : void state_init(struct snapraid_state* state); + 186 : + 187 : /** + 188 : * Deinitialize the state. + 189 : */ + 190 : void state_done(struct snapraid_state* state); + 191 : + 192 : /** + 193 : * Read the configuration file. + 194 : */ + 195 : void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk); + 196 : + 197 : /** + 198 : * Read the state. + 199 : */ + 200 : void state_read(struct snapraid_state* state); + 201 : + 202 : /** + 203 : * Write the new state. + 204 : */ + 205 : void state_write(struct snapraid_state* state); + 206 : + 207 : /** + 208 : * Diff all the disks. + 209 : */ + 210 : int state_diff(struct snapraid_state* state); + 211 : + 212 : /** + 213 : * Scan all the disks to update the state. + 214 : */ + 215 : void state_scan(struct snapraid_state* state); + 216 : + 217 : /** + 218 : * Set the nanosecond timestamp of all files that have a zero value. + 219 : */ + 220 : void state_nano(struct snapraid_state* state); + 221 : + 222 : /** + 223 : * Devices operations. + 224 : */ + 225 : void state_device(struct snapraid_state* state, int operation); + 226 : + 227 : /** + 228 : * Sync the parity data. + 229 : */ + 230 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); + 231 : + 232 : /** + 233 : * Check (and fixes) all the files and parity data. + 234 : * \param fix If we have to fix, after checking. + 235 : */ + 236 : int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount); + 237 : + 238 : /** + 239 : * Dry the files. + 240 : */ + 241 : void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); + 242 : + 243 : /** + 244 : * Rehash the files. + 245 : */ + 246 : void state_rehash(struct snapraid_state* state); + 247 : + 248 : /** + 249 : * Scrub levels. + 250 : */ + 251 : #define SCRUB_AUTO -1 /**< Automatic selection. */ + 252 : #define SCRUB_BAD -2 /**< Scrub only the bad blocks. */ + 253 : #define SCRUB_NEW -3 /**< Scub the new blocks. */ + 254 : #define SCRUB_FULL -4 /**< Scrub everything. */ + 255 : #define SCRUB_EVEN -5 /**< Even blocks. */ + 256 : + 257 : /** + 258 : * Scrub the files. + 259 : */ + 260 : int state_scrub(struct snapraid_state* state, int plan, int olderthan); + 261 : + 262 : /** + 263 : * Print the status. + 264 : */ + 265 : int state_status(struct snapraid_state* state); + 266 : + 267 : /** + 268 : * Find duplicates. + 269 : */ + 270 : void state_dup(struct snapraid_state* state); + 271 : + 272 : /** + 273 : * List content. + 274 : */ + 275 : void state_list(struct snapraid_state* state); + 276 : + 277 : /** + 278 : * Create pool tree. + 279 : */ + 280 : void state_pool(struct snapraid_state* state); + 281 : + 282 : /** + 283 : * Refresh the free space info. + 284 : * + 285 : * Note that it requires disks access. + 286 : */ + 287 : void state_refresh(struct snapraid_state* state); + 288 : + 289 : /** + 290 : * Skip files, symlinks and dirs. + 291 : * Apply any skip access disk. + 292 : */ + 293 : void state_skip(struct snapraid_state* state); + 294 : + 295 : /** + 296 : * Filter files, symlinks and dirs. + 297 : * Apply an additional filter to the list currently loaded. + 298 : */ + 299 : void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error); + 300 : + 301 : /** + 302 : * Begin the progress visualization. + 303 : */ + 304 : int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax); + 305 : + 306 : /** + 307 : * End the progress visualization. + 308 : */ + 309 : void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize); + 310 : + 311 : /** + 312 : * Write the progress. + 313 : */ + 314 : int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize); + 315 : + 316 : /** + 317 : * Stop temporarily the progress. + 318 : */ + 319 : void state_progress_stop(struct snapraid_state* state); + 320 : + 321 : /** + 322 : * Restart the progress. + 323 : */ + 324 : void state_progress_restart(struct snapraid_state* state); + 325 : + 326 : /** + 327 : * Set the usage time as wasted one not counted. + 328 : */ + 329 97 : static inline void state_usage_waste(struct snapraid_state* state) + 330 : { + 331 97 : uint64_t now = tick(); + 332 : + 333 97 : state->tick_last = now; + 334 97 : } + 335 : + 336 : /** + 337 : * Set the usage time for CPU. + 338 : */ + 339 833206 : static inline void state_usage_cpu(struct snapraid_state* state) + 340 : { + 341 833206 : uint64_t now = tick(); + 342 833206 : uint64_t delta = now - state->tick_last; + 343 : + 344 : /* increment the time spent in computations */ + 345 833206 : state->tick_cpu += delta; + 346 : + 347 833206 : state->tick_last = now; + 348 833206 : } + 349 : + 350 : /** + 351 : * Set the usage time for data disk. + 352 : */ + 353 673880 : static inline void state_usage_disk(struct snapraid_state* state, struct snapraid_disk* disk) + 354 : { + 355 673880 : uint64_t now = tick(); + 356 673880 : uint64_t delta = now - state->tick_last; 357 : - 358 622545 : state->tick_last = now; - 359 622545 : } - 360 : - 361 : /** - 362 : * Set the usage time for parity disk. - 363 : */ - 364 653350 : static inline void state_usage_parity(struct snapraid_state* state, unsigned level) - 365 : { - 366 653350 : uint64_t now = tick(); - 367 653350 : uint64_t delta = now - state->tick_last; - 368 : - 369 653350 : assert(level < LEV_MAX); - 370 : - 371 : /* increment the time spent in the parity disk */ - 372 653350 : state->parity[level].tick += delta; - 373 653350 : state->tick_io += delta; + 358 : /* increment the time spent in the data disk */ + 359 673880 : disk->tick += delta; + 360 673880 : state->tick_io += delta; + 361 : + 362 673880 : state->tick_last = now; + 363 673880 : } + 364 : + 365 : /** + 366 : * Set the usage time for parity disk. + 367 : */ + 368 706913 : static inline void state_usage_parity(struct snapraid_state* state, unsigned level) + 369 : { + 370 706913 : uint64_t now = tick(); + 371 706913 : uint64_t delta = now - state->tick_last; + 372 : + 373 706913 : assert(level < LEV_MAX); 374 : - 375 653350 : state->tick_last = now; - 376 653350 : } - 377 : - 378 : /** - 379 : * Print the stats of the usage time. - 380 : */ - 381 : void state_usage_print(struct snapraid_state* state); - 382 : - 383 : /** - 384 : * Check the filesystem on all disks. - 385 : * On error it aborts. - 386 : */ - 387 : void state_fscheck(struct snapraid_state* state, const char* ope); - 388 : - 389 : /****************************************************************************/ - 390 : /* misc */ - 391 : - 392 : /** - 393 : * Generate a dummy configuration file from a content file. - 394 : */ - 395 : void generate_configuration(const char* content); - 396 : - 397 : #endif - 398 : + 375 : /* increment the time spent in the parity disk */ + 376 706913 : state->parity[level].tick += delta; + 377 706913 : state->tick_io += delta; + 378 : + 379 706913 : state->tick_last = now; + 380 706913 : } + 381 : + 382 : /** + 383 : * Print the stats of the usage time. + 384 : */ + 385 : void state_usage_print(struct snapraid_state* state); + 386 : + 387 : /** + 388 : * Check the file-system on all disks. + 389 : * On error it aborts. + 390 : */ + 391 : void state_fscheck(struct snapraid_state* state, const char* ope); + 392 : + 393 : /****************************************************************************/ + 394 : /* misc */ + 395 : + 396 : /** + 397 : * Generate a dummy configuration file from a content file. + 398 : */ + 399 : void generate_configuration(const char* content); + 400 : + 401 : #endif + 402 : diff --git a/cov/cmdline/status.c.func-sort-c.html b/cov/cmdline/status.c.func-sort-c.html index 3a3013e8..1c2639e5 100644 --- a/cov/cmdline/status.c.func-sort-c.html +++ b/cov/cmdline/status.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 diff --git a/cov/cmdline/status.c.func.html b/cov/cmdline/status.c.func.html index fd04e329..4558d05e 100644 --- a/cov/cmdline/status.c.func.html +++ b/cov/cmdline/status.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 diff --git a/cov/cmdline/status.c.gcov.html b/cov/cmdline/status.c.gcov.html index 59c5f405..6c2b85f8 100644 --- a/cov/cmdline/status.c.gcov.html +++ b/cov/cmdline/status.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -159,9 +159,9 @@ 97 84 : log_tag("summary:parity_block_total:%s:%u\n", lev_config_name(l), state->parity[l].total_blocks); 98 84 : log_tag("summary:parity_block_free:%s:%u\n", lev_config_name(l), state->parity[l].free_blocks); 99 84 : if (state->parity[l].free_blocks < parity_block_free) - 100 4 : parity_block_free = state->parity[l].free_blocks; + 100 1 : parity_block_free = state->parity[l].free_blocks; 101 84 : if (state->parity[l].free_blocks != 0) - 102 58 : free_not_zero = 1; + 102 73 : free_not_zero = 1; 103 : } 104 14 : log_tag("summary:parity_block_free_min:%u\n", parity_block_free); 105 : @@ -195,50 +195,50 @@ 133 : 134 : /* for each file in the disk */ 135 84 : node = disk->filelist; - 136 95610 : while (node) { + 136 95666 : while (node) { 137 : struct snapraid_file* file; 138 : - 139 95442 : file = node->data; - 140 95442 : node = node->next; /* next node */ + 139 95498 : file = node->data; + 140 95498 : node = node->next; /* next node */ 141 : 142 : /* check fragmentation */ - 143 95442 : if (file->blockmax != 0) { + 143 95498 : if (file->blockmax != 0) { 144 : block_off_t prev_pos; 145 : block_off_t last_pos; 146 : int fragmented; 147 : - 148 95304 : fragmented = 0; - 149 95304 : prev_pos = fs_file2par_get(disk, file, 0); - 150 234999 : for (j = 1; j < file->blockmax; ++j) { - 151 139695 : block_off_t parity_pos = fs_file2par_get(disk, file, j); - 152 139695 : if (prev_pos + 1 != parity_pos) { + 148 95360 : fragmented = 0; + 149 95360 : prev_pos = fs_file2par_get(disk, file, 0); + 150 235447 : for (j = 1; j < file->blockmax; ++j) { + 151 140087 : block_off_t parity_pos = fs_file2par_get(disk, file, j); + 152 140087 : if (prev_pos + 1 != parity_pos) { 153 698 : fragmented = 1; 154 698 : ++extra_fragment; 155 698 : ++disk_extra_fragment; 156 : } - 157 139695 : prev_pos = parity_pos; + 157 140087 : prev_pos = parity_pos; 158 : } 159 : 160 : /* keep track of latest block used */ - 161 95304 : last_pos = fs_file2par_get(disk, file, file->blockmax - 1); - 162 95304 : if (last_pos > disk_block_latest_used) { - 163 92447 : disk_block_latest_used = last_pos; + 161 95360 : last_pos = fs_file2par_get(disk, file, file->blockmax - 1); + 162 95360 : if (last_pos > disk_block_latest_used) { + 163 92502 : disk_block_latest_used = last_pos; 164 : } 165 : - 166 95304 : if (fragmented) { + 166 95360 : if (fragmented) { 167 582 : ++file_fragmented; 168 582 : ++disk_file_fragmented; 169 : } 170 : - 171 95304 : disk_block_count += file->blockmax; + 171 95360 : disk_block_count += file->blockmax; 172 : } 173 : 174 : /* count files */ - 175 95442 : ++file_count; - 176 95442 : ++disk_file_count; - 177 95442 : file_size += file->size; - 178 95442 : file_block_count += file->blockmax; - 179 95442 : disk_file_size += file->size; + 175 95498 : ++file_count; + 176 95498 : ++disk_file_count; + 177 95498 : file_size += file->size; + 178 95498 : file_block_count += file->blockmax; + 179 95498 : disk_file_size += file->size; 180 : } 181 : 182 84 : if (disk->free_blocks != 0) @@ -253,9 +253,9 @@ 191 : /* the wasted space is the space that we have to leave */ 192 : /* free on the data disk, when the parity is filled up */ 193 84 : if (disk_block_max_by_space < disk_block_max_by_parity) { - 194 50 : disk_block_max = disk_block_max_by_space; + 194 65 : disk_block_max = disk_block_max_by_space; 195 : } else { - 196 34 : disk_block_max = disk_block_max_by_parity; + 196 19 : disk_block_max = disk_block_max_by_parity; 197 : } 198 : 199 : /* wasted space is the difference of the two maximum size */ @@ -264,7 +264,7 @@ 202 84 : wasted *= state->block_size; 203 : 204 84 : if (wasted > 0) - 205 24 : all_wasted += wasted; + 205 6 : all_wasted += wasted; 206 84 : file_block_free += disk_block_max - disk_block_count; 207 : 208 84 : printf("%8u", disk_file_count); @@ -338,57 +338,57 @@ 276 14 : unsynced_blocks = 0; 277 14 : unscrubbed_blocks = 0; 278 14 : log_tag("block_count:%u\n", blockmax); - 279 39620 : for (i = 0; i < blockmax; ++i) { + 279 39702 : for (i = 0; i < blockmax; ++i) { 280 : int one_invalid; 281 : int one_valid; 282 : - 283 39606 : snapraid_info info = info_get(&state->infoarr, i); + 283 39688 : snapraid_info info = info_get(&state->infoarr, i); 284 : 285 : /* for each disk */ - 286 39606 : one_invalid = 0; - 287 39606 : one_valid = 0; - 288 277242 : for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) { - 289 237636 : struct snapraid_disk* disk = node_disk->data; - 290 237636 : struct snapraid_block* block = fs_par2block_get(disk, i); + 286 39688 : one_invalid = 0; + 287 39688 : one_valid = 0; + 288 277816 : for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) { + 289 238128 : struct snapraid_disk* disk = node_disk->data; + 290 238128 : struct snapraid_block* block = fs_par2block_get(disk, i); 291 : - 292 237636 : if (block_has_file(block)) - 293 234999 : one_valid = 1; - 294 237636 : if (block_has_invalid_parity(block)) + 292 238128 : if (block_has_file(block)) + 293 235447 : one_valid = 1; + 294 238128 : if (block_has_invalid_parity(block)) 295 0 : one_invalid = 1; 296 : } 297 : 298 : /* if both valid and invalid, we need to update */ - 299 39606 : if (one_invalid && one_valid) { + 299 39688 : if (one_invalid && one_valid) { 300 0 : ++unsynced_blocks; 301 : } 302 : 303 : /* skip unused blocks */ - 304 39606 : if (info != 0) { + 304 39688 : if (info != 0) { 305 : time_t scrub_time; 306 : - 307 39606 : if (info_get_bad(info)) { - 308 1802 : if (bad == 0) + 307 39688 : if (info_get_bad(info)) { + 308 1771 : if (bad == 0) 309 2 : bad_first = i; - 310 1802 : bad_last = i; - 311 1802 : ++bad; + 310 1771 : bad_last = i; + 311 1771 : ++bad; 312 : } 313 : - 314 39606 : if (info_get_rehash(info)) - 315 4599 : ++rehash; + 314 39688 : if (info_get_rehash(info)) + 315 4603 : ++rehash; 316 : - 317 39606 : scrub_time = info_get_time(info); + 317 39688 : scrub_time = info_get_time(info); 318 : - 319 39606 : if (info_get_justsynced(info)) { - 320 20364 : ++unscrubbed_blocks; + 319 39688 : if (info_get_justsynced(info)) { + 320 20419 : ++unscrubbed_blocks; 321 : 322 : /* mark the time as not scrubbed */ - 323 20364 : scrub_time |= TIME_NEW; + 323 20419 : scrub_time |= TIME_NEW; 324 : } 325 : - 326 39606 : timemap[count++] = scrub_time; + 326 39688 : timemap[count++] = scrub_time; 327 : } 328 : - 329 39606 : if (state->opt.gui) { + 329 39688 : if (state->opt.gui) { 330 0 : if (info != 0) 331 0 : log_tag("block:%u:%" PRIu64 ":%s:%s:%s:%s\n", i, (uint64_t)info_get_time(info), one_valid ? "used" : "", one_invalid ? "unsynced" : "", info_get_bad(info) ? "bad" : "", info_get_rehash(info) ? "rehash" : ""); 332 : else @@ -414,16 +414,16 @@ 352 : /* output the info map */ 353 8 : i = 0; 354 8 : log_tag("info_count:%u\n", count); - 355 41 : while (i < count) { - 356 25 : unsigned j = i + 1; - 357 39631 : while (j < count && timemap[i] == timemap[j]) - 358 39581 : ++j; - 359 25 : if ((timemap[i] & TIME_NEW) == 0) { - 360 9 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i); + 355 39 : while (i < count) { + 356 23 : unsigned j = i + 1; + 357 39711 : while (j < count && timemap[i] == timemap[j]) + 358 39665 : ++j; + 359 23 : if ((timemap[i] & TIME_NEW) == 0) { + 360 8 : log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i); 361 : } else { - 362 16 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i); + 362 15 : log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i); 363 : } - 364 25 : i = j; + 364 23 : i = j; 365 : } 366 : 367 8 : oldest = timemap[0]; @@ -444,12 +444,12 @@ 382 : 383 560 : step_scrubbed = 0; 384 560 : step_new = 0; - 385 40726 : while (barpos < count && timemap[barpos] <= limit) { - 386 39606 : if ((timemap[barpos] & TIME_NEW) != 0) - 387 20364 : ++step_new; + 385 40808 : while (barpos < count && timemap[barpos] <= limit) { + 386 39688 : if ((timemap[barpos] & TIME_NEW) != 0) + 387 20419 : ++step_new; 388 : else - 389 19242 : ++step_scrubbed; - 390 39606 : ++barpos; + 389 19269 : ++step_scrubbed; + 390 39688 : ++barpos; 391 : } 392 : 393 560 : if (step_new + step_scrubbed > barmax) @@ -478,20 +478,20 @@ 416 8400 : unsigned scrubbed = bar_scrubbed[x]; 417 : 418 8400 : if (both > pivot_upper) { - 419 168 : if (scrubbed > pivot_lower) - 420 74 : printf("*"); + 419 171 : if (scrubbed > pivot_lower) + 420 75 : printf("*"); 421 : else - 422 94 : printf("o"); - 423 8232 : } else if (both > pivot_lower) { - 424 25 : if (scrubbed == both) - 425 9 : printf("*"); + 422 96 : printf("o"); + 423 8229 : } else if (both > pivot_lower) { + 424 23 : if (scrubbed == both) + 425 8 : printf("*"); 426 : else - 427 16 : printf("o"); + 427 15 : printf("o"); 428 : } else { - 429 8207 : if (y == GRAPH_ROW - 1) - 430 535 : printf("_"); + 429 8206 : if (y == GRAPH_ROW - 1) + 430 537 : printf("_"); 431 : else - 432 7672 : printf(" "); + 432 7669 : printf(" "); 433 : } 434 : } 435 120 : printf("\n"); @@ -536,19 +536,19 @@ 474 : 475 : /* print some of the errors */ 476 2 : bad_print = 0; - 477 609 : for (i = 0; i < blockmax; ++i) { - 478 609 : snapraid_info info = info_get(&state->infoarr, i); + 477 709 : for (i = 0; i < blockmax; ++i) { + 478 709 : snapraid_info info = info_get(&state->infoarr, i); 479 : 480 : /* skip unused blocks */ - 481 609 : if (info == 0) + 481 709 : if (info == 0) 482 0 : continue; 483 : - 484 609 : if (info_get_bad(info)) { + 484 709 : if (info_get_bad(info)) { 485 202 : printf(" %u", i); 486 202 : ++bad_print; 487 : } 488 : - 489 609 : if (bad_print > 100) { + 489 709 : if (bad_print > 100) { 490 2 : printf(" and %u more...", bad - bad_print); 491 2 : break; 492 : } diff --git a/cov/cmdline/stream.c.func-sort-c.html b/cov/cmdline/stream.c.func-sort-c.html index 929397e4..94e5987f 100644 --- a/cov/cmdline/stream.c.func-sort-c.html +++ b/cov/cmdline/stream.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 261 + 257 280 - 93.2 % + 91.8 % Date: - 2015-11-20 + 2016-01-09 Functions: + 27 28 - 28 - 100.0 % + 96.4 % @@ -61,116 +61,116 @@ swrite - 129597634 - - - sputb32 - 62339359 - - - sputb64 - 34173479 + 20661703 sgetb32 - 18710390 + 18259411 sread - 12342909 - - - sputbs - 12306366 + 12515245 sgetb64 - 10465937 + 10605158 + + + sputb32 + 9119259 + + + sputb64 + 5293948 sgetbs - 3732790 + 3782241 + + + sputbs + 1884788 sfill - 606496 + 607118 sgetc_uncached - 298585 + 298684 sflush - 52590 + 39024 sgettok - 7623 + 7892 sgetline - 5069 + 5251 sgetlasttok - 5035 + 5217 sclose - 2575 - - - scrc - 2333 + 1903 sopen_read - 1701 + 1794 + + + scrc + 1650 sdeplete - 1042 + 1119 sopen_multi_file - 1041 - - - scrc_stream - 929 - - - sputble32 - 929 - - - sopen_multi_write - 928 - - - sopen_write - 913 - - - ssync - 912 + 1118 sgetble32 - 362 + 370 sgetu32 - 247 + 255 shandle - 235 + 243 + + + scrc_stream + 161 + + + sopen_multi_write + 161 + + + sputble32 + 161 + + + ssync + 145 stell 1 + + sopen_write + 0 +
diff --git a/cov/cmdline/stream.c.func.html b/cov/cmdline/stream.c.func.html index 518a0543..e0d1e567 100644 --- a/cov/cmdline/stream.c.func.html +++ b/cov/cmdline/stream.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 261 + 257 280 - 93.2 % + 91.8 % Date: - 2015-11-20 + 2016-01-09 Functions: + 27 28 - 28 - 100.0 % + 96.4 % @@ -61,107 +61,107 @@ sclose - 2575 + 1903 scrc - 2333 + 1650 scrc_stream - 929 + 161 sdeplete - 1042 + 1119 sfill - 606496 + 607118 sflush - 52590 + 39024 sgetb32 - 18710390 + 18259411 sgetb64 - 10465937 + 10605158 sgetble32 - 362 + 370 sgetbs - 3732790 + 3782241 sgetc_uncached - 298585 + 298684 sgetlasttok - 5035 + 5217 sgetline - 5069 + 5251 sgettok - 7623 + 7892 sgetu32 - 247 + 255 shandle - 235 + 243 sopen_multi_file - 1041 + 1118 sopen_multi_write - 928 + 161 sopen_read - 1701 + 1794 sopen_write - 913 + 0 sputb32 - 62339359 + 9119259 sputb64 - 34173479 + 5293948 sputble32 - 929 + 161 sputbs - 12306366 + 1884788 sread - 12342909 + 12515245 ssync - 912 + 145 stell @@ -169,7 +169,7 @@ swrite - 129597634 + 20661703
diff --git a/cov/cmdline/stream.c.gcov.html b/cov/cmdline/stream.c.gcov.html index 93ec3984..10fc5b3f 100644 --- a/cov/cmdline/stream.c.gcov.html +++ b/cov/cmdline/stream.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 261 + 257 280 - 93.2 % + 91.8 % Date: - 2015-11-20 + 2016-01-09 Functions: + 27 28 - 28 - 100.0 % + 96.4 % @@ -88,19 +88,19 @@ 26 : 27 : unsigned STREAM_SIZE = 1024 * 64; 28 : - 29 1701 : STREAM* sopen_read(const char* file) + 29 1794 : STREAM* sopen_read(const char* file) 30 : { 31 : #if HAVE_POSIX_FADVISE 32 : int ret; 33 : #endif - 34 1701 : STREAM* s = malloc_nofail(sizeof(STREAM)); + 34 1794 : STREAM* s = malloc_nofail(sizeof(STREAM)); 35 : - 36 1701 : s->handle_size = 1; - 37 1701 : s->handle = malloc_nofail(sizeof(struct stream_handle)); + 36 1794 : s->handle_size = 1; + 37 1794 : s->handle = malloc_nofail(sizeof(struct stream_handle)); 38 : - 39 1700 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); - 40 1701 : s->handle[0].f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL); - 41 1700 : if (s->handle[0].f == -1) { + 39 1794 : pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); + 40 1794 : s->handle[0].f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL); + 41 1794 : if (s->handle[0].f == -1) { 42 50 : free(s->handle); 43 50 : free(s); 44 50 : return 0; @@ -108,8 +108,8 @@ 46 : 47 : #if HAVE_POSIX_FADVISE 48 : /* advise sequential access */ - 49 1650 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL); - 50 1644 : if (ret != 0) { + 49 1744 : ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL); + 50 1744 : if (ret != 0) { 51 : /* LCOV_EXCL_START */ 52 : close(s->handle[0].f); 53 : free(s->handle); @@ -119,57 +119,57 @@ 57 : } 58 : #endif 59 : - 60 1644 : s->buffer = malloc_nofail_test(STREAM_SIZE); - 61 1650 : s->pos = s->buffer; - 62 1650 : s->end = s->buffer; - 63 1650 : s->state = STREAM_STATE_READ; - 64 1650 : s->state_index = 0; - 65 1650 : s->offset = 0; - 66 1650 : s->offset_uncached = 0; - 67 1650 : s->crc = 0; - 68 1650 : s->crc_uncached = 0; - 69 1650 : s->crc_stream = CRC_IV; + 60 1744 : s->buffer = malloc_nofail_test(STREAM_SIZE); + 61 1744 : s->pos = s->buffer; + 62 1744 : s->end = s->buffer; + 63 1744 : s->state = STREAM_STATE_READ; + 64 1744 : s->state_index = 0; + 65 1744 : s->offset = 0; + 66 1744 : s->offset_uncached = 0; + 67 1744 : s->crc = 0; + 68 1744 : s->crc_uncached = 0; + 69 1744 : s->crc_stream = CRC_IV; 70 : - 71 1650 : return s; + 71 1744 : return s; 72 : } 73 : - 74 928 : STREAM* sopen_multi_write(unsigned count) + 74 161 : STREAM* sopen_multi_write(unsigned count) 75 : { 76 : unsigned i; 77 : - 78 928 : STREAM* s = malloc_nofail(sizeof(STREAM)); + 78 161 : STREAM* s = malloc_nofail(sizeof(STREAM)); 79 : - 80 929 : s->handle_size = count; - 81 929 : s->handle = malloc_nofail(count * sizeof(struct stream_handle)); + 80 161 : s->handle_size = count; + 81 161 : s->handle = malloc_nofail(count * sizeof(struct stream_handle)); 82 : - 83 1968 : for (i = 0; i < count; ++i) - 84 1040 : s->handle[i].f = -1; + 83 1279 : for (i = 0; i < count; ++i) + 84 1118 : s->handle[i].f = -1; 85 : - 86 928 : s->buffer = malloc_nofail_test(STREAM_SIZE); - 87 929 : s->pos = s->buffer; - 88 929 : s->end = s->buffer + STREAM_SIZE; - 89 929 : s->state = STREAM_STATE_WRITE; - 90 929 : s->state_index = 0; - 91 929 : s->offset = 0; - 92 929 : s->offset_uncached = 0; - 93 929 : s->crc = 0; - 94 929 : s->crc_uncached = 0; - 95 929 : s->crc_stream = CRC_IV; + 86 161 : s->buffer = malloc_nofail_test(STREAM_SIZE); + 87 161 : s->pos = s->buffer; + 88 161 : s->end = s->buffer + STREAM_SIZE; + 89 161 : s->state = STREAM_STATE_WRITE; + 90 161 : s->state_index = 0; + 91 161 : s->offset = 0; + 92 161 : s->offset_uncached = 0; + 93 161 : s->crc = 0; + 94 161 : s->crc_uncached = 0; + 95 161 : s->crc_stream = CRC_IV; 96 : - 97 929 : return s; + 97 161 : return s; 98 : } 99 : - 100 1041 : int sopen_multi_file(STREAM* s, unsigned i, const char* file) + 100 1118 : int sopen_multi_file(STREAM* s, unsigned i, const char* file) 101 : { 102 : #if HAVE_POSIX_FADVISE 103 : int ret; 104 : #endif 105 : int f; 106 : - 107 1041 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file); + 107 1118 : pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file); 108 : - 109 1041 : f = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_SEQUENTIAL, 0600); - 110 1041 : if (f == -1) { + 109 1118 : f = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_SEQUENTIAL, 0600); + 110 1118 : if (f == -1) { 111 : /* LCOV_EXCL_START */ 112 : return -1; 113 : /* LCOV_EXCL_STOP */ @@ -177,8 +177,8 @@ 115 : 116 : #if HAVE_POSIX_FADVISE 117 : /* advise sequential access */ - 118 1041 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); - 119 1041 : if (ret != 0) { + 118 1118 : ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + 119 1118 : if (ret != 0) { 120 : /* LCOV_EXCL_START */ 121 : close(f); 122 : return -1; @@ -186,167 +186,167 @@ 124 : } 125 : #endif 126 : - 127 1041 : s->handle[i].f = f; + 127 1118 : s->handle[i].f = f; 128 : - 129 1041 : return 0; + 129 1118 : return 0; 130 : } 131 : - 132 913 : STREAM* sopen_write(const char* file) + 132 0 : STREAM* sopen_write(const char* file) 133 : { - 134 913 : STREAM* s = sopen_multi_write(1); + 134 0 : STREAM* s = sopen_multi_write(1); 135 : - 136 913 : if (sopen_multi_file(s, 0, file) != 0) { + 136 0 : if (sopen_multi_file(s, 0, file) != 0) { 137 0 : sclose(s); 138 0 : return 0; 139 : } 140 : - 141 913 : return s; + 141 0 : return s; 142 : } 143 : - 144 2575 : int sclose(STREAM* s) + 144 1903 : int sclose(STREAM* s) 145 : { - 146 2575 : int fail = 0; + 146 1903 : int fail = 0; 147 : unsigned i; 148 : - 149 2575 : if (s->state == STREAM_STATE_WRITE) { - 150 927 : if (sflush(s) != 0) { + 149 1903 : if (s->state == STREAM_STATE_WRITE) { + 150 161 : if (sflush(s) != 0) { 151 : /* LCOV_EXCL_START */ 152 : fail = 1; 153 : /* LCOV_EXCL_STOP */ 154 : } 155 : } 156 : - 157 5266 : for (i = 0; i < s->handle_size; ++i) { - 158 2688 : if (close(s->handle[i].f) != 0) { + 157 4763 : for (i = 0; i < s->handle_size; ++i) { + 158 2860 : if (close(s->handle[i].f) != 0) { 159 : /* LCOV_EXCL_START */ 160 : fail = 1; 161 : /* LCOV_EXCL_STOP */ 162 : } 163 : } 164 : - 165 2578 : free(s->handle); - 166 2578 : free(s->buffer); - 167 2578 : free(s); + 165 1903 : free(s->handle); + 166 1903 : free(s->buffer); + 167 1903 : free(s); 168 : - 169 2578 : if (fail) { + 169 1903 : if (fail) { 170 : /* LCOV_EXCL_START */ 171 : return -1; 172 : /* LCOV_EXCL_STOP */ 173 : } 174 : - 175 2578 : return 0; + 175 1903 : return 0; 176 : } 177 : - 178 235 : int shandle(STREAM* s) + 178 243 : int shandle(STREAM* s) 179 : { - 180 235 : if (!s->handle_size) { + 180 243 : if (!s->handle_size) { 181 : /* LCOV_EXCL_START */ 182 : return -1; 183 : /* LCOV_EXCL_STOP */ 184 : } 185 : - 186 235 : return s->handle[0].f; + 186 243 : return s->handle[0].f; 187 : } 188 : 189 : /** 190 : * Fill the read stream buffer. 191 : * \return 0 if at least on char is read, or EOF on error. 192 : */ - 193 606496 : static int sfill(STREAM* s) + 193 607118 : static int sfill(STREAM* s) 194 : { 195 : ssize_t ret; 196 : - 197 606496 : if (s->state != STREAM_STATE_READ) { + 197 607118 : if (s->state != STREAM_STATE_READ) { 198 : /* LCOV_EXCL_START */ 199 : return EOF; 200 : /* LCOV_EXCL_STOP */ 201 : } 202 : - 203 605512 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE); + 203 606102 : ret = read(s->handle[0].f, s->buffer, STREAM_SIZE); 204 : - 205 605512 : if (ret < 0) { + 205 606102 : if (ret < 0) { 206 : /* LCOV_EXCL_START */ 207 : s->state = STREAM_STATE_ERROR; 208 : return EOF; 209 : /* LCOV_EXCL_STOP */ 210 : } - 211 605512 : if (ret == 0) { - 212 1522 : s->state = STREAM_STATE_EOF; - 213 1522 : return EOF; + 211 606102 : if (ret == 0) { + 212 1615 : s->state = STREAM_STATE_EOF; + 213 1615 : return EOF; 214 : } 215 : 216 : /* update the crc */ - 217 603990 : s->crc_uncached = s->crc; - 218 603990 : s->crc = crc32c(s->crc, s->buffer, ret); + 217 604487 : s->crc_uncached = s->crc; + 218 604487 : s->crc = crc32c(s->crc, s->buffer, ret); 219 : 220 : /* update the offset */ - 221 603990 : s->offset_uncached = s->offset; - 222 603990 : s->offset += ret; + 221 604487 : s->offset_uncached = s->offset; + 222 604487 : s->offset += ret; 223 : - 224 603990 : s->pos = s->buffer; - 225 603990 : s->end = s->buffer + ret; + 224 604487 : s->pos = s->buffer; + 225 604487 : s->end = s->buffer + ret; 226 : - 227 603990 : return 0; + 227 604487 : return 0; 228 : } 229 : - 230 1042 : int sdeplete(STREAM* s, unsigned char* last) + 230 1119 : int sdeplete(STREAM* s, unsigned char* last) 231 : { 232 : /* last four bytes */ - 233 1042 : last[0] = 0; - 234 1042 : last[1] = 0; - 235 1042 : last[2] = 0; - 236 1042 : last[3] = 0; + 233 1119 : last[0] = 0; + 234 1119 : last[1] = 0; + 235 1119 : last[2] = 0; + 236 1119 : last[3] = 0; 237 : 238 : while (1) { 239 : /* increase the position up to 4 bytes before the end */ - 240 307911 : if (s->pos + 4 <= s->end) - 241 148134 : s->pos = s->end - 4; + 240 308434 : if (s->pos + 4 <= s->end) + 241 148580 : s->pos = s->end - 4; 242 : 243 : /* insert the last 4 bytes */ - 244 1468126 : while (s->pos < s->end) { - 245 852304 : last[0] = last[1]; - 246 852304 : last[1] = last[2]; - 247 852304 : last[2] = last[3]; - 248 852304 : last[3] = *s->pos++; + 244 1470956 : while (s->pos < s->end) { + 245 854088 : last[0] = last[1]; + 246 854088 : last[1] = last[2]; + 247 854088 : last[2] = last[3]; + 248 854088 : last[3] = *s->pos++; 249 : } 250 : 251 : /* fill again the buffer until the end of the file */ - 252 307911 : if (sfill(s) != 0) { + 252 308434 : if (sfill(s) != 0) { 253 : /* on error fail */ - 254 1042 : if (serror(s)) { + 254 1119 : if (serror(s)) { 255 : /* LCOV_EXCL_START */ 256 : return EOF; 257 : /* LCOV_EXCL_STOP */ 258 : } 259 : 260 : /* on EOF terminate */ - 261 1042 : break; + 261 1119 : break; 262 : } - 263 306869 : } + 263 307315 : } 264 : - 265 1042 : return 0; + 265 1119 : return 0; 266 : } 267 : - 268 52590 : int sflush(STREAM* s) + 268 39024 : int sflush(STREAM* s) 269 : { 270 : ssize_t ret; 271 : ssize_t size; 272 : unsigned i; 273 : - 274 52590 : if (s->state != STREAM_STATE_WRITE) { + 274 39024 : if (s->state != STREAM_STATE_WRITE) { 275 : /* LCOV_EXCL_START */ 276 : return EOF; 277 : /* LCOV_EXCL_STOP */ 278 : } 279 : - 280 52590 : size = s->pos - s->buffer; - 281 52590 : if (!size) - 282 909 : return 0; + 280 39024 : size = s->pos - s->buffer; + 281 39024 : if (!size) + 282 145 : return 0; 283 : - 284 359449 : for (i = 0; i < s->handle_size; ++i) { - 285 307768 : ret = write(s->handle[i].f, s->buffer, size); + 284 347171 : for (i = 0; i < s->handle_size; ++i) { + 285 308292 : ret = write(s->handle[i].f, s->buffer, size); 286 : - 287 307768 : if (ret != size) { + 287 308292 : if (ret != size) { 288 : /* LCOV_EXCL_START */ 289 : s->state = STREAM_STATE_ERROR; 290 : s->state_index = i; @@ -362,16 +362,16 @@ 300 : * to be able to detect memory errors on the buffer, 301 : * happening during the write. 302 : */ - 303 51681 : s->crc = crc32c(s->crc, s->buffer, size); - 304 51680 : s->crc_uncached = s->crc; + 303 38879 : s->crc = crc32c(s->crc, s->buffer, size); + 304 38879 : s->crc_uncached = s->crc; 305 : 306 : /* update the offset */ - 307 51680 : s->offset += size; - 308 51680 : s->offset_uncached = s->offset; + 307 38879 : s->offset += size; + 308 38879 : s->offset_uncached = s->offset; 309 : - 310 51680 : s->pos = s->buffer; + 310 38879 : s->pos = s->buffer; 311 : - 312 51680 : return 0; + 312 38879 : return 0; 313 : } 314 : 315 1 : int64_t stell(STREAM* s) @@ -379,100 +379,100 @@ 317 1 : return s->offset_uncached + (s->pos - s->buffer); 318 : } 319 : - 320 2333 : uint32_t scrc(STREAM*s) + 320 1650 : uint32_t scrc(STREAM*s) 321 : { - 322 2333 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer); + 322 1650 : return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer); 323 : } 324 : - 325 929 : uint32_t scrc_stream(STREAM*s) + 325 161 : uint32_t scrc_stream(STREAM*s) 326 : { - 327 929 : return s->crc_stream ^ CRC_IV; + 327 161 : return s->crc_stream ^ CRC_IV; 328 : } 329 : - 330 298585 : int sgetc_uncached(STREAM* s) + 330 298684 : int sgetc_uncached(STREAM* s) 331 : { 332 : /* if at the end of the buffer, fill it */ - 333 298585 : if (s->pos == s->end && sfill(s) != 0) - 334 1464 : return EOF; - 335 297121 : return *s->pos++; + 333 298684 : if (s->pos == s->end && sfill(s) != 0) + 334 1512 : return EOF; + 335 297172 : return *s->pos++; 336 : } 337 : - 338 7623 : int sgettok(STREAM* f, char* str, int size) + 338 7892 : int sgettok(STREAM* f, char* str, int size) 339 : { - 340 7623 : char* i = str; - 341 7623 : char* send = str + size; + 340 7892 : char* i = str; + 341 7892 : char* send = str + size; 342 : int c; 343 : 344 : while (1) { - 345 50866 : c = sgetc(f); - 346 50866 : if (c == EOF) { - 347 246 : break; + 345 52707 : c = sgetc(f); + 346 52707 : if (c == EOF) { + 347 254 : break; 348 : } - 349 50620 : if (c == ' ' || c == '\t') { - 350 7131 : sungetc(c, f); - 351 7131 : break; + 349 52453 : if (c == ' ' || c == '\t') { + 350 7383 : sungetc(c, f); + 351 7383 : break; 352 : } - 353 43489 : if (c == '\n') { + 353 45070 : if (c == '\n') { 354 : /* remove ending carrige return to support the Windows CR+LF format */ - 355 246 : if (i != str && i[-1] == '\r') + 355 255 : if (i != str && i[-1] == '\r') 356 0 : --i; - 357 246 : sungetc(c, f); - 358 246 : break; + 357 255 : sungetc(c, f); + 358 255 : break; 359 : } 360 : - 361 43243 : *i++ = c; + 361 44815 : *i++ = c; 362 : - 363 43243 : if (i == send) { + 363 44815 : if (i == send) { 364 : /* LCOV_EXCL_START */ 365 : return -1; 366 : /* LCOV_EXCL_STOP */ 367 : } - 368 43243 : } + 368 44815 : } 369 : - 370 7623 : *i = 0; + 370 7892 : *i = 0; 371 : - 372 7623 : return i - str; + 372 7892 : return i - str; 373 : } 374 : - 375 12342909 : int sread(STREAM* f, void* void_data, unsigned size) + 375 12515245 : int sread(STREAM* f, void* void_data, unsigned size) 376 : { - 377 12342909 : unsigned char* data = void_data; + 377 12515245 : unsigned char* data = void_data; 378 : 379 : /* if there is enough space in memory */ - 380 12342909 : if (sptrlookup(f, size)) { + 380 12515245 : if (sptrlookup(f, size)) { 381 : /* optimized version with all the data in memory */ - 382 12316849 : unsigned char* pos = sptrget(f); + 382 12489054 : unsigned char* pos = sptrget(f); 383 : 384 : /* copy it */ - 385 209697747 : while (size--) - 386 185064049 : *data++ = *pos++; + 385 212622570 : while (size--) + 386 187644462 : *data++ = *pos++; 387 : - 388 12316849 : sptrset(f, pos); + 388 12489054 : sptrset(f, pos); 389 : } else { 390 : /* standard version using sgetc() */ - 391 1373859 : while (size--) { - 392 1321739 : int c = sgetc(f); - 393 1321739 : if (c == EOF) { + 391 1376682 : while (size--) { + 392 1324300 : int c = sgetc(f); + 393 1324300 : if (c == EOF) { 394 : /* LCOV_EXCL_START */ 395 : return -1; 396 : /* LCOV_EXCL_STOP */ 397 : } 398 : - 399 1321739 : *data++ = c; + 399 1324300 : *data++ = c; 400 : } 401 : } 402 : - 403 12342909 : return 0; + 403 12515245 : return 0; 404 : } 405 : - 406 5069 : int sgetline(STREAM* f, char* str, int size) + 406 5251 : int sgetline(STREAM* f, char* str, int size) 407 : { - 408 5069 : char* i = str; - 409 5069 : char* send = str + size; + 408 5251 : char* i = str; + 409 5251 : char* send = str + size; 410 : int c; 411 : 412 : /* if there is enough data in memory */ - 413 5069 : if (sptrlookup(f, size)) { + 413 5251 : if (sptrlookup(f, size)) { 414 : /* optimized version with all the data in memory */ 415 0 : unsigned char* pos = sptrget(f); 416 : @@ -498,75 +498,75 @@ 436 0 : sptrset(f, pos); 437 : } else { 438 : while (1) { - 439 68948 : c = sgetc(f); - 440 68948 : if (c == EOF) { + 439 71440 : c = sgetc(f); + 440 71440 : if (c == EOF) { 441 : /* LCOV_EXCL_START */ 442 : break; 443 : /* LCOV_EXCL_STOP */ 444 : } - 445 68948 : if (c == '\n') { + 445 71440 : if (c == '\n') { 446 : /* remove ending carrige return to support the Windows CR+LF format */ - 447 5069 : if (i != str && i[-1] == '\r') + 447 5251 : if (i != str && i[-1] == '\r') 448 0 : --i; - 449 5069 : sungetc(c, f); - 450 5069 : break; + 449 5251 : sungetc(c, f); + 450 5251 : break; 451 : } 452 : - 453 63879 : *i++ = c; + 453 66189 : *i++ = c; 454 : - 455 63879 : if (i == send) { + 455 66189 : if (i == send) { 456 : /* LCOV_EXCL_START */ 457 : return -1; 458 : /* LCOV_EXCL_STOP */ 459 : } - 460 63879 : } + 460 66189 : } 461 : } 462 : - 463 5069 : *i = 0; + 463 5251 : *i = 0; 464 : - 465 5069 : return i - str; + 465 5251 : return i - str; 466 : } 467 : - 468 5035 : int sgetlasttok(STREAM* f, char* str, int size) + 468 5217 : int sgetlasttok(STREAM* f, char* str, int size) 469 : { 470 : int ret; 471 : - 472 5035 : ret = sgetline(f, str, size); - 473 5035 : if (ret < 0) { + 472 5217 : ret = sgetline(f, str, size); + 473 5217 : if (ret < 0) { 474 : /* LCOV_EXCL_START */ 475 : return ret; 476 : /* LCOV_EXCL_STOP */ 477 : } 478 : - 479 10070 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t')) + 479 10434 : while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t')) 480 0 : --ret; 481 : - 482 5035 : str[ret] = 0; + 482 5217 : str[ret] = 0; 483 : - 484 5035 : return ret; + 484 5217 : return ret; 485 : } 486 : - 487 247 : int sgetu32(STREAM* f, uint32_t* value) + 487 255 : int sgetu32(STREAM* f, uint32_t* value) 488 : { 489 : int c; 490 : - 491 247 : c = sgetc(f); - 492 247 : if (c >= '0' && c <= '9') { + 491 255 : c = sgetc(f); + 492 255 : if (c >= '0' && c <= '9') { 493 : uint32_t v; 494 : - 495 247 : v = c - '0'; + 495 255 : v = c - '0'; 496 : - 497 247 : c = sgetc(f); - 498 494 : while (c >= '0' && c <= '9') { + 497 255 : c = sgetc(f); + 498 510 : while (c >= '0' && c <= '9') { 499 0 : v *= 10; 500 0 : v += c - '0'; 501 0 : c = sgetc(f); 502 : } 503 : - 504 247 : *value = v; + 504 255 : *value = v; 505 : - 506 247 : sungetc(c, f); - 507 247 : return 0; + 506 255 : sungetc(c, f); + 507 255 : return 0; 508 : } else { 509 : /* LCOV_EXCL_START */ 510 : /* nothing read */ @@ -575,122 +575,122 @@ 513 : } 514 : } 515 : - 516 18710390 : int sgetb32(STREAM* f, uint32_t* value) + 516 18259411 : int sgetb32(STREAM* f, uint32_t* value) 517 : { 518 : uint32_t v; 519 : unsigned char b; 520 : unsigned char s; 521 : int c; 522 : - 523 18710390 : v = 0; - 524 18710390 : s = 0; + 523 18259411 : v = 0; + 524 18259411 : s = 0; 525 : loop: - 526 35314985 : c = sgetc(f); - 527 35314985 : if (c == EOF) { + 526 35244347 : c = sgetc(f); + 527 35244347 : if (c == EOF) { 528 : /* LCOV_EXCL_START */ 529 : return -1; 530 : /* LCOV_EXCL_STOP */ 531 : } 532 : - 533 35314985 : b = (unsigned char)c; - 534 35314985 : if ((b & 0x80) == 0) { - 535 16604595 : v |= (uint32_t)b << s; - 536 16604595 : s += 7; - 537 16604595 : if (s >= 32) { + 533 35244347 : b = (unsigned char)c; + 534 35244347 : if ((b & 0x80) == 0) { + 535 16984936 : v |= (uint32_t)b << s; + 536 16984936 : s += 7; + 537 16984936 : if (s >= 32) { 538 : /* LCOV_EXCL_START */ 539 : return -1; 540 : /* LCOV_EXCL_STOP */ 541 : } - 542 16604595 : goto loop; + 542 16984936 : goto loop; 543 : } 544 : - 545 18710390 : v |= (uint32_t)(b & 0x7f) << s; + 545 18259411 : v |= (uint32_t)(b & 0x7f) << s; 546 : - 547 18710390 : *value = v; + 547 18259411 : *value = v; 548 : - 549 18710390 : return 0; + 549 18259411 : return 0; 550 : } 551 : - 552 10465937 : int sgetb64(STREAM* f, uint64_t* value) + 552 10605158 : int sgetb64(STREAM* f, uint64_t* value) 553 : { 554 : uint64_t v; 555 : unsigned char b; 556 : unsigned char s; 557 : int c; 558 : - 559 10465937 : v = 0; - 560 10465937 : s = 0; + 559 10605158 : v = 0; + 560 10605158 : s = 0; 561 : loop: - 562 38271575 : c = sgetc(f); - 563 38271575 : if (c == EOF) { + 562 38780587 : c = sgetc(f); + 563 38780587 : if (c == EOF) { 564 : /* LCOV_EXCL_START */ 565 : return -1; 566 : /* LCOV_EXCL_STOP */ 567 : } 568 : - 569 38271575 : b = (unsigned char)c; - 570 38271575 : if ((b & 0x80) == 0) { - 571 27805638 : v |= (uint64_t)b << s; - 572 27805638 : s += 7; - 573 27805638 : if (s >= 64) { + 569 38780587 : b = (unsigned char)c; + 570 38780587 : if ((b & 0x80) == 0) { + 571 28175429 : v |= (uint64_t)b << s; + 572 28175429 : s += 7; + 573 28175429 : if (s >= 64) { 574 : /* LCOV_EXCL_START */ 575 : return -1; 576 : /* LCOV_EXCL_STOP */ 577 : } - 578 27805638 : goto loop; + 578 28175429 : goto loop; 579 : } 580 : - 581 10465937 : v |= (uint64_t)(b & 0x7f) << s; + 581 10605158 : v |= (uint64_t)(b & 0x7f) << s; 582 : - 583 10465937 : *value = v; + 583 10605158 : *value = v; 584 : - 585 10465937 : return 0; + 585 10605158 : return 0; 586 : } 587 : - 588 362 : int sgetble32(STREAM* f, uint32_t* value) + 588 370 : int sgetble32(STREAM* f, uint32_t* value) 589 : { 590 : unsigned char buf[4]; 591 : - 592 362 : if (sread(f, buf, 4) != 0) { + 592 370 : if (sread(f, buf, 4) != 0) { 593 : /* LCOV_EXCL_START */ 594 : return -1; 595 : /* LCOV_EXCL_STOP */ 596 : } 597 : - 598 362 : *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + 598 370 : *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; 599 : - 600 362 : return 0; + 600 370 : return 0; 601 : } 602 : - 603 3732790 : int sgetbs(STREAM* f, char* str, int size) + 603 3782241 : int sgetbs(STREAM* f, char* str, int size) 604 : { 605 : uint32_t len; 606 : - 607 3732790 : if (sgetb32(f, &len) < 0) { + 607 3782241 : if (sgetb32(f, &len) < 0) { 608 : /* LCOV_EXCL_START */ 609 : return -1; 610 : /* LCOV_EXCL_STOP */ 611 : } 612 : - 613 3732790 : if (len + 1 > (uint32_t)size) { + 613 3782241 : if (len + 1 > (uint32_t)size) { 614 : /* LCOV_EXCL_START */ 615 : return -1; 616 : /* LCOV_EXCL_STOP */ 617 : } 618 : - 619 3732790 : str[len] = 0; + 619 3782240 : str[len] = 0; 620 : - 621 3732790 : return sread(f, str, (int)len); + 621 3782240 : return sread(f, str, (int)len); 622 : } 623 : - 624 129597634 : int swrite(const void* void_data, unsigned size, STREAM* f) + 624 20661703 : int swrite(const void* void_data, unsigned size, STREAM* f) 625 : { - 626 129597634 : const unsigned char* data = void_data; + 626 20661703 : const unsigned char* data = void_data; 627 : 628 : /* if there is enough space in memory */ - 629 129597634 : if (sptrlookup(f, size)) { + 629 20661703 : if (sptrlookup(f, size)) { 630 : /* optimized version with all the data in memory */ - 631 128366511 : unsigned char* pos = sptrget(f); + 631 20655549 : unsigned char* pos = sptrget(f); 632 : 633 : /** 634 : * Update the crc *before* writing the data in the buffer @@ -699,17 +699,17 @@ 637 : * to be able to detect memory errors on the buffer, 638 : * happening before we write it on the file. 639 : */ - 640 127220529 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); + 640 20655549 : f->crc_stream = crc32c_plain(f->crc_stream, data, size); 641 : 642 : /* copy it */ - 643 984312399 : while (size--) - 644 729779043 : *pos++ = *data++; + 643 172057609 : while (size--) + 644 130746511 : *pos++ = *data++; 645 : - 646 127266678 : sptrset(f, pos); + 646 20655549 : sptrset(f, pos); 647 : } else { 648 : /* standard version using sputc() */ - 649 352837 : while (size--) { - 650 318158 : if (sputc(*data++, f) != 0) { + 649 201458 : while (size--) { + 650 189150 : if (sputc(*data++, f) != 0) { 651 : /* LCOV_EXCL_START */ 652 : return -1; 653 : /* LCOV_EXCL_STOP */ @@ -717,83 +717,83 @@ 655 : } 656 : } 657 : - 658 129224881 : return 0; + 658 20661703 : return 0; 659 : } 660 : - 661 62339359 : int sputb32(uint32_t value, STREAM* s) + 661 9119259 : int sputb32(uint32_t value, STREAM* s) 662 : { 663 : unsigned char b; 664 : unsigned char buf[16]; 665 : unsigned i; 666 : - 667 62339359 : i = 0; + 667 9119259 : i = 0; 668 : loop: - 669 117525500 : b = value & 0x7f; - 670 117525500 : value >>= 7; + 669 17637493 : b = value & 0x7f; + 670 17637493 : value >>= 7; 671 : - 672 117525500 : if (value) { - 673 55186141 : buf[i++] = b; - 674 55186141 : goto loop; + 672 17637493 : if (value) { + 673 8518234 : buf[i++] = b; + 674 8518234 : goto loop; 675 : } 676 : - 677 62339359 : buf[i++] = b | 0x80; + 677 9119259 : buf[i++] = b | 0x80; 678 : - 679 62339359 : return swrite(buf, i, s); + 679 9119259 : return swrite(buf, i, s); 680 : } 681 : - 682 34173479 : int sputb64(uint64_t value, STREAM* s) + 682 5293948 : int sputb64(uint64_t value, STREAM* s) 683 : { 684 : unsigned char b; 685 : unsigned char buf[16]; 686 : unsigned i; 687 : - 688 34173479 : i = 0; + 688 5293948 : i = 0; 689 : loop: - 690 124705929 : b = value & 0x7f; - 691 124705929 : value >>= 7; + 690 19354594 : b = value & 0x7f; + 691 19354594 : value >>= 7; 692 : - 693 124705929 : if (value) { - 694 90532450 : buf[i++] = b; - 695 90532450 : goto loop; + 693 19354594 : if (value) { + 694 14060646 : buf[i++] = b; + 695 14060646 : goto loop; 696 : } 697 : - 698 34173479 : buf[i++] = b | 0x80; + 698 5293948 : buf[i++] = b | 0x80; 699 : - 700 34173479 : return swrite(buf, i, s); + 700 5293948 : return swrite(buf, i, s); 701 : } 702 : - 703 929 : int sputble32(uint32_t value, STREAM* s) + 703 161 : int sputble32(uint32_t value, STREAM* s) 704 : { 705 : unsigned char buf[4]; 706 : - 707 929 : buf[0] = value & 0xFF; - 708 929 : buf[1] = (value >> 8) & 0xFF; - 709 929 : buf[2] = (value >> 16) & 0xFF; - 710 929 : buf[3] = (value >> 24) & 0xFF; + 707 161 : buf[0] = value & 0xFF; + 708 161 : buf[1] = (value >> 8) & 0xFF; + 709 161 : buf[2] = (value >> 16) & 0xFF; + 710 161 : buf[3] = (value >> 24) & 0xFF; 711 : - 712 929 : return swrite(buf, 4, s); + 712 161 : return swrite(buf, 4, s); 713 : } 714 : - 715 12306366 : int sputbs(const char* str, STREAM* f) + 715 1884788 : int sputbs(const char* str, STREAM* f) 716 : { - 717 12306366 : size_t len = strlen(str); + 717 1884788 : size_t len = strlen(str); 718 : - 719 12306366 : if (sputb32(len, f) != 0) { + 719 1884788 : if (sputb32(len, f) != 0) { 720 : /* LCOV_EXCL_START */ 721 : return -1; 722 : /* LCOV_EXCL_STOP */ 723 : } 724 : - 725 12287997 : return swrite(str, len, f); + 725 1884788 : return swrite(str, len, f); 726 : } 727 : 728 : #if HAVE_FSYNC - 729 912 : int ssync(STREAM* s) + 729 145 : int ssync(STREAM* s) 730 : { 731 : unsigned i; 732 : - 733 1824 : for (i = 0; i < s->handle_size; ++i) { - 734 913 : if (fsync(s->handle[i].f) != 0) { + 733 1135 : for (i = 0; i < s->handle_size; ++i) { + 734 990 : if (fsync(s->handle[i].f) != 0) { 735 : /* LCOV_EXCL_START */ 736 : s->state = STREAM_STATE_ERROR; 737 : s->state_index = i; @@ -802,7 +802,7 @@ 740 : } 741 : } 742 : - 743 911 : return 0; + 743 145 : return 0; 744 : } 745 : #endif 746 : diff --git a/cov/cmdline/stream.h.func-sort-c.html b/cov/cmdline/stream.h.func-sort-c.html index 6fd4d017..3d5cc907 100644 --- a/cov/cmdline/stream.h.func-sort-c.html +++ b/cov/cmdline/stream.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -60,40 +60,40 @@ Hit count Sort by hit count - sptrlookup - 140471390 + sgetc + 82747474 - sptrget - 140020205 + sptrlookup + 33182199 sptrset - 138951723 + 33144603 - sgetc - 82206359 - - - serror - 24784868 + sptrget + 33144603 sputc - 23611223 + 3794625 + + + serror + 3632818 sungetc - 32166 + 33308 sgetspace - 19238 + 19921 sgeteol - 5807 + 6014 seof diff --git a/cov/cmdline/stream.h.func.html b/cov/cmdline/stream.h.func.html index 50565355..b6043b90 100644 --- a/cov/cmdline/stream.h.func.html +++ b/cov/cmdline/stream.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -65,7 +65,7 @@ serror - 24784868 + 3632818 serrorfile @@ -73,35 +73,35 @@ sgetc - 82206359 + 82747474 sgeteol - 5807 + 6014 sgetspace - 19238 + 19921 sptrget - 140020205 + 33144603 sptrlookup - 140471390 + 33182199 sptrset - 138951723 + 33144603 sputc - 23611223 + 3794625 sungetc - 32166 + 33308
diff --git a/cov/cmdline/stream.h.gcov.html b/cov/cmdline/stream.h.gcov.html index 04b9f268..cf65bf9c 100644 --- a/cov/cmdline/stream.h.gcov.html +++ b/cov/cmdline/stream.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -94,8 +94,8 @@ 32 : 33 : #define STREAM_STATE_READ 0 /**< The stream is in a normal state of read. */ 34 : #define STREAM_STATE_WRITE 1 /**< The stream is in a normal state of write. */ - 35 : #define STREAM_STATE_ERROR -1 /**< An error was encoutered. */ - 36 : #define STREAM_STATE_EOF 2 /**< The end of file was encoutered. */ + 35 : #define STREAM_STATE_ERROR -1 /**< An error was encountered. */ + 36 : #define STREAM_STATE_EOF 2 /**< The end of file was encountered. */ 37 : 38 : struct stream_handle { 39 : int f; /**< Handle of the file. */ @@ -221,33 +221,33 @@ 159 : /** 160 : * Check if the buffer has enough data loaded. 161 : */ - 162 140471390 : static inline int sptrlookup(STREAM* s, int size) + 162 33182199 : static inline int sptrlookup(STREAM* s, int size) 163 : { - 164 140471390 : return s->pos + size <= s->end; + 164 33182199 : return s->pos + size <= s->end; 165 : } 166 : 167 : /** 168 : * Get the current stream ptr. 169 : */ - 170 140020205 : static inline unsigned char* sptrget(STREAM* s) + 170 33144603 : static inline unsigned char* sptrget(STREAM* s) 171 : { - 172 140020205 : return s->pos; + 172 33144603 : return s->pos; 173 : } 174 : 175 : /** 176 : * Set the current stream ptr. 177 : */ - 178 138951723 : static inline void sptrset(STREAM* s, unsigned char* ptr) + 178 33144603 : static inline void sptrset(STREAM* s, unsigned char* ptr) 179 : { - 180 138951723 : s->pos = ptr; - 181 138951723 : } + 180 33144603 : s->pos = ptr; + 181 33144603 : } 182 : 183 : /** 184 : * Check the error status. Like ferror(). 185 : */ - 186 24784868 : static inline int serror(STREAM* s) + 186 3632818 : static inline int serror(STREAM* s) 187 : { - 188 24784868 : return s->state == STREAM_STATE_ERROR; + 188 3632818 : return s->state == STREAM_STATE_ERROR; 189 : } 190 : 191 : /** @@ -291,22 +291,22 @@ 229 : /** 230 : * Read a char. Like fgetc(). 231 : */ - 232 82206359 : static inline int sgetc(STREAM* s) + 232 82747474 : static inline int sgetc(STREAM* s) 233 : { - 234 82206359 : if (tommy_unlikely(s->pos == s->end)) - 235 298585 : return sgetc_uncached(s); - 236 81907774 : return *s->pos++; + 234 82747474 : if (tommy_unlikely(s->pos == s->end)) + 235 298684 : return sgetc_uncached(s); + 236 82448790 : return *s->pos++; 237 : } 238 : 239 : /** 240 : * Unread a char. 241 : * Like ungetc() but you have to unget the same char read. 242 : */ - 243 32166 : static inline void sungetc(int c, STREAM* s) + 243 33308 : static inline void sungetc(int c, STREAM* s) 244 : { - 245 32166 : if (c != EOF) - 246 31428 : --s->pos; - 247 32166 : } + 245 33308 : if (c != EOF) + 246 32546 : --s->pos; + 247 33308 : } 248 : 249 : /** 250 : * Read a fixed amount of chars. @@ -317,34 +317,34 @@ 255 : /** 256 : * Get a char from a stream, ignoring one '\r'. 257 : */ - 258 5807 : static inline int sgeteol(STREAM* f) + 258 6014 : static inline int sgeteol(STREAM* f) 259 : { 260 : int c; 261 : - 262 5807 : c = sgetc(f); - 263 5807 : if (c == '\r') + 262 6014 : c = sgetc(f); + 263 6014 : if (c == '\r') 264 0 : c = sgetc(f); 265 : - 266 5807 : return c; + 266 6014 : return c; 267 : } 268 : 269 : /** 270 : * Read all the spaces and tabs. 271 : * Return the number of spaces and tabs read. 272 : */ - 273 19238 : static inline int sgetspace(STREAM* f) + 273 19921 : static inline int sgetspace(STREAM* f) 274 : { - 275 19238 : int count = 0; + 275 19921 : int count = 0; 276 : int c; 277 : - 278 19238 : c = sgetc(f); - 279 45607 : while (c == ' ' || c == '\t') { - 280 7131 : ++count; - 281 7131 : c = sgetc(f); + 278 19921 : c = sgetc(f); + 279 47225 : while (c == ' ' || c == '\t') { + 280 7383 : ++count; + 281 7383 : c = sgetc(f); 282 : } 283 : - 284 19238 : sungetc(c, f); - 285 19238 : return count; + 284 19921 : sungetc(c, f); + 285 19921 : return count; 286 : } 287 : 288 : /** @@ -407,10 +407,10 @@ 345 : * Write a char. Like fputc(). 346 : * Return 0 on success or -1 on error. 347 : */ - 348 23611223 : static inline int sputc(int c, STREAM* s) + 348 3794625 : static inline int sputc(int c, STREAM* s) 349 : { - 350 23611223 : if (s->pos == s->end) { - 351 49838 : if (sflush(s) != 0) + 350 3794625 : if (s->pos == s->end) { + 351 38573 : if (sflush(s) != 0) 352 0 : return -1; 353 : } 354 : @@ -421,11 +421,11 @@ 359 : * to be able to detect memory errors on the buffer, 360 : * happening before we write it on the file. 361 : */ - 362 23611224 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); + 362 3794625 : s->crc_stream = crc32c_plain_char(s->crc_stream, c); 363 : - 364 23809904 : *s->pos++ = c; + 364 3794625 : *s->pos++ = c; 365 : - 366 23809904 : return 0; + 366 3794625 : return 0; 367 : } 368 : 369 : /** diff --git a/cov/cmdline/support.c.func-sort-c.html b/cov/cmdline/support.c.func-sort-c.html index e77ef92a..468d779e 100644 --- a/cov/cmdline/support.c.func-sort-c.html +++ b/cov/cmdline/support.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 232 - 293 - 79.2 % + 240 + 301 + 79.7 % Date: - 2015-11-20 + 2016-01-09 Functions: - 29 - 31 - 93.5 % + 30 + 32 + 93.8 % @@ -60,88 +60,92 @@ Hit count Sort by hit count - pathcmp - 50336221 + pathcmp + 51328958 pathprint - 50030363 + 50908928 - malloc_nofail - 13871886 + malloc_counter_inc + 19792624 + + + malloc_nofail + 14067108 pathcpy - 6858601 + 6956056 - strdup_nofail - 5663011 + strdup_nofail + 5715940 log_tag - 4041705 + 4058806 esc - 3592843 + 3612178 - mkancestor - 792978 + mkancestor + 793073 log_error - 614592 + 615188 msg_info - 295863 + 295974 msg_verbose - 126936 + 127002 - fmtime - 117937 + fmtime + 119629 pathexport - 17569 + 17583 log_expected - 11751 + 11440 - calloc_nofail - 9283 + calloc_nofail + 9576 pathimport - 8852 + 9180 - pathslash - 7319 + pathslash + 7469 msg_progress - 3911 + 4145 log_flush - 1108 + 1148 msg_bar - 952 + 945 log_fatal - 804 + 822 pathcatc @@ -149,30 +153,30 @@ msg_status - 569 + 577 - malloc_counter - 444 + malloc_counter_get + 460 msg_flush - 440 + 442 pathcat - 248 + 256 - pathcut + pathcut 30 - smartctl_attribute + smartctl_attribute 25 - smartctl_flush + smartctl_flush 12 @@ -180,7 +184,7 @@ 0 - smatch + smatch 0 diff --git a/cov/cmdline/support.c.func.html b/cov/cmdline/support.c.func.html index 65c60503..9872d2eb 100644 --- a/cov/cmdline/support.c.func.html +++ b/cov/cmdline/support.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 232 - 293 - 79.2 % + 240 + 301 + 79.7 % Date: - 2015-11-20 + 2016-01-09 Functions: - 29 - 31 - 93.5 % + 30 + 32 + 93.8 % @@ -60,128 +60,132 @@ Hit count Sort by hit count - calloc_nofail - 9283 + calloc_nofail + 9576 esc - 3592843 + 3612178 - fmtime - 117937 + fmtime + 119629 log_error - 614592 + 615188 log_expected - 11751 + 11440 log_fatal - 804 + 822 log_flush - 1108 + 1148 log_tag - 4041705 + 4058806 - malloc_counter - 444 + malloc_counter_get + 460 - malloc_nofail - 13871886 + malloc_counter_inc + 19792624 - mkancestor - 792978 + malloc_nofail + 14067108 + + + mkancestor + 793073 msg_bar - 952 + 945 msg_flush - 440 + 442 msg_info - 295863 + 295974 msg_progress - 3911 + 4145 msg_status - 569 + 577 msg_verbose - 126936 + 127002 pathcat - 248 + 256 pathcatc 788 - pathcmp - 50336221 + pathcmp + 51328958 pathcpy - 6858601 + 6956056 - pathcut + pathcut 30 pathexport - 17569 + 17583 pathimport - 8852 + 9180 pathprint - 50030363 + 50908928 - pathslash - 7319 + pathslash + 7469 polish 0 - smartctl_attribute + smartctl_attribute 25 - smartctl_flush + smartctl_flush 12 - smatch + smatch 0 - strdup_nofail - 5663011 + strdup_nofail + 5715940
diff --git a/cov/cmdline/support.c.gcov.html b/cov/cmdline/support.c.gcov.html index 07fccc29..265ef117 100644 --- a/cov/cmdline/support.c.gcov.html +++ b/cov/cmdline/support.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 232 - 293 - 79.2 % + 240 + 301 + 79.7 % Date: - 2015-11-20 + 2016-01-09 Functions: - 29 - 31 - 93.5 % + 30 + 32 + 93.8 % @@ -116,13 +116,13 @@ 54 : * caller should use log_flush(). 55 : */ 56 : - 57 804 : void log_fatal(const char* format, ...) + 57 822 : void log_fatal(const char* format, ...) 58 : { 59 : va_list ap; 60 : - 61 804 : pthread_mutex_lock(&msg_lock); + 61 822 : pthread_mutex_lock(&msg_lock); 62 : - 63 804 : if (stdlog) { + 63 822 : if (stdlog) { 64 103 : va_start(ap, format); 65 103 : fprintf(stdlog, "msg:fatal: "); 66 103 : vfprintf(stdlog, format, ap); @@ -130,89 +130,89 @@ 68 103 : va_end(ap); 69 : } 70 : - 71 804 : va_start(ap, format); - 72 804 : vfprintf(stderr, format, ap); - 73 804 : fflush(stderr); - 74 804 : va_end(ap); + 71 822 : va_start(ap, format); + 72 822 : vfprintf(stderr, format, ap); + 73 822 : fflush(stderr); + 74 822 : va_end(ap); 75 : - 76 804 : pthread_mutex_unlock(&msg_lock); - 77 804 : } + 76 822 : pthread_mutex_unlock(&msg_lock); + 77 822 : } 78 : - 79 614592 : void log_error(const char* format, ...) + 79 615188 : void log_error(const char* format, ...) 80 : { 81 : va_list ap; 82 : - 83 614592 : pthread_mutex_lock(&msg_lock); + 83 615188 : pthread_mutex_lock(&msg_lock); 84 : - 85 614592 : if (stdlog) { - 86 612682 : va_start(ap, format); - 87 612682 : fprintf(stdlog, "msg:error: "); - 88 612682 : vfprintf(stdlog, format, ap); - 89 612682 : fflush(stdlog); - 90 612682 : va_end(ap); + 85 615188 : if (stdlog) { + 86 613309 : va_start(ap, format); + 87 613309 : fprintf(stdlog, "msg:error: "); + 88 613309 : vfprintf(stdlog, format, ap); + 89 613309 : fflush(stdlog); + 90 613309 : va_end(ap); 91 : } else { - 92 1910 : va_start(ap, format); - 93 1910 : vfprintf(stderr, format, ap); - 94 1910 : fflush(stderr); - 95 1910 : va_end(ap); + 92 1879 : va_start(ap, format); + 93 1879 : vfprintf(stderr, format, ap); + 94 1879 : fflush(stderr); + 95 1879 : va_end(ap); 96 : } 97 : - 98 614592 : pthread_mutex_unlock(&msg_lock); - 99 614592 : } + 98 615188 : pthread_mutex_unlock(&msg_lock); + 99 615188 : } 100 : - 101 11751 : void log_expected(const char* format, ...) + 101 11440 : void log_expected(const char* format, ...) 102 : { 103 : va_list ap; 104 : - 105 11751 : pthread_mutex_lock(&msg_lock); + 105 11440 : pthread_mutex_lock(&msg_lock); 106 : - 107 11751 : if (stdlog) { - 108 11751 : va_start(ap, format); - 109 11751 : fprintf(stdlog, "msg:expected: "); - 110 11751 : vfprintf(stdlog, format, ap); - 111 11751 : fflush(stdlog); - 112 11751 : va_end(ap); + 107 11440 : if (stdlog) { + 108 11440 : va_start(ap, format); + 109 11440 : fprintf(stdlog, "msg:expected: "); + 110 11440 : vfprintf(stdlog, format, ap); + 111 11440 : fflush(stdlog); + 112 11440 : va_end(ap); 113 : } 114 : - 115 11751 : pthread_mutex_unlock(&msg_lock); - 116 11751 : } + 115 11440 : pthread_mutex_unlock(&msg_lock); + 116 11440 : } 117 : - 118 4041705 : void log_tag(const char* format, ...) + 118 4058806 : void log_tag(const char* format, ...) 119 : { 120 : va_list ap; 121 : - 122 4041705 : pthread_mutex_lock(&msg_lock); + 122 4058806 : pthread_mutex_lock(&msg_lock); 123 : - 124 4041705 : if (stdlog) { - 125 2962677 : va_start(ap, format); - 126 2962677 : vfprintf(stdlog, format, ap); + 124 4058806 : if (stdlog) { + 125 2977413 : va_start(ap, format); + 126 2977413 : vfprintf(stdlog, format, ap); 127 : /* here we intentionally don't flush */ 128 : /* to make the output faster */ - 129 2962677 : va_end(ap); + 129 2977413 : va_end(ap); 130 : } 131 : - 132 4041705 : pthread_mutex_unlock(&msg_lock); - 133 4041705 : } + 132 4058806 : pthread_mutex_unlock(&msg_lock); + 133 4058806 : } 134 : - 135 1108 : void log_flush(void) + 135 1148 : void log_flush(void) 136 : { - 137 1108 : pthread_mutex_lock(&msg_lock); + 137 1148 : pthread_mutex_lock(&msg_lock); 138 : - 139 1108 : if (stdlog) + 139 1148 : if (stdlog) 140 326 : fflush(stdlog); - 141 1108 : fflush(stdout); - 142 1108 : fflush(stderr); + 141 1148 : fflush(stdout); + 142 1148 : fflush(stderr); 143 : - 144 1108 : pthread_mutex_unlock(&msg_lock); - 145 1108 : } + 144 1148 : pthread_mutex_unlock(&msg_lock); + 145 1148 : } 146 : - 147 569 : void msg_status(const char* format, ...) + 147 577 : void msg_status(const char* format, ...) 148 : { 149 : va_list ap; 150 : - 151 569 : pthread_mutex_lock(&msg_lock); + 151 577 : pthread_mutex_lock(&msg_lock); 152 : - 153 569 : if (stdlog) { + 153 577 : if (stdlog) { 154 276 : va_start(ap, format); 155 276 : fprintf(stdlog, "msg:status: "); 156 276 : vfprintf(stdlog, format, ap); @@ -220,42 +220,42 @@ 158 276 : va_end(ap); 159 : } 160 : - 161 569 : if (msg_level >= MSG_STATUS) { - 162 569 : va_start(ap, format); - 163 569 : vfprintf(stdout, format, ap); - 164 569 : fflush(stdout); - 165 569 : va_end(ap); + 161 577 : if (msg_level >= MSG_STATUS) { + 162 577 : va_start(ap, format); + 163 577 : vfprintf(stdout, format, ap); + 164 577 : fflush(stdout); + 165 577 : va_end(ap); 166 : } 167 : - 168 569 : pthread_mutex_unlock(&msg_lock); - 169 569 : } + 168 577 : pthread_mutex_unlock(&msg_lock); + 169 577 : } 170 : - 171 295863 : void msg_info(const char* format, ...) + 171 295974 : void msg_info(const char* format, ...) 172 : { 173 : va_list ap; 174 : - 175 295863 : pthread_mutex_lock(&msg_lock); + 175 295974 : pthread_mutex_lock(&msg_lock); 176 : 177 : /* don't output in stdlog as these messages */ 178 : /* are always paired with a msg_tag() call */ 179 : - 180 295863 : if (msg_level >= MSG_INFO) { - 181 28776 : va_start(ap, format); - 182 28776 : vfprintf(stdout, format, ap); - 183 28776 : fflush(stdout); - 184 28776 : va_end(ap); + 180 295974 : if (msg_level >= MSG_INFO) { + 181 28827 : va_start(ap, format); + 182 28827 : vfprintf(stdout, format, ap); + 183 28827 : fflush(stdout); + 184 28827 : va_end(ap); 185 : } 186 : - 187 295863 : pthread_mutex_unlock(&msg_lock); - 188 295863 : } + 187 295974 : pthread_mutex_unlock(&msg_lock); + 188 295974 : } 189 : - 190 3911 : void msg_progress(const char* format, ...) + 190 4145 : void msg_progress(const char* format, ...) 191 : { 192 : va_list ap; 193 : - 194 3911 : pthread_mutex_lock(&msg_lock); + 194 4145 : pthread_mutex_lock(&msg_lock); 195 : - 196 3911 : if (stdlog) { + 196 4145 : if (stdlog) { 197 775 : va_start(ap, format); 198 775 : fprintf(stdlog, "msg:progress: "); 199 775 : vfprintf(stdlog, format, ap); @@ -263,68 +263,68 @@ 201 775 : va_end(ap); 202 : } 203 : - 204 3911 : if (msg_level >= MSG_PROGRESS) { + 204 4145 : if (msg_level >= MSG_PROGRESS) { 205 153 : va_start(ap, format); 206 153 : vfprintf(stdout, format, ap); 207 153 : fflush(stdout); 208 153 : va_end(ap); 209 : } 210 : - 211 3911 : pthread_mutex_unlock(&msg_lock); - 212 3911 : } + 211 4145 : pthread_mutex_unlock(&msg_lock); + 212 4145 : } 213 : - 214 952 : void msg_bar(const char* format, ...) + 214 945 : void msg_bar(const char* format, ...) 215 : { 216 : va_list ap; 217 : - 218 952 : pthread_mutex_lock(&msg_lock); + 218 945 : pthread_mutex_lock(&msg_lock); 219 : 220 : /* don't output in stdlog as these messages */ 221 : /* are intended for screen only */ 222 : /* also don't flush stdout as they are intended to be partial messages */ 223 : - 224 952 : if (msg_level >= MSG_BAR) { + 224 945 : if (msg_level >= MSG_BAR) { 225 0 : va_start(ap, format); 226 0 : vfprintf(stdout, format, ap); 227 0 : va_end(ap); 228 : } 229 : - 230 952 : pthread_mutex_unlock(&msg_lock); - 231 952 : } + 230 945 : pthread_mutex_unlock(&msg_lock); + 231 945 : } 232 : - 233 126936 : void msg_verbose(const char* format, ...) + 233 127002 : void msg_verbose(const char* format, ...) 234 : { 235 : va_list ap; 236 : - 237 126936 : pthread_mutex_lock(&msg_lock); + 237 127002 : pthread_mutex_lock(&msg_lock); 238 : - 239 126936 : if (stdlog) { - 240 125292 : va_start(ap, format); - 241 125292 : fprintf(stdlog, "msg:verbose: "); - 242 125292 : vfprintf(stdlog, format, ap); - 243 125292 : fflush(stdlog); - 244 125292 : va_end(ap); + 239 127002 : if (stdlog) { + 240 125226 : va_start(ap, format); + 241 125226 : fprintf(stdlog, "msg:verbose: "); + 242 125226 : vfprintf(stdlog, format, ap); + 243 125226 : fflush(stdlog); + 244 125226 : va_end(ap); 245 : } 246 : - 247 126936 : if (msg_level >= MSG_VERBOSE) { + 247 127002 : if (msg_level >= MSG_VERBOSE) { 248 79 : va_start(ap, format); 249 79 : vfprintf(stdout, format, ap); 250 79 : fflush(stdout); 251 79 : va_end(ap); 252 : } 253 : - 254 126936 : pthread_mutex_unlock(&msg_lock); - 255 126936 : } + 254 127002 : pthread_mutex_unlock(&msg_lock); + 255 127002 : } 256 : - 257 440 : void msg_flush(void) + 257 442 : void msg_flush(void) 258 : { - 259 440 : pthread_mutex_lock(&msg_lock); + 259 442 : pthread_mutex_lock(&msg_lock); 260 : - 261 440 : fflush(stdout); - 262 440 : fflush(stderr); + 261 442 : fflush(stdout); + 262 442 : fflush(stderr); 263 : - 264 440 : pthread_mutex_unlock(&msg_lock); - 265 440 : } + 264 442 : pthread_mutex_unlock(&msg_lock); + 265 442 : } 266 : 267 : /** 268 : * Number of buffers for esc(). @@ -351,20 +351,20 @@ 289 : *p++ = to; \ 290 : break 291 : - 292 3592843 : const char* esc(const char* str) + 292 3612178 : const char* esc(const char* str) 293 : { - 294 3592843 : char* begin = esc_table[esc_index]; - 295 3592843 : char* end = begin + PATH_MAX; - 296 3592843 : char* p = begin; + 294 3612178 : char* begin = esc_table[esc_index]; + 295 3612178 : char* end = begin + PATH_MAX; + 296 3612178 : char* p = begin; 297 : 298 : /* next call uses the next buffer */ - 299 3592843 : esc_index = (esc_index + 1) % ESC_MAX; + 299 3612178 : esc_index = (esc_index + 1) % ESC_MAX; 300 : 301 : /* copy string with escaping */ - 302 53695808 : while (*str) { - 303 46510122 : char c = *str; + 302 53980125 : while (*str) { + 303 46755769 : char c = *str; 304 : - 305 46510122 : switch (c) { + 305 46755769 : switch (c) { 306 : 307 0 : ESCAPE('\n', 'n'); 308 0 : ESCAPE('\r', 'r'); @@ -372,21 +372,21 @@ 310 0 : ESCAPE('\\', '\\'); 311 : 312 : default: - 313 46510122 : if (p == end) + 313 46755769 : if (p == end) 314 0 : goto bail; - 315 46510122 : *p++ = c; - 316 46510122 : break; + 315 46755769 : *p++ = c; + 316 46755769 : break; 317 : } 318 : - 319 46510122 : ++str; + 319 46755769 : ++str; 320 : } 321 : 322 : /* put final 0 */ - 323 3592843 : if (p == end) + 323 3612178 : if (p == end) 324 0 : goto bail; - 325 3592843 : *p = 0; + 325 3612178 : *p = 0; 326 : - 327 7185686 : return begin; + 327 7224356 : return begin; 328 : 329 : bail: 330 : /* LCOV_EXCL_START */ @@ -411,34 +411,34 @@ 349 : /****************************************************************************/ 350 : /* path */ 351 : - 352 6858601 : void pathcpy(char* dst, size_t size, const char* src) + 352 6956056 : void pathcpy(char* dst, size_t size, const char* src) 353 : { - 354 6858601 : size_t len = strlen(src); + 354 6956056 : size_t len = strlen(src); 355 : - 356 6858601 : if (len + 1 > size) { + 356 6956056 : if (len + 1 > size) { 357 : /* LCOV_EXCL_START */ - 358 : log_fatal("Path too long\n"); - 359 : exit(EXIT_FAILURE); + 358 : log_fatal("Path too long '%s'\n", src); + 359 : os_abort(); 360 : /* LCOV_EXCL_STOP */ 361 : } 362 : - 363 6858601 : memcpy(dst, src, len + 1); - 364 6858601 : } + 363 6956056 : memcpy(dst, src, len + 1); + 364 6956056 : } 365 : - 366 248 : void pathcat(char* dst, size_t size, const char* src) + 366 256 : void pathcat(char* dst, size_t size, const char* src) 367 : { - 368 248 : size_t dst_len = strlen(dst); - 369 248 : size_t src_len = strlen(src); + 368 256 : size_t dst_len = strlen(dst); + 369 256 : size_t src_len = strlen(src); 370 : - 371 248 : if (dst_len + src_len + 1 > size) { + 371 256 : if (dst_len + src_len + 1 > size) { 372 : /* LCOV_EXCL_START */ - 373 : log_fatal("Path too long\n"); - 374 : exit(EXIT_FAILURE); + 373 : log_fatal("Path too long '%s%s'\n", dst, src); + 374 : os_abort(); 375 : /* LCOV_EXCL_STOP */ 376 : } 377 : - 378 248 : memcpy(dst + dst_len, src, src_len + 1); - 379 248 : } + 378 256 : memcpy(dst + dst_len, src, src_len + 1); + 379 256 : } 380 : 381 788 : void pathcatc(char* dst, size_t size, char c) 382 : { @@ -446,8 +446,8 @@ 384 : 385 788 : if (dst_len + 2 > size) { 386 : /* LCOV_EXCL_START */ - 387 : log_fatal("Path too long\n"); - 388 : exit(EXIT_FAILURE); + 387 : log_fatal("Path too long '%s%c'\n", dst, c); + 388 : os_abort(); 389 : /* LCOV_EXCL_STOP */ 390 : } 391 : @@ -455,9 +455,9 @@ 393 788 : dst[dst_len + 1] = 0; 394 788 : } 395 : - 396 8852 : void pathimport(char* dst, size_t size, const char* src) + 396 9180 : void pathimport(char* dst, size_t size, const char* src) 397 : { - 398 8852 : pathcpy(dst, size, src); + 398 9180 : pathcpy(dst, size, src); 399 : 400 : #ifdef _WIN32 401 : /* convert all Windows '\' to C '/' */ @@ -467,11 +467,11 @@ 405 : ++dst; 406 : } 407 : #endif - 408 8852 : } + 408 9180 : } 409 : - 410 17569 : void pathexport(char* dst, size_t size, const char* src) + 410 17583 : void pathexport(char* dst, size_t size, const char* src) 411 : { - 412 17569 : pathcpy(dst, size, src); + 412 17583 : pathcpy(dst, size, src); 413 : 414 : #ifdef _WIN32 415 : /* convert all C '/' to Windows '\' */ @@ -481,434 +481,465 @@ 419 : ++dst; 420 : } 421 : #endif - 422 17569 : } + 422 17583 : } 423 : - 424 50030363 : void pathprint(char* dst, size_t size, const char* format, ...) + 424 50908928 : void pathprint(char* dst, size_t size, const char* format, ...) 425 : { 426 : size_t len; 427 : va_list ap; 428 : - 429 50030363 : va_start(ap, format); - 430 50030363 : len = vsnprintf(dst, size, format, ap); - 431 50030363 : va_end(ap); + 429 50908928 : va_start(ap, format); + 430 50908928 : len = vsnprintf(dst, size, format, ap); + 431 50908928 : va_end(ap); 432 : - 433 50030363 : if (len >= size) { + 433 50908928 : if (len >= size) { 434 : /* LCOV_EXCL_START */ - 435 : log_fatal("Path too long\n"); - 436 : exit(EXIT_FAILURE); - 437 : /* LCOV_EXCL_STOP */ - 438 : } - 439 50030363 : } - 440 : - 441 7319 : void pathslash(char* dst, size_t size) - 442 : { - 443 7319 : size_t len = strlen(dst); - 444 : - 445 7319 : if (len > 0 && dst[len - 1] != '/') { - 446 5842 : if (len + 2 >= size) { - 447 : /* LCOV_EXCL_START */ - 448 : log_fatal("Path too long\n"); - 449 : exit(EXIT_FAILURE); - 450 : /* LCOV_EXCL_STOP */ - 451 : } - 452 : - 453 5842 : dst[len] = '/'; - 454 5842 : dst[len + 1] = 0; - 455 : } - 456 7319 : } + 435 : if (size > 0) { + 436 : dst[size - 1] = 0; + 437 : log_fatal("Path too long '%s...'\n", dst); + 438 : } else { + 439 : log_fatal("Path too long for empty size'\n"); + 440 : } + 441 : os_abort(); + 442 : /* LCOV_EXCL_STOP */ + 443 : } + 444 50908928 : } + 445 : + 446 7469 : void pathslash(char* dst, size_t size) + 447 : { + 448 7469 : size_t len = strlen(dst); + 449 : + 450 7469 : if (len > 0 && dst[len - 1] != '/') { + 451 5944 : if (len + 2 >= size) { + 452 : /* LCOV_EXCL_START */ + 453 : log_fatal("Path too long '%s/'\n", dst); + 454 : os_abort(); + 455 : /* LCOV_EXCL_STOP */ + 456 : } 457 : - 458 30 : void pathcut(char* dst) - 459 : { - 460 30 : char* slash = strrchr(dst, '/'); - 461 30 : if (slash) - 462 30 : slash[1] = 0; - 463 : else - 464 0 : dst[0] = 0; - 465 30 : } - 466 : - 467 50336221 : int pathcmp(const char* a, const char* b) - 468 : { - 469 : #ifdef _WIN32 - 470 : char ai[PATH_MAX]; - 471 : char bi[PATH_MAX]; - 472 : - 473 : /* import to convert \ to / */ - 474 : pathimport(ai, sizeof(ai), a); - 475 : pathimport(bi, sizeof(bi), b); - 476 : - 477 : /* case insensitive compare in Windows */ - 478 : return stricmp(ai, bi); - 479 : #else - 480 50336221 : return strcmp(a, b); - 481 : #endif - 482 : } - 483 : - 484 : /****************************************************************************/ - 485 : /* filesystem */ - 486 : - 487 792978 : int mkancestor(const char* file) - 488 : { - 489 : char dir[PATH_MAX]; - 490 : struct stat st; - 491 : char* c; - 492 : - 493 792978 : pathcpy(dir, sizeof(dir), file); - 494 : - 495 792978 : c = strrchr(dir, '/'); - 496 792978 : if (!c) { - 497 : /* no ancestor */ - 498 0 : return 0; - 499 : } - 500 : - 501 : /* clear the file */ - 502 792978 : *c = 0; - 503 : - 504 : /* if it's the root dir */ - 505 792978 : if (*dir == 0) { - 506 : /* nothing more to do */ - 507 0 : return 0; - 508 : } - 509 : - 510 : #ifdef _WIN32 - 511 : /* if it's a drive specificaion like "C:" */ - 512 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { - 513 : /* nothing more to do */ - 514 : return 0; - 515 : } - 516 : #endif - 517 : - 518 : /* - 519 : * Check if the dir already exists using lstat(). - 520 : * - 521 : * Note that in Windows when dealing with read-only media - 522 : * you cannot try to create the directory, and expecting - 523 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. - 524 : * - 525 : * Also in Windows it's better to use lstat() than stat() because it - 526 : * doen't need to open the dir with CreateFile(). - 527 : */ - 528 792978 : if (lstat(dir, &st) == 0) { - 529 : /* it already exists */ - 530 792898 : return 0; - 531 : } - 532 : - 533 : /* recursively create them all */ - 534 80 : if (mkancestor(dir) != 0) { - 535 : /* LCOV_EXCL_START */ - 536 : return -1; - 537 : /* LCOV_EXCL_STOP */ - 538 : } - 539 : - 540 : /* create it */ - 541 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { - 542 : /* LCOV_EXCL_START */ - 543 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno)); - 544 : return -1; - 545 : /* LCOV_EXCL_STOP */ - 546 : } - 547 : - 548 80 : return 0; - 549 : } - 550 : - 551 117937 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) - 552 : { - 553 : #if HAVE_FUTIMENS - 554 : struct timespec tv[2]; - 555 : #else - 556 : struct timeval tv[2]; - 557 : #endif - 558 : int ret; - 559 : - 560 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ - 561 117937 : tv[0].tv_sec = mtime_sec; - 562 117937 : if (mtime_nsec != STAT_NSEC_INVALID) - 563 117937 : tv[0].tv_nsec = mtime_nsec; - 564 : else - 565 0 : tv[0].tv_nsec = 0; - 566 117937 : tv[1].tv_sec = tv[0].tv_sec; - 567 117937 : tv[1].tv_nsec = tv[0].tv_nsec; - 568 : - 569 117937 : ret = futimens(f, tv); - 570 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ - 571 : tv[0].tv_sec = mtime_sec; - 572 : if (mtime_nsec != STAT_NSEC_INVALID) - 573 : tv[0].tv_usec = mtime_nsec / 1000; - 574 : else - 575 : tv[0].tv_usec = 0; - 576 : tv[1].tv_sec = tv[0].tv_sec; - 577 : tv[1].tv_usec = tv[0].tv_usec; - 578 : - 579 : ret = futimes(f, tv); - 580 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ - 581 : tv[0].tv_sec = mtime_sec; - 582 : if (mtime_nsec != STAT_NSEC_INVALID) - 583 : tv[0].tv_usec = mtime_nsec / 1000; - 584 : else - 585 : tv[0].tv_usec = 0; - 586 : tv[1].tv_sec = tv[0].tv_sec; - 587 : tv[1].tv_usec = tv[0].tv_usec; - 588 : - 589 : ret = futimesat(f, 0, tv); - 590 : #else - 591 : #error No function available to set file timestamps with sub-second precision - 592 : #endif + 458 5944 : dst[len] = '/'; + 459 5944 : dst[len + 1] = 0; + 460 : } + 461 7469 : } + 462 : + 463 30 : void pathcut(char* dst) + 464 : { + 465 30 : char* slash = strrchr(dst, '/'); + 466 30 : if (slash) + 467 30 : slash[1] = 0; + 468 : else + 469 0 : dst[0] = 0; + 470 30 : } + 471 : + 472 51328958 : int pathcmp(const char* a, const char* b) + 473 : { + 474 : #ifdef _WIN32 + 475 : char ai[PATH_MAX]; + 476 : char bi[PATH_MAX]; + 477 : + 478 : /* import to convert \ to / */ + 479 : pathimport(ai, sizeof(ai), a); + 480 : pathimport(bi, sizeof(bi), b); + 481 : + 482 : /* case insensitive compare in Windows */ + 483 : return stricmp(ai, bi); + 484 : #else + 485 51328958 : return strcmp(a, b); + 486 : #endif + 487 : } + 488 : + 489 : /****************************************************************************/ + 490 : /* file-system */ + 491 : + 492 793073 : int mkancestor(const char* file) + 493 : { + 494 : char dir[PATH_MAX]; + 495 : struct stat st; + 496 : char* c; + 497 : + 498 793073 : pathcpy(dir, sizeof(dir), file); + 499 : + 500 793073 : c = strrchr(dir, '/'); + 501 793073 : if (!c) { + 502 : /* no ancestor */ + 503 0 : return 0; + 504 : } + 505 : + 506 : /* clear the file */ + 507 793073 : *c = 0; + 508 : + 509 : /* if it's the root dir */ + 510 793073 : if (*dir == 0) { + 511 : /* nothing more to do */ + 512 0 : return 0; + 513 : } + 514 : + 515 : #ifdef _WIN32 + 516 : /* if it's a drive specificaion like "C:" */ + 517 : if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { + 518 : /* nothing more to do */ + 519 : return 0; + 520 : } + 521 : #endif + 522 : + 523 : /* + 524 : * Check if the dir already exists using lstat(). + 525 : * + 526 : * Note that in Windows when dealing with read-only media + 527 : * you cannot try to create the directory, and expecting + 528 : * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. + 529 : * + 530 : * Also in Windows it's better to use lstat() than stat() because it + 531 : * doen't need to open the dir with CreateFile(). + 532 : */ + 533 793073 : if (lstat(dir, &st) == 0) { + 534 : /* it already exists */ + 535 792993 : return 0; + 536 : } + 537 : + 538 : /* recursively create them all */ + 539 80 : if (mkancestor(dir) != 0) { + 540 : /* LCOV_EXCL_START */ + 541 : return -1; + 542 : /* LCOV_EXCL_STOP */ + 543 : } + 544 : + 545 : /* create it */ + 546 80 : if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + 547 : /* LCOV_EXCL_START */ + 548 : log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno)); + 549 : return -1; + 550 : /* LCOV_EXCL_STOP */ + 551 : } + 552 : + 553 80 : return 0; + 554 : } + 555 : + 556 119629 : int fmtime(int f, int64_t mtime_sec, int mtime_nsec) + 557 : { + 558 : #if HAVE_FUTIMENS + 559 : struct timespec tv[2]; + 560 : #else + 561 : struct timeval tv[2]; + 562 : #endif + 563 : int ret; + 564 : + 565 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ + 566 119629 : tv[0].tv_sec = mtime_sec; + 567 119629 : if (mtime_nsec != STAT_NSEC_INVALID) + 568 119629 : tv[0].tv_nsec = mtime_nsec; + 569 : else + 570 0 : tv[0].tv_nsec = 0; + 571 119629 : tv[1].tv_sec = tv[0].tv_sec; + 572 119629 : tv[1].tv_nsec = tv[0].tv_nsec; + 573 : + 574 119629 : ret = futimens(f, tv); + 575 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ + 576 : tv[0].tv_sec = mtime_sec; + 577 : if (mtime_nsec != STAT_NSEC_INVALID) + 578 : tv[0].tv_usec = mtime_nsec / 1000; + 579 : else + 580 : tv[0].tv_usec = 0; + 581 : tv[1].tv_sec = tv[0].tv_sec; + 582 : tv[1].tv_usec = tv[0].tv_usec; + 583 : + 584 : ret = futimes(f, tv); + 585 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + 586 : tv[0].tv_sec = mtime_sec; + 587 : if (mtime_nsec != STAT_NSEC_INVALID) + 588 : tv[0].tv_usec = mtime_nsec / 1000; + 589 : else + 590 : tv[0].tv_usec = 0; + 591 : tv[1].tv_sec = tv[0].tv_sec; + 592 : tv[1].tv_usec = tv[0].tv_usec; 593 : - 594 117937 : return ret; - 595 : } - 596 : - 597 : /****************************************************************************/ - 598 : /* memory */ - 599 : - 600 : /** - 601 : * Total amount of memory allocated. - 602 : */ - 603 : static size_t mcounter; + 594 : ret = futimesat(f, 0, tv); + 595 : #else + 596 : #error No function available to set file timestamps with sub-second precision + 597 : #endif + 598 : + 599 119629 : return ret; + 600 : } + 601 : + 602 : /****************************************************************************/ + 603 : /* memory */ 604 : - 605 444 : size_t malloc_counter(void) - 606 : { - 607 444 : return mcounter; - 608 : } + 605 : /** + 606 : * Total amount of memory allocated. + 607 : */ + 608 : static size_t mcounter; 609 : - 610 : /* LCOV_EXCL_START */ - 611 : static ssize_t malloc_print(int f, const char* str) - 612 : { - 613 : ssize_t len = 0; - 614 : while (str[len]) - 615 : ++len; - 616 : return write(f, str, len); - 617 : } - 618 : /* LCOV_EXCL_STOP */ - 619 : - 620 : /* LCOV_EXCL_START */ - 621 : static ssize_t malloc_printn(int f, size_t value) - 622 : { - 623 : char buf[32]; - 624 : int i; - 625 : - 626 : if (!value) - 627 : return write(f, "0", 1); - 628 : - 629 : i = sizeof(buf); - 630 : while (value) { - 631 : buf[--i] = (value % 10) + '0'; - 632 : value /= 10; - 633 : } - 634 : - 635 : return write(f, buf + i, sizeof(buf) - i); - 636 : } - 637 : /* LCOV_EXCL_STOP */ - 638 : - 639 : /* LCOV_EXCL_START */ - 640 : void malloc_fail(size_t size) - 641 : { - 642 : /* don't use printf to avoid any possible extra allocation */ - 643 : int f = 2; /* stderr */ - 644 : - 645 : malloc_print(f, "Failed for Low Memory!\n"); - 646 : malloc_print(f, "Allocating "); - 647 : malloc_printn(f, size); - 648 : malloc_print(f, " bytes.\n"); - 649 : malloc_print(f, "Already allocated "); - 650 : malloc_printn(f, malloc_counter()); - 651 : malloc_print(f, " bytes.\n"); - 652 : if (sizeof(void*) == 4) { - 653 : malloc_print(f, "You are currently using a 32 bits executable.\n"); - 654 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); - 655 : } - 656 : } - 657 : /* LCOV_EXCL_STOP */ - 658 : - 659 13871886 : void* malloc_nofail(size_t size) - 660 : { - 661 13871886 : void* ptr = malloc(size); - 662 : - 663 13871886 : if (!ptr) { - 664 : /* LCOV_EXCL_START */ - 665 : malloc_fail(size); - 666 : exit(EXIT_FAILURE); - 667 : /* LCOV_EXCL_STOP */ - 668 : } + 610 : /** + 611 : * Mutex protection for the global memory counter. + 612 : */ + 613 : #if HAVE_PTHREAD + 614 : pthread_mutex_t mcounter_mutex = PTHREAD_MUTEX_INITIALIZER; + 615 : #endif + 616 : + 617 460 : size_t malloc_counter_get(void) + 618 : { + 619 : size_t ret; + 620 : #if HAVE_PTHREAD + 621 460 : pthread_mutex_lock(&mcounter_mutex); + 622 : #endif + 623 460 : ret = mcounter; + 624 : #if HAVE_PTHREAD + 625 460 : pthread_mutex_unlock(&mcounter_mutex); + 626 : #endif + 627 460 : return ret; + 628 : } + 629 : + 630 19792624 : void malloc_counter_inc(size_t inc) + 631 : { + 632 : #if HAVE_PTHREAD + 633 19792624 : pthread_mutex_lock(&mcounter_mutex); + 634 : #endif + 635 19792624 : mcounter += inc; + 636 : #if HAVE_PTHREAD + 637 19792624 : pthread_mutex_unlock(&mcounter_mutex); + 638 : #endif + 639 19792624 : } + 640 : + 641 : /* LCOV_EXCL_START */ + 642 : static ssize_t malloc_print(int f, const char* str) + 643 : { + 644 : ssize_t len = 0; + 645 : while (str[len]) + 646 : ++len; + 647 : return write(f, str, len); + 648 : } + 649 : /* LCOV_EXCL_STOP */ + 650 : + 651 : /* LCOV_EXCL_START */ + 652 : static ssize_t malloc_printn(int f, size_t value) + 653 : { + 654 : char buf[32]; + 655 : int i; + 656 : + 657 : if (!value) + 658 : return write(f, "0", 1); + 659 : + 660 : i = sizeof(buf); + 661 : while (value) { + 662 : buf[--i] = (value % 10) + '0'; + 663 : value /= 10; + 664 : } + 665 : + 666 : return write(f, buf + i, sizeof(buf) - i); + 667 : } + 668 : /* LCOV_EXCL_STOP */ 669 : - 670 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ - 671 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ - 672 : /* and not only reserving the addressable space. */ - 673 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ - 674 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ - 675 : /* get a real error from malloc() instead than a process killed. */ - 676 : /* Note that calloc() doesn't have the same effect. */ - 677 13871886 : memset(ptr, 0xA5, size); - 678 : #endif - 679 : - 680 13871886 : mcounter += size; - 681 : - 682 13871886 : return ptr; - 683 : } - 684 : - 685 9283 : void* calloc_nofail(size_t count, size_t size) - 686 : { - 687 : void* ptr; - 688 : - 689 9283 : size *= count; - 690 : - 691 : /* see the note in malloc_nofail() of why we don't use calloc() */ - 692 9283 : ptr = malloc(size); + 670 : /* LCOV_EXCL_START */ + 671 : void malloc_fail(size_t size) + 672 : { + 673 : /* don't use printf to avoid any possible extra allocation */ + 674 : int f = 2; /* stderr */ + 675 : + 676 : malloc_print(f, "Failed for Low Memory!\n"); + 677 : malloc_print(f, "Allocating "); + 678 : malloc_printn(f, size); + 679 : malloc_print(f, " bytes.\n"); + 680 : malloc_print(f, "Already allocated "); + 681 : malloc_printn(f, malloc_counter_get()); + 682 : malloc_print(f, " bytes.\n"); + 683 : if (sizeof(void*) == 4) { + 684 : malloc_print(f, "You are currently using a 32 bits executable.\n"); + 685 : malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); + 686 : } + 687 : } + 688 : /* LCOV_EXCL_STOP */ + 689 : + 690 14067108 : void* malloc_nofail(size_t size) + 691 : { + 692 14067108 : void* ptr = malloc(size); 693 : - 694 9283 : if (!ptr) { + 694 14067108 : if (!ptr) { 695 : /* LCOV_EXCL_START */ 696 : malloc_fail(size); 697 : exit(EXIT_FAILURE); 698 : /* LCOV_EXCL_STOP */ 699 : } 700 : - 701 9283 : memset(ptr, 0, size); - 702 : - 703 9283 : mcounter += size; - 704 : - 705 9283 : return ptr; - 706 : } - 707 : - 708 5663011 : char* strdup_nofail(const char* str) - 709 : { - 710 : size_t size; - 711 : char* ptr; + 701 : #ifndef CHECKER /* Don't preinitialize when running for valgrind */ + 702 : /* Here we preinitialize the memory to ensure that the OS is really allocating it */ + 703 : /* and not only reserving the addressable space. */ + 704 : /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ + 705 : /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ + 706 : /* get a real error from malloc() instead than a process killed. */ + 707 : /* Note that calloc() doesn't have the same effect. */ + 708 14067108 : memset(ptr, 0xA5, size); + 709 : #endif + 710 : + 711 14067108 : malloc_counter_inc(size); 712 : - 713 5663011 : size = strlen(str) + 1; - 714 : - 715 5663011 : ptr = malloc(size); - 716 : - 717 5663011 : if (!ptr) { - 718 : /* LCOV_EXCL_START */ - 719 : malloc_fail(size); - 720 : exit(EXIT_FAILURE); - 721 : /* LCOV_EXCL_STOP */ - 722 : } - 723 : - 724 5663011 : memcpy(ptr, str, size); - 725 : - 726 5663011 : mcounter += size; - 727 : - 728 5663011 : return ptr; - 729 : } - 730 : - 731 : /****************************************************************************/ - 732 : /* smartctl */ + 713 14067108 : return ptr; + 714 : } + 715 : + 716 9576 : void* calloc_nofail(size_t count, size_t size) + 717 : { + 718 : void* ptr; + 719 : + 720 9576 : size *= count; + 721 : + 722 : /* see the note in malloc_nofail() of why we don't use calloc() */ + 723 9576 : ptr = malloc(size); + 724 : + 725 9576 : if (!ptr) { + 726 : /* LCOV_EXCL_START */ + 727 : malloc_fail(size); + 728 : exit(EXIT_FAILURE); + 729 : /* LCOV_EXCL_STOP */ + 730 : } + 731 : + 732 9576 : memset(ptr, 0, size); 733 : - 734 : /** - 735 : * Match a string with the specified pattern. - 736 : * Like sscanf() a space match any sequence of spaces. - 737 : * Return 0 if it matches. - 738 : */ - 739 0 : static int smatch(const char* str, const char* pattern) + 734 9576 : malloc_counter_inc(size); + 735 : + 736 9576 : return ptr; + 737 : } + 738 : + 739 5715940 : char* strdup_nofail(const char* str) 740 : { - 741 0 : while (*pattern) { - 742 0 : if (isspace(*pattern)) { - 743 0 : ++pattern; - 744 0 : while (isspace(*str)) - 745 0 : ++str; - 746 0 : } else if (*pattern == *str) { - 747 0 : ++pattern; - 748 0 : ++str; - 749 : } else - 750 0 : return -1; - 751 : } - 752 : - 753 0 : return 0; - 754 : } - 755 : - 756 25 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial) - 757 : { - 758 : unsigned i; - 759 : int inside; - 760 : - 761 : /* preclear attribute */ - 762 25 : *serial = 0; - 763 6501 : for (i = 0; i < SMART_COUNT; ++i) - 764 6476 : smart[i] = SMART_UNASSIGNED; - 765 : - 766 : /* read the file */ - 767 25 : inside = 0; - 768 : while (1) { - 769 : char buf[256]; - 770 : char attr[64]; - 771 : unsigned id; - 772 : uint64_t raw; - 773 : char* s; - 774 : - 775 25 : s = fgets(buf, sizeof(buf), f); - 776 25 : if (s == 0) - 777 25 : break; - 778 : - 779 : /* remove extraneous chars */ - 780 0 : s = polish(buf); - 781 : - 782 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 741 : size_t size; + 742 : char* ptr; + 743 : + 744 5715940 : size = strlen(str) + 1; + 745 : + 746 5715940 : ptr = malloc(size); + 747 : + 748 5715940 : if (!ptr) { + 749 : /* LCOV_EXCL_START */ + 750 : malloc_fail(size); + 751 : exit(EXIT_FAILURE); + 752 : /* LCOV_EXCL_STOP */ + 753 : } + 754 : + 755 5715940 : memcpy(ptr, str, size); + 756 : + 757 5715940 : malloc_counter_inc(size); + 758 : + 759 5715940 : return ptr; + 760 : } + 761 : + 762 : /****************************************************************************/ + 763 : /* smartctl */ + 764 : + 765 : /** + 766 : * Match a string with the specified pattern. + 767 : * Like sscanf() a space match any sequence of spaces. + 768 : * Return 0 if it matches. + 769 : */ + 770 0 : static int smatch(const char* str, const char* pattern) + 771 : { + 772 0 : while (*pattern) { + 773 0 : if (isspace(*pattern)) { + 774 0 : ++pattern; + 775 0 : while (isspace(*str)) + 776 0 : ++str; + 777 0 : } else if (*pattern == *str) { + 778 0 : ++pattern; + 779 0 : ++str; + 780 : } else + 781 0 : return -1; + 782 : } 783 : - 784 : /* skip initial spaces */ - 785 0 : while (isspace(*s)) - 786 0 : ++s; - 787 : - 788 0 : if (*s == 0) { - 789 0 : inside = 0; - 790 0 : } else if (smatch(s, "ID#") == 0) { - 791 0 : inside = 1; - 792 0 : } else if (smatch(s, "No Errors Logged") == 0) { - 793 0 : smart[SMART_ERROR] = 0; - 794 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - 795 0 : smart[SMART_ERROR] = raw; - 796 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { - 797 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { - 798 0 : smart[SMART_ROTATION_RATE] = 0; - 799 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) { - 800 0 : } else if (sscanf(s, "User Capacity: %63s", attr) == 1) { - 801 0 : smart[SMART_SIZE] = 0; - 802 0 : for (i = 0; attr[i]; ++i) { - 803 0 : if (isdigit(attr[i])) { - 804 0 : smart[SMART_SIZE] *= 10; - 805 0 : smart[SMART_SIZE] += attr[i] - '0'; - 806 : } - 807 : } - 808 0 : } else if (inside) { - 809 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { - 810 : /* LCOV_EXCL_START */ - 811 : log_fatal("Invalid smartctl line '%s'.\n", s); - 812 : return -1; - 813 : /* LCOV_EXCL_STOP */ - 814 : } - 815 : - 816 0 : if (id >= 256) { - 817 : /* LCOV_EXCL_START */ - 818 : log_fatal("Invalid SMART id '%u'.\n", id); - 819 : return -1; - 820 : /* LCOV_EXCL_STOP */ - 821 : } - 822 : - 823 0 : smart[id] = raw; - 824 : } - 825 0 : } - 826 : - 827 25 : return 0; - 828 : } - 829 : - 830 12 : int smartctl_flush(FILE* f, const char* file, const char* name) - 831 : { - 832 : /* read the file */ - 833 : while (1) { - 834 : char buf[256]; - 835 : char* s; - 836 : - 837 12 : s = fgets(buf, sizeof(buf), f); - 838 12 : if (s == 0) - 839 12 : break; - 840 : - 841 : /* remove extraneous chars */ - 842 0 : s = polish(buf); - 843 : - 844 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); - 845 0 : } + 784 0 : return 0; + 785 : } + 786 : + 787 25 : int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial) + 788 : { + 789 : unsigned i; + 790 : int inside; + 791 : + 792 : /* preclear attribute */ + 793 25 : *serial = 0; + 794 6525 : for (i = 0; i < SMART_COUNT; ++i) + 795 6500 : smart[i] = SMART_UNASSIGNED; + 796 : + 797 : /* read the file */ + 798 25 : inside = 0; + 799 : while (1) { + 800 : char buf[256]; + 801 : char attr[64]; + 802 : unsigned id; + 803 : uint64_t raw; + 804 : char* s; + 805 : + 806 25 : s = fgets(buf, sizeof(buf), f); + 807 24 : if (s == 0) + 808 24 : break; + 809 : + 810 : /* remove extraneous chars */ + 811 0 : s = polish(buf); + 812 : + 813 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 814 : + 815 : /* skip initial spaces */ + 816 0 : while (isspace(*s)) + 817 0 : ++s; + 818 : + 819 0 : if (*s == 0) { + 820 0 : inside = 0; + 821 0 : } else if (smatch(s, "ID#") == 0) { + 822 0 : inside = 1; + 823 0 : } else if (smatch(s, "No Errors Logged") == 0) { + 824 0 : smart[SMART_ERROR] = 0; + 825 0 : } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { + 826 0 : smart[SMART_ERROR] = raw; + 827 0 : } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { + 828 0 : } else if (smatch(s, "Rotation Rate: Solid State") == 0) { + 829 0 : smart[SMART_ROTATION_RATE] = 0; + 830 0 : } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) { + 831 0 : } else if (sscanf(s, "User Capacity: %63s", attr) == 1) { + 832 0 : smart[SMART_SIZE] = 0; + 833 0 : for (i = 0; attr[i]; ++i) { + 834 0 : if (isdigit(attr[i])) { + 835 0 : smart[SMART_SIZE] *= 10; + 836 0 : smart[SMART_SIZE] += attr[i] - '0'; + 837 : } + 838 : } + 839 0 : } else if (inside) { + 840 0 : if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { + 841 : /* LCOV_EXCL_START */ + 842 : log_fatal("Invalid smartctl line '%s'.\n", s); + 843 : return -1; + 844 : /* LCOV_EXCL_STOP */ + 845 : } 846 : - 847 24 : return 0; - 848 : } - 849 : + 847 0 : if (id >= 256) { + 848 : /* LCOV_EXCL_START */ + 849 : log_fatal("Invalid SMART id '%u'.\n", id); + 850 : return -1; + 851 : /* LCOV_EXCL_STOP */ + 852 : } + 853 : + 854 0 : smart[id] = raw; + 855 : } + 856 0 : } + 857 : + 858 24 : return 0; + 859 : } + 860 : + 861 12 : int smartctl_flush(FILE* f, const char* file, const char* name) + 862 : { + 863 : /* read the file */ + 864 : while (1) { + 865 : char buf[256]; + 866 : char* s; + 867 : + 868 12 : s = fgets(buf, sizeof(buf), f); + 869 12 : if (s == 0) + 870 12 : break; + 871 : + 872 : /* remove extraneous chars */ + 873 0 : s = polish(buf); + 874 : + 875 0 : log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + 876 0 : } + 877 : + 878 24 : return 0; + 879 : } + 880 : diff --git a/cov/cmdline/sync.c.func-sort-c.html b/cov/cmdline/sync.c.func-sort-c.html index f3bdcd37..bb2fb51e 100644 --- a/cov/cmdline/sync.c.func-sort-c.html +++ b/cov/cmdline/sync.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ block_is_enabled - 733118 + 772244 state_sync - 72 + 80 state_sync_process - 68 + 76 state_hash_process diff --git a/cov/cmdline/sync.c.func.html b/cov/cmdline/sync.c.func.html index e5f48fb5..b1272bb6 100644 --- a/cov/cmdline/sync.c.func.html +++ b/cov/cmdline/sync.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,7 +61,7 @@ block_is_enabled - 733118 + 772244 state_hash_process @@ -69,11 +69,11 @@ state_sync - 72 + 80 state_sync_process - 68 + 76
diff --git a/cov/cmdline/sync.c.gcov.html b/cov/cmdline/sync.c.gcov.html index 36ec1bda..c1ef01a5 100644 --- a/cov/cmdline/sync.c.gcov.html +++ b/cov/cmdline/sync.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -123,18 +123,18 @@ 61 42 : if (!disk) 62 0 : continue; 63 : - 64 235986 : for (i = blockstart; i < blockmax; ++i) { + 64 236382 : for (i = blockstart; i < blockmax; ++i) { 65 : struct snapraid_block* block; 66 : unsigned block_state; 67 : - 68 235944 : block = fs_par2block_get(disk, i); + 68 236340 : block = fs_par2block_get(disk, i); 69 : 70 : /* get the state of the block */ - 71 235944 : block_state = block_state_get(block); + 71 236340 : block_state = block_state_get(block); 72 : 73 : /* process REP and CHG blocks */ - 74 235944 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) - 75 222594 : continue; + 74 236340 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) + 75 222990 : continue; 76 : 77 13350 : ++countmax; 78 : } @@ -155,7 +155,7 @@ 93 42 : if (!disk) 94 0 : continue; 95 : - 96 235986 : for (i = blockstart; i < blockmax; ++i) { + 96 236382 : for (i = blockstart; i < blockmax; ++i) { 97 : snapraid_info info; 98 : int rehash; 99 : struct snapraid_block* block; @@ -165,14 +165,14 @@ 103 : struct snapraid_file* file; 104 : block_off_t file_pos; 105 : - 106 235944 : block = fs_par2block_get(disk, i); + 106 236340 : block = fs_par2block_get(disk, i); 107 : 108 : /* get the state of the block */ - 109 235944 : block_state = block_state_get(block); + 109 236340 : block_state = block_state_get(block); 110 : 111 : /* process REP and CHG blocks */ - 112 235944 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) - 113 445198 : continue; + 112 236340 : if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) + 113 445990 : continue; 114 : 115 : /* get the file of this block */ 116 13350 : file = fs_par2file_get(disk, i, &file_pos); @@ -316,7 +316,7 @@ 254 : 255 13341 : if (block_state == BLOCK_STATE_REP) { 256 : /* compare the hash */ - 257 673 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 257 13339 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { 258 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc(file->sub)); 259 1 : log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos); 260 1 : log_error("WARNING! Unexpected data modification of a file without parity!\n"); @@ -339,16 +339,16 @@ 277 : } 278 : } else { 279 : /* the only other case is BLOCK_STATE_CHG */ - 280 12668 : assert(block_state == BLOCK_STATE_CHG); + 280 2 : assert(block_state == BLOCK_STATE_CHG); 281 : 282 : /* copy the hash in the block */ - 283 12668 : memcpy(block->hash, hash, HASH_SIZE); + 283 2 : memcpy(block->hash, hash, HASH_SIZE); 284 : 285 : /* and mark the block as hashed */ - 286 12668 : block_state_set(block, BLOCK_STATE_REP); + 286 2 : block_state_set(block, BLOCK_STATE_REP); 287 : 288 : /* mark the state as needing write */ - 289 12668 : state->need_write = 1; + 289 2 : state->need_write = 1; 290 : } 291 : 292 : /* count the number of processed block */ @@ -466,39 +466,39 @@ 404 : /** 405 : * Check if we have to process the specified block index ::i. 406 : */ - 407 733118 : static int block_is_enabled(block_off_t i, struct snapraid_handle* handle, unsigned diskmax) + 407 772244 : static int block_is_enabled(block_off_t i, struct snapraid_handle* handle, unsigned diskmax) 408 : { 409 : unsigned j; 410 : int one_invalid; 411 : int one_valid; 412 : 413 : /* for each disk */ - 414 733118 : one_invalid = 0; - 415 733118 : one_valid = 0; - 416 5131826 : for (j = 0; j < diskmax; ++j) { + 414 772244 : one_invalid = 0; + 415 772244 : one_valid = 0; + 416 5405708 : for (j = 0; j < diskmax; ++j) { 417 : struct snapraid_block* block; 418 : 419 : /* if no disk, nothing to check */ - 420 4398708 : if (!handle[j].disk) - 421 9342 : continue; + 420 4633464 : if (!handle[j].disk) + 421 9358 : continue; 422 : - 423 4389366 : block = fs_par2block_get(handle[j].disk, i); + 423 4624106 : block = fs_par2block_get(handle[j].disk, i); 424 : - 425 4389366 : if (block_has_file(block)) - 426 4180078 : one_valid = 1; + 425 4624106 : if (block_has_file(block)) + 426 4407290 : one_valid = 1; 427 : - 428 4389366 : if (block_has_invalid_parity(block)) - 429 361206 : one_invalid = 1; + 428 4624106 : if (block_has_invalid_parity(block)) + 429 469940 : one_invalid = 1; 430 : } 431 : 432 : /* if none valid or none invalid, we don't need to update */ - 433 733118 : if (!one_invalid || !one_valid) - 434 568436 : return 0; + 433 772244 : if (!one_invalid || !one_valid) + 434 589930 : return 0; 435 : - 436 164682 : return 1; + 436 182314 : return 1; 437 : } 438 : - 439 68 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) + 439 76 : static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) 440 : { 441 : struct snapraid_handle* handle; 442 : void* rehandle_alloc; @@ -526,59 +526,59 @@ 464 : 465 : /* the sync process assumes that all the hashes are correct */ 466 : /* including the ones from CHG and DELETED blocks */ - 467 68 : assert(state->clear_past_hash != 0); + 467 76 : assert(state->clear_past_hash != 0); 468 : 469 : /* get the present time */ - 470 68 : now = time(0); + 470 76 : now = time(0); 471 : 472 : /* maps the disks to handles */ - 473 68 : handle = handle_map(state, &diskmax); + 473 76 : handle = handle_map(state, &diskmax); 474 : 475 : /* rehash buffers */ - 476 68 : rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc); + 476 76 : rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc); 477 : 478 : /* we need 2 * data + 1 * parity + 1 * zero */ - 479 68 : buffermax = 2 * diskmax + state->level + 1; + 479 76 : buffermax = 2 * diskmax + state->level + 1; 480 : - 481 68 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); - 482 68 : if (!state->opt.skip_self) + 481 76 : buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); + 482 76 : if (!state->opt.skip_self) 483 0 : mtest_vector(buffermax, state->block_size, buffer); 484 : 485 : /* fill up the zero buffer */ - 486 68 : memset(buffer[buffermax - 1], 0, state->block_size); - 487 68 : raid_zero(buffer[buffermax - 1]); + 486 76 : memset(buffer[buffermax - 1], 0, state->block_size); + 487 76 : raid_zero(buffer[buffermax - 1]); 488 : - 489 68 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); - 490 68 : failed_map = malloc_nofail(diskmax * sizeof(unsigned)); + 489 76 : failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); + 490 76 : failed_map = malloc_nofail(diskmax * sizeof(unsigned)); 491 : - 492 68 : error = 0; - 493 68 : silent_error = 0; - 494 68 : io_error = 0; + 492 76 : error = 0; + 493 76 : silent_error = 0; + 494 76 : io_error = 0; 495 : 496 : /* first count the number of blocks to process */ - 497 68 : countmax = 0; - 498 366627 : for (i = blockstart; i < blockmax; ++i) { - 499 366559 : if (!block_is_enabled(i, handle, diskmax)) - 500 284218 : continue; - 501 82341 : ++countmax; + 497 76 : countmax = 0; + 498 386198 : for (i = blockstart; i < blockmax; ++i) { + 499 386122 : if (!block_is_enabled(i, handle, diskmax)) + 500 294965 : continue; + 501 91157 : ++countmax; 502 : } 503 : 504 : /* compute the autosave size for all disk, even if not read */ 505 : /* this makes sense because the speed should be almost the same */ 506 : /* if the disks are read in parallel */ - 507 68 : autosavelimit = state->autosave / (diskmax * state->block_size); - 508 68 : autosavemissing = countmax; /* blocks to do */ - 509 68 : autosavedone = 0; /* blocks done */ + 507 76 : autosavelimit = state->autosave / (diskmax * state->block_size); + 508 76 : autosavemissing = countmax; /* blocks to do */ + 509 76 : autosavedone = 0; /* blocks done */ 510 : 511 : /* drop until now */ - 512 68 : state_usage_waste(state); + 512 76 : state_usage_waste(state); 513 : - 514 68 : countsize = 0; - 515 68 : countpos = 0; - 516 68 : if (!state_progress_begin(state, blockstart, blockmax, countmax)) + 514 76 : countsize = 0; + 515 76 : countpos = 0; + 516 76 : if (!state_progress_begin(state, blockstart, blockmax, countmax)) 517 0 : goto end; 518 : - 519 366627 : for (i = blockstart; i < blockmax; ++i) { + 519 386198 : for (i = blockstart; i < blockmax; ++i) { 520 : unsigned failed_count; 521 : int error_on_this_block; 522 : int silent_error_on_this_block; @@ -588,27 +588,27 @@ 526 : snapraid_info info; 527 : int rehash; 528 : - 529 366559 : if (!block_is_enabled(i, handle, diskmax)) - 530 284218 : continue; + 529 386122 : if (!block_is_enabled(i, handle, diskmax)) + 530 294965 : continue; 531 : 532 : /* one more block processed for autosave */ - 533 82341 : ++autosavedone; - 534 82341 : --autosavemissing; + 533 91157 : ++autosavedone; + 534 91157 : --autosavemissing; 535 : 536 : /* by default process the block, and skip it if something go wrong */ - 537 82341 : error_on_this_block = 0; - 538 82341 : silent_error_on_this_block = 0; - 539 82341 : io_error_on_this_block = 0; - 540 82341 : fixed_error_on_this_block = 0; + 537 91157 : error_on_this_block = 0; + 538 91157 : silent_error_on_this_block = 0; + 539 91157 : io_error_on_this_block = 0; + 540 91157 : fixed_error_on_this_block = 0; 541 : 542 : /* keep track of the number of failed blocks */ - 543 82341 : failed_count = 0; + 543 91157 : failed_count = 0; 544 : 545 : /* get block specific info */ - 546 82341 : info = info_get(&state->infoarr, i); + 546 91157 : info = info_get(&state->infoarr, i); 547 : 548 : /* if we have to use the old hash */ - 549 82341 : rehash = info_get_rehash(info); + 549 91157 : rehash = info_get_rehash(info); 550 : 551 : /* it could happens that all the blocks are EMPTY/BLK and CHG but with the hash */ 552 : /* still matching because the specific CHG block was not modified. */ @@ -616,55 +616,55 @@ 554 : /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */ 555 : /* We are treating only CHG blocks created at runtime. */ 556 : /* In such case, we can avoid to update parity, because it would be the same as before */ - 557 82341 : parity_needs_to_be_updated = 0; + 557 91157 : parity_needs_to_be_updated = state->opt.force_parity_update; 558 : 559 : /* if the block is marked as bad, we force the parity update */ 560 : /* because the bad block may be the result of a wrong parity */ - 561 82341 : if (info_get_bad(info)) + 561 91157 : if (info_get_bad(info)) 562 0 : parity_needs_to_be_updated = 1; 563 : 564 : /* for each disk, process the block */ - 565 576387 : for (j = 0; j < diskmax; ++j) { + 565 638099 : for (j = 0; j < diskmax; ++j) { 566 : int read_size; 567 : unsigned char hash[HASH_SIZE]; 568 : struct snapraid_block* block; 569 : unsigned block_state; - 570 494046 : struct snapraid_disk* disk = handle[j].disk; + 570 546942 : struct snapraid_disk* disk = handle[j].disk; 571 : struct snapraid_file* file; 572 : block_off_t file_pos; 573 : 574 : /* by default no rehash in case of "continue" */ - 575 494046 : rehandle[j].block = 0; + 575 546942 : rehandle[j].block = 0; 576 : 577 : /* if the disk position is not used */ - 578 494046 : if (!disk) { + 578 546942 : if (!disk) { 579 : /* use an empty block */ 580 0 : memset(buffer[j], 0, state->block_size); - 581 89194 : continue; + 581 91088 : continue; 582 : } 583 : 584 : /* get the block */ - 585 494046 : block = fs_par2block_get(disk, i); + 585 546942 : block = fs_par2block_get(disk, i); 586 : 587 : /* get the state of the block */ - 588 494046 : block_state = block_state_get(block); + 588 546942 : block_state = block_state_get(block); 589 : 590 : /* if the block has invalid parity, */ 591 : /* we have to take care of it in case of recover */ - 592 494046 : if (block_has_invalid_parity(block)) { + 592 546942 : if (block_has_invalid_parity(block)) { 593 : /* store it in the failed set, because */ 594 : /* the parity may be still computed with the previous content */ - 595 180603 : failed[failed_count].index = j; - 596 180603 : failed[failed_count].size = state->block_size; - 597 180603 : failed[failed_count].block = block; - 598 180603 : ++failed_count; + 595 234970 : failed[failed_count].index = j; + 596 234970 : failed[failed_count].size = state->block_size; + 597 234970 : failed[failed_count].block = block; + 598 234970 : ++failed_count; 599 : 600 : /* if the block has invalid parity, we have to update the parity */ 601 : /* to include this block change */ 602 : /* This also apply to CHG blocks, but we are going to handle */ 603 : /* later this case to do the updates only if really needed */ - 604 180603 : if (block_state != BLOCK_STATE_CHG) - 605 56266 : parity_needs_to_be_updated = 1; + 604 234970 : if (block_state != BLOCK_STATE_CHG) + 605 140521 : parity_needs_to_be_updated = 1; 606 : 607 : /* note that DELETE blocks are skipped in the next check */ 608 : /* and we have to store them in the failed blocks */ @@ -675,24 +675,24 @@ 613 : 614 : /* if the block has no file, meanining that it's EMPTY or DELETED, */ 615 : /* it doesn't partecipate in the new parity computation */ - 616 494046 : if (!block_has_file(block)) { + 616 546942 : if (!block_has_file(block)) { 617 : /* use an empty block */ - 618 88293 : memset(buffer[j], 0, state->block_size); - 619 88293 : continue; + 618 90218 : memset(buffer[j], 0, state->block_size); + 619 90218 : continue; 620 : } 621 : 622 : /* get the file of this block */ - 623 405753 : file = fs_par2file_get(disk, i, &file_pos); + 623 456724 : file = fs_par2file_get(disk, i, &file_pos); 624 : 625 : /* until now is CPU */ - 626 405753 : state_usage_cpu(state); + 626 456724 : state_usage_cpu(state); 627 : 628 : /* if the file is different than the current one, close it */ - 629 405753 : if (handle[j].file != 0 && handle[j].file != file) { + 629 456724 : if (handle[j].file != 0 && handle[j].file != file) { 630 : /* keep a pointer at the file we are going to close for error reporting */ - 631 168779 : struct snapraid_file* report = handle[j].file; - 632 168779 : ret = handle_close(&handle[j]); - 633 168779 : if (ret == -1) { + 631 189542 : struct snapraid_file* report = handle[j].file; + 632 189542 : ret = handle_close(&handle[j]); + 633 189542 : if (ret == -1) { 634 : /* LCOV_EXCL_START */ 635 : /* This one is really an unexpected error, because we are only reading */ 636 : /* and closing a descriptor should never fail */ @@ -715,8 +715,8 @@ 653 : } 654 : } 655 : - 656 405753 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); - 657 405753 : if (ret == -1) { + 656 456724 : ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); + 657 456724 : if (ret == -1) { 658 12 : if (errno == EIO) { 659 : /* LCOV_EXCL_START */ 660 : log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); @@ -762,10 +762,10 @@ 700 : } 701 : 702 : /* check if the file is changed */ - 703 405741 : if (handle[j].st.st_size != file->size - 704 405739 : || handle[j].st.st_mtime != file->mtime_sec - 705 405737 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec - 706 405737 : || handle[j].st.st_ino != file->inode + 703 456712 : if (handle[j].st.st_size != file->size + 704 456710 : || handle[j].st.st_mtime != file->mtime_sec + 705 456708 : || STAT_NSEC(&handle[j].st) != file->mtime_nsec + 706 456708 : || handle[j].st.st_ino != file->inode 707 : ) { 708 6 : log_tag("error:%u:%s:%s: Unexpected attribute change\n", i, disk->name, esc(file->sub)); 709 6 : if (handle[j].st.st_size != file->size) { @@ -785,8 +785,8 @@ 723 6 : continue; 724 : } 725 : - 726 405735 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0); - 727 405735 : if (read_size == -1) { + 726 456706 : read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, log_error, 0); + 727 456706 : if (read_size == -1) { 728 : /* LCOV_EXCL_START */ 729 : if (errno == EIO) { 730 : log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc(file->sub), file_pos, strerror(errno)); @@ -814,26 +814,26 @@ 752 : } 753 : 754 : /* until now is disk */ - 755 405735 : state_usage_disk(state, disk); + 755 456706 : state_usage_disk(state, disk); 756 : - 757 405735 : countsize += read_size; + 757 456706 : countsize += read_size; 758 : 759 : /* now compute the hash */ - 760 405735 : if (rehash) { - 761 52244 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); + 760 456706 : if (rehash) { + 761 27231 : memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); 762 : 763 : /* compute the new hash, and store it */ - 764 52244 : rehandle[j].block = block; - 765 52244 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size); + 764 27231 : rehandle[j].block = block; + 765 27231 : memhash(state->hash, state->hashseed, rehandle[j].hash, buffer[j], read_size); 766 : } else { - 767 353491 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + 767 429475 : memhash(state->hash, state->hashseed, hash, buffer[j], read_size); 768 : } 769 : - 770 405735 : if (block_has_updated_hash(block)) { + 770 456706 : if (block_has_updated_hash(block)) { 771 : /* compare the hash */ - 772 281416 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 772 362275 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { 773 : /* if the file has invalid parity, it's a REP changed during the sync */ - 774 883 : if (block_has_invalid_parity(block)) { + 774 852 : if (block_has_invalid_parity(block)) { 775 1 : log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc(file->sub)); 776 1 : log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos); 777 1 : log_error("WARNING! Unexpected data modification of a file without parity!\n"); @@ -854,48 +854,48 @@ 792 1 : error_on_this_block = 1; 793 1 : continue; 794 : } else { /* otherwise it's a BLK with silent error */ - 795 882 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE); - 796 882 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff); - 797 882 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", handle[j].path, file_pos, diff); + 795 851 : unsigned diff = memdiff(hash, block->hash, HASH_SIZE); + 796 851 : log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u\n", i, disk->name, esc(file->sub), file_pos, diff); + 797 851 : log_error("Data error in file '%s' at position '%u', diff bits %u\n", handle[j].path, file_pos, diff); 798 : 799 : /* save the failed block for the fix */ - 800 882 : failed[failed_count].index = j; - 801 882 : failed[failed_count].size = read_size; - 802 882 : failed[failed_count].block = block; - 803 882 : ++failed_count; + 800 851 : failed[failed_count].index = j; + 801 851 : failed[failed_count].size = read_size; + 802 851 : failed[failed_count].block = block; + 803 851 : ++failed_count; 804 : 805 : /* silent errors are very rare, and are not a signal that a disk */ 806 : /* is going to fail. So, we just continue marking the block as bad */ 807 : /* just like in scrub */ - 808 882 : ++silent_error; - 809 882 : silent_error_on_this_block = 1; - 810 882 : continue; + 808 851 : ++silent_error; + 809 851 : silent_error_on_this_block = 1; + 810 851 : continue; 811 : } 812 : } 813 : } else { 814 : /* if until now the parity doesn't need to be updated */ - 815 124319 : if (!parity_needs_to_be_updated) { + 815 94431 : if (!parity_needs_to_be_updated) { 816 : /* for sure it's a CHG block, because EMPTY are processed before with "continue" */ 817 : /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */ 818 : /* have "parity_needs_to_be_updated" already at 1 */ - 819 56741 : assert(block_state_get(block) == BLOCK_STATE_CHG); + 819 35089 : assert(block_state_get(block) == BLOCK_STATE_CHG); 820 : 821 : /* if there is an hash */ - 822 56741 : if (hash_is_real(block->hash)) { + 822 35089 : if (hash_is_real(block->hash)) { 823 : /* check if the hash is changed */ - 824 13014 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { + 824 8465 : if (memcmp(hash, block->hash, HASH_SIZE) != 0) { 825 : /* the block is different, and we must update parity */ - 826 10443 : parity_needs_to_be_updated = 1; + 826 5991 : parity_needs_to_be_updated = 1; 827 : } 828 : } else { 829 : /* if the hash is already invalid, we update parity */ - 830 43727 : parity_needs_to_be_updated = 1; + 830 26624 : parity_needs_to_be_updated = 1; 831 : } 832 : } 833 : 834 : /* copy the hash in the block, but doesn't mark the block as hashed */ 835 : /* this allow in case of skipped block to do not save the failed computation */ - 836 124319 : memcpy(block->hash, hash, HASH_SIZE); + 836 94431 : memcpy(block->hash, hash, HASH_SIZE); 837 : 838 : /* note that in case of rehash, this is the wrong hash, */ 839 : /* but it will be overwritten later */ @@ -905,52 +905,52 @@ 843 : /* if we have only silent errors we can try to fix them on-the-fly */ 844 : /* note the the fix is not written to disk, but used only to */ 845 : /* compute the new parity */ - 846 82341 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { + 846 91157 : if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { 847 : unsigned failed_mac; - 848 882 : int something_to_recover = 0; + 848 851 : int something_to_recover = 0; 849 : 850 : /* setup the blocks to recover */ - 851 882 : failed_mac = 0; - 852 2646 : for (j = 0; j < failed_count; ++j) { - 853 1764 : unsigned char* block_buffer = buffer[failed[j].index]; - 854 1764 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index]; - 855 1764 : unsigned block_state = block_state_get(failed[j].block); + 851 851 : failed_mac = 0; + 852 2553 : for (j = 0; j < failed_count; ++j) { + 853 1702 : unsigned char* block_buffer = buffer[failed[j].index]; + 854 1702 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index]; + 855 1702 : unsigned block_state = block_state_get(failed[j].block); 856 : 857 : /* we try to recover only if at least one BLK is present */ - 858 1764 : if (block_state == BLOCK_STATE_BLK) - 859 882 : something_to_recover = 1; + 858 1702 : if (block_state == BLOCK_STATE_BLK) + 859 851 : something_to_recover = 1; 860 : 861 : /* save a copy of the content just read */ 862 : /* that it's going to be overwritten by the recovering function */ - 863 1764 : memcpy(block_copy, block_buffer, state->block_size); + 863 1702 : memcpy(block_copy, block_buffer, state->block_size); 864 : - 865 1764 : if (block_state == BLOCK_STATE_CHG - 866 882 : && hash_is_zero(failed[j].block->hash) + 865 1702 : if (block_state == BLOCK_STATE_CHG + 866 851 : && hash_is_zero(failed[j].block->hash) 867 : ) { 868 : /* if the block was filled with 0, restore this state */ 869 : /* and avoid to recover it */ 870 0 : memset(block_buffer, 0, state->block_size); 871 : } else { 872 : /* if we have too many failures, we cannot recover */ - 873 1764 : if (failed_mac >= state->level) + 873 1702 : if (failed_mac >= state->level) 874 0 : break; 875 : 876 : /* otherwise it has to be recovered */ - 877 1764 : failed_map[failed_mac++] = failed[j].index; + 877 1702 : failed_map[failed_mac++] = failed[j].index; 878 : } 879 : } 880 : 881 : /* if we have something to recover and enough parity */ - 882 882 : if (something_to_recover && j == failed_count) { + 882 851 : if (something_to_recover && j == failed_count) { 883 : /* until now is CPU */ - 884 882 : state_usage_cpu(state); + 884 851 : state_usage_cpu(state); 885 : 886 : /* read the parity */ 887 : /* we are sure that parity exists because */ 888 : /* we have at least one BLK block */ - 889 6174 : for (l = 0; l < state->level; ++l) { - 890 5292 : ret = parity_read(parity[l], i, buffer[diskmax + l], state->block_size, log_error); - 891 5292 : if (ret == -1) { + 889 5957 : for (l = 0; l < state->level; ++l) { + 890 5106 : ret = parity_read(parity[l], i, buffer[diskmax + l], state->block_size, log_error); + 891 5106 : if (ret == -1) { 892 : /* LCOV_EXCL_START */ 893 : if (errno == EIO) { 894 : log_tag("parity_error:%u:%s: Read EIO error. %s\n", i, lev_config_name(l), strerror(errno)); @@ -978,74 +978,74 @@ 916 : } 917 : 918 : /* until now is parity */ - 919 5292 : state_usage_parity(state, l); + 919 5106 : state_usage_parity(state, l); 920 : } 921 : 922 : /* if no error in parity read */ - 923 882 : if (!io_error_on_this_block) { + 923 851 : if (!io_error_on_this_block) { 924 : /* try to fix the data */ 925 : /* note that this is a simple fix algorithm, that doesn't take into */ 926 : /* account the case of a wrong parity */ 927 : /* only 'fix' supports the most advanced fixing */ - 928 882 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer); + 928 851 : raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer); 929 : 930 : /* check the result and prepare the data */ - 931 5292 : for (j = 0; j < failed_count; ++j) { + 931 5106 : for (j = 0; j < failed_count; ++j) { 932 : unsigned char hash[HASH_SIZE]; - 933 1764 : unsigned char* block_buffer = buffer[failed[j].index]; - 934 1764 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index]; - 935 1764 : unsigned block_state = block_state_get(failed[j].block); + 933 1702 : unsigned char* block_buffer = buffer[failed[j].index]; + 934 1702 : unsigned char* block_copy = buffer[diskmax + state->level + failed[j].index]; + 935 1702 : unsigned block_state = block_state_get(failed[j].block); 936 : - 937 1764 : if (block_state == BLOCK_STATE_BLK) { - 938 882 : unsigned size = failed[j].size; + 937 1702 : if (block_state == BLOCK_STATE_BLK) { + 938 851 : unsigned size = failed[j].size; 939 : 940 : /* compute the hash of the recovered block */ - 941 882 : if (rehash) { + 941 851 : if (rehash) { 942 0 : memhash(state->prevhash, state->prevhashseed, hash, block_buffer, size); 943 : } else { - 944 882 : memhash(state->hash, state->hashseed, hash, block_buffer, size); + 944 851 : memhash(state->hash, state->hashseed, hash, block_buffer, size); 945 : } 946 : 947 : /* if the hash doesn't match */ - 948 882 : if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) { + 948 851 : if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) { 949 : /* we have not recovered */ 950 0 : break; 951 : } 952 : 953 : /* pad with 0 if needed */ - 954 882 : if (size < state->block_size) - 955 342 : memset(block_buffer + size, 0, state->block_size - size); + 954 851 : if (size < state->block_size) + 955 325 : memset(block_buffer + size, 0, state->block_size - size); 956 : } else { 957 : /* otherwise restore the content */ 958 : /* because we are not interested in the old state */ 959 : /* that it's recovered for CHG, REP and DELETED blocks */ - 960 882 : memcpy(block_buffer, block_copy, state->block_size); + 960 851 : memcpy(block_buffer, block_copy, state->block_size); 961 : } 962 : } 963 : 964 : /* if all is processed, we have fixed it */ - 965 882 : if (j == failed_count) - 966 882 : fixed_error_on_this_block = 1; + 965 851 : if (j == failed_count) + 966 851 : fixed_error_on_this_block = 1; 967 : } 968 : } 969 : } 970 : 971 : /* if we have read all the data required and it's correct, proceed with the parity */ - 972 82341 : if (!error_on_this_block && !io_error_on_this_block - 973 82322 : && (!silent_error_on_this_block || fixed_error_on_this_block) + 972 91157 : if (!error_on_this_block && !io_error_on_this_block + 973 91138 : && (!silent_error_on_this_block || fixed_error_on_this_block) 974 : ) { 975 : /* update the parity only if really needed */ - 976 82322 : if (parity_needs_to_be_updated) { + 976 91138 : if (parity_needs_to_be_updated) { 977 : /* compute the parity */ - 978 79972 : raid_gen(diskmax, state->level, state->block_size, buffer); + 978 88856 : raid_gen(diskmax, state->level, state->block_size, buffer); 979 : 980 : /* until now is CPU */ - 981 79972 : state_usage_cpu(state); + 981 88856 : state_usage_cpu(state); 982 : 983 : /* write the parity */ - 984 523484 : for (l = 0; l < state->level; ++l) { - 985 443512 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); - 986 443512 : if (ret == -1) { + 984 585697 : for (l = 0; l < state->level; ++l) { + 985 496841 : ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); + 986 496841 : if (ret == -1) { 987 : /* LCOV_EXCL_START */ 988 : if (errno == EIO) { 989 : log_tag("parity_error:%u:%s: Write EIO error. %s\n", i, lev_config_name(l), strerror(errno)); @@ -1073,35 +1073,35 @@ 1011 : } 1012 : 1013 : /* until now is parity */ - 1014 443512 : state_usage_parity(state, l); + 1014 496841 : state_usage_parity(state, l); 1015 : } 1016 : } 1017 : 1018 : /* if no error in parity write */ - 1019 82322 : if (!io_error_on_this_block) { + 1019 91138 : if (!io_error_on_this_block) { 1020 : /* for each disk, mark the blocks as processed */ - 1021 576254 : for (j = 0; j < diskmax; ++j) { + 1021 637966 : for (j = 0; j < diskmax; ++j) { 1022 : struct snapraid_block* block; 1023 : - 1024 493932 : if (!handle[j].disk) + 1024 546828 : if (!handle[j].disk) 1025 0 : continue; 1026 : - 1027 493932 : block = fs_par2block_get(handle[j].disk, i); + 1027 546828 : block = fs_par2block_get(handle[j].disk, i); 1028 : - 1029 493932 : if (block == BLOCK_EMPTY) { + 1029 546828 : if (block == BLOCK_EMPTY) { 1030 : /* nothing to do */ - 1031 77225 : continue; + 1031 79287 : continue; 1032 : } 1033 : 1034 : /* if it's a deleted block */ - 1035 416707 : if (block_state_get(block) == BLOCK_STATE_DELETED) { + 1035 467541 : if (block_state_get(block) == BLOCK_STATE_DELETED) { 1036 : /* the parity is now updated without this block, so it's now empty */ - 1037 11066 : fs_deallocate(handle[j].disk, i); - 1038 11066 : continue; + 1037 10929 : fs_deallocate(handle[j].disk, i); + 1038 10929 : continue; 1039 : } 1040 : 1041 : /* now all the blocks have the hash and the parity computed */ - 1042 405641 : block_state_set(block, BLOCK_STATE_BLK); + 1042 456612 : block_state_set(block, BLOCK_STATE_BLK); 1043 : } 1044 : } 1045 : @@ -1110,52 +1110,52 @@ 1048 : /* wrote the parity at this time */ 1049 : /* we also update the info block only if no silent error was found */ 1050 : /* because has no sense to refresh the time for data that we know bad */ - 1051 82322 : if (parity_needs_to_be_updated - 1052 79972 : && !silent_error_on_this_block - 1053 79625 : && !io_error_on_this_block + 1051 91138 : if (parity_needs_to_be_updated + 1052 88856 : && !silent_error_on_this_block + 1053 88511 : && !io_error_on_this_block 1054 : ) { 1055 : /* if rehash is neeed */ - 1056 79625 : if (rehash) { + 1056 88511 : if (rehash) { 1057 : /* store all the new hash already computed */ - 1058 64358 : for (j = 0; j < diskmax; ++j) { - 1059 55164 : if (rehandle[j].block) - 1060 52244 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE); + 1058 32221 : for (j = 0; j < diskmax; ++j) { + 1059 27618 : if (rehandle[j].block) + 1060 27231 : memcpy(rehandle[j].block->hash, rehandle[j].hash, HASH_SIZE); 1061 : } 1062 : } 1063 : 1064 : /* update the time info of the block */ 1065 : /* we are also clearing any previous bad and rehash flag */ - 1066 79625 : info_set(&state->infoarr, i, info_make(now, 0, 0, 1)); + 1066 88511 : info_set(&state->infoarr, i, info_make(now, 0, 0, 1)); 1067 : } 1068 : } 1069 : 1070 : /* if a silent (even if corrected) or input/output error was found */ 1071 : /* mark the block as bad to have check/fix to handle it */ 1072 : /* because our correction is in memory only and not yet written */ - 1073 82341 : if (silent_error_on_this_block || io_error_on_this_block) { + 1073 91157 : if (silent_error_on_this_block || io_error_on_this_block) { 1074 : /* set the error status keeping the other info */ - 1075 882 : info_set(&state->infoarr, i, info_set_bad(info)); + 1075 851 : info_set(&state->infoarr, i, info_set_bad(info)); 1076 : } 1077 : 1078 : /* mark the state as needing write */ - 1079 82341 : state->need_write = 1; + 1079 91157 : state->need_write = 1; 1080 : 1081 : /* count the number of processed block */ - 1082 82341 : ++countpos; + 1082 91157 : ++countpos; 1083 : 1084 : /* progress */ - 1085 82341 : if (state_progress(state, i, countpos, countmax, countsize)) { + 1085 91157 : if (state_progress(state, i, countpos, countmax, countsize)) { 1086 : /* LCOV_EXCL_START */ 1087 : break; 1088 : /* LCOV_EXCL_STOP */ 1089 : } 1090 : 1091 : /* autosave */ - 1092 82341 : if ((state->autosave != 0 - 1093 7264 : && autosavedone >= autosavelimit /* if we have reached the limit */ + 1092 91157 : if ((state->autosave != 0 + 1093 7259 : && autosavedone >= autosavelimit /* if we have reached the limit */ 1094 0 : && autosavemissing >= autosavelimit) /* if we have at least a full step to do */ 1095 : /* or if we have a forced autosave at the specified block */ - 1096 82341 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == i) + 1096 91157 : || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == i) 1097 : ) { 1098 1 : autosavedone = 0; /* restart the counter */ 1099 : @@ -1193,15 +1193,15 @@ 1131 : } 1132 : 1133 : end: - 1134 68 : state_progress_end(state, countpos, countmax, countsize); + 1134 76 : state_progress_end(state, countpos, countmax, countsize); 1135 : - 1136 68 : state_usage_print(state); + 1136 76 : state_usage_print(state); 1137 : 1138 : /* before returning we ensure that */ 1139 : /* the parity is really written flushing the disk cache */ - 1140 461 : for (l = 0; l < state->level; ++l) { - 1141 393 : ret = parity_sync(parity[l]); - 1142 393 : if (ret == -1) { + 1140 517 : for (l = 0; l < state->level; ++l) { + 1141 441 : ret = parity_sync(parity[l]); + 1142 441 : if (ret == -1) { 1143 : /* LCOV_EXCL_START */ 1144 : log_tag("parity_error:%u:%s: Sync error\n", i, lev_config_name(l)); 1145 : log_fatal("DANGER! Unexpected sync error in %s disk.\n", lev_name(l)); @@ -1213,43 +1213,43 @@ 1151 : } 1152 : } 1153 : - 1154 68 : if (error || silent_error || io_error) { + 1154 76 : if (error || silent_error || io_error) { 1155 12 : msg_status("\n"); 1156 12 : msg_status("%8u file errors\n", error); 1157 12 : msg_status("%8u io errors\n", io_error); 1158 12 : msg_status("%8u data errors\n", silent_error); 1159 : } else { 1160 : /* print the result only if processed something */ - 1161 56 : if (countpos != 0) - 1162 42 : msg_status("Everything OK\n"); + 1161 64 : if (countpos != 0) + 1162 47 : msg_status("Everything OK\n"); 1163 : } 1164 : - 1165 68 : if (error) + 1165 76 : if (error) 1166 11 : log_fatal("WARNING! Unexpected file errors!\n"); - 1167 68 : if (io_error) + 1167 76 : if (io_error) 1168 0 : log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n"); - 1169 68 : if (silent_error) + 1169 76 : if (silent_error) 1170 1 : log_fatal("DANGER! Unexpected data errors! The failing blocks are now marked as bad!\n"); - 1171 68 : if (io_error || silent_error) { + 1171 76 : if (io_error || silent_error) { 1172 1 : log_fatal("Use 'snapraid status' to list the bad blocks.\n"); 1173 1 : log_fatal("Use 'snapraid -e fix' to recover.\n"); 1174 : } 1175 : - 1176 68 : log_tag("summary:error_file:%u\n", error); - 1177 68 : log_tag("summary:error_io:%u\n", io_error); - 1178 68 : log_tag("summary:error_data:%u\n", silent_error); - 1179 68 : if (error + silent_error + io_error == 0) - 1180 56 : log_tag("summary:exit:ok\n"); + 1176 76 : log_tag("summary:error_file:%u\n", error); + 1177 76 : log_tag("summary:error_io:%u\n", io_error); + 1178 76 : log_tag("summary:error_data:%u\n", silent_error); + 1179 76 : if (error + silent_error + io_error == 0) + 1180 64 : log_tag("summary:exit:ok\n"); 1181 : else 1182 12 : log_tag("summary:exit:error\n"); - 1183 68 : log_flush(); + 1183 76 : log_flush(); 1184 : 1185 : bail: - 1186 476 : for (j = 0; j < diskmax; ++j) { - 1187 408 : struct snapraid_file* file = handle[j].file; - 1188 408 : struct snapraid_disk* disk = handle[j].disk; - 1189 408 : ret = handle_close(&handle[j]); - 1190 408 : if (ret == -1) { + 1186 532 : for (j = 0; j < diskmax; ++j) { + 1187 456 : struct snapraid_file* file = handle[j].file; + 1188 456 : struct snapraid_disk* disk = handle[j].disk; + 1189 456 : ret = handle_close(&handle[j]); + 1190 456 : if (ret == -1) { 1191 : /* LCOV_EXCL_START */ 1192 : log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc(file->sub), strerror(errno)); 1193 : log_fatal("DANGER! Unexpected close error in a data disk.\n"); @@ -1259,24 +1259,24 @@ 1197 : } 1198 : } 1199 : - 1200 68 : free(handle); - 1201 68 : free(buffer_alloc); - 1202 68 : free(buffer); - 1203 68 : free(rehandle_alloc); - 1204 68 : free(failed); - 1205 68 : free(failed_map); + 1200 76 : free(handle); + 1201 76 : free(buffer_alloc); + 1202 76 : free(buffer); + 1203 76 : free(rehandle_alloc); + 1204 76 : free(failed); + 1205 76 : free(failed_map); 1206 : - 1207 68 : if (state->opt.expect_recoverable) { + 1207 76 : if (state->opt.expect_recoverable) { 1208 1 : if (error + silent_error + io_error == 0) 1209 0 : return -1; 1210 : } else { - 1211 67 : if (error + silent_error + io_error != 0) + 1211 75 : if (error + silent_error + io_error != 0) 1212 11 : return -1; 1213 : } - 1214 57 : return 0; + 1214 65 : return 0; 1215 : } 1216 : - 1217 72 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount) + 1217 80 : int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount) 1218 : { 1219 : block_off_t blockmax; 1220 : block_off_t used_paritymax; @@ -1287,23 +1287,23 @@ 1225 : struct snapraid_parity_handle parity[LEV_MAX]; 1226 : /* the following initialization is to avoid clang warnings about */ 1227 : /* potential state->level change, that never happens */ - 1228 72 : struct snapraid_parity_handle* parity_ptr[LEV_MAX] = { 0 }; + 1228 80 : struct snapraid_parity_handle* parity_ptr[LEV_MAX] = { 0 }; 1229 : unsigned unrecoverable_error; 1230 : unsigned l; - 1231 72 : int skip_sync = 0; + 1231 80 : int skip_sync = 0; 1232 : - 1233 72 : msg_progress("Initializing...\n"); + 1233 80 : msg_progress("Initializing...\n"); 1234 : - 1235 72 : blockmax = parity_allocated_size(state); - 1236 72 : size = blockmax * (data_off_t)state->block_size; + 1235 80 : blockmax = parity_allocated_size(state); + 1236 80 : size = blockmax * (data_off_t)state->block_size; 1237 : 1238 : /* minum size of the parity files we expect */ - 1239 72 : used_paritymax = parity_used_size(state); + 1239 80 : used_paritymax = parity_used_size(state); 1240 : 1241 : /* effective size of the parity files */ - 1242 72 : file_paritymax = 0; + 1242 80 : file_paritymax = 0; 1243 : - 1244 72 : if (blockstart > blockmax) { + 1244 80 : if (blockstart > blockmax) { 1245 : /* LCOV_EXCL_START */ 1246 : log_fatal("Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); 1247 : exit(EXIT_FAILURE); @@ -1311,17 +1311,17 @@ 1249 : } 1250 : 1251 : /* adjust the number of block to process */ - 1252 72 : if (blockcount != 0 && blockstart + blockcount < blockmax) { + 1252 80 : if (blockcount != 0 && blockstart + blockcount < blockmax) { 1253 6 : blockmax = blockstart + blockcount; 1254 : } 1255 : - 1256 489 : for (l = 0; l < state->level; ++l) { + 1256 545 : for (l = 0; l < state->level; ++l) { 1257 : block_off_t parityblocks; 1258 : 1259 : /* create the file and open for writing */ - 1260 417 : parity_ptr[l] = &parity[l]; - 1261 417 : ret = parity_create(parity_ptr[l], state->parity[l].path, &out_size, state->file_mode); - 1262 417 : if (ret == -1) { + 1260 465 : parity_ptr[l] = &parity[l]; + 1261 465 : ret = parity_create(parity_ptr[l], state->parity[l].path, &out_size, state->file_mode); + 1262 465 : if (ret == -1) { 1263 : /* LCOV_EXCL_START */ 1264 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); 1265 : exit(EXIT_FAILURE); @@ -1329,22 +1329,22 @@ 1267 : } 1268 : 1269 : /* number of block in the parity file */ - 1270 417 : parityblocks = out_size / state->block_size; + 1270 465 : parityblocks = out_size / state->block_size; 1271 : 1272 : /* if the file is too small */ - 1273 417 : if (parityblocks < used_paritymax) { + 1273 465 : if (parityblocks < used_paritymax) { 1274 0 : log_fatal("WARNING! The %s file %s has data only %u blocks instead of %u.\n", lev_name(l), state->parity[l].path, parityblocks, used_paritymax); 1275 : } 1276 : 1277 : /* keep the smallest parity number of blocks */ - 1278 417 : if (l == 0 || file_paritymax > parityblocks) - 1279 72 : file_paritymax = parityblocks; + 1278 465 : if (l == 0 || file_paritymax > parityblocks) + 1279 80 : file_paritymax = parityblocks; 1280 : } 1281 : 1282 : /* if we do a full sync, having a wrong parity size is expected */ - 1283 72 : if (!state->opt.force_full) { + 1283 80 : if (!state->opt.force_full) { 1284 : /* if the parities are too small */ - 1285 71 : if (file_paritymax < used_paritymax) { + 1285 78 : if (file_paritymax < used_paritymax) { 1286 : /* LCOV_EXCL_START */ 1287 : log_fatal("DANGER! One or more the parity files are smaller than expected!\n"); 1288 : if (file_paritymax != 0) { @@ -1362,12 +1362,12 @@ 1300 : } 1301 : 1302 : /* now change the size of all parities */ - 1303 489 : for (l = 0; l < state->level; ++l) { + 1303 545 : for (l = 0; l < state->level; ++l) { 1304 : /* change the size of the parity file, truncating or extending it */ 1305 : /* from this point all the DELETED blocks after the end of the parity are invalid */ 1306 : /* and they are automatically removed when we save the new content file */ - 1307 417 : ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate); - 1308 417 : if (ret == -1) { + 1307 465 : ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate); + 1308 465 : if (ret == -1) { 1309 : /* LCOV_EXCL_START */ 1310 : parity_overflow(state, out_size); 1311 : log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); @@ -1377,11 +1377,11 @@ 1315 : } 1316 : 1317 : /* after resizing parity files, refresh again the free info */ - 1318 72 : state_refresh(state); + 1318 80 : state_refresh(state); 1319 : - 1320 72 : unrecoverable_error = 0; + 1320 80 : unrecoverable_error = 0; 1321 : - 1322 72 : if (state->opt.prehash) { + 1322 80 : if (state->opt.prehash) { 1323 7 : msg_progress("Hashing...\n"); 1324 : 1325 7 : ret = state_hash_process(state, blockstart, blockmax, &skip_sync); @@ -1394,16 +1394,16 @@ 1332 : 1333 : /* save with the new hash information */ 1334 7 : if (state->need_write) - 1335 3 : state_write(state); + 1335 2 : state_write(state); 1336 : } 1337 : - 1338 72 : if (!skip_sync) { - 1339 71 : msg_progress("Syncing...\n"); + 1338 80 : if (!skip_sync) { + 1339 79 : msg_progress("Syncing...\n"); 1340 : 1341 : /* skip degenerated cases of empty parity, or skipping all */ - 1342 71 : if (blockstart < blockmax) { - 1343 68 : ret = state_sync_process(state, parity_ptr, blockstart, blockmax); - 1344 68 : if (ret == -1) { + 1342 79 : if (blockstart < blockmax) { + 1343 76 : ret = state_sync_process(state, parity_ptr, blockstart, blockmax); + 1344 76 : if (ret == -1) { 1345 : /* LCOV_EXCL_START */ 1346 : ++unrecoverable_error; 1347 : /* continue, as we are already exiting */ @@ -1414,9 +1414,9 @@ 1352 : } 1353 : } 1354 : - 1355 489 : for (l = 0; l < state->level; ++l) { - 1356 417 : ret = parity_close(parity_ptr[l]); - 1357 417 : if (ret == -1) { + 1355 545 : for (l = 0; l < state->level; ++l) { + 1356 465 : ret = parity_close(parity_ptr[l]); + 1357 465 : if (ret == -1) { 1358 : /* LCOV_EXCL_START */ 1359 : log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); 1360 : ++unrecoverable_error; @@ -1426,9 +1426,9 @@ 1364 : } 1365 : 1366 : /* abort if required */ - 1367 72 : if (unrecoverable_error != 0) + 1367 80 : if (unrecoverable_error != 0) 1368 12 : return -1; - 1369 60 : return 0; + 1369 68 : return 0; 1370 : } 1371 : diff --git a/cov/cmdline/unix.c.func-sort-c.html b/cov/cmdline/unix.c.func-sort-c.html index 5b352a9b..c194779e 100644 --- a/cov/cmdline/unix.c.func-sort-c.html +++ b/cov/cmdline/unix.c.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 229 - 289 - 79.2 % + 255 + 332 + 76.8 % Date: - 2015-11-20 + 2016-01-09 Functions: - 21 23 - 91.3 % + 25 + 92.0 % @@ -60,87 +60,95 @@ Hit count Sort by hit count - tick - 2049010 + tick + 2214352 open_noatime - 1640600 + 1661733 - filephy + filephy 11432 - devuuid - 2279 + fsinfo + 2415 - fsinfo - 2175 + devuuid + 2404 - randomize - 263 + devuuid_dev + 2404 - os_init - 252 + randomize + 271 - os_done - 230 + os_init + 260 - devresolve + os_done + 238 + + + devresolve 97 - devread + devread 86 - devtree + devtree 72 - tick_ms + tick_ms 36 - thread_smart + devsmart 25 - devsmart - 25 + thread_smart + 22 - thread_spindown + thread_spindown 12 - devdown + devdown 12 - devup + devup 12 - thread_spinup + thread_spinup 12 - devquery + devquery 4 - device_thread + device_thread 3 - devscan + devscan + 1 + + + devuuid_blkid 1 diff --git a/cov/cmdline/unix.c.func.html b/cov/cmdline/unix.c.func.html index bd939ad7..c3a13d67 100644 --- a/cov/cmdline/unix.c.func.html +++ b/cov/cmdline/unix.c.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 229 - 289 - 79.2 % + 255 + 332 + 76.8 % Date: - 2015-11-20 + 2016-01-09 Functions: - 21 23 - 91.3 % + 25 + 92.0 % @@ -60,95 +60,103 @@ Hit count Sort by hit count - devdown + devdown 12 - device_thread + device_thread 3 - devquery + devquery 4 - devread + devread 86 - devresolve + devresolve 97 - devscan + devscan 1 - devsmart + devsmart 25 - devtree + devtree 72 - devup + devup 12 - devuuid - 2279 + devuuid + 2404 + + + devuuid_blkid + 1 + + + devuuid_dev + 2404 dirent_hidden 0 - filephy + filephy 11432 - fsinfo - 2175 + fsinfo + 2415 open_noatime - 1640600 + 1661733 - os_done - 230 + os_done + 238 - os_init - 252 + os_init + 260 - randomize - 263 + randomize + 271 stat_desc 0 - thread_smart - 25 + thread_smart + 22 - thread_spindown + thread_spindown 12 - thread_spinup + thread_spinup 12 - tick - 2049010 + tick + 2214352 - tick_ms + tick_ms 36 diff --git a/cov/cmdline/unix.c.gcov.html b/cov/cmdline/unix.c.gcov.html index 3a428fcf..59fb3346 100644 --- a/cov/cmdline/unix.c.gcov.html +++ b/cov/cmdline/unix.c.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 229 - 289 - 79.2 % + 255 + 332 + 76.8 % Date: - 2015-11-20 + 2016-01-09 Functions: - 21 23 - 91.3 % + 25 + 92.0 % @@ -90,15 +90,15 @@ 28 : int exit_failure = 1; 29 : int exit_sync_needed = 2; 30 : - 31 1640600 : int open_noatime(const char* file, int flags) + 31 1661733 : int open_noatime(const char* file, int flags) 32 : { 33 : #ifdef O_NOATIME - 34 1640600 : int f = open(file, flags | O_NOATIME); + 34 1661733 : int f = open(file, flags | O_NOATIME); 35 : 36 : /* only root is allowed to use O_NOATIME, in case retry without it */ - 37 1640600 : if (f == -1 && errno == EPERM) + 37 1661733 : if (f == -1 && errno == EPERM) 38 0 : f = open(file, flags); - 39 1640600 : return f; + 39 1661733 : return f; 40 : #else 41 : return open(file, flags); 42 : #endif @@ -130,952 +130,1123 @@ 68 0 : return "unknown"; 69 : } 70 : - 71 : #if HAVE_FSTATAT - 72 : /** - 73 : * This function get the UUID using the /dev/disk/by-uuid/ links. - 74 : * Comparing with the libblkid library, it works also from not root processes. - 75 : */ - 76 2279 : int devuuid(uint64_t device, char* uuid, size_t uuid_size) - 77 : { - 78 : int ret; - 79 : DIR* d; - 80 : struct dirent* dd; - 81 : struct stat st; - 82 : - 83 : /* scan the UUID directory searching for the device */ - 84 2279 : d = opendir("/dev/disk/by-uuid"); - 85 2279 : if (!d) { - 86 : /* directory missing?, likely we are not in Linux */ - 87 0 : return -1; - 88 : } - 89 : - 90 38781 : while ((dd = readdir(d)) != 0) { - 91 : /* skip "." and ".." files, UUIDs never start with '.' */ - 92 36500 : if (dd->d_name[0] == '.') - 93 4558 : continue; - 94 : - 95 31942 : ret = fstatat(dirfd(d), dd->d_name, &st, 0); - 96 31942 : if (ret != 0) { - 97 : /* generic error, ignore and continue the search */ - 98 0 : continue; - 99 : } - 100 : - 101 : /* if it matches, we have the uuid */ - 102 31942 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { - 103 : /* found */ - 104 2277 : pathcpy(uuid, uuid_size, dd->d_name); - 105 2277 : closedir(d); - 106 2277 : return 0; - 107 : } - 108 : } - 109 : - 110 : /* not found */ - 111 2 : closedir(d); - 112 2 : return -1; - 113 : } - 114 : #else - 115 : int devuuid(uint64_t device, char* uuid, size_t uuid_size) - 116 : { - 117 : (void)device; - 118 : (void)uuid; - 119 : (void)uuid_size; - 120 : - 121 : /* not supported */ - 122 : return -1; - 123 : } - 124 : #endif - 125 : - 126 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) - 127 : { - 128 : #if HAVE_LINUX_FIEMAP_H - 129 : /* In Linux get the real physical address of the file */ - 130 : /* Note that FIEMAP doesn't require root permission */ - 131 : int f; - 132 : struct { - 133 : struct fiemap fiemap; - 134 : struct fiemap_extent extent; - 135 : } fm; - 136 : unsigned int blknum; - 137 : - 138 11432 : f = open(path, O_RDONLY); - 139 11432 : if (f == -1) { - 140 0 : return -1; - 141 : } + 71 : /** + 72 : * Cache used by blkid. + 73 : */ + 74 : #if HAVE_BLKID + 75 : static blkid_cache cache = 0; + 76 : #endif + 77 : + 78 : /** + 79 : * Get the UUID using the /dev/disk/by-uuid/ links. + 80 : * It doesn't require root permission, and the uuid are always updated. + 81 : * It doesn't work with Btrfs file-systems that don't export the main UUID + 82 : * in /dev/disk/by-uuid/. + 83 : */ + 84 : #if HAVE_FSTATAT + 85 2404 : static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) + 86 : { + 87 : int ret; + 88 : DIR* d; + 89 : struct dirent* dd; + 90 : struct stat st; + 91 : + 92 : /* scan the UUID directory searching for the device */ + 93 2404 : d = opendir("/dev/disk/by-uuid"); + 94 2404 : if (!d) { + 95 0 : log_tag("uuid:by-uuidd:%u:%u: opendir(/dev/disk/by-uuid) failed\n", major(device), minor(device)); + 96 : /* directory missing?, likely we are not in Linux */ + 97 0 : return -1; + 98 : } + 99 : + 100 40887 : while ((dd = readdir(d)) != 0) { + 101 : /* skip "." and ".." files, UUIDs never start with '.' */ + 102 38482 : if (dd->d_name[0] == '.') + 103 4808 : continue; + 104 : + 105 33674 : ret = fstatat(dirfd(d), dd->d_name, &st, 0); + 106 33674 : if (ret != 0) { + 107 0 : log_tag("uuid:by-uuidd:%u:%u: fstatat(%s) failed\n", major(device), minor(device), dd->d_name); + 108 : /* generic error, ignore and continue the search */ + 109 0 : continue; + 110 : } + 111 : + 112 : /* if it matches, we have the uuid */ + 113 33674 : if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { + 114 : char buf[PATH_MAX]; + 115 : char path[PATH_MAX]; + 116 : + 117 : /* resolve the link */ + 118 2403 : pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); + 119 2403 : ret = readlink(path, buf, sizeof(buf)); + 120 2403 : if (ret < 0 || ret == sizeof(buf)) { + 121 0 : log_tag("uuid:by-uuidd:%u:%u: readlink(/dev/disk/by-uuid/%s) failed\n", major(device), minor(device), dd->d_name); + 122 : /* generic error, ignore and continue the search */ + 123 0 : continue; + 124 : } + 125 2403 : buf[ret] = 0; + 126 : + 127 : /* found */ + 128 2403 : pathcpy(uuid, uuid_size, dd->d_name); + 129 : + 130 2403 : log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); + 131 : + 132 2403 : closedir(d); + 133 2403 : return 0; + 134 : } + 135 : } + 136 : + 137 : /* not found */ + 138 1 : closedir(d); + 139 1 : return -1; + 140 : } + 141 : #endif 142 : - 143 : /* first try with FIEMAP */ - 144 : /* if works for ext2, ext3, ext4, xfs, btrfs */ - 145 11432 : memset(&fm, 0, sizeof(fm)); - 146 11432 : fm.fiemap.fm_start = 0; - 147 11432 : fm.fiemap.fm_length = ~0ULL; - 148 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ - 149 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */ - 150 : - 151 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) { - 152 11432 : *physical = fm.fiemap.fm_extents[0].fe_physical + FILEPHY_REAL_OFFSET; - 153 11432 : if (close(f) == -1) - 154 0 : return -1; - 155 11432 : return 0; - 156 : } - 157 : - 158 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ - 159 0 : if (size == 0) { - 160 0 : *physical = FILEPHY_WITHOUT_OFFSET; - 161 0 : if (close(f) == -1) - 162 0 : return -1; - 163 0 : return 0; - 164 : } - 165 : - 166 : /* then try with FIBMAP */ - 167 : /* it works for jfs, reiserfs, ntfs-3g */ - 168 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ - 169 0 : blknum = 0; /* first block */ - 170 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { - 171 0 : *physical = blknum + FILEPHY_REAL_OFFSET; - 172 0 : if (close(f) == -1) - 173 0 : return -1; - 174 0 : return 0; - 175 : } - 176 : - 177 : /* otherwise don't use anything, and keep the directory traversal order */ - 178 : /* at now this should happen only for vfat */ - 179 : /* and it's surely better than using fake inodes */ - 180 0 : *physical = FILEPHY_UNREPORTED_OFFSET; - 181 0 : if (close(f) == -1) - 182 0 : return -1; - 183 : #else - 184 : /* In a generic Unix use a dummy value for all the files */ - 185 : /* We don't want to risk to use the inode without knowing */ - 186 : /* if it really improves performance. */ - 187 : /* In this way we keep them in the directory traversal order */ - 188 : /* that at least keeps files in the same directory together. */ - 189 : /* Note also that in newer filesystem with snapshot, like ZFS, */ - 190 : /* the inode doesn't represent even less the disk position, because files */ - 191 : /* are not overwritten in place, but rewritten in another location */ - 192 : /* of the disk. */ - 193 : *physical = FILEPHY_UNREPORTED_OFFSET; - 194 : - 195 : (void)path; /* not used here */ - 196 : (void)size; - 197 : #endif - 198 : - 199 0 : return 0; - 200 : } - 201 : - 202 2175 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space) - 203 : { - 204 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE - 205 : struct statfs st; - 206 : - 207 2175 : if (statfs(path, &st) != 0) { - 208 : char dir[PATH_MAX]; - 209 : char* slash; - 210 : - 211 6 : if (errno != ENOENT) { - 212 0 : return -1; - 213 : } - 214 : - 215 : /* if it doesn't exist, we assume a file */ - 216 : /* and we check for the containing dir */ - 217 6 : if (strlen(path) + 1 > sizeof(dir)) { - 218 0 : errno = ENAMETOOLONG; - 219 0 : return -1; - 220 : } - 221 : - 222 6 : strcpy(dir, path); - 223 : - 224 6 : slash = strrchr(dir, '/'); - 225 6 : if (!slash) - 226 0 : return -1; - 227 : - 228 6 : *slash = 0; - 229 6 : if (statfs(dir, &st) != 0) - 230 0 : return -1; - 231 : } + 143 : /** + 144 : * Get the UUID using liblkid. + 145 : * It uses a cache to work without root permission, resultin in UUID + 146 : * not necessarily recent. + 147 : * We could call blkid_probe_all() to refresh the UUID, but it would + 148 : * require root permission to read the superblocks, and to have + 149 : * all the disks spinning. + 150 : */ + 151 : #if HAVE_BLKID + 152 1 : static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) + 153 : { + 154 : char* devname; + 155 : char* uuidname; + 156 : + 157 1 : devname = blkid_devno_to_devname(device); + 158 1 : if (!devname) { + 159 1 : log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed\n", major(device), minor(device)); + 160 : /* device mapping failed */ + 161 1 : return -1; + 162 : } + 163 : + 164 0 : uuidname = blkid_get_tag_value(cache, "UUID", devname); + 165 0 : if (!uuidname) { + 166 0 : log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(%s) failed\n", major(device), minor(device), devname); + 167 : /* uuid mapping failed */ + 168 0 : free(devname); + 169 0 : return -1; + 170 : } + 171 : + 172 0 : pathcpy(uuid, uuid_size, uuidname); + 173 : + 174 0 : log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); + 175 : + 176 0 : free(devname); + 177 0 : free(uuidname); + 178 0 : return 0; + 179 : } + 180 : #endif + 181 : + 182 2404 : int devuuid(uint64_t device, char* uuid, size_t uuid_size) + 183 : { + 184 : /* first try with the /dev/disk/by-uuid version */ + 185 : #if HAVE_FSTATAT + 186 2404 : if (devuuid_dev(device, uuid, uuid_size) == 0) + 187 2403 : return 0; + 188 : #endif + 189 : + 190 : /* fall back to blkid for other cases */ + 191 : #if HAVE_BLKID + 192 1 : if (devuuid_blkid(device, uuid, uuid_size) == 0) + 193 0 : return 0; + 194 : #endif + 195 : + 196 1 : log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); + 197 : + 198 : /* not supported */ + 199 : (void)uuid; + 200 : (void)uuid_size; + 201 1 : return -1; + 202 : } + 203 : + 204 11432 : int filephy(const char* path, uint64_t size, uint64_t* physical) + 205 : { + 206 : #if HAVE_LINUX_FIEMAP_H + 207 : /* In Linux get the real physical address of the file */ + 208 : /* Note that FIEMAP doesn't require root permission */ + 209 : int f; + 210 : struct { + 211 : struct fiemap fiemap; + 212 : struct fiemap_extent extent; + 213 : } fm; + 214 : unsigned int blknum; + 215 : + 216 11432 : f = open(path, O_RDONLY); + 217 11432 : if (f == -1) { + 218 0 : return -1; + 219 : } + 220 : + 221 : /* first try with FIEMAP */ + 222 : /* if works for ext2, ext3, ext4, xfs, btrfs */ + 223 11432 : memset(&fm, 0, sizeof(fm)); + 224 11432 : fm.fiemap.fm_start = 0; + 225 11432 : fm.fiemap.fm_length = ~0ULL; + 226 11432 : fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ + 227 11432 : fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */ + 228 : + 229 11432 : if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) { + 230 11432 : uint32_t flags = fm.fiemap.fm_extents[0].fe_flags; + 231 11432 : uint64_t offset = fm.fiemap.fm_extents[0].fe_physical; 232 : - 233 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ - 234 2175 : if (has_persistent_inode) - 235 479 : switch (st.f_type) { - 236 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */ - 237 : case 0x4d44 : /* VFAT, "msdos" in the stat command */ - 238 0 : *has_persistent_inode = 0; - 239 0 : break; - 240 : default : - 241 : /* by default assume yes */ - 242 479 : *has_persistent_inode = 1; - 243 479 : break; - 244 : } - 245 : - 246 2175 : if (total_space) - 247 1696 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; - 248 2175 : if (free_space) - 249 1696 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; - 250 : #else - 251 : (void)path; - 252 : - 253 : /* by default assume yes */ - 254 : if (has_persistent_inode) - 255 : *has_persistent_inode = 1; - 256 : if (total_space) - 257 : *total_space = 0; - 258 : if (free_space) - 259 : *free_space = 0; - 260 : #endif + 233 : /* check some condition for validating the offset */ + 234 11432 : if (flags & FIEMAP_EXTENT_DATA_INLINE) { + 235 : /* if the data is inline, we don't have an offset to report */ + 236 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 237 11432 : } else if (flags & FIEMAP_EXTENT_UNKNOWN) { + 238 : /* if the offset is unknown, we don't have an offset to report */ + 239 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 240 11432 : } else if (offset == 0) { + 241 : /* 0 is the general fallback for file-systems when */ + 242 : /* they don't have an offset to report */ + 243 14 : *physical = FILEPHY_WITHOUT_OFFSET; + 244 : } else { + 245 : /* finally report the real offset */ + 246 11418 : *physical = offset + FILEPHY_REAL_OFFSET; + 247 : } + 248 : + 249 11432 : if (close(f) == -1) + 250 0 : return -1; + 251 11432 : return 0; + 252 : } + 253 : + 254 : /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ + 255 0 : if (size == 0) { + 256 0 : *physical = FILEPHY_WITHOUT_OFFSET; + 257 0 : if (close(f) == -1) + 258 0 : return -1; + 259 0 : return 0; + 260 : } 261 : - 262 2175 : return 0; - 263 : } - 264 : - 265 2049010 : uint64_t tick(void) - 266 : { - 267 : #if HAVE_MACH_ABSOLUTE_TIME - 268 : /* for Mac OS X */ - 269 : return mach_absolute_time(); - 270 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) - 271 : /* for Linux */ - 272 : struct timespec tv; - 273 : - 274 : /* nanosecond precision with clock_gettime() */ - 275 : #if defined(CLOCK_MONOTONIC_RAW) - 276 2049010 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { - 277 : #else - 278 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { - 279 : #endif - 280 0 : return 0; - 281 : } - 282 : - 283 2049010 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; - 284 : #else - 285 : /* other platforms */ - 286 : struct timeval tv; - 287 : - 288 : /* microsecond precision with gettimeofday() */ - 289 : if (gettimeofday(&tv, 0) != 0) { - 290 : return 0; - 291 : } - 292 : - 293 : return tv.tv_sec * 1000000ULL + tv.tv_usec; - 294 : #endif - 295 : } - 296 : - 297 36 : uint64_t tick_ms(void) - 298 : { - 299 : struct timeval tv; - 300 : - 301 36 : if (gettimeofday(&tv, 0) != 0) - 302 0 : return 0; - 303 : - 304 36 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; - 305 : } + 262 : /* then try with FIBMAP */ + 263 : /* it works for jfs, reiserfs, ntfs-3g */ + 264 : /* in exfat it always returns 0, that it's anyway better than the fake inodes */ + 265 0 : blknum = 0; /* first block */ + 266 0 : if (ioctl(f, FIBMAP, &blknum) != -1) { + 267 0 : *physical = blknum + FILEPHY_REAL_OFFSET; + 268 0 : if (close(f) == -1) + 269 0 : return -1; + 270 0 : return 0; + 271 : } + 272 : + 273 : /* otherwise don't use anything, and keep the directory traversal order */ + 274 : /* at now this should happen only for vfat */ + 275 : /* and it's surely better than using fake inodes */ + 276 0 : *physical = FILEPHY_UNREPORTED_OFFSET; + 277 0 : if (close(f) == -1) + 278 0 : return -1; + 279 : #else + 280 : /* In a generic Unix use a dummy value for all the files */ + 281 : /* We don't want to risk to use the inode without knowing */ + 282 : /* if it really improves performance. */ + 283 : /* In this way we keep them in the directory traversal order */ + 284 : /* that at least keeps files in the same directory together. */ + 285 : /* Note also that in newer file-system with snapshot, like ZFS, */ + 286 : /* the inode doesn't represent even less the disk position, because files */ + 287 : /* are not overwritten in place, but rewritten in another location */ + 288 : /* of the disk. */ + 289 : *physical = FILEPHY_UNREPORTED_OFFSET; + 290 : + 291 : (void)path; /* not used here */ + 292 : (void)size; + 293 : #endif + 294 : + 295 0 : return 0; + 296 : } + 297 : + 298 2415 : int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space) + 299 : { + 300 : #if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + 301 : struct statfs st; + 302 : + 303 2415 : if (statfs(path, &st) != 0) { + 304 : char dir[PATH_MAX]; + 305 : char* slash; 306 : - 307 263 : int randomize(void* ptr, size_t size) - 308 : { - 309 : int f; - 310 : ssize_t ret; - 311 : - 312 263 : f = open("/dev/urandom", O_RDONLY); - 313 263 : if (f == -1) - 314 0 : return -1; - 315 : - 316 263 : ret = read(f, ptr, size); - 317 263 : if (ret < 0 || (size_t)ret != size) { - 318 0 : close(f); - 319 0 : return -1; - 320 : } - 321 : - 322 263 : if (close(f) != 0) - 323 0 : return -1; - 324 : - 325 263 : return 0; - 326 : } - 327 : - 328 : /** - 329 : * Read a file extracting the contained device number in %u:%u format. - 330 : * Return 0 on error. - 331 : */ - 332 : #if HAVE_LINUX_DEVICE - 333 86 : static dev_t devread(const char* path) - 334 : { - 335 : int f; - 336 : int ret; - 337 : char buf[64]; - 338 : char* e; - 339 : unsigned ma; - 340 : unsigned mi; + 307 6 : if (errno != ENOENT) { + 308 0 : return -1; + 309 : } + 310 : + 311 : /* if it doesn't exist, we assume a file */ + 312 : /* and we check for the containing dir */ + 313 6 : if (strlen(path) + 1 > sizeof(dir)) { + 314 0 : errno = ENAMETOOLONG; + 315 0 : return -1; + 316 : } + 317 : + 318 6 : strcpy(dir, path); + 319 : + 320 6 : slash = strrchr(dir, '/'); + 321 6 : if (!slash) + 322 0 : return -1; + 323 : + 324 6 : *slash = 0; + 325 6 : if (statfs(dir, &st) != 0) + 326 0 : return -1; + 327 : } + 328 : + 329 : /* to get the fs type check "man stat" or "stat -f -t FILE" */ + 330 2415 : if (has_persistent_inode) + 331 527 : switch (st.f_type) { + 332 : case 0x65735546 : /* FUSE, "fuseblk" in the stat command */ + 333 : case 0x4d44 : /* VFAT, "msdos" in the stat command */ + 334 0 : *has_persistent_inode = 0; + 335 0 : break; + 336 : default : + 337 : /* by default assume yes */ + 338 527 : *has_persistent_inode = 1; + 339 527 : break; + 340 : } 341 : - 342 86 : f = open(path, O_RDONLY); - 343 86 : if (f == -1) { - 344 : /* LCOV_EXCL_START */ - 345 : log_fatal("Failed to open '%s'.\n", path); - 346 : return 0; - 347 : /* LCOV_EXCL_STOP */ - 348 : } - 349 : - 350 86 : ret = read(f, buf, sizeof(buf)); - 351 86 : if (ret < 0) { - 352 : /* LCOV_EXCL_START */ - 353 : close(f); - 354 : log_fatal("Failed to read '%s'.\n", path); - 355 : return 0; - 356 : /* LCOV_EXCL_STOP */ - 357 : } - 358 86 : if (ret == sizeof(buf)) { - 359 : /* LCOV_EXCL_START */ - 360 : close(f); - 361 : log_fatal("Too long read '%s'.\n", path); - 362 : return 0; - 363 : /* LCOV_EXCL_STOP */ - 364 : } - 365 : - 366 86 : buf[ret] = 0; - 367 : - 368 86 : ma = strtoul(buf, &e, 10); - 369 86 : if (*e != ':') { - 370 : /* LCOV_EXCL_START */ - 371 : close(f); - 372 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); - 373 : return 0; - 374 : /* LCOV_EXCL_STOP */ - 375 : } - 376 : - 377 86 : mi = strtoul(e+1, &e, 10); - 378 86 : if (*e != 0 && !isspace(*e)) { - 379 : /* LCOV_EXCL_START */ - 380 : close(f); - 381 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); - 382 : return 0; - 383 : /* LCOV_EXCL_STOP */ - 384 : } - 385 : - 386 86 : ret = close(f); - 387 86 : if (ret != 0) { - 388 : /* LCOV_EXCL_START */ - 389 : log_fatal("Failed to close '%s'.\n", path); - 390 : return 0; - 391 : /* LCOV_EXCL_STOP */ - 392 : } - 393 : - 394 86 : return makedev(ma, mi); - 395 : } - 396 : #endif - 397 : - 398 : #if HAVE_LINUX_DEVICE - 399 : /** - 400 : * Get the device file from the device number. - 401 : */ - 402 97 : static int devresolve(dev_t device, char* path, size_t path_size) - 403 : { - 404 : struct stat st; - 405 : char buf[PATH_MAX]; - 406 : int ret; + 342 2415 : if (total_space) + 343 1888 : *total_space = st.f_bsize * (uint64_t)st.f_blocks; + 344 2415 : if (free_space) + 345 1888 : *free_space = st.f_bsize * (uint64_t)st.f_bfree; + 346 : #else + 347 : (void)path; + 348 : + 349 : /* by default assume yes */ + 350 : if (has_persistent_inode) + 351 : *has_persistent_inode = 1; + 352 : if (total_space) + 353 : *total_space = 0; + 354 : if (free_space) + 355 : *free_space = 0; + 356 : #endif + 357 : + 358 2415 : return 0; + 359 : } + 360 : + 361 2214352 : uint64_t tick(void) + 362 : { + 363 : #if HAVE_MACH_ABSOLUTE_TIME + 364 : /* for Mac OS X */ + 365 : return mach_absolute_time(); + 366 : #elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) + 367 : /* for Linux */ + 368 : struct timespec tv; + 369 : + 370 : /* nanosecond precision with clock_gettime() */ + 371 : #if defined(CLOCK_MONOTONIC_RAW) + 372 2214352 : if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { + 373 : #else + 374 : if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { + 375 : #endif + 376 0 : return 0; + 377 : } + 378 : + 379 2214352 : return tv.tv_sec * 1000000000ULL + tv.tv_nsec; + 380 : #else + 381 : /* other platforms */ + 382 : struct timeval tv; + 383 : + 384 : /* microsecond precision with gettimeofday() */ + 385 : if (gettimeofday(&tv, 0) != 0) { + 386 : return 0; + 387 : } + 388 : + 389 : return tv.tv_sec * 1000000ULL + tv.tv_usec; + 390 : #endif + 391 : } + 392 : + 393 36 : uint64_t tick_ms(void) + 394 : { + 395 : struct timeval tv; + 396 : + 397 36 : if (gettimeofday(&tv, 0) != 0) + 398 0 : return 0; + 399 : + 400 36 : return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; + 401 : } + 402 : + 403 271 : int randomize(void* ptr, size_t size) + 404 : { + 405 : int f; + 406 : ssize_t ret; 407 : - 408 : /* default device path from device number */ - 409 97 : pathprint(path, path_size, "/dev/block/%u:%u", major(device), minor(device)); - 410 : - 411 : /* resolve the link from /dev/block */ - 412 97 : ret = readlink(path, buf, sizeof(buf)); - 413 97 : if (ret < 0) { - 414 : /* LCOV_EXCL_START */ - 415 : log_fatal("Failed to readlink '%s'.\n", path); - 416 : return -1; - 417 : /* LCOV_EXCL_STOP */ - 418 : } - 419 97 : if (ret == sizeof(buf)) { - 420 : /* LCOV_EXCL_START */ - 421 : log_fatal("Too long readlink '%s'.\n", path); - 422 : return -1; - 423 : /* LCOV_EXCL_STOP */ - 424 : } - 425 : - 426 97 : buf[ret] = 0; - 427 : - 428 97 : if (buf[0] != '.' || buf[1] != '.' || buf[2] != '/') { - 429 : /* LCOV_EXCL_START */ - 430 : log_fatal("Unexpected link '%s' at '%s'.\n", buf, path); - 431 : return -1; - 432 : /* LCOV_EXCL_STOP */ - 433 : } - 434 : - 435 : /* set the real device path */ - 436 97 : pathprint(path, path_size, "/dev/%s", buf + 3); + 408 271 : f = open("/dev/urandom", O_RDONLY); + 409 271 : if (f == -1) + 410 0 : return -1; + 411 : + 412 271 : ret = read(f, ptr, size); + 413 271 : if (ret < 0 || (size_t)ret != size) { + 414 0 : close(f); + 415 0 : return -1; + 416 : } + 417 : + 418 271 : if (close(f) != 0) + 419 0 : return -1; + 420 : + 421 271 : return 0; + 422 : } + 423 : + 424 : /** + 425 : * Read a file extracting the contained device number in %u:%u format. + 426 : * Return 0 on error. + 427 : */ + 428 : #if HAVE_LINUX_DEVICE + 429 86 : static dev_t devread(const char* path) + 430 : { + 431 : int f; + 432 : int ret; + 433 : char buf[64]; + 434 : char* e; + 435 : unsigned ma; + 436 : unsigned mi; 437 : - 438 : /* check the device */ - 439 97 : if (stat(path, &st) != 0) { + 438 86 : f = open(path, O_RDONLY); + 439 86 : if (f == -1) { 440 : /* LCOV_EXCL_START */ - 441 : log_fatal("Failed to stat '%s'.\n", path); - 442 : return -1; + 441 : log_fatal("Failed to open '%s'.\n", path); + 442 : return 0; 443 : /* LCOV_EXCL_STOP */ 444 : } - 445 97 : if (st.st_rdev != device) { - 446 : /* LCOV_EXCL_START */ - 447 : log_fatal("Unexpected device '%u:%u' instead of '%u:%u' for '%s'.\n", major(st.st_rdev), minor(st.st_rdev), major(device), minor(device), path); - 448 : return -1; - 449 : /* LCOV_EXCL_STOP */ - 450 : } - 451 : - 452 97 : return 0; - 453 : } - 454 : #endif - 455 : - 456 : /** - 457 : * Read a device tree filling the specified list of disk_t entries. - 458 : */ - 459 : #if HAVE_LINUX_DEVICE - 460 72 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) - 461 : { - 462 : char path[PATH_MAX]; - 463 : DIR* d; - 464 72 : int slaves = 0; - 465 : - 466 72 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); - 467 : - 468 : /* check if there is a slaves list */ - 469 72 : d = opendir(path); - 470 72 : if (d != 0) { - 471 : struct dirent* dd; + 445 : + 446 86 : ret = read(f, buf, sizeof(buf)); + 447 86 : if (ret < 0) { + 448 : /* LCOV_EXCL_START */ + 449 : close(f); + 450 : log_fatal("Failed to read '%s'.\n", path); + 451 : return 0; + 452 : /* LCOV_EXCL_STOP */ + 453 : } + 454 86 : if (ret == sizeof(buf)) { + 455 : /* LCOV_EXCL_START */ + 456 : close(f); + 457 : log_fatal("Too long read '%s'.\n", path); + 458 : return 0; + 459 : /* LCOV_EXCL_STOP */ + 460 : } + 461 : + 462 86 : buf[ret] = 0; + 463 : + 464 86 : ma = strtoul(buf, &e, 10); + 465 86 : if (*e != ':') { + 466 : /* LCOV_EXCL_START */ + 467 : close(f); + 468 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + 469 : return 0; + 470 : /* LCOV_EXCL_STOP */ + 471 : } 472 : - 473 180 : while ((dd = readdir(d)) != 0) { - 474 108 : if (dd->d_name[0] != '.') { - 475 : /* for each slave, expand the full potential tree */ - 476 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); - 477 : - 478 36 : device = devread(path); - 479 36 : if (!device) { - 480 : /* LCOV_EXCL_START */ - 481 : closedir(d); - 482 : return -1; - 483 : /* LCOV_EXCL_STOP */ - 484 : } - 485 : - 486 36 : if (devtree(name, custom, device, parent, list) != 0) { - 487 : /* LCOV_EXCL_START */ - 488 : closedir(d); - 489 : return -1; - 490 : /* LCOV_EXCL_STOP */ - 491 : } - 492 : - 493 36 : ++slaves; - 494 : } - 495 : } - 496 : - 497 36 : closedir(d); - 498 : } - 499 : - 500 : /* if no slaves found */ - 501 72 : if (!slaves) { - 502 : /* this is a raw device */ - 503 : devinfo_t* devinfo; - 504 : - 505 : /* check if it's a real device */ - 506 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); - 507 36 : if (access(path, F_OK) != 0) { - 508 : /* get the parent device */ - 509 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); - 510 : - 511 36 : device = devread(path); - 512 36 : if (!device) { - 513 : /* LCOV_EXCL_START */ - 514 : return -1; - 515 : /* LCOV_EXCL_STOP */ - 516 : } - 517 : } - 518 : - 519 : /* get the device file */ - 520 36 : if (devresolve(device, path, sizeof(path)) != 0) { - 521 : /* LCOV_EXCL_START */ - 522 : return -1; - 523 : /* LCOV_EXCL_STOP */ - 524 : } - 525 : - 526 36 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); - 527 : - 528 36 : devinfo->device = device; - 529 36 : pathcpy(devinfo->name, sizeof(devinfo->name), name); - 530 36 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); - 531 36 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 532 36 : devinfo->parent = parent; + 473 86 : mi = strtoul(e+1, &e, 10); + 474 86 : if (*e != 0 && !isspace(*e)) { + 475 : /* LCOV_EXCL_START */ + 476 : close(f); + 477 : log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + 478 : return 0; + 479 : /* LCOV_EXCL_STOP */ + 480 : } + 481 : + 482 86 : ret = close(f); + 483 86 : if (ret != 0) { + 484 : /* LCOV_EXCL_START */ + 485 : log_fatal("Failed to close '%s'.\n", path); + 486 : return 0; + 487 : /* LCOV_EXCL_STOP */ + 488 : } + 489 : + 490 86 : return makedev(ma, mi); + 491 : } + 492 : #endif + 493 : + 494 : #if HAVE_LINUX_DEVICE + 495 : /** + 496 : * Get the device file from the device number. + 497 : */ + 498 97 : static int devresolve(dev_t device, char* path, size_t path_size) + 499 : { + 500 : struct stat st; + 501 : char buf[PATH_MAX]; + 502 : int ret; + 503 : + 504 : /* default device path from device number */ + 505 97 : pathprint(path, path_size, "/dev/block/%u:%u", major(device), minor(device)); + 506 : + 507 : /* resolve the link from /dev/block */ + 508 97 : ret = readlink(path, buf, sizeof(buf)); + 509 97 : if (ret < 0) { + 510 : /* LCOV_EXCL_START */ + 511 : log_fatal("Failed to readlink '%s'.\n", path); + 512 : return -1; + 513 : /* LCOV_EXCL_STOP */ + 514 : } + 515 97 : if (ret == sizeof(buf)) { + 516 : /* LCOV_EXCL_START */ + 517 : log_fatal("Too long readlink '%s'.\n", path); + 518 : return -1; + 519 : /* LCOV_EXCL_STOP */ + 520 : } + 521 : + 522 97 : buf[ret] = 0; + 523 : + 524 97 : if (buf[0] != '.' || buf[1] != '.' || buf[2] != '/') { + 525 : /* LCOV_EXCL_START */ + 526 : log_fatal("Unexpected link '%s' at '%s'.\n", buf, path); + 527 : return -1; + 528 : /* LCOV_EXCL_STOP */ + 529 : } + 530 : + 531 : /* set the real device path */ + 532 97 : pathprint(path, path_size, "/dev/%s", buf + 3); 533 : - 534 : /* insert in the list */ - 535 36 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 536 : } - 537 : - 538 72 : return 0; - 539 : } - 540 : #endif - 541 : - 542 : /** - 543 : * Scan all the devices. - 544 : * - 545 : * If a device is already in, it's not added again. - 546 : */ - 547 : #if HAVE_LINUX_DEVICE - 548 1 : static int devscan(tommy_list* list) - 549 : { - 550 : char dir[PATH_MAX]; - 551 : DIR* d; - 552 : struct dirent* dd; - 553 : - 554 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); - 555 : - 556 : /* check if there is a slaves list */ - 557 1 : d = opendir(dir); - 558 1 : if (d == 0) { - 559 : /* LCOV_EXCL_START */ - 560 : log_fatal("Failed to open dir '%s'.\n", dir); - 561 : return -1; - 562 : /* LCOV_EXCL_STOP */ - 563 : } - 564 : - 565 75 : while ((dd = readdir(d)) != 0) { - 566 73 : if (dd->d_name[0] != '.') { - 567 : char path[PATH_MAX]; + 534 : /* check the device */ + 535 97 : if (stat(path, &st) != 0) { + 536 : /* LCOV_EXCL_START */ + 537 : log_fatal("Failed to stat '%s'.\n", path); + 538 : return -1; + 539 : /* LCOV_EXCL_STOP */ + 540 : } + 541 97 : if (st.st_rdev != device) { + 542 : /* LCOV_EXCL_START */ + 543 : log_fatal("Unexpected device '%u:%u' instead of '%u:%u' for '%s'.\n", major(st.st_rdev), minor(st.st_rdev), major(device), minor(device), path); + 544 : return -1; + 545 : /* LCOV_EXCL_STOP */ + 546 : } + 547 : + 548 97 : return 0; + 549 : } + 550 : #endif + 551 : + 552 : /** + 553 : * Read a device tree filling the specified list of disk_t entries. + 554 : */ + 555 : #if HAVE_LINUX_DEVICE + 556 72 : static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) + 557 : { + 558 : char path[PATH_MAX]; + 559 : DIR* d; + 560 72 : int slaves = 0; + 561 : + 562 72 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); + 563 : + 564 : /* check if there is a slaves list */ + 565 72 : d = opendir(path); + 566 72 : if (d != 0) { + 567 : struct dirent* dd; 568 : - 569 71 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); - 570 : - 571 : /* check if it's a real device */ - 572 71 : if (access(path, F_OK) == 0) { - 573 : tommy_node* i; - 574 : dev_t device; - 575 : - 576 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); - 577 : - 578 14 : device = devread(path); - 579 14 : if (!device) { - 580 : /* LCOV_EXCL_START */ - 581 : closedir(d); - 582 : return -1; - 583 : /* LCOV_EXCL_STOP */ - 584 : } - 585 : - 586 : /* check if already present */ - 587 248 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 588 235 : devinfo_t* devinfo = i->data; - 589 235 : if (devinfo->device == device) - 590 1 : break; - 591 : } + 569 180 : while ((dd = readdir(d)) != 0) { + 570 108 : if (dd->d_name[0] != '.') { + 571 : /* for each slave, expand the full potential tree */ + 572 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); + 573 : + 574 36 : device = devread(path); + 575 36 : if (!device) { + 576 : /* LCOV_EXCL_START */ + 577 : closedir(d); + 578 : return -1; + 579 : /* LCOV_EXCL_STOP */ + 580 : } + 581 : + 582 36 : if (devtree(name, custom, device, parent, list) != 0) { + 583 : /* LCOV_EXCL_START */ + 584 : closedir(d); + 585 : return -1; + 586 : /* LCOV_EXCL_STOP */ + 587 : } + 588 : + 589 36 : ++slaves; + 590 : } + 591 : } 592 : - 593 : /* if not found */ - 594 14 : if (i == 0) { - 595 : devinfo_t* devinfo; - 596 : - 597 : /* get the device file */ - 598 13 : if (devresolve(device, path, sizeof(path)) != 0) { - 599 : /* LCOV_EXCL_START */ - 600 : closedir(d); - 601 : return -1; - 602 : /* LCOV_EXCL_STOP */ - 603 : } - 604 : - 605 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 593 36 : closedir(d); + 594 : } + 595 : + 596 : /* if no slaves found */ + 597 72 : if (!slaves) { + 598 : /* this is a raw device */ + 599 : devinfo_t* devinfo; + 600 : + 601 : /* check if it's a real device */ + 602 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); + 603 36 : if (access(path, F_OK) != 0) { + 604 : /* get the parent device */ + 605 36 : pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); 606 : - 607 13 : devinfo->device = device; - 608 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path); - 609 : - 610 : /* insert in the list */ - 611 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo); - 612 : } - 613 : } - 614 : } - 615 : } - 616 : - 617 1 : closedir(d); - 618 1 : return 0; - 619 : } - 620 : #endif + 607 36 : device = devread(path); + 608 36 : if (!device) { + 609 : /* LCOV_EXCL_START */ + 610 : return -1; + 611 : /* LCOV_EXCL_STOP */ + 612 : } + 613 : } + 614 : + 615 : /* get the device file */ + 616 36 : if (devresolve(device, path, sizeof(path)) != 0) { + 617 : /* LCOV_EXCL_START */ + 618 : return -1; + 619 : /* LCOV_EXCL_STOP */ + 620 : } 621 : - 622 : /** - 623 : * Get SMART attributes. - 624 : */ - 625 25 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial) - 626 : { - 627 : char cmd[128]; - 628 : char file[128]; - 629 : FILE* f; - 630 : int ret; - 631 : - 632 25 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); + 622 36 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 623 : + 624 36 : devinfo->device = device; + 625 36 : pathcpy(devinfo->name, sizeof(devinfo->name), name); + 626 36 : pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); + 627 36 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 628 36 : devinfo->parent = parent; + 629 : + 630 : /* insert in the list */ + 631 36 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 632 : } 633 : - 634 : /* if there is a custom command */ - 635 25 : if (custom[0]) { - 636 : char option[128]; - 637 2 : snprintf(option, sizeof(option), custom, file); - 638 2 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); - 639 : } else { - 640 23 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); - 641 : } - 642 : - 643 25 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 644 : - 645 25 : f = popen(cmd, "r"); - 646 25 : if (!f) { - 647 : /* LCOV_EXCL_START */ - 648 : log_fatal("Failed to run '%s' (from popen).\n", cmd); - 649 : return -1; - 650 : /* LCOV_EXCL_STOP */ - 651 : } - 652 : - 653 25 : if (smartctl_attribute(f, file, name, smart, serial) != 0) { - 654 : /* LCOV_EXCL_START */ - 655 : pclose(f); - 656 : return -1; - 657 : /* LCOV_EXCL_STOP */ - 658 : } - 659 : - 660 25 : ret = pclose(f); - 661 : - 662 25 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); - 663 : - 664 25 : if (!WIFEXITED(ret)) { - 665 : /* LCOV_EXCL_START */ - 666 : log_fatal("Failed to run '%s' (not exited).\n", cmd); - 667 : return -1; - 668 : /* LCOV_EXCL_STOP */ - 669 : } - 670 25 : if (WEXITSTATUS(ret) == 127) { - 671 : /* LCOV_EXCL_START */ - 672 : log_fatal("Failed to run '%s' (from sh).\n", cmd); - 673 : return -1; - 674 : /* LCOV_EXCL_STOP */ - 675 : } - 676 : - 677 : /* store the return smartctl return value */ - 678 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret); - 679 : - 680 0 : return 0; - 681 : } - 682 : - 683 : /** - 684 : * Spin down a specific device. - 685 : */ - 686 : #if HAVE_LINUX_DEVICE - 687 12 : static int devdown(dev_t device, const char* name, const char* custom) - 688 : { - 689 : char cmd[128]; - 690 : char file[128]; - 691 : FILE* f; - 692 : int ret; - 693 : - 694 12 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); - 695 : - 696 : /* if there is a custom command */ - 697 12 : if (custom[0]) { - 698 : char option[128]; - 699 2 : snprintf(option, sizeof(option), custom, file); - 700 2 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option); - 701 : } else { - 702 10 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file); - 703 : } - 704 : - 705 12 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); - 706 : - 707 12 : f = popen(cmd, "r"); - 708 12 : if (!f) { - 709 : /* LCOV_EXCL_START */ - 710 : log_fatal("Failed to run '%s' (from popen).\n", cmd); - 711 : return -1; - 712 : /* LCOV_EXCL_STOP */ - 713 : } - 714 : - 715 12 : if (smartctl_flush(f, file, name) != 0) { - 716 : /* LCOV_EXCL_START */ - 717 : pclose(f); - 718 : return -1; - 719 : /* LCOV_EXCL_STOP */ - 720 : } - 721 : - 722 12 : ret = pclose(f); - 723 : - 724 12 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); - 725 : - 726 12 : if (!WIFEXITED(ret)) { - 727 : /* LCOV_EXCL_START */ - 728 : log_fatal("Failed to run '%s' (not exited).\n", cmd); - 729 : return -1; - 730 : /* LCOV_EXCL_STOP */ - 731 : } - 732 12 : if (WEXITSTATUS(ret) == 127) { - 733 : /* LCOV_EXCL_START */ - 734 : log_fatal("Failed to run '%s' (from sh).\n", cmd); - 735 : return -1; - 736 : /* LCOV_EXCL_STOP */ + 634 72 : return 0; + 635 : } + 636 : #endif + 637 : + 638 : /** + 639 : * Scan all the devices. + 640 : * + 641 : * If a device is already in, it's not added again. + 642 : */ + 643 : #if HAVE_LINUX_DEVICE + 644 1 : static int devscan(tommy_list* list) + 645 : { + 646 : char dir[PATH_MAX]; + 647 : DIR* d; + 648 : struct dirent* dd; + 649 : + 650 1 : pathprint(dir, sizeof(dir), "/sys/dev/block/"); + 651 : + 652 : /* check if there is a slaves list */ + 653 1 : d = opendir(dir); + 654 1 : if (d == 0) { + 655 : /* LCOV_EXCL_START */ + 656 : log_fatal("Failed to open dir '%s'.\n", dir); + 657 : return -1; + 658 : /* LCOV_EXCL_STOP */ + 659 : } + 660 : + 661 74 : while ((dd = readdir(d)) != 0) { + 662 72 : if (dd->d_name[0] != '.') { + 663 : char path[PATH_MAX]; + 664 : + 665 70 : pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); + 666 : + 667 : /* check if it's a real device */ + 668 70 : if (access(path, F_OK) == 0) { + 669 : tommy_node* i; + 670 : dev_t device; + 671 : + 672 14 : pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); + 673 : + 674 14 : device = devread(path); + 675 14 : if (!device) { + 676 : /* LCOV_EXCL_START */ + 677 : closedir(d); + 678 : return -1; + 679 : /* LCOV_EXCL_STOP */ + 680 : } + 681 : + 682 : /* check if already present */ + 683 248 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 684 235 : devinfo_t* devinfo = i->data; + 685 235 : if (devinfo->device == device) + 686 1 : break; + 687 : } + 688 : + 689 : /* if not found */ + 690 14 : if (i == 0) { + 691 : devinfo_t* devinfo; + 692 : + 693 : /* get the device file */ + 694 13 : if (devresolve(device, path, sizeof(path)) != 0) { + 695 : /* LCOV_EXCL_START */ + 696 : closedir(d); + 697 : return -1; + 698 : /* LCOV_EXCL_STOP */ + 699 : } + 700 : + 701 13 : devinfo = calloc_nofail(1, sizeof(devinfo_t)); + 702 : + 703 13 : devinfo->device = device; + 704 13 : pathcpy(devinfo->file, sizeof(devinfo->file), path); + 705 : + 706 : /* insert in the list */ + 707 13 : tommy_list_insert_tail(list, &devinfo->node, devinfo); + 708 : } + 709 : } + 710 : } + 711 : } + 712 : + 713 1 : closedir(d); + 714 1 : return 0; + 715 : } + 716 : #endif + 717 : + 718 : /** + 719 : * Get SMART attributes. + 720 : */ + 721 25 : static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial) + 722 : { + 723 : char cmd[128]; + 724 : char file[128]; + 725 : FILE* f; + 726 : int ret; + 727 : + 728 25 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); + 729 : + 730 : /* if there is a custom command */ + 731 25 : if (custom[0]) { + 732 : char option[128]; + 733 2 : snprintf(option, sizeof(option), custom, file); + 734 2 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); + 735 : } else { + 736 23 : snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); 737 : } - 738 0 : if (WEXITSTATUS(ret) != 0) { - 739 : /* LCOV_EXCL_START */ - 740 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); - 741 : return -1; - 742 : /* LCOV_EXCL_STOP */ - 743 : } - 744 : - 745 0 : return 0; - 746 : } - 747 : #endif + 738 : + 739 25 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + 740 : + 741 25 : f = popen(cmd, "r"); + 742 25 : if (!f) { + 743 : /* LCOV_EXCL_START */ + 744 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 745 : return -1; + 746 : /* LCOV_EXCL_STOP */ + 747 : } 748 : - 749 : /** - 750 : * Spin up a device. - 751 : * - 752 : * There isn't a defined way to spin up a device, - 753 : * so we just do a generic write. - 754 : */ - 755 12 : static int devup(const char* mountpoint) - 756 : { - 757 : int ret; - 758 : char path[PATH_MAX]; + 749 25 : if (smartctl_attribute(f, file, name, smart, serial) != 0) { + 750 : /* LCOV_EXCL_START */ + 751 : pclose(f); + 752 : return -1; + 753 : /* LCOV_EXCL_STOP */ + 754 : } + 755 : + 756 24 : ret = pclose(f); + 757 : + 758 25 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); 759 : - 760 : /* add a temporary name used for writing */ - 761 12 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint); - 762 : - 763 : /* do a generic write, and immediately undo it */ - 764 12 : ret = mkdir(path, 0); - 765 12 : if (ret != 0 && errno != EEXIST) { - 766 : /* LCOV_EXCL_START */ - 767 : log_fatal("Failed to create dir '%s'.\n", path); - 768 : return -1; - 769 : /* LCOV_EXCL_STOP */ - 770 : } - 771 : - 772 : /* remove the just created dir */ - 773 12 : rmdir(path); - 774 : - 775 12 : return 0; - 776 : } - 777 : - 778 : /** - 779 : * Thread for spinning up. - 780 : * - 781 : * Note that filling up the devinfo object is done inside this thread, - 782 : * to avoid to block the main thread if the device need to be spin up - 783 : * to handle stat/resolve requests. - 784 : */ - 785 12 : static void* thread_spinup(void* arg) - 786 : { - 787 12 : devinfo_t* devinfo = arg; - 788 : struct stat st; - 789 : uint64_t start; - 790 : - 791 12 : start = tick_ms(); - 792 : - 793 : /* first get the device number, this usually doesn't trigger a thread_spinup */ - 794 12 : if (stat(devinfo->mount, &st) != 0) { - 795 : /* LCOV_EXCL_START */ - 796 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount); - 797 : return (void*)-1; - 798 : /* LCOV_EXCL_STOP */ + 760 25 : if (!WIFEXITED(ret)) { + 761 : /* LCOV_EXCL_START */ + 762 : log_fatal("Failed to run '%s' (not exited).\n", cmd); + 763 : return -1; + 764 : /* LCOV_EXCL_STOP */ + 765 : } + 766 25 : if (WEXITSTATUS(ret) == 127) { + 767 : /* LCOV_EXCL_START */ + 768 : log_fatal("Failed to run '%s' (from sh).\n", cmd); + 769 : return -1; + 770 : /* LCOV_EXCL_STOP */ + 771 : } + 772 : + 773 : /* store the return smartctl return value */ + 774 0 : smart[SMART_FLAGS] = WEXITSTATUS(ret); + 775 : + 776 0 : return 0; + 777 : } + 778 : + 779 : /** + 780 : * Spin down a specific device. + 781 : */ + 782 : #if HAVE_LINUX_DEVICE + 783 12 : static int devdown(dev_t device, const char* name, const char* custom) + 784 : { + 785 : char cmd[128]; + 786 : char file[128]; + 787 : FILE* f; + 788 : int ret; + 789 : + 790 12 : snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); + 791 : + 792 : /* if there is a custom command */ + 793 12 : if (custom[0]) { + 794 : char option[128]; + 795 2 : snprintf(option, sizeof(option), custom, file); + 796 2 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option); + 797 : } else { + 798 10 : snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file); 799 : } 800 : - 801 : /* set the device number for printing */ - 802 12 : devinfo->device = st.st_dev; - 803 : - 804 : #if HAVE_LINUX_DEVICE - 805 : /* get the device file, but only in Linux and only for the message */ - 806 12 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { - 807 : /* LCOV_EXCL_START */ - 808 : return (void*)-1; - 809 : /* LCOV_EXCL_STOP */ - 810 : } - 811 : #endif - 812 : - 813 12 : if (devup(devinfo->mount) != 0) { - 814 : /* LCOV_EXCL_START */ - 815 : return (void*)-1; - 816 : /* LCOV_EXCL_STOP */ - 817 : } - 818 : - 819 : #if HAVE_LINUX_DEVICE - 820 12 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); - 821 : #else - 822 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); - 823 : #endif - 824 : - 825 12 : return 0; - 826 : } - 827 : - 828 : /** - 829 : * Thread for spinning down. - 830 : */ - 831 12 : static void* thread_spindown(void* arg) - 832 : { - 833 : #if HAVE_LINUX_DEVICE - 834 12 : devinfo_t* devinfo = arg; - 835 : uint64_t start; - 836 : - 837 12 : start = tick_ms(); - 838 : - 839 12 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { - 840 : /* LCOV_EXCL_START */ - 841 : return (void*)-1; - 842 : /* LCOV_EXCL_STOP */ - 843 : } + 801 12 : log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + 802 : + 803 12 : f = popen(cmd, "r"); + 804 12 : if (!f) { + 805 : /* LCOV_EXCL_START */ + 806 : log_fatal("Failed to run '%s' (from popen).\n", cmd); + 807 : return -1; + 808 : /* LCOV_EXCL_STOP */ + 809 : } + 810 : + 811 12 : if (smartctl_flush(f, file, name) != 0) { + 812 : /* LCOV_EXCL_START */ + 813 : pclose(f); + 814 : return -1; + 815 : /* LCOV_EXCL_STOP */ + 816 : } + 817 : + 818 12 : ret = pclose(f); + 819 : + 820 12 : log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + 821 : + 822 12 : if (!WIFEXITED(ret)) { + 823 : /* LCOV_EXCL_START */ + 824 : log_fatal("Failed to run '%s' (not exited).\n", cmd); + 825 : return -1; + 826 : /* LCOV_EXCL_STOP */ + 827 : } + 828 12 : if (WEXITSTATUS(ret) == 127) { + 829 : /* LCOV_EXCL_START */ + 830 : log_fatal("Failed to run '%s' (from sh).\n", cmd); + 831 : return -1; + 832 : /* LCOV_EXCL_STOP */ + 833 : } + 834 0 : if (WEXITSTATUS(ret) != 0) { + 835 : /* LCOV_EXCL_START */ + 836 : log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); + 837 : return -1; + 838 : /* LCOV_EXCL_STOP */ + 839 : } + 840 : + 841 0 : return 0; + 842 : } + 843 : #endif 844 : - 845 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); - 846 : - 847 0 : return 0; - 848 : #else - 849 : (void)arg; - 850 : return (void*)-1; - 851 : #endif - 852 : } - 853 : - 854 : /** - 855 : * Thread for getting smart info. - 856 : */ - 857 25 : static void* thread_smart(void* arg) - 858 : { - 859 25 : devinfo_t* devinfo = arg; - 860 : - 861 25 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) { + 845 : /** + 846 : * Spin up a device. + 847 : * + 848 : * There isn't a defined way to spin up a device, + 849 : * so we just do a generic write. + 850 : */ + 851 12 : static int devup(const char* mountpoint) + 852 : { + 853 : int ret; + 854 : char path[PATH_MAX]; + 855 : + 856 : /* add a temporary name used for writing */ + 857 12 : pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint); + 858 : + 859 : /* do a generic write, and immediately undo it */ + 860 12 : ret = mkdir(path, 0); + 861 12 : if (ret != 0 && errno != EEXIST) { 862 : /* LCOV_EXCL_START */ - 863 : return (void*)-1; - 864 : /* LCOV_EXCL_STOP */ - 865 : } - 866 : - 867 0 : return 0; - 868 : } - 869 : - 870 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) - 871 : { - 872 3 : int fail = 0; - 873 : tommy_node* i; - 874 : - 875 : #if HAVE_PTHREAD_CREATE - 876 : /* start all threads */ - 877 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 878 49 : devinfo_t* devinfo = i->data; - 879 : - 880 49 : if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) { - 881 : /* LCOV_EXCL_START */ - 882 : log_fatal("Failed to create thread.\n"); - 883 : exit(EXIT_FAILURE); - 884 : /* LCOV_EXCL_STOP */ - 885 : } - 886 : } - 887 : - 888 : /* join all threads */ - 889 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 890 49 : devinfo_t* devinfo = i->data; - 891 : void* retval; - 892 : - 893 49 : if (pthread_join(devinfo->thread, &retval) != 0) { - 894 : /* LCOV_EXCL_START */ - 895 : log_fatal("Failed to join thread.\n"); - 896 : exit(EXIT_FAILURE); - 897 : /* LCOV_EXCL_STOP */ - 898 : } + 863 : log_fatal("Failed to create dir '%s'.\n", path); + 864 : return -1; + 865 : /* LCOV_EXCL_STOP */ + 866 : } + 867 : + 868 : /* remove the just created dir */ + 869 12 : rmdir(path); + 870 : + 871 12 : return 0; + 872 : } + 873 : + 874 : /** + 875 : * Thread for spinning up. + 876 : * + 877 : * Note that filling up the devinfo object is done inside this thread, + 878 : * to avoid to block the main thread if the device need to be spin up + 879 : * to handle stat/resolve requests. + 880 : */ + 881 12 : static void* thread_spinup(void* arg) + 882 : { + 883 12 : devinfo_t* devinfo = arg; + 884 : struct stat st; + 885 : uint64_t start; + 886 : + 887 12 : start = tick_ms(); + 888 : + 889 : /* first get the device number, this usually doesn't trigger a thread_spinup */ + 890 12 : if (stat(devinfo->mount, &st) != 0) { + 891 : /* LCOV_EXCL_START */ + 892 : log_fatal("Failed to stat device '%s'.\n", devinfo->mount); + 893 : return (void*)-1; + 894 : /* LCOV_EXCL_STOP */ + 895 : } + 896 : + 897 : /* set the device number for printing */ + 898 12 : devinfo->device = st.st_dev; 899 : - 900 49 : if (retval != 0) - 901 37 : ++fail; - 902 : } - 903 : #else - 904 : for (i = tommy_list_head(list); i != 0; i = i->next) { - 905 : devinfo_t* devinfo = i->data; - 906 : - 907 : if (func(devinfo) != 0) - 908 : ++fail; - 909 : } - 910 : #endif - 911 3 : if (fail != 0) { - 912 : /* LCOV_EXCL_START */ - 913 : return -1; - 914 : /* LCOV_EXCL_STOP */ - 915 : } - 916 : - 917 1 : return 0; - 918 : } - 919 : - 920 4 : int devquery(tommy_list* high, tommy_list* low, int operation) - 921 : { - 922 : tommy_node* i; - 923 4 : void* (*func)(void* arg) = 0; - 924 : - 925 : #if HAVE_LINUX_DEVICE - 926 4 : if (operation != DEVICE_UP) { - 927 : struct stat st; - 928 : /* sysfs and devfs interfaces are required */ - 929 3 : if (stat("/sys/dev/block", &st) != 0) { - 930 : /* LCOV_EXCL_START */ - 931 : log_fatal("Missing interface /sys/dev/block.\n"); - 932 : return -1; - 933 : /* LCOV_EXCL_STOP */ - 934 : } - 935 3 : if (stat("/dev/block", &st) != 0) { - 936 : /* LCOV_EXCL_START */ - 937 : log_fatal("Missing interface /dev/block.\n"); - 938 : return -1; - 939 : /* LCOV_EXCL_STOP */ - 940 : } - 941 : - 942 : /* for each device */ - 943 39 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 944 36 : devinfo_t* devinfo = i->data; - 945 : - 946 : /* get the device file */ - 947 36 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { - 948 : /* LCOV_EXCL_START */ - 949 : log_fatal("Failed to resolve device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); - 950 : return -1; - 951 : /* LCOV_EXCL_STOP */ - 952 : } - 953 : - 954 : /* expand the tree of devices */ - 955 36 : if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) { - 956 : /* LCOV_EXCL_START */ - 957 : log_fatal("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); - 958 : return -1; - 959 : /* LCOV_EXCL_STOP */ - 960 : } - 961 : } - 962 : } - 963 : #endif - 964 : - 965 4 : if (operation == DEVICE_UP) { - 966 : /* duplicate the high */ - 967 13 : for (i = tommy_list_head(high); i != 0; i = i->next) { - 968 12 : devinfo_t* devinfo = i->data; - 969 : devinfo_t* entry; + 900 : #if HAVE_LINUX_DEVICE + 901 : /* get the device file, but only in Linux and only for the message */ + 902 12 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { + 903 : /* LCOV_EXCL_START */ + 904 : return (void*)-1; + 905 : /* LCOV_EXCL_STOP */ + 906 : } + 907 : #endif + 908 : + 909 12 : if (devup(devinfo->mount) != 0) { + 910 : /* LCOV_EXCL_START */ + 911 : return (void*)-1; + 912 : /* LCOV_EXCL_STOP */ + 913 : } + 914 : + 915 : #if HAVE_LINUX_DEVICE + 916 12 : msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 917 : #else + 918 : msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); + 919 : #endif + 920 : + 921 12 : return 0; + 922 : } + 923 : + 924 : /** + 925 : * Thread for spinning down. + 926 : */ + 927 12 : static void* thread_spindown(void* arg) + 928 : { + 929 : #if HAVE_LINUX_DEVICE + 930 12 : devinfo_t* devinfo = arg; + 931 : uint64_t start; + 932 : + 933 12 : start = tick_ms(); + 934 : + 935 12 : if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { + 936 : /* LCOV_EXCL_START */ + 937 : return (void*)-1; + 938 : /* LCOV_EXCL_STOP */ + 939 : } + 940 : + 941 0 : msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + 942 : + 943 0 : return 0; + 944 : #else + 945 : (void)arg; + 946 : return (void*)-1; + 947 : #endif + 948 : } + 949 : + 950 : /** + 951 : * Thread for getting smart info. + 952 : */ + 953 22 : static void* thread_smart(void* arg) + 954 : { + 955 22 : devinfo_t* devinfo = arg; + 956 : + 957 22 : if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) { + 958 : /* LCOV_EXCL_START */ + 959 : return (void*)-1; + 960 : /* LCOV_EXCL_STOP */ + 961 : } + 962 : + 963 0 : return 0; + 964 : } + 965 : + 966 3 : static int device_thread(tommy_list* list, void* (*func)(void* arg)) + 967 : { + 968 3 : int fail = 0; + 969 : tommy_node* i; 970 : - 971 12 : entry = calloc_nofail(1, sizeof(devinfo_t)); - 972 : - 973 12 : entry->device = devinfo->device; - 974 12 : pathcpy(entry->name, sizeof(entry->name), devinfo->name); - 975 12 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); - 976 : - 977 : /* insert in the high */ - 978 12 : tommy_list_insert_tail(low, &entry->node, entry); - 979 : } - 980 : } - 981 : - 982 : #if HAVE_LINUX_DEVICE - 983 : /* add other devices */ - 984 4 : if (operation == DEVICE_SMART) { - 985 1 : if (devscan(low) != 0) { - 986 : /* LCOV_EXCL_START */ - 987 : log_fatal("Failed to list other devices.\n"); - 988 : return -1; - 989 : /* LCOV_EXCL_STOP */ - 990 : } - 991 : } - 992 : #endif - 993 : - 994 4 : switch (operation) { - 995 1 : case DEVICE_UP : func = thread_spinup; break; - 996 1 : case DEVICE_DOWN : func = thread_spindown; break; - 997 1 : case DEVICE_SMART : func = thread_smart; break; + 971 : #if HAVE_PTHREAD + 972 : /* start all threads */ + 973 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 974 49 : devinfo_t* devinfo = i->data; + 975 : + 976 49 : if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) { + 977 : /* LCOV_EXCL_START */ + 978 : log_fatal("Failed to create thread.\n"); + 979 : exit(EXIT_FAILURE); + 980 : /* LCOV_EXCL_STOP */ + 981 : } + 982 : } + 983 : + 984 : /* join all threads */ + 985 52 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 986 49 : devinfo_t* devinfo = i->data; + 987 : void* retval; + 988 : + 989 49 : if (pthread_join(devinfo->thread, &retval) != 0) { + 990 : /* LCOV_EXCL_START */ + 991 : log_fatal("Failed to join thread.\n"); + 992 : exit(EXIT_FAILURE); + 993 : /* LCOV_EXCL_STOP */ + 994 : } + 995 : + 996 49 : if (retval != 0) + 997 37 : ++fail; 998 : } - 999 : - 1000 4 : if (!func) - 1001 1 : return 0; + 999 : #else + 1000 : for (i = tommy_list_head(list); i != 0; i = i->next) { + 1001 : devinfo_t* devinfo = i->data; 1002 : - 1003 3 : return device_thread(low, func); - 1004 : } - 1005 : - 1006 252 : void os_init(int opt) - 1007 : { - 1008 : (void)opt; - 1009 252 : } - 1010 : - 1011 230 : void os_done(void) - 1012 : { - 1013 230 : } - 1014 : - 1015 : #endif - 1016 : + 1003 : if (func(devinfo) != 0) + 1004 : ++fail; + 1005 : } + 1006 : #endif + 1007 3 : if (fail != 0) { + 1008 : /* LCOV_EXCL_START */ + 1009 : return -1; + 1010 : /* LCOV_EXCL_STOP */ + 1011 : } + 1012 : + 1013 1 : return 0; + 1014 : } + 1015 : + 1016 4 : int devquery(tommy_list* high, tommy_list* low, int operation) + 1017 : { + 1018 : tommy_node* i; + 1019 4 : void* (*func)(void* arg) = 0; + 1020 : + 1021 : #if HAVE_LINUX_DEVICE + 1022 4 : if (operation != DEVICE_UP) { + 1023 : struct stat st; + 1024 : /* sysfs and devfs interfaces are required */ + 1025 3 : if (stat("/sys/dev/block", &st) != 0) { + 1026 : /* LCOV_EXCL_START */ + 1027 : log_fatal("Missing interface /sys/dev/block.\n"); + 1028 : return -1; + 1029 : /* LCOV_EXCL_STOP */ + 1030 : } + 1031 3 : if (stat("/dev/block", &st) != 0) { + 1032 : /* LCOV_EXCL_START */ + 1033 : log_fatal("Missing interface /dev/block.\n"); + 1034 : return -1; + 1035 : /* LCOV_EXCL_STOP */ + 1036 : } + 1037 : + 1038 : /* for each device */ + 1039 39 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 1040 36 : devinfo_t* devinfo = i->data; + 1041 : + 1042 : /* get the device file */ + 1043 36 : if (devresolve(devinfo->device, devinfo->file, sizeof(devinfo->file)) != 0) { + 1044 : /* LCOV_EXCL_START */ + 1045 : log_fatal("Failed to resolve device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); + 1046 : return -1; + 1047 : /* LCOV_EXCL_STOP */ + 1048 : } + 1049 : + 1050 : /* expand the tree of devices */ + 1051 36 : if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) { + 1052 : /* LCOV_EXCL_START */ + 1053 : log_fatal("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); + 1054 : return -1; + 1055 : /* LCOV_EXCL_STOP */ + 1056 : } + 1057 : } + 1058 : } + 1059 : #endif + 1060 : + 1061 4 : if (operation == DEVICE_UP) { + 1062 : /* duplicate the high */ + 1063 13 : for (i = tommy_list_head(high); i != 0; i = i->next) { + 1064 12 : devinfo_t* devinfo = i->data; + 1065 : devinfo_t* entry; + 1066 : + 1067 12 : entry = calloc_nofail(1, sizeof(devinfo_t)); + 1068 : + 1069 12 : entry->device = devinfo->device; + 1070 12 : pathcpy(entry->name, sizeof(entry->name), devinfo->name); + 1071 12 : pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); + 1072 : + 1073 : /* insert in the high */ + 1074 12 : tommy_list_insert_tail(low, &entry->node, entry); + 1075 : } + 1076 : } + 1077 : + 1078 : #if HAVE_LINUX_DEVICE + 1079 : /* add other devices */ + 1080 4 : if (operation == DEVICE_SMART) { + 1081 1 : if (devscan(low) != 0) { + 1082 : /* LCOV_EXCL_START */ + 1083 : log_fatal("Failed to list other devices.\n"); + 1084 : return -1; + 1085 : /* LCOV_EXCL_STOP */ + 1086 : } + 1087 : } + 1088 : #endif + 1089 : + 1090 4 : switch (operation) { + 1091 1 : case DEVICE_UP : func = thread_spinup; break; + 1092 1 : case DEVICE_DOWN : func = thread_spindown; break; + 1093 1 : case DEVICE_SMART : func = thread_smart; break; + 1094 : } + 1095 : + 1096 4 : if (!func) + 1097 1 : return 0; + 1098 : + 1099 3 : return device_thread(low, func); + 1100 : } + 1101 : + 1102 260 : void os_init(int opt) + 1103 : { + 1104 : #if HAVE_BLKID + 1105 : int ret; + 1106 260 : ret = blkid_get_cache(&cache, NULL); + 1107 260 : if (ret != 0) { + 1108 : /* LCOV_EXCL_START */ + 1109 : log_fatal("WARNING Failed to get blkid cache\n"); + 1110 : /* LCOV_EXCL_STOP */ + 1111 : } + 1112 : #endif + 1113 : + 1114 : (void)opt; + 1115 260 : } + 1116 : + 1117 238 : void os_done(void) + 1118 : { + 1119 : #if HAVE_BLKID + 1120 238 : if (cache != 0) + 1121 238 : blkid_put_cache(cache); + 1122 : #endif + 1123 238 : } + 1124 : + 1125 : /* LCOV_EXCL_START */ + 1126 : void os_abort(void) + 1127 : { + 1128 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 1129 : void* stack[32]; + 1130 : char** messages; + 1131 : size_t size; + 1132 : unsigned i; + 1133 : #endif + 1134 : + 1135 : printf("Stacktrace of " PACKAGE " v" VERSION); + 1136 : #ifdef _linux + 1137 : printf(", linux"); + 1138 : #endif + 1139 : #ifdef __GNUC__ + 1140 : printf(", gcc " __VERSION__); + 1141 : #endif + 1142 : printf(", %d-bit", (int)sizeof(void *) * 8); + 1143 : printf(", PATH_MAX=%d", PATH_MAX); + 1144 : printf("\n"); + 1145 : + 1146 : #if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + 1147 : size = backtrace(stack, 32); + 1148 : + 1149 : messages = backtrace_symbols(stack, size); + 1150 : + 1151 : for (i=1; i<size; ++i) { + 1152 : const char* msg; + 1153 : + 1154 : if (messages) + 1155 : msg = messages[i]; + 1156 : else + 1157 : msg = "<unknown>"; + 1158 : + 1159 : printf("[bt] %02u: %s\n", i, msg); + 1160 : + 1161 : if (messages) { + 1162 : int ret; + 1163 : char addr2line[1024]; + 1164 : size_t j = 0; + 1165 : while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) + 1166 : ++j; + 1167 : + 1168 : snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); + 1169 : + 1170 : ret = system(addr2line); + 1171 : if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) + 1172 : printf("exit:%d\n", WEXITSTATUS(ret)); + 1173 : if (WIFSIGNALED(ret)) + 1174 : printf("signal:%d\n", WTERMSIG(ret)); + 1175 : } + 1176 : } + 1177 : #endif + 1178 : + 1179 : printf("Please report this error to the SnapRAID Forum:\n"); + 1180 : printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); + 1181 : + 1182 : abort(); + 1183 : } + 1184 : /* LCOV_EXCL_STOP */ + 1185 : + 1186 : #endif + 1187 : diff --git a/cov/cmdline/util.c.func-sort-c.html b/cov/cmdline/util.c.func-sort-c.html index 8fc8b9ea..83cf470e 100644 --- a/cov/cmdline/util.c.func-sort-c.html +++ b/cov/cmdline/util.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 14 @@ -61,55 +61,55 @@ util_rotl32 - 924861211 + 796761149 util_rotl64 - 461015664 + 511410252 memhash - 5724756 + 5791413 crc32c_x86 - 659527 + 646616 memdiff - 25190 + 25329 malloc_nofail_test - 2580 + 1905 mtest_vector - 2580 + 1905 crc32c_gen - 353 + 369 crc32c_init - 268 + 276 lock_lock - 243 + 251 lock_unlock - 223 + 231 malloc_nofail_vector_align - 201 + 209 malloc_nofail_align - 83 + 91 hash_config_name diff --git a/cov/cmdline/util.c.func.html b/cov/cmdline/util.c.func.html index a05830bd..24210007 100644 --- a/cov/cmdline/util.c.func.html +++ b/cov/cmdline/util.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 14 @@ -61,15 +61,15 @@ crc32c_gen - 353 + 369 crc32c_init - 268 + 276 crc32c_x86 - 659527 + 646616 hash_config_name @@ -77,43 +77,43 @@ lock_lock - 243 + 251 lock_unlock - 223 + 231 malloc_nofail_align - 83 + 91 malloc_nofail_test - 2580 + 1905 malloc_nofail_vector_align - 201 + 209 memdiff - 25190 + 25329 memhash - 5724756 + 5791413 mtest_vector - 2580 + 1905 util_rotl32 - 924861211 + 796761149 util_rotl64 - 461015664 + 511410252
diff --git a/cov/cmdline/util.c.gcov.html b/cov/cmdline/util.c.gcov.html index 501f3b20..f023adf7 100644 --- a/cov/cmdline/util.c.gcov.html +++ b/cov/cmdline/util.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 14 @@ -87,59 +87,59 @@ 25 : /****************************************************************************/ 26 : /* memory */ 27 : - 28 83 : void* malloc_nofail_align(size_t size, void** freeptr) + 28 91 : void* malloc_nofail_align(size_t size, void** freeptr) 29 : { 30 : void* ptr; 31 : - 32 83 : ptr = raid_malloc_align(size, freeptr); + 32 91 : ptr = raid_malloc_align(size, freeptr); 33 : - 34 83 : if (!ptr) { + 34 91 : if (!ptr) { 35 : /* LCOV_EXCL_START */ 36 : malloc_fail(size); 37 : exit(EXIT_FAILURE); 38 : /* LCOV_EXCL_STOP */ 39 : } 40 : - 41 83 : return ptr; + 41 91 : return ptr; 42 : } 43 : - 44 201 : void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr) + 44 209 : void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr) 45 : { 46 : void* ptr; 47 : - 48 201 : ptr = raid_malloc_vector(nd, n, size, freeptr); + 48 209 : ptr = raid_malloc_vector(nd, n, size, freeptr); 49 : - 50 201 : if (!ptr) { + 50 209 : if (!ptr) { 51 : /* LCOV_EXCL_START */ 52 : malloc_fail(n * size); 53 : exit(EXIT_FAILURE); 54 : /* LCOV_EXCL_STOP */ 55 : } 56 : - 57 201 : return ptr; + 57 209 : return ptr; 58 : } 59 : - 60 2580 : void* malloc_nofail_test(size_t size) + 60 1905 : void* malloc_nofail_test(size_t size) 61 : { 62 : void* ptr; 63 : - 64 2580 : ptr = malloc_nofail(size); + 64 1905 : ptr = malloc_nofail(size); 65 : - 66 2580 : mtest_vector(1, size, &ptr); + 66 1905 : mtest_vector(1, size, &ptr); 67 : - 68 2580 : return ptr; + 68 1905 : return ptr; 69 : } 70 : - 71 2580 : void mtest_vector(int n, size_t size, void** vv) + 71 1905 : void mtest_vector(int n, size_t size, void** vv) 72 : { - 73 2580 : if (raid_mtest_vector(n, size, vv) != 0) { + 73 1905 : if (raid_mtest_vector(n, size, vv) != 0) { 74 : /* LCOV_EXCL_START */ 75 : log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); 76 : log_fatal("Try running a memory test like http://www.memtest86.com/\n"); 77 : exit(EXIT_FAILURE); 78 : /* LCOV_EXCL_STOP */ 79 : } - 80 2580 : } + 80 1905 : } 81 : 82 : /****************************************************************************/ 83 : /* crc */ @@ -416,42 +416,42 @@ 354 : int crc_x86; 355 : #endif 356 : - 357 353 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size) + 357 369 : uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size) 358 : { - 359 353 : crc ^= CRC_IV; + 359 369 : crc ^= CRC_IV; 360 : - 361 353 : crc = crc32c_gen_plain(crc, ptr, size); + 361 369 : crc = crc32c_gen_plain(crc, ptr, size); 362 : - 363 353 : crc ^= CRC_IV; + 363 369 : crc ^= CRC_IV; 364 : - 365 353 : return crc; + 365 369 : return crc; 366 : } 367 : 368 : #if HAVE_SSE42 - 369 659527 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) + 369 646616 : uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) 370 : { - 371 659527 : crc ^= CRC_IV; + 371 646616 : crc ^= CRC_IV; 372 : - 373 659527 : crc = crc32c_x86_plain(crc, ptr, size); + 373 646616 : crc = crc32c_x86_plain(crc, ptr, size); 374 : - 375 659526 : crc ^= CRC_IV; + 375 646616 : crc ^= CRC_IV; 376 : - 377 659526 : return crc; + 377 646616 : return crc; 378 : } 379 : #endif 380 : 381 : uint32_t (*crc32c)(uint32_t crc, const unsigned char* ptr, unsigned size); 382 : - 383 268 : void crc32c_init(void) + 383 276 : void crc32c_init(void) 384 : { - 385 268 : crc32c = crc32c_gen; + 385 276 : crc32c = crc32c_gen; 386 : #if HAVE_SSE42 - 387 268 : if (raid_cpu_has_crc32()) { - 388 266 : crc_x86 = 1; - 389 266 : crc32c = crc32c_x86; + 387 276 : if (raid_cpu_has_crc32()) { + 388 274 : crc_x86 = 1; + 389 274 : crc32c = crc32c_x86; 390 : } 391 : #endif - 392 268 : } + 392 276 : } 393 : 394 : /****************************************************************************/ 395 : /* byte operations */ @@ -460,14 +460,14 @@ 398 : * Rotate left. 399 : * In x86/x64 they are optimized with a single assembler instruction. 400 : */ - 401 924861211 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) + 401 796761149 : static inline uint32_t util_rotl32(uint32_t x, int8_t r) 402 : { - 403 924861211 : return (x << r) | (x >> (32 - r)); + 403 796761149 : return (x << r) | (x >> (32 - r)); 404 : } 405 : - 406 461015664 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) + 406 511410252 : static inline uint64_t util_rotl64(uint64_t x, int8_t r) 407 : { - 408 461015664 : return (x << r) | (x >> (64 - r)); + 408 511410252 : return (x << r) | (x >> (64 - r)); 409 : } 410 : 411 : /** @@ -508,15 +508,15 @@ 446 : #include "murmur3.c" 447 : #include "spooky2.c" 448 : - 449 5724756 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) + 449 5791413 : void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) 450 : { - 451 5724756 : switch (kind) { + 451 5791413 : switch (kind) { 452 : case HASH_MURMUR3 : - 453 2252582 : MurmurHash3_x86_128(src, size, seed, digest); - 454 2252582 : break; + 453 1936261 : MurmurHash3_x86_128(src, size, seed, digest); + 454 1936261 : break; 455 : case HASH_SPOOKY2 : - 456 3472174 : SpookyHash128(src, size, seed, digest); - 457 3472174 : break; + 456 3855152 : SpookyHash128(src, size, seed, digest); + 457 3855152 : break; 458 : default : 459 : /* LCOV_EXCL_START */ 460 : log_fatal("Internal inconsistency in hash function %u\n", kind); @@ -524,7 +524,7 @@ 462 : break; 463 : /* LCOV_EXCL_STOP */ 464 : } - 465 5724756 : } + 465 5791413 : } 466 : 467 42 : const char* hash_config_name(unsigned kind) 468 : { @@ -539,67 +539,67 @@ 477 : } 478 : } 479 : - 480 25190 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) + 480 25329 : unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) 481 : { 482 : size_t i; 483 : unsigned count; 484 : - 485 25190 : count = 0; - 486 11153350 : for (i = 0; i < size; ++i) { + 485 25329 : count = 0; + 486 11266593 : for (i = 0; i < size; ++i) { 487 : unsigned j; - 488 11128160 : unsigned char diff = data1[i] ^ data2[i]; - 489 100153440 : for (j = 0; j < 8; ++j) { - 490 89025280 : if ((diff & 1) != 0) - 491 39291929 : ++count; - 492 89025280 : diff >>= 1; + 488 11241264 : unsigned char diff = data1[i] ^ data2[i]; + 489 101171376 : for (j = 0; j < 8; ++j) { + 490 89930112 : if ((diff & 1) != 0) + 491 39652202 : ++count; + 492 89930112 : diff >>= 1; 493 : } 494 : } 495 : - 496 25190 : return 0; + 496 25329 : return count; 497 : } 498 : 499 : /****************************************************************************/ 500 : /* lock */ 501 : 502 : #if HAVE_LOCKFILE - 503 243 : int lock_lock(const char* file) + 503 251 : int lock_lock(const char* file) 504 : { 505 : int f; 506 : - 507 243 : f = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600); - 508 243 : if (f == -1) { + 507 251 : f = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600); + 508 251 : if (f == -1) { 509 : /* LCOV_EXCL_START */ 510 : return -1; 511 : /* LCOV_EXCL_STOP */ 512 : } 513 : 514 : /* exclusive lock, not blocking */ - 515 243 : if (flock(f, LOCK_EX | LOCK_NB) == -1) { + 515 251 : if (flock(f, LOCK_EX | LOCK_NB) == -1) { 516 : /* LCOV_EXCL_START */ 517 : close(f); 518 : return -1; 519 : /* LCOV_EXCL_STOP */ 520 : } 521 : - 522 243 : return f; + 522 251 : return f; 523 : } 524 : #endif 525 : 526 : #if HAVE_LOCKFILE - 527 223 : int lock_unlock(int f) + 527 231 : int lock_unlock(int f) 528 : { 529 : /* 530 : * Intentionally don't remove the lock file. 531 : * Removing it just introduces race course with other process 532 : * that could have already opened it. 533 : */ - 534 223 : if (close(f) == -1) { + 534 231 : if (close(f) == -1) { 535 : /* LCOV_EXCL_START */ 536 : return -1; 537 : /* LCOV_EXCL_STOP */ 538 : } 539 : - 540 223 : return 0; + 540 231 : return 0; 541 : } 542 : #endif 543 : diff --git a/cov/cmdline/util.h.func-sort-c.html b/cov/cmdline/util.h.func-sort-c.html index aba2a712..d5e05907 100644 --- a/cov/cmdline/util.h.func-sort-c.html +++ b/cov/cmdline/util.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,19 +61,19 @@ crc32c_x86_plain - 131602718 + 21302165 crc32c_plain - 128046334 + 20655549 crc32c_plain_char - 23675077 + 3794625 crc32c_gen_plain - 353 + 369
diff --git a/cov/cmdline/util.h.func.html b/cov/cmdline/util.h.func.html index 92bc1cda..de250087 100644 --- a/cov/cmdline/util.h.func.html +++ b/cov/cmdline/util.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,19 +61,19 @@ crc32c_gen_plain - 353 + 369 crc32c_plain - 128046334 + 20655549 crc32c_plain_char - 23675077 + 3794625 crc32c_x86_plain - 131602718 + 21302165
diff --git a/cov/cmdline/util.h.gcov.html b/cov/cmdline/util.h.gcov.html index a736fd08..0023bf5a 100644 --- a/cov/cmdline/util.h.gcov.html +++ b/cov/cmdline/util.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -133,12 +133,12 @@ 71 : /** 72 : * Compute CRC-32 (Castagnoli) for a single byte without the IV. 73 : */ - 74 23675077 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) + 74 3794625 : static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) 75 : { 76 : #if HAVE_SSE42 - 77 23675077 : if (tommy_likely(crc_x86)) { - 78 23675077 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); - 79 23675077 : return crc; + 77 3794625 : if (tommy_likely(crc_x86)) { + 78 3794625 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); + 79 3794625 : return crc; 80 : } 81 : #endif 82 0 : return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8); @@ -147,29 +147,29 @@ 85 : /** 86 : * Compute the CRC-32 (Castagnoli) without the IV. 87 : */ - 88 353 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 88 369 : static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 89 : { - 90 22020969 : while (size >= 4) { - 91 22020263 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; - 92 22020263 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24]; - 93 22020263 : ptr += 4; - 94 22020263 : size -= 4; + 90 23069577 : while (size >= 4) { + 91 23068839 : crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; + 92 23068839 : crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24]; + 93 23068839 : ptr += 4; + 94 23068839 : size -= 4; 95 : } 96 : - 97 715 : while (size) { + 97 747 : while (size) { 98 9 : crc = CRC32C_0[(crc ^ *ptr) & 0xff] ^ (crc >> 8); 99 9 : ++ptr; 100 9 : --size; 101 : } 102 : - 103 353 : return crc; + 103 369 : return crc; 104 : } 105 : 106 : /** 107 : * Compute the CRC-32 (Castagnoli) without the IV. 108 : */ 109 : #if HAVE_SSE42 - 110 131602718 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 110 21302165 : static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 111 : { 112 : #ifdef CONFIG_X86_64 113 : uint64_t crc64 = crc; @@ -180,30 +180,30 @@ 118 : } 119 : crc = crc64; 120 : #else - 121 969717854 : while (size >= 4) { - 122 706512418 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); - 123 706512418 : ptr += 4; - 124 706512418 : size -= 4; + 121 437931649 : while (size >= 4) { + 122 395327319 : asm("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); + 123 395327319 : ptr += 4; + 124 395327319 : size -= 4; 125 : } 126 : #endif - 127 382941674 : while (size) { - 128 119736238 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); - 129 119736238 : ++ptr; - 130 119736238 : --size; + 127 62072231 : while (size) { + 128 19467901 : asm("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); + 129 19467901 : ++ptr; + 130 19467901 : --size; 131 : } 132 : - 133 131602718 : return crc; + 133 21302165 : return crc; 134 : } 135 : #endif 136 : 137 : /** 138 : * Compute CRC-32 (Castagnoli) without the IV. 139 : */ - 140 128046334 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) + 140 20655549 : static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) 141 : { 142 : #if HAVE_SSE42 - 143 128046334 : if (tommy_likely(crc_x86)) { - 144 128046334 : return crc32c_x86_plain(crc, ptr, size); + 143 20655549 : if (tommy_likely(crc_x86)) { + 144 20655549 : return crc32c_x86_plain(crc, ptr, size); 145 : } 146 : #endif 147 0 : return crc32c_gen_plain(crc, ptr, size); diff --git a/cov/index-sort-f.html b/cov/index-sort-f.html index bc18c20f..4839cf1f 100644 --- a/cov/index-sort-f.html +++ b/cov/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 9667 - 10368 - 93.2 % + 9724 + 10419 + 93.3 % Date: - 2015-11-20 + 2016-01-09 Functions: - 553 - 562 - 98.4 % + 555 + 566 + 98.1 % @@ -72,12 +72,12 @@ cmdline -
91.4%91.4%
+
91.6%91.6%
- 91.4 % - 7344 / 8033 - 97.7 % - 388 / 397 + 91.6 % + 7401 / 8084 + 97.3 % + 390 / 401 tommyds diff --git a/cov/index-sort-l.html b/cov/index-sort-l.html index 5f59d954..1ebddaa3 100644 --- a/cov/index-sort-l.html +++ b/cov/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 9667 - 10368 - 93.2 % + 9724 + 10419 + 93.3 % Date: - 2015-11-20 + 2016-01-09 Functions: - 553 - 562 - 98.4 % + 555 + 566 + 98.1 % @@ -72,12 +72,12 @@ cmdline -
91.4%91.4%
+
91.6%91.6%
- 91.4 % - 7344 / 8033 - 97.7 % - 388 / 397 + 91.6 % + 7401 / 8084 + 97.3 % + 390 / 401 raid diff --git a/cov/index.html b/cov/index.html index abaf833c..b78b1c9d 100644 --- a/cov/index.html +++ b/cov/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 9667 - 10368 - 93.2 % + 9724 + 10419 + 93.3 % Date: - 2015-11-20 + 2016-01-09 Functions: - 553 - 562 - 98.4 % + 555 + 566 + 98.1 % @@ -72,12 +72,12 @@ cmdline -
91.4%91.4%
+
91.6%91.6%
- 91.4 % - 7344 / 8033 - 97.7 % - 388 / 397 + 91.6 % + 7401 / 8084 + 97.3 % + 390 / 401 raid diff --git a/cov/raid/check.c.func-sort-c.html b/cov/raid/check.c.func-sort-c.html index 0c9b19f8..f959d7cc 100644 --- a/cov/raid/check.c.func-sort-c.html +++ b/cov/raid/check.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 diff --git a/cov/raid/check.c.func.html b/cov/raid/check.c.func.html index eaef437a..0521de7f 100644 --- a/cov/raid/check.c.func.html +++ b/cov/raid/check.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 diff --git a/cov/raid/check.c.gcov.html b/cov/raid/check.c.gcov.html index 7b809175..adb2d25e 100644 --- a/cov/raid/check.c.gcov.html +++ b/cov/raid/check.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 diff --git a/cov/raid/combo.h.func-sort-c.html b/cov/raid/combo.h.func-sort-c.html index 9dc0148a..acdfb314 100644 --- a/cov/raid/combo.h.func-sort-c.html +++ b/cov/raid/combo.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/combo.h.func.html b/cov/raid/combo.h.func.html index 428b1c38..38c5a666 100644 --- a/cov/raid/combo.h.func.html +++ b/cov/raid/combo.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/combo.h.gcov.html b/cov/raid/combo.h.gcov.html index b8f76138..2ab1cb73 100644 --- a/cov/raid/combo.h.gcov.html +++ b/cov/raid/combo.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 @@ -170,10 +170,10 @@ 108 : int i; 109 : 110 : (void)n; /* unused, but kept for clarity */ - 111 215930 : assert(0 < r && r <= n); + 111 209410 : assert(0 < r && r <= n); 112 : - 113 713829 : for (i = 0; i < r; ++i) - 114 497899 : c[i] = i; + 113 691629 : for (i = 0; i < r; ++i) + 114 482219 : c[i] = i; 115 : } 116 : 117 : /** @@ -182,19 +182,19 @@ 120 : */ 121 : static __always_inline int combination_next(int r, int n, int *c) 122 : { - 123 51676 : int i = r - 1; /* present position */ - 124 51676 : int h = n; /* high limit for this position */ + 123 51718 : int i = r - 1; /* present position */ + 124 51718 : int h = n; /* high limit for this position */ 125 : 126 : recurse: 127 : /* next element at position i */ - 128 84549 : ++c[i]; + 128 84591 : ++c[i]; 129 : 130 : /* if the position has reached the max */ - 131 84549 : if (c[i] >= h) { + 131 84591 : if (c[i] >= h) { 132 : 133 : /* if we are at the first level, we have finished */ - 134 44859 : if (i == 0) - 135 11986 : return 0; + 134 44873 : if (i == 0) + 135 12000 : return 0; 136 : 137 : /* increase the previous position */ 138 32873 : --i; @@ -202,16 +202,16 @@ 140 : goto recurse; 141 : } 142 : - 143 39690 : ++i; + 143 39718 : ++i; 144 : 145 : /* initialize all the next positions, if any */ - 146 62235 : while (i < r) { + 146 62263 : while (i < r) { 147 : /* each position start at the next value of the previous one */ 148 22545 : c[i] = c[i - 1] + 1; 149 22545 : ++i; 150 : } 151 : - 152 39690 : return 1; + 152 39718 : return 1; 153 : } 154 : #endif 155 : diff --git a/cov/raid/cpu.h.func-sort-c.html b/cov/raid/cpu.h.func-sort-c.html index 8c4e735a..0c37739e 100644 --- a/cov/raid/cpu.h.func-sort-c.html +++ b/cov/raid/cpu.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 12 @@ -61,43 +61,43 @@ raid_cpuid - 1960 + 2016 raid_cpu_match_sse - 1117 + 1149 raid_cpu_has_ssse3 - 553 + 569 raid_cpu_match_avx - 300 + 308 raid_cpu_has_avx2 - 300 + 308 raid_cpu_has_sse2 - 288 + 296 raid_cpu_has_crc32 - 276 + 284 raid_cpu_info - 260 + 268 raid_cpu_is_atom - 256 + 264 raid_cpu_has_slowmult - 252 + 260 raid_xgetbv diff --git a/cov/raid/cpu.h.func.html b/cov/raid/cpu.h.func.html index d313f5e0..738406d1 100644 --- a/cov/raid/cpu.h.func.html +++ b/cov/raid/cpu.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 12 @@ -61,11 +61,11 @@ raid_cpu_has_avx2 - 300 + 308 raid_cpu_has_crc32 - 276 + 284 raid_cpu_has_slowextendedreg @@ -73,35 +73,35 @@ raid_cpu_has_slowmult - 252 - - - raid_cpu_has_sse2 - 288 - - - raid_cpu_has_ssse3 - 553 - - - raid_cpu_info 260 + + raid_cpu_has_sse2 + 296 + + + raid_cpu_has_ssse3 + 569 + + + raid_cpu_info + 268 + raid_cpu_is_atom - 256 + 264 raid_cpu_match_avx - 300 + 308 raid_cpu_match_sse - 1117 + 1149 raid_cpuid - 1960 + 2016 raid_xgetbv diff --git a/cov/raid/cpu.h.gcov.html b/cov/raid/cpu.h.gcov.html index af6259db..18c79d61 100644 --- a/cov/raid/cpu.h.gcov.html +++ b/cov/raid/cpu.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 12 @@ -79,9 +79,9 @@ 17 : 18 : #ifdef CONFIG_X86 19 : - 20 1960 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg) + 20 2016 : static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg) 21 : { - 22 1960 : asm volatile ( + 22 2016 : asm volatile ( 23 : #if defined(__i386__) && defined(__PIC__) 24 : /* allow compilation in PIC mode saving ebx */ 25 : "xchgl %%ebx, %1\n" @@ -91,11 +91,11 @@ 29 : : "0" (func_eax), "2" (sub_ecx) 30 : #else 31 : "cpuid\n" - 32 1960 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) + 32 2016 : : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) 33 : : "0" (func_eax), "2" (sub_ecx) 34 : #endif 35 : ); - 36 1960 : } + 36 2016 : } 37 : 38 23 : static inline void raid_xgetbv(uint32_t* reg) 39 : { @@ -112,26 +112,26 @@ 50 : 51 : #define CPU_VENDOR_MAX 13 52 : - 53 260 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model) + 53 268 : static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model) 54 : { 55 : uint32_t reg[4]; 56 : unsigned f, ef, m, em; 57 : - 58 260 : raid_cpuid(0, 0, reg); + 58 268 : raid_cpuid(0, 0, reg); 59 : - 60 260 : ((uint32_t*)vendor)[0] = reg[1]; - 61 260 : ((uint32_t*)vendor)[1] = reg[3]; - 62 260 : ((uint32_t*)vendor)[2] = reg[2]; - 63 260 : vendor[12] = 0; + 60 268 : ((uint32_t*)vendor)[0] = reg[1]; + 61 268 : ((uint32_t*)vendor)[1] = reg[3]; + 62 268 : ((uint32_t*)vendor)[2] = reg[2]; + 63 268 : vendor[12] = 0; 64 : - 65 260 : raid_cpuid(1, 0, reg); + 65 268 : raid_cpuid(1, 0, reg); 66 : - 67 260 : f = (reg[0] >> 8) & 0xF; - 68 260 : ef = (reg[0] >> 20) & 0xFF; - 69 260 : m = (reg[0] >> 4) & 0xF; - 70 260 : em = (reg[0] >> 16) & 0xF; + 67 268 : f = (reg[0] >> 8) & 0xF; + 68 268 : ef = (reg[0] >> 20) & 0xFF; + 69 268 : m = (reg[0] >> 4) & 0xF; + 70 268 : em = (reg[0] >> 16) & 0xF; 71 : - 72 260 : if (strcmp(vendor, "AuthenticAMD") == 0) { + 72 268 : if (strcmp(vendor, "AuthenticAMD") == 0) { 73 0 : if (f < 15) { 74 0 : *family = f; 75 0 : *model = m; @@ -140,31 +140,31 @@ 78 0 : *model = m + (em << 4); 79 : } 80 : } else { - 81 260 : *family = f + ef; - 82 260 : *model = m + (em << 4); + 81 268 : *family = f + ef; + 82 268 : *model = m + (em << 4); 83 : } - 84 260 : } + 84 268 : } 85 : - 86 1117 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx) + 86 1149 : static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx) 87 : { 88 : uint32_t reg[4]; 89 : - 90 1117 : raid_cpuid(1, 0, reg); - 91 1117 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + 90 1149 : raid_cpuid(1, 0, reg); + 91 1149 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) 92 18 : return 0; - 93 1099 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx) + 93 1131 : if ((reg[3] & cpuid_1_edx) != cpuid_1_edx) 94 0 : return 0; 95 : - 96 1099 : return 1; + 96 1131 : return 1; 97 : } 98 : - 99 300 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0) + 99 308 : static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0) 100 : { 101 : uint32_t reg[4]; 102 : - 103 300 : raid_cpuid(1, 0, reg); - 104 300 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) - 105 277 : return 0; + 103 308 : raid_cpuid(1, 0, reg); + 104 308 : if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + 105 285 : return 0; 106 : 107 23 : raid_xgetbv(reg); 108 23 : if ((reg[0] & xcr0) != xcr0) @@ -177,7 +177,7 @@ 115 23 : return 1; 116 : } 117 : - 118 288 : static inline int raid_cpu_has_sse2(void) + 118 296 : static inline int raid_cpu_has_sse2(void) 119 : { 120 : /* 121 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -191,12 +191,12 @@ 129 : * 2. Check that the processor supports the SSE and/or SSE2 extensions (true if 130 : * CPUID.01H:EDX.SSE[bit 25] = 1 and/or CPUID.01H:EDX.SSE2[bit 26] = 1). 131 : */ - 132 288 : return raid_cpu_match_sse( + 132 296 : return raid_cpu_match_sse( 133 : 0, 134 : 1 << 26); /* SSE2 */ 135 : } 136 : - 137 553 : static inline int raid_cpu_has_ssse3(void) + 137 569 : static inline int raid_cpu_has_ssse3(void) 138 : { 139 : /* 140 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -208,12 +208,12 @@ 146 : * Next, use the additional step provided below: 147 : * Check that the processor supports SSSE3 (if CPUID.01H:ECX.SSSE3[bit 9] = 1). 148 : */ - 149 553 : return raid_cpu_match_sse( + 149 569 : return raid_cpu_match_sse( 150 : 1 << 9, /* SSSE3 */ 151 : 1 << 26); /* SSE2 */ 152 : } 153 : - 154 276 : static inline int raid_cpu_has_crc32(void) + 154 284 : static inline int raid_cpu_has_crc32(void) 155 : { 156 : /* 157 : * Intel® 64 and IA-32 Architectures Software Developer's Manual @@ -224,12 +224,12 @@ 162 : * Before an application attempts to use the CRC32 instruction, it must check 163 : * that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1). 164 : */ - 165 276 : return raid_cpu_match_sse( + 165 284 : return raid_cpu_match_sse( 166 : 1 << 20, /* CRC32 */ 167 : 0); 168 : } 169 : - 170 300 : static inline int raid_cpu_has_avx2(void) + 170 308 : static inline int raid_cpu_has_avx2(void) 171 : { 172 : /* 173 : * Intel Architecture Instruction Set Extensions Programming Reference @@ -246,7 +246,7 @@ 184 : * Application Software must identify that hardware supports AVX, after that it must 185 : * also detect support for AVX2 by checking CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]. 186 : */ - 187 300 : return raid_cpu_match_avx( + 187 308 : return raid_cpu_match_avx( 188 : (1 << 27) | (1 << 28), /* OSXSAVE and AVX */ 189 : 1 << 5, /* AVX2 */ 190 : 3 << 1); /* OS saves XMM and YMM registers */ @@ -277,9 +277,9 @@ 215 : /** 216 : * Check if it's an Intel Atom CPU. 217 : */ - 218 256 : static inline int raid_cpu_is_atom(unsigned family, unsigned model) + 218 264 : static inline int raid_cpu_is_atom(unsigned family, unsigned model) 219 : { - 220 256 : if (family != 6) + 220 264 : if (family != 6) 221 3 : return 0; 222 : 223 : /* @@ -300,17 +300,17 @@ 238 : * 4D (77) Atom 8C (22 nm) 4 MB L2 (AVN) 239 : * ?? Atom ?C (14 nm) ? MB L2 (DVN) 240 : */ - 241 506 : return model == 28 || model == 38 || model == 54 - 242 253 : || model == 39 || model == 53 || model == 74 - 243 253 : || model == 90 || model == 55 || model == 76 - 244 506 : || model == 93 || model == 77; + 241 522 : return model == 28 || model == 38 || model == 54 + 242 261 : || model == 39 || model == 53 || model == 74 + 243 261 : || model == 90 || model == 55 || model == 76 + 244 522 : || model == 93 || model == 77; 245 : } 246 : 247 : /** 248 : * Check if the processor has a slow MULT implementation. 249 : * If yes, it's better to use a hash not based on multiplication. 250 : */ - 251 252 : static inline int raid_cpu_has_slowmult(void) + 251 260 : static inline int raid_cpu_has_slowmult(void) 252 : { 253 : char vendor[CPU_VENDOR_MAX]; 254 : unsigned family; @@ -320,9 +320,9 @@ 258 : * In some cases Murmur3 based on MUL instruction, 259 : * is a LOT slower than Spooky2 based on SHIFTs. 260 : */ - 261 252 : raid_cpu_info(vendor, &family, &model); + 261 260 : raid_cpu_info(vendor, &family, &model); 262 : - 263 252 : if (strcmp(vendor, "GenuineIntel") == 0) { + 263 260 : if (strcmp(vendor, "GenuineIntel") == 0) { 264 : /* 265 : * Intel Atom (Model 28) 266 : * murmur3:378 MB/s, spooky2:3413 MB/s (x86) @@ -330,11 +330,11 @@ 268 : * Intel Atom (Model 77) 269 : * murmur3:1311 MB/s, spooky2:4056 MB/s (x64) 270 : */ - 271 252 : if (raid_cpu_is_atom(family, model)) + 271 260 : if (raid_cpu_is_atom(family, model)) 272 0 : return 1; 273 : } 274 : - 275 252 : return 0; + 275 260 : return 0; 276 : } 277 : 278 : /** @@ -368,17 +368,29 @@ 306 : * Intel Atom (Model 77) 307 : * par2_sse2:5686 MB/s, par2_sse2e:5250 MB/s 308 : * parz_sse2:3100 MB/s, parz_sse2e:3400 MB/s - 309 : */ - 310 4 : if (raid_cpu_is_atom(family, model)) - 311 0 : return 1; - 312 : } - 313 : - 314 4 : return 0; - 315 : } - 316 : #endif - 317 : - 318 : #endif - 319 : + 309 : * par3_sse3:1921 MB/s, par3_sse3e:1813 MB/s + 310 : * par4_sse3:1175 MB/s, par4_sse3e:1113 MB/s + 311 : * par5_sse3:876 MB/s, par5_sse3e:675 MB/s + 312 : * par6_sse3:705 MB/s, par6_sse3e:529 MB/s + 313 : * + 314 : * Intel Atom (Model 77) "Avoton C2750" + 315 : * par2_sse2:5661 MB/s, par2_sse2e:5382 MB/s + 316 : * parz_sse2:3110 MB/s, parz_sse2e:3450 MB/s + 317 : * par3_sse3:1769 MB/s, par3_sse3e:1856 MB/s + 318 : * par4_sse3:1221 MB/s, par4_sse3e:1141 MB/s + 319 : * par5_sse3:910 MB/s, par5_sse3e:675 MB/s + 320 : * par6_sse3:720 MB/s, par6_sse3e:534 MB/s + 321 : */ + 322 4 : if (raid_cpu_is_atom(family, model)) + 323 0 : return 1; + 324 : } + 325 : + 326 4 : return 0; + 327 : } + 328 : #endif + 329 : + 330 : #endif + 331 : diff --git a/cov/raid/gf.h.func-sort-c.html b/cov/raid/gf.h.func-sort-c.html index 38e50d01..7af0ce91 100644 --- a/cov/raid/gf.h.func-sort-c.html +++ b/cov/raid/gf.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/gf.h.func.html b/cov/raid/gf.h.func.html index d99cf543..888e7000 100644 --- a/cov/raid/gf.h.func.html +++ b/cov/raid/gf.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/gf.h.gcov.html b/cov/raid/gf.h.gcov.html index f7076a13..df951c95 100644 --- a/cov/raid/gf.h.gcov.html +++ b/cov/raid/gf.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 @@ -88,7 +88,7 @@ 26 : */ 27 : static __always_inline uint8_t mul(uint8_t a, uint8_t b) 28 : { - 29 23813346 : return gfmul[a][b]; + 29 23756618 : return gfmul[a][b]; 30 : } 31 : 32 : /* @@ -97,9 +97,9 @@ 35 : */ 36 : static __always_inline uint8_t inv(uint8_t v) 37 : { - 38 635522 : BUG_ON(v == 0); /* division by zero */ + 38 634222 : BUG_ON(v == 0); /* division by zero */ 39 : - 40 635522 : return gfinv[v]; + 40 634222 : return gfinv[v]; 41 : } 42 : 43 : /* @@ -125,7 +125,7 @@ 63 : */ 64 : static __always_inline uint8_t A(int p, int d) 65 : { - 66 2605866 : return gfgen[p][d]; + 66 2600612 : return gfgen[p][d]; 67 : } 68 : 69 : /* diff --git a/cov/raid/helper.c.func-sort-c.html b/cov/raid/helper.c.func-sort-c.html index 47ed9277..108d31b9 100644 --- a/cov/raid/helper.c.func-sort-c.html +++ b/cov/raid/helper.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/helper.c.func.html b/cov/raid/helper.c.func.html index d1b46f34..0d73260c 100644 --- a/cov/raid/helper.c.func.html +++ b/cov/raid/helper.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/helper.c.gcov.html b/cov/raid/helper.c.gcov.html index 16b6e3f4..884204c0 100644 --- a/cov/raid/helper.c.gcov.html +++ b/cov/raid/helper.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/index-sort-f.html b/cov/raid/index-sort-f.html index 53f2d677..c85a5cc2 100644 --- a/cov/raid/index-sort-f.html +++ b/cov/raid/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 83 diff --git a/cov/raid/index-sort-l.html b/cov/raid/index-sort-l.html index 194b0b2c..f03066e7 100644 --- a/cov/raid/index-sort-l.html +++ b/cov/raid/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 83 diff --git a/cov/raid/index.html b/cov/raid/index.html index c0b34a7b..bf806d40 100644 --- a/cov/raid/index.html +++ b/cov/raid/index.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 83 diff --git a/cov/raid/int.c.func-sort-c.html b/cov/raid/int.c.func-sort-c.html index 1e9686f8..660780c1 100644 --- a/cov/raid/int.c.func-sort-c.html +++ b/cov/raid/int.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -69,7 +69,7 @@ raid_gen1_int64 - 188 + 191 raid_rec1_int8 @@ -77,7 +77,7 @@ raid_gen1_int32 - 117 + 119 raid_gen2_int64 @@ -101,7 +101,7 @@ raid_gen6_int8 - 16 + 18
diff --git a/cov/raid/int.c.func.html b/cov/raid/int.c.func.html index a9474d76..15c0b92e 100644 --- a/cov/raid/int.c.func.html +++ b/cov/raid/int.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -61,11 +61,11 @@ raid_gen1_int32 - 117 + 119 raid_gen1_int64 - 188 + 191 raid_gen2_int32 @@ -89,7 +89,7 @@ raid_gen6_int8 - 16 + 18 raid_rec1_int8 diff --git a/cov/raid/int.c.gcov.html b/cov/raid/int.c.gcov.html index c6a492cd..861cd372 100644 --- a/cov/raid/int.c.gcov.html +++ b/cov/raid/int.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -80,9 +80,9 @@ 18 : /* 19 : * GEN1 (RAID5 with xor) 32bit C implementation 20 : */ - 21 117 : void raid_gen1_int32(int nd, size_t size, void **vv) + 21 119 : void raid_gen1_int32(int nd, size_t size, void **vv) 22 : { - 23 117 : uint8_t **v = (uint8_t **)vv; + 23 119 : uint8_t **v = (uint8_t **)vv; 24 : uint8_t *p; 25 : int d, l; 26 : size_t i; @@ -90,27 +90,27 @@ 28 : uint32_t p0; 29 : uint32_t p1; 30 : - 31 117 : l = nd - 1; - 32 117 : p = v[nd]; + 31 119 : l = nd - 1; + 32 119 : p = v[nd]; 33 : - 34 3735765 : for (i = 0; i < size; i += 8) { - 35 3735648 : p0 = v_32(v[l][i]); - 36 3735648 : p1 = v_32(v[l][i + 4]); - 37 29886496 : for (d = l - 1; d >= 0; --d) { - 38 26150848 : p0 ^= v_32(v[d][i]); - 39 26150848 : p1 ^= v_32(v[d][i + 4]); + 34 3801303 : for (i = 0; i < size; i += 8) { + 35 3801184 : p0 = v_32(v[l][i]); + 36 3801184 : p1 = v_32(v[l][i + 4]); + 37 30410784 : for (d = l - 1; d >= 0; --d) { + 38 26609600 : p0 ^= v_32(v[d][i]); + 39 26609600 : p1 ^= v_32(v[d][i + 4]); 40 : } - 41 3735648 : v_32(p[i]) = p0; - 42 3735648 : v_32(p[i + 4]) = p1; + 41 3801184 : v_32(p[i]) = p0; + 42 3801184 : v_32(p[i + 4]) = p1; 43 : } - 44 117 : } + 44 119 : } 45 : 46 : /* 47 : * GEN1 (RAID5 with xor) 64bit C implementation 48 : */ - 49 188 : void raid_gen1_int64(int nd, size_t size, void **vv) + 49 191 : void raid_gen1_int64(int nd, size_t size, void **vv) 50 : { - 51 188 : uint8_t **v = (uint8_t **)vv; + 51 191 : uint8_t **v = (uint8_t **)vv; 52 : uint8_t *p; 53 : int d, l; 54 : size_t i; @@ -118,20 +118,20 @@ 56 : uint64_t p0; 57 : uint64_t p1; 58 : - 59 188 : l = nd - 1; - 60 188 : p = v[nd]; + 59 191 : l = nd - 1; + 60 191 : p = v[nd]; 61 : - 62 3031276 : for (i = 0; i < size; i += 16) { - 63 3031088 : p0 = v_64(v[l][i]); - 64 3031088 : p1 = v_64(v[l][i + 8]); - 65 24249360 : for (d = l - 1; d >= 0; --d) { - 66 21218272 : p0 ^= v_64(v[d][i]); - 67 21218272 : p1 ^= v_64(v[d][i + 8]); + 62 3080431 : for (i = 0; i < size; i += 16) { + 63 3080240 : p0 = v_64(v[l][i]); + 64 3080240 : p1 = v_64(v[l][i + 8]); + 65 24642576 : for (d = l - 1; d >= 0; --d) { + 66 21562336 : p0 ^= v_64(v[d][i]); + 67 21562336 : p1 ^= v_64(v[d][i + 8]); 68 : } - 69 3031088 : v_64(p[i]) = p0; - 70 3031088 : v_64(p[i + 8]) = p1; + 69 3080240 : v_64(p[i]) = p0; + 70 3080240 : v_64(p[i + 8]) = p1; 71 : } - 72 188 : } + 72 191 : } 73 : 74 : /* 75 : * GEN2 (RAID6 with powers of 2) 32bit C implementation @@ -379,9 +379,9 @@ 317 : * But this is only a kind of reference function, and we are not really 318 : * interested in speed. 319 : */ - 320 16 : void raid_gen6_int8(int nd, size_t size, void **vv) + 320 18 : void raid_gen6_int8(int nd, size_t size, void **vv) 321 : { - 322 16 : uint8_t **v = (uint8_t **)vv; + 322 18 : uint8_t **v = (uint8_t **)vv; 323 : uint8_t *p; 324 : uint8_t *q; 325 : uint8_t *r; @@ -393,45 +393,45 @@ 331 : 332 : uint8_t d0, u0, t0, s0, r0, q0, p0; 333 : - 334 16 : l = nd - 1; - 335 16 : p = v[nd]; - 336 16 : q = v[nd + 1]; - 337 16 : r = v[nd + 2]; - 338 16 : s = v[nd + 3]; - 339 16 : t = v[nd + 4]; - 340 16 : u = v[nd + 5]; + 334 18 : l = nd - 1; + 335 18 : p = v[nd]; + 336 18 : q = v[nd + 1]; + 337 18 : r = v[nd + 2]; + 338 18 : s = v[nd + 3]; + 339 18 : t = v[nd + 4]; + 340 18 : u = v[nd + 5]; 341 : - 342 3670544 : for (i = 0; i < size; i += 1) { - 343 3670528 : p0 = q0 = r0 = s0 = t0 = u0 = 0; - 344 29368576 : for (d = l; d > 0; --d) { - 345 25698048 : d0 = v_8(v[d][i]); + 342 4194834 : for (i = 0; i < size; i += 1) { + 343 4194816 : p0 = q0 = r0 = s0 = t0 = u0 = 0; + 344 33562880 : for (d = l; d > 0; --d) { + 345 29368064 : d0 = v_8(v[d][i]); 346 : - 347 25698048 : p0 ^= d0; - 348 25698048 : q0 ^= gfmul[d0][gfgen[1][d]]; - 349 25698048 : r0 ^= gfmul[d0][gfgen[2][d]]; - 350 25698048 : s0 ^= gfmul[d0][gfgen[3][d]]; - 351 25698048 : t0 ^= gfmul[d0][gfgen[4][d]]; - 352 25698048 : u0 ^= gfmul[d0][gfgen[5][d]]; + 347 29368064 : p0 ^= d0; + 348 29368064 : q0 ^= gfmul[d0][gfgen[1][d]]; + 349 29368064 : r0 ^= gfmul[d0][gfgen[2][d]]; + 350 29368064 : s0 ^= gfmul[d0][gfgen[3][d]]; + 351 29368064 : t0 ^= gfmul[d0][gfgen[4][d]]; + 352 29368064 : u0 ^= gfmul[d0][gfgen[5][d]]; 353 : } 354 : 355 : /* first disk with all coefficients at 1 */ - 356 3670528 : d0 = v_8(v[0][i]); + 356 4194816 : d0 = v_8(v[0][i]); 357 : - 358 3670528 : p0 ^= d0; - 359 3670528 : q0 ^= d0; - 360 3670528 : r0 ^= d0; - 361 3670528 : s0 ^= d0; - 362 3670528 : t0 ^= d0; - 363 3670528 : u0 ^= d0; + 358 4194816 : p0 ^= d0; + 359 4194816 : q0 ^= d0; + 360 4194816 : r0 ^= d0; + 361 4194816 : s0 ^= d0; + 362 4194816 : t0 ^= d0; + 363 4194816 : u0 ^= d0; 364 : - 365 3670528 : v_8(p[i]) = p0; - 366 3670528 : v_8(q[i]) = q0; - 367 3670528 : v_8(r[i]) = r0; - 368 3670528 : v_8(s[i]) = s0; - 369 3670528 : v_8(t[i]) = t0; - 370 3670528 : v_8(u[i]) = u0; + 365 4194816 : v_8(p[i]) = p0; + 366 4194816 : v_8(q[i]) = q0; + 367 4194816 : v_8(r[i]) = r0; + 368 4194816 : v_8(s[i]) = s0; + 369 4194816 : v_8(t[i]) = t0; + 370 4194816 : v_8(u[i]) = u0; 371 : } - 372 16 : } + 372 18 : } 373 : 374 : /* 375 : * Recover failure of one data block at index id[0] using parity at index diff --git a/cov/raid/internal.h.func-sort-c.html b/cov/raid/internal.h.func-sort-c.html index 3b75e83e..7dd87557 100644 --- a/cov/raid/internal.h.func-sort-c.html +++ b/cov/raid/internal.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/internal.h.func.html b/cov/raid/internal.h.func.html index ee4ceee8..967a0919 100644 --- a/cov/raid/internal.h.func.html +++ b/cov/raid/internal.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 diff --git a/cov/raid/internal.h.gcov.html b/cov/raid/internal.h.gcov.html index 3e410102..ebbd007d 100644 --- a/cov/raid/internal.h.gcov.html +++ b/cov/raid/internal.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 0 @@ -159,11 +159,11 @@ 97 : */ 98 : static __always_inline void *__align_ptr(void *ptr, uintptr_t size) 99 : { - 100 696987 : uintptr_t offset = (uintptr_t)ptr; + 100 706415 : uintptr_t offset = (uintptr_t)ptr; 101 : - 102 696987 : offset = (offset + size - 1U) & ~(size - 1U); + 102 706415 : offset = (offset + size - 1U) & ~(size - 1U); 103 : - 104 696987 : return (void *)offset; + 104 706415 : return (void *)offset; 105 : } 106 : 107 : /* @@ -284,7 +284,7 @@ 222 : /* that use a weak memory model. To ensure that other processors */ 223 : /* see correctly the data written, we use a store-store memory */ 224 : /* barrier at the end of the asm code */ - 225 1365700 : asm volatile ("sfence" : : : "memory"); + 225 1360449 : asm volatile ("sfence" : : : "memory"); 226 : 227 : /* clobbers registers used in the asm code */ 228 : /* this is required because in the Windows ABI, */ diff --git a/cov/raid/intz.c.func-sort-c.html b/cov/raid/intz.c.func-sort-c.html index b79b344c..55b7b56a 100644 --- a/cov/raid/intz.c.func-sort-c.html +++ b/cov/raid/intz.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/intz.c.func.html b/cov/raid/intz.c.func.html index 081fcf8b..53b342cf 100644 --- a/cov/raid/intz.c.func.html +++ b/cov/raid/intz.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/intz.c.gcov.html b/cov/raid/intz.c.gcov.html index 68473b3c..5e3bd004 100644 --- a/cov/raid/intz.c.gcov.html +++ b/cov/raid/intz.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 diff --git a/cov/raid/memory.c.func-sort-c.html b/cov/raid/memory.c.func-sort-c.html index fd1f5017..5c3a69d2 100644 --- a/cov/raid/memory.c.func-sort-c.html +++ b/cov/raid/memory.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ raid_mtest_vector - 2579 + 1908 raid_malloc_align - 290 + 306 raid_malloc_vector - 207 + 215 raid_mrand_vector diff --git a/cov/raid/memory.c.func.html b/cov/raid/memory.c.func.html index 25536f02..cc06ef36 100644 --- a/cov/raid/memory.c.func.html +++ b/cov/raid/memory.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,11 +61,11 @@ raid_malloc_align - 290 + 306 raid_malloc_vector - 207 + 215 raid_mrand_vector @@ -73,7 +73,7 @@ raid_mtest_vector - 2579 + 1908
diff --git a/cov/raid/memory.c.gcov.html b/cov/raid/memory.c.gcov.html index 3830eccb..aa6061b4 100644 --- a/cov/raid/memory.c.gcov.html +++ b/cov/raid/memory.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -77,66 +77,66 @@ 15 : #include "internal.h" 16 : #include "memory.h" 17 : - 18 290 : void *raid_malloc_align(size_t size, void **freeptr) + 18 306 : void *raid_malloc_align(size_t size, void **freeptr) 19 : { 20 : unsigned char *ptr; 21 : uintptr_t offset; 22 : - 23 290 : ptr = malloc(size + RAID_MALLOC_ALIGN); - 24 290 : if (!ptr) { + 23 306 : ptr = malloc(size + RAID_MALLOC_ALIGN); + 24 306 : if (!ptr) { 25 : /* LCOV_EXCL_START */ 26 : return 0; 27 : /* LCOV_EXCL_STOP */ 28 : } 29 : - 30 290 : *freeptr = ptr; + 30 306 : *freeptr = ptr; 31 : - 32 290 : offset = ((uintptr_t)ptr) % RAID_MALLOC_ALIGN; + 32 306 : offset = ((uintptr_t)ptr) % RAID_MALLOC_ALIGN; 33 : - 34 290 : if (offset != 0) - 35 287 : ptr += RAID_MALLOC_ALIGN - offset; + 34 306 : if (offset != 0) + 35 297 : ptr += RAID_MALLOC_ALIGN - offset; 36 : - 37 290 : return ptr; + 37 306 : return ptr; 38 : } 39 : - 40 207 : void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr) + 40 215 : void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr) 41 : { 42 : void **v; 43 : unsigned char *va; 44 : int i; 45 : - 46 207 : BUG_ON(n <= 0 || nd < 0); + 46 215 : BUG_ON(n <= 0 || nd < 0); 47 : - 48 207 : v = malloc(n * sizeof(void *)); - 49 207 : if (!v) { + 48 215 : v = malloc(n * sizeof(void *)); + 49 215 : if (!v) { 50 : /* LCOV_EXCL_START */ 51 : return 0; 52 : /* LCOV_EXCL_STOP */ 53 : } 54 : - 55 207 : va = raid_malloc_align(n * (size + RAID_MALLOC_DISPLACEMENT), freeptr); - 56 207 : if (!va) { + 55 215 : va = raid_malloc_align(n * (size + RAID_MALLOC_DISPLACEMENT), freeptr); + 56 215 : if (!va) { 57 : /* LCOV_EXCL_START */ 58 : free(v); 59 : return 0; 60 : /* LCOV_EXCL_STOP */ 61 : } 62 : - 63 3676 : for (i = 0; i < n; ++i) { - 64 3469 : v[i] = va; - 65 3469 : va += size + RAID_MALLOC_DISPLACEMENT; + 63 3836 : for (i = 0; i < n; ++i) { + 64 3621 : v[i] = va; + 65 3621 : va += size + RAID_MALLOC_DISPLACEMENT; 66 : } 67 : 68 : /* reverse order of the data blocks */ 69 : /* because they are usually accessed from the last one */ - 70 866 : for (i = 0; i < nd / 2; ++i) { - 71 659 : void *ptr = v[i]; + 70 898 : for (i = 0; i < nd / 2; ++i) { + 71 683 : void *ptr = v[i]; 72 : - 73 659 : v[i] = v[nd - 1 - i]; - 74 659 : v[nd - 1 - i] = ptr; + 73 683 : v[i] = v[nd - 1 - i]; + 74 683 : v[nd - 1 - i] = ptr; 75 : } 76 : - 77 207 : return v; + 77 215 : return v; 78 : } 79 : 80 5 : void raid_mrand_vector(unsigned seed, int n, size_t size, void **vv) @@ -154,9 +154,9 @@ 92 : } 93 5 : } 94 : - 95 2579 : int raid_mtest_vector(int n, size_t size, void **vv) + 95 1908 : int raid_mtest_vector(int n, size_t size, void **vv) 96 : { - 97 2579 : unsigned char **v = (unsigned char **)vv; + 97 1908 : unsigned char **v = (unsigned char **)vv; 98 : int i; 99 : size_t j; 100 : unsigned k; @@ -164,44 +164,44 @@ 102 : unsigned char p; 103 : 104 : /* fill with 0 */ - 105 2579 : d = 0; - 106 5254 : for (i = 0; i < n; ++i) - 107 137567034 : for (j = 0; j < size; ++j) - 108 137564359 : v[i][j] = d; + 105 1908 : d = 0; + 106 3908 : for (i = 0; i < n; ++i) + 107 107048920 : for (j = 0; j < size; ++j) + 108 107046920 : v[i][j] = d; 109 : 110 : /* test with all the byte patterns */ - 111 661244 : for (k = 1; k < 256; ++k) { - 112 658661 : p = d; - 113 658661 : d = k; + 111 488448 : for (k = 1; k < 256; ++k) { + 112 486540 : p = d; + 113 486540 : d = k; 114 : 115 : /* forward fill */ - 116 1340781 : for (i = 0; i < n; ++i) { - 117 24484944507 : for (j = 0; j < size; ++j) { - 118 24484262387 : if (v[i][j] != p) { + 116 996540 : for (i = 0; i < n; ++i) { + 117 27297474600 : for (j = 0; j < size; ++j) { + 118 27296964600 : if (v[i][j] != p) { 119 : /* LCOV_EXCL_START */ 120 : return -1; 121 : /* LCOV_EXCL_STOP */ 122 : } - 123 24484262387 : v[i][j] = d; + 123 27296964600 : v[i][j] = d; 124 : } 125 : } 126 : - 127 658661 : p = d; - 128 658661 : d = ~p; + 127 486540 : p = d; + 128 486540 : d = ~p; 129 : /* backward fill with complement */ - 130 1340786 : for (i = 0; i < n; ++i) { - 131 24126962138 : for (j = size; j > 0; --j) { - 132 24126280013 : if (v[i][j - 1] != p) { + 130 996540 : for (i = 0; i < n; ++i) { + 131 27297474600 : for (j = size; j > 0; --j) { + 132 27296964600 : if (v[i][j - 1] != p) { 133 : /* LCOV_EXCL_START */ 134 : return -1; 135 : /* LCOV_EXCL_STOP */ 136 : } - 137 24126280017 : v[i][j - 1] = d; + 137 27296964600 : v[i][j - 1] = d; 138 : } 139 : } 140 : } 141 : - 142 2583 : return 0; + 142 1908 : return 0; 143 : } 144 : diff --git a/cov/raid/module.c.func-sort-c.html b/cov/raid/module.c.func-sort-c.html index 3a1aa0e0..7e3f1ccb 100644 --- a/cov/raid/module.c.func-sort-c.html +++ b/cov/raid/module.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -61,30 +61,30 @@ raid_init - 252 + 260 - raid_test_rec + raid_test_rec 18 - raid_test_data + raid_test_data 18 - raid_test_scan + raid_test_scan 7 - raid_gen_ref + raid_gen_ref 6 - raid_test_par + raid_test_par 6 - raid_selftest + raid_selftest 1 diff --git a/cov/raid/module.c.func.html b/cov/raid/module.c.func.html index a93ef0a6..b40762dd 100644 --- a/cov/raid/module.c.func.html +++ b/cov/raid/module.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -60,31 +60,31 @@ Hit count Sort by hit count - raid_gen_ref + raid_gen_ref 6 raid_init - 252 + 260 - raid_selftest + raid_selftest 1 - raid_test_data + raid_test_data 18 - raid_test_par + raid_test_par 6 - raid_test_rec + raid_test_rec 18 - raid_test_scan + raid_test_scan 7 diff --git a/cov/raid/module.c.gcov.html b/cov/raid/module.c.gcov.html index 5769f207..ffb20426 100644 --- a/cov/raid/module.c.gcov.html +++ b/cov/raid/module.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 @@ -81,34 +81,34 @@ 19 : /* 20 : * Initializes and selects the best algorithm. 21 : */ - 22 252 : void raid_init(void) + 22 260 : void raid_init(void) 23 : { - 24 252 : raid_gen3_ptr = raid_gen3_int8; - 25 252 : raid_gen_ptr[3] = raid_gen4_int8; - 26 252 : raid_gen_ptr[4] = raid_gen5_int8; - 27 252 : raid_gen_ptr[5] = raid_gen6_int8; + 24 260 : raid_gen3_ptr = raid_gen3_int8; + 25 260 : raid_gen_ptr[3] = raid_gen4_int8; + 26 260 : raid_gen_ptr[4] = raid_gen5_int8; + 27 260 : raid_gen_ptr[5] = raid_gen6_int8; 28 : 29 : if (sizeof(void *) == 4) { - 30 252 : raid_gen_ptr[0] = raid_gen1_int32; - 31 252 : raid_gen_ptr[1] = raid_gen2_int32; - 32 252 : raid_genz_ptr = raid_genz_int32; + 30 260 : raid_gen_ptr[0] = raid_gen1_int32; + 31 260 : raid_gen_ptr[1] = raid_gen2_int32; + 32 260 : raid_genz_ptr = raid_genz_int32; 33 : } else { 34 : raid_gen_ptr[0] = raid_gen1_int64; 35 : raid_gen_ptr[1] = raid_gen2_int64; 36 : raid_genz_ptr = raid_genz_int64; 37 : } 38 : - 39 252 : raid_rec_ptr[0] = raid_rec1_int8; - 40 252 : raid_rec_ptr[1] = raid_rec2_int8; - 41 252 : raid_rec_ptr[2] = raid_recX_int8; - 42 252 : raid_rec_ptr[3] = raid_recX_int8; - 43 252 : raid_rec_ptr[4] = raid_recX_int8; - 44 252 : raid_rec_ptr[5] = raid_recX_int8; + 39 260 : raid_rec_ptr[0] = raid_rec1_int8; + 40 260 : raid_rec_ptr[1] = raid_rec2_int8; + 41 260 : raid_rec_ptr[2] = raid_recX_int8; + 42 260 : raid_rec_ptr[3] = raid_recX_int8; + 43 260 : raid_rec_ptr[4] = raid_recX_int8; + 44 260 : raid_rec_ptr[5] = raid_recX_int8; 45 : 46 : #ifdef CONFIG_X86 47 : #ifdef CONFIG_SSE2 - 48 252 : if (raid_cpu_has_sse2()) { - 49 252 : raid_gen_ptr[0] = raid_gen1_sse2; + 48 260 : if (raid_cpu_has_sse2()) { + 49 260 : raid_gen_ptr[0] = raid_gen1_sse2; 50 : #ifdef CONFIG_X86_64 51 : if (raid_cpu_has_slowextendedreg()) { 52 : raid_gen_ptr[1] = raid_gen2_sse2; @@ -118,414 +118,421 @@ 56 : /* note that raid_cpu_has_slowextendedreg() doesn't affect parz */ 57 : raid_genz_ptr = raid_genz_sse2ext; 58 : #else - 59 252 : raid_gen_ptr[1] = raid_gen2_sse2; - 60 252 : raid_genz_ptr = raid_genz_sse2; + 59 260 : raid_gen_ptr[1] = raid_gen2_sse2; + 60 260 : raid_genz_ptr = raid_genz_sse2; 61 : #endif 62 : } 63 : #endif 64 : 65 : #ifdef CONFIG_SSSE3 - 66 252 : if (raid_cpu_has_ssse3()) { + 66 260 : if (raid_cpu_has_ssse3()) { 67 : #ifdef CONFIG_X86_64 - 68 : raid_gen3_ptr = raid_gen3_ssse3ext; - 69 : raid_gen_ptr[3] = raid_gen4_ssse3ext; - 70 : raid_gen_ptr[4] = raid_gen5_ssse3ext; - 71 : raid_gen_ptr[5] = raid_gen6_ssse3ext; - 72 : #else - 73 251 : raid_gen3_ptr = raid_gen3_ssse3; - 74 251 : raid_gen_ptr[3] = raid_gen4_ssse3; - 75 251 : raid_gen_ptr[4] = raid_gen5_ssse3; - 76 251 : raid_gen_ptr[5] = raid_gen6_ssse3; - 77 : #endif - 78 251 : raid_rec_ptr[0] = raid_rec1_ssse3; - 79 251 : raid_rec_ptr[1] = raid_rec2_ssse3; - 80 251 : raid_rec_ptr[2] = raid_recX_ssse3; - 81 251 : raid_rec_ptr[3] = raid_recX_ssse3; - 82 251 : raid_rec_ptr[4] = raid_recX_ssse3; - 83 251 : raid_rec_ptr[5] = raid_recX_ssse3; - 84 : } - 85 : #endif - 86 : - 87 : #ifdef CONFIG_AVX2 - 88 252 : if (raid_cpu_has_avx2()) { - 89 2 : raid_gen_ptr[0] = raid_gen1_avx2; - 90 2 : raid_gen_ptr[1] = raid_gen2_avx2; - 91 : #ifdef CONFIG_X86_64 - 92 : raid_gen3_ptr = raid_gen3_avx2ext; - 93 : raid_genz_ptr = raid_genz_avx2ext; - 94 : raid_gen_ptr[3] = raid_gen4_avx2ext; - 95 : raid_gen_ptr[4] = raid_gen5_avx2ext; - 96 : raid_gen_ptr[5] = raid_gen6_avx2ext; - 97 : #endif - 98 2 : raid_rec_ptr[0] = raid_rec1_avx2; - 99 2 : raid_rec_ptr[1] = raid_rec2_avx2; - 100 2 : raid_rec_ptr[2] = raid_recX_avx2; - 101 2 : raid_rec_ptr[3] = raid_recX_avx2; - 102 2 : raid_rec_ptr[4] = raid_recX_avx2; - 103 2 : raid_rec_ptr[5] = raid_recX_avx2; - 104 : } - 105 : #endif - 106 : #endif /* CONFIG_X86 */ - 107 : - 108 : /* set the default mode */ - 109 252 : raid_mode(RAID_MODE_CAUCHY); - 110 252 : } - 111 : - 112 : /* - 113 : * Reference parity computation. - 114 : */ - 115 6 : void raid_gen_ref(int nd, int np, size_t size, void **vv) - 116 : { - 117 6 : uint8_t **v = (uint8_t **)vv; - 118 : size_t i; - 119 : - 120 5382 : for (i = 0; i < size; ++i) { - 121 : uint8_t p[RAID_PARITY_MAX]; - 122 : int j, d; - 123 : - 124 36096 : for (j = 0; j < np; ++j) - 125 30720 : p[j] = 0; + 68 : if (raid_cpu_has_slowextendedreg()) { + 69 : raid_gen3_ptr = raid_gen3_ssse3; + 70 : raid_gen_ptr[3] = raid_gen4_ssse3; + 71 : raid_gen_ptr[4] = raid_gen5_ssse3; + 72 : raid_gen_ptr[5] = raid_gen6_ssse3; + 73 : } else { + 74 : raid_gen3_ptr = raid_gen3_ssse3ext; + 75 : raid_gen_ptr[3] = raid_gen4_ssse3ext; + 76 : raid_gen_ptr[4] = raid_gen5_ssse3ext; + 77 : raid_gen_ptr[5] = raid_gen6_ssse3ext; + 78 : } + 79 : #else + 80 259 : raid_gen3_ptr = raid_gen3_ssse3; + 81 259 : raid_gen_ptr[3] = raid_gen4_ssse3; + 82 259 : raid_gen_ptr[4] = raid_gen5_ssse3; + 83 259 : raid_gen_ptr[5] = raid_gen6_ssse3; + 84 : #endif + 85 259 : raid_rec_ptr[0] = raid_rec1_ssse3; + 86 259 : raid_rec_ptr[1] = raid_rec2_ssse3; + 87 259 : raid_rec_ptr[2] = raid_recX_ssse3; + 88 259 : raid_rec_ptr[3] = raid_recX_ssse3; + 89 259 : raid_rec_ptr[4] = raid_recX_ssse3; + 90 259 : raid_rec_ptr[5] = raid_recX_ssse3; + 91 : } + 92 : #endif + 93 : + 94 : #ifdef CONFIG_AVX2 + 95 260 : if (raid_cpu_has_avx2()) { + 96 2 : raid_gen_ptr[0] = raid_gen1_avx2; + 97 2 : raid_gen_ptr[1] = raid_gen2_avx2; + 98 : #ifdef CONFIG_X86_64 + 99 : raid_gen3_ptr = raid_gen3_avx2ext; + 100 : raid_genz_ptr = raid_genz_avx2ext; + 101 : raid_gen_ptr[3] = raid_gen4_avx2ext; + 102 : raid_gen_ptr[4] = raid_gen5_avx2ext; + 103 : raid_gen_ptr[5] = raid_gen6_avx2ext; + 104 : #endif + 105 2 : raid_rec_ptr[0] = raid_rec1_avx2; + 106 2 : raid_rec_ptr[1] = raid_rec2_avx2; + 107 2 : raid_rec_ptr[2] = raid_recX_avx2; + 108 2 : raid_rec_ptr[3] = raid_recX_avx2; + 109 2 : raid_rec_ptr[4] = raid_recX_avx2; + 110 2 : raid_rec_ptr[5] = raid_recX_avx2; + 111 : } + 112 : #endif + 113 : #endif /* CONFIG_X86 */ + 114 : + 115 : /* set the default mode */ + 116 260 : raid_mode(RAID_MODE_CAUCHY); + 117 260 : } + 118 : + 119 : /* + 120 : * Reference parity computation. + 121 : */ + 122 6 : void raid_gen_ref(int nd, int np, size_t size, void **vv) + 123 : { + 124 6 : uint8_t **v = (uint8_t **)vv; + 125 : size_t i; 126 : - 127 93696 : for (d = 0; d < nd; ++d) { - 128 88320 : uint8_t b = v[d][i]; - 129 : - 130 584448 : for (j = 0; j < np; ++j) - 131 496128 : p[j] ^= gfmul[b][gfgen[j][d]]; - 132 : } + 127 5382 : for (i = 0; i < size; ++i) { + 128 : uint8_t p[RAID_PARITY_MAX]; + 129 : int j, d; + 130 : + 131 36096 : for (j = 0; j < np; ++j) + 132 30720 : p[j] = 0; 133 : - 134 36096 : for (j = 0; j < np; ++j) - 135 30720 : v[nd + j][i] = p[j]; - 136 : } - 137 6 : } - 138 : - 139 : /* - 140 : * Size of the blocks to test. - 141 : */ - 142 : #define TEST_SIZE 4096 - 143 : - 144 : /* - 145 : * Number of data blocks to test. - 146 : */ - 147 : #define TEST_COUNT (65536 / TEST_SIZE) - 148 : - 149 : /* - 150 : * Parity generation test. - 151 : */ - 152 6 : static int raid_test_par(int nd, int np, size_t size, void **v, void **ref) - 153 : { - 154 : int i; - 155 : void *t[TEST_COUNT + RAID_PARITY_MAX]; - 156 : - 157 : /* setup data */ - 158 102 : for (i = 0; i < nd; ++i) - 159 96 : t[i] = ref[i]; - 160 : - 161 : /* setup parity */ - 162 27 : for (i = 0; i < np; ++i) - 163 21 : t[nd + i] = v[nd + i]; - 164 : - 165 6 : raid_gen(nd, np, size, t); - 166 : - 167 : /* compare parity */ - 168 27 : for (i = 0; i < np; ++i) { - 169 21 : if (memcmp(t[nd + i], ref[nd + i], size) != 0) { - 170 : /* LCOV_EXCL_START */ - 171 : return -1; - 172 : /* LCOV_EXCL_STOP */ - 173 : } - 174 : } - 175 : - 176 6 : return 0; - 177 : } - 178 : - 179 : /* - 180 : * Recovering test. - 181 : */ - 182 18 : static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) - 183 : { - 184 : int i, j; - 185 : void *t[TEST_COUNT + RAID_PARITY_MAX]; - 186 : - 187 : /* setup data and parity vector */ - 188 369 : for (i = 0, j = 0; i < nd + np; ++i) { - 189 351 : if (j < nr && ir[j] == i) { - 190 : /* this block has to be recovered */ - 191 63 : t[i] = v[i]; - 192 63 : ++j; - 193 : } else { - 194 : /* this block is used for recovering */ - 195 288 : t[i] = ref[i]; - 196 : } - 197 : } - 198 : - 199 18 : raid_rec(nr, ir, nd, np, size, t); - 200 : - 201 : /* compare all data and parity */ - 202 369 : for (i = 0; i < nd + np; ++i) { - 203 351 : if (t[i] != ref[i] - 204 63 : && memcmp(t[i], ref[i], size) != 0) { - 205 : /* LCOV_EXCL_START */ - 206 : return -1; - 207 : /* LCOV_EXCL_STOP */ - 208 : } - 209 : } - 210 : - 211 18 : return 0; - 212 : } - 213 : - 214 : /* - 215 : * Recovering test for data. - 216 : */ - 217 18 : static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref) - 218 : { - 219 : int i, j; - 220 : void *t[TEST_COUNT + RAID_PARITY_MAX]; - 221 : - 222 : /* setup data vector */ - 223 306 : for (i = 0, j = 0; i < nd; ++i) { - 224 288 : if (j < nr && id[j] == i) { - 225 : /* this block has to be recovered */ - 226 39 : t[i] = v[i]; - 227 39 : ++j; - 228 : } else { - 229 : /* this block is left unchanged */ - 230 249 : t[i] = ref[i]; - 231 : } - 232 : } - 233 : - 234 : /* setup parity vector */ - 235 81 : for (i = 0, j = 0; i < np; ++i) { - 236 63 : if (j < nr && ip[j] == i) { - 237 : /* this block is used for recovering */ - 238 39 : t[nd + i] = ref[nd + i]; - 239 39 : ++j; - 240 : } else { - 241 : /* this block should not be read or written */ - 242 24 : t[nd + i] = 0; - 243 : } - 244 : } - 245 : - 246 18 : raid_data(nr, id, ip, nd, size, t); - 247 : - 248 : /* compare all data and parity */ - 249 306 : for (i = 0; i < nd; ++i) { - 250 288 : if (t[i] != ref[i] - 251 39 : && t[i] != 0 - 252 39 : && memcmp(t[i], ref[i], size) != 0) { - 253 : /* LCOV_EXCL_START */ - 254 : return -1; - 255 : /* LCOV_EXCL_STOP */ - 256 : } - 257 : } - 258 : - 259 18 : return 0; - 260 : } - 261 : - 262 : /* - 263 : * Scan test. - 264 : */ - 265 7 : static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) - 266 : { - 267 : int i, j, ret; - 268 : void *t[TEST_COUNT + RAID_PARITY_MAX]; - 269 : int is[RAID_PARITY_MAX]; - 270 : - 271 : /* setup data and parity vector */ - 272 140 : for (i = 0, j = 0; i < nd + np; ++i) { - 273 133 : if (j < nr && ir[j] == i) { - 274 : /* this block is bad */ - 275 15 : t[i] = v[i]; - 276 15 : ++j; - 277 : } else { - 278 : /* this block is used for recovering */ - 279 118 : t[i] = ref[i]; - 280 : } - 281 : } - 282 : - 283 7 : ret = raid_scan(is, nd, np, size, t); - 284 : - 285 : /* compare identified bad blocks */ - 286 7 : if (ret != nr) - 287 1 : return -1; - 288 21 : for (i = 0; i < nr; ++i) { - 289 15 : if (ir[i] != is[i]) { - 290 : /* LCOV_EXCL_START */ - 291 : return -1; - 292 : /* LCOV_EXCL_STOP */ - 293 : } - 294 : } - 295 : - 296 6 : return 0; - 297 : } - 298 : - 299 : /* - 300 : * Basic functionality self test. - 301 : */ - 302 1 : int raid_selftest(void) - 303 : { - 304 1 : const int nd = TEST_COUNT; - 305 1 : const size_t size = TEST_SIZE; - 306 1 : const int nv = nd + RAID_PARITY_MAX * 2 + 1; - 307 : void *v_alloc; - 308 : void **v; - 309 1 : void *ref[nd + RAID_PARITY_MAX]; - 310 : int ir[RAID_PARITY_MAX]; - 311 : int ip[RAID_PARITY_MAX]; - 312 : int i, np; - 313 1 : int ret = 0; - 314 : - 315 : /* ensure to have enough space for data */ - 316 1 : BUG_ON(nd * size > 65536); - 317 : - 318 1 : v = raid_malloc_vector(nd, nv, size, &v_alloc); - 319 1 : if (!v) { - 320 : /* LCOV_EXCL_START */ - 321 : return -1; - 322 : /* LCOV_EXCL_STOP */ - 323 : } + 134 93696 : for (d = 0; d < nd; ++d) { + 135 88320 : uint8_t b = v[d][i]; + 136 : + 137 584448 : for (j = 0; j < np; ++j) + 138 496128 : p[j] ^= gfmul[b][gfgen[j][d]]; + 139 : } + 140 : + 141 36096 : for (j = 0; j < np; ++j) + 142 30720 : v[nd + j][i] = p[j]; + 143 : } + 144 6 : } + 145 : + 146 : /* + 147 : * Size of the blocks to test. + 148 : */ + 149 : #define TEST_SIZE 4096 + 150 : + 151 : /* + 152 : * Number of data blocks to test. + 153 : */ + 154 : #define TEST_COUNT (65536 / TEST_SIZE) + 155 : + 156 : /* + 157 : * Parity generation test. + 158 : */ + 159 6 : static int raid_test_par(int nd, int np, size_t size, void **v, void **ref) + 160 : { + 161 : int i; + 162 : void *t[TEST_COUNT + RAID_PARITY_MAX]; + 163 : + 164 : /* setup data */ + 165 102 : for (i = 0; i < nd; ++i) + 166 96 : t[i] = ref[i]; + 167 : + 168 : /* setup parity */ + 169 27 : for (i = 0; i < np; ++i) + 170 21 : t[nd + i] = v[nd + i]; + 171 : + 172 6 : raid_gen(nd, np, size, t); + 173 : + 174 : /* compare parity */ + 175 27 : for (i = 0; i < np; ++i) { + 176 21 : if (memcmp(t[nd + i], ref[nd + i], size) != 0) { + 177 : /* LCOV_EXCL_START */ + 178 : return -1; + 179 : /* LCOV_EXCL_STOP */ + 180 : } + 181 : } + 182 : + 183 6 : return 0; + 184 : } + 185 : + 186 : /* + 187 : * Recovering test. + 188 : */ + 189 18 : static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) + 190 : { + 191 : int i, j; + 192 : void *t[TEST_COUNT + RAID_PARITY_MAX]; + 193 : + 194 : /* setup data and parity vector */ + 195 369 : for (i = 0, j = 0; i < nd + np; ++i) { + 196 351 : if (j < nr && ir[j] == i) { + 197 : /* this block has to be recovered */ + 198 63 : t[i] = v[i]; + 199 63 : ++j; + 200 : } else { + 201 : /* this block is used for recovering */ + 202 288 : t[i] = ref[i]; + 203 : } + 204 : } + 205 : + 206 18 : raid_rec(nr, ir, nd, np, size, t); + 207 : + 208 : /* compare all data and parity */ + 209 369 : for (i = 0; i < nd + np; ++i) { + 210 351 : if (t[i] != ref[i] + 211 63 : && memcmp(t[i], ref[i], size) != 0) { + 212 : /* LCOV_EXCL_START */ + 213 : return -1; + 214 : /* LCOV_EXCL_STOP */ + 215 : } + 216 : } + 217 : + 218 18 : return 0; + 219 : } + 220 : + 221 : /* + 222 : * Recovering test for data. + 223 : */ + 224 18 : static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref) + 225 : { + 226 : int i, j; + 227 : void *t[TEST_COUNT + RAID_PARITY_MAX]; + 228 : + 229 : /* setup data vector */ + 230 306 : for (i = 0, j = 0; i < nd; ++i) { + 231 288 : if (j < nr && id[j] == i) { + 232 : /* this block has to be recovered */ + 233 39 : t[i] = v[i]; + 234 39 : ++j; + 235 : } else { + 236 : /* this block is left unchanged */ + 237 249 : t[i] = ref[i]; + 238 : } + 239 : } + 240 : + 241 : /* setup parity vector */ + 242 81 : for (i = 0, j = 0; i < np; ++i) { + 243 63 : if (j < nr && ip[j] == i) { + 244 : /* this block is used for recovering */ + 245 39 : t[nd + i] = ref[nd + i]; + 246 39 : ++j; + 247 : } else { + 248 : /* this block should not be read or written */ + 249 24 : t[nd + i] = 0; + 250 : } + 251 : } + 252 : + 253 18 : raid_data(nr, id, ip, nd, size, t); + 254 : + 255 : /* compare all data and parity */ + 256 306 : for (i = 0; i < nd; ++i) { + 257 288 : if (t[i] != ref[i] + 258 39 : && t[i] != 0 + 259 39 : && memcmp(t[i], ref[i], size) != 0) { + 260 : /* LCOV_EXCL_START */ + 261 : return -1; + 262 : /* LCOV_EXCL_STOP */ + 263 : } + 264 : } + 265 : + 266 18 : return 0; + 267 : } + 268 : + 269 : /* + 270 : * Scan test. + 271 : */ + 272 7 : static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) + 273 : { + 274 : int i, j, ret; + 275 : void *t[TEST_COUNT + RAID_PARITY_MAX]; + 276 : int is[RAID_PARITY_MAX]; + 277 : + 278 : /* setup data and parity vector */ + 279 140 : for (i = 0, j = 0; i < nd + np; ++i) { + 280 133 : if (j < nr && ir[j] == i) { + 281 : /* this block is bad */ + 282 15 : t[i] = v[i]; + 283 15 : ++j; + 284 : } else { + 285 : /* this block is used for recovering */ + 286 118 : t[i] = ref[i]; + 287 : } + 288 : } + 289 : + 290 7 : ret = raid_scan(is, nd, np, size, t); + 291 : + 292 : /* compare identified bad blocks */ + 293 7 : if (ret != nr) + 294 1 : return -1; + 295 21 : for (i = 0; i < nr; ++i) { + 296 15 : if (ir[i] != is[i]) { + 297 : /* LCOV_EXCL_START */ + 298 : return -1; + 299 : /* LCOV_EXCL_STOP */ + 300 : } + 301 : } + 302 : + 303 6 : return 0; + 304 : } + 305 : + 306 : /* + 307 : * Basic functionality self test. + 308 : */ + 309 1 : int raid_selftest(void) + 310 : { + 311 1 : const int nd = TEST_COUNT; + 312 1 : const size_t size = TEST_SIZE; + 313 1 : const int nv = nd + RAID_PARITY_MAX * 2 + 1; + 314 : void *v_alloc; + 315 : void **v; + 316 1 : void *ref[nd + RAID_PARITY_MAX]; + 317 : int ir[RAID_PARITY_MAX]; + 318 : int ip[RAID_PARITY_MAX]; + 319 : int i, np; + 320 1 : int ret = 0; + 321 : + 322 : /* ensure to have enough space for data */ + 323 1 : BUG_ON(nd * size > 65536); 324 : - 325 1 : memset(v[nv - 1], 0, size); - 326 1 : raid_zero(v[nv - 1]); - 327 : - 328 : /* use the multiplication table as data */ - 329 17 : for (i = 0; i < nd; ++i) - 330 16 : ref[i] = ((uint8_t *)gfmul) + size * i; + 325 1 : v = raid_malloc_vector(nd, nv, size, &v_alloc); + 326 1 : if (!v) { + 327 : /* LCOV_EXCL_START */ + 328 : return -1; + 329 : /* LCOV_EXCL_STOP */ + 330 : } 331 : - 332 : /* setup reference parity */ - 333 7 : for (i = 0; i < RAID_PARITY_MAX; ++i) - 334 6 : ref[nd + i] = v[nd + RAID_PARITY_MAX + i]; - 335 : - 336 : /* compute reference parity */ - 337 1 : raid_gen_ref(nd, RAID_PARITY_MAX, size, ref); + 332 1 : memset(v[nv - 1], 0, size); + 333 1 : raid_zero(v[nv - 1]); + 334 : + 335 : /* use the multiplication table as data */ + 336 17 : for (i = 0; i < nd; ++i) + 337 16 : ref[i] = ((uint8_t *)gfmul) + size * i; 338 : - 339 : /* test for each parity level */ - 340 7 : for (np = 1; np <= RAID_PARITY_MAX; ++np) { - 341 : /* test parity generation */ - 342 6 : ret = raid_test_par(nd, np, size, v, ref); - 343 6 : if (ret != 0) { - 344 : /* LCOV_EXCL_START */ - 345 : goto bail; - 346 : /* LCOV_EXCL_STOP */ - 347 : } - 348 : - 349 : /* test recovering with broken ending data disks */ - 350 27 : for (i = 0; i < np; ++i) { - 351 : /* bad data */ - 352 21 : ir[i] = nd - np + i; - 353 : - 354 : /* good parity */ - 355 21 : ip[i] = i; - 356 : } - 357 : - 358 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); - 359 6 : if (ret != 0) { - 360 : /* LCOV_EXCL_START */ - 361 : goto bail; - 362 : /* LCOV_EXCL_STOP */ + 339 : /* setup reference parity */ + 340 7 : for (i = 0; i < RAID_PARITY_MAX; ++i) + 341 6 : ref[nd + i] = v[nd + RAID_PARITY_MAX + i]; + 342 : + 343 : /* compute reference parity */ + 344 1 : raid_gen_ref(nd, RAID_PARITY_MAX, size, ref); + 345 : + 346 : /* test for each parity level */ + 347 7 : for (np = 1; np <= RAID_PARITY_MAX; ++np) { + 348 : /* test parity generation */ + 349 6 : ret = raid_test_par(nd, np, size, v, ref); + 350 6 : if (ret != 0) { + 351 : /* LCOV_EXCL_START */ + 352 : goto bail; + 353 : /* LCOV_EXCL_STOP */ + 354 : } + 355 : + 356 : /* test recovering with broken ending data disks */ + 357 27 : for (i = 0; i < np; ++i) { + 358 : /* bad data */ + 359 21 : ir[i] = nd - np + i; + 360 : + 361 : /* good parity */ + 362 21 : ip[i] = i; 363 : } 364 : - 365 6 : ret = raid_test_data(np, ir, ip, nd, np, size, v, ref); + 365 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); 366 6 : if (ret != 0) { 367 : /* LCOV_EXCL_START */ 368 : goto bail; 369 : /* LCOV_EXCL_STOP */ 370 : } 371 : - 372 : /* test recovering with broken leading data and broken leading parity */ - 373 15 : for (i = 0; i < np / 2; ++i) { - 374 : /* bad data */ - 375 9 : ir[i] = i; - 376 : - 377 : /* good parity */ - 378 9 : ip[i] = (np + 1) / 2 + i; - 379 : } - 380 : - 381 : /* bad parity */ - 382 18 : for (i = 0; i < (np + 1) / 2; ++i) - 383 12 : ir[np / 2 + i] = nd + i; - 384 : - 385 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); - 386 6 : if (ret != 0) { - 387 : /* LCOV_EXCL_START */ - 388 : goto bail; - 389 : /* LCOV_EXCL_STOP */ - 390 : } + 372 6 : ret = raid_test_data(np, ir, ip, nd, np, size, v, ref); + 373 6 : if (ret != 0) { + 374 : /* LCOV_EXCL_START */ + 375 : goto bail; + 376 : /* LCOV_EXCL_STOP */ + 377 : } + 378 : + 379 : /* test recovering with broken leading data and broken leading parity */ + 380 15 : for (i = 0; i < np / 2; ++i) { + 381 : /* bad data */ + 382 9 : ir[i] = i; + 383 : + 384 : /* good parity */ + 385 9 : ip[i] = (np + 1) / 2 + i; + 386 : } + 387 : + 388 : /* bad parity */ + 389 18 : for (i = 0; i < (np + 1) / 2; ++i) + 390 12 : ir[np / 2 + i] = nd + i; 391 : - 392 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + 392 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); 393 6 : if (ret != 0) { 394 : /* LCOV_EXCL_START */ 395 : goto bail; 396 : /* LCOV_EXCL_STOP */ 397 : } 398 : - 399 : /* test recovering with broken leading data and broken ending parity */ - 400 15 : for (i = 0; i < np / 2; ++i) { - 401 : /* bad data */ - 402 9 : ir[i] = i; - 403 : - 404 : /* good parity */ - 405 9 : ip[i] = i; - 406 : } - 407 : - 408 : /* bad parity */ - 409 18 : for (i = 0; i < (np + 1) / 2; ++i) - 410 12 : ir[np / 2 + i] = nd + np - (np + 1) / 2 + i; - 411 : - 412 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); - 413 6 : if (ret != 0) { - 414 : /* LCOV_EXCL_START */ - 415 : goto bail; - 416 : /* LCOV_EXCL_STOP */ - 417 : } + 399 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + 400 6 : if (ret != 0) { + 401 : /* LCOV_EXCL_START */ + 402 : goto bail; + 403 : /* LCOV_EXCL_STOP */ + 404 : } + 405 : + 406 : /* test recovering with broken leading data and broken ending parity */ + 407 15 : for (i = 0; i < np / 2; ++i) { + 408 : /* bad data */ + 409 9 : ir[i] = i; + 410 : + 411 : /* good parity */ + 412 9 : ip[i] = i; + 413 : } + 414 : + 415 : /* bad parity */ + 416 18 : for (i = 0; i < (np + 1) / 2; ++i) + 417 12 : ir[np / 2 + i] = nd + np - (np + 1) / 2 + i; 418 : - 419 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + 419 6 : ret = raid_test_rec(np, ir, nd, np, size, v, ref); 420 6 : if (ret != 0) { 421 : /* LCOV_EXCL_START */ 422 : goto bail; 423 : /* LCOV_EXCL_STOP */ 424 : } 425 : - 426 : /* scan test with broken data and parity */ - 427 15 : for (i = 0; i < np / 2; ++i) { - 428 : /* bad data */ - 429 9 : ir[i] = i; - 430 : } - 431 12 : for (i = 0; i < (np - 1) / 2; ++i) { - 432 : /* bad parity */ - 433 6 : ir[np / 2 + i] = nd + i; - 434 : } - 435 21 : for (i = 0; i < np - 1; ++i) { - 436 : /* make blocks bad */ - 437 : /* we cannot fill them with 0, because the original */ - 438 : /* data may be already filled with 0 */ - 439 15 : memset(v[ir[i]], 0x55, size); - 440 : } - 441 : - 442 6 : ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref); - 443 6 : if (ret != 0) { - 444 : /* LCOV_EXCL_START */ - 445 : goto bail; - 446 : /* LCOV_EXCL_STOP */ + 426 6 : ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + 427 6 : if (ret != 0) { + 428 : /* LCOV_EXCL_START */ + 429 : goto bail; + 430 : /* LCOV_EXCL_STOP */ + 431 : } + 432 : + 433 : /* scan test with broken data and parity */ + 434 15 : for (i = 0; i < np / 2; ++i) { + 435 : /* bad data */ + 436 9 : ir[i] = i; + 437 : } + 438 12 : for (i = 0; i < (np - 1) / 2; ++i) { + 439 : /* bad parity */ + 440 6 : ir[np / 2 + i] = nd + i; + 441 : } + 442 21 : for (i = 0; i < np - 1; ++i) { + 443 : /* make blocks bad */ + 444 : /* we cannot fill them with 0, because the original */ + 445 : /* data may be already filled with 0 */ + 446 15 : memset(v[ir[i]], 0x55, size); 447 : } - 448 : } - 449 : - 450 : /* scan test with no parity */ - 451 1 : ret = raid_test_scan(0, 0, nd, 0, size, v, ref); - 452 1 : if (ret != -1) { - 453 : /* LCOV_EXCL_START */ - 454 : goto bail; - 455 : /* LCOV_EXCL_STOP */ - 456 : } - 457 : - 458 1 : ret = 0; - 459 : - 460 : bail: - 461 1 : free(v); - 462 1 : free(v_alloc); - 463 : - 464 1 : return ret; - 465 : } + 448 : + 449 6 : ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref); + 450 6 : if (ret != 0) { + 451 : /* LCOV_EXCL_START */ + 452 : goto bail; + 453 : /* LCOV_EXCL_STOP */ + 454 : } + 455 : } + 456 : + 457 : /* scan test with no parity */ + 458 1 : ret = raid_test_scan(0, 0, nd, 0, size, v, ref); + 459 1 : if (ret != -1) { + 460 : /* LCOV_EXCL_START */ + 461 : goto bail; + 462 : /* LCOV_EXCL_STOP */ + 463 : } + 464 : + 465 1 : ret = 0; 466 : + 467 : bail: + 468 1 : free(v); + 469 1 : free(v_alloc); + 470 : + 471 1 : return ret; + 472 : } + 473 : diff --git a/cov/raid/raid.c.func-sort-c.html b/cov/raid/raid.c.func-sort-c.html index 77b192da..aa6d9f7a 100644 --- a/cov/raid/raid.c.func-sort-c.html +++ b/cov/raid/raid.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -61,35 +61,35 @@ raid_gen - 1212946 + 1208170 raid_data - 217853 + 211361 raid_invert - 172667 + 172152 raid_delta_gen - 171311 + 170824 raid_rec1of1 - 104953 + 98917 raid_rec - 900 + 869 raid_mode - 503 + 519 raid_zero - 193 + 201 raid_rec2of2_int8 diff --git a/cov/raid/raid.c.func.html b/cov/raid/raid.c.func.html index 88ff8f70..6978ce2b 100644 --- a/cov/raid/raid.c.func.html +++ b/cov/raid/raid.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -61,31 +61,31 @@ raid_data - 217853 + 211361 raid_delta_gen - 171311 + 170824 raid_gen - 1212946 + 1208170 raid_invert - 172667 + 172152 raid_mode - 503 + 519 raid_rec - 900 + 869 raid_rec1of1 - 104953 + 98917 raid_rec2of2_int8 @@ -93,7 +93,7 @@ raid_zero - 193 + 201
diff --git a/cov/raid/raid.c.gcov.html b/cov/raid/raid.c.gcov.html index 54d53596..ce8ab3b6 100644 --- a/cov/raid/raid.c.gcov.html +++ b/cov/raid/raid.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 9 @@ -235,26 +235,26 @@ 173 : */ 174 : const uint8_t (*raid_gfgen)[256]; 175 : - 176 503 : void raid_mode(int mode) + 176 519 : void raid_mode(int mode) 177 : { - 178 503 : if (mode == RAID_MODE_VANDERMONDE) { + 178 519 : if (mode == RAID_MODE_VANDERMONDE) { 179 2 : raid_gen_ptr[2] = raid_genz_ptr; 180 2 : raid_gfgen = gfvandermonde; 181 : } else { - 182 501 : raid_gen_ptr[2] = raid_gen3_ptr; - 183 501 : raid_gfgen = gfcauchy; + 182 517 : raid_gen_ptr[2] = raid_gen3_ptr; + 183 517 : raid_gfgen = gfcauchy; 184 : } - 185 503 : } + 185 519 : } 186 : 187 : /** 188 : * Buffer filled with 0 used in recovering. 189 : */ 190 : static void *raid_zero_block; 191 : - 192 193 : void raid_zero(void *zero) + 192 201 : void raid_zero(void *zero) 193 : { - 194 193 : raid_zero_block = zero; - 195 193 : } + 194 201 : raid_zero_block = zero; + 195 201 : } 196 : 197 : /* 198 : * Forwarders for parity computation. @@ -282,17 +282,17 @@ 220 : void (*raid_gen3_ptr)(int nd, size_t size, void **vv); 221 : void (*raid_genz_ptr)(int nd, size_t size, void **vv); 222 : - 223 1212946 : void raid_gen(int nd, int np, size_t size, void **v) + 223 1208170 : void raid_gen(int nd, int np, size_t size, void **v) 224 : { 225 : /* enforce limit on size */ - 226 1212946 : BUG_ON(size % 64 != 0); + 226 1208170 : BUG_ON(size % 64 != 0); 227 : 228 : /* enforce limit on number of failures */ - 229 1212946 : BUG_ON(np < 1); - 230 1212946 : BUG_ON(np > RAID_PARITY_MAX); + 229 1208170 : BUG_ON(np < 1); + 230 1208170 : BUG_ON(np > RAID_PARITY_MAX); 231 : - 232 1212946 : raid_gen_ptr[np - 1](nd, size, v); - 233 1212946 : } + 232 1208170 : raid_gen_ptr[np - 1](nd, size, v); + 233 1208170 : } 234 : 235 : /** 236 : * Inverts the square matrix M of size nxn into V. @@ -305,44 +305,44 @@ 243 : * @V Destination matrix where the result is put. 244 : * @n Number of rows and columns of the matrix. 245 : */ - 246 172667 : void raid_invert(uint8_t *M, uint8_t *V, int n) + 246 172152 : void raid_invert(uint8_t *M, uint8_t *V, int n) 247 : { 248 : int i, j, k; 249 : 250 : /* set the identity matrix in V */ - 251 798158 : for (i = 0; i < n; ++i) - 252 3221590 : for (j = 0; j < n; ++j) - 253 2596099 : V[i * n + j] = i == j; + 251 796315 : for (i = 0; i < n; ++i) + 252 3214980 : for (j = 0; j < n; ++j) + 253 2590817 : V[i * n + j] = i == j; 254 : 255 : /* for each element in the diagonal */ - 256 798158 : for (k = 0; k < n; ++k) { + 256 796315 : for (k = 0; k < n; ++k) { 257 : uint8_t f; 258 : 259 : /* the diagonal element cannot be 0 because */ 260 : /* we are inverting matrices with all the square */ 261 : /* submatrices not singular */ - 262 625491 : BUG_ON(M[k * n + k] == 0); + 262 624163 : BUG_ON(M[k * n + k] == 0); 263 : 264 : /* make the diagonal element to be 1 */ - 265 1250982 : f = inv(M[k * n + k]); - 266 3221590 : for (j = 0; j < n; ++j) { - 267 5192198 : M[k * n + j] = mul(f, M[k * n + j]); - 268 5192198 : V[k * n + j] = mul(f, V[k * n + j]); + 265 1248326 : f = inv(M[k * n + k]); + 266 3214980 : for (j = 0; j < n; ++j) { + 267 5181634 : M[k * n + j] = mul(f, M[k * n + j]); + 268 5181634 : V[k * n + j] = mul(f, V[k * n + j]); 269 : } 270 : 271 : /* make all the elements over and under the diagonal */ 272 : /* to be zero */ - 273 3221590 : for (i = 0; i < n; ++i) { - 274 2596099 : if (i == k) - 275 625491 : continue; - 276 1970608 : f = M[i * n + k]; - 277 11281182 : for (j = 0; j < n; ++j) { - 278 18621148 : M[i * n + j] ^= mul(f, M[k * n + j]); - 279 18621148 : V[i * n + j] ^= mul(f, V[k * n + j]); + 273 3214980 : for (i = 0; i < n; ++i) { + 274 2590817 : if (i == k) + 275 624163 : continue; + 276 1966654 : f = M[i * n + k]; + 277 11254146 : for (j = 0; j < n; ++j) { + 278 18574984 : M[i * n + j] ^= mul(f, M[k * n + j]); + 279 18574984 : V[i * n + j] ^= mul(f, V[k * n + j]); 280 : } 281 : } 282 : } - 283 172667 : } + 283 172152 : } 284 : 285 : /** 286 : * Computes the parity without the missing data blocks @@ -350,7 +350,7 @@ 288 : * 289 : * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua in the equations. 290 : */ - 291 171311 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) + 291 170824 : void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) 292 : { 293 : void *p[RAID_PARITY_MAX]; 294 : void *pa[RAID_PARITY_MAX]; @@ -360,17 +360,17 @@ 298 : 299 : /* total number of parities we are going to process */ 300 : /* they are both the used and the unused ones */ - 301 171311 : np = ip[nr - 1] + 1; + 301 170824 : np = ip[nr - 1] + 1; 302 : 303 : /* latest missing data block */ - 304 171311 : latest = v[id[nr - 1]]; + 304 170824 : latest = v[id[nr - 1]]; 305 : 306 : /* setup pointers for delta computation */ - 307 872577 : for (i = 0, j = 0; i < np; ++i) { + 307 870818 : for (i = 0, j = 0; i < np; ++i) { 308 : /* keep a copy of the original parity vector */ - 309 701266 : p[i] = v[nd + i]; + 309 699994 : p[i] = v[nd + i]; 310 : - 311 701266 : if (ip[j] == i) { + 311 699994 : if (ip[j] == i) { 312 : /* 313 : * Set used parities to point to the missing 314 : * data blocks. @@ -381,19 +381,19 @@ 319 : 320 : /* the latest parity to use ends the for loop and */ 321 : /* then it cannot happen to process more of them */ - 322 605461 : BUG_ON(j >= nr); + 322 604161 : BUG_ON(j >= nr); 323 : 324 : /* buffer for missing data blocks */ - 325 605461 : pa[j] = v[id[j]]; + 325 604161 : pa[j] = v[id[j]]; 326 : 327 : /* set at zero the missing data blocks */ - 328 605461 : v[id[j]] = raid_zero_block; + 328 604161 : v[id[j]] = raid_zero_block; 329 : 330 : /* compute the parity over the missing data blocks */ - 331 605461 : v[nd + i] = pa[j]; + 331 604161 : v[nd + i] = pa[j]; 332 : 333 : /* check for the next used entry */ - 334 605461 : ++j; + 334 604161 : ++j; 335 : } else { 336 : /* 337 : * Unused parities are going to be rewritten with @@ -413,25 +413,25 @@ 351 : * multiple times and only the latest write will 352 : * contain the correct data. 353 : */ - 354 95805 : v[nd + i] = latest; + 354 95833 : v[nd + i] = latest; 355 : } 356 : } 357 : 358 : /* all the parities have to be processed */ - 359 171311 : BUG_ON(j != nr); + 359 170824 : BUG_ON(j != nr); 360 : 361 : /* recompute the parity, note that np may be smaller than the */ 362 : /* total number of parities available */ - 363 171311 : raid_gen(nd, np, size, v); + 363 170824 : raid_gen(nd, np, size, v); 364 : 365 : /* restore data buffers as before */ - 366 776772 : for (j = 0; j < nr; ++j) - 367 605461 : v[id[j]] = pa[j]; + 366 774985 : for (j = 0; j < nr; ++j) + 367 604161 : v[id[j]] = pa[j]; 368 : 369 : /* restore parity buffers as before */ - 370 872577 : for (i = 0; i < np; ++i) - 371 701266 : v[nd + i] = p[i]; - 372 171311 : } + 370 870818 : for (i = 0; i < np; ++i) + 371 699994 : v[nd + i] = p[i]; + 372 170824 : } 373 : 374 : /** 375 : * Recover failure of one data block for PAR1. @@ -444,29 +444,29 @@ 382 : * 383 : * Dx = Pd 384 : */ - 385 104953 : void raid_rec1of1(int *id, int nd, size_t size, void **v) + 385 98917 : void raid_rec1of1(int *id, int nd, size_t size, void **v) 386 : { 387 : void *p; 388 : void *pa; 389 : 390 : /* for PAR1 we can directly compute the missing block */ 391 : /* and we don't need to use the zero buffer */ - 392 104953 : p = v[nd]; - 393 104953 : pa = v[id[0]]; + 392 98917 : p = v[nd]; + 393 98917 : pa = v[id[0]]; 394 : 395 : /* use the parity as missing data block */ - 396 104953 : v[id[0]] = p; + 396 98917 : v[id[0]] = p; 397 : 398 : /* compute the parity over the missing data block */ - 399 104953 : v[nd] = pa; + 399 98917 : v[nd] = pa; 400 : 401 : /* compute */ - 402 104953 : raid_gen(nd, 1, size, v); + 402 98917 : raid_gen(nd, 1, size, v); 403 : 404 : /* restore as before */ - 405 104953 : v[id[0]] = pa; - 406 104953 : v[nd] = p; - 407 104953 : } + 405 98917 : v[id[0]] = pa; + 406 98917 : v[nd] = p; + 407 98917 : } 408 : 409 : /** 410 : * Recover failure of two data blocks for PAR2. @@ -554,97 +554,97 @@ 492 : void (*raid_rec_ptr[RAID_PARITY_MAX])( 493 : int nr, int *id, int *ip, int nd, size_t size, void **vv); 494 : - 495 900 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v) + 495 869 : void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v) 496 : { 497 : int nrd; /* number of data blocks to recover */ 498 : int nrp; /* number of parity blocks to recover */ 499 : 500 : /* enforce limit on size */ - 501 900 : BUG_ON(size % 64 != 0); + 501 869 : BUG_ON(size % 64 != 0); 502 : 503 : /* enforce limit on number of failures */ - 504 900 : BUG_ON(nr > np); - 505 900 : BUG_ON(np > RAID_PARITY_MAX); + 504 869 : BUG_ON(nr > np); + 505 869 : BUG_ON(np > RAID_PARITY_MAX); 506 : 507 : /* enforce order in index vector */ - 508 900 : BUG_ON(nr >= 2 && ir[0] >= ir[1]); - 509 900 : BUG_ON(nr >= 3 && ir[1] >= ir[2]); - 510 900 : BUG_ON(nr >= 4 && ir[2] >= ir[3]); - 511 900 : BUG_ON(nr >= 5 && ir[3] >= ir[4]); - 512 900 : BUG_ON(nr >= 6 && ir[4] >= ir[5]); + 508 869 : BUG_ON(nr >= 2 && ir[0] >= ir[1]); + 509 869 : BUG_ON(nr >= 3 && ir[1] >= ir[2]); + 510 869 : BUG_ON(nr >= 4 && ir[2] >= ir[3]); + 511 869 : BUG_ON(nr >= 5 && ir[3] >= ir[4]); + 512 869 : BUG_ON(nr >= 6 && ir[4] >= ir[5]); 513 : 514 : /* enforce limit on index vector */ - 515 900 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np); + 515 869 : BUG_ON(nr > 0 && ir[nr-1] >= nd + np); 516 : 517 : /* count the number of data blocks to recover */ - 518 900 : nrd = 0; - 519 3603 : while (nrd < nr && ir[nrd] < nd) - 520 1803 : ++nrd; + 518 869 : nrd = 0; + 519 3479 : while (nrd < nr && ir[nrd] < nd) + 520 1741 : ++nrd; 521 : 522 : /* all the remaining are parity */ - 523 900 : nrp = nr - nrd; + 523 869 : nrp = nr - nrd; 524 : 525 : /* enforce limit on number of failures */ - 526 900 : BUG_ON(nrd > nd); - 527 900 : BUG_ON(nrp > np); + 526 869 : BUG_ON(nrd > nd); + 527 869 : BUG_ON(nrp > np); 528 : 529 : /* if failed data is present */ - 530 900 : if (nrd != 0) { + 530 869 : if (nrd != 0) { 531 : int ip[RAID_PARITY_MAX]; 532 : int i, j, k; 533 : 534 : /* setup the vector of parities to use */ - 535 6251 : for (i = 0, j = 0, k = 0; i < np; ++i) { - 536 5353 : if (j < nrp && ir[nrd + j] == nd + i) { + 535 6034 : for (i = 0, j = 0, k = 0; i < np; ++i) { + 536 5167 : if (j < nrp && ir[nrd + j] == nd + i) { 537 : /* this parity has to be recovered */ 538 22 : ++j; 539 : } else { 540 : /* this parity is used for recovering */ - 541 5331 : ip[k] = i; - 542 5331 : ++k; + 541 5145 : ip[k] = i; + 542 5145 : ++k; 543 : } 544 : } 545 : 546 : /* recover the nrd data blocks specified in ir[], */ 547 : /* using the first nrd parity in ip[] for recovering */ - 548 898 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v); + 548 867 : raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v); 549 : } 550 : 551 : /* recompute all the parities up to the last bad one */ - 552 900 : if (nrp != 0) + 552 869 : if (nrp != 0) 553 12 : raid_gen(nd, ir[nr - 1] - nd + 1, size, v); - 554 900 : } + 554 869 : } 555 : - 556 217853 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) + 556 211361 : void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) 557 : { 558 : /* enforce limit on size */ - 559 217853 : BUG_ON(size % 64 != 0); + 559 211361 : BUG_ON(size % 64 != 0); 560 : 561 : /* enforce limit on number of failures */ - 562 217853 : BUG_ON(nr > nd); - 563 217853 : BUG_ON(nr > RAID_PARITY_MAX); + 562 211361 : BUG_ON(nr > nd); + 563 211361 : BUG_ON(nr > RAID_PARITY_MAX); 564 : 565 : /* enforce order in index vector for data */ - 566 217853 : BUG_ON(nr >= 2 && id[0] >= id[1]); - 567 217853 : BUG_ON(nr >= 3 && id[1] >= id[2]); - 568 217853 : BUG_ON(nr >= 4 && id[2] >= id[3]); - 569 217853 : BUG_ON(nr >= 5 && id[3] >= id[4]); - 570 217853 : BUG_ON(nr >= 6 && id[4] >= id[5]); + 566 211361 : BUG_ON(nr >= 2 && id[0] >= id[1]); + 567 211361 : BUG_ON(nr >= 3 && id[1] >= id[2]); + 568 211361 : BUG_ON(nr >= 4 && id[2] >= id[3]); + 569 211361 : BUG_ON(nr >= 5 && id[3] >= id[4]); + 570 211361 : BUG_ON(nr >= 6 && id[4] >= id[5]); 571 : 572 : /* enforce limit on index vector for data */ - 573 217853 : BUG_ON(nr > 0 && id[nr-1] >= nd); + 573 211361 : BUG_ON(nr > 0 && id[nr-1] >= nd); 574 : 575 : /* enforce order in index vector for parity */ - 576 217853 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); - 577 217853 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); - 578 217853 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); - 579 217853 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); - 580 217853 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); + 576 211361 : BUG_ON(nr >= 2 && ip[0] >= ip[1]); + 577 211361 : BUG_ON(nr >= 3 && ip[1] >= ip[2]); + 578 211361 : BUG_ON(nr >= 4 && ip[2] >= ip[3]); + 579 211361 : BUG_ON(nr >= 5 && ip[3] >= ip[4]); + 580 211361 : BUG_ON(nr >= 6 && ip[4] >= ip[5]); 581 : 582 : /* if failed data is present */ - 583 217853 : if (nr != 0) - 584 217851 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); - 585 217853 : } + 583 211361 : if (nr != 0) + 584 211359 : raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); + 585 211361 : } 586 : diff --git a/cov/raid/tag.c.func-sort-c.html b/cov/raid/tag.c.func-sort-c.html index 31c0d253..3fd08c9b 100644 --- a/cov/raid/tag.c.func-sort-c.html +++ b/cov/raid/tag.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 diff --git a/cov/raid/tag.c.func.html b/cov/raid/tag.c.func.html index 14aa49dc..3d1d2299 100644 --- a/cov/raid/tag.c.func.html +++ b/cov/raid/tag.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 diff --git a/cov/raid/tag.c.gcov.html b/cov/raid/tag.c.gcov.html index 942fdb77..57254a98 100644 --- a/cov/raid/tag.c.gcov.html +++ b/cov/raid/tag.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 diff --git a/cov/raid/test.c.func-sort-c.html b/cov/raid/test.c.func-sort-c.html index 98effa0b..3e30deb8 100644 --- a/cov/raid/test.c.func-sort-c.html +++ b/cov/raid/test.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 diff --git a/cov/raid/test.c.func.html b/cov/raid/test.c.func.html index 7a09c565..3fcc40a8 100644 --- a/cov/raid/test.c.func.html +++ b/cov/raid/test.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 diff --git a/cov/raid/test.c.gcov.html b/cov/raid/test.c.gcov.html index 6104fd17..46a5ea0a 100644 --- a/cov/raid/test.c.gcov.html +++ b/cov/raid/test.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 7 diff --git a/cov/raid/x86.c.func-sort-c.html b/cov/raid/x86.c.func-sort-c.html index 5c4222d3..576bb3bc 100644 --- a/cov/raid/x86.c.func-sort-c.html +++ b/cov/raid/x86.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 14 @@ -61,39 +61,39 @@ raid_gen6_ssse3 - 549666 + 559030 raid_gen2_sse2 - 276492 + 267701 raid_gen1_sse2 - 273337 + 267673 raid_rec1_ssse3 - 114430 + 108422 raid_recX_ssse3 - 79298 + 79451 raid_gen5_ssse3 - 50258 + 50169 raid_rec2_ssse3 - 44206 + 43538 raid_gen4_ssse3 - 32613 + 32723 raid_gen3_ssse3 - 29451 + 29756 raid_recX_avx2 diff --git a/cov/raid/x86.c.func.html b/cov/raid/x86.c.func.html index adc9e8a9..ee9d7e4c 100644 --- a/cov/raid/x86.c.func.html +++ b/cov/raid/x86.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 14 @@ -65,7 +65,7 @@ raid_gen1_sse2 - 273337 + 267673 raid_gen2_avx2 @@ -73,23 +73,23 @@ raid_gen2_sse2 - 276492 + 267701 raid_gen3_ssse3 - 29451 + 29756 raid_gen4_ssse3 - 32613 + 32723 raid_gen5_ssse3 - 50258 + 50169 raid_gen6_ssse3 - 549666 + 559030 raid_rec1_avx2 @@ -97,7 +97,7 @@ raid_rec1_ssse3 - 114430 + 108422 raid_rec2_avx2 @@ -105,7 +105,7 @@ raid_rec2_ssse3 - 44206 + 43538 raid_recX_avx2 @@ -113,7 +113,7 @@ raid_recX_ssse3 - 79298 + 79451
diff --git a/cov/raid/x86.c.gcov.html b/cov/raid/x86.c.gcov.html index 8835cf3b..da2e429e 100644 --- a/cov/raid/x86.c.gcov.html +++ b/cov/raid/x86.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 273337 : void raid_gen1_sse2(int nd, size_t size, void **vv) + 36 267673 : void raid_gen1_sse2(int nd, size_t size, void **vv) 37 : { - 38 273337 : uint8_t **v = (uint8_t **)vv; + 38 267673 : uint8_t **v = (uint8_t **)vv; 39 : uint8_t *p; 40 : int d, l; 41 : size_t i; 42 : - 43 273337 : l = nd - 1; - 44 273337 : p = v[nd]; + 43 267673 : l = nd - 1; + 44 267673 : p = v[nd]; 45 : 46 : raid_sse_begin(); 47 : - 48 5895173 : for (i = 0; i < size; i += 64) { - 49 5621836 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 50 5621836 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 51 5621836 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); - 52 5621836 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); - 53 36237956 : for (d = l - 1; d >= 0; --d) { - 54 30616120 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); - 55 30616120 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); - 56 30616120 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); - 57 30616120 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); + 48 5827445 : for (i = 0; i < size; i += 64) { + 49 5559772 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 50 5559772 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 51 5559772 : asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + 52 5559772 : asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + 53 35922916 : for (d = l - 1; d >= 0; --d) { + 54 30363144 : asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); + 55 30363144 : asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); + 56 30363144 : asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); + 57 30363144 : asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); 58 : } - 59 5621836 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 60 5621836 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 61 5621836 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); - 62 5621836 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + 59 5559772 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 60 5559772 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 61 5559772 : asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + 62 5559772 : asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); 63 : } 64 : 65 : raid_sse_end(); - 66 273337 : } + 66 267673 : } 67 : #endif 68 : 69 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2) @@ -183,54 +183,54 @@ 121 : /* 122 : * GEN2 (RAID6 with powers of 2) SSE2 implementation 123 : */ - 124 276492 : void raid_gen2_sse2(int nd, size_t size, void **vv) + 124 267701 : void raid_gen2_sse2(int nd, size_t size, void **vv) 125 : { - 126 276492 : uint8_t **v = (uint8_t **)vv; + 126 267701 : uint8_t **v = (uint8_t **)vv; 127 : uint8_t *p; 128 : uint8_t *q; 129 : int d, l; 130 : size_t i; 131 : - 132 276492 : l = nd - 1; - 133 276492 : p = v[nd]; - 134 276492 : q = v[nd + 1]; + 132 267701 : l = nd - 1; + 133 267701 : p = v[nd]; + 134 267701 : q = v[nd + 1]; 135 : 136 : raid_sse_begin(); 137 : - 138 276492 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 138 267701 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 139 : - 140 11074404 : for (i = 0; i < size; i += 32) { - 141 10797912 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 142 10797912 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); - 143 10797912 : asm volatile ("movdqa %xmm0,%xmm2"); - 144 10797912 : asm volatile ("movdqa %xmm1,%xmm3"); - 145 68703624 : for (d = l - 1; d >= 0; --d) { - 146 57905712 : asm volatile ("pxor %xmm4,%xmm4"); - 147 57905712 : asm volatile ("pxor %xmm5,%xmm5"); - 148 57905712 : asm volatile ("pcmpgtb %xmm2,%xmm4"); - 149 57905712 : asm volatile ("pcmpgtb %xmm3,%xmm5"); - 150 57905712 : asm volatile ("paddb %xmm2,%xmm2"); - 151 57905712 : asm volatile ("paddb %xmm3,%xmm3"); - 152 57905712 : asm volatile ("pand %xmm7,%xmm4"); - 153 57905712 : asm volatile ("pand %xmm7,%xmm5"); - 154 57905712 : asm volatile ("pxor %xmm4,%xmm2"); - 155 57905712 : asm volatile ("pxor %xmm5,%xmm3"); + 140 10816941 : for (i = 0; i < size; i += 32) { + 141 10549240 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 142 10549240 : asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + 143 10549240 : asm volatile ("movdqa %xmm0,%xmm2"); + 144 10549240 : asm volatile ("movdqa %xmm1,%xmm3"); + 145 67277128 : for (d = l - 1; d >= 0; --d) { + 146 56727888 : asm volatile ("pxor %xmm4,%xmm4"); + 147 56727888 : asm volatile ("pxor %xmm5,%xmm5"); + 148 56727888 : asm volatile ("pcmpgtb %xmm2,%xmm4"); + 149 56727888 : asm volatile ("pcmpgtb %xmm3,%xmm5"); + 150 56727888 : asm volatile ("paddb %xmm2,%xmm2"); + 151 56727888 : asm volatile ("paddb %xmm3,%xmm3"); + 152 56727888 : asm volatile ("pand %xmm7,%xmm4"); + 153 56727888 : asm volatile ("pand %xmm7,%xmm5"); + 154 56727888 : asm volatile ("pxor %xmm4,%xmm2"); + 155 56727888 : asm volatile ("pxor %xmm5,%xmm3"); 156 : - 157 57905712 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 158 57905712 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16])); - 159 57905712 : asm volatile ("pxor %xmm4,%xmm0"); - 160 57905712 : asm volatile ("pxor %xmm5,%xmm1"); - 161 57905712 : asm volatile ("pxor %xmm4,%xmm2"); - 162 57905712 : asm volatile ("pxor %xmm5,%xmm3"); + 157 56727888 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 158 56727888 : asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16])); + 159 56727888 : asm volatile ("pxor %xmm4,%xmm0"); + 160 56727888 : asm volatile ("pxor %xmm5,%xmm1"); + 161 56727888 : asm volatile ("pxor %xmm4,%xmm2"); + 162 56727888 : asm volatile ("pxor %xmm5,%xmm3"); 163 : } - 164 10797912 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 165 10797912 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); - 166 10797912 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i])); - 167 10797912 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16])); + 164 10549240 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 165 10549240 : asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + 166 10549240 : asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i])); + 167 10549240 : asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16])); 168 : } 169 : 170 : raid_sse_end(); - 171 276492 : } + 171 267701 : } 172 : #endif 173 : 174 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2) @@ -370,93 +370,93 @@ 308 : /* 309 : * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation 310 : */ - 311 29451 : void raid_gen3_ssse3(int nd, size_t size, void **vv) + 311 29756 : void raid_gen3_ssse3(int nd, size_t size, void **vv) 312 : { - 313 29451 : uint8_t **v = (uint8_t **)vv; + 313 29756 : uint8_t **v = (uint8_t **)vv; 314 : uint8_t *p; 315 : uint8_t *q; 316 : uint8_t *r; 317 : int d, l; 318 : size_t i; 319 : - 320 29451 : l = nd - 1; - 321 29451 : p = v[nd]; - 322 29451 : q = v[nd + 1]; - 323 29451 : r = v[nd + 2]; + 320 29756 : l = nd - 1; + 321 29756 : p = v[nd]; + 322 29756 : q = v[nd + 1]; + 323 29756 : r = v[nd + 2]; 324 : 325 : /* special case with only one data disk */ - 326 29451 : if (l == 0) { + 326 29756 : if (l == 0) { 327 4 : for (i = 0; i < 3; ++i) 328 3 : memcpy(v[1 + i], v[0], size); - 329 29452 : return; + 329 29757 : return; 330 : } 331 : 332 : raid_sse_begin(); 333 : 334 : /* generic case with at least two data disks */ - 335 29450 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); - 336 29450 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 335 29755 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); + 336 29755 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 337 : - 338 4915546 : for (i = 0; i < size; i += 16) { + 338 4935371 : for (i = 0; i < size; i += 16) { 339 : /* last disk without the by two multiplication */ - 340 4886096 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 340 4905616 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 341 : - 342 4886096 : asm volatile ("movdqa %xmm4,%xmm0"); - 343 4886096 : asm volatile ("movdqa %xmm4,%xmm1"); + 342 4905616 : asm volatile ("movdqa %xmm4,%xmm0"); + 343 4905616 : asm volatile ("movdqa %xmm4,%xmm1"); 344 : - 345 4886096 : asm volatile ("movdqa %xmm4,%xmm5"); - 346 4886096 : asm volatile ("psrlw $4,%xmm5"); - 347 4886096 : asm volatile ("pand %xmm7,%xmm4"); - 348 4886096 : asm volatile ("pand %xmm7,%xmm5"); + 345 4905616 : asm volatile ("movdqa %xmm4,%xmm5"); + 346 4905616 : asm volatile ("psrlw $4,%xmm5"); + 347 4905616 : asm volatile ("pand %xmm7,%xmm4"); + 348 4905616 : asm volatile ("pand %xmm7,%xmm5"); 349 : - 350 4886096 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); - 351 4886096 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); - 352 4886096 : asm volatile ("pshufb %xmm4,%xmm2"); - 353 4886096 : asm volatile ("pshufb %xmm5,%xmm6"); - 354 4886096 : asm volatile ("pxor %xmm6,%xmm2"); + 350 4905616 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + 351 4905616 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); + 352 4905616 : asm volatile ("pshufb %xmm4,%xmm2"); + 353 4905616 : asm volatile ("pshufb %xmm5,%xmm6"); + 354 4905616 : asm volatile ("pxor %xmm6,%xmm2"); 355 : 356 : /* intermediate disks */ - 357 30688944 : for (d = l - 1; d > 0; --d) { - 358 25802848 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 357 30786544 : for (d = l - 1; d > 0; --d) { + 358 25880928 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 359 : - 360 25802848 : asm volatile ("pxor %xmm5,%xmm5"); - 361 25802848 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 362 25802848 : asm volatile ("paddb %xmm1,%xmm1"); - 363 25802848 : asm volatile ("pand %xmm3,%xmm5"); - 364 25802848 : asm volatile ("pxor %xmm5,%xmm1"); + 360 25880928 : asm volatile ("pxor %xmm5,%xmm5"); + 361 25880928 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 362 25880928 : asm volatile ("paddb %xmm1,%xmm1"); + 363 25880928 : asm volatile ("pand %xmm3,%xmm5"); + 364 25880928 : asm volatile ("pxor %xmm5,%xmm1"); 365 : - 366 25802848 : asm volatile ("pxor %xmm4,%xmm0"); - 367 25802848 : asm volatile ("pxor %xmm4,%xmm1"); + 366 25880928 : asm volatile ("pxor %xmm4,%xmm0"); + 367 25880928 : asm volatile ("pxor %xmm4,%xmm1"); 368 : - 369 25802848 : asm volatile ("movdqa %xmm4,%xmm5"); - 370 25802848 : asm volatile ("psrlw $4,%xmm5"); - 371 25802848 : asm volatile ("pand %xmm7,%xmm4"); - 372 25802848 : asm volatile ("pand %xmm7,%xmm5"); + 369 25880928 : asm volatile ("movdqa %xmm4,%xmm5"); + 370 25880928 : asm volatile ("psrlw $4,%xmm5"); + 371 25880928 : asm volatile ("pand %xmm7,%xmm4"); + 372 25880928 : asm volatile ("pand %xmm7,%xmm5"); 373 : - 374 25802848 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 375 25802848 : asm volatile ("pshufb %xmm4,%xmm6"); - 376 25802848 : asm volatile ("pxor %xmm6,%xmm2"); - 377 25802848 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); - 378 25802848 : asm volatile ("pshufb %xmm5,%xmm6"); - 379 25802848 : asm volatile ("pxor %xmm6,%xmm2"); + 374 25880928 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 375 25880928 : asm volatile ("pshufb %xmm4,%xmm6"); + 376 25880928 : asm volatile ("pxor %xmm6,%xmm2"); + 377 25880928 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); + 378 25880928 : asm volatile ("pshufb %xmm5,%xmm6"); + 379 25880928 : asm volatile ("pxor %xmm6,%xmm2"); 380 : } 381 : 382 : /* first disk with all coefficients at 1 */ - 383 4886096 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 383 4905616 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); 384 : - 385 4886096 : asm volatile ("pxor %xmm5,%xmm5"); - 386 4886096 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 387 4886096 : asm volatile ("paddb %xmm1,%xmm1"); - 388 4886096 : asm volatile ("pand %xmm3,%xmm5"); - 389 4886096 : asm volatile ("pxor %xmm5,%xmm1"); + 385 4905616 : asm volatile ("pxor %xmm5,%xmm5"); + 386 4905616 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 387 4905616 : asm volatile ("paddb %xmm1,%xmm1"); + 388 4905616 : asm volatile ("pand %xmm3,%xmm5"); + 389 4905616 : asm volatile ("pxor %xmm5,%xmm1"); 390 : - 391 4886096 : asm volatile ("pxor %xmm4,%xmm0"); - 392 4886096 : asm volatile ("pxor %xmm4,%xmm1"); - 393 4886096 : asm volatile ("pxor %xmm4,%xmm2"); + 391 4905616 : asm volatile ("pxor %xmm4,%xmm0"); + 392 4905616 : asm volatile ("pxor %xmm4,%xmm1"); + 393 4905616 : asm volatile ("pxor %xmm4,%xmm2"); 394 : - 395 4886096 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 396 4886096 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 397 4886096 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 395 4905616 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 396 4905616 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 397 4905616 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 398 : } 399 : 400 : raid_sse_end(); @@ -741,9 +741,9 @@ 679 : /* 680 : * GEN4 (quad parity with Cauchy matrix) SSSE3 implementation 681 : */ - 682 32613 : void raid_gen4_ssse3(int nd, size_t size, void **vv) + 682 32723 : void raid_gen4_ssse3(int nd, size_t size, void **vv) 683 : { - 684 32613 : uint8_t **v = (uint8_t **)vv; + 684 32723 : uint8_t **v = (uint8_t **)vv; 685 : uint8_t *p; 686 : uint8_t *q; 687 : uint8_t *r; @@ -751,102 +751,102 @@ 689 : int d, l; 690 : size_t i; 691 : - 692 32613 : l = nd - 1; - 693 32613 : p = v[nd]; - 694 32613 : q = v[nd + 1]; - 695 32613 : r = v[nd + 2]; - 696 32613 : s = v[nd + 3]; + 692 32723 : l = nd - 1; + 693 32723 : p = v[nd]; + 694 32723 : q = v[nd + 1]; + 695 32723 : r = v[nd + 2]; + 696 32723 : s = v[nd + 3]; 697 : 698 : /* special case with only one data disk */ - 699 32613 : if (l == 0) { + 699 32723 : if (l == 0) { 700 5 : for (i = 0; i < 4; ++i) 701 4 : memcpy(v[1 + i], v[0], size); - 702 32614 : return; + 702 32724 : return; 703 : } 704 : 705 : raid_sse_begin(); 706 : 707 : /* generic case with at least two data disks */ - 708 3376804 : for (i = 0; i < size; i += 16) { + 708 3383954 : for (i = 0; i < size; i += 16) { 709 : /* last disk without the by two multiplication */ - 710 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 711 3344192 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 710 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 711 3351232 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 712 : - 713 3344192 : asm volatile ("movdqa %xmm4,%xmm0"); - 714 3344192 : asm volatile ("movdqa %xmm4,%xmm1"); + 713 3351232 : asm volatile ("movdqa %xmm4,%xmm0"); + 714 3351232 : asm volatile ("movdqa %xmm4,%xmm1"); 715 : - 716 3344192 : asm volatile ("movdqa %xmm4,%xmm5"); - 717 3344192 : asm volatile ("psrlw $4,%xmm5"); - 718 3344192 : asm volatile ("pand %xmm7,%xmm4"); - 719 3344192 : asm volatile ("pand %xmm7,%xmm5"); + 716 3351232 : asm volatile ("movdqa %xmm4,%xmm5"); + 717 3351232 : asm volatile ("psrlw $4,%xmm5"); + 718 3351232 : asm volatile ("pand %xmm7,%xmm4"); + 719 3351232 : asm volatile ("pand %xmm7,%xmm5"); 720 : - 721 3344192 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); - 722 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); - 723 3344192 : asm volatile ("pshufb %xmm4,%xmm2"); - 724 3344192 : asm volatile ("pshufb %xmm5,%xmm7"); - 725 3344192 : asm volatile ("pxor %xmm7,%xmm2"); + 721 3351232 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + 722 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + 723 3351232 : asm volatile ("pshufb %xmm4,%xmm2"); + 724 3351232 : asm volatile ("pshufb %xmm5,%xmm7"); + 725 3351232 : asm volatile ("pxor %xmm7,%xmm2"); 726 : - 727 3344192 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); - 728 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); - 729 3344192 : asm volatile ("pshufb %xmm4,%xmm3"); - 730 3344192 : asm volatile ("pshufb %xmm5,%xmm7"); - 731 3344192 : asm volatile ("pxor %xmm7,%xmm3"); + 727 3351232 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + 728 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + 729 3351232 : asm volatile ("pshufb %xmm4,%xmm3"); + 730 3351232 : asm volatile ("pshufb %xmm5,%xmm7"); + 731 3351232 : asm volatile ("pxor %xmm7,%xmm3"); 732 : 733 : /* intermediate disks */ - 734 20046208 : for (d = l - 1; d > 0; --d) { - 735 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); - 736 16702016 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 734 20081408 : for (d = l - 1; d > 0; --d) { + 735 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 736 16730176 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 737 : - 738 16702016 : asm volatile ("pxor %xmm5,%xmm5"); - 739 16702016 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 740 16702016 : asm volatile ("paddb %xmm1,%xmm1"); - 741 16702016 : asm volatile ("pand %xmm7,%xmm5"); - 742 16702016 : asm volatile ("pxor %xmm5,%xmm1"); + 738 16730176 : asm volatile ("pxor %xmm5,%xmm5"); + 739 16730176 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 740 16730176 : asm volatile ("paddb %xmm1,%xmm1"); + 741 16730176 : asm volatile ("pand %xmm7,%xmm5"); + 742 16730176 : asm volatile ("pxor %xmm5,%xmm1"); 743 : - 744 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 744 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 745 : - 746 16702016 : asm volatile ("pxor %xmm4,%xmm0"); - 747 16702016 : asm volatile ("pxor %xmm4,%xmm1"); + 746 16730176 : asm volatile ("pxor %xmm4,%xmm0"); + 747 16730176 : asm volatile ("pxor %xmm4,%xmm1"); 748 : - 749 16702016 : asm volatile ("movdqa %xmm4,%xmm5"); - 750 16702016 : asm volatile ("psrlw $4,%xmm5"); - 751 16702016 : asm volatile ("pand %xmm7,%xmm4"); - 752 16702016 : asm volatile ("pand %xmm7,%xmm5"); + 749 16730176 : asm volatile ("movdqa %xmm4,%xmm5"); + 750 16730176 : asm volatile ("psrlw $4,%xmm5"); + 751 16730176 : asm volatile ("pand %xmm7,%xmm4"); + 752 16730176 : asm volatile ("pand %xmm7,%xmm5"); 753 : - 754 16702016 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 755 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); - 756 16702016 : asm volatile ("pshufb %xmm4,%xmm6"); - 757 16702016 : asm volatile ("pshufb %xmm5,%xmm7"); - 758 16702016 : asm volatile ("pxor %xmm6,%xmm2"); - 759 16702016 : asm volatile ("pxor %xmm7,%xmm2"); + 754 16730176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 755 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + 756 16730176 : asm volatile ("pshufb %xmm4,%xmm6"); + 757 16730176 : asm volatile ("pshufb %xmm5,%xmm7"); + 758 16730176 : asm volatile ("pxor %xmm6,%xmm2"); + 759 16730176 : asm volatile ("pxor %xmm7,%xmm2"); 760 : - 761 16702016 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); - 762 16702016 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); - 763 16702016 : asm volatile ("pshufb %xmm4,%xmm6"); - 764 16702016 : asm volatile ("pshufb %xmm5,%xmm7"); - 765 16702016 : asm volatile ("pxor %xmm6,%xmm3"); - 766 16702016 : asm volatile ("pxor %xmm7,%xmm3"); + 761 16730176 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + 762 16730176 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + 763 16730176 : asm volatile ("pshufb %xmm4,%xmm6"); + 764 16730176 : asm volatile ("pshufb %xmm5,%xmm7"); + 765 16730176 : asm volatile ("pxor %xmm6,%xmm3"); + 766 16730176 : asm volatile ("pxor %xmm7,%xmm3"); 767 : } 768 : 769 : /* first disk with all coefficients at 1 */ - 770 3344192 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); - 771 3344192 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 770 3351232 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 771 3351232 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); 772 : - 773 3344192 : asm volatile ("pxor %xmm5,%xmm5"); - 774 3344192 : asm volatile ("pcmpgtb %xmm1,%xmm5"); - 775 3344192 : asm volatile ("paddb %xmm1,%xmm1"); - 776 3344192 : asm volatile ("pand %xmm7,%xmm5"); - 777 3344192 : asm volatile ("pxor %xmm5,%xmm1"); + 773 3351232 : asm volatile ("pxor %xmm5,%xmm5"); + 774 3351232 : asm volatile ("pcmpgtb %xmm1,%xmm5"); + 775 3351232 : asm volatile ("paddb %xmm1,%xmm1"); + 776 3351232 : asm volatile ("pand %xmm7,%xmm5"); + 777 3351232 : asm volatile ("pxor %xmm5,%xmm1"); 778 : - 779 3344192 : asm volatile ("pxor %xmm4,%xmm0"); - 780 3344192 : asm volatile ("pxor %xmm4,%xmm1"); - 781 3344192 : asm volatile ("pxor %xmm4,%xmm2"); - 782 3344192 : asm volatile ("pxor %xmm4,%xmm3"); + 779 3351232 : asm volatile ("pxor %xmm4,%xmm0"); + 780 3351232 : asm volatile ("pxor %xmm4,%xmm1"); + 781 3351232 : asm volatile ("pxor %xmm4,%xmm2"); + 782 3351232 : asm volatile ("pxor %xmm4,%xmm3"); 783 : - 784 3344192 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 785 3344192 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 786 3344192 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); - 787 3344192 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + 784 3351232 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 785 3351232 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 786 3351232 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 787 3351232 : asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); 788 : } 789 : 790 : raid_sse_end(); @@ -1191,9 +1191,9 @@ 1129 : /* 1130 : * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation 1131 : */ - 1132 50258 : void raid_gen5_ssse3(int nd, size_t size, void **vv) + 1132 50169 : void raid_gen5_ssse3(int nd, size_t size, void **vv) 1133 : { - 1134 50258 : uint8_t **v = (uint8_t **)vv; + 1134 50169 : uint8_t **v = (uint8_t **)vv; 1135 : uint8_t *p; 1136 : uint8_t *q; 1137 : uint8_t *r; @@ -1202,122 +1202,122 @@ 1140 : int d, l; 1141 : size_t i; 1142 : uint8_t buffer[16+16]; - 1143 50258 : uint8_t *pd = __align_ptr(buffer, 16); + 1143 50169 : uint8_t *pd = __align_ptr(buffer, 16); 1144 : - 1145 50258 : l = nd - 1; - 1146 50258 : p = v[nd]; - 1147 50258 : q = v[nd + 1]; - 1148 50258 : r = v[nd + 2]; - 1149 50258 : s = v[nd + 3]; - 1150 50258 : t = v[nd + 4]; + 1145 50169 : l = nd - 1; + 1146 50169 : p = v[nd]; + 1147 50169 : q = v[nd + 1]; + 1148 50169 : r = v[nd + 2]; + 1149 50169 : s = v[nd + 3]; + 1150 50169 : t = v[nd + 4]; 1151 : 1152 : /* special case with only one data disk */ - 1153 50258 : if (l == 0) { + 1153 50169 : if (l == 0) { 1154 6 : for (i = 0; i < 5; ++i) 1155 5 : memcpy(v[1 + i], v[0], size); - 1156 50259 : return; + 1156 50170 : return; 1157 : } 1158 : 1159 : raid_sse_begin(); 1160 : 1161 : /* generic case with at least two data disks */ - 1162 3944417 : for (i = 0; i < size; i += 16) { + 1162 3938632 : for (i = 0; i < size; i += 16) { 1163 : /* last disk without the by two multiplication */ - 1164 3894160 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 1164 3888464 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 1165 : - 1166 3894160 : asm volatile ("movdqa %xmm4,%xmm0"); - 1167 3894160 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + 1166 3888464 : asm volatile ("movdqa %xmm4,%xmm0"); + 1167 3888464 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); 1168 : - 1169 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1170 3894160 : asm volatile ("movdqa %xmm4,%xmm5"); - 1171 3894160 : asm volatile ("psrlw $4,%xmm5"); - 1172 3894160 : asm volatile ("pand %xmm7,%xmm4"); - 1173 3894160 : asm volatile ("pand %xmm7,%xmm5"); + 1169 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1170 3888464 : asm volatile ("movdqa %xmm4,%xmm5"); + 1171 3888464 : asm volatile ("psrlw $4,%xmm5"); + 1172 3888464 : asm volatile ("pand %xmm7,%xmm4"); + 1173 3888464 : asm volatile ("pand %xmm7,%xmm5"); 1174 : - 1175 3894160 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0])); - 1176 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); - 1177 3894160 : asm volatile ("pshufb %xmm4,%xmm1"); - 1178 3894160 : asm volatile ("pshufb %xmm5,%xmm7"); - 1179 3894160 : asm volatile ("pxor %xmm7,%xmm1"); + 1175 3888464 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0])); + 1176 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + 1177 3888464 : asm volatile ("pshufb %xmm4,%xmm1"); + 1178 3888464 : asm volatile ("pshufb %xmm5,%xmm7"); + 1179 3888464 : asm volatile ("pxor %xmm7,%xmm1"); 1180 : - 1181 3894160 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0])); - 1182 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); - 1183 3894160 : asm volatile ("pshufb %xmm4,%xmm2"); - 1184 3894160 : asm volatile ("pshufb %xmm5,%xmm7"); - 1185 3894160 : asm volatile ("pxor %xmm7,%xmm2"); + 1181 3888464 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0])); + 1182 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + 1183 3888464 : asm volatile ("pshufb %xmm4,%xmm2"); + 1184 3888464 : asm volatile ("pshufb %xmm5,%xmm7"); + 1185 3888464 : asm volatile ("pxor %xmm7,%xmm2"); 1186 : - 1187 3894160 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0])); - 1188 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); - 1189 3894160 : asm volatile ("pshufb %xmm4,%xmm3"); - 1190 3894160 : asm volatile ("pshufb %xmm5,%xmm7"); - 1191 3894160 : asm volatile ("pxor %xmm7,%xmm3"); + 1187 3888464 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0])); + 1188 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + 1189 3888464 : asm volatile ("pshufb %xmm4,%xmm3"); + 1190 3888464 : asm volatile ("pshufb %xmm5,%xmm7"); + 1191 3888464 : asm volatile ("pxor %xmm7,%xmm3"); 1192 : 1193 : /* intermediate disks */ - 1194 23366000 : for (d = l - 1; d > 0; --d) { - 1195 19471840 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 1196 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); - 1197 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1194 23337520 : for (d = l - 1; d > 0; --d) { + 1195 19449056 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 1196 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + 1197 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1198 : - 1199 19471840 : asm volatile ("pxor %xmm5,%xmm5"); - 1200 19471840 : asm volatile ("pcmpgtb %xmm0,%xmm5"); - 1201 19471840 : asm volatile ("paddb %xmm0,%xmm0"); - 1202 19471840 : asm volatile ("pand %xmm7,%xmm5"); - 1203 19471840 : asm volatile ("pxor %xmm5,%xmm0"); + 1199 19449056 : asm volatile ("pxor %xmm5,%xmm5"); + 1200 19449056 : asm volatile ("pcmpgtb %xmm0,%xmm5"); + 1201 19449056 : asm volatile ("paddb %xmm0,%xmm0"); + 1202 19449056 : asm volatile ("pand %xmm7,%xmm5"); + 1203 19449056 : asm volatile ("pxor %xmm5,%xmm0"); 1204 : - 1205 19471840 : asm volatile ("pxor %xmm4,%xmm0"); - 1206 19471840 : asm volatile ("pxor %xmm4,%xmm6"); - 1207 19471840 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0])); + 1205 19449056 : asm volatile ("pxor %xmm4,%xmm0"); + 1206 19449056 : asm volatile ("pxor %xmm4,%xmm6"); + 1207 19449056 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0])); 1208 : - 1209 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1210 19471840 : asm volatile ("movdqa %xmm4,%xmm5"); - 1211 19471840 : asm volatile ("psrlw $4,%xmm5"); - 1212 19471840 : asm volatile ("pand %xmm7,%xmm4"); - 1213 19471840 : asm volatile ("pand %xmm7,%xmm5"); + 1209 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1210 19449056 : asm volatile ("movdqa %xmm4,%xmm5"); + 1211 19449056 : asm volatile ("psrlw $4,%xmm5"); + 1212 19449056 : asm volatile ("pand %xmm7,%xmm4"); + 1213 19449056 : asm volatile ("pand %xmm7,%xmm5"); 1214 : - 1215 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 1216 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); - 1217 19471840 : asm volatile ("pshufb %xmm4,%xmm6"); - 1218 19471840 : asm volatile ("pshufb %xmm5,%xmm7"); - 1219 19471840 : asm volatile ("pxor %xmm6,%xmm1"); - 1220 19471840 : asm volatile ("pxor %xmm7,%xmm1"); + 1215 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 1216 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + 1217 19449056 : asm volatile ("pshufb %xmm4,%xmm6"); + 1218 19449056 : asm volatile ("pshufb %xmm5,%xmm7"); + 1219 19449056 : asm volatile ("pxor %xmm6,%xmm1"); + 1220 19449056 : asm volatile ("pxor %xmm7,%xmm1"); 1221 : - 1222 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); - 1223 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); - 1224 19471840 : asm volatile ("pshufb %xmm4,%xmm6"); - 1225 19471840 : asm volatile ("pshufb %xmm5,%xmm7"); - 1226 19471840 : asm volatile ("pxor %xmm6,%xmm2"); - 1227 19471840 : asm volatile ("pxor %xmm7,%xmm2"); + 1222 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + 1223 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + 1224 19449056 : asm volatile ("pshufb %xmm4,%xmm6"); + 1225 19449056 : asm volatile ("pshufb %xmm5,%xmm7"); + 1226 19449056 : asm volatile ("pxor %xmm6,%xmm2"); + 1227 19449056 : asm volatile ("pxor %xmm7,%xmm2"); 1228 : - 1229 19471840 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); - 1230 19471840 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); - 1231 19471840 : asm volatile ("pshufb %xmm4,%xmm6"); - 1232 19471840 : asm volatile ("pshufb %xmm5,%xmm7"); - 1233 19471840 : asm volatile ("pxor %xmm6,%xmm3"); - 1234 19471840 : asm volatile ("pxor %xmm7,%xmm3"); + 1229 19449056 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + 1230 19449056 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + 1231 19449056 : asm volatile ("pshufb %xmm4,%xmm6"); + 1232 19449056 : asm volatile ("pshufb %xmm5,%xmm7"); + 1233 19449056 : asm volatile ("pxor %xmm6,%xmm3"); + 1234 19449056 : asm volatile ("pxor %xmm7,%xmm3"); 1235 : } 1236 : 1237 : /* first disk with all coefficients at 1 */ - 1238 3894160 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); - 1239 3894160 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); - 1240 3894160 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1238 3888464 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 1239 3888464 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + 1240 3888464 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1241 : - 1242 3894160 : asm volatile ("pxor %xmm5,%xmm5"); - 1243 3894160 : asm volatile ("pcmpgtb %xmm0,%xmm5"); - 1244 3894160 : asm volatile ("paddb %xmm0,%xmm0"); - 1245 3894160 : asm volatile ("pand %xmm7,%xmm5"); - 1246 3894160 : asm volatile ("pxor %xmm5,%xmm0"); + 1242 3888464 : asm volatile ("pxor %xmm5,%xmm5"); + 1243 3888464 : asm volatile ("pcmpgtb %xmm0,%xmm5"); + 1244 3888464 : asm volatile ("paddb %xmm0,%xmm0"); + 1245 3888464 : asm volatile ("pand %xmm7,%xmm5"); + 1246 3888464 : asm volatile ("pxor %xmm5,%xmm0"); 1247 : - 1248 3894160 : asm volatile ("pxor %xmm4,%xmm0"); - 1249 3894160 : asm volatile ("pxor %xmm4,%xmm1"); - 1250 3894160 : asm volatile ("pxor %xmm4,%xmm2"); - 1251 3894160 : asm volatile ("pxor %xmm4,%xmm3"); - 1252 3894160 : asm volatile ("pxor %xmm4,%xmm6"); + 1248 3888464 : asm volatile ("pxor %xmm4,%xmm0"); + 1249 3888464 : asm volatile ("pxor %xmm4,%xmm1"); + 1250 3888464 : asm volatile ("pxor %xmm4,%xmm2"); + 1251 3888464 : asm volatile ("pxor %xmm4,%xmm3"); + 1252 3888464 : asm volatile ("pxor %xmm4,%xmm6"); 1253 : - 1254 3894160 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i])); - 1255 3894160 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i])); - 1256 3894160 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i])); - 1257 3894160 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i])); - 1258 3894160 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i])); + 1254 3888464 : asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i])); + 1255 3888464 : asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i])); + 1256 3888464 : asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i])); + 1257 3888464 : asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i])); + 1258 3888464 : asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i])); 1259 : } 1260 : 1261 : raid_sse_end(); @@ -1591,9 +1591,9 @@ 1529 : /* 1530 : * GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation 1531 : */ - 1532 549666 : void raid_gen6_ssse3(int nd, size_t size, void **vv) + 1532 559030 : void raid_gen6_ssse3(int nd, size_t size, void **vv) 1533 : { - 1534 549666 : uint8_t **v = (uint8_t **)vv; + 1534 559030 : uint8_t **v = (uint8_t **)vv; 1535 : uint8_t *p; 1536 : uint8_t *q; 1537 : uint8_t *r; @@ -1603,142 +1603,142 @@ 1541 : int d, l; 1542 : size_t i; 1543 : uint8_t buffer[2*16+16]; - 1544 549666 : uint8_t *pd = __align_ptr(buffer, 16); + 1544 559030 : uint8_t *pd = __align_ptr(buffer, 16); 1545 : - 1546 549666 : l = nd - 1; - 1547 549666 : p = v[nd]; - 1548 549666 : q = v[nd + 1]; - 1549 549666 : r = v[nd + 2]; - 1550 549666 : s = v[nd + 3]; - 1551 549666 : t = v[nd + 4]; - 1552 549666 : u = v[nd + 5]; + 1546 559030 : l = nd - 1; + 1547 559030 : p = v[nd]; + 1548 559030 : q = v[nd + 1]; + 1549 559030 : r = v[nd + 2]; + 1550 559030 : s = v[nd + 3]; + 1551 559030 : t = v[nd + 4]; + 1552 559030 : u = v[nd + 5]; 1553 : 1554 : /* special case with only one data disk */ - 1555 549666 : if (l == 0) { + 1555 559030 : if (l == 0) { 1556 7 : for (i = 0; i < 6; ++i) 1557 6 : memcpy(v[1 + i], v[0], size); - 1558 549667 : return; + 1558 559031 : return; 1559 : } 1560 : 1561 : raid_sse_begin(); 1562 : 1563 : /* generic case with at least two data disks */ - 1564 35154865 : for (i = 0; i < size; i += 16) { + 1564 35763525 : for (i = 0; i < size; i += 16) { 1565 : /* last disk without the by two multiplication */ - 1566 34605200 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + 1566 35204496 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); 1567 : - 1568 34605200 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); - 1569 34605200 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16])); + 1568 35204496 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + 1569 35204496 : asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16])); 1570 : - 1571 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1572 34605200 : asm volatile ("movdqa %xmm4,%xmm5"); - 1573 34605200 : asm volatile ("psrlw $4,%xmm5"); - 1574 34605200 : asm volatile ("pand %xmm7,%xmm4"); - 1575 34605200 : asm volatile ("pand %xmm7,%xmm5"); + 1571 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1572 35204496 : asm volatile ("movdqa %xmm4,%xmm5"); + 1573 35204496 : asm volatile ("psrlw $4,%xmm5"); + 1574 35204496 : asm volatile ("pand %xmm7,%xmm4"); + 1575 35204496 : asm volatile ("pand %xmm7,%xmm5"); 1576 : - 1577 34605200 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0])); - 1578 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); - 1579 34605200 : asm volatile ("pshufb %xmm4,%xmm0"); - 1580 34605200 : asm volatile ("pshufb %xmm5,%xmm7"); - 1581 34605200 : asm volatile ("pxor %xmm7,%xmm0"); + 1577 35204496 : asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0])); + 1578 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + 1579 35204496 : asm volatile ("pshufb %xmm4,%xmm0"); + 1580 35204496 : asm volatile ("pshufb %xmm5,%xmm7"); + 1581 35204496 : asm volatile ("pxor %xmm7,%xmm0"); 1582 : - 1583 34605200 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0])); - 1584 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); - 1585 34605200 : asm volatile ("pshufb %xmm4,%xmm1"); - 1586 34605200 : asm volatile ("pshufb %xmm5,%xmm7"); - 1587 34605200 : asm volatile ("pxor %xmm7,%xmm1"); + 1583 35204496 : asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0])); + 1584 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + 1585 35204496 : asm volatile ("pshufb %xmm4,%xmm1"); + 1586 35204496 : asm volatile ("pshufb %xmm5,%xmm7"); + 1587 35204496 : asm volatile ("pxor %xmm7,%xmm1"); 1588 : - 1589 34605200 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0])); - 1590 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); - 1591 34605200 : asm volatile ("pshufb %xmm4,%xmm2"); - 1592 34605200 : asm volatile ("pshufb %xmm5,%xmm7"); - 1593 34605200 : asm volatile ("pxor %xmm7,%xmm2"); + 1589 35204496 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0])); + 1590 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + 1591 35204496 : asm volatile ("pshufb %xmm4,%xmm2"); + 1592 35204496 : asm volatile ("pshufb %xmm5,%xmm7"); + 1593 35204496 : asm volatile ("pxor %xmm7,%xmm2"); 1594 : - 1595 34605200 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0])); - 1596 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0])); - 1597 34605200 : asm volatile ("pshufb %xmm4,%xmm3"); - 1598 34605200 : asm volatile ("pshufb %xmm5,%xmm7"); - 1599 34605200 : asm volatile ("pxor %xmm7,%xmm3"); + 1595 35204496 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0])); + 1596 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0])); + 1597 35204496 : asm volatile ("pshufb %xmm4,%xmm3"); + 1598 35204496 : asm volatile ("pshufb %xmm5,%xmm7"); + 1599 35204496 : asm volatile ("pxor %xmm7,%xmm3"); 1600 : 1601 : /* intermediate disks */ - 1602 179030896 : for (d = l - 1; d > 0; --d) { - 1603 144425696 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); - 1604 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); - 1605 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1602 182027376 : for (d = l - 1; d > 0; --d) { + 1603 146822880 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + 1604 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + 1605 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1606 : - 1607 144425696 : asm volatile ("pxor %xmm4,%xmm4"); - 1608 144425696 : asm volatile ("pcmpgtb %xmm6,%xmm4"); - 1609 144425696 : asm volatile ("paddb %xmm6,%xmm6"); - 1610 144425696 : asm volatile ("pand %xmm7,%xmm4"); - 1611 144425696 : asm volatile ("pxor %xmm4,%xmm6"); + 1607 146822880 : asm volatile ("pxor %xmm4,%xmm4"); + 1608 146822880 : asm volatile ("pcmpgtb %xmm6,%xmm4"); + 1609 146822880 : asm volatile ("paddb %xmm6,%xmm6"); + 1610 146822880 : asm volatile ("pand %xmm7,%xmm4"); + 1611 146822880 : asm volatile ("pxor %xmm4,%xmm6"); 1612 : - 1613 144425696 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 1613 146822880 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); 1614 : - 1615 144425696 : asm volatile ("pxor %xmm4,%xmm5"); - 1616 144425696 : asm volatile ("pxor %xmm4,%xmm6"); - 1617 144425696 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0])); - 1618 144425696 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16])); + 1615 146822880 : asm volatile ("pxor %xmm4,%xmm5"); + 1616 146822880 : asm volatile ("pxor %xmm4,%xmm6"); + 1617 146822880 : asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0])); + 1618 146822880 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16])); 1619 : - 1620 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 1621 144425696 : asm volatile ("movdqa %xmm4,%xmm5"); - 1622 144425696 : asm volatile ("psrlw $4,%xmm5"); - 1623 144425696 : asm volatile ("pand %xmm7,%xmm4"); - 1624 144425696 : asm volatile ("pand %xmm7,%xmm5"); + 1620 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 1621 146822880 : asm volatile ("movdqa %xmm4,%xmm5"); + 1622 146822880 : asm volatile ("psrlw $4,%xmm5"); + 1623 146822880 : asm volatile ("pand %xmm7,%xmm4"); + 1624 146822880 : asm volatile ("pand %xmm7,%xmm5"); 1625 : - 1626 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); - 1627 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); - 1628 144425696 : asm volatile ("pshufb %xmm4,%xmm6"); - 1629 144425696 : asm volatile ("pshufb %xmm5,%xmm7"); - 1630 144425696 : asm volatile ("pxor %xmm6,%xmm0"); - 1631 144425696 : asm volatile ("pxor %xmm7,%xmm0"); + 1626 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + 1627 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + 1628 146822880 : asm volatile ("pshufb %xmm4,%xmm6"); + 1629 146822880 : asm volatile ("pshufb %xmm5,%xmm7"); + 1630 146822880 : asm volatile ("pxor %xmm6,%xmm0"); + 1631 146822880 : asm volatile ("pxor %xmm7,%xmm0"); 1632 : - 1633 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); - 1634 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); - 1635 144425696 : asm volatile ("pshufb %xmm4,%xmm6"); - 1636 144425696 : asm volatile ("pshufb %xmm5,%xmm7"); - 1637 144425696 : asm volatile ("pxor %xmm6,%xmm1"); - 1638 144425696 : asm volatile ("pxor %xmm7,%xmm1"); + 1633 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + 1634 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + 1635 146822880 : asm volatile ("pshufb %xmm4,%xmm6"); + 1636 146822880 : asm volatile ("pshufb %xmm5,%xmm7"); + 1637 146822880 : asm volatile ("pxor %xmm6,%xmm1"); + 1638 146822880 : asm volatile ("pxor %xmm7,%xmm1"); 1639 : - 1640 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); - 1641 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); - 1642 144425696 : asm volatile ("pshufb %xmm4,%xmm6"); - 1643 144425696 : asm volatile ("pshufb %xmm5,%xmm7"); - 1644 144425696 : asm volatile ("pxor %xmm6,%xmm2"); - 1645 144425696 : asm volatile ("pxor %xmm7,%xmm2"); + 1640 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + 1641 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + 1642 146822880 : asm volatile ("pshufb %xmm4,%xmm6"); + 1643 146822880 : asm volatile ("pshufb %xmm5,%xmm7"); + 1644 146822880 : asm volatile ("pxor %xmm6,%xmm2"); + 1645 146822880 : asm volatile ("pxor %xmm7,%xmm2"); 1646 : - 1647 144425696 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0])); - 1648 144425696 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0])); - 1649 144425696 : asm volatile ("pshufb %xmm4,%xmm6"); - 1650 144425696 : asm volatile ("pshufb %xmm5,%xmm7"); - 1651 144425696 : asm volatile ("pxor %xmm6,%xmm3"); - 1652 144425696 : asm volatile ("pxor %xmm7,%xmm3"); + 1647 146822880 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0])); + 1648 146822880 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0])); + 1649 146822880 : asm volatile ("pshufb %xmm4,%xmm6"); + 1650 146822880 : asm volatile ("pshufb %xmm5,%xmm7"); + 1651 146822880 : asm volatile ("pxor %xmm6,%xmm3"); + 1652 146822880 : asm volatile ("pxor %xmm7,%xmm3"); 1653 : } 1654 : 1655 : /* first disk with all coefficients at 1 */ - 1656 34605200 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); - 1657 34605200 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); - 1658 34605200 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + 1656 35204496 : asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + 1657 35204496 : asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + 1658 35204496 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); 1659 : - 1660 34605200 : asm volatile ("pxor %xmm4,%xmm4"); - 1661 34605200 : asm volatile ("pcmpgtb %xmm6,%xmm4"); - 1662 34605200 : asm volatile ("paddb %xmm6,%xmm6"); - 1663 34605200 : asm volatile ("pand %xmm7,%xmm4"); - 1664 34605200 : asm volatile ("pxor %xmm4,%xmm6"); + 1660 35204496 : asm volatile ("pxor %xmm4,%xmm4"); + 1661 35204496 : asm volatile ("pcmpgtb %xmm6,%xmm4"); + 1662 35204496 : asm volatile ("paddb %xmm6,%xmm6"); + 1663 35204496 : asm volatile ("pand %xmm7,%xmm4"); + 1664 35204496 : asm volatile ("pxor %xmm4,%xmm6"); 1665 : - 1666 34605200 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); - 1667 34605200 : asm volatile ("pxor %xmm4,%xmm0"); - 1668 34605200 : asm volatile ("pxor %xmm4,%xmm1"); - 1669 34605200 : asm volatile ("pxor %xmm4,%xmm2"); - 1670 34605200 : asm volatile ("pxor %xmm4,%xmm3"); - 1671 34605200 : asm volatile ("pxor %xmm4,%xmm5"); - 1672 34605200 : asm volatile ("pxor %xmm4,%xmm6"); + 1666 35204496 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + 1667 35204496 : asm volatile ("pxor %xmm4,%xmm0"); + 1668 35204496 : asm volatile ("pxor %xmm4,%xmm1"); + 1669 35204496 : asm volatile ("pxor %xmm4,%xmm2"); + 1670 35204496 : asm volatile ("pxor %xmm4,%xmm3"); + 1671 35204496 : asm volatile ("pxor %xmm4,%xmm5"); + 1672 35204496 : asm volatile ("pxor %xmm4,%xmm6"); 1673 : - 1674 34605200 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i])); - 1675 34605200 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i])); - 1676 34605200 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i])); - 1677 34605200 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i])); - 1678 34605200 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i])); - 1679 34605200 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i])); + 1674 35204496 : asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i])); + 1675 35204496 : asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i])); + 1676 35204496 : asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i])); + 1677 35204496 : asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i])); + 1678 35204496 : asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i])); + 1679 35204496 : asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i])); 1680 : } 1681 : 1682 : raid_sse_end(); @@ -2046,9 +2046,9 @@ 1984 : /* 1985 : * RAID recovering for one disk SSSE3 implementation 1986 : */ - 1987 114430 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 1987 108422 : void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 1988 : { - 1989 114430 : uint8_t **v = (uint8_t **)vv; + 1989 108422 : uint8_t **v = (uint8_t **)vv; 1990 : uint8_t *p; 1991 : uint8_t *pa; 1992 : uint8_t G; @@ -2058,43 +2058,43 @@ 1996 : (void)nr; /* unused, it's always 1 */ 1997 : 1998 : /* if it's RAID5 uses the faster function */ - 1999 114430 : if (ip[0] == 0) { - 2000 104899 : raid_rec1of1(id, nd, size, vv); - 2001 219329 : return; + 1999 108422 : if (ip[0] == 0) { + 2000 98863 : raid_rec1of1(id, nd, size, vv); + 2001 207285 : return; 2002 : } 2003 : 2004 : /* setup the coefficients matrix */ - 2005 19062 : G = A(ip[0], id[0]); + 2005 19118 : G = A(ip[0], id[0]); 2006 : 2007 : /* invert it to solve the system of linear equations */ - 2008 19062 : V = inv(G); + 2008 19118 : V = inv(G); 2009 : 2010 : /* compute delta parity */ - 2011 9531 : raid_delta_gen(1, id, ip, nd, size, vv); + 2011 9559 : raid_delta_gen(1, id, ip, nd, size, vv); 2012 : - 2013 9531 : p = v[nd + ip[0]]; - 2014 9531 : pa = v[id[0]]; + 2013 9559 : p = v[nd + ip[0]]; + 2014 9559 : pa = v[id[0]]; 2015 : 2016 : raid_sse_begin(); 2017 : - 2018 9531 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); - 2019 9531 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); - 2020 9531 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); + 2018 9559 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2019 9559 : asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); + 2020 9559 : asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); 2021 : - 2022 1529403 : for (i = 0; i < size; i += 16) { - 2023 1519872 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); - 2024 1519872 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); - 2025 1519872 : asm volatile ("movdqa %xmm4,%xmm2"); - 2026 1519872 : asm volatile ("movdqa %xmm5,%xmm3"); - 2027 1519872 : asm volatile ("pxor %xmm0,%xmm1"); - 2028 1519872 : asm volatile ("movdqa %xmm1,%xmm0"); - 2029 1519872 : asm volatile ("psrlw $4,%xmm1"); - 2030 1519872 : asm volatile ("pand %xmm7,%xmm0"); - 2031 1519872 : asm volatile ("pand %xmm7,%xmm1"); - 2032 1519872 : asm volatile ("pshufb %xmm0,%xmm2"); - 2033 1519872 : asm volatile ("pshufb %xmm1,%xmm3"); - 2034 1519872 : asm volatile ("pxor %xmm3,%xmm2"); - 2035 1519872 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); + 2022 1531223 : for (i = 0; i < size; i += 16) { + 2023 1521664 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); + 2024 1521664 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); + 2025 1521664 : asm volatile ("movdqa %xmm4,%xmm2"); + 2026 1521664 : asm volatile ("movdqa %xmm5,%xmm3"); + 2027 1521664 : asm volatile ("pxor %xmm0,%xmm1"); + 2028 1521664 : asm volatile ("movdqa %xmm1,%xmm0"); + 2029 1521664 : asm volatile ("psrlw $4,%xmm1"); + 2030 1521664 : asm volatile ("pand %xmm7,%xmm0"); + 2031 1521664 : asm volatile ("pand %xmm7,%xmm1"); + 2032 1521664 : asm volatile ("pshufb %xmm0,%xmm2"); + 2033 1521664 : asm volatile ("pshufb %xmm1,%xmm3"); + 2034 1521664 : asm volatile ("pxor %xmm3,%xmm2"); + 2035 1521664 : asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); 2036 : } 2037 : 2038 : raid_sse_end(); @@ -2105,182 +2105,182 @@ 2043 : /* 2044 : * RAID recovering for two disks SSSE3 implementation 2045 : */ - 2046 44206 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 2046 43538 : void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 2047 : { - 2048 44206 : uint8_t **v = (uint8_t **)vv; - 2049 44206 : const int N = 2; - 2050 44206 : uint8_t *p[N]; - 2051 44206 : uint8_t *pa[N]; - 2052 44206 : uint8_t G[N * N]; - 2053 44206 : uint8_t V[N * N]; + 2048 43538 : uint8_t **v = (uint8_t **)vv; + 2049 43538 : const int N = 2; + 2050 43538 : uint8_t *p[N]; + 2051 43538 : uint8_t *pa[N]; + 2052 43538 : uint8_t G[N * N]; + 2053 43538 : uint8_t V[N * N]; 2054 : size_t i; 2055 : int j, k; 2056 : 2057 : (void)nr; /* unused, it's always 2 */ 2058 : 2059 : /* setup the coefficients matrix */ - 2060 132618 : for (j = 0; j < N; ++j) - 2061 265236 : for (k = 0; k < N; ++k) - 2062 353648 : G[j * N + k] = A(ip[j], id[k]); + 2060 130614 : for (j = 0; j < N; ++j) + 2061 261228 : for (k = 0; k < N; ++k) + 2062 348304 : G[j * N + k] = A(ip[j], id[k]); 2063 : 2064 : /* invert it to solve the system of linear equations */ - 2065 44206 : raid_invert(G, V, N); + 2065 43538 : raid_invert(G, V, N); 2066 : 2067 : /* compute delta parity */ - 2068 44206 : raid_delta_gen(N, id, ip, nd, size, vv); + 2068 43538 : raid_delta_gen(N, id, ip, nd, size, vv); 2069 : - 2070 132618 : for (j = 0; j < N; ++j) { - 2071 88412 : p[j] = v[nd + ip[j]]; - 2072 88412 : pa[j] = v[id[j]]; + 2070 130614 : for (j = 0; j < N; ++j) { + 2071 87076 : p[j] = v[nd + ip[j]]; + 2072 87076 : pa[j] = v[id[j]]; 2073 : } 2074 : 2075 : raid_sse_begin(); 2076 : - 2077 44206 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2077 43538 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 2078 : - 2079 3599726 : for (i = 0; i < size; i += 16) { - 2080 3555520 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); - 2081 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); - 2082 3555520 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); - 2083 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); - 2084 3555520 : asm volatile ("pxor %xmm2,%xmm0"); - 2085 3555520 : asm volatile ("pxor %xmm3,%xmm1"); + 2079 3556306 : for (i = 0; i < size; i += 16) { + 2080 3512768 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); + 2081 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); + 2082 3512768 : asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); + 2083 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); + 2084 3512768 : asm volatile ("pxor %xmm2,%xmm0"); + 2085 3512768 : asm volatile ("pxor %xmm3,%xmm1"); 2086 : - 2087 3555520 : asm volatile ("pxor %xmm6,%xmm6"); + 2087 3512768 : asm volatile ("pxor %xmm6,%xmm6"); 2088 : - 2089 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); - 2090 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); - 2091 3555520 : asm volatile ("movdqa %xmm0,%xmm4"); - 2092 3555520 : asm volatile ("movdqa %xmm0,%xmm5"); - 2093 3555520 : asm volatile ("psrlw $4,%xmm5"); - 2094 3555520 : asm volatile ("pand %xmm7,%xmm4"); - 2095 3555520 : asm volatile ("pand %xmm7,%xmm5"); - 2096 3555520 : asm volatile ("pshufb %xmm4,%xmm2"); - 2097 3555520 : asm volatile ("pshufb %xmm5,%xmm3"); - 2098 3555520 : asm volatile ("pxor %xmm2,%xmm6"); - 2099 3555520 : asm volatile ("pxor %xmm3,%xmm6"); + 2089 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); + 2090 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); + 2091 3512768 : asm volatile ("movdqa %xmm0,%xmm4"); + 2092 3512768 : asm volatile ("movdqa %xmm0,%xmm5"); + 2093 3512768 : asm volatile ("psrlw $4,%xmm5"); + 2094 3512768 : asm volatile ("pand %xmm7,%xmm4"); + 2095 3512768 : asm volatile ("pand %xmm7,%xmm5"); + 2096 3512768 : asm volatile ("pshufb %xmm4,%xmm2"); + 2097 3512768 : asm volatile ("pshufb %xmm5,%xmm3"); + 2098 3512768 : asm volatile ("pxor %xmm2,%xmm6"); + 2099 3512768 : asm volatile ("pxor %xmm3,%xmm6"); 2100 : - 2101 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); - 2102 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); - 2103 3555520 : asm volatile ("movdqa %xmm1,%xmm4"); - 2104 3555520 : asm volatile ("movdqa %xmm1,%xmm5"); - 2105 3555520 : asm volatile ("psrlw $4,%xmm5"); - 2106 3555520 : asm volatile ("pand %xmm7,%xmm4"); - 2107 3555520 : asm volatile ("pand %xmm7,%xmm5"); - 2108 3555520 : asm volatile ("pshufb %xmm4,%xmm2"); - 2109 3555520 : asm volatile ("pshufb %xmm5,%xmm3"); - 2110 3555520 : asm volatile ("pxor %xmm2,%xmm6"); - 2111 3555520 : asm volatile ("pxor %xmm3,%xmm6"); + 2101 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); + 2102 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); + 2103 3512768 : asm volatile ("movdqa %xmm1,%xmm4"); + 2104 3512768 : asm volatile ("movdqa %xmm1,%xmm5"); + 2105 3512768 : asm volatile ("psrlw $4,%xmm5"); + 2106 3512768 : asm volatile ("pand %xmm7,%xmm4"); + 2107 3512768 : asm volatile ("pand %xmm7,%xmm5"); + 2108 3512768 : asm volatile ("pshufb %xmm4,%xmm2"); + 2109 3512768 : asm volatile ("pshufb %xmm5,%xmm3"); + 2110 3512768 : asm volatile ("pxor %xmm2,%xmm6"); + 2111 3512768 : asm volatile ("pxor %xmm3,%xmm6"); 2112 : - 2113 3555520 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); + 2113 3512768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); 2114 : - 2115 3555520 : asm volatile ("pxor %xmm6,%xmm6"); + 2115 3512768 : asm volatile ("pxor %xmm6,%xmm6"); 2116 : - 2117 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); - 2118 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); - 2119 3555520 : asm volatile ("movdqa %xmm0,%xmm4"); - 2120 3555520 : asm volatile ("movdqa %xmm0,%xmm5"); - 2121 3555520 : asm volatile ("psrlw $4,%xmm5"); - 2122 3555520 : asm volatile ("pand %xmm7,%xmm4"); - 2123 3555520 : asm volatile ("pand %xmm7,%xmm5"); - 2124 3555520 : asm volatile ("pshufb %xmm4,%xmm2"); - 2125 3555520 : asm volatile ("pshufb %xmm5,%xmm3"); - 2126 3555520 : asm volatile ("pxor %xmm2,%xmm6"); - 2127 3555520 : asm volatile ("pxor %xmm3,%xmm6"); + 2117 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); + 2118 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); + 2119 3512768 : asm volatile ("movdqa %xmm0,%xmm4"); + 2120 3512768 : asm volatile ("movdqa %xmm0,%xmm5"); + 2121 3512768 : asm volatile ("psrlw $4,%xmm5"); + 2122 3512768 : asm volatile ("pand %xmm7,%xmm4"); + 2123 3512768 : asm volatile ("pand %xmm7,%xmm5"); + 2124 3512768 : asm volatile ("pshufb %xmm4,%xmm2"); + 2125 3512768 : asm volatile ("pshufb %xmm5,%xmm3"); + 2126 3512768 : asm volatile ("pxor %xmm2,%xmm6"); + 2127 3512768 : asm volatile ("pxor %xmm3,%xmm6"); 2128 : - 2129 3555520 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); - 2130 3555520 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); - 2131 3555520 : asm volatile ("movdqa %xmm1,%xmm4"); - 2132 3555520 : asm volatile ("movdqa %xmm1,%xmm5"); - 2133 3555520 : asm volatile ("psrlw $4,%xmm5"); - 2134 3555520 : asm volatile ("pand %xmm7,%xmm4"); - 2135 3555520 : asm volatile ("pand %xmm7,%xmm5"); - 2136 3555520 : asm volatile ("pshufb %xmm4,%xmm2"); - 2137 3555520 : asm volatile ("pshufb %xmm5,%xmm3"); - 2138 3555520 : asm volatile ("pxor %xmm2,%xmm6"); - 2139 3555520 : asm volatile ("pxor %xmm3,%xmm6"); + 2129 3512768 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); + 2130 3512768 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); + 2131 3512768 : asm volatile ("movdqa %xmm1,%xmm4"); + 2132 3512768 : asm volatile ("movdqa %xmm1,%xmm5"); + 2133 3512768 : asm volatile ("psrlw $4,%xmm5"); + 2134 3512768 : asm volatile ("pand %xmm7,%xmm4"); + 2135 3512768 : asm volatile ("pand %xmm7,%xmm5"); + 2136 3512768 : asm volatile ("pshufb %xmm4,%xmm2"); + 2137 3512768 : asm volatile ("pshufb %xmm5,%xmm3"); + 2138 3512768 : asm volatile ("pxor %xmm2,%xmm6"); + 2139 3512768 : asm volatile ("pxor %xmm3,%xmm6"); 2140 : - 2141 3555520 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); + 2141 3512768 : asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); 2142 : } 2143 : 2144 : raid_sse_end(); - 2145 44206 : } + 2145 43538 : } 2146 : #endif 2147 : 2148 : #if defined(CONFIG_X86) && defined(CONFIG_SSSE3) 2149 : /* 2150 : * RAID recovering SSSE3 implementation 2151 : */ - 2152 79298 : void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) + 2152 79451 : void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) 2153 : { - 2154 79298 : uint8_t **v = (uint8_t **)vv; - 2155 79298 : int N = nr; + 2154 79451 : uint8_t **v = (uint8_t **)vv; + 2155 79451 : int N = nr; 2156 : uint8_t *p[RAID_PARITY_MAX]; 2157 : uint8_t *pa[RAID_PARITY_MAX]; 2158 : uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX]; 2159 : uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX]; 2160 : uint8_t buffer[RAID_PARITY_MAX*16+16]; - 2161 79298 : uint8_t *pd = __align_ptr(buffer, 16); + 2161 79451 : uint8_t *pd = __align_ptr(buffer, 16); 2162 : size_t i; 2163 : int j, k; 2164 : 2165 : /* setup the coefficients matrix */ - 2166 435232 : for (j = 0; j < N; ++j) - 2167 2047624 : for (k = 0; k < N; ++k) - 2168 3383380 : G[j * N + k] = A(ip[j], id[k]); + 2166 435393 : for (j = 0; j < N; ++j) + 2167 2045022 : for (k = 0; k < N; ++k) + 2168 3378160 : G[j * N + k] = A(ip[j], id[k]); 2169 : 2170 : /* invert it to solve the system of linear equations */ - 2171 79298 : raid_invert(G, V, N); + 2171 79451 : raid_invert(G, V, N); 2172 : 2173 : /* compute delta parity */ - 2174 79298 : raid_delta_gen(N, id, ip, nd, size, vv); + 2174 79451 : raid_delta_gen(N, id, ip, nd, size, vv); 2175 : - 2176 435232 : for (j = 0; j < N; ++j) { - 2177 355934 : p[j] = v[nd + ip[j]]; - 2178 355934 : pa[j] = v[id[j]]; + 2176 435393 : for (j = 0; j < N; ++j) { + 2177 355942 : p[j] = v[nd + ip[j]]; + 2178 355942 : pa[j] = v[id[j]]; 2179 : } 2180 : 2181 : raid_sse_begin(); 2182 : - 2183 79298 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + 2183 79451 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); 2184 : - 2185 5870482 : for (i = 0; i < size; i += 16) { + 2185 5880427 : for (i = 0; i < size; i += 16) { 2186 : /* delta */ - 2187 32123728 : for (j = 0; j < N; ++j) { - 2188 26332544 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[j][i])); - 2189 26332544 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[j][i])); - 2190 26332544 : asm volatile ("pxor %xmm1,%xmm0"); - 2191 26332544 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pd[j*16])); + 2187 32134032 : for (j = 0; j < N; ++j) { + 2188 26333056 : asm volatile ("movdqa %0,%%xmm0" : : "m" (p[j][i])); + 2189 26333056 : asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[j][i])); + 2190 26333056 : asm volatile ("pxor %xmm1,%xmm0"); + 2191 26333056 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pd[j*16])); 2192 : } 2193 : 2194 : /* reconstruct */ - 2195 32123728 : for (j = 0; j < N; ++j) { - 2196 26332544 : asm volatile ("pxor %xmm0,%xmm0"); - 2197 26332544 : asm volatile ("pxor %xmm1,%xmm1"); + 2195 32134032 : for (j = 0; j < N; ++j) { + 2196 26333056 : asm volatile ("pxor %xmm0,%xmm0"); + 2197 26333056 : asm volatile ("pxor %xmm1,%xmm1"); 2198 : - 2199 153287872 : for (k = 0; k < N; ++k) { - 2200 126955328 : uint8_t m = V[j * N + k]; + 2199 153121344 : for (k = 0; k < N; ++k) { + 2200 126788288 : uint8_t m = V[j * N + k]; 2201 : - 2202 126955328 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0])); - 2203 126955328 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0])); - 2204 126955328 : asm volatile ("movdqa %0,%%xmm4" : : "m" (pd[k*16])); - 2205 126955328 : asm volatile ("movdqa %xmm4,%xmm5"); - 2206 126955328 : asm volatile ("psrlw $4,%xmm5"); - 2207 126955328 : asm volatile ("pand %xmm7,%xmm4"); - 2208 126955328 : asm volatile ("pand %xmm7,%xmm5"); - 2209 126955328 : asm volatile ("pshufb %xmm4,%xmm2"); - 2210 126955328 : asm volatile ("pshufb %xmm5,%xmm3"); - 2211 126955328 : asm volatile ("pxor %xmm2,%xmm0"); - 2212 126955328 : asm volatile ("pxor %xmm3,%xmm1"); + 2202 126788288 : asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0])); + 2203 126788288 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0])); + 2204 126788288 : asm volatile ("movdqa %0,%%xmm4" : : "m" (pd[k*16])); + 2205 126788288 : asm volatile ("movdqa %xmm4,%xmm5"); + 2206 126788288 : asm volatile ("psrlw $4,%xmm5"); + 2207 126788288 : asm volatile ("pand %xmm7,%xmm4"); + 2208 126788288 : asm volatile ("pand %xmm7,%xmm5"); + 2209 126788288 : asm volatile ("pshufb %xmm4,%xmm2"); + 2210 126788288 : asm volatile ("pshufb %xmm5,%xmm3"); + 2211 126788288 : asm volatile ("pxor %xmm2,%xmm0"); + 2212 126788288 : asm volatile ("pxor %xmm3,%xmm1"); 2213 : } 2214 : - 2215 26332544 : asm volatile ("pxor %xmm1,%xmm0"); - 2216 26332544 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pa[j][i])); + 2215 26333056 : asm volatile ("pxor %xmm1,%xmm0"); + 2216 26333056 : asm volatile ("movdqa %%xmm0,%0" : "=m" (pa[j][i])); 2217 : } 2218 : } 2219 : 2220 : raid_sse_end(); - 2221 79298 : } + 2221 79451 : } 2222 : #endif 2223 : 2224 : #if defined(CONFIG_X86) && defined(CONFIG_AVX2) diff --git a/cov/raid/x86z.c.func-sort-c.html b/cov/raid/x86z.c.func-sort-c.html index cb2cfb47..65751eb9 100644 --- a/cov/raid/x86z.c.func-sort-c.html +++ b/cov/raid/x86z.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -61,7 +61,7 @@ raid_genz_sse2 - 1177 + 1178
diff --git a/cov/raid/x86z.c.func.html b/cov/raid/x86z.c.func.html index f498b4e6..3fb78598 100644 --- a/cov/raid/x86z.c.func.html +++ b/cov/raid/x86z.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -61,7 +61,7 @@ raid_genz_sse2 - 1177 + 1178
diff --git a/cov/raid/x86z.c.gcov.html b/cov/raid/x86z.c.gcov.html index 9039ba20..fb6c8977 100644 --- a/cov/raid/x86z.c.gcov.html +++ b/cov/raid/x86z.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 @@ -102,58 +102,58 @@ 40 : /* 41 : * GENz (triple parity with powers of 2^-1) SSE2 implementation 42 : */ - 43 1177 : void raid_genz_sse2(int nd, size_t size, void **vv) + 43 1178 : void raid_genz_sse2(int nd, size_t size, void **vv) 44 : { - 45 1177 : uint8_t **v = (uint8_t**)vv; + 45 1178 : uint8_t **v = (uint8_t**)vv; 46 : uint8_t *p; 47 : uint8_t *q; 48 : uint8_t *r; 49 : int d, l; 50 : size_t i; 51 : - 52 1177 : l = nd - 1; - 53 1177 : p = v[nd]; - 54 1177 : q = v[nd + 1]; - 55 1177 : r = v[nd + 2]; + 52 1178 : l = nd - 1; + 53 1178 : p = v[nd]; + 54 1178 : q = v[nd + 1]; + 55 1178 : r = v[nd + 2]; 56 : 57 : raid_sse_begin(); 58 : - 59 1177 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); - 60 1177 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); - 61 1177 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); + 59 1178 : asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); + 60 1178 : asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); + 61 1178 : asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); 62 : - 63 1394921 : for (i = 0; i < size; i += 16) { - 64 1393744 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); - 65 1393744 : asm volatile ("movdqa %xmm0,%xmm1"); - 66 1393744 : asm volatile ("movdqa %xmm0,%xmm2"); - 67 11220224 : for (d = l - 1; d >= 0; --d) { - 68 9826480 : asm volatile ("pxor %xmm4,%xmm4"); - 69 9826480 : asm volatile ("pcmpgtb %xmm1,%xmm4"); - 70 9826480 : asm volatile ("paddb %xmm1,%xmm1"); - 71 9826480 : asm volatile ("pand %xmm7,%xmm4"); - 72 9826480 : asm volatile ("pxor %xmm4,%xmm1"); + 63 1411306 : for (i = 0; i < size; i += 16) { + 64 1410128 : asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + 65 1410128 : asm volatile ("movdqa %xmm0,%xmm1"); + 66 1410128 : asm volatile ("movdqa %xmm0,%xmm2"); + 67 11351296 : for (d = l - 1; d >= 0; --d) { + 68 9941168 : asm volatile ("pxor %xmm4,%xmm4"); + 69 9941168 : asm volatile ("pcmpgtb %xmm1,%xmm4"); + 70 9941168 : asm volatile ("paddb %xmm1,%xmm1"); + 71 9941168 : asm volatile ("pand %xmm7,%xmm4"); + 72 9941168 : asm volatile ("pxor %xmm4,%xmm1"); 73 : - 74 9826480 : asm volatile ("movdqa %xmm2,%xmm4"); - 75 9826480 : asm volatile ("pxor %xmm5,%xmm5"); - 76 9826480 : asm volatile ("psllw $7,%xmm4"); - 77 9826480 : asm volatile ("psrlw $1,%xmm2"); - 78 9826480 : asm volatile ("pcmpgtb %xmm4,%xmm5"); - 79 9826480 : asm volatile ("pand %xmm6,%xmm2"); - 80 9826480 : asm volatile ("pand %xmm3,%xmm5"); - 81 9826480 : asm volatile ("pxor %xmm5,%xmm2"); + 74 9941168 : asm volatile ("movdqa %xmm2,%xmm4"); + 75 9941168 : asm volatile ("pxor %xmm5,%xmm5"); + 76 9941168 : asm volatile ("psllw $7,%xmm4"); + 77 9941168 : asm volatile ("psrlw $1,%xmm2"); + 78 9941168 : asm volatile ("pcmpgtb %xmm4,%xmm5"); + 79 9941168 : asm volatile ("pand %xmm6,%xmm2"); + 80 9941168 : asm volatile ("pand %xmm3,%xmm5"); + 81 9941168 : asm volatile ("pxor %xmm5,%xmm2"); 82 : - 83 9826480 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); - 84 9826480 : asm volatile ("pxor %xmm4,%xmm0"); - 85 9826480 : asm volatile ("pxor %xmm4,%xmm1"); - 86 9826480 : asm volatile ("pxor %xmm4,%xmm2"); + 83 9941168 : asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + 84 9941168 : asm volatile ("pxor %xmm4,%xmm0"); + 85 9941168 : asm volatile ("pxor %xmm4,%xmm1"); + 86 9941168 : asm volatile ("pxor %xmm4,%xmm2"); 87 : } - 88 1393744 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); - 89 1393744 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); - 90 1393744 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + 88 1410128 : asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + 89 1410128 : asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + 90 1410128 : asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); 91 : } 92 : 93 : raid_sse_end(); - 94 1177 : } + 94 1178 : } 95 : #endif 96 : 97 : #if defined(CONFIG_X86_64) && defined(CONFIG_SSE2) diff --git a/cov/tommyds/index-sort-f.html b/cov/tommyds/index-sort-f.html index 10ac305b..9a76fe79 100644 --- a/cov/tommyds/index-sort-f.html +++ b/cov/tommyds/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 82 diff --git a/cov/tommyds/index-sort-l.html b/cov/tommyds/index-sort-l.html index ac04e945..f9780f3b 100644 --- a/cov/tommyds/index-sort-l.html +++ b/cov/tommyds/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 82 diff --git a/cov/tommyds/index.html b/cov/tommyds/index.html index ecd00113..6fdcec83 100644 --- a/cov/tommyds/index.html +++ b/cov/tommyds/index.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 82 diff --git a/cov/tommyds/tommyarray.c.func-sort-c.html b/cov/tommyds/tommyarray.c.func-sort-c.html index eb0f50ec..79c98e30 100644 --- a/cov/tommyds/tommyarray.c.func-sort-c.html +++ b/cov/tommyds/tommyarray.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ tommy_array_grow - 2086 + 2134 tommy_array_init - 486 + 502 tommy_array_done - 463 + 479 tommy_array_memory_usage diff --git a/cov/tommyds/tommyarray.c.func.html b/cov/tommyds/tommyarray.c.func.html index ea4d5acb..e35a328c 100644 --- a/cov/tommyds/tommyarray.c.func.html +++ b/cov/tommyds/tommyarray.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ tommy_array_done - 463 + 479 tommy_array_grow - 2086 + 2134 tommy_array_init - 486 + 502 tommy_array_memory_usage diff --git a/cov/tommyds/tommyarray.c.gcov.html b/cov/tommyds/tommyarray.c.gcov.html index 1e28d9b1..86c90ec9 100644 --- a/cov/tommyds/tommyarray.c.gcov.html +++ b/cov/tommyds/tommyarray.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -92,38 +92,38 @@ 30 : /******************************************************************************/ 31 : /* array */ 32 : - 33 486 : void tommy_array_init(tommy_array* array) + 33 502 : void tommy_array_init(tommy_array* array) 34 : { 35 : tommy_uint_t i; 36 : 37 : /* fixed initial size */ - 38 486 : array->bucket_bit = TOMMY_ARRAY_BIT; - 39 486 : array->bucket_max = 1 << array->bucket_bit; - 40 486 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); - 41 2916 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i) - 42 2430 : array->bucket[i] = array->bucket[0]; + 38 502 : array->bucket_bit = TOMMY_ARRAY_BIT; + 39 502 : array->bucket_max = 1 << array->bucket_bit; + 40 502 : array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + 41 3012 : for (i = 1; i < TOMMY_ARRAY_BIT; ++i) + 42 2510 : array->bucket[i] = array->bucket[0]; 43 : - 44 486 : array->count = 0; - 45 486 : } + 44 502 : array->count = 0; + 45 502 : } 46 : - 47 463 : void tommy_array_done(tommy_array* array) + 47 479 : void tommy_array_done(tommy_array* array) 48 : { 49 : tommy_uint_t i; 50 : - 51 463 : tommy_free(array->bucket[0]); - 52 465 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) { + 51 479 : tommy_free(array->bucket[0]); + 52 481 : for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) { 53 2 : void** segment = array->bucket[i]; 54 2 : tommy_free(&segment[((tommy_ptrdiff_t)1) << i]); 55 : } - 56 463 : } + 56 479 : } 57 : - 58 2086 : void tommy_array_grow(tommy_array* array, tommy_count_t count) + 58 2134 : void tommy_array_grow(tommy_array* array, tommy_count_t count) 59 : { - 60 2086 : if (array->count >= count) - 61 2086 : return; - 62 2086 : array->count = count; + 60 2134 : if (array->count >= count) + 61 2134 : return; + 62 2134 : array->count = count; 63 : - 64 4174 : while (count > array->bucket_max) { + 64 4270 : while (count > array->bucket_max) { 65 : void** segment; 66 : 67 : /* allocate one more segment */ diff --git a/cov/tommyds/tommyarray.h.func-sort-c.html b/cov/tommyds/tommyarray.h.func-sort-c.html index 47f38cb2..eae84ff6 100644 --- a/cov/tommyds/tommyarray.h.func-sort-c.html +++ b/cov/tommyds/tommyarray.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -60,20 +60,20 @@ Hit count Sort by hit count - tommy_array_get - 15295882 + tommy_array_ref + 10133914 - tommy_array_ref - 15273609 + tommy_array_get + 10131780 tommy_array_size - 1519764 + 1541305 tommy_array_set - 2086 + 2134 tommy_array_insert diff --git a/cov/tommyds/tommyarray.h.func.html b/cov/tommyds/tommyarray.h.func.html index 094f71fc..8232c615 100644 --- a/cov/tommyds/tommyarray.h.func.html +++ b/cov/tommyds/tommyarray.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -61,7 +61,7 @@ tommy_array_get - 15295882 + 10131780 tommy_array_insert @@ -69,15 +69,15 @@ tommy_array_ref - 15273609 + 10133914 tommy_array_set - 2086 + 2134 tommy_array_size - 1519764 + 1541305
diff --git a/cov/tommyds/tommyarray.h.gcov.html b/cov/tommyds/tommyarray.h.gcov.html index 306db8c1..43dd4250 100644 --- a/cov/tommyds/tommyarray.h.gcov.html +++ b/cov/tommyds/tommyarray.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 15273609 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos) + 93 10133914 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos) 94 : { 95 : tommy_uint_t bsr; 96 : - 97 15273609 : assert(pos < array->count); + 97 10133914 : assert(pos < array->count); 98 : 99 : /* get the highest bit set, in case of all 0, return 0 */ - 100 15273609 : bsr = tommy_ilog2_u32(pos | 1); + 100 10133914 : bsr = tommy_ilog2_u32(pos | 1); 101 : - 102 15288941 : return &array->bucket[bsr][pos]; + 102 10133914 : return &array->bucket[bsr][pos]; 103 : } 104 : 105 : /** @@ -169,19 +169,19 @@ 107 : * You must be sure that space for this position is already 108 : * allocated calling tommy_array_grow(). 109 : */ - 110 2086 : tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element) + 110 2134 : tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element) 111 : { - 112 2086 : *tommy_array_ref(array, pos) = element; - 113 2086 : } + 112 2134 : *tommy_array_ref(array, pos) = element; + 113 2134 : } 114 : 115 : /** 116 : * Gets the element at the specified position. 117 : * You must be sure that space for this position is already 118 : * allocated calling tommy_array_grow(). 119 : */ - 120 15295882 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos) + 120 10131780 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos) 121 : { - 122 15295882 : return *tommy_array_ref(array, pos); + 122 10131780 : return *tommy_array_ref(array, pos); 123 : } 124 : 125 : /** @@ -199,9 +199,9 @@ 137 : /** 138 : * Gets the initialized size of the array. 139 : */ - 140 1519764 : tommy_inline tommy_count_t tommy_array_size(tommy_array* array) + 140 1541305 : tommy_inline tommy_count_t tommy_array_size(tommy_array* array) 141 : { - 142 1519764 : return array->count; + 142 1541305 : return array->count; 143 : } 144 : 145 : /** diff --git a/cov/tommyds/tommyarrayblk.c.func-sort-c.html b/cov/tommyds/tommyarrayblk.c.func-sort-c.html index b81595fd..f95f1c5f 100644 --- a/cov/tommyds/tommyarrayblk.c.func-sort-c.html +++ b/cov/tommyds/tommyarrayblk.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblk.c.func.html b/cov/tommyds/tommyarrayblk.c.func.html index 06bbfd2d..127cd197 100644 --- a/cov/tommyds/tommyarrayblk.c.func.html +++ b/cov/tommyds/tommyarrayblk.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblk.c.gcov.html b/cov/tommyds/tommyarrayblk.c.gcov.html index deef2d86..5de3ddaf 100644 --- a/cov/tommyds/tommyarrayblk.c.gcov.html +++ b/cov/tommyds/tommyarrayblk.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblk.h.func-sort-c.html b/cov/tommyds/tommyarrayblk.h.func-sort-c.html index 774c7f4c..c47df152 100644 --- a/cov/tommyds/tommyarrayblk.h.func-sort-c.html +++ b/cov/tommyds/tommyarrayblk.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblk.h.func.html b/cov/tommyds/tommyarrayblk.h.func.html index 0c988a32..c9e1a0b7 100644 --- a/cov/tommyds/tommyarrayblk.h.func.html +++ b/cov/tommyds/tommyarrayblk.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblk.h.gcov.html b/cov/tommyds/tommyarrayblk.h.gcov.html index dd4893ab..78cb8df9 100644 --- a/cov/tommyds/tommyarrayblk.h.gcov.html +++ b/cov/tommyds/tommyarrayblk.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 diff --git a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html index 9b15c5a4..a308945e 100644 --- a/cov/tommyds/tommyarrayblkof.c.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ tommy_arrayblkof_grow - 1609741 + 1640038 tommy_arrayblkof_init - 249 + 257 tommy_arrayblkof_done - 227 + 235 tommy_arrayblkof_memory_usage diff --git a/cov/tommyds/tommyarrayblkof.c.func.html b/cov/tommyds/tommyarrayblkof.c.func.html index 17140f12..1549efe9 100644 --- a/cov/tommyds/tommyarrayblkof.c.func.html +++ b/cov/tommyds/tommyarrayblkof.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -61,15 +61,15 @@ tommy_arrayblkof_done - 227 + 235 tommy_arrayblkof_grow - 1609741 + 1640038 tommy_arrayblkof_init - 249 + 257 tommy_arrayblkof_memory_usage diff --git a/cov/tommyds/tommyarrayblkof.c.gcov.html b/cov/tommyds/tommyarrayblkof.c.gcov.html index 4da680ca..414b307c 100644 --- a/cov/tommyds/tommyarrayblkof.c.gcov.html +++ b/cov/tommyds/tommyarrayblkof.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 4 @@ -92,48 +92,48 @@ 30 : /******************************************************************************/ 31 : /* array */ 32 : - 33 249 : void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) + 33 257 : void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) 34 : { - 35 249 : tommy_array_init(&array->block); + 35 257 : tommy_array_init(&array->block); 36 : - 37 249 : array->element_size = element_size; - 38 249 : array->count = 0; - 39 249 : } + 37 257 : array->element_size = element_size; + 38 257 : array->count = 0; + 39 257 : } 40 : - 41 227 : void tommy_arrayblkof_done(tommy_arrayblkof* array) + 41 235 : void tommy_arrayblkof_done(tommy_arrayblkof* array) 42 : { 43 : tommy_count_t i; 44 : - 45 723 : for (i = 0; i < tommy_array_size(&array->block); ++i) - 46 496 : tommy_free(tommy_array_get(&array->block, i)); + 45 743 : for (i = 0; i < tommy_array_size(&array->block); ++i) + 46 508 : tommy_free(tommy_array_get(&array->block, i)); 47 : - 48 227 : tommy_array_done(&array->block); - 49 227 : } + 48 235 : tommy_array_done(&array->block); + 49 235 : } 50 : - 51 1609741 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count) + 51 1640038 : void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count) 52 : { 53 : tommy_count_t block_max; 54 : tommy_count_t block_mac; 55 : - 56 1609741 : if (array->count >= count) - 57 1700701 : return; - 58 1518781 : array->count = count; + 56 1640038 : if (array->count >= count) + 57 1739774 : return; + 58 1540302 : array->count = count; 59 : - 60 1518781 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE; - 61 1518781 : block_mac = tommy_array_size(&array->block); + 60 1540302 : block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE; + 61 1540302 : block_mac = tommy_array_size(&array->block); 62 : - 63 1518781 : if (block_mac < block_max) { + 63 1540302 : if (block_mac < block_max) { 64 : /* grow the block array */ - 65 524 : tommy_array_grow(&array->block, block_max); + 65 537 : tommy_array_grow(&array->block, block_max); 66 : 67 : /* allocate new blocks */ - 68 1572 : while (block_mac < block_max) { - 69 524 : void** ptr = tommy_cast(void**, tommy_calloc(TOMMY_ARRAYBLKOF_SIZE, array->element_size)); + 68 1611 : while (block_mac < block_max) { + 69 537 : void** ptr = tommy_cast(void**, tommy_calloc(TOMMY_ARRAYBLKOF_SIZE, array->element_size)); 70 : 71 : /* set the new block */ - 72 524 : tommy_array_set(&array->block, block_mac, ptr); + 72 537 : tommy_array_set(&array->block, block_mac, ptr); 73 : - 74 524 : ++block_mac; + 74 537 : ++block_mac; 75 : } 76 : } 77 : } diff --git a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html index 5a904630..52261451 100644 --- a/cov/tommyds/tommyarrayblkof.h.func-sort-c.html +++ b/cov/tommyds/tommyarrayblkof.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_ref - 11688426 + 6481666 tommy_arrayblkof_size - 10571361 + 5104110
diff --git a/cov/tommyds/tommyarrayblkof.h.func.html b/cov/tommyds/tommyarrayblkof.h.func.html index aab7c7c9..75b07f3a 100644 --- a/cov/tommyds/tommyarrayblkof.h.func.html +++ b/cov/tommyds/tommyarrayblkof.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_arrayblkof_ref - 11688426 + 6481666 tommy_arrayblkof_size - 10571361 + 5104110
diff --git a/cov/tommyds/tommyarrayblkof.h.gcov.html b/cov/tommyds/tommyarrayblkof.h.gcov.html index 41d4c08a..a9b2c14e 100644 --- a/cov/tommyds/tommyarrayblkof.h.gcov.html +++ b/cov/tommyds/tommyarrayblkof.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 11688426 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos) + 89 6481666 : tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos) 90 : { 91 : unsigned char* base; 92 : - 93 11688426 : assert(pos < array->count); + 93 6481666 : assert(pos < array->count); 94 : - 95 11688426 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); + 95 6481666 : base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); 96 : - 97 11693987 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; + 97 6481666 : return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; 98 : } 99 : 100 : /** 101 : * Gets the initialized size of the array. 102 : */ - 103 10571361 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array) + 103 5104110 : tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array) 104 : { - 105 10571361 : return array->count; + 105 5104110 : return array->count; 106 : } 107 : 108 : /** diff --git a/cov/tommyds/tommychain.h.func-sort-c.html b/cov/tommyds/tommychain.h.func-sort-c.html index 9f911f5f..ddbb6bb4 100644 --- a/cov/tommyds/tommychain.h.func-sort-c.html +++ b/cov/tommyds/tommychain.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -61,23 +61,23 @@ tommy_chain_splice - 4073661 + 4261933 tommy_chain_merge_degenerated - 1153954 + 1203475 tommy_chain_concat - 1147870 + 1197191 tommy_chain_merge - 427121 + 446438 tommy_chain_mergesort - 1473 + 1558
diff --git a/cov/tommyds/tommychain.h.func.html b/cov/tommyds/tommychain.h.func.html index 5ac1a9e6..2298e9b8 100644 --- a/cov/tommyds/tommychain.h.func.html +++ b/cov/tommyds/tommychain.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -61,23 +61,23 @@ tommy_chain_concat - 1147870 + 1197191 tommy_chain_merge - 427121 + 446438 tommy_chain_merge_degenerated - 1153954 + 1203475 tommy_chain_mergesort - 1473 + 1558 tommy_chain_splice - 4073661 + 4261933
diff --git a/cov/tommyds/tommychain.h.gcov.html b/cov/tommyds/tommychain.h.gcov.html index 8ed60019..a9d47b12 100644 --- a/cov/tommyds/tommychain.h.gcov.html +++ b/cov/tommyds/tommychain.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 5 @@ -119,83 +119,83 @@ 57 : /** 58 : * Splices a chain in the middle of another chain. 59 : */ - 60 4073661 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) + 60 4261933 : tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) 61 : { 62 : /* set the prev list */ - 63 4073661 : first_after->prev = second_tail; - 64 4073661 : second_head->prev = first_before; + 63 4261933 : first_after->prev = second_tail; + 64 4261933 : second_head->prev = first_before; 65 : 66 : /* set the next list */ - 67 4073661 : first_before->next = second_head; - 68 4073661 : second_tail->next = first_after; - 69 4073661 : } + 67 4261933 : first_before->next = second_head; + 68 4261933 : second_tail->next = first_after; + 69 4261933 : } 70 : 71 : /** 72 : * Concats two chains. 73 : */ - 74 1147870 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) + 74 1197191 : tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) 75 : { 76 : /* set the prev list */ - 77 1147870 : second_head->prev = first_tail; + 77 1197191 : second_head->prev = first_tail; 78 : 79 : /* set the next list */ - 80 1147870 : first_tail->next = second_head; - 81 1147870 : } + 80 1197191 : first_tail->next = second_head; + 81 1197191 : } 82 : 83 : /** 84 : * Merges two chains. 85 : */ - 86 427121 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 86 446438 : tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 87 : { - 88 427121 : tommy_node* first_i = first->head; - 89 427121 : tommy_node* second_i = second->head; + 88 446438 : tommy_node* first_i = first->head; + 89 446438 : tommy_node* second_i = second->head; 90 : 91 : /* merge */ 92 : while (1) { - 93 8866117 : if (cmp(first_i->data, second_i->data) > 0) { - 94 4284467 : tommy_node* next = second_i->next; - 95 4284467 : if (first_i == first->head) { - 96 210806 : tommy_chain_concat(second_i, first_i); - 97 210806 : first->head = second_i; + 93 9274986 : if (cmp(first_i->data, second_i->data) > 0) { + 94 4482275 : tommy_node* next = second_i->next; + 95 4482275 : if (first_i == first->head) { + 96 220342 : tommy_chain_concat(second_i, first_i); + 97 220342 : first->head = second_i; 98 : } else { - 99 4073661 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); + 99 4261933 : tommy_chain_splice(first_i->prev, first_i, second_i, second_i); 100 : } - 101 4284467 : if (second_i == second->tail) - 102 216890 : break; - 103 4067577 : second_i = next; + 101 4482275 : if (second_i == second->tail) + 102 226626 : break; + 103 4255649 : second_i = next; 104 : } else { - 105 4581650 : if (first_i == first->tail) { - 106 210231 : tommy_chain_concat(first_i, second_i); - 107 210231 : first->tail = second->tail; - 108 210231 : break; + 105 4792711 : if (first_i == first->tail) { + 106 219812 : tommy_chain_concat(first_i, second_i); + 107 219812 : first->tail = second->tail; + 108 219812 : break; 109 : } - 110 4371419 : first_i = first_i->next; + 110 4572899 : first_i = first_i->next; 111 : } - 112 8438996 : } - 113 427121 : } + 112 8828548 : } + 113 446438 : } 114 : 115 : /** 116 : * Merges two chains managing special degenerated cases. 117 : * It's funtionally equivalent at tommy_chain_merge() but faster with already ordered chains. 118 : */ - 119 1153954 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) + 119 1203475 : tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) 120 : { 121 : /* identify the condition first <= second */ - 122 1153954 : if (cmp(first->tail->data, second->head->data) <= 0) { - 123 422991 : tommy_chain_concat(first->tail, second->head); - 124 422991 : first->tail = second->tail; - 125 422991 : return; + 122 1203475 : if (cmp(first->tail->data, second->head->data) <= 0) { + 123 439434 : tommy_chain_concat(first->tail, second->head); + 124 439434 : first->tail = second->tail; + 125 439434 : return; 126 : } 127 : 128 : /* identify the condition second < first */ 129 : /* here we must be strict on comparison to keep the sort stable */ - 130 730963 : if (cmp(second->tail->data, first->head->data) < 0) { - 131 303842 : tommy_chain_concat(second->tail, first->head); - 132 303842 : first->head = second->head; - 133 303842 : return; + 130 764041 : if (cmp(second->tail->data, first->head->data) < 0) { + 131 317603 : tommy_chain_concat(second->tail, first->head); + 132 317603 : first->head = second->head; + 133 317603 : return; 134 : } 135 : - 136 427121 : tommy_chain_merge(first, second, cmp); + 136 446438 : tommy_chain_merge(first, second, cmp); 137 : } 138 : 139 : /** @@ -215,7 +215,7 @@ 153 : * Linux Kernel lib/list_sort.c 154 : * http://lxr.linux.no/#linux+v2.6.36/lib/list_sort.c 155 : */ - 156 1473 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) + 156 1558 : tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) 157 : { 158 : /* 159 : * Bit buckets of chains. @@ -230,57 +230,57 @@ 168 : * It's used to know which bucket is empty of full. 169 : */ 170 : tommy_count_t counter; - 171 1473 : tommy_node* node = chain->head; - 172 1473 : tommy_node* tail = chain->tail; + 171 1558 : tommy_node* node = chain->head; + 172 1558 : tommy_node* tail = chain->tail; 173 : tommy_count_t mask; 174 : tommy_count_t i; 175 : - 176 1473 : counter = 0; + 176 1558 : counter = 0; 177 : while (1) { 178 : tommy_node* next; 179 : tommy_chain* last; 180 : 181 : /* carry bit to add */ - 182 1155427 : last = &bit[TOMMY_CHAIN_BIT_MAX]; - 183 1155427 : bit[TOMMY_CHAIN_BIT_MAX].head = node; - 184 1155427 : bit[TOMMY_CHAIN_BIT_MAX].tail = node; - 185 1155427 : next = node->next; + 182 1205033 : last = &bit[TOMMY_CHAIN_BIT_MAX]; + 183 1205033 : bit[TOMMY_CHAIN_BIT_MAX].head = node; + 184 1205033 : bit[TOMMY_CHAIN_BIT_MAX].tail = node; + 185 1205033 : next = node->next; 186 : 187 : /* add the bit, propagating the carry */ - 188 1155427 : i = 0; - 189 1155427 : mask = counter; - 190 3459506 : while ((mask & 1) != 0) { - 191 1148652 : tommy_chain_merge_degenerated(&bit[i], last, cmp); - 192 1148652 : mask >>= 1; - 193 1148652 : last = &bit[i]; - 194 1148652 : ++i; + 188 1205033 : i = 0; + 189 1205033 : mask = counter; + 190 3607881 : while ((mask & 1) != 0) { + 191 1197815 : tommy_chain_merge_degenerated(&bit[i], last, cmp); + 192 1197815 : mask >>= 1; + 193 1197815 : last = &bit[i]; + 194 1197815 : ++i; 195 : } 196 : 197 : /* copy the carry in the first empty bit */ - 198 1155427 : bit[i] = *last; + 198 1205033 : bit[i] = *last; 199 : 200 : /* add the carry in the counter */ - 201 1155427 : ++counter; + 201 1205033 : ++counter; 202 : - 203 1155427 : if (node == tail) - 204 1473 : break; - 205 1153954 : node = next; - 206 1153954 : } + 203 1205033 : if (node == tail) + 204 1558 : break; + 205 1203475 : node = next; + 206 1203475 : } 207 : 208 : /* merge the buckets */ - 209 1473 : i = tommy_ctz_u32(counter); - 210 1473 : mask = counter >> i; - 211 10792 : while (mask != 1) { - 212 7846 : mask >>= 1; - 213 7846 : if (mask & 1) - 214 5302 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); + 209 1558 : i = tommy_ctz_u32(counter); + 210 1558 : mask = counter >> i; + 211 11511 : while (mask != 1) { + 212 8395 : mask >>= 1; + 213 8395 : if (mask & 1) + 214 5660 : tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); 215 : else - 216 2544 : bit[i + 1] = bit[i]; - 217 7846 : ++i; + 216 2735 : bit[i + 1] = bit[i]; + 217 8395 : ++i; 218 : } 219 : - 220 1473 : *chain = bit[i]; - 221 1473 : } + 220 1558 : *chain = bit[i]; + 221 1558 : } 222 : 223 : #endif 224 : diff --git a/cov/tommyds/tommyhash.c.func-sort-c.html b/cov/tommyds/tommyhash.c.func-sort-c.html index 9466aeab..7a44421b 100644 --- a/cov/tommyds/tommyhash.c.func-sort-c.html +++ b/cov/tommyds/tommyhash.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -61,11 +61,11 @@ tommy_le_uint32_read - 11236438 + 11379991 tommy_hash_u32 - 3932841 + 3984897 tommy_hash_u64 diff --git a/cov/tommyds/tommyhash.c.func.html b/cov/tommyds/tommyhash.c.func.html index 311a42c9..6e925c33 100644 --- a/cov/tommyds/tommyhash.c.func.html +++ b/cov/tommyds/tommyhash.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -61,7 +61,7 @@ tommy_hash_u32 - 3932841 + 3984897 tommy_hash_u64 @@ -69,7 +69,7 @@ tommy_le_uint32_read - 11236438 + 11379991
diff --git a/cov/tommyds/tommyhash.c.gcov.html b/cov/tommyds/tommyhash.c.gcov.html index 30b59be8..e0683e1f 100644 --- a/cov/tommyds/tommyhash.c.gcov.html +++ b/cov/tommyds/tommyhash.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -92,12 +92,12 @@ 30 : /******************************************************************************/ 31 : /* hash */ 32 : - 33 11236438 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) + 33 11379991 : tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) 34 : { 35 : /* allow unaligned read on Intel x86 and x86_64 platforms */ 36 : #if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__x86_64__) || defined(_M_X64) 37 : /* defines from http://predef.sourceforge.net/ */ - 38 11236438 : return *(const tommy_uint32_t*)ptr; + 38 11379991 : return *(const tommy_uint32_t*)ptr; 39 : #else 40 : const unsigned char* ptr8 = tommy_cast(const unsigned char*, ptr); 41 : return ptr8[0] + ((tommy_uint32_t)ptr8[1] << 8) + ((tommy_uint32_t)ptr8[2] << 16) + ((tommy_uint32_t)ptr8[3] << 24); @@ -128,53 +128,53 @@ 66 : c ^= b; c -= tommy_rot(b, 24); \ 67 : } while (0) 68 : - 69 3932841 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) + 69 3984897 : tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) 70 : { - 71 3932841 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); + 71 3984897 : const unsigned char* key = tommy_cast(const unsigned char*, void_key); 72 : tommy_uint32_t a, b, c; 73 : - 74 3932841 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; + 74 3984897 : a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; 75 : - 76 9922648 : while (key_len > 12) { - 77 2056966 : a += tommy_le_uint32_read(key + 0); - 78 2056966 : b += tommy_le_uint32_read(key + 4); - 79 2056966 : c += tommy_le_uint32_read(key + 8); + 76 10052462 : while (key_len > 12) { + 77 2082668 : a += tommy_le_uint32_read(key + 0); + 78 2082668 : b += tommy_le_uint32_read(key + 4); + 79 2082668 : c += tommy_le_uint32_read(key + 8); 80 : - 81 2056966 : tommy_mix(a, b, c); + 81 2082668 : tommy_mix(a, b, c); 82 : - 83 2056966 : key_len -= 12; - 84 2056966 : key += 12; + 83 2082668 : key_len -= 12; + 84 2082668 : key += 12; 85 : } 86 : - 87 3932841 : switch (key_len) { + 87 3984897 : switch (key_len) { 88 : case 0 : 89 1 : return c; /* used only when called with a zero length */ 90 : case 12 : - 91 201770 : c += tommy_le_uint32_read(key + 8); - 92 201770 : b += tommy_le_uint32_read(key + 4); - 93 201770 : a += tommy_le_uint32_read(key + 0); - 94 201770 : break; - 95 210915 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; - 96 620733 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; - 97 1027724 : case 9 : c += key[8]; + 91 204266 : c += tommy_le_uint32_read(key + 8); + 92 204266 : b += tommy_le_uint32_read(key + 4); + 93 204266 : a += tommy_le_uint32_read(key + 0); + 94 204266 : break; + 95 213540 : case 11 : c += ((tommy_uint32_t)key[10]) << 16; + 96 628617 : case 10 : c += ((tommy_uint32_t)key[9]) << 8; + 97 1040835 : case 9 : c += key[8]; 98 : case 8 : - 99 1425951 : b += tommy_le_uint32_read(key + 4); - 100 1425951 : a += tommy_le_uint32_read(key + 0); - 101 1425951 : break; - 102 400019 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; - 103 787136 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; - 104 1189288 : case 5 : b += key[4]; + 99 1444224 : b += tommy_le_uint32_read(key + 4); + 100 1444224 : a += tommy_le_uint32_read(key + 0); + 101 1444224 : break; + 102 405262 : case 7 : b += ((tommy_uint32_t)key[6]) << 16; + 103 797887 : case 6 : b += ((tommy_uint32_t)key[5]) << 8; + 104 1206407 : case 5 : b += key[4]; 105 : case 4 : - 106 1608279 : a += tommy_le_uint32_read(key + 0); - 107 1608279 : break; - 108 291874 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; - 109 493291 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; - 110 696840 : case 1 : a += key[0]; + 106 1630692 : a += tommy_le_uint32_read(key + 0); + 107 1630692 : break; + 108 295633 : case 3 : a += ((tommy_uint32_t)key[2]) << 16; + 109 499608 : case 2 : a += ((tommy_uint32_t)key[1]) << 8; + 110 705714 : case 1 : a += key[0]; 111 : } 112 : - 113 3932840 : tommy_final(a, b, c); + 113 3984896 : tommy_final(a, b, c); 114 : - 115 3932840 : return c; + 115 3984896 : return c; 116 : } 117 : 118 19 : tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) diff --git a/cov/tommyds/tommyhash.h.func-sort-c.html b/cov/tommyds/tommyhash.h.func-sort-c.html index bd9b8354..45a1fc87 100644 --- a/cov/tommyds/tommyhash.h.func-sort-c.html +++ b/cov/tommyds/tommyhash.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u32 - 18417414 + 18594807 tommy_inthash_u64 - 4822298 + 4924816
diff --git a/cov/tommyds/tommyhash.h.func.html b/cov/tommyds/tommyhash.h.func.html index d1761086..8e649746 100644 --- a/cov/tommyds/tommyhash.h.func.html +++ b/cov/tommyds/tommyhash.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_inthash_u32 - 18417414 + 18594807 tommy_inthash_u64 - 4822298 + 4924816
diff --git a/cov/tommyds/tommyhash.h.gcov.html b/cov/tommyds/tommyhash.h.gcov.html index 33130e85..ef81f711 100644 --- a/cov/tommyds/tommyhash.h.gcov.html +++ b/cov/tommyds/tommyhash.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -139,17 +139,17 @@ 77 : * Implementation of the Robert Jenkins "4-byte Integer Hashing", 78 : * from http://burtleburtle.net/bob/hash/integer.html 79 : */ - 80 18417414 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) + 80 18594807 : tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) 81 : { - 82 18417414 : key -= key << 6; - 83 18417414 : key ^= key >> 17; - 84 18417414 : key -= key << 9; - 85 18417414 : key ^= key << 4; - 86 18417414 : key -= key << 3; - 87 18417414 : key ^= key << 10; - 88 18417414 : key ^= key >> 15; + 82 18594807 : key -= key << 6; + 83 18594807 : key ^= key >> 17; + 84 18594807 : key -= key << 9; + 85 18594807 : key ^= key << 4; + 86 18594807 : key -= key << 3; + 87 18594807 : key ^= key << 10; + 88 18594807 : key ^= key >> 15; 89 : - 90 18417414 : return key; + 90 18594807 : return key; 91 : } 92 : 93 : /** @@ -157,17 +157,17 @@ 95 : * Implementation of the Thomas Wang "Integer Hash Function", 96 : * from http://www.cris.com/~Ttwang/tech/inthash.htm 97 : */ - 98 4822298 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) + 98 4924816 : tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) 99 : { - 100 4822298 : key = ~key + (key << 21); - 101 4822298 : key = key ^ (key >> 24); - 102 4822298 : key = key + (key << 3) + (key << 8); - 103 4822298 : key = key ^ (key >> 14); - 104 4822298 : key = key + (key << 2) + (key << 4); - 105 4822298 : key = key ^ (key >> 28); - 106 4822298 : key = key + (key << 31); + 100 4924816 : key = ~key + (key << 21); + 101 4924816 : key = key ^ (key >> 24); + 102 4924816 : key = key + (key << 3) + (key << 8); + 103 4924816 : key = key ^ (key >> 14); + 104 4924816 : key = key + (key << 2) + (key << 4); + 105 4924816 : key = key ^ (key >> 28); + 106 4924816 : key = key + (key << 31); 107 : - 108 4822298 : return key; + 108 4924816 : return key; 109 : } 110 : 111 : #endif diff --git a/cov/tommyds/tommyhashdyn.c.func-sort-c.html b/cov/tommyds/tommyhashdyn.c.func-sort-c.html index 13e53317..cd0ec00e 100644 --- a/cov/tommyds/tommyhashdyn.c.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -61,31 +61,31 @@ hashdyn_grow_step - 12860296 + 13012162 tommy_hashdyn_insert - 12860296 + 13012162 hashdyn_shrink_step - 284348 + 299207 tommy_hashdyn_remove_existing - 284220 + 299079 tommy_hashdyn_resize - 39860 + 40383 tommy_hashdyn_init - 8133 + 8397 tommy_hashdyn_done - 7437 + 7701 tommy_hashdyn_remove @@ -93,7 +93,7 @@ tommy_hashdyn_foreach - 230 + 238 tommy_hashdyn_foreach_arg diff --git a/cov/tommyds/tommyhashdyn.c.func.html b/cov/tommyds/tommyhashdyn.c.func.html index 190f8d85..d3cc0bca 100644 --- a/cov/tommyds/tommyhashdyn.c.func.html +++ b/cov/tommyds/tommyhashdyn.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -61,19 +61,19 @@ hashdyn_grow_step - 12860296 + 13012162 hashdyn_shrink_step - 284348 + 299207 tommy_hashdyn_done - 7437 + 7701 tommy_hashdyn_foreach - 230 + 238 tommy_hashdyn_foreach_arg @@ -81,11 +81,11 @@ tommy_hashdyn_init - 8133 + 8397 tommy_hashdyn_insert - 12860296 + 13012162 tommy_hashdyn_memory_usage @@ -97,11 +97,11 @@ tommy_hashdyn_remove_existing - 284220 + 299079 tommy_hashdyn_resize - 39860 + 40383
diff --git a/cov/tommyds/tommyhashdyn.c.gcov.html b/cov/tommyds/tommyhashdyn.c.gcov.html index b140fbee..6e43758a 100644 --- a/cov/tommyds/tommyhashdyn.c.gcov.html +++ b/cov/tommyds/tommyhashdyn.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 11 @@ -93,26 +93,26 @@ 31 : /******************************************************************************/ 32 : /* hashdyn */ 33 : - 34 8133 : void tommy_hashdyn_init(tommy_hashdyn* hashdyn) + 34 8397 : void tommy_hashdyn_init(tommy_hashdyn* hashdyn) 35 : { 36 : /* fixed initial size */ - 37 8133 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; - 38 8133 : hashdyn->bucket_max = 1 << hashdyn->bucket_bit; - 39 8133 : hashdyn->bucket_mask = hashdyn->bucket_max - 1; - 40 8133 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); + 37 8397 : hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; + 38 8397 : hashdyn->bucket_max = 1 << hashdyn->bucket_bit; + 39 8397 : hashdyn->bucket_mask = hashdyn->bucket_max - 1; + 40 8397 : hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); 41 : - 42 8133 : hashdyn->count = 0; - 43 8133 : } + 42 8397 : hashdyn->count = 0; + 43 8397 : } 44 : - 45 7437 : void tommy_hashdyn_done(tommy_hashdyn* hashdyn) + 45 7701 : void tommy_hashdyn_done(tommy_hashdyn* hashdyn) 46 : { - 47 7437 : tommy_free(hashdyn->bucket); - 48 7437 : } + 47 7701 : tommy_free(hashdyn->bucket); + 48 7701 : } 49 : 50 : /** 51 : * Resize the bucket vector. 52 : */ - 53 39860 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit) + 53 40383 : static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit) 54 : { 55 : tommy_count_t bucket_bit; 56 : tommy_count_t bucket_max; @@ -120,38 +120,38 @@ 58 : tommy_count_t new_bucket_mask; 59 : tommy_hashdyn_node** new_bucket; 60 : - 61 39860 : bucket_bit = hashdyn->bucket_bit; - 62 39860 : bucket_max = hashdyn->bucket_max; + 61 40383 : bucket_bit = hashdyn->bucket_bit; + 62 40383 : bucket_max = hashdyn->bucket_max; 63 : - 64 39860 : new_bucket_max = 1 << new_bucket_bit; - 65 39860 : new_bucket_mask = new_bucket_max - 1; + 64 40383 : new_bucket_max = 1 << new_bucket_bit; + 65 40383 : new_bucket_mask = new_bucket_max - 1; 66 : 67 : /* allocate the new vector using malloc() and not calloc() */ 68 : /* because data is fully initialized in the update process */ - 69 39860 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); + 69 40383 : new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); 70 : 71 : /* reinsert all the elements */ - 72 39860 : if (new_bucket_bit > bucket_bit) { + 72 40383 : if (new_bucket_bit > bucket_bit) { 73 : tommy_count_t i; 74 : 75 : /* grow */ - 76 31390627 : for (i = 0; i < bucket_max; ++i) { + 76 31674382 : for (i = 0; i < bucket_max; ++i) { 77 : tommy_hashdyn_node* j; 78 : 79 : /* setup the new two buckets */ - 80 31350816 : new_bucket[i] = 0; - 81 31350816 : new_bucket[i + bucket_max] = 0; + 80 31634048 : new_bucket[i] = 0; + 81 31634048 : new_bucket[i + bucket_max] = 0; 82 : 83 : /* reinsert the bucket */ - 84 31350816 : j = hashdyn->bucket[i]; - 85 78377040 : while (j) { - 86 15675408 : tommy_hashdyn_node* j_next = j->next; - 87 15675408 : tommy_count_t pos = j->key & new_bucket_mask; - 88 15675408 : if (new_bucket[pos]) - 89 1860861 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); + 84 31634048 : j = hashdyn->bucket[i]; + 85 79085120 : while (j) { + 86 15817024 : tommy_hashdyn_node* j_next = j->next; + 87 15817024 : tommy_count_t pos = j->key & new_bucket_mask; + 88 15817024 : if (new_bucket[pos]) + 89 1907725 : tommy_list_insert_tail_not_empty(new_bucket[pos], j); 90 : else - 91 13814547 : tommy_list_insert_first(&new_bucket[pos], j); - 92 15675408 : j = j_next; + 91 13909299 : tommy_list_insert_first(&new_bucket[pos], j); + 92 15817024 : j = j_next; 93 : } 94 : } 95 : } else { @@ -167,59 +167,59 @@ 105 : } 106 : } 107 : - 108 39860 : tommy_free(hashdyn->bucket); + 108 40383 : tommy_free(hashdyn->bucket); 109 : 110 : /* setup */ - 111 39860 : hashdyn->bucket_bit = new_bucket_bit; - 112 39860 : hashdyn->bucket_max = new_bucket_max; - 113 39860 : hashdyn->bucket_mask = new_bucket_mask; - 114 39860 : hashdyn->bucket = new_bucket; - 115 39860 : } + 111 40383 : hashdyn->bucket_bit = new_bucket_bit; + 112 40383 : hashdyn->bucket_max = new_bucket_max; + 113 40383 : hashdyn->bucket_mask = new_bucket_mask; + 114 40383 : hashdyn->bucket = new_bucket; + 115 40383 : } 116 : 117 : /** 118 : * Grow. 119 : */ - 120 12860296 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) + 120 13012162 : tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) 121 : { 122 : /* grow if more than 50% full */ - 123 12860296 : if (hashdyn->count >= hashdyn->bucket_max / 2) - 124 39811 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); - 125 12860296 : } + 123 13012162 : if (hashdyn->count >= hashdyn->bucket_max / 2) + 124 40334 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); + 125 13012162 : } 126 : 127 : /** 128 : * Shrink. 129 : */ - 130 284348 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) + 130 299207 : tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) 131 : { 132 : /* shrink if less than 12.5% full */ - 133 284348 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) + 133 299207 : if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) 134 49 : tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1); - 135 284348 : } + 135 299207 : } 136 : - 137 12860296 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) + 137 13012162 : void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) 138 : { - 139 12860296 : tommy_count_t pos = hash & hashdyn->bucket_mask; + 139 13012162 : tommy_count_t pos = hash & hashdyn->bucket_mask; 140 : - 141 12860296 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); + 141 13012162 : tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); 142 : - 143 12860296 : node->key = hash; + 143 13012162 : node->key = hash; 144 : - 145 12860296 : ++hashdyn->count; + 145 13012162 : ++hashdyn->count; 146 : - 147 12860296 : hashdyn_grow_step(hashdyn); - 148 12860296 : } + 147 13012162 : hashdyn_grow_step(hashdyn); + 148 13012162 : } 149 : - 150 284220 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) + 150 299079 : void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) 151 : { - 152 284220 : tommy_count_t pos = node->key & hashdyn->bucket_mask; + 152 299079 : tommy_count_t pos = node->key & hashdyn->bucket_mask; 153 : - 154 284220 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); + 154 299079 : tommy_list_remove_existing(&hashdyn->bucket[pos], node); 155 : - 156 284220 : --hashdyn->count; + 156 299079 : --hashdyn->count; 157 : - 158 284220 : hashdyn_shrink_step(hashdyn); + 158 299079 : hashdyn_shrink_step(hashdyn); 159 : - 160 284220 : return node->data; + 160 299079 : return node->data; 161 : } 162 : 163 256 : void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) @@ -244,22 +244,22 @@ 182 128 : return 0; 183 : } 184 : - 185 230 : void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) + 185 238 : void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) 186 : { - 187 230 : tommy_count_t bucket_max = hashdyn->bucket_max; - 188 230 : tommy_hashdyn_node** bucket = hashdyn->bucket; + 187 238 : tommy_count_t bucket_max = hashdyn->bucket_max; + 188 238 : tommy_hashdyn_node** bucket = hashdyn->bucket; 189 : tommy_count_t pos; 190 : - 191 5812246 : for (pos = 0; pos < bucket_max; ++pos) { - 192 5812016 : tommy_hashdyn_node* node = bucket[pos]; + 191 5812382 : for (pos = 0; pos < bucket_max; ++pos) { + 192 5812144 : tommy_hashdyn_node* node = bucket[pos]; 193 : - 194 13483818 : while (node) { - 195 1859786 : void* data = node->data; - 196 1859786 : node = node->next; - 197 1859786 : func(data); + 194 13484803 : while (node) { + 195 1860515 : void* data = node->data; + 196 1860515 : node = node->next; + 197 1860515 : func(data); 198 : } 199 : } - 200 230 : } + 200 238 : } 201 : 202 1 : void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) 203 : { diff --git a/cov/tommyds/tommyhashdyn.h.func-sort-c.html b/cov/tommyds/tommyhashdyn.h.func-sort-c.html index 524259cb..58911c95 100644 --- a/cov/tommyds/tommyhashdyn.h.func-sort-c.html +++ b/cov/tommyds/tommyhashdyn.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -61,11 +61,11 @@ tommy_hashdyn_bucket - 3070554 + 3059036 tommy_hashdyn_search - 3070554 + 3059036 tommy_hashdyn_count diff --git a/cov/tommyds/tommyhashdyn.h.func.html b/cov/tommyds/tommyhashdyn.h.func.html index 204c62c7..a87b29ec 100644 --- a/cov/tommyds/tommyhashdyn.h.func.html +++ b/cov/tommyds/tommyhashdyn.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -61,7 +61,7 @@ tommy_hashdyn_bucket - 3070554 + 3059036 tommy_hashdyn_count @@ -69,7 +69,7 @@ tommy_hashdyn_search - 3070554 + 3059036
diff --git a/cov/tommyds/tommyhashdyn.h.gcov.html b/cov/tommyds/tommyhashdyn.h.gcov.html index 448c8108..0751c333 100644 --- a/cov/tommyds/tommyhashdyn.h.gcov.html +++ b/cov/tommyds/tommyhashdyn.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 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 3070554 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) + 208 3059036 : tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) 209 : { - 210 3070554 : return hashdyn->bucket[hash & hashdyn->bucket_mask]; + 210 3059036 : return hashdyn->bucket[hash & hashdyn->bucket_mask]; 211 : } 212 : 213 : /** @@ -282,17 +282,17 @@ 220 : * \param hash Hash of the element to find. 221 : * \return The first element found, or 0 if none. 222 : */ - 223 3070554 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) + 223 3059036 : tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) 224 : { - 225 3070554 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); + 225 3059036 : tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); 226 : - 227 6829396 : while (i) { + 227 6783670 : while (i) { 228 : /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ - 229 1728517 : if (i->key == hash && cmp(cmp_arg, i->data) == 0) - 230 1040229 : return i->data; - 231 688288 : i = i->next; + 229 1775604 : if (i->key == hash && cmp(cmp_arg, i->data) == 0) + 230 1110006 : return i->data; + 231 665598 : i = i->next; 232 : } - 233 2030325 : return 0; + 233 1949030 : return 0; 234 : } 235 : 236 : /** diff --git a/cov/tommyds/tommylist.c.func-sort-c.html b/cov/tommyds/tommylist.c.func-sort-c.html index 50240eef..b292b5c8 100644 --- a/cov/tommyds/tommylist.c.func-sort-c.html +++ b/cov/tommyds/tommylist.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -65,11 +65,11 @@ tommy_list_sort - 2129 + 2276 tommy_list_set - 1473 + 1558
diff --git a/cov/tommyds/tommylist.c.func.html b/cov/tommyds/tommylist.c.func.html index 4a3655e5..f3b2b5cb 100644 --- a/cov/tommyds/tommylist.c.func.html +++ b/cov/tommyds/tommylist.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -65,11 +65,11 @@ tommy_list_set - 1473 + 1558 tommy_list_sort - 2129 + 2276
diff --git a/cov/tommyds/tommylist.c.gcov.html b/cov/tommyds/tommylist.c.gcov.html index a3fd03cb..200bf008 100644 --- a/cov/tommyds/tommylist.c.gcov.html +++ b/cov/tommyds/tommylist.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 3 @@ -97,53 +97,53 @@ 35 : tommy_node* second_head; 36 : 37 63152 : if (tommy_list_empty(second)) - 38 55942 : return; + 38 55862 : return; 39 : - 40 7210 : if (tommy_list_empty(first)) { - 41 6347 : *first = *second; - 42 6347 : return; + 40 7290 : if (tommy_list_empty(first)) { + 41 6456 : *first = *second; + 42 6456 : return; 43 : } 44 : - 45 863 : first_head = tommy_list_head(first); - 46 863 : second_head = tommy_list_head(second); - 47 863 : first_tail = tommy_list_tail(first); + 45 834 : first_head = tommy_list_head(first); + 46 834 : second_head = tommy_list_head(second); + 47 834 : first_tail = tommy_list_tail(first); 48 : 49 : /* set the "circular" prev list */ - 50 863 : first_head->prev = second_head->prev; - 51 863 : second_head->prev = first_tail; + 50 834 : first_head->prev = second_head->prev; + 51 834 : second_head->prev = first_tail; 52 : 53 : /* set the "0 terminated" next list */ - 54 863 : first_tail->next = second_head; + 54 834 : first_tail->next = second_head; 55 : } 56 : 57 : /** \internal 58 : * Setup a list. 59 : */ - 60 1473 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail) + 60 1558 : tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail) 61 : { - 62 1473 : head->prev = tail; - 63 1473 : tail->next = 0; - 64 1473 : *list = head; - 65 1473 : } + 62 1558 : head->prev = tail; + 63 1558 : tail->next = 0; + 64 1558 : *list = head; + 65 1558 : } 66 : - 67 2129 : void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) + 67 2276 : void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) 68 : { 69 : tommy_chain chain; 70 : tommy_node* head; 71 : - 72 2129 : if (tommy_list_empty(list)) - 73 2785 : return; + 72 2276 : if (tommy_list_empty(list)) + 73 2994 : return; 74 : - 75 1473 : head = tommy_list_head(list); + 75 1558 : head = tommy_list_head(list); 76 : 77 : /* create a chain from the list */ - 78 1473 : chain.head = head; - 79 1473 : chain.tail = head->prev; + 78 1558 : chain.head = head; + 79 1558 : chain.tail = head->prev; 80 : - 81 1473 : tommy_chain_mergesort(&chain, cmp); + 81 1558 : tommy_chain_mergesort(&chain, cmp); 82 : 83 : /* restore the list */ - 84 1473 : tommy_list_set(list, chain.head, chain.tail); + 84 1558 : tommy_list_set(list, chain.head, chain.tail); 85 : } 86 : diff --git a/cov/tommyds/tommylist.h.func-sort-c.html b/cov/tommyds/tommylist.h.func-sort-c.html index 9c8d2d57..5d6d527a 100644 --- a/cov/tommyds/tommylist.h.func-sort-c.html +++ b/cov/tommyds/tommylist.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -61,43 +61,43 @@ tommy_list_head - 24488786 + 24857398 tommy_list_insert_first - 22741744 + 22927997 tommy_list_insert_tail - 17767092 + 18022355 tommy_list_insert_tail_not_empty - 10700756 + 10911382 tommy_list_remove_existing - 341445 + 359148 tommy_list_empty - 74175 + 74540 tommy_list_init - 10804 + 11303 tommy_list_foreach - 7071 + 7327 tommy_list_tail - 864 + 835 tommy_list_count - 241 + 249
diff --git a/cov/tommyds/tommylist.h.func.html b/cov/tommyds/tommylist.h.func.html index c10d1292..14b14b56 100644 --- a/cov/tommyds/tommylist.h.func.html +++ b/cov/tommyds/tommylist.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -61,43 +61,43 @@ tommy_list_count - 241 + 249 tommy_list_empty - 74175 + 74540 tommy_list_foreach - 7071 + 7327 tommy_list_head - 24488786 + 24857398 tommy_list_init - 10804 + 11303 tommy_list_insert_first - 22741744 + 22927997 tommy_list_insert_tail - 17767092 + 18022355 tommy_list_insert_tail_not_empty - 10700756 + 10911382 tommy_list_remove_existing - 341445 + 359148 tommy_list_tail - 864 + 835
diff --git a/cov/tommyds/tommylist.h.gcov.html b/cov/tommyds/tommylist.h.gcov.html index 34f2c18f..b69a338e 100644 --- a/cov/tommyds/tommylist.h.gcov.html +++ b/cov/tommyds/tommylist.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 10 @@ -173,32 +173,32 @@ 111 : * Initializes the list. 112 : * The list is completely inplace, so it doesn't need to be deinitialized. 113 : */ - 114 10804 : tommy_inline void tommy_list_init(tommy_list* list) + 114 11303 : tommy_inline void tommy_list_init(tommy_list* list) 115 : { - 116 10804 : *list = 0; - 117 10804 : } + 116 11303 : *list = 0; + 117 11303 : } 118 : 119 : /** 120 : * Gets the head of the list. 121 : * \return The head node. For empty lists 0 is returned. 122 : */ - 123 24488786 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) + 123 24857398 : tommy_inline tommy_node* tommy_list_head(tommy_list* list) 124 : { - 125 24488786 : return *list; + 125 24857398 : return *list; 126 : } 127 : 128 : /** 129 : * Gets the tail of the list. 130 : * \return The tail node. For empty lists 0 is returned. 131 : */ - 132 864 : tommy_inline tommy_node* tommy_list_tail(tommy_list* list) + 132 835 : tommy_inline tommy_node* tommy_list_tail(tommy_list* list) 133 : { - 134 864 : tommy_node* head = tommy_list_head(list); + 134 835 : tommy_node* head = tommy_list_head(list); 135 : - 136 864 : if (!head) + 136 835 : if (!head) 137 1 : return 0; 138 : - 139 863 : return head->prev; + 139 834 : return head->prev; 140 : } 141 : 142 : /** \internal @@ -206,16 +206,16 @@ 144 : * \param list The list to initialize. 145 : * \param node The node to insert. 146 : */ - 147 22741744 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) + 147 22927997 : tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) 148 : { 149 : /* one element "circular" prev list */ - 150 22741744 : node->prev = node; + 150 22927997 : node->prev = node; 151 : 152 : /* one element "0 terminated" next list */ - 153 22741744 : node->next = 0; + 153 22927997 : node->next = 0; 154 : - 155 22741744 : *list = node; - 156 22741744 : } + 155 22927997 : *list = node; + 156 22927997 : } 157 : 158 : /** \internal 159 : * Inserts an element at the head of a not empty list. @@ -243,16 +243,16 @@ 181 : * \param head The node at the list head. It cannot be 0. 182 : * \param node The node to insert. 183 : */ - 184 10700756 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) + 184 10911382 : tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) 185 : { 186 : /* insert in the "circular" prev list */ - 187 10700756 : node->prev = head->prev; - 188 10700756 : head->prev = node; + 187 10911382 : node->prev = head->prev; + 188 10911382 : head->prev = node; 189 : 190 : /* insert in the "0 terminated" next list */ - 191 10700756 : node->next = 0; - 192 10700756 : node->prev->next = node; - 193 10700756 : } + 191 10911382 : node->next = 0; + 192 10911382 : node->prev->next = node; + 193 10911382 : } 194 : 195 : /** 196 : * Inserts an element at the head of a list. @@ -276,17 +276,17 @@ 214 : * \param node The node to insert. 215 : * \param data The object containing the node. It's used to set the tommy_node::data field of the node. 216 : */ - 217 17767092 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) + 217 18022355 : tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) 218 : { - 219 17767092 : tommy_node* head = tommy_list_head(list); + 219 18022355 : tommy_node* head = tommy_list_head(list); 220 : - 221 17767092 : if (head) - 222 8839895 : tommy_list_insert_tail_not_empty(head, node); + 221 18022355 : if (head) + 222 9003657 : tommy_list_insert_tail_not_empty(head, node); 223 : else - 224 8927197 : tommy_list_insert_first(list, node); + 224 9018698 : tommy_list_insert_first(list, node); 225 : - 226 17767092 : node->data = data; - 227 17767092 : } + 226 18022355 : node->data = data; + 227 18022355 : } 228 : 229 : /** \internal 230 : * Removes an element from the head of a not empty list. @@ -314,23 +314,23 @@ 252 : * \param node The node to remove. The node must be in the list. 253 : * \return The tommy_node::data field of the node removed. 254 : */ - 255 341445 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) + 255 359148 : tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) 256 : { - 257 341445 : tommy_node* head = tommy_list_head(list); + 257 359148 : tommy_node* head = tommy_list_head(list); 258 : 259 : /* remove from the "circular" prev list */ - 260 341445 : if (node->next) - 261 118988 : node->next->prev = node->prev; + 260 359148 : if (node->next) + 261 122485 : node->next->prev = node->prev; 262 : else - 263 222457 : head->prev = node->prev; /* the last */ + 263 236663 : head->prev = node->prev; /* the last */ 264 : 265 : /* remove from the "0 terminated" next list */ - 266 341445 : if (head == node) - 267 241019 : *list = node->next; /* the new head, in case 0 */ + 266 359148 : if (head == node) + 267 252248 : *list = node->next; /* the new head, in case 0 */ 268 : else - 269 100426 : node->prev->next = node->next; + 269 106900 : node->prev->next = node->next; 270 : - 271 341445 : return node->data; + 271 359148 : return node->data; 272 : } 273 : 274 : /** @@ -355,26 +355,26 @@ 293 : * Checks if empty. 294 : * \return If the list is empty. 295 : */ - 296 74175 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) + 296 74540 : tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) 297 : { - 298 74175 : return tommy_list_head(list) == 0; + 298 74540 : return tommy_list_head(list) == 0; 299 : } 300 : 301 : /** 302 : * Gets the number of elements. 303 : * \note This operation is O(n). 304 : */ - 305 241 : tommy_inline tommy_count_t tommy_list_count(tommy_list* list) + 305 249 : tommy_inline tommy_count_t tommy_list_count(tommy_list* list) 306 : { - 307 241 : tommy_count_t count = 0; - 308 241 : tommy_node* i = tommy_list_head(list); + 307 249 : tommy_count_t count = 0; + 308 249 : tommy_node* i = tommy_list_head(list); 309 : - 310 1923 : while (i) { - 311 1441 : ++count; - 312 1441 : i = i->next; + 310 1987 : while (i) { + 311 1489 : ++count; + 312 1489 : i = i->next; 313 : } 314 : - 315 241 : return count; + 315 249 : return count; 316 : } 317 : 318 : /** @@ -405,16 +405,16 @@ 343 : * tommy_list_foreach(&list, free); 344 : * \endcode 345 : */ - 346 7071 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) + 346 7327 : tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) 347 : { - 348 7071 : tommy_node* node = tommy_list_head(list); + 348 7327 : tommy_node* node = tommy_list_head(list); 349 : - 350 3547533 : while (node) { - 351 3533391 : void* data = node->data; - 352 3533391 : node = node->next; - 353 3533391 : func(data); + 350 3598724 : while (node) { + 351 3584070 : void* data = node->data; + 352 3584070 : node = node->next; + 353 3584070 : func(data); 354 : } - 355 7071 : } + 355 7327 : } 356 : 357 : /** 358 : * Calls the specified function with an argument for each element in the list. diff --git a/cov/tommyds/tommytree.c.func-sort-c.html b/cov/tommyds/tommytree.c.func-sort-c.html index b79d2f99..c432723c 100644 --- a/cov/tommyds/tommytree.c.func-sort-c.html +++ b/cov/tommyds/tommytree.c.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 19 @@ -61,67 +61,67 @@ tommy_tree_search_node - 324348165 + 125457281 tommy_tree_delta - 108663041 + 109388905 tommy_tree_balance - 101410069 + 102241942 tommy_tree_insert_node - 93001793 - - - tommy_tree_search_compare - 31336465 + 93986144 tommy_tree_foreach_arg_node - 25171385 + 25770381 - tommy_tree_rotate_left - 7241652 + tommy_tree_search_compare + 11217144 tommy_tree_insert - 7215779 + 7315111 + + + tommy_tree_rotate_left + 7135360 tommy_tree_foreach_node - 6799230 + 6892468 tommy_tree_remove_node - 775421 - - - tommy_tree_move_right - 183618 + 838361 tommy_tree_rotate_right - 168850 + 218129 + + + tommy_tree_move_right + 192710 tommy_tree_remove - 78058 + 83634 tommy_tree_foreach_arg - 5353 + 5677 tommy_tree_init - 2955 + 3051 tommy_tree_foreach - 1352 + 1400 tommy_tree_remove_existing diff --git a/cov/tommyds/tommytree.c.func.html b/cov/tommyds/tommytree.c.func.html index c84d6f4c..6d0cebe5 100644 --- a/cov/tommyds/tommytree.c.func.html +++ b/cov/tommyds/tommytree.c.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 19 @@ -61,39 +61,39 @@ tommy_tree_balance - 101410069 + 102241942 tommy_tree_delta - 108663041 + 109388905 tommy_tree_foreach - 1352 + 1400 tommy_tree_foreach_arg - 5353 + 5677 tommy_tree_foreach_arg_node - 25171385 + 25770381 tommy_tree_foreach_node - 6799230 + 6892468 tommy_tree_init - 2955 + 3051 tommy_tree_insert - 7215779 + 7315111 tommy_tree_insert_node - 93001793 + 93986144 tommy_tree_memory_usage @@ -101,11 +101,11 @@ tommy_tree_move_right - 183618 + 192710 tommy_tree_remove - 78058 + 83634 tommy_tree_remove_existing @@ -113,15 +113,15 @@ tommy_tree_remove_node - 775421 + 838361 tommy_tree_rotate_left - 7241652 + 7135360 tommy_tree_rotate_right - 168850 + 218129 tommy_tree_search @@ -129,11 +129,11 @@ tommy_tree_search_compare - 31336465 + 11217144 tommy_tree_search_node - 324348165 + 125457281
diff --git a/cov/tommyds/tommytree.c.gcov.html b/cov/tommyds/tommytree.c.gcov.html index 4658bf45..2035f253 100644 --- a/cov/tommyds/tommytree.c.gcov.html +++ b/cov/tommyds/tommytree.c.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 19 @@ -94,104 +94,104 @@ 32 : /******************************************************************************/ 33 : /* tree */ 34 : - 35 2955 : void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) + 35 3051 : void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) 36 : { - 37 2955 : tree->root = 0; - 38 2955 : tree->count = 0; - 39 2955 : tree->cmp = cmp; - 40 2955 : } + 37 3051 : tree->root = 0; + 38 3051 : tree->count = 0; + 39 3051 : tree->cmp = cmp; + 40 3051 : } 41 : - 42 108663041 : static int tommy_tree_delta(tommy_tree_node* root) + 42 109388905 : static int tommy_tree_delta(tommy_tree_node* root) 43 : { - 44 108663041 : int left_height = root->prev ? root->prev->key : 0; - 45 108663041 : int right_height = root->next ? root->next->key : 0; + 44 109388905 : int left_height = root->prev ? root->prev->key : 0; + 45 109388905 : int right_height = root->next ? root->next->key : 0; 46 : - 47 108663041 : return left_height - right_height; + 47 109388905 : return left_height - right_height; 48 : } 49 : 50 : /* AVL tree operations */ 51 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*); 52 : - 53 7241652 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) + 53 7135360 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) 54 : { - 55 7241652 : tommy_tree_node* next = root->next; + 55 7135360 : tommy_tree_node* next = root->next; 56 : - 57 7241652 : root->next = next->prev; + 57 7135360 : root->next = next->prev; 58 : - 59 7241652 : next->prev = tommy_tree_balance(root); + 59 7135360 : next->prev = tommy_tree_balance(root); 60 : - 61 7241652 : return tommy_tree_balance(next); + 61 7135360 : return tommy_tree_balance(next); 62 : } 63 : - 64 168850 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) + 64 218129 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) 65 : { - 66 168850 : tommy_tree_node* prev = root->prev; + 66 218129 : tommy_tree_node* prev = root->prev; 67 : - 68 168850 : root->prev = prev->next; + 68 218129 : root->prev = prev->next; 69 : - 70 168850 : prev->next = tommy_tree_balance(root); + 70 218129 : prev->next = tommy_tree_balance(root); 71 : - 72 168850 : return tommy_tree_balance(prev); + 72 218129 : return tommy_tree_balance(prev); 73 : } 74 : - 75 183618 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) + 75 192710 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) 76 : { - 77 183618 : if (!root) - 78 77930 : return node; + 77 192710 : if (!root) + 78 83506 : return node; 79 : - 80 105688 : root->next = tommy_tree_move_right(root->next, node); + 80 109204 : root->next = tommy_tree_move_right(root->next, node); 81 : - 82 105688 : return tommy_tree_balance(root); + 82 109204 : return tommy_tree_balance(root); 83 : } 84 : - 85 101410069 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) + 85 102241942 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) 86 : { - 87 101410069 : int delta = tommy_tree_delta(root); + 87 102241942 : int delta = tommy_tree_delta(root); 88 : - 89 101410069 : if (delta < -1) { - 90 7125675 : if (tommy_tree_delta(root->next) > 0) - 91 41553 : root->next = tommy_tree_rotate_right(root->next); - 92 7125675 : return tommy_tree_rotate_left(root); + 89 102241942 : if (delta < -1) { + 90 6971745 : if (tommy_tree_delta(root->next) > 0) + 91 42911 : root->next = tommy_tree_rotate_right(root->next); + 92 6971745 : return tommy_tree_rotate_left(root); 93 : } 94 : - 95 94284394 : if (delta > 1) { - 96 127297 : if (tommy_tree_delta(root->prev) < 0) - 97 115977 : root->prev = tommy_tree_rotate_left(root->prev); - 98 127297 : return tommy_tree_rotate_right(root); + 95 95270197 : if (delta > 1) { + 96 175218 : if (tommy_tree_delta(root->prev) < 0) + 97 163615 : root->prev = tommy_tree_rotate_left(root->prev); + 98 175218 : return tommy_tree_rotate_right(root); 99 : } 100 : 101 : /* recompute key */ - 102 94157097 : root->key = 0; + 102 95094979 : root->key = 0; 103 : - 104 94157097 : if (root->prev && root->prev->key > root->key) - 105 76188949 : root->key = root->prev->key; + 104 95094979 : if (root->prev && root->prev->key > root->key) + 105 77186914 : root->key = root->prev->key; 106 : - 107 94157097 : if (root->next && root->next->key > root->key) - 108 43401597 : root->key = root->next->key; + 107 95094979 : if (root->next && root->next->key > root->key) + 108 43098001 : root->key = root->next->key; 109 : 110 : /* count itself */ - 111 94157097 : root->key += 1; + 111 95094979 : root->key += 1; 112 : - 113 94157097 : return root; + 113 95094979 : return root; 114 : } 115 : - 116 93001793 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) + 116 93986144 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) 117 : { 118 : int c; 119 : - 120 93001793 : if (!root) - 121 7215778 : return *let; + 120 93986144 : if (!root) + 121 7315110 : return *let; 122 : - 123 85786015 : c = cmp((*let)->data, root->data); + 123 86671034 : c = cmp((*let)->data, root->data); 124 : - 125 85786015 : if (c < 0) { - 126 1492912 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); - 127 1492912 : return tommy_tree_balance(root); + 125 86671034 : if (c < 0) { + 126 2767362 : root->prev = tommy_tree_insert_node(cmp, root->prev, let); + 127 2767362 : return tommy_tree_balance(root); 128 : } 129 : - 130 84293103 : if (c > 0) { - 131 84293102 : root->next = tommy_tree_insert_node(cmp, root->next, let); - 132 84293102 : return tommy_tree_balance(root); + 130 83903672 : if (c > 0) { + 131 83903671 : root->next = tommy_tree_insert_node(cmp, root->next, let); + 132 83903671 : return tommy_tree_balance(root); 133 : } 134 : 135 : /* already present, set the return pointer */ @@ -200,78 +200,78 @@ 138 1 : return root; 139 : } 140 : - 141 7215779 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) + 141 7315111 : void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) 142 : { - 143 7215779 : tommy_tree_node* insert = node; + 143 7315111 : tommy_tree_node* insert = node; 144 : - 145 7215779 : insert->data = data; - 146 7215779 : insert->prev = 0; - 147 7215779 : insert->next = 0; - 148 7215779 : insert->key = 0; + 145 7315111 : insert->data = data; + 146 7315111 : insert->prev = 0; + 147 7315111 : insert->next = 0; + 148 7315111 : insert->key = 0; 149 : - 150 7215779 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); + 150 7315111 : tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); 151 : - 152 7215779 : if (insert == node) - 153 7215778 : ++tree->count; + 152 7315111 : if (insert == node) + 153 7315110 : ++tree->count; 154 : - 155 7215779 : return node->data; + 155 7315111 : return node->data; 156 : } 157 : - 158 775421 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) + 158 838361 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) 159 : { 160 : int c; 161 : - 162 775421 : if (!root) + 162 838361 : if (!root) 163 128 : return 0; 164 : - 165 775293 : c = cmp(data, root->data); + 165 838233 : c = cmp(data, root->data); 166 : - 167 775293 : if (c < 0) { - 168 298766 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); - 169 298766 : return tommy_tree_balance(root); + 167 838233 : if (c < 0) { + 168 330789 : root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); + 169 330789 : return tommy_tree_balance(root); 170 : } 171 : - 172 476527 : if (c > 0) { - 173 398597 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); - 174 398597 : return tommy_tree_balance(root); + 172 507444 : if (c > 0) { + 173 423938 : root->next = tommy_tree_remove_node(cmp, root->next, data, let); + 174 423938 : return tommy_tree_balance(root); 175 : } 176 : 177 : /* found */ - 178 77930 : *let = root; + 178 83506 : *let = root; 179 : - 180 77930 : return tommy_tree_move_right(root->prev, root->next); + 180 83506 : return tommy_tree_move_right(root->prev, root->next); 181 : } 182 : - 183 78058 : void* tommy_tree_remove(tommy_tree* tree, void* data) + 183 83634 : void* tommy_tree_remove(tommy_tree* tree, void* data) 184 : { - 185 78058 : tommy_tree_node* node = 0; + 185 83634 : tommy_tree_node* node = 0; 186 : - 187 78058 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); + 187 83634 : tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); 188 : - 189 78058 : if (!node) + 189 83634 : if (!node) 190 128 : return 0; 191 : - 192 77930 : --tree->count; + 192 83506 : --tree->count; 193 : - 194 77930 : return node->data; + 194 83506 : return node->data; 195 : } 196 : - 197 324348165 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) + 197 125457281 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) 198 : { 199 : int c; 200 : - 201 324348165 : if (!root) - 202 2354776 : return 0; + 201 125457281 : if (!root) + 202 1561728 : return 0; 203 : - 204 321993389 : c = cmp(data, root->data); + 204 123895553 : c = cmp(data, root->data); 205 : - 206 330820889 : if (c < 0) - 207 130151880 : return tommy_tree_search_node(cmp, root->prev, data); + 206 123895553 : if (c < 0) + 207 44385963 : return tommy_tree_search_node(cmp, root->prev, data); 208 : - 209 200669009 : if (c > 0) - 210 171722863 : return tommy_tree_search_node(cmp, root->next, data); + 209 79509590 : if (c > 0) + 210 69854172 : return tommy_tree_search_node(cmp, root->next, data); 211 : - 212 28946146 : return root; + 212 9655418 : return root; 213 : } 214 : 215 2 : void* tommy_tree_search(tommy_tree* tree, void* data) @@ -284,14 +284,14 @@ 222 1 : return node->data; 223 : } 224 : - 225 31336465 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) + 225 11217144 : void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) 226 : { - 227 31336465 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); + 227 11217144 : tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); 228 : - 229 31273364 : if (!node) - 230 2346177 : return 0; + 229 11217144 : if (!node) + 230 1561727 : return 0; 231 : - 232 28927187 : return node->data; + 232 9655417 : return node->data; 233 : } 234 : 235 128 : void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) @@ -303,49 +303,49 @@ 241 128 : return data; 242 : } 243 : - 244 6799230 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) + 244 6892468 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) 245 : { 246 : tommy_tree_node* next; 247 : - 248 6799230 : if (!root) - 249 10199521 : return; + 248 6892468 : if (!root) + 249 10339402 : return; 250 : - 251 3398939 : tommy_tree_foreach_node(root->prev, func); + 251 3445534 : tommy_tree_foreach_node(root->prev, func); 252 : 253 : /* make a copy in case func is free() */ - 254 3398939 : next = root->next; + 254 3445534 : next = root->next; 255 : - 256 3398939 : func(root->data); + 256 3445534 : func(root->data); 257 : - 258 3398939 : tommy_tree_foreach_node(next, func); + 258 3445534 : tommy_tree_foreach_node(next, func); 259 : } 260 : - 261 1352 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) + 261 1400 : void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) 262 : { - 263 1352 : tommy_tree_foreach_node(tree->root, func); - 264 1352 : } + 263 1400 : tommy_tree_foreach_node(tree->root, func); + 264 1400 : } 265 : - 266 25171385 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) + 266 25770381 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) 267 : { 268 : tommy_tree_node* next; 269 : - 270 25171385 : if (!root) - 271 37759754 : return; + 270 25770381 : if (!root) + 271 38658410 : return; 272 : - 273 12583016 : tommy_tree_foreach_arg_node(root->prev, func, arg); + 273 12882352 : tommy_tree_foreach_arg_node(root->prev, func, arg); 274 : 275 : /* make a copy in case func is free() */ - 276 12583016 : next = root->next; + 276 12882352 : next = root->next; 277 : - 278 12583016 : func(arg, root->data); + 278 12882352 : func(arg, root->data); 279 : - 280 12583016 : tommy_tree_foreach_arg_node(next, func, arg); + 280 12882352 : tommy_tree_foreach_arg_node(next, func, arg); 281 : } 282 : - 283 5353 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) + 283 5677 : void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) 284 : { - 285 5353 : tommy_tree_foreach_arg_node(tree->root, func, arg); - 286 5353 : } + 285 5677 : tommy_tree_foreach_arg_node(tree->root, func, arg); + 286 5677 : } 287 : 288 1 : tommy_size_t tommy_tree_memory_usage(tommy_tree* tree) 289 : { diff --git a/cov/tommyds/tommytree.h.func-sort-c.html b/cov/tommyds/tommytree.h.func-sort-c.html index 402c3c72..6e568820 100644 --- a/cov/tommyds/tommytree.h.func-sort-c.html +++ b/cov/tommyds/tommytree.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/tommyds/tommytree.h.func.html b/cov/tommyds/tommytree.h.func.html index 6566356b..e8884ad1 100644 --- a/cov/tommyds/tommytree.h.func.html +++ b/cov/tommyds/tommytree.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/tommyds/tommytree.h.gcov.html b/cov/tommyds/tommytree.h.gcov.html index ec3ff04a..637a5c9c 100644 --- a/cov/tommyds/tommytree.h.gcov.html +++ b/cov/tommyds/tommytree.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 1 diff --git a/cov/tommyds/tommytypes.h.func-sort-c.html b/cov/tommyds/tommytypes.h.func-sort-c.html index 5b79e95e..473c3b65 100644 --- a/cov/tommyds/tommytypes.h.func-sort-c.html +++ b/cov/tommyds/tommytypes.h.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_ilog2_u32 - 15297694 + 10133914 tommy_ctz_u32 - 1473 + 1558
diff --git a/cov/tommyds/tommytypes.h.func.html b/cov/tommyds/tommytypes.h.func.html index e495be7b..be1af3e9 100644 --- a/cov/tommyds/tommytypes.h.func.html +++ b/cov/tommyds/tommytypes.h.func.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -61,11 +61,11 @@ tommy_ctz_u32 - 1473 + 1558 tommy_ilog2_u32 - 15297694 + 10133914
diff --git a/cov/tommyds/tommytypes.h.gcov.html b/cov/tommyds/tommytypes.h.gcov.html index 018a04b9..52e2afdd 100644 --- a/cov/tommyds/tommytypes.h.gcov.html +++ b/cov/tommyds/tommytypes.h.gcov.html @@ -37,7 +37,7 @@ Date: - 2015-11-20 + 2016-01-09 Functions: 2 @@ -385,7 +385,7 @@ 323 : * \param value Value to scan. 0 is not allowed. 324 : * \return The index of the most significant bit set. 325 : */ - 326 15297694 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value) + 326 10133914 : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value) 327 : { 328 : #if defined(_MSC_VER) 329 : unsigned long count; @@ -401,7 +401,7 @@ 339 : * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)", 340 : * to allow the double xor to be optimized out. 341 : */ - 342 15297694 : return __builtin_clz(value) ^ 31; + 342 10133914 : return __builtin_clz(value) ^ 31; 343 : #else 344 : /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */ 345 : /* from http://graphics.stanford.edu/~seander/bithacks.html */ @@ -428,14 +428,14 @@ 366 : * \param value Value to scan. 0 is not allowed. 367 : * \return The index of the least significant bit set. 368 : */ - 369 1473 : tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value) + 369 1558 : tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value) 370 : { 371 : #if defined(_MSC_VER) 372 : unsigned long count; 373 : _BitScanForward(&count, value); 374 : return count; 375 : #elif defined(__GNUC__) - 376 1473 : return __builtin_ctz(value); + 376 1558 : return __builtin_ctz(value); 377 : #else 378 : /* Count the consecutive zero bits (trailing) on the right with multiply and lookup */ 379 : /* from http://graphics.stanford.edu/~seander/bithacks.html */