diff options
author | Tianjie Xu <xunchang@google.com> | 2019-07-10 19:40:37 +0200 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-07-10 19:40:37 +0200 |
commit | 5f408dd48a6ed4887d1c5e623ab7b702a6435137 (patch) | |
tree | e54980f253f5b28db706f1d3dc4a2086acc40212 | |
parent | Merge "Change the symlink to system_ext" (diff) | |
parent | Create a fallback to install from fuse if mmap fails (diff) | |
download | android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar.gz android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar.bz2 android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar.lz android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar.xz android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.tar.zst android_bootable_recovery-5f408dd48a6ed4887d1c5e623ab7b702a6435137.zip |
-rw-r--r-- | install/fuse_install.cpp | 7 | ||||
-rw-r--r-- | otautil/sysutil.cpp | 2 | ||||
-rw-r--r-- | recovery.cpp | 28 |
3 files changed, 29 insertions, 8 deletions
diff --git a/install/fuse_install.cpp b/install/fuse_install.cpp index ffde4a348..8a7a278e0 100644 --- a/install/fuse_install.cpp +++ b/install/fuse_install.cpp @@ -128,11 +128,12 @@ static bool StartInstallPackageFuse(std::string_view path) { constexpr auto FUSE_BLOCK_SIZE = 65536; bool is_block_map = android::base::ConsumePrefix(&path, "@"); - auto file_data_reader = + auto fuse_data_provider = is_block_map ? FuseBlockDataProvider::CreateFromBlockMap(std::string(path), FUSE_BLOCK_SIZE) : FuseFileDataProvider::CreateFromFile(std::string(path), FUSE_BLOCK_SIZE); - if (!file_data_reader->Valid()) { + if (!fuse_data_provider || !fuse_data_provider->Valid()) { + LOG(ERROR) << "Failed to create fuse data provider."; return false; } @@ -142,7 +143,7 @@ static bool StartInstallPackageFuse(std::string_view path) { umount2(SDCARD_ROOT, MNT_DETACH); } - return run_fuse_sideload(std::move(file_data_reader)) == 0; + return run_fuse_sideload(std::move(fuse_data_provider)) == 0; } InstallResult InstallWithFuseFromPath(std::string_view path, RecoveryUI* ui) { diff --git a/otautil/sysutil.cpp b/otautil/sysutil.cpp index a8829858d..6cd46c6a9 100644 --- a/otautil/sysutil.cpp +++ b/otautil/sysutil.cpp @@ -38,7 +38,7 @@ BlockMapData BlockMapData::ParseBlockMapFile(const std::string& block_map_path) { std::string content; if (!android::base::ReadFileToString(block_map_path, &content)) { - LOG(ERROR) << "Failed to read " << block_map_path; + PLOG(ERROR) << "Failed to read " << block_map_path; return {}; } diff --git a/recovery.cpp b/recovery.cpp index b18a8e74a..97ca0a504 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -84,6 +84,8 @@ const char* reason = nullptr; * * The arguments which may be supplied in the recovery.command file: * --update_package=path - verify install an OTA package file + * --install_with_fuse - install the update package with FUSE. This allows installation of large + * packages on LP32 builds. Since the mmap will otherwise fail due to out of memory. * --wipe_data - erase user data (and cache), then reboot * --prompt_and_wipe_data - prompt the user that data is corrupt, with their consent erase user * data (and cache), then reboot @@ -577,6 +579,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri static constexpr struct option OPTIONS[] = { { "fastboot", no_argument, nullptr, 0 }, { "fsck_unshare_blocks", no_argument, nullptr, 0 }, + { "install_with_fuse", no_argument, nullptr, 0 }, { "just_exit", no_argument, nullptr, 'x' }, { "locale", required_argument, nullptr, 0 }, { "prompt_and_wipe_data", no_argument, nullptr, 0 }, @@ -597,6 +600,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri }; const char* update_package = nullptr; + bool install_with_fuse = false; // memory map the update package by default. bool should_wipe_data = false; bool should_prompt_and_wipe_data = false; bool should_wipe_cache = false; @@ -632,6 +636,8 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri std::string option = OPTIONS[option_index].name; if (option == "fsck_unshare_blocks") { fsck_unshare_blocks = true; + } else if (option == "install_with_fuse") { + install_with_fuse = true; } else if (option == "locale" || option == "fastboot") { // Handled in recovery_main.cpp } else if (option == "prompt_and_wipe_data") { @@ -737,10 +743,24 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } else { ensure_path_mounted(update_package); } - // TODO(xunchang) install package from fuse for large packages on ILP32 builds. - auto package = Package::CreateMemoryPackage( - update_package, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); - status = InstallPackage(package.get(), update_package, should_wipe_cache, retry_count, ui); + + if (install_with_fuse) { + LOG(INFO) << "Installing package " << update_package << " with fuse"; + status = InstallWithFuseFromPath(update_package, ui); + } else if (auto memory_package = Package::CreateMemoryPackage( + update_package, + std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); + memory_package != nullptr) { + status = InstallPackage(memory_package.get(), update_package, should_wipe_cache, + retry_count, ui); + } else { + // We may fail to memory map the package on 32 bit builds for packages with 2GiB+ size. + // In such cases, we will try to install the package with fuse. This is not the default + // installation method because it introduces a layer of indirection from the kernel space. + LOG(WARNING) << "Failed to memory map package " << update_package + << "; falling back to install with fuse"; + status = InstallWithFuseFromPath(update_package, ui); + } if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); |