mksquashfs: queue fragment and empty file buffers directly to main thread

Queue these buffers directly to the main thread, rather than
queuing them to the deflate threads which pass them to the main thread.

For empty file buffers these are passed directly to the main thread,
and it is unnecessary overhead to pass them to the deflate threads.
For fragments these were passed to the deflate threads for sparse
checking, but move sparse checking for fragments to the main
thread.

Doing this frees up the deflate threads to concentrate on
compressing buffers.  It also means the reader thread to deflate
queue now accurately represents the number of uncompressed
buffers in flight to the deflate threads, without the value being
obscured by the presence of the other buffers.  The number of
uncompressed fragment buffers in flight from the reader thead
to the main thread can be seen from the uncompressed fragment queue.

Also add a function which centralises the logic which decides where
to send the buffers.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
index 4601aa8..0aa5c69 100644
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -1932,11 +1932,28 @@
 	if(inode->noF != noF)
 		return FALSE;
 
-	return !inode->no_fragments && (file_size < block_size ||
+	return !inode->no_fragments && file_size && (file_size < block_size ||
 		(inode->always_use_fragments && file_size & (block_size - 1)));
 }
 
 
+void put_file_buffer(struct file_buffer *file_buffer)
+{
+	/*
+	 * Decide where to send the file buffer - only compressible non-
+	 * fragment blocks need to be send to the deflate threads, all
+	 * others can be sent directly to the main thread
+	 */
+	if(file_buffer->error) {
+		file_buffer->fragment = 0;
+		seq_queue_put(from_deflate, file_buffer);
+	} else if (file_buffer->file_size == 0 || file_buffer->fragment)
+		seq_queue_put(from_deflate, file_buffer);
+	else
+		queue_put(from_reader, file_buffer);
+}
+
+
 static int seq = 0;
 void reader_read_process(struct dir_ent *dir_ent)
 {
@@ -1976,7 +1993,7 @@
 		progress_bar_size(1);
 
 		if(prev_buffer)
-			queue_put(from_reader, prev_buffer);
+			put_file_buffer(prev_buffer);
 		prev_buffer = file_buffer;
 	}
 
@@ -1998,7 +2015,7 @@
 	}
 	prev_buffer->file_size = bytes;
 	prev_buffer->fragment = is_fragment(inode);
-	queue_put(from_reader, prev_buffer);
+	put_file_buffer(prev_buffer);
 
 	return;
 
@@ -2009,7 +2026,7 @@
 		file_buffer = prev_buffer;
 	}
 	file_buffer->error = TRUE;
-	seq_queue_put(from_deflate, file_buffer);
+	put_file_buffer(file_buffer);
 }
 
 
@@ -2045,7 +2062,7 @@
 			read_size - ((long long) count * block_size);
 
 		if(file_buffer)
-			queue_put(from_reader, file_buffer);
+			put_file_buffer(file_buffer);
 		file_buffer = cache_get_nohash(reader_buffer);
 		file_buffer->sequence = seq ++;
 		file_buffer->noD = inode->noD;
@@ -2099,7 +2116,7 @@
 	}
 
 	file_buffer->fragment = is_fragment(inode);
-	queue_put(from_reader, file_buffer);
+	put_file_buffer(file_buffer);
 
 	close(file);
 
@@ -2117,14 +2134,14 @@
 		close(file);
 		memcpy(buf, &buf2, sizeof(struct stat));
 		file_buffer->error = 2;
-		seq_queue_put(from_deflate, file_buffer);
+		put_file_buffer(file_buffer);
 		goto again;
 	}
 read_err:
 	close(file);
 read_err2:
 	file_buffer->error = TRUE;
-	seq_queue_put(from_deflate, file_buffer);
+	put_file_buffer(file_buffer);
 }
 
 
@@ -2241,15 +2258,9 @@
 		struct file_buffer *file_buffer = queue_get(from_reader);
 		struct file_buffer *write_buffer;
 
-		if(file_buffer->file_size == 0) {
+		if(sparse_files && all_zero(file_buffer)) { 
 			file_buffer->c_byte = 0;
 			seq_queue_put(from_deflate, file_buffer);
-		} else if(sparse_files && all_zero(file_buffer)) { 
-			file_buffer->c_byte = 0;
-			seq_queue_put(from_deflate, file_buffer);
-		} else if(file_buffer->fragment) {
-			file_buffer->c_byte = file_buffer->size;
-			seq_queue_put(from_deflate, file_buffer);
 		} else {
 			write_buffer = cache_get(writer_buffer, -1);
 			write_buffer->c_byte = mangle2(stream,
@@ -2318,7 +2329,16 @@
 
 struct file_buffer *get_file_buffer(struct seq_queue *queue)
 {
-	return seq_queue_get(queue);
+	struct file_buffer *file_buffer = seq_queue_get(queue);
+
+	if(file_buffer->fragment) {
+		if(sparse_files && all_zero(file_buffer))
+			file_buffer->c_byte = 0;
+		else
+			file_buffer->c_byte = file_buffer->size;
+	}
+
+	return file_buffer;
 }