Specialize block hash copies for the full hash size

This commit is contained in:
Andrea Mazzoleni 2026-09-09 23:40:37 +02:00
parent b64c28b537
commit 902c19b668
8 changed files with 29 additions and 15 deletions

View file

@ -52,7 +52,7 @@ struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_d
for (i = 0; i < file->blockmax; ++i) {
struct snapraid_block* block = fs_file2block_get(file, i);
memcpy(buf + i * hash_size, block->hash, hash_size);
hash_copy(buf + i * hash_size, block->hash);
if (!block_has_updated_hash(block)) {
free(buf);

View file

@ -528,7 +528,7 @@ struct snapraid_file* file_dup(struct snapraid_file* copy)
struct snapraid_block* block = file_block(file, i);
struct snapraid_block* copy_block = file_block(copy, i);
block->state = copy_block->state;
memcpy(block->hash, copy_block->hash, BLOCK_HASH_SIZE);
hash_copy(block->hash, copy_block->hash);
}
return file;
@ -581,7 +581,7 @@ void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file)
block_state_set(file_block(dst_file, i), BLOCK_STATE_REP);
/* copy the hash */
memcpy(file_block(dst_file, i)->hash, file_block(src_file, i)->hash, BLOCK_HASH_SIZE);
hash_copy(file_block(dst_file, i)->hash, file_block(src_file, i)->hash);
}
file_flag_set(dst_file, FILE_IS_COPY);
@ -898,7 +898,7 @@ void dealloc_import(struct snapraid_dealloc* dealloc, struct snapraid_file* file
case BLOCK_STATE_BLK :
case BLOCK_STATE_REP :
case BLOCK_STATE_REBUILD :
memcpy(hash, block->hash, BLOCK_HASH_SIZE);
hash_copy(hash, block->hash);
break;
case BLOCK_STATE_CHG :
hash_invalid_set(hash);

View file

@ -692,6 +692,20 @@ int filter_content(tommy_list* contentlist, const char* mount_point, size_t moun
*/
int filter_snapshot(int enable, const char* sub, const char* name);
/**
* Copy a block hash using the configured hash size.
*
* Keep the common full-size case explicit so the compiler can inline a fixed
* 16-byte copy instead of emitting a call to memcpy() with a runtime size.
*/
static __always_inline void* hash_copy(void* dst, const void* src)
{
if (BLOCK_HASH_SIZE == HASH_MAX)
return memcpy(dst, src, HASH_MAX);
else
return memcpy(dst, src, BLOCK_HASH_SIZE);
}
/**
* Check if the specified hash is invalid.
*
@ -707,7 +721,7 @@ static inline int hash_is_invalid(const unsigned char* hash)
if (BLOCK_HASH_SIZE != HASH_MAX)
return 0;
for (i = 0; i < BLOCK_HASH_SIZE; ++i)
for (i = 0; i < HASH_MAX; ++i)
if (hash[i] != 0x00)
return 0;

View file

@ -224,7 +224,7 @@ static void import_dealloc(struct snapraid_state* state, const char* dir, struct
block->offset = offset;
block->size = read_size;
memcpy(block->hash, dealloc->blockhash + i * BLOCK_HASH_SIZE, BLOCK_HASH_SIZE);
hash_copy(block->hash, dealloc->blockhash + i * BLOCK_HASH_SIZE);
/* do not insert invalid hashes */
if (!hash_is_invalid(block->hash)) {
@ -244,7 +244,7 @@ static void import_dealloc(struct snapraid_state* state, const char* dir, struct
* a new-hash block, or vice-versa) will miss in hash lookup and fall
* back to parity reconstruction. Only same-generation matches will succeed.
*/
memcpy(block->prevhash, block->hash, BLOCK_HASH_SIZE);
hash_copy(block->prevhash, block->hash);
tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash));
} else {
hash_invalid_set(block->prevhash);

View file

@ -341,7 +341,7 @@ static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file*
*/
/* copy the past hash of the block */
memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE);
hash_copy(block->hash, over_block->hash);
}
}

View file

@ -909,7 +909,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
/* store all the new hashes already computed */
for (j = 0; j < diskmax; ++j) {
if (rehandle[j].block)
memcpy(rehandle[j].block->hash, rehandle[j].hash, BLOCK_HASH_SIZE);
hash_copy(rehandle[j].block->hash, rehandle[j].hash);
}
/* complete the rehash */

View file

@ -2311,7 +2311,7 @@ static int state_read_block_run(STREAM* f, struct snapraid_file* file, block_off
if (hash_mode == STATE_BLOCK_HASH_DISCARD)
hash_invalid_set(block->hash);
else
memcpy(block->hash, input, BLOCK_HASH_SIZE);
hash_copy(block->hash, input);
input += BLOCK_HASH_SIZE;
block_ptr += block_stride;
@ -3887,7 +3887,7 @@ static int state_write_block_run(STREAM* f, struct snapraid_file* file, block_of
struct snapraid_block* block = (struct snapraid_block*)block_ptr;
crc = crc32c_plain(crc, block->hash, BLOCK_HASH_SIZE);
memcpy(output, block->hash, BLOCK_HASH_SIZE);
hash_copy(output, block->hash);
output += BLOCK_HASH_SIZE;
block_ptr += block_stride;

View file

@ -547,7 +547,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
*/
/* copy the hash in the block */
memcpy(block->hash, hash, BLOCK_HASH_SIZE);
hash_copy(block->hash, hash);
/* and mark the block as hashed */
block_state_set(block, BLOCK_STATE_REP);
@ -1353,7 +1353,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
* During rehash this uses the previous hash algorithm and is
* overwritten with the new hash below when rehash is committed.
*/
memcpy(rehandle[diskcur].sync_hash, hash, BLOCK_HASH_SIZE);
hash_copy(rehandle[diskcur].sync_hash, hash);
}
}
@ -1574,7 +1574,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
* was handled above. Publish the staged hash atomically with CHG -> BLK.
*/
if (block_state_get(block) == BLOCK_STATE_CHG)
memcpy(block->hash, rehandle[j].sync_hash, BLOCK_HASH_SIZE);
hash_copy(block->hash, rehandle[j].sync_hash);
/* now all the blocks have the hash and the parity computed */
block_state_set(block, BLOCK_STATE_BLK);
@ -1595,7 +1595,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* store all the new hash already computed */
for (j = 0; j < diskmax; ++j) {
if (rehandle[j].block)
memcpy(rehandle[j].block->hash, rehandle[j].new_hash, BLOCK_HASH_SIZE);
hash_copy(rehandle[j].block->hash, rehandle[j].new_hash);
}
}