diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-05-23 17:21:24 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-05-23 17:30:29 +0200 |
commit | d9e5895829a2c20e7624326ce391f0e56762b855 (patch) | |
tree | c7ba4fa9322d5038da8e53aef200a47d01558604 /lib/sqfs/block_processor/common.c | |
parent | 4587a56466f0c55d91ece168f0dc872f81a8196c (diff) |
block processor: move the block consolidation to the worker thread
Instead of merging fragments into the fragment block inside the
process_completed_fragment function, store a linked list of fragments
in the fragment block and do the actual merging (several memcpy calls
totaling of up to 1M of data in worst case) in the worker thread
instead of the locked, serial path.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/block_processor/common.c')
-rw-r--r-- | lib/sqfs/block_processor/common.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c index b8f2760..c3363f9 100644 --- a/lib/sqfs/block_processor/common.c +++ b/lib/sqfs/block_processor/common.c @@ -63,6 +63,18 @@ static sqfs_block_t *get_new_block(sqfs_block_processor_t *proc) static void release_old_block(sqfs_block_processor_t *proc, sqfs_block_t *blk) { + sqfs_block_t *it; + + if (blk->flags & SQFS_BLK_FRAGMENT_BLOCK && blk->frag_list != NULL) { + it = blk->frag_list; + + while (it->next != NULL) + it = it->next; + + it->next = proc->free_list; + proc->free_list = blk->frag_list; + } + blk->next = proc->free_list; proc->free_list = blk; } @@ -120,11 +132,29 @@ static bool is_zero_block(unsigned char *ptr, size_t size) int block_processor_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp, sqfs_u8 *scratch, size_t scratch_size) { + sqfs_block_t *it; + size_t offset; sqfs_s32 ret; if (block->size == 0) return 0; + if (block->flags & SQFS_BLK_FRAGMENT_BLOCK) { + offset = block->size; + + for (it = block->frag_list; it != NULL; it = it->next) { + assert(offset >= it->size); + offset -= it->size; + + memcpy(block->data + offset, it->data, it->size); + + block->flags |= (it->flags & SQFS_BLK_DONT_COMPRESS); + + sqfs_inode_set_frag_location(*(it->inode), + block->index, offset); + } + } + if (is_zero_block(block->data, block->size)) { block->flags |= SQFS_BLK_IS_SPARSE; return 0; @@ -211,17 +241,11 @@ int process_completed_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag, if (err) goto fail; - sqfs_inode_set_frag_location(*(frag->inode), proc->frag_block->index, - proc->frag_block->size); + frag->next = proc->frag_block->frag_list; + proc->frag_block->frag_list = frag; - memcpy(proc->frag_block->data + proc->frag_block->size, - frag->data, frag->size); - - proc->frag_block->flags |= (frag->flags & SQFS_BLK_DONT_COMPRESS); proc->frag_block->size += frag->size; proc->stats.actual_frag_count += 1; - - release_old_block(proc, frag); return 0; fail: release_old_block(proc, frag); |