From b64c28b5379ef7a1242a3b01cb0d625d9c3aafc6 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 9 Sep 2026 23:16:19 +0200 Subject: [PATCH] Serialize deleted blocks by ordered parity extents --- cmdline/state.c | 88 ++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/cmdline/state.c b/cmdline/state.c index 30d2e87c..892e6a7c 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -2145,7 +2145,7 @@ static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t /** * Check if a block position in a disk is deleted. */ -static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) +static inline int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) { struct snapraid_block* block = fs_par2block_find(disk, pos); @@ -4286,54 +4286,58 @@ static void* state_write_thread(void* arg) goto bail; /* LCOV_EXCL_STOP */ } + begin = 0; - while (begin < blockmax) { - int is_deleted; - block_off_t end; - - is_deleted = fs_is_block_deleted(disk, begin); - - /* find the end of run of blocks */ - end = begin + 1; - while (end < blockmax - && is_deleted == fs_is_block_deleted(disk, end) - ) { - ++end; - } - - sputb64(end - begin, f); - - if (is_deleted) { - /* write the run of deleted blocks with hash */ - sputc('o', f); - - /* write all the hash */ - while (begin < end) { - struct snapraid_block* block = fs_par2block_get(disk, begin); - - swrite(block->hash, BLOCK_HASH_SIZE, f); - - ++begin; - } - } else { - /* - * Write the run of blocks without hash - * they can be either used or empty blocks - */ + if (tommy_list_empty(&disk->deletedlist)) { + /* the common case needs only one non-deleted run */ + if (blockmax) { + sputb64(blockmax, f); sputc('O', f); - - /* next begin position */ - begin = end; } + } else { + while (begin < blockmax) { + int is_deleted; + block_off_t end; - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - goto bail; - /* LCOV_EXCL_STOP */ + is_deleted = fs_is_block_deleted(disk, begin); + + /* find the end of run of blocks */ + end = begin + 1; + while (end < blockmax + && is_deleted == fs_is_block_deleted(disk, end) + ) { + ++end; + } + + sputb64(end - begin, f); + + if (is_deleted) { + /* write the run of deleted blocks with hash */ + sputc('o', f); + + /* write all the hashes */ + while (begin < end) { + struct snapraid_block* block = fs_par2block_get(disk, begin); + + swrite(block->hash, BLOCK_HASH_SIZE, f); + + ++begin; + } + } else { + /* used and empty blocks don't have a hash in this section */ + sputc('O', f); + begin = end; + } } } + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal(errno, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + /* deallocated files of the disk */ if (!tommy_list_empty(&disk->dealloclist)) { sputc('d', f);