1bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe/* 2bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * Copyright (C) 2016 The Android Open Source Project 3bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * 4bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 5bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * you may not use this file except in compliance with the License. 6bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * You may obtain a copy of the License at 7bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * 8bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 9bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * 10bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * Unless required by applicable law or agreed to in writing, software 11bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 12bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * See the License for the specific language governing permissions and 14bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe * limitations under the License. 15bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe */ 16bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 17bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_ 18bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_ 19bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 20bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include <dirent.h> 21bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include <dlfcn.h> 22bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 23bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "base/logging.h" 24bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "base/macros.h" 25bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "base/stringprintf.h" 26bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "base/unix_file/fd_file.h" 27bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "globals.h" 28bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "os.h" 29a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe#include "runtime.h" 30bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#include "utils.h" 31bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 32bec635813789a7365900d3db01c16e12a20c2815Andreas Gampenamespace art { 33bec635813789a7365900d3db01c16e12a20c2815Andreas Gampenamespace gc { 34bec635813789a7365900d3db01c16e12a20c2815Andreas Gampenamespace space { 35bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 36bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// This file contains helper code for ImageSpace. It has most of the file-system 37bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// related code, including handling A/B OTA. 38bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 39bec635813789a7365900d3db01c16e12a20c2815Andreas Gampenamespace impl { 40bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 41bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// Delete the directory and its (regular or link) contents. If the recurse flag is true, delete 42bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// sub-directories recursively. 43bec635813789a7365900d3db01c16e12a20c2815Andreas Gampestatic void DeleteDirectoryContents(const std::string& dir, bool recurse) { 44bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (!OS::DirectoryExists(dir.c_str())) { 45bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe return; 46bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 47bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe DIR* c_dir = opendir(dir.c_str()); 48bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (c_dir == nullptr) { 49bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents"; 50bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe return; 51bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 52bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 53bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) { 54bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe const char* name = de->d_name; 55bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 56bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe continue; 57bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 58bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe // We only want to delete regular files and symbolic links. 59bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe std::string file = StringPrintf("%s/%s", dir.c_str(), name); 60bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (de->d_type != DT_REG && de->d_type != DT_LNK) { 61bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (de->d_type == DT_DIR) { 62bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (recurse) { 63bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe DeleteDirectoryContents(file, recurse); 64bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe // Try to rmdir the directory. 6566fdcbdb1fde4bf65da5e801ba76a8e65391635bVladimir Marko if (rmdir(file.c_str()) != 0) { 66bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(ERROR) << "Unable to rmdir " << file; 67bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 68bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 69bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } else { 70bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe LOG(WARNING) << "Unexpected file type of " << std::hex << de->d_type << " encountered."; 71bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 72bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } else { 73bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe // Try to unlink the file. 7466fdcbdb1fde4bf65da5e801ba76a8e65391635bVladimir Marko if (unlink(file.c_str()) != 0) { 75bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(ERROR) << "Unable to unlink " << file; 76bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 77bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 78bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 7966fdcbdb1fde4bf65da5e801ba76a8e65391635bVladimir Marko CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; 80bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} 81bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 82bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} // namespace impl 83bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 84bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 85bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// We are relocating or generating the core image. We should get rid of everything. It is all 86bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// out-of-date. We also don't really care if this fails since it is just a convenience. 87bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// Adapted from prune_dex_cache(const char* subdir) in frameworks/native/cmds/installd/commands.c 88bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// Note this should only be used during first boot. 89bec635813789a7365900d3db01c16e12a20c2815Andreas Gampestatic void PruneDalvikCache(InstructionSet isa) { 90bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe CHECK_NE(isa, kNone); 91bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe // Prune the base /data/dalvik-cache. 92bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe impl::DeleteDirectoryContents(GetDalvikCacheOrDie(".", false), false); 93bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe // Prune /data/dalvik-cache/<isa>. 94bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe impl::DeleteDirectoryContents(GetDalvikCacheOrDie(GetInstructionSetString(isa), false), false); 95a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe 96a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe // Be defensive. There should be a runtime created here, but this may be called in a test. 97a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe if (Runtime::Current() != nullptr) { 98a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe Runtime::Current()->SetPrunedDalvikCache(true); 99a1425a1c9c98ae3fc772834933a5d55566fb5699Andreas Gampe } 100bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} 101bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 102bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// We write out an empty file to the zygote's ISA specific cache dir at the start of 103bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// every zygote boot and delete it when the boot completes. If we find a file already 104bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// present, it usually means the boot didn't complete. We wipe the entire dalvik 105bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe// cache if that's the case. 106bec635813789a7365900d3db01c16e12a20c2815Andreas Gampestatic void MarkZygoteStart(const InstructionSet isa, const uint32_t max_failed_boots) { 107bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe const std::string isa_subdir = GetDalvikCacheOrDie(GetInstructionSetString(isa), false); 108bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe const std::string boot_marker = isa_subdir + "/.booting"; 109bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe const char* file_name = boot_marker.c_str(); 110bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 111bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe uint32_t num_failed_boots = 0; 112bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe std::unique_ptr<File> file(OS::OpenFileReadWrite(file_name)); 113bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (file.get() == nullptr) { 114bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe file.reset(OS::CreateEmptyFile(file_name)); 115bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 116bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (file.get() == nullptr) { 117f242f66cf7137ef681e44a494758976e11579260Andreas Gampe int saved_errno = errno; 118bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Failed to create boot marker."; 119f242f66cf7137ef681e44a494758976e11579260Andreas Gampe if (saved_errno != ENOSPC) { 120f242f66cf7137ef681e44a494758976e11579260Andreas Gampe return; 121f242f66cf7137ef681e44a494758976e11579260Andreas Gampe } 122f242f66cf7137ef681e44a494758976e11579260Andreas Gampe 123f242f66cf7137ef681e44a494758976e11579260Andreas Gampe LOG(WARNING) << "Pruning dalvik cache because of low-memory situation."; 124f242f66cf7137ef681e44a494758976e11579260Andreas Gampe impl::DeleteDirectoryContents(isa_subdir, false); 125f242f66cf7137ef681e44a494758976e11579260Andreas Gampe 126f242f66cf7137ef681e44a494758976e11579260Andreas Gampe // Try once more. 127f242f66cf7137ef681e44a494758976e11579260Andreas Gampe file.reset(OS::OpenFileReadWrite(file_name)); 128f242f66cf7137ef681e44a494758976e11579260Andreas Gampe if (file == nullptr) { 129f242f66cf7137ef681e44a494758976e11579260Andreas Gampe PLOG(WARNING) << "Failed to create boot marker."; 130f242f66cf7137ef681e44a494758976e11579260Andreas Gampe return; 131f242f66cf7137ef681e44a494758976e11579260Andreas Gampe } 132bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 133bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } else { 134bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (!file->ReadFully(&num_failed_boots, sizeof(num_failed_boots))) { 135bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Failed to read boot marker."; 136bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe file->Erase(); 137bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe return; 138bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 139bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 140bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 141bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (max_failed_boots != 0 && num_failed_boots > max_failed_boots) { 142bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe LOG(WARNING) << "Incomplete boot detected. Pruning dalvik cache"; 143bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe impl::DeleteDirectoryContents(isa_subdir, false); 144bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 145bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 146bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe ++num_failed_boots; 147bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe VLOG(startup) << "Number of failed boots on : " << boot_marker << " = " << num_failed_boots; 148bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 149bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (lseek(file->Fd(), 0, SEEK_SET) == -1) { 150bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Failed to write boot marker."; 151bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe file->Erase(); 152bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe return; 153bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 154bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 155bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (!file->WriteFully(&num_failed_boots, sizeof(num_failed_boots))) { 156bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Failed to write boot marker."; 157bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe file->Erase(); 158bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe return; 159bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 160bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 161bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe if (file->FlushCloseOrErase() != 0) { 162bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe PLOG(WARNING) << "Failed to flush boot marker."; 163bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe } 164bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} 165bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 166bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} // namespace space 167bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} // namespace gc 168bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe} // namespace art 169bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe 170bec635813789a7365900d3db01c16e12a20c2815Andreas Gampe#endif // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_ 171