From 1fc10c7115f71d9338bc79da72db2ee9e1a87073 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Thu, 14 Jan 2021 04:40:36 +0100
Subject: Fix: Move fragment consolidation back to block processor serial part

Keeping a list of fragments stored away in the current fragment block
and consolidating them in the thread pool takes them out of circulation.

If we have a lot of tiny fragments, this can lead to a situation where
all the limit is reached, but we cannot do anything, because we are
waiting for a block to complete, but they are all attached to the
current fragment block and the queue is empty.

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 lib/sqfs/block_processor/common.c   | 35 +++++------------------------------
 lib/sqfs/block_processor/internal.h |  4 ----
 lib/sqfs/block_processor/serial.c   | 12 ------------
 3 files changed, 5 insertions(+), 46 deletions(-)

(limited to 'lib/sqfs')

diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c
index 9c80502..b2657e6 100644
--- a/lib/sqfs/block_processor/common.c
+++ b/lib/sqfs/block_processor/common.c
@@ -46,18 +46,6 @@ static int set_block_size(sqfs_inode_generic_t **inode,
 
 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;
 }
@@ -128,26 +116,11 @@ static bool is_zero_block(unsigned char *ptr, size_t size)
 static int process_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);
-		}
-	}
-
 	if (!(block->flags & SQFS_BLK_IGNORE_SPARSE) &&
 	    is_zero_block(block->data, block->size)) {
 		block->flags |= SQFS_BLK_IS_SPARSE;
@@ -241,15 +214,17 @@ static int process_completed_fragment(sqfs_block_processor_t *proc,
 		proc->frag_block->index = index;
 		proc->frag_block->flags &= SQFS_BLK_DONT_COMPRESS;
 		proc->frag_block->flags |= SQFS_BLK_FRAGMENT_BLOCK;
-		proc->frag_block->frag_list = NULL;
 	} else {
 		index = proc->frag_block->index;
 		offset = 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->size += frag->size;
+		proc->frag_block->flags |=
+			(frag->flags & SQFS_BLK_DONT_COMPRESS);
+		release_old_block(proc, frag);
 	}
 
 	if (proc->frag_tbl != NULL) {
diff --git a/lib/sqfs/block_processor/internal.h b/lib/sqfs/block_processor/internal.h
index 0c4f2b3..ee76946 100644
--- a/lib/sqfs/block_processor/internal.h
+++ b/lib/sqfs/block_processor/internal.h
@@ -53,10 +53,6 @@ typedef struct sqfs_block_t {
 	   For fragment fragment blocks: fragment table index. */
 	sqfs_u32 index;
 
-	/* For fragment blocks: list of fragments to
-	   consolidate in reverse order. */
-	struct sqfs_block_t *frag_list;
-
 	/* User data pointer */
 	void *user;
 
diff --git a/lib/sqfs/block_processor/serial.c b/lib/sqfs/block_processor/serial.c
index f56f3cb..4d6b3ec 100644
--- a/lib/sqfs/block_processor/serial.c
+++ b/lib/sqfs/block_processor/serial.c
@@ -13,17 +13,6 @@ typedef struct {
 	sqfs_u8 scratch[];
 } serial_block_processor_t;
 
-static void free_block_list(sqfs_block_t *list)
-{
-	sqfs_block_t *blk;
-
-	while (list != NULL) {
-		blk = list;
-		list = blk->next;
-		free(blk);
-	}
-}
-
 static void block_processor_destroy(sqfs_object_t *obj)
 {
 	sqfs_block_processor_t *proc = (sqfs_block_processor_t *)obj;
@@ -63,7 +52,6 @@ static int append_to_work_queue(sqfs_block_processor_t *proc,
 	sproc->status = proc->process_completed_block(proc, block);
 	return sproc->status;
 fail:
-	free_block_list(block->frag_list);
 	free(block);
 	return sproc->status;
 }
-- 
cgit v1.2.3