/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "Checkpoint"
#include "Checkpoint.h"
#include "VoldUtil.h"

#include <fstream>
#include <list>
#include <memory>
#include <string>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <cutils/android_reboot.h>
#include <fcntl.h>
#include <fs_mgr.h>
#include <linux/fs.h>
#include <mntent.h>
#include <sys/mount.h>
#include <sys/stat.h>

using android::base::SetProperty;
using android::binder::Status;
using android::fs_mgr::Fstab;
using android::fs_mgr::ReadDefaultFstab;
using android::fs_mgr::ReadFstabFromFile;
using android::hardware::hidl_string;
using android::hardware::boot::V1_0::BoolResult;
using android::hardware::boot::V1_0::CommandResult;
using android::hardware::boot::V1_0::IBootControl;
using android::hardware::boot::V1_0::Slot;

namespace android {
namespace vold {

namespace {
const std::string kMetadataCPFile = "/metadata/vold/checkpoint";

bool setBowState(std::string const& block_device, std::string const& state) {
    if (block_device.substr(0, 5) != "/dev/") {
        LOG(ERROR) << "Expected block device, got " << block_device;
        return false;
    }

    std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
    if (!android::base::WriteStringToFile(state, state_filename)) {
        PLOG(ERROR) << "Failed to write to file " << state_filename;
        return false;
    }

    return true;
}

}  // namespace

Status cp_supportsCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_supportsBlockCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_blk) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_supportsFileCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_fs) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_startCheckpoint(int retry) {
    if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
    std::string content = std::to_string(retry + 1);
    if (retry == -1) {
        sp<IBootControl> module = IBootControl::getService();
        if (module) {
            std::string suffix;
            auto cb = [&suffix](hidl_string s) { suffix = s; };
            if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
        }
    }
    if (!android::base::WriteStringToFile(content, kMetadataCPFile))
        return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
    return Status::ok();
}

namespace {

bool isCheckpointing = false;
}

Status cp_commitChanges() {
    if (!isCheckpointing) {
        return Status::ok();
    }
    sp<IBootControl> module = IBootControl::getService();
    if (module) {
        CommandResult cr;
        module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
        if (!cr.success) {
            std::string msg = "Error marking booted successfully: " + std::string(cr.errMsg);
            return Status::fromExceptionCode(EINVAL, String8(msg.c_str()));
        }
        LOG(INFO) << "Marked slot as booted successfully.";
    }
    // Must take action for list of mounted checkpointed things here
    // To do this, we walk the list of mounted file systems.
    // But we also need to get the matching fstab entries to see
    // the original flags
    std::string err_str;

    Fstab mounts;
    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
    }

    // Walk mounted file systems
    for (const auto& mount_rec : mounts) {
        const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
        if (!fstab_rec) continue;

        if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
            if (fstab_rec->fs_type == "f2fs") {
                std::string options = mount_rec.fs_options + ",checkpoint=enable";
                if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
                          MS_REMOUNT | fstab_rec->flags, options.c_str())) {
                    return Status::fromExceptionCode(EINVAL, "Failed to remount");
                }
            }
        } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
            if (!setBowState(mount_rec.blk_device, "2"))
                return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
        }
    }
    SetProperty("vold.checkpoint_committed", "1");
    LOG(INFO) << "Checkpoint has been committed.";
    isCheckpointing = false;
    if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
        return Status::fromExceptionCode(errno, err_str.c_str());
    return Status::ok();
}

namespace {
void abort_metadata_file() {
    std::string oldContent, newContent;
    int retry = 0;
    struct stat st;
    int result = stat(kMetadataCPFile.c_str(), &st);

    // If the file doesn't exist, we aren't managing a checkpoint retry counter
    if (result != 0) return;
    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
        PLOG(ERROR) << "Failed to read checkpoint file";
        return;
    }
    std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));

    if (!android::base::ParseInt(retryContent, &retry)) {
        PLOG(ERROR) << "Could not parse retry count";
        return;
    }
    if (retry > 0) {
        newContent = "0";
        if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
            PLOG(ERROR) << "Could not write checkpoint file";
    }
}
}  // namespace

