blob: 7a29514a506c2edb4dd7821cd6670353ada45c61 [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 Rosenberg14ca4ac2019-01-24 18:23:18 -0800132 std::string options = mount_rec->fs_options;
133 options += ",checkpoint=enable";
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800134 if (mount(mount_rec->blk_device, mount_rec->mount_point, "none",
Daniel Rosenberg14ca4ac2019-01-24 18:23:18 -0800135 MS_REMOUNT | fstab_rec->flags, options.c_str())) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800136 return Status::fromExceptionCode(EINVAL, "Failed to remount");
137 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700138 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700139 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800140 if (!setBowState(mount_rec->blk_device, "2"))
141 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700142 }
143 }
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800144 SetProperty("vold.checkpoint_committed", "1");
145 isCheckpointing = false;
Daniel Rosenberg4b86df12018-11-08 22:18:37 -0800146 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700147 return Status::fromExceptionCode(errno, err_str.c_str());
148 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700149}
150
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700151Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700152 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700153 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700154}
155
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700156bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700157 std::string content;
158 bool ret;
159
160 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700161 if (ret) {
162 if (content == "0") return true;
163 if (content.substr(0, 3) == "-1 ") {
164 std::string oldSuffix = content.substr(3);
165 sp<IBootControl> module = IBootControl::getService();
166 std::string newSuffix;
167
168 if (module) {
169 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
170 module->getSuffix(module->getCurrentSlot(), cb);
171 if (oldSuffix == newSuffix) return true;
172 }
173 }
174 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700175 return false;
176}
177
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700178bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700179 bool ret;
180 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700181 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700182
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800183 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
184 isCheckpointing = true;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700185 return true;
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800186 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700187 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergffa1bb02018-12-14 00:20:03 -0800188 if (ret) {
189 ret = content != "0";
190 isCheckpointing = ret;
191 return ret;
192 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700193 return false;
194}
195
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700196Status cp_prepareCheckpoint() {
Paul Lawrence20400892018-10-03 14:14:52 -0700197 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
198 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700199 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700200
Paul Lawrence20400892018-10-03 14:14:52 -0700201 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
202 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700203 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700204
205 for (int i = 0; i < mounts->num_entries; ++i) {
206 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700207 const fstab_rec* fstab_rec =
208 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700209 if (!fstab_rec) continue;
210
211 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
212 android::base::unique_fd fd(
213 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
214 if (!fd) {
215 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
216 continue;
217 }
218
219 struct fstrim_range range = {};
220 range.len = ULLONG_MAX;
221 if (ioctl(fd, FITRIM, &range)) {
222 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
223 continue;
224 }
225
226 setBowState(mount_rec->blk_device, "1");
227 }
228 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700229 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700230}
231
232namespace {
233const int kBlockSize = 4096;
234const int kSectorSize = 512;
235
236typedef uint64_t sector_t;
237
238struct log_entry {
239 sector_t source;
240 sector_t dest;
241 uint32_t size;
242 uint32_t checksum;
243} __attribute__((packed));
244
245struct log_sector {
246 uint32_t magic;
247 uint32_t count;
248 uint32_t sequence;
Paul Lawrence27691c22018-11-20 14:07:59 -0800249 uint64_t sector0;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700250 struct log_entry entries[];
251} __attribute__((packed));
252
253// MAGIC is BOW in ascii
254const int kMagic = 0x00574f42;
255
256void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
257 static uint32_t table[0x100] = {
258 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
259 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
260 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
261 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
262 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
263 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
264 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
265 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
266 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
267 0xB6662D3D,
268
269 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
270 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
271 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
272 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
273 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
274 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
275 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
276 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
277 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
278 0xC0BA6CAD,
279
280 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
281 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
282 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
283 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
284 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
285 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
286 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
287 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
288 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
289 0x5BDEAE1D,
290
291 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
292 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
293 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
294 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
295 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
296 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
297 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
298 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
299 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
300 0x2D02EF8D};
301
302 for (size_t i = 0; i < n_bytes; ++i) {
303 *crc ^= ((uint8_t*)data)[i];
304 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
305 }
306}
307
308} // namespace
309
Paul Lawrence27691c22018-11-20 14:07:59 -0800310static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
311 char* buffer) {
312 for (auto l = logs.rbegin(); l != logs.rend(); l++)
313 if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
314 sector = sector - l->source + l->dest;
315
316 device.seekg(sector * kSectorSize);
317 device.read(buffer, kBlockSize);
318}
319
320static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
321 bool validating, sector_t sector, uint32_t size) {
322 if (!validating) {
323 std::vector<char> buffer(size);
324 device.seekg(sector * kSectorSize);
325 device.read(&buffer[0], size);
326 return buffer;
327 }
328
329 // Crude approach at first where we do this sector by sector and just scan
330 // the entire logs for remappings each time
331 std::vector<char> buffer(size);
332
333 for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
334 read(device, logs, sector, &buffer[i]);
335
336 return buffer;
337}
338
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700339Status cp_restoreCheckpoint(const std::string& blockDevice) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800340 bool validating = true;
341 std::string action = "Validating";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700342
Paul Lawrence27691c22018-11-20 14:07:59 -0800343 for (;;) {
344 std::vector<log_entry> logs;
345 Status status = Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700346
Paul Lawrence27691c22018-11-20 14:07:59 -0800347 LOG(INFO) << action << " checkpoint on " << blockDevice;
348 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
349 if (!device) {
350 PLOG(ERROR) << "Cannot open " << blockDevice;
351 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
352 }
353 auto buffer = read(device, logs, validating, 0, kBlockSize);
354 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700355 if (ls.magic != kMagic) {
Paul Lawrence27691c22018-11-20 14:07:59 -0800356 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700357 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700358 }
359
Paul Lawrence27691c22018-11-20 14:07:59 -0800360 LOG(INFO) << action << " " << ls.sequence << " log sectors";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700361
Paul Lawrence27691c22018-11-20 14:07:59 -0800362 for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
363 auto buffer = read(device, logs, validating, 0, kBlockSize);
364 log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
365 if (ls.magic != kMagic) {
366 LOG(ERROR) << "No magic!";
367 status = Status::fromExceptionCode(EINVAL, "No magic");
368 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700369 }
370
Paul Lawrence27691c22018-11-20 14:07:59 -0800371 if ((int)ls.sequence != sequence) {
372 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
373 status = Status::fromExceptionCode(
374 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
375 std::to_string(ls.sequence))
376 .c_str());
377 break;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700378 }
379
Paul Lawrence27691c22018-11-20 14:07:59 -0800380 LOG(INFO) << action << " from log sector " << ls.sequence;
381
382 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
383 LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
384 << " to " << le->source << " with checksum " << std::hex << le->checksum;
385 auto buffer = read(device, logs, validating, le->dest, le->size);
386 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
387 for (size_t i = 0; i < le->size; i += kBlockSize) {
388 crc32(&buffer[i], kBlockSize, &checksum);
389 }
390
391 if (le->checksum && checksum != le->checksum) {
392 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
393 status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
394 break;
395 }
396
397 logs.push_back(*le);
398
399 if (!validating) {
400 device.seekg(le->source * kSectorSize);
401 device.write(&buffer[0], le->size);
402 }
403 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700404 }
Paul Lawrence27691c22018-11-20 14:07:59 -0800405
406 if (!status.isOk()) {
407 if (!validating) {
408 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
409 return status;
410 }
411
412 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
413 auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
414 device.seekg(0);
415 device.write(&buffer[0], kBlockSize);
416 return Status::ok();
417 }
418
419 if (!validating) break;
420
421 validating = false;
422 action = "Restoring";
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700423 }
424
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700425 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700426}
427
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700428Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700429 std::string oldContent, newContent;
430 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700431 struct stat st;
432 int result = stat(kMetadataCPFile.c_str(), &st);
433
434 // If the file doesn't exist, we aren't managing a checkpoint retry counter
435 if (result != 0) return Status::ok();
436 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
437 PLOG(ERROR) << "Failed to read checkpoint file";
438 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
439 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700440 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700441
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700442 if (!android::base::ParseInt(retryContent, &retry))
443 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
444 if (retry > 0) {
445 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700446
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700447 newContent = std::to_string(retry);
448 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
449 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
450 }
451 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700452}
453
454} // namespace vold
455} // namespace android