/*
 * 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 <thread>
#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>
#include <sys/statvfs.h>
#include <unistd.h>

using android::base::GetBoolProperty;
using android::base::GetUintProperty;
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 {

volatile 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;
}

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();
    }

    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");
        }
        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();
}

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
