Avoid redundant block initialization when loading content files

This commit is contained in:
Andrea Mazzoleni 2026-09-09 17:56:44 +02:00
parent bc564e7465
commit b14f703d2b
4 changed files with 22 additions and 10 deletions

View file

@ -472,7 +472,6 @@ int filter_snapshot(int enable, const char* sub, const char* name)
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)
{
struct snapraid_file* file;
block_off_t i;
block_off_t blockmax;
blockmax = size / block_size;
@ -498,12 +497,6 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_
file->flag = 0;
file->blockvec = nalloc_nofail((size_t)file->blockmax, block_sizeof());
for (i = 0; i < file->blockmax; ++i) {
struct snapraid_block* block = file_block(file, i);
block_state_set(block, BLOCK_STATE_CHG);
hash_invalid_set(block->hash);
}
return file;
}

View file

@ -883,7 +883,7 @@ static inline void file_flag_clear(struct snapraid_file* file, unsigned mask)
}
/**
* Allocate a file.
* Allocate a file without initializing its blocks.
*/
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);

View file

@ -691,6 +691,7 @@ static void scan_file_apply(void* void_scan, void* void_disc)
struct snapraid_disk* disk = scan->disk;
int is_diff = scan->is_diff;
struct snapraid_file* file;
block_off_t block_pos;
tommy_node* i;
int is_original_file_size_different_than_zero;
int is_file_already_present;
@ -997,6 +998,18 @@ static void scan_file_apply(void* void_scan, void* void_disc)
/* insert it */
file = file_alloc(state->block_size, sub, disc->size, disc->mtime_sec, disc->mtime_nsec, disc->inode);
/*
* Copy detection recognizes reused hashes from REP blocks before parity
* allocation. Initialize new scan blocks to CHG so uninitialized state can
* never be mistaken for a reusable hash.
*/
for (block_pos = 0; block_pos < file->blockmax; ++block_pos) {
struct snapraid_block* block = fs_file2block_get(file, block_pos);
block_state_set(block, BLOCK_STATE_CHG);
hash_invalid_set(block->hash);
}
/* mark it as present and physically discovered during Phase 1 */
file_flag_set(file, FILE_IS_PRESENT);
file_flag_set(file, FILE_IS_DISCOVERED);

View file

@ -2422,7 +2422,10 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
/* LCOV_EXCL_STOP */
}
/* allocate the file */
/*
* Allocate without initializing blocks. The runs below cover the whole
* file and set every state and hash before exposing the loaded state.
*/
file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode);
/* insert the file in the file containers */
@ -2750,7 +2753,10 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
/* LCOV_EXCL_STOP */
}
/* allocate a fake deleted file */
/*
* Allocate without initializing blocks. This deleted run sets every
* state and hash before the file is inserted in the extent map.
*/
deleted = file_alloc(state->block_size, "<deleted>", v_count * (data_off_t)state->block_size, 0, 0, 0);
/* mark the file as deleted */