blob: f96ca390a518246a828b5ba226f77ec9314ebc5a [file] [log] [blame]
Daniel Rosenberg65f99c92018-08-28 01:58:49 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Checkpoint"
18#include "Checkpoint.h"
Daniel Rosenberg253b44e2019-02-01 19:25:47 -080019#include "VoldUtil.h"
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070020
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070021#include <fstream>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070022#include <list>
Paul Lawrence20400892018-10-03 14:14:52 -070023#include <memory>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070024#include <string>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070025#include <vector>
26
27#include <android-base/file.h>
28#include <android-base/logging.h>
29#include <android-base/parseint.h>
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080030#include <android-base/properties.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070031#include <android-base/unique_fd.h>
Daniel Rosenbergd3992492018-10-02 17:40:44 -070032#include <android/hardware/boot/1.0/IBootControl.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070033#include <cutils/android_reboot.h>
34#include <fcntl.h>
35#include <fs_mgr.h>
36#include <linux/fs.h>
37#include <mntent.h>
38#include <sys/mount.h>
39#include <sys/stat.h>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070040
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080041using android::base::SetProperty;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070042using android::binder::Status;
Tom Cherry4c5bde22019-01-29 14:34:01 -080043using android::fs_mgr::Fstab;
44using android::fs_mgr::ReadDefaultFstab;
45using android::fs_mgr::ReadFstabFromFile;
Daniel Rosenbergd3992492018-10-02 17:40:44 -070046using android::hardware::hidl_string;
47using android::hardware::boot::V1_0::BoolResult;
Daniel Rosenberg886915b2019-01-23 15:16:04 -080048using android::hardware::boot::V1_0::CommandResult;
Daniel Rosenbergd3992492018-10-02 17:40:44 -070049using android::hardware::boot::V1_0::IBootControl;
50using android::hardware::boot::V1_0::Slot;
51
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070052namespace android {
53namespace vold {
54
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070055namespace {
56const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
57
58bool setBowState(std::string const& block_device, std::string const& state) {
59 if (block_device.substr(0, 5) != "/dev/") {
60 LOG(ERROR) << "Expected block device, got " << block_device;
61 return false;
62 }
63
64 std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
65 if (!android::base::WriteStringToFile(state, state_filename)) {
66 PLOG(ERROR) << "Failed to write to file " << state_filename;
67 return false;
68 }
69
70 return true;
71}
72
73} // namespace
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070074
Daniel Rosenberg9b667fb2019-01-22 17:27:25 -080075Status cp_supportsCheckpoint(bool& result) {
76 result = false;
Daniel Rosenberg9b667fb2019-01-22 17:27:25 -080077
Tom Cherry4c5bde22019-01-29 14:34:01 -080078 for (const auto& entry : fstab_default) {
79 if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
Daniel Rosenberg9b667fb2019-01-22 17:27:25 -080080 result = true;
81 return Status::ok();
82 }
83 }
84 return Status::ok();
85}
86
Paul Lawrencec5c79c52019-03-18 13:36:40 -070087Status cp_supportsBlockCheckpoint(bool& result) {
88 result = false;
89
90 for (const auto& entry : fstab_default) {
91 if (entry.fs_mgr_flags.checkpoint_blk) {
92 result = true;
93 return Status::ok();
94 }
95 }
96 return Status::ok();
97}
98
99Status cp_supportsFileCheckpoint(bool& result) {
100 result = false;
101
102 for (const auto& entry : fstab_default) {
103 if (entry.fs_mgr_flags.checkpoint_fs) {
104 result = true;
105 return Status::ok();
106 }
107 }
108 return Status::ok();
109}
110
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700111Status cp_startCheckpoint(int retry) {
112 if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700113 std::string content = std::to_string(retry + 1);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700114 if (retry == -1) {
115 sp<IBootControl> module = IBootControl::getService();
116 if (module) {
117 std::string suffix;
118 auto cb = [&suffix](hidl_string s) { suffix = s; };
119 if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
120 }
121 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700122 if (!android::base::WriteStringToFile(content, kMetadataCPFile))
123 return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
124 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700125}
126
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800127namespace {
128
129bool isCheckpointing = false;
130}
131
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700132Status cp_commitChanges() {
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800133 if (!isCheckpointing) {
134 return Status::ok();
135 }
Daniel Rosenberg886915b2019-01-23 15:16:04 -0800136 sp<IBootControl> module = IBootControl::getService();
137 if (module) {
138 CommandResult cr;
139 module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
140 if (!cr.success) {
141 std::string msg = "Error marking booted successfully: " + std::string(cr.errMsg);
142 return Status::fromExceptionCode(EINVAL, String8(msg.c_str()));
143 }
144 LOG(INFO) << "Marked slot as booted successfully.";
145 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700146 // Must take action for list of mounted checkpointed things here
147 // To do this, we walk the list of mounted file systems.
148 // But we also need to get the matching fstab entries to see
149 // the original flags
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700150 std::string err_str;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700151
Tom Cherry4c5bde22019-01-29 14:34:01 -0800152 Fstab mounts;
153 if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
154 return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
155 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700156
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700157 // Walk mounted file systems
Tom Cherry4c5bde22019-01-29 14:34:01 -0800158 for (const auto& mount_rec : mounts) {
159 const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700160 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700161
Tom Cherry4c5bde22019-01-29 14:34:01 -0800162 if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
163 if (fstab_rec->fs_type == "f2fs") {
164 std::string options = mount_rec.fs_options + ",checkpoint=enable";
165 if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
Daniel Rosenberg14ca4ac2019-01-24 18:23:18 -0800166 MS_REMOUNT | fstab_rec->flags, options.c_str())) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800167 return Status::fromExceptionCode(EINVAL, "Failed to remount");
168 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700169 }
Tom Cherry4c5bde22019-01-29 14:34:01 -0800170 } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
171 if (!setBowState(mount_rec.blk_device, "2"))
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800172 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700173 }
174 }
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800175 SetProperty("vold.checkpoint_committed", "1");
Daniel Rosenberg886915b2019-01-23 15:16:04 -0800176 LOG(INFO) << "Checkpoint has been committed.";
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800177 isCheckpointing = false;
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800178 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700179 return Status::fromExceptionCode(errno, err_str.c_str());
180 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700181}
182
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700183Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700184 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700185 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700186}
187
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700188bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700189 std::string content;
190 bool ret;
191
192 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700193 if (ret) {
194 if (content == "0") return true;
195 if (content.substr(0, 3) == "-1 ") {
196 std::string oldSuffix = content.substr(3);
197 sp<IBootControl> module = IBootControl::getService();
198 std::string newSuffix;
199
200 if (module) {
201 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
202 module->getSuffix(module->getCurrentSlot(), cb);
203 if (oldSuffix == newSuffix) return true;
204 }
205 }
206 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700207 return false;
208}
209
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700210bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700211 bool ret;
212 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700213 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700214
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800215 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
216 isCheckpointing = true;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700217 return true;
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800218 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700219 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800220 if (ret) {
221 ret = content != "0";
222 isCheckpointing = ret;
223 return ret;
224 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700225 return false;
226}
227
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700228Status cp_prepareCheckpoint() {
Paul Lawrencedb086942019-02-19 14:18:54 -0800229 if (!isCheckpointing) {
230 return Status::ok();
231 }
232
Tom Cherry4c5bde22019-01-29 14:34:01 -0800233 Fstab mounts;
234 if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
235 return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
236 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700237
Tom Cherry4c5bde22019-01-29 14:34:01 -0800238 for (const auto& mount_rec : mounts) {
239 const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700240 if (!fstab_rec) continue;
241
Tom Cherry4c5bde22019-01-29 14:34:01 -0800242 if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700243 android::base::unique_fd fd(
Tom Cherry4c5bde22019-01-29 14:34:01 -0800244 TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700245 if (!fd) {
Tom Cherry4c5bde22019-01-29 14:34:01 -0800246 PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700247 continue;
248 }
249
250 struct fstrim_range range = {};
251 range.len = ULLONG_MAX;
252 if (ioctl(fd, FITRIM, &range)) {
Tom Cherry4c5bde22019-01-29 14:34:01 -0800253 PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700254 continue;
255 }
256
Tom Cherry4c5bde22019-01-29 14:34:01 -0800257 setBowState(mount_rec.blk_device, "1");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700258 }
259 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700260 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700261}
262
263namespace {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700264const int kSectorSize = 512;
265
266typedef uint64_t sector_t;
267
268struct log_entry {
Paul Lawrenced41a9392019-01-22 14:31:43 -0800269 sector_t source; // in sectors of size kSectorSize
270 sector_t dest; // in sectors of size kSectorSize
271 uint32_t size; // in bytes
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700272 uint32_t checksum;
273} __attribute__((packed));
274
Paul Lawrencef5077682019-01-18 10:28:34 -0800275struct log_sector_v1_0 {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700276 uint32_t magic;
Paul Lawrencef5077682019-01-18 10:28:34 -0800277 uint16_t header_version;
278 uint16_t header_size;
Paul Lawrence4f13a902019-01-10 13:06:07 -0800279 uint32_t block_size;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700280 uint32_t count;
281 uint32_t sequence;
Paul Lawrence27691c22018-11-20 14:07:59 -0800282 uint64_t sector0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700283} __attribute__((packed));
284
285// MAGIC is BOW in ascii
286const int kMagic = 0x00574f42;
Daniel Rosenberg52985932019-03-01 22:01:22 -0800287// Partially restored MAGIC is WOB in ascii
288const int kPartialRestoreMagic = 0x00424f57;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700289
290void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
291 static uint32_t table[0x100] = {
292 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
293 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
294 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
295 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
296 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
297 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
298 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
299 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
300 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
301 0xB6662D3D,
302
303 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
304 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
305 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
306 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
307 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
308 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
309 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
310 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
311 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
312 0xC0BA6CAD,
313
314 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
315 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
316 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
317 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
318 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
319 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
320 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
321 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
322 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
323 0x5BDEAE1D,
324
325 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
326 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
327 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
328 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
329 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
330 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
331 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
332 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
333 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
334 0x2D02EF8D};
335
336 for (size_t i = 0; i < n_bytes; ++i) {
337 *crc ^= ((uint8_t*)data)[i];
338 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
339 }
340}
341
Paul Lawrenced41a9392019-01-22 14:31:43 -0800342// A map of relocations.
343// The map must be initialized so that relocations[0] = 0
344// During restore, we replay the log records in reverse, copying from dest to
345// source
346// To validate, we must be able to read the 'dest' sectors as though they had
347// been copied but without actually copying. This map represents how the sectors
348// would have been moved. To read a sector s, find the index <= s and read
349// relocations[index] + s - index
350typedef std::map<sector_t, sector_t> Relocations;
Paul Lawrence27691c22018-11-20 14:07:59 -0800351
Paul Lawrenced41a9392019-01-22 14:31:43 -0800352void relocate(Relocations& relocations, sector_t dest, sector_t source, int count) {
353 // Find first one we're equal to or greater than
354 auto s = --relocations.upper_bound(source);
355
356 // Take slice
357 Relocations slice;
358 slice[dest] = source - s->first + s->second;
359 ++s;
360
361 // Add rest of elements
362 for (; s != relocations.end() && s->first < source + count; ++s)
363 slice[dest - source + s->first] = s->second;
364
365 // Split range at end of dest
366 auto dest_end = --relocations.upper_bound(dest + count);
367 relocations[dest + count] = dest + count - dest_end->first + dest_end->second;
368
369 // Remove all elements in [dest, dest + count)
370 relocations.erase(relocations.lower_bound(dest), relocations.lower_bound(dest + count));
371
372 // Add new elements
373 relocations.insert(slice.begin(), slice.end());
Paul Lawrence27691c22018-11-20 14:07:59 -0800374}
375
Daniel Rosenberg52985932019-03-01 22:01:22 -0800376// A map of sectors that have been written to.
377// The final entry must always be False.
378// When we restart the restore after an interruption, we must take care that
379// when we copy from dest to source, that the block we copy to was not
380// previously copied from.
381// i e. A->B C->A; If we replay this sequence, we end up copying C->B
382// We must save our partial result whenever we finish a page, or when we copy
383// to a location that was copied from earlier (our source is an earlier dest)
384typedef std::map<sector_t, bool> Used_Sectors;
385
386bool checkCollision(Used_Sectors& used_sectors, sector_t start, sector_t end) {
387 auto second_overlap = used_sectors.upper_bound(start);
388 auto first_overlap = --second_overlap;
389
390 if (first_overlap->second) {
391 return true;
392 } else if (second_overlap != used_sectors.end() && second_overlap->first < end) {
393 return true;
394 }
395 return false;
396}
397
398void markUsed(Used_Sectors& used_sectors, sector_t start, sector_t end) {
399 auto start_pos = used_sectors.insert_or_assign(start, true).first;
400 auto end_pos = used_sectors.insert_or_assign(end, false).first;
401
402 if (start_pos == used_sectors.begin() || !std::prev(start_pos)->second) {
403 start_pos++;
404 }
405 if (std::next(end_pos) != used_sectors.end() && !std::next(end_pos)->second) {
406 end_pos++;
407 }
408 if (start_pos->first < end_pos->first) {
409 used_sectors.erase(start_pos, end_pos);
410 }
411}
412
413// Restores the given log_entry's data from dest -> source
414// If that entry is a log sector, set the magic to kPartialRestoreMagic and flush.
415void restoreSector(int device_fd, Used_Sectors& used_sectors, std::vector<char>& ls_buffer,
416 log_entry* le, std::vector<char>& buffer) {
417 log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
418 uint32_t index = le - ((log_entry*)&ls_buffer[ls.header_size]);
419 int count = (le->size - 1) / kSectorSize + 1;
420
421 if (checkCollision(used_sectors, le->source, le->source + count)) {
422 fsync(device_fd);
423 lseek64(device_fd, 0, SEEK_SET);
424 ls.count = index + 1;
425 ls.magic = kPartialRestoreMagic;
426 write(device_fd, &ls_buffer[0], ls.block_size);
427 fsync(device_fd);
428 used_sectors.clear();
429 used_sectors[0] = false;
430 }
431
432 markUsed(used_sectors, le->dest, le->dest + count);
433
434 if (index == 0 && ls.sequence != 0) {
435 log_sector_v1_0* next = reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
436 if (next->magic == kMagic) {
437 next->magic = kPartialRestoreMagic;
438 }
439 }
440
441 lseek64(device_fd, le->source * kSectorSize, SEEK_SET);
442 write(device_fd, &buffer[0], le->size);
443
444 if (index == 0) {
445 fsync(device_fd);
446 }
447}
448
Paul Lawrenced41a9392019-01-22 14:31:43 -0800449// Read from the device
450// If we are validating, the read occurs as though the relocations had happened
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800451std::vector<char> relocatedRead(int device_fd, Relocations const& relocations, bool validating,
452 sector_t sector, uint32_t size, uint32_t block_size) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800453 if (!validating) {
454 std::vector<char> buffer(size);
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800455 lseek64(device_fd, sector * kSectorSize, SEEK_SET);
456 read(device_fd, &buffer[0], size);
Paul Lawrence27691c22018-11-20 14:07:59 -0800457 return buffer;
458 }
459
Paul Lawrence27691c22018-11-20 14:07:59 -0800460 std::vector<char> buffer(size);
Paul Lawrenced41a9392019-01-22 14:31:43 -0800461 for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize) {
462 auto relocation = --relocations.upper_bound(sector);
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800463 lseek64(device_fd, (sector + relocation->second - relocation->first) * kSectorSize,
464 SEEK_SET);
465 read(device_fd, &buffer[i], block_size);
Paul Lawrenced41a9392019-01-22 14:31:43 -0800466 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800467
468 return buffer;
469}
470
Paul Lawrence4f13a902019-01-10 13:06:07 -0800471} // namespace
472
Daniel Rosenbergdda59812019-03-06 17:45:17 -0800473Status cp_restoreCheckpoint(const std::string& blockDevice, int restore_limit) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800474 bool validating = true;
475 std::string action = "Validating";
Daniel Rosenbergdda59812019-03-06 17:45:17 -0800476 int restore_count = 0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700477
Paul Lawrence27691c22018-11-20 14:07:59 -0800478 for (;;) {
Paul Lawrenced41a9392019-01-22 14:31:43 -0800479 Relocations relocations;
480 relocations[0] = 0;
Paul Lawrence27691c22018-11-20 14:07:59 -0800481 Status status = Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700482
Paul Lawrence27691c22018-11-20 14:07:59 -0800483 LOG(INFO) << action << " checkpoint on " << blockDevice;
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800484 base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR));
485 if (device_fd < 0) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800486 PLOG(ERROR) << "Cannot open " << blockDevice;
487 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
488 }
Paul Lawrence4f13a902019-01-10 13:06:07 -0800489
Paul Lawrencef5077682019-01-18 10:28:34 -0800490 log_sector_v1_0 original_ls;
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800491 read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
Daniel Rosenberg52985932019-03-01 22:01:22 -0800492 if (original_ls.magic == kPartialRestoreMagic) {
493 validating = false;
494 action = "Restoring";
495 } else if (original_ls.magic != kMagic) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800496 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700497 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700498 }
499
Paul Lawrence4f13a902019-01-10 13:06:07 -0800500 LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700501
Paul Lawrence4f13a902019-01-10 13:06:07 -0800502 for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
Daniel Rosenberg52985932019-03-01 22:01:22 -0800503 auto ls_buffer = relocatedRead(device_fd, relocations, validating, 0,
504 original_ls.block_size, original_ls.block_size);
505 log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
506
507 Used_Sectors used_sectors;
508 used_sectors[0] = false;
509
510 if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800511 LOG(ERROR) << "No magic!";
512 status = Status::fromExceptionCode(EINVAL, "No magic");
513 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700514 }
515
Paul Lawrence4f13a902019-01-10 13:06:07 -0800516 if (ls.block_size != original_ls.block_size) {
517 LOG(ERROR) << "Block size mismatch!";
518 status = Status::fromExceptionCode(EINVAL, "Block size mismatch");
519 break;
520 }
521
Paul Lawrence27691c22018-11-20 14:07:59 -0800522 if ((int)ls.sequence != sequence) {
523 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
524 status = Status::fromExceptionCode(
525 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
526 std::to_string(ls.sequence))
527 .c_str());
528 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700529 }
530
Paul Lawrence27691c22018-11-20 14:07:59 -0800531 LOG(INFO) << action << " from log sector " << ls.sequence;
Paul Lawrencef5077682019-01-18 10:28:34 -0800532 for (log_entry* le =
Daniel Rosenberg52985932019-03-01 22:01:22 -0800533 reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]) + ls.count - 1;
534 le >= reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]); --le) {
Paul Lawrencef5077682019-01-18 10:28:34 -0800535 // This is very noisy - limit to DEBUG only
Paul Lawrenced41a9392019-01-22 14:31:43 -0800536 LOG(VERBOSE) << action << " " << le->size << " bytes from sector " << le->dest
537 << " to " << le->source << " with checksum " << std::hex
538 << le->checksum;
Paul Lawrencef5077682019-01-18 10:28:34 -0800539
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800540 auto buffer = relocatedRead(device_fd, relocations, validating, le->dest, le->size,
Paul Lawrenced41a9392019-01-22 14:31:43 -0800541 ls.block_size);
Paul Lawrence4f13a902019-01-10 13:06:07 -0800542 uint32_t checksum = le->source / (ls.block_size / kSectorSize);
543 for (size_t i = 0; i < le->size; i += ls.block_size) {
544 crc32(&buffer[i], ls.block_size, &checksum);
Paul Lawrence27691c22018-11-20 14:07:59 -0800545 }
546
547 if (le->checksum && checksum != le->checksum) {
548 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
549 status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
550 break;
551 }
552
Paul Lawrenced41a9392019-01-22 14:31:43 -0800553 if (validating) {
Daniel Rosenberg52985932019-03-01 22:01:22 -0800554 relocate(relocations, le->source, le->dest, (le->size - 1) / kSectorSize + 1);
Paul Lawrenced41a9392019-01-22 14:31:43 -0800555 } else {
Daniel Rosenberg52985932019-03-01 22:01:22 -0800556 restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
Daniel Rosenbergdda59812019-03-06 17:45:17 -0800557 restore_count++;
558 if (restore_limit && restore_count >= restore_limit) {
559 LOG(WARNING) << "Hit the test limit";
560 status = Status::fromExceptionCode(EAGAIN, "Hit the test limit");
561 break;
562 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800563 }
564 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700565 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800566
567 if (!status.isOk()) {
568 if (!validating) {
569 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
570 return status;
571 }
572
573 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800574 auto buffer = relocatedRead(device_fd, relocations, false, original_ls.sector0,
Paul Lawrenced41a9392019-01-22 14:31:43 -0800575 original_ls.block_size, original_ls.block_size);
Daniel Rosenberg8271ae92019-03-04 21:46:31 -0800576 lseek64(device_fd, 0, SEEK_SET);
577 write(device_fd, &buffer[0], original_ls.block_size);
Paul Lawrence27691c22018-11-20 14:07:59 -0800578 return Status::ok();
579 }
580
581 if (!validating) break;
582
583 validating = false;
584 action = "Restoring";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700585 }
586
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700587 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700588}
589
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700590Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700591 std::string oldContent, newContent;
592 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700593 struct stat st;
594 int result = stat(kMetadataCPFile.c_str(), &st);
595
596 // If the file doesn't exist, we aren't managing a checkpoint retry counter
597 if (result != 0) return Status::ok();
598 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
599 PLOG(ERROR) << "Failed to read checkpoint file";
600 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
601 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700602 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700603
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700604 if (!android::base::ParseInt(retryContent, &retry))
605 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
606 if (retry > 0) {
607 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700608
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700609 newContent = std::to_string(retry);
610 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
611 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
612 }
613 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700614}
615
616} // namespace vold
617} // namespace android