Whamcloud - gitweb
AOSP: e2fsdroid: Properly free the dedup block map.
authorDavid Anderson <dvander@google.com>
Wed, 29 Jan 2020 23:31:14 +0000 (15:31 -0800)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 21 Mar 2020 03:15:01 +0000 (23:15 -0400)
When BaseFS specifies the same block for two files, it gets added to a
separate "dedup" bitmap, and removed from the free block bitmap. If the
new build does not use every block in this bitmap, there will be an
inconsistency: the block bitmap marks blocks as in-use when they are
actually free. Although this doesn't matter for AOSP's read-only file
systems, it does cause e2fsck to complain, which breaks the build.

Fix the inconsistency by properly freeing all unused blocks within the
dedup block set.

Bug: 139201772
Test: build AOSP using BaseFS
Change-Id: I6b6511eb713a56fec932f1d5668f1766d64d9479
From AOSP commit: 346bee6f8b97aefe7714688f738606c116099fbc

contrib/android/basefs_allocator.c

index 658a751..325aed8 100644 (file)
@@ -39,6 +39,28 @@ static void fs_free_blocks_range(ext2_filsys fs,
        }
 }
 
+/*
+ * Free any blocks in the bitmap that were reserved but never used. This is
+ * needed to free dedup_block_map and ensure the free block bitmap is
+ * internally consistent.
+ */
+static void fs_free_blocks_bitmap(ext2_filsys fs, ext2fs_block_bitmap bitmap)
+{
+       blk64_t block = 0;
+       blk64_t start = fs->super->s_first_data_block;
+       blk64_t end = ext2fs_blocks_count(fs->super) - 1;
+       errcode_t retval;
+
+       for (;;) {
+               retval = ext2fs_find_first_set_block_bitmap2(bitmap, start, end,
+                       &block);
+               if (retval)
+                       break;
+               ext2fs_unmark_block_bitmap2(fs->block_map, block);
+               start = block + 1;
+       }
+}
+
 static void basefs_allocator_free(ext2_filsys fs,
                                  struct base_fs_allocator *allocator)
 {
@@ -53,6 +75,7 @@ static void basefs_allocator_free(ext2_filsys fs,
                }
                ext2fs_hashmap_free(entries);
        }
+       fs_free_blocks_bitmap(fs, allocator->dedup_block_map);
        ext2fs_free_block_bitmap(allocator->exclusive_block_map);
        ext2fs_free_block_bitmap(allocator->dedup_block_map);
        free(allocator);