From: David Anderson Date: Sat, 7 Dec 2019 00:48:52 +0000 (-0800) Subject: AOSP: e2fsdroid: Skip Base FS entries that no longer exist. X-Git-Tag: v1.45.5~16 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=67467ea5d742b05f7f3ccbee87aaa65656685e0d;p=tools%2Fe2fsprogs.git AOSP: e2fsdroid: Skip Base FS entries that no longer exist. Don't reserve blocks in the base map if the file does not exist in the target image. This can happen if a file is removed or renamed in between two builds. If the removed file is quite large, skipping it is important since otherwise it will prevent blocks from being allocated for new files. Bug: 145316683 Test: e2fsdroid with dynamic partitions Change-Id: I63a9372c58adeaae3e1235fd92fed78a284ed391 From AOSP commit: 2b6646a3d2a7dd9972275cb829239ae033762da5 --- diff --git a/contrib/android/basefs_allocator.c b/contrib/android/basefs_allocator.c index 3fe42a0..658a751 100644 --- a/contrib/android/basefs_allocator.c +++ b/contrib/android/basefs_allocator.c @@ -1,3 +1,4 @@ +#include #include #include #include "basefs_allocator.h" @@ -111,20 +112,39 @@ static void fs_reserve_blocks_range(ext2_filsys fs, * the actual block map. This prevents libext2fs from allocating them for * general purpose use, and ensures that if the file needs data blocks, they * can be re-acquired exclusively for that file. + * + * If a file in the base map is missing, or not a regular file in the new + * filesystem, then it's skipped to ensure that its blocks are reusable. */ -static void fs_reserve_blocks(ext2_filsys fs, - struct base_fs_allocator *allocator) +static errcode_t fs_reserve_blocks(ext2_filsys fs, + struct base_fs_allocator *allocator, + const char *src_dir) { + int nbytes; + char full_path[PATH_MAX]; + const char *sep = "/"; + struct stat st; struct basefs_entry *e; struct ext2fs_hashmap_entry *it = NULL; struct ext2fs_hashmap *entries = allocator->entries; - while ((e = ext2fs_hashmap_iter_in_order(entries, &it))) + if (strlen(src_dir) && src_dir[strlen(src_dir) - 1] == '/') + sep = ""; + + while ((e = ext2fs_hashmap_iter_in_order(entries, &it))) { + nbytes = snprintf(full_path, sizeof(full_path), "%s%s%s", + src_dir, sep, e->path); + if (nbytes >= sizeof(full_path)) + return ENAMETOOLONG; + if (lstat(full_path, &st) || !S_ISREG(st.st_mode)) + continue; fs_reserve_blocks_range(fs, allocator, &e->blocks); + } + return 0; } errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file, - const char *mountpoint) + const char *mountpoint, const char *src_dir) { errcode_t retval = 0; struct base_fs_allocator *allocator; @@ -154,7 +174,9 @@ errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file, if (retval) goto err_load; - fs_reserve_blocks(fs, allocator); + retval = fs_reserve_blocks(fs, allocator, src_dir); + if (retval) + goto err_load; /* Override the default allocator */ fs->get_alloc_block2 = basefs_block_allocator; @@ -200,6 +222,7 @@ static errcode_t basefs_block_allocator(ext2_filsys fs, blk64_t goal, errcode_t retval; struct base_fs_allocator *allocator = fs->priv_data; struct basefs_entry *e = allocator->cur_entry; + ext2fs_block_bitmap dedup_map = allocator->dedup_block_map; if (e && ctx && (ctx->flags & BLOCK_ALLOC_DATA)) { if (!get_next_block(fs, allocator, &e->blocks, ret)) @@ -207,10 +230,21 @@ static errcode_t basefs_block_allocator(ext2_filsys fs, blk64_t goal, } retval = ext2fs_new_block2(fs, goal, fs->block_map, ret); - if (retval) - return retval; - ext2fs_mark_block_bitmap2(fs->block_map, *ret); - return 0; + if (!retval) { + ext2fs_mark_block_bitmap2(fs->block_map, *ret); + return 0; + } + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) { + /* Try to steal a block from the dedup pool. */ + retval = ext2fs_find_first_set_block_bitmap2(dedup_map, + fs->super->s_first_data_block, + ext2fs_blocks_count(fs->super) - 1, ret); + if (!retval) { + ext2fs_unmark_block_bitmap2(dedup_map, *ret); + return 0; + } + } + return retval; } void base_fs_alloc_cleanup(ext2_filsys fs) diff --git a/contrib/android/basefs_allocator.h b/contrib/android/basefs_allocator.h index f1109cd..6d1c65e 100644 --- a/contrib/android/basefs_allocator.h +++ b/contrib/android/basefs_allocator.h @@ -5,7 +5,7 @@ # include errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file, - const char *mountpoint); + const char *mountpoint, const char *src_dir); void base_fs_alloc_cleanup(ext2_filsys fs); errcode_t base_fs_alloc_set_target(ext2_filsys fs, const char *target_path, diff --git a/contrib/android/e2fsdroid.c b/contrib/android/e2fsdroid.c index 3264a99..1beb1e2 100644 --- a/contrib/android/e2fsdroid.c +++ b/contrib/android/e2fsdroid.c @@ -301,7 +301,8 @@ int main(int argc, char *argv[]) if (src_dir) { ext2fs_read_bitmaps(fs); if (basefs_in) { - retval = base_fs_alloc_load(fs, basefs_in, mountpoint); + retval = base_fs_alloc_load(fs, basefs_in, mountpoint, + src_dir); if (retval) { com_err(prog_name, retval, "%s", "while reading base_fs file");