blob: 1b85b165c808dc4d9028f01deeebd9335aa46090 [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 Rosenberg14ca4ac2019-01-24 18:23:18 -0800117 std::string options = mount_rec->fs_options;
118 options += ",checkpoint=enable";
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800119 if (mount(mount_rec->blk_device, mount_rec->mount_point, "none",
Daniel Rosenberg14ca4ac2019-01-24 18:23:18 -0800120 MS_REMOUNT | fstab_rec->flags, options.c_str())) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800121 return Status::fromExceptionCode(EINVAL, "Failed to remount");
122 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700123 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700124 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800125 if (!setBowState(mount_rec->blk_device, "2"))
126 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700127 }
128 }
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800129 SetProperty("vold.checkpoint_committed", "1");
130 isCheckpointing = false;
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800131 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700132 return Status::fromExceptionCode(errno, err_str.c_str());
133 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700134}
135
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700136Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700137 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700138 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700139}
140
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700141bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700142 std::string content;
143 bool ret;
144
145 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700146 if (ret) {
147 if (content == "0") return true;
148 if (content.substr(0, 3) == "-1 ") {
149 std::string oldSuffix = content.substr(3);
150 sp<IBootControl> module = IBootControl::getService();
151 std::string newSuffix;
152
153 if (module) {
154 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
155 module->getSuffix(module->getCurrentSlot(), cb);
156 if (oldSuffix == newSuffix) return true;
157 }
158 }
159 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700160 return false;
161}
162
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700163bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700164 bool ret;
165 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700166 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700167
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800168 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
169 isCheckpointing = true;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700170 return true;
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800171 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700172 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800173 if (ret) {
174 ret = content != "0";
175 isCheckpointing = ret;
176 return ret;
177 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700178 return false;
179}
180
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700181Status cp_prepareCheckpoint() {
Paul Lawrence20400892018-10-03 14:14:52 -0700182 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
183 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700184 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700185
Paul Lawrence20400892018-10-03 14:14:52 -0700186 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
187 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700188 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700189
190 for (int i = 0; i < mounts->num_entries; ++i) {
191 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700192 const fstab_rec* fstab_rec =
193 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700194 if (!fstab_rec) continue;
195
196 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
197 android::base::unique_fd fd(
198 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
199 if (!fd) {
200 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
201 continue;
202 }
203
204 struct fstrim_range range = {};
205 range.len = ULLONG_MAX;
206 if (ioctl(fd, FITRIM, &range)) {
207 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
208 continue;
209 }
210
211 setBowState(mount_rec->blk_device, "1");
212 }
213 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700214 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700215}
216
217namespace {
218const int kBlockSize = 4096;
219const int kSectorSize = 512;
220
221typedef uint64_t sector_t;
222
223struct log_entry {
224 sector_t source;
225 sector_t dest;
226 uint32_t size;
227 uint32_t checksum;
228} __attribute__((packed));
229
230struct log_sector {
231 uint32_t magic;
232 uint32_t count;
233 uint32_t sequence;
Paul Lawrence27691c22018-11-20 14:07:59 -0800234 uint64_t sector0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700235 struct log_entry entries[];
236} __attribute__((packed));
237
238// MAGIC is BOW in ascii
239const int kMagic = 0x00574f42;
240
241void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
242 static uint32_t table[0x100] = {
243 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
244 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
245 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
246 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
247 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
248 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
249 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
250 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
251 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
252 0xB6662D3D,
253
254 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
255 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
256 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
257 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
258 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
259 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
260 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
261 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
262 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
263 0xC0BA6CAD,
264
265 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
266 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
267 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
268 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
269 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
270 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
271 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
272 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
273 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
274 0x5BDEAE1D,
275
276 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
277 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
278 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
279 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
280 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
281 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
282 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
283 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
284 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
285 0x2D02EF8D};
286
287 for (size_t i = 0; i < n_bytes; ++i) {
288 *crc ^= ((uint8_t*)data)[i];
289 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
290 }
291}
292
293} // namespace
294
Paul Lawrence27691c22018-11-20 14:07:59 -0800295static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
296 char* buffer) {
297 for (auto l = logs.rbegin(); l != logs.rend(); l++)
298 if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
299 sector = sector - l->source + l->dest;
300
301 device.seekg(sector * kSectorSize);
302 device.read(buffer, kBlockSize);
303}
304
305static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
306 bool validating, sector_t sector, uint32_t size) {
307 if (!validating) {
308 std::vector<char> buffer(size);
309 device.seekg(sector * kSectorSize);
310 device.read(&buffer[0], size);
311 return buffer;
312 }
313
314 // Crude approach at first where we do this sector by sector and just scan
315 // the entire logs for remappings each time
316 std::vector<char> buffer(size);
317
318 for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
319 read(device, logs, sector, &buffer[i]);
320
321 return buffer;
322}
323
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700324Status cp_restoreCheckpoint(const std::string& blockDevice) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800325 bool validating = true;
326 std::string action = "Validating";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700327
Paul Lawrence27691c22018-11-20 14:07:59 -0800328 for (;;) {
329 std::vector<log_entry> logs;
330 Status status = Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700331
Paul Lawrence27691c22018-11-20 14:07:59 -0800332 LOG(INFO) << action << " checkpoint on " << blockDevice;
333 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
334 if (!device) {
335 PLOG(ERROR) << "Cannot open " << blockDevice;
336 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
337 }
338 auto buffer = read(device, logs, validating, 0, kBlockSize);
339 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700340 if (ls.magic != kMagic) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800341 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700342 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700343 }
344
Paul Lawrence27691c22018-11-20 14:07:59 -0800345 LOG(INFO) << action << " " << ls.sequence << " log sectors";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700346
Paul Lawrence27691c22018-11-20 14:07:59 -0800347 for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
348 auto buffer = read(device, logs, validating, 0, kBlockSize);
349 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
350 if (ls.magic != kMagic) {
351 LOG(ERROR) << "No magic!";
352 status = Status::fromExceptionCode(EINVAL, "No magic");
353 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700354 }
355
Paul Lawrence27691c22018-11-20 14:07:59 -0800356 if ((int)ls.sequence != sequence) {
357 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
358 status = Status::fromExceptionCode(
359 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
360 std::to_string(ls.sequence))
361 .c_str());
362 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700363 }
364
Paul Lawrence27691c22018-11-20 14:07:59 -0800365 LOG(INFO) << action << " from log sector " << ls.sequence;
366
367 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
368 LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
369 << " to " << le->source << " with checksum " << std::hex << le->checksum;
370 auto buffer = read(device, logs, validating, le->dest, le->size);
371 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
372 for (size_t i = 0; i < le->size; i += kBlockSize) {
373 crc32(&buffer[i], kBlockSize, &checksum);
374 }
375
376 if (le->checksum && checksum != le->checksum) {
377 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
378 status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
379 break;
380 }
381
382 logs.push_back(*le);
383
384 if (!validating) {
385 device.seekg(le->source * kSectorSize);
386 device.write(&buffer[0], le->size);
387 }
388 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700389 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800390
391 if (!status.isOk()) {
392 if (!validating) {
393 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
394 return status;
395 }
396
397 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
398 auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
399 device.seekg(0);
400 device.write(&buffer[0], kBlockSize);
401 return Status::ok();
402 }
403
404 if (!validating) break;
405
406 validating = false;
407 action = "Restoring";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700408 }
409
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700410 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700411}
412
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700413Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700414 std::string oldContent, newContent;
415 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700416 struct stat st;
417 int result = stat(kMetadataCPFile.c_str(), &st);
418
419 // If the file doesn't exist, we aren't managing a checkpoint retry counter
420 if (result != 0) return Status::ok();
421 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
422 PLOG(ERROR) << "Failed to read checkpoint file";
423 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
424 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700425 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700426
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700427 if (!android::base::ParseInt(retryContent, &retry))
428 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
429 if (retry > 0) {
430 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700431
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700432 newContent = std::to_string(retry);
433 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
434 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
435 }
436 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700437}
438
439} // namespace vold
440} // namespace android