Merge "Do not trim unless we are actually checkpointing"
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 0f6edcf..abda045 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -237,7 +237,6 @@
 }
 
 namespace {
-const int kBlockSize = 4096;
 const int kSectorSize = 512;
 
 typedef uint64_t sector_t;
@@ -249,12 +248,14 @@
     uint32_t checksum;
 } __attribute__((packed));
 
-struct log_sector {
+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;
-    struct log_entry entries[];
 } __attribute__((packed));
 
 // MAGIC is BOW in ascii
@@ -312,20 +313,21 @@
     }
 }
 
-}  // namespace
-
-static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
-                 char* buffer) {
+void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector, char* buffer,
+          uint32_t block_size) {
+    // Crude approach at first where we do this sector by sector and just scan
+    // the entire logs for remappings each time
     for (auto l = logs.rbegin(); l != logs.rend(); l++)
         if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
             sector = sector - l->source + l->dest;
 
     device.seekg(sector * kSectorSize);
-    device.read(buffer, kBlockSize);
+    device.read(buffer, block_size);
 }
 
-static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
-                              bool validating, sector_t sector, uint32_t size) {
+// Read from the device as though we were restoring, even if we are validating
+std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs, bool validating,
+                       sector_t sector, uint32_t size, uint32_t block_size) {
     if (!validating) {
         std::vector<char> buffer(size);
         device.seekg(sector * kSectorSize);
@@ -333,16 +335,15 @@
         return buffer;
     }
 
-    // Crude approach at first where we do this sector by sector and just scan
-    // the entire logs for remappings each time
     std::vector<char> buffer(size);
-
-    for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
-        read(device, logs, sector, &buffer[i]);
+    for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize)
+        read(device, logs, sector, &buffer[i], block_size);
 
     return buffer;
 }
 
+}  // namespace
+
 Status cp_restoreCheckpoint(const std::string& blockDevice) {
     bool validating = true;
     std::string action = "Validating";
@@ -357,24 +358,32 @@
             PLOG(ERROR) << "Cannot open " << blockDevice;
             return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
         }
-        auto buffer = read(device, logs, validating, 0, kBlockSize);
-        log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
-        if (ls.magic != kMagic) {
+
+        log_sector_v1_0 original_ls;
+        device.read(reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
+        if (original_ls.magic != kMagic) {
             LOG(ERROR) << "No magic";
             return Status::fromExceptionCode(EINVAL, "No magic");
         }
 
-        LOG(INFO) << action << " " << ls.sequence << " log sectors";
+        LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
 
-        for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
-            auto buffer = read(device, logs, validating, 0, kBlockSize);
-            log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
+        for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
+            auto buffer =
+                read(device, logs, validating, 0, original_ls.block_size, original_ls.block_size);
+            log_sector_v1_0 const& ls = *reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
             if (ls.magic != kMagic) {
                 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(
@@ -386,13 +395,17 @@
 
             LOG(INFO) << action << " from log sector " << ls.sequence;
 
-            for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
-                LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
-                          << " to " << le->source << " with checksum " << std::hex << le->checksum;
-                auto buffer = read(device, logs, validating, le->dest, le->size);
-                uint32_t checksum = le->source / (kBlockSize / kSectorSize);
-                for (size_t i = 0; i < le->size; i += kBlockSize) {
-                    crc32(&buffer[i], kBlockSize, &checksum);
+            for (log_entry* le =
+                     reinterpret_cast<log_entry*>(&buffer[ls.header_size]) + ls.count - 1;
+                 le >= reinterpret_cast<log_entry*>(&buffer[ls.header_size]); --le) {
+                // This is very noisy - limit to DEBUG only
+                LOG(DEBUG) << action << " " << le->size << " bytes from sector " << le->dest
+                           << " to " << le->source << " with checksum " << std::hex << le->checksum;
+
+                auto buffer = read(device, logs, 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) {
@@ -417,9 +430,10 @@
             }
 
             LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
-            auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
+            auto buffer = read(device, logs, false, original_ls.sector0, original_ls.block_size,
+                               original_ls.block_size);
             device.seekg(0);
-            device.write(&buffer[0], kBlockSize);
+            device.write(&buffer[0], original_ls.block_size);
             return Status::ok();
         }
 
diff --git a/main.cpp b/main.cpp
index b930941..687a0a9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -226,7 +226,7 @@
     *has_adoptable = false;
     *has_quota = false;
     *has_reserved = false;
-    for (const auto& entry : fstab_default) {
+    for (auto& entry : fstab_default) {
         if (entry.fs_mgr_flags.quota) {
             *has_quota = true;
         }
@@ -234,6 +234,11 @@
             *has_reserved = true;
         }
 
+        /* Make sure logical partitions have an updated blk_device. */
+        if (entry.fs_mgr_flags.logical && !fs_mgr_update_logical_partition(&entry)) {
+            PLOG(FATAL) << "could not find logical partition " << entry.blk_device;
+        }
+
         if (entry.fs_mgr_flags.vold_managed) {
             if (entry.fs_mgr_flags.nonremovable) {
                 LOG(WARNING) << "nonremovable no longer supported; ignoring volume";