blob: e06e8550de386dd0441efec9f98047efa2e8660e [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"
19
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070020#include <fstream>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070021#include <list>
Paul Lawrence20400892018-10-03 14:14:52 -070022#include <memory>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070023#include <string>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070024#include <vector>
25
26#include <android-base/file.h>
27#include <android-base/logging.h>
28#include <android-base/parseint.h>
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080029#include <android-base/properties.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070030#include <android-base/unique_fd.h>
Daniel Rosenbergd3992492018-10-02 17:40:44 -070031#include <android/hardware/boot/1.0/IBootControl.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070032#include <cutils/android_reboot.h>
33#include <fcntl.h>
34#include <fs_mgr.h>
35#include <linux/fs.h>
36#include <mntent.h>
37#include <sys/mount.h>
38#include <sys/stat.h>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070039
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080040using android::base::SetProperty;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070041using android::binder::Status;
Daniel Rosenbergd3992492018-10-02 17:40:44 -070042using android::hardware::hidl_string;
43using android::hardware::boot::V1_0::BoolResult;
44using android::hardware::boot::V1_0::IBootControl;
45using android::hardware::boot::V1_0::Slot;
46
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070047namespace android {
48namespace vold {
49
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070050namespace {
51const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
52
53bool setBowState(std::string const& block_device, std::string const& state) {
54 if (block_device.substr(0, 5) != "/dev/") {
55 LOG(ERROR) << "Expected block device, got " << block_device;
56 return false;
57 }
58
59 std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
60 if (!android::base::WriteStringToFile(state, state_filename)) {
61 PLOG(ERROR) << "Failed to write to file " << state_filename;
62 return false;
63 }
64
65 return true;
66}
67
68} // namespace
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070069
Daniel Rosenberg9b667fb2019-01-22 17:27:25 -080070Status cp_supportsCheckpoint(bool& result) {
71 result = false;
72 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
73 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
74 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
75
76 for (int i = 0; i < fstab_default->num_entries; ++i) {
77 if (fs_mgr_is_checkpoint(&fstab_default->recs[i])) {
78 result = true;
79 return Status::ok();
80 }
81 }
82 return Status::ok();
83}
84
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070085Status cp_startCheckpoint(int retry) {
86 if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -070087 std::string content = std::to_string(retry + 1);
Daniel Rosenbergd3992492018-10-02 17:40:44 -070088 if (retry == -1) {
89 sp<IBootControl> module = IBootControl::getService();
90 if (module) {
91 std::string suffix;
92 auto cb = [&suffix](hidl_string s) { suffix = s; };
93 if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
94 }
95 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070096 if (!android::base::WriteStringToFile(content, kMetadataCPFile))
97 return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
98 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070099}
100
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800101namespace {
102
103bool isCheckpointing = false;
104}
105
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700106Status cp_commitChanges() {
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800107 if (!isCheckpointing) {
108 return Status::ok();
109 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700110 // Must take action for list of mounted checkpointed things here
111 // To do this, we walk the list of mounted file systems.
112 // But we also need to get the matching fstab entries to see
113 // the original flags
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700114 std::string err_str;
Paul Lawrence20400892018-10-03 14:14:52 -0700115 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
116 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700117 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700118
Paul Lawrence20400892018-10-03 14:14:52 -0700119 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
120 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700121 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700122
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700123 // Walk mounted file systems
124 for (int i = 0; i < mounts->num_entries; ++i) {
125 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700126 const fstab_rec* fstab_rec =
127 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700128 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700129
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700130 if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
131 if (!strcmp(fstab_rec->fs_type, "f2fs")) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800132 if (mount(mount_rec->blk_device, mount_rec->mount_point, "none",
133 MS_REMOUNT | fstab_rec->flags, "checkpoint=enable")) {
134 return Status::fromExceptionCode(EINVAL, "Failed to remount");
135 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700136 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700137 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800138 if (!setBowState(mount_rec->blk_device, "2"))
139 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700140 }
141 }
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800142 SetProperty("vold.checkpoint_committed", "1");
143 isCheckpointing = false;
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800144 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700145 return Status::fromExceptionCode(errno, err_str.c_str());
146 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700147}
148
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700149Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700150 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700151 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700152}
153
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700154bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700155 std::string content;
156 bool ret;
157
158 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700159 if (ret) {
160 if (content == "0") return true;
161 if (content.substr(0, 3) == "-1 ") {
162 std::string oldSuffix = content.substr(3);
163 sp<IBootControl> module = IBootControl::getService();
164 std::string newSuffix;
165
166 if (module) {
167 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
168 module->getSuffix(module->getCurrentSlot(), cb);
169 if (oldSuffix == newSuffix) return true;
170 }
171 }
172 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700173 return false;
174}
175
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700176bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700177 bool ret;
178 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700179 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700180
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800181 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
182 isCheckpointing = true;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700183 return true;
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800184 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700185 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800186 if (ret) {
187 ret = content != "0";
188 isCheckpointing = ret;
189 return ret;
190 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700191 return false;
192}
193
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700194Status cp_prepareCheckpoint() {
Paul Lawrence20400892018-10-03 14:14:52 -0700195 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
196 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700197 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700198
Paul Lawrence20400892018-10-03 14:14:52 -0700199 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
200 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700201 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700202
203 for (int i = 0; i < mounts->num_entries; ++i) {
204 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700205 const fstab_rec* fstab_rec =
206 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700207 if (!fstab_rec) continue;
208
209 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
210 android::base::unique_fd fd(
211 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
212 if (!fd) {
213 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
214 continue;
215 }
216
217 struct fstrim_range range = {};
218 range.len = ULLONG_MAX;
219 if (ioctl(fd, FITRIM, &range)) {
220 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
221 continue;
222 }
223
224 setBowState(mount_rec->blk_device, "1");
225 }
226 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700227 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700228}
229
230namespace {
231const int kBlockSize = 4096;
232const int kSectorSize = 512;
233
234typedef uint64_t sector_t;
235
236struct log_entry {
237 sector_t source;
238 sector_t dest;
239 uint32_t size;
240 uint32_t checksum;
241} __attribute__((packed));
242
243struct log_sector {
244 uint32_t magic;
245 uint32_t count;
246 uint32_t sequence;
Paul Lawrence27691c22018-11-20 14:07:59 -0800247 uint64_t sector0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700248 struct log_entry entries[];
249} __attribute__((packed));
250
251// MAGIC is BOW in ascii
252const int kMagic = 0x00574f42;
253
254void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
255 static uint32_t table[0x100] = {
256 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
257 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
258 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
259 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
260 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
261 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
262 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
263 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
264 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
265 0xB6662D3D,
266
267 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
268 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
269 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
270 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
271 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
272 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
273 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
274 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
275 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
276 0xC0BA6CAD,
277
278 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
279 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
280 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
281 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
282 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
283 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
284 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
285 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
286 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
287 0x5BDEAE1D,
288
289 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
290 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
291 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
292 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
293 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
294 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
295 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
296 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
297 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
298 0x2D02EF8D};
299
300 for (size_t i = 0; i < n_bytes; ++i) {
301 *crc ^= ((uint8_t*)data)[i];
302 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
303 }
304}
305
306} // namespace
307
Paul Lawrence27691c22018-11-20 14:07:59 -0800308static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
309 char* buffer) {
310 for (auto l = logs.rbegin(); l != logs.rend(); l++)
311 if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
312 sector = sector - l->source + l->dest;
313
314 device.seekg(sector * kSectorSize);
315 device.read(buffer, kBlockSize);
316}
317
318static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
319 bool validating, sector_t sector, uint32_t size) {
320 if (!validating) {
321 std::vector<char> buffer(size);
322 device.seekg(sector * kSectorSize);
323 device.read(&buffer[0], size);
324 return buffer;
325 }
326
327 // Crude approach at first where we do this sector by sector and just scan
328 // the entire logs for remappings each time
329 std::vector<char> buffer(size);
330
331 for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
332 read(device, logs, sector, &buffer[i]);
333
334 return buffer;
335}
336
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700337Status cp_restoreCheckpoint(const std::string& blockDevice) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800338 bool validating = true;
339 std::string action = "Validating";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700340
Paul Lawrence27691c22018-11-20 14:07:59 -0800341 for (;;) {
342 std::vector<log_entry> logs;
343 Status status = Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700344
Paul Lawrence27691c22018-11-20 14:07:59 -0800345 LOG(INFO) << action << " checkpoint on " << blockDevice;
346 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
347 if (!device) {
348 PLOG(ERROR) << "Cannot open " << blockDevice;
349 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
350 }
351 auto buffer = read(device, logs, validating, 0, kBlockSize);
352 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700353 if (ls.magic != kMagic) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800354 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700355 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700356 }
357
Paul Lawrence27691c22018-11-20 14:07:59 -0800358 LOG(INFO) << action << " " << ls.sequence << " log sectors";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700359
Paul Lawrence27691c22018-11-20 14:07:59 -0800360 for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
361 auto buffer = read(device, logs, validating, 0, kBlockSize);
362 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
363 if (ls.magic != kMagic) {
364 LOG(ERROR) << "No magic!";
365 status = Status::fromExceptionCode(EINVAL, "No magic");
366 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700367 }
368
Paul Lawrence27691c22018-11-20 14:07:59 -0800369 if ((int)ls.sequence != sequence) {
370 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
371 status = Status::fromExceptionCode(
372 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
373 std::to_string(ls.sequence))
374 .c_str());
375 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700376 }
377
Paul Lawrence27691c22018-11-20 14:07:59 -0800378 LOG(INFO) << action << " from log sector " << ls.sequence;
379
380 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
381 LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
382 << " to " << le->source << " with checksum " << std::hex << le->checksum;
383 auto buffer = read(device, logs, validating, le->dest, le->size);
384 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
385 for (size_t i = 0; i < le->size; i += kBlockSize) {
386 crc32(&buffer[i], kBlockSize, &checksum);
387 }
388
389 if (le->checksum && checksum != le->checksum) {
390 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
391 status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
392 break;
393 }
394
395 logs.push_back(*le);
396
397 if (!validating) {
398 device.seekg(le->source * kSectorSize);
399 device.write(&buffer[0], le->size);
400 }
401 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700402 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800403
404 if (!status.isOk()) {
405 if (!validating) {
406 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
407 return status;
408 }
409
410 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
411 auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
412 device.seekg(0);
413 device.write(&buffer[0], kBlockSize);
414 return Status::ok();
415 }
416
417 if (!validating) break;
418
419 validating = false;
420 action = "Restoring";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700421 }
422
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700423 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700424}
425
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700426Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700427 std::string oldContent, newContent;
428 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700429 struct stat st;
430 int result = stat(kMetadataCPFile.c_str(), &st);
431
432 // If the file doesn't exist, we aren't managing a checkpoint retry counter
433 if (result != 0) return Status::ok();
434 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
435 PLOG(ERROR) << "Failed to read checkpoint file";
436 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
437 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700438 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700439
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700440 if (!android::base::ParseInt(retryContent, &retry))
441 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
442 if (retry > 0) {
443 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700444
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700445 newContent = std::to_string(retry);
446 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
447 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
448 }
449 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700450}
451
452} // namespace vold
453} // namespace android