void cp_abortChanges(const std::string& message, bool retry) {
    if (!cp_needsCheckpoint()) return;
    if (!retry) abort_metadata_file();
    android_reboot(ANDROID_RB_RESTART2, 0, message.c_str());
}

bool cp_needsRollback() {
    std::string content;
    bool ret;

    ret = android::base::ReadFileToString(kMetadataCPFile, &content);
    if (ret) {
        if (content == "0") return true;
        if (content.substr(0, 3) == "-1 ") {
            std::string oldSuffix = content.substr(3);
            sp<IBootControl> module = IBootControl::getService();
            std::string newSuffix;

            if (module) {
                auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
                module->getSuffix(module->getCurrentSlot(), cb);
                if (oldSuffix == newSuffix) return true;
            }
        }
    }
    return false;
}

bool cp_needsCheckpoint() {
    bool ret;
    std::string content;
    sp<IBootControl> module = IBootControl::getService();

    if (isCheckpointing) return isCheckpointing;

    if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
        isCheckpointing = true;
        return true;
    }
    ret = android::base::ReadFileToString(kMetadataCPFile, &content);
    if (ret) {
        ret = content != "0";
        isCheckpointing = ret;
        return ret;
    }
    return false;
}

Status cp_prepareCheckpoint() {
    if (!isCheckpointing) {
        return Status::ok();
    }

    Fstab mounts;
    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
    }

    for (const auto& mount_rec : mounts) {
        const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
        if (!fstab_rec) continue;

        if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
            android::base::unique_fd fd(
                TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
            if (!fd) {
                PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
                continue;
            }

            struct fstrim_range range = {};
            range.len = ULLONG_MAX;
            if (ioctl(fd, FITRIM, &range)) {
                PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
                continue;
            }

            setBowState(mount_rec.blk_device, "1");
        }
    }
    return Status::ok();
}

namespace {
const int kSectorSize = 512;

typedef uint64_t sector_t;

struct log_entry {
    sector_t source;  // in sectors of size kSectorSize
    sector_t dest;    // in sectors of size kSectorSize
    uint32_t size;    // in bytes
    uint32_t checksum;
} __attribute__((packed));

struct log_sector_v1_0 {
    uint32_t magic;
    uint16_t header_version;
    uint16_t header_size;
    uint32_t block_size;
    uint32_t count;
    uint32_t sequence;
    uint64_t sector0;
} __attribute__((packed));

// MAGIC is BOW in ascii
const int kMagic = 0x00574f42;
// Partially restored MAGIC is WOB in ascii
const int kPartialRestoreMagic = 0x00424f57;

void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
    static uint32_t table[0x100] = {
        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
        0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
        0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
        0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
        0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
        0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
        0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
        0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
        0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
        0xB6662D3D,

        0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
        0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
        0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
        0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
        0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
        0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
        0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
        0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
        0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
        0xC0BA6CAD,

        0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
        0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
        0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
        0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
        0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
        0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
        0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
        0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
        0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
        0x5BDEAE1D,

        0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
        0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
        0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
        0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
        0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
        0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
        0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
        0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
        0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
        0x2D02EF8D};

    for (size_t i = 0; i < n_bytes; ++i) {
        *crc ^= ((uint8_t*)data)[i];
        *crc = table[(uint8_t)*crc] ^ *crc >> 8;
    }
}

// A map of relocations.
// The map must be initialized so that relocations[0] = 0
// During restore, we replay the log records in reverse, copying from dest to
// source
// To validate, we must be able to read the 'dest' sectors as though they had
// been copied but without actually copying. This map represents how the sectors
// would have been moved. To read a sector s, find the index <= s and read
// relocations[index] + s - index
typedef std::map<sector_t, sector_t> Relocations;

