From 267508381a1d44930b4bd1018b231ba42a827a5f Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Sat, 9 Jul 2016 10:51:12 -0700 Subject: [PATCH] ART: Remove zygote OTA code The renaming and relabeling of the A/B artifacts is now done in a special-purpose script started by init, so as to not complicate the logic here (e.g., name of the current slot). Partially reverts commit 754479f7aa056602de8282f4f03718b42c20b89b. Bug: 25612095 Bug: 28069686 Change-Id: I4d965361000fd448e199c9af059b6d18bfe928bb (cherry picked from commit ff2a8ef2ed6b3f21da26f85197170d7d2a9f5134) --- runtime/gc/space/image_space.cc | 23 ------ runtime/gc/space/image_space_fs.h | 156 -------------------------------------- 2 files changed, 179 deletions(-) diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 8d406b343..6fcad295b 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -384,30 +384,7 @@ ImageSpace* ImageSpace::CreateBootImage(const char* image_location, &has_system, &cache_filename, &dalvik_cache_exists, &has_cache, &is_global_cache); - // If we're starting with the global cache, and we're the zygote, try to see whether there are - // OTA artifacts from the A/B OTA preopting to move over. - // (It is structurally simpler to check this here, instead of complicating the compile/relocate - // logic below.) const bool is_zygote = Runtime::Current()->IsZygote(); - if (is_global_cache && is_zygote) { - VLOG(startup) << "Checking for A/B OTA data."; - TryMoveOTAArtifacts(cache_filename, dalvik_cache_exists); - - // Retry. There are two cases where the old info is outdated: - // * There wasn't a boot image before (e.g., some failure on boot), but now the OTA preopted - // image has been moved in-place. - // * There was a boot image before, and we tried to move the OTA preopted image, but a failure - // happened and there is no file anymore. - found_image = FindImageFilename(image_location, - image_isa, - &system_filename, - &has_system, - &cache_filename, - &dalvik_cache_exists, - &has_cache, - &is_global_cache); - } - if (is_zygote && !secondary_image) { MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots()); } diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h index 4d539d205..fc9a3cfed 100644 --- a/runtime/gc/space/image_space_fs.h +++ b/runtime/gc/space/image_space_fs.h @@ -79,115 +79,6 @@ static void DeleteDirectoryContents(const std::string& dir, bool recurse) { CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; } -static bool HasContent(const char* dir) { - if (!OS::DirectoryExists(dir)) { - return false; - } - DIR* c_dir = opendir(dir); - if (c_dir == nullptr) { - PLOG(WARNING) << "Unable to open " << dir << " to delete it if empty"; - return false; - } - - for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) { - const char* name = de->d_name; - if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - continue; - } - // Something here. - CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; - return true; - } - CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; - return false; -} - -// Delete this directory, if empty. Then repeat with the parents. Skips non-existing directories. -// If stop_at isn't null, the recursion will stop when a directory with the given name is found. -static void DeleteEmptyDirectoriesUpTo(const std::string& dir, const char* stop_at) { - if (HasContent(dir.c_str())) { - return; - } - if (stop_at != nullptr) { - // This check isn't precise, but good enough in practice. - if (EndsWith(dir, stop_at)) { - return; - } - } - if (OS::DirectoryExists(dir.c_str())) { - if (rmdir(dir.c_str()) != 0) { - PLOG(ERROR) << "Unable to rmdir " << dir; - return; - } - } - size_t last_slash = dir.rfind('/'); - if (last_slash != std::string::npos) { - DeleteEmptyDirectoriesUpTo(dir.substr(0, last_slash), stop_at); - } -} - -static void MoveOTAArtifacts(const char* src, const char* trg) { - DCHECK(OS::DirectoryExists(src)); - DCHECK(OS::DirectoryExists(trg)); - - if (HasContent(trg)) { - LOG(WARNING) << "We do not support merging caches, but the target isn't empty: " << src - << " to " << trg; - return; - } - - if (rename(src, trg) != 0) { - PLOG(ERROR) << "Could not rename OTA cache " << src << " to target " << trg; - } -} - -// This is some dlopen/dlsym and hardcoded data to avoid a dependency on libselinux. Make sure -// this stays in sync! -static bool RelabelOTAFiles(const std::string& dalvik_cache_dir) { - // We only expect selinux on devices. Don't even attempt this on the host. - if (!kIsTargetBuild) { - return true; - } - - // Custom deleter, so we can use std::unique_ptr. - struct HandleDeleter { - void operator()(void* in) { - if (in != nullptr && dlclose(in) != 0) { - PLOG(ERROR) << "Could not close selinux handle."; - } - } - }; - - // Look for selinux library. - std::unique_ptr selinux_handle(dlopen("libselinux.so", RTLD_NOW)); - if (selinux_handle == nullptr) { - // Assume everything's OK if we can't open the library. - return true; - } - dlerror(); // Clean dlerror string. - - void* restorecon_ptr = dlsym(selinux_handle.get(), "selinux_android_restorecon"); - if (restorecon_ptr == nullptr) { - // Can't find the relabel function. That's bad. Make sure the zygote fails, as we have no - // other recourse to make this error obvious. - const char* error_string = dlerror(); - LOG(FATAL) << "Could not find selinux restorecon function: " - << ((error_string != nullptr) ? error_string : "(unknown error)"); - UNREACHABLE(); - } - - using RestoreconFn = int (*)(const char*, unsigned int); - constexpr unsigned int kRecursive = 4U; - - RestoreconFn restorecon_fn = reinterpret_cast(restorecon_ptr); - if (restorecon_fn(dalvik_cache_dir.c_str(), kRecursive) != 0) { - LOG(ERROR) << "Failed to restorecon " << dalvik_cache_dir; - return false; - } - - return true; -} - } // namespace impl @@ -272,53 +163,6 @@ static void MarkZygoteStart(const InstructionSet isa, const uint32_t max_failed_ } } -static void TryMoveOTAArtifacts(const std::string& cache_filename, bool dalvik_cache_exists) { - // We really assume here global means /data/dalvik-cache, and we'll inject 'ota.' Make sure - // that's true. - CHECK(StartsWith(cache_filename, "/data/dalvik-cache")) << cache_filename; - - // Inject ota subdirectory. - std::string ota_filename(cache_filename); - ota_filename = ota_filename.insert(strlen("/data/"), "ota/"); - CHECK(StartsWith(ota_filename, "/data/ota/dalvik-cache")) << ota_filename; - - // See if the file exists. - if (OS::FileExists(ota_filename.c_str())) { - VLOG(startup) << "OTA directory does exist, checking for artifacts"; - - size_t last_slash = ota_filename.rfind('/'); - CHECK_NE(last_slash, std::string::npos); - std::string ota_source_dir = ota_filename.substr(0, last_slash); - - // We need the dalvik cache now, really. - if (dalvik_cache_exists) { - size_t last_cache_slash = cache_filename.rfind('/'); - DCHECK_NE(last_cache_slash, std::string::npos); - std::string dalvik_cache_target_dir = cache_filename.substr(0, last_cache_slash); - - // First clean the target cache. - impl::DeleteDirectoryContents(dalvik_cache_target_dir.c_str(), false); - - // Now move things over. - impl::MoveOTAArtifacts(ota_source_dir.c_str(), dalvik_cache_target_dir.c_str()); - - // Last step: ensure the files have the right selinux label. - if (!impl::RelabelOTAFiles(dalvik_cache_target_dir)) { - // This isn't good. We potentially moved files, but they have the wrong label. Delete the - // files. - LOG(WARNING) << "Could not relabel files, must delete dalvik-cache."; - impl::DeleteDirectoryContents(dalvik_cache_target_dir.c_str(), false); - } - } - - // Cleanup. - impl::DeleteDirectoryContents(ota_source_dir.c_str(), true); - impl::DeleteEmptyDirectoriesUpTo(ota_source_dir, "ota"); - } else { - VLOG(startup) << "No OTA directory."; - } -} - } // namespace space } // namespace gc } // namespace art -- 2.11.0