| From d88f281f827a681928609af0f917e6970c805f52 Mon Sep 17 00:00:00 2001 |
| From: Amin Hassani <ahassani@google.com> |
| Date: Thu, 15 Dec 2016 10:43:15 -0800 |
| Subject: [PATCH] mksquashfs 4K aligns the files inside the squashfs image |
| |
| Files inside a squashfs image are not necessarily 4k (4096) |
| aligned. This patch starts each file in a 4k aligned address and pads |
| zero to the end of the file until it reaches the next 4k aligned |
| address. This will not change the size of the compressed |
| blocks (especially the last one) and hence it will not change how the |
| files are being loaded in kernel or unsquashfs. However on average this |
| increases the size of the squashfs image which can be calculated by the |
| following formula: |
| |
| increased_size = (number_of_unfragmented_files_in_image + number of fragments) * 2048 |
| |
| The 4k alignment can be enabled by flag '-4k-align' |
| --- |
| squashfs-tools/mksquashfs.c | 20 +++++++++++++++++--- |
| 1 file changed, 17 insertions(+), 3 deletions(-) |
| |
| diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c |
| index ba28d65..a6f3bcb 100644 |
| --- a/squashfs-tools/mksquashfs.c |
| +++ b/squashfs-tools/mksquashfs.c |
| @@ -179,6 +179,8 @@ int exit_on_error = FALSE; |
| |
| /* Is filesystem stored at an offset from the start of the block device/file? */ |
| long long start_offset = 0; |
| +int do_4k_align = FALSE; |
| +#define ALIGN_UP(bytes, size) (bytes = (bytes + size - 1) & ~(size - 1)) |
| |
| /* File count statistics used to print summary and fill in superblock */ |
| unsigned int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, |
| @@ -1624,6 +1626,9 @@ static void unlock_fragments() |
| * queue at this time. |
| */ |
| while(!queue_empty(locked_fragment)) { |
| + // 4k align the start of remaining queued fragments. |
| + if(do_4k_align) |
| + ALIGN_UP(bytes, 4096); |
| write_buffer = queue_get(locked_fragment); |
| frg = write_buffer->block; |
| size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[frg].size); |
| @@ -2627,6 +2632,9 @@ static void *frag_deflator(void *arg) |
| write_buffer->size = compressed_size; |
| pthread_mutex_lock(&fragment_mutex); |
| if(fragments_locked == FALSE) { |
| + // 4k align the start of each fragment. |
| + if(do_4k_align) |
| + ALIGN_UP(bytes, 4096); |
| fragment_table[file_buffer->block].size = c_byte; |
| fragment_table[file_buffer->block].start_block = bytes; |
| write_buffer->block = bytes; |
| @@ -3024,6 +3032,10 @@ static struct file_info *write_file_blocks(int *status, struct dir_ent *dir_ent, |
| struct file_info *file; |
| int bl_hash = 0; |
| |
| + // 4k align the start of each file. |
| + if(do_4k_align) |
| + ALIGN_UP(bytes, 4096); |
| + |
| if(pre_duplicate(read_size, dir_ent->inode, read_buffer, &bl_hash)) |
| return write_file_blocks_dup(status, dir_ent, read_buffer, dup, bl_hash); |
| |
| @@ -5825,9 +5837,6 @@ static void write_filesystem_tables(struct squashfs_super_block *sBlk) |
| |
| SQUASHFS_INSWAP_SUPER_BLOCK(sBlk); |
| write_destination(fd, SQUASHFS_START, sizeof(*sBlk), sBlk); |
| - |
| - total_bytes += total_inode_bytes + total_directory_bytes + |
| - sizeof(struct squashfs_super_block) + total_xattr_bytes; |
| } |
| |
| |
| @@ -6240,6 +6249,7 @@ static void print_options(FILE *stream, char *name, int total_mem) |
| fprintf(stream, "create a root\n"); |
| fprintf(stream, "\t\t\tdirectory containing that directory, rather than the\n"); |
| fprintf(stream, "\t\t\tcontents of the directory\n"); |
| + fprintf(stream, "-4k-align\t\tenables 4k alignment of all files\n"); |
| fprintf(stream, "\nFilesystem filter options:\n"); |
| fprintf(stream, "-p <pseudo-definition>\tadd pseudo file "); |
| fprintf(stream, "definition. The definition should\n"); |
| @@ -6529,6 +6539,7 @@ static void print_sqfstar_options(FILE *stream, char *name, int total_mem) |
| fprintf(stream, "-no-tailends\t\tdo not pack tail ends into fragments\n"); |
| fprintf(stream, "-no-duplicates\t\tdo not perform duplicate checking\n"); |
| fprintf(stream, "-no-hardlinks\t\tdo not hardlink files, instead store duplicates\n"); |
| + fprintf(stream, "-4k-align\t\tenables 4k alignment of all files\n"); |
| fprintf(stream, "\nFilesystem filter options:\n"); |
| fprintf(stream, "-p <pseudo-definition>\tadd pseudo file "); |
| fprintf(stream, "definition. The definition should\n"); |
| @@ -6693,6 +6704,7 @@ static void print_summary() |
| "compressed", no_fragments ? "no" : noF ? "uncompressed" : |
| "compressed", no_xattrs ? "no" : noX ? "uncompressed" : |
| "compressed", noI || noId ? "uncompressed" : "compressed"); |
| + printf("\t4k %saligned\n", do_4k_align ? "" : "un"); |
| printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : |
| "not "); |
| printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, |
| @@ -8420,6 +8432,8 @@ print_compressor_options: |
| } else if(strcmp(argv[i], "-comp") == 0) { |
| /* parsed previously */ |
| i++; |
| + } else if(strcmp(argv[i], "-4k-align") == 0) { |
| + do_4k_align = TRUE; |
| } else { |
| ERROR("%s: invalid option\n\n", argv[0]); |
| print_options(stderr, argv[0], total_mem); |
| -- |
| 2.43.0.472.g3155946c3a-goog |
| |