diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-24 03:45:30 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-24 04:01:10 +0200 |
commit | 8d9f24a65ef27a52615b3225776632de08462eba (patch) | |
tree | 76d64437a98e94b2749cbb2f48117f9d1b4af947 /lib/sqfs/blk_proc/fragtbl.c | |
parent | 035cbdfe1bc5aea16cbcada5e3c00ecf5ac08c96 (diff) |
Move entire fragment processing from data writer to block processor
So far, this is mostly a direct port from the block processor. The
actual fragment checksumming is not done through the thread pool.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/blk_proc/fragtbl.c')
-rw-r--r-- | lib/sqfs/blk_proc/fragtbl.c | 110 |
1 files changed, 99 insertions, 11 deletions
diff --git a/lib/sqfs/blk_proc/fragtbl.c b/lib/sqfs/blk_proc/fragtbl.c index 3f6c644..84f5ed6 100644 --- a/lib/sqfs/blk_proc/fragtbl.c +++ b/lib/sqfs/blk_proc/fragtbl.c @@ -35,24 +35,112 @@ int sqfs_block_processor_write_fragment_table(sqfs_block_processor_t *proc, return 0; } -int grow_fragment_table(sqfs_block_processor_t *proc, size_t index) +static int grow_fragment_table(sqfs_block_processor_t *proc) { size_t newsz; void *new; - if (index < proc->max_fragments) - return 0; - - do { + if (proc->num_fragments >= proc->max_fragments) { newsz = proc->max_fragments ? proc->max_fragments * 2 : 16; - } while (index >= newsz); - new = realloc(proc->fragments, sizeof(proc->fragments[0]) * newsz); + new = realloc(proc->fragments, + sizeof(proc->fragments[0]) * newsz); + + if (new == NULL) + return SQFS_ERROR_ALLOC; + + proc->max_fragments = newsz; + proc->fragments = new; + } + + return 0; +} + +static int store_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag, + uint64_t signature) +{ + size_t new_sz; + void *new; + + if (proc->frag_list_num == proc->frag_list_max) { + new_sz = proc->frag_list_max * 2; + new = realloc(proc->frag_list, + sizeof(proc->frag_list[0]) * new_sz); + + if (new == NULL) + return SQFS_ERROR_ALLOC; + + proc->frag_list = new; + proc->frag_list_max = new_sz; + } + + proc->frag_list[proc->frag_list_num].index = proc->frag_block->index; + proc->frag_list[proc->frag_list_num].offset = proc->frag_block->size; + proc->frag_list[proc->frag_list_num].signature = signature; + proc->frag_list_num += 1; + + sqfs_inode_set_frag_location(frag->inode, proc->frag_block->index, + proc->frag_block->size); + + 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; + return 0; +} + +int handle_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag, + sqfs_block_t **blk_out) +{ + uint64_t signature; + size_t i, size; + int err; + + signature = MK_BLK_SIG(frag->checksum, frag->size); + + for (i = 0; i < proc->frag_list_num; ++i) { + if (proc->frag_list[i].signature == signature) { + sqfs_inode_set_frag_location(frag->inode, + proc->frag_list[i].index, + proc->frag_list[i].offset); + return 0; + } + } + + if (proc->frag_block != NULL) { + size = proc->frag_block->size + frag->size; + + if (size > proc->max_block_size) { + *blk_out = proc->frag_block; + proc->frag_block = NULL; + } + } + + if (proc->frag_block == NULL) { + size = sizeof(sqfs_block_t) + proc->max_block_size; + + err = grow_fragment_table(proc); + if (err) + goto fail; + + proc->frag_block = calloc(1, size); + if (proc->frag_block == NULL) { + err = SQFS_ERROR_ALLOC; + goto fail; + } + + proc->frag_block->index = proc->num_fragments++; + proc->frag_block->flags = SQFS_BLK_FRAGMENT_BLOCK; + } - if (new == NULL) - return SQFS_ERROR_ALLOC; + err = store_fragment(proc, frag, signature); + if (err) + goto fail; - proc->max_fragments = newsz; - proc->fragments = new; return 0; +fail: + free(*blk_out); + *blk_out = NULL; + return err; } |