blob: 7586a6cc6d8337082b89a37168c77864ca579c91 [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 Rosenberg73680ec2018-10-10 18:52:04 -070070Status cp_startCheckpoint(int retry) {
71 if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -070072 std::string content = std::to_string(retry + 1);
Daniel Rosenbergd3992492018-10-02 17:40:44 -070073 if (retry == -1) {
74 sp<IBootControl> module = IBootControl::getService();
75 if (module) {
76 std::string suffix;
77 auto cb = [&suffix](hidl_string s) { suffix = s; };
78 if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
79 }
80 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070081 if (!android::base::WriteStringToFile(content, kMetadataCPFile))
82 return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
83 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070084}
85
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080086namespace {
87
88bool isCheckpointing = false;
89}
90
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070091Status cp_commitChanges() {
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -080092 if (!isCheckpointing) {
93 return Status::ok();
94 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070095 // Must take action for list of mounted checkpointed things here
96 // To do this, we walk the list of mounted file systems.
97 // But we also need to get the matching fstab entries to see
98 // the original flags
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070099 std::string err_str;
Paul Lawrence20400892018-10-03 14:14:52 -0700100 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
101 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700102 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700103
Paul Lawrence20400892018-10-03 14:14:52 -0700104 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
105 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700106 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700107
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700108 // Walk mounted file systems
109 for (int i = 0; i < mounts->num_entries; ++i) {
110 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700111 const fstab_rec* fstab_rec =
112 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700113 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700114
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700115 if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
116 if (!strcmp(fstab_rec->fs_type, "f2fs")) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800117 if (mount(mount_rec->blk_device, mount_rec->mount_point, "none",
118 MS_REMOUNT | fstab_rec->flags, "checkpoint=enable")) {
119 return Status::fromExceptionCode(EINVAL, "Failed to remount");
120 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700121 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700122 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800123 if (!setBowState(mount_rec->blk_device, "2"))
124 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700125 }
126 }
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800127 SetProperty("vold.checkpoint_committed", "1");
128 isCheckpointing = false;
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800129 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700130 return Status::fromExceptionCode(errno, err_str.c_str());
131 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700132}
133
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700134Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700135 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700136 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700137}
138
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700139bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700140 std::string content;
141 bool ret;
142
143 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700144 if (ret) {
145 if (content == "0") return true;
146 if (content.substr(0, 3) == "-1 ") {
147 std::string oldSuffix = content.substr(3);
148 sp<IBootControl> module = IBootControl::getService();
149 std::string newSuffix;
150
151 if (module) {
152 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
153 module->getSuffix(module->getCurrentSlot(), cb);
154 if (oldSuffix == newSuffix) return true;
155 }
156 }
157 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700158 return false;
159}
160
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700161bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700162 bool ret;
163 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700164 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700165
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800166 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
167 isCheckpointing = true;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700168 return true;
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800169 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700170 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800171 if (ret) {
172 ret = content != "0";
173 isCheckpointing = ret;
174 return ret;
175 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700176 return false;
177}
178
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700179Status cp_prepareCheckpoint() {
Paul Lawrence20400892018-10-03 14:14:52 -0700180 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
181 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700182 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700183
Paul Lawrence20400892018-10-03 14:14:52 -0700184 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
185 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700186 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700187
188 for (int i = 0; i < mounts->num_entries; ++i) {
189 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700190 const fstab_rec* fstab_rec =
191 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700192 if (!fstab_rec) continue;
193
194 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
195 android::base::unique_fd fd(
196 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
197 if (!fd) {
198 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
199 continue;
200 }
201
202 struct fstrim_range range = {};
203 range.len = ULLONG_MAX;
204 if (ioctl(fd, FITRIM, &range)) {
205 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
206 continue;
207 }
208
209 setBowState(mount_rec->blk_device, "1");
210 }
211 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700212 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700213}
214
215namespace {
216const int kBlockSize = 4096;
217const int kSectorSize = 512;
218
219typedef uint64_t sector_t;
220
221struct log_entry {
222 sector_t source;
223 sector_t dest;
224 uint32_t size;
225 uint32_t checksum;
226} __attribute__((packed));
227
228struct log_sector {
229 uint32_t magic;
230 uint32_t count;
231 uint32_t sequence;
Paul Lawrence27691c22018-11-20 14:07:59 -0800232 uint64_t sector0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700233 struct log_entry entries[];
234} __attribute__((packed));
235
236// MAGIC is BOW in ascii
237const int kMagic = 0x00574f42;
238
239void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
240 static uint32_t table[0x100] = {
241 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
242 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
243 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
244 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
245 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
246 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
247 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
248 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
249 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
250 0xB6662D3D,
251
252 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
253 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
254 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
255 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
256 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
257 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
258 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
259 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
260 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
261 0xC0BA6CAD,
262
263 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
264 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
265 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
266 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
267 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
268 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
269 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
270 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
271 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
272 0x5BDEAE1D,
273
274 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
275 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
276 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
277 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
278 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
279 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
280 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
281 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
282 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
283 0x2D02EF8D};
284
285 for (size_t i = 0; i < n_bytes; ++i) {
286 *crc ^= ((uint8_t*)data)[i];
287 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
288 }
289}
290
291} // namespace
292
Paul Lawrence27691c22018-11-20 14:07:59 -0800293static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
294 char* buffer) {
295 for (auto l = logs.rbegin(); l != logs.rend(); l++)
296 if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
297 sector = sector - l->source + l->dest;
298
299 device.seekg(sector * kSectorSize);
300 device.read(buffer, kBlockSize);
301}
302
303static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
304 bool validating, sector_t sector, uint32_t size) {
305 if (!validating) {
306 std::vector<char> buffer(size);
307 device.seekg(sector * kSectorSize);
308 device.read(&buffer[0], size);
309 return buffer;
310 }
311
312 // Crude approach at first where we do this sector by sector and just scan
313 // the entire logs for remappings each time
314 std::vector<char> buffer(size);
315
316 for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
317 read(device, logs, sector, &buffer[i]);
318
319 return buffer;
320}
321
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700322Status cp_restoreCheckpoint(const std::string& blockDevice) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800323 bool validating = true;
324 std::string action = "Validating";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700325
Paul Lawrence27691c22018-11-20 14:07:59 -0800326 for (;;) {
327 std::vector<log_entry> logs;
328 Status status = Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700329
Paul Lawrence27691c22018-11-20 14:07:59 -0800330 LOG(INFO) << action << " checkpoint on " << blockDevice;
331 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
332 if (!device) {
333 PLOG(ERROR) << "Cannot open " << blockDevice;
334 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
335 }
336 auto buffer = read(device, logs, validating, 0, kBlockSize);
337 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700338 if (ls.magic != kMagic) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800339 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700340 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700341 }
342
Paul Lawrence27691c22018-11-20 14:07:59 -0800343 LOG(INFO) << action << " " << ls.sequence << " log sectors";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700344
Paul Lawrence27691c22018-11-20 14:07:59 -0800345 for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
346 auto buffer = read(device, logs, validating, 0, kBlockSize);
347 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
348 if (ls.magic != kMagic) {
349 LOG(ERROR) << "No magic!";
350 status = Status::fromExceptionCode(EINVAL, "No magic");
351 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700352 }
353
Paul Lawrence27691c22018-11-20 14:07:59 -0800354 if ((int)ls.sequence != sequence) {
355 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
356 status = Status::fromExceptionCode(
357 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
358 std::to_string(ls.sequence))
359 .c_str());
360 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700361 }
362
Paul Lawrence27691c22018-11-20 14:07:59 -0800363 LOG(INFO) << action << " from log sector " << ls.sequence;
364
365 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
366 LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
367 << " to " << le->source << " with checksum " << std::hex << le->checksum;
368 auto buffer = read(device, logs, validating, le->dest, le->size);
369 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
370 for (size_t i = 0; i < le->size; i += kBlockSize) {
371 crc32(&buffer[i], kBlockSize, &checksum);
372 }
373
374 if (le->checksum && checksum != le->checksum) {
375 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
376 status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
377 break;
378 }
379
380 logs.push_back(*le);
381
382 if (!validating) {
383 device.seekg(le->source * kSectorSize);
384 device.write(&buffer[0], le->size);
385 }
386 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700387 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800388
389 if (!status.isOk()) {
390 if (!validating) {
391 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
392 return status;
393 }
394
395 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
396 auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
397 device.seekg(0);
398 device.write(&buffer[0], kBlockSize);
399 return Status::ok();
400 }
401
402 if (!validating) break;
403
404 validating = false;
405 action = "Restoring";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700406 }
407
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700408 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700409}
410
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700411Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700412 std::string oldContent, newContent;
413 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700414 struct stat st;
415 int result = stat(kMetadataCPFile.c_str(), &st);
416
417 // If the file doesn't exist, we aren't managing a checkpoint retry counter
418 if (result != 0) return Status::ok();
419 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
420 PLOG(ERROR) << "Failed to read checkpoint file";
421 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
422 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700423 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700424
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700425 if (!android::base::ParseInt(retryContent, &retry))
426 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
427 if (retry > 0) {
428 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700429
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700430 newContent = std::to_string(retry);
431 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
432 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
433 }
434 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700435}
436
437} // namespace vold
438} // namespace android