diff --git a/Checkpoint.cpp b/Checkpoint.cpp index 1762521..1a89039 100644 --- a/Checkpoint.cpp +++ b/Checkpoint.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,11 @@ #include #include #include +#include +#include +using android::base::GetBoolProperty; +using android::base::GetUintProperty; using android::base::SetProperty; using android::binder::Status; using android::fs_mgr::Fstab; @@ -126,7 +131,7 @@ Status cp_startCheckpoint(int retry) { namespace { -bool isCheckpointing = false; +volatile bool isCheckpointing = false; } Status cp_commitChanges() { @@ -255,6 +260,53 @@ bool cp_needsCheckpoint() { return false; } +namespace { +const std::string kSleepTimeProp = "ro.sys.cp_usleeptime"; +const uint32_t usleeptime_default = 1000; // 1 s + +const std::string kMinFreeBytesProp = "ro.sys.cp_min_free_bytes"; +const uint64_t min_free_bytes_default = 100 * (1 << 20); // 100 MiB + +const std::string kCommitOnFullProp = "ro.sys.cp_commit_on_full"; +const bool commit_on_full_default = true; + +static void cp_healthDaemon(std::string mnt_pnt, std::string blk_device, bool is_fs_cp) { + struct statvfs data; + uint64_t free_bytes = 0; + uint32_t usleeptime = GetUintProperty(kSleepTimeProp, usleeptime_default, (uint32_t)-1); + uint64_t min_free_bytes = GetUintProperty(kSleepTimeProp, min_free_bytes_default, (uint64_t)-1); + bool commit_on_full = GetBoolProperty(kCommitOnFullProp, commit_on_full_default); + + while (isCheckpointing) { + if (is_fs_cp) { + statvfs(mnt_pnt.c_str(), &data); + free_bytes = data.f_bavail * data.f_frsize; + } else { + int ret; + std::string size_filename = std::string("/sys/") + blk_device.substr(5) + "/bow/free"; + std::string content; + ret = android::base::ReadFileToString(kMetadataCPFile, &content); + if (ret) { + free_bytes = std::strtoul(content.c_str(), NULL, 10); + } + } + if (free_bytes < min_free_bytes) { + if (commit_on_full) { + LOG(INFO) << "Low space for checkpointing. Commiting changes"; + cp_commitChanges(); + break; + } else { + LOG(INFO) << "Low space for checkpointing. Rebooting"; + cp_abortChanges("checkpoint,low_space", false); + break; + } + } + usleep(usleeptime); + } +} + +} // namespace + Status cp_prepareCheckpoint() { if (!isCheckpointing) { return Status::ok(); @@ -286,6 +338,12 @@ Status cp_prepareCheckpoint() { setBowState(mount_rec.blk_device, "1"); } + if (fstab_rec->fs_mgr_flags.checkpoint_blk || fstab_rec->fs_mgr_flags.checkpoint_fs) { + std::thread(cp_healthDaemon, std::string(mount_rec.mount_point), + std::string(mount_rec.mount_point), + fstab_rec->fs_mgr_flags.checkpoint_fs == 1) + .detach(); + } } return Status::ok(); }