blob: 94a78eb3c611cd8fa8eaf948d8fc957ede0feae3 [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>
29#include <android-base/unique_fd.h>
Daniel Rosenbergd3992492018-10-02 17:40:44 -070030#include <android/hardware/boot/1.0/IBootControl.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070031#include <cutils/android_reboot.h>
32#include <fcntl.h>
33#include <fs_mgr.h>
34#include <linux/fs.h>
35#include <mntent.h>
36#include <sys/mount.h>
37#include <sys/stat.h>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070038
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070039using android::binder::Status;
Daniel Rosenbergd3992492018-10-02 17:40:44 -070040using android::hardware::hidl_string;
41using android::hardware::boot::V1_0::BoolResult;
42using android::hardware::boot::V1_0::IBootControl;
43using android::hardware::boot::V1_0::Slot;
44
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070045namespace android {
46namespace vold {
47
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070048namespace {
49const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
50
51bool setBowState(std::string const& block_device, std::string const& state) {
52 if (block_device.substr(0, 5) != "/dev/") {
53 LOG(ERROR) << "Expected block device, got " << block_device;
54 return false;
55 }
56
57 std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
58 if (!android::base::WriteStringToFile(state, state_filename)) {
59 PLOG(ERROR) << "Failed to write to file " << state_filename;
60 return false;
61 }
62
63 return true;
64}
65
66} // namespace
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070067
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070068Status cp_startCheckpoint(int retry) {
69 if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -070070 std::string content = std::to_string(retry + 1);
Daniel Rosenbergd3992492018-10-02 17:40:44 -070071 if (retry == -1) {
72 sp<IBootControl> module = IBootControl::getService();
73 if (module) {
74 std::string suffix;
75 auto cb = [&suffix](hidl_string s) { suffix = s; };
76 if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
77 }
78 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070079 if (!android::base::WriteStringToFile(content, kMetadataCPFile))
80 return Status::fromExceptionCode(errno, "Failed to write checkpoint file");
81 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070082}
83
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070084Status cp_commitChanges() {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070085 // Must take action for list of mounted checkpointed things here
86 // To do this, we walk the list of mounted file systems.
87 // But we also need to get the matching fstab entries to see
88 // the original flags
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070089 std::string err_str;
Paul Lawrence20400892018-10-03 14:14:52 -070090 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
91 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070092 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070093
Paul Lawrence20400892018-10-03 14:14:52 -070094 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
95 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -070096 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070097
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070098 // Walk mounted file systems
99 for (int i = 0; i < mounts->num_entries; ++i) {
100 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700101 const fstab_rec* fstab_rec =
102 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700103 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700104
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700105 if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
106 if (!strcmp(fstab_rec->fs_type, "f2fs")) {
107 mount(mount_rec->blk_device, mount_rec->mount_point, "none",
108 MS_REMOUNT | fstab_rec->flags, "checkpoint=enable");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700109 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700110 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
111 setBowState(mount_rec->blk_device, "2");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700112 }
113 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700114 if (android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
115 return Status::fromExceptionCode(errno, err_str.c_str());
116 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700117}
118
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700119Status cp_abortChanges() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700120 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700121 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700122}
123
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700124bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700125 std::string content;
126 bool ret;
127
128 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700129 if (ret) {
130 if (content == "0") return true;
131 if (content.substr(0, 3) == "-1 ") {
132 std::string oldSuffix = content.substr(3);
133 sp<IBootControl> module = IBootControl::getService();
134 std::string newSuffix;
135
136 if (module) {
137 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
138 module->getSuffix(module->getCurrentSlot(), cb);
139 if (oldSuffix == newSuffix) return true;
140 }
141 }
142 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700143 return false;
144}
145
Daniel Rosenberg80d1ca52018-10-09 19:26:57 -0700146bool cp_needsCheckpoint() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700147 bool ret;
148 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700149 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700150
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700151 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE)
152 return true;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700153 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
154 if (ret) return content != "0";
155 return false;
156}
157
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700158Status cp_prepareCheckpoint() {
Paul Lawrence20400892018-10-03 14:14:52 -0700159 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
160 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700161 if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700162
Paul Lawrence20400892018-10-03 14:14:52 -0700163 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
164 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700165 if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700166
167 for (int i = 0; i < mounts->num_entries; ++i) {
168 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700169 const fstab_rec* fstab_rec =
170 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700171 if (!fstab_rec) continue;
172
173 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
174 android::base::unique_fd fd(
175 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
176 if (!fd) {
177 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
178 continue;
179 }
180
181 struct fstrim_range range = {};
182 range.len = ULLONG_MAX;
183 if (ioctl(fd, FITRIM, &range)) {
184 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
185 continue;
186 }
187
188 setBowState(mount_rec->blk_device, "1");
189 }
190 }
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700191 return Status::ok();
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700192}
193
194namespace {
195const int kBlockSize = 4096;
196const int kSectorSize = 512;
197
198typedef uint64_t sector_t;
199
200struct log_entry {
201 sector_t source;
202 sector_t dest;
203 uint32_t size;
204 uint32_t checksum;
205} __attribute__((packed));
206
207struct log_sector {
208 uint32_t magic;
209 uint32_t count;
210 uint32_t sequence;
211 struct log_entry entries[];
212} __attribute__((packed));
213
214// MAGIC is BOW in ascii
215const int kMagic = 0x00574f42;
216
217void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
218 static uint32_t table[0x100] = {
219 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
220 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
221 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
222 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
223 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
224 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
225 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
226 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
227 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
228 0xB6662D3D,
229
230 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
231 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
232 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
233 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
234 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
235 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
236 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
237 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
238 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
239 0xC0BA6CAD,
240
241 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
242 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
243 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
244 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
245 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
246 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
247 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
248 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
249 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
250 0x5BDEAE1D,
251
252 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
253 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
254 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
255 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
256 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
257 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
258 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
259 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
260 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
261 0x2D02EF8D};
262
263 for (size_t i = 0; i < n_bytes; ++i) {
264 *crc ^= ((uint8_t*)data)[i];
265 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
266 }
267}
268
269} // namespace
270
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700271Status cp_restoreCheckpoint(const std::string& blockDevice) {
272 LOG(INFO) << "Restoring checkpoint on " << blockDevice;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700273 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
274 if (!device) {
275 PLOG(ERROR) << "Cannot open " << blockDevice;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700276 return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700277 }
278 char buffer[kBlockSize];
279 device.read(buffer, kBlockSize);
280 log_sector& ls = *(log_sector*)buffer;
281 if (ls.magic != kMagic) {
282 LOG(ERROR) << "No magic";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700283 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700284 }
285
286 LOG(INFO) << "Restoring " << ls.sequence << " log sectors";
287
288 for (int sequence = ls.sequence; sequence >= 0; sequence--) {
289 char buffer[kBlockSize];
290 device.seekg(0);
291 device.read(buffer, kBlockSize);
292 log_sector& ls = *(log_sector*)buffer;
293 if (ls.magic != kMagic) {
294 LOG(ERROR) << "No magic!";
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700295 return Status::fromExceptionCode(EINVAL, "No magic");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700296 }
297
298 if ((int)ls.sequence != sequence) {
299 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700300 return Status::fromExceptionCode(
301 EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
302 std::to_string(ls.sequence))
303 .c_str());
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700304 }
305
306 LOG(INFO) << "Restoring from log sector " << ls.sequence;
307
308 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
309 LOG(INFO) << "Restoring " << le->size << " bytes from sector " << le->dest << " to "
310 << le->source << " with checksum " << std::hex << le->checksum;
311 std::vector<char> buffer(le->size);
312 device.seekg(le->dest * kSectorSize);
313 device.read(&buffer[0], le->size);
314
315 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
316 for (size_t i = 0; i < le->size; i += kBlockSize) {
317 crc32(&buffer[i], kBlockSize, &checksum);
318 }
319
320 if (le->checksum && checksum != le->checksum) {
321 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700322 return Status::fromExceptionCode(EINVAL, "Checksums don't match");
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700323 }
324
325 device.seekg(le->source * kSectorSize);
326 device.write(&buffer[0], le->size);
327 }
328 }
329
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700330 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700331}
332
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700333Status cp_markBootAttempt() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700334 std::string oldContent, newContent;
335 int retry = 0;
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700336 struct stat st;
337 int result = stat(kMetadataCPFile.c_str(), &st);
338
339 // If the file doesn't exist, we aren't managing a checkpoint retry counter
340 if (result != 0) return Status::ok();
341 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
342 PLOG(ERROR) << "Failed to read checkpoint file";
343 return Status::fromExceptionCode(errno, "Failed to read checkpoint file");
344 }
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700345 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700346
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700347 if (!android::base::ParseInt(retryContent, &retry))
348 return Status::fromExceptionCode(EINVAL, "Could not parse retry count");
349 if (retry > 0) {
350 retry--;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700351
Daniel Rosenberg73680ec2018-10-10 18:52:04 -0700352 newContent = std::to_string(retry);
353 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
354 return Status::fromExceptionCode(errno, "Could not write checkpoint file");
355 }
356 return Status::ok();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700357}
358
359} // namespace vold
360} // namespace android