void relocate(Relocations& relocations, sector_t dest, sector_t source, int count) {
    // Find first one we're equal to or greater than
    auto s = --relocations.upper_bound(source);

    // Take slice
    Relocations slice;
    slice[dest] = source - s->first + s->second;
    ++s;

    // Add rest of elements
    for (; s != relocations.end() && s->first < source + count; ++s)
        slice[dest - source + s->first] = s->second;

    // Split range at end of dest
    auto dest_end = --relocations.upper_bound(dest + count);
    relocations[dest + count] = dest + count - dest_end->first + dest_end->second;

    // Remove all elements in [dest, dest + count)
    relocations.erase(relocations.lower_bound(dest), relocations.lower_bound(dest + count));

    // Add new elements
    relocations.insert(slice.begin(), slice.end());
}

// A map of sectors that have been written to.
// The final entry must always be False.
// When we restart the restore after an interruption, we must take care that
// when we copy from dest to source, that the block we copy to was not
// previously copied from.
// i e. A->B C->A; If we replay this sequence, we end up copying C->B
// We must save our partial result whenever we finish a page, or when we copy
// to a location that was copied from earlier (our source is an earlier dest)
typedef std::map<sector_t, bool> Used_Sectors;

bool checkCollision(Used_Sectors& used_sectors, sector_t start, sector_t end) {
    auto second_overlap = used_sectors.upper_bound(start);
    auto first_overlap = --second_overlap;

    if (first_overlap->second) {
        return true;
    } else if (second_overlap != used_sectors.end() && second_overlap->first < end) {
        return true;
    }
    return false;
}

void markUsed(Used_Sectors& used_sectors, sector_t start, sector_t end) {
    auto start_pos = used_sectors.insert_or_assign(start, true).first;
    auto end_pos = used_sectors.insert_or_assign(end, false).first;

    if (start_pos == used_sectors.begin() || !std::prev(start_pos)->second) {
        start_pos++;
    }
    if (std::next(end_pos) != used_sectors.end() && !std::next(end_pos)->second) {
        end_pos++;
    }
    if (start_pos->first < end_pos->first) {
        used_sectors.erase(start_pos, end_pos);
    }
}

// Restores the given log_entry's data from dest -> source
// If that entry is a log sector, set the magic to kPartialRestoreMagic and flush.
void restoreSector(int device_fd, Used_Sectors& used_sectors, std::vector<char>& ls_buffer,
                   log_entry* le, std::vector<char>& buffer) {
    log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
    uint32_t index = le - ((log_entry*)&ls_buffer[ls.header_size]);
    int count = (le->size - 1) / kSectorSize + 1;

    if (checkCollision(used_sectors, le->source, le->source + count)) {
        fsync(device_fd);
        lseek64(device_fd, 0, SEEK_SET);
        ls.count = index + 1;
        ls.magic = kPartialRestoreMagic;
        write(device_fd, &ls_buffer[0], ls.block_size);
        fsync(device_fd);
        used_sectors.clear();
        used_sectors[0] = false;
    }

    markUsed(used_sectors, le->dest, le->dest + count);

    if (index == 0 && ls.sequence != 0) {
        log_sector_v1_0* next = reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
        if (next->magic == kMagic) {
            next->magic = kPartialRestoreMagic;
        }
    }

    lseek64(device_fd, le->source * kSectorSize, SEEK_SET);
    write(device_fd, &buffer[0], le->size);

    if (index == 0) {
        fsync(device_fd);
    }
}

// Read from the device
// If we are validating, the read occurs as though the relocations had happened
std::vector<char> relocatedRead(int device_fd, Relocations const& relocations, bool validating,
                                sector_t sector, uint32_t size, uint32_t block_size) {
    if (!validating) {
        std::vector<char> buffer(size);
        lseek64(device_fd, sector * kSectorSize, SEEK_SET);
        read(device_fd, &buffer[0], size);
        return buffer;
    }

    std::vector<char> buffer(size);
    for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize) {
        auto relocation = --relocations.upper_bound(sector);
        lseek64(device_fd, (sector + relocation->second - relocation->first) * kSectorSize,
                SEEK_SET);
        read(device_fd, &buffer[i], block_size);
    }

    return buffer;
}

}  // namespace

Status cp_restoreCheckpoint(const std::string& blockDevice, int restore_limit) {
    bool validating = true;
    std::string action = "Validating";
    int restore_count = 0;

    for (;;) {
        Relocations relocations;
        relocations[0] = 0;
        Status status = Status::ok();

        LOG(INFO) << action << " checkpoint on " << blockDevice;
        base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR));
        if (device_fd < 0) {
            PLOG(ERROR) << "Cannot open " << blockDevice;
            return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
        }

        log_sector_v1_0 original_ls;
        read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
        if (original_ls.magic == kPartialRestoreMagic) {
            validating = false;
            action = "Restoring";
        } else if (original_ls.magic != kMagic) {
            LOG(ERROR) << "No magic";
            return Status::fromExceptionCode(EINVAL, "No magic");
        }

        LOG(INFO) << action << " " << original_ls.sequence << " log sectors";

        for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
            auto ls_buffer = relocatedRead(device_fd, relocations, validating, 0,
                                           original_ls.block_size, original_ls.block_size);
            log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);

            Used_Sectors used_sectors;
            used_sectors[0] = false;

            if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
                LOG(ERROR) << "No magic!";
                status = Status::fromExceptionCode(EINVAL, "No magic");
                break;
            }

            if (ls.block_size != original_ls.block_size) {
                LOG(ERROR) << "Block size mismatch!";
                status = Status::fromExceptionCode(EINVAL, "Block size mismatch");
                break;
            }

            if ((int)ls.sequence != sequence) {
                LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
                status = Status::fromExceptionCode(
                    EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
                             std::to_string(ls.sequence))
                                .c_str());
                break;
            }

            LOG(INFO) << action << " from log sector " << ls.sequence;
            for (log_entry* le =
                     reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]) + ls.count - 1;
                 le >= reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]); --le) {
                // This is very noisy - limit to DEBUG only
                LOG(VERBOSE) << action << " " << le->size << " bytes from sector " << le->dest
                             << " to " << le->source << " with checksum " << std::hex
                             << le->checksum;

                auto buffer = relocatedRead(device_fd, relocations, validating, le->dest, le->size,
                                            ls.block_size);
                uint32_t checksum = le->source / (ls.block_size / kSectorSize);
                for (size_t i = 0; i < le->size; i += ls.block_size) {
                    crc32(&buffer[i], ls.block_size, &checksum);
                }

                if (le->checksum && checksum != le->checksum) {
                    LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
                    status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
                    break;
                }

                if (validating) {
                    relocate(relocations, le->source, le->dest, (le->size - 1) / kSectorSize + 1);
                } else {
                    restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
                    restore_count++;
                    if (restore_limit && restore_count >= restore_limit) {
                        LOG(WARNING) << "Hit the test limit";
                        status = Status::fromExceptionCode(EAGAIN, "Hit the test limit");
                        break;
                    }
                }
            }
        }

        if (!status.isOk()) {
            if (!validating) {
                LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
                return status;
            }

            LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
            auto buffer = relocatedRead(device_fd, relocations, false, original_ls.sector0,
                                        original_ls.block_size, original_ls.block_size);
            lseek64(device_fd, 0, SEEK_SET);
            write(device_fd, &buffer[0], original_ls.block_size);
            return Status::ok();
        }

        if (!validating) break;

        validating = false;
        action = "Restoring";
    }

    return Status::ok();
}

Status cp_markBootAttempt() {
    std::string oldContent, newContent;
    int retry = 0;
    struct stat st;
    int result = stat(kMetadataCPFile.c_str(), &st);

    // If the file doesn't exist, we aren't managing a checkpoint retry counter
    if (result != 0) return Status::ok();
    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
        PLOG(ERROR) << "Failed to read checkpoint file";
        return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
    }
    std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));

    if (!android::base::ParseInt(retryContent, &retry))
        return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
    if (retry > 0) {
        retry--;

        newContent = std::to_string(retry);
        if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
            return Status::fromExceptionCode(errno, "Could not write checkpoint file");
    }
    return Status::ok();
}

}  // namespace vold
}  // namespace android
