blob: 5d1ec1f5607fed54da492e55ace4f6e9f5123741 [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>
22#include <string>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070023#include <vector>
24
25#include <android-base/file.h>
26#include <android-base/logging.h>
27#include <android-base/parseint.h>
28#include <android-base/unique_fd.h>
Daniel Rosenbergd3992492018-10-02 17:40:44 -070029#include <android/hardware/boot/1.0/IBootControl.h>
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070030#include <cutils/android_reboot.h>
31#include <fcntl.h>
32#include <fs_mgr.h>
33#include <linux/fs.h>
34#include <mntent.h>
35#include <sys/mount.h>
36#include <sys/stat.h>
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070037
Daniel Rosenbergd3992492018-10-02 17:40:44 -070038using android::hardware::hidl_string;
39using android::hardware::boot::V1_0::BoolResult;
40using android::hardware::boot::V1_0::IBootControl;
41using android::hardware::boot::V1_0::Slot;
42
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070043namespace android {
44namespace vold {
45
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070046namespace {
47const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
48
49bool setBowState(std::string const& block_device, std::string const& state) {
50 if (block_device.substr(0, 5) != "/dev/") {
51 LOG(ERROR) << "Expected block device, got " << block_device;
52 return false;
53 }
54
55 std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
56 if (!android::base::WriteStringToFile(state, state_filename)) {
57 PLOG(ERROR) << "Failed to write to file " << state_filename;
58 return false;
59 }
60
61 return true;
62}
63
64} // namespace
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070065
66bool cp_startCheckpoint(int retry) {
67 if (retry < -1) return false;
68 std::string content = std::to_string(retry);
Daniel Rosenbergd3992492018-10-02 17:40:44 -070069 if (retry == -1) {
70 sp<IBootControl> module = IBootControl::getService();
71 if (module) {
72 std::string suffix;
73 auto cb = [&suffix](hidl_string s) { suffix = s; };
74 if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
75 }
76 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070077 return android::base::WriteStringToFile(content, kMetadataCPFile);
78}
79
80bool cp_commitChanges() {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070081 // Must take action for list of mounted checkpointed things here
82 // To do this, we walk the list of mounted file systems.
83 // But we also need to get the matching fstab entries to see
84 // the original flags
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070085 struct fstab* fstab = fs_mgr_read_fstab_default();
86 if (!fstab) return false;
87
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070088 struct fstab* mounts = fs_mgr_read_fstab("/proc/mounts");
89 if (mounts == NULL) {
90 fs_mgr_free_fstab(fstab);
91 return false;
92 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070093
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070094 // Walk mounted file systems
95 for (int i = 0; i < mounts->num_entries; ++i) {
96 const fstab_rec* mount_rec = &mounts->recs[i];
97 const fstab_rec* fstab_rec = fs_mgr_get_entry_for_mount_point(fstab, mount_rec->mount_point);
98 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070099
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700100 if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
101 if (!strcmp(fstab_rec->fs_type, "f2fs")) {
102 mount(mount_rec->blk_device, mount_rec->mount_point, "none",
103 MS_REMOUNT | fstab_rec->flags, "checkpoint=enable");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700104 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700105 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
106 setBowState(mount_rec->blk_device, "2");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700107 }
108 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700109 fs_mgr_free_fstab(mounts);
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700110 fs_mgr_free_fstab(fstab);
111 return android::base::RemoveFileIfExists(kMetadataCPFile);
112}
113
114void cp_abortChanges() {
115 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
116}
117
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700118bool cp_needsRollback() {
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700119 std::string content;
120 bool ret;
121
122 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700123 if (ret) {
124 if (content == "0") return true;
125 if (content.substr(0, 3) == "-1 ") {
126 std::string oldSuffix = content.substr(3);
127 sp<IBootControl> module = IBootControl::getService();
128 std::string newSuffix;
129
130 if (module) {
131 auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
132 module->getSuffix(module->getCurrentSlot(), cb);
133 if (oldSuffix == newSuffix) return true;
134 }
135 }
136 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700137 return false;
138}
139
140bool cp_needsCheckpoint(void) {
141 bool ret;
142 std::string content;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700143 sp<IBootControl> module = IBootControl::getService();
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700144
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700145 if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE)
146 return true;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700147 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
148 if (ret) return content != "0";
149 return false;
150}
151
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700152bool cp_prepareDriveForCheckpoint(const std::string&) {
153 struct fstab* fstab = fs_mgr_read_fstab_default();
154 if (!fstab) return false;
155
156 struct fstab* mounts = fs_mgr_read_fstab("/proc/mounts");
157 if (mounts == NULL) {
158 fs_mgr_free_fstab(fstab);
159 return false;
160 }
161
162 for (int i = 0; i < mounts->num_entries; ++i) {
163 const fstab_rec* mount_rec = &mounts->recs[i];
164 const fstab_rec* fstab_rec = fs_mgr_get_entry_for_mount_point(fstab, mount_rec->mount_point);
165 if (!fstab_rec) continue;
166
167 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
168 android::base::unique_fd fd(
169 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
170 if (!fd) {
171 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
172 continue;
173 }
174
175 struct fstrim_range range = {};
176 range.len = ULLONG_MAX;
177 if (ioctl(fd, FITRIM, &range)) {
178 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
179 continue;
180 }
181
182 setBowState(mount_rec->blk_device, "1");
183 }
184 }
185 fs_mgr_free_fstab(mounts);
186 fs_mgr_free_fstab(fstab);
187 return true;
188}
189
190namespace {
191const int kBlockSize = 4096;
192const int kSectorSize = 512;
193
194typedef uint64_t sector_t;
195
196struct log_entry {
197 sector_t source;
198 sector_t dest;
199 uint32_t size;
200 uint32_t checksum;
201} __attribute__((packed));
202
203struct log_sector {
204 uint32_t magic;
205 uint32_t count;
206 uint32_t sequence;
207 struct log_entry entries[];
208} __attribute__((packed));
209
210// MAGIC is BOW in ascii
211const int kMagic = 0x00574f42;
212
213void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
214 static uint32_t table[0x100] = {
215 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
216 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
217 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
218 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
219 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
220 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
221 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
222 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
223 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
224 0xB6662D3D,
225
226 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
227 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
228 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
229 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
230 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
231 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
232 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
233 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
234 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
235 0xC0BA6CAD,
236
237 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
238 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
239 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
240 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
241 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
242 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
243 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
244 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
245 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
246 0x5BDEAE1D,
247
248 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
249 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
250 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
251 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
252 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
253 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
254 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
255 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
256 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
257 0x2D02EF8D};
258
259 for (size_t i = 0; i < n_bytes; ++i) {
260 *crc ^= ((uint8_t*)data)[i];
261 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
262 }
263}
264
265} // namespace
266
267bool cp_restoreCheckpoint(const std::string& blockDevice) {
268 LOG(ERROR) << "Restoring checkpoint on " << blockDevice;
269 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
270 if (!device) {
271 PLOG(ERROR) << "Cannot open " << blockDevice;
272 return false;
273 }
274 char buffer[kBlockSize];
275 device.read(buffer, kBlockSize);
276 log_sector& ls = *(log_sector*)buffer;
277 if (ls.magic != kMagic) {
278 LOG(ERROR) << "No magic";
279 return false;
280 }
281
282 LOG(INFO) << "Restoring " << ls.sequence << " log sectors";
283
284 for (int sequence = ls.sequence; sequence >= 0; sequence--) {
285 char buffer[kBlockSize];
286 device.seekg(0);
287 device.read(buffer, kBlockSize);
288 log_sector& ls = *(log_sector*)buffer;
289 if (ls.magic != kMagic) {
290 LOG(ERROR) << "No magic!";
291 return false;
292 }
293
294 if ((int)ls.sequence != sequence) {
295 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
296 return false;
297 }
298
299 LOG(INFO) << "Restoring from log sector " << ls.sequence;
300
301 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
302 LOG(INFO) << "Restoring " << le->size << " bytes from sector " << le->dest << " to "
303 << le->source << " with checksum " << std::hex << le->checksum;
304 std::vector<char> buffer(le->size);
305 device.seekg(le->dest * kSectorSize);
306 device.read(&buffer[0], le->size);
307
308 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
309 for (size_t i = 0; i < le->size; i += kBlockSize) {
310 crc32(&buffer[i], kBlockSize, &checksum);
311 }
312
313 if (le->checksum && checksum != le->checksum) {
314 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
315 return false;
316 }
317
318 device.seekg(le->source * kSectorSize);
319 device.write(&buffer[0], le->size);
320 }
321 }
322
323 return true;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700324}
325
326bool cp_markBootAttempt() {
327 std::string oldContent, newContent;
328 int retry = 0;
329 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) return false;
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700330 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700331
Daniel Rosenbergd3992492018-10-02 17:40:44 -0700332 if (!android::base::ParseInt(retryContent, &retry)) return false;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700333 if (retry > 0) retry--;
334
335 newContent = std::to_string(retry);
336 return android::base::WriteStringToFile(newContent, kMetadataCPFile);
337}
338
339} // namespace vold
340} // namespace android