aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2016-12-08 15:19:49 -0800
committerAlex Deymo <deymo@google.com>2016-12-09 12:12:24 -0800
commit4445cd175ee8ed20fdec0537a76a6e3cb65fdb53 (patch)
tree79c30e3740fe95a56f81f0cf27df11fc89e7bfc7
parentec11d019bfbba513daa31caf53d33316c4deef62 (diff)
downloadsquashfs-tools-4445cd175ee8ed20fdec0537a76a6e3cb65fdb53.tar.gz
Fix rounding error when generating .map files.
This patch fixes the rounding of bytes to blocks in the .map file generation process so all blocks are assigned to files while still keeping the files not overlaping. This fixes the previous behavior where the last 4K-block of a file wouldn't be assigned to that block, even in the default 4k-align case leaving the last block of each file unassigned. To achieve this, we assign each block based on the first byte of the block, which prevents overlapping and assigns all the blocks. Bug: 28150981 Test: `make dist` compared system.map with the previous version. No more "gaps" observed. Change-Id: Ib1a77036a578725a25bafa28b4f86d9dc859adb2
-rw-r--r--squashfs-tools/mksquashfs.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
index a91fd9e..936ae05 100644
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -863,11 +863,29 @@ static inline unsigned int get_parent_no(struct dir_info *dir)
/* ANDROID CHANGES START*/
#ifdef ANDROID
+
+/* Round up the passed |n| value to the smallest multiple of 4096 greater or
+ * equal than |n| and return the 4K-block number for that value. */
+static unsigned long long round_up_block(unsigned long long n) {
+ const unsigned long long kMapBlockSize = 4096;
+ return (n + kMapBlockSize - 1) / kMapBlockSize;
+}
+
static inline void write_block_map_entry(char *sub_path, unsigned long long start_block, unsigned long long total_size,
char * mount_point, FILE *block_map_file) {
if (block_map_file) {
- unsigned long long round_start = (start_block + (1 << 12) - 1) >> 12;
- unsigned long long round_end = ((start_block + total_size) >> 12) - 1;
+ /* We assign each 4K block based on what file the first byte of the block
+ * belongs to. The current file consists of the chunk of bytes in the
+ * interval [start_block, start_block + total_size), (closed on the left end
+ * and open on the right end). We then compute the first block whose first
+ * byte is equal to or greater than start_block as |round_start| and then
+ * the first block whose first byte is *past* this interval, as
+ * |round_end + 1|. This means that the blocks that should be assigned to
+ * the current file are in the interval [round_start, round_end + 1), or
+ * simply [round_start, round_end].
+ */
+ unsigned long long round_start = round_up_block(start_block);
+ unsigned long long round_end = round_up_block(start_block + total_size) - 1;
if (round_start && total_size && round_start <= round_end) {
fprintf(block_map_file, "/%s", mount_point);
if (sub_path[0] != '/') fprintf(block_map_file, "